=================================================================== RCS file: /home/cvs/OpenXM_contrib/gnuplot/Attic/graphics.c,v retrieving revision 1.1.1.2 retrieving revision 1.1.1.3 diff -u -p -r1.1.1.2 -r1.1.1.3 --- OpenXM_contrib/gnuplot/Attic/graphics.c 2000/01/22 14:15:57 1.1.1.2 +++ 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.2 2000/01/22 14:15:57 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.2 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; @@ -668,7 +674,7 @@ int count; /* 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; @@ -704,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) @@ -844,7 +854,7 @@ 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) @@ -905,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; */ @@ -1012,7 +1022,7 @@ int count; 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; } @@ -1175,8 +1185,8 @@ double amin, amax; */ double set_tic(l10, guide) -double l10; -int guide; + double l10; + int guide; { double xnorm, tics, posns; @@ -1214,7 +1224,7 @@ int guide; /*{{{ make_tics() */ static double make_tics(axis, guide) -int axis, guide; + int axis, guide; { register double xr, tic, l10; @@ -1285,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 */ @@ -1369,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)) { @@ -1388,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; @@ -1409,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)) { @@ -1426,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; @@ -1454,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; @@ -1470,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; @@ -1490,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)) { @@ -1507,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; @@ -1560,45 +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_Y_AXIS] = map_y(0.0); - axis_zero[FIRST_X_AXIS] = map_x(0.0); - if (axis_zero[FIRST_Y_AXIS] < ybot || is_log_y) + if (y_min >= 0.0 && y_max >= 0.0 || is_log_y) axis_zero[FIRST_Y_AXIS] = ybot; /* save for impulse plotting */ - else if (axis_zero[FIRST_Y_AXIS] >= ytop) + else if (y_min <= 0.0 && y_max <= 0.0) axis_zero[FIRST_Y_AXIS] = ytop; - else 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]); + 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_X_AXIS] >= xleft - && axis_zero[FIRST_X_AXIS] < xright) { - term_apply_lp_properties(&yzeroaxis); - (*t->move) (axis_zero[FIRST_X_AXIS], ybot); - (*t->vector) (axis_zero[FIRST_X_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_Y_AXIS] = map_y(0.0); - axis_zero[SECOND_X_AXIS] = map_x(0.0); - if (axis_zero[SECOND_Y_AXIS] < ybot || is_log_y2) + if (is_log_y2 || y_min >= 0.0 && y_max >= 0.0) axis_zero[SECOND_Y_AXIS] = ybot; /* save for impulse plotting */ - else if (axis_zero[SECOND_Y_AXIS] >= ytop) + else if (y_min <= 0.0 && y_max <= 0.0) axis_zero[SECOND_Y_AXIS] = ytop; - else 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]); + 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_X_AXIS] >= xleft && - axis_zero[SECOND_X_AXIS] < xright) { - term_apply_lp_properties(&y2zeroaxis); - (*t->move) (axis_zero[SECOND_X_AXIS], ybot); - (*t->vector) (axis_zero[SECOND_X_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) { @@ -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); } } @@ -1808,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); } @@ -1958,10 +1975,6 @@ int pcount; /* count of plots in linked list */ } -/* BODGES */ -#undef ytic -#undef xtic - /* plot_impulses: * Plot the curves in IMPULSES style */ @@ -2213,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 @@ -2221,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 */ @@ -2236,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; @@ -2248,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); @@ -2284,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); } @@ -2734,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); + } + } + } } } } @@ -3724,9 +3806,13 @@ char *font; /* NULL or "" means use default */ } +/* 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; @@ -3799,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; @@ -3886,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 */ @@ -3900,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 { @@ -3982,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; @@ -4147,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; @@ -4159,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 @@ -4176,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; @@ -4226,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 @@ -4237,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 */ @@ -4257,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 */ @@ -4365,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; @@ -4487,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; } } @@ -4512,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; } }