#ifndef lint static char *RCSid() { return RCSid("$Id: set.c,v 1.558.2.6 2017/10/10 03:55:43 sfeam Exp $"); } #endif /* GNUPLOT - set.c */ /*[ * Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley * * Permission to use, copy, and distribute this software and its * documentation for any purpose with or without fee is hereby granted, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. * * Permission to modify the software is granted, but not the right to * distribute the complete modified source code. Modifications are to * be distributed as patches to the released version. Permission to * distribute binaries produced by compiling modified sources is granted, * provided you * 1. distribute the corresponding source modifications from the * released version in the form of a patch file along with the binaries, * 2. add special version identification to distinguish your version * in addition to the base release version number, * 3. provide your name and address as the primary contact for the * support of your modified version, and * 4. retain our contact information in regard to use of the base * software. * Permission to distribute the released version of the source code along * with corresponding source modifications in the form of a patch file is * granted with same provisions 2 through 4 for binary distributions. * * This software is provided "as is" without express or implied warranty * to the extent permitted by applicable law. ]*/ /* * 19 September 1992 Lawrence Crowl (crowl@cs.orst.edu) * Added user-specified bases for log scaling. */ #include "setshow.h" #include "alloc.h" #include "axis.h" #include "command.h" #include "contour.h" #include "datafile.h" #include "datablock.h" #include "fit.h" #include "gp_hist.h" #include "gp_time.h" #include "hidden3d.h" #include "jitter.h" #include "misc.h" #include "plot.h" #include "plot2d.h" #include "plot3d.h" #include "tables.h" #include "tabulate.h" #include "term_api.h" #include "util.h" #include "variable.h" #include "pm3d.h" #include "getcolor.h" #include #ifdef HAVE_ICONV #include #endif #ifdef HAVE_LANGINFO_H #include #endif static palette_color_mode pm3d_last_set_palette_mode = SMPAL_COLOR_MODE_NONE; static void set_angles __PROTO((void)); static void set_arrow __PROTO((void)); static int assign_arrow_tag __PROTO((void)); static void set_autoscale __PROTO((void)); static void set_bars __PROTO((void)); static void set_border __PROTO((void)); static void set_boxplot __PROTO((void)); static void set_boxwidth __PROTO((void)); static void set_clabel __PROTO((void)); static void set_clip __PROTO((void)); static void set_cntrparam __PROTO((void)); static void set_cntrlabel __PROTO((void)); static void set_contour __PROTO((void)); static void set_dashtype __PROTO((void)); static void set_dgrid3d __PROTO((void)); static void set_decimalsign __PROTO((void)); static void set_degreesign __PROTO((char *)); static void set_dummy __PROTO((void)); static void set_encoding __PROTO((void)); static void set_fit __PROTO((void)); static void set_grid __PROTO((void)); static void set_hidden3d __PROTO((void)); static void set_history __PROTO((void)); static void set_isosamples __PROTO((void)); static void set_key __PROTO((void)); static void set_label __PROTO((void)); static int assign_label_tag __PROTO((void)); static void set_loadpath __PROTO((void)); static void set_fontpath __PROTO((void)); static void set_locale __PROTO((void)); static void set_logscale __PROTO((void)); static void set_mapping __PROTO((void)); static void set_margin __PROTO((t_position *)); static void set_minus_sign __PROTO((void)); static void set_micro __PROTO((void)); static void set_missing __PROTO((void)); static void set_separator __PROTO((char **)); static void set_datafile_commentschars __PROTO((void)); static void set_monochrome __PROTO((void)); #ifdef USE_MOUSE static void set_mouse __PROTO((void)); #endif static void set_offsets __PROTO((void)); static void set_origin __PROTO((void)); static void set_output __PROTO((void)); static void set_parametric __PROTO((void)); static void set_pm3d __PROTO((void)); static void set_palette __PROTO((void)); static void set_colorbox __PROTO((void)); static void set_pointsize __PROTO((void)); static void set_pointintervalbox __PROTO((void)); static void set_polar __PROTO((void)); static void set_print __PROTO((void)); #ifdef EAM_OBJECTS static void set_object __PROTO((void)); static void set_obj __PROTO((int, int)); #endif static void set_psdir __PROTO((void)); static void set_rgbmax __PROTO((void)); static void set_samples __PROTO((void)); static void set_size __PROTO((void)); static void set_style __PROTO((void)); static void set_surface __PROTO((void)); static void set_table __PROTO((void)); static void set_terminal __PROTO((void)); static void set_termoptions __PROTO((void)); static void set_theta __PROTO((void)); static void set_tics __PROTO((void)); static void set_ticscale __PROTO((void)); static void set_timefmt __PROTO((void)); static void set_timestamp __PROTO((void)); static void set_view __PROTO((void)); static void set_zero __PROTO((void)); static void set_timedata __PROTO((struct axis *)); static void set_range __PROTO((struct axis *)); static void set_paxis __PROTO((void)); static void set_raxis __PROTO((void)); static void set_xyplane __PROTO((void)); static void set_ticslevel __PROTO((void)); static void set_zeroaxis __PROTO((AXIS_INDEX)); static void set_allzeroaxis __PROTO((void)); /******** Local functions ********/ static void set_xyzlabel __PROTO((text_label * label)); static void load_tics __PROTO((struct axis * axis)); static void load_tic_user __PROTO((struct axis * axis)); static void load_tic_series __PROTO((struct axis * axis)); static void set_linestyle __PROTO((struct linestyle_def **head, lp_class destination_class)); static void set_arrowstyle __PROTO((void)); static int assign_arrowstyle_tag __PROTO((void)); static int set_tic_prop __PROTO((struct axis *)); static void set_mttics __PROTO((struct axis *this_axis)); static void check_palette_grayscale __PROTO((void)); static int set_palette_defined __PROTO((void)); static void set_palette_file __PROTO((void)); static void set_palette_function __PROTO((void)); static void parse_histogramstyle __PROTO((histogram_style *hs, t_histogram_type def_type, int def_gap)); static void set_style_parallel __PROTO((void)); static void parse_lighting_options __PROTO((void)); static const char *encoding_micro __PROTO((void)); static const char *encoding_minus __PROTO((void)); static const struct position default_position = {first_axes, first_axes, first_axes, 0., 0., 0.}; static const struct position default_offset = {character, character, character, 0., 0., 0.}; static lp_style_type default_hypertext_point_style = {1, LT_BLACK, 4, DASHTYPE_SOLID, 0, 0, 1.0, PTSZ_DEFAULT, DEFAULT_P_CHAR, {TC_RGB, 0x000000, 0.0}, DEFAULT_DASHPATTERN}; /******** The 'set' command ********/ void set_command() { c_token++; /* Mild form of backwards compatibility */ /* Allow "set no{foo}" rather than "unset foo" */ if (gp_input_line[token[c_token].start_index] == 'n' && gp_input_line[token[c_token].start_index+1] == 'o' && gp_input_line[token[c_token].start_index+2] != 'n') { if (interactive) int_warn(c_token, "deprecated syntax, use \"unset\""); token[c_token].start_index += 2; token[c_token].length -= 2; c_token--; unset_command(); } else { int save_token = c_token; set_iterator = check_for_iteration(); if (empty_iteration(set_iterator)) { /* Skip iteration [i=start:end] where start > end */ while (!END_OF_COMMAND) c_token++; set_iterator = cleanup_iteration(set_iterator); return; } if (forever_iteration(set_iterator)) { set_iterator = cleanup_iteration(set_iterator); int_error(save_token, "unbounded iteration"); } save_token = c_token; ITERATE: switch(lookup_table(&set_tbl[0],c_token)) { case S_ANGLES: set_angles(); break; case S_ARROW: set_arrow(); break; case S_AUTOSCALE: set_autoscale(); break; case S_BARS: set_bars(); break; case S_BORDER: set_border(); break; case S_BOXWIDTH: set_boxwidth(); break; case S_CLABEL: set_clabel(); break; case S_CLIP: set_clip(); break; case S_COLOR: unset_monochrome(); c_token++; break; case S_COLORSEQUENCE: set_colorsequence(0); break; case S_CNTRPARAM: set_cntrparam(); break; case S_CNTRLABEL: set_cntrlabel(); break; case S_CONTOUR: set_contour(); break; case S_DASHTYPE: set_dashtype(); break; case S_DGRID3D: set_dgrid3d(); break; case S_DECIMALSIGN: set_decimalsign(); break; case S_DUMMY: set_dummy(); break; case S_ENCODING: set_encoding(); break; case S_FIT: set_fit(); break; case S_FONTPATH: set_fontpath(); break; case S_FORMAT: set_format(); break; case S_GRID: set_grid(); break; case S_HIDDEN3D: set_hidden3d(); break; case S_HISTORYSIZE: /* Deprecated in favor of "set history size" */ case S_HISTORY: set_history(); break; case S_ISOSAMPLES: set_isosamples(); break; case S_JITTER: set_jitter(); break; case S_KEY: set_key(); break; case S_LINESTYLE: set_linestyle(&first_linestyle, LP_STYLE); break; case S_LINETYPE: if (equals(c_token+1,"cycle")) { c_token += 2; linetype_recycle_count = int_expression(); } else set_linestyle(&first_perm_linestyle, LP_TYPE); break; case S_LABEL: set_label(); break; case S_LINK: case S_NONLINEAR: link_command(); break; case S_LOADPATH: set_loadpath(); break; case S_LOCALE: set_locale(); break; case S_LOGSCALE: set_logscale(); break; case S_MACROS: /* Aug 2013 - macros are always enabled */ c_token++; break; case S_MAPPING: set_mapping(); break; case S_MARGIN: /* Jan 2015: CHANGE to order ,,, */ set_margin(&lmargin); if (!equals(c_token,",")) break; set_margin(&rmargin); if (!equals(c_token,",")) break; set_margin(&bmargin); if (!equals(c_token,",")) break; set_margin(&tmargin); break; case S_BMARGIN: set_margin(&bmargin); break; case S_LMARGIN: set_margin(&lmargin); break; case S_RMARGIN: set_margin(&rmargin); break; case S_TMARGIN: set_margin(&tmargin); break; case S_MICRO: set_micro(); break; case S_MINUS_SIGN: set_minus_sign(); break; case S_DATAFILE: if (almost_equals(++c_token,"miss$ing")) set_missing(); else if (almost_equals(c_token,"sep$arators")) set_separator(&df_separators); else if (almost_equals(c_token,"com$mentschars")) set_datafile_commentschars(); else if (almost_equals(c_token,"bin$ary")) df_set_datafile_binary(); else if (almost_equals(c_token,"fort$ran")) { df_fortran_constants = TRUE; c_token++; } else if (almost_equals(c_token,"nofort$ran")) { df_fortran_constants = FALSE; c_token++; } else if (almost_equals(c_token,"fpe_trap")) { df_nofpe_trap = FALSE; c_token++; } else if (almost_equals(c_token,"nofpe_trap")) { df_nofpe_trap = TRUE; c_token++; } else int_error(c_token,"expecting datafile modifier"); break; #ifdef USE_MOUSE case S_MOUSE: set_mouse(); break; #endif case S_MONOCHROME: set_monochrome(); break; case S_MULTIPLOT: term_start_multiplot(); break; case S_OFFSETS: set_offsets(); break; case S_ORIGIN: set_origin(); break; case SET_OUTPUT: set_output(); break; case S_PARAMETRIC: set_parametric(); break; case S_PM3D: set_pm3d(); break; case S_PALETTE: set_palette(); break; case S_COLORBOX: set_colorbox(); break; case S_POINTINTERVALBOX: set_pointintervalbox(); break; case S_POINTSIZE: set_pointsize(); break; case S_POLAR: set_polar(); break; case S_PRINT: set_print(); break; case S_PSDIR: set_psdir(); break; #ifdef EAM_OBJECTS case S_OBJECT: set_object(); break; #endif case S_SAMPLES: set_samples(); break; case S_RGBMAX: set_rgbmax(); break; case S_SIZE: set_size(); break; case S_STYLE: set_style(); break; case S_SURFACE: set_surface(); break; case S_TABLE: set_table(); break; case S_TERMINAL: set_terminal(); break; case S_TERMOPTIONS: set_termoptions(); break; case S_THETA: set_theta(); break; case S_TICS: set_tics(); break; case S_TICSCALE: set_ticscale(); break; case S_TIMEFMT: set_timefmt(); break; case S_TIMESTAMP: set_timestamp(); break; case S_TITLE: set_xyzlabel(&title); title.rotate = 0.0; break; case S_VIEW: set_view(); break; case S_ZERO: set_zero(); break; case S_MXTICS: case S_NOMXTICS: case S_XTICS: case S_NOXTICS: case S_XDTICS: case S_NOXDTICS: case S_XMTICS: case S_NOXMTICS: set_tic_prop(&axis_array[FIRST_X_AXIS]); break; case S_MYTICS: case S_NOMYTICS: case S_YTICS: case S_NOYTICS: case S_YDTICS: case S_NOYDTICS: case S_YMTICS: case S_NOYMTICS: set_tic_prop(&axis_array[FIRST_Y_AXIS]); break; case S_MX2TICS: case S_NOMX2TICS: case S_X2TICS: case S_NOX2TICS: case S_X2DTICS: case S_NOX2DTICS: case S_X2MTICS: case S_NOX2MTICS: set_tic_prop(&axis_array[SECOND_X_AXIS]); break; case S_MY2TICS: case S_NOMY2TICS: case S_Y2TICS: case S_NOY2TICS: case S_Y2DTICS: case S_NOY2DTICS: case S_Y2MTICS: case S_NOY2MTICS: set_tic_prop(&axis_array[SECOND_Y_AXIS]); break; case S_MZTICS: case S_NOMZTICS: case S_ZTICS: case S_NOZTICS: case S_ZDTICS: case S_NOZDTICS: case S_ZMTICS: case S_NOZMTICS: set_tic_prop(&axis_array[FIRST_Z_AXIS]); break; case S_MCBTICS: case S_NOMCBTICS: case S_CBTICS: case S_NOCBTICS: case S_CBDTICS: case S_NOCBDTICS: case S_CBMTICS: case S_NOCBMTICS: set_tic_prop(&axis_array[COLOR_AXIS]); break; case S_RTICS: case S_MRTICS: set_tic_prop(&axis_array[POLAR_AXIS]); break; case S_TTICS: set_tic_prop(&THETA_AXIS); break; case S_MTTICS: set_mttics(&THETA_AXIS); break; case S_XDATA: set_timedata(&axis_array[FIRST_X_AXIS]); axis_array[T_AXIS].datatype = axis_array[U_AXIS].datatype = axis_array[FIRST_X_AXIS].datatype; break; case S_YDATA: set_timedata(&axis_array[FIRST_Y_AXIS]); axis_array[V_AXIS].datatype = axis_array[FIRST_X_AXIS].datatype; break; case S_ZDATA: set_timedata(&axis_array[FIRST_Z_AXIS]); break; case S_CBDATA: set_timedata(&axis_array[COLOR_AXIS]); break; case S_X2DATA: set_timedata(&axis_array[SECOND_X_AXIS]); break; case S_Y2DATA: set_timedata(&axis_array[SECOND_Y_AXIS]); break; case S_XLABEL: set_xyzlabel(&axis_array[FIRST_X_AXIS].label); break; case S_YLABEL: set_xyzlabel(&axis_array[FIRST_Y_AXIS].label); break; case S_ZLABEL: set_xyzlabel(&axis_array[FIRST_Z_AXIS].label); break; case S_CBLABEL: set_xyzlabel(&axis_array[COLOR_AXIS].label); break; case S_RLABEL: set_xyzlabel(&axis_array[POLAR_AXIS].label); break; case S_X2LABEL: set_xyzlabel(&axis_array[SECOND_X_AXIS].label); break; case S_Y2LABEL: set_xyzlabel(&axis_array[SECOND_Y_AXIS].label); break; case S_XRANGE: set_range(&axis_array[FIRST_X_AXIS]); break; case S_X2RANGE: set_range(&axis_array[SECOND_X_AXIS]); break; case S_YRANGE: set_range(&axis_array[FIRST_Y_AXIS]); break; case S_Y2RANGE: set_range(&axis_array[SECOND_Y_AXIS]); break; case S_ZRANGE: set_range(&axis_array[FIRST_Z_AXIS]); break; case S_CBRANGE: set_range(&axis_array[COLOR_AXIS]); break; case S_RRANGE: set_range(&axis_array[POLAR_AXIS]); if (polar) rrange_to_xy(); break; case S_TRANGE: set_range(&axis_array[T_AXIS]); break; case S_URANGE: set_range(&axis_array[U_AXIS]); break; case S_VRANGE: set_range(&axis_array[V_AXIS]); break; case S_PAXIS: set_paxis(); break; case S_RAXIS: set_raxis(); break; case S_XZEROAXIS: set_zeroaxis(FIRST_X_AXIS); break; case S_YZEROAXIS: set_zeroaxis(FIRST_Y_AXIS); break; case S_ZZEROAXIS: set_zeroaxis(FIRST_Z_AXIS); break; case S_X2ZEROAXIS: set_zeroaxis(SECOND_X_AXIS); break; case S_Y2ZEROAXIS: set_zeroaxis(SECOND_Y_AXIS); break; case S_ZEROAXIS: set_allzeroaxis(); break; case S_XYPLANE: set_xyplane(); break; case S_TICSLEVEL: set_ticslevel(); break; default: int_error(c_token, "unrecognized option - see 'help set'."); break; } if (next_iteration(set_iterator)) { c_token = save_token; goto ITERATE; } } update_gpval_variables(0); set_iterator = cleanup_iteration(set_iterator); } /* process 'set angles' command */ static void set_angles() { c_token++; if (END_OF_COMMAND) { /* assuming same as defaults */ ang2rad = 1; } else if (almost_equals(c_token, "r$adians")) { c_token++; ang2rad = 1; } else if (almost_equals(c_token, "d$egrees")) { c_token++; ang2rad = DEG2RAD; } else int_error(c_token, "expecting 'radians' or 'degrees'"); if (polar && axis_array[T_AXIS].set_autoscale) { /* set trange if in polar mode and no explicit range */ axis_array[T_AXIS].set_min = 0; axis_array[T_AXIS].set_max = 2 * M_PI / ang2rad; } } /* process a 'set arrow' command */ /* set arrow {tag} {from x,y} {to x,y} {{no}head} ... */ /* allow any order of options - pm 25.11.2001 */ static void set_arrow() { struct arrow_def *this_arrow = NULL; struct arrow_def *new_arrow = NULL; struct arrow_def *prev_arrow = NULL; TBOOLEAN duplication = FALSE; TBOOLEAN set_start = FALSE; TBOOLEAN set_end = FALSE; int save_token; int tag; c_token++; /* get tag */ if (almost_equals(c_token, "back$head") || equals(c_token, "front") || equals(c_token, "from") || equals(c_token, "at") || equals(c_token, "to") || equals(c_token, "rto") || equals(c_token, "size") || equals(c_token, "filled") || equals(c_token, "empty") || equals(c_token, "as") || equals(c_token, "arrowstyle") || almost_equals(c_token, "head$s") || equals(c_token, "nohead") || almost_equals(c_token, "nobo$rder")) { tag = assign_arrow_tag(); } else tag = int_expression(); if (tag <= 0) int_error(c_token, "tag must be > 0"); /* OK! add arrow */ if (first_arrow != NULL) { /* skip to last arrow */ for (this_arrow = first_arrow; this_arrow != NULL; prev_arrow = this_arrow, this_arrow = this_arrow->next) /* is this the arrow we want? */ if (tag <= this_arrow->tag) break; } if (this_arrow == NULL || tag != this_arrow->tag) { new_arrow = gp_alloc(sizeof(struct arrow_def), "arrow"); if (prev_arrow == NULL) first_arrow = new_arrow; else prev_arrow->next = new_arrow; new_arrow->tag = tag; new_arrow->next = this_arrow; this_arrow = new_arrow; this_arrow->start = default_position; this_arrow->end = default_position; this_arrow->angle = 0.0; this_arrow->type = arrow_end_undefined; default_arrow_style(&(new_arrow->arrow_properties)); } while (!END_OF_COMMAND) { /* get start position */ if (equals(c_token, "from") || equals(c_token,"at")) { if (set_start) { duplication = TRUE; break; } c_token++; if (END_OF_COMMAND) int_error(c_token, "start coordinates expected"); /* get coordinates */ get_position(&this_arrow->start); set_start = TRUE; continue; } /* get end or relative end position */ if (equals(c_token, "to") || equals(c_token,"rto")) { if (set_end) { duplication = TRUE; break; } if (equals(c_token,"rto")) this_arrow->type = arrow_end_relative; else this_arrow->type = arrow_end_absolute; c_token++; if (END_OF_COMMAND) int_error(c_token, "end coordinates expected"); /* get coordinates */ get_position(&this_arrow->end); set_end = TRUE; continue; } /* get end position specified as length + orientation angle */ if (almost_equals(c_token, "len$gth")) { if (set_end) { duplication = TRUE; break; } this_arrow->type = arrow_end_oriented; c_token++; get_position_default(&this_arrow->end, first_axes, 1); set_end = TRUE; continue; } if (almost_equals(c_token,"ang$le")) { c_token++; this_arrow->angle = real_expression(); continue; } /* Allow interspersed style commands */ save_token = c_token; arrow_parse(&this_arrow->arrow_properties, TRUE); if (save_token != c_token) continue; if (!END_OF_COMMAND) int_error(c_token, "wrong argument in set arrow"); } /* while (!END_OF_COMMAND) */ if (duplication) int_error(c_token, "duplicate or contradictory arguments"); } /* assign a new arrow tag * arrows are kept sorted by tag number, so this is easy * returns the lowest unassigned tag number */ static int assign_arrow_tag() { struct arrow_def *this_arrow; int last = 0; /* previous tag value */ for (this_arrow = first_arrow; this_arrow != NULL; this_arrow = this_arrow->next) if (this_arrow->tag == last + 1) last++; else break; return (last + 1); } /* helper routine for 'set autoscale' on a single axis */ static TBOOLEAN set_autoscale_axis(struct axis *this) { char keyword[16]; char *name = (char *) &(axis_name(this->index)[0]); if (equals(c_token, name)) { this->set_autoscale = AUTOSCALE_BOTH; this->min_constraint = CONSTRAINT_NONE; this->max_constraint = CONSTRAINT_NONE; ++c_token; return TRUE; } sprintf(keyword, "%smi$n", name); if (almost_equals(c_token, keyword)) { this->set_autoscale |= AUTOSCALE_MIN; this->min_constraint = CONSTRAINT_NONE; ++c_token; return TRUE; } sprintf(keyword, "%sma$x", name); if (almost_equals(c_token, keyword)) { this->set_autoscale |= AUTOSCALE_MAX; this->max_constraint = CONSTRAINT_NONE; ++c_token; return TRUE; } sprintf(keyword, "%sfix", name); if (equals(c_token, keyword)) { this->set_autoscale |= AUTOSCALE_FIXMIN | AUTOSCALE_FIXMAX; ++c_token; return TRUE; } sprintf(keyword, "%sfixmi$n", name); if (almost_equals(c_token, keyword)) { this->set_autoscale |= AUTOSCALE_FIXMIN; ++c_token; return TRUE; } sprintf(keyword, "%sfixma$x", name); if (almost_equals(c_token, keyword)) { this->set_autoscale |= AUTOSCALE_FIXMAX; ++c_token; return TRUE; } return FALSE; } /* process 'set autoscale' command */ static void set_autoscale() { int axis; c_token++; if (END_OF_COMMAND) { for (axis=0; axis 1) int_error(c_token-1,"fraction must be less than 1"); boxplot_opts.limit_type = 1; } else if (almost_equals(c_token,"candle$sticks")) { c_token++; boxplot_opts.plotstyle = CANDLESTICKS; } else if (almost_equals(c_token,"finance$bars")) { c_token++; boxplot_opts.plotstyle = FINANCEBARS; } else if (almost_equals(c_token,"sep$aration")) { c_token++; boxplot_opts.separation = real_expression(); if (boxplot_opts.separation < 0) int_error(c_token-1,"separation must be > 0"); } else if (almost_equals(c_token,"lab$els")) { c_token++; if (equals(c_token, "off")) { boxplot_opts.labels = BOXPLOT_FACTOR_LABELS_OFF; } else if (equals(c_token, "x")) { boxplot_opts.labels = BOXPLOT_FACTOR_LABELS_X; } else if (equals(c_token, "x2")) { boxplot_opts.labels = BOXPLOT_FACTOR_LABELS_X2; } else if (equals(c_token, "auto")) { boxplot_opts.labels = BOXPLOT_FACTOR_LABELS_AUTO; } else int_error(c_token-1,"expecting 'x', 'x2', 'auto' or 'off'"); c_token++; } else if (almost_equals(c_token, "so$rted")) { boxplot_opts.sort_factors = TRUE; c_token++; } else if (almost_equals(c_token, "un$sorted")) { boxplot_opts.sort_factors = FALSE; c_token++; } else int_error(c_token,"unrecognized option"); } } /* process 'set boxwidth' command */ static void set_boxwidth() { c_token++; if (END_OF_COMMAND) { boxwidth = -1.0; boxwidth_is_absolute = TRUE; } else { boxwidth = real_expression(); } if (END_OF_COMMAND) return; else { if (almost_equals(c_token, "a$bsolute")) boxwidth_is_absolute = TRUE; else if (almost_equals(c_token, "r$elative")) boxwidth_is_absolute = FALSE; else int_error(c_token, "expecting 'absolute' or 'relative' "); } c_token++; } /* process 'set clabel' command */ static void set_clabel() { char *new_format; c_token++; clabel_onecolor = FALSE; if ((new_format = try_to_get_string())) { strncpy(contour_format, new_format, sizeof(contour_format)); free(new_format); } } /* process 'set clip' command */ static void set_clip() { c_token++; if (END_OF_COMMAND) { /* assuming same as points */ clip_points = TRUE; } else if (almost_equals(c_token, "p$oints")) { clip_points = TRUE; c_token++; } else if (almost_equals(c_token, "o$ne")) { clip_lines1 = TRUE; c_token++; } else if (almost_equals(c_token, "t$wo")) { clip_lines2 = TRUE; c_token++; } else int_error(c_token, "expecting 'points', 'one', or 'two'"); } /* process 'set cntrparam' command */ static void set_cntrparam() { c_token++; if (END_OF_COMMAND) { /* assuming same as defaults */ contour_pts = DEFAULT_NUM_APPROX_PTS; contour_kind = CONTOUR_KIND_LINEAR; contour_order = DEFAULT_CONTOUR_ORDER; contour_levels = DEFAULT_CONTOUR_LEVELS; contour_levels_kind = LEVELS_AUTO; } else if (almost_equals(c_token, "p$oints")) { c_token++; contour_pts = int_expression(); } else if (almost_equals(c_token, "li$near")) { c_token++; contour_kind = CONTOUR_KIND_LINEAR; } else if (almost_equals(c_token, "c$ubicspline")) { c_token++; contour_kind = CONTOUR_KIND_CUBIC_SPL; } else if (almost_equals(c_token, "b$spline")) { c_token++; contour_kind = CONTOUR_KIND_BSPLINE; } else if (almost_equals(c_token, "le$vels")) { c_token++; if (!(set_iterator && set_iterator->iteration)) { free_dynarray(&dyn_contour_levels_list); init_dynarray(&dyn_contour_levels_list, sizeof(double), 5, 10); } /* RKC: I have modified the next two: * to use commas to separate list elements as in xtics * so that incremental lists start,incr[,end]as in " */ if (almost_equals(c_token, "di$screte")) { contour_levels_kind = LEVELS_DISCRETE; c_token++; if (END_OF_COMMAND) int_error(c_token, "expecting discrete level"); else *(double *)nextfrom_dynarray(&dyn_contour_levels_list) = real_expression(); while(!END_OF_COMMAND) { if (!equals(c_token, ",")) int_error(c_token, "expecting comma to separate discrete levels"); c_token++; *(double *)nextfrom_dynarray(&dyn_contour_levels_list) = real_expression(); } contour_levels = dyn_contour_levels_list.end; } else if (almost_equals(c_token, "in$cremental")) { int i = 0; /* local counter */ contour_levels_kind = LEVELS_INCREMENTAL; c_token++; contour_levels_list[i++] = real_expression(); if (!equals(c_token, ",")) int_error(c_token, "expecting comma to separate start,incr levels"); c_token++; if ((contour_levels_list[i++] = real_expression()) == 0) int_error(c_token, "increment cannot be 0"); if (!END_OF_COMMAND) { if (!equals(c_token, ",")) int_error(c_token, "expecting comma to separate incr,stop levels"); c_token++; /* need to round up, since 10,10,50 is 5 levels, not four, * but 10,10,49 is four */ dyn_contour_levels_list.end = i; contour_levels = (int) ( (real_expression()-contour_levels_list[0])/contour_levels_list[1] + 1.0); } } else if (almost_equals(c_token, "au$to")) { contour_levels_kind = LEVELS_AUTO; c_token++; if (!END_OF_COMMAND) contour_levels = int_expression(); } else { if (contour_levels_kind == LEVELS_DISCRETE) int_error(c_token, "Levels type is discrete, ignoring new number of contour levels"); contour_levels = int_expression(); } } else if (almost_equals(c_token, "o$rder")) { int order; c_token++; order = int_expression(); if ( order < 2 || order > MAX_BSPLINE_ORDER ) int_error(c_token, "bspline order must be in [2..10] range."); contour_order = order; } else int_error(c_token, "expecting 'linear', 'cubicspline', 'bspline', 'points', 'levels' or 'order'"); } /* process 'set cntrlabel' command */ static void set_cntrlabel() { c_token++; if (END_OF_COMMAND) { strcpy(contour_format, "%8.3g"); clabel_onecolor = FALSE; return; } while (!END_OF_COMMAND) { if (almost_equals(c_token, "form$at")) { char *new; c_token++; if ((new = try_to_get_string())) strncpy(contour_format,new,sizeof(contour_format)); free(new); } else if (equals(c_token, "font")) { char *ctmp; c_token++; if ((ctmp = try_to_get_string())) { free(clabel_font); clabel_font = ctmp; } } else if (almost_equals(c_token, "one$color")) { c_token++; clabel_onecolor = TRUE; } else if (equals(c_token, "start")) { c_token++; clabel_start = int_expression(); if (clabel_start <= 0) clabel_start = 5; } else if (almost_equals(c_token, "int$erval")) { c_token++; clabel_interval = int_expression(); } else { int_error(c_token, "unrecognized option"); } } } /* process 'set contour' command */ static void set_contour() { c_token++; if (END_OF_COMMAND) /* assuming same as points */ draw_contour = CONTOUR_BASE; else { if (almost_equals(c_token, "ba$se")) draw_contour = CONTOUR_BASE; else if (almost_equals(c_token, "s$urface")) draw_contour = CONTOUR_SRF; else if (almost_equals(c_token, "bo$th")) draw_contour = CONTOUR_BOTH; else int_error(c_token, "expecting 'base', 'surface', or 'both'"); c_token++; } } /* process 'set colorsequence command */ void set_colorsequence(int option) { unsigned long default_colors[] = DEFAULT_COLOR_SEQUENCE; unsigned long podo_colors[] = PODO_COLOR_SEQUENCE; if (option == 0) { /* Read option from command line */ if (equals(++c_token, "default")) option = 1; else if (equals(c_token, "podo")) option = 2; else if (equals(c_token, "classic")) option = 3; else int_error(c_token, "unrecognized color set"); } if (option == 1 || option == 2) { int i; char *command; char *command_template = "set linetype %2d lc rgb 0x%06x"; unsigned long *colors = default_colors; if (option == 2) colors = podo_colors; linetype_recycle_count = 8; for (i = 1; i <= 8; i++) { command = gp_alloc(strlen(command_template)+8, "dynamic command"); sprintf(command, command_template, i, colors[i-1]); do_string_and_free(command); } } else if (option == 3) { struct linestyle_def *this; for (this = first_perm_linestyle; this != NULL; this = this->next) { this->lp_properties.pm3d_color.type = TC_LT; this->lp_properties.pm3d_color.lt = this->tag-1; } linetype_recycle_count = 0; } else { int_error(c_token, "Expecting 'classic' or 'default'"); } c_token++; } /* process 'set dashtype' command */ static void set_dashtype() { struct custom_dashtype_def *this_dashtype = NULL; struct custom_dashtype_def *new_dashtype = NULL; struct custom_dashtype_def *prev_dashtype = NULL; int tag, is_new = FALSE; c_token++; /* get tag */ if (END_OF_COMMAND || ((tag = int_expression()) <= 0)) int_error(c_token, "tag must be > zero"); /* Check if dashtype is already defined */ for (this_dashtype = first_custom_dashtype; this_dashtype != NULL; prev_dashtype = this_dashtype, this_dashtype = this_dashtype->next) if (tag <= this_dashtype->tag) break; if (this_dashtype == NULL || tag != this_dashtype->tag) { struct t_dashtype loc_dt = DEFAULT_DASHPATTERN; new_dashtype = gp_alloc(sizeof(struct custom_dashtype_def), "dashtype"); if (prev_dashtype != NULL) prev_dashtype->next = new_dashtype; /* add it to end of list */ else first_custom_dashtype = new_dashtype; /* make it start of list */ new_dashtype->tag = tag; new_dashtype->d_type = DASHTYPE_SOLID; new_dashtype->next = this_dashtype; new_dashtype->dashtype = loc_dt; this_dashtype = new_dashtype; is_new = TRUE; } if (almost_equals(c_token, "def$ault")) { delete_dashtype(prev_dashtype, this_dashtype); is_new = FALSE; c_token++; } else { /* FIXME: Maybe this should reject return values > 0 because */ /* otherwise we have potentially recursive definitions. */ this_dashtype->d_type = parse_dashtype(&this_dashtype->dashtype); } if (!END_OF_COMMAND) { if (is_new) delete_dashtype(prev_dashtype, this_dashtype); int_error(c_token,"Extraneous arguments to set dashtype"); } } /* * Delete dashtype from linked list. */ void delete_dashtype(struct custom_dashtype_def *prev, struct custom_dashtype_def *this) { if (this != NULL) { /* there really is something to delete */ if (this == first_custom_dashtype) first_custom_dashtype = this->next; else prev->next = this->next; free(this); } } /* process 'set dgrid3d' command */ static void set_dgrid3d() { int token_cnt = 0; /* Number of comma-separated values read in */ int gridx = dgrid3d_row_fineness; int gridy = dgrid3d_col_fineness; int normval = dgrid3d_norm_value; double scalex = dgrid3d_x_scale; double scaley = dgrid3d_y_scale; /* dgrid3d has two different syntax alternatives: classic and new. If there is a "mode" keyword, the syntax is new, otherwise it is classic.*/ dgrid3d_mode = DGRID3D_DEFAULT; dgrid3d_kdensity = FALSE; c_token++; while ( !(END_OF_COMMAND) ) { int tmp_mode = lookup_table(&dgrid3d_mode_tbl[0],c_token); if (tmp_mode != DGRID3D_OTHER) { dgrid3d_mode = tmp_mode; c_token++; } switch (tmp_mode) { case DGRID3D_QNORM: if (!(END_OF_COMMAND)) normval = int_expression(); break; case DGRID3D_SPLINES: break; case DGRID3D_GAUSS: case DGRID3D_CAUCHY: case DGRID3D_EXP: case DGRID3D_BOX: case DGRID3D_HANN: if (!(END_OF_COMMAND) && almost_equals( c_token, "kdens$ity2d" )) { dgrid3d_kdensity = TRUE; c_token++; } if (!(END_OF_COMMAND)) { scalex = real_expression(); scaley = scalex; if (equals(c_token, ",")) { c_token++; scaley = real_expression(); } } break; default: /* {rows}{,cols{,norm}}} */ if ( equals( c_token, "," )) { c_token++; token_cnt++; } else if (token_cnt == 0) { gridx = int_expression(); gridy = gridx; /* gridy defaults to gridx, unless overridden below */ } else if (token_cnt == 1) { gridy = int_expression(); } else if (token_cnt == 2) { normval = int_expression(); } else int_error(c_token,"Unrecognized keyword or unexpected value"); break; } } /* we could warn here about floating point values being truncated... */ if (gridx < 2 || gridx > 1000 || gridy < 2 || gridy > 1000) int_error( NO_CARET, "Number of grid points must be in [2:1000] - not changed!"); /* no mode token found: classic format */ if (dgrid3d_mode == DGRID3D_DEFAULT) dgrid3d_mode = DGRID3D_QNORM; if (scalex < 0.0 || scaley < 0.0) int_error( NO_CARET, "Scale factors must be greater than zero - not changed!" ); dgrid3d_row_fineness = gridx; dgrid3d_col_fineness = gridy; dgrid3d_norm_value = normval; dgrid3d_x_scale = scalex; dgrid3d_y_scale = scaley; dgrid3d = TRUE; } /* process 'set decimalsign' command */ static void set_decimalsign() { c_token++; /* Clear current setting */ free(decimalsign); decimalsign=NULL; if (END_OF_COMMAND) { reset_numeric_locale(); free(numeric_locale); numeric_locale = NULL; #ifdef HAVE_LOCALE_H } else if (equals(c_token,"locale")) { char *newlocale = NULL; c_token++; newlocale = try_to_get_string(); if (!newlocale) newlocale = gp_strdup(setlocale(LC_NUMERIC,"")); if (!newlocale) newlocale = gp_strdup(getenv("LC_ALL")); if (!newlocale) newlocale = gp_strdup(getenv("LC_NUMERIC")); if (!newlocale) newlocale = gp_strdup(getenv("LANG")); if (!setlocale(LC_NUMERIC, newlocale ? newlocale : "")) int_error(c_token-1, "Could not find requested locale"); decimalsign = gp_strdup(get_decimal_locale()); fprintf(stderr,"decimal_sign in locale is %s\n", decimalsign); /* Save this locale for later use, but return to "C" for now */ free(numeric_locale); numeric_locale = newlocale; setlocale(LC_NUMERIC,"C"); #endif } else if (!(decimalsign = try_to_get_string())) int_error(c_token, "expecting string"); } /* process 'set dummy' command */ static void set_dummy() { int i; c_token++; for (i=0; i 0.) && (value < 1.)) { v = add_udv_by_name((char *)FITLIMIT); Gcomplex(&v->udv_value, value, 0); } else { del_udv_by_name((char *)FITLIMIT, FALSE); } } else if (equals(c_token, "limit_abs")) { double value; c_token++; value = real_expression(); epsilon_abs = (value > 0.) ? value : 0.; } else if (equals(c_token, "maxiter")) { /* preserve compatibility with FIT_MAXITER user variable */ struct udvt_entry *v; int maxiter; c_token++; if (equals(c_token, "default")) { c_token++; maxiter = 0; } else maxiter = int_expression(); if (maxiter > 0) { v = add_udv_by_name((char *)FITMAXITER); Ginteger(&v->udv_value, maxiter); } else { del_udv_by_name((char *)FITMAXITER, FALSE); } } else if (equals(c_token, "start_lambda")) { /* preserve compatibility with FIT_START_LAMBDA user variable */ struct udvt_entry *v; double value; c_token++; if (equals(c_token, "default")) { c_token++; value = 0.; } else value = real_expression(); if (value > 0.) { v = add_udv_by_name((char *)FITSTARTLAMBDA); Gcomplex(&v->udv_value, value, 0); } else { del_udv_by_name((char *)FITSTARTLAMBDA, FALSE); } } else if (equals(c_token, "lambda_factor")) { /* preserve compatibility with FIT_LAMBDA_FACTOR user variable */ struct udvt_entry *v; double value; c_token++; if (equals(c_token, "default")) { c_token++; value = 0.; } else value = real_expression(); if (value > 0.) { v = add_udv_by_name((char *)FITLAMBDAFACTOR); Gcomplex(&v->udv_value, value, 0); } else { del_udv_by_name((char *)FITLAMBDAFACTOR, FALSE); } } else if (equals(c_token, "script")) { char *tmp; c_token++; if (END_OF_COMMAND) { free(fit_script); fit_script = NULL; } else if (equals(c_token, "default")) { c_token++; free(fit_script); fit_script = NULL; } else if ((tmp = try_to_get_string())) { free(fit_script); fit_script = tmp; } else { int_error(c_token, "expecting string"); } } else if (equals(c_token, "wrap")) { c_token++; fit_wrap = int_expression(); if (fit_wrap < 0) fit_wrap = 0; } else if (equals(c_token, "nowrap")) { c_token++; fit_wrap = 0; } else if (equals(c_token, "v4")) { c_token++; fit_v4compatible = TRUE; } else if (equals(c_token, "v5")) { c_token++; fit_v4compatible = FALSE; } else { int_error(c_token, "unrecognized option --- see `help set fit`"); } } /* while (!end) */ } /* process 'set format' command */ void set_format() { TBOOLEAN set_for_axis[AXIS_ARRAY_SIZE] = AXIS_ARRAY_INITIALIZER(FALSE); AXIS_INDEX axis; char *format; td_type tictype = DT_UNINITIALIZED; c_token++; if ((axis = lookup_table(axisname_tbl, c_token)) >= 0) { set_for_axis[axis] = TRUE; c_token++; } else if (equals(c_token,"xy") || equals(c_token,"yx")) { set_for_axis[FIRST_X_AXIS] = set_for_axis[FIRST_Y_AXIS] = TRUE; c_token++; } else { /* Set all of them */ for (axis = 0; axis < AXIS_ARRAY_SIZE; axis++) set_for_axis[axis] = TRUE; } if (END_OF_COMMAND) { for (axis = FIRST_AXES; axis <= POLAR_AXIS; axis++) { if (set_for_axis[axis]) { free(axis_array[axis].formatstring); axis_array[axis].formatstring = gp_strdup(DEF_FORMAT); axis_array[axis].tictype = DT_NORMAL; } } return; } if (!(format = try_to_get_string())) int_error(c_token, "expecting format string"); if (almost_equals(c_token,"time$date")) { tictype = DT_TIMEDATE; c_token++; } else if (almost_equals(c_token,"geo$graphic")) { tictype = DT_DMS; c_token++; } else if (almost_equals(c_token,"num$eric")) { tictype = DT_NORMAL; c_token++; } for (axis = FIRST_AXES; axis <= POLAR_AXIS; axis++) { if (set_for_axis[axis]) { free(axis_array[axis].formatstring); axis_array[axis].formatstring = gp_strdup(format); if (tictype != DT_UNINITIALIZED) axis_array[axis].tictype = tictype; } } free(format); } /* process 'set grid' command */ static void set_grid() { TBOOLEAN explicit_change = FALSE; c_token++; #define GRID_MATCH(axis, string) \ if (almost_equals(c_token, string+2)) { \ if (string[2] == 'm') \ axis_array[axis].gridminor = TRUE; \ else \ axis_array[axis].gridmajor = TRUE; \ explicit_change = TRUE; \ ++c_token; \ } else if (almost_equals(c_token, string)) { \ if (string[2] == 'm') \ axis_array[axis].gridminor = FALSE; \ else \ axis_array[axis].gridmajor = FALSE; \ explicit_change = TRUE; \ ++c_token; \ } while (!END_OF_COMMAND) { GRID_MATCH(FIRST_X_AXIS, "nox$tics") else GRID_MATCH(FIRST_Y_AXIS, "noy$tics") else GRID_MATCH(FIRST_Z_AXIS, "noz$tics") else GRID_MATCH(SECOND_X_AXIS, "nox2$tics") else GRID_MATCH(SECOND_Y_AXIS, "noy2$tics") else GRID_MATCH(FIRST_X_AXIS, "nomx$tics") else GRID_MATCH(FIRST_Y_AXIS, "nomy$tics") else GRID_MATCH(FIRST_Z_AXIS, "nomz$tics") else GRID_MATCH(SECOND_X_AXIS, "nomx2$tics") else GRID_MATCH(SECOND_Y_AXIS, "nomy2$tics") else GRID_MATCH(COLOR_AXIS, "nocb$tics") else GRID_MATCH(COLOR_AXIS, "nomcb$tics") else GRID_MATCH(POLAR_AXIS, "nor$tics") else GRID_MATCH(POLAR_AXIS, "nomr$tics") else if (almost_equals(c_token,"po$lar")) { /* Dec 2016 - zero or negative disables radial grid lines */ axis_array[POLAR_AXIS].gridmajor = TRUE; /* Enable both circles and radii */ polar_grid_angle = 30*DEG2RAD; c_token++; if (isanumber(c_token) || type_udv(c_token) == INTGR || type_udv(c_token) == CMPLX) { double ang = real_expression(); polar_grid_angle = (ang > 2.*M_PI) ? DEG2RAD*ang : ang2rad*ang; } } else if (almost_equals(c_token,"nopo$lar")) { polar_grid_angle = 0; /* not polar grid */ c_token++; } else if (equals(c_token,"back")) { grid_layer = LAYER_BACK; c_token++; } else if (equals(c_token,"front")) { grid_layer = LAYER_FRONT; c_token++; } else if (almost_equals(c_token,"layerd$efault") || equals(c_token, "behind")) { grid_layer = LAYER_BEHIND; c_token++; } else { /* only remaining possibility is a line type */ int save_token = c_token; lp_parse(&grid_lp, LP_ADHOC, FALSE); if (equals(c_token,",")) { c_token++; lp_parse(&mgrid_lp, LP_ADHOC, FALSE); } else if (save_token != c_token) mgrid_lp = grid_lp; if (save_token == c_token) break; } } if (!explicit_change && !some_grid_selected()) { /* no axis specified, thus select default grid */ if (polar) { axis_array[POLAR_AXIS].gridmajor = TRUE; polar_grid_angle = 30.*DEG2RAD; } else { axis_array[FIRST_X_AXIS].gridmajor = TRUE; axis_array[FIRST_Y_AXIS].gridmajor = TRUE; } } } /* process 'set hidden3d' command */ static void set_hidden3d() { c_token++; set_hidden3doptions(); hidden3d = TRUE; } static void set_history() { c_token++; while (!END_OF_COMMAND) { if (equals(c_token, "quiet")) { c_token++; history_quiet = TRUE; continue; } else if (almost_equals(c_token, "num$bers")) { c_token++; history_quiet = FALSE; continue; } else if (equals(c_token, "full")) { c_token++; history_full = TRUE; continue; } else if (equals(c_token, "trim")) { c_token++; history_full = FALSE; continue; } else if (almost_equals(c_token, "def$ault")) { c_token++; history_quiet = FALSE; history_full = TRUE; gnuplot_history_size = HISTORY_SIZE; continue; } else if (equals(c_token, "size")) { c_token++; /* fall through */ } /* Catches both the deprecated "set historysize" and "set history size" */ gnuplot_history_size = int_expression(); #ifndef GNUPLOT_HISTORY int_warn(NO_CARET, "This copy of gnuplot was built without support for command history."); #endif } } /* process 'set isosamples' command */ static void set_isosamples() { int tsamp1, tsamp2; c_token++; tsamp1 = abs(int_expression()); tsamp2 = tsamp1; if (!END_OF_COMMAND) { if (!equals(c_token,",")) int_error(c_token, "',' expected"); c_token++; tsamp2 = abs(int_expression()); } if (tsamp1 < 2 || tsamp2 < 2) int_error(c_token, "sampling rate must be > 1; sampling unchanged"); else { struct curve_points *f_p = first_plot; struct surface_points *f_3dp = first_3dplot; first_plot = NULL; first_3dplot = NULL; cp_free(f_p); sp_free(f_3dp); iso_samples_1 = tsamp1; iso_samples_2 = tsamp2; } } /* When plotting an external key, the margin and l/r/t/b/c are used to determine one of twelve possible positions. They must be defined appropriately in the case where stack direction determines exact position. */ static void set_key_position_from_stack_direction(legend_key *key) { if (key->stack_dir == GPKEY_VERTICAL) { switch(key->hpos) { case LEFT: key->margin = GPKEY_LMARGIN; break; case CENTRE: if (key->vpos == JUST_TOP) key->margin = GPKEY_TMARGIN; else key->margin = GPKEY_BMARGIN; break; case RIGHT: key->margin = GPKEY_RMARGIN; break; } } else { switch(key->vpos) { case JUST_TOP: key->margin = GPKEY_TMARGIN; break; case JUST_CENTRE: if (key->hpos == LEFT) key->margin = GPKEY_LMARGIN; else key->margin = GPKEY_RMARGIN; break; case JUST_BOT: key->margin = GPKEY_BMARGIN; break; } } } /* process 'set key' command */ static void set_key() { TBOOLEAN vpos_set = FALSE, hpos_set = FALSE, reg_set = FALSE, sdir_set = FALSE; char *vpos_warn = "Multiple vertical position settings"; char *hpos_warn = "Multiple horizontal position settings"; char *reg_warn = "Multiple location region settings"; char *sdir_warn = "Multiple stack direction settings"; legend_key *key = &keyT; /* Only for backward compatibility with deprecated "set keytitle foo" */ if (almost_equals(c_token,"keyt$itle")) goto S_KEYTITLE; c_token++; key->visible = TRUE; while (!END_OF_COMMAND) { switch(lookup_table(&set_key_tbl[0],c_token)) { case S_KEY_ON: key->visible = TRUE; break; case S_KEY_OFF: key->visible = FALSE; break; case S_KEY_DEFAULT: reset_key(); break; case S_KEY_TOP: if (vpos_set) int_warn(c_token, vpos_warn); key->vpos = JUST_TOP; vpos_set = TRUE; break; case S_KEY_BOTTOM: if (vpos_set) int_warn(c_token, vpos_warn); key->vpos = JUST_BOT; vpos_set = TRUE; break; case S_KEY_LEFT: if (hpos_set) int_warn(c_token, hpos_warn); key->hpos = LEFT; hpos_set = TRUE; break; case S_KEY_RIGHT: if (hpos_set) int_warn(c_token, hpos_warn); key->hpos = RIGHT; hpos_set = TRUE; break; case S_KEY_CENTER: if (!vpos_set) key->vpos = JUST_CENTRE; if (!hpos_set) key->hpos = CENTRE; if (vpos_set || hpos_set) vpos_set = hpos_set = TRUE; break; case S_KEY_VERTICAL: if (sdir_set) int_warn(c_token, sdir_warn); key->stack_dir = GPKEY_VERTICAL; sdir_set = TRUE; break; case S_KEY_HORIZONTAL: if (sdir_set) int_warn(c_token, sdir_warn); key->stack_dir = GPKEY_HORIZONTAL; sdir_set = TRUE; break; case S_KEY_OVER: if (reg_set) int_warn(c_token, reg_warn); /* Fall through */ case S_KEY_ABOVE: if (!hpos_set) key->hpos = CENTRE; if (!sdir_set) key->stack_dir = GPKEY_HORIZONTAL; key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_TMARGIN; reg_set = TRUE; break; case S_KEY_UNDER: if (reg_set) int_warn(c_token, reg_warn); /* Fall through */ case S_KEY_BELOW: if (!hpos_set) key->hpos = CENTRE; if (!sdir_set) key->stack_dir = GPKEY_HORIZONTAL; key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_BMARGIN; reg_set = TRUE; break; case S_KEY_INSIDE: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_INTERIOR_LRTBC; key->fixed = FALSE; reg_set = TRUE; break; case S_KEY_OUTSIDE: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_EXTERIOR_LRTBC; reg_set = TRUE; break; case S_KEY_FIXED: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_INTERIOR_LRTBC; key->fixed = TRUE; reg_set = TRUE; break; case S_KEY_TMARGIN: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_TMARGIN; reg_set = TRUE; break; case S_KEY_BMARGIN: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_BMARGIN; reg_set = TRUE; break; case S_KEY_LMARGIN: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_LMARGIN; reg_set = TRUE; break; case S_KEY_RMARGIN: if (reg_set) int_warn(c_token, reg_warn); key->region = GPKEY_AUTO_EXTERIOR_MARGIN; key->margin = GPKEY_RMARGIN; reg_set = TRUE; break; case S_KEY_LLEFT: key->just = GPKEY_LEFT; break; case S_KEY_RRIGHT: key->just = GPKEY_RIGHT; break; case S_KEY_REVERSE: key->reverse = TRUE; break; case S_KEY_NOREVERSE: key->reverse = FALSE; break; case S_KEY_INVERT: key->invert = TRUE; break; case S_KEY_NOINVERT: key->invert = FALSE; break; case S_KEY_ENHANCED: key->enhanced = TRUE; break; case S_KEY_NOENHANCED: key->enhanced = FALSE; break; case S_KEY_BOX: c_token++; key->box.l_type = LT_BLACK; if (!END_OF_COMMAND) { int old_token = c_token; lp_parse(&key->box, LP_ADHOC, FALSE); if (old_token == c_token && isanumber(c_token)) { key->box.l_type = int_expression() - 1; c_token++; } } c_token--; /* is incremented after loop */ break; case S_KEY_NOBOX: key->box.l_type = LT_NODRAW; break; case S_KEY_SAMPLEN: c_token++; key->swidth = real_expression(); c_token--; /* it is incremented after loop */ break; case S_KEY_SPACING: c_token++; key->vert_factor = real_expression(); if (key->vert_factor < 0.0) key->vert_factor = 0.0; c_token--; /* it is incremented after loop */ break; case S_KEY_WIDTH: c_token++; key->width_fix = real_expression(); c_token--; /* it is incremented after loop */ break; case S_KEY_HEIGHT: c_token++; key->height_fix = real_expression(); c_token--; /* it is incremented after loop */ break; case S_KEY_AUTOTITLES: if (almost_equals(++c_token, "col$umnheader")) key->auto_titles = COLUMNHEAD_KEYTITLES; else { key->auto_titles = FILENAME_KEYTITLES; c_token--; } break; case S_KEY_NOAUTOTITLES: key->auto_titles = NOAUTO_KEYTITLES; break; case S_KEY_TITLE: S_KEYTITLE: key->title.pos = CENTRE; set_xyzlabel( &key->title ); c_token--; break; case S_KEY_NOTITLE: free(key->title.text); key->title.text = NULL; break; case S_KEY_FONT: c_token++; /* Make sure they've specified a font */ if (!isstringvalue(c_token)) int_error(c_token,"expected font"); else { char *tmp = try_to_get_string(); if (tmp) { free(key->font); key->font = tmp; } c_token--; } break; case S_KEY_TEXTCOLOR: { struct t_colorspec lcolor = DEFAULT_COLORSPEC; parse_colorspec(&lcolor, TC_VARIABLE); /* Only for backwards compatibility */ if (lcolor.type == TC_RGB && lcolor.value == -1.0) lcolor.type = TC_VARIABLE; key->textcolor = lcolor; } c_token--; break; case S_KEY_MAXCOLS: c_token++; if (END_OF_COMMAND || almost_equals(c_token, "a$utomatic")) key->maxcols = 0; else key->maxcols = int_expression(); if (key->maxcols < 0) key->maxcols = 0; c_token--; /* it is incremented after loop */ break; case S_KEY_MAXROWS: c_token++; if (END_OF_COMMAND || almost_equals(c_token, "a$utomatic")) key->maxrows = 0; else key->maxrows = int_expression(); if (key->maxrows < 0) key->maxrows = 0; c_token--; /* it is incremented after loop */ break; case S_KEY_FRONT: key->front = TRUE; break; case S_KEY_NOFRONT: key->front = FALSE; break; case S_KEY_MANUAL: c_token++; if (reg_set) int_warn(c_token, reg_warn); get_position(&key->user_pos); key->region = GPKEY_USER_PLACEMENT; reg_set = TRUE; c_token--; /* will be incremented again soon */ break; case S_KEY_INVALID: default: int_error(c_token, "unknown key option"); break; } c_token++; } if (key->region == GPKEY_AUTO_EXTERIOR_LRTBC) set_key_position_from_stack_direction(key); else if (key->region == GPKEY_AUTO_EXTERIOR_MARGIN) { if (vpos_set && (key->margin == GPKEY_TMARGIN || key->margin == GPKEY_BMARGIN)) int_warn(NO_CARET, "ignoring top/center/bottom; incompatible with tmargin/bmargin."); else if (hpos_set && (key->margin == GPKEY_LMARGIN || key->margin == GPKEY_RMARGIN)) int_warn(NO_CARET, "ignoring left/center/right; incompatible with lmargin/tmargin."); } } /* process 'set label' command */ /* set label {tag} {"label_text"{,{,...}}} {