1 /*[ 2 * Copyright 2000, 2004 Thomas Williams, Colin Kelley 3 * 4 * Permission to use, copy, and distribute this software and its 5 * documentation for any purpose with or without fee is hereby granted, 6 * provided that the above copyright notice appear in all copies and 7 * that both that copyright notice and this permission notice appear 8 * in supporting documentation. 9 * 10 * Permission to modify the software is granted, but not the right to 11 * distribute the complete modified source code. Modifications are to 12 * be distributed as patches to the released version. Permission to 13 * distribute binaries produced by compiling modified sources is granted, 14 * provided you 15 * 1. distribute the corresponding source modifications from the 16 * released version in the form of a patch file along with the binaries, 17 * 2. add special version identification to distinguish your version 18 * in addition to the base release version number, 19 * 3. provide your name and address as the primary contact for the 20 * support of your modified version, and 21 * 4. retain our contact information in regard to use of the base 22 * software. 23 * Permission to distribute the released version of the source code along 24 * with corresponding source modifications in the form of a patch file is 25 * granted with same provisions 2 through 4 for binary distributions. 26 * 27 * This software is provided "as is" without express or implied warranty 28 * to the extent permitted by applicable law. 29 ]*/ 30 31 #ifndef GNUPLOT_AXIS_H 32 #define GNUPLOT_AXIS_H 33 34 /* Aug 2017 - unconditional support for nonlinear axes */ 35 # define nonlinear(axis) ((axis)->linked_to_primary != NULL && (axis)->link_udf->at != NULL) 36 # define invalid_coordinate(x,y) ((unsigned)(x)==intNaN || (unsigned)(y)==intNaN) 37 38 #include <stddef.h> /* for offsetof() */ 39 #include "gp_types.h" /* for TBOOLEAN */ 40 41 #include "gadgets.h" 42 #include "parse.h" /* for const_*() */ 43 #include "tables.h" /* for the axis name parse table */ 44 #include "term_api.h" /* for lp_style_type */ 45 #include "util.h" /* for int_error() */ 46 47 /* typedefs / #defines */ 48 49 /* give some names to some array elements used in command.c and grap*.c 50 * maybe one day the relevant items in setshow will also be stored 51 * in arrays. 52 * 53 * Always keep the following conditions alive: 54 * SECOND_X_AXIS = FIRST_X_AXIS + SECOND_AXES 55 * FIRST_X_AXIS & SECOND_AXES == 0 56 */ 57 58 typedef enum AXIS_INDEX { 59 NO_AXIS = -2, 60 ALL_AXES = -1, 61 FIRST_Z_AXIS = 0, 62 #define FIRST_AXES FIRST_Z_AXIS 63 FIRST_Y_AXIS, 64 FIRST_X_AXIS, 65 COLOR_AXIS, /* fill gap */ 66 SECOND_Z_AXIS, /* not used, yet */ 67 #define SECOND_AXES SECOND_Z_AXIS 68 SAMPLE_AXIS=SECOND_Z_AXIS, 69 SECOND_Y_AXIS, 70 SECOND_X_AXIS, 71 POLAR_AXIS, 72 #define NUMBER_OF_MAIN_VISIBLE_AXES (POLAR_AXIS + 1) 73 T_AXIS, 74 U_AXIS, 75 V_AXIS, /* Last index into axis_array[] */ 76 PARALLEL_AXES, /* Parallel axis structures are allocated dynamically */ 77 THETA_index = 1234, /* Used to identify THETA_AXIS */ 78 79 AXIS_ARRAY_SIZE = PARALLEL_AXES 80 } AXIS_INDEX; 81 82 83 /* sample axis doesn't need mtics, so use the slot to hold sample interval */ 84 # define SAMPLE_INTERVAL mtic_freq 85 86 /* What kind of ticmarking is wanted? */ 87 typedef enum en_ticseries_type { 88 TIC_COMPUTED=1, /* default; gnuplot figures them */ 89 TIC_SERIES, /* user-defined series */ 90 TIC_USER, /* user-defined points */ 91 TIC_MONTH, /* print out month names ((mo-1)%12)+1 */ 92 TIC_DAY /* print out day of week */ 93 } t_ticseries_type; 94 95 /* Defines one ticmark for TIC_USER style. 96 * If label==NULL, the value is printed with the usual format string. 97 * else, it is used as the format string (note that it may be a constant 98 * string, like "high" or "low"). 99 */ 100 typedef struct ticmark { 101 double position; /* where on axis is this */ 102 char *label; /* optional (format) string label */ 103 int level; /* 0=major tic, 1=minor tic */ 104 struct ticmark *next; /* linked list */ 105 } ticmark; 106 107 /* Tic-mark labelling definition; see set xtics */ 108 typedef struct ticdef { 109 t_ticseries_type type; 110 char *font; 111 struct t_colorspec textcolor; 112 struct { 113 struct ticmark *user; /* for TIC_USER */ 114 struct { /* for TIC_SERIES */ 115 double start, incr; 116 double end; /* ymax, if VERYLARGE */ 117 } series; 118 TBOOLEAN mix; /* TRUE to use both the above */ 119 } def; 120 struct position offset; 121 TBOOLEAN rangelimited; /* Limit tics to data range */ 122 TBOOLEAN enhanced; /* Use enhanced text mode or labels */ 123 TBOOLEAN logscaling; /* place tics using old logscale algorithm */ 124 } t_ticdef; 125 126 /* we want two auto modes for minitics - default where minitics are 127 * auto for log/time and off for linear, and auto where auto for all 128 * graphs I've done them in this order so that logscale-mode can 129 * simply test bit 0 to see if it must do the minitics automatically. 130 * similarly, conventional plot can test bit 1 to see if minitics are 131 * required */ 132 typedef enum en_minitics_status { 133 MINI_OFF, 134 MINI_DEFAULT, 135 MINI_USER, 136 MINI_AUTO 137 } t_minitics_status; 138 139 /* Values to put in the axis_tics[] variables that decides where the 140 * ticmarks should be drawn: not at all, on one or both plot borders, 141 * or the zeroaxes. These look like a series of values, but TICS_MASK 142 * shows that they're actually bit masks --> don't turn into an enum 143 * */ 144 #define NO_TICS 0 145 #define TICS_ON_BORDER 1 146 #define TICS_ON_AXIS 2 147 #define TICS_MASK 3 148 #define TICS_MIRROR 4 149 150 /* Tic levels 0 and 1 are maintained in the axis structure. 151 * Tic levels 2 - MAX_TICLEVEL have only one property - scale. 152 */ 153 #define MAX_TICLEVEL 5 154 extern double ticscale[MAX_TICLEVEL]; 155 156 /* HBB 20010610: new type for storing autoscale activity. Effectively 157 * two booleans (bits) in a single variable, so I'm using an enum with 158 * all 4 possible bit masks given readable names. */ 159 typedef enum e_autoscale { 160 AUTOSCALE_NONE = 0, 161 AUTOSCALE_MIN = 1<<0, 162 AUTOSCALE_MAX = 1<<1, 163 AUTOSCALE_BOTH = (1<<0 | 1 << 1), 164 AUTOSCALE_FIXMIN = 1<<2, 165 AUTOSCALE_FIXMAX = 1<<3 166 } t_autoscale; 167 168 typedef enum e_constraint { 169 CONSTRAINT_NONE = 0, 170 CONSTRAINT_LOWER = 1<<0, 171 CONSTRAINT_UPPER = 1<<1, 172 CONSTRAINT_BOTH = (1<<0 | 1<<1) 173 } t_constraint; 174 175 /* The unit the tics of a given time/date axis are to interpreted in */ 176 /* HBB 20040318: start at one, to avoid undershoot */ 177 typedef enum e_timelevel { 178 TIMELEVEL_SECONDS = 1, TIMELEVEL_MINUTES, TIMELEVEL_HOURS, 179 TIMELEVEL_DAYS, TIMELEVEL_WEEKS, TIMELEVEL_MONTHS, 180 TIMELEVEL_YEARS 181 } t_timelevel; 182 183 typedef struct axis { 184 /* range of this axis */ 185 t_autoscale autoscale; /* Which end(s) are autoscaled? */ 186 t_autoscale set_autoscale; /* what does 'set' think autoscale to be? */ 187 int range_flags; /* flag bits about autoscale/writeback: */ 188 /* write auto-ed ranges back to variables for autoscale */ 189 #define RANGE_WRITEBACK 1 190 #define RANGE_SAMPLED 2 191 #define RANGE_IS_REVERSED 4 192 double min; /* 'transient' axis extremal values */ 193 double max; 194 double set_min; /* set/show 'permanent' values */ 195 double set_max; 196 double writeback_min; /* ULIG's writeback implementation */ 197 double writeback_max; 198 double data_min; /* Not necessarily the same as axis min */ 199 double data_max; 200 201 /* range constraints */ 202 t_constraint min_constraint; 203 t_constraint max_constraint; 204 double min_lb, min_ub; /* min lower- and upper-bound */ 205 double max_lb, max_ub; /* min lower- and upper-bound */ 206 207 /* output-related quantities */ 208 int term_lower; /* low and high end of the axis on output, */ 209 int term_upper; /* ... (in terminal coordinates)*/ 210 double term_scale; /* scale factor: plot --> term coords */ 211 unsigned int term_zero; /* position of zero axis */ 212 213 /* log axis control */ 214 TBOOLEAN log; /* log axis stuff: flag "islog?" */ 215 double base; /* logarithm base value */ 216 double log_base; /* ln(base), for easier computations */ 217 218 /* linked axis information (used only by x2, y2) 219 * If axes are linked, the primary axis info will be cloned into the 220 * secondary axis only up to this point in the structure. 221 */ 222 struct axis *linked_to_primary; /* Set only in a secondary axis */ 223 struct axis *linked_to_secondary; /* Set only in a primary axis */ 224 struct udft_entry *link_udf; 225 226 /* ticmark control variables */ 227 int ticmode; /* tics on border/axis? mirrored? */ 228 struct ticdef ticdef; /* tic series definition */ 229 int tic_rotate; /* ticmarks rotated by this angle */ 230 enum JUSTIFY tic_pos; /* left/center/right tic label justification */ 231 TBOOLEAN gridmajor; /* Grid lines wanted on major tics? */ 232 TBOOLEAN gridminor; /* Grid lines for minor tics? */ 233 t_minitics_status minitics; /* minor tic mode (none/auto/user)? */ 234 double mtic_freq; /* minitic stepsize */ 235 double ticscale; /* scale factor for tic marks (was (0..1])*/ 236 double miniticscale; /* and for minitics */ 237 double ticstep; /* increment used to generate tic placement */ 238 TBOOLEAN tic_in; /* tics to be drawn inward? */ 239 240 /* time/date axis control */ 241 td_type datatype; /* {DT_NORMAL|DT_TIMEDATE} controls _input_ */ 242 td_type tictype; /* {DT_NORMAL|DT_TIMEDATE|DT_DMS} controls _output_ */ 243 char *formatstring; /* the format string for output */ 244 char *ticfmt; /* autogenerated alternative to formatstring (needed??) */ 245 t_timelevel timelevel; /* minimum time unit used to quantize ticks */ 246 247 /* other miscellaneous fields */ 248 int index; /* if this is a permanent axis, this indexes axis_array[] */ 249 /* (index >= PARALLEL_AXES) indexes parallel axes */ 250 /* (index < 0) indicates a dynamically allocated structure */ 251 text_label label; /* label string and position offsets */ 252 TBOOLEAN manual_justify; /* override automatic justification */ 253 lp_style_type *zeroaxis; /* usually points to default_axis_zeroaxis */ 254 double paxis_x; /* x coordinate of parallel axis */ 255 } AXIS; 256 257 #define DEFAULT_AXIS_TICDEF {TIC_COMPUTED, NULL, {TC_DEFAULT, 0, 0.0}, {NULL, {0.,0.,0.}, FALSE}, { character, character, character, 0., 0., 0. }, FALSE, TRUE, FALSE } 258 #define DEFAULT_AXIS_ZEROAXIS {0, LT_AXIS, 0, DASHTYPE_AXIS, 0, 0, 1.0, PTSZ_DEFAULT, DEFAULT_P_CHAR, BLACK_COLORSPEC, DEFAULT_DASHPATTERN} 259 260 #define DEFAULT_AXIS_STRUCT { \ 261 AUTOSCALE_BOTH, AUTOSCALE_BOTH, /* auto, set_auto */ \ 262 0, /* range_flags for autoscaling */ \ 263 -10.0, 10.0, /* 3 pairs of min/max for axis itself */ \ 264 -10.0, 10.0, \ 265 -10.0, 10.0, \ 266 0.0, 0.0, /* and another min/max for the data */ \ 267 CONSTRAINT_NONE, CONSTRAINT_NONE, /* min and max constraints */ \ 268 0., 0., 0., 0., /* lower and upper bound for min and max */ \ 269 0, 0, /* terminal lower and upper coords */ \ 270 0., /* terminal scale */ \ 271 0, /* zero axis position */ \ 272 FALSE, 10.0, 0.0, /* log, base, log(base) */ \ 273 NULL, NULL, /* linked_to_primary, linked_to_secondary */\ 274 NULL, /* link function */ \ 275 NO_TICS, /* tic output positions (border, mirror) */ \ 276 DEFAULT_AXIS_TICDEF, /* tic series definition */ \ 277 0, CENTRE, /* tic_rotate, horizontal justification */ \ 278 FALSE, FALSE, /* grid{major,minor} */ \ 279 MINI_DEFAULT, 10., /* minitics, mtic_freq */ \ 280 1.0, 0.5, 0.0, TRUE, /* ticscale, miniticscale, ticstep, tic_in */ \ 281 DT_NORMAL, DT_NORMAL, /* datatype for input, output */ \ 282 NULL, NULL, /* output format, another output format */ \ 283 0, /* timelevel */ \ 284 0, /* index (e.g.FIRST_Y_AXIS) */ \ 285 EMPTY_LABELSTRUCT, /* axis label */ \ 286 FALSE, /* override automatic justification */ \ 287 NULL /* NULL means &default_axis_zeroaxis */ \ 288 } 289 290 /* This much of the axis structure is cloned by the "set x2range link" command */ 291 #define AXIS_CLONE_SIZE offsetof(AXIS, linked_to_primary) 292 293 /* Table of default behaviours --- a subset of the struct above. Only 294 * those fields are present that differ from axis to axis. */ 295 typedef struct axis_defaults { 296 double min; /* default axis endpoints */ 297 double max; 298 char name[4]; /* axis name, like in "x2" or "t" */ 299 int ticmode; /* tics on border/axis? mirrored? */ 300 } AXIS_DEFAULTS; 301 302 /* global variables in axis.c */ 303 304 extern AXIS axis_array[AXIS_ARRAY_SIZE]; 305 extern AXIS *shadow_axis_array; 306 extern const AXIS_DEFAULTS axis_defaults[AXIS_ARRAY_SIZE]; 307 extern const AXIS default_axis_state; 308 309 /* Dynamic allocation of parallel axis structures */ 310 extern AXIS *parallel_axis_array; 311 extern int num_parallel_axes; 312 313 /* A parsing table for mapping axis names into axis indices. For use 314 * by the set/show machinery, mainly */ 315 extern const struct gen_table axisname_tbl[]; 316 317 318 extern const struct ticdef default_axis_ticdef; 319 320 /* default format for tic mark labels */ 321 #define DEF_FORMAT "% h" 322 #define DEF_FORMAT_LATEX "$%h$" 323 324 /* default parse timedata string */ 325 #define TIMEFMT "%d/%m/%y,%H:%M" 326 extern char *timefmt; 327 328 /* axis labels */ 329 extern const text_label default_axis_label; 330 331 /* zeroaxis linetype (flag type==-3 if none wanted) */ 332 extern const lp_style_type default_axis_zeroaxis; 333 334 /* default grid linetype, to be used by 'unset grid' and 'reset' */ 335 extern const struct lp_style_type default_grid_lp; 336 337 /* grid layer: LAYER_BEHIND LAYER_BACK LAYER_FRONT */ 338 extern int grid_layer; 339 340 /* Whether to draw the axis tic labels and tic marks in front of everything else */ 341 extern TBOOLEAN grid_tics_in_front; 342 343 /* Whether to draw vertical grid lines in 3D */ 344 extern TBOOLEAN grid_vertical_lines; 345 346 /* Whether to draw a grid in spiderplots */ 347 extern TBOOLEAN grid_spiderweb; 348 349 /* Whether or not to draw a separate polar axis in polar mode */ 350 extern TBOOLEAN raxis; 351 352 /* global variables for communication with the tic callback functions */ 353 /* FIXME HBB 20010806: had better be collected into a struct that's 354 * passed to the callback */ 355 extern int tic_start, tic_direction, tic_mirror; 356 /* These are for passing on to write_multiline(): */ 357 extern int tic_text, rotate_tics, tic_hjust, tic_vjust; 358 /* The remaining ones are for grid drawing; controlled by 'set grid': */ 359 /* extern int grid_selection; --- comm'ed out, HBB 20010806 */ 360 extern struct lp_style_type grid_lp; /* linestyle for major grid lines */ 361 extern struct lp_style_type mgrid_lp; /* linestyle for minor grid lines */ 362 363 extern double polar_grid_angle; /* angle step in polar grid in radians */ 364 extern double theta_origin; /* 0 = right side of plot */ 365 extern double theta_direction; /* 1 = counterclockwise -1 = clockwise */ 366 367 /* Length of the longest tics label, set by widest_tic_callback(): */ 368 extern int widest_tic_strlen; 369 370 /* flag to indicate that in-line axis ranges should be ignored */ 371 extern TBOOLEAN inside_zoom; 372 373 /* axes being used by the current plot */ 374 extern AXIS_INDEX x_axis, y_axis, z_axis; 375 376 extern struct axis THETA_AXIS; 377 378 /* macros to reduce code clutter caused by the array notation, mainly 379 * in graphics.c and fit.c */ 380 #define X_AXIS axis_array[x_axis] 381 #define Y_AXIS axis_array[y_axis] 382 #define Z_AXIS axis_array[z_axis] 383 #define R_AXIS axis_array[POLAR_AXIS] 384 #define CB_AXIS axis_array[COLOR_AXIS] 385 386 /* -------- macros using these variables: */ 387 388 /* Macros to map from user to terminal coordinates and back */ 389 #define AXIS_MAP(axis, variable) axis_map( &axis_array[axis], variable) 390 #define AXIS_MAP_DOUBLE(axis, variable) axis_map_double( &axis_array[axis], variable) 391 #define AXIS_MAPBACK(axis, pos) axis_mapback( &axis_array[axis], pos) 392 393 /* Same thing except that "axis" is a pointer, not an index */ 394 #define axis_map_double(axis, variable) \ 395 ((axis)->term_lower + ((variable) - (axis)->min) * (axis)->term_scale) 396 #define axis_map_toint(x) (int)( (x) + 0.5 ) 397 #define axis_map(axis, variable) axis_map_toint( axis_map_double(axis, variable) ) 398 399 #define axis_mapback(axis, pos) \ 400 (((double)(pos) - (axis)->term_lower)/(axis)->term_scale + (axis)->min) 401 402 /* parse a position of the form 403 * [coords] x, [coords] y {,[coords] z} 404 * where coords is one of first,second.graph,screen,character 405 * if first or second, we need to take axis.datatype into account 406 * FIXME: Cannot handle parallel axes 407 */ 408 #define GET_NUMBER_OR_TIME(store,axes,axis) \ 409 do { \ 410 AXIS *this_axis = (axes == NO_AXIS) ? NULL \ 411 : &(axis_array[(axes)+(axis)]); \ 412 (store) = get_num_or_time(this_axis); \ 413 } while(0) 414 415 416 /* 417 * Gradually replacing extremely complex macro ACTUAL_STORE_AND_UPDATE_RANGE 418 * (called 50+ times) with a subroutine. The original logic was that in-line 419 * code was faster than calls to a subroutine, but on current hardware it is 420 * better to have one cached copy than to have 50 separate uncached copies. 421 * 422 * The difference between STORE_AND_UPDATE_RANGE and store_and_update_range 423 * is that the former takes an axis index and the latter an axis pointer. 424 */ 425 #define STORE_AND_UPDATE_RANGE(STORE, VALUE, TYPE, AXIS, NOAUTOSCALE, UNDEF_ACTION) \ 426 if (AXIS != NO_AXIS) do { \ 427 if (store_and_update_range( &(STORE), VALUE, &(TYPE), (&axis_array[AXIS]), NOAUTOSCALE) \ 428 == UNDEFINED) { \ 429 UNDEF_ACTION; \ 430 } \ 431 } while(0) 432 433 /* Use NOOP for UNDEF_ACTION if no action is wanted */ 434 #define NOOP ((void)0) 435 436 437 438 /* HBB 20000506: new macro to automatically build initializer lists 439 * for arrays of AXIS_ARRAY_SIZE=11 equal elements */ 440 #define AXIS_ARRAY_INITIALIZER(value) { \ 441 value, value, value, value, value, \ 442 value, value, value, value, value, value } 443 444 /* 'roundoff' check tolerance: less than one hundredth of a tic mark */ 445 #define SIGNIF (0.01) 446 /* (DFK) Watch for cancellation error near zero on axes labels */ 447 /* FIXME HBB 20000521: these seem not to be used much, anywhere... */ 448 #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x)) 449 450 /* Function pointer type for callback functions to generate ticmarks */ 451 typedef void (*tic_callback) (struct axis *, double, char *, int, 452 struct lp_style_type, struct ticmark *); 453 454 /* ------------ functions exported by axis.c */ 455 coord_type store_and_update_range(double *store, double curval, coord_type *type, 456 struct axis *axis, TBOOLEAN noautoscale); 457 void autoscale_one_point( struct axis *axis, double x ); 458 t_autoscale load_range(struct axis *, double *, double *, t_autoscale); 459 void check_log_limits(struct axis *, double, double); 460 void axis_invert_if_requested(struct axis *); 461 void axis_check_range(AXIS_INDEX); 462 void axis_init(AXIS *this_axis, TBOOLEAN infinite); 463 void set_explicit_range(struct axis *axis, double newmin, double newmax); 464 double axis_log_value_checked(AXIS_INDEX, double, const char *); 465 void axis_checked_extend_empty_range(AXIS_INDEX, const char *mesg); 466 void axis_check_empty_nonlinear(struct axis *this_axis); 467 char * copy_or_invent_formatstring(struct axis *); 468 double quantize_normal_tics(double, int); 469 void setup_tics(struct axis *, int); 470 void gen_tics(struct axis *, tic_callback); 471 void axis_output_tics(AXIS_INDEX, int *, AXIS_INDEX, tic_callback); 472 void axis_set_scale_and_range(struct axis *axis, int lower, int upper); 473 void axis_draw_2d_zeroaxis(AXIS_INDEX, AXIS_INDEX); 474 TBOOLEAN some_grid_selected(void); 475 void add_tic_user(struct axis *, char *, double, int); 476 double get_num_or_time(struct axis *); 477 TBOOLEAN bad_axis_range(struct axis *axis); 478 479 void save_writeback_all_axes(void); 480 int parse_range(AXIS_INDEX axis); 481 void parse_skip_range(void); 482 void check_axis_reversed(AXIS_INDEX axis); 483 484 /* set widest_tic_label: length of the longest tics label */ 485 void widest_tic_callback(struct axis *, double place, char *text, int ticlevel, 486 struct lp_style_type grid, struct ticmark *); 487 488 void get_position(struct position *pos); 489 void get_position_default(struct position *pos, enum position_type default_type, int ndim); 490 491 void gstrdms(char *label, char *format, double value); 492 493 void clone_linked_axes(AXIS *axis1, AXIS *axis2); 494 AXIS *get_shadow_axis(AXIS *axis); 495 void extend_primary_ticrange(AXIS *axis); 496 void update_primary_axis_range(struct axis *secondary); 497 void update_secondary_axis_range(struct axis *primary); 498 void reconcile_linked_axes(AXIS *primary, AXIS *secondary); 499 500 int map_x(double value); 501 int map_y(double value); 502 503 double map_x_double(double value); 504 double map_y_double(double value); 505 506 coord_type polar_to_xy( double theta, double r, double *x, double *y, TBOOLEAN update); 507 double polar_radius(double r); 508 509 void set_cbminmax(void); 510 511 void save_autoscaled_ranges(AXIS *, AXIS *); 512 void restore_autoscaled_ranges(AXIS *, AXIS *); 513 514 char * axis_name(AXIS_INDEX); 515 void init_sample_range(AXIS *axis, enum PLOT_TYPE plot_type); 516 void init_parallel_axis(AXIS *, AXIS_INDEX); 517 void extend_parallel_axis(int); 518 519 /* Evaluate the function linking a secondary axis to its primary axis */ 520 double eval_link_function(AXIS *, double); 521 522 /* For debugging */ 523 void dump_axis_range(AXIS *axis); 524 525 /* macro for tic scale, used in all tic_callback functions */ 526 #define tic_scale(ticlevel, axis) \ 527 (ticlevel <= 0 ? axis->ticscale : \ 528 ticlevel == 1 ? axis->miniticscale : \ 529 ticlevel < MAX_TICLEVEL ? ticscale[ticlevel] : \ 530 0) 531 532 /* convenience macro to make sure min < max */ 533 #define reorder_if_necessary( min, max ) \ 534 do { if (max < min) { double temp = min; min = max; max = temp; } \ 535 } while (0) 536 537 #endif /* GNUPLOT_AXIS_H */ 538