home *** CD-ROM | disk | FTP | other *** search
/ pc.louisiana.edu/pub/unix/ / Louisiana_UNIX.tar / Louisiana_UNIX / xspread3.0.zoo / plot_line.c < prev    next >
C/C++ Source or Header  |  1994-06-02  |  22KB  |  760 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 procedure will display the line graph given the values provided by    *
  56.  * the user.  It evenly spaces out the columns depending on the number of     *
  57.  * X-Values which are used.
  58.  * Dan Gruber - October 1991                                                  *
  59.  *   Modified 5/94 by Dan Coppersmith to improve user friendliness of
  60.  *   error messages.
  61.  **************************************************************************** 
  62.  */
  63.  
  64. #include <math.h>
  65. #include <stdio.h>
  66. #include <X11/Xlib.h>
  67. #include <X11/Xutil.h>
  68. #include "config.h"
  69. #include "plot.h" 
  70. #include "graphic_gvar.h"
  71. #include "sc.h"
  72. #include "scXstuff.h"
  73. #define TITLE "XSPREAD-Grapher (Line Plot)"
  74. #define PIX_SEP 3
  75.  
  76. #ifndef irint
  77. #define irint(x) floor((x)+0.5)
  78. #endif
  79.  
  80. /*
  81.  * This structure forms the WM_HINTS property of the window,
  82.  * letting the window manager know how to handle this window.
  83.  * See Section 9.1 of the Xlib manual.
  84.  */
  85.  
  86.    XWMHints     XWMH = {
  87.       (InputHint|StateHint),   /* flags         */
  88.           False,                   /* input         */
  89.           NormalState,             /* initial_state */
  90.       0,                       /* icon pixmap   */
  91.       0,                       /* icon window   */
  92.           0, 0,                    /* icon location */
  93.           0,                       /* icon mask     */
  94.           0,                       /* Window group  */
  95.    };
  96.  
  97.  
  98. plot_line()
  99. {   double max_y, min_y; 
  100.     double Y_Range;
  101.     double y_power, x_power; 
  102.     double grid_w;
  103.    
  104.     int  i, j, k, len;
  105.     int  first_y_datum=1;
  106.     int  grid_l_x, grid_l_y, grid_h;
  107.     int  font_w, text_w;
  108.     int  legend_n;
  109.     int  x, y, x1, y1;
  110.     int  looping = 1;  /* true if we shouldn't exit yet                    */
  111.     int  draw = 0;     /* true if we should paint the window               */
  112.     char format;       /* graph format specifier, (L)ine, (S)ymbol, (B)oth */
  113.     int  first_point;  /* true when getting coords for 1st point in curve  */
  114.     struct ent *p;
  115.     struct ent *yent;  /* table entries y values                           */
  116.     int cells=0; 
  117.     int items=0;
  118.     int number_of_items=0;
  119.     int width;         /* used to calculate the Labelsize */
  120.     int labelsize;     /* The size of the Label to be drawn */
  121.     
  122.     char str[100];
  123.     register int c;
  124.  
  125.     int argc = 0;
  126.     char **argv;
  127.  
  128. /* check that we have enough valid x values.  While we are looping,
  129.  * determine the minimum and maximum x values, in case we need them
  130.  */
  131.  
  132.    for (i=graphic_range[0].r1; i <= graphic_range[0].r2; i++) { 
  133.      p = lookat( i, graphic_range[0].c);
  134.      if (!(p->label)) continue;
  135.        cells++;
  136.    } /* for i */
  137.  
  138.    if (cells < 2) {
  139.      fprintf(stderr,"\007");
  140.      if (graphic_range[0].r2 - graphic_range[0].r1 > 1)
  141.     message("x values must be strings");
  142.      else message("Not enough valid X values");
  143.      return;
  144.    }
  145.  
  146.    number_of_items = cells;
  147.  
  148. /* 
  149.  * The plotting job now
  150.  */
  151.  
  152.     /*
  153.      *  Decide the scale for x and y axes
  154.      */
  155.  
  156.      /* calculate y limits automatically or manually */
  157.      if (g_auto_man[1] == 'M'){
  158.         max_y = graphic_scale[1][1];
  159.         min_y = graphic_scale[1][0];
  160.      } else {
  161.         first_y_datum = 1;
  162.     for (j = 1; j < GRAPHRANGES; j++) { 
  163.  
  164.            if (*(graphic_range[j].col) == '\0') continue;
  165.  
  166.            for (i=graphic_range[j].r1; i <= graphic_range[j].r2; i++) { 
  167.          p = lookat(i, graphic_range[j].c);
  168.          if ( !(p->flags & is_valid)) continue; /* ignore invalid */
  169.              if (first_y_datum) {
  170.                max_y = p->v;
  171.                min_y = p->v;
  172.                first_y_datum = 0;
  173.              } else {
  174.                max_y = Max(max_y, p->v); 
  175.                min_y = Min(min_y, p->v);
  176.          }
  177.            }
  178.         }
  179.      } 
  180.    /* protection for the case max == min */
  181.    if (min_y == max_y) {
  182.        max_y = 1.01 * max_y;
  183.        min_y = 0.99 * min_y;
  184.     }
  185.    
  186.     y_power = - floor(log10((max_y - min_y)));
  187.     y_power = Lpow10(y_power);
  188.  
  189.     min_y = floor(min_y * y_power) / y_power;
  190.     max_y = ceil(max_y * y_power) / y_power;
  191.     Y_Range = max_y - min_y;
  192.     
  193.     /* 
  194.      * Open a new display window
  195.      */
  196.  
  197.     /*
  198.      * Select colors for the border,  the window background,  and the
  199.      * foreground.
  200.      */
  201.  
  202.     bd = WhitePixel(dpy, DefaultScreen(dpy));
  203.     bg = BlackPixel(dpy, DefaultScreen(dpy));
  204.     fg = WhitePixel(dpy, DefaultScreen(dpy));
  205.  
  206.     /*
  207.      * Set the border width of the window,  and the gap between the text
  208.      * and the edge of the window, "pad".
  209.      */
  210.  
  211.     pad = BORDER;
  212.     bw = 1;
  213.  
  214.     /*
  215.      * Deal with providing the window with an initial position & size.
  216.      * Fill out the XSizeHints struct to inform the window manager.
  217.      */
  218.  
  219.     xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);
  220.  
  221.     xsh.flags = (PPosition | PSize);
  222.     xsh.height = WIN_H; 
  223.     xsh.width = WIN_W; 
  224.     xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
  225.     xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;
  226.  
  227.     /*
  228.      * Create the Window with the information in the XSizeHints, the
  229.      * border width,  and the border & background pixels.
  230.      */
  231.  
  232.     win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
  233.                   xsh.x, xsh.y, xsh.width, xsh.height,
  234.                   bw, bd, bg);
  235.  
  236.     /*
  237.      * Set the standard properties for the window managers. 
  238.      */
  239.  
  240.     XSetStandardProperties(dpy, win, TITLE, TITLE, 
  241.                None, argv, argc, &xsh);
  242.     XSetWMHints(dpy, win, &XWMH);
  243.  
  244.     /*
  245.      * Ensure that the window's colormap field points to the default
  246.      * colormap,  so that the window manager knows the correct colormap to
  247.      * use for the window.   Also,  set the window's Bit Gravity to reduce 
  248.      * Expose events.
  249.      */
  250.  
  251.     xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
  252.     xswa.bit_gravity = CenterGravity;
  253.     XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);
  254.  
  255.  
  256.     /* 
  257.      * Map the window to make it visible.  
  258.      */
  259.    
  260.      XMapWindow(dpy, win);
  261.  
  262.     /*
  263.      * Find out the dimension of the window.
  264.      */
  265.  
  266.     if (XGetWindowAttributes(dpy, win, &xwa) == 0){
  267.        fprintf(stderr,"plot_XY: Can't access attributes for graph window\n");
  268.        exit(1);    
  269.     }
  270.  
  271.     XClearWindow(dpy, win);
  272.     XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);
  273.  
  274. while(looping)
  275.  {   
  276.  
  277.     XEvent event;
  278.  
  279.     XNextEvent(dpy,&event);
  280.     switch (event.type){
  281.       case KeyPress: 
  282.       case ButtonPress: looping = 0; 
  283.             break;
  284.       case Expose: draw = 1;
  285.     }
  286.  
  287.  
  288.     /* if not drawing, go back and get another event */
  289.     if (!draw) continue;
  290.  
  291.     /*
  292.      * Draw the coordinate box
  293.      */
  294.  
  295.     XDrawRectangle(dpy, win, maingcreversed, RECT_X, RECT_Y, RECT_W, RECT_H); 
  296.     
  297.     /*  grid_l_y and grid_l_x are the length of the grid lines.  
  298.      *  Only tick marks are drawn when the value is '8'.
  299.      */
  300.  
  301.     if (graphic_grid == 'H') {              /* horizontal grid     */
  302.        grid_l_x = RECT_W;
  303.        grid_l_y = 8;
  304.     }
  305.     else if (graphic_grid == 'V') {         /* vertical grid       */
  306.        grid_l_x = 8;
  307.        grid_l_y = RECT_H;
  308.     }
  309.     else if (graphic_grid == 'B') {         /* both direction grid */
  310.        grid_l_x = RECT_W;
  311.        grid_l_y = RECT_H;
  312.     }
  313.     else {
  314.        grid_l_x = 8;                        /* no grid             */
  315.        grid_l_y = 8;
  316.     }
  317.        
  318.  
  319.     grid_w = RECT_W / (double)(number_of_items + 1);  /* grid seperation */
  320.     grid_h = RECT_H / 10;
  321.  
  322.     /*
  323.      * Draw grids along with the labels on the Y-Axis
  324.      */
  325.  
  326.     for (i = 0; i < 11; i++) {
  327.        XDrawLine(dpy, win, maingcreversed, 
  328.          RECT_X, RECT_Y + i * grid_h, 
  329.          RECT_X + grid_l_x, RECT_Y + i * grid_h); 
  330.        XDrawLine(dpy, win, maingcreversed, 
  331.          RECT_X + RECT_W, RECT_Y + i * grid_h, 
  332.                  RECT_X + RECT_W - grid_l_x, RECT_Y + i * grid_h); 
  333.  
  334.                  sprintf(str,"%.1f",(max_y - Y_Range*i/10));
  335.                  len = strlen(str);
  336.                  text_w = XTextWidth(curfont,str,len+2);
  337.                  XDrawImageString(dpy,win,maingcreversed,
  338.                             RECT_X - text_w,
  339.                             RECT_Y + i*grid_h + curfontheight/3,
  340.                             str,len);
  341.  
  342.        } /*end for loop*/
  343.  
  344.  
  345.     for (i = 1; i < (number_of_items + 1); i++) {
  346.        x = RECT_X + i * grid_w;
  347.        XDrawLine(dpy, win, maingcreversed, 
  348.          x, RECT_Y, 
  349.          x, RECT_Y + grid_l_y); 
  350.        XDrawLine(dpy, win, maingcreversed,
  351.                  x, RECT_Y + RECT_H, 
  352.                  x, RECT_Y + RECT_H - grid_l_y); 
  353.     }
  354.  
  355.     /*
  356.      * Draw titles
  357.      */
  358.  
  359.     /* first graph title */
  360.     len = strlen(graphic_title[0]);   
  361.     text_w= XTextWidth(curfont, graphic_title[0], len);
  362.     XDrawImageString(dpy, win, maingcreversed, (WIN_W - text_w)/2, RECT_Y/3,
  363.                      graphic_title[0], len);
  364.  
  365.     /* second graph title */
  366.     len = strlen(graphic_title[1]);
  367.     text_w= XTextWidth(curfont, graphic_title[1], len);
  368.     XDrawImageString(dpy, win, maingcreversed, (WIN_W - text_w)/2, RECT_Y*2/3, 
  369.                      graphic_title[1], len);
  370.  
  371.     /* x-axis title */
  372.     len = strlen(graphic_title[2]);
  373.     text_w= XTextWidth(curfont, graphic_title[2], len);
  374.     XDrawImageString(dpy, win, maingcreversed, 
  375.              (WIN_W - text_w)/2, RECT_H + RECT_Y * 3/2, 
  376.              graphic_title[2], len);
  377.   
  378.     /* y-axis title */
  379.     len = strlen(graphic_title[3]);
  380.     text_w=XTextWidth(curfont,graphic_title[3],len);
  381.        if ((RECT_X-text_w) < 0)
  382.            x = curfontwidth;
  383.        else
  384.            x = RECT_X-text_w;
  385.     XDrawImageString(dpy, win, maingcreversed,
  386.        x, RECT_Y - curfontheight,
  387.        graphic_title[3],len);
  388.  
  389.  
  390.     /*
  391.      * Draw Labels on the X-Axis
  392.      */
  393.  
  394.     width = (RECT_W - (PIX_SEP * (number_of_items + 1)))/number_of_items;
  395.     labelsize = irint(floor(width/(double)curfontwidth)-1);
  396.     y = RECT_Y + RECT_H + curfontheight;
  397.     items = 0; 
  398.     for (i=graphic_range[0].r1; i<=graphic_range[0].r2; i++)
  399.     {
  400.         p = lookat(i,graphic_range[0].c);
  401.         if (!(p->label)) continue;
  402.  
  403.         x1 = RECT_X + ((items+1)*(grid_w));
  404.         items++;
  405.         strncpy(str, p->label, labelsize);
  406.         str[labelsize] = '\0';
  407.         len = strlen(str);
  408.         text_w = XTextWidth(curfont, str, len);
  409.         
  410.         x = x1-(text_w / 2);
  411.         XDrawImageString(dpy,win,maingcreversed,
  412.                     x,y,str,len);
  413.     } 
  414.  
  415.  
  416.     /*
  417.      *  Draw legends
  418.      */
  419.  
  420.     legend_n = 0;
  421.     for (i = 0;  i < GRAPHLEGENDS; i++) {
  422.        if ((*(graphic_range[i + 1].col) == '\0') || (curves_n < 1) || 
  423.            (graphic_legend[i][0] == '\0')) 
  424.           continue;
  425.  
  426.       len = strlen(graphic_legend[i]);
  427.           text_w = XTextWidth(curfont, graphic_legend[i], len);
  428.       if (curves_n == 1) { 
  429.                                 /* Draw the legend symble */
  430.         if (graphic_format[i] == 'L') {
  431.            XDrawLine(dpy, win, maingcreversed, 
  432.              RECT_X +(RECT_W - text_w) / 2  - 15, 
  433.                      RECT_Y * 7 / 4 +RECT_H, RECT_X +(RECT_W - text_w) / 2 - 5, 
  434.                      RECT_Y * 7 / 4 +RECT_H); 
  435.         }
  436.         else if ((graphic_format[i] == 'S') || (graphic_format[i] == 'B')) {
  437.        x = RECT_X + (RECT_W - text_w) / 2 - 10;
  438.        y = RECT_Y * 7 / 4 + RECT_H;
  439.            switch (i) {
  440.              case 0: LDrawOpenSquare(x,y);     break;
  441.              case 1: LDrawOpenTriangle(x,y);     break;
  442.              case 2: LDrawOpenDiamon(x,y);     break;
  443.              case 3: LDrawCross(x,y);         break;
  444.              case 4: LDrawCloseSquare(x,y);     break;
  445.              case 5: LDrawCloseDiamon(x,y);     break;
  446.            }
  447.            if (graphic_format[i] == 'B') 
  448.               XDrawLine(dpy, win, maingcreversed, 
  449.             x-5, y,
  450.             x+5, y); 
  451.         } 
  452.                                  /* Draw the legend title */
  453.  
  454.         XDrawImageString(dpy, win, maingcreversed, 
  455.              RECT_X + (RECT_W - text_w)/2, RECT_Y*7/4 + RECT_H, 
  456.              graphic_legend[i], len);
  457.         break;
  458.      }
  459.      else {
  460.  
  461.                  /* Draw the legend symbols */
  462.  
  463.         if (graphic_format[i] == 'L') {
  464.            XDrawLine(dpy, win, maingcreversed ,
  465.              RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 15, 
  466.              RECT_Y * 7 / 4 + RECT_H, 
  467.              RECT_X / 2 + legend_n * (WIN_W / curves_n - 10) - 5, 
  468.              RECT_Y *7 / 4 + RECT_H); 
  469.         }
  470.         else if ((graphic_format[i] == 'S') || (graphic_format[i] == 'B')) {
  471.            switch (i) {
  472.            case 0:
  473.               LDrawOpenSquare(RECT_X/2 + legend_n*(WIN_W / curves_n - 10) - 10, 
  474.                              RECT_Y * 7 / 4 + RECT_H);
  475.               break;
  476.            case 1:
  477.               LDrawOpenTriangle(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  478.                                RECT_Y * 7 / 4 + RECT_H);
  479.               break;
  480.            case 2:
  481.               LDrawOpenDiamon(RECT_X/2 + legend_n * (WIN_W/curves_n - 10) - 10, 
  482.                              RECT_Y*7/4 + RECT_H);
  483.               break;
  484.            case 3:
  485.               LDrawCross(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  486.                         RECT_Y*7/4 + RECT_H);
  487.               break;
  488.            case 4:
  489.               LDrawCloseSquare(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  490.                               RECT_Y*7/4 + RECT_H);
  491.               break;
  492.            case 5:
  493.               LDrawCloseDiamon(RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 10, 
  494.                               RECT_Y*7/4 + RECT_H);
  495.               break;
  496.            }
  497.            if (graphic_format[i] == 'B')
  498.               XDrawLine(dpy, win, maingcreversed ,
  499.             RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 15, 
  500.             RECT_Y*7/4 + RECT_H, 
  501.             RECT_X/2 + legend_n*(WIN_W/curves_n - 10) - 5, 
  502.             RECT_Y*7/4 + RECT_H); 
  503.           
  504.         }
  505.  
  506.                                    /* Draw the legend titles */
  507.         XDrawImageString(dpy, win, maingcreversed, 
  508.              RECT_X/2 + legend_n*(WIN_W/curves_n - 10), 
  509.              RECT_Y*7/4 + RECT_H, 
  510.                          graphic_legend[i], len);
  511.         legend_n ++;
  512.       }
  513.    }
  514.  
  515.  
  516. /* 
  517.  * Draw curves
  518.  */
  519.         for (i = 1; i < GRAPHRANGES; i++) { 
  520.            if (*(graphic_range[i].col) == '\0') continue;
  521.        
  522.        first_point = 1;
  523.        format = graphic_format[i];
  524.            items = 0; 
  525.  
  526.            for (j = graphic_range[0].r1, k = graphic_range[i].r1;
  527.                (j <= graphic_range[0].r2) && (k <= graphic_range[i].r2); j++, k++) {
  528.               if (!((p=lookat(j,graphic_range[0].c))->label)) continue;
  529.               x = RECT_X + (items+1)*grid_w ;
  530.               items++;
  531.  
  532.           yent = lookat(j, graphic_range[i].c);
  533.           if (!(yent->flags & is_valid) || (yent->v < min_y) 
  534.           || (yent->v > max_y))
  535.         continue;
  536.  
  537.           if (first_point){
  538.                 x1 = x;
  539.                y1 = RECT_Y + RECT_H - RECT_H * (yent->v - min_y) / Y_Range;   
  540.             if ((format == 'S') || (format == 'B'))
  541.             switch(i){
  542.             case 1: LDrawOpenSquare(x1, y1);     break;
  543.                     case 2: LDrawOpenTriangle(x1, y1);     break;
  544.                     case 3: LDrawOpenDiamon(x1, y1);     break;
  545.                       case 4: LDrawCross(x1, y1);          break;
  546.                     case 5: LDrawCloseSquare(x1, y1);    break;
  547.                     case 6: LDrawCloseDiamon(x1, y1);    break;
  548.                   }
  549.         first_point = 0;
  550.         continue;
  551.           }
  552.  
  553.               y = RECT_Y + RECT_H - RECT_H * (yent->v - min_y) / Y_Range;   
  554.  
  555.           if ((format == 'L') || (format == 'B')) 
  556.                 XDrawLine(dpy, win, maingcreversed, x1, y1, x, y);
  557.           if ((format == 'S') || (format == 'B'))
  558.         switch(i){
  559.           case 1: LDrawOpenSquare(x, y);     break;
  560.                   case 2: LDrawOpenTriangle(x, y);     break;
  561.                   case 3: LDrawOpenDiamon(x, y);     break;
  562.                     case 4: LDrawCross(x, y);          break;
  563.                   case 5: LDrawCloseSquare(x, y);    break;
  564.                   case 6: LDrawCloseDiamon(x, y);    break;
  565.                 }
  566.               x1 = x;
  567.               y1 = y;
  568.            }
  569.         }      
  570.      }  /* end of while */
  571.     XUnmapWindow(dpy, win);
  572.     XDestroyWindow(dpy, win);
  573.     /*XCloseDisplay(dpy); */  /* NO. don't do this anymore */
  574. }  /* end of plot_line */
  575.  
  576.  
  577. /*
  578.  * The following Drawing functions draw diffrent symbols. 
  579.  */
  580.  
  581. void LDrawOpenDiamon(x, y)
  582. short x, y;
  583. {
  584.   XPoint points[5];
  585.  
  586.   points[0].x = x; 
  587.   points[0].y = y - 3; 
  588.   points[1].x = 3; 
  589.   points[1].y = 3; 
  590.   points[2].x = -3; 
  591.   points[2].y = 3; 
  592.   points[3].x = -3; 
  593.   points[3].y = -3; 
  594.   points[4].x = 3; 
  595.   points[4].y = -3; 
  596.   XDrawLines(dpy, win, maingcreversed, points, 5, CoordModePrevious);
  597. }
  598.  
  599. void LDrawCloseDiamon(x, y)
  600. short x, y;
  601. {
  602.   XPoint points[12];
  603.  
  604.   points[0].x = x; 
  605.   points[0].y = y; 
  606.   points[1].x = -2; 
  607.   points[1].y = 0; 
  608.   points[2].x = 4; 
  609.   points[2].y = 0; 
  610.   points[3].x = -2; 
  611.   points[3].y = 0; 
  612.   points[4].x = 0; 
  613.   points[4].y = -2; 
  614.   points[5].x = 0; 
  615.   points[5].y = 4; 
  616.   points[6].x = 0; 
  617.   points[6].y = -2; 
  618.   points[7].x = 1; 
  619.   points[7].y = 1; 
  620.   points[8].x = -2; 
  621.   points[8].y = -2; 
  622.   points[9].x = 1; 
  623.   points[9].y = 1; 
  624.   points[10].x = -1; 
  625.   points[10].y = 1; 
  626.   points[11].x = 2; 
  627.   points[11].y = -2; 
  628.   XDrawLines(dpy, win, maingcreversed, points, 12, CoordModePrevious);
  629. }
  630.  
  631. void LDrawOpenSquare(x, y)
  632. short x, y;
  633. {
  634.   XPoint points[5];
  635.   points[0].x = x - 2; 
  636.   points[0].y = y - 2; 
  637.   points[1].x = 4; 
  638.   points[1].y = 0; 
  639.   points[2].x = 0; 
  640.   points[2].y = 4; 
  641.   points[3].x = -4; 
  642.   points[3].y = 0; 
  643.   points[4].x = 0; 
  644.   points[4].y = -4; 
  645.   XDrawLines(dpy, win, maingcreversed, points, 5, CoordModePrevious);
  646. }
  647.  
  648. void LDrawCloseSquare(x, y)
  649. short x, y;
  650. {
  651.   XPoint points[9];
  652.  
  653.   points[0].x = x - 2; 
  654.   points[0].y = y - 2; 
  655.   points[1].x = 4; 
  656.   points[1].y = 0; 
  657.   points[2].x = 0; 
  658.   points[2].y = 4; 
  659.   points[3].x = -4; 
  660.   points[3].y = 0; 
  661.   points[4].x = 0; 
  662.   points[4].y = -4; 
  663.   points[5].x = 4; 
  664.   points[5].y = 4; 
  665.   points[6].x = -2; 
  666.   points[6].y = -2; 
  667.   points[7].x = -2; 
  668.   points[7].y = 2; 
  669.   points[8].x = 4; 
  670.   points[8].y = -4; 
  671.   XDrawLines(dpy, win, maingcreversed, points, 9, CoordModePrevious);
  672. }
  673.  
  674. void LDrawOpenTriangle(x, y)
  675. short x, y;
  676.   XPoint points[4];
  677.  
  678.   points[0].x = x; 
  679.   points[0].y = y - 3; 
  680.   points[1].x = 2; 
  681.   points[1].y = 5; 
  682.   points[2].x = -4; 
  683.   points[2].y = 0; 
  684.   points[3].x = 2; 
  685.   points[3].y = -5; 
  686.   XDrawLines(dpy, win, maingcreversed, points, 4, CoordModePrevious);
  687. }
  688.  
  689.  
  690. void LDrawCross(x, y)
  691. short x, y;
  692. {
  693.   XPoint points[6];
  694.  
  695.   points[0].x = x; 
  696.   points[0].y = y; 
  697.   points[1].x = -2; 
  698.   points[1].y = 0; 
  699.   points[2].x = 4; 
  700.   points[2].y = 0; 
  701.   points[3].x = -2; 
  702.   points[3].y = 0; 
  703.   points[4].x = 0; 
  704.   points[4].y = -2; 
  705.   points[5].x = 0; 
  706.   points[5].y = 4; 
  707.   XDrawLines(dpy, win, maingcreversed, points, 6, CoordModePrevious);
  708. }
  709.  
  710. /*
  711.  * Lpow10 calculates the power function of base 10
  712.  */
  713.  
  714. double Lpow10(p)
  715.    double p;
  716. {
  717.    double q;
  718.  
  719.    p = floor(p);
  720.    if (p >= 0) {
  721.       for (q = 1; p > 0; --p)
  722.          q = q * 10;
  723.    }
  724.    else {
  725.       p = -p;
  726.       for (q = 1; p > 0; --p)
  727.          q = q / 10;
  728.    }
  729.    return q;
  730. }
  731.  
  732.  
  733. /*
  734.  * Lrm_tail_zero removes heading white spaces, trailing white spaces, 
  735.  * zero '0' and '.' of a string for nice printing of graph lable 
  736.  *
  737.  */
  738.  
  739. char *Lrm_tail_zero(s)
  740.    char  *s;
  741. {  
  742.    char *t;
  743.    /* Get rid of heading white spaces */
  744.    for (t = s; *t == ' ' || *t == '\t'; t++);
  745.    strcpy(s, t);
  746.  
  747.    /* Get rid of trailing white spaces and zeros */
  748.    t = s;
  749.    while ((*t) && (*t != '\n')) /* while not null or newline */
  750.       t++;
  751.    t--;
  752.    while ((t != s) && ((*t == ' ') || (*t == '0')))
  753.       t--;
  754.    if (*t != '.')     /* Get rid of trailing '.' */
  755.       t++;
  756.    *t = '\0';
  757.    return s;
  758. }
  759.