Annotation of OpenXM_contrib/pari-2.2/src/graph/plotgnuplot.c, Revision 1.2
1.2 ! noro 1: /* $Id: plotgnuplot.c,v 1.10 2002/06/29 09:31:16 karim Exp $
1.1 noro 2:
3: Copyright (C) 2000 The PARI group.
4:
5: This file is part of the PARI/GP package.
6:
7: PARI/GP is free software; you can redistribute it and/or modify it under the
8: terms of the GNU General Public License as published by the Free Software
9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
10: ANY WARRANTY WHATSOEVER.
11:
12: Check the License for details. You should have received a copy of it, along
13: with the package; see the file 'COPYING'. If not, write to the Free Software
14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
15:
16: /*******************************************************************/
17: /* */
18: /* HI-RES PLOT. GNUPLOT INTERFACE */
19: /* written by Ilya Zakharevich */
20: /* */
21: /*******************************************************************/
22: # include "pari.h"
23: #include "rect.h"
24: #define croak(str) err(talker,str)
25: #define SET_OPTIONS_FROM_STRING
26: #define GNUPLOT_OUTLINE_STDOUT
27: #define DONT_POLLUTE_INIT
1.2 ! noro 28:
! 29: /* The gnuplot library may reference a function with *this* name */
! 30: #define mys_mouse_feedback_rectangle set_mouse_feedback_rectangle
1.1 noro 31: #include "Gnuplot.h"
32:
33: #ifdef __EMX__
34: # define DEF_TERM "pm"
35: #else
36: # define DEF_TERM (getenv("DISPLAY") ? "X11" : "dumb")
37: #endif
38:
1.2 ! noro 39: #ifdef BOTH_GNUPLOT_AND_X11
! 40: # ifdef GNUPLOT_AND_X11_PREFER_GNUPLOT
! 41: # define DEFAULT_IS_BUILTIN 0
! 42: # else /* !( defined GNUPLOT_AND_X11_PREFER_GNUPLOT ) */
! 43: # define DEFAULT_IS_BUILTIN 1
! 44: # endif /* defined GNUPLOT_AND_X11_PREFER_GNUPLOT */
! 45: #endif
! 46:
! 47: # ifdef BOTH_GNUPLOT_AND_X11
! 48: int is_builtin = DEFAULT_IS_BUILTIN;
! 49: int X11_init;
! 50: static void my_rectdraw0(long *w, long *x, long *y, long lw, long do_free);
! 51: # endif
! 52:
1.1 noro 53: void
54: rectdraw0(long *w, long *x, long *y, long lw, long do_free)
1.2 ! noro 55: # ifdef BOTH_GNUPLOT_AND_X11
! 56: {
! 57: if (is_builtin) {
! 58: X11_rectdraw0(w, x, y, lw, do_free);
! 59: return;
! 60: }
! 61:
! 62: my_rectdraw0(w, x, y, lw, do_free);
! 63: return;
! 64: }
! 65:
! 66: static void
! 67: my_rectdraw0(long *w, long *x, long *y, long lw, long do_free)
! 68: # endif /* defined BOTH_GNUPLOT_AND_X11 */
1.1 noro 69: {
70: double *ptx,*pty;
71: long i,j,x0,y0, hjust, vjust, hgap, vgap, hgapsize, vgapsize;
72: long good, seen_graph = 0;
73: int point_type = -1, line_type = 0;
74: PariRect *e;
75: RectObj *p1;
76: int strdir = RoSTdirLEFT, can_justify = 1, shift = 0, xstart, xend;
77:
78: (void)do_free;
79: PARI_get_plot(0);
80:
81: hgapsize = h_unit; vgapsize = v_unit;
82: if (hgapsize == 1)
83: hgapsize = 2; /* Vertical direction is subjectively different! */
84: /* Find the info about the *actual* x and y-coords of the
85: rectangles. Use the first rectangle with has_graph attribute. */
86:
87: for(i=0;i<lw;i++) {
88: e=rectgraph[w[i]];
89: if (RHasGraph(e)) {
90: set_mouse_feedback_rectangle(
91: x[i], x[i] + RXsize(e) - 1,
92: w_height - 1 - y[i] - (RYsize(e) - 1), w_height - 1 - y[i],
93: (0 - RXshift(e))/RXscale(e),
94: (RXsize(e) - 1 - RXshift(e))/RXscale(e),
95: (RYsize(e) - 1 - RYshift(e))/RYscale(e),
96: (0 - RYshift(e))/RYscale(e)
97: );
98: seen_graph = 1;
99: break;
100: }
101: }
102: if (!seen_graph) /* Put some reasonable values */
103: set_mouse_feedback_rectangle( 0, w_width - 1, 0, w_height - 1,
104: 0, 0, 0, 0);
105:
106: #if 0
107: graphics(); /* Switch on terminal. */
108: #else
109: term_start_plot(); /* Switch on terminal. */
110: #endif
111: linetype(line_type); /* X does not work otherwise. */
112: setpointsize(pointsize);
113:
114: for(i=0;i<lw;i++)
115: {
116: e=rectgraph[w[i]]; p1=RHead(e); x0=x[i]; y0=y[i];
117: while(p1)
118: {
119: switch(RoType(p1))
120: {
121: case ROt_PT:
122: point(DTOL(RoPTx(p1)+x0), w_height - 1 - DTOL(RoPTy(p1) + y0),
123: point_type);
124: break;
125: case ROt_LN:
126: move(DTOL(RoLNx1(p1)+x0), w_height - 1 - DTOL(RoLNy1(p1) + y0));
127: vector(DTOL(RoLNx2(p1)+x0), w_height - 1 - DTOL(RoLNy2(p1) + y0));
128: break;
129: case ROt_BX:
130: move(DTOL(RoBXx1(p1)+x0), w_height - 1 - DTOL(RoBXy1(p1) + y0));
131: vector(DTOL(RoBXx2(p1)+x0), w_height - 1 - DTOL(RoBXy1(p1) + y0));
132: vector(DTOL(RoBXx2(p1)+x0), w_height - 1 - DTOL(RoBXy2(p1) + y0));
133: vector(DTOL(RoBXx1(p1)+x0), w_height - 1 - DTOL(RoBXy2(p1) + y0));
134: vector(DTOL(RoBXx1(p1)+x0), w_height - 1 - DTOL(RoBXy1(p1) + y0));
135: break;
136: case ROt_MP:
137: ptx=RoMPxs(p1);
138: pty=RoMPys(p1);
139: for(j=0;j<RoMPcnt(p1);j++)
140: {
141: point(DTOL(ptx[j] + x0), w_height - 1 - DTOL(pty[j] + y0),
142: point_type);
143: }
144: break;
145: case ROt_ML:
146: ptx=RoMLxs(p1);
147: pty=RoMLys(p1);
148: j = 0;
149: if (DTOL(ptx[j]+x0) < 0 || DTOL(ptx[j]+x0) >= w_width
150: || DTOL(pty[j] + y0) < 0 || DTOL(pty[j] + y0) >= w_height) {
151: good = 0;
152: } else {
153: move(DTOL(ptx[j]+x0), w_height - 1 - DTOL(pty[j] + y0));
154: good = 1;
155: }
156: for(j=1;j<RoMLcnt(p1);j++)
157: {
158: if (good) {
159: if (DTOL(ptx[j] + x0) < 0 || DTOL(ptx[j]+x0) >= w_width
160: || DTOL(pty[j] + y0) < 0 || DTOL(pty[j] + y0) >= w_height) {
161: good = 0;
162: } else {
163: vector(DTOL(ptx[j] + x0), w_height - 1 - DTOL(pty[j] + y0));
164: }
165: } else {
166: if (DTOL(ptx[j] + x0) < 0 || DTOL(ptx[j] + x0) >= w_width
167: || DTOL(pty[j] + y0) < 0 || DTOL(pty[j] + y0) >= w_height) {
168: } else {
169: move(DTOL(ptx[j]+x0), w_height - 1 - DTOL(pty[j] + y0));
170: good = 1;
171: }
172: }
173: }
174: break;
175: case ROt_ST:
176: hjust = RoSTdir(p1) & RoSTdirHPOS_mask;
177: vjust = RoSTdir(p1) & RoSTdirVPOS_mask;
178: hgap = RoSTdir(p1) & RoSTdirHGAP;
179: if (hgap)
180: hgap = (hjust == RoSTdirLEFT) ? hgapsize : -hgapsize;
181: vgap = RoSTdir(p1) & RoSTdirVGAP;
182: if (vgap)
183: vgap = (vjust == RoSTdirBOTTOM) ? vgapsize : -vgapsize;
184: if (vjust != RoSTdirVCENTER)
185: vgap += ((vjust == RoSTdirTOP) ? -1 : 1) * (f_height - 1)/2;
186: if (strdir != hjust) {
187: shift = (hjust == RoSTdirLEFT ? 0 :
188: (hjust == RoSTdirRIGHT ? 2 : 1));
189: can_justify = justify_text(shift); /* 1 for LEFT */
190: strdir = RoSTdir(p1);
191: }
192: xstart = DTOL(RoSTx(p1) + x0) + hgap
193: - (can_justify ? 0
194: : ((RoSTl(p1) * pari_plot.fwidth - 1) * shift / 2));
195: xend = xstart + (can_justify ? 0 : RoSTl(p1) * pari_plot.fwidth - 1);
196: if (xstart < 0 || xend >= w_width
197: || DTOL(RoSTy(p1) + y0) < 0
198: || DTOL(RoSTy(p1) + y0) >= w_height) {
199: } else {
200: put_text(xstart,
201: w_height - 1 - DTOL(RoSTy(p1) + y0) + vgap,
202: RoSTs(p1));
203: }
204: break;
205: case ROt_PTT:
206: point_type = RoPTTpen(p1);
207: break;
208: case ROt_PTS:
209: pointsize = RoPTSsize(p1);
210: setpointsize(pointsize);
211: break;
212: case ROt_LNT:
213: linetype(RoLNTpen(p1));
214: break;
215: default: break;
216: }
217: p1=RoNext(p1);
218: }
219: }
220: #if 0
221: text(); /* Reset terminal */
222: #else
223: term_end_plot(); /* Reset terminal. */
224: #endif
225: }
226:
227: void
228: PARI_get_plot(long fatal)
229: {
1.2 ! noro 230: #ifdef BOTH_GNUPLOT_AND_X11
! 231: if (is_builtin) {
! 232: if (X11_init)
! 233: return;
! 234: if (getenv("DISPLAY")) {
! 235: X11_PARI_get_plot(fatal);
! 236: X11_init = 1;
! 237: return;
! 238: }
! 239: is_builtin = 0; /* Don't defaut to X11 if no DISPLAY */
! 240: }
! 241: #endif /* defined BOTH_GNUPLOT_AND_X11 */
! 242: if (pari_plot.init)
1.1 noro 243: return;
244: term_set( DEF_TERM );
1.2 ! noro 245: (void)fatal;
1.1 noro 246: }
247:
248:
249: long
250: term_set(char *s)
251: {
252: char *t, *size = NULL;
253: double x, y;
254: static int had_error;
255:
1.2 ! noro 256: #ifdef BOTH_GNUPLOT_AND_X11
! 257: if (is_builtin) {
! 258: if (!strcmp(s,"builtin")) {
! 259: if (!getenv("DISPLAY"))
! 260: goto complain;
! 261: return X11_term_set(s);
! 262: }
! 263: is_builtin = 0;
! 264: /* The following line may switch on Gnuplot's X11 term first: */
! 265: /* PARI_get_plot(1); */
! 266: } else if (!strcmp(s,"builtin")) {
! 267: /* if (!X11_init) {*/
! 268: if (!getenv("DISPLAY")) {
! 269: complain:
! 270: croak("The builtin-X11 plotting requires DISPLAY environment variable set");
! 271: }
! 272: /* Restore the safe state by switching to a do-little terminal */
! 273: if (pari_plot.init && strcmp(pari_plot.name, "dumb"))
! 274: term_set("dumb");
! 275: is_builtin = 1;
! 276: X11_PARI_get_plot(1);
! 277: X11_init = 1;
! 278: /* }*/
! 279: return X11_term_set(s);
! 280: }
! 281: #endif /* defined BOTH_GNUPLOT_AND_X11 */
1.1 noro 282: setup_gpshim();
283: if (*s == 0)
284: s = pari_plot.name;
285: t = s;
286: if (t[1] == '\0' && t[0] == '?') {
287: list_terms();
288: return 1;
289: }
290: while (*t && !(*t == ' ' || *t == '\t' || *t == '\n' || *t == '='))
291: t++;
292: if ((t-s) > PLOT_NAME_LEN)
293: err(talker,"name \"%s\" for terminal too long", s);
294: if (*pari_plot.name && !had_error
295: && (strlen(pari_plot.name) != t - s /* As strcmp() without \0 at end */
296: || (strncmp(pari_plot.name, s, t-s) != 0)) )
297: reset();
298: strncpy(pari_plot.name,s,t-s);
299: pari_plot.name[t-s] = '\0';
300:
301: had_error = 1;
302: if (!termset( pari_plot.name ))
303: err(talker,"error setting terminal \"%s\"", pari_plot.name);
304: had_error = 0;
305:
306: if (*t == '=') {
307: size = ++t;
308: x = atof(size);
309: while (*t && !(*t == ' ' || *t == '\t' || *t == '\n' || *t == ','))
310: t++;
311: if (*t != ',')
312: err(talker, "Terminal size directive without ','");
313: y = atof(++t);
314: while (*t && !(*t == ' ' || *t == '\t' || *t == '\n'))
315: t++;
316: plotsizes_scale(x*(1 + 1e-6)/termprop(xmax),
317: y*(1 + 1e-6)/termprop(ymax)); /* Later - truncated! */
318: } else {
319: plotsizes_scale(1,1);
320: }
321:
322: /* *Needed*, say, by gif output: */
323: set_options_from(t);
324:
325: #if 0
326: gptable_init(); /* Init terminal. */
327: #else
328: term_init();
329: #endif
330:
331: setpointsize(pointsize);
332:
333: w_width = scaled_xmax();
334: w_height = scaled_ymax();
335: f_height = termprop(v_char);
336: f_width = termprop(h_char);
337: h_unit = termprop(h_tic);
338: v_unit = termprop(v_tic);
339: pari_plot.init = 1;
340:
341: return 1;
342: }
343:
344: long
1.2 ! noro 345: plot_outfile_set(char *s)
! 346: {
1.1 noro 347: int normal = (strcmp(s,"-") == 0);
348:
1.2 ! noro 349: /* Intentionally no check for is_builtin, let it always affect gnuplot:
! 350: this way one can set the outfile before switching the terminal... */
! 351:
1.1 noro 352: setup_gpshim();
353: /* Delegate all the hard work to term_set_output() */
354:
355: if (normal)
356: term_set_output(NULL);
357: else { /* term_set_output() needs
358: a malloced string */
359: char *s1 = (char*) malloc(strlen(s) + 1);
360:
361: strcpy(s1,s);
362: term_set_output(s1);
363: }
364: return 1;
365: }
366:
367: void
368: set_pointsize(double d)
369: {
1.2 ! noro 370: #ifdef BOTH_GNUPLOT_AND_X11
! 371: if (is_builtin) {
! 372: X11_set_pointsize(d);
! 373: return;
! 374: }
! 375: #endif /* defined BOTH_GNUPLOT_AND_X11 */
1.1 noro 376: pointsize = d;
377: if (pari_plot.init)
378: setpointsize(d);
379: }
380:
1.2 ! noro 381: #ifdef HAS_DLOPEN
1.1 noro 382: #include <dlfcn.h>
383:
384: get_term_ftable_t *
385: get_term_ftable_get(void) /* Establish runtime link with gnuplot engine */
386: {
1.2 ! noro 387: char *s = getenv("GNUPLOT_DRAW_DLL"), *s1, buf[4096];
1.1 noro 388: void *h, *f;
389: int mode = RTLD_LAZY;
1.2 ! noro 390: char fbuf[2048];
1.1 noro 391:
392: #ifdef RTLD_GLOBAL
393: mode |= RTLD_GLOBAL;
394: #endif
395:
1.2 ! noro 396: #ifdef DYNAMIC_PLOTTING_RUNTIME_LINK
1.1 noro 397: if (!s)
398: s = DYNAMIC_PLOTTING_RUNTIME_LINK;
1.2 ! noro 399: #endif
! 400: #ifndef DYNAMIC_PLOTTING_RUNTIME_LINK_NO_PERL
! 401: /* Allow user disabling by setting GNUPLOT_DRAW_DLL_NO_PERL=1 */
! 402: if (!s && (!(s1 = getenv("GNUPLOT_DRAW_DLL_NO_PERL")) || !atoi(s1))) {
! 403: char cmdbuf[256];
! 404: FILE *p;
! 405: char ext[256];
! 406: char *sub;
! 407: char name[256];
! 408: char *n = "Gnuplot";
! 409:
! 410: /* Make 2 runs of Perl to shorten the command length */
! 411: /* Find the directory of the Term::Gnuplot's PM and DLL extension */
! 412: sprintf(cmdbuf, "perl -MTerm::Gnuplot -MConfig -wle %c"
! 413: "print $INC{qq(Term/Gnuplot.pm)};print $Config{dlext}%c",
! 414: SHELL_Q, SHELL_Q);
! 415: p = popen(cmdbuf, "r");
! 416: if (!p || !fgets(fbuf, sizeof(fbuf), p) || !fgets(ext, sizeof(ext), p))
! 417: goto end_find;
! 418: pclose(p);
! 419: /* Find the directory of the DLL file */
! 420: sub = strrchr(fbuf,'/');
! 421: if (!sub)
! 422: goto end_find;
! 423: /* Do as XSLoader */
! 424: sub[0] = 0;
! 425: sub = strrchr(fbuf,'/');
! 426: if (!sub)
! 427: goto end_find;
! 428: if (sub - fbuf >= 9 && !strncmp(sub - 9, "/blib/lib",9)) {
! 429: strcpy(sub - 3,"arch/"); /* Uninstalled module */
! 430: sub++;
! 431: }
! 432: strcpy(sub + 1,"auto/Term/Gnuplot/");
! 433: /* Find the name of the DLL file */
! 434: sprintf(cmdbuf, "perl -MDynaLoader -we %c"
! 435: "package DynaLoader; "
! 436: "print mod2fname([qw(Term Gnuplot)]) if defined &mod2fname%c",
! 437: SHELL_Q, SHELL_Q);
! 438: p = popen(cmdbuf, "r");
! 439: if (p) {
! 440: if (fgets(name, sizeof(name), p))
! 441: n = name;
! 442: pclose(p);
! 443: }
! 444: if (strlen(fbuf) + 10 + strlen(n) + strlen(ext) > sizeof(fbuf))
! 445: croak("Buffer overflow finding gnuplot DLL");
! 446: strcpy(sub + strlen(sub), n);
! 447: strcpy(sub + strlen(sub), ".");
! 448: strcpy(sub + strlen(sub), ext);
! 449: sub[strlen(sub)-1] = 0; /* Trailing \n of ext */
! 450: s = fbuf;
! 451: }
! 452: end_find:
! 453: #endif
! 454: if (!s) /* The trailing \n is important: one may put . to the command */
! 455: croak("Can't find Gnuplot drawing engine DLL,\n\t"
! 456: "set GNUPLOT_DRAW_DLL environment variable"
! 457: " to the name of the DLL,\n\t"
! 458: "or install Perl module Term::Gnuplot, e.g., by running\n\t\t"
! 459: "perl -MCPAN -e \"install Term::Gnuplot\"\n");
1.1 noro 460: h = dlopen(s, mode);
461: if (!h) {
462: sprintf(buf,"Can't load Gnuplot drawing engine from '%s': %s", s, dlerror());
463: croak(buf);
464: return 0;
465: }
466: f = dlsym(h, "get_term_ftable");
467: if (f)
468: return (get_term_ftable_t *)f;
469: sprintf(buf, "Can't resolve 'get_term_ftable' function from Gnuplot drawing engine '%s': %s", s, dlerror());
470: croak(buf);
471: return 0;
472: }
1.2 ! noro 473: #else /* !( defined HAS_DLOPEN ) */
! 474:
! 475: get_term_ftable_t *
! 476: get_term_ftable_get(void) /* Establish runtime link with gnuplot engine */
! 477: {
! 478: croak("No dlopen() support present, required for dynamic gnuplot-DLL link");
! 479: return NULL;
! 480: }
! 481:
! 482: #endif /* defined HAS_DLOPEN */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>