Annotation of OpenXM_contrib/gnuplot/misc.c, Revision 1.1.1.1
1.1 maekawa 1: #ifndef lint
2: static char *RCSid = "$Id: misc.c,v 1.79 1998/04/14 00:16:02 drd Exp $";
3: #endif
4:
5: /* GNUPLOT - misc.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: #ifdef AMIGA_AC_5
38: # include <exec/types.h>
39: #endif /* AMIGA_AC_5 */
40:
41: #include "plot.h"
42: #include "setshow.h"
43:
44: extern int key_vpos, key_hpos, key_just;
45: extern int datatype[];
46: extern char timefmt[];
47:
48: static void save_range __PROTO((FILE * fp, int axis, double min, double max, int autosc, char *text));
49: static void save_tics __PROTO((FILE * fp, int where, int axis, struct ticdef * tdef, TBOOLEAN rotate, char *text));
50: static void save_position __PROTO((FILE * fp, struct position * pos));
51: static void save_functions__sub __PROTO((FILE * fp));
52: static void save_variables__sub __PROTO((FILE * fp));
53: static int lf_pop __PROTO((void));
54: static void lf_push __PROTO((FILE * fp));
55: static int find_maxl_cntr __PROTO((struct gnuplot_contours * contours, int *count));
56:
57:
58: #define SAVE_NUM_OR_TIME(fp, x, axis) \
59: do{if (datatype[axis]==TIME) { \
60: char s[80]; char *p; \
61: putc('"', fp); \
62: gstrftime(s,80,timefmt,(double)(x)); \
63: for(p=s; *p; ++p) {\
64: if ( *p == '\t' ) fputs("\\t",fp);\
65: else if (*p == '\n') fputs("\\n",fp); \
66: else if ( *p > 126 || *p < 32 ) fprintf(fp,"\\%03o",*p);\
67: else putc(*p, fp);\
68: }\
69: putc('"', fp);\
70: } else {\
71: fprintf(fp,"%g",x);\
72: }} while(0)
73:
74:
75: /* State information for load_file(), to recover from errors
76: * and properly handle recursive load_file calls
77: */
78: typedef struct lf_state_struct LFS;
79: struct lf_state_struct {
80: FILE *fp; /* file pointer for load file */
81: char *name; /* name of file */
82: TBOOLEAN interactive; /* value of interactive flag on entry */
83: TBOOLEAN do_load_arg_substitution; /* likewise ... */
84: int inline_num; /* inline_num on entry */
85: LFS *prev; /* defines a stack */
86: char *call_args[10]; /* args when file is 'call'ed instead of 'load'ed */
87: } *lf_head = NULL; /* NULL if not in load_file */
88:
89: /* these two could be in load_file, except for error recovery */
90: extern TBOOLEAN do_load_arg_substitution;
91: extern char *call_args[10];
92:
93: /*
94: * cp_alloc() allocates a curve_points structure that can hold 'num'
95: * points.
96: */
97: struct curve_points *
98: cp_alloc(num)
99: int num;
100: {
101: struct curve_points *cp;
102:
103: cp = (struct curve_points *) gp_alloc((unsigned long) sizeof(struct curve_points), "curve");
104: cp->p_max = (num >= 0 ? num : 0);
105:
106: if (num > 0) {
107: cp->points = (struct coordinate GPHUGE *)
108: gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
109: } else
110: cp->points = (struct coordinate GPHUGE *) NULL;
111: cp->next_cp = NULL;
112: cp->title = NULL;
113: return (cp);
114: }
115:
116:
117: /*
118: * cp_extend() reallocates a curve_points structure to hold "num"
119: * points. This will either expand or shrink the storage.
120: */
121: void cp_extend(cp, num)
122: struct curve_points *cp;
123: int num;
124: {
125:
126: #if defined(DOS16) || defined(WIN16)
127: /* Make sure we do not allocate more than 64k points in msdos since
128: * indexing is done with 16-bit int
129: * Leave some bytes for malloc maintainance.
130: */
131: if (num > 32700)
132: int_error("Array index must be less than 32k in msdos", NO_CARET);
133: #endif /* MSDOS */
134:
135: if (num == cp->p_max)
136: return;
137:
138: if (num > 0) {
139: if (cp->points == NULL) {
140: cp->points = (struct coordinate GPHUGE *)
141: gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
142: } else {
143: cp->points = (struct coordinate GPHUGE *)
144: gp_realloc(cp->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
145: }
146: cp->p_max = num;
147: } else {
148: if (cp->points != (struct coordinate GPHUGE *) NULL)
149: free(cp->points);
150: cp->points = (struct coordinate GPHUGE *) NULL;
151: cp->p_max = 0;
152: }
153: }
154:
155: /*
156: * cp_free() releases any memory which was previously malloc()'d to hold
157: * curve points (and recursively down the linked list).
158: */
159: void cp_free(cp)
160: struct curve_points *cp;
161: {
162: if (cp) {
163: cp_free(cp->next_cp);
164: if (cp->title)
165: free((char *) cp->title);
166: if (cp->points)
167: free((char *) cp->points);
168: free((char *) cp);
169: }
170: }
171:
172: /*
173: * iso_alloc() allocates a iso_curve structure that can hold 'num'
174: * points.
175: */
176: struct iso_curve *
177: iso_alloc(num)
178: int num;
179: {
180: struct iso_curve *ip;
181: ip = (struct iso_curve *) gp_alloc((unsigned long) sizeof(struct iso_curve), "iso curve");
182: ip->p_max = (num >= 0 ? num : 0);
183: if (num > 0) {
184: ip->points = (struct coordinate GPHUGE *)
185: gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
186: } else
187: ip->points = (struct coordinate GPHUGE *) NULL;
188: ip->next = NULL;
189: return (ip);
190: }
191:
192: /*
193: * iso_extend() reallocates a iso_curve structure to hold "num"
194: * points. This will either expand or shrink the storage.
195: */
196: void iso_extend(ip, num)
197: struct iso_curve *ip;
198: int num;
199: {
200: if (num == ip->p_max)
201: return;
202:
203: #if defined(DOS16) || defined(WIN16)
204: /* Make sure we do not allocate more than 64k points in msdos since
205: * indexing is done with 16-bit int
206: * Leave some bytes for malloc maintainance.
207: */
208: if (num > 32700)
209: int_error("Array index must be less than 32k in msdos", NO_CARET);
210: #endif /* 16bit (Win)Doze */
211:
212: if (num > 0) {
213: if (ip->points == NULL) {
214: ip->points = (struct coordinate GPHUGE *)
215: gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
216: } else {
217: ip->points = (struct coordinate GPHUGE *)
218: gp_realloc(ip->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
219: }
220: ip->p_max = num;
221: } else {
222: if (ip->points != (struct coordinate GPHUGE *) NULL)
223: free(ip->points);
224: ip->points = (struct coordinate GPHUGE *) NULL;
225: ip->p_max = 0;
226: }
227: }
228:
229: /*
230: * iso_free() releases any memory which was previously malloc()'d to hold
231: * iso curve points.
232: */
233: void iso_free(ip)
234: struct iso_curve *ip;
235: {
236: if (ip) {
237: if (ip->points)
238: free((char *) ip->points);
239: free((char *) ip);
240: }
241: }
242:
243: /*
244: * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
245: * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
246: * 'num_samp_1' samples.
247: * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
248: */
249: struct surface_points *
250: sp_alloc(num_samp_1, num_iso_1, num_samp_2, num_iso_2)
251: int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
252: {
253: struct surface_points *sp;
254:
255: sp = (struct surface_points *) gp_alloc((unsigned long) sizeof(struct surface_points), "surface");
256: sp->next_sp = NULL;
257: sp->title = NULL;
258: sp->contours = NULL;
259: sp->iso_crvs = NULL;
260: sp->num_iso_read = 0;
261:
262: if (num_iso_2 > 0 && num_samp_1 > 0) {
263: int i;
264: struct iso_curve *icrv;
265:
266: for (i = 0; i < num_iso_1; i++) {
267: icrv = iso_alloc(num_samp_2);
268: icrv->next = sp->iso_crvs;
269: sp->iso_crvs = icrv;
270: }
271: for (i = 0; i < num_iso_2; i++) {
272: icrv = iso_alloc(num_samp_1);
273: icrv->next = sp->iso_crvs;
274: sp->iso_crvs = icrv;
275: }
276: } else
277: sp->iso_crvs = (struct iso_curve *) NULL;
278:
279: return (sp);
280: }
281:
282: /*
283: * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
284: * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
285: * 'num_samp_1' samples.
286: * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
287: */
288: void sp_replace(sp, num_samp_1, num_iso_1, num_samp_2, num_iso_2)
289: struct surface_points *sp;
290: int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
291: {
292: int i;
293: struct iso_curve *icrv, *icrvs = sp->iso_crvs;
294:
295: while (icrvs) {
296: icrv = icrvs;
297: icrvs = icrvs->next;
298: iso_free(icrv);
299: }
300: sp->iso_crvs = NULL;
301:
302: if (num_iso_2 > 0 && num_samp_1 > 0) {
303: for (i = 0; i < num_iso_1; i++) {
304: icrv = iso_alloc(num_samp_2);
305: icrv->next = sp->iso_crvs;
306: sp->iso_crvs = icrv;
307: }
308: for (i = 0; i < num_iso_2; i++) {
309: icrv = iso_alloc(num_samp_1);
310: icrv->next = sp->iso_crvs;
311: sp->iso_crvs = icrv;
312: }
313: } else
314: sp->iso_crvs = (struct iso_curve *) NULL;
315: }
316:
317: /*
318: * sp_free() releases any memory which was previously malloc()'d to hold
319: * surface points.
320: */
321: void sp_free(sp)
322: struct surface_points *sp;
323: {
324: if (sp) {
325: sp_free(sp->next_sp);
326: if (sp->title)
327: free((char *) sp->title);
328: if (sp->contours) {
329: struct gnuplot_contours *cntr, *cntrs = sp->contours;
330:
331: while (cntrs) {
332: cntr = cntrs;
333: cntrs = cntrs->next;
334: free(cntr->coords);
335: free(cntr);
336: }
337: }
338: if (sp->iso_crvs) {
339: struct iso_curve *icrv, *icrvs = sp->iso_crvs;
340:
341: while (icrvs) {
342: icrv = icrvs;
343: icrvs = icrvs->next;
344: iso_free(icrv);
345: }
346: }
347: free((char *) sp);
348: }
349: }
350:
351:
352: /*
353: * functions corresponding to the arguments of the GNUPLOT `save` command
354: */
355: void save_functions(fp)
356: FILE *fp;
357: {
358: if (fp) {
359: show_version(fp); /* I _love_ information written */
360: save_functions__sub(fp); /* at the top and the end of an */
361: fputs("# EOF\n", fp); /* human readable ASCII file. */
362: (void) fclose(fp); /* (JFi) */
363: } else
364: os_error("Cannot open save file", c_token);
365: }
366:
367:
368: void save_variables(fp)
369: FILE *fp;
370: {
371: if (fp) {
372: show_version(fp);
373: save_variables__sub(fp);
374: fputs("# EOF\n", fp);
375: (void) fclose(fp);
376: } else
377: os_error("Cannot open save file", c_token);
378: }
379:
380:
381: void save_set(fp)
382: FILE *fp;
383: {
384: if (fp) {
385: show_version(fp);
386: save_set_all(fp);
387: fputs("# EOF\n", fp);
388: (void) fclose(fp);
389: } else
390: os_error("Cannot open save file", c_token);
391: }
392:
393:
394: void save_all(fp)
395: FILE *fp;
396: {
397: if (fp) {
398: show_version(fp);
399: save_set_all(fp);
400: save_functions__sub(fp);
401: save_variables__sub(fp);
402: fprintf(fp, "%s\n", replot_line);
403: if (wri_to_fil_last_fit_cmd(NULL)) {
404: fputs("## ", fp);
405: wri_to_fil_last_fit_cmd(fp);
406: putc('\n', fp);
407: }
408: fputs("# EOF\n", fp);
409: (void) fclose(fp);
410: } else
411: os_error("Cannot open save file", c_token);
412: }
413:
414: /*
415: * auxiliary functions
416: */
417:
418: static void save_functions__sub(fp)
419: FILE *fp;
420: {
421: register struct udft_entry *udf = first_udf;
422:
423: while (udf) {
424: if (udf->definition) {
425: fprintf(fp, "%s\n", udf->definition);
426: }
427: udf = udf->next_udf;
428: }
429: }
430:
431: static void save_variables__sub(fp)
432: FILE *fp;
433: {
434: register struct udvt_entry *udv = first_udv->next_udv; /* always skip pi */
435:
436: while (udv) {
437: if (!udv->udv_undef) {
438: fprintf(fp, "%s = ", udv->udv_name);
439: disp_value(fp, &(udv->udv_value));
440: (void) putc('\n', fp);
441: }
442: udv = udv->next_udv;
443: }
444: }
445:
446: void save_set_all(fp)
447: FILE *fp;
448: {
449: struct text_label *this_label;
450: struct arrow_def *this_arrow;
451: struct linestyle_def *this_linestyle;
452: char str[MAX_LINE_LEN + 1];
453:
454: /* opinions are split as to whether we save term and outfile
455: * as a compromise, we output them as comments !
456: */
457: if (term)
458: fprintf(fp, "# set terminal %s %s\n", term->name, term_options);
459: else
460: fputs("# set terminal unknown\n", fp);
461:
462: if (outstr)
463: fprintf(fp, "# set output '%s'\n", outstr);
464: else
465: fputs("# set output\n", fp);
466:
467: fprintf(fp, "\
468: set %sclip points\n\
469: set %sclip one\n\
470: set %sclip two\n\
471: set bar %f\n",
472: (clip_points) ? "" : "no",
473: (clip_lines1) ? "" : "no",
474: (clip_lines2) ? "" : "no",
475: bar_size);
476:
477: if (draw_border)
478: /* HBB 980609: handle border linestyle, too */
479: fprintf(fp, "set border %d lt %d lw %.3f\n", draw_border, border_lp.l_type + 1, border_lp.l_width);
480: else
481: fprintf(fp, "set noborder\n");
482:
483: fprintf(fp, "\
484: set xdata%s\n\
485: set ydata%s\n\
486: set zdata%s\n\
487: set x2data%s\n\
488: set y2data%s\n",
489: datatype[FIRST_X_AXIS] == TIME ? " time" : "",
490: datatype[FIRST_Y_AXIS] == TIME ? " time" : "",
491: datatype[FIRST_Z_AXIS] == TIME ? " time" : "",
492: datatype[SECOND_X_AXIS] == TIME ? " time" : "",
493: datatype[SECOND_Y_AXIS] == TIME ? " time" : "");
494:
495: if (boxwidth < 0.0)
496: fputs("set boxwidth\n", fp);
497: else
498: fprintf(fp, "set boxwidth %g\n", boxwidth);
499: if (dgrid3d)
500: fprintf(fp, "set dgrid3d %d,%d, %d\n",
501: dgrid3d_row_fineness,
502: dgrid3d_col_fineness,
503: dgrid3d_norm_value);
504:
505: fprintf(fp, "\
506: set dummy %s,%s\n\
507: set format x \"%s\"\n\
508: set format y \"%s\"\n\
509: set format x2 \"%s\"\n\
510: set format y2 \"%s\"\n\
511: set format z \"%s\"\n\
512: set angles %s\n",
513: dummy_var[0], dummy_var[1],
514: conv_text(str, xformat),
515: conv_text(str, yformat),
516: conv_text(str, x2format),
517: conv_text(str, y2format),
518: conv_text(str, zformat),
519: (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
520:
521: if (work_grid.l_type == 0)
522: fputs("set nogrid\n", fp);
523: else {
524: if (polar_grid_angle) /* set angle already output */
525: fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
526: else
527: fputs("set grid nopolar\n", fp);
528: fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
529: work_grid.l_type & GRID_X ? "" : "no",
530: work_grid.l_type & GRID_Y ? "" : "no",
531: work_grid.l_type & GRID_Z ? "" : "no",
532: work_grid.l_type & GRID_X2 ? "" : "no",
533: work_grid.l_type & GRID_Y2 ? "" : "no",
534: work_grid.l_type & GRID_MX ? "" : "no",
535: work_grid.l_type & GRID_MY ? "" : "no",
536: work_grid.l_type & GRID_MZ ? "" : "no",
537: work_grid.l_type & GRID_MX2 ? "" : "no",
538: work_grid.l_type & GRID_MY2 ? "" : "no",
539: grid_lp.l_type + 1, grid_lp.l_width,
540: mgrid_lp.l_type + 1, mgrid_lp.l_width);
541: }
542: fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
543: switch (key) {
544: case -1:{
545: fputs("set key", fp);
546: switch (key_hpos) {
547: case TRIGHT:
548: fputs(" right", fp);
549: break;
550: case TLEFT:
551: fputs(" left", fp);
552: break;
553: case TOUT:
554: fputs(" out", fp);
555: break;
556: }
557: switch (key_vpos) {
558: case TTOP:
559: fputs(" top", fp);
560: break;
561: case TBOTTOM:
562: fputs(" bottom", fp);
563: break;
564: case TUNDER:
565: fputs(" below", fp);
566: break;
567: }
568: break;
569: }
570: case 0:
571: fputs("set nokey\n", fp);
572: break;
573: case 1:
574: fputs("set key ", fp);
575: save_position(fp, &key_user_pos);
576: break;
577: }
578: if (key) {
579: fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
580: key_just == JLEFT ? "Left" : "Right",
581: key_reverse ? "" : "no",
582: key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
583: }
584: fputs("set nolabel\n", fp);
585: for (this_label = first_label; this_label != NULL;
586: this_label = this_label->next) {
587: fprintf(fp, "set label %d \"%s\" at ",
588: this_label->tag,
589: conv_text(str, this_label->text));
590: save_position(fp, &this_label->place);
591:
592: switch (this_label->pos) {
593: case LEFT:
594: fputs(" left", fp);
595: break;
596: case CENTRE:
597: fputs(" centre", fp);
598: break;
599: case RIGHT:
600: fputs(" right", fp);
601: break;
602: }
603: fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
604: if ((this_label->font)[0] != NUL)
605: fprintf(fp, " font \"%s\"", this_label->font);
606: /* Entry font added by DJL */
607: fputc('\n', fp);
608: }
609: fputs("set noarrow\n", fp);
610: for (this_arrow = first_arrow; this_arrow != NULL;
611: this_arrow = this_arrow->next) {
612: fprintf(fp, "set arrow %d from ", this_arrow->tag);
613: save_position(fp, &this_arrow->start);
614: fputs(" to ", fp);
615: save_position(fp, &this_arrow->end);
616: fprintf(fp, " %s linetype %d linewidth %.3f\n",
617: this_arrow->head ? "" : " nohead",
618: this_arrow->lp_properties.l_type + 1,
619: this_arrow->lp_properties.l_width);
620: }
621: fputs("set nolinestyle\n", fp);
622: for (this_linestyle = first_linestyle; this_linestyle != NULL;
623: this_linestyle = this_linestyle->next) {
624: fprintf(fp, "set linestyle %d ", this_linestyle->tag);
625: fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
626: this_linestyle->lp_properties.l_type + 1,
627: this_linestyle->lp_properties.l_width,
628: this_linestyle->lp_properties.p_type + 1,
629: this_linestyle->lp_properties.p_size);
630: }
631: fputs("set nologscale\n", fp);
632: if (is_log_x)
633: fprintf(fp, "set logscale x %g\n", base_log_x);
634: if (is_log_y)
635: fprintf(fp, "set logscale y %g\n", base_log_y);
636: if (is_log_z)
637: fprintf(fp, "set logscale z %g\n", base_log_z);
638: if (is_log_x2)
639: fprintf(fp, "set logscale x2 %g\n", base_log_x2);
640: if (is_log_y2)
641: fprintf(fp, "set logscale y2 %g\n", base_log_y2);
642:
643: fprintf(fp, "\
644: set offsets %g, %g, %g, %g\n\
645: set pointsize %g\n\
646: set encoding %s\n\
647: set %spolar\n\
648: set %sparametric\n\
649: set view %g, %g, %g, %g\n\
650: set samples %d, %d\n\
651: set isosamples %d, %d\n\
652: set %ssurface\n\
653: set %scontour",
654: loff, roff, toff, boff,
655: pointsize,
656: encoding_names[encoding],
657: (polar) ? "" : "no",
658: (parametric) ? "" : "no",
659: surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
660: samples_1, samples_2,
661: iso_samples_1, iso_samples_2,
662: (draw_surface) ? "" : "no",
663: (draw_contour) ? "" : "no");
664:
665: switch (draw_contour) {
666: case CONTOUR_NONE:
667: fputc('\n', fp);
668: break;
669: case CONTOUR_BASE:
670: fputs(" base\n", fp);
671: break;
672: case CONTOUR_SRF:
673: fputs(" surface\n", fp);
674: break;
675: case CONTOUR_BOTH:
676: fputs(" both\n", fp);
677: break;
678: }
679: if (label_contours)
680: fprintf(fp, "set clabel '%s'\n", contour_format);
681: else
682: fputs("set noclabel\n", fp);
683:
684: fputs("set mapping ", fp);
685: switch(mapping3d) {
686: case MAP3D_SPHERICAL:
687: fputs("spherical\n", fp);
688: break;
689: case MAP3D_CYLINDRICAL:
690: fputs("cylindrical\n", fp);
691: break;
692: case MAP3D_CARTESIAN:
693: default:
694: fputs("cartesian\n", fp);
695: break;
696: }
697:
698: if (missing_val != NULL)
699: fprintf(fp, "set missing %s\n", missing_val);
700:
701: save_hidden3doptions(fp);
702: fprintf(fp, "set cntrparam order %d\n", contour_order);
703: fputs("set cntrparam ", fp);
704: switch (contour_kind) {
705: case CONTOUR_KIND_LINEAR:
706: fputs("linear\n", fp);
707: break;
708: case CONTOUR_KIND_CUBIC_SPL:
709: fputs("cubicspline\n", fp);
710: break;
711: case CONTOUR_KIND_BSPLINE:
712: fputs("bspline\n", fp);
713: break;
714: }
715: fputs("set cntrparam levels ", fp);
716: switch (levels_kind) {
717: case LEVELS_AUTO:
718: fprintf(fp, "auto %d\n", contour_levels);
719: break;
720: case LEVELS_INCREMENTAL:
721: fprintf(fp, "incremental %g,%g,%g\n",
722: levels_list[0], levels_list[1],
723: levels_list[0] + levels_list[1] * contour_levels);
724: break;
725: case LEVELS_DISCRETE:
726: {
727: int i;
728: fprintf(fp, "discrete %g", levels_list[0]);
729: for (i = 1; i < contour_levels; i++)
730: fprintf(fp, ",%g ", levels_list[i]);
731: fputc('\n', fp);
732: }
733: }
734: fprintf(fp, "\
735: set cntrparam points %d\n\
736: set size ratio %g %g,%g\n\
737: set origin %g,%g\n\
738: set data style ",
739: contour_pts,
740: aspect_ratio, xsize, ysize,
741: xoffset, yoffset);
742:
743: switch (data_style) {
744: case LINES:
745: fputs("lines\n", fp);
746: break;
747: case POINTSTYLE:
748: fputs("points\n", fp);
749: break;
750: case IMPULSES:
751: fputs("impulses\n", fp);
752: break;
753: case LINESPOINTS:
754: fputs("linespoints\n", fp);
755: break;
756: case DOTS:
757: fputs("dots\n", fp);
758: break;
759: case YERRORBARS:
760: fputs("yerrorbars\n", fp);
761: break;
762: case XERRORBARS:
763: fputs("xerrorbars\n", fp);
764: break;
765: case XYERRORBARS:
766: fputs("xyerrorbars\n", fp);
767: break;
768: case BOXES:
769: fputs("boxes\n", fp);
770: break;
771: case BOXERROR:
772: fputs("boxerrorbars\n", fp);
773: break;
774: case BOXXYERROR:
775: fputs("boxxyerrorbars\n", fp);
776: break;
777: case STEPS:
778: fputs("steps\n", fp);
779: break; /* JG */
780: case FSTEPS:
781: fputs("fsteps\n", fp);
782: break; /* HOE */
783: case HISTEPS:
784: fputs("histeps\n", fp);
785: break; /* CAC */
786: case VECTOR:
787: fputs("vector\n", fp);
788: break;
789: case FINANCEBARS:
790: fputs("financebars\n", fp);
791: break;
792: case CANDLESTICKS:
793: fputs("candlesticks\n", fp);
794: break;
795: }
796: fputs("set function style ", fp);
797: switch (func_style) {
798: case LINES:
799: fputs("lines\n", fp);
800: break;
801: case POINTSTYLE:
802: fputs("points\n", fp);
803: break;
804: case IMPULSES:
805: fputs("impulses\n", fp);
806: break;
807: case LINESPOINTS:
808: fputs("linespoints\n", fp);
809: break;
810: case DOTS:
811: fputs("dots\n", fp);
812: break;
813: case YERRORBARS:
814: fputs("yerrorbars\n", fp);
815: break;
816: case XERRORBARS:
817: fputs("xerrorbars\n", fp);
818: break;
819: case XYERRORBARS:
820: fputs("xyerrorbars\n", fp);
821: break;
822: case BOXXYERROR:
823: fputs("boxxyerrorbars\n", fp);
824: break;
825: case BOXES:
826: fputs("boxes\n", fp);
827: break;
828: case BOXERROR:
829: fputs("boxerrorbars\n", fp);
830: break;
831: case STEPS:
832: fputs("steps\n", fp);
833: break; /* JG */
834: case FSTEPS:
835: fputs("fsteps\n", fp);
836: break; /* HOE */
837: case HISTEPS:
838: fputs("histeps\n", fp);
839: break; /* CAC */
840: case VECTOR:
841: fputs("vector\n", fp);
842: break;
843: case FINANCEBARS:
844: fputs("financebars\n", fp);
845: break;
846: case CANDLESTICKS:
847: fputs("candlesticks\n", fp);
848: break;
849: default:
850: /* HBB: default case demanded by gcc, still needed ?? */
851: fputs("---error!---\n", fp);
852: }
853:
854: fprintf(fp, "\
855: set xzeroaxis lt %d lw %.3f\n\
856: set x2zeroaxis lt %d lw %.3f\n\
857: set yzeroaxis lt %d lw %.3f\n\
858: set y2zeroaxis lt %d lw %.3f\n\
859: set tics %s\n\
860: set ticslevel %g\n\
861: set ticscale %g %g\n",
862: xzeroaxis.l_type + 1, xzeroaxis.l_width,
863: x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
864: yzeroaxis.l_type + 1, yzeroaxis.l_width,
865: y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
866: (tic_in) ? "in" : "out",
867: ticslevel,
868: ticscale, miniticscale);
869:
870: #define SAVE_XYZLABEL(name,lab) { \
871: fprintf(fp, "set %s \"%s\" %f,%f ", \
872: name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
873: fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
874: }
875:
876:
877: #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
878: case 0: fprintf(fp, "set no%s\n", name); break; \
879: case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
880: case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
881: case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
882: }
883: SAVE_MINI("mxtics", mxtics, mxtfreq)
884: SAVE_MINI("mytics", mytics, mytfreq)
885: SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
886: SAVE_MINI("my2tics", my2tics, my2tfreq)
887: save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
888: save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
889: save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
890: save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
891: save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
892: SAVE_XYZLABEL("title", title);
893:
894: fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
895: "timestamp", conv_text(str, timelabel.text),
896: (timelabel_bottom ? "bottom" : "top"),
897: (timelabel_rotate ? "" : "no"),
898: timelabel.xoffset, timelabel.yoffset);
899: fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
900:
901: save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
902: save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
903: save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
904: save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
905:
906: SAVE_XYZLABEL("xlabel", xlabel);
907: SAVE_XYZLABEL("x2label", x2label);
908:
909: if (strlen(timefmt)) {
910: fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
911: }
912: save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
913: save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
914:
915: SAVE_XYZLABEL("ylabel", ylabel);
916: SAVE_XYZLABEL("y2label", y2label);
917:
918: save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
919: save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
920:
921: SAVE_XYZLABEL("zlabel", zlabel);
922: save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
923:
924: fprintf(fp, "set zero %g\n", zero);
925: fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
926: lmargin, bmargin, rmargin, tmargin);
927:
928: fprintf(fp, "set locale \"%s\"\n", cur_locale);
929: }
930:
931: static void save_tics(fp, where, axis, tdef, rotate, text)
932: FILE *fp;
933: int where;
934: int axis;
935: struct ticdef *tdef;
936: TBOOLEAN rotate;
937: char *text;
938: {
939: char str[MAX_LINE_LEN + 1];
940:
941: if (where == NO_TICS) {
942: fprintf(fp, "set no%stics\n", text);
943: return;
944: }
945: fprintf(fp, "set %stics %s %smirror %srotate ", text,
946: (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
947: (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
948: switch (tdef->type) {
949: case TIC_COMPUTED:{
950: fputs("autofreq ", fp);
951: break;
952: }
953: case TIC_MONTH:{
954: fprintf(fp, "\nset %smtics", text);
955: break;
956: }
957: case TIC_DAY:{
958: fprintf(fp, "\nset %cdtics", axis);
959: break;
960: }
961: case TIC_SERIES:
962: if (datatype[axis] == TIME) {
963: if (tdef->def.series.start != -VERYLARGE) {
964: char fd[26];
965: gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
966: fprintf(fp, "\"%s\",", conv_text(str, fd));
967: }
968: fprintf(fp, "%g", tdef->def.series.incr);
969:
970: if (tdef->def.series.end != VERYLARGE) {
971: char td[26];
972: gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
973: fprintf(fp, ",\"%s\"", conv_text(str, td));
974: }
975: } else { /* !TIME */
976:
977: if (tdef->def.series.start != -VERYLARGE)
978: fprintf(fp, "%g,", tdef->def.series.start);
979: fprintf(fp, "%g", tdef->def.series.incr);
980: if (tdef->def.series.end != VERYLARGE)
981: fprintf(fp, ",%g", tdef->def.series.end);
982: }
983:
984: break;
985:
986: case TIC_USER:{
987: register struct ticmark *t;
988: int flag_time;
989: flag_time = (datatype[axis] == TIME);
990: fputs(" (", fp);
991: for (t = tdef->def.user; t != NULL; t = t->next) {
992: if (t->label)
993: fprintf(fp, "\"%s\" ", conv_text(str, t->label));
994: if (flag_time) {
995: char td[26];
996: gstrftime(td, 24, timefmt, (double) t->position);
997: fprintf(fp, "\"%s\"", conv_text(str, td));
998: } else {
999: fprintf(fp, "%g", t->position);
1000: }
1001: if (t->next) {
1002: fputs(", ", fp);
1003: }
1004: }
1005: fputs(")", fp);
1006: break;
1007: }
1008: }
1009: putc('\n', fp);
1010: }
1011:
1012: static void save_position(fp, pos)
1013: FILE *fp;
1014: struct position *pos;
1015: {
1016: static char *msg[] =
1017: {"first_axes ", "second axes ", "graph ", "screen "};
1018:
1019: assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
1020:
1021: fprintf(fp, "%s%g, %s%g, %s%g",
1022: pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
1023: pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
1024: pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
1025: }
1026:
1027: void load_file(fp, name, can_do_args)
1028: FILE *fp;
1029: char *name;
1030: TBOOLEAN can_do_args;
1031: {
1032: register int len;
1033:
1034: int start, left;
1035: int more;
1036: int stop = FALSE;
1037:
1038: lf_push(fp); /* save state for errors and recursion */
1039: do_load_arg_substitution = can_do_args;
1040:
1041: if (fp == (FILE *) NULL) {
1042: /* HBB 980311: alloc() it, to save valuable stack space: */
1043: char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
1044: (void) sprintf(errbuf, "Cannot open %s file '%s'",
1045: can_do_args ? "call" : "load", name);
1046: os_error(errbuf, c_token);
1047: free(errbuf);
1048: } else if (fp == stdin) {
1049: /* DBT 10-6-98 go interactive if "-" named as load file */
1050: interactive = TRUE;
1051: while(!com_line())
1052: ;
1053: } else {
1054: /* go into non-interactive mode during load */
1055: /* will be undone below, or in load_file_error */
1056: interactive = FALSE;
1057: inline_num = 0;
1058: infile_name = name;
1059:
1060: if (can_do_args) {
1061: int aix = 0;
1062: while (++c_token < num_tokens && aix <= 9) {
1063: if (isstring(c_token))
1064: m_quote_capture(&call_args[aix++], c_token, c_token);
1065: else
1066: m_capture(&call_args[aix++], c_token, c_token);
1067: }
1068:
1069: /* A GNUPLOT "call" command can have up to _10_ arguments named "$0"
1070: to "$9". After reading the 10th argument (i.e.: "$9") the variable
1071: 'aix' contains the value '10' because of the 'aix++' construction
1072: in '&call_args[aix++]'. So I think the following test of 'aix'
1073: should be done against '10' instead of '9'. (JFi) */
1074:
1075: /* if (c_token >= num_tokens && aix > 9) */
1076: if (c_token >= num_tokens && aix > 10)
1077: int_error("too many arguments for CALL <file>", ++c_token);
1078: }
1079: while (!stop) { /* read all commands in file */
1080: /* read one command */
1081: left = input_line_len;
1082: start = 0;
1083: more = TRUE;
1084:
1085: while (more) {
1086: if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
1087: stop = TRUE; /* EOF in file */
1088: input_line[start] = '\0';
1089: more = FALSE;
1090: } else {
1091: inline_num++;
1092: len = strlen(input_line) - 1;
1093: if (input_line[len] == '\n') { /* remove any newline */
1094: input_line[len] = '\0';
1095: /* Look, len was 1-1 = 0 before, take care here! */
1096: if (len > 0)
1097: --len;
1098: if (input_line[len] == '\r') { /* remove any carriage return */
1099: input_line[len] = NUL;
1100: if (len > 0)
1101: --len;
1102: }
1103: }
1104: else if (len + 2 >= left) {
1105: extend_input_line();
1106: left = input_line_len - len - 1;
1107: start = len + 1;
1108: continue; /* don't check for '\' */
1109: }
1110: if (input_line[len] == '\\') {
1111: /* line continuation */
1112: start = len;
1113: left = input_line_len - start;
1114: } else
1115: more = FALSE;
1116: }
1117: }
1118:
1119: if (strlen(input_line) > 0) {
1120: if (can_do_args) {
1121: register int il = 0;
1122: register char *rl;
1123: char *raw_line = rl = gp_alloc((unsigned long) strlen(input_line) + 1, "string");
1124:
1125: strcpy(raw_line, input_line);
1126: *input_line = '\0';
1127: while (*rl) {
1128: register int aix;
1129: if (*rl == '$'
1130: && ((aix = *(++rl)) != 0) /* HBB 980308: quiet BCC warning */
1131: &&aix >= '0' && aix <= '9') {
1132: if (call_args[aix -= '0']) {
1133: len = strlen(call_args[aix]);
1134: while (input_line_len - il < len + 1) {
1135: extend_input_line();
1136: }
1137: strcpy(input_line + il, call_args[aix]);
1138: il += len;
1139: }
1140: } else {
1141: /* substitute for $<n> here */
1142: if (il + 1 > input_line_len) {
1143: extend_input_line();
1144: }
1145: input_line[il++] = *rl;
1146: }
1147: rl++;
1148: }
1149: if (il + 1 > input_line_len) {
1150: extend_input_line();
1151: }
1152: input_line[il] = '\0';
1153: free(raw_line);
1154: }
1155: screen_ok = FALSE; /* make sure command line is
1156: echoed on error */
1157: do_line();
1158: }
1159: }
1160: }
1161:
1162: /* pop state */
1163: (void) lf_pop(); /* also closes file fp */
1164: }
1165:
1166: /* pop from load_file state stack */
1167: static TBOOLEAN /* FALSE if stack was empty */
1168: lf_pop()
1169: { /* called by load_file and load_file_error */
1170: LFS *lf;
1171:
1172: if (lf_head == NULL)
1173: return (FALSE);
1174: else {
1175: int argindex;
1176: lf = lf_head;
1177: if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
1178: /* DBT 10-6-98 do not close stdin in the case
1179: * that "-" is named as a load file
1180: */
1181: (void) fclose(lf->fp);
1182: }
1183: for (argindex = 0; argindex < 10; argindex++) {
1184: if (call_args[argindex]) {
1185: free(call_args[argindex]);
1186: }
1187: call_args[argindex] = lf->call_args[argindex];
1188: }
1189: do_load_arg_substitution = lf->do_load_arg_substitution;
1190: interactive = lf->interactive;
1191: inline_num = lf->inline_num;
1192: infile_name = lf->name;
1193: lf_head = lf->prev;
1194: free((char *) lf);
1195: return (TRUE);
1196: }
1197: }
1198:
1199: /* push onto load_file state stack */
1200: /* essentially, we save information needed to undo the load_file changes */
1201: static void lf_push(fp) /* called by load_file */
1202: FILE *fp;
1203: {
1204: LFS *lf;
1205: int argindex;
1206:
1207: lf = (LFS *) gp_alloc((unsigned long) sizeof(LFS), (char *) NULL);
1208: if (lf == (LFS *) NULL) {
1209: if (fp != (FILE *) NULL)
1210: (void) fclose(fp); /* it won't be otherwise */
1211: int_error("not enough memory to load file", c_token);
1212: }
1213: lf->fp = fp; /* save this file pointer */
1214: lf->name = infile_name; /* save current name */
1215: lf->interactive = interactive; /* save current state */
1216: lf->inline_num = inline_num; /* save current line number */
1217: lf->do_load_arg_substitution = do_load_arg_substitution;
1218: for (argindex = 0; argindex < 10; argindex++) {
1219: lf->call_args[argindex] = call_args[argindex];
1220: call_args[argindex] = NULL; /* initially no args */
1221: }
1222: lf->prev = lf_head; /* link to stack */
1223: lf_head = lf;
1224: }
1225:
1226: /* used for reread vsnyder@math.jpl.nasa.gov */
1227: FILE *lf_top()
1228: {
1229: if (lf_head == (LFS *) NULL)
1230: return ((FILE *) NULL);
1231: return (lf_head->fp);
1232: }
1233:
1234: /* called from main */
1235: void load_file_error()
1236: {
1237: /* clean up from error in load_file */
1238: /* pop off everything on stack */
1239: while (lf_pop());
1240: }
1241:
1242: /* find char c in string str; return p such that str[p]==c;
1243: * if c not in str then p=strlen(str)
1244: */
1245: int instring(str, c)
1246: char *str;
1247: int c;
1248: {
1249: int pos = 0;
1250:
1251: while (str != NULL && *str != NUL && c != *str) {
1252: str++;
1253: pos++;
1254: }
1255: return (pos);
1256: }
1257:
1258: void show_functions()
1259: {
1260: register struct udft_entry *udf = first_udf;
1261:
1262: fputs("\n\tUser-Defined Functions:\n", stderr);
1263:
1264: while (udf) {
1265: if (udf->definition)
1266: fprintf(stderr, "\t%s\n", udf->definition);
1267: else
1268: fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
1269: udf = udf->next_udf;
1270: }
1271: }
1272:
1273:
1274: void show_at()
1275: {
1276: (void) putc('\n', stderr);
1277: disp_at(temp_at(), 0);
1278: }
1279:
1280:
1281: void disp_at(curr_at, level)
1282: struct at_type *curr_at;
1283: int level;
1284: {
1285: register int i, j;
1286: register union argument *arg;
1287:
1288: for (i = 0; i < curr_at->a_count; i++) {
1289: (void) putc('\t', stderr);
1290: for (j = 0; j < level; j++)
1291: (void) putc(' ', stderr); /* indent */
1292:
1293: /* print name of instruction */
1294:
1295: fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
1296: arg = &(curr_at->actions[i].arg);
1297:
1298: /* now print optional argument */
1299:
1300: switch (curr_at->actions[i].index) {
1301: case PUSH:
1302: fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
1303: break;
1304: case PUSHC:
1305: (void) putc(' ', stderr);
1306: disp_value(stderr, &(arg->v_arg));
1307: (void) putc('\n', stderr);
1308: break;
1309: case PUSHD1:
1310: fprintf(stderr, " %c dummy\n",
1311: arg->udf_arg->udf_name[0]);
1312: break;
1313: case PUSHD2:
1314: fprintf(stderr, " %c dummy\n",
1315: arg->udf_arg->udf_name[1]);
1316: break;
1317: case CALL:
1318: fprintf(stderr, " %s", arg->udf_arg->udf_name);
1319: if (level < 6) {
1320: if (arg->udf_arg->at) {
1321: (void) putc('\n', stderr);
1322: disp_at(arg->udf_arg->at, level + 2); /* recurse! */
1323: } else
1324: fputs(" (undefined)\n", stderr);
1325: } else
1326: (void) putc('\n', stderr);
1327: break;
1328: case CALLN:
1329: fprintf(stderr, " %s", arg->udf_arg->udf_name);
1330: if (level < 6) {
1331: if (arg->udf_arg->at) {
1332: (void) putc('\n', stderr);
1333: disp_at(arg->udf_arg->at, level + 2); /* recurse! */
1334: } else
1335: fputs(" (undefined)\n", stderr);
1336: } else
1337: (void) putc('\n', stderr);
1338: break;
1339: case JUMP:
1340: case JUMPZ:
1341: case JUMPNZ:
1342: case JTERN:
1343: fprintf(stderr, " +%d\n", arg->j_arg);
1344: break;
1345: case DOLLARS:
1346: fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
1347: break;
1348: default:
1349: (void) putc('\n', stderr);
1350: }
1351: }
1352: }
1353:
1354: /* find max len of keys and count keys with len > 0 */
1355:
1356: int find_maxl_keys(plots, count, kcnt)
1357: struct curve_points *plots;
1358: int count, *kcnt;
1359: {
1360: int mlen, len, curve, cnt;
1361: register struct curve_points *this_plot;
1362:
1363: mlen = cnt = 0;
1364: this_plot = plots;
1365: for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
1366: if (this_plot->title
1367: && ((len = /*assign */ strlen(this_plot->title)) != 0) /* HBB 980308: quiet BCC warning */
1368: ) {
1369: cnt++;
1370: if (len > mlen)
1371: mlen = strlen(this_plot->title);
1372: }
1373: if (kcnt != NULL)
1374: *kcnt = cnt;
1375: return (mlen);
1376: }
1377:
1378:
1379: /* calculate the number and max-width of the keys for an splot.
1380: * Note that a blank line is issued after each set of contours
1381: */
1382: int find_maxl_keys3d(plots, count, kcnt)
1383: struct surface_points *plots;
1384: int count, *kcnt;
1385: {
1386: int mlen, len, surf, cnt;
1387: struct surface_points *this_plot;
1388:
1389: mlen = cnt = 0;
1390: this_plot = plots;
1391: for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
1392:
1393: /* we draw a main entry if there is one, and we are
1394: * drawing either surface, or unlabelled contours
1395: */
1396: if (this_plot->title && *this_plot->title &&
1397: (draw_surface || (draw_contour && !label_contours))) {
1398: ++cnt;
1399: len = strlen(this_plot->title);
1400: if (len > mlen)
1401: mlen = len;
1402: }
1403: if (draw_contour && label_contours && this_plot->contours != NULL) {
1404: len = find_maxl_cntr(this_plot->contours, &cnt);
1405: if (len > mlen)
1406: mlen = len;
1407: }
1408: }
1409:
1410: if (kcnt != NULL)
1411: *kcnt = cnt;
1412: return (mlen);
1413: }
1414:
1415: static int find_maxl_cntr(contours, count)
1416: struct gnuplot_contours *contours;
1417: int *count;
1418: {
1419: register int cnt;
1420: register int mlen, len;
1421: register struct gnuplot_contours *cntrs = contours;
1422:
1423: mlen = cnt = 0;
1424: while (cntrs) {
1425: if (label_contours && cntrs->isNewLevel) {
1426: len = strlen(cntrs->label);
1427: if (len)
1428: cnt++;
1429: if (len > mlen)
1430: mlen = len;
1431: }
1432: cntrs = cntrs->next;
1433: }
1434: *count += cnt;
1435: return (mlen);
1436: }
1437:
1438: static void save_range(fp, axis, min, max, autosc, text)
1439: FILE *fp;
1440: int axis;
1441: double min, max;
1442: TBOOLEAN autosc;
1443: char *text;
1444: {
1445: int i;
1446:
1447: i = axis;
1448: fprintf(fp, "set %srange [ ", text);
1449: if (autosc & 1) {
1450: putc('*', fp);
1451: } else {
1452: SAVE_NUM_OR_TIME(fp, min, axis);
1453: }
1454: fputs(" : ", fp);
1455: if (autosc & 2) {
1456: putc('*', fp);
1457: } else {
1458: SAVE_NUM_OR_TIME(fp, max, axis);
1459: }
1460:
1461: fprintf(fp, " ] %sreverse %swriteback",
1462: range_flags[axis] & RANGE_REVERSE ? "" : "no",
1463: range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
1464:
1465: if (autosc) {
1466: /* add current (hidden) range as comments */
1467: fputs(" # (currently [", fp);
1468: if (autosc & 1) {
1469: SAVE_NUM_OR_TIME(fp, min, axis);
1470: }
1471: putc(':', fp);
1472: if (autosc & 2) {
1473: SAVE_NUM_OR_TIME(fp, max, axis);
1474: }
1475: fputs("] )", fp);
1476: }
1477: putc('\n', fp);
1478: }
1479:
1480: /* check user defined format strings for valid double conversions */
1481: TBOOLEAN valid_format(format)
1482: const char *format;
1483: {
1484: for (;;) {
1485: if (!(format = strchr(format, '%'))) /* look for format spec */
1486: return TRUE; /* passed Test */
1487: do { /* scan format statement */
1488: format++;
1489: } while (strchr("+-#0123456789.", *format));
1490:
1491: switch (*format) { /* Now at format modifier */
1492: case '*': /* Ignore '*' statements */
1493: case '%': /* Char '%' itself */
1494: format++;
1495: continue;
1496: case 'l': /* Now we found it !!! */
1497: if (!strchr("fFeEgG", format[1])) /* looking for a valid format */
1498: return FALSE;
1499: format++;
1500: break;
1501: default:
1502: return FALSE;
1503: }
1504: }
1505: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>