/*
 * Copyright (C) 1992  Board of Regents of the University of Wisconsin
 * on behalf of the Department of Electrical Engineering and Computer
 * Science, University of Wisconsin-Milwaukee, Milwaukee, WI 53201.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * a copy of which is included here in file "GNU_GENERAL"
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * The programs in this directory were developed by software engineering 
 * teams as part of the course "Introduction to Software Engineering" 
 * under the supervision of Professor G. Davida.
 * This is a modification of a program written or modified by
 * others.  The original copyrights, as per GNU General Public License,
 * may still be applicable.  The UWM copyright is applicable only
 * the those parts generated at UWM.
 *
 * Please send all changes, enhancements, and other comments about this
 * software to
 *     		soft-eng@cs.uwm.edu
 *
 * No Warranty, expressed or implied, comes with this software.
 * This software is intended to be used by not-for-profit
 * organizations or by individuals for personal HOME use. 
 * This software, or any of its parts, may not be used by for-profit
 * organization, regardless of application or intended product or
 * customer, without the permission of the Board of Regents of the 
 * University  of Wisconsin. 
 *
 * Contact:	soft-eng@cs.uwm.edu
 *			or
 *		
 *		Software Engineering Coordinator
 *		Computer Science
 *    		Department of EECS
 *		University of Wisconsin - Milwaukee
 *		Milwaukee, WI  53201
 *		414-229-4677
 *
 *		HISTORY,CLAIMS and CONTRIBUTIONS
 */
/***************************************************************************
 * This procedure produces a Pie Graph for the selected values in the current
 * spreadsheet.  It calculates the percentage of each cell, and then draws a
 * Pie slice the size according to the percentage.  It uses patterns located
 * in the file pattern.h which were created using the bitmap editor. 
 * Dan Gruber - November 1991         
 *
 * Modified 5/94 by Dan Coppersmith to improve user
 * friendliness of error functions. 
 **************************************************************************/ 
#include <config.h>

#ifdef HAVE_X11_X_H	/* this code for now is X specific */

#include <math.h>
#include <curses.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "plot.h" 
#include "graphic_gvar.h"
#include "sc.h"
#include "scXstuff.h"
#include "pattern.h"
#define TITLE "XSPREAD-Grapher (Pie Plot)"
#define PIE_D 300   /* Pie Diameter */
#define PIE_R 150   /* Pie Radius   */

#ifndef irint
#define irint(x) floor((x)+0.5)
#endif

/*
 * This structure forms the WM_HINTS property of the window,
 * letting the window manager know how to handle this window.
 * See Section 9.1 of the Xlib manual.
 */

   XWMHints     MyWMHints = {
	  (InputHint|StateHint),   /* flags         */
          False,                   /* input         */
          NormalState,             /* initial_state */
	  0,                       /* icon pixmap   */
	  0,                       /* icon window   */
          0, 0,                    /* icon location */
          0,                       /* icon mask     */
          0,                       /* Window group  */
   };

void
plot_pie()
{   
    int i,/* j, k, */ len;
    int text_w;
    int X, Y, X1, Y1, Temp_X,Temp_Y;
    struct ent *p, *val /*, *next_val */ ;
    int  looping = 1;             /* true if we shouldn't exit yet           */
    int draw  = 0;                /* true if we should paint the window      */
    int cells = 0; 
    int slice;                    /* Slice number                            */
    double Range_Total = 0;       /* Total of all of the cell values         */
    double Percentage = 0;        /* Percentage of the slice                 */ 
    double Angle_Size = 0;        /* Angle size of the slice                 */
    double Starting_Angle = 0;    /* Starting position for each slice        */
    double Rad_Angle = 0;         /* The angle in radians                    */ 
    double Bisector_Angle = 0;    /* The 'middle' of the angle               */
    double Label_R = 0;           /* Radius of the circle for drawing labels */
    Pixmap Pattern;               /* Pattern for a given slice               */
          
    char str[100];
    char per_str[10];
    /* register int c; */

    int argc = 0;
    char **argv = 0;


/*---- Colors added by Rama Devi ---------*/
Colormap cmap;
XColor exactBlack, exactOrange;
XColor exactGreen, exactGreenYellow, exactOrchid;
XColor exactYellow, exactAquamarine, exactGoldenrod;

XColor Black, Orange;
XColor Green, GreenYellow, Orchid, Yellow, Aquamarine, Goldenrod;

extern XFontStruct *curfont;       /* Font descriptor struct for current font */
extern Font       curfontid;       /* resource id of current font */
extern int        curfontwidth,
           curfontheight;   /* pixel dimensions of current font */

/* check that we have enough valid x values.  While we are looping,
 * determine the minimum and maximum x values, in case we need them
 */

   Range_Total = 0;
   for (i=graphic_range[0].r1; i <= graphic_range[0].r2; i++) { 
     p = lookat( i, graphic_range[0].c);
     val = lookat( i, graphic_range[1].c);
     if ((p->label) && (val->v)) /*FIXME continue;*/
       {
           Range_Total = Range_Total + val->v;
           cells++;
       } 
   } /* for i */

   if (cells < 1) {
     fprintf(stderr,"\007");
     if (graphic_range[0].r2 - graphic_range[0].r1 > 1)
	message("x values must be strings");
     else
	message("Not enough valid Labels (X values)");
     return;
   }

   /* 
    * Open a new display window
    */

   /*
    * Select colors for the border,  the window background,  and the
    * foreground.
    */

    /*---- Color added by Rama Devi --*/
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor(dpy, cmap, "Black", &exactBlack,
             &Black) != 0) && (XAllocNamedColor (dpy, cmap,
             "Orange", &exactOrange, &Orange) != 0))
      {
      bd = Orange.pixel;
      bg = Black.pixel;
      fg = Orange.pixel;
      }
    else 
      {
      bd = WhitePixel(dpy, DefaultScreen(dpy));
      bg = BlackPixel(dpy, DefaultScreen(dpy));
      fg = WhitePixel(dpy, DefaultScreen(dpy));
      }


  if (userfont == NULL)
     curfont = XLoadQueryFont(dpy, SC_FONT);
  else
     curfont = XLoadQueryFont(dpy, userfont);
  if (curfont == NULL)
  {
    fprintf(stderr, "%s: Display %s doesn't know font \"%s\" \n",
          progname, DisplayString(dpy), userfont == NULL ? SC_FONT : userfont);
    exit(1);
  }
  /* initialize the font-related globals */
  /* usefont(curfont); */
  curfontid = curfont->fid;
  curfontheight = curfont->max_bounds.ascent + curfont->max_bounds.descent;
  curfontwidth = curfont->max_bounds.width;

   /*
    * Set the border width of the window,  and the gap between the text
    * and the edge of the window, "pad".
    */

   pad = BORDER;
   bw = 1;

   /*
    * Deal with providing the window with an initial position & size.
    * Fill out the XSizeHints struct to inform the window manager.
    */

   xsh.width = XTextWidth(curfont, TITLE, 80 + pad * 2);
   xsh.flags = (PPosition | PSize);
   xsh.height = WIN_H; 
   xsh.width = WIN_W; 
   xsh.x = (DisplayWidth(dpy, DefaultScreen(dpy)) - xsh.width) / 2;
   xsh.y = (DisplayHeight(dpy, DefaultScreen(dpy)) - xsh.height) / 2;

   /*
    * Create the Window with the information in the XSizeHints, the
    * border width,  and the border & background pixels.
    */

   win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
                 xsh.x, xsh.y, xsh.width, xsh.height,
                            /*---  bw, bd, bg); ---*/
                              bw, fg, bg);

   /*
    * Set the standard properties for the window managers. 
    */

   XSetStandardProperties(dpy, win, TITLE, TITLE, 
		 None, argv, argc, &xsh);
   XSetWMHints(dpy, win, &MyWMHints);

   /*
    * Ensure that the window's colormap field points to the default
    * colormap,  so that the window manager knows the correct colormap to
    * use for the window.   Also,  set the window's Bit Gravity to reduce 
    * Expose events.
    */

   xswa.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
   xswa.bit_gravity = CenterGravity;
   XChangeWindowAttributes(dpy, win, (CWColormap | CWBitGravity), &xswa);

/*--- The following statement is added by Rama Devi ---*/
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Orange", &exactOrange, &Orange) != 0))
       {
       maingcreversed = XCreateGC(dpy, win, 0,0);
       XSetFont(dpy, maingcreversed, curfontid);
       XSetForeground (dpy, maingcreversed, Orange.pixel);
       XSetBackground (dpy, maingcreversed, Black.pixel);
       }
    else
       {
       maingcreversed = XCreateGC(dpy, win, 0,0);
       XSetFont(dpy, maingcreversed, curfontid);
       XSetForeground (dpy, maingcreversed, fg);
       XSetBackground (dpy, maingcreversed, bg);
       }  /*---*/

   /* 
    * Map the window to make it visible.  
    */
  
   XMapWindow(dpy, win);

   /*
    * Find out the dimension of the window.
    */

   if (XGetWindowAttributes(dpy, win, &xwa) == 0){
      fprintf(stderr,"plot_pie: Can't access attributes for graph window\n");
      exit(1);    
   }

   XClearWindow(dpy, win);
   XSelectInput(dpy,win, ButtonPressMask|KeyPressMask|ExposureMask);


while(looping)
 {   

    XEvent event;

    XNextEvent(dpy,&event);
    switch (event.type){
      case KeyPress: 
      case ButtonPress: looping = 0; 
			break;
      case Expose: draw = 1;
    }


    /* 
     * if not drawing, go back and get another event 
     */

    if (!draw) continue;

    /*
     * Draw titles
     */

    /* first graph title */
    len = strlen(graphic_title[0]);   
    text_w= XTextWidth(curfont, graphic_title[0], len);
    XDrawImageString(dpy, win, maingcreversed, (WIN_W-text_w)/2, RECT_Y/3,
                     graphic_title[0], len);

    /* second graph title */
    len = strlen(graphic_title[1]);
    text_w= XTextWidth(curfont, graphic_title[1], len);
    XDrawImageString(dpy, win, maingcreversed, 
		     (WIN_W - text_w)/2  , RECT_Y * 2/3,
                     graphic_title[1], len);

    Starting_Angle = 0;
    slice = 1;

    /*------- The following is commented by Rama Devi ----------

    -------for (i=graphic_range[0].r1,j=graphic_range[1].r1; 
        (i<=graphic_range[0].r2) && (j<=graphic_range[1].r2); i++, j++)----
    {  

    if graphic_range[1].r1 is greater than graphic_range[0].r1 and the
    difference between graphic-range[1].r1 and graphic-range[1].r2 is
    less than the difference between graphic_range[0].r1 and graphic_range[0].r2
    then the loop is executed only the difference between graphic-range[0].r1 
    and graphic-range[0].r2 times and comes out without drawing the graphs 
    for all the specified ranges     
    --------------------------------------------------------------*/
    /*-------- The following line is added by Rama Devi ----------*/

    for (i = graphic_range[0].r1; i <= graphic_range[0].r2; i++)
       {
       
      if (!((p=lookat(i,graphic_range[0].c))->label))
        continue;

      val=lookat(i,graphic_range[1].c);

      /* Calculate the percentage of the slice */
      Percentage = (val->v / Range_Total);
     
      /* 
       * If this is the last slice to be drawn, take '360 - Starting_Angle'
       * in case there is round-off errors.   
       */

      if (i == graphic_range[0].r2)
         Angle_Size = 360 - Starting_Angle;
      else 
         Angle_Size = Percentage * 360;

      /* Choose a pattern for drawing (They are located in pattern.h) */

/* ---- the following switch statement added by Rama Devi ----*/
              switch (slice % 6) {
    case 1 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Green", &exactGreen, &Green) != 0))
       {
       XSetForeground (dpy, maingcreversed, Green.pixel);
       XSetBackground (dpy, maingcreversed, Black.pixel);
       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       XSetBackground (dpy, maingcreversed, bg);
       }
                             break;

    case 2 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Orchid", &exactOrchid, &Orchid) != 0))
       {
       XSetForeground (dpy, maingcreversed, Orchid.pixel);
       }

    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       }
                             break;

    case 3 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "GreenYellow", &exactGreenYellow, &GreenYellow) != 0))
       {
       XSetForeground (dpy, maingcreversed, GreenYellow.pixel);
       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       }
                             break;

    case 4 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Goldenrod", &exactGoldenrod, &Goldenrod) != 0))
       {
       XSetForeground (dpy, maingcreversed, Goldenrod.pixel);

       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       }
                             break;

    case 5 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));

    if ((XAllocNamedColor (dpy, cmap, "Aquamarine", &exactAquamarine, &Aquamarine) != 0))
       {
       XSetForeground (dpy, maingcreversed, Aquamarine.pixel);
       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       }
                             break;

    case 0 :
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Yellow", &exactYellow, &Yellow) != 0))

      {
       XSetForeground (dpy, maingcreversed, Yellow.pixel);
       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       }
                             break; } /* --switch --- */


      switch (slice) {
        case 1 : Pattern = XCreateBitmapFromData(dpy,win,dark_wide_weave_bits,
                     dark_wide_weave_width, dark_wide_weave_height);
                     break;
        case 2: Pattern = XCreateBitmapFromData(dpy,win,diag_l_bits,
                     diag_l_width, diag_l_height);
                     break;
        case 3: Pattern = XCreateBitmapFromData(dpy,win,dark_root_weave_bits,
                     dark_root_weave_width, dark_root_weave_height);
                     break;
        case 4: Pattern = XCreateBitmapFromData(dpy,win,horiz_lines_bits,
                     horiz_lines_width, horiz_lines_height);
                     break;
        case 5: Pattern = XCreateBitmapFromData(dpy,win,dark_cross_weave_bits,
                     dark_cross_weave_width, dark_cross_weave_height);
                     break;
        case 6: Pattern = XCreateBitmapFromData(dpy,win,dark_diamond_bits,
                     dark_diamond_width, dark_diamond_height);
                     break;
        case 7 : Pattern = XCreateBitmapFromData(dpy,win,gray3_bits,
                     gray3_width, gray3_height);
                     break;
        case 8 : Pattern = XCreateBitmapFromData(dpy,win,gray5_bits,
                     gray5_width, gray5_height);
                     break;
        case 9 : Pattern = XCreateBitmapFromData(dpy,win,gray2_bits,
                     gray2_width, gray2_height);
                     break;
        case 10: Pattern = XCreateBitmapFromData(dpy,win,light_wide_weave_bits,
                     light_wide_weave_width, light_wide_weave_height);
                     break;
        case 11 : Pattern = XCreateBitmapFromData(dpy,win,diag_r_bits,
                     diag_r_width, diag_r_height);
                     break;
        case 12: Pattern = XCreateBitmapFromData(dpy,win,light_root_weave_bits,
                     light_root_weave_width, light_root_weave_height);
                     break;
        case 13: Pattern = XCreateBitmapFromData(dpy,win,vert_lines_bits,
                     vert_lines_width, vert_lines_height);
                     break;
        case 14: Pattern = XCreateBitmapFromData(dpy,win,light_cross_weave_bits,
                     light_cross_weave_width, light_cross_weave_height);
                     break;
        case 15: Pattern = XCreateBitmapFromData(dpy,win,light_diamond_bits,
                     light_diamond_width, light_diamond_height);
                     break;
        case 16 : Pattern = XCreateBitmapFromData(dpy,win,gray4_bits,
                     gray4_width, gray4_height);
                     break;
        case 17 : Pattern = XCreateBitmapFromData(dpy,win,gray1_bits,
                     gray1_width, gray1_height);
                     break;
        case 18: Pattern = XCreateBitmapFromData(dpy,win,checker_bits,
                     checker_width, checker_height);
                     break;
        case 19 : Pattern = XCreateBitmapFromData(dpy,win,black_bits,
                     black_width, black_height);
                     break;
        case 20 : Pattern = XCreateBitmapFromData(dpy,win,black_bits,
                     black_width, black_height);
                     break;
        
      };
      
      /* Set the fill style to allow for drawing patterns */ 
      XSetStipple(dpy,maingcreversed,Pattern);
      XSetFillStyle(dpy, maingcreversed, FillStippled);
      
      /* Draw a single pie slice */
      XFillArc(dpy, win, maingcreversed,
            (WIN_W/2)-(PIE_R), (WIN_H/2)-(PIE_R)*4/5, PIE_D, PIE_D,
            irint(Starting_Angle)*64, irint(Angle_Size*64) );

      /* Set fill style back to solid for drawing lines */
      XSetFillStyle(dpy, maingcreversed, FillSolid); 
       
      /* 
       * This section converts the Starting_Angle from degrees to radians 
       * and then calculates the proper positions for drawing the line
       * separators, and then draws them.
       */ 

      Rad_Angle = Starting_Angle * PI / 180;
      Temp_X = (PIE_R) * cos(Rad_Angle);
      Temp_Y = -((PIE_R) * sin(Rad_Angle));
      X = Temp_X + (WIN_W/2);
      Y = Temp_Y + (WIN_H/2) + (PIE_R/5);
      XDrawLine(dpy,win,maingcreversed,WIN_W/2,(WIN_H/2 + PIE_R/5),X,Y); 

      /* 
       * This section draws the label for the given slice by calculating the
       * angle bisector of the slice and then draws the Labels outside the
       * Pie a distance of one fifth the radius of the Pie.
       */

      Label_R = PIE_R + (PIE_R/5);
      Bisector_Angle = Starting_Angle + (Angle_Size/2);
      Rad_Angle = Bisector_Angle * PI / 180;
      Temp_X = (Label_R) * cos(Rad_Angle);
      Temp_Y = -((Label_R) * sin(Rad_Angle));
      X1 = Temp_X + (WIN_W/2);
      Y1 = Temp_Y + (WIN_H/2) + (PIE_R/5);
      strncpy(str,p->label,strlen(p->label));
      len = strlen(p->label); 
      str[len] = '\0';
      sprintf(per_str,"%.1f",(Percentage * 100));
      strcat(str, " (");
      strcat(str,per_str);
      strcat(str,"%)");
      len = strlen(str);
      text_w = XTextWidth(curfont, str, len);
      
      /* If the slice is on the left side of the Pie, make proper adjustment */
      if ((Bisector_Angle > 90) && (Bisector_Angle <= 270))
          X = X1 - text_w;
      else
          X = X1;
      Y = Y1 + curfontheight/2;
      XDrawImageString(dpy,win,maingcreversed,X,Y,str,len);
  
      /* Calculate the next Starting_Angle */
      /*Starting_Angle = irint(Starting_Angle) + irint(Angle_Size);*/
      /* irint changed to rint by Bob Parbs */
      Starting_Angle = (Starting_Angle) + (Angle_Size);
      slice++;
    } 
    /*---- The following two statements added by Rama Devi ----*/
    cmap = DefaultColormap(dpy, DefaultScreen(dpy));
    if ((XAllocNamedColor (dpy, cmap, "Orange", &exactOrange, &Orange) != 0))
       {
       XSetForeground (dpy, maingcreversed, Orange.pixel);
       XSetBackground (dpy, maingcreversed, Black.pixel);
       }
    else
       {
       XSetForeground (dpy, maingcreversed, fg);
       XSetBackground (dpy, maingcreversed, bg);
       }

    /* Draw a complete circle around the Pie */
    XSetFillStyle(dpy, maingcreversed, FillSolid); 
    XDrawArc(dpy, win, maingcreversed,(WIN_W/2)-(PIE_R),(WIN_H/2)-(PIE_R)*4/5, 
             PIE_D, PIE_D, 0, 360*64); 
  } /* end of while */  

    /*---- The following statements added by Rama Devi ----*/
cmap = DefaultColormap (dpy, DefaultScreen (dpy));
if (backg && (XAllocNamedColor (dpy, cmap, backg, &exactOrange, &Orange) != 0))
    {
    bg = Orange.pixel;
    }
   else
    {
    bg = WhitePixel(dpy, DefaultScreen(dpy)); /* background */
    }
if (foreg && (XAllocNamedColor (dpy, cmap, foreg, &exactBlack, &Black) != 0))
    {
    fg = Black.pixel;
    }
   else
    {
    fg = BlackPixel(dpy, DefaultScreen(dpy)); /* foreground */
    }
      XSetForeground (dpy, maingc, fg);
      XSetBackground (dpy, maingc, bg);
      XSetForeground (dpy, maingcreversed, bg);
      XSetBackground (dpy, maingcreversed, fg);

XSetPlaneMask(dpy, invertgc, bg^fg);

  XUnmapWindow(dpy, win);
  XDestroyWindow(dpy, win);
}
#endif /* HAVE_X11_X_H	this code for now is X specific */


syntax highlighted by Code2HTML, v. 0.9.1