| Ilya Zakharevich on Wed, 7 Mar 2001 19:18:39 -0500 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
| [PATCH] gnuplot plotting |
This patch:
a) removes warnings for a compile with -DDYNAMIC_PLOTTING;
b) adds support for two new types of DYNAMIC_PLOTTING which may be
usable in the "plain" GP (the old type was easy to use from a capable
runtime only, such as Perl in Math::Pari);
c) You could have get "stuck" if you mistyped the name of the terminal
in plotterm(): after this plotterm() would like to reset() the "previous"
terminal which is not in working order ==> plotterm() would fail;
When I teach Perl building the DLLs needed for the new types in (b),
I will support these variants of the build in Configure. Right now,
given a Gnuplot-engine DLL which exports get_term_ftable() entry point,
one can either
1) define DYNAMIC_PLOTTING_STATIC_LINK, and link with -lname-of-dll,
2) or define DYNAMIC_PLOTTING_RUNTIME_LINK=\"name-of-dll\", and
gp will transparently link at runtime when plotting is requested.
Note that (2) does not require any additional software present when
gp is compiled (except dlopen()); thus it may safely replace "none"
type of graphic.
Ilya
--- ./src/graph/Gnuplot.h-pre Fri Nov 3 16:00:24 2000
+++ ./src/graph/Gnuplot.h Tue Mar 6 22:47:02 2001
@@ -161,10 +161,9 @@ char term_options[200] = "";
#define AXIS_ARRAY_SIZE 10
#define DATATYPE_ARRAY_SIZE 10
-extern double min_array[], max_array[], base_array[], log_base_array[];
+extern double base_array[], log_base_array[];
extern TBOOLEAN log_array[];
/* graphics.c */
-extern int xleft, xright, ybot, ytop;
extern TBOOLEAN is_3d_plot;
double min_array[AXIS_ARRAY_SIZE], max_array[AXIS_ARRAY_SIZE], base_array[AXIS_ARRAY_SIZE], log_base_array[AXIS_ARRAY_SIZE];
@@ -362,6 +361,10 @@ 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);
+typedef void (*SET_MOUSE_FEEDBACK_RECTAGLE_t)(int term_xmin, int term_xmax,
+ int term_ymin, int term_ymax,
+ double plot_xmin, double plot_xmax,
+ double plot_ymin, double plot_ymax);
struct t_ftable {
int loaded;
@@ -370,13 +373,16 @@ struct t_ftable {
SET_SIZES_t set_sizesp;
GET_SIZES_t get_sizesp;
TST_END_FP term_funcs[TTABLE_COUNT];
+ SET_MOUSE_FEEDBACK_RECTAGLE_t mouse_feedback_func;
};
#ifdef DYNAMIC_PLOTTING /* Can load plotting DLL later */
+int
UNKNOWN_null()
{
croak("gnuplot-like plotting environment not loaded yet");
+ return 0;
}
static void myterm_table_not_loaded_v(void);
@@ -384,7 +390,10 @@ 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);
-
+static void myterm_table_not_loaded_v4i4d(int term_xmin, int term_xmax,
+ int term_ymin, int term_ymax,
+ double plot_xmin, double plot_xmax,
+ double plot_ymin, double plot_ymax);
#if 0
static int ftable_warned;
static void
@@ -403,7 +412,8 @@ static struct t_ftable my_term_ftable =
&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}
+ &myterm_table_not_loaded_v, &myterm_table_not_loaded_v},
+ myterm_table_not_loaded_v4i4d
};
static struct t_ftable *my_term_ftablep = &my_term_ftable;
@@ -434,6 +444,7 @@ static double
myterm_table_not_loaded_di(int flag)
{
myterm_table_not_loaded_v();
+ return 0; /* NOT REACHED */
}
static int
@@ -443,6 +454,14 @@ myterm_table_not_loaded_u()
return 0;
}
+void myterm_table_not_loaded_v4i4d(int term_xmin, int term_xmax,
+ int term_ymin, int term_ymax,
+ double plot_xmin, double plot_xmax,
+ double plot_ymin, double plot_ymax)
+{
+ myterm_table_not_loaded_v();
+}
+
# 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])
@@ -453,6 +472,7 @@ myterm_table_not_loaded_u()
# 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 set_mouse_feedback_rectangle (*my_term_ftablep->mouse_feedback_func)
# define scaled_xmax() ((int)termprop(xmax)*plotsizes_scale_get(0))
# define scaled_ymax() ((int)termprop(ymax)*plotsizes_scale_get(1))
@@ -468,6 +488,7 @@ my_change_term(char*s,int l)
return term = (struct termentry *)(*my_term_ftablep->change_term_p)(s,l);
}
+#if 0
static struct termentry dummy_term_tbl[] = {
{"unknown", "Unknown terminal type - not a plotting device",
100, 100, 1, 1,
@@ -477,6 +498,7 @@ 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},
};
+#endif
#define set_term_funcp(change_p, term_p) set_term_funcp2((change_p), 0)
/* #define set_term_funcp3(change_p, term_p, tchange) \
@@ -508,9 +530,27 @@ set_term_ftable(struct t_ftable *p)
my_term_ftablep = p;
}
+extern struct t_ftable *get_term_ftable();
+
#else /* !DYNAMIC_PLOTTING */
extern struct termentry term_tbl[];
+extern double min_array[], max_array[];
+extern int xleft, xright, ybot, ytop;
+
+void
+mys_mouse_feedback_rectangle(int term_xmin, int term_xmax,
+ int term_ymin, int term_ymax,
+ double plot_xmin, double plot_xmax,
+ double plot_ymin, double plot_ymax)
+{
+ xleft = term_xmin, xright = term_xmax;
+ ybot = term_ymin, ytop = term_ymax;
+ min_array[FIRST_X_AXIS] = min_array[SECOND_X_AXIS] = plot_xmin;
+ max_array[FIRST_X_AXIS] = max_array[SECOND_X_AXIS] = plot_xmax;
+ min_array[FIRST_Y_AXIS] = min_array[SECOND_Y_AXIS] = plot_ymin;
+ max_array[FIRST_Y_AXIS] = max_array[SECOND_Y_AXIS] = plot_ymax;
+}
# define my_change_term change_term
# define my_term_tbl term_tbl
@@ -534,13 +574,13 @@ 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}
+ &term_start_multiplot, &term_end_multiplot, &term_init, &list_terms},
+ &mys_mouse_feedback_rectangle
};
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)
{
@@ -564,8 +604,35 @@ set_term_funcp3(FUNC_PTR change_p, void
void
v_set_term_ftable(void *a) { set_term_ftable((struct t_ftable*)a); }
+typedef void (*set_term_ftable_t)(struct t_ftable *p);
+typedef struct t_ftable *(get_term_ftable_t)(void);
+
+extern get_term_ftable_t *get_term_ftable_get(void);
+
+static int shim_set;
+
void
-setup_gpshim(void) { SET_OUTFILE; }
+setup_gpshim(void) {
+#if 0
+ if (shim_set++)
+ return;
+#endif
+
+ if (!shim_set++) {
+#ifdef DYNAMIC_PLOTTING_RUNTIME_LINK
+ get_term_ftable_t *f = get_term_ftable_get(); /* Resolve the getter */
+
+ if (f)
+ v_set_term_ftable(f()); /* Get the external table */
+#endif
+
+#ifdef DYNAMIC_PLOTTING_STATIC_LINK
+ void *a = get_term_ftable(); /* Get the external one */
+ v_set_term_ftable(get_term_ftable());
+#endif
+ }
+ SET_OUTFILE;
+}
#ifdef SET_OPTIONS_FROM_STRING
/* This sets the tokens for the options */
@@ -653,10 +720,10 @@ set_options_from(char *s)
#ifdef GNUPLOT_OUTLINE_STDOUT
int
-StartOutput() {}
+StartOutput() { return 0; }
int
-EndOutput() {}
+EndOutput() { return 0; }
int
OutLine(char *s)
--- ./src/graph/plotgnuplot.c-pre Fri Nov 3 16:00:24 2000
+++ ./src/graph/plotgnuplot.c Tue Mar 6 22:59:08 2001
@@ -56,31 +56,22 @@ rectdraw0(long *w, long *x, long *y, lon
for(i=0;i<lw;i++) {
e=rectgraph[w[i]];
if (RHasGraph(e)) {
- double t;
-
- xleft = x[i]; xright = xleft + RXsize(e) - 1;
- ytop = w_height - 1 - y[i]; ybot = ytop - (RYsize(e) - 1);
- t = (0 - RXshift(e))/RXscale(e);
- min_array[FIRST_X_AXIS] = min_array[SECOND_X_AXIS] = t;
- t = (RXsize(e) - 1 - RXshift(e))/RXscale(e);
- max_array[FIRST_X_AXIS] = max_array[SECOND_X_AXIS] = t;
- t = (RYsize(e) - 1 - RYshift(e))/RYscale(e);
- min_array[FIRST_Y_AXIS] = min_array[SECOND_Y_AXIS] = t;
- t = (0 - RYshift(e))/RYscale(e);
- max_array[FIRST_Y_AXIS] = max_array[SECOND_Y_AXIS] = t;
+ set_mouse_feedback_rectangle(
+ x[i], x[i] + RXsize(e) - 1,
+ w_height - 1 - y[i] - (RYsize(e) - 1), w_height - 1 - y[i],
+ (0 - RXshift(e))/RXscale(e),
+ (RXsize(e) - 1 - RXshift(e))/RXscale(e),
+ (RYsize(e) - 1 - RYshift(e))/RYscale(e),
+ (0 - RYshift(e))/RYscale(e)
+ );
seen_graph = 1;
break;
}
}
- if (!seen_graph) { /* Put some reasonable values */
- xleft = 0; xright = w_width - 1;
- ybot = 0; ytop = w_height - 1;
- min_array[FIRST_X_AXIS] = min_array[SECOND_X_AXIS] = 0;
- max_array[FIRST_X_AXIS] = max_array[SECOND_X_AXIS] = 0;
- min_array[FIRST_Y_AXIS] = min_array[SECOND_Y_AXIS] = 0;
- max_array[FIRST_Y_AXIS] = max_array[SECOND_Y_AXIS] = 0;
- }
-
+ if (!seen_graph) /* Put some reasonable values */
+ set_mouse_feedback_rectangle( 0, w_width - 1, 0, w_height - 1,
+ 0, 0, 0, 0);
+
#if 0
graphics(); /* Switch on terminal. */
#else
@@ -209,7 +200,6 @@ PARI_get_plot(long fatal)
if (pari_plot.init) {
return;
}
- setup_gpshim();
term_set( DEF_TERM );
}
@@ -219,6 +209,7 @@ term_set(char *s)
{
char *t, *size = NULL;
double x, y;
+ static int had_error;
setup_gpshim();
if (*s == 0)
@@ -231,16 +222,18 @@ term_set(char *s)
while (*t && !(*t == ' ' || *t == '\t' || *t == '\n' || *t == '='))
t++;
if ((t-s) > PLOT_NAME_LEN)
- err(talker,"too long name \"%s\"for terminal", s);
- if (*pari_plot.name
- && (strlen(pari_plot.name) != t - s /* Why this? */
+ err(talker,"name \"%s\" for terminal too long", s);
+ if (*pari_plot.name && !had_error
+ && (strlen(pari_plot.name) != t - s /* As strcmp() without \0 at end */
|| (strncmp(pari_plot.name, s, t-s) != 0)) )
reset();
strncpy(pari_plot.name,s,t-s);
pari_plot.name[t-s] = '\0';
+ had_error = 1;
if (!termset( pari_plot.name ))
err(talker,"error setting terminal \"%s\"", pari_plot.name);
+ had_error = 0;
if (*t == '=') {
size = ++t;
@@ -306,3 +299,34 @@ set_pointsize(double d)
if (pari_plot.init)
setpointsize(d);
}
+
+#ifdef DYNAMIC_PLOTTING_RUNTIME_LINK
+#include <dlfcn.h>
+
+get_term_ftable_t *
+get_term_ftable_get(void) /* Establish runtime link with gnuplot engine */
+{
+ char *s = getenv("GNUPLOT_DRAW_DLL"), buf[4096];
+ void *h, *f;
+ int mode = RTLD_LAZY;
+
+#ifdef RTLD_GLOBAL
+ mode |= RTLD_GLOBAL;
+#endif
+
+ if (!s)
+ s = DYNAMIC_PLOTTING_RUNTIME_LINK;
+ h = dlopen(s, mode);
+ if (!h) {
+ sprintf(buf,"Can't load Gnuplot drawing engine from '%s': %s", s, dlerror());
+ croak(buf);
+ return 0;
+ }
+ f = dlsym(h, "get_term_ftable");
+ if (f)
+ return (get_term_ftable_t *)f;
+ sprintf(buf, "Can't resolve 'get_term_ftable' function from Gnuplot drawing engine '%s': %s", s, dlerror());
+ croak(buf);
+ return 0;
+}
+#endif