[BACK]Return to set.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/set.c, Revision 1.1.1.1

1.1       maekawa     1: #ifndef lint
                      2: static char *RCSid = "$Id: set.c,v 1.68 1998/06/22 12:24:54 ddenholm Exp $";
                      3: #endif
                      4:
                      5: /* GNUPLOT - set.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37:
                     38: /*
                     39:  * 19 September 1992  Lawrence Crowl  (crowl@cs.orst.edu)
                     40:  * Added user-specified bases for log scaling.
                     41:  */
                     42:
                     43: #include "plot.h"
                     44: #include "stdfn.h"
                     45: #include "setshow.h"
                     46: #include "national.h"
                     47:
                     48: #define DEF_FORMAT   "%g"      /* default format for tic mark labels */
                     49: #define SIGNIF (0.01)          /* less than one hundredth of a tic mark */
                     50:
                     51: /*
                     52:  * global variables to hold status of 'set' options
                     53:  *
                     54:  * IMPORTANT NOTE:
                     55:  * ===============
                     56:  * If you change the default values of one of the variables below, or if
                     57:  * you add another global variable, make sure that the change you make is
                     58:  * done in reset_command() as well (if that makes sense).
                     59:  */
                     60:
                     61: TBOOLEAN autoscale_r = DTRUE;
                     62: TBOOLEAN autoscale_t = DTRUE;
                     63: TBOOLEAN autoscale_u = DTRUE;
                     64: TBOOLEAN autoscale_v = DTRUE;
                     65: TBOOLEAN autoscale_x = DTRUE;
                     66: TBOOLEAN autoscale_y = DTRUE;
                     67: TBOOLEAN autoscale_z = DTRUE;
                     68: TBOOLEAN autoscale_x2 = DTRUE;
                     69: TBOOLEAN autoscale_y2 = DTRUE;
                     70: TBOOLEAN autoscale_lt = DTRUE;
                     71: TBOOLEAN autoscale_lu = DTRUE;
                     72: TBOOLEAN autoscale_lv = DTRUE;
                     73: TBOOLEAN autoscale_lx = DTRUE;
                     74: TBOOLEAN autoscale_ly = DTRUE;
                     75: TBOOLEAN autoscale_lz = DTRUE;
                     76: TBOOLEAN multiplot = FALSE;
                     77:
                     78: double boxwidth = -1.0;                /* box width (automatic) */
                     79: TBOOLEAN clip_points = FALSE;
                     80: TBOOLEAN clip_lines1 = TRUE;
                     81: TBOOLEAN clip_lines2 = FALSE;
                     82: struct lp_style_type border_lp = { 0, -2, 0, 1.0, 1.0 };
                     83: int draw_border = 31;
                     84: TBOOLEAN draw_surface = TRUE;
                     85: char dummy_var[MAX_NUM_VAR][MAX_ID_LEN+1] = { "x", "y" };
                     86: char default_font[MAX_ID_LEN+1] = "";  /* Entry font added by DJL */
                     87: char xformat[MAX_ID_LEN+1] = DEF_FORMAT;
                     88: char yformat[MAX_ID_LEN+1] = DEF_FORMAT;
                     89: char zformat[MAX_ID_LEN+1] = DEF_FORMAT;
                     90: char x2format[MAX_ID_LEN+1] = DEF_FORMAT;
                     91: char y2format[MAX_ID_LEN+1] = DEF_FORMAT;
                     92:
                     93: /* do formats look like times - use FIRST_X_AXIS etc as index
                     94:  * - never saved or shown ...
                     95:  */
                     96: #if AXIS_ARRAY_SIZE != 10
                     97: # error error in initialiser for format_is_numeric
                     98: #endif
                     99:
                    100: int format_is_numeric[AXIS_ARRAY_SIZE] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
                    101:
                    102: enum PLOT_STYLE data_style = POINTSTYLE;
                    103: enum PLOT_STYLE func_style = LINES;
                    104: double bar_size = 1.0;
                    105: struct lp_style_type work_grid = { 0, GRID_OFF, 0, 1.0, 1.0 };
                    106: struct lp_style_type grid_lp   = { 0, -1, 0, 1.0, 1.0 };
                    107: struct lp_style_type mgrid_lp  = { 0, -1, 0, 1.0, 1.0 };
                    108: double polar_grid_angle = 0;   /* nonzero means a polar grid */
                    109: int key = -1;                  /* default position */
                    110: struct position key_user_pos;  /* user specified position for key */
                    111: TBOOLEAN key_reverse = FALSE;  /* reverse text & sample ? */
                    112: struct lp_style_type key_box = { 0, -3, 0, 1.0, 1.0 };         /* -3 = no linetype */
                    113: double key_swidth = 4.0;
                    114: double key_vert_factor = 1.0;
                    115: double key_width_fix = 0.0;
                    116: TBOOLEAN is_log_x = FALSE;
                    117: TBOOLEAN is_log_y = FALSE;
                    118: TBOOLEAN is_log_z = FALSE;
                    119: TBOOLEAN is_log_x2 = FALSE;
                    120: TBOOLEAN is_log_y2 = FALSE;
                    121: double base_log_x = 0.0;
                    122: double base_log_y = 0.0;
                    123: double base_log_z = 0.0;
                    124: double base_log_x2 = 0.0;
                    125: double base_log_y2 = 0.0;
                    126: double log_base_log_x = 0.0;
                    127: double log_base_log_y = 0.0;
                    128: double log_base_log_z = 0.0;
                    129: double log_base_log_x2 = 0.0;
                    130: double log_base_log_y2 = 0.0;
                    131: FILE *gpoutfile;
                    132: char *outstr = NULL;           /* means "STDOUT" */
                    133: TBOOLEAN parametric = FALSE;
                    134: double pointsize = 1.0;
                    135: int encoding;
                    136: char *encoding_names[] = { "default", "iso_8859_1", "cp437", "cp850", NULL };
                    137: TBOOLEAN polar = FALSE;
                    138: TBOOLEAN hidden3d = FALSE;
                    139: TBOOLEAN label_contours = TRUE;        /* different linestyles are used for contours when set */
                    140: char contour_format[32] = "%8.3g";     /* format for contour key entries */
                    141: int angles_format = ANGLES_RADIANS;
                    142: double ang2rad = 1.0;          /* 1 or pi/180, tracking angles_format */
                    143: int mapping3d = MAP3D_CARTESIAN;
                    144: int samples = SAMPLES;         /* samples is always equal to samples_1 */
                    145: int samples_1 = SAMPLES;
                    146: int samples_2 = SAMPLES;
                    147: int iso_samples_1 = ISO_SAMPLES;
                    148: int iso_samples_2 = ISO_SAMPLES;
                    149: float xsize = 1.0;             /* scale factor for size */
                    150: float ysize = 1.0;             /* scale factor for size */
                    151: float zsize = 1.0;             /* scale factor for size */
                    152: float xoffset = 0.0;           /* x origin */
                    153: float yoffset = 0.0;           /* y origin */
                    154: float aspect_ratio = 0.0;      /* don't attempt to force it */
                    155: float surface_rot_z = 30.0;    /* Default 3d transform. */
                    156: float surface_rot_x = 60.0;
                    157: float surface_scale = 1.0;
                    158: float surface_zscale = 1.0;
                    159: struct termentry *term = NULL; /* unknown */
                    160: char term_options[MAX_LINE_LEN+1] = "";
                    161: label_struct title = { "", 0.0, 0.0, "" };
                    162: label_struct timelabel = { "", 0.0, 0.0, "" };
                    163: label_struct xlabel = { "", 0.0, 0.0, "" };
                    164: label_struct ylabel = { "", 0.0, 0.0, "" };
                    165: label_struct zlabel = { "", 0.0, 0.0, "" };
                    166: label_struct x2label = { "", 0.0, 0.0, "" };
                    167: label_struct y2label = { "", 0.0, 0.0, "" };
                    168:
                    169: int timelabel_rotate = FALSE;
                    170: int timelabel_bottom = TRUE;
                    171: char key_title[MAX_LINE_LEN+1] = "";
                    172: double rmin = -0.0;
                    173: double rmax = 10.0;
                    174: double tmin = -5.0;
                    175: double tmax = 5.0;
                    176: double umin = -5.0;
                    177: double umax = 5.0;
                    178: double vmin = -5.0;
                    179: double vmax = 5.0;
                    180: double xmin = -10.0;
                    181: double xmax = 10.0;
                    182: double ymin = -10.0;
                    183: double ymax = 10.0;
                    184: double zmin = -10.0;
                    185: double zmax = 10.0;
                    186: double x2min = -10.0;
                    187: double x2max = 10.0;
                    188: double y2min = -10.0;
                    189: double y2max = 10.0;
                    190: double loff = 0.0;
                    191: double roff = 0.0;
                    192: double toff = 0.0;
                    193: double boff = 0.0;
                    194: int draw_contour = CONTOUR_NONE;
                    195: int contour_pts = 5;
                    196: int contour_kind = CONTOUR_KIND_LINEAR;
                    197: int contour_order = 4;
                    198: int contour_levels = 5;
                    199: double zero = ZERO;            /* zero threshold, not 0! */
                    200: int levels_kind = LEVELS_AUTO;
                    201: double levels_list[MAX_DISCRETE_LEVELS];       /* storage for z levels to draw contours at */
                    202:
                    203: int dgrid3d_row_fineness = 10;
                    204: int dgrid3d_col_fineness = 10;
                    205: int dgrid3d_norm_value = 1;
                    206: TBOOLEAN dgrid3d = FALSE;
                    207:
                    208: struct lp_style_type xzeroaxis = { 0, -3, 0, 1.0, 1.0 };
                    209: struct lp_style_type yzeroaxis = { 0, -3, 0, 1.0, 1.0 };
                    210: struct lp_style_type x2zeroaxis = { 0, -3, 0, 1.0, 1.0 };
                    211: struct lp_style_type y2zeroaxis = { 0, -3, 0, 1.0, 1.0 };
                    212:
                    213: /* perhaps make these into an array one day */
                    214:
                    215: int xtics = TICS_ON_BORDER | TICS_MIRROR;
                    216: int ytics = TICS_ON_BORDER | TICS_MIRROR;
                    217: int ztics = TICS_ON_BORDER;    /* no mirror by default for ztics */
                    218: int x2tics = NO_TICS;
                    219: int y2tics = NO_TICS;
                    220:
                    221: TBOOLEAN rotate_xtics = FALSE;
                    222: TBOOLEAN rotate_ytics = FALSE;
                    223: TBOOLEAN rotate_ztics = FALSE;
                    224: TBOOLEAN rotate_x2tics = FALSE;
                    225: TBOOLEAN rotate_y2tics = FALSE;
                    226:
                    227: int range_flags[AXIS_ARRAY_SIZE];      /* = {0,0,...} */
                    228:
                    229: int mxtics = MINI_DEFAULT;
                    230: int mytics = MINI_DEFAULT;
                    231: int mztics = MINI_DEFAULT;
                    232: int mx2tics = MINI_DEFAULT;
                    233: int my2tics = MINI_DEFAULT;
                    234:
                    235: double mxtfreq = 10;           /* # intervals between major */
                    236: double mytfreq = 10;           /* tic marks */
                    237: double mztfreq = 10;
                    238: double mx2tfreq = 10;
                    239: double my2tfreq = 10;
                    240:
                    241: double ticscale = 1.0;         /* scale factor for tic mark */
                    242: double miniticscale = 0.5;     /* and for minitics */
                    243:
                    244: float ticslevel = 0.5;
                    245:
                    246: struct ticdef xticdef = { TIC_COMPUTED };
                    247: struct ticdef yticdef = { TIC_COMPUTED };
                    248: struct ticdef zticdef = { TIC_COMPUTED };
                    249: struct ticdef x2ticdef = { TIC_COMPUTED };
                    250: struct ticdef y2ticdef = { TIC_COMPUTED };
                    251:
                    252: TBOOLEAN tic_in = TRUE;
                    253:
                    254: struct text_label *first_label = NULL;
                    255: struct arrow_def *first_arrow = NULL;
                    256: struct linestyle_def *first_linestyle = NULL;
                    257:
                    258: int lmargin = -1;              /* space between left edge and xleft in chars (-1: computed) */
                    259: int bmargin = -1;              /* space between bottom and ybot in chars (-1: computed) */
                    260: int rmargin = -1;              /* space between right egde and xright in chars (-1: computed) */
                    261: int tmargin = -1;              /* space between top egde and ytop in chars (-1: computed) */
                    262:
                    263: /* string representing missing values in ascii datafiles */
                    264: char *missing_val = NULL;
                    265:
                    266: /* date&time language conversions */
                    267:                                 /* extern struct dtconv *dtc; *//* HBB 980317: unused and not defined anywhere !? */
                    268:
                    269: /*** other things we need *****/
                    270:
                    271: /* input data, parsing variables */
                    272:
                    273: extern TBOOLEAN is_3d_plot;
                    274:
                    275: /* From plot2d.c */
                    276: extern struct curve_points *first_plot;
                    277: /* From plot3d.c */
                    278: extern struct surface_points *first_3dplot;
                    279:
                    280: int key_hpos = TRIGHT;         /* place for curve-labels, corner or outside */
                    281: int key_vpos = TTOP;           /* place for curve-labels, corner or below */
                    282: int key_just = JRIGHT;         /* alignment of key labels, left or right */
                    283:
                    284: #ifndef TIMEFMT
                    285: #define TIMEFMT "%d/%m/%y\n%H:%M"
                    286: #endif
                    287: /* format for date/time for reading time in datafile */
                    288: char timefmt[25] = TIMEFMT;
                    289:
                    290: /* array of datatypes (x in 0,y in 1,z in 2,..(rtuv)) */
                    291: /* not sure how rtuv come into it ?
                    292:  * oh well, make first six compatible with FIRST_X_AXIS, etc
                    293:  */
                    294: int datatype[DATATYPE_ARRAY_SIZE];
                    295:
                    296: char cur_locale[MAX_ID_LEN+1] = "C";
                    297:
                    298: /* not set or shown directly, but controlled by 'set locale'
                    299:  * defined in national.h
                    300:  */
                    301:
                    302: char full_month_names[12][32] =
                    303: { FMON01, FMON02, FMON03, FMON04, FMON05, FMON06, FMON07, FMON08, FMON09, FMON10, FMON11, FMON12 };
                    304: char abbrev_month_names[12][8] =
                    305: { AMON01, AMON02, AMON03, AMON04, AMON05, AMON06, AMON07, AMON08, AMON09, AMON10, AMON11, AMON12 };
                    306:
                    307: char full_day_names[7][32] =
                    308: { FDAY0, FDAY1, FDAY2, FDAY3, FDAY4, FDAY5, FDAY6 };
                    309: char abbrev_day_names[7][8] =
                    310: { ADAY0, ADAY1, ADAY2, ADAY3, ADAY4, ADAY5, ADAY6 };
                    311:
                    312:
                    313:
                    314: /******** Local functions ********/
                    315: static void get_position __PROTO((struct position * pos));
                    316: static void get_position_type __PROTO((enum position_type * type, int *axes));
                    317: static void set_xyzlabel __PROTO((label_struct * label));
                    318: static void set_label __PROTO((void));
                    319: static void set_nolabel __PROTO((void));
                    320: static void set_arrow __PROTO((void));
                    321: static void set_noarrow __PROTO((void));
                    322: static void load_tics __PROTO((int axis, struct ticdef * tdef));
                    323: static void load_tic_user __PROTO((int axis, struct ticdef * tdef));
                    324: static void free_marklist __PROTO((struct ticmark * list));
                    325: static void load_tic_series __PROTO((int axis, struct ticdef * tdef));
                    326: static void load_offsets __PROTO((double *a, double *b, double *c, double *d));
                    327: static void delete_label __PROTO((struct text_label * prev, struct text_label * this));
                    328: static int assign_label_tag __PROTO((void));
                    329: static void delete_arrow __PROTO((struct arrow_def * prev, struct arrow_def * this));
                    330: static int assign_arrow_tag __PROTO((void));
                    331: static void set_linestyle __PROTO((void));
                    332: static void set_nolinestyle __PROTO((void));
                    333: static int assign_linestyle_tag __PROTO((void));
                    334: static void delete_linestyle __PROTO((struct linestyle_def * prev, struct linestyle_def * this));
                    335: static TBOOLEAN set_one __PROTO((void));
                    336: static TBOOLEAN set_two __PROTO((void));
                    337: static TBOOLEAN set_three __PROTO((void));
                    338: static int looks_like_numeric __PROTO((char *));
                    339: static void set_lp_properties __PROTO((struct lp_style_type * arg, int allow_points, int lt, int pt, double lw, double ps));
                    340: static void reset_lp_properties __PROTO((struct lp_style_type *arg));
                    341: static void set_locale __PROTO((char *));
                    342:
                    343: static int set_tic_prop __PROTO((int *TICS, int *MTICS, double *FREQ,
                    344:      struct ticdef * tdef, int AXIS, TBOOLEAN * ROTATE, char *tic_side));
                    345:
                    346:
                    347: /* following code segment appears over and over again */
                    348: #define GET_NUM_OR_TIME(store,axis) \
                    349: do{if ( datatype[axis] == TIME && isstring(c_token) ) { \
                    350:     char ss[80]; struct tm tm; \
                    351:     quote_str(ss,c_token, 80); ++c_token; \
                    352:     if (gstrptime(ss,timefmt,&tm)) store = (double) gtimegm(&tm); else store = 0;\
                    353:    } else {\
                    354:     struct value value; \
                    355:     store = real(const_express(&value));\
                    356:   }}while(0)
                    357:
                    358: /******** The 'reset' command ********/
                    359: void reset_command()
                    360: {
                    361:     register struct curve_points *f_p = first_plot;
                    362:     register struct surface_points *f_3dp = first_3dplot;
                    363:
                    364:     c_token++;
                    365:     first_plot = NULL;
                    366:     first_3dplot = NULL;
                    367:     cp_free(f_p);
                    368:     sp_free(f_3dp);
                    369:     /* delete arrows */
                    370:     while (first_arrow != NULL)
                    371:        delete_arrow((struct arrow_def *) NULL, first_arrow);
                    372:     /* delete labels */
                    373:     while (first_label != NULL)
                    374:        delete_label((struct text_label *) NULL, first_label);
                    375:     /* delete linestyles */
                    376:     while (first_linestyle != NULL)
                    377:        delete_linestyle((struct linestyle_def *) NULL, first_linestyle);
                    378:     strcpy(dummy_var[0], "x");
                    379:     strcpy(dummy_var[1], "y");
                    380:     strcpy(title.text, "");
                    381:     strcpy(xlabel.text, "");
                    382:     strcpy(ylabel.text, "");
                    383:     strcpy(zlabel.text, "");
                    384:     strcpy(x2label.text, "");
                    385:     strcpy(y2label.text, "");
                    386:     *title.font = 0;
                    387:     *xlabel.font = 0;
                    388:     *ylabel.font = 0;
                    389:     *zlabel.font = 0;
                    390:     *x2label.font = 0;
                    391:     *y2label.font = 0;
                    392:     strcpy(key_title, "");
                    393:     strcpy(timefmt, TIMEFMT);
                    394:     strcpy(xformat, DEF_FORMAT);
                    395:     strcpy(yformat, DEF_FORMAT);
                    396:     strcpy(zformat, DEF_FORMAT);
                    397:     strcpy(x2format, DEF_FORMAT);
                    398:     strcpy(y2format, DEF_FORMAT);
                    399:     format_is_numeric[FIRST_X_AXIS] = format_is_numeric[SECOND_X_AXIS] = 1;
                    400:     format_is_numeric[FIRST_Y_AXIS] = format_is_numeric[SECOND_Y_AXIS] = 1;
                    401:     format_is_numeric[FIRST_Z_AXIS] = format_is_numeric[SECOND_Z_AXIS] = 1;
                    402:     autoscale_r = DTRUE;
                    403:     autoscale_t = DTRUE;
                    404:     autoscale_u = DTRUE;
                    405:     autoscale_v = DTRUE;
                    406:     autoscale_x = DTRUE;
                    407:     autoscale_y = DTRUE;
                    408:     autoscale_z = DTRUE;
                    409:     autoscale_x2 = DTRUE;
                    410:     autoscale_y2 = DTRUE;
                    411:     autoscale_lt = DTRUE;
                    412:     autoscale_lu = DTRUE;
                    413:     autoscale_lv = DTRUE;
                    414:     autoscale_lx = DTRUE;
                    415:     autoscale_ly = DTRUE;
                    416:     autoscale_lz = DTRUE;
                    417:     boxwidth = -1.0;
                    418:     clip_points = FALSE;
                    419:     clip_lines1 = TRUE;
                    420:     clip_lines2 = FALSE;
                    421:     set_lp_properties(&border_lp, 0, -2, 0, 1.0, 1.0);
                    422:     draw_border = 31;
                    423:     draw_surface = TRUE;
                    424:     data_style = POINTSTYLE;
                    425:     func_style = LINES;
                    426:     bar_size = 1.0;
                    427:     set_lp_properties(&work_grid, 0, GRID_OFF, 0, 0.5, 1.0);
                    428:     set_lp_properties(&grid_lp, 0, -1, 0, 0.5, 1.0);
                    429:     set_lp_properties(&mgrid_lp, 0, -1, 0, 0.5, 1.0);
                    430:     polar_grid_angle = 0;
                    431:     key = -1;
                    432:     is_log_x = FALSE;
                    433:     is_log_y = FALSE;
                    434:     is_log_z = FALSE;
                    435:     is_log_x2 = FALSE;
                    436:     is_log_y2 = FALSE;
                    437:     base_log_x = 0.0;
                    438:     base_log_y = 0.0;
                    439:     base_log_z = 0.0;
                    440:     base_log_x2 = 0.0;
                    441:     base_log_y2 = 0.0;
                    442:     log_base_log_x = 0.0;
                    443:     log_base_log_y = 0.0;
                    444:     log_base_log_z = 0.0;
                    445:     log_base_log_x2 = 0.0;
                    446:     log_base_log_y2 = 0.0;
                    447:     parametric = FALSE;
                    448:     polar = FALSE;
                    449:     hidden3d = FALSE;
                    450:     label_contours = TRUE;
                    451:     strcpy(contour_format, "%8.3g");
                    452:     angles_format = ANGLES_RADIANS;
                    453:     ang2rad = 1.0;
                    454:     mapping3d = MAP3D_CARTESIAN;
                    455:     samples = SAMPLES;
                    456:     samples_1 = SAMPLES;
                    457:     samples_2 = SAMPLES;
                    458:     iso_samples_1 = ISO_SAMPLES;
                    459:     iso_samples_2 = ISO_SAMPLES;
                    460:     xsize = 1.0;
                    461:     ysize = 1.0;
                    462:     zsize = 1.0;
                    463:     xoffset = 0.0;
                    464:     yoffset = 0.0;
                    465:     aspect_ratio = 0.0;                /* dont force it */
                    466:     surface_rot_z = 30.0;
                    467:     surface_rot_x = 60.0;
                    468:     surface_scale = 1.0;
                    469:     surface_zscale = 1.0;
                    470:     *timelabel.text = 0;
                    471:     timelabel.xoffset = 0;
                    472:     timelabel.yoffset = 0;
                    473:     *timelabel.font = 0;
                    474:     timelabel_rotate = FALSE;
                    475:     timelabel_bottom = TRUE;
                    476:     title.xoffset = 0;
                    477:     title.yoffset = 0;
                    478:     xlabel.xoffset = 0;
                    479:     xlabel.yoffset = 0;
                    480:     ylabel.xoffset = 0;
                    481:     ylabel.yoffset = 0;
                    482:     zlabel.xoffset = 0;
                    483:     zlabel.yoffset = 0;
                    484:     x2label.xoffset = 0;
                    485:     x2label.yoffset = 0;
                    486:     y2label.xoffset = 0;
                    487:     y2label.yoffset = 0;
                    488:     rmin = -0.0;
                    489:     rmax = 10.0;
                    490:     tmin = -5.0;
                    491:     tmax = 5.0;
                    492:     umin = -5.0;
                    493:     umax = 5.0;
                    494:     vmin = -5.0;
                    495:     vmax = 5.0;
                    496:     xmin = -10.0;
                    497:     xmax = 10.0;
                    498:     ymin = -10.0;
                    499:     ymax = 10.0;
                    500:     zmin = -10.0;
                    501:     zmax = 10.0;
                    502:     x2min = -10.0;
                    503:     x2max = 10.0;
                    504:     y2min = -10.0;
                    505:     y2max = 10.0;
                    506:     memset(range_flags, 0, sizeof(range_flags));       /* all = 0 */
                    507:
                    508:     loff = 0.0;
                    509:     roff = 0.0;
                    510:     toff = 0.0;
                    511:     boff = 0.0;
                    512:     draw_contour = CONTOUR_NONE;
                    513:     contour_pts = 5;
                    514:     contour_kind = CONTOUR_KIND_LINEAR;
                    515:     contour_order = 4;
                    516:     contour_levels = 5;
                    517:     zero = ZERO;
                    518:     levels_kind = LEVELS_AUTO;
                    519:     dgrid3d_row_fineness = 10;
                    520:     dgrid3d_col_fineness = 10;
                    521:     dgrid3d_norm_value = 1;
                    522:     dgrid3d = FALSE;
                    523:     set_lp_properties(&xzeroaxis, 0, -3, 0, 1.0, 1.0);
                    524:     set_lp_properties(&yzeroaxis, 0, -3, 0, 1.0, 1.0);
                    525:     set_lp_properties(&x2zeroaxis, 0, -3, 0, 1.0, 1.0);
                    526:     set_lp_properties(&y2zeroaxis, 0, -3, 0, 1.0, 1.0);
                    527:     xtics =
                    528:        ytics = TICS_ON_BORDER | TICS_MIRROR;
                    529:     ztics = TICS_ON_BORDER;    /* no mirror by default */
                    530:     x2tics = NO_TICS;
                    531:     y2tics = NO_TICS;
                    532:     mxtics =
                    533:        mytics =
                    534:        mztics =
                    535:        mx2tics =
                    536:        my2tics = MINI_DEFAULT;
                    537:     mxtfreq = 10.0;
                    538:     mytfreq = 10.0;
                    539:     mztfreq = 10.0;
                    540:     mx2tfreq = 10.0;
                    541:     my2tfreq = 10.0;
                    542:     ticscale = 1.0;
                    543:     miniticscale = 0.5;
                    544:     ticslevel = 0.5;
                    545:     xticdef.type = TIC_COMPUTED;
                    546:     yticdef.type = TIC_COMPUTED;
                    547:     zticdef.type = TIC_COMPUTED;
                    548:     x2ticdef.type = TIC_COMPUTED;
                    549:     y2ticdef.type = TIC_COMPUTED;
                    550:     tic_in = TRUE;
                    551:     lmargin =
                    552:        bmargin =
                    553:        rmargin =
                    554:        tmargin = -1;           /* autocomputed */
                    555:     key_hpos = TRIGHT;
                    556:     key_vpos = TTOP;
                    557:     key_just = JRIGHT;
                    558:     key_reverse = FALSE;
                    559:     set_lp_properties(&key_box, 0, -3, 0, 1.0, 1.0);
                    560:     key_swidth = 4;
                    561:     key_vert_factor = 1;
                    562:     key_width_fix = 0;
                    563:     datatype[FIRST_X_AXIS] = FALSE;
                    564:     datatype[FIRST_Y_AXIS] = FALSE;
                    565:     datatype[FIRST_Z_AXIS] = FALSE;
                    566:     datatype[SECOND_X_AXIS] = FALSE;
                    567:     datatype[SECOND_Y_AXIS] = FALSE;
                    568:     datatype[SECOND_Z_AXIS] = FALSE;
                    569:     datatype[R_AXIS] = FALSE;
                    570:     datatype[T_AXIS] = FALSE;
                    571:     datatype[U_AXIS] = FALSE;
                    572:     datatype[V_AXIS] = FALSE;
                    573:
                    574:     pointsize = 1.0;
                    575:     encoding = ENCODING_DEFAULT;
                    576:
                    577:     set_locale("C");           /* default */
                    578: }
                    579:
                    580: /******** The 'set' command ********/
                    581: void set_command()
                    582: {
                    583:     static char GPFAR setmess[] = "\
                    584: valid set options:  [] = choose one, {} means optional\n\n\
                    585: \t'angles',  '{no}arrow',  '{no}autoscale',  'bars',  '{no}border',\n\
                    586: \t'boxwidth', '{no}clabel', '{no}clip', 'cntrparam', '{no}contour',\n\
                    587: \t'data style',  '{no}dgrid3d',  'dummy',  'encoding',  'format',\n\
                    588: \t'function style',   '{no}grid',   '{no}hidden3d',   'isosamples',\n\
                    589: \t'{no}key', '{no}label', '{no}linestyle', 'locale', '{no}logscale',\n\
                    590: \t'[blrt]margin', 'mapping', 'missing', '{no}multiplot', 'offsets',\n\
                    591: \t'origin', 'output', '{no}parametric', 'pointsize', '{no}polar',\n\
                    592: \t'[rtuv]range',  'samples',  'size',  '{no}surface',  'terminal',\n\
                    593: \t'tics',  'ticscale',  'ticslevel',  '{no}timestamp',  'timefmt',\n\
                    594: \t'title', 'view', '[xyz]{2}data', '[xyz]{2}label', '[xyz]{2}range',\n\
                    595: \t'{no}{m}[xyz]{2}tics', '[xyz]{2}[md]tics', '{no}{[xyz]{2}}zeroaxis',\n\
                    596: \t'zero'";
                    597:
                    598:     c_token++;
                    599:
                    600:     if (!set_one() && !set_two() && !set_three())
                    601:        int_error(setmess, c_token);
                    602: }
                    603:
                    604: /* return TRUE if a command match, FALSE if not */
                    605: static TBOOLEAN
                    606: set_one()
                    607: {
                    608: /* save on replication with a macro */
                    609: #define PROCESS_AUTO_LETTER(AUTO, STRING,MIN,MAX) \
                    610: else if (equals(c_token, STRING))       { AUTO = DTRUE; ++c_token; } \
                    611: else if (almost_equals(c_token, MIN)) { AUTO |= 1;    ++c_token; } \
                    612: else if (almost_equals(c_token, MAX)) { AUTO |= 2;    ++c_token; }
                    613:
                    614:     if (almost_equals(c_token, "ar$row")) {
                    615:        c_token++;
                    616:        set_arrow();
                    617:     } else if (almost_equals(c_token, "noar$row")) {
                    618:        c_token++;
                    619:        set_noarrow();
                    620:     } else if (almost_equals(c_token, "au$toscale")) {
                    621:        c_token++;
                    622:        if (END_OF_COMMAND) {
                    623:            autoscale_r = autoscale_t = autoscale_x = autoscale_y = autoscale_z = autoscale_x2 = autoscale_y2 = DTRUE;
                    624:        } else if (equals(c_token, "xy") || equals(c_token, "yx")) {
                    625:            autoscale_x = autoscale_y = DTRUE;
                    626:            c_token++;
                    627:        }
                    628:        PROCESS_AUTO_LETTER(autoscale_r, "r", "rmi$n", "rma$x")
                    629:        PROCESS_AUTO_LETTER(autoscale_t, "t", "tmi$n", "tma$x")
                    630:        PROCESS_AUTO_LETTER(autoscale_u, "u", "umi$n", "uma$x")
                    631:        PROCESS_AUTO_LETTER(autoscale_v, "v", "vmi$n", "vma$x")
                    632:        PROCESS_AUTO_LETTER(autoscale_x, "x", "xmi$n", "xma$x")
                    633:        PROCESS_AUTO_LETTER(autoscale_y, "y", "ymi$n", "yma$x")
                    634:        PROCESS_AUTO_LETTER(autoscale_z, "z", "zmi$n", "zma$x")
                    635:        PROCESS_AUTO_LETTER(autoscale_x2, "x2", "x2mi$n", "x2ma$x")
                    636:        PROCESS_AUTO_LETTER(autoscale_y2, "y2", "y2mi$n", "y2ma$x")
                    637:        else
                    638:            int_error("Invalid range", c_token);
                    639:     } else if (almost_equals(c_token,"noau$toscale")) {
                    640:        c_token++;
                    641:        if (END_OF_COMMAND) {
                    642:            autoscale_r = autoscale_t = autoscale_x = autoscale_y = autoscale_z = FALSE;
                    643:        } else if (equals(c_token, "xy") || equals(c_token, "tyx")) {
                    644:            autoscale_x = autoscale_y = FALSE;
                    645:            c_token++;
                    646:        } else if (equals(c_token, "r")) {
                    647:            autoscale_r = FALSE;
                    648:            c_token++;
                    649:        } else if (equals(c_token, "t")) {
                    650:            autoscale_t = FALSE;
                    651:            c_token++;
                    652:        } else if (equals(c_token, "u")) {
                    653:            autoscale_u = FALSE;
                    654:            c_token++;
                    655:        } else if (equals(c_token, "v")) {
                    656:            autoscale_v = FALSE;
                    657:            c_token++;
                    658:        } else if (equals(c_token, "x")) {
                    659:            autoscale_x = FALSE;
                    660:            c_token++;
                    661:        } else if (equals(c_token, "y")) {
                    662:            autoscale_y = FALSE;
                    663:            c_token++;
                    664:        } else if (equals(c_token, "z")) {
                    665:            autoscale_z = FALSE;
                    666:            c_token++;
                    667:        }
                    668:     } else if (almost_equals(c_token,"nobor$der")) {
                    669:        draw_border = 0;
                    670:        c_token++;
                    671:        }
                    672:     else if (almost_equals(c_token,"box$width")) {
                    673:        struct value a;
                    674:        c_token++;
                    675:        if (END_OF_COMMAND)
                    676:            boxwidth = -1.0;
                    677:        else
                    678: /*              if((boxwidth = real(const_express(&a))) != -2.0)*/
                    679: /*                      boxwidth = magnitude(const_express(&a));*/
                    680:            boxwidth = real(const_express(&a));
                    681:     } else if (almost_equals(c_token,"c$lip")) {
                    682:        c_token++;
                    683:        if (END_OF_COMMAND)
                    684:            /* assuming same as points */
                    685:            clip_points = TRUE;
                    686:        else if (almost_equals(c_token, "p$oints"))
                    687:            clip_points = TRUE;
                    688:        else if (almost_equals(c_token, "o$ne"))
                    689:            clip_lines1 = TRUE;
                    690:        else if (almost_equals(c_token, "t$wo"))
                    691:            clip_lines2 = TRUE;
                    692:        else
                    693:            int_error("expecting 'points', 'one', or 'two'", c_token);
                    694:        c_token++;
                    695:     } else if (almost_equals(c_token,"noc$lip")) {
                    696:        c_token++;
                    697:        if (END_OF_COMMAND) {
                    698:            /* same as all three */
                    699:            clip_points = FALSE;
                    700:            clip_lines1 = FALSE;
                    701:            clip_lines2 = FALSE;
                    702:        } else if (almost_equals(c_token, "p$oints"))
                    703:            clip_points = FALSE;
                    704:        else if (almost_equals(c_token, "o$ne"))
                    705:            clip_lines1 = FALSE;
                    706:        else if (almost_equals(c_token, "t$wo"))
                    707:            clip_lines2 = FALSE;
                    708:        else
                    709:            int_error("expecting 'points', 'one', or 'two'", c_token);
                    710:        c_token++;
                    711:     } else if (almost_equals(c_token,"hi$dden3d")) {
                    712: #ifdef LITE
                    713:        printf(" Hidden Line Removal Not Supported in LITE version\n");
                    714:        c_token++;
                    715: #else
                    716:        /* HBB 970618: new parsing engine for hidden3d options */
                    717:        set_hidden3doptions();
                    718:        hidden3d = TRUE;
                    719: #endif /* LITE */
                    720:     } else if (almost_equals(c_token,"nohi$dden3d")) {
                    721: #ifdef LITE
                    722:        printf(" Hidden Line Removal Not Supported in LITE version\n");
                    723: #else
                    724:        hidden3d = FALSE;
                    725: #endif /* LITE */
                    726:        c_token++;
                    727:     } else if (almost_equals(c_token,"cla$bel")) {
                    728:        label_contours = TRUE;
                    729:        c_token++;
                    730:        if (isstring(c_token))
                    731:            quote_str(contour_format, c_token++, 30);
                    732:     } else if (almost_equals(c_token,"nocla$bel")) {
                    733:        label_contours = FALSE;
                    734:        c_token++;
                    735:     } else if (almost_equals(c_token,"ma$pping3d")) {
                    736:        c_token++;
                    737:        if (END_OF_COMMAND)
                    738:            /* assuming same as points */
                    739:            mapping3d = MAP3D_CARTESIAN;
                    740:        else if (almost_equals(c_token, "ca$rtesian"))
                    741:            mapping3d = MAP3D_CARTESIAN;
                    742:        else if (almost_equals(c_token, "s$pherical"))
                    743:            mapping3d = MAP3D_SPHERICAL;
                    744:        else if (almost_equals(c_token, "cy$lindrical"))
                    745:            mapping3d = MAP3D_CYLINDRICAL;
                    746:        else
                    747:            int_error("expecting 'cartesian', 'spherical', or 'cylindrical'", c_token);
                    748:        c_token++;
                    749:     } else if (almost_equals(c_token,"co$ntour")) {
                    750:        c_token++;
                    751:        if (END_OF_COMMAND)
                    752:            /* assuming same as points */
                    753:            draw_contour = CONTOUR_BASE;
                    754:        else {
                    755:            if (almost_equals(c_token, "ba$se"))
                    756:                draw_contour = CONTOUR_BASE;
                    757:            else if (almost_equals(c_token, "s$urface"))
                    758:                draw_contour = CONTOUR_SRF;
                    759:            else if (almost_equals(c_token, "bo$th"))
                    760:                draw_contour = CONTOUR_BOTH;
                    761:            else
                    762:                int_error("expecting 'base', 'surface', or 'both'", c_token);
                    763:            c_token++;
                    764:        }
                    765:     } else if (almost_equals(c_token,"noco$ntour")) {
                    766:        c_token++;
                    767:        draw_contour = CONTOUR_NONE;
                    768:     } else if (almost_equals(c_token,"cntrp$aram")) {
                    769:        struct value a;
                    770:
                    771:        c_token++;
                    772:        if (END_OF_COMMAND) {
                    773:            /* assuming same as defaults */
                    774:            contour_pts = 5;
                    775:            contour_kind = CONTOUR_KIND_LINEAR;
                    776:            contour_order = 4;
                    777:            contour_levels = 5;
                    778:            levels_kind = LEVELS_AUTO;
                    779:        } else if (almost_equals(c_token, "p$oints")) {
                    780:            c_token++;
                    781:            contour_pts = (int) real(const_express(&a));
                    782:        } else if (almost_equals(c_token, "li$near")) {
                    783:            c_token++;
                    784:            contour_kind = CONTOUR_KIND_LINEAR;
                    785:        } else if (almost_equals(c_token, "c$ubicspline")) {
                    786:            c_token++;
                    787:            contour_kind = CONTOUR_KIND_CUBIC_SPL;
                    788:        } else if (almost_equals(c_token, "b$spline")) {
                    789:            c_token++;
                    790:            contour_kind = CONTOUR_KIND_BSPLINE;
                    791:        } else if (almost_equals(c_token, "le$vels")) {
                    792:            int i = 0;  /* local counter */
                    793:            c_token++;
                    794:            /*  RKC: I have modified the next two:
                    795:             *   to use commas to separate list elements as in xtics
                    796:             *   so that incremental lists start,incr[,end]as in "
                    797:             */
                    798:            if (almost_equals(c_token, "di$screte")) {
                    799:                levels_kind = LEVELS_DISCRETE;
                    800:                c_token++;
                    801:                if(END_OF_COMMAND)
                    802:                    int_error("expecting discrete level", c_token);
                    803:                else
                    804:                    levels_list[i++] = real(const_express(&a));
                    805:
                    806:                while(!END_OF_COMMAND) {
                    807:                    if (!equals(c_token, ","))
                    808:                        int_error("expecting comma to separate discrete levels", c_token);
                    809:                    c_token++;
                    810:                    levels_list[i++] = real(const_express(&a));
                    811:                }
                    812:                contour_levels = i;
                    813:            } else if (almost_equals(c_token, "in$cremental")) {
                    814:                levels_kind = LEVELS_INCREMENTAL;
                    815:                c_token++;
                    816:                levels_list[i++] = real(const_express(&a));
                    817:                if (!equals(c_token, ","))
                    818:                    int_error("expecting comma to separate start,incr levels", c_token);
                    819:                c_token++;
                    820:                if((levels_list[i++] = real(const_express(&a))) == 0)
                    821:                    int_error("increment cannot be 0", c_token);
                    822:                if(!END_OF_COMMAND) {
                    823:                    if (!equals(c_token, ","))
                    824:                        int_error("expecting comma to separate incr,stop levels", c_token);
                    825:                    c_token++;
                    826:                    /* need to round up, since 10,10,50 is 5 levels, not four,
                    827:                     * but 10,10,49 is four
                    828:                     */
                    829:                    contour_levels = (int) ( (real(const_express(&a))-levels_list[0])/levels_list[1] + 1.0);
                    830:                }
                    831:            } else if (almost_equals(c_token, "au$to")) {
                    832:                levels_kind = LEVELS_AUTO;
                    833:                c_token++;
                    834:                if(!END_OF_COMMAND)
                    835:                    contour_levels = (int) real(const_express(&a));
                    836:            } else {
                    837:                if(levels_kind == LEVELS_DISCRETE)
                    838:                    int_error("Levels type is discrete, ignoring new number of contour levels", c_token);
                    839:                contour_levels = (int) real(const_express(&a));
                    840:            }
                    841:        } else if (almost_equals(c_token, "o$rder")) {
                    842:            int order;
                    843:            c_token++;
                    844:            order = (int) real(const_express(&a));
                    845:            if ( order < 2 || order > 10 )
                    846:                int_error("bspline order must be in [2..10] range.", c_token);
                    847:                contour_order = order;
                    848:        } else
                    849:            int_error("expecting 'linear', 'cubicspline', 'bspline', 'points', 'levels' or 'order'", c_token);
                    850:     } else if (almost_equals(c_token,"da$ta")) {
                    851:        c_token++;
                    852:        if (!almost_equals(c_token,"s$tyle"))
                    853:            int_error("expecting keyword 'style'",c_token);
                    854:        data_style = get_style();
                    855:     } else if (almost_equals(c_token,"dg$rid3d")) {
                    856:        int i;
                    857:        TBOOLEAN was_comma = TRUE;
                    858:        int local_vals[3];
                    859:        struct value a;
                    860:
                    861:        local_vals[0] = dgrid3d_row_fineness;
                    862:        local_vals[1] = dgrid3d_col_fineness;
                    863:        local_vals[2] = dgrid3d_norm_value;
                    864:        c_token++;
                    865:        for (i = 0; i < 3 && !(END_OF_COMMAND);) {
                    866:            if (equals(c_token,",")) {
                    867:                if (was_comma) i++;
                    868:                    was_comma = TRUE;
                    869:                c_token++;
                    870:            } else {
                    871:                if (!was_comma)
                    872:                    int_error("',' expected",c_token);
                    873:                local_vals[i] = real(const_express(&a));
                    874:                i++;
                    875:                was_comma = FALSE;
                    876:            }
                    877:        }
                    878:
                    879:        if (local_vals[0] < 2 || local_vals[0] > 1000)
                    880:            int_error("Row size must be in [2:1000] range; size unchanged",
                    881:                      c_token);
                    882:        if (local_vals[1] < 2 || local_vals[1] > 1000)
                    883:            int_error("Col size must be in [2:1000] range; size unchanged",
                    884:                      c_token);
                    885:        if (local_vals[2] < 1 || local_vals[2] > 100)
                    886:            int_error("Norm must be in [1:100] range; norm unchanged", c_token);
                    887:
                    888:        dgrid3d_row_fineness = local_vals[0];
                    889:        dgrid3d_col_fineness = local_vals[1];
                    890:        dgrid3d_norm_value = local_vals[2];
                    891:        dgrid3d = TRUE;
                    892:     } else if (almost_equals(c_token,"nodg$rid3d")) {
                    893:        c_token++;
                    894:        dgrid3d = FALSE;
                    895:     } else if (almost_equals(c_token,"mis$sing")) {
                    896:        c_token++;
                    897:        if (END_OF_COMMAND) {
                    898:            if (missing_val)
                    899:                free(missing_val);
                    900:            missing_val = NULL;
                    901:        } else {
                    902:            if (!isstring(c_token))
                    903:                int_error("Expected missing-value string", c_token);
                    904:            m_quote_capture(&missing_val, c_token, c_token);
                    905:            c_token++;
                    906:        }
                    907:     } else if (almost_equals(c_token,"nomis$sing")) {
                    908:        ++c_token;
                    909:        if (missing_val)
                    910:            free(missing_val);
                    911:        missing_val = NULL;
                    912:     } else if (almost_equals(c_token,"du$mmy")) {
                    913:        c_token++;
                    914:        if (END_OF_COMMAND)
                    915:            int_error("expecting dummy variable name", c_token);
                    916:        else {
                    917:            if (!equals(c_token,","))
                    918:                copy_str(dummy_var[0],c_token++, MAX_ID_LEN);
                    919:            if (!END_OF_COMMAND && equals(c_token,",")) {
                    920:                c_token++;
                    921:                if (END_OF_COMMAND)
                    922:                    int_error("expecting second dummy variable name", c_token);
                    923:                copy_str(dummy_var[1],c_token++, MAX_ID_LEN);
                    924:            }
                    925:        }
                    926:     } else if (almost_equals(c_token,"fo$rmat")) {
                    927:        TBOOLEAN setx = FALSE, sety = FALSE, setz = FALSE;
                    928:        TBOOLEAN setx2 = FALSE, sety2 = FALSE;
                    929:        c_token++;
                    930:        if (equals(c_token,"x")) {
                    931:            setx = TRUE;
                    932:            c_token++;
                    933:        } else if (equals(c_token,"y")) {
                    934:            sety = TRUE;
                    935:            c_token++;
                    936:        } else if (equals(c_token,"x2")) {
                    937:                setx2 = TRUE;
                    938:                c_token++;
                    939:        } else if (equals(c_token,"y2")) {
                    940:                sety2 = TRUE;
                    941:                c_token++;
                    942:        } else if (equals(c_token,"z")) {
                    943:                setz = TRUE;
                    944:                c_token++;
                    945:        } else if (equals(c_token,"xy") || equals(c_token,"yx")) {
                    946:                setx = sety = TRUE;
                    947:                c_token++;
                    948:        } else if (isstring(c_token) || END_OF_COMMAND) {
                    949:                /* Assume he wants all */
                    950:                setx = sety = setz = setx2 = sety2 = TRUE;
                    951:        }
                    952:
                    953:        if (END_OF_COMMAND) {
                    954:            if (setx) {
                    955:                (void) strcpy(xformat,DEF_FORMAT);
                    956:                format_is_numeric[FIRST_X_AXIS] = 1;
                    957:            }
                    958:            if (sety) {
                    959:                (void) strcpy(yformat,DEF_FORMAT);
                    960:                format_is_numeric[FIRST_Y_AXIS] = 1;
                    961:            }
                    962:            if (setz) {
                    963:                (void) strcpy(zformat,DEF_FORMAT);
                    964:                format_is_numeric[FIRST_Z_AXIS] = 1;
                    965:            }
                    966:            if (setx2) {
                    967:                (void) strcpy(x2format,DEF_FORMAT);
                    968:                format_is_numeric[SECOND_X_AXIS] = 1;
                    969:            }
                    970:            if (sety2) {
                    971:                (void) strcpy(y2format,DEF_FORMAT);
                    972:                format_is_numeric[SECOND_Y_AXIS] = 1;
                    973:            }
                    974:        } else {
                    975:            if (!isstring(c_token))
                    976:                int_error("expecting format string",c_token);
                    977:            else {
                    978:                if (setx) {
                    979:                    quote_str(xformat,c_token, MAX_ID_LEN);
                    980:                    format_is_numeric[FIRST_X_AXIS] = looks_like_numeric(xformat);
                    981:                }
                    982:                if (sety) {
                    983:                    quote_str(yformat,c_token, MAX_ID_LEN);
                    984:                    format_is_numeric[FIRST_Y_AXIS] = looks_like_numeric(yformat);
                    985:                }
                    986:                if (setz) {
                    987:                    quote_str(zformat,c_token, MAX_ID_LEN);
                    988:                    format_is_numeric[FIRST_Z_AXIS] =looks_like_numeric(zformat);
                    989:                }
                    990:                if (setx2) {
                    991:                    quote_str(x2format,c_token, MAX_ID_LEN);
                    992:                    format_is_numeric[SECOND_X_AXIS] = looks_like_numeric(x2format);
                    993:                }
                    994:                if (sety2) {
                    995:                    quote_str(y2format,c_token, MAX_ID_LEN);
                    996:                    format_is_numeric[SECOND_Y_AXIS] = looks_like_numeric(y2format);
                    997:                }
                    998:                c_token++;
                    999:            }
                   1000:        }
                   1001:     } else if (almost_equals(c_token,"fu$nction")) {
                   1002:        c_token++;
                   1003:        if (!almost_equals(c_token,"s$tyle"))
                   1004:            int_error("expecting keyword 'style'",c_token);
                   1005:        func_style = get_style();
                   1006:     } else if (almost_equals(c_token,"la$bel")) {
                   1007:        c_token++;
                   1008:        set_label();
                   1009:     } else if (almost_equals(c_token,"nola$bel")) {
                   1010:        c_token++;
                   1011:        set_nolabel();
                   1012:     } else if (almost_equals(c_token,"li$nestyle") || equals(c_token, "ls" )) {
                   1013:        c_token++;
                   1014:        set_linestyle();
                   1015:     } else if (almost_equals(c_token,"noli$nestyle") || equals(c_token, "nols" )) {
                   1016:        c_token++;
                   1017:        set_nolinestyle();
                   1018:     } else if (almost_equals(c_token,"lo$gscale")) {
                   1019:        c_token++;
                   1020:        if (END_OF_COMMAND) {
                   1021:            is_log_x = is_log_y = is_log_z = is_log_x2 = is_log_y2 = TRUE;
                   1022:            base_log_x = base_log_y = base_log_z = base_log_x2 = base_log_y2 = 10.0;
                   1023:            log_base_log_x = log_base_log_y = log_base_log_z = log_base_log_x2 = log_base_log_y2 = M_LN10;
                   1024:        } else {
                   1025:            TBOOLEAN change_x = FALSE;
                   1026:            TBOOLEAN change_y = FALSE;
                   1027:            TBOOLEAN change_z = FALSE;
                   1028:            TBOOLEAN change_x2 = FALSE;
                   1029:            TBOOLEAN change_y2 = FALSE;
                   1030:            double newbase = 10, log_newbase;
                   1031:
                   1032:            if (equals(c_token, "x2"))
                   1033:                change_x2 = TRUE;
                   1034:            else if (equals(c_token, "y2"))
                   1035:                change_y2 = TRUE;
                   1036:            else { /* must not see x when x2, etc */
                   1037:                if (chr_in_str(c_token, 'x'))
                   1038:                    change_x = TRUE;
                   1039:                if (chr_in_str(c_token, 'y'))
                   1040:                    change_y = TRUE;
                   1041:                if (chr_in_str(c_token, 'z'))
                   1042:                    change_z = TRUE;
                   1043:            }
                   1044:            c_token++;
                   1045:            if (!END_OF_COMMAND) {
                   1046:                struct value a;
                   1047:                newbase = magnitude(const_express(&a));
                   1048:                if (newbase < 1.1)
                   1049:                    int_error("log base must be >= 1.1; logscale unchanged",
                   1050:                c_token);
                   1051:            }
                   1052:            log_newbase = log(newbase);
                   1053:
                   1054:            if (change_x) {
                   1055:                is_log_x = TRUE;
                   1056:                base_log_x = newbase;
                   1057:                log_base_log_x = log_newbase;
                   1058:            }
                   1059:            if (change_y) {
                   1060:                is_log_y = TRUE;
                   1061:                base_log_y = newbase;
                   1062:                log_base_log_y = log_newbase;
                   1063:            }
                   1064:            if (change_z) {
                   1065:                is_log_z = TRUE;
                   1066:                base_log_z = newbase;
                   1067:                log_base_log_z = log_newbase;
                   1068:            }
                   1069:            if (change_x2) {
                   1070:                is_log_x2 = TRUE;
                   1071:                base_log_x2 = newbase;
                   1072:                log_base_log_x2 = log_newbase;
                   1073:            }
                   1074:            if (change_y2) {
                   1075:                is_log_y2 = TRUE;
                   1076:                base_log_y2 = newbase;
                   1077:                log_base_log_y2 = log_newbase;
                   1078:            }
                   1079:        }
                   1080:     } else if (almost_equals(c_token,"nolo$gscale")) {
                   1081:        c_token++;
                   1082:        if (END_OF_COMMAND) {
                   1083:            is_log_x = is_log_y = is_log_z = is_log_x2 = is_log_y2 = FALSE;
                   1084:        } else if (equals(c_token, "x2")) {
                   1085:            is_log_x2 = FALSE; ++c_token;
                   1086:        } else if (equals(c_token, "y2")) {
                   1087:            is_log_y2 = FALSE; ++c_token;
                   1088:        } else {
                   1089:            if (chr_in_str(c_token, 'x')) {
                   1090:                is_log_x = FALSE;
                   1091:                base_log_x = 0.0;
                   1092:                log_base_log_x = 0.0;
                   1093:            }
                   1094:            if (chr_in_str(c_token, 'y')) {
                   1095:                is_log_y = FALSE;
                   1096:                base_log_y = 0.0;
                   1097:                log_base_log_y = 0.0;
                   1098:            }
                   1099:            if (chr_in_str(c_token, 'z')) {
                   1100:                is_log_z = FALSE;
                   1101:                base_log_z = 0.0;
                   1102:                log_base_log_z = 0.0;
                   1103:            }
                   1104:            c_token++;
                   1105:        }
                   1106:     } else if (almost_equals(c_token,"of$fsets")) {
                   1107:        c_token++;
                   1108:        if (END_OF_COMMAND) {
                   1109:            loff = roff = toff = boff = 0.0;  /* Reset offsets */
                   1110:        } else {
                   1111:            load_offsets (&loff,&roff,&toff,&boff);
                   1112:        }
                   1113:     } else if (almost_equals(c_token, "noof$fsets")) {
                   1114:        loff = roff = toff = boff = 0.0;
                   1115:        ++c_token;
                   1116:     } else if(almost_equals(c_token,"b$ars")) {
                   1117:        c_token++;
                   1118:        if(END_OF_COMMAND) {
                   1119:            bar_size = 1.0;
                   1120:        } else if(almost_equals(c_token,"s$mall")) {
                   1121:            bar_size = 0.0;
                   1122:            ++c_token;
                   1123:        } else if(almost_equals(c_token,"l$arge")) {
                   1124:            bar_size = 1.0;
                   1125:            ++c_token;
                   1126:        } else {
                   1127:            struct value a;
                   1128:            bar_size = real(const_express(&a));
                   1129:        }
                   1130:     } else if (almost_equals(c_token, "nob$ars")) {
                   1131:        ++c_token;
                   1132:        bar_size = 0.0;
                   1133:     } else if (almost_equals(c_token, "enco$ding")) {
                   1134:        c_token++;
                   1135:        if(END_OF_COMMAND) {
                   1136:            encoding = ENCODING_DEFAULT;
                   1137:        } else if (almost_equals(c_token,"def$ault")) {
                   1138:            c_token++;
                   1139:            encoding = ENCODING_DEFAULT;
                   1140:        } else if (almost_equals(c_token,"iso$_8859_1")) {
                   1141:            c_token++;
                   1142:            encoding = ENCODING_ISO_8859_1;
                   1143:        } else if (almost_equals(c_token,"cp4$37")) {
                   1144:            c_token++;
                   1145:            encoding = ENCODING_CP_437;
                   1146:        } else if (almost_equals(c_token,"cp8$50")) {
                   1147:            c_token++;
                   1148:            encoding = ENCODING_CP_850;
                   1149:        } else {
                   1150:            int_error("expecting one of 'default', 'iso_8859_1', 'cp437' or 'cp850'", c_token);
                   1151:        }
                   1152:     } else
                   1153:        return(FALSE);  /* no command match */
                   1154:
                   1155:     return(TRUE);
                   1156: }
                   1157:
                   1158:
                   1159: /* return TRUE if a command match, FALSE if not */
                   1160: static TBOOLEAN
                   1161: set_two()
                   1162: {
                   1163:     if (almost_equals(c_token,"o$utput")) {
                   1164:        if (multiplot) {
                   1165:            int_error("you can't change the output in multiplot mode", c_token);
                   1166:        }
                   1167:
                   1168:        c_token++;
                   1169:        if (END_OF_COMMAND) {   /* no file specified */
                   1170:            term_set_output(NULL);
                   1171:            if (outstr) {
                   1172:                free(outstr);
                   1173:                outstr = NULL; /* means STDOUT */
                   1174:            }
                   1175:        } else if (!isstring(c_token)) {
                   1176:            int_error("expecting filename",c_token);
                   1177:        } else {
                   1178:            /* on int_error, we'd like to remember that this is allocated */
                   1179:            static char *testfile = NULL;
                   1180:            m_quote_capture(&testfile,c_token, c_token); /* reallocs store */
                   1181:            /* Skip leading whitespace */
                   1182:            while (isspace((int)*testfile))
                   1183:                testfile++;
                   1184:            ++c_token;
                   1185:            term_set_output(testfile);
                   1186:            /* if we get here then it worked, and outstr now = testfile */
                   1187:            testfile = NULL;
                   1188:        }
                   1189:     } else if (almost_equals(c_token,"origin")) {
                   1190:        struct value s;
                   1191:        c_token++;
                   1192:        if (END_OF_COMMAND) {
                   1193:            xoffset = 0.0;
                   1194:            yoffset = 0.0;
                   1195:        } else {
                   1196:            xoffset = real(const_express(&s));
                   1197:            if (!equals(c_token,","))
                   1198:                int_error("',' expected",c_token);
                   1199:            c_token++;
                   1200:            yoffset = real(const_express(&s));
                   1201:        }
                   1202:     } else if (almost_equals(c_token,"tit$le")) {
                   1203:        set_xyzlabel(&title);
                   1204:     } else if (almost_equals(c_token,"xl$abel")) {
                   1205:        set_xyzlabel(&xlabel);
                   1206:     } else if (almost_equals(c_token,"yl$abel")) {
                   1207:        set_xyzlabel(&ylabel);
                   1208:     } else if (almost_equals(c_token,"zl$abel")) {
                   1209:        set_xyzlabel(&zlabel);
                   1210:     } else if (almost_equals(c_token,"x2l$abel")) {
                   1211:        set_xyzlabel(&x2label);
                   1212:     } else if (almost_equals(c_token,"y2l$abel")) {
                   1213:        set_xyzlabel(&y2label);
                   1214:     } else if (almost_equals(c_token,"keyt$itle")) {
                   1215:        c_token++;
                   1216:        if (END_OF_COMMAND) {   /* set to default */
                   1217:            key_title[0] = NUL;
                   1218:        } else {
                   1219:            if (isstring(c_token)) {
                   1220:                /* We have string specified - grab it. */
                   1221:                quote_str(key_title,c_token, MAX_LINE_LEN);
                   1222:                c_token++;
                   1223:            }
                   1224:            /* c_token++; */
                   1225:        }
                   1226:     } else if (almost_equals(c_token, "nokeyt$itle")) {
                   1227:        ++c_token;
                   1228:        *key_title = 0;
                   1229:     } else if (almost_equals(c_token,"timef$mt")) {
                   1230:        c_token++;
                   1231:        if (END_OF_COMMAND) {   /* set to default */
                   1232:            strcpy(timefmt,TIMEFMT);
                   1233:        } else {
                   1234:            if (isstring(c_token)) {
                   1235:                /* We have string specified - grab it. */
                   1236:                quote_str(timefmt,c_token, 25);
                   1237:            }
                   1238:            c_token++;
                   1239:        }
                   1240:     } else if (almost_equals(c_token,"loc$ale")) {
                   1241:        c_token++;
                   1242:        if (END_OF_COMMAND) {
                   1243:            set_locale("C");
                   1244:        } else if (isstring(c_token)) {
                   1245:            char ss[MAX_ID_LEN+1];
                   1246:            quote_str(ss,c_token,MAX_ID_LEN);
                   1247:            set_locale(ss);
                   1248:            ++c_token;
                   1249:        } else {
                   1250:            int_error("Expected string", c_token);
                   1251:        }
                   1252:     }
                   1253:
                   1254: #define DO_ZEROAX(variable, string,neg) \
                   1255: else if (almost_equals(c_token, string)) { \
                   1256:    ++c_token; if (END_OF_COMMAND) variable.l_type = -1; \
                   1257:    else { \
                   1258:       struct value a; \
                   1259:       int old_token = c_token;\
                   1260:       LP_PARSE(variable,1,0,-1,0); \
                   1261:       if (old_token == c_token) \
                   1262:          variable.l_type = real(const_express(&a)) - 1; \
                   1263:    }\
                   1264: } else if (almost_equals(c_token, neg)) { \
                   1265:    ++c_token; variable.l_type = -3; \
                   1266: }
                   1267:
                   1268:     DO_ZEROAX(xzeroaxis, "xzero$axis", "noxzero$axis")
                   1269:     DO_ZEROAX(yzeroaxis, "yzero$axis", "noyzero$axis")
                   1270:     DO_ZEROAX(x2zeroaxis, "x2zero$axis", "nox2zero$axis")
                   1271:     DO_ZEROAX(y2zeroaxis, "y2zero$axis", "noy2zero$axis")
                   1272:
                   1273:     else if (almost_equals(c_token,"zeroa$xis")) {
                   1274:        c_token++;
                   1275:        LP_PARSE(xzeroaxis,1,0,-1,0);
                   1276:        memcpy(&yzeroaxis,&xzeroaxis,sizeof(struct lp_style_type));
                   1277:     } else if (almost_equals(c_token,"nozero$axis")) {
                   1278:        c_token++;
                   1279:        xzeroaxis.l_type  = -3;
                   1280:        yzeroaxis.l_type  = -3;
                   1281:        x2zeroaxis.l_type = -3;
                   1282:        y2zeroaxis.l_type = -3;
                   1283:     } else if (almost_equals(c_token,"par$ametric")) {
                   1284:        if (!parametric) {
                   1285:            parametric = TRUE;
                   1286:            if (!polar) { /* already done for polar */
                   1287:                strcpy (dummy_var[0], "t");
                   1288:                strcpy (dummy_var[1], "y");
                   1289:                if (interactive)
                   1290:                     (void) fprintf(stderr,"\n\tdummy variable is t for curves, u/v for surfaces\n");
                   1291:            }
                   1292:        }
                   1293:        c_token++;
                   1294:     } else if (almost_equals(c_token,"nopar$ametric")) {
                   1295:        if (parametric) {
                   1296:            parametric = FALSE;
                   1297:            if (!polar) { /* keep t for polar */
                   1298:                strcpy (dummy_var[0], "x");
                   1299:                strcpy (dummy_var[1], "y");
                   1300:                if (interactive)
                   1301:                   (void) fprintf(stderr,"\n\tdummy variable is x for curves, x/y for surfaces\n");
                   1302:            }
                   1303:        }
                   1304:        c_token++;
                   1305:     } else if (almost_equals(c_token, "poi$ntsize")) {
                   1306:        struct value a;
                   1307:        c_token++;
                   1308:        if (END_OF_COMMAND)
                   1309:           pointsize = 1.0;
                   1310:        else
                   1311:            pointsize = real(const_express(&a));
                   1312:        if(pointsize <= 0) pointsize = 1;
                   1313:     } else if (almost_equals(c_token,"pol$ar")) {
                   1314:        if (!polar) {
                   1315:            if (!parametric) {
                   1316:                if (interactive)
                   1317:                    (void) fprintf(stderr,"\n\tdummy variable is t for curves\n");
                   1318:                strcpy (dummy_var[0], "t");
                   1319:            }
                   1320:            polar = TRUE;
                   1321:            if (autoscale_t) {
                   1322:                /* only if user has not set a range manually */
                   1323:                tmin = 0.0;
                   1324:                tmax = 2*Pi / ang2rad;  /* 360 if degrees, 2pi if radians */
                   1325:            }
                   1326:        }
                   1327:        c_token++;
                   1328:     } else if (almost_equals(c_token,"nopo$lar")) {
                   1329:        if (polar) {
                   1330:            polar = FALSE;
                   1331:            if (parametric && autoscale_t) {
                   1332:                /* only if user has not set an explicit range */
                   1333:                tmin = -5.0;
                   1334:                tmax = 5.0;
                   1335:            }
                   1336:            if (!parametric) {
                   1337:                strcpy (dummy_var[0], "x");
                   1338:                if (interactive)
                   1339:                    (void) fprintf(stderr,"\n\tdummy variable is x for curves\n");
                   1340:            }
                   1341:        }
                   1342:        c_token++;
                   1343:     } else if (almost_equals(c_token,"an$gles")) {
                   1344:        c_token++;
                   1345:        if (END_OF_COMMAND) {
                   1346:            /* assuming same as defaults */
                   1347:            angles_format = ANGLES_RADIANS;
                   1348:            ang2rad = 1;
                   1349:        } else if (almost_equals(c_token, "r$adians")) {
                   1350:            angles_format = ANGLES_RADIANS;
                   1351:            c_token++;
                   1352:            ang2rad = 1;
                   1353:        } else if (almost_equals(c_token, "d$egrees")) {
                   1354:            angles_format = ANGLES_DEGREES;
                   1355:            c_token++;
                   1356:            ang2rad = DEG2RAD;
                   1357:        } else
                   1358:            int_error("expecting 'radians' or 'degrees'", c_token);
                   1359:
                   1360:        if (polar && autoscale_t) {
                   1361:            /* set trange if in polar mode and no explicit range */
                   1362:            tmin = 0;
                   1363:            tmax = 2*Pi/ang2rad;
                   1364:        }
                   1365:     }
                   1366:
                   1367: #define GRID_MATCH(string, neg, mask) \
                   1368: if (almost_equals(c_token, string)) { work_grid.l_type |= mask; ++c_token; } \
                   1369: else if (almost_equals(c_token, neg)) { work_grid.l_type &= ~(mask); ++c_token; }
                   1370:
                   1371:     else if (almost_equals(c_token,"g$rid")) {
                   1372:        c_token++;
                   1373:        if (END_OF_COMMAND && !work_grid.l_type)
                   1374:            work_grid.l_type = GRID_X|GRID_Y;
                   1375:        else
                   1376:            while (!END_OF_COMMAND) {
                   1377:                GRID_MATCH("x$tics", "nox$tics", GRID_X)
                   1378:                else GRID_MATCH("y$tics", "noy$tics", GRID_Y)
                   1379:                else GRID_MATCH("z$tics", "noz$tics", GRID_Z)
                   1380:                else GRID_MATCH("x2$tics", "nox2$tics", GRID_X2)
                   1381:                else GRID_MATCH("y2$tics", "noy2$tics", GRID_Y2)
                   1382:                else GRID_MATCH("mx$tics", "nomx$tics", GRID_MX)
                   1383:                else GRID_MATCH("my$tics", "nomy$tics", GRID_MY)
                   1384:                else GRID_MATCH("mz$tics", "nomz$tics", GRID_MZ)
                   1385:                else GRID_MATCH("mx2$tics", "nomx2$tics", GRID_MX2)
                   1386:                else GRID_MATCH("my2$tics", "nomy2$tics", GRID_MY2)
                   1387:                else if (almost_equals(c_token,"po$lar")) {
                   1388:                    if (!work_grid.l_type)
                   1389:                        work_grid.l_type = GRID_X;
                   1390:                    c_token++;
                   1391:                    if (END_OF_COMMAND) {
                   1392:                        polar_grid_angle = 30*DEG2RAD;
                   1393:                    } else {
                   1394:                        /* get radial interval */
                   1395:                        struct value a;
                   1396:                        polar_grid_angle = ang2rad*real(const_express(&a));
                   1397:                    }
                   1398:                } else if (almost_equals(c_token,"nopo$lar")) {
                   1399:                    polar_grid_angle = 0; /* not polar grid */
                   1400:                    c_token++;
                   1401:                } else
                   1402:                    break; /* might be a linetype */
                   1403:            }
                   1404:
                   1405:        if (!END_OF_COMMAND) {
                   1406:            struct value a;
                   1407:            int old_token = c_token;
                   1408:
                   1409:            LP_PARSE(grid_lp,1,0,-1,1);
                   1410:            if (c_token == old_token) { /* nothing parseable found... */
                   1411:                grid_lp.l_type = real(const_express(&a)) - 1;
                   1412:            }
                   1413:
                   1414:            if (!work_grid.l_type)
                   1415:                work_grid.l_type = GRID_X|GRID_Y;
                   1416:                /* probably just  set grid <linetype> */
                   1417:
                   1418:            if (END_OF_COMMAND) {
                   1419:                memcpy(&mgrid_lp,&grid_lp,sizeof(struct lp_style_type));
                   1420:            } else {
                   1421:                if (equals(c_token,","))
                   1422:                    c_token++;
                   1423:                old_token = c_token;
                   1424:                LP_PARSE(mgrid_lp,1,0,-1,1);
                   1425:                if (c_token == old_token) {
                   1426:                    mgrid_lp.l_type = real(const_express(&a)) -1;
                   1427:                }
                   1428:            }
                   1429:
                   1430:            if (!work_grid.l_type)
                   1431:                work_grid.l_type = GRID_X|GRID_Y;
                   1432:            /* probably just  set grid <linetype> */
                   1433:        }
                   1434:
                   1435:     } else if (almost_equals(c_token,"nog$rid")) {
                   1436:        work_grid.l_type = GRID_OFF;
                   1437:        c_token++;
                   1438:     } else if (almost_equals(c_token,"su$rface")) {
                   1439:        draw_surface = TRUE;
                   1440:        c_token++;
                   1441:     } else if (almost_equals(c_token,"nosu$rface")) {
                   1442:        draw_surface = FALSE;
                   1443:        c_token++;
                   1444:     } else if (almost_equals(c_token,"bor$der")) {
                   1445:        struct value a;
                   1446:        c_token++;
                   1447:        if(END_OF_COMMAND){
                   1448:            draw_border = 31;
                   1449:        } else {
                   1450:            draw_border = (int)real(const_express(&a));
                   1451:        }
                   1452:        /* HBB 980609: add linestyle handling for 'set border...' */
                   1453:        /* For now, you have to give a border bitpattern to be able to specify a linestyle. Sorry for this,
                   1454:         * but the gnuplot parser really is too messy for any other solution, currently */
                   1455:        if(END_OF_COMMAND) {
                   1456:            set_lp_properties(&border_lp, 0, -2, 0, 1.0, 1.0);
                   1457:        } else {
                   1458:            LP_PARSE(border_lp, 1, 0, -2, 0);
                   1459:        }
                   1460:     } else if (almost_equals(c_token,"k$ey")) {
                   1461:        struct value a;
                   1462:        c_token++;
                   1463:        if (END_OF_COMMAND) {
                   1464:            key = -1;
                   1465:            key_vpos = TTOP;
                   1466:            key_hpos = TRIGHT;
                   1467:            key_just = JRIGHT;
                   1468:            key_reverse = FALSE;
                   1469:            set_lp_properties(&key_box,0,-3,0,1.0,1.0);
                   1470:            key_swidth = 4;
                   1471:            key_vert_factor = 1;
                   1472:            key_width_fix = 0;
                   1473:            key_title[0] = 0;
                   1474:        } else {
                   1475:            while (!END_OF_COMMAND) {
                   1476:                if (almost_equals(c_token,"t$op")) {
                   1477:                    key_vpos = TTOP;
                   1478:                    key = -1;
                   1479:                } else if (almost_equals(c_token,"b$ottom")) {
                   1480:                    key_vpos = TBOTTOM;
                   1481:                    key = -1;
                   1482:                } else if (almost_equals(c_token,"l$eft")) {
                   1483:                    key_hpos = TLEFT;
                   1484:                    /* key_just = TRIGHT; */
                   1485:                    key = -1;
                   1486:                } else if (almost_equals(c_token,"r$ight")) {
                   1487:                    key_hpos = TRIGHT;
                   1488:                    key = -1;
                   1489:                } else if (almost_equals(c_token,"u$nder") ||
                   1490:                           almost_equals(c_token,"be$low")) {
                   1491:                    key_vpos = TUNDER;
                   1492:                    if (key_hpos == TOUT)
                   1493:                        key_hpos--;
                   1494:                    key = -1;
                   1495:                } else if (almost_equals(c_token,"o$utside")) {
                   1496:                    key_hpos = TOUT;
                   1497:                    if (key_vpos == TUNDER)
                   1498:                        key_vpos--;
                   1499:                    key = -1;
                   1500:                } else if (almost_equals(c_token,"L$eft")) {
                   1501:                    /* key_hpos = TLEFT; */
                   1502:                    key_just = JLEFT;
                   1503:                    /* key = -1; */
                   1504:                } else if (almost_equals(c_token,"R$ight")) {
                   1505:                    /* key_hpos = TLEFT; */
                   1506:                    key_just = JRIGHT;
                   1507:                    /* key = -1; */
                   1508:                } else if (almost_equals(c_token,"rev$erse")) {
                   1509:                    key_reverse = TRUE;
                   1510:                } else if (almost_equals(c_token,"norev$erse")) {
                   1511:                    key_reverse = FALSE;
                   1512:                } else if (equals(c_token,"box")) {
                   1513:                    ++c_token;
                   1514:                    if (END_OF_COMMAND)
                   1515:                        key_box.l_type = -2;
                   1516:                    else {
                   1517:                        int old_token = c_token;
                   1518:
                   1519:                        LP_PARSE(key_box,1,0,-2,0);
                   1520:                        if (old_token == c_token) {
                   1521:                            key_box.l_type = real(const_express(&a)) -1;
                   1522:                        }
                   1523:                    }
                   1524:                    --c_token;  /* is incremented after loop */
                   1525:                } else if (almost_equals(c_token,"nob$ox")) {
                   1526:                    key_box.l_type = -3;
                   1527:                } else if (almost_equals(c_token, "sa$mplen")) {
                   1528:                    ++c_token;
                   1529:                    key_swidth = real(const_express(&a));
                   1530:                    --c_token; /* it is incremented after loop */
                   1531:                } else if (almost_equals(c_token, "sp$acing")) {
                   1532:                    ++c_token;
                   1533:                    key_vert_factor = real(const_express(&a));
                   1534:                    if (key_vert_factor < 0.0)
                   1535:                        key_vert_factor = 0.0;
                   1536:                    --c_token; /* it is incremented after loop */
                   1537:                } else if (almost_equals(c_token, "w$idth")) {
                   1538:                    ++c_token;
                   1539:                    key_width_fix = real(const_express(&a));
                   1540:                    --c_token; /* it is incremented after loop */
                   1541:                } else if (almost_equals(c_token,"ti$tle")) {
                   1542:                    if (isstring(c_token+1)) {
                   1543:                        /* We have string specified - grab it. */
                   1544:                        quote_str(key_title,++c_token, MAX_LINE_LEN);
                   1545:                    }
                   1546:                    else
                   1547:                        key_title[0] = 0;
                   1548:                } else {
                   1549:                    get_position(&key_user_pos);
                   1550:                    key = 1;
                   1551:                    --c_token;  /* will be incremented again soon */
                   1552:                }
                   1553:                c_token++;
                   1554:            }
                   1555:        }
                   1556:     } else if (almost_equals(c_token,"nok$ey")) {
                   1557:        key = 0;
                   1558:        c_token++;
                   1559:     } else if (almost_equals(c_token,"tic$s")) {
                   1560:        tic_in = TRUE;
                   1561:        c_token++;
                   1562:        if (almost_equals(c_token,"i$n")) {
                   1563:            tic_in = TRUE;
                   1564:            c_token++;
                   1565:        } else if (almost_equals(c_token,"o$ut")) {
                   1566:            tic_in = FALSE;
                   1567:            c_token++;
                   1568:        }
                   1569:     } else if (almost_equals(c_token,"xda$ta")) {
                   1570:        c_token++;
                   1571:        if(END_OF_COMMAND) {
                   1572:            datatype[FIRST_X_AXIS] = FALSE;
                   1573:            /* eh ? - t and u have nothing to do with x */
                   1574:            datatype[T_AXIS] = FALSE;
                   1575:            datatype[U_AXIS] = FALSE;
                   1576:        } else {
                   1577:            if (almost_equals(c_token,"t$ime")) {
                   1578:                datatype[FIRST_X_AXIS] = TIME;
                   1579:                datatype[T_AXIS] = TIME;
                   1580:                datatype[U_AXIS] = TIME;
                   1581:            } else {
                   1582:                datatype[FIRST_X_AXIS] = FALSE;
                   1583:                datatype[T_AXIS] = FALSE;
                   1584:                datatype[U_AXIS] = FALSE;
                   1585:            }
                   1586:            c_token++;
                   1587:        }
                   1588:     } else if (almost_equals(c_token,"yda$ta")) {
                   1589:        c_token++;
                   1590:        if(END_OF_COMMAND) {
                   1591:            datatype[FIRST_Y_AXIS] = FALSE;
                   1592:            datatype[V_AXIS] = FALSE;
                   1593:        } else {
                   1594:            if (almost_equals(c_token,"t$ime")) {
                   1595:                datatype[FIRST_Y_AXIS] = TIME;
                   1596:                datatype[V_AXIS] = TIME;
                   1597:            } else {
                   1598:                datatype[FIRST_Y_AXIS] = FALSE;
                   1599:                datatype[V_AXIS] = FALSE;
                   1600:            }
                   1601:            c_token++;
                   1602:        }
                   1603:     } else if (almost_equals(c_token,"zda$ta")) {
                   1604:        c_token++;
                   1605:        if(END_OF_COMMAND) {
                   1606:            datatype[FIRST_Z_AXIS] = FALSE;
                   1607:        } else {
                   1608:            if (almost_equals(c_token,"t$ime")) {
                   1609:                datatype[FIRST_Z_AXIS] = TIME;
                   1610:            } else {
                   1611:                datatype[FIRST_Z_AXIS] = FALSE;
                   1612:            }
                   1613:            c_token++;
                   1614:        }
                   1615:     } else if (almost_equals(c_token,"x2da$ta")) {
                   1616:        c_token++;
                   1617:        if(END_OF_COMMAND) {
                   1618:            datatype[SECOND_X_AXIS] = FALSE;
                   1619:        } else {
                   1620:            if (almost_equals(c_token,"t$ime")) {
                   1621:                datatype[SECOND_X_AXIS] = TIME;
                   1622:            } else {
                   1623:                datatype[SECOND_X_AXIS] = FALSE;
                   1624:            }
                   1625:            c_token++;
                   1626:        }
                   1627:     } else if (almost_equals(c_token,"y2da$ta")) {
                   1628:        c_token++;
                   1629:        if(END_OF_COMMAND) {
                   1630:            datatype[SECOND_Y_AXIS] = FALSE;
                   1631:        } else {
                   1632:            if (almost_equals(c_token,"t$ime")) {
                   1633:                datatype[SECOND_Y_AXIS] = TIME;
                   1634:            } else {
                   1635:                datatype[SECOND_Y_AXIS] = FALSE;
                   1636:            }
                   1637:            c_token++;
                   1638:        }
                   1639:     }
                   1640:
                   1641: /* to save duplicating code for x/y/z/x2/y2, make a macro
                   1642:  * (should perhaps be a function ?)
                   1643:  * unfortunately, string concatenation is not supported on all compilers,
                   1644:  * so we have to explicitly include both 'on' and 'no' strings in
                   1645:  * the args
                   1646:  */
                   1647:
                   1648: /* change to a function: lph 25.09.1998 */
                   1649:
                   1650: #define PROCESS_TIC_COMMANDS  set_tic_prop
                   1651:
                   1652:     else if
                   1653:        (PROCESS_TIC_COMMANDS(&x2tics, &mx2tics, &mx2tfreq, &x2ticdef,
                   1654:         SECOND_X_AXIS, &rotate_x2tics, "x2") );
                   1655:     else if
                   1656:        (PROCESS_TIC_COMMANDS(&y2tics, &my2tics, &my2tfreq, &y2ticdef,
                   1657:         SECOND_Y_AXIS, &rotate_y2tics, "y2") );
                   1658:     else if
                   1659:        (PROCESS_TIC_COMMANDS(&xtics,   &mxtics, &mxtfreq,  &xticdef,
                   1660:         FIRST_X_AXIS, &rotate_xtics, "x") );
                   1661:     else if
                   1662:        (PROCESS_TIC_COMMANDS(&ytics,   &mytics, &mytfreq,  &yticdef,
                   1663:         FIRST_Y_AXIS, &rotate_ytics, "y") );
                   1664:     else if
                   1665:        (PROCESS_TIC_COMMANDS(&ztics,   &mztics, &mztfreq,  &zticdef,
                   1666:         FIRST_Z_AXIS, &rotate_ztics, "z") );
                   1667:
                   1668:     else if (almost_equals(c_token,"ticsl$evel")) {
                   1669:        double tlvl;
                   1670:        struct value a;
                   1671:
                   1672:        c_token++;
                   1673:        /* is datatype 'time' relevant here ? */
                   1674:        tlvl = real(const_express(&a));
                   1675:        ticslevel = tlvl;
                   1676:     }
                   1677:
                   1678: #define PROCESS_MARGIN(variable, string) \
                   1679: else if (almost_equals(c_token,string)) {\
                   1680:  ++c_token; if (END_OF_COMMAND) variable = -1;\
                   1681:  else { struct value a; variable = real(const_express(&a)); } \
                   1682: }
                   1683:
                   1684:     PROCESS_MARGIN(lmargin, "lmar$gin")
                   1685:     PROCESS_MARGIN(bmargin, "bmar$gin")
                   1686:     PROCESS_MARGIN(rmargin, "rmar$gin")
                   1687:     PROCESS_MARGIN(tmargin, "tmar$gin")
                   1688:
                   1689:     else
                   1690:        return(FALSE);  /* no command match */
                   1691:
                   1692:     return(TRUE);
                   1693: }
                   1694:
                   1695:
                   1696:
                   1697: /* return TRUE if a command match, FALSE if not */
                   1698: static TBOOLEAN
                   1699: set_three()
                   1700: {
                   1701:     if (almost_equals(c_token,"sa$mples")) {
                   1702:        register int tsamp1, tsamp2;
                   1703:        struct value a;
                   1704:
                   1705:        c_token++;
                   1706:        tsamp1 = (int)magnitude(const_express(&a));
                   1707:        tsamp2 = tsamp1;
                   1708:        if (!END_OF_COMMAND) {
                   1709:            if (!equals(c_token,","))
                   1710:                int_error("',' expected",c_token);
                   1711:            c_token++;
                   1712:            tsamp2 = (int)magnitude(const_express(&a));
                   1713:        }
                   1714:        if (tsamp1 < 2 || tsamp2 < 2)
                   1715:            int_error("sampling rate must be > 1; sampling unchanged",c_token);
                   1716:        else {
                   1717:            register struct surface_points *f_3dp = first_3dplot;
                   1718:
                   1719:            first_3dplot = NULL;
                   1720:            sp_free(f_3dp);
                   1721:
                   1722:            samples = tsamp1;
                   1723:            samples_1 = tsamp1;
                   1724:            samples_2 = tsamp2;
                   1725:        }
                   1726:     } else if (almost_equals(c_token,"isosa$mples")) {
                   1727:        register int tsamp1, tsamp2;
                   1728:        struct value a;
                   1729:
                   1730:        c_token++;
                   1731:        tsamp1 = (int)magnitude(const_express(&a));
                   1732:        tsamp2 = tsamp1;
                   1733:        if (!END_OF_COMMAND) {
                   1734:            if (!equals(c_token,","))
                   1735:                int_error("',' expected",c_token);
                   1736:            c_token++;
                   1737:            tsamp2 = (int)magnitude(const_express(&a));
                   1738:        }
                   1739:        if (tsamp1 < 2 || tsamp2 < 2)
                   1740:            int_error("sampling rate must be > 1; sampling unchanged",c_token);
                   1741:        else {
                   1742:            register struct curve_points *f_p = first_plot;
                   1743:            register struct surface_points *f_3dp = first_3dplot;
                   1744:
                   1745:            first_plot = NULL;
                   1746:            first_3dplot = NULL;
                   1747:            cp_free(f_p);
                   1748:            sp_free(f_3dp);
                   1749:
                   1750:            iso_samples_1 = tsamp1;
                   1751:            iso_samples_2 = tsamp2;
                   1752:        }
                   1753:     } else if (almost_equals(c_token,"si$ze")) {
                   1754:        struct value s;
                   1755:        c_token++;
                   1756:        if (END_OF_COMMAND) {
                   1757:            xsize = 1.0;
                   1758:            ysize = 1.0;
                   1759:        } else {
                   1760:            if (almost_equals(c_token, "sq$uare")) {
                   1761:                aspect_ratio = 1.0;
                   1762:                ++c_token;
                   1763:            } else if (almost_equals(c_token,"ra$tio")) {
                   1764:                ++c_token;
                   1765:                aspect_ratio = real(const_express(&s));
                   1766:            } else if (almost_equals(c_token, "nora$tio") || almost_equals(c_token, "nosq$uare")) {
                   1767:                aspect_ratio = 0.0;
                   1768:                ++c_token;
                   1769:            }
                   1770:
                   1771:            if (!END_OF_COMMAND) {
                   1772:                xsize = real(const_express(&s));
                   1773:                if (equals(c_token,",")) {
                   1774:                    c_token++;
                   1775:                    ysize = real(const_express(&s));
                   1776:                } else {
                   1777:                    ysize = xsize;
                   1778:                }
                   1779:            }
                   1780:        }
                   1781:     } else if (almost_equals(c_token,"ticsc$ale")) {
                   1782:        struct value tscl;
                   1783:        c_token++;
                   1784:        if (END_OF_COMMAND) {
                   1785:            ticscale = 1.0;
                   1786:            miniticscale = 0.5;
                   1787:        } else {
                   1788:            ticscale = real(const_express(&tscl));
                   1789:            if (END_OF_COMMAND) {
                   1790:                miniticscale = ticscale*0.5;
                   1791:            } else {
                   1792:                miniticscale = real(const_express(&tscl));
                   1793:            }
                   1794:        }
                   1795:     } else if (almost_equals(c_token,"t$erminal")) {
                   1796:        if (multiplot) {
                   1797:            int_error("You can't change the terminal in multiplot mode", c_token);
                   1798:        }
                   1799:
                   1800:        c_token++;
                   1801:        if (END_OF_COMMAND) {
                   1802:            list_terms();
                   1803:            screen_ok = FALSE;
                   1804:        } else {
                   1805:            term_reset();
                   1806:            term = 0; /* in case set_term() fails */
                   1807:            term = set_term(c_token);
                   1808:            c_token++;
                   1809:
                   1810:            /* get optional mode parameters
                   1811:             * not all drivers reset the option string before
                   1812:             * strcat-ing to it, so we reset it for them
                   1813:             */
                   1814:            *term_options = 0;
                   1815:            if (term)
                   1816:                (*term->options)();
                   1817:            if (interactive && *term_options)
                   1818:                fprintf(stderr,"Options are '%s'\n",term_options);
                   1819:        }
                   1820:     } else if (almost_equals(c_token,"tim$estamp")) {
                   1821:        c_token++;
                   1822:        if (END_OF_COMMAND || !isstring(c_token))
                   1823:            strcpy(timelabel.text, DEFAULT_TIMESTAMP_FORMAT);
                   1824:
                   1825:        if (!END_OF_COMMAND) {
                   1826:            struct value a;
                   1827:
                   1828:            if (isstring(c_token)) {
                   1829:                /* we have a format string */
                   1830:                quote_str(timelabel.text, c_token, MAX_LINE_LEN);
                   1831:                ++c_token;
                   1832:            } else {
                   1833:                strcpy(timelabel.text, DEFAULT_TIMESTAMP_FORMAT);
                   1834:            }
                   1835:            if (almost_equals(c_token,"t$op")) {
                   1836:                timelabel_bottom = FALSE;
                   1837:                ++c_token;
                   1838:            } else if (almost_equals(c_token, "b$ottom")) {
                   1839:                timelabel_bottom = TRUE;
                   1840:                ++c_token;
                   1841:            }
                   1842:            if (almost_equals(c_token,"r$otate")) {
                   1843:                timelabel_rotate = TRUE;
                   1844:                ++c_token;
                   1845:            } else if (almost_equals(c_token, "n$orotate")) {
                   1846:                timelabel_rotate = FALSE;
                   1847:                ++c_token;
                   1848:            }
                   1849:            /* We have x,y offsets specified */
                   1850:            if (!END_OF_COMMAND && !equals(c_token,","))
                   1851:                timelabel.xoffset = real(const_express(&a));
                   1852:            if (!END_OF_COMMAND && equals(c_token,",")) {
                   1853:                c_token++;
                   1854:                timelabel.yoffset = real(const_express(&a));
                   1855:            }
                   1856:            if (!END_OF_COMMAND && isstring(c_token)) {
                   1857:                quote_str(timelabel.font, c_token, MAX_LINE_LEN);
                   1858:                ++c_token;
                   1859:            } else {
                   1860:                *timelabel.font = 0;
                   1861:            }
                   1862:        }
                   1863:     } else if (almost_equals(c_token,"not$imestamp")) {
                   1864:        *timelabel.text = 0;
                   1865:        c_token++;
                   1866:     } else if (almost_equals(c_token,"vi$ew")) {
                   1867:        int i;
                   1868:        TBOOLEAN was_comma = TRUE;
                   1869:        double local_vals[4];
                   1870:        struct value a;
                   1871:
                   1872:        local_vals[0] = surface_rot_x;
                   1873:        local_vals[1] = surface_rot_z;
                   1874:        local_vals[2] = surface_scale;
                   1875:        local_vals[3] = surface_zscale;
                   1876:        c_token++;
                   1877:        for (i = 0; i < 4 && !(END_OF_COMMAND);) {
                   1878:            if (equals(c_token,",")) {
                   1879:                if (was_comma) i++;
                   1880:                    was_comma = TRUE;
                   1881:                c_token++;
                   1882:            } else {
                   1883:                if (!was_comma)
                   1884:                    int_error("',' expected",c_token);
                   1885:                local_vals[i] = real(const_express(&a));
                   1886:                i++;
                   1887:                was_comma = FALSE;
                   1888:            }
                   1889:        }
                   1890:
                   1891:        if (local_vals[0] < 0 || local_vals[0] > 180)
                   1892:            int_error("rot_x must be in [0:180] degrees range; view unchanged", c_token);
                   1893:        if (local_vals[1] < 0 || local_vals[1] > 360)
                   1894:            int_error("rot_z must be in [0:360] degrees range; view unchanged", c_token);
                   1895:        if (local_vals[2] < 1e-6)
                   1896:            int_error("scale must be > 0; view unchanged", c_token);
                   1897:        if (local_vals[3] < 1e-6)
                   1898:            int_error("zscale must be > 0; view unchanged", c_token);
                   1899:
                   1900:        surface_rot_x = local_vals[0];
                   1901:        surface_rot_z = local_vals[1];
                   1902:        surface_scale = local_vals[2];
                   1903:        surface_zscale = local_vals[3];
                   1904:     }
                   1905:
                   1906: /* to save replicated code, define a macro */
                   1907: #define PROCESS_RANGE(AXIS,STRING, MIN, MAX, AUTO) \
                   1908: else if (almost_equals(c_token, STRING)) { \
                   1909:  if (!equals(++c_token,"[")) int_error("expecting '['",c_token); \
                   1910:  c_token++; \
                   1911:  AUTO = load_range(AXIS,&MIN,&MAX,AUTO); \
                   1912:  if (!equals(c_token,"]")) int_error("expecting ']'",c_token); \
                   1913:  c_token++; \
                   1914:  if (almost_equals(c_token, "rev$erse")) { \
                   1915:    ++c_token; range_flags[AXIS] |= RANGE_REVERSE;\
                   1916:  } else if (almost_equals(c_token, "norev$erse")) { \
                   1917:    ++c_token; range_flags[AXIS] &= ~RANGE_REVERSE;\
                   1918:  } if (almost_equals(c_token, "wr$iteback")) { \
                   1919:    ++c_token; range_flags[AXIS] |= RANGE_WRITEBACK;\
                   1920:  } else if (almost_equals(c_token, "nowri$teback")) { \
                   1921:    ++c_token; range_flags[AXIS] &= ~RANGE_WRITEBACK;\
                   1922: }}
                   1923:
                   1924:     PROCESS_RANGE(R_AXIS, "rr$ange", rmin, rmax, autoscale_r)
                   1925:     PROCESS_RANGE(T_AXIS, "tr$ange", tmin, tmax, autoscale_t)
                   1926:     PROCESS_RANGE(U_AXIS, "ur$ange", umin, umax, autoscale_u)
                   1927:     PROCESS_RANGE(V_AXIS, "vr$ange", vmin, vmax, autoscale_v)
                   1928:     PROCESS_RANGE(FIRST_X_AXIS, "xr$ange", xmin, xmax, autoscale_x)
                   1929:     PROCESS_RANGE(FIRST_Y_AXIS, "yr$ange", ymin, ymax, autoscale_y)
                   1930:     PROCESS_RANGE(FIRST_Z_AXIS, "zr$ange", zmin, zmax, autoscale_z)
                   1931:     PROCESS_RANGE(SECOND_X_AXIS, "x2r$ange", x2min, x2max, autoscale_x2)
                   1932:     PROCESS_RANGE(SECOND_Y_AXIS, "y2r$ange", y2min, y2max, autoscale_y2)
                   1933:
                   1934:     else if (almost_equals(c_token,"z$ero")) {
                   1935:        struct value a;
                   1936:        c_token++;
                   1937:        zero = magnitude(const_express(&a));
                   1938:     } else if (almost_equals(c_token,"multi$plot")) {
                   1939:        term_start_multiplot();
                   1940:        c_token++;
                   1941:     } else if (almost_equals(c_token,"nomulti$plot")) {
                   1942:        term_end_multiplot();
                   1943:        c_token++;
                   1944:     } else
                   1945:        return(FALSE);  /* no command match */
                   1946:
                   1947:     return(TRUE);
                   1948: }
                   1949:
                   1950:
                   1951: /*********** Support functions for set_command ***********/
                   1952:
                   1953: /*
                   1954:  * The set.c PROCESS_TIC_PROP macro has the following characteristics:
                   1955:  *   (a) options must in the correct order
                   1956:  *   (b) 'set xtics' (no option) resets only the interval (FREQ)
                   1957:  *       {it will also negate NO_TICS, see (d)}
                   1958:  *   (c) changing any property also resets the interval to automatic
                   1959:  *   (d) set no[xy]tics; set [xy]tics changes border to nomirror, rather
                   1960:  *       than to the default, mirror.
                   1961:  *   (e) effect of 'set no[]tics; set []tics border ...' is compiler
                   1962:  *       dependent;  if '!(TICS)' is evaluated first, 'border' is an
                   1963:  *       undefined variable :-(
                   1964:  *
                   1965:  * This function replaces the macro, and introduces a new option
                   1966:  * 'au$tofreq' to give somewhat different behaviour:
                   1967:  *   (a) no change
                   1968:  *   (b) 'set xtics' (no option) only affects NO_TICS;  'autofreq' resets
                   1969:  *       the interval calulation to automatic
                   1970:  *   (c) the interval mode is not affected by changing some other option
                   1971:  *   (d) if NO_TICS, set []tics will restore defaults (borders, mirror
                   1972:  *       where appropriate)
                   1973:  *   (e) if (NO_TICS), border option is processed.
                   1974:  *
                   1975:  *  A 'default' option could easily be added to reset all options to
                   1976:  *  the initial values - mostly book-keeping.
                   1977:  *
                   1978:  *  To retain tic properties after setting no[]tics may also be
                   1979:  *  straightforward (save value as negative), but requires changes
                   1980:  *  in other code ( e.g. for  'if (xtics)', use 'if (xtics > 0)'
                   1981:  */
                   1982:
                   1983: static int set_tic_prop(TICS, MTICS, FREQ, tdef, AXIS, ROTATE, tic_side)
                   1984: /*    generates PROCESS_TIC_PROP strings from tic_side, e.g. "x2"
                   1985:    STRING, NOSTRING, MONTH, NOMONTH, DAY, NODAY, MINISTRING, NOMINI
                   1986:    "nox2t$ics"     "nox2m$tics"  "nox2d$tics"    "nomx2t$ics"
                   1987:  */
                   1988:
                   1989: int *TICS, *MTICS, AXIS;
                   1990: double *FREQ;
                   1991: struct ticdef *tdef;
                   1992: TBOOLEAN *ROTATE;
                   1993: char *tic_side;
                   1994:
                   1995:
                   1996: {
                   1997:     int match = 0;             /* flag, set by matching a tic command */
                   1998:     char nocmd[12];            /* fill w/ "no"+'tic_side'+suffix */
                   1999:     char *cmdptr, *sfxptr;
                   2000:
                   2001:     (void) strcpy(nocmd, "no");
                   2002:     cmdptr = &nocmd[2];
                   2003:     (void) strcpy(cmdptr, tic_side);
                   2004:     sfxptr = &nocmd[strlen(nocmd)];
                   2005:     (void) strcpy(sfxptr, "t$ics");    /* STRING */
                   2006:
                   2007:     if (almost_equals(c_token, cmdptr)) {
                   2008:        match = 1;
                   2009:        if (almost_equals(++c_token, "ax$is")) {
                   2010:            *TICS &= ~TICS_ON_BORDER;
                   2011:            *TICS |= TICS_ON_AXIS;
                   2012:            ++c_token;
                   2013:        }
                   2014:        /* if tics are off, reset to default (border) */
                   2015:        if (*TICS == NO_TICS) {
                   2016:            *TICS = TICS_ON_BORDER;
                   2017:            if (!strcmp(tic_side, "x") || !strcmp(tic_side, "y")) {
                   2018:                *TICS |= TICS_MIRROR;
                   2019:            }
                   2020:        }
                   2021:        if (almost_equals(c_token, "bo$rder")) {
                   2022:            *TICS &= ~TICS_ON_AXIS;
                   2023:            *TICS |= TICS_ON_BORDER;
                   2024:            ++c_token;
                   2025:        }
                   2026:        if (almost_equals(c_token, "mi$rror")) {
                   2027:            *TICS |= TICS_MIRROR;
                   2028:            ++c_token;
                   2029:        } else if (almost_equals(c_token, "nomi$rror")) {
                   2030:            *TICS &= ~TICS_MIRROR;
                   2031:            ++c_token;
                   2032:        }
                   2033:        if (almost_equals(c_token, "ro$tate")) {
                   2034:            *ROTATE = TRUE;
                   2035:            ++c_token;
                   2036:        } else if (almost_equals(c_token, "noro$tate")) {
                   2037:            *ROTATE = FALSE;
                   2038:            ++c_token;
                   2039:        }
                   2040:        if (almost_equals(c_token, "au$tofreq")) {      /* auto tic interval */
                   2041:            ++c_token;
                   2042:            if (tdef->type == TIC_USER) {
                   2043:                free_marklist(tdef->def.user);
                   2044:                tdef->def.user = NULL;
                   2045:            }
                   2046:            tdef->type = TIC_COMPUTED;
                   2047:        }
                   2048:        /* user spec. is last */
                   2049:        else if (!END_OF_COMMAND) {
                   2050:            load_tics(AXIS, tdef);
                   2051:        }
                   2052:     }
                   2053:     if (almost_equals(c_token, nocmd)) {       /* NOSTRING */
                   2054:        *TICS = NO_TICS;
                   2055:        c_token++;
                   2056:        match = 1;
                   2057:     }
                   2058: /* other options */
                   2059:
                   2060:     (void) strcpy(sfxptr, "m$tics");   /* MONTH */
                   2061:     if (almost_equals(c_token, cmdptr)) {
                   2062:        if (tdef->type == TIC_USER) {
                   2063:            free_marklist(tdef->def.user);
                   2064:            tdef->def.user = NULL;
                   2065:        }
                   2066:        tdef->type = TIC_MONTH;
                   2067:        ++c_token;
                   2068:        match = 1;
                   2069:     }
                   2070:     if (almost_equals(c_token, nocmd)) {       /* NOMONTH */
                   2071:        tdef->type = TIC_COMPUTED;
                   2072:        ++c_token;
                   2073:        match = 1;
                   2074:     }
                   2075:     (void) strcpy(sfxptr, "d$tics");   /* DAYS */
                   2076:     if (almost_equals(c_token, cmdptr)) {
                   2077:        match = 1;
                   2078:        if (tdef->type == TIC_USER) {
                   2079:            free_marklist(tdef->def.user);
                   2080:            tdef->def.user = NULL;
                   2081:        }
                   2082:        tdef->type = TIC_DAY;
                   2083:        ++c_token;
                   2084:     }
                   2085:     if (almost_equals(c_token, nocmd)) {       /* NODAYS */
                   2086:        tdef->type = TIC_COMPUTED;
                   2087:        ++c_token;
                   2088:        match = 1;
                   2089:     }
                   2090:     *cmdptr = 'm';
                   2091:     (void) strcpy(cmdptr + 1, tic_side);
                   2092:     (void) strcat(cmdptr, "t$ics");    /* MINISTRING */
                   2093:
                   2094:     if (almost_equals(c_token, cmdptr)) {
                   2095:        struct value freq;
                   2096:        c_token++;
                   2097:        match = 1;
                   2098:        if (END_OF_COMMAND) {
                   2099:            *MTICS = MINI_AUTO;
                   2100:        } else if (almost_equals(c_token, "def$ault")) {
                   2101:            *MTICS = MINI_DEFAULT;
                   2102:            ++c_token;
                   2103:        } else {
                   2104:            *FREQ = real(const_express(&freq));
                   2105:            *FREQ = floor(*FREQ);
                   2106:            *MTICS = MINI_USER;
                   2107:        }
                   2108:     }
                   2109:     if (almost_equals(c_token, nocmd)) {       /* NOMINI */
                   2110:        *MTICS = FALSE;
                   2111:        c_token++;
                   2112:        match = 1;
                   2113:     }
                   2114:     return (match);
                   2115: }
                   2116:
                   2117:
                   2118: /* process a 'set {x/y/z}label command */
                   2119: /* set {x/y/z}label {label_text} {x}{,y} */
                   2120: static void set_xyzlabel(label)
                   2121: label_struct *label;
                   2122: {
                   2123:     c_token++;
                   2124:     if (END_OF_COMMAND) {      /* no label specified */
                   2125:        *label->text = '\0';
                   2126:        return;
                   2127:     }
                   2128:     if (isstring(c_token)) {
                   2129:        /* We have string specified - grab it. */
                   2130:        quote_str(label->text, c_token, MAX_LINE_LEN);
                   2131:        c_token++;
                   2132:     }
                   2133:     if (END_OF_COMMAND)
                   2134:        return;
                   2135:
                   2136:     if (!almost_equals(c_token, "font") && !isstring(c_token)) {
                   2137:        /* We have x,y offsets specified */
                   2138:        struct value a;
                   2139:        if (!equals(c_token, ","))
                   2140:            label->xoffset = real(const_express(&a));
                   2141:
                   2142:        if (END_OF_COMMAND)
                   2143:            return;
                   2144:
                   2145:        if (equals(c_token, ",")) {
                   2146:            c_token++;
                   2147:            label->yoffset = real(const_express(&a));
                   2148:        }
                   2149:     }
                   2150:     if (END_OF_COMMAND)
                   2151:        return;
                   2152:
                   2153:     /* optional keyword 'font' can go here */
                   2154:
                   2155:     if (almost_equals(c_token, "f$ont"))
                   2156:        ++c_token;              /* skip it */
                   2157:
                   2158:     if (!isstring(c_token))
                   2159:        int_error("Expected font", c_token);
                   2160:
                   2161:     quote_str(label->font, c_token, MAX_LINE_LEN);
                   2162:     c_token++;
                   2163: }
                   2164:
                   2165: /* process a 'set label' command */
                   2166: /* set label {tag} {label_text} {at x,y} {pos} {font name,size} */
                   2167: /* Entry font added by DJL */
                   2168: static void set_label()
                   2169: {
                   2170:     struct value a;
                   2171:     struct text_label *this_label = NULL;
                   2172:     struct text_label *new_label = NULL;
                   2173:     struct text_label *prev_label = NULL;
                   2174:     struct position pos;
                   2175:     char text[MAX_LINE_LEN + 1], font[MAX_LINE_LEN + 1];
                   2176:     enum JUSTIFY just = LEFT;
                   2177:     int rotate = 0;
                   2178:     int tag;
                   2179:     TBOOLEAN set_text, set_position, set_just = FALSE, set_rot = FALSE,
                   2180:      set_font;
                   2181:
                   2182:     /* get tag */
                   2183:     if (!END_OF_COMMAND
                   2184:        && !isstring(c_token)
                   2185:        && !equals(c_token, "at")
                   2186:        && !equals(c_token, "left")
                   2187:        && !equals(c_token, "center")
                   2188:        && !equals(c_token, "centre")
                   2189:        && !equals(c_token, "right")
                   2190:        && !almost_equals(c_token, "rot$ate")
                   2191:        && !almost_equals(c_token, "norot$ate")
                   2192:        && !equals(c_token, "font")) {
                   2193:        /* must be a tag expression! */
                   2194:        tag = (int) real(const_express(&a));
                   2195:        if (tag <= 0)
                   2196:            int_error("tag must be > zero", c_token);
                   2197:     } else
                   2198:        tag = assign_label_tag();       /* default next tag */
                   2199:
                   2200:     /* get text */
                   2201:     if (!END_OF_COMMAND && isstring(c_token)) {
                   2202:        /* get text */
                   2203:        quote_str(text, c_token, MAX_LINE_LEN);
                   2204:        c_token++;
                   2205:        set_text = TRUE;
                   2206:     } else {
                   2207:        text[0] = '\0';         /* default no text */
                   2208:        set_text = FALSE;
                   2209:     }
                   2210:
                   2211:     /* get justification - what the heck, let him put it here */
                   2212:     if (!END_OF_COMMAND && !equals(c_token, "at") && !equals(c_token, "font")
                   2213:        && !almost_equals(c_token, "rot$ate") && !almost_equals(c_token, "norot$ate")) {
                   2214:        if (almost_equals(c_token, "l$eft")) {
                   2215:            just = LEFT;
                   2216:        } else if (almost_equals(c_token, "c$entre")
                   2217:                   || almost_equals(c_token, "c$enter")) {
                   2218:            just = CENTRE;
                   2219:        } else if (almost_equals(c_token, "r$ight")) {
                   2220:            just = RIGHT;
                   2221:        } else
                   2222:            int_error("bad syntax in set label", c_token);
                   2223:        c_token++;
                   2224:        set_just = TRUE;
                   2225:     }
                   2226:     /* get position */
                   2227:     if (!END_OF_COMMAND && equals(c_token, "at")) {
                   2228:        c_token++;
                   2229:
                   2230:        get_position(&pos);
                   2231:        set_position = TRUE;
                   2232:     } else {
                   2233:        pos.x = pos.y = pos.z = 0;
                   2234:        pos.scalex = pos.scaley = pos.scalez = first_axes;
                   2235:        set_position = FALSE;
                   2236:     }
                   2237:
                   2238:     /* get justification */
                   2239:     if (!END_OF_COMMAND && !almost_equals(c_token, "rot$ate") && !almost_equals(c_token, "norot$ate") && !equals(c_token, "font")) {
                   2240:        if (set_just)
                   2241:            int_error("only one justification is allowed", c_token);
                   2242:        if (almost_equals(c_token, "l$eft")) {
                   2243:            just = LEFT;
                   2244:        } else if (almost_equals(c_token, "c$entre")
                   2245:                   || almost_equals(c_token, "c$enter")) {
                   2246:            just = CENTRE;
                   2247:        } else if (almost_equals(c_token, "r$ight")) {
                   2248:            just = RIGHT;
                   2249:        } else
                   2250:            int_error("bad syntax in set label", c_token);
                   2251:
                   2252:        c_token++;
                   2253:        set_just = TRUE;
                   2254:     }
                   2255:     /* get rotation (added by RCC) */
                   2256:     if (!END_OF_COMMAND && !equals(c_token, "font")) {
                   2257:        if (almost_equals(c_token, "rot$ate")) {
                   2258:            rotate = TRUE;
                   2259:        } else if (almost_equals(c_token, "norot$ate")) {
                   2260:            rotate = FALSE;
                   2261:        } else
                   2262:            int_error("bad syntax in set label", c_token);
                   2263:
                   2264:        c_token++;
                   2265:        set_rot = TRUE;
                   2266:     }
                   2267:     /* get font */
                   2268:     font[0] = NUL;
                   2269:     set_font = FALSE;
                   2270:     if (!END_OF_COMMAND && equals(c_token, "font")) {
                   2271:        c_token++;
                   2272:        if (END_OF_COMMAND)
                   2273:            int_error("font name and size expected", c_token);
                   2274:        if (isstring(c_token)) {
                   2275:            quote_str(font, c_token, MAX_ID_LEN);
                   2276:            /* get 'name,size', no further check */
                   2277:            set_font = TRUE;
                   2278:        } else
                   2279:            int_error("'fontname,fontsize' expected", c_token);
                   2280:
                   2281:        c_token++;
                   2282:     }                          /* Entry font added by DJL */
                   2283:     if (!END_OF_COMMAND)
                   2284:        int_error("extraenous or out-of-order arguments in set label", c_token);
                   2285:
                   2286:     /* OK! add label */
                   2287:     if (first_label != NULL) { /* skip to last label */
                   2288:        for (this_label = first_label; this_label != NULL;
                   2289:             prev_label = this_label, this_label = this_label->next)
                   2290:            /* is this the label we want? */
                   2291:            if (tag <= this_label->tag)
                   2292:                break;
                   2293:     }
                   2294:     if (this_label != NULL && tag == this_label->tag) {
                   2295:        /* changing the label */
                   2296:        if (set_position) {
                   2297:            this_label->place = pos;
                   2298:        }
                   2299:        if (set_text)
                   2300:            (void) strcpy(this_label->text, text);
                   2301:        if (set_just)
                   2302:            this_label->pos = just;
                   2303:        if (set_rot)
                   2304:            this_label->rotate = rotate;
                   2305:        if (set_font)
                   2306:            (void) strcpy(this_label->font, font);
                   2307:     } else {
                   2308:        /* adding the label */
                   2309:        new_label = (struct text_label *)
                   2310:            gp_alloc((unsigned long) sizeof(struct text_label), "label");
                   2311:        if (prev_label != NULL)
                   2312:            prev_label->next = new_label;       /* add it to end of list */
                   2313:        else
                   2314:            first_label = new_label;    /* make it start of list */
                   2315:        new_label->tag = tag;
                   2316:        new_label->next = this_label;
                   2317:        new_label->place = pos;
                   2318:        (void) strcpy(new_label->text, text);
                   2319:        new_label->pos = just;
                   2320:        new_label->rotate = rotate;
                   2321:        (void) strcpy(new_label->font, font);
                   2322:     }
                   2323: }                              /* Entry font added by DJL */
                   2324:
                   2325: /* process 'set nolabel' command */
                   2326: /* set nolabel {tag} */
                   2327: static void set_nolabel()
                   2328: {
                   2329:     struct value a;
                   2330:     struct text_label *this_label;
                   2331:     struct text_label *prev_label;
                   2332:     int tag;
                   2333:
                   2334:     if (END_OF_COMMAND) {
                   2335:        /* delete all labels */
                   2336:        while (first_label != NULL)
                   2337:            delete_label((struct text_label *) NULL, first_label);
                   2338:     } else {
                   2339:        /* get tag */
                   2340:        tag = (int) real(const_express(&a));
                   2341:        if (!END_OF_COMMAND)
                   2342:            int_error("extraneous arguments to set nolabel", c_token);
                   2343:        for (this_label = first_label, prev_label = NULL;
                   2344:             this_label != NULL;
                   2345:             prev_label = this_label, this_label = this_label->next) {
                   2346:            if (this_label->tag == tag) {
                   2347:                delete_label(prev_label, this_label);
                   2348:                return;         /* exit, our job is done */
                   2349:            }
                   2350:        }
                   2351:        int_error("label not found", c_token);
                   2352:     }
                   2353: }
                   2354:
                   2355: /* assign a new label tag */
                   2356: /* labels are kept sorted by tag number, so this is easy */
                   2357: static int /* the lowest unassigned tag number */ assign_label_tag()
                   2358: {
                   2359:     struct text_label *this_label;
                   2360:     int last = 0;              /* previous tag value */
                   2361:
                   2362:     for (this_label = first_label; this_label != NULL;
                   2363:         this_label = this_label->next)
                   2364:        if (this_label->tag == last + 1)
                   2365:            last++;
                   2366:        else
                   2367:            break;
                   2368:
                   2369:     return (last + 1);
                   2370: }
                   2371:
                   2372: /* delete label from linked list started by first_label.
                   2373:  * called with pointers to the previous label (prev) and the
                   2374:  * label to delete (this).
                   2375:  * If there is no previous label (the label to delete is
                   2376:  * first_label) then call with prev = NULL.
                   2377:  */
                   2378: static void delete_label(prev, this)
                   2379: struct text_label *prev, *this;
                   2380: {
                   2381:     if (this != NULL) {                /* there really is something to delete */
                   2382:        if (prev != NULL)       /* there is a previous label */
                   2383:            prev->next = this->next;
                   2384:        else                    /* this = first_label so change first_label */
                   2385:            first_label = this->next;
                   2386:        free((char *) this);
                   2387:     }
                   2388: }
                   2389:
                   2390:
                   2391: /* process a 'set arrow' command */
                   2392: /* set arrow {tag} {from x,y} {to x,y} {{no}head} */
                   2393: static void set_arrow()
                   2394: {
                   2395:     struct value a;
                   2396:     struct arrow_def *this_arrow = NULL;
                   2397:     struct arrow_def *new_arrow = NULL;
                   2398:     struct arrow_def *prev_arrow = NULL;
                   2399:     struct position spos, epos;
                   2400:     struct lp_style_type loc_lp;
                   2401:     int axes = FIRST_AXES;
                   2402:     int tag;
                   2403:     TBOOLEAN set_start, set_end, head = 1, set_axes = 0, set_line = 0;
                   2404:
                   2405:     /* Init struct lp_style_type loc_lp */
                   2406:     reset_lp_properties (&loc_lp);
                   2407:
                   2408:     /* get tag */
                   2409:     if (!END_OF_COMMAND
                   2410:        && !equals(c_token, "from")
                   2411:        && !equals(c_token, "to")
                   2412:        && !equals(c_token, "first")
                   2413:        && !equals(c_token, "second")) {
                   2414:        /* must be a tag expression! */
                   2415:        tag = (int) real(const_express(&a));
                   2416:        if (tag <= 0)
                   2417:            int_error("tag must be > zero", c_token);
                   2418:     } else
                   2419:        tag = assign_arrow_tag();       /* default next tag */
                   2420:
                   2421:     if (!END_OF_COMMAND && equals(c_token, "first")) {
                   2422:        ++c_token;
                   2423:        axes = FIRST_AXES;
                   2424:        set_axes = 1;
                   2425:     } else if (!END_OF_COMMAND && equals(c_token, "second")) {
                   2426:        ++c_token;
                   2427:        axes = SECOND_AXES;
                   2428:        set_axes = 1;
                   2429:     }
                   2430:     /* get start position */
                   2431:     if (!END_OF_COMMAND && equals(c_token, "from")) {
                   2432:        c_token++;
                   2433:        if (END_OF_COMMAND)
                   2434:            int_error("start coordinates expected", c_token);
                   2435:        /* get coordinates */
                   2436:        get_position(&spos);
                   2437:        set_start = TRUE;
                   2438:     } else {
                   2439:        spos.x = spos.y = spos.z = 0;
                   2440:        spos.scalex = spos.scaley = spos.scalez = first_axes;
                   2441:        set_start = FALSE;
                   2442:     }
                   2443:
                   2444:     /* get end position */
                   2445:     if (!END_OF_COMMAND && equals(c_token, "to")) {
                   2446:        c_token++;
                   2447:        if (END_OF_COMMAND)
                   2448:            int_error("end coordinates expected", c_token);
                   2449:        /* get coordinates */
                   2450:        get_position(&epos);
                   2451:        set_end = TRUE;
                   2452:     } else {
                   2453:        epos.x = epos.y = epos.z = 0;
                   2454:        epos.scalex = epos.scaley = epos.scalez = first_axes;
                   2455:        set_end = FALSE;
                   2456:     }
                   2457:
                   2458:     /* get start position - what the heck, either order is ok */
                   2459:     if (!END_OF_COMMAND && equals(c_token, "from")) {
                   2460:        if (set_start)
                   2461:            int_error("only one 'from' is allowed", c_token);
                   2462:        c_token++;
                   2463:        if (END_OF_COMMAND)
                   2464:            int_error("start coordinates expected", c_token);
                   2465:        /* get coordinates */
                   2466:        get_position(&spos);
                   2467:        set_start = TRUE;
                   2468:     }
                   2469:     if (!END_OF_COMMAND && equals(c_token, "nohead")) {
                   2470:        c_token++;
                   2471:        head = 0;
                   2472:     }
                   2473:     if (!END_OF_COMMAND && equals(c_token, "head")) {
                   2474:        c_token++;
                   2475:        head = 1;
                   2476:     }
                   2477:     set_line = 1;
                   2478:
                   2479:     /* pick up a line spec - allow ls, but no point. */
                   2480:     LP_PARSE(loc_lp, 1, 0, 0, 0);
                   2481:     loc_lp.pointflag = 0;      /* standard value for arrows, don't use points */
                   2482:
                   2483:     if (!END_OF_COMMAND)
                   2484:        int_error("extraneous or out-of-order arguments in set arrow", c_token);
                   2485:
                   2486:     /* OK! add arrow */
                   2487:     if (first_arrow != NULL) { /* skip to last arrow */
                   2488:        for (this_arrow = first_arrow; this_arrow != NULL;
                   2489:             prev_arrow = this_arrow, this_arrow = this_arrow->next)
                   2490:            /* is this the arrow we want? */
                   2491:            if (tag <= this_arrow->tag)
                   2492:                break;
                   2493:     }
                   2494:     if (this_arrow != NULL && tag == this_arrow->tag) {
                   2495:        /* changing the arrow */
                   2496:        if (set_start) {
                   2497:            this_arrow->start = spos;
                   2498:        }
                   2499:        if (set_end) {
                   2500:            this_arrow->end = epos;
                   2501:        }
                   2502:        this_arrow->head = head;
                   2503:        if (set_line) {
                   2504:            this_arrow->lp_properties = loc_lp;
                   2505:        }
                   2506:     } else {
                   2507:        /* adding the arrow */
                   2508:        new_arrow = (struct arrow_def *)
                   2509:            gp_alloc((unsigned long) sizeof(struct arrow_def), "arrow");
                   2510:        if (prev_arrow != NULL)
                   2511:            prev_arrow->next = new_arrow;       /* add it to end of list */
                   2512:        else
                   2513:            first_arrow = new_arrow;    /* make it start of list */
                   2514:        new_arrow->tag = tag;
                   2515:        new_arrow->next = this_arrow;
                   2516:        new_arrow->start = spos;
                   2517:        new_arrow->end = epos;
                   2518:        new_arrow->head = head;
                   2519:        new_arrow->lp_properties = loc_lp;
                   2520:     }
                   2521: }
                   2522:
                   2523: /* process 'set noarrow' command */
                   2524: /* set noarrow {tag} */
                   2525: static void set_noarrow()
                   2526: {
                   2527:     struct value a;
                   2528:     struct arrow_def *this_arrow;
                   2529:     struct arrow_def *prev_arrow;
                   2530:     int tag;
                   2531:
                   2532:     if (END_OF_COMMAND) {
                   2533:        /* delete all arrows */
                   2534:        while (first_arrow != NULL)
                   2535:            delete_arrow((struct arrow_def *) NULL, first_arrow);
                   2536:     } else {
                   2537:        /* get tag */
                   2538:        tag = (int) real(const_express(&a));
                   2539:        if (!END_OF_COMMAND)
                   2540:            int_error("extraneous arguments to set noarrow", c_token);
                   2541:        for (this_arrow = first_arrow, prev_arrow = NULL;
                   2542:             this_arrow != NULL;
                   2543:             prev_arrow = this_arrow, this_arrow = this_arrow->next) {
                   2544:            if (this_arrow->tag == tag) {
                   2545:                delete_arrow(prev_arrow, this_arrow);
                   2546:                return;         /* exit, our job is done */
                   2547:            }
                   2548:        }
                   2549:        int_error("arrow not found", c_token);
                   2550:     }
                   2551: }
                   2552:
                   2553: /* assign a new arrow tag */
                   2554: /* arrows are kept sorted by tag number, so this is easy */
                   2555: static int /* the lowest unassigned tag number */ assign_arrow_tag()
                   2556: {
                   2557:     struct arrow_def *this_arrow;
                   2558:     int last = 0;              /* previous tag value */
                   2559:
                   2560:     for (this_arrow = first_arrow; this_arrow != NULL;
                   2561:         this_arrow = this_arrow->next)
                   2562:        if (this_arrow->tag == last + 1)
                   2563:            last++;
                   2564:        else
                   2565:            break;
                   2566:
                   2567:     return (last + 1);
                   2568: }
                   2569:
                   2570: /* delete arrow from linked list started by first_arrow.
                   2571:  * called with pointers to the previous arrow (prev) and the
                   2572:  * arrow to delete (this).
                   2573:  * If there is no previous arrow (the arrow to delete is
                   2574:  * first_arrow) then call with prev = NULL.
                   2575:  */
                   2576: static void delete_arrow(prev, this)
                   2577: struct arrow_def *prev, *this;
                   2578: {
                   2579:     if (this != NULL) {                /* there really is something to delete */
                   2580:        if (prev != NULL)       /* there is a previous arrow */
                   2581:            prev->next = this->next;
                   2582:        else                    /* this = first_arrow so change first_arrow */
                   2583:            first_arrow = this->next;
                   2584:        free((char *) this);
                   2585:     }
                   2586: }
                   2587:
                   2588: /* ======================================================== */
                   2589: /* process a 'set linestyle' command */
                   2590: /* set linestyle {tag} {linetype n} {linewidth x} {pointtype n} {pointsize x} */
                   2591: static void set_linestyle()
                   2592: {
                   2593:     struct value a;
                   2594:     struct linestyle_def *this_linestyle = NULL;
                   2595:     struct linestyle_def *new_linestyle = NULL;
                   2596:     struct linestyle_def *prev_linestyle = NULL;
                   2597:     struct lp_style_type loc_lp;
                   2598:     int tag;
                   2599:
                   2600:     /* Init struct lp_style_type loc_lp */
                   2601:     reset_lp_properties (&loc_lp);
                   2602:
                   2603:     /* get tag */
                   2604:     if (!END_OF_COMMAND) {
                   2605:        /* must be a tag expression! */
                   2606:        tag = (int) real(const_express(&a));
                   2607:        if (tag <= 0)
                   2608:            int_error("tag must be > zero", c_token);
                   2609:     } else
                   2610:        tag = assign_linestyle_tag();   /* default next tag */
                   2611:
                   2612:     /* pick up a line spec : dont allow ls, do allow point type
                   2613:      * default to same line type = point type = tag
                   2614:      */
                   2615:     LP_PARSE(loc_lp, 0, 1, tag - 1, tag - 1);
                   2616:
                   2617:     if (!END_OF_COMMAND)
                   2618:        int_error("extraneous or out-of-order arguments in set linestyle", c_token);
                   2619:
                   2620:     /* OK! add linestyle */
                   2621:     if (first_linestyle != NULL) {     /* skip to last linestyle */
                   2622:        for (this_linestyle = first_linestyle; this_linestyle != NULL;
                   2623:             prev_linestyle = this_linestyle, this_linestyle = this_linestyle->next)
                   2624:            /* is this the linestyle we want? */
                   2625:            if (tag <= this_linestyle->tag)
                   2626:                break;
                   2627:     }
                   2628:     if (this_linestyle != NULL && tag == this_linestyle->tag) {
                   2629:        /* changing the linestyle */
                   2630:        this_linestyle->lp_properties = loc_lp;
                   2631:     } else {
                   2632:        /* adding the linestyle */
                   2633:        new_linestyle = (struct linestyle_def *)
                   2634:            gp_alloc((unsigned long) sizeof(struct linestyle_def), "linestyle");
                   2635:        if (prev_linestyle != NULL)
                   2636:            prev_linestyle->next = new_linestyle;       /* add it to end of list */
                   2637:        else
                   2638:            first_linestyle = new_linestyle;    /* make it start of list */
                   2639:        new_linestyle->tag = tag;
                   2640:        new_linestyle->next = this_linestyle;
                   2641:        new_linestyle->lp_properties = loc_lp;
                   2642:     }
                   2643: }
                   2644:
                   2645: /* process 'set nolinestyle' command */
                   2646: /* set nolinestyle {tag} */
                   2647: static void set_nolinestyle()
                   2648: {
                   2649:     struct value a;
                   2650:     struct linestyle_def *this, *prev;
                   2651:     int tag;
                   2652:
                   2653:     if (END_OF_COMMAND) {
                   2654:        /* delete all linestyles */
                   2655:        while (first_linestyle != NULL)
                   2656:            delete_linestyle((struct linestyle_def *) NULL, first_linestyle);
                   2657:     } else {
                   2658:        /* get tag */
                   2659:        tag = (int) real(const_express(&a));
                   2660:        if (!END_OF_COMMAND)
                   2661:            int_error("extraneous arguments to set nolinestyle", c_token);
                   2662:        for (this = first_linestyle, prev = NULL;
                   2663:             this != NULL;
                   2664:             prev = this, this = this->next) {
                   2665:            if (this->tag == tag) {
                   2666:                delete_linestyle(prev, this);
                   2667:                return;         /* exit, our job is done */
                   2668:            }
                   2669:        }
                   2670:        int_error("linestyle not found", c_token);
                   2671:     }
                   2672: }
                   2673:
                   2674: /* assign a new linestyle tag */
                   2675: /* linestyles are kept sorted by tag number, so this is easy */
                   2676: static int /* the lowest unassigned tag number */ assign_linestyle_tag()
                   2677: {
                   2678:     struct linestyle_def *this;
                   2679:     int last = 0;              /* previous tag value */
                   2680:
                   2681:     for (this = first_linestyle; this != NULL; this = this->next)
                   2682:        if (this->tag == last + 1)
                   2683:            last++;
                   2684:        else
                   2685:            break;
                   2686:
                   2687:     return (last + 1);
                   2688: }
                   2689:
                   2690: /* delete linestyle from linked list started by first_linestyle.
                   2691:  * called with pointers to the previous linestyle (prev) and the
                   2692:  * linestyle to delete (this).
                   2693:  * If there is no previous linestyle (the linestyle to delete is
                   2694:  * first_linestyle) then call with prev = NULL.
                   2695:  */
                   2696: static void delete_linestyle(prev, this)
                   2697: struct linestyle_def *prev, *this;
                   2698: {
                   2699:     if (this != NULL) {                /* there really is something to delete */
                   2700:        if (prev != NULL)       /* there is a previous linestyle */
                   2701:            prev->next = this->next;
                   2702:        else                    /* this = first_linestyle so change first_linestyle */
                   2703:            first_linestyle = this->next;
                   2704:        free((char *) this);
                   2705:     }
                   2706: }
                   2707:
                   2708: /*
                   2709:  * auxiliary functions for the `set linestyle` command
                   2710:  */
                   2711:
                   2712: void lp_use_properties(lp, tag, pointflag)
                   2713: struct lp_style_type *lp;
                   2714: int tag, pointflag;
                   2715: {
                   2716:     /*  This function looks for a linestyle defined by 'tag' and copies
                   2717:      *  its data into the structure 'lp'.
                   2718:      *
                   2719:      *  If 'pointflag' equals ZERO, the properties belong to a linestyle
                   2720:      *  used with arrows.  In this case no point properties will be
                   2721:      *  passed to the terminal (cf. function 'term_apply_lp_properties' below).
                   2722:      */
                   2723:
                   2724:     struct linestyle_def *this;
                   2725:
                   2726:     this = first_linestyle;
                   2727:     while (this != NULL) {
                   2728:        if (this->tag == tag) {
                   2729:            *lp = this->lp_properties;
                   2730:            lp->pointflag = pointflag;
                   2731:            return;
                   2732:        } else {
                   2733:            this = this->next;
                   2734:        }
                   2735:     }
                   2736:
                   2737:     /* tag not found: */
                   2738:     int_error("linestyle not found", NO_CARET);
                   2739: }
                   2740:
                   2741: /* ======================================================== */
                   2742:
                   2743: enum PLOT_STYLE /* not static; used by command.c */ get_style()
                   2744: {
                   2745:     register enum PLOT_STYLE ps = LINES;       /* HBB: initial value, for 'gcc -W} */
                   2746:
                   2747:     c_token++;
                   2748:     if (almost_equals(c_token, "l$ines"))
                   2749:        ps = LINES;
                   2750:     else if (almost_equals(c_token, "i$mpulses"))
                   2751:        ps = IMPULSES;
                   2752:     else if (almost_equals(c_token, "p$oints"))
                   2753:        ps = POINTSTYLE;
                   2754:     else if (almost_equals(c_token, "linesp$oints") || equals(c_token, "lp"))
                   2755:        ps = LINESPOINTS;
                   2756:     else if (almost_equals(c_token, "d$ots"))
                   2757:        ps = DOTS;
                   2758:     else if (almost_equals(c_token, "ye$rrorbars"))
                   2759:        ps = YERRORBARS;
                   2760:     else if (almost_equals(c_token, "e$rrorbars"))
                   2761:        ps = YERRORBARS;
                   2762:     else if (almost_equals(c_token, "xe$rrorbars"))
                   2763:        ps = XERRORBARS;
                   2764:     else if (almost_equals(c_token, "xye$rrorbars"))
                   2765:        ps = XYERRORBARS;
                   2766:     else if (almost_equals(c_token, "boxes"))
                   2767:        ps = BOXES;
                   2768:     else if (almost_equals(c_token, "boxer$rorbars"))
                   2769:        ps = BOXERROR;
                   2770:     else if (almost_equals(c_token, "boxx$yerrorbars"))
                   2771:        ps = BOXXYERROR;
                   2772:     else if (almost_equals(c_token, "st$eps"))
                   2773:        ps = STEPS;
                   2774:     else if (almost_equals(c_token, "fs$teps"))
                   2775:        ps = FSTEPS;
                   2776:     else if (almost_equals(c_token, "his$teps"))
                   2777:        ps = HISTEPS;
                   2778:     else if (almost_equals(c_token, "vec$tor"))                /* HBB: minor cosmetic change */
                   2779:        ps = VECTOR;
                   2780:     else if (almost_equals(c_token, "fin$ancebars"))
                   2781:        ps = FINANCEBARS;
                   2782:     else if (almost_equals(c_token, "can$dlesticks"))
                   2783:        ps = CANDLESTICKS;
                   2784:     else {
                   2785:        int_error("expecting 'lines', 'points', 'linespoints', 'dots', 'impulses',\n\
                   2786:         'yerrorbars', 'xerrorbars', 'xyerrorbars', 'steps', 'fsteps', 'histeps',\n\
                   2787:         'boxes', 'boxerrorbars', 'boxxyerrorbars', 'vector', 'financebars', 'candlesticks'", c_token);
                   2788:        return LINES;           /* keep gcc -Wuninitialised happy */
                   2789:     }
                   2790:     c_token++;
                   2791:     return (ps);
                   2792: }
                   2793:
                   2794: /* For set [xy]tics... command */
                   2795: static void load_tics(axis, tdef)
                   2796: int axis;
                   2797: struct ticdef *tdef;           /* change this ticdef */
                   2798: {
                   2799:     if (equals(c_token, "(")) {        /* set : TIC_USER */
                   2800:        c_token++;
                   2801:        load_tic_user(axis, tdef);
                   2802:     } else {                   /* series : TIC_SERIES */
                   2803:        load_tic_series(axis, tdef);
                   2804:     }
                   2805: }
                   2806:
                   2807: /* load TIC_USER definition */
                   2808: /* (tic[,tic]...)
                   2809:  * where tic is ["string"] value
                   2810:  * Left paren is already scanned off before entry.
                   2811:  */
                   2812: static void load_tic_user(axis, tdef)
                   2813: int axis;
                   2814: struct ticdef *tdef;
                   2815: {
                   2816:     struct ticmark *list = NULL;       /* start of list */
                   2817:     struct ticmark *last = NULL;       /* end of list */
                   2818:     struct ticmark *tic = NULL;        /* new ticmark */
                   2819:     char temp_string[MAX_LINE_LEN];
                   2820:
                   2821:     while (!END_OF_COMMAND) {
                   2822:        /* parse a new ticmark */
                   2823:        tic = (struct ticmark *) gp_alloc((unsigned long) sizeof(struct ticmark), (char *) NULL);
                   2824:        if (tic == (struct ticmark *) NULL) {
                   2825:            free_marklist(list);
                   2826:            int_error("out of memory for tic mark", c_token);
                   2827:        }
                   2828:        /* syntax is  (  ['format'] value , ... )
                   2829:         * but for timedata, the value itself is a string, which
                   2830:         * complicates things somewhat
                   2831:         */
                   2832:
                   2833:        /* has a string with it? */
                   2834:        if (isstring(c_token) &&
                   2835:            (datatype[axis] != TIME || isstring(c_token + 1))) {
                   2836:            quote_str(temp_string, c_token, MAX_LINE_LEN);
                   2837:            tic->label = gp_alloc((unsigned long) strlen(temp_string) + 1, "tic label");
                   2838:            (void) strcpy(tic->label, temp_string);
                   2839:            c_token++;
                   2840:        } else
                   2841:            tic->label = NULL;
                   2842:
                   2843:        /* in any case get the value */
                   2844:        GET_NUM_OR_TIME(tic->position, axis);
                   2845:        tic->next = NULL;
                   2846:
                   2847:        /* append to list */
                   2848:        if (list == NULL)
                   2849:            last = list = tic;  /* new list */
                   2850:        else {                  /* append to list */
                   2851:            last->next = tic;
                   2852:            last = tic;
                   2853:        }
                   2854:
                   2855:        /* expect "," or ")" here */
                   2856:        if (!END_OF_COMMAND && equals(c_token, ","))
                   2857:            c_token++;          /* loop again */
                   2858:        else
                   2859:            break;              /* hopefully ")" */
                   2860:     }
                   2861:
                   2862:     if (END_OF_COMMAND || !equals(c_token, ")")) {
                   2863:        free_marklist(list);
                   2864:        int_error("expecting right parenthesis )", c_token);
                   2865:     }
                   2866:     c_token++;
                   2867:
                   2868:     /* successful list */
                   2869:     if (tdef->type == TIC_USER) {
                   2870:        /* remove old list */
                   2871:        /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
                   2872:        free_marklist(tdef->def.user);
                   2873:        tdef->def.user = NULL;
                   2874:     }
                   2875:     tdef->type = TIC_USER;
                   2876:     tdef->def.user = list;
                   2877: }
                   2878:
                   2879: static void free_marklist(list)
                   2880: struct ticmark *list;
                   2881: {
                   2882:     register struct ticmark *freeable;
                   2883:
                   2884:     while (list != NULL) {
                   2885:        freeable = list;
                   2886:        list = list->next;
                   2887:        if (freeable->label != NULL)
                   2888:            free((char *) freeable->label);
                   2889:        free((char *) freeable);
                   2890:     }
                   2891: }
                   2892:
                   2893: /* load TIC_SERIES definition */
                   2894: /* [start,]incr[,end] */
                   2895: static void load_tic_series(axis, tdef)
                   2896: int axis;
                   2897: struct ticdef *tdef;
                   2898: {
                   2899:     double start, incr, end;
                   2900:     int incr_token;
                   2901:
                   2902:     GET_NUM_OR_TIME(start, axis);
                   2903:
                   2904:     if (!equals(c_token, ",")) {
                   2905:        /* only step specified */
                   2906:        incr = start;
                   2907:        start = -VERYLARGE;
                   2908:        end = VERYLARGE;
                   2909:     } else {
                   2910:
                   2911:        c_token++;
                   2912:
                   2913:        incr_token = c_token;
                   2914:        GET_NUM_OR_TIME(incr, axis);
                   2915:
                   2916:        if (END_OF_COMMAND)
                   2917:            end = VERYLARGE;
                   2918:        else {
                   2919:            if (!equals(c_token, ","))
                   2920:                int_error("expecting comma to separate incr,end", c_token);
                   2921:            c_token++;
                   2922:            GET_NUM_OR_TIME(end, axis);
                   2923:        }
                   2924:        if (!END_OF_COMMAND)
                   2925:            int_error("tic series is defined by [start,]increment[,end]", c_token);
                   2926:
                   2927:        if (start < end && incr <= 0)
                   2928:            int_error("increment must be positive", incr_token);
                   2929:        if (start > end && incr >= 0)
                   2930:            int_error("increment must be negative", incr_token);
                   2931:        if (start > end) {
                   2932:            /* put in order */
                   2933:            double numtics;
                   2934:            numtics = floor((end * (1 + SIGNIF) - start) / incr);
                   2935:            end = start;
                   2936:            start = end + numtics * incr;
                   2937:            incr = -incr;
                   2938: /*
                   2939:    double temp = start;
                   2940:    start = end;
                   2941:    end = temp;
                   2942:    incr = -incr;
                   2943:  */
                   2944:        }
                   2945:     }
                   2946:
                   2947:     if (tdef->type == TIC_USER) {
                   2948:        /* remove old list */
                   2949:        /* VAX Optimiser was stuffing up following line. Turn Optimiser OFF */
                   2950:        free_marklist(tdef->def.user);
                   2951:        tdef->def.user = NULL;
                   2952:     }
                   2953:     tdef->type = TIC_SERIES;
                   2954:     tdef->def.series.start = start;
                   2955:     tdef->def.series.incr = incr;
                   2956:     tdef->def.series.end = end;
                   2957: }
                   2958:
                   2959: static void load_offsets(a, b, c, d)
                   2960: double *a, *b, *c, *d;
                   2961: {
                   2962:     struct value t;
                   2963:
                   2964:     *a = real(const_express(&t));      /* loff value */
                   2965:     if (!equals(c_token, ","))
                   2966:        return;
                   2967:
                   2968:     c_token++;
                   2969:     *b = real(const_express(&t));      /* roff value */
                   2970:     if (!equals(c_token, ","))
                   2971:        return;
                   2972:
                   2973:     c_token++;
                   2974:     *c = real(const_express(&t));      /* toff value */
                   2975:     if (!equals(c_token, ","))
                   2976:        return;
                   2977:
                   2978:     c_token++;
                   2979:     *d = real(const_express(&t));      /* boff value */
                   2980: }
                   2981:
                   2982: TBOOLEAN                       /* new value for autosc */
                   2983: load_range(axis, a, b, autosc)         /* also used by command.c */
                   2984: int axis;
                   2985: double *a, *b;
                   2986: TBOOLEAN autosc;
                   2987: {
                   2988:     if (equals(c_token, "]"))
                   2989:        return (autosc);
                   2990:     if (END_OF_COMMAND) {
                   2991:        int_error("starting range value or ':' or 'to' expected", c_token);
                   2992:     } else if (!equals(c_token, "to") && !equals(c_token, ":")) {
                   2993:        if (equals(c_token, "*")) {
                   2994:            autosc |= 1;
                   2995:            c_token++;
                   2996:        } else {
                   2997:            GET_NUM_OR_TIME(*a, axis);
                   2998:            autosc &= 2;
                   2999:        }
                   3000:     }
                   3001:     if (!equals(c_token, "to") && !equals(c_token, ":"))
                   3002:        int_error("':' or keyword 'to' expected", c_token);
                   3003:     c_token++;
                   3004:     if (!equals(c_token, "]")) {
                   3005:        if (equals(c_token, "*")) {
                   3006:            autosc |= 2;
                   3007:            c_token++;
                   3008:        } else {
                   3009:            GET_NUM_OR_TIME(*b, axis);
                   3010:            autosc &= 1;
                   3011:        }
                   3012:     }
                   3013:     return (autosc);
                   3014: }
                   3015:
                   3016: /* return 1 if format looks like a numeric format
                   3017:  * ie more than one %{efg}, or %something-else
                   3018:  */
                   3019:
                   3020: static int looks_like_numeric(format)
                   3021: char *format;
                   3022: {
                   3023:     if (!(format = strchr(format, '%')))
                   3024:        return 0;
                   3025:
                   3026:     while (++format, (*format >= '0' && *format <= '9') || *format == '.');
                   3027:
                   3028:     return (*format == 'f' || *format == 'g' || *format == 'e');
                   3029: }
                   3030:
                   3031:
                   3032: /* parse a position of the form
                   3033:  *    [coords] x, [coords] y {,[coords] z}
                   3034:  * where coords is one of first,second.graph,screen
                   3035:  * if first or second, we need to take datatype into account
                   3036:  * mixed co-ordinates are for specialists, but it's not particularly
                   3037:  * hard to implement...
                   3038:  */
                   3039:
                   3040: #define GET_NUMBER_OR_TIME(store,axes,axis) \
                   3041: do{if (axes >= 0 && datatype[axes+axis] == TIME && isstring(c_token) ) { \
                   3042:     char ss[80]; struct tm tm; \
                   3043:     quote_str(ss,c_token, 80); ++c_token; \
                   3044:     if (gstrptime(ss,timefmt,&tm)) store = (double) gtimegm(&tm); \
                   3045:    } else {\
                   3046:     struct value value; \
                   3047:     store = real(const_express(&value));\
                   3048:   }}while(0)
                   3049:
                   3050:
                   3051: /* get_position_type - for use by get_position().
                   3052:  * parses first/second/graph/screen keyword
                   3053:  */
                   3054:
                   3055: static void get_position_type(type, axes)
                   3056: enum position_type *type;
                   3057: int *axes;
                   3058: {
                   3059:     if (almost_equals(c_token, "fir$st")) {
                   3060:        ++c_token;
                   3061:        *type = first_axes;
                   3062:     } else if (almost_equals(c_token, "sec$ond")) {
                   3063:        ++c_token;
                   3064:        *type = second_axes;
                   3065:     } else if (almost_equals(c_token, "gr$aph")) {
                   3066:        ++c_token;
                   3067:        *type = graph;
                   3068:     } else if (almost_equals(c_token, "sc$reen")) {
                   3069:        ++c_token;
                   3070:        *type = screen;
                   3071:     }
                   3072:     switch (*type) {
                   3073:     case first_axes:
                   3074:        *axes = FIRST_AXES;
                   3075:        return;
                   3076:     case second_axes:
                   3077:        *axes = SECOND_AXES;
                   3078:        return;
                   3079:     default:
                   3080:        *axes = (-1);
                   3081:        return;
                   3082:     }
                   3083: }
                   3084:
                   3085: /* get_position() - reads a position for label,arrow,key,... */
                   3086:
                   3087: static void get_position(pos)
                   3088: struct position *pos;
                   3089: {
                   3090:     int axes;
                   3091:     enum position_type type = first_axes;
                   3092:
                   3093:     get_position_type(&type, &axes);
                   3094:     pos->scalex = type;
                   3095:     GET_NUMBER_OR_TIME(pos->x, axes, FIRST_X_AXIS);
                   3096:     if (!equals(c_token, ","))
                   3097:        int_error("Expected comma", c_token);
                   3098:     ++c_token;
                   3099:     get_position_type(&type, &axes);
                   3100:     pos->scaley = type;
                   3101:     GET_NUMBER_OR_TIME(pos->y, axes, FIRST_Y_AXIS);
                   3102:
                   3103:     /* z is not really allowed for a screen co-ordinate, but keep it simple ! */
                   3104:     if (equals(c_token, ",")) {
                   3105:        ++c_token;
                   3106:        get_position_type(&type, &axes);
                   3107:        pos->scalez = type;
                   3108:        GET_NUMBER_OR_TIME(pos->z, axes, FIRST_Z_AXIS);
                   3109:     } else {
                   3110:        pos->z = 0;
                   3111:        pos->scalez = type;     /* same as y */
                   3112:     }
                   3113: }
                   3114:
                   3115: static void set_lp_properties(arg, allow_points, lt, pt, lw, ps)
                   3116: struct lp_style_type *arg;
                   3117: int allow_points, lt, pt;
                   3118: double lw, ps;
                   3119: {
                   3120:     arg->pointflag = allow_points;
                   3121:     arg->l_type = lt;
                   3122:     arg->p_type = pt;
                   3123:     arg->l_width = lw;
                   3124:     arg->p_size = ps;
                   3125: }
                   3126:
                   3127: static void reset_lp_properties(arg)
                   3128: struct lp_style_type *arg;
                   3129: {
                   3130:     /* See plot.h for struct lp_style_type */
                   3131:     arg->pointflag = arg->l_type = arg->p_type = 0;
                   3132:     arg->l_width = arg->p_size = 1.0;
                   3133: }
                   3134:
                   3135: static void set_locale(lcl)
                   3136: char *lcl;
                   3137: {
                   3138: #ifndef NO_LOCALE_H
                   3139:     int i;
                   3140:     struct tm tm;
                   3141:
                   3142:     if (setlocale(LC_TIME, lcl))
                   3143:        safe_strncpy(cur_locale, lcl, sizeof(cur_locale));
                   3144:     else
                   3145:        int_error("Locale not available", c_token);
                   3146:
                   3147:     /* we can do a *lot* better than this ; eg use system functions
                   3148:      * where available; create values on first use, etc
                   3149:      */
                   3150:     memset(&tm, 0, sizeof(struct tm));
                   3151:     for (i = 0; i < 7; ++i) {
                   3152:        tm.tm_wday = i;         /* hope this enough */
                   3153:        strftime(full_day_names[i], sizeof(full_day_names[i]), "%A", &tm);
                   3154:        strftime(abbrev_day_names[i], sizeof(abbrev_day_names[i]), "%a", &tm);
                   3155:     }
                   3156:     for (i = 0; i < 12; ++i) {
                   3157:        tm.tm_mon = i;          /* hope this enough */
                   3158:        strftime(full_month_names[i], sizeof(full_month_names[i]), "%B", &tm);
                   3159:        strftime(abbrev_month_names[i], sizeof(abbrev_month_names[i]), "%b", &tm);
                   3160:     }
                   3161: #else
                   3162:     safe_strncpy(cur_locale, lcl, sizeof(cur_locale));
                   3163: #endif /* NO_LOCALE_H */
                   3164: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>