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