Ilya Zakharevich on Mon, 7 Jun 1999 02:43:08 -0400 (EDT)


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

[PATCH 2.0.15] Newer gnuplot plotting


This more or less finishes (again? ;-) support for gnuplot terminals
as output for the graphic.

a) Strings were put too low in gnuplot terminal;
b) Allow setting of the output file sizes, as in plotterm("gif=300,200");
c) Allow querying of possible output terminals, via plotterm("?").
d) Update to newer Gnuplot-interface-layer (Gnuplot.h).  This
   allows compilation on Linux (stdout was bad as an initializer),
   corrects bugs in processing of terminal options.

Enjoy,
Ilya

diff -pru pari-2.0.15.beta.old/src/graph/Gnuplot.h pari-2.0.15.beta/src/graph/Gnuplot.h
--- pari-2.0.15.beta.old/src/graph/Gnuplot.h	Thu May 20 09:02:46 1999
+++ pari-2.0.15.beta/src/graph/Gnuplot.h	Mon Jun  7 01:54:42 1999
@@ -49,10 +49,20 @@
 
 /* Compatibility with the old gnuplot: */
 extern  FILE *outfile;
-FILE *outfile = stdout;
+FILE *outfile = NULL;
 
 extern  FILE *gpoutfile;
-FILE *gpoutfile = stdout;
+FILE *gpoutfile = NULL;
+
+static outfile_set;
+static void
+set_gpoutfile(void)
+{
+  outfile = stdout;
+  gpoutfile = stdout;
+}
+
+#define SET_OUTFILE (outfile_set++ ? 1 : set_gpoutfile(), 1)
 
 extern int encoding;
 int        encoding = 0;
@@ -226,9 +236,14 @@ struct termentry *term;
        ) :							\
        (term->flags & (mask)))
 
-#define do_init()	CALL_G_METH0(init)
-#define reset()	CALL_G_METH0(reset)
-#define text()	CALL_G_METH0(text)
+#ifdef DONT_POLLUTE_INIT
+#  define gptable_init()	CALL_G_METH0(init)
+#else
+#  define init()		CALL_G_METH0(init)
+#  define gptable_init		init
+#endif
+#define reset()		CALL_G_METH0(reset)
+#define text()		CALL_G_METH0(text)
 #define options()	CALL_G_METH0(options)
 #define graphics()	CALL_G_METH0(graphics)
 #define linetype(lt)	CALL_G_METH1(linetype,lt)
@@ -252,28 +267,127 @@ struct termentry *term;
 
 #define termprop(prop) (term->prop)
 #define termset(term) my_change_term(term,strlen(term))
+
 struct termentry * change_term(char*,int);
 
+#define TTABLE_STARTPLOT	0
+#define TTABLE_ENDPLOT		1
+#define TTABLE_STARTMPLOT	2
+#define TTABLE_ENDMPLOT		3
+#define TTABLE_INIT		4
+#define TTABLE_LIST		5
+#define TTABLE_COUNT		6
+
+typedef void (*TSET_FP)(char *s);
+typedef void (*TST_END_FP)(void);
+typedef void (*SET_SIZES_t)(double x, double y);
+typedef double (*GET_SIZES_t)(int flag);
+
+struct t_ftable {
+  int loaded;
+  FUNC_PTR change_term_p;
+  TSET_FP term_set_outputp;
+  SET_SIZES_t set_sizesp;
+  GET_SIZES_t get_sizesp;
+  TST_END_FP term_funcs[TTABLE_COUNT];
+};
+
 #ifdef DYNAMIC_PLOTTING			/* Can load plotting DLL later */
 
 UNKNOWN_null()
 {
-    err(talker,"gnuplot-like plotting environment not loaded yet");
+    croak("gnuplot-like plotting environment not loaded yet");
+}
+
+static void myterm_table_not_loaded_v(void);
+static void myterm_table_not_loaded(char*);
+static int myterm_table_not_loaded_u();
+static void myterm_table_not_loaded_vdd(double x, double y);
+static double myterm_table_not_loaded_di(int flag);
+
+#if 0
+static int ftable_warned;
+static void
+tmp_my_term_init
+{
+  if (!warned++)
+     warn("This runtime link with gnuplot-shim does not implement midlevel start/end functions");
+  shim_myinit();
+}
+#endif
+
+static struct t_ftable my_term_ftable = 
+{
+	0, &myterm_table_not_loaded_u, &myterm_table_not_loaded,
+	&myterm_table_not_loaded_vdd,
+	&myterm_table_not_loaded_di,
+	{&myterm_table_not_loaded_v, &myterm_table_not_loaded_v, 
+	 &myterm_table_not_loaded_v, &myterm_table_not_loaded_v,
+	 &myterm_table_not_loaded_v, &myterm_table_not_loaded_v}
+};
+
+static struct t_ftable *my_term_ftablep = &my_term_ftable;
+
+static void
+myterm_table_not_loaded_v(void)
+{
+    if (!my_term_ftablep->loaded) {
+        UNKNOWN_null();
+	return;
+    }
+    croak("This runtime link with gnuplot-shim does not implement midlevel start/end functions");
+}
+
+static void
+myterm_table_not_loaded(char *s)
+{
+  myterm_table_not_loaded_v();
+}
+
+static void
+myterm_table_not_loaded_vdd(double x, double y)
+{
+  myterm_table_not_loaded_v();
+}
+
+static double
+myterm_table_not_loaded_di(int flag)
+{
+  myterm_table_not_loaded_v();
+}
+
+static int
+myterm_table_not_loaded_u()
+{
+  myterm_table_not_loaded_v();
+  return 0;
 }
 
