Annotation of OpenXM_contrib/gnuplot/misc.c, Revision 1.1.1.3
1.1 maekawa 1: #ifndef lint
1.1.1.3 ! ohara 2: static char *RCSid = "$Id: misc.c,v 1.15.2.5 2002/04/21 13:52:55 broeker Exp $";
1.1 maekawa 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 {\
1.1.1.2 maekawa 71: fprintf(fp,"%#g",x);\
1.1 maekawa 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:
1.1.1.3 ! ohara 103: cp = (struct curve_points *) gp_alloc(sizeof(struct curve_points), "curve");
1.1 maekawa 104: cp->p_max = (num >= 0 ? num : 0);
105:
106: if (num > 0) {
107: cp->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara 108: gp_alloc(num * sizeof(struct coordinate), "curve points");
1.1 maekawa 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 *)
1.1.1.3 ! ohara 141: gp_alloc(num * sizeof(struct coordinate), "curve points");
1.1 maekawa 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;
1.1.1.3 ! ohara 181: ip = (struct iso_curve *) gp_alloc(sizeof(struct iso_curve), "iso curve");
1.1 maekawa 182: ip->p_max = (num >= 0 ? num : 0);
183: if (num > 0) {
184: ip->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara 185: gp_alloc(num * sizeof(struct coordinate), "iso curve points");
1.1 maekawa 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 *)
1.1.1.3 ! ohara 215: gp_alloc(num * sizeof(struct coordinate), "iso curve points");
1.1 maekawa 216: } else {
217: ip->points = (struct coordinate GPHUGE *)
1.1.1.3 ! ohara 218: gp_realloc(ip->points, num * sizeof(struct coordinate), "expanding curve points");
1.1 maekawa 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:
1.1.1.3 ! ohara 255: sp = (struct surface_points *) gp_alloc(sizeof(struct surface_points), "surface");
1.1 maekawa 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;
1.1.1.2 maekawa 452: char str[MAX_LINE_LEN+1];
1.1 maekawa 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:
1.1.1.2 maekawa 505: fprintf(fp, "set dummy %s,%s\n",dummy_var[0], dummy_var[1]);
506: fprintf(fp, "set format x \"%s\"\n", conv_text(str, xformat));
507: fprintf(fp, "set format y \"%s\"\n", conv_text(str, yformat));
508: fprintf(fp, "set format x2 \"%s\"\n", conv_text(str, x2format));
509: fprintf(fp, "set format y2 \"%s\"\n", conv_text(str, y2format));
510: fprintf(fp, "set format z \"%s\"\n", conv_text(str, zformat));
511: fprintf(fp, "set angles %s\n",
1.1 maekawa 512: (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
513:
514: if (work_grid.l_type == 0)
515: fputs("set nogrid\n", fp);
516: else {
517: if (polar_grid_angle) /* set angle already output */
518: fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
519: else
520: fputs("set grid nopolar\n", fp);
521: fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
522: work_grid.l_type & GRID_X ? "" : "no",
523: work_grid.l_type & GRID_Y ? "" : "no",
524: work_grid.l_type & GRID_Z ? "" : "no",
525: work_grid.l_type & GRID_X2 ? "" : "no",
526: work_grid.l_type & GRID_Y2 ? "" : "no",
527: work_grid.l_type & GRID_MX ? "" : "no",
528: work_grid.l_type & GRID_MY ? "" : "no",
529: work_grid.l_type & GRID_MZ ? "" : "no",
530: work_grid.l_type & GRID_MX2 ? "" : "no",
531: work_grid.l_type & GRID_MY2 ? "" : "no",
532: grid_lp.l_type + 1, grid_lp.l_width,
533: mgrid_lp.l_type + 1, mgrid_lp.l_width);
534: }
535: fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
536: switch (key) {
537: case -1:{
538: fputs("set key", fp);
539: switch (key_hpos) {
540: case TRIGHT:
541: fputs(" right", fp);
542: break;
543: case TLEFT:
544: fputs(" left", fp);
545: break;
546: case TOUT:
547: fputs(" out", fp);
548: break;
549: }
550: switch (key_vpos) {
551: case TTOP:
552: fputs(" top", fp);
553: break;
554: case TBOTTOM:
555: fputs(" bottom", fp);
556: break;
557: case TUNDER:
558: fputs(" below", fp);
559: break;
560: }
561: break;
562: }
563: case 0:
564: fputs("set nokey\n", fp);
565: break;
566: case 1:
567: fputs("set key ", fp);
568: save_position(fp, &key_user_pos);
569: break;
570: }
571: if (key) {
572: fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
573: key_just == JLEFT ? "Left" : "Right",
574: key_reverse ? "" : "no",
575: key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
576: }
577: fputs("set nolabel\n", fp);
578: for (this_label = first_label; this_label != NULL;
579: this_label = this_label->next) {
580: fprintf(fp, "set label %d \"%s\" at ",
581: this_label->tag,
582: conv_text(str, this_label->text));
583: save_position(fp, &this_label->place);
584:
585: switch (this_label->pos) {
586: case LEFT:
587: fputs(" left", fp);
588: break;
589: case CENTRE:
590: fputs(" centre", fp);
591: break;
592: case RIGHT:
593: fputs(" right", fp);
594: break;
595: }
596: fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
597: if ((this_label->font)[0] != NUL)
598: fprintf(fp, " font \"%s\"", this_label->font);
599: /* Entry font added by DJL */
600: fputc('\n', fp);
601: }
602: fputs("set noarrow\n", fp);
603: for (this_arrow = first_arrow; this_arrow != NULL;
604: this_arrow = this_arrow->next) {
605: fprintf(fp, "set arrow %d from ", this_arrow->tag);
606: save_position(fp, &this_arrow->start);
607: fputs(" to ", fp);
608: save_position(fp, &this_arrow->end);
609: fprintf(fp, " %s linetype %d linewidth %.3f\n",
610: this_arrow->head ? "" : " nohead",
611: this_arrow->lp_properties.l_type + 1,
612: this_arrow->lp_properties.l_width);
613: }
614: fputs("set nolinestyle\n", fp);
615: for (this_linestyle = first_linestyle; this_linestyle != NULL;
616: this_linestyle = this_linestyle->next) {
617: fprintf(fp, "set linestyle %d ", this_linestyle->tag);
618: fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
619: this_linestyle->lp_properties.l_type + 1,
620: this_linestyle->lp_properties.l_width,
621: this_linestyle->lp_properties.p_type + 1,
622: this_linestyle->lp_properties.p_size);
623: }
624: fputs("set nologscale\n", fp);
625: if (is_log_x)
626: fprintf(fp, "set logscale x %g\n", base_log_x);
627: if (is_log_y)
628: fprintf(fp, "set logscale y %g\n", base_log_y);
629: if (is_log_z)
630: fprintf(fp, "set logscale z %g\n", base_log_z);
631: if (is_log_x2)
632: fprintf(fp, "set logscale x2 %g\n", base_log_x2);
633: if (is_log_y2)
634: fprintf(fp, "set logscale y2 %g\n", base_log_y2);
635:
636: fprintf(fp, "\
637: set offsets %g, %g, %g, %g\n\
638: set pointsize %g\n\
639: set encoding %s\n\
640: set %spolar\n\
641: set %sparametric\n\
642: set view %g, %g, %g, %g\n\
643: set samples %d, %d\n\
644: set isosamples %d, %d\n\
645: set %ssurface\n\
646: set %scontour",
647: loff, roff, toff, boff,
648: pointsize,
649: encoding_names[encoding],
650: (polar) ? "" : "no",
651: (parametric) ? "" : "no",
652: surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
653: samples_1, samples_2,
654: iso_samples_1, iso_samples_2,
655: (draw_surface) ? "" : "no",
656: (draw_contour) ? "" : "no");
657:
658: switch (draw_contour) {
659: case CONTOUR_NONE:
660: fputc('\n', fp);
661: break;
662: case CONTOUR_BASE:
663: fputs(" base\n", fp);
664: break;
665: case CONTOUR_SRF:
666: fputs(" surface\n", fp);
667: break;
668: case CONTOUR_BOTH:
669: fputs(" both\n", fp);
670: break;
671: }
672: if (label_contours)
673: fprintf(fp, "set clabel '%s'\n", contour_format);
674: else
675: fputs("set noclabel\n", fp);
676:
677: fputs("set mapping ", fp);
678: switch(mapping3d) {
679: case MAP3D_SPHERICAL:
680: fputs("spherical\n", fp);
681: break;
682: case MAP3D_CYLINDRICAL:
683: fputs("cylindrical\n", fp);
684: break;
685: case MAP3D_CARTESIAN:
686: default:
687: fputs("cartesian\n", fp);
688: break;
689: }
690:
691: if (missing_val != NULL)
1.1.1.3 ! ohara 692: fprintf(fp, "set missing '%s'\n", missing_val);
1.1 maekawa 693:
694: save_hidden3doptions(fp);
695: fprintf(fp, "set cntrparam order %d\n", contour_order);
696: fputs("set cntrparam ", fp);
697: switch (contour_kind) {
698: case CONTOUR_KIND_LINEAR:
699: fputs("linear\n", fp);
700: break;
701: case CONTOUR_KIND_CUBIC_SPL:
702: fputs("cubicspline\n", fp);
703: break;
704: case CONTOUR_KIND_BSPLINE:
705: fputs("bspline\n", fp);
706: break;
707: }
708: fputs("set cntrparam levels ", fp);
709: switch (levels_kind) {
710: case LEVELS_AUTO:
711: fprintf(fp, "auto %d\n", contour_levels);
712: break;
713: case LEVELS_INCREMENTAL:
714: fprintf(fp, "incremental %g,%g,%g\n",
715: levels_list[0], levels_list[1],
716: levels_list[0] + levels_list[1] * contour_levels);
717: break;
718: case LEVELS_DISCRETE:
719: {
720: int i;
721: fprintf(fp, "discrete %g", levels_list[0]);
722: for (i = 1; i < contour_levels; i++)
723: fprintf(fp, ",%g ", levels_list[i]);
724: fputc('\n', fp);
725: }
726: }
727: fprintf(fp, "\
728: set cntrparam points %d\n\
729: set size ratio %g %g,%g\n\
730: set origin %g,%g\n\
731: set data style ",
732: contour_pts,
733: aspect_ratio, xsize, ysize,
734: xoffset, yoffset);
735:
736: switch (data_style) {
737: case LINES:
738: fputs("lines\n", fp);
739: break;
740: case POINTSTYLE:
741: fputs("points\n", fp);
742: break;
743: case IMPULSES:
744: fputs("impulses\n", fp);
745: break;
746: case LINESPOINTS:
747: fputs("linespoints\n", fp);
748: break;
749: case DOTS:
750: fputs("dots\n", fp);
751: break;
752: case YERRORBARS:
753: fputs("yerrorbars\n", fp);
754: break;
755: case XERRORBARS:
756: fputs("xerrorbars\n", fp);
757: break;
758: case XYERRORBARS:
759: fputs("xyerrorbars\n", fp);
760: break;
761: case BOXES:
762: fputs("boxes\n", fp);
763: break;
764: case BOXERROR:
765: fputs("boxerrorbars\n", fp);
766: break;
767: case BOXXYERROR:
768: fputs("boxxyerrorbars\n", fp);
769: break;
770: case STEPS:
771: fputs("steps\n", fp);
772: break; /* JG */
773: case FSTEPS:
774: fputs("fsteps\n", fp);
775: break; /* HOE */
776: case HISTEPS:
777: fputs("histeps\n", fp);
778: break; /* CAC */
779: case VECTOR:
780: fputs("vector\n", fp);
781: break;
782: case FINANCEBARS:
783: fputs("financebars\n", fp);
784: break;
785: case CANDLESTICKS:
786: fputs("candlesticks\n", fp);
787: break;
788: }
789: fputs("set function style ", fp);
790: switch (func_style) {
791: case LINES:
792: fputs("lines\n", fp);
793: break;
794: case POINTSTYLE:
795: fputs("points\n", fp);
796: break;
797: case IMPULSES:
798: fputs("impulses\n", fp);
799: break;
800: case LINESPOINTS:
801: fputs("linespoints\n", fp);
802: break;
803: case DOTS:
804: fputs("dots\n", fp);
805: break;
806: case YERRORBARS:
807: fputs("yerrorbars\n", fp);
808: break;
809: case XERRORBARS:
810: fputs("xerrorbars\n", fp);
811: break;
812: case XYERRORBARS:
813: fputs("xyerrorbars\n", fp);
814: break;
815: case BOXXYERROR:
816: fputs("boxxyerrorbars\n", fp);
817: break;
818: case BOXES:
819: fputs("boxes\n", fp);
820: break;
821: case BOXERROR:
822: fputs("boxerrorbars\n", fp);
823: break;
824: case STEPS:
825: fputs("steps\n", fp);
826: break; /* JG */
827: case FSTEPS:
828: fputs("fsteps\n", fp);
829: break; /* HOE */
830: case HISTEPS:
831: fputs("histeps\n", fp);
832: break; /* CAC */
833: case VECTOR:
834: fputs("vector\n", fp);
835: break;
836: case FINANCEBARS:
837: fputs("financebars\n", fp);
838: break;
839: case CANDLESTICKS:
840: fputs("candlesticks\n", fp);
841: break;
842: default:
843: /* HBB: default case demanded by gcc, still needed ?? */
844: fputs("---error!---\n", fp);
845: }
846:
847: fprintf(fp, "\
848: set xzeroaxis lt %d lw %.3f\n\
849: set x2zeroaxis lt %d lw %.3f\n\
850: set yzeroaxis lt %d lw %.3f\n\
851: set y2zeroaxis lt %d lw %.3f\n\
852: set tics %s\n\
853: set ticslevel %g\n\
854: set ticscale %g %g\n",
855: xzeroaxis.l_type + 1, xzeroaxis.l_width,
856: x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
857: yzeroaxis.l_type + 1, yzeroaxis.l_width,
858: y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
859: (tic_in) ? "in" : "out",
860: ticslevel,
861: ticscale, miniticscale);
862:
863: #define SAVE_XYZLABEL(name,lab) { \
864: fprintf(fp, "set %s \"%s\" %f,%f ", \
865: name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
866: fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
867: }
868:
869:
870: #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
871: case 0: fprintf(fp, "set no%s\n", name); break; \
872: case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
873: case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
874: case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
875: }
876: SAVE_MINI("mxtics", mxtics, mxtfreq)
877: SAVE_MINI("mytics", mytics, mytfreq)
878: SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
879: SAVE_MINI("my2tics", my2tics, my2tfreq)
880: save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
881: save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
882: save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
883: save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
884: save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
885: SAVE_XYZLABEL("title", title);
886:
887: fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
888: "timestamp", conv_text(str, timelabel.text),
889: (timelabel_bottom ? "bottom" : "top"),
890: (timelabel_rotate ? "" : "no"),
891: timelabel.xoffset, timelabel.yoffset);
892: fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
893:
894: save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
895: save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
896: save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
897: save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
898:
899: SAVE_XYZLABEL("xlabel", xlabel);
900: SAVE_XYZLABEL("x2label", x2label);
901:
902: if (strlen(timefmt)) {
903: fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
904: }
905: save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
906: save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
907:
908: SAVE_XYZLABEL("ylabel", ylabel);
909: SAVE_XYZLABEL("y2label", y2label);
910:
911: save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
912: save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
913:
914: SAVE_XYZLABEL("zlabel", zlabel);
915: save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
916:
917: fprintf(fp, "set zero %g\n", zero);
918: fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
919: lmargin, bmargin, rmargin, tmargin);
920:
921: fprintf(fp, "set locale \"%s\"\n", cur_locale);
922: }
923:
924: static void save_tics(fp, where, axis, tdef, rotate, text)
925: FILE *fp;
926: int where;
927: int axis;
928: struct ticdef *tdef;
929: TBOOLEAN rotate;
930: char *text;
931: {
932: char str[MAX_LINE_LEN + 1];
933:
934: if (where == NO_TICS) {
935: fprintf(fp, "set no%stics\n", text);
936: return;
937: }
938: fprintf(fp, "set %stics %s %smirror %srotate ", text,
939: (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
940: (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
941: switch (tdef->type) {
942: case TIC_COMPUTED:{
943: fputs("autofreq ", fp);
944: break;
945: }
946: case TIC_MONTH:{
947: fprintf(fp, "\nset %smtics", text);
948: break;
949: }
950: case TIC_DAY:{
951: fprintf(fp, "\nset %cdtics", axis);
952: break;
953: }
954: case TIC_SERIES:
955: if (datatype[axis] == TIME) {
956: if (tdef->def.series.start != -VERYLARGE) {
957: char fd[26];
958: gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
959: fprintf(fp, "\"%s\",", conv_text(str, fd));
960: }
961: fprintf(fp, "%g", tdef->def.series.incr);
962:
963: if (tdef->def.series.end != VERYLARGE) {
964: char td[26];
965: gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
966: fprintf(fp, ",\"%s\"", conv_text(str, td));
967: }
968: } else { /* !TIME */
969:
970: if (tdef->def.series.start != -VERYLARGE)
971: fprintf(fp, "%g,", tdef->def.series.start);
972: fprintf(fp, "%g", tdef->def.series.incr);
973: if (tdef->def.series.end != VERYLARGE)
974: fprintf(fp, ",%g", tdef->def.series.end);
975: }
976:
977: break;
978:
979: case TIC_USER:{
980: register struct ticmark *t;
981: int flag_time;
982: flag_time = (datatype[axis] == TIME);
983: fputs(" (", fp);
984: for (t = tdef->def.user; t != NULL; t = t->next) {
985: if (t->label)
986: fprintf(fp, "\"%s\" ", conv_text(str, t->label));
987: if (flag_time) {
988: char td[26];
989: gstrftime(td, 24, timefmt, (double) t->position);
990: fprintf(fp, "\"%s\"", conv_text(str, td));
991: } else {
992: fprintf(fp, "%g", t->position);
993: }
994: if (t->next) {
995: fputs(", ", fp);
996: }
997: }
998: fputs(")", fp);
999: break;
1000: }
1001: }
1002: putc('\n', fp);
1003: }
1004:
1005: static void save_position(fp, pos)
1006: FILE *fp;
1007: struct position *pos;
1008: {
1009: static char *msg[] =
1.1.1.3 ! ohara 1010: {"first ", "second ", "graph ", "screen "};
1.1 maekawa 1011:
1012: assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
1013:
1014: fprintf(fp, "%s%g, %s%g, %s%g",
1015: pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
1016: pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
1017: pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
1018: }
1019:
1020: void load_file(fp, name, can_do_args)
1021: FILE *fp;
1022: char *name;
1023: TBOOLEAN can_do_args;
1024: {
1025: register int len;
1026:
1027: int start, left;
1028: int more;
1029: int stop = FALSE;
1030:
1031: lf_push(fp); /* save state for errors and recursion */
1032: do_load_arg_substitution = can_do_args;
1033:
1034: if (fp == (FILE *) NULL) {
1035: /* HBB 980311: alloc() it, to save valuable stack space: */
1036: char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
1037: (void) sprintf(errbuf, "Cannot open %s file '%s'",
1038: can_do_args ? "call" : "load", name);
1039: os_error(errbuf, c_token);
1040: free(errbuf);
1041: } else if (fp == stdin) {
1042: /* DBT 10-6-98 go interactive if "-" named as load file */
1043: interactive = TRUE;
1044: while(!com_line())
1045: ;
1046: } else {
1047: /* go into non-interactive mode during load */
1048: /* will be undone below, or in load_file_error */
1049: interactive = FALSE;
1050: inline_num = 0;
1051: infile_name = name;
1052:
1053: if (can_do_args) {
1054: int aix = 0;
1055: while (++c_token < num_tokens && aix <= 9) {
1056: if (isstring(c_token))
1057: m_quote_capture(&call_args[aix++], c_token, c_token);
1058: else
1059: m_capture(&call_args[aix++], c_token, c_token);
1060: }
1061:
1062: /* A GNUPLOT "call" command can have up to _10_ arguments named "$0"
1063: to "$9". After reading the 10th argument (i.e.: "$9") the variable
1064: 'aix' contains the value '10' because of the 'aix++' construction
1065: in '&call_args[aix++]'. So I think the following test of 'aix'
1066: should be done against '10' instead of '9'. (JFi) */
1067:
1068: /* if (c_token >= num_tokens && aix > 9) */
1069: if (c_token >= num_tokens && aix > 10)
1070: int_error("too many arguments for CALL <file>", ++c_token);
1071: }
1072: while (!stop) { /* read all commands in file */
1073: /* read one command */
1074: left = input_line_len;
1075: start = 0;
1076: more = TRUE;
1077:
1078: while (more) {
1079: if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
1080: stop = TRUE; /* EOF in file */
1081: input_line[start] = '\0';
1082: more = FALSE;
1083: } else {
1084: inline_num++;
1085: len = strlen(input_line) - 1;
1086: if (input_line[len] == '\n') { /* remove any newline */
1087: input_line[len] = '\0';
1088: /* Look, len was 1-1 = 0 before, take care here! */
1089: if (len > 0)
1090: --len;
1091: if (input_line[len] == '\r') { /* remove any carriage return */
1092: input_line[len] = NUL;
1093: if (len > 0)
1094: --len;
1095: }
1096: }
1097: else if (len + 2 >= left) {
1098: extend_input_line();
1099: left = input_line_len - len - 1;
1100: start = len + 1;
1101: continue; /* don't check for '\' */
1102: }
1103: if (input_line[len] == '\\') {
1104: /* line continuation */
1105: start = len;
1106: left = input_line_len - start;
1107: } else
1108: more = FALSE;
1109: }
1110: }
1111:
1112: if (strlen(input_line) > 0) {
1113: if (can_do_args) {
1114: register int il = 0;
1115: register char *rl;
1.1.1.3 ! ohara 1116: char *raw_line = gp_strdup(input_line);
1.1 maekawa 1117:
1.1.1.3 ! ohara 1118: rl = raw_line;
1.1 maekawa 1119: *input_line = '\0';
1120: while (*rl) {
1121: register int aix;
1122: if (*rl == '$'
1123: && ((aix = *(++rl)) != 0) /* HBB 980308: quiet BCC warning */
1124: &&aix >= '0' && aix <= '9') {
1125: if (call_args[aix -= '0']) {
1126: len = strlen(call_args[aix]);
1127: while (input_line_len - il < len + 1) {
1128: extend_input_line();
1129: }
1130: strcpy(input_line + il, call_args[aix]);
1131: il += len;
1132: }
1133: } else {
1134: /* substitute for $<n> here */
1135: if (il + 1 > input_line_len) {
1136: extend_input_line();
1137: }
1138: input_line[il++] = *rl;
1139: }
1140: rl++;
1141: }
1142: if (il + 1 > input_line_len) {
1143: extend_input_line();
1144: }
1145: input_line[il] = '\0';
1146: free(raw_line);
1147: }
1148: screen_ok = FALSE; /* make sure command line is
1149: echoed on error */
1.1.1.2 maekawa 1150: if (do_line())
1151: stop = TRUE;
1.1 maekawa 1152: }
1153: }
1154: }
1155:
1156: /* pop state */
1157: (void) lf_pop(); /* also closes file fp */
1158: }
1159:
1160: /* pop from load_file state stack */
1161: static TBOOLEAN /* FALSE if stack was empty */
1162: lf_pop()
1163: { /* called by load_file and load_file_error */
1164: LFS *lf;
1165:
1166: if (lf_head == NULL)
1167: return (FALSE);
1168: else {
1169: int argindex;
1170: lf = lf_head;
1171: if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
1172: /* DBT 10-6-98 do not close stdin in the case
1173: * that "-" is named as a load file
1174: */
1175: (void) fclose(lf->fp);
1176: }
1177: for (argindex = 0; argindex < 10; argindex++) {
1178: if (call_args[argindex]) {
1179: free(call_args[argindex]);
1180: }
1181: call_args[argindex] = lf->call_args[argindex];
1182: }
1183: do_load_arg_substitution = lf->do_load_arg_substitution;
1184: interactive = lf->interactive;
1185: inline_num = lf->inline_num;
1186: infile_name = lf->name;
1187: lf_head = lf->prev;
1188: free((char *) lf);
1189: return (TRUE);
1190: }
1191: }
1192:
1193: /* push onto load_file state stack */
1194: /* essentially, we save information needed to undo the load_file changes */
1195: static void lf_push(fp) /* called by load_file */
1196: FILE *fp;
1197: {
1198: LFS *lf;
1199: int argindex;
1200:
1.1.1.3 ! ohara 1201: lf = (LFS *) gp_alloc(sizeof(LFS), (char *) NULL);
1.1 maekawa 1202: if (lf == (LFS *) NULL) {
1203: if (fp != (FILE *) NULL)
1204: (void) fclose(fp); /* it won't be otherwise */
1205: int_error("not enough memory to load file", c_token);
1206: }
1207: lf->fp = fp; /* save this file pointer */
1208: lf->name = infile_name; /* save current name */
1209: lf->interactive = interactive; /* save current state */
1210: lf->inline_num = inline_num; /* save current line number */
1211: lf->do_load_arg_substitution = do_load_arg_substitution;
1212: for (argindex = 0; argindex < 10; argindex++) {
1213: lf->call_args[argindex] = call_args[argindex];
1214: call_args[argindex] = NULL; /* initially no args */
1215: }
1216: lf->prev = lf_head; /* link to stack */
1217: lf_head = lf;
1218: }
1219:
1220: /* used for reread vsnyder@math.jpl.nasa.gov */
1221: FILE *lf_top()
1222: {
1223: if (lf_head == (LFS *) NULL)
1224: return ((FILE *) NULL);
1225: return (lf_head->fp);
1226: }
1227:
1228: /* called from main */
1229: void load_file_error()
1230: {
1231: /* clean up from error in load_file */
1232: /* pop off everything on stack */
1233: while (lf_pop());
1234: }
1235:
1236: /* find char c in string str; return p such that str[p]==c;
1237: * if c not in str then p=strlen(str)
1238: */
1239: int instring(str, c)
1240: char *str;
1241: int c;
1242: {
1243: int pos = 0;
1244:
1245: while (str != NULL && *str != NUL && c != *str) {
1246: str++;
1247: pos++;
1248: }
1249: return (pos);
1250: }
1251:
1252: void show_functions()
1253: {
1254: register struct udft_entry *udf = first_udf;
1255:
1256: fputs("\n\tUser-Defined Functions:\n", stderr);
1257:
1258: while (udf) {
1259: if (udf->definition)
1260: fprintf(stderr, "\t%s\n", udf->definition);
1261: else
1262: fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
1263: udf = udf->next_udf;
1264: }
1265: }
1266:
1267:
1268: void show_at()
1269: {
1270: (void) putc('\n', stderr);
1271: disp_at(temp_at(), 0);
1272: }
1273:
1274:
1275: void disp_at(curr_at, level)
1276: struct at_type *curr_at;
1277: int level;
1278: {
1279: register int i, j;
1280: register union argument *arg;
1281:
1282: for (i = 0; i < curr_at->a_count; i++) {
1283: (void) putc('\t', stderr);
1284: for (j = 0; j < level; j++)
1285: (void) putc(' ', stderr); /* indent */
1286:
1287: /* print name of instruction */
1288:
1289: fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
1290: arg = &(curr_at->actions[i].arg);
1291:
1292: /* now print optional argument */
1293:
1294: switch (curr_at->actions[i].index) {
1295: case PUSH:
1296: fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
1297: break;
1298: case PUSHC:
1299: (void) putc(' ', stderr);
1300: disp_value(stderr, &(arg->v_arg));
1301: (void) putc('\n', stderr);
1302: break;
1303: case PUSHD1:
1304: fprintf(stderr, " %c dummy\n",
1305: arg->udf_arg->udf_name[0]);
1306: break;
1307: case PUSHD2:
1308: fprintf(stderr, " %c dummy\n",
1309: arg->udf_arg->udf_name[1]);
1310: break;
1311: case CALL:
1312: fprintf(stderr, " %s", arg->udf_arg->udf_name);
1313: if (level < 6) {
1314: if (arg->udf_arg->at) {
1315: (void) putc('\n', stderr);
1316: disp_at(arg->udf_arg->at, level + 2); /* recurse! */
1317: } else
1318: fputs(" (undefined)\n", stderr);
1319: } else
1320: (void) putc('\n', stderr);
1321: break;
1322: case CALLN:
1323: fprintf(stderr, " %s", arg->udf_arg->udf_name);
1324: if (level < 6) {
1325: if (arg->udf_arg->at) {
1326: (void) putc('\n', stderr);
1327: disp_at(arg->udf_arg->at, level + 2); /* recurse! */
1328: } else
1329: fputs(" (undefined)\n", stderr);
1330: } else
1331: (void) putc('\n', stderr);
1332: break;
1333: case JUMP:
1334: case JUMPZ:
1335: case JUMPNZ:
1336: case JTERN:
1337: fprintf(stderr, " +%d\n", arg->j_arg);
1338: break;
1339: case DOLLARS:
1340: fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
1341: break;
1342: default:
1343: (void) putc('\n', stderr);
1344: }
1345: }
1346: }
1347:
1348: /* find max len of keys and count keys with len > 0 */
1349:
1350: int find_maxl_keys(plots, count, kcnt)
1351: struct curve_points *plots;
1352: int count, *kcnt;
1353: {
1354: int mlen, len, curve, cnt;
1355: register struct curve_points *this_plot;
1356:
1357: mlen = cnt = 0;
1358: this_plot = plots;
1359: for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
1360: if (this_plot->title
1361: && ((len = /*assign */ strlen(this_plot->title)) != 0) /* HBB 980308: quiet BCC warning */
1362: ) {
1363: cnt++;
1364: if (len > mlen)
1365: mlen = strlen(this_plot->title);
1366: }
1367: if (kcnt != NULL)
1368: *kcnt = cnt;
1369: return (mlen);
1370: }
1371:
1372:
1373: /* calculate the number and max-width of the keys for an splot.
1374: * Note that a blank line is issued after each set of contours
1375: */
1376: int find_maxl_keys3d(plots, count, kcnt)
1377: struct surface_points *plots;
1378: int count, *kcnt;
1379: {
1380: int mlen, len, surf, cnt;
1381: struct surface_points *this_plot;
1382:
1383: mlen = cnt = 0;
1384: this_plot = plots;
1385: for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
1386:
1387: /* we draw a main entry if there is one, and we are
1388: * drawing either surface, or unlabelled contours
1389: */
1390: if (this_plot->title && *this_plot->title &&
1391: (draw_surface || (draw_contour && !label_contours))) {
1392: ++cnt;
1393: len = strlen(this_plot->title);
1394: if (len > mlen)
1395: mlen = len;
1396: }
1397: if (draw_contour && label_contours && this_plot->contours != NULL) {
1398: len = find_maxl_cntr(this_plot->contours, &cnt);
1399: if (len > mlen)
1400: mlen = len;
1401: }
1402: }
1403:
1404: if (kcnt != NULL)
1405: *kcnt = cnt;
1406: return (mlen);
1407: }
1408:
1409: static int find_maxl_cntr(contours, count)
1410: struct gnuplot_contours *contours;
1411: int *count;
1412: {
1413: register int cnt;
1414: register int mlen, len;
1415: register struct gnuplot_contours *cntrs = contours;
1416:
1417: mlen = cnt = 0;
1418: while (cntrs) {
1419: if (label_contours && cntrs->isNewLevel) {
1420: len = strlen(cntrs->label);
1421: if (len)
1422: cnt++;
1423: if (len > mlen)
1424: mlen = len;
1425: }
1426: cntrs = cntrs->next;
1427: }
1428: *count += cnt;
1429: return (mlen);
1430: }
1431:
1432: static void save_range(fp, axis, min, max, autosc, text)
1433: FILE *fp;
1434: int axis;
1435: double min, max;
1436: TBOOLEAN autosc;
1437: char *text;
1438: {
1439: int i;
1440:
1441: i = axis;
1442: fprintf(fp, "set %srange [ ", text);
1443: if (autosc & 1) {
1444: putc('*', fp);
1445: } else {
1446: SAVE_NUM_OR_TIME(fp, min, axis);
1447: }
1448: fputs(" : ", fp);
1449: if (autosc & 2) {
1450: putc('*', fp);
1451: } else {
1452: SAVE_NUM_OR_TIME(fp, max, axis);
1453: }
1454:
1455: fprintf(fp, " ] %sreverse %swriteback",
1456: range_flags[axis] & RANGE_REVERSE ? "" : "no",
1457: range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
1458:
1459: if (autosc) {
1460: /* add current (hidden) range as comments */
1461: fputs(" # (currently [", fp);
1462: if (autosc & 1) {
1463: SAVE_NUM_OR_TIME(fp, min, axis);
1464: }
1465: putc(':', fp);
1466: if (autosc & 2) {
1467: SAVE_NUM_OR_TIME(fp, max, axis);
1468: }
1469: fputs("] )", fp);
1470: }
1471: putc('\n', fp);
1472: }
1473:
1474: /* check user defined format strings for valid double conversions */
1475: TBOOLEAN valid_format(format)
1476: const char *format;
1477: {
1478: for (;;) {
1479: if (!(format = strchr(format, '%'))) /* look for format spec */
1480: return TRUE; /* passed Test */
1481: do { /* scan format statement */
1482: format++;
1483: } while (strchr("+-#0123456789.", *format));
1484:
1485: switch (*format) { /* Now at format modifier */
1486: case '*': /* Ignore '*' statements */
1487: case '%': /* Char '%' itself */
1488: format++;
1489: continue;
1490: case 'l': /* Now we found it !!! */
1491: if (!strchr("fFeEgG", format[1])) /* looking for a valid format */
1492: return FALSE;
1493: format++;
1494: break;
1495: default:
1496: return FALSE;
1497: }
1498: }
1499: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>