home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume19 / xfig / part17 / f_read.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-27  |  27.5 KB  |  1,113 lines

  1. /*
  2.  * FIG : Facility for Interactive Generation of figures
  3.  * Copyright (c) 1985 by Supoj Sutanthavibul
  4.  *
  5.  * "Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both the copyright
  8.  * notice and this permission notice appear in supporting documentation. 
  9.  * No representations are made about the suitability of this software for 
  10.  * any purpose.  It is provided "as is" without express or implied warranty."
  11.  */
  12.  
  13. #include "fig.h"
  14. #include "figx.h"
  15. #include "resources.h"
  16. #include "object.h"
  17. #include "mode.h"
  18. #include "u_fonts.h"
  19. #include "u_create.h"
  20. #include "version.h"
  21. #include "w_setup.h"
  22. #include "w_util.h"
  23. #include "w_zoom.h"
  24.  
  25. /* file popup information */
  26. extern Widget    file_popup;    /* the popup itself */
  27. extern Boolean    file_up;
  28.  
  29. /* so w_file.c can access */
  30. Boolean    file_msg_is_popped=False;
  31. Widget    file_msg_popup;
  32.  
  33. static Widget    file_msg_panel,
  34.         file_msg_win, file_msg_dismiss;
  35. static Boolean    first_file_msg;
  36. static int    file_msg_length=0;
  37. static char    *read_file_name;
  38. static char    tmpstr[100];
  39.  
  40. static String    file_msg_translations =
  41.     "<Message>WM_PROTOCOLS: DismissFileMsg()\n";
  42. static XtEventHandler file_msg_panel_dismiss();
  43. static XtActionsRec    file_msg_actions[] =
  44. {
  45.     {"DismissFileMsg", (XtActionProc) file_msg_panel_dismiss},
  46. };
  47.  
  48. static char    Err_incomp[] = "Incomplete %s object at line %d.";
  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.             (((proto>=20) || (f) == UNFILLED || !TFX) \
  59.                 ? (f) : (!TFX? 21 - ((f)-1)*5: 0))
  60.  
  61. #define        BUF_SIZE        1024
  62.  
  63. DeclareStaticArgs(10);
  64. char        buf[BUF_SIZE];
  65. int        line_no;
  66. int        num_object;
  67. int        proto;        /* file protocol*10 */
  68. int        TFX;        /* true for 1.4TFX protocol */
  69.  
  70. read_fail_message(file, err)
  71.     char       *file;
  72.     int            err;
  73. {
  74.     if (err == 0)        /* Successful read */
  75.     return;
  76. #ifdef ENAMETOOLONG
  77.     else if (err == ENAMETOOLONG)
  78.     file_msg("File name \"%s\" is too long", file);
  79. #endif
  80.     else if (err == ENOENT)
  81.     file_msg("File \"%s\" does not exist", file);
  82.     else if (err == ENOTDIR)
  83.     file_msg("A name in the path \"%s\" is not a directory", file);
  84.     else if (err == EACCES)
  85.     file_msg("Read access to file \"%s\" is blocked", file);
  86.     else if (err == EISDIR)
  87.     file_msg("File \"%s\" is a directory", file);
  88.     else if (err == -2) {
  89.     file_msg("File \"%s\" is empty", file);
  90.     } else if (err == -1) {
  91.     /* Format error; relevant error message is already delivered */
  92.     } else
  93.     file_msg("File \"%s\" is not accessable; %s", file, sys_errlist[err]);
  94. }
  95.  
  96. /**********************************************************
  97. Read_fig returns :
  98.  
  99.      0 : successful read.
  100.     -1 : File is in incorrect format
  101.     -2 : File is empty
  102. err_no : if file can not be read for various reasons
  103.  
  104. The resolution (ppi) and the coordinate system (coord_sys) are
  105. stored in obj->nwcorner.x and obj->nwcorner.y respectively.
  106. The coordinate system is 1 for lower left at 0,0 and
  107. 2 for upper left at 0,0
  108. >>> xfig only uses 2 for the coordinate system. <<<
  109. **********************************************************/
  110.  
  111. read_fig(file_name, obj)
  112.     char       *file_name;
  113.     F_compound       *obj;
  114. {
  115.     FILE       *fp;
  116.  
  117.     line_no = 0;
  118.     read_file_name = file_name;
  119.     first_file_msg = True;
  120.     if ((fp = fopen(file_name, "r")) == NULL)
  121.     return (errno);
  122.     else {
  123.     put_msg("Reading objects from \"%s\" ...", file_name);
  124.     return (readfp_fig(fp, obj));
  125.     }
  126. }
  127.  
  128. readfp_fig(fp, obj)
  129.     FILE       *fp;
  130.     F_compound       *obj;
  131. {
  132.     int            status;
  133.     float        fproto;
  134.     char        tmpstr[10];
  135.  
  136.     num_object = 0;
  137.     bzero(obj, COMOBJ_SIZE);
  138.     if (fgets(buf, BUF_SIZE, fp) == 0)    /* version */
  139.     return -2;
  140.     if (strncmp(buf, "#FIG", 4) == 0) { /* versions 1.4/later have #FIG in
  141.                      * first line */
  142.     if ((sscanf((char*)(index(buf, ' ') + 1), "%f", &fproto)) == 0)    /* assume 1.4 */
  143.         proto = 14;
  144.     else
  145.         proto = (fproto + .01) * 10;    /* protocol version*10 */
  146.     /* if file protocol != current protocol, give message */
  147.     sprintf(tmpstr,"%.1f",fproto);
  148.     if (strcmp(tmpstr,PROTOCOL_VERSION) != 0)
  149.         file_msg("Converting figure from %s format to %s",tmpstr,PROTOCOL_VERSION);
  150.     TFX = False;
  151.     if (strstr(buf, "TFX") != NULL)
  152.         TFX = True;
  153.     status = read_objects(fp, obj);
  154.     } else {
  155.     file_msg("Converting figure from 1.3 format to %s",PROTOCOL_VERSION);
  156.     proto = 13;
  157.     status = read_1_3_objects(fp, obj);
  158.     }
  159.  
  160.     /* shift the figure on the page if there are negative coords */
  161.     /**** DISABLE UNTIL WE PUT IN AN *OPTION* TO DO THIS */
  162.     /* shift_figure(obj); */
  163.  
  164.     fclose(fp);
  165.     return (status);
  166. }
  167.  
  168. int
  169. read_objects(fp, obj)
  170.     FILE       *fp;
  171.     F_compound       *obj;
  172. {
  173.     F_ellipse       *e, *le = NULL;
  174.     F_line       *l, *ll = NULL;
  175.     F_text       *t, *lt = NULL;
  176.     F_spline       *s, *ls = NULL;
  177.     F_arc       *a, *la = NULL;
  178.     F_compound       *c, *lc = NULL;
  179.     int            object, ppi, coord_sys;
  180.  
  181.     line_no++;
  182.     if (get_line(fp) < 0) {
  183.     file_msg("File is truncated");
  184.     return (-1);
  185.     }
  186.     if (2 != sscanf(buf, "%d%d\n", &ppi, &coord_sys)) {
  187.     file_msg("Incomplete data at line %d", line_no);
  188.     return (-1);
  189.     }
  190.     obj->nwcorner.x = ppi;
  191.     obj->nwcorner.y = coord_sys;
  192.     while (get_line(fp) > 0) {
  193.     if (1 != sscanf(buf, "%d", &object)) {
  194.         file_msg("Incorrect format at line %d", line_no);
  195.         return (-1);
  196.     }
  197.     switch (object) {
  198.     case O_POLYLINE:
  199.         if ((l = read_lineobject(fp)) == NULL)
  200.         return (-1);
  201.         if (ll)
  202.         ll = (ll->next = l);
  203.         else
  204.         ll = obj->lines = l;
  205.         num_object++;
  206.         break;
  207.     case O_SPLINE:
  208.         if ((s = read_splineobject(fp)) == NULL)
  209.         return (-1);
  210.         if (ls)
  211.         ls = (ls->next = s);
  212.         else
  213.         ls = obj->splines = s;
  214.         num_object++;
  215.         break;
  216.     case O_ELLIPSE:
  217.         if ((e = read_ellipseobject()) == NULL)
  218.         return (-1);
  219.         if (le)
  220.         le = (le->next = e);
  221.         else
  222.         le = obj->ellipses = e;
  223.         num_object++;
  224.         break;
  225.     case O_ARC:
  226.         if ((a = read_arcobject(fp)) == NULL)
  227.         return (-1);
  228.         if (la)
  229.         la = (la->next = a);
  230.         else
  231.         la = obj->arcs = a;
  232.         num_object++;
  233.         break;
  234.     case O_TEXT:
  235.         if ((t = read_textobject(fp)) == NULL)
  236.         continue;
  237.         /*return (-1);*/
  238.         if (lt)
  239.         lt = (lt->next = t);
  240.         else
  241.         lt = obj->texts = t;
  242.         num_object++;
  243.         break;
  244.     case O_COMPOUND:
  245.         if ((c = read_compoundobject(fp)) == NULL)
  246.         return (-1);
  247.         if (lc)
  248.         lc = (lc->next = c);
  249.         else
  250.         lc = obj->compounds = c;
  251.         num_object++;
  252.         break;
  253.     default:
  254.         file_msg("Incorrect object code at line %d", line_no);
  255.         return (-1);
  256.     }            /* switch */
  257.     }                /* while */
  258.     if (feof(fp))
  259.     return (0);
  260.     else
  261.     return (errno);
  262. }                /* read_objects */
  263.  
  264. static F_arc   *
  265. read_arcobject(fp)
  266.     FILE       *fp;
  267. {
  268.     F_arc       *a;
  269.     int            n, fa, ba;
  270.     int            type, style;
  271.     float        thickness, wid, ht;
  272.  
  273.     if ((a = create_arc()) == NULL)
  274.     return (NULL);
  275.  
  276.     a->next = NULL;
  277.     a->for_arrow = a->back_arrow = NULL;    /* added 8/23/89 B.V.Smith */
  278.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%f%d%d%d%f%f%d%d%d%d%d%d\n",
  279.            &a->type, &a->style, &a->thickness,
  280.            &a->color, &a->depth,
  281.            &a->pen, &a->fill_style,
  282.            &a->style_val, &a->direction, &fa, &ba,
  283.            &a->center.x, &a->center.y,
  284.            &a->point[0].x, &a->point[0].y,
  285.            &a->point[1].x, &a->point[1].y,
  286.            &a->point[2].x, &a->point[2].y);
  287.     if (n != 19) {
  288.     file_msg(Err_incomp, "arc", line_no);
  289.     free((char *) a);
  290.     return (NULL);
  291.     }
  292.     a->fill_style = FILL_CONVERT(a->fill_style);
  293.     fixdepth(&a->depth);
  294.     skip_comment(fp);
  295.     if (fa) {
  296.     line_no++;
  297.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  298.         fprintf(stderr, Err_incomp, "arc", line_no);
  299.         return (NULL);
  300.     }
  301.     skip_line(fp);
  302.     a->for_arrow = new_arrow(type, style, thickness, wid, ht);
  303.     skip_comment(fp);
  304.     }
  305.     skip_comment(fp);
  306.     if (ba) {
  307.     line_no++;
  308.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  309.         fprintf(stderr, Err_incomp, "arc", line_no);
  310.         return (NULL);
  311.     }
  312.     skip_line(fp);
  313.     a->back_arrow = new_arrow(type, style, thickness, wid, ht);
  314.     }
  315.     return (a);
  316. }
  317.  
  318. static F_compound *
  319. read_compoundobject(fp)
  320.     FILE       *fp;
  321. {
  322.     F_arc       *a, *la = NULL;
  323.     F_ellipse       *e, *le = NULL;
  324.     F_line       *l, *ll = NULL;
  325.     F_spline       *s, *ls = NULL;
  326.     F_text       *t, *lt = NULL;
  327.     F_compound       *com, *c, *lc = NULL;
  328.     int            n, object;
  329.  
  330.     if ((com = create_compound()) == NULL)
  331.     return (NULL);
  332.  
  333.     com->arcs = NULL;
  334.     com->ellipses = NULL;
  335.     com->lines = NULL;
  336.     com->splines = NULL;
  337.     com->texts = NULL;
  338.     com->compounds = NULL;
  339.     com->next = NULL;
  340.     n = sscanf(buf, "%*d%d%d%d%d\n", &com->nwcorner.x, &com->nwcorner.y,
  341.            &com->secorner.x, &com->secorner.y);
  342.     if (4 != n) {
  343.     file_msg(Err_incomp, "compound", line_no);
  344.     free((char *) com);
  345.     return (NULL);
  346.     }
  347.     while (get_line(fp) > 0) {
  348.     if (1 != sscanf(buf, "%d", &object)) {
  349.         file_msg(Err_incomp, "compound", line_no);
  350.         free_compound(&com);
  351.         return (NULL);
  352.     }
  353.     switch (object) {
  354.     case O_POLYLINE:
  355.         if ((l = read_lineobject(fp)) == NULL) {
  356.         free_line(&l);
  357.         return (NULL);
  358.         }
  359.         if (ll)
  360.         ll = (ll->next = l);
  361.         else
  362.         ll = com->lines = l;
  363.         break;
  364.     case O_SPLINE:
  365.         if ((s = read_splineobject(fp)) == NULL) {
  366.         free_spline(&s);
  367.         return (NULL);
  368.         }
  369.         if (ls)
  370.         ls = (ls->next = s);
  371.         else
  372.         ls = com->splines = s;
  373.         break;
  374.     case O_ELLIPSE:
  375.         if ((e = read_ellipseobject()) == NULL) {
  376.         free_ellipse(&e);
  377.         return (NULL);
  378.         }
  379.         if (le)
  380.         le = (le->next = e);
  381.         else
  382.         le = com->ellipses = e;
  383.         break;
  384.     case O_ARC:
  385.         if ((a = read_arcobject(fp)) == NULL) {
  386.         free_arc(&a);
  387.         return (NULL);
  388.         }
  389.         if (la)
  390.         la = (la->next = a);
  391.         else
  392.         la = com->arcs = a;
  393.         break;
  394.     case O_TEXT:
  395.         if ((t = read_textobject(fp)) == NULL) {
  396.         free_text(&t);
  397.         return (NULL);
  398.         }
  399.         if (lt)
  400.         lt = (lt->next = t);
  401.         else
  402.         lt = com->texts = t;
  403.         break;
  404.     case O_COMPOUND:
  405.         if ((c = read_compoundobject(fp)) == NULL) {
  406.         free_compound(&c);
  407.         return (NULL);
  408.         }
  409.         if (lc)
  410.         lc = (lc->next = c);
  411.         else
  412.         lc = com->compounds = c;
  413.         break;
  414.     case O_END_COMPOUND:
  415.         return (com);
  416.     default:
  417.         file_msg("Incorrect object code at line %d", line_no);
  418.         return (NULL);
  419.     }            /* switch */
  420.     }
  421.     if (feof(fp))
  422.     return (com);
  423.     else
  424.     return (NULL);
  425. }
  426.  
  427. static F_ellipse *
  428. read_ellipseobject()
  429. {
  430.     F_ellipse       *e;
  431.     int            n;
  432.  
  433.     if ((e = create_ellipse()) == NULL)
  434.     return (NULL);
  435.  
  436.     e->next = NULL;
  437.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%f%d%f%d%d%d%d%d%d%d%d\n",
  438.            &e->type, &e->style, &e->thickness,
  439.            &e->color, &e->depth, &e->pen, &e->fill_style,
  440.            &e->style_val, &e->direction, &e->angle,
  441.            &e->center.x, &e->center.y,
  442.            &e->radiuses.x, &e->radiuses.y,
  443.            &e->start.x, &e->start.y,
  444.            &e->end.x, &e->end.y);
  445.     if (n != 18) {
  446.     file_msg(Err_incomp, "ellipse", line_no);
  447.     free((char *) e);
  448.     return (NULL);
  449.     }
  450.     e->fill_style = FILL_CONVERT(e->fill_style);
  451.     fixdepth(&e->depth);
  452.     return (e);
  453. }
  454.  
  455. static F_line  *
  456. read_lineobject(fp)
  457.     FILE       *fp;
  458. {
  459.     F_line       *l;
  460.     F_point       *p, *q;
  461.     int            n, x, y, fa, ba;
  462.     int            type, style, radius_flag;
  463.     float        thickness, wid, ht;
  464.  
  465.     if ((l = create_line()) == NULL)
  466.     return (NULL);
  467.  
  468.     l->points = NULL;
  469.     l->for_arrow = l->back_arrow = NULL;
  470.     l->next = NULL;
  471.  
  472.     sscanf(buf, "%*d%d", &l->type);
  473.  
  474.     /* 2.1 or later has radius parm for all line objects */
  475.     /* 2.0 has radius parm only for arc-box objects */
  476.     radius_flag = ((proto >= 21) || (l->type == T_ARC_BOX && proto == 20));
  477.     if (radius_flag) {
  478.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%f%d%d%d",
  479.            &l->type, &l->style, &l->thickness, &l->color, &l->depth,
  480.           &l->pen, &l->fill_style, &l->style_val, &l->radius, &fa, &ba);
  481.     } else {            /* old format uses pen for radius of arc-box
  482.                  * corners */
  483.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%f%d%d",
  484.            &l->type, &l->style, &l->thickness, &l->color,
  485.            &l->depth, &l->pen, &l->fill_style, &l->style_val, &fa, &ba);
  486.     if (l->type == T_ARC_BOX) {
  487.         l->radius = l->pen;
  488.         l->pen = 0;
  489.     } else
  490.         l->radius = 0;
  491.     }
  492.     if ((!radius_flag && n != 10) || (radius_flag && n != 11)) {
  493.     file_msg(Err_incomp, "line", line_no);
  494.     free((char *) l);
  495.     return (NULL);
  496.     }
  497.     l->fill_style = FILL_CONVERT(l->fill_style);
  498.     fixdepth(&l->depth);
  499.     skip_comment(fp);
  500.     if (fa) {
  501.     line_no++;
  502.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  503.         fprintf(stderr, Err_incomp, "line", line_no);
  504.         return (NULL);
  505.     }
  506.     skip_line(fp);
  507.     l->for_arrow = new_arrow(type, style, thickness, wid, ht);
  508.     skip_comment(fp);
  509.     }
  510.     if (ba) {
  511.     line_no++;
  512.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  513.         fprintf(stderr, Err_incomp, "line", line_no);
  514.         return (NULL);
  515.     }
  516.     skip_line(fp);
  517.     l->back_arrow = new_arrow(type, style, thickness, wid, ht);
  518.     skip_comment(fp);
  519.     }
  520.     if (l->type == T_EPS_BOX) {
  521.     line_no++;
  522.     if ((l->eps = create_eps()) == NULL) {
  523.         free((char *) l);
  524.         return (NULL);
  525.     }
  526.     if (2 != fscanf(fp, "%d %s", &l->eps->flipped, l->eps->file)) {
  527.         file_msg(Err_incomp, "Encapsulated Postscript", line_no);
  528.         fprintf(stderr, Err_incomp, "Encapsulated Postscript", line_no);
  529.         return (NULL);
  530.     }
  531.     read_epsf(l->eps);
  532.     } else
  533.     l->eps = NULL;
  534.  
  535.     /* points start on new line */
  536.     line_no++;
  537.     if ((p = create_point()) == NULL)
  538.     return (NULL);
  539.  
  540.     l->points = p;
  541.     p->next = NULL;
  542.  
  543.     /* read first point */
  544.     if (fscanf(fp, "%d%d", &p->x, &p->y) != 2) {
  545.     file_msg(Err_incomp, "line", line_no);
  546.     free_linestorage(l);
  547.     return (NULL);
  548.     }
  549.     /* read subsequent points */
  550.     for (;;) {
  551.     if (fscanf(fp, "%d%d", &x, &y) != 2) {
  552.         file_msg(Err_incomp, "line", line_no);
  553.         free_linestorage(l);
  554.         return (NULL);
  555.     }
  556.     if (x == 9999)
  557.         break;
  558.     if ((q = create_point()) == NULL) {
  559.         free_linestorage(l);
  560.         return (NULL);
  561.     }
  562.     q->x = x;
  563.     q->y = y;
  564.     q->next = NULL;
  565.     p->next = q;
  566.     p = q;
  567.     }
  568.     skip_line(fp);
  569.     return (l);
  570. }
  571.  
  572. static F_spline *
  573. read_splineobject(fp)
  574.     FILE       *fp;
  575. {
  576.     F_spline       *s;
  577.     F_point       *p, *q;
  578.     F_control       *cp, *cq;
  579.     int            c, n, x, y, fa, ba;
  580.     int            type, style;
  581.     float        thickness, wid, ht;
  582.     float        lx, ly, rx, ry;
  583.  
  584.     if ((s = create_spline()) == NULL)
  585.     return (NULL);
  586.  
  587.     s->points = NULL;
  588.     s->controls = NULL;
  589.     s->for_arrow = s->back_arrow = NULL;
  590.     s->next = NULL;
  591.  
  592.     n = sscanf(buf, "%*d%d%d%d%d%d%d%d%f%d%d%d%d%d%d",
  593.            &s->type, &s->style, &s->thickness, &s->color,
  594.            &s->depth, &s->pen, &s->fill_style, &s->style_val, &fa, &ba);
  595.     if (n != 10) {
  596.     file_msg(Err_incomp, "spline", line_no);
  597.     free((char *) s);
  598.     return (NULL);
  599.     }
  600.     s->fill_style = FILL_CONVERT(s->fill_style);
  601.     fixdepth(&s->depth);
  602.     skip_comment(fp);
  603.     if (fa) {
  604.     line_no++;
  605.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  606.         fprintf(stderr, Err_incomp, "spline", line_no);
  607.         return (NULL);
  608.     }
  609.     skip_line(fp);
  610.     s->for_arrow = new_arrow(type, style, thickness, wid, ht);
  611.     skip_comment(fp);
  612.     }
  613.     if (ba) {
  614.     line_no++;
  615.     if (5 != fscanf(fp, "%d%d%f%f%f", &type, &style, &thickness, &wid, &ht)) {
  616.         fprintf(stderr, Err_incomp, "spline", line_no);
  617.         return (NULL);
  618.     }
  619.     skip_line(fp);
  620.     s->back_arrow = new_arrow(type, style, thickness, wid, ht);
  621.     skip_comment(fp);
  622.     }
  623.     line_no++;
  624.  
  625.     /* Read points */
  626.     if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) {
  627.     file_msg(Err_incomp, "spline", line_no);
  628.     free_splinestorage(s);
  629.     return (NULL);
  630.     };
  631.     if ((p = create_point()) == NULL) {
  632.     free_splinestorage(s);
  633.     return (NULL);
  634.     }
  635.     s->points = p;
  636.     p->x = x;
  637.     p->y = y;
  638.     for (c = 1;;) {
  639.     if (fscanf(fp, "%d%d", &x, &y) != 2) {
  640.         file_msg(Err_incomp, "spline", line_no);
  641.         p->next = NULL;
  642.         free_splinestorage(s);
  643.         return (NULL);
  644.     };
  645.     if (x == 9999)
  646.         break;
  647.     if ((q = create_point()) == NULL) {
  648.         free_splinestorage(s);
  649.         return (NULL);
  650.     }
  651.     q->x = x;
  652.     q->y = y;
  653.     p->next = q;
  654.     p = q;
  655.     c++;
  656.     }
  657.     p->next = NULL;
  658.     skip_line(fp);
  659.  
  660.     if (normal_spline(s))
  661.     return (s);
  662.  
  663.     line_no++;
  664.     skip_comment(fp);
  665.     /* Read controls */
  666.     if ((n = fscanf(fp, "%f%f%f%f", &lx, &ly, &rx, &ry)) != 4) {
  667.     file_msg(Err_incomp, "spline", line_no);
  668.     free_splinestorage(s);
  669.     return (NULL);
  670.     };
  671.     if ((cp = create_cpoint()) == NULL) {
  672.     free_splinestorage(s);
  673.     return (NULL);
  674.     }
  675.     s->controls = cp;
  676.     cp->lx = lx;
  677.     cp->ly = ly;
  678.     cp->rx = rx;
  679.     cp->ry = ry;
  680.     while (--c) {
  681.     if (fscanf(fp, "%f%f%f%f", &lx, &ly, &rx, &ry) != 4) {
  682.         file_msg(Err_incomp, "spline", line_no);
  683.         cp->next = NULL;
  684.         free_splinestorage(s);
  685.         return (NULL);
  686.     };
  687.     if ((cq = create_cpoint()) == NULL) {
  688.         cp->next = NULL;
  689.         free_splinestorage(s);
  690.         return (NULL);
  691.     }
  692.     cq->lx = lx;
  693.     cq->ly = ly;
  694.     cq->rx = rx;
  695.     cq->ry = ry;
  696.     cp->next = cq;
  697.     cp = cq;
  698.     }
  699.     cp->next = NULL;
  700.  
  701.     skip_line(fp);
  702.     return (s);
  703. }
  704.  
  705. static F_text  *
  706. read_textobject(fp)
  707.     FILE       *fp;
  708. {
  709.     F_text       *t;
  710.     int            n;
  711.     int            ignore = 0;
  712.     char        s[BUF_SIZE], s_temp[BUF_SIZE], junk[2];
  713.     float        tx_size, tx_height, tx_length;
  714.     extern PIX_ROT_FONT lookfont();
  715.  
  716.     if ((t = create_text()) == NULL)
  717.     return (NULL);
  718.  
  719.     t->next = NULL;
  720.     /*
  721.      * The text object is terminated by a CONTROL-A, so we read everything up
  722.      * to the CONTROL-A and then read that character. If we do not find the
  723.      * CONTROL-A on this line then this must be a multi-line text object and
  724.      * we will have to read more.
  725.      * 
  726.      * We read text size, height and length as floats because TransFig uses
  727.      * floats for these, but they are rounded to ints internally to xfig.
  728.      */
  729.     /* read the leading blanks for the string, but delete the first later */
  730.     n = sscanf(buf, "%*d%d%d%f%d%d%d%f%d%f%f%d%d%[^\1]%[\1]",
  731.            &t->type, &t->font, &tx_size, &t->pen,
  732.            &t->color, &t->depth, &t->angle,
  733.            &t->flags, &tx_height, &tx_length,
  734.            &t->base_x, &t->base_y, s, junk);
  735.     if (n != 13 && n != 14) {
  736.     file_msg(Err_incomp, "text", line_no);
  737.     free((char *) t);
  738.     return (NULL);
  739.     }
  740.     /* now round size, height and length to int */
  741.     if ((int) tx_size == DEFAULT)    /* just copy DEFAULT */
  742.     t->size = DEFAULT;
  743.     else
  744.     t->size = round(tx_size);
  745.     while (t->angle < 0.0)
  746.     t->angle += M_2PI;
  747.     while (t->angle > M_2PI)
  748.     t->angle -= M_2PI;
  749.     /* get the font struct */
  750.     t->fontstruct = lookfont(x_fontnum(t->flags, t->font), 
  751.             round(t->size*zoomscale), t->angle);  
  752.     t->height = round(tx_height);
  753.     t->length = round(tx_length);
  754.     fixdepth(&t->depth);
  755.     if (n == 13) {
  756.     /* Read in the remainder of the text object. */
  757.     do {
  758.         /*
  759.          * khc 06JUL90 - test for end-of-file or else hangs in loop if no
  760.          * ^A is found
  761.          */
  762.         if (fgets(buf, BUF_SIZE, fp) == NULL)
  763.         break;
  764.         line_no++;        /* As is done in get_line */
  765.         n = sscanf(buf, "%[^\1]%[\1]", s_temp, junk);
  766.         /* Safety check */
  767.         if (strlen(s) + 1 + strlen(s_temp) + 1 > BUF_SIZE) {
  768.         /* Too many characters.     Ignore the rest. */
  769.         if (!ignore)
  770.             file_msg("Truncating TEXT object to %d chars in line %d",
  771.                 BUF_SIZE,line_no);
  772.         ignore = 1;
  773.         }
  774.         if (!ignore)
  775.         strcat(s, s_temp);
  776.     } while (n == 1);
  777.     }
  778.     if (t->type > T_RIGHT_JUSTIFIED) {
  779.     file_msg("Invalid text justification at line %d, setting to LEFT.", line_no);
  780.     t->type = T_LEFT_JUSTIFIED;
  781.     }
  782.  
  783.     /* convert all pre-2.1 NON-TFX text flags (used to be font_style) to PostScript
  784.        and all pre-2.1 TFX flags to PostScript + Special */
  785.     if (proto <= 20)
  786.     {
  787.     t->flags = PSFONT_TEXT;
  788.     if (TFX)
  789.         t->flags |= SPECIAL_TEXT;
  790.     }
  791.  
  792.     if (t->font >= MAXFONT(t)) {
  793.     file_msg("Invalid text font (%d) at line %d, setting to DEFAULT.",
  794.         t->font, line_no);
  795.     t->font = DEFAULT;
  796.     }
  797.     if (strlen(s) <= 1)
  798.     {
  799.     file_msg("Empty text string at line %d", line_no);
  800.     return (NULL);
  801.     }
  802.     /* skip first blank from input file by starting at s[1] */
  803.     if ((t->cstring = new_string(strlen(&s[1]) + 1)) == NULL) {
  804.     free((char *) t);
  805.     return (NULL);
  806.     }
  807.     (void) strcpy(t->cstring, &s[1]);
  808.  
  809.     return (t);
  810. }
  811.  
  812. get_line(fp)
  813.     FILE       *fp;
  814. {
  815.     while (1) {
  816.     if (NULL == fgets(buf, BUF_SIZE, fp)) {
  817.         return (-1);
  818.     }
  819.     line_no++;
  820.     if (*buf != '\n' && *buf != '#')    /* Skip empty and comment
  821.                          * lines */
  822.         return (1);
  823.     }
  824. }
  825.  
  826. skip_comment(fp)
  827.     FILE       *fp;
  828. {
  829.     char        c;
  830.  
  831.     while ((c = fgetc(fp)) == '#')
  832.     skip_line(fp);
  833.     if (c != '#')
  834.     ungetc(c, fp);
  835. }
  836.  
  837. skip_line(fp)
  838.     FILE       *fp;
  839. {
  840.     while (fgetc(fp) != '\n') {
  841.     if (feof(fp))
  842.         return;
  843.     }
  844. }
  845.  
  846. fixdepth(depth) 
  847.     int          *depth;
  848. {
  849.     if (*depth>MAXDEPTH) {
  850.         *depth=MAXDEPTH; 
  851.         file_msg("Depth > %d, setting to %d in line %d", 
  852.             MAXDEPTH,line_no,MAXDEPTH); 
  853.     } 
  854.     else if (*depth<0 || proto<21) { 
  855.         *depth=0; 
  856.         if (proto>=21) 
  857.         file_msg("Depth < 0, setting to 0 in line %d", line_no); 
  858.     }
  859. }
  860.  
  861. shift_figure(obj)
  862. F_compound       *obj;
  863. {
  864.     F_ellipse       *e;
  865.     F_arc       *a;
  866.     F_line       *l;
  867.     F_spline       *s;
  868.     F_compound       *c;
  869.     F_text       *t;
  870.     int            lowx,lowy,dx,dy;
  871.     int            llx,lly,urx,ury;
  872.     int            rnd;
  873.  
  874.     lowx = 10000;
  875.     lowy = 10000;
  876.     for (e = obj->ellipses; e != NULL; e = e->next) {
  877.     ellipse_bound(e, &llx, &lly, &urx, &ury);
  878.     lowx = min2(llx,lowx);
  879.     lowy = min2(lly,lowy);
  880.     }
  881.     for (a = obj->arcs; a != NULL; a = a->next) {
  882.     arc_bound(a, &llx, &lly, &urx, &ury);
  883.     lowx = min2(llx,lowx);
  884.     lowy = min2(lly,lowy);
  885.     }
  886.     for (l = obj->lines; l != NULL; l = l->next) {
  887.     line_bound(l, &llx, &lly, &urx, &ury);
  888.     lowx = min2(llx,lowx);
  889.     lowy = min2(lly,lowy);
  890.     }
  891.     for (s = obj->splines; s != NULL; s = s->next) {
  892.     spline_bound(s, &llx, &lly, &urx, &ury);
  893.     lowx = min2(llx,lowx);
  894.     lowy = min2(lly,lowy);
  895.     }
  896.     for (c = obj->compounds; c != NULL; c = c->next) {
  897.     compound_bound(c, &llx, &lly, &urx, &ury);
  898.     lowx = min2(llx,lowx);
  899.     lowy = min2(lly,lowy);
  900.     }
  901.     for (t = obj->texts; t != NULL; t = t->next) {
  902.     int   dum;
  903.     text_bound_actual(t, t->angle, &llx, &lly, &urx, &ury, 
  904.               &dum,&dum,&dum,&dum,&dum,&dum,&dum,&dum);
  905.     lowx = min2(llx,lowx);
  906.     lowy = min2(lly,lowy);
  907.     }
  908.     /* check if any part of the figure has negative coords */
  909.     if (lowx >= 0 && lowy >= 0)
  910.     return;                /* no, ok */
  911.  
  912.     /* shift the whole figure to keep it "on the page" */
  913.     dx = dy = 0;
  914.     rnd = posn_rnd[cur_pointposn];
  915.     if (lowx < 0)
  916.     {
  917.     dx = -lowx+rnd;    /* and round up to small grid */
  918.     if (rnd != 0)
  919.         dx--;
  920.     }
  921.     if (lowy < 0)
  922.     {
  923.     dy = -lowy+rnd;
  924.     if (rnd != 0)
  925.         dy--;
  926.     }
  927.     file_msg(
  928.     "Shifting entire figure %d pixels right and %d pixels down to keep on page",
  929.     dx,dy);
  930.     for (e = obj->ellipses; e != NULL; e = e->next)
  931.     translate_ellipse(e, dx, dy);
  932.     for (a = obj->arcs; a != NULL; a = a->next)
  933.     translate_arc(a, dx, dy);
  934.     for (l = obj->lines; l != NULL; l = l->next)
  935.     translate_line(l, dx, dy);
  936.     for (s = obj->splines; s != NULL; s = s->next)
  937.     translate_spline(s, dx, dy);
  938.     for (c = obj->compounds; c != NULL; c = c->next)
  939.     translate_compound(c, dx, dy);
  940.     for (t = obj->texts; t != NULL; t = t->next)
  941.     translate_text(t, dx, dy);
  942. }
  943.  
  944. /* VARARGS1 */
  945. file_msg(format, arg1, arg2, arg3, arg4, arg5)
  946.     char       *format;
  947.     int            arg1, arg2, arg3, arg4, arg5;
  948. {
  949.     XawTextBlock block;
  950.     popup_file_msg();
  951.     if (first_file_msg)
  952.     {
  953.     first_file_msg = False;
  954.     file_msg("---------------------");
  955.     file_msg("File %s:",read_file_name);
  956.     }
  957.     sprintf(tmpstr, format, arg1, arg2, arg3, arg4, arg5);
  958.     strcat(tmpstr,"\n");
  959.     /* append this message to the file message widget string */
  960.     block.firstPos = 0;
  961.     block.ptr = tmpstr;
  962.     block.length = strlen(tmpstr);
  963.     block.format = FMT8BIT;
  964.     /* make editable to add new message */
  965.     FirstArg(XtNeditType, XawtextEdit);
  966.     SetValues(file_msg_win);
  967.     /* insert the new message after the end */
  968.     (void) XawTextReplace(file_msg_win,file_msg_length,file_msg_length,&block);
  969.     (void) XawTextSetInsertionPoint(file_msg_win,file_msg_length);
  970.  
  971.     /* make read-only again */
  972.     FirstArg(XtNeditType, XawtextRead);
  973.     SetValues(file_msg_win);
  974.     file_msg_length += block.length;
  975. }
  976.  
  977. clear_file_message(w, ev)
  978.     Widget        w;
  979.     XButtonEvent   *ev;
  980. {
  981.     XawTextBlock    block;
  982.     int            replcode;
  983.  
  984.     if (!file_msg_popup)
  985.     return;
  986.  
  987.     tmpstr[0]=' ';
  988.     block.firstPos = 0;
  989.     block.ptr = tmpstr;
  990.     block.length = 1;
  991.     block.format = FMT8BIT;
  992.  
  993.     /* make editable to clear message */
  994.     FirstArg(XtNeditType, XawtextEdit);
  995.     NextArg(XtNdisplayPosition, 0);
  996.     SetValues(file_msg_win);
  997.  
  998.     /* replace all messages with one blank */
  999.     replcode = XawTextReplace(file_msg_win,0,file_msg_length,&block);
  1000.     if (replcode == XawPositionError)
  1001.     fprintf(stderr,"XawTextReplace XawPositionError\n");
  1002.     else if (replcode == XawEditError)
  1003.     fprintf(stderr,"XawTextReplace XawEditError\n");
  1004.  
  1005.     /* make read-only again */
  1006.     FirstArg(XtNeditType, XawtextRead);
  1007.     SetValues(file_msg_win);
  1008.     file_msg_length = 0;
  1009. }
  1010.  
  1011. static Bool grabbed=False;
  1012.  
  1013. static
  1014. XtEventHandler
  1015. file_msg_panel_dismiss(w, ev)
  1016.     Widget        w;
  1017.     XButtonEvent   *ev;
  1018. {
  1019.     if ((grabbed) && (!file_up))
  1020.         XtAddGrab(file_msg_popup, False, False);
  1021.     XtPopdown(file_msg_popup);
  1022.     file_msg_is_popped=False;
  1023. }
  1024.  
  1025. popup_file_msg()
  1026. {
  1027.     extern Atom wm_delete_window;
  1028.  
  1029.     if (file_msg_popup)
  1030.         {
  1031.         if (!file_msg_is_popped)
  1032.             {
  1033.             if (file_up)
  1034.                 {
  1035.                 XtPopup(file_msg_popup, XtGrabNonexclusive);
  1036.                     XSetWMProtocols(XtDisplay(file_msg_popup), 
  1037.                         XtWindow(file_msg_popup),
  1038.                                &wm_delete_window, 1);
  1039.                 grabbed = True;
  1040.                 }
  1041.             else
  1042.                 {
  1043.                 XtPopup(file_msg_popup, XtGrabNone);
  1044.                     XSetWMProtocols(XtDisplay(file_msg_popup), 
  1045.                         XtWindow(file_msg_popup),
  1046.                                &wm_delete_window, 1);
  1047.                 grabbed = False;
  1048.                 }
  1049.             }
  1050.         file_msg_is_popped = True;
  1051.         return;
  1052.         }
  1053.  
  1054.     file_msg_is_popped = True;
  1055.     FirstArg(XtNx, 0);
  1056.     NextArg(XtNy, 0);
  1057.     NextArg(XtNtitle, "Xfig: File error messages");
  1058.     file_msg_popup = XtCreatePopupShell("xfig_file_msg",
  1059.                     transientShellWidgetClass,
  1060.                     tool, Args, ArgCount);
  1061.     XtOverrideTranslations(file_msg_popup,
  1062.             XtParseTranslationTable(file_msg_translations));
  1063.     XtAppAddActions(tool_app, file_msg_actions, XtNumber(file_msg_actions));
  1064.  
  1065.     file_msg_panel = XtCreateManagedWidget("file_msg_panel", formWidgetClass,
  1066.                        file_msg_popup, NULL, ZERO);
  1067.     FirstArg(XtNwidth, 500);
  1068.     NextArg(XtNheight, 200);
  1069.     NextArg(XtNeditType, XawtextRead);
  1070.     NextArg(XtNdisplayCaret, False);
  1071.     NextArg(XtNborderWidth, INTERNAL_BW);
  1072.     NextArg(XtNscrollHorizontal, XawtextScrollWhenNeeded);
  1073.     NextArg(XtNscrollVertical, XawtextScrollAlways);
  1074.     file_msg_win = XtCreateManagedWidget("file_msg_win", asciiTextWidgetClass,
  1075.                          file_msg_panel, Args, ArgCount);
  1076.  
  1077.     FirstArg(XtNlabel, "Dismiss");
  1078.     NextArg(XtNheight, 25);
  1079.     NextArg(XtNborderWidth, INTERNAL_BW);
  1080.     NextArg(XtNfromVert, file_msg_win);
  1081.     file_msg_dismiss = XtCreateManagedWidget("dismiss", commandWidgetClass,
  1082.                        file_msg_panel, Args, ArgCount);
  1083.     XtAddEventHandler(file_msg_dismiss, ButtonReleaseMask, (Boolean) 0,
  1084.               (XtEventHandler)file_msg_panel_dismiss, (XtPointer) NULL);
  1085.  
  1086.     FirstArg(XtNlabel, "Clear");
  1087.     NextArg(XtNheight, 25);
  1088.     NextArg(XtNborderWidth, INTERNAL_BW);
  1089.     NextArg(XtNfromVert, file_msg_win);
  1090.     NextArg(XtNfromHoriz, file_msg_dismiss);
  1091.     file_msg_dismiss = XtCreateManagedWidget("clear", commandWidgetClass,
  1092.                        file_msg_panel, Args, ArgCount);
  1093.     XtAddEventHandler(file_msg_dismiss, ButtonReleaseMask, (Boolean) 0,
  1094.               (XtEventHandler)clear_file_message, (XtPointer) NULL);
  1095.  
  1096.     if (file_up)
  1097.         {
  1098.         XtPopup(file_msg_popup, XtGrabNonexclusive);
  1099.             XSetWMProtocols(XtDisplay(file_msg_popup), 
  1100.                 XtWindow(file_msg_popup),
  1101.                        &wm_delete_window, 1);
  1102.         grabbed = True;
  1103.         }
  1104.     else
  1105.         {
  1106.         XtPopup(file_msg_popup, XtGrabNone);
  1107.             XSetWMProtocols(XtDisplay(file_msg_popup), 
  1108.                 XtWindow(file_msg_popup),
  1109.                        &wm_delete_window, 1);
  1110.         grabbed = False;
  1111.         }
  1112. }
  1113.