home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / XAP / XFIG / TRANSFIG.2 / TRANSFIG / transfig / fig2dev / read.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-10  |  20.3 KB  |  888 lines

  1. /*
  2.  * TransFig: Facility for Translating Fig code
  3.  * Copyright (c) 1985 Supoj Sutantavibul
  4.  * Copyright (c) 1991 Micah Beck
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation. The authors make no representations about the suitability 
  11.  * of this software for any purpose.  It is provided "as is" without express 
  12.  * or implied warranty.
  13.  *
  14.  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19.  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  */
  23.  
  24. /* 
  25.  *    FIG : Facility for Interactive Generation of figures
  26.  *
  27.  *    Copyright (c) 1985, 1988 by Supoj Sutanthavibul (supoj@sally.UTEXAS.EDU)
  28.  *    January 1985.
  29.  *    1st revision : August 1985.
  30.  *    2nd revision : March 1988.
  31.  *
  32.  *    %W%    %G%
  33. */
  34. #include <stdio.h>
  35. #include <ctype.h>
  36. #include <errno.h>
  37. #include "alloc.h"
  38. #include "object.h"
  39.  
  40. #if defined(hpux) || defined(SYSV)
  41. #define bzero(s,n) memset((s),'\0',(n))
  42. #endif
  43.  
  44. extern int            errno;
  45.  
  46. extern F_arrow        *make_arrow();
  47. extern char        *calloc();
  48. extern double            floor(), ceil();
  49.  
  50. static F_ellipse    *read_ellipseobject();
  51. static F_line        *read_lineobject();
  52. static F_text        *read_textobject();
  53. static F_spline        *read_splineobject();
  54. static F_arc        *read_arcobject();
  55. static F_compound    *read_compoundobject();
  56.  
  57. #define            FILL_CONVERT(f) \
  58.                 ((v2_flag || (f) < WHITE_FILL) \
  59.                     ? (f) : 21 - ((f)-1)*5)
  60.  
  61. #define            BUF_SIZE        1024
  62.  
  63. char            buf[BUF_SIZE];
  64. int            line_no = 0;
  65. int            num_object;
  66. int            v2_flag;    /* Protocol V2.0 or V2.1 */
  67. int            v21_flag;    /* Protocol V2.1 */
  68.  
  69. read_fail_message(file, err)
  70. char    *file;
  71. int    err;
  72. {
  73.     extern char    *sys_errlist[];
  74.  
  75.     if (err == 0)        /* Successful read */
  76.         return;
  77. #if !defined(hpux) && !defined(SYSV)
  78.     else if (err == ENAMETOOLONG)
  79.         put_msg("File name \"%s\" is too long", file);
  80. #endif
  81.     else if (err == ENOENT)
  82.         put_msg("File \"%s\" does not exist", file);
  83.     else if (err == ENOTDIR)
  84.         put_msg("A name in the path \"%s\" is not a directory", file);
  85.     else if (err == EACCES)
  86.         put_msg("Read access to file \"%s\" is blocked", file);
  87.     else if (err == EISDIR)
  88.         put_msg("File \"%s\" is a directory", file);
  89.     else if (err == -2) {
  90.         put_msg("File \"%s\" is empty", file);
  91.         }
  92.     else if (err == -1) {
  93.         /* Format error; relevant error message is already delivered */
  94.         }
  95.     else
  96.         put_msg("File \"%s\" is not accessable; %s", file, sys_errlist[err]);
  97.     }
  98.  
  99. /**********************************************************
  100. Read_fig returns :
  101.  
  102.      0 : successful read.
  103.     -1 : File is in incorrect format
  104.     -2 : File is empty
  105. err_no : if file can not be read for various reasons
  106.  
  107. The resolution (ppi) and the cooridnate system (coord_sys) are
  108. stored in obj->nwcorner.x and obj->nwcorner.x respectively.
  109. **********************************************************/
  110.  
  111. read_fig(file_name, obj)
  112. char        *file_name;
  113. F_compound    *obj;
  114. {
  115.     FILE        *fp;
  116.  
  117.     if ((fp = fopen(file_name, "r")) == NULL)
  118.         return(errno);
  119.     else
  120.         return(readfp_fig(fp, obj));
  121.     }
  122.  
  123. readfp_fig(fp, obj)
  124. FILE    *fp;
  125. F_compound    *obj;
  126. {
  127.     char        c;
  128.     int        status;
  129.  
  130.     num_object = 0;
  131.     c = fgetc(fp);
  132.     if (feof(fp)) return(-2);
  133.     ungetc(c, fp);
  134.     bzero((char*)obj, COMOBJ_SIZE);
  135.     if (c == '#')
  136.         status = read_objects(fp, obj);
  137.     else
  138.         status = read_1_3_objects(fp, obj);
  139.     (void)fclose(fp);
  140.     return(status);
  141.     }
  142.     
  143. int
  144. read_objects(fp, obj)
  145. FILE        *fp;
  146. F_compound    *obj;
  147. {
  148.     F_ellipse    *e, *le = NULL;
  149.     F_line        *l, *ll = NULL;
  150.     F_text        *t, *lt = NULL;
  151.     F_spline    *s, *ls = NULL;
  152.     F_arc        *a, *la = NULL;
  153.     F_compound    *c, *lc = NULL;
  154.     int        object, ppi, coord_sys;
  155.  
  156.     bzero((char*)obj, COMOBJ_SIZE);
  157.     (void)fgets(buf, BUF_SIZE, fp);    /* get the version line */
  158.  
  159.     v2_flag = (!strncmp(buf, "#FIG 2", 6));
  160.     v21_flag = (!strncmp(buf, "#FIG 2.1", 8));
  161.  
  162.     line_no++;
  163.     if (get_line(fp) < 0) {
  164.         put_msg("File is truncated");
  165.         return(-1);
  166.         }
  167.     if (2 != sscanf(buf,"%d%d\n", &ppi, &coord_sys)) {
  168.         put_msg("Incomplete data at line %d", line_no);
  169.         return(-1);
  170.         }
  171.  
  172.     obj->nwcorner.x = ppi;
  173.     obj->nwcorner.y = coord_sys;
  174.     while (get_line(fp) > 0) {
  175.         if (1 != sscanf(buf, "%d", &object)) {
  176.         put_msg("Incorrect format at line %d", line_no);
  177.         return(-1);
  178.         }
  179.         switch (object) {
  180.         case O_POLYLINE :
  181.             if ((l = read_lineobject(fp)) == NULL) return(-1);
  182.             if (ll)
  183.             ll = (ll->next = l);
  184.             else 
  185.             ll = obj->lines = l;
  186.             num_object++;
  187.             break;
  188.         case O_SPLINE :
  189.             if ((s = read_splineobject(fp)) == NULL) return(-1);
  190.             if (ls)
  191.             ls = (ls->next = s);
  192.             else 
  193.             ls = obj->splines = s;
  194.             num_object++;
  195.             break;
  196.         case O_ELLIPSE :
  197.             if ((e = read_ellipseobject()) == NULL) return(-1);
  198.             if (le)
  199.             le = (le->next = e);
  200.             else 
  201.             le = obj->ellipses = e;
  202.             num_object++;
  203.             break;
  204.         case O_ARC :
  205.             if ((a = read_arcobject(fp)) == NULL) return(-1);
  206.             if (la)
  207.             la = (la->next = a);
  208.             else 
  209.             la = obj->arcs = a;
  210.             num_object++;
  211.             break;
  212.         case O_TEXT :
  213.             if ((t = read_textobject(fp)) == NULL) return(-1);
  214.             if (lt)
  215.             lt = (lt->next = t);
  216.             else 
  217.             lt = obj->texts = t;
  218.             num_object++;
  219.             break;
  220.         case O_COMPOUND :
  221.             if ((c = read_compoundobject(fp)) == NULL) return(-1);
  222.             if (lc)
  223.             lc = (lc->next = c);
  224.             else 
  225.             lc = obj->compounds = c;
  226.             num_object++;
  227.             break;
  228.         default :
  229.             put_msg("Incorrect object code at line %d", line_no);
  230.             return(-1);
  231.         } /*  switch */
  232.         } /*  while */
  233.     if (feof(fp))
  234.         return(0);
  235.     else
  236.         return(errno);
  237.     } /*  read_objects */
  238.  
  239. static F_arc *
  240. read_arcobject(fp)
  241. FILE    *fp;
  242. {
  243.     F_arc    *a;
  244.     int    n, fa, ba;
  245.     int    type, style;
  246.     double    thickness, wid, ht;
  247.  
  248.     if (NULL == (Arc_malloc(a))) {
  249.         put_msg(Err_mem);
  250.         return(NULL);
  251.         }
  252.     a->pen = 0;
  253.     a->area_fill = 0;
  254.     a->for_arrow = NULL;
  255.     a->back_arrow = NULL;
  256.     a->next = NULL;
  257.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d\n",
  258.         &a->type, &a->style, &a->thickness, 
  259.         &a->color, &a->depth, &a->pen, &a->area_fill, 
  260.         &a->style_val, &a->direction, &fa, &ba,
  261.         &a->center.x, &a->center.y, 
  262.         &a->point[0].x, &a->point[0].y, 
  263.         &a->point[1].x, &a->point[1].y, 
  264.         &a->point[2].x, &a->point[2].y);
  265.     if (n != 19) {
  266.         put_msg(Err_incomp, "arc", line_no);
  267.         free((char*)a);
  268.         return(NULL);
  269.         }
  270.     a->area_fill = FILL_CONVERT(a->area_fill);
  271.     skip_comment(fp);
  272.     if (fa) {
  273.         line_no++;
  274.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  275.         fprintf(stderr, Err_incomp, "arc", line_no);
  276.         return(NULL);
  277.         }
  278.         skip_line(fp);
  279.         a->for_arrow = make_arrow(type, style, thickness, wid, ht);
  280.         skip_comment(fp);
  281.         }
  282.     skip_comment(fp);
  283.     if (ba) {
  284.         line_no++;
  285.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  286.         fprintf(stderr, Err_incomp, "arc", line_no);
  287.         return(NULL);
  288.         }
  289.         skip_line(fp);
  290.         a->back_arrow = make_arrow(type, style, thickness, wid, ht);
  291.         }
  292.     return(a);
  293.     }
  294.  
  295. static F_compound *
  296. read_compoundobject(fp)
  297. FILE    *fp;
  298. {
  299.     F_arc        *a, *la = NULL;
  300.     F_ellipse    *e, *le = NULL;
  301.     F_line        *l, *ll = NULL;
  302.     F_spline    *s, *ls = NULL;
  303.     F_text        *t, *lt = NULL;
  304.     F_compound    *com, *c, *lc = NULL;
  305.     int        n, object;
  306.  
  307.     Compound_malloc(com);
  308.     com->arcs = NULL;
  309.     com->ellipses = NULL;
  310.     com->lines = NULL;
  311.     com->splines = NULL;
  312.     com->texts = NULL;
  313.     com->compounds = NULL;
  314.     com->next = NULL;
  315.     n = sscanf(buf, "%*d%d%d%d%d\n", &com->nwcorner.x, &com->nwcorner.y,
  316.         &com->secorner.x, &com->secorner.y);
  317.     if (4 != n) {
  318.         put_msg(Err_incomp, "compound", line_no);
  319.         free((char*)com);
  320.         return(NULL);
  321.         }
  322.     while (get_line(fp) > 0) {
  323.         if (1 != sscanf(buf, "%d", &object)) {
  324.         put_msg(Err_incomp, "compound", line_no);
  325.         free_compound(&com);
  326.         return(NULL);
  327.         }
  328.         switch (object) {
  329.         case O_POLYLINE :
  330.             if ((l = read_lineobject(fp)) == NULL) { 
  331.             free_line(&l);
  332.             return(NULL);
  333.             }
  334.             if (ll)
  335.             ll = (ll->next = l);
  336.             else 
  337.             ll = com->lines = l;
  338.             break;
  339.         case O_SPLINE :
  340.             if ((s = read_splineobject(fp)) == NULL) { 
  341.             free_spline(&s);
  342.             return(NULL);
  343.             }
  344.             if (ls)
  345.             ls = (ls->next = s);
  346.             else 
  347.             ls = com->splines = s;
  348.             break;
  349.         case O_ELLIPSE :
  350.             if ((e = read_ellipseobject()) == NULL) { 
  351.             free_ellipse(&e);
  352.             return(NULL);
  353.             }
  354.             if (le)
  355.             le = (le->next = e);
  356.             else 
  357.             le = com->ellipses = e;
  358.             break;
  359.         case O_ARC :
  360.             if ((a = read_arcobject(fp)) == NULL) { 
  361.             free_arc(&a);
  362.             return(NULL);
  363.             }
  364.             if (la)
  365.             la = (la->next = a);
  366.             else 
  367.             la = com->arcs = a;
  368.             break;
  369.         case O_TEXT :
  370.             if ((t = read_textobject(fp)) == NULL) { 
  371.             free_text(&t);
  372.             return(NULL);
  373.             }
  374.             if (lt)
  375.             lt = (lt->next = t);
  376.             else 
  377.             lt = com->texts = t;
  378.             break;
  379.         case O_COMPOUND :
  380.             if ((c = read_compoundobject(fp)) == NULL) { 
  381.             free_compound(&c);
  382.             return(NULL);
  383.             }
  384.             if (lc)
  385.             lc = (lc->next = c);
  386.             else 
  387.             lc = com->compounds = c;
  388.             break;
  389.         case O_END_COMPOUND :
  390.             return(com);
  391.         default :
  392.             put_msg("Wrong object code at line %d", line_no);
  393.             return(NULL);
  394.         } /*  switch */
  395.         }
  396.     if (feof(fp))
  397.         return(com);
  398.     else
  399.         return(NULL);
  400.     }
  401.  
  402. static F_ellipse *
  403. read_ellipseobject()
  404. {
  405.     F_ellipse    *e;
  406.     int        n;
  407.  
  408.     Ellipse_malloc(e);
  409.     e->area_fill = 0;
  410.     e->pen = 0;
  411.     e->next = NULL;
  412.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n",
  413.         &e->type, &e->style, &e->thickness,
  414.         &e->color, &e->depth, &e->pen, &e->area_fill,
  415.         &e->style_val, &e->direction, &e->angle,
  416.         &e->center.x, &e->center.y, 
  417.         &e->radiuses.x, &e->radiuses.y, 
  418.         &e->start.x, &e->start.y, 
  419.         &e->end.x, &e->end.y);
  420.     if (n != 18) {
  421.         put_msg(Err_incomp, "ellipse", line_no);
  422.         free((char*)e);
  423.         return(NULL);
  424.         }
  425.     e->area_fill = FILL_CONVERT(e->area_fill);
  426.     return(e);
  427.     }
  428.  
  429. static F_line *
  430. read_lineobject(fp)
  431. FILE    *fp;
  432. {
  433.     F_line    *l;
  434.     F_point    *p, *q;
  435.     int    n, x, y, fa, ba;
  436.     int    type, style, radius_flag;
  437.     double    thickness, wid, ht;
  438.  
  439.     Line_malloc(l);
  440.     l->points = NULL;
  441.     l->pen = 0;
  442.     l->area_fill = 0;
  443.     l->for_arrow = NULL;
  444.     l->back_arrow = NULL;
  445.     l->next = NULL;
  446.  
  447.     sscanf(buf,"%*d%d",&l->type);    /* get the line type */
  448.  
  449.     radius_flag = v21_flag || (v2_flag && l->type == T_ARC_BOX);
  450.     if (radius_flag)
  451.         {
  452.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d",
  453.         &l->type, &l->style, &l->thickness, &l->color,
  454.         &l->depth, &l->pen, &l->area_fill, &l->style_val, &l->radius, &fa, &ba);
  455.         }
  456.     /* old format uses pen for radius of arc-box corners */
  457.     else
  458.         {
  459.         n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
  460.         &l->type, &l->style, &l->thickness, &l->color,
  461.         &l->depth, &l->pen, &l->area_fill, &l->style_val, &fa, &ba);
  462.         if (l->type == T_ARC_BOX)
  463.         {
  464.         l->radius = (int) l->pen;
  465.         l->pen = 0;
  466.         }
  467.         else
  468.         l->radius = 0;
  469.         }
  470.     if ((!radius_flag && n!=10) || (radius_flag && n!=11)) {
  471.         put_msg(Err_incomp, "line", line_no);
  472.         free((char*)l);
  473.         return(NULL);
  474.         }
  475.     l->area_fill = FILL_CONVERT(l->area_fill);
  476.     skip_comment(fp);
  477.     if (fa) {
  478.         line_no++;
  479.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  480.         fprintf(stderr, Err_incomp, "line", line_no);
  481.         return(NULL);
  482.         }
  483.         skip_line(fp);
  484.         l->for_arrow = make_arrow(type, style, thickness, wid, ht);
  485.         skip_comment(fp);
  486.         }
  487.     if (ba) {
  488.         line_no++;
  489.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  490.         fprintf(stderr, Err_incomp, "line", line_no);
  491.         return(NULL);
  492.         }
  493.         skip_line(fp);
  494.         l->back_arrow = make_arrow(type, style, thickness, wid, ht);
  495.         skip_comment(fp);
  496.         }
  497.         if (l->type == T_EPS_BOX) {
  498.         line_no++;
  499.         Eps_malloc(l->eps);
  500.         if (l->eps  == NULL) {
  501.             free((char *) l);
  502.             return (NULL);
  503.         }
  504.         if (2 != fscanf(fp, "%d %s", &l->eps->flipped, l->eps->file)) {
  505.                 put_msg(Err_incomp,
  506.                 "Encapsulated Postscript", line_no);
  507.                 fprintf(stderr, Err_incomp,
  508.                 "Encapsulated Postscript", line_no);
  509.             return (NULL);
  510.         }
  511.         read_epsf(l->eps);
  512.         } else
  513.         l->eps = NULL;
  514.  
  515.     if (NULL == (l->points = Point_malloc(p))) {
  516.         put_msg(Err_mem);
  517.         return(NULL);
  518.         }
  519.     p->next = NULL;
  520.     if (fscanf(fp, "%d%d", &p->x, &p->y) != 2) {
  521.         put_msg(Err_incomp, "line", line_no);
  522.         free_linestorage(l);
  523.         return(NULL);
  524.         }
  525.     for (;;) {
  526.         if (fscanf(fp, "%d%d", &x, &y) != 2) {
  527.         put_msg(Err_incomp, "line", line_no);
  528.         free_linestorage(l);
  529.         return(NULL);
  530.         }
  531.         if (x == 9999) break;
  532.         if (NULL == (Point_malloc(q))) {
  533.         put_msg(Err_mem);
  534.         free_linestorage(l);
  535.         return(NULL);
  536.         }
  537.         q->x = x;
  538.         q->y = y;
  539.         q->next = NULL;
  540.         p->next = q;
  541.         p = q;
  542.         }
  543.     skip_line(fp);
  544.     return(l);
  545.     }
  546.  
  547. static F_spline *
  548. read_splineobject(fp)
  549. FILE    *fp;
  550. {
  551.     F_spline    *s;
  552.     F_point        *p, *q;
  553.     F_control    *cp, *cq;
  554.     int        c, n, x, y, fa, ba;
  555.     int        type, style;
  556.     double        thickness, wid, ht;
  557.     double        lx, ly, rx, ry;
  558.  
  559.     Spline_malloc(s);
  560.     s->points = NULL;
  561.     s->controls = NULL;
  562.     s->pen = 0;
  563.     s->area_fill = 0;
  564.     s->for_arrow = NULL;
  565.     s->back_arrow = NULL;
  566.     s->next = NULL;
  567.  
  568.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
  569.             &s->type, &s->style, &s->thickness, &s->color,
  570.         &s->depth, &s->pen, &s->area_fill, &s->style_val, &fa, &ba);
  571.     if (n != 10) {
  572.         put_msg(Err_incomp, "spline", line_no);
  573.         free((char*)s);
  574.         return(NULL);
  575.         }
  576.     s->area_fill = FILL_CONVERT(s->area_fill);
  577.     skip_comment(fp);
  578.     if (fa) {
  579.         line_no++;
  580.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  581.         fprintf(stderr, Err_incomp, "spline", line_no);
  582.         return(NULL);
  583.         }
  584.         skip_line(fp);
  585.         s->for_arrow = make_arrow(type, style, thickness, wid, ht);
  586.         skip_comment(fp);
  587.         }
  588.     if (ba) {
  589.         line_no++;
  590.         if (5 != fscanf(fp, "%d%d%lf%lf%lf", &type, &style, &thickness, &wid, &ht)) {
  591.         fprintf(stderr, Err_incomp, "spline", line_no);
  592.         return(NULL);
  593.         }
  594.         skip_line(fp);
  595.         s->back_arrow = make_arrow(type, style, thickness, wid, ht);
  596.         skip_comment(fp);
  597.         }
  598.  
  599.     /* Read points */
  600.     if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) {
  601.         put_msg(Err_incomp, "spline", line_no);
  602.         free_splinestorage(s);
  603.         return(NULL);
  604.         };
  605.     if (NULL == (s->points = Point_malloc(p))) {
  606.         put_msg(Err_mem);
  607.         free_splinestorage(s);
  608.         return(NULL);
  609.         }
  610.     p->x = x; p->y = y;
  611.     for (c = 1;;) {
  612.         if (fscanf(fp, "%d%d", &x, &y) != 2) {
  613.         put_msg(Err_incomp, "spline", line_no);
  614.         p->next = NULL;
  615.         free_splinestorage(s);
  616.         return(NULL);
  617.         };
  618.         if (x == 9999) break;
  619.         if (NULL == (Point_malloc(q))) {
  620.         put_msg(Err_mem);
  621.         free_splinestorage(s);
  622.         return(NULL);
  623.         }
  624.         q->x = x;
  625.         q->y = y;
  626.         p->next = q;
  627.         p = q;
  628.         c++;
  629.         }
  630.     p->next = NULL;
  631.     skip_line(fp);
  632.  
  633.     if (normal_spline(s)) return(s);
  634.  
  635.     skip_comment(fp);
  636.     /* Read controls */
  637.     if ((n = fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry)) != 4) {
  638.         put_msg(Err_incomp, "spline", line_no);
  639.         free_splinestorage(s);
  640.         return(NULL);
  641.         };
  642.     if (NULL == (s->controls = Control_malloc(cp))) {
  643.         put_msg(Err_mem);
  644.         free_splinestorage(s);
  645.         return(NULL);
  646.         }
  647.     cp->lx = lx; cp->ly = ly;
  648.     cp->rx = rx; cp->ry = ry;
  649.     while (--c) {
  650.         if (fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry) != 4) {
  651.         put_msg(Err_incomp, "spline", line_no);
  652.         cp->next = NULL;
  653.         free_splinestorage(s);
  654.         return(NULL);
  655.         };
  656.         if (NULL == (Control_malloc(cq))) {
  657.         put_msg(Err_mem);
  658.         cp->next = NULL;
  659.         free_splinestorage(s);
  660.         return(NULL);
  661.         }
  662.         cq->lx = lx; cq->ly = ly;
  663.         cq->rx = rx; cq->ry = ry;
  664.         cp->next = cq;
  665.         cp = cq;
  666.         }
  667.     cp->next = NULL;
  668.  
  669.     skip_line(fp);
  670.     return(s);
  671.     }
  672.  
  673. static F_text *
  674. read_textobject(fp)
  675. FILE    *fp;
  676. {
  677.     F_text    *t;
  678.     int    n, ignore = 0;
  679.     char    s[BUF_SIZE], s_temp[BUF_SIZE], junk[2];
  680.  
  681.     Text_malloc(t);
  682.     t->font = 0;
  683.     t->size = 0.0;
  684.     t->next = NULL;
  685.     /* The text object is terminated by a CONTROL-A, so we read
  686.        everything up to the CONTROL-A and then read that character.
  687.        If we do not find the CONTROL-A on this line then this must
  688.        be a multi-line text object and we will have to read more. */
  689.     n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%[\1]",
  690.         &t->type, &t->font, &t->size, &t->pen,
  691.         &t->color, &t->depth, &t->angle,
  692.         &t->flags, &t->height, &t->length, 
  693.         &t->base_x, &t->base_y, s, junk);
  694.     if ((n != 14) && (n != 13)) {
  695.       put_msg(Err_incomp, "text", line_no);
  696.       free((char*)t);
  697. /*       return(NULL); */
  698.     }
  699.     if (n == 13) {
  700.       /* Read in the remainder of the text object. */
  701.       do {
  702.         fgets(buf, BUF_SIZE, fp);
  703.         line_no++;  /* As is done in get_line */
  704.         n = sscanf(buf,"%[^\1]%[\1]", s_temp, junk);
  705.         /* Safety check */
  706.         if (strlen(s)+1 + strlen(s_temp)+1 > BUF_SIZE) {
  707.           /* Too many characters.  Ignore the rest. */
  708.           ignore = 1;
  709.         }
  710.         if (!ignore)
  711.           strcat(s, s_temp);
  712.       } while (n == 1);
  713.     }
  714.     if (strlen(s) == 0) (void)strcpy(s, " ");
  715.     t->cstring = (char*)calloc((unsigned)(strlen(s)), sizeof(char));
  716.     if (NULL == t->cstring) {
  717.         put_msg(Err_mem);
  718.         free((char*)t);
  719.         return(NULL);
  720.         }
  721.     (void)strcpy(t->cstring, s+1);
  722.  
  723.     if (!v21_flag && (t->font == 0 || t->font == DEFAULT))
  724.         t->flags = ((t->flags != DEFAULT) ? t->flags : 0)
  725.                 | SPECIAL_TEXT;
  726.  
  727.     if (v2_flag && !v21_flag && !special_text(t)) 
  728.         t->flags = ((t->flags != DEFAULT) ? t->flags : 0)
  729.                 | PSFONT_TEXT;
  730.  
  731.     return(t);
  732.       }
  733.  
  734. get_line(fp)
  735. FILE    *fp;
  736. {
  737.     while (1) {
  738.         if (NULL == fgets(buf, BUF_SIZE, fp)) {
  739.         return(-1);
  740.         }
  741.         line_no++;
  742.         if (*buf != '\n' && *buf != '#') return(1);
  743.             /* Skip empty and comment lines */
  744.         }
  745.     }
  746.  
  747. skip_comment(fp)
  748. FILE    *fp;
  749. {
  750.     char c;
  751.  
  752.     while ((c = fgetc(fp)) == '#') skip_line(fp);
  753.     if (c != '#') ungetc(c, fp);
  754.     }
  755.  
  756. skip_line(fp)
  757. FILE    *fp;
  758. {
  759.     while (fgetc(fp) != '\n') {
  760.         if (feof(fp)) return;
  761.         }
  762.     }
  763.  
  764. read_epsf(eps)
  765.     F_eps          *eps;
  766. {
  767.     int             nbitmap;
  768.     int             bitmapz;
  769.     char           *cp;
  770.     unsigned char  *mp;
  771.     int             n;
  772.     int             flag;
  773.     char            buf[300];
  774.     int             llx, lly, urx, ury;
  775.     FILE           *epsf;
  776.     register unsigned char *last;
  777.     double          fllx, flly, furx, fury;
  778.  
  779.     epsf = fopen(eps->file, "r");
  780.     if (epsf == NULL) {
  781.     put_msg("Cannot open file: %s", eps->file);
  782.     return 0;
  783.     }
  784.     while (fgets(buf, 300, epsf) != NULL) {
  785.     lower(buf);
  786.     if (!strncmp(buf, "%%boundingbox", 13)) {
  787.         if (sscanf(buf, "%%%%boundingbox: %lf %lf %lf %lf",
  788.                &fllx, &flly, &furx, &fury) < 4) {
  789.         put_msg("Bad EPS bitmap file: %s", eps->file);
  790.         fclose(epsf);
  791.         return 0;
  792.         }
  793.           llx= floor(fllx);
  794.           lly= floor(flly);
  795.           urx= ceil(furx);
  796.           ury= ceil(fury);
  797.         break;
  798.     }
  799.     }
  800.  
  801.     eps->hw_ratio = (float) (ury - lly) / (float) (urx - llx);
  802.  
  803.     eps->bitmap = NULL;
  804.     eps->bit_size.x = 0;
  805.     eps->bit_size.y = 0;
  806.  
  807.     eps->pix_rotation = 0;
  808.     eps->pix_width = 0;
  809.     eps->pix_height = 0;
  810.  
  811.     if (ury - lly <= 0 || urx - llx <= 0) {
  812.     put_msg("Bad values in EPS bitmap bounding box");
  813.     }
  814.     bitmapz = 0;
  815.  
  816.     /* look for a preview bitmap */
  817.     while (fgets(buf, 300, epsf) != NULL) {
  818.     lower(buf);
  819.     if (!strncmp(buf, "%%beginpreview", 14)) {
  820.         sscanf(buf, "%%%%beginpreview: %d %d %d",
  821.            &eps->bit_size.x, &eps->bit_size.y, &bitmapz);
  822.         break;
  823.     }
  824.     }
  825.  
  826.     if (eps->bit_size.x > 0 && eps->bit_size.y > 0 && bitmapz == 1) {
  827.     nbitmap = (eps->bit_size.x + 7) / 8 * eps->bit_size.y;
  828.     eps->bitmap = (unsigned char *) malloc(nbitmap);
  829.     if (eps->bitmap == NULL)
  830.         fprintf(stderr, "could not allocate %d bytes of memory\n", nbitmap);
  831.     }
  832.     /* read for a preview bitmap */
  833.     if (eps->bitmap != NULL) {
  834.     mp = eps->bitmap;
  835.     bzero(mp, nbitmap);    /* init bitmap to zero */
  836.     last = eps->bitmap + nbitmap;
  837.     flag = 1;
  838.     while (fgets(buf, 300, epsf) != NULL && mp < last) {
  839.         lower(buf);
  840.         if (!strncmp(buf, "%%endpreview", 12) ||
  841.         !strncmp(buf, "%%endimage", 10))
  842.         break;
  843.         cp = buf;
  844.         if (*cp != '%')
  845.         break;
  846.         cp++;
  847.         while (*cp != '\0') {
  848.         if (isxdigit(*cp)) {
  849.             n = hex(*cp);
  850.             if (flag) {
  851.             flag = 0;
  852.             *mp = n << 4;
  853.             } else {
  854.             flag = 1;
  855.             *mp = *mp + n;
  856.             mp++;
  857.             if (mp >= last)
  858.                 break;
  859.             }
  860.         }
  861.         cp++;
  862.         }
  863.     }
  864.     }
  865.     fclose(epsf);
  866.     return 1;
  867. }
  868.  
  869. int
  870. hex(c)
  871.     char            c;
  872. {
  873.     if (isdigit(c))
  874.     return (c - 48);
  875.     else
  876.     return (c - 87);
  877. }
  878.  
  879. lower(buf)
  880.     char           *buf;
  881. {
  882.     while (*buf) {
  883.     if (isupper(*buf))
  884.         *buf = (char) tolower(*buf);
  885.     buf++;
  886.     }
  887. }
  888.