home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / xspread3.0.zoo / plot_XY.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  22KB  |  729 lines

  1. /*
  2.  * Copyright (C) 1992  Board of Regents of the University of Wisconsin
  3.  * on behalf of the Department of Electrical Engineering and Computer
  4.  * Science, University of Wisconsin-Milwaukee, Milwaukee, WI 53201.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * a copy of which is included here in file "GNU_GENERAL"
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  * The programs in this directory were developed by software engineering 
  22.  * teams as part of the course "Introduction to Software Engineering" 
  23.  * under the supervision of Professor G. Davida.
  24.  * This is a modification of a program written or modified by
  25.  * others.  The original copyrights, as per GNU General Public License,
  26.  * may still be applicable.  The UWM copyright is applicable only
  27.  * the those parts generated at UWM.
  28.  *
  29.  * Please send all changes, enhancements, and other comments about this
  30.  * software to
  31.  *             soft-eng@cs.uwm.edu
  32.  *
  33.  * No Warranty, expressed or implied, comes with this software.
  34.  * This software is intended to be used by not-for-profit
  35.  * organizations or by individuals for personal HOME use. 
  36.  * This software, or any of its parts, may not be used by for-profit
  37.  * organization, regardless of application or intended product or
  38.  * customer, without the permission of the Board of Regents of the 
  39.  * University  of Wisconsin is strictly forbidden. 
  40.  *
  41.  * Contact:    soft-eng@cs.uwm.edu
  42.  *            or
  43.  *        
  44.  *        Software Engineering Coordinator
  45.  *        Computer Science
  46.  *            Department of EECS
  47.  *        University of Wisconsin - Milwaukee
  48.  *        Milwaukee, WI  53201
  49.  *        414-229-4677
  50.  *
  51.  *        HISTORY,CLAIMS and CONTRIBUTIONS
  52.  */
  53. /*
  54.  ******************************************************************************
  55.     This function interfaces the spread sheet (sc) program and plots x-y graph 
  56.   in the X enviroment. Up to six curves can be plotted at the same time.      
  57.   Different curves can be plotted with different symbles. Plotting style can be
  58.   symble or line alone, or both together. Grid lines can be plotted horizotally
  59.   or vertically, or both at the same time. There are four titles that can be  
  60.   put on the screen. Two titles will be printed on the top of the graph, and a 
  61.   x-title and y-title will be printed at sides of the graph.Both the horizontal
  62.   and vertical scale can be set to automatic or manual,in first case the scale 
  63.   will be determined by the data range provided, in the second case both the   
  64.   upper and the lower bounds can be changed by the user. There one legend with
  65.   a symble for each of the curves that will be appear at the bottom of the   
  66.   graph once they are set. Null string that entered to either the titles    
  67.   or the legends will erase them on the graph.                             
  68.      This function was written by using the X liberiry X11 Release 3 by SWLin,
  69.   at the University of Wisconsin-Milwaukee, August, 1990.                    
  70.  
  71.   Modified 12/01/91 - Dan Gruber.  I corrected the problem with plot_XY so that
  72.               it is now able to display legends with this type of graph
  73.   Modified 5/94 - Dan Coppersmith, improved user friendliness of error
  74.                   messages.  
  75.  ***************************************************************************/ 
  76.  
  77. #include <math.h>
  78. #include <stdio.h>
  79. #include <X11/Xlib.h>
  80. #include <X11/Xutil.h>
  81. #include "config.h"
  82. #include "plot.h" 
  83. #include "graphic_gvar.h"
  84. #include "sc.h"
  85. #include "scXstuff.h"
  86.  
  87. #define TITLE "XSPREAD-Grapher (XY Plot)" 
  88.  
  89. /*
  90.  * This structure forms the WM_HINTS property of the window,
  91.  * letting the window manager know how to handle this window.
  92.  * See Section 9.1 of the Xlib manual.
  93.  */
  94.  
  95.    XWMHints     xwmh = {
  96.       (InputHint|StateHint),   /* flags         */
  97.           False,                   /* input         */
  98.           NormalState,             /* initial_state */
  99.       0,                       /* icon pixmap   */
  100.       0,                       /* icon window   */
  101.           0, 0,                    /* icon location */
  102.           0,                       /* icon mask     */
  103.           0,                       /* Window group  */
  104.    };
  105.  
  106.  
  107. plot_XY()
  108. {   double x_max, x_min, y_max, y_min; 
  109.     double x_range, y_range;
  110.     double y_power, x_power; 
  111.    
  112.     int  i, j, k, len;
  113.     int  first_y_datum;
  114.     int  grid_l_x, grid_l_y, grid_w, grid_h;
  115.     int  font_w, text_w;
  116.     int  legend_n;
  117.     int  x, y, x1, y1;
  118.     int  looping = 1; /* true if we shouldn't exit yet */
  119.     int  draw = 0;  /* true if we should paint the window */
  120.     char format;    /* graph format specifier, (L)ine, (S)ymbol, (B)oth */
  121.     int  first_point; /* true when getting coords for 1st point in curve */
  122.     struct ent *p;
  123.     struct ent *xent, *yent;  /* table entries for x and y values */
  124.     int cells=0; 
  125.     int first_x_datum=1;
  126.     
  127.     char str[100];
  128.     register int c;
  129.  
  130.     int argc = 0;
  131.     char **argv;
  132. /* check that we have enough valid x values.  While we are looping,
  133.  * determine the minimum and maximum x values, in case we need them
  134.  */
  135.    for (i=graphic_range[0].r1; i <= graphic_range[0].r2; i++) { 
  136.      p = lookat( i, graphic_range[0].c);
  137.      if (!(p->flags & is_valid)) continue;
  138.        cells++;
  139.        if (first_x_datum){
  140.          x_max = p->v;
  141.          x_min = p->v;
  142.          first_x_datum = 0;
  143.        } else {
  144.          x_max = Max(x_max, p->v); 
  145.          x_min = Min(x_min, p->v);
  146.        }
  147.    } /* for i */
  148.    if (cells < 2) {
  149.      fprintf(stderr,"\007");
  150.      message("Not enough valid X values");
  151.      return;
  152.    }
  153. /* 
  154.  * The plotting job now
  155.  */
  156.  
  157.     /*
  158.      * Decide the scale for x and y axes
  159.      */
  160.      /* if x-scale is manual, override limits calculated above*/
  161.      if (g_auto_man[0] == 'M'){
  162.         x_max = graphic_scale[0][1];
  163.         x_min = graphic_scale[0][0];
  164.      }
  165.  
  166.      /* calculate y limits automatically or manually */
  167.      if (g_auto_man[1] == 'M'){
  168.         y_max = graphic_scale[1][1];
  169.         y_min = graphic_scale[1][0];
  170.      } else {
  171.         first_y_datum = 1;
  172.     for (j = 1; j < GRAPHRANGES; j++) { 
  173.  
  174.            if (*(graphic_range[j].col) == '\0') continue;
  175.  
  176.            for (i=graphic_range[j].r1; i <= graphic_range[j].r2; i++) { 
  177.          p = lookat(i, graphic_range[j].c);
  178.          if ( !(p->flags & is_valid)) continue; /* ignore invalid */
  179.              if (first_y_datum) {
  180.                y_max = p->v;
  181.                y_min = p->v;
  182.                first_y_datum = 0;
  183.              } else {
  184.                y_max = Max(y_max, p->v); 
  185.                y_min = Min(y_min, p->v);
  186.          }
  187.            }
  188.         }
  189.      } 
  190.    if (x_min == x_max) {              /* protection for the case max == min */
  191.        x_max = 1.01 * x_max;
  192.        x_min = 0.99 * x_min;
  193.     }
  194.    if (y_min == y_max) {
  195.        y_max = 1.01 * y_max;
  196.        y_min = 0.99 * y_min;
  197.     }
  198.    
  199.     x_power = - floor(log10((x_max - x_min)));     /* try to print nice lable */
  200.     y_power = - floor(log10((y_max - y_min)));
  201.     x_power = pow10(x_power);
  202.     y_power = pow10(y_power);
  203.     x_min = floor(x_min * x_power) / x_power;
  204.     x_max = ceil(x_max * x_power) / x_power;
  205.  
  206.     y_min = floor(y_min * y_power) / y_power;
  207.     y_max = ceil(y_max * y_power) / y_power;
  208.     x_range = x_max - x_min;
  209.     y_range = y_max - y_min;
  210.     
  211.     /* 
  212.      * Open a new display window
  213.      */
  214.  
  215.     /*
  216.      * Select colors for the border,  the window background,  and the
  217.      * foreground.
  218.      */
  219.  
  220.     bd = WhitePixel(dpy, DefaultScreen(dpy));
  221.     bg = BlackPixel(dpy, DefaultScreen(dpy));
  222.     fg = WhitePixel(dpy, DefaultScreen(dpy));
  223.  
  224.     /*
  225.      * Set the border width of the window,  and the gap between the text
  226.      * and the edge of the window, "pad".
  227.      */
  228.  
  229.     pad = BORDER;
  230.     bw = 1;
  231.  
  232.     /*
  233.      * Deal with providing the window with an initial position & size.
  234.      * Fill out the XSizeHints struct to inform the window manager.
  235.      */
  236.  
  237.     xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);
  238.  
  239.     xsh.flags = (PPosition | PSize);
  240.     xsh.height = WIN_H; 
  241.     xsh.width = WIN_W; 
  242.     xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
  243.     xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;
  244.  
  245.     /*
  246.      * Create the Window with the information in the XSizeHints, the
  247.      * border width,  and the border & background pixels.
  248.      */
  249.  
  250.     win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  251.                   xsh.x, xsh.y, xsh.width, xsh.height,
  252.                   bw, bd, bg);
  253.  
  254.     /*
  255.      * Set the standard properties for the window managers. 
  256.      */
  257.  
  258.     XSetStandardProperties(dpy, win, TITLE, TITLE, 
  259.                None, argv, argc, &xsh);
  260.     XSetWMHints(dpy, win, &xwmh);
  261.  
  262.     /*
  263.      * Ensure that the window's colormap field points to the default
  264.      * colormap,  so that the window manager knows the correct colormap to
  265.      * use for the window.   Also,  set the window's Bit Gravity to reduce 
  266.      * Expose events.
  267.      */
  268.  
  269.     xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
  270.     xswa.bit_gravity = CenterGravity;
  271.     XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
  272.  
  273.  
  274.     /* 
  275.      * Map the window to make it visible.  
  276.      */
  277.    
  278.      XMapWindow(dpy, win);
  279.  
  280.     /*
  281.      * Find out the dimension of the window.
  282.      */
  283.  
  284.     if (XGetWindowAttributes(dpy, win, &xwa) == 0){
  285.        fprintf(stderr,"plot_XY: Can't access attributes for graph window\n");
  286.        exit(1);    
  287.     }
  288.  
  289.     XClearWindow(dpy, win);
  290.     XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);
  291.  
  292. while(looping)
  293.  {   
  294.  
  295.     XEvent event;
  296.  
  297.     XNextEvent(dpy,&event);
  298.     switch (event.type){
  299.       case KeyPress: 
  300.       case ButtonPress: looping = 0; 
  301.             break;
  302.       case Expose: draw = 1;
  303.     }
  304.  
  305.  
  306.     /* if not drawing, go back and get another event */
  307.     if (!draw) continue;
  308.  
  309.     /*
  310.      * Draw the coordinate box
  311.      */
  312.  
  313.     XDrawRectangle(dpy, win, maingcreversed, RECT_X, RECT_Y, RECT_W, RECT_H); 
  314.     
  315.     /*
  316.      * Draw grids
  317.      */
  318.     /* In case it is as unobvious to future programmers as it was to this
  319.      * one, 8 is the length of a hash-mark, as opposed to a full grid line
  320.      */
  321.     if (graphic_grid == 'H') {              /* horizontal grid     */
  322.        grid_l_x = RECT_W;
  323.        grid_l_y = 8;
  324.     }
  325.     else if (graphic_grid == 'V') {         /* vertical grid       */
  326.        grid_l_x = 8;
  327.        grid_l_y = RECT_H;
  328.     }
  329.     else if (graphic_grid == 'B') {         /* both direction grid */
  330.        grid_l_x = RECT_W;
  331.        grid_l_y = RECT_H;
  332.     }
  333.     else {
  334.        grid_l_x = 8;                        /* no grid             */
  335.        grid_l_y = 8;
  336.     }
  337.        
  338.  
  339.     grid_w = RECT_W / 10;                   /* grid seperation     */
  340.     grid_h = RECT_H / 10;
  341.  
  342.     for (i = 0; i < 11; i++) {
  343.        XDrawLine(dpy, win, maingcreversed, 
  344.          RECT_X, RECT_Y + i * grid_h, 
  345.          RECT_X + grid_l_x, RECT_Y + i * grid_h); 
  346.        XDrawLine(dpy, win, maingcreversed, 
  347.          RECT_X + RECT_W, RECT_Y + i * grid_h, 
  348.                  RECT_X + RECT_W - grid_l_x, RECT_Y + i * grid_h); 
  349.        XDrawLine(dpy, win, maingcreversed, 
  350.          RECT_X + i * grid_w, RECT_Y, 
  351.          RECT_X + i * grid_w, RECT_Y + grid_l_y); 
  352.        XDrawLine(dpy,win,maingcreversed,RECT_X + i * grid_w, RECT_Y + RECT_H, 
  353.                  RECT_X + i * grid_w, RECT_Y + RECT_H- grid_l_y); 
  354.  
  355.                  sprintf(str,"%.1f",(y_max - y_range*i/10));
  356.                  len = strlen(str);
  357.                  text_w = XTextWidth(curfont,str,len+2);
  358.                  XDrawImageString(dpy,win,maingcreversed,
  359.                             RECT_X - text_w,
  360.                             RECT_Y + i*grid_h + curfontheight/3,
  361.                             str,len);
  362.  
  363.                  sprintf(str,"%.1f",(x_max - x_range*i/10));
  364.                  len = strlen(str);
  365.                  text_w = XTextWidth(curfont,str,len);
  366.                  XDrawImageString(dpy,win,maingcreversed,
  367.                     RECT_X+RECT_W-i*grid_w-text_w/2,RECT_H+RECT_Y*7/6, 
  368.                             str,len);
  369.  
  370.     }
  371.  
  372.     /*
  373.      * Draw titles
  374.      */
  375.     /* first graph title */
  376.     len = strlen(graphic_title[0]);   
  377.     text_w= XTextWidth(curfont, graphic_title[0], len);
  378.     XDrawImageString(dpy, win, maingcreversed, (WIN_W - text_w) / 2  , RECT_Y / 3,
  379.                      graphic_title[0], len);
  380.     /* second graph title */
  381.     len = strlen(graphic_title[1]);
  382.     text_w= XTextWidth(curfont, graphic_title[1], len);
  383.     XDrawImageString(dpy, win, maingcreversed, 
  384.              (WIN_W - text_w) / 2  , RECT_Y * 2 / 3,
  385.                      graphic_title[1], len);
  386.  
  387.     /* x-axis title */
  388.     len = strlen(graphic_title[2]);
  389.     text_w= XTextWidth(curfont, graphic_title[2], len);
  390.     XDrawImageString(dpy, win, maingcreversed, 
  391.              (WIN_W - text_w) / 2  , RECT_H + RECT_Y * 3 / 2, 
  392.              graphic_title[2], len);
  393.   
  394.     /* y-axis title */
  395.     len = strlen(graphic_title[3]);
  396.     text_w=XTextWidth(curfont,graphic_title[3],len);
  397.     if ((RECT_X-text_w) < 0)
  398.        x = curfontwidth;
  399.     else
  400.        x = RECT_X-text_w;
  401.     XDrawImageString(dpy,win,maingcreversed,
  402.                      x, RECT_Y - curfontheight,
  403.                      graphic_title[3],len);
  404.  
  405.  
  406.     /*
  407.      * Draw legends
  408.      */
  409.  
  410.     legend_n = 0;
  411.     for (i = 0;  i < GRAPHLEGENDS; i++) {
  412.       if ((*(graphic_range[i + 1].col) == '\0') || (curves_n < 1) || 
  413.            (graphic_legend[i][0] == '\0')) 
  414.           continue; 
  415.  
  416.       len = strlen(graphic_legend[i]);
  417.           text_w = XTextWidth(curfont, graphic_legend[i], len);
  418.       if (curves_n == 1) { 
  419.                                 /* Draw the legend symble */
  420.         if (graphic_format[i] == 'L') {
  421.            XDrawLine(dpy, win, maingcreversed, 
  422.              RECT_X +(RECT_W - text_w) / 2  - 15, 
  423.                      RECT_Y * 7 / 4 +RECT_H, RECT_X +(RECT_W - text_w) / 2 - 5, 
  424.                      RECT_Y * 7 / 4 +RECT_H); 
  425.         }
  426.         else if ((graphic_format[i] == 'S') || (graphic_format[i] == 'B')) {
  427.        x = RECT_X + (RECT_W - text_w) / 2 - 10;
  428.        y = RECT_Y * 7 / 4 + RECT_H;
  429.            switch (i) {
  430.              case 0: DrawOpenSquare(x,y);     break;
  431.              case 1: DrawOpenTriangle(x,y);     break;
  432.              case 2: DrawOpenDiamon(x,y);     break;
  433.              case 3: DrawCross(x,y);         break;
  434.              case 4: DrawCloseSquare(x,y);     break;
  435.              case 5: DrawCloseDiamon(x,y);     break;
  436.            }
  437.            if (graphic_format[i] == 'B') 
  438.               XDrawLine(dpy, win, maingcreversed, 
  439.             x-5, y,
  440.             x+5, y); 
  441.         } 
  442.                                  /* Draw the legend title */
  443.  
  444.         XDrawImageString(dpy, win, maingcreversed, 
  445.              RECT_X + (RECT_W - text_w)/2, RECT_Y*7/4 + RECT_H, 
  446.              graphic_legend[i], len);
  447.         break;
  448.      }
  449.      else {
  450.  
  451.                  /* Draw the legend symbols */
  452.  
  453.         if (graphic_format[i] == 'L') {
  454.            XDrawLine(dpy, win, maingcreversed ,
  455.              RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 15, 
  456.              RECT_Y * 7 / 4 + RECT_H, 
  457.              RECT_X / 2 + legend_n * (WIN_W / curves_n - 10) - 5, 
  458.              RECT_Y *7 / 4 + RECT_H); 
  459.         }
  460.         else if ((graphic_format[i] == 'S') || (graphic_format[i] == 'B')) {
  461.            switch (i) {
  462.            case 0:
  463.               DrawOpenSquare(RECT_X/2 + legend_n*(WIN_W / curves_n - 10) - 10, 
  464.                              RECT_Y * 7 / 4 + RECT_H);
  465.               break;
  466.            case 1:
  467.               DrawOpenTriangle(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  468.                                RECT_Y * 7 / 4 + RECT_H);
  469.               break;
  470.            case 2:
  471.               DrawOpenDiamon(RECT_X/2 + legend_n * (WIN_W/curves_n - 10) - 10, 
  472.                              RECT_Y*7/4 + RECT_H);
  473.               break;
  474.            case 3:
  475.               DrawCross(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  476.                         RECT_Y*7/4 + RECT_H);
  477.               break;
  478.            case 4:
  479.               DrawCloseSquare(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  480.                               RECT_Y*7/4 + RECT_H);
  481.               break;
  482.            case 5:
  483.               DrawCloseDiamon(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  484.                               RECT_Y*7/4 + RECT_H);
  485.               break;
  486.            }
  487.            if (graphic_format[i] == 'B')
  488.               XDrawLine(dpy, win, maingcreversed ,
  489.             RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 15, 
  490.             RECT_Y*7/4 + RECT_H, 
  491.             RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 5, 
  492.             RECT_Y*7/4 + RECT_H); 
  493.           
  494.         }
  495.  
  496.                                    /* Draw the legend titles */
  497.         XDrawImageString(dpy, win, maingcreversed, 
  498.              RECT_X/2 + legend_n*(WIN_W/curves_n - 10), 
  499.              RECT_Y*7/4 + RECT_H, 
  500.                          graphic_legend[i], len);
  501.         legend_n ++;
  502.       }
  503.    }
  504.  
  505.  
  506. /* 
  507.  * Draw curves
  508.  */
  509.  
  510.         for (i = 1; i < GRAPHRANGES; i++) { 
  511.            if (*(graphic_range[i].col) == '\0') continue;
  512.        
  513.        first_point = 1;
  514.        format = graphic_format[i];
  515.  
  516.            for (j = graphic_range[0].r1, k = graphic_range[i].r1;
  517.                (j <= graphic_range[0].r2) && (k <= graphic_range[i].r2); j++, k++) {
  518.  
  519.           xent = lookat(j,graphic_range[0].c);
  520.           if (!(xent->flags & is_valid) || (xent->v < x_min) 
  521.           || (xent->v > x_max))
  522.         continue;
  523.           yent = lookat(j, graphic_range[i].c);
  524.           if (!(yent->flags & is_valid) || (yent->v < y_min) 
  525.           || (yent->v > y_max))
  526.         continue;
  527.  
  528.           if (first_point){
  529.                 x1 = RECT_X + RECT_W * (xent->v - x_min) / x_range;  
  530.                y1 = RECT_Y + RECT_H - RECT_H * (yent->v - y_min) / y_range;   
  531.             if ((format == 'S') || (format == 'B'))
  532.             switch(i){
  533.             case 1: DrawOpenSquare(x1, y1);     break;
  534.                     case 2: DrawOpenTriangle(x1, y1);     break;
  535.                     case 3: DrawOpenDiamon(x1, y1);     break;
  536.                       case 4: DrawCross(x1, y1);          break;
  537.                     case 5: DrawCloseSquare(x1, y1);    break;
  538.                     case 6: DrawCloseDiamon(x1, y1);    break;
  539.                   }
  540.         first_point = 0;
  541.         continue;
  542.           }
  543.  
  544.               x = RECT_X + RECT_W * (xent->v - x_min) / x_range;   
  545.               y = RECT_Y + RECT_H - RECT_H * (yent->v - y_min) / y_range;   
  546.  
  547.           if ((format == 'L') || (format == 'B')) 
  548.                 XDrawLine(dpy, win, maingcreversed, x1, y1, x, y);
  549.           if ((format == 'S') || (format == 'B'))
  550.         switch(i){
  551.           case 1: DrawOpenSquare(x, y);     break;
  552.                   case 2: DrawOpenTriangle(x, y);     break;
  553.                   case 3: DrawOpenDiamon(x, y);     break;
  554.                     case 4: DrawCross(x, y);          break;
  555.                   case 5: DrawCloseSquare(x, y);    break;
  556.                   case 6: DrawCloseDiamon(x, y);    break;
  557.                 }
  558.               x1 = x;
  559.               y1 = y;
  560.            }
  561.         }      
  562.      }  /* end of while */
  563.     XUnmapWindow(dpy, win);
  564.     XDestroyWindow(dpy, win);
  565.     /*XCloseDisplay(dpy); */  /* NO. don't do this anymore */
  566. }  /* end of plot_line */
  567.  
  568.  
  569. /*
  570.  * The following Drawing functions draw diffrent symbols. 
  571.  */
  572.  
  573. void DrawOpenDiamon(x, y)
  574. short x, y;
  575. {
  576.   XPoint points[5];
  577.  
  578.   points[0].x = x; 
  579.   points[0].y = y - 3; 
  580.   points[1].x = 3; 
  581.   points[1].y = 3; 
  582.   points[2].x = -3; 
  583.   points[2].y = 3; 
  584.   points[3].x = -3; 
  585.   points[3].y = -3; 
  586.   points[4].x = 3; 
  587.   points[4].y = -3; 
  588.   XDrawLines(dpy, win, maingcreversed, points, 5, CoordModePrevious);
  589. }
  590.  
  591. void DrawCloseDiamon(x, y)
  592. short x, y;
  593. {
  594.   XPoint points[12];
  595.  
  596.   points[0].x = x; 
  597.   points[0].y = y; 
  598.   points[1].x = -2; 
  599.   points[1].y = 0; 
  600.   points[2].x = 4; 
  601.   points[2].y = 0; 
  602.   points[3].x = -2; 
  603.   points[3].y = 0; 
  604.   points[4].x = 0; 
  605.   points[4].y = -2; 
  606.   points[5].x = 0; 
  607.   points[5].y = 4; 
  608.   points[6].x = 0; 
  609.   points[6].y = -2; 
  610.   points[7].x = 1; 
  611.   points[7].y = 1; 
  612.   points[8].x = -2; 
  613.   points[8].y = -2; 
  614.   points[9].x = 1; 
  615.   points[9].y = 1; 
  616.   points[10].x = -1; 
  617.   points[10].y = 1; 
  618.   points[11].x = 2; 
  619.   points[11].y = -2; 
  620.   XDrawLines(dpy, win, maingcreversed, points, 12, CoordModePrevious);
  621. }
  622.  
  623. void DrawOpenSquare(x, y)
  624. short x, y;
  625. {
  626.   XPoint points[5];
  627.   points[0].x = x - 2; 
  628.   points[0].y = y - 2; 
  629.   points[1].x = 4; 
  630.   points[1].y = 0; 
  631.   points[2].x = 0; 
  632.   points[2].y = 4; 
  633.   points[3].x = -4; 
  634.   points[3].y = 0; 
  635.   points[4].x = 0; 
  636.   points[4].y = -4; 
  637.   XDrawLines(dpy, win, maingcreversed, points, 5, CoordModePrevious);
  638. }
  639.  
  640. void DrawCloseSquare(x, y)
  641. short x, y;
  642. {
  643.   XPoint points[9];
  644.  
  645.   points[0].x = x - 2; 
  646.   points[0].y = y - 2; 
  647.   points[1].x = 4; 
  648.   points[1].y = 0; 
  649.   points[2].x = 0; 
  650.   points[2].y = 4; 
  651.   points[3].x = -4; 
  652.   points[3].y = 0; 
  653.   points[4].x = 0; 
  654.   points[4].y = -4; 
  655.   points[5].x = 4; 
  656.   points[5].y = 4; 
  657.   points[6].x = -2; 
  658.   points[6].y = -2; 
  659.   points[7].x = -2; 
  660.   points[7].y = 2; 
  661.   points[8].x = 4; 
  662.   points[8].y = -4; 
  663.   XDrawLines(dpy, win, maingcreversed, points, 9, CoordModePrevious);
  664. }
  665.  
  666. void DrawOpenTriangle(x, y)
  667. short x, y;
  668.   XPoint points[4];
  669.  
  670.   points[0].x = x; 
  671.   points[0].y = y - 3; 
  672.   points[1].x = 2; 
  673.   points[1].y = 5; 
  674.   points[2].x = -4; 
  675.   points[2].y = 0; 
  676.   points[3].x = 2; 
  677.   points[3].y = -5; 
  678.   XDrawLines(dpy, win, maingcreversed, points, 4, CoordModePrevious);
  679. }
  680.  
  681.  
  682. void DrawCross(x, y)
  683. short x, y;
  684. {
  685.   XPoint points[6];
  686.  
  687.   points[0].x = x; 
  688.   points[0].y = y; 
  689.   points[1].x = -2; 
  690.   points[1].y = 0; 
  691.   points[2].x = 4; 
  692.   points[2].y = 0; 
  693.   points[3].x = -2; 
  694.   points[3].y = 0; 
  695.   points[4].x = 0; 
  696.   points[4].y = -2; 
  697.   points[5].x = 0; 
  698.   points[5].y = 4; 
  699.   XDrawLines(dpy, win, maingcreversed, points, 6, CoordModePrevious);
  700. }
  701.  
  702. /*
  703.  * rm_tail_zero removes heading white spaces, trailing white spaces, 
  704.  * zero '0' and '.' of a string for nice printing of graph lable 
  705.  *
  706.  */
  707.  
  708. char *rm_tail_zero(s)
  709.    char  *s;
  710. {  
  711.    char *t;
  712.    /* Get rid of heading white spaces */
  713.    for (t = s; *t == ' ' || *t == '\t'; t++);
  714.    strcpy(s, t);
  715.  
  716.    /* Get rid of trailing white spaces and zeros */
  717.    t = s;
  718.    while ((*t) && (*t != '\n')) /* while not null or newline */
  719.       t++;
  720.    t--;
  721.    while ((t != s) && ((*t == ' ') || (*t == '0')))
  722.       t--;
  723.    if (*t != '.')     /* Get rid of trailing '.' */
  724.       t++;
  725.    *t = '\0';
  726.    return s;
  727. }
  728.