-static FUNC_PTR change_term_p;
+#  define change_term		(*my_term_ftablep->change_term_p)
+#  define term_set_output	(*my_term_ftablep->term_set_outputp)
+#  define term_start_plot	(*my_term_ftablep->term_funcs[TTABLE_STARTPLOT])
+#  define term_end_plot	(*my_term_ftablep->term_funcs[TTABLE_ENDPLOT])
+#  define term_start_multiplot	(*my_term_ftablep->term_funcs[TTABLE_STARTMPLOT])
+#  define term_end_multiplot	(*my_term_ftablep->term_funcs[TTABLE_ENDMPLOT])
+#  define term_init		(*my_term_ftablep->term_funcs[TTABLE_INIT])
+#  define list_terms		(*my_term_ftablep->term_funcs[TTABLE_LIST])
+#  define plotsizes_scale	(*my_term_ftablep->set_sizesp)
+#  define plotsizes_scale_get	(*my_term_ftablep->get_sizesp)
+
+#  define scaled_xmax()	((int)termprop(xmax)*plotsizes_scale_get(0))
+#  define scaled_ymax()	((int)termprop(ymax)*plotsizes_scale_get(1))
+
+#define USE_FUNCTION_FROM_TABLE
 
-struct termentry *
+static struct termentry *
 my_change_term(char*s,int l)
 {
-    if (!change_term_p)
+    SET_OUTFILE;
+    if (!my_term_ftablep->change_term_p)
 	UNKNOWN_null();
-    return term = (struct termentry *)(*change_term_p)(s,l);
+    return term = (struct termentry *)(*my_term_ftablep->change_term_p)(s,l);
 }
 
-#  define change_term(p,l) my_change_term(p,l)
-#  define term_tbl (my_term_tbl)
-
 static struct termentry dummy_term_tbl[] = {
     {"unknown", "Unknown terminal type - not a plotting device",
 	  100, 100, 1, 1,
@@ -283,45 +397,94 @@ static struct termentry dummy_term_tbl[]
      UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, 0,
 	  UNKNOWN_null, UNKNOWN_null, UNKNOWN_null, UNKNOWN_null},
 };
-static struct termentry *my_term_tbl = dummy_term_tbl;
 
-#  define term_set_output (*term_set_outputp)
-static void
-myterm_set_output(char *s)
+#define set_term_funcp(change_p, term_p) set_term_funcp2((change_p), 0)
+/* #define set_term_funcp3(change_p, term_p, tchange) \
+			set_term_funcp2((change_p), (tchange)) */
+
+/* This function should be called before any graphic code can be used... */
+void
+set_term_funcp2(FUNC_PTR change_p, TSET_FP tchange)
 {
-    croak("Change terminal not implemented yet with dynamic gnuplot");
+    SET_OUTFILE;
+    my_term_ftable.change_term_p = change_p;
+    my_term_ftable.loaded = 1;
+    if (tchange) {
+	my_term_ftable.term_set_outputp = tchange;
+    }
 }
 
-typedef void (*TSET_FP)(char *s);
-TSET_FP term_set_outputp = &myterm_set_output;
+/* Used from Math::Pari */
+void
+set_term_funcp3(FUNC_PTR change_p, void *term_p, TSET_FP tchange)
+{
+  set_term_funcp2(change_p, tchange);
+}
 
-/* This function should be called before any graphic code can be used... */
-set_term_funcp(FUNC_PTR change_p, struct termentry *term_p)
+void
+set_term_ftable(struct t_ftable *p)
 {
-    my_term_tbl = term_p;
-    change_term_p = change_p;
-    /* XXXX Need to set term_set_outputp as well */
+  SET_OUTFILE;
+  my_term_ftablep = p;
 }
 
-/* This function should be called before any graphic code can be used... */
-set_term_funcp3(FUNC_PTR change_p, struct termentry *term_p, TSET_FP tchange)
+#else /* !DYNAMIC_PLOTTING */
+
+extern struct termentry term_tbl[];
+
+#  define my_change_term	change_term
+#  define my_term_tbl		term_tbl
+
+extern void term_set_output(char *s);
+extern void term_start_plot(void);
+extern void term_end_plot(void);
+extern void term_start_multiplot(void);
+extern void term_end_multiplot(void);
+extern void term_init(void);
+extern void list_terms(void);
+
+static void
+plotsizes_scale(double x, double y)	{ xsize=x; ysize=y; }
+
+static double
+plotsizes_get(int flag)	{ return (flag ? ysize : xsize); }
+
+struct t_ftable my_term_ftable =
+{
+	1, (FUNC_PTR)&change_term, &term_set_output,
+	&plotsizes_scale, &plotsizes_get,
+	{&term_start_plot, &term_end_plot, 
+	 &term_start_multiplot, &term_end_multiplot, &term_init, &list_terms}
+};
+
+struct t_ftable *get_term_ftable()	{ SET_OUTFILE; return &my_term_ftable; }
+void set_term_ftable()	{ SET_OUTFILE; }
+
+
+void
+set_term_funcp3(FUNC_PTR change_p, void *term_p, TSET_FP tchange)
 {
-    my_term_tbl = term_p;
-    change_term_p = change_p;
+    SET_OUTFILE;
+    my_term_ftable.change_term_p = change_p;
+    my_term_ftable.loaded = 1;
     if (tchange) {
-	term_set_outputp = tchange;
+	my_term_ftable.term_set_outputp = tchange;
     }
-    /* XXXX Need to set term_set_outputp as well */
 }
 
-#else /* !DYNAMIC_PLOTTING */
+#define scaled_xmax()	((int)termprop(xmax)*xsize)
+#define scaled_ymax()	((int)termprop(ymax)*ysize)
 
-extern struct termentry term_tbl[];
+#endif /* !DYNAMIC_PLOTTING */
+
+#define int_get_term_ftable()	((IV)get_term_ftable())
+#define int_set_term_ftable(a) (v_set_term_ftable((void*)a))
 
-#  define my_change_term change_term
-#  define my_term_tbl term_tbl
+void
+v_set_term_ftable(void *a) { set_term_ftable((struct t_ftable*)a); }
 
-#endif /* DYNAMIC_PLOTTING */
+void
+setup_gpshim(void) { SET_OUTFILE; }
 
 #ifdef SET_OPTIONS_FROM_STRING
 /* This sets the tokens for the options */
@@ -339,6 +502,11 @@ set_tokens_string(char *start)
 	if (!*s)
 	    return;
 	tstart = s;
+	if (*s == ',') {
+	    s++;
+	    is_integer = is_real = 0;
+	    goto process;
+	}
 	is_integer = is_real = ((*s) != 0);
 	if (*s == '+' || *s == '-')
 	    s++;
@@ -350,19 +518,24 @@ set_tokens_string(char *start)
 			is_real = 0;
 		    else if (is_integer == 1 && !(s[1] <= '9' && s[1] >= '0'))
 			is_real = 0;
-		} else if (*s != 'e' || *s == 'E') {
+		} else if (*s == 'e' || *s == 'E') {
 		    if (has_exp)
 			is_real = 0;
 		    has_exp = 1;
 		    if (s[1] == '+' || s[1] == '-')
 			s++;
-		} else
+		} else if (*s == ',' && (is_integer || is_real))
+		    break;
+		else
 		    is_real = 0;
 		is_integer = 0;
 	    } else if (is_integer)
 		is_integer++;
 	    s++;	    
 	}
+      process:
+	token[num_tokens].start_index = tstart - input_line;
+	token[num_tokens].length = s - tstart;
 	if (is_integer) {
 	    token[num_tokens].is_token = 0;
 	    token[num_tokens].l_val.type = INTGR;
@@ -374,8 +547,6 @@ set_tokens_string(char *start)
 	    token[num_tokens].l_val.v.cmplx_val.imag = 0;
 	} else {
 	    token[num_tokens].is_token = 1;
-	    token[num_tokens].start_index = tstart - input_line;
-	    token[num_tokens].length = s - tstart;
 	}
 	num_tokens++;
     }
@@ -389,8 +560,12 @@ set_tokens_string(char *start)
 void
 set_options_from(char *s)
 {
+    char *o = input_line;
+
+    input_line = s;		/* for error reports */
     set_tokens_string(s);
     options();
+    input_line = o;
     c_token = num_tokens = 0;
 }
 #endif
diff -pru pari-2.0.15.beta.old/src/graph/plotgnuplot.c pari-2.0.15.beta/src/graph/plotgnuplot.c
--- pari-2.0.15.beta.old/src/graph/plotgnuplot.c	Mon Jun  7 02:27:33 1999
+++ pari-2.0.15.beta/src/graph/plotgnuplot.c	Mon Jun  7 01:55:16 1999
@@ -14,6 +14,7 @@
 #define croak(str) err(talker,str)
 #define SET_OPTIONS_FROM_STRING
 #define GNUPLOT_OUTLINE_STDOUT
+#define DONT_POLLUTE_INIT
 #include "Gnuplot.h"
 
 #ifdef __EMX__
@@ -34,7 +35,11 @@ rectdraw0(long *w, long *x, long *y, lon
 
   PARI_get_plot(0);
 
+#if 0
   graphics();				/* Switch on terminal. */
+#else
+  term_start_plot();			/* Switch on terminal. */
+#endif
   linetype(line_type);			/* X does not work otherwise. */
   setpointsize(pointsize);
   for(i=0;i<lw;i++)
@@ -100,7 +105,9 @@ rectdraw0(long *w, long *x, long *y, lon
 	  if (RoSTx(p1)+x0 < 0 || RoSTx(p1)+x0+RoSTl(p1)-1 >= w_width
 	      || RoSTy(p1) + y0 < 0 || RoSTy(p1) + y0 >= w_height) {
 	  } else {
-	    put_text(RoSTx(p1)+x0,  w_height - 1 - RoSTy(p1) - y0, RoSTs(p1));
+	    put_text(RoSTx(p1)+x0,
+		     w_height - 1 - RoSTy(p1) - y0 + (f_height - 1)/2,
+		     RoSTs(p1));
 	  }
 	  break;
 	case ROt_PTT:
@@ -118,7 +125,11 @@ rectdraw0(long *w, long *x, long *y, lon
       p1=RoNext(p1);
     }
   }
+#if 0
   text();				/* Reset terminal */
+#else
+  term_end_plot();			/* Reset terminal. */
+#endif
 }
 
 void
@@ -127,6 +138,7 @@ PARI_get_plot(long fatal)
   if (pari_plot.init) {
     return;
   }
+  setup_gpshim();
   term_set( DEF_TERM );
 }
 
@@ -134,12 +146,17 @@ PARI_get_plot(long fatal)
 long
 term_set(char *s)
 {
-  char *t;
+  char *t, *size = NULL;
+  double x, y;
 
   if (*s == 0)
       s = pari_plot.name;
   t = s;
-  while (*t && !(*t == ' ' || *t == '\t' || *s == '\t'))
+  if (t[1] == '\0' && t[0] == '?') {
+     list_terms();
+     return 1;
+  }
+  while (*t && !(*t == ' ' || *t == '\t' || *t == '\n' || *t == '='))
 	t++;
   if ((t-s) > PLOT_NAME_LEN)
       err(talker,"too long name \"%s\"for terminal", s);
@@ -149,17 +166,39 @@ term_set(char *s)
 	reset();
   strncpy(pari_plot.name,s,t-s);
   pari_plot.name[t-s] = '\0';
+
   if (!termset( pari_plot.name ))
       err(talker,"error setting terminal \"%s\"", pari_plot.name);
 
+  if (*t == '=') {
+    size = ++t;
+    x = atof(size);
+    while (*t && !(*t == ' ' || *t == '\t' || *t == '\n' || *t == ','))
+  	t++;
+    if (*t != ',')
+      err(talker, "Terminal size directive without ','");
+    y = atof(++t);
+    while (*t && !(*t == ' ' || *t == '\t' || *t == '\n'))
+  	t++;
+    plotsizes_scale(x*(1 + 1e-6)/termprop(xmax),
+		    y*(1 + 1e-6)/termprop(ymax)); /* Later - truncated! */
+  } else {
+    plotsizes_scale(1,1);
+  }
+
   /* *Needed*, say, by gif output: */
   set_options_from(t);
 
-  do_init();				/* Init terminal. */
+#if 0
+  gptable_init();			/* Init terminal. */
+#else
+  term_init();
+#endif
+
   setpointsize(pointsize);
 
-  w_width = termprop(xmax);
-  w_height = termprop(ymax);
+  w_width = scaled_xmax();
+  w_height = scaled_ymax();
   f_height = termprop(v_char);
   f_width = termprop(h_char);
   h_unit = termprop(h_tic);
@@ -173,6 +212,7 @@ long
 plot_outfile_set(char *s) { 
     int normal = (strcmp(s,"-") == 0);
 
+    setup_gpshim();
     /* Delegate all the hard work to term_set_output() */
 
     if (normal)