/******************************************************************** This file is part of the abs 0.907 distribution. abs is a spreadsheet with graphical user interface. Copyright (C) 1998-2001 André Bertin (Andre.Bertin@ping.be) 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 if in the same spirit as version 2. 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 along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Concact: abs@pi.be http://home.pi.be/bertin/abs.shtml *********************************************************************/ #include #include #include #include #include #include #include "plot.h" #include #include #include "plot.h" #include "graphic_gvar.h" #include "graph.h" #include "gr_interf.h" #ifndef PI #define PI 3.14 #endif #ifdef mips #define irint(x) rint(x) #endif #ifndef irint #define irint(x) floor((x)+0.5) #endif extern char *textparsing (char *buf); int D; int curfontwidth, curfontheight; #define Nwidths 10 unsigned int widths[Nwidths] = {2, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #define Ndashes 10 char dashes[Ndashes][5]; int plotcol[10] = {20 + 5, 2 + 5, 17 + 5, 25 + 4, 27 + 4, 29 + 4, 31 + 4, 1 + 4, 24 + 4, 20 + 4}; enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode; extern int getpixmap (); extern double get_value (); extern char *get_text (); static Pixmap gpixmap; static Display *gdpy; static Graph *ggr; static int X0, Y0; static double grvalue[10][100]; static char grtext[100][32]; static int imax, jmax; int newplot (Widget drawa, Graph * gr) { int gX, gY, W, H; ggr = gr; if (ggr == NULL) return -1; if (ggr->pixmap == 0) return -2; getpixmap (gr, &gX, &gY, &W, &H); gpixmap = gr->pixmap; X0 = gX; Y0 = gY; WIN_W = W; WIN_H = H; RECT_X = 40; RECT_Y = 40; RECT_W = W - 80; RECT_H = H - 80; D = 8; gdpy = XtDisplay (drawa); setfont2 (0, 1, 0, 2); curfontheight = gettexth ("W", 1, 1, 0, 2); curfontwidth = gettextw ("W", 1, 1, 0, 2); fillrectangle (gdpy, gpixmap, 0, 0, 0, W, H, X0, Y0, -1); setbackground (0, 0); setforeground (0, 1); drawrectangle (gdpy, gpixmap, 0, 0, 0, W, H, X0, Y0); set_grvalue (); switch (gr->type) { case 0: plot_XY (); break; case 1: plot_pie (); break; case 2: plot_bar (); break; default: plot_XY (); break; } return 0; } int set_grvalue () { int ii, jj, i, j; char *buf; jmax = 0; if (ggr->numrange == 1) { jj = 0; for (i = (ggr->range[0]).i1; i <= (ggr->range[0]).i2; i++) { for (j = (ggr->range[0]).j1; j <= (ggr->range[0]).j2; j++) { if (jj < 100) { grvalue[1][jj] = get_value (i, j); grvalue[0][jj] = jj + 1; buf = get_text (i, j); if (buf != NULL) if (strlen (buf) > 0) strncpy (grtext[jj], buf, 30); j++; } if (jj > jmax) jmax = jj; } } imax = 2; } else if (ggr->numrange > 1) { for (ii = 0; ii < ggr->numrange && ii < 10; ii++) { jj = 0; for (i = (ggr->range[ii]).i1; i <= (ggr->range[ii]).i2; i++) { for (j = (ggr->range[ii]).j1; j <= (ggr->range[ii]).j2; j++) { if (jj < 100 && ii < 11) { grvalue[ii][jj] = get_value (i, j); if (ii == 0) { buf = get_text (i, j); if (buf != NULL) if (strlen (buf) > 0) strncpy (grtext[jj], buf, 30); } jj++; } if (jj > jmax) jmax = jj; } } } imax = ii; } return 0; } int plot_XY () { double x_max, x_min, y_max, y_min, x_unit, y_unit; double x_range, y_range; double y_power, x_power; double xx, yy, x0, y0; char label[256]; int i, j, k, len; int grid_l_x, grid_l_y, grid_w, grid_h; int text_w; int legend_n; int x, y, x1 = 0, y1 = 0; int first_point; double pv; double xentv, yentv; int cells = 0; int cheight; char str[100]; x_max = x_min = grvalue[0][0]; for (j = 1; j < jmax; j++) { pv = grvalue[0][j]; cells++; x_max = Max (x_max, pv); x_min = Min (x_min, pv); } if (cells < 2) { return -1; } y_max = y_min = grvalue[1][0]; for (i = 1; i < imax; i++) { for (j = 0; j <= jmax; j++) { pv = grvalue[i][j]; y_max = Max (y_max, pv); y_min = Min (y_min, pv); } } x_power = -floor (log10 ((x_max - x_min))); y_power = -floor (log10 ((y_max - y_min))); x_power = pow10 (x_power); y_power = pow10 (y_power); x_min = floor (x_min * x_power) / x_power; x_max = ceil (x_max * x_power) / x_power; y_min = floor (y_min * y_power) / y_power; y_max = ceil (y_max * y_power) / y_power; x_unit = (x_max - x_min) / (jmax - 1); y_unit = (y_max - y_min) / 10; if (!ggr->Axes[xlCategory].MinimumScaleIsAuto) x_min = ggr->Axes[xlCategory].MinimumScale; else ggr->Axes[xlCategory].MinimumScale = x_min; if (!ggr->Axes[xlCategory].MaximumScaleIsAuto) x_max = ggr->Axes[xlCategory].MaximumScale; else ggr->Axes[xlCategory].MaximumScale = x_max; if (!ggr->Axes[xlCategory].MajorUnitIsAuto) x_unit = ggr->Axes[xlCategory].MajorUnit; else ggr->Axes[xlCategory].MajorUnit = x_unit; if (!ggr->Axes[xlValue].MinimumScaleIsAuto) y_min = ggr->Axes[xlValue].MinimumScale; else ggr->Axes[xlValue].MinimumScale = y_min; if (!ggr->Axes[xlValue].MaximumScaleIsAuto) y_max = ggr->Axes[xlValue].MaximumScale; else ggr->Axes[xlValue].MaximumScale = y_max; if (!ggr->Axes[xlValue].MajorUnitIsAuto) y_unit = ggr->Axes[xlValue].MajorUnit; else ggr->Axes[xlValue].MajorUnit = y_unit; x_range = x_max - x_min; y_range = y_max - y_min; pad = PLBORDER; bw = 1; drawrectangle (gdpy, gpixmap, 1, RECT_X, RECT_Y, RECT_W, RECT_H, X0, Y0); grid_l_x = 5; grid_l_y = 5; if (ggr->Axes[xlValue].HasMajorGridLines) { grid_l_x = RECT_W; } if (ggr->Axes[xlCategory].HasMajorGridLines) { grid_l_y = RECT_H; } grid_w = RECT_W; grid_h = RECT_H; xx = x_min; while (xx <= x_max && x_min != x_max) { x0 = (xx - x_min) / x_range * grid_w; x = (int) x0; if (xx > x_min && xx < x_max) { drawline (gdpy, gpixmap, 2, RECT_X + x, RECT_Y + 1, RECT_X + x, RECT_Y + grid_l_y, X0, Y0); drawline (gdpy, gpixmap, 2, RECT_X + x, RECT_Y + RECT_H - 1, RECT_X + x, RECT_Y + RECT_H - grid_l_y, X0, Y0); } sprintf (str, "%g", xx); len = strlen (str); cheight = gettexth (str, len, 1, 0, 2); text_w = gettextw (str, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, RECT_X + x - text_w / 2, RECT_H + RECT_Y * 8 / 6, str, len, X0, Y0); xx += x_unit; } yy = y_min; while (yy <= y_max && y_min != y_max) { y0 = (yy - y_min) / y_range * grid_h; y = (int) y0; if (yy > y_min && yy < y_max) { drawline (gdpy, gpixmap, 2, RECT_X, RECT_Y + RECT_H - y, RECT_X + grid_l_x, RECT_Y + RECT_H - y, X0, Y0); drawline (gdpy, gpixmap, 2, RECT_X + RECT_W, RECT_Y + RECT_H - y, RECT_X + RECT_W - grid_l_x, RECT_Y + RECT_H - y, X0, Y0); } sprintf (str, "%g", yy); len = strlen (str); cheight = gettexth (str, len, 1, 0, 2); text_w = gettextw (str, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, RECT_X - text_w * 8 / 6, RECT_Y + RECT_H - y + curfontheight / 3, str, len, X0, Y0); yy += y_unit; } if (ggr->HasTitle) { if (strlen (ggr->ChartTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->ChartTitle.Text)); else strcpy (label, ggr->ChartTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, (WIN_W - text_w) / 2, RECT_Y / 3, label, len, X0, Y0); } if (ggr->Axes[xlCategory].HasTitle) { if (strlen (ggr->Axes[xlCategory].AxisTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->Axes[xlCategory].AxisTitle.Text)); else strcpy (label, ggr->Axes[xlCategory].AxisTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, (WIN_W - text_w) / 2, RECT_H + RECT_Y * 9 / 6 + curfontheight, label, len, X0, Y0); } if (ggr->Axes[xlValue].HasTitle) { if (strlen (ggr->Axes[xlValue].AxisTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->Axes[xlValue].AxisTitle.Text)); else strcpy (label, ggr->Axes[xlValue].AxisTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); if ((RECT_X - text_w) < 0) x = curfontwidth; else x = RECT_X - text_w; drawimagestring (gdpy, gpixmap, 1, x, RECT_Y - 2 * curfontheight, label, len, X0, Y0); } legend_n = 0; curves_n = imax; for (i = 1; i < imax; i++) { if (strlen ((ggr->range[i]).name) > 1) strcpy (label, (char *) textparsing ((ggr->range[i]).name)); else strcpy (label, (ggr->range[i]).name); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); if (imax == 2) { x = RECT_X + (RECT_W - text_w) / 2 - 25; y = RECT_Y * 2 + RECT_H - curfontheight / 2; switch (i - 1) { case 0: DrawOpenSquare (x + 10, y, plotcol[i - 1]); break; case 1: DrawOpenTriangle (x + 10, y, plotcol[i - 1]); break; case 2: DrawOpenDiamon (x + 10, y, plotcol[i - 1]); break; case 3: DrawCross (x + 10, y, plotcol[i - 1]); break; case 4: DrawCloseSquare (x + 10, y, plotcol[i - 1]); break; case 5: DrawCloseDiamon (x + 10, y, plotcol[i - 1]); break; } drawline (gdpy, gpixmap, plotcol[i - 1], x, y, x + 20, y, X0, Y0); drawimagestring (gdpy, gpixmap, plotcol[i - 1], RECT_X + (RECT_W - text_w) / 2, RECT_Y * 2 + RECT_H, label, len, X0, Y0); break; } else { y = RECT_Y * 2 + RECT_H - curfontheight / 2; switch (i - 1) { case 0: DrawOpenSquare (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; case 1: DrawOpenTriangle (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; case 2: DrawOpenDiamon (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; case 3: DrawCross (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; case 4: DrawCloseSquare (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; case 5: DrawCloseDiamon (RECT_X / 2 + legend_n * (WIN_W / curves_n - 10), y, plotcol[i - 1]); break; } drawline (gdpy, gpixmap, plotcol[i - 1], RECT_X / 2 + legend_n * (WIN_W / curves_n - 10) - 10, y, RECT_X / 2 + legend_n * (WIN_W / curves_n - 10) + 10, y, X0, Y0); drawimagestring (gdpy, gpixmap, plotcol[i - 1], RECT_X / 2 + legend_n * (WIN_W / curves_n - 10) + 25, y, label, len, X0, Y0); legend_n++; } } for (i = 1; i < imax; i++) { first_point = 1; for (j = 0, k = 0; j < jmax && k < jmax; j++, k++) { xentv = grvalue[0][j]; if ((xentv < x_min) || (xentv > x_max)) continue; yentv = grvalue[i][j]; if ((yentv < y_min) || (yentv > y_max)) continue; if (first_point) { x1 = RECT_X + RECT_W * (xentv - x_min) / x_range; y1 = RECT_Y + RECT_H - RECT_H * (yentv - y_min) / y_range; if ((ggr->graphic_format[i] == grsymb) || (ggr->graphic_format[i] == grboth)) switch (i - 1) { case 0: DrawOpenSquare (x1, y1, plotcol[i - 1]); break; case 1: DrawOpenTriangle (x1, y1, plotcol[i - 1]); break; case 2: DrawOpenDiamon (x1, y1, plotcol[i - 1]); break; case 3: DrawCross (x1, y1, plotcol[i - 1]); break; case 4: DrawCloseSquare (x1, y1, plotcol[i - 1]); break; case 5: DrawCloseDiamon (x1, y1, plotcol[i - 1]); break; } first_point = 0; continue; } x = RECT_X + RECT_W * (xentv - x_min) / x_range; y = RECT_Y + RECT_H - RECT_H * (yentv - y_min) / y_range; if ((ggr->graphic_format[i] == grline) || (ggr->graphic_format[i] == grboth)) drawline (gdpy, gpixmap, plotcol[i - 1], x1, y1, x, y, X0, Y0); if ((ggr->graphic_format[i] == grsymb) || (ggr->graphic_format[i] == grboth)) switch (i - 1) { case 0: DrawOpenSquare (x, y, plotcol[i - 1]); break; case 1: DrawOpenTriangle (x, y, plotcol[i - 1]); break; case 2: DrawOpenDiamon (x, y, plotcol[i - 1]); break; case 3: DrawCross (x, y, plotcol[i - 1]); break; case 4: DrawCloseSquare (x, y, plotcol[i - 1]); break; case 5: DrawCloseDiamon (x, y, plotcol[i - 1]); break; } x1 = x; y1 = y; } } return 0; } int plot_pie () { int i, j, len; int text_w; int X, Y, X1, Y1, Temp_X, Temp_Y; double pv; int cells = 0; int slice; double Range_Total = 0; double Percentage = 0; double Angle_Size = 0; double Starting_Angle = 0; double Rad_Angle = 0; double Bisector_Angle = 0; double Label_R = 0; char label[256]; char str[100]; char per_str[10]; int PIE_D; int PIE_R; int col; int a1, a2; if (ggr->numrange > 1) col = 1; else col = 0; Range_Total = 0; for (j = 0; j <= jmax; j++) { pv = grvalue[col][j]; cells++; Range_Total = Range_Total + pv; } if (cells < 1) { return -1; } pad = PLBORDER; bw = 1; if (WIN_H > WIN_W) PIE_D = WIN_W - 20; else PIE_D = WIN_H - 50; if (WIN_H < 5) return -1; PIE_R = PIE_D / 2; if (ggr->HasTitle) { if (strlen (ggr->ChartTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->ChartTitle.Text)); else strcpy (label, ggr->ChartTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, (WIN_W - text_w) / 2, RECT_Y / 3, label, len, X0, Y0); } Starting_Angle = 0; slice = 1; for (j = 0; j < jmax; j++) { pv = grvalue[col][j]; Percentage = (pv / Range_Total); Angle_Size = Percentage * 360; i = slice; while (i > 9) i -= 10; setforeground (0, plotcol[i]); i = slice; while (i > 9) i -= 10; setforeground (0, plotcol[i]); a1 = Starting_Angle * 64; a2 = Angle_Size * 64; fillarc (gdpy, gpixmap, plotcol[slice - 1], (WIN_W / 2) - (PIE_R), (WIN_H / 2) - (PIE_R) + 10, PIE_D, PIE_D, a1, a2, X0, Y0); setforeground (0, 1); setfillstyle (gdpy, 1, FillSolid); 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) + 10; drawline (gdpy, gpixmap, 1, WIN_W / 2, (WIN_H / 2 + 10), X, Y, X0, Y0); setfillstyle (gdpy, 0, FillSolid); drawarc (gdpy, gpixmap, 1, (WIN_W / 2) - (PIE_R), (WIN_H / 2) - (PIE_R) + 10, PIE_D, PIE_D, 0, 360 * 64, X0, Y0); Label_R = PIE_R - (PIE_R / 4); 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) + 10; if (col > 0) sprintf (str, "%s", grtext[j]); else str[0] = '\0'; sprintf (per_str, "%.0f", (Percentage * 100)); strcat (str, " ("); strcat (str, per_str); strcat (str, "%)"); len = strlen (str); text_w = gettextw (str, len, 1, 0, 2); if ((Bisector_Angle > 90) && (Bisector_Angle <= 270)) X = X1 - text_w; else X = X1; Y = Y1 + curfontheight / 2; drawimagestring (gdpy, gpixmap, 1, X, Y, str, len, X0, Y0); Starting_Angle = (Starting_Angle) + (Angle_Size); slice++; } return 0; } void DrawOpenDiamon (x, y, col) short x, y, col; { XPoint points[5]; points[0].x = x; points[0].y = y - 3; points[1].x = 3; points[1].y = 3; points[2].x = -3; points[2].y = 3; points[3].x = -3; points[3].y = -3; points[4].x = 3; points[4].y = -3; drawlines (gdpy, gpixmap, col, points, 5, CoordModePrevious, X0, Y0); } void DrawCloseDiamon (x, y, col) short x, y, col; { XPoint points[12]; points[0].x = x; points[0].y = y; points[1].x = -2; points[1].y = 0; points[2].x = 4; points[2].y = 0; points[3].x = -2; points[3].y = 0; points[4].x = 0; points[4].y = -2; points[5].x = 0; points[5].y = 4; points[6].x = 0; points[6].y = -2; points[7].x = 1; points[7].y = 1; points[8].x = -2; points[8].y = -2; points[9].x = 1; points[9].y = 1; points[10].x = -1; points[10].y = 1; points[11].x = 2; points[11].y = -2; drawlines (gdpy, gpixmap, col, points, 12, CoordModePrevious, X0, Y0); } void DrawOpenSquare (x, y, col) short x, y, col; { XPoint points[5]; points[0].x = x - 2; points[0].y = y - 2; points[1].x = 4; points[1].y = 0; points[2].x = 0; points[2].y = 4; points[3].x = -4; points[3].y = 0; points[4].x = 0; points[4].y = -4; drawlines (gdpy, gpixmap, col, points, 5, CoordModePrevious, X0, Y0); } void DrawCloseSquare (x, y, col) short x, y, col; { XPoint points[9]; points[0].x = x - 2; points[0].y = y - 2; points[1].x = 4; points[1].y = 0; points[2].x = 0; points[2].y = 4; points[3].x = -4; points[3].y = 0; points[4].x = 0; points[4].y = -4; points[5].x = 4; points[5].y = 4; points[6].x = -2; points[6].y = -2; points[7].x = -2; points[7].y = 2; points[8].x = 4; points[8].y = -4; drawlines (gdpy, gpixmap, col, points, 9, CoordModePrevious, X0, Y0); } void DrawOpenTriangle (x, y, col) short x, y, col; { XPoint points[4]; points[0].x = x; points[0].y = y - 3; points[1].x = 2; points[1].y = 5; points[2].x = -4; points[2].y = 0; points[3].x = 2; points[3].y = -5; drawlines (gdpy, gpixmap, col, points, 4, CoordModePrevious, X0, Y0); } void DrawCross (x, y, col) short x, y, col; { XPoint points[6]; points[0].x = x; points[0].y = y; points[1].x = -2; points[1].y = 0; points[2].x = 4; points[2].y = 0; points[3].x = -2; points[3].y = 0; points[4].x = 0; points[4].y = -2; points[5].x = 0; points[5].y = 4; drawlines (gdpy, gpixmap, col, points, 6, CoordModePrevious, X0, Y0); } double pow10 (p) double p; { double q; if (p > 1e99 || p < -1e99) return 0; p = floor (p); if (p >= 0) { for (q = 1; p > 0; --p) q = q * 10; } else { p = -p; for (q = 1; p > 0; --p) q = q / 10; } return q; } char * rm_tail_zero (s) char *s; { char *t; return s; for (t = s; *t == ' ' || *t == '\t'; t++); strcpy (s, t); t = s; while ((*t) && (*t != '\n')) t++; t--; while ((t != s) && ((*t == ' ') || (*t == '0'))) t--; if (*t != '.') t++; *t = '\0'; return s; } #define PIX_SEP 6 int plot_bar () { double max_y = 0; double min_y = 0; double y_power; double Y_Range; double pv; char label[256]; int i, j, k; int len; int grid_l_x; int grid_l_y; int grid_h; char str[100]; int height, width; int text_w; int x, y; int first_bar = 1; int num_rows = 0; int num_cols = 0; int row; int bars; int labelsize; bars = 0; for (j = 0; j < jmax; j++) { pv = grvalue[0][j]; bars++; } if (bars < 1) { fprintf (stderr, "\007"); fprintf (stderr, "Not enough valid X labels"); return -1; } for (i = 1; i < imax; i++) { num_cols++; row = 0; for (j = 0; j < jmax; j++) { pv = grvalue[i][j]; row++; if (first_bar) { max_y = pv; min_y = pv; first_bar = 0; } else { max_y = Max (max_y, pv); min_y = Min (min_y, pv); } num_rows = Max (row, num_rows); } } min_y -= 0.1 * (fabs (min_y)); y_power = -floor (log10 ((max_y - min_y))); y_power = pow10 (y_power); min_y = floor (min_y * y_power) / y_power; max_y = ceil (max_y * y_power) / y_power; if (!ggr->Axes[xlValue].MinimumScaleIsAuto) min_y = ggr->Axes[xlValue].MinimumScale; else ggr->Axes[xlValue].MinimumScale = min_y; if (!ggr->Axes[xlValue].MaximumScaleIsAuto) max_y = ggr->Axes[xlValue].MaximumScale; else ggr->Axes[xlValue].MaximumScale = max_y; bw = 1; drawrectangle (gdpy, gpixmap, 1, RECT_X, RECT_Y, RECT_W, RECT_H, X0, Y0); grid_l_x = 0; grid_l_y = 0; if (ggr->Axes[xlValue].HasMajorGridLines) { grid_l_x = RECT_W; } if (ggr->Axes[xlCategory].HasMajorGridLines) { grid_l_y = RECT_H; } grid_h = RECT_H; Y_Range = max_y - min_y; width = (RECT_W - (PIX_SEP * num_rows)) / (num_cols * num_rows); for (i = 0; i < 11; i++) { if (i > 0 && i < 10) drawline (gdpy, gpixmap, 2, RECT_X - 4, RECT_Y + i * grid_h / 10, RECT_X, RECT_Y + i * grid_h / 10, X0, Y0); drawline (gdpy, gpixmap, 2, RECT_X, RECT_Y + i * grid_h / 10, RECT_X + grid_l_x, RECT_Y + i * grid_h / 10, X0, Y0); drawline (gdpy, gpixmap, 2, RECT_X + RECT_W, RECT_Y + i * grid_h / 10, RECT_X + RECT_W - grid_l_x, RECT_Y + i * grid_h / 10, X0, Y0); sprintf (str, "%.1f", (max_y - Y_Range * i / 10)); len = strlen (str); text_w = gettextw (str, len + 2, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, RECT_X - text_w, RECT_Y + i * grid_h / 10 + curfontheight / 3, str, len, X0, Y0); } for (i = 1; i < num_rows; i++) { x = RECT_X + PIX_SEP * i + i * width * (num_cols); drawline (gdpy, gpixmap, 1, x, RECT_Y, x, RECT_Y + grid_l_y, X0, Y0); drawline (gdpy, gpixmap, 1, x, RECT_Y + RECT_H, x, RECT_Y + RECT_H - grid_l_y, X0, Y0); } if (ggr->HasTitle) { if (strlen (ggr->ChartTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->ChartTitle.Text)); else strcpy (label, ggr->ChartTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, (WIN_W - text_w) / 2, RECT_Y / 3, label, len, X0, Y0); } if (ggr->Axes[xlCategory].HasTitle) { if (strlen (ggr->Axes[xlCategory].AxisTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->Axes[xlCategory].AxisTitle.Text)); else strcpy (label, ggr->Axes[xlCategory].AxisTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); drawimagestring (gdpy, gpixmap, 1, (WIN_W - text_w) / 2, RECT_H + RECT_Y * 9 / 6 + curfontheight, label, len, X0, Y0); } if (ggr->Axes[xlValue].HasTitle) { if (strlen (ggr->Axes[xlValue].AxisTitle.Text) > 1) strcpy (label, (char *) textparsing (ggr->Axes[xlValue].AxisTitle.Text)); else strcpy (label, ggr->Axes[xlValue].AxisTitle.Text); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); if ((RECT_X - text_w) < 0) x = curfontwidth; else x = RECT_X - text_w; drawimagestring (gdpy, gpixmap, 1, x, RECT_Y - 2 * curfontheight, label, len, X0, Y0); } labelsize = irint (floor ((width * num_cols) / (double) curfontwidth) - 1); y = RECT_Y * 2 + RECT_H - curfontheight / 2; bars = 0; x = RECT_X + (PIX_SEP) * (bars - 1) + width * (bars - 1) * num_cols; for (i = 1; i < imax; i++) { if (strlen ((ggr->range[i]).name) > 1) strcpy (label, (char *) textparsing ((ggr->range[i]).name)); else strcpy (label, (ggr->range[i]).name); len = strlen (label); text_w = gettextw (label, len, 1, 0, 2); x = x + (width * num_cols / 2) + text_w + 25; drawimagestring (gdpy, gpixmap, plotcol[i - 1], x + 25, y, label, len, X0, Y0); fillrectangle (gdpy, gpixmap, plotcol[i - 1], x, y - curfontheight, 20, curfontheight, X0, Y0, 1); } for (i = 1; i < imax; i++) { row = 0; for (j = 0, k = 0; j < jmax && k < jmax; j++, k++) { row++; x = RECT_X + (row - 1) * (PIX_SEP) + (row - 1) * (num_cols) * width + width * (i - 1); pv = grvalue[i][j]; height = (pv * RECT_H) / (max_y); y = RECT_Y + RECT_H - height; setforeground (0, plotcol[i - 1]); fillrectangle (gdpy, gpixmap, plotcol[i - 1], x, y, width, height, X0, Y0, 1); setforeground (0, 1); drawrectangle (gdpy, gpixmap, plotcol[i - 1], x, y, width, height, X0, Y0); } } return 0; }