=================================================================== RCS file: /home/cvs/OpenXM_contrib/gnuplot/Attic/graphics.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.3 diff -u -p -r1.1.1.1 -r1.1.1.3 --- OpenXM_contrib/gnuplot/Attic/graphics.c 2000/01/09 17:00:51 1.1.1.1 +++ OpenXM_contrib/gnuplot/Attic/graphics.c 2003/09/15 07:09:24 1.1.1.3 @@ -1,5 +1,5 @@ #ifndef lint -static char *RCSid = "$Id: graphics.c,v 1.1.1.1 2000/01/09 17:00:51 maekawa Exp $"; +static char *RCSid = "$Id: graphics.c,v 1.1.1.3 2003/09/15 07:09:24 ohara Exp $"; #endif /* GNUPLOT - graphics.c */ @@ -37,6 +37,7 @@ static char *RCSid = "$Id: graphics.c,v 1.1.1.1 2000/0 #include "plot.h" #include "setshow.h" +#include "alloc.h" /* key placement is calculated in boundary, so we need file-wide variables * To simplify adjustments to the key, we set all these once [depends on @@ -137,12 +138,14 @@ static double make_tics __PROTO((int axis, int guide)) /* widest2d_callback keeps longest so far in here */ static int widest_tic; -static void widest2d_callback __PROTO((int axis, double place, char *text, - struct lp_style_type grid)); -static void ytick2d_callback __PROTO((int axis, double place, char *text, - struct lp_style_type grid)); -static void xtick2d_callback __PROTO((int axis, double place, char *text, - struct lp_style_type grid)); +/* HBB 20010118: these should be static, but can't --- HP-UX assembler bug */ +void widest2d_callback __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); +void ytick2d_callback __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); +void xtick2d_callback __PROTO((int axis, double place, char *text, + struct lp_style_type grid)); +int histeps_compare __PROTO((SORTFUNC_ARGS p1, SORTFUNC_ARGS p2)); static void map_position __PROTO((struct position * pos, unsigned int *x, unsigned int *y, char *what)); static void mant_exp __PROTO((double log_base, double x, int scientific, @@ -244,7 +247,6 @@ static double scale[AXIS_ARRAY_SIZE]; /* scale factors /* (DFK) Watch for cancellation error near zero on axes labels */ /* less than one hundredth of a tic mark */ -#define SIGNIF (0.01) #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x)) #define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF)) /*}}} */ @@ -425,8 +427,11 @@ char *axis_name; /* we determine widest tick label by getting gen_ticks to call this * routine with every label */ +/* HBB 20010118: all the *_callback() functions made non-static. This + * is necessary to work around a bug in HP's assembler shipped with + * HP-UX 10 and higher, if GCC tries to use it */ -static void widest2d_callback(axis, place, text, grid) +void widest2d_callback(axis, place, text, grid) int axis; double place; char *text; @@ -461,9 +466,9 @@ struct lp_style_type grid; */ static void boundary(scaling, plots, count) -TBOOLEAN scaling; /* TRUE if terminal is doing the scaling */ -struct curve_points *plots; -int count; + TBOOLEAN scaling; /* TRUE if terminal is doing the scaling */ + struct curve_points *plots; + int count; { int ytlen; int yticlin = 0, y2ticlin = 0, timelin = 0; @@ -583,7 +588,8 @@ int count; /* compute ytop from the various components * unless tmargin is explicitly specified */ - ytop = (int) ((ysize + yoffset) * (t->ymax)); + /* HBB 20020426: fix round-off bug --- in 3.8 since 20010118 ;-[ */ + ytop = (int) (0.5 + (ysize + yoffset) * (t->ymax)); if (tmargin < 0) { int top_margin = x2label_textheight + title_textheight; @@ -593,12 +599,14 @@ int count; top_margin = y2label_textheight; top_margin += x2tic_height + x2tic_textheight; -/* FIXME: what is this additional space reservation for??? */ + /* x2tic_height and x2tic_textheight are computed as only the + * relevant heights, but they nonetheless need a blank + * space above them */ if (top_margin > x2tic_height) top_margin += (int) (t->v_char); ytop -= top_margin; - if (ytop == (int) ((ysize + yoffset) * (t->ymax))) { + if (ytop == (int) (0.5 + (ysize + yoffset) * (t->ymax))) { /* make room for the end of rotated ytics or y2tics */ ytop -= (int) ((t->h_char) * 2); } @@ -646,7 +654,7 @@ int count; /* xlabel */ if (xlablin) { - /* offset is subtracted because if . 0, the margin is smaller */ + /* offset is subtracted because if > 0, the margin is smaller */ xlabel_textheight = (int) ((xlablin - xlabel.yoffset) * (t->v_char)); if (!xtics) xlabel_textheight += 0.5 * t->v_char; @@ -659,21 +667,24 @@ int count; * DBT 11-18-98 resize plot for vertical timelabels too ! */ /* offset is subtracted because if . 0, the margin is smaller */ - timebot_textheight = (int) ((timelin - timelabel.yoffset + 1.5) * (t->v_char)); - } - else + timebot_textheight = (int) ((timelin - timelabel.yoffset) * (t->v_char)); + } else timebot_textheight = 0; /* compute ybot from the various components * unless bmargin is explicitly specified */ - ybot = (int) ((t->ymax) * yoffset); + ybot = (int) (0.5 + (t->ymax) * yoffset); if (bmargin < 0) { ybot += xtic_height + xtic_textheight; - if (timebot_textheight > 0 || xlabel_textheight > 0) - ybot += (timebot_textheight > xlabel_textheight) ? timebot_textheight : xlabel_textheight; - if (ybot == (t->ymax) * yoffset) { + if (xlabel_textheight > 0) + ybot += xlabel_textheight; + if (timebot_textheight > 0) + ybot += timebot_textheight; + /* HBB 19990616: round to nearest integer, required to escape + * floating point inaccuracies */ + if (ybot == (int)(0.5 + (t->ymax) * yoffset)) { /* make room for the end of rotated ytics or y2tics */ ybot += (int) ((t->h_char) * 2); } @@ -699,6 +710,10 @@ int count; if (key_entry_height < (t->v_char)) key_entry_height = (t->v_char) * key_vert_factor; + /* HBB 20020122: safeguard to prevent division by zero later */ + if (key_entry_height == 0) + key_entry_height = 1; + /* count max_len key and number keys with len > 0 */ max_ptitl_len = find_maxl_keys(plots, count, &ptitl_cnt); if ((ytlen = label_width(key_title, &ktitl_lines)) > max_ptitl_len) @@ -839,13 +854,18 @@ int count; /* compute xleft from the various components * unless lmargin is explicitly specified */ - xleft = (int) ((t->xmax) * xoffset); + xleft = (int) (0.5 + (t->xmax) * xoffset); if (lmargin < 0) { xleft += (timelabel_textwidth > ylabel_textwidth ? timelabel_textwidth : ylabel_textwidth) + ytic_width + ytic_textwidth; - if (xleft == (t->xmax) * xoffset) { + /* make sure xleft is wide enough for a negatively + * x-offset horizontal timestamp + */ + if (!vertical_timelabel && xleft - ytic_width - ytic_textwidth < -(int) (timelabel.xoffset * (t->h_char))) + xleft = ytic_width + ytic_textwidth - (int) (timelabel.xoffset * (t->h_char)); + if (xleft == (int)(0.5 + (t->xmax) * xoffset)) { /* make room for end of xtic or x2tic label */ xleft += (int) ((t->h_char) * 2); } @@ -854,11 +874,6 @@ int count; } else xleft += (int) (lmargin * (t->h_char)); - /* make sure xleft is wide enough for a negatively - * x-offset horizontal timestamp - */ - if (!vertical_timelabel && xleft - ytic_width - ytic_textwidth < -(int) (timelabel.xoffset * (t->h_char))) - xleft = ytic_width + ytic_textwidth - (int) (timelabel.xoffset * (t->h_char)); /* end of xleft calculation }}} */ @@ -900,7 +915,7 @@ int count; /* compute xright from the various components * unless rmargin is explicitly specified */ - xright = (int) ((t->xmax) * (xsize + xoffset)); + xright = (int) (0.5 + (t->xmax) * (xsize + xoffset)); if (rmargin < 0) { /* xright -= y2label_textwidth + y2tic_width + y2tic_textwidth; */ @@ -913,7 +928,7 @@ int count; xright -= key_col_wth * key_cols; key_xl = xright + (int) (t->h_tic); } - if (xright == (t->xmax) * (xsize + xoffset)) { + if (xright == (int)(0.5 + (t->xmax) * (xsize + xoffset))) { /* make room for end of xtic or x2tic label */ xright -= (int) ((t->h_char) * 2); } @@ -929,7 +944,7 @@ int count; double current_aspect_ratio; if (aspect_ratio < 0 && (max_array[x_axis] - min_array[x_axis]) != 0.0) { - current_aspect_ratio = -aspect_ratio * (max_array[y_axis] - min_array[y_axis]) / (max_array[x_axis] - min_array[x_axis]); + current_aspect_ratio = -aspect_ratio * fabs((max_array[y_axis] - min_array[y_axis]) / (max_array[x_axis] - min_array[x_axis])); } else current_aspect_ratio = aspect_ratio; @@ -942,8 +957,6 @@ int count; /* too tall */ ytop = ybot + required * (xright - xleft); } else { - /* HBB: y2label_x wasn't defined yet, and would be - * overwritten later */ xright = xleft + (ytop - ybot) / required; } } @@ -973,18 +986,14 @@ int count; if (tmargin < 0 && x2tics & TICS_ON_BORDER && vertical_x2tics) { widest_tic = 0; /* reset the global variable ... */ gen_tics(SECOND_X_AXIS, &x2ticdef, 0, 0, 0.0, widest2d_callback); -/* HBB: redid this: remove rough guess value first. Among other reasons, - * I suspected the '-4 lines' of the original code to be in error, as the - * original calc. of x2tic_textheight uses *5* lines */ ytop += x2tic_textheight; -/* Now compute a new one and use that instead: */ + /* Now compute a new one and use that instead: */ x2tic_textheight = (int) ((t->h_char) * (widest_tic)); ytop -= x2tic_textheight; } if (bmargin < 0 && xtics & TICS_ON_BORDER && vertical_xtics) { widest_tic = 0; /* reset the global variable ... */ gen_tics(FIRST_X_AXIS, &xticdef, 0, 0, 0.0, widest2d_callback); -/* HBB: same changes as for tmargin/ytop above */ ybot -= xtic_textheight; xtic_textheight = (int) ((t->h_char) * widest_tic); ybot += xtic_textheight; @@ -1002,24 +1011,24 @@ int count; y2label_y = ytop + x2tic_height + x2tic_textheight + y2label_textheight; - xlabel_y = ybot - xtic_height - xtic_textheight - xlabel_textheight + t->v_char; + xlabel_y = ybot - xtic_height - xtic_textheight - xlabel_textheight + xlablin*(t->v_char); ylabel_x = xleft - ytic_width - ytic_textwidth; if (*ylabel.text && can_rotate) ylabel_x -= ylabel_textwidth; y2label_x = xright + y2tic_width + y2tic_textwidth; if (*y2label.text && can_rotate) - y2label_x += y2label_textwidth - t->v_char; + y2label_x += y2label_textwidth - y2lablin * t->v_char; if (vertical_timelabel) { if (timelabel_bottom) - time_y = xlabel_y - timebot_textheight + xlabel_textheight; + time_y = ybot - xtic_height - xtic_textheight - xlabel_textheight - timebot_textheight + t->v_char; else { time_y = title_y + timetop_textheight - title_textheight - x2label_textheight; } } else { if (timelabel_bottom) - time_y = xlabel_y - timebot_textheight + xlabel_textheight; + time_y = ybot - xtic_height - xtic_textheight - xlabel_textheight - timebot_textheight + t->v_char; else if (ylabel_textheight > 0) time_y = ylabel_y + timetop_textheight; else @@ -1176,8 +1185,8 @@ double amin, amax; */ double set_tic(l10, guide) -double l10; -int guide; + double l10; + int guide; { double xnorm, tics, posns; @@ -1215,7 +1224,7 @@ int guide; /*{{{ make_tics() */ static double make_tics(axis, guide) -int axis, guide; + int axis, guide; { register double xr, tic, l10; @@ -1286,14 +1295,9 @@ int axis, guide; void do_plot(plots, pcount) -struct curve_points *plots; -int pcount; /* count of plots in linked list */ + struct curve_points *plots; + int pcount; /* count of plots in linked list */ { - -/* BODGES BEFORE I FIX IT UP */ -#define ytic ticstep[y_axis] -#define xtic ticstep[x_axis] - register struct termentry *t = term; register int curve; int axis_zero[AXIS_ARRAY_SIZE]; /* axes in terminal coords for FIRST_X_AXIS, etc */ @@ -1304,7 +1308,7 @@ int pcount; /* count of plots in linked list */ struct text_label *this_label; struct arrow_def *this_arrow; TBOOLEAN scaling; - char ss[MAX_LINE_LEN + 1], *s, *e; + char *s, *e; /* so that macros for x_min etc pick up correct values * until this is done properly @@ -1370,7 +1374,6 @@ int pcount; /* count of plots in linked list */ /* label first y axis tics */ if (ytics) { - int axis = map_x(ZERO); /* set the globals ytick2d_callback() needs */ if (rotate_ytics && (*t->text_angle) (1)) { @@ -1389,8 +1392,8 @@ int pcount; /* count of plots in linked list */ else tic_mirror = -1; /* no thank you */ - if ((ytics & TICS_ON_AXIS) && !log_array[FIRST_X_AXIS] && inrange(axis, xleft, xright)) { - tic_start = axis; + if ((ytics & TICS_ON_AXIS) && !log_array[FIRST_X_AXIS] && inrange(0.0, x_min, x_max)) { + tic_start = map_x(0.0); tic_direction = -1; if (ytics & TICS_MIRROR) tic_mirror = tic_start; @@ -1410,7 +1413,6 @@ int pcount; /* count of plots in linked list */ } /* label first x axis tics */ if (xtics) { - int axis = map_y(ZERO); /* set the globals xtick2d_callback() needs */ if (rotate_xtics && (*t->text_angle) (1)) { @@ -1427,8 +1429,8 @@ int pcount; /* count of plots in linked list */ tic_mirror = ytop; else tic_mirror = -1; /* no thank you */ - if ((xtics & TICS_ON_AXIS) && !log_array[FIRST_Y_AXIS] && inrange(axis, ybot, ytop)) { - tic_start = axis; + if ((xtics & TICS_ON_AXIS) && !log_array[FIRST_Y_AXIS] && inrange(0.0, y_min, y_max)) { + tic_start = map_y(0.0); tic_direction = -1; if (xtics & TICS_MIRROR) tic_mirror = tic_start; @@ -1455,7 +1457,6 @@ int pcount; /* count of plots in linked list */ /* label second y axis tics */ if (y2tics) { /* set the globalss ytick2d_callback() needs */ - int axis = map_x(ZERO); if (rotate_y2tics && (*t->text_angle) (1)) { tic_hjust = CENTRE; @@ -1471,8 +1472,8 @@ int pcount; /* count of plots in linked list */ tic_mirror = xleft; else tic_mirror = -1; /* no thank you */ - if ((y2tics & TICS_ON_AXIS) && !log_array[FIRST_X_AXIS] && inrange(axis, xleft, xright)) { - tic_start = axis; + if ((y2tics & TICS_ON_AXIS) && !log_array[FIRST_X_AXIS] && inrange(0.0, x_min, x_max)) { + tic_start = map_x(0.0); tic_direction = 1; if (y2tics & TICS_MIRROR) tic_mirror = tic_start; @@ -1491,7 +1492,6 @@ int pcount; /* count of plots in linked list */ } /* label second x axis tics */ if (x2tics) { - int axis = map_y(ZERO); /* set the globals xtick2d_callback() needs */ if (rotate_x2tics && (*t->text_angle) (1)) { @@ -1508,8 +1508,8 @@ int pcount; /* count of plots in linked list */ tic_mirror = ybot; else tic_mirror = -1; /* no thank you */ - if ((x2tics & TICS_ON_AXIS) && !log_array[SECOND_Y_AXIS] && inrange(axis, ybot, ytop)) { - tic_start = axis; + if ((x2tics & TICS_ON_AXIS) && !log_array[SECOND_Y_AXIS] && inrange(0.0, y_min, y_max)) { + tic_start = map_y(0.0); tic_direction = 1; if (x2tics & TICS_MIRROR) tic_mirror = tic_start; @@ -1561,44 +1561,58 @@ int pcount; /* count of plots in linked list */ x_axis = FIRST_X_AXIS; y_axis = FIRST_Y_AXIS; /* chose scaling */ - axis_zero[FIRST_X_AXIS] = map_y(0.0); - axis_zero[FIRST_Y_AXIS] = map_x(0.0); - if (axis_zero[FIRST_X_AXIS] < ybot || is_log_y) - axis_zero[FIRST_X_AXIS] = ybot; /* save for impulse plotting */ - else if (axis_zero[FIRST_X_AXIS] >= ytop) - axis_zero[FIRST_X_AXIS] = ytop; - else if (xzeroaxis.l_type > -3) { - term_apply_lp_properties(&xzeroaxis); - (*t->move) (xleft, axis_zero[FIRST_X_AXIS]); - (*t->vector) (xright, axis_zero[FIRST_X_AXIS]); + if (y_min >= 0.0 && y_max >= 0.0 || is_log_y) + axis_zero[FIRST_Y_AXIS] = ybot; /* save for impulse plotting */ + else if (y_min <= 0.0 && y_max <= 0.0) + axis_zero[FIRST_Y_AXIS] = ytop; + else { + axis_zero[FIRST_Y_AXIS] = map_y(0.0); + if (xzeroaxis.l_type > -3) { + term_apply_lp_properties(&xzeroaxis); + (*t->move) (xleft, axis_zero[FIRST_Y_AXIS]); + (*t->vector) (xright, axis_zero[FIRST_Y_AXIS]); + } } - if ((yzeroaxis.l_type > -3) && !is_log_x - && axis_zero[FIRST_Y_AXIS] >= xleft - && axis_zero[FIRST_Y_AXIS] < xright) { - term_apply_lp_properties(&yzeroaxis); - (*t->move) (axis_zero[FIRST_Y_AXIS], ybot); - (*t->vector) (axis_zero[FIRST_Y_AXIS], ytop); + if (x_min >= 0.0 && x_max >= 0.0) + axis_zero[FIRST_X_AXIS] = xleft; + else if (x_min <= 0.0 && x_max <= 0.0) + axis_zero[FIRST_X_AXIS] = xright; + else { + axis_zero[FIRST_X_AXIS] = map_x(0.0); + if ((yzeroaxis.l_type > -3) && !is_log_x) { + term_apply_lp_properties(&yzeroaxis); + (*t->move) (axis_zero[FIRST_X_AXIS], ybot); + (*t->vector) (axis_zero[FIRST_X_AXIS], ytop); + } } + x_axis = SECOND_X_AXIS; y_axis = SECOND_Y_AXIS; /* chose scaling */ - axis_zero[SECOND_X_AXIS] = map_y(0.0); - axis_zero[SECOND_Y_AXIS] = map_x(0.0); - if (axis_zero[SECOND_X_AXIS] < ybot || is_log_y2) - axis_zero[SECOND_X_AXIS] = ybot; /* save for impulse plotting */ - else if (axis_zero[SECOND_X_AXIS] >= ytop) - axis_zero[SECOND_X_AXIS] = ytop; - else if (x2zeroaxis.l_type > -3) { - term_apply_lp_properties(&x2zeroaxis); - (*t->move) (xleft, axis_zero[SECOND_X_AXIS]); - (*t->vector) (xright, axis_zero[SECOND_X_AXIS]); + if (is_log_y2 || y_min >= 0.0 && y_max >= 0.0) + axis_zero[SECOND_Y_AXIS] = ybot; /* save for impulse plotting */ + else if (y_min <= 0.0 && y_max <= 0.0) + axis_zero[SECOND_Y_AXIS] = ytop; + else { + axis_zero[SECOND_Y_AXIS] = map_y(0.0); + if (x2zeroaxis.l_type > -3) { + term_apply_lp_properties(&x2zeroaxis); + (*t->move) (xleft, axis_zero[SECOND_Y_AXIS]); + (*t->vector) (xright, axis_zero[SECOND_Y_AXIS]); + } } - if ((y2zeroaxis.l_type > -3) && !is_log_x2 && axis_zero[SECOND_Y_AXIS] >= xleft && - axis_zero[SECOND_Y_AXIS] < xright) { - term_apply_lp_properties(&y2zeroaxis); - (*t->move) (axis_zero[SECOND_Y_AXIS], ybot); - (*t->vector) (axis_zero[SECOND_Y_AXIS], ytop); + if (y_min >= 0.0 && y_max >= 0.0) + axis_zero[SECOND_X_AXIS] = xleft; + else if (x_min <= 0.0 && x_max <= 0.0) + axis_zero[SECOND_X_AXIS] = xright; + else { + axis_zero[SECOND_X_AXIS] = map_x(0.0); + if ((y2zeroaxis.l_type > -3) && !is_log_x2) { + term_apply_lp_properties(&y2zeroaxis); + (*t->move) (axis_zero[SECOND_X_AXIS], ybot); + (*t->vector) (axis_zero[SECOND_X_AXIS], ytop); + } } /* DRAW PLOT BORDER */ if (draw_border) { @@ -1629,68 +1643,66 @@ int pcount; /* count of plots in linked list */ } /* YLABEL */ if (*ylabel.text) { - strcpy(ss, ylabel.text); /* we worked out x-posn in boundary() */ if ((*t->text_angle) (1)) { unsigned int x = ylabel_x + (t->v_char / 2); unsigned int y = (ytop + ybot) / 2 + ylabel.yoffset * (t->h_char); - write_multiline(x, y, ss, CENTRE, JUST_TOP, 1, ylabel.font); + write_multiline(x, y, ylabel.text, CENTRE, JUST_TOP, 1, ylabel.font); (*t->text_angle) (0); } else { /* really bottom just, but we know number of lines so we need to adjust x-posn by one line */ unsigned int x = ylabel_x; unsigned int y = ylabel_y; - write_multiline(x, y, ss, LEFT, JUST_TOP, 0, ylabel.font); + write_multiline(x, y, ylabel.text, LEFT, JUST_TOP, 0, ylabel.font); } } /* Y2LABEL */ if (*y2label.text) { - strcpy(ss, y2label.text); /* we worked out coordinates in boundary() */ if ((*t->text_angle) (1)) { unsigned int x = y2label_x + (t->v_char / 2) - 1; unsigned int y = (ytop + ybot) / 2 + y2label.yoffset * (t->h_char); - write_multiline(x, y, ss, CENTRE, JUST_TOP, 1, y2label.font); + write_multiline(x, y, y2label.text, CENTRE, JUST_TOP, 1, y2label.font); (*t->text_angle) (0); } else { /* really bottom just, but we know number of lines */ unsigned int x = y2label_x; unsigned int y = y2label_y; - write_multiline(x, y, ss, RIGHT, JUST_TOP, 0, y2label.font); + write_multiline(x, y, y2label.text, RIGHT, JUST_TOP, 0, y2label.font); } } /* XLABEL */ if (*xlabel.text) { unsigned int x = (xright + xleft) / 2 + xlabel.xoffset * (t->h_char); unsigned int y = xlabel_y - t->v_char / 2; /* HBB */ - strcpy(ss, xlabel.text); - write_multiline(x, y, ss, CENTRE, JUST_TOP, 0, xlabel.font); + write_multiline(x, y, xlabel.text, CENTRE, JUST_TOP, 0, xlabel.font); } /* PLACE TITLE */ if (*title.text) { /* we worked out y-coordinate in boundary() */ unsigned int x = (xleft + xright) / 2 + title.xoffset * t->h_char; unsigned int y = title_y - t->v_char / 2; - strcpy(ss, title.text); - write_multiline(x, y, ss, CENTRE, JUST_TOP, 0, title.font); + write_multiline(x, y, title.text, CENTRE, JUST_TOP, 0, title.font); } /* X2LABEL */ if (*x2label.text) { /* we worked out y-coordinate in boundary() */ unsigned int x = (xright + xleft) / 2 + x2label.xoffset * (t->h_char); unsigned int y = x2label_y - t->v_char / 2 - 1; - strcpy(ss, x2label.text); - write_multiline(x, y, ss, CENTRE, JUST_TOP, 0, x2label.font); + write_multiline(x, y, x2label.text, CENTRE, JUST_TOP, 0, x2label.font); } /* PLACE TIMEDATE */ if (*timelabel.text) { /* we worked out coordinates in boundary() */ - char str[MAX_LINE_LEN + 1]; + char *str; time_t now; unsigned int x = time_x; unsigned int y = time_y; time(&now); + /* there is probably now way to find out in advance how many + * chars strftime() writes */ + str = gp_alloc(MAX_LINE_LEN + 1, "timelabel.text"); strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now)); if (timelabel_rotate && (*t->text_angle) (1)) { @@ -1713,12 +1725,11 @@ int pcount; /* count of plots in linked list */ this_label = this_label->next) { unsigned int x, y; map_position(&this_label->place, &x, &y, "label"); - strcpy(ss, this_label->text); if (this_label->rotate && (*t->text_angle) (1)) { - write_multiline(x, y, ss, this_label->pos, JUST_TOP, 1, this_label->font); + write_multiline(x, y, this_label->text, this_label->pos, JUST_TOP, 1, this_label->font); (*t->text_angle) (0); } else { - write_multiline(x, y, ss, this_label->pos, JUST_TOP, 0, this_label->font); + write_multiline(x, y, this_label->text, this_label->pos, JUST_TOP, 0, this_label->font); } } @@ -1742,7 +1753,10 @@ int pcount; /* count of plots in linked list */ yl = key_yt; if (*key_title) { - sprintf(ss, "%s\n", key_title); + char *ss = gp_alloc(strlen(key_title) + 2, "tmp string ss"); + strcpy(ss, key_title); + strcat(ss, "\n"); + s = ss; yl -= t->v_char / 2; while ((e = (char *) strchr(s, '\n')) != NULL) { @@ -1755,7 +1769,9 @@ int pcount; /* count of plots in linked list */ (*t->put_text) (xl + key_text_right, yl, s); } else { int x = xl + key_text_right - (t->h_char) * strlen(s); - if (key_hpos == TOUT || inrange(x, xleft, xright)) + if (key_hpos == TOUT || + key_vpos == TUNDER || /* HBB 990327 */ + inrange(x, xleft, xright)) (*t->put_text) (x, yl, s); } } @@ -1763,6 +1779,7 @@ int pcount; /* count of plots in linked list */ yl -= t->v_char; } yl += t->v_char / 2; + free(ss); } yl_ref = yl -= key_entry_height / 2; /* centralise the keys */ key_count = 0; @@ -1807,6 +1824,7 @@ int pcount; /* count of plots in linked list */ } else { int x = xl + key_text_right - (t->h_char) * strlen(this_plot->title); if (key_hpos == TOUT || + key_vpos == TUNDER || /* HBB 990327 */ i_inrange(x, xleft, xright)) (*t->put_text) (x, yl, this_plot->title); } @@ -1841,7 +1859,7 @@ int pcount; /* count of plots in linked list */ switch (this_plot->plot_style) { /*{{{ IMPULSE */ case IMPULSES: - plot_impulses(this_plot, axis_zero[y_axis], axis_zero[x_axis]); + plot_impulses(this_plot, axis_zero[x_axis], axis_zero[y_axis]); break; /*}}} */ /*{{{ LINES */ @@ -1905,7 +1923,7 @@ int pcount; /* count of plots in linked list */ /*}}} */ /*{{{ BOXXYERROR */ case BOXXYERROR: - plot_boxes(this_plot, axis_zero[x_axis]); + plot_boxes(this_plot, axis_zero[y_axis]); break; /*}}} */ /*{{{ BOXERROR (falls through to) */ @@ -1916,7 +1934,7 @@ int pcount; /* count of plots in linked list */ /*}}} */ /*{{{ BOXES */ case BOXES: - plot_boxes(this_plot, axis_zero[x_axis]); + plot_boxes(this_plot, axis_zero[y_axis]); break; /*}}} */ /*{{{ VECTOR */ @@ -1957,10 +1975,6 @@ int pcount; /* count of plots in linked list */ } -/* BODGES */ -#undef ytic -#undef xtic - /* plot_impulses: * Plot the curves in IMPULSES style */ @@ -2212,6 +2226,27 @@ struct curve_points *plot; } } +/* HBB 20010625: replaced homegrown bubblesort in plot_histeps() by + * call of standard routine qsort(). Need to tell the compare function + * about the plotted dataset via this file scope variable: */ +static struct curve_points *histeps_current_plot; + +/* NOTE: I'd have made the comp.function 'static', but the HP-sUX gcc + * bug seems to forbid that :-( */ +int +histeps_compare(p1, p2) + SORTFUNC_ARGS p1; + SORTFUNC_ARGS p2; +{ + double x1=histeps_current_plot->points[*(int *)p1].x; + double x2=histeps_current_plot->points[*(int *)p2].x; + + if (x1 < x2) + return -1; + else + return (x2 > x1); +} + /* CAC */ /* plot_histeps: * Plot the curves in HISTEPS style @@ -2220,10 +2255,10 @@ static void plot_histeps(plot) struct curve_points *plot; { int i; /* point index */ - int hold, bigi; /* indices for sorting */ int xl, yl; /* cursor position in terminal coordinates */ struct termentry *t = term; double x, y, xn, yn; /* point position */ + double y_null; /* y coordinate of histogram baseline */ int *gl, goodcount; /* array to hold list of valid points */ /* preliminary count of points inside array */ @@ -2235,7 +2270,7 @@ struct curve_points *plot; if (goodcount < 2) return; /* cannot plot less than 2 points */ - gl = (int *) gp_alloc(goodcount * sizeof(int), "histeps valid point mapping"); + gl = gp_alloc(goodcount * sizeof(int), "histeps valid point mapping"); if (gl == NULL) return; @@ -2247,29 +2282,30 @@ struct curve_points *plot; gl[goodcount] = i; ++goodcount; } -/* sort the data */ - for (bigi = i = 1; i < goodcount;) { - if (plot->points[gl[i]].x < plot->points[gl[i - 1]].x) { - hold = gl[i]; - gl[i] = gl[i - 1]; - gl[i - 1] = hold; - if (i > 1) { - i--; - continue; - } - } - i = ++bigi; - } + /* sort the data --- tell histeps_compare about the plot + * datastructure to look at, then call qsort() */ + histeps_current_plot = plot; + qsort(gl, goodcount, sizeof(*gl), histeps_compare); + /* play it safe: invalidate the static pointer after usage */ + histeps_current_plot = NULL; + + /* HBB 20010625: log y axis must treat 0.0 as -infinity. Define + * the correct y position for the histogram's baseline once. It'll + * be used twice (once for each endpoint of the histogram). */ + if (log_array[y_axis]) + y_null = GPMIN(min_array[y_axis], max_array[y_axis]); + else + y_null = 0.0; + x = (3.0 * plot->points[gl[0]].x - plot->points[gl[1]].x) / 2.0; - y = 0.0; + y = y_null; xl = map_x(x); yl = map_y(y); (*t->move) (xl, yl); for (i = 0; i < goodcount - 1; i++) { /* loop over all points except last */ - yn = plot->points[gl[i]].y; xn = (plot->points[gl[i]].x + plot->points[gl[i + 1]].x) / 2.0; histeps_vertical(&xl, &yl, x, y, yn); @@ -2283,7 +2319,7 @@ struct curve_points *plot; xn = (3.0 * plot->points[gl[i]].x - plot->points[gl[i - 1]].x) / 2.0; histeps_vertical(&xl, &yl, x, y, yn); histeps_horizontal(&xl, &yl, x, xn, yn); - histeps_vertical(&xl, &yl, xn, yn, 0.0); + histeps_vertical(&xl, &yl, xn, yn, y_null); free(gl); } @@ -2733,19 +2769,66 @@ struct curve_points *plot; * Plot the curves in VECTORS style */ static void plot_vectors(plot) -struct curve_points *plot; + struct curve_points *plot; { int i; int x1, y1, x2, y2; struct termentry *t = term; + TBOOLEAN head; + struct coordinate points[2]; + double ex, ey; + double lx[2], ly[2]; for (i = 0; i < plot->p_count; i++) { - if (plot->points[i].type == INRANGE) { - x1 = map_x(plot->points[i].xlow); - y1 = map_y(plot->points[i].ylow); - x2 = map_x(plot->points[i].xhigh); - y2 = map_y(plot->points[i].yhigh); - (*t->arrow) (x1, y1, x2, y2, TRUE); + points[0] = plot->points[i]; + points[1].x = plot->points[i].xhigh; + points[1].y = plot->points[i].yhigh; + if (inrange(points[1].x, x_min, x_max) && + inrange(points[1].y, y_min, y_max)) { + /* to inrange */ + points[1].type = INRANGE; + x2 = map_x(points[1].x); + y2 = map_y(points[1].y); + head = TRUE; + if (points[0].type == INRANGE) { + x1 = map_x(points[0].x); + y1 = map_y(points[0].y); + (*t->arrow) (x1, y1, x2, y2, head); + } else if (points[0].type == OUTRANGE) { + /* from outrange to inrange */ + if (clip_lines1) { + edge_intersect(points, 1, &ex, &ey); + x1 = map_x(ex); + y1 = map_y(ey); + (*t->arrow) (x1, y1, x2, y2, head); + } + } + } else { + /* to outrange */ + points[1].type = OUTRANGE; + head = FALSE; + if (points[0].type == INRANGE) { + /* from inrange to outrange */ + if (clip_lines1) { + x1 = map_x(points[0].x); + y1 = map_y(points[0].y); + edge_intersect(points, 1, &ex, &ey); + x2 = map_x(ex); + y2 = map_y(ey); + (*t->arrow) (x1, y1, x2, y2, head); + } + } else if (points[0].type == OUTRANGE) { + /* from outrange to outrange */ + if (clip_lines2) { + if (two_edge_intersect(points, 1, lx, ly)) { + x1 = map_x(lx[0]); + y1 = map_y(ly[0]); + x2 = map_x(lx[1]); + y2 = map_y(ly[1]); + (*t->arrow) (x1, y1, x2, y2, head); + } + } + } } } } @@ -3667,15 +3750,19 @@ int vert; /* ... and vertical just - text in hor dir int angle; /* assume term has already been set for this */ char *font; /* NULL or "" means use default */ { - /* assumes we are free to mangle the text */ register struct termentry *t = term; - char *p; + char *p = text; + + if (!p) + return; + if (vert != JUST_TOP) { /* count lines and adjust y */ int lines = 0; /* number of linefeeds - one fewer than lines */ - for (p = text; *p; ++p) + while (*p++) { if (*p == '\n') ++lines; + } if (angle) x -= (vert * lines * t->v_char) / 2; else @@ -3687,7 +3774,7 @@ char *font; /* NULL or "" means use default */ for (;;) { /* we will explicitly break out */ - if ((p = strchr(text, '\n')) != NULL) + if ((text != NULL) && (p = strchr(text, '\n')) != NULL) *p = 0; /* terminate the string */ if ((*t->justify_text) (hor)) { @@ -3706,17 +3793,26 @@ char *font; /* NULL or "" means use default */ if (!p) break; + else { + /* put it back */ + *p = '\n'; + } text = p + 1; } /* unconditional branch back to the for(;;) - just a goto ! */ if (font && *font) (*t->set_font) (default_font); + } +/* HBB 20010118: all the *_callback() functions made non-static. This + * is necessary to work around a bug in HP's assembler shipped with + * HP-UX 10 and higher, if GCC tries to use it */ + /* display a x-axis ticmark - called by gen_ticks */ /* also uses global tic_start, tic_direction, tic_text and tic_just */ -static void xtick2d_callback(axis, place, text, grid) +void xtick2d_callback(axis, place, text, grid) int axis; double place; char *text; @@ -3789,7 +3885,7 @@ struct lp_style_type grid; /* linetype or -2 for no gr /* display a y-axis ticmark - called by gen_ticks */ /* also uses global tic_start, tic_direction, tic_text and tic_just */ -static void ytick2d_callback(axis, place, text, grid) +void ytick2d_callback(axis, place, text, grid) int axis; double place; char *text; @@ -3876,10 +3972,10 @@ int *lines; void setup_tics(axis, ticdef, format, max) -int axis; -struct ticdef *ticdef; -char *format; -int max; /* approx max number of slots available */ + int axis; + struct ticdef *ticdef; + char *format; + int max; /* approx max number of slots available */ { double tic = 0; /* HBB: shut up gcc -Wall */ @@ -3890,6 +3986,8 @@ int max; /* approx max number of slots available */ ticstep[axis] = tic = ticdef->def.series.incr; fixmin &= (ticdef->def.series.start == -VERYLARGE); fixmax &= (ticdef->def.series.end == VERYLARGE); + if (log_array[axis]) + tic = fabs(log(fabs(tic))) / log_base_array[axis]; } else if (ticdef->type == TIC_COMPUTED) { ticstep[axis] = tic = make_tics(axis, max); } else { @@ -3972,7 +4070,6 @@ char *dest, *format; size_t count; double log_base, x; /* we print one number in a number of different formats */ { -#define LOC_PI 3.14159265358979323846 /* local definition of PI */ char temp[MAX_LINE_LEN]; char *t; @@ -4137,7 +4234,7 @@ double log_base, x; /* we print one number in a numbe { t[0] = 'f'; t[1] = 0; - sprintf(dest, temp, x / LOC_PI); + sprintf(dest, temp, x / M_PI); dest += strlen(dest); ++format; break; @@ -4149,7 +4246,6 @@ double log_base, x; /* we print one number in a numbe /*}}} */ } } -#undef LOC_PI /* local definition of PI */ /*}}} */ #ifdef HAVE_SNPRINTF # undef sprintf @@ -4166,12 +4262,12 @@ double log_base, x; /* we print one number in a numbe */ void gen_tics(axis, def, grid, minitics, minifreq, callback) -int axis; /* FIRST_X_AXIS, etc */ -struct ticdef *def; /* tic defn */ -int grid; /* GRID_X | GRID_MX etc */ -int minitics; /* minitics - off/default/auto/explicit */ -double minifreq; /* frequency */ -tic_callback callback; /* fn to call to actually do the work */ + int axis; /* FIRST_X_AXIS, etc */ + struct ticdef *def; /* tic defn */ + int grid; /* GRID_X | GRID_MX etc */ + int minitics; /* minitics - off/default/auto/explicit */ + double minifreq; /* frequency */ + tic_callback callback; /* fn to call to actually do the work */ { /* seperate main-tic part of grid */ struct lp_style_type lgrd, mgrd; @@ -4216,6 +4312,7 @@ tic_callback callback; /* fn to call to actually do t return; /* NO MINITICS FOR USER-DEF TICS */ /*}}} */ } + /* series-tics * need to distinguish user co-ords from internal co-ords. * - for logscale, internal = log(user), else internal = user @@ -4227,7 +4324,6 @@ tic_callback callback; /* fn to call to actually do t * If step>1, we are looking at 1,1e6,1e12 for example, so * minitics are 10,100,1000,... - done in internal co-ords */ - { double tic; /* loop counter */ double internal; /* in internal co-ords */ @@ -4247,28 +4343,30 @@ tic_callback callback; /* fn to call to actually do t lmin = lmax; lmax = temp; } + /*{{{ choose start, step and end */ switch (def->type) { case TIC_SERIES: + start = def->def.series.start; + step = def->def.series.incr; + end = def->def.series.end; + if (log_array[axis]) { - /* we can tolerate start <= 0 if step and end > 0 */ - if (def->def.series.end <= 0 || - def->def.series.incr <= 0) - return; /* just quietly ignore */ - step = log(def->def.series.incr) / log_base_array[axis]; - end = log(def->def.series.end) / log_base_array[axis]; - start = def->def.series.start > 0 ? - log(def->def.series.start) / log_base_array[axis] : - step; - } else { - start = def->def.series.start; - step = def->def.series.incr; - end = def->def.series.end; - if (start == -VERYLARGE) - start = step * floor(lmin / step); - if (end == VERYLARGE) - end = step * ceil(lmax / step); + step = fabs(log(fabs(step))) / log_base_array[axis]; } + + /* NOTE: lmin/lmax already are already logarithms, if + * applicable */ + if (start == -VERYLARGE) + start = step * floor(lmin / step); + else if (log_array[axis]) + start = log(fabs(start)) / log_base_array[axis]; + + if (end == VERYLARGE) + end = step * ceil(lmax / step); + else if (log_array[axis]) + end = log(fabs(end)) / log_base_array[axis]; + break; case TIC_COMPUTED: /* round to multiple of step */ @@ -4355,6 +4453,7 @@ tic_callback callback; /* fn to call to actually do t minitics = 0; /* dont get stuck in infinite loop */ /*}}} */ } + /*{{{ a few tweaks and checks */ /* watch rounding errors */ end += SIGNIF * step; @@ -4413,7 +4512,9 @@ tic_callback callback; /* fn to call to actually do t gstrftime(label, 24, ticfmt[axis], (double) user); } else if (polar) { /* if rmin is set, we stored internally with r-rmin */ -#if 0 /* Igor's polar-grid patch */ +/* Igor's polar-grid patch */ +#if 1 + /* HBB 990327: reverted to 'pre-Igor' version... */ double r = fabs(user) + (autoscale_r & 1 ? 0 : rmin); #else /* Igor removed fabs to allow -ve labels */ @@ -4475,7 +4576,9 @@ char *what; case screen: { register struct termentry *t = term; - *x = pos->x * (t->xmax) + 0.5; + /* HBB 20000914: Off-by-one bug. Max. allowable result is + * t->xmax - 1, not t->xmax ! */ + *x = pos->x * (t->xmax - 1) + 0.5; break; } } @@ -4500,7 +4603,9 @@ char *what; case screen: { register struct termentry *t = term; - *y = pos->y * (t->ymax) + 0.5; + /* HBB 20000914: Off-by-one bug. Max. allowable result is + * t->ymax - 1, not t->ymax ! */ + *y = pos->y * (t->ymax -1) + 0.5; return; } }