home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / graphics-0.17 / xplot / xplot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-11  |  14.1 KB  |  651 lines

  1. /* This source file is based on the xplot written by Arthur Smith
  2. <arthur@helios.tn.cornell.edu>.  It has been further modified by Rich
  3. Murphey <Rich@rice.edu>.*/
  4.  
  5.  
  6. #include "sys-defines.h"
  7.  
  8. #include <X11/Intrinsic.h>
  9. #include <X11/StringDefs.h>
  10. #include <X11/Shell.h>
  11. #include <X11/Xaw/Label.h>
  12. #include <X11/Xaw/Cardinals.h>
  13. #include <X11/Xaw/Command.h>
  14.  
  15. #include "libplot.h"
  16. #include "getopt.h"
  17.  
  18. FILE *ostrm = stderr;
  19. int fork_flag = 1;        /* nonzero means fork before exit. */
  20. #ifdef DEBUG
  21. int debug_flag = 0;        /* nonzero means output debugging info. */
  22. #endif
  23. #ifndef DONT_HANDLE_SIGHUP
  24. #include <signal.h>
  25. int sighup_flag = 1;        /* nonzero means ignore sighup. */
  26. #endif
  27.  
  28. char *b;            /* location of the bufffer */
  29. int b_in=0;            /* where to read next char from */
  30. int b_out=0;            /* where to write next char to */
  31. int b_length=0;            /* number of bytes allocated */
  32.  
  33. char *sbuf;
  34. int sbuf_length;
  35.  
  36. static XtCallbackProc Quit();
  37. static XtCallbackProc do_plot ();
  38. String fallback_resources[] = {
  39.   "xplot*geometry:        500x500",
  40.   "xplot*font:            fixed",
  41.   NULL };
  42.  
  43. Display *dpy;
  44. Pixmap pixmap;
  45. GC gc;
  46. XGCValues gcv;
  47.  
  48. int xmin=0, xmax=4096, ymin=0, ymax=4096;
  49. double xfactor=1., yfactor=1.;
  50. int last_x, last_y;
  51.  
  52. #define MAPX(x) ((int) (((x) - xmin) * xfactor))
  53. #define MAPY(y) ((int) ((ymax - (y)) * yfactor))
  54.  
  55. int win_width=100, win_height=100;
  56.  
  57. Widget toplevel;
  58. Widget child;
  59. Arg wargs[20];
  60. int nargc;
  61. char **nargv;
  62.  
  63. char *startup_font = "";    /* null string means use sever default */
  64. int high_byte_first = 0;
  65. char *progname;            /* argv[0] or the name of this program */
  66.  
  67. void
  68. display_version ()
  69. {
  70.     (void) fprintf (stderr, "\
  71. %s version %s, by Arthur Smith <arthur@helios.tn.cornell.edu>, modified by\n\
  72. Rich Murphey <Rich@rice.edu>.  %s comes with ABSOLUTELY NO WARRANTY.\n",
  73.             progname, VERS, progname);
  74. }
  75.  
  76. /* Long options we recognize */
  77. #define    ARG_NONE    0
  78. #define    ARG_REQUIRED    1
  79. #define    ARG_OPTIONAL    2
  80.  
  81. struct option    long_options[] = {
  82.     { "fontname",    ARG_REQUIRED,    NULL, 'f' },
  83.     { "help",        ARG_NONE,    NULL, 'H' },
  84.     { "high-byte-first", ARG_NONE,    NULL, 'h' },
  85.     { "low-byte-first",    ARG_NONE,    NULL, 'l' },
  86.     { "no-fork",    ARG_NONE,    NULL, 'N' },
  87.     { "version",    ARG_NONE,    NULL, 'V' },
  88.     { "warranty",    ARG_NONE,    NULL, 'W' },
  89. #ifndef DONT_HANDLE_SIGHUP
  90.     { "catch-sighup",    ARG_NONE,    NULL, 'C' },
  91. #endif
  92. #ifdef DEBUG
  93.     { "debug",        ARG_NONE,    NULL, 'D' },
  94. #endif
  95.     { NULL,        0,        NULL, 0}
  96. };
  97.  
  98. void
  99. display_help ()
  100. {
  101.   int i;
  102.   fprintf (stderr, "usage: %s", progname);
  103.   for (i=0; long_options[i].name; i++)
  104.     {
  105.       fprintf (stderr, " [+%s", long_options[i].name);
  106.       if (isprint (long_options[i].val))
  107.     fprintf (stderr, "|-%c", long_options[i].val);
  108.       if (long_options[i].has_arg == ARG_REQUIRED)
  109.     fprintf (stderr, " arg]");
  110.       else
  111.     fprintf (stderr, "]");
  112.     }
  113.   fprintf (stderr, "\n");
  114. }
  115.  
  116. int
  117. main (argc, argv)
  118.      int argc;
  119.      char **argv;
  120. {
  121.   int i, bytes_recieved;
  122.   int option;
  123.   int opt_index;
  124.   int errcnt = 0;        /* errors encountered */
  125.   int show_version = 0;        /* remember to show version message */
  126.   int show_usage = 0;        /* remember whether to output usage message. */
  127.   int named_input = 0;        /* count named plot files on command line. */
  128.  
  129.   progname = argv[0];
  130.  
  131.   b_length = 128;        /* allocate the input buffer */
  132.   b = (char*) malloc (b_length);
  133.  
  134.   while ((option = getopt_long (argc, argv, "CDHNVWf:g:hlx:", long_options, &opt_index)) != EOF) {
  135.       if (option == 0)
  136.     option = long_options[opt_index].val;
  137.  
  138.       switch (option)
  139.     {
  140.     case 'f':
  141.       startup_font = optarg;
  142.       break;
  143.     case 'h':        /* read high byte first */
  144.       high_byte_first = 1;
  145.       break;
  146.     case 'l':        /* read low byte first */
  147.       high_byte_first = -1;
  148.       break;
  149.     case 'N':        /* do not fork */
  150.       fork_flag = 0;
  151.       break;
  152. #ifdef DEBUG
  153.     case 'D':        /* output debuggin info */
  154.       debug_flag = 1;
  155.       break;
  156. #endif
  157. #ifndef DONT_HANDLE_SIGHUP
  158.     case 'C':
  159.       sighup_flag = 0;        /* do not ignore sighup. */
  160.       break;
  161. #endif
  162.     case 'H':        /* Help */
  163.       show_usage = 1;
  164.       break;
  165.     case 'v':
  166.     case 'V':        /* Version */
  167.       show_version = 1;
  168.       break;
  169.     case 1:
  170.       {
  171.         FILE *data_file;
  172.  
  173.         if (strcmp (optarg, "-") == 0)
  174.           data_file = stdin;
  175.         else
  176.           {
  177.         data_file = fopen (optarg, "r");
  178.         if (data_file == NULL)
  179.           {
  180.             (void) fprintf (stderr, "%s:  ignoring nonexistent or inaccessible file `%s'\n",
  181.                     argv[0], optarg);
  182.             continue;
  183.           }
  184.           }
  185.  
  186.         do {
  187. #ifdef DEBUG
  188.           if (debug_flag) fprintf (ostrm, "input buffer: %d %d %d %d\n", b, b_in, b_out, b_length);
  189. #endif
  190.           bytes_recieved = fread(&b[b_out], sizeof(char), b_length - b_out, data_file);
  191.           b_out += bytes_recieved > 0 ? bytes_recieved : 0;
  192.           if (b_out >= b_length)
  193.         { b_length *= 2;
  194.           b = (char*) realloc (b, b_length);}
  195.         } while (bytes_recieved > 0);
  196.         named_input++;
  197.  
  198.         if (data_file != stdin) /* Don't close stdin */
  199.           fclose (data_file);
  200.       }
  201.       break;
  202.     default:
  203.       errcnt++;
  204.       break;
  205.     }
  206.     }
  207.   
  208.  
  209. #ifndef DONT_HANDLE_SIGHUP
  210.   if (sighup_flag)
  211.     signal(SIGHUP, SIG_IGN);
  212. #endif
  213.  
  214.   if (!named_input)
  215.     do {
  216.       bytes_recieved = fread(&b[b_out], sizeof(char), b_length - b_out, stdin);
  217.       b_out += bytes_recieved > 0 ? bytes_recieved : 0;
  218.       if (b_out >= b_length)
  219.     { b_length *= 2;
  220.       b = (char*) realloc (b, b_length);}
  221.     } while (bytes_recieved > 0);
  222.  
  223.   sbuf_length = 128;
  224.   sbuf = (char*) malloc (sbuf_length);
  225. #ifdef DEBUG
  226.   if (debug_flag)
  227.     {
  228.       int i;
  229.       fprintf (ostrm, "input buffer: %d %d %d %d\n", b, b_in, b_out, b_length);
  230.       for (i=0; i<argc; i++)
  231.     fprintf (ostrm, "args %d %s\n", i, argv[i]);
  232.     }  
  233. #endif
  234.   nargc = argc;
  235.   nargv = argv;
  236.  
  237.   if (b_out==0)
  238.     fprintf (ostrm, "%s: Abort: zero bytes read from input.\n", argv[0]);
  239.   else
  240.     openpl ();
  241.   return 0;
  242. }
  243. /* Openpl creates an X window which will contain the plot's pixmap. */
  244. int openpl ()
  245. {
  246.   int i, narg;
  247.   XtAppContext app_con;
  248.   char *default_val;
  249.  
  250.   toplevel = XtAppInitialize(&app_con, "Xplot", NULL, ZERO, &nargc, nargv,
  251.                  fallback_resources, NULL, ZERO);
  252.   child = XtCreateManagedWidget("", commandWidgetClass, toplevel, NULL, ZERO);
  253.   XtRealizeWidget (toplevel);
  254.   dpy = XtDisplay(toplevel);
  255.                 /* get the size of the window */
  256.   XtSetArg(wargs[0], XtNwidth, 0);
  257.   XtSetArg(wargs[1], XtNheight, 0);
  258.   XtGetValues(toplevel, wargs, TWO);
  259.   win_width = wargs[0].value;
  260.   win_height = wargs[1].value;
  261.   if ((xmax + 1 - xmin)!=0)
  262.     xfactor = ((double) win_width)/(xmax + 1 - xmin);
  263.   else
  264.     xfactor = win_width;
  265.   if ((ymax + 1 - ymin)!=0)
  266.     yfactor = ((double) win_height)/(ymax + 1 - ymin);
  267.   else
  268.     yfactor = win_height;
  269.  
  270. #ifdef DEBUG
  271.   if (debug_flag) fprintf (ostrm, "pixmap: %d x %d\n", win_width, win_height);
  272. #endif
  273.                 /* create the bitmap */
  274.   pixmap = XCreatePixmap(dpy, DefaultRootWindow (dpy), win_width, win_height, 1);
  275.   gc = XCreateGC (dpy, pixmap, 0L, &gcv);
  276.                 /* install the bitmap in the command widget */
  277.   XtSetArg (wargs[0], XtNbitmap, pixmap);
  278.   XtSetValues(child, wargs, ONE);
  279.   XtAddCallback(child, XtNcallback, Quit, NULL);
  280.  
  281.   erase ();            /* erase the window */
  282.   fontname (startup_font);    /* set the default font */
  283.  
  284.   do_plot (0, 0, 0);
  285.   if (fork_flag)
  286.     if (fork ())
  287.       {
  288.     sleep (1);        /* give the child window time to get mapped. */
  289.     exit (0);
  290.       }
  291.   XtAppMainLoop(app_con);
  292. }
  293.  
  294. static XtCallbackProc
  295. do_plot (data, fd, id)
  296.      XtPointer data;
  297.      int *fd;
  298.      XtInputId *id;
  299. {
  300.   char c;
  301.   int x[6];
  302.   while ((b_out - b_in) > 0)
  303.     {
  304.       c = b[b_in++];
  305. #ifdef DEBUG
  306.       if (debug_flag) fprintf (ostrm, "%c", c);
  307. #endif
  308.       switch (c)
  309.     {
  310.     case 'm':        /* Move */
  311.       if (getcoords (x, 2))
  312.         move (x[0], x[1]);
  313.       break;
  314.     case 'n':        /* Continue */
  315.       if (getcoords (x, 2))
  316.         cont (x[0], x[1]);
  317.       break;
  318.     case 'p':        /* Point */
  319.       if (getcoords (x, 2))
  320.         point (x[0], x[1]);
  321.       break;
  322.     case 'l':        /* Draw Line */
  323.       if (getcoords (x, 4))
  324.         line (x[0], x[1], x[2], x[3]);
  325.       break;
  326.     case 't':        /* Label */
  327.       if (getstring ())
  328.         alabel ('l', 'b', sbuf);
  329.       break;
  330.     case 'T':        /* Adjusted Label */
  331.       {
  332.         char x_justify, y_justify;
  333.         x_justify = b[b_in++];
  334.         y_justify = b[b_in++];
  335. #ifdef DEBUG
  336.         if (debug_flag) fprintf (ostrm, " %c %c", x_justify, y_justify);
  337. #endif
  338.         if (getstring ())
  339.           alabel (x_justify, y_justify, sbuf);
  340.       }
  341.       break;
  342.     case 'a':        /* Arc */
  343.       if (getcoords (x, 6))
  344.         arc (x[0], x[1], x[2], x[3], x[4], x[5]);
  345.       break;
  346.     case 'c':        /* Circle */
  347.       if (getcoords (x, 3))
  348.         circle (x[0], x[1], x[2]);
  349.       break;
  350.     case 'e':        /* Erase */
  351. #ifdef DEBUG
  352.       if (debug_flag) fprintf (ostrm, "\n");
  353. #endif
  354.       erase ();
  355.       break;
  356.     case 'f':        /* Linemod */
  357.       if (getstring ())
  358.         linemod (sbuf);
  359.       break;
  360.     case 's':        /* Space */
  361.       if (getcoords (x, 4))
  362.         space (x[0], x[1], x[2], x[3]);
  363.       break;
  364.     case 'C':        /* Color */
  365.       if (getcoords (x, 3))
  366.         color (x[0], x[1], x[2]);
  367.       break;
  368.     case 'F':        /* font name */
  369.       if (getstring ())
  370.         fontname (sbuf);
  371.       break;
  372.     case 'S':        /* font size */
  373.       if (getcoords (x, 1))
  374.         fontsize (x[0]);
  375.       break;
  376.     case 'r':        /* rotate */
  377.       if (getcoords (x, 3))
  378.         rotate (x[0], x[1], x[2]);
  379.       break;
  380.     case 'L':        /* Fill */
  381.       if (getcoords (x, 1))
  382.         fill (x[0]);
  383.       break;
  384.     default:
  385. #ifdef DEBUG
  386.       fprintf (ostrm, "Unrecognized plot command `%c' (%o octal) ignored.\n", 
  387.           c, c&0xFF);
  388. #endif
  389.       break;
  390.     }
  391.     }
  392.   XClearArea (dpy, XtWindow (child), 0, 0, 0, 0, True);
  393. }
  394.  
  395. drawellipse (x, y, r1, r2)
  396.      int x, y, r1, r2;
  397. {
  398.   XDrawArc(dpy, pixmap, gc, x - r1, y - r2, 2 * r1, 2 * r2, 0, 64 * 360 - 1);
  399. }
  400.  
  401. int
  402. drawarc (x, y, x0, y0, x1, y1)
  403.      int x, y, x0, y0, x1, y1;
  404. {
  405.   int a0, b0, a1, b1;
  406.   int a02, b02, a12, b12;
  407.   double ar, br, ar2, br2;
  408.   double theta0, theta1;
  409.  
  410.   a0 = x0 - x;
  411.   a02 = a0*a0;
  412.   a1 = x1 - x;
  413.   a12 = a1*a1;
  414.   b0 = y0 - y;
  415.   b02 = b0*b0;
  416.   b1 = y1 - y;
  417.   b12 = b1*b1;
  418.   if (b12 == b02) return 0;    /* punt rather than divide by zero.  */
  419.   ar2 = (a02*b12 - a12*b02)/(b12 - b02);
  420.   if (ar2 < 0) return 0;
  421.   ar = sqrt (ar2);
  422.   if (a12 == a02) return 0;
  423.   br2 = (b02*a12 - b12*a02)/(a12 - a02);
  424.   if (br2 < 0) return 0;
  425.   br = sqrt (br2);
  426.   if ((br==0)||(ar==0)) return 0;
  427.   theta0 = -atan2 (b0/br, a0/ar);
  428.   theta1 = -atan2 (b1/br, a1/ar);
  429.   if (theta0 > theta1) theta1 += 2 * M_PI;
  430.   if (theta0 < 0)
  431.     {
  432.       theta0 += 2 * M_PI;
  433.       theta1 += 2 * M_PI;
  434.     }
  435.   XDrawArc (dpy, pixmap, gc, (int) (x - ar), (int) (y - br), 
  436.         (int)(2 * ar), (int) (2 * br), 
  437.         (int) (64* theta0 * 180/M_PI), 
  438.         (int) (64 * (theta1 - theta0) * 180/M_PI));
  439.   return 0;
  440. }
  441.  
  442.  
  443. /* Erase should wait for the current page to be absorbed, before creating
  444.   a new one (presumably by erasing the pixmap and then redrawing the widget.*/
  445. int
  446. erase ()
  447. {
  448.                 /* clear the screen */
  449.   XSetFunction(dpy, gc, GXxor);
  450.   XCopyArea(dpy, pixmap, pixmap, gc, 0, 0, win_width, win_height, 0, 0);
  451.  
  452.   XSetFunction(dpy, gc, GXcopyInverted);
  453.   return 0;
  454. }
  455.  
  456. int
  457. label (s)
  458.      char *s;
  459. {
  460.   XDrawString (dpy, pixmap, gc, MAPX (last_x), MAPY (last_y), s, strlen (s));
  461.   return 0;
  462. }
  463.  
  464. int
  465. line (x1, y1, x2, y2)
  466.      int x1, y1, x2, y2;
  467. {
  468.   XDrawLine (dpy, pixmap, gc, MAPX (x1), MAPY (y1), MAPX (x2), MAPY (y2));
  469.   last_x = x2;
  470.   last_y = y2;
  471.   return 0;
  472. }
  473.  
  474. int
  475. circle (x, y, r)
  476.      int x, y, r;
  477. {
  478.   drawellipse(MAPX(x), MAPY(y), (int) (r * xfactor), (int) (r*yfactor));
  479.   last_x = x;
  480.   last_y = y;
  481.   return 0;
  482. }
  483.  
  484.  
  485. int
  486. arc (x, y, x0, y0, x1, y1)
  487.      int x, y, x0, y0, x1, y1;
  488. {
  489.   drawarc (MAPX (x), MAPY (y), MAPX (x0), MAPY (y0), MAPX (x1), MAPY (y1));
  490.   last_x = x;
  491.   last_y = y;
  492.   return 0;
  493. }
  494.  
  495. int
  496. move (x, y)
  497.      int x, y;
  498. {
  499.   last_x = x;
  500.   last_y = y;
  501.   return 0;
  502. }
  503.  
  504. int
  505. cont (x, y)
  506.      int x, y;
  507. {
  508.   line (last_x, last_y, x, y);
  509.   return 0;
  510. }
  511.  
  512. int
  513. point (x, y)
  514.      int x, y;
  515. {
  516.   XDrawPoint (dpy, pixmap, gc, MAPX (x), MAPY (y));
  517.   last_x = x;
  518.   last_y = y;
  519.   return 0;
  520. }
  521.  
  522. int
  523. linemod (s)
  524.      char *s;
  525. {
  526.   int line_style;
  527.   line_style = gcv.line_style;
  528.  
  529.   if (!strcmp (s, "solid"))
  530.     line_style = LineSolid;
  531.   else if ((!strcmp (s, "dotted"))||(!strcmp (s, "shortdashed")))
  532.     line_style = LineOnOffDash;
  533.   else if ((!strcmp (s, "longdashed"))||(!strcmp (s, "dotdashed")))
  534.     line_style = LineDoubleDash;
  535.   gcv.line_style = line_style;
  536.   XChangeGC (dpy, gc, GCLineStyle, &gcv);
  537.   return 0;
  538. }
  539.  
  540.                 /* swap the lower two bytes */
  541. #define byte_swap(x) ((((x)&0xff)<<8) | (((x)<<8)&0xff00))
  542.  
  543. int
  544. space (x0, y0, x1, y1)
  545.      int x0, y0, x1, y1;
  546. {
  547.   xmin = x0;
  548.   xmax = x1;
  549.   ymin = y0;
  550.   ymax = y1;
  551.                 /* determine the byte order */
  552.   if ((high_byte_first == 0)
  553.       && ((xmin > xmax)
  554.       || (ymin > ymax)
  555.       || (xmax < byte_swap(xmax))
  556.       || (ymax < byte_swap(ymax)) ))
  557.     {
  558.       xmin = byte_swap (xmin);
  559.       xmax = byte_swap (xmax);
  560.       ymin = byte_swap (ymin);
  561.       ymax = byte_swap (ymax);
  562.       high_byte_first = high_byte_first > 0 ? -1 : 1;
  563.     }
  564. #ifdef DEBUG
  565.   if (debug_flag) fprintf (ostrm, "%s byte first -> %d %d %d %d\n",
  566.                (high_byte_first > 0 ? "high" : "low"),
  567.                xmin, ymin, xmax, ymax);
  568. #endif
  569.   if ((xmax + 1 - xmin)!=0)
  570.     xfactor = ((double) win_width)/(xmax + 1 - xmin);
  571.   else
  572.     xfactor = win_width;
  573.   if ((ymax + 1 - ymin)!=0)
  574.     yfactor = ((double) win_height)/(ymax + 1 - ymin);
  575.   else
  576.     yfactor = win_height;
  577.   return 0;
  578. }
  579.  
  580. int
  581. closepl ()
  582. {
  583.   XFreeGC (dpy, gc);
  584.   XFreePixmap (dpy, pixmap);
  585.   XtDestroyWidget (toplevel);
  586.   return 0;
  587. }
  588.  
  589. int getcoords (x, n)
  590.      int *x;
  591.      int n;
  592. {
  593.   unsigned char c, d;
  594.   int i;
  595.  
  596.   if ((b_out - b_in) < 2*n) 
  597.     return 0;
  598.   for (i = 0; i < n; i++)
  599.     {
  600.       if (high_byte_first)
  601.     {
  602.       d = b[b_in++];
  603.       c = b[b_in++];
  604.     }
  605.       else
  606.     {
  607.       c = b[b_in++];
  608.       d = b[b_in++];
  609.     }
  610.       x[i] = (int) ((d << 8) | c);
  611. #ifdef DEBUG
  612.       if (debug_flag) fprintf (ostrm, " %d", x[i]);
  613. #endif
  614.     }
  615. #ifdef DEBUG
  616.   if (debug_flag) fprintf (ostrm, "\n");
  617. #endif
  618.   return 1;
  619. }
  620.  
  621. int getstring ()
  622. {
  623.   char *string_end;
  624.   int string_length;
  625.  
  626.   if ((string_end = index (&b[b_in], '\n')) == NULL)
  627.     return 0;
  628.  
  629.   string_length = string_end - &b[b_in];
  630.   while (string_length >= sbuf_length)
  631.     { sbuf_length *= 2;
  632.       sbuf = (char*) realloc (sbuf, sbuf_length);}
  633.   bcopy (&b[b_in], sbuf, string_length);
  634.   sbuf[string_length] = 0;
  635.   b_in += string_length + 1;
  636.  
  637. #ifdef DEBUG
  638.   if (debug_flag) fprintf (ostrm, " %s\n", sbuf);
  639. #endif
  640.   return string_length;
  641. }
  642.  
  643. static XtCallbackProc 
  644. Quit(widget, client_data, call_data)
  645.      Widget    widget;        
  646.      XtPointer client_data, call_data;
  647. {
  648.   XtDestroyApplicationContext(XtWidgetToApplicationContext(widget));
  649.   exit(0);
  650. }
  651.