Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /*******************************************************************/
16 : /* */
17 : /* HIGH RESOLUTION PLOT */
18 : /* */
19 : /*******************************************************************/
20 :
21 : #include "pari.h"
22 : #include "paripriv.h"
23 : #include "rect.h"
24 :
25 : #ifdef HPPA
26 : # ifndef __GNUC__
27 : typedef char *caddr_t;
28 : # endif
29 : #endif
30 :
31 : BEGINEXTERN
32 : #include <X11/XKBlib.h>
33 : #include <X11/Xutil.h>
34 : #include <X11/Xos.h>
35 : #ifndef XK_c
36 : # include <X11/keysym.h>
37 : #endif
38 : ENDEXTERN
39 :
40 : static Colormap PARI_Colormap;
41 :
42 : struct data_x
43 : {
44 : Display *display;
45 : Window win;
46 : int numcolors;
47 : GC gc;
48 : };
49 :
50 : /* after fork(), we don't want the child to recover but to exit */
51 : static void
52 0 : exiterr(const char *str)
53 : {
54 0 : term_color(c_ERR);
55 0 : err_printf("\n *** X fatal error: %s\n",str);
56 0 : term_color(c_NONE); _exit(1);
57 : }
58 :
59 : static long
60 0 : rgb_to_pixel(Display *display, int r, int g, int b)
61 : {
62 : XColor X;
63 0 : X.red = r*65535/255;
64 0 : X.green = g*65535/255;
65 0 : X.blue = b*65535/255;
66 0 : X.flags = DoRed | DoGreen | DoBlue;
67 0 : if (!XAllocColor(display,PARI_Colormap,&X)) exiterr("cannot allocate color");
68 0 : return X.pixel;
69 : }
70 : static long
71 0 : colormapindex_to_pixel(Display *display, long i)
72 : {
73 0 : GEN c = gel(GP_DATA->colormap, i+1);
74 0 : int r,g,b; color_to_rgb(c, &r,&g,&b);
75 0 : return rgb_to_pixel(display, r, g, b);
76 : }
77 : static long
78 0 : rgb_color(Display *display, long c)
79 : {
80 0 : int r,g,b; long_to_rgb(c, &r, &g, &b);
81 0 : return rgb_to_pixel(display, r, g, b);
82 : }
83 :
84 0 : static void SetForeground(void *data, long col)
85 : {
86 0 : struct data_x *dx = (struct data_x *) data;
87 0 : XSetForeground(dx->display,dx->gc, rgb_color(dx->display,col));
88 0 : }
89 :
90 0 : static void DrawPoint(void *data, long x, long y)
91 : {
92 0 : struct data_x *dx = (struct data_x *) data;
93 0 : XDrawPoint(dx->display,dx->win,dx->gc, x,y);
94 0 : }
95 :
96 0 : static void DrawLine(void *data, long x1, long y1, long x2, long y2)
97 : {
98 0 : struct data_x *dx = (struct data_x *) data;
99 0 : XDrawLine(dx->display,dx->win,dx->gc, x1,y1, x2,y2);
100 0 : }
101 :
102 0 : static void DrawArc(void *data, long x, long y, long w, long h)
103 : {
104 0 : struct data_x *dx = (struct data_x *) data;
105 0 : XDrawArc(dx->display,dx->win,dx->gc, x,y, w,h, 0, 64*360);
106 0 : }
107 :
108 0 : static void FillArc(void *data, long x, long y, long w, long h)
109 : {
110 0 : struct data_x *dx = (struct data_x *) data;
111 0 : XFillArc(dx->display,dx->win,dx->gc, x,y, w,h, 0, 64*360);
112 0 : }
113 :
114 0 : static void DrawRectangle(void *data, long x, long y, long w, long h)
115 : {
116 0 : struct data_x *dx = (struct data_x *) data;
117 0 : XDrawRectangle(dx->display,dx->win,dx->gc, x,y, w,h);
118 0 : }
119 :
120 0 : static void FillRectangle(void *data, long x, long y, long w, long h)
121 : {
122 0 : struct data_x *dx = (struct data_x *) data;
123 0 : XFillRectangle(dx->display,dx->win,dx->gc, x,y, w,h);
124 0 : }
125 :
126 0 : static void DrawPoints(void *data, long nb, struct plot_points *p)
127 : {
128 0 : struct data_x *dx = (struct data_x *) data;
129 0 : XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb);
130 : long i;
131 0 : for (i=0;i<nb;i++)
132 : {
133 0 : xp[i].x=p[i].x;
134 0 : xp[i].y=p[i].y;
135 : }
136 0 : XDrawPoints(dx->display,dx->win,dx->gc, xp, nb, 0);
137 0 : pari_free(xp);
138 0 : }
139 :
140 0 : static void DrawLines(void *data, long nb, struct plot_points *p)
141 : {
142 0 : struct data_x *dx = (struct data_x *) data;
143 0 : XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb);
144 : long i;
145 0 : for (i=0;i<nb;i++)
146 : {
147 0 : xp[i].x=p[i].x;
148 0 : xp[i].y=p[i].y;
149 : }
150 0 : XDrawLines(dx->display,dx->win,dx->gc, xp, nb, 0);
151 0 : pari_free(xp);
152 0 : }
153 :
154 0 : static void DrawString(void *data, long x, long y, char *text, long numtext)
155 : {
156 0 : struct data_x *dx = (struct data_x *) data;
157 0 : XDrawString(dx->display,dx->win,dx->gc, x,y, text, numtext);
158 0 : }
159 :
160 : #define MAX_BUF 256
161 :
162 : static int
163 0 : Xerror(Display *d, XErrorEvent *pari_err) {
164 : char buf[MAX_BUF];
165 0 : XGetErrorText(d,pari_err->error_code,buf,MAX_BUF);
166 0 : exiterr(buf); return 0;
167 : }
168 :
169 : static int
170 0 : IOerror(Display *d) {
171 : char buf[MAX_BUF];
172 0 : sprintf(buf, "lost display on %s", DisplayString(d));
173 0 : exiterr(buf); return 0;
174 : }
175 :
176 : static void
177 76 : draw(PARI_plot *T, GEN w, GEN x, GEN y)
178 : {
179 : long oldwidth,oldheight;
180 : struct plot_eng plotX;
181 : struct data_x dx;
182 76 : double xs = 1, ys = 1;
183 : int screen, keystate;
184 : Display *display;
185 : GC gc;
186 : Window win;
187 : XEvent event;
188 : XSizeHints size_hints;
189 : XFontStruct *font_info;
190 : XSetWindowAttributes attrib;
191 : Atom wm_delete_window, wm_protocols;
192 :
193 76 : if (pari_daemon()) return; /* parent process returns */
194 :
195 0 : display = XOpenDisplay(NULL);
196 0 : if (!display) exiterr("cannot open Display");
197 0 : font_info = XLoadQueryFont(display, "7x13");
198 0 : if (!font_info) exiterr("cannot open 7x13 font");
199 0 : XSetErrorHandler(Xerror);
200 0 : XSetIOErrorHandler(IOerror);
201 0 : PARI_Colormap = DefaultColormap(display, 0);
202 :
203 0 : screen = DefaultScreen(display);
204 0 : win = XCreateSimpleWindow
205 0 : (display, RootWindow(display, screen), 0, 0,
206 0 : T->width, T->height, 4,
207 0 : colormapindex_to_pixel(display, 1),
208 0 : colormapindex_to_pixel(display, 0));
209 :
210 0 : size_hints.flags = PPosition | PSize;
211 0 : size_hints.x = 0;
212 0 : size_hints.y = 0;
213 0 : size_hints.width = T->width;
214 0 : size_hints.height = T->height;
215 0 : XSetStandardProperties
216 : (display, win, "PARI plot", NULL, None, NULL, 0, &size_hints);
217 :
218 0 : wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
219 0 : wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
220 0 : XSetWMProtocols(display,win,&wm_delete_window, 1);
221 :
222 0 : XSelectInput (display, win,
223 : ExposureMask | ButtonPressMask | KeyReleaseMask | StructureNotifyMask);
224 :
225 : /* enable backing-store */
226 0 : attrib.backing_store = Always;
227 0 : attrib.backing_planes = AllPlanes;
228 0 : XChangeWindowAttributes(display,win,CWBackingStore|CWBackingPlanes,&attrib);
229 :
230 0 : gc = XCreateGC(display, win, 0, NULL);
231 0 : XSetFont(display, gc, font_info->fid);
232 :
233 0 : XClearWindow(display, win);
234 0 : XMapWindow(display, win);
235 0 : oldwidth = T->width;
236 0 : oldheight = T->height;
237 0 : dx.display= display;
238 0 : dx.win = win;
239 0 : dx.numcolors = lg(GP_DATA->colormap)-1;
240 0 : dx.gc = gc;
241 0 : plotX.sc = &SetForeground;
242 0 : plotX.pt = &DrawPoint;
243 0 : plotX.ln = &DrawLine;
244 0 : plotX.ac = &DrawArc;
245 0 : plotX.fa = &FillArc;
246 0 : plotX.bx = &DrawRectangle;
247 0 : plotX.fb = &FillRectangle;
248 0 : plotX.mp = &DrawPoints;
249 0 : plotX.ml = &DrawLines;
250 0 : plotX.st = &DrawString;
251 0 : plotX.pl = T;
252 0 : plotX.data = (void*)&dx;
253 :
254 0 : if (mt_is_thread())
255 0 : pari_thread_close();
256 : else
257 0 : pari_close();
258 : for(;;)
259 : {
260 0 : XNextEvent(display, &event);
261 0 : switch(event.type)
262 : {
263 0 : case ClientMessage:
264 0 : if (event.xclient.message_type != wm_protocols ||
265 0 : (Atom)event.xclient.data.l[0] != wm_delete_window) break;
266 : case ButtonPress:
267 : case DestroyNotify:
268 0 : EXIT:
269 0 : XUnloadFont(display,font_info->fid);
270 0 : XFreeGC(display,gc);
271 0 : XCloseDisplay(display); _exit(0);
272 :
273 0 : case KeyRelease:
274 : /* Mod4 == Super on "std" Linux */
275 0 : keystate = event.xkey.state & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask);
276 0 : switch (XkbKeycodeToKeysym(display, event.xkey.keycode, 0,0))
277 : {
278 0 : case XK_q:
279 0 : if (!keystate || keystate == ControlMask) goto EXIT;
280 0 : break;
281 0 : case XK_c:
282 0 : if (keystate == ControlMask) goto EXIT;
283 0 : break;
284 : }
285 0 : break;
286 :
287 0 : case ConfigureNotify:
288 : {
289 0 : int width = event.xconfigure.width;
290 0 : int height = event.xconfigure.height;
291 :
292 0 : if (width == oldwidth && height == oldheight) break;
293 0 : oldwidth = width;
294 0 : oldheight = height;
295 :
296 : /* recompute scale */
297 0 : xs = ((double)width)/T->width;
298 0 : ys = ((double)height)/T->height;
299 0 : XClearWindow(display, win);
300 : }
301 0 : case Expose:
302 0 : gen_draw(&plotX, w, x, y, xs, ys);
303 : }
304 : }
305 : }
306 :
307 : INLINE void
308 176 : gp_get_display_sizes(long *dwidth, long *dheight, long *fwidth, long *fheight)
309 : {
310 : Display *display;
311 :
312 176 : display = XOpenDisplay(NULL);
313 176 : if (display)
314 : {
315 0 : int screen = DefaultScreen(display);
316 0 : *dwidth = DisplayWidth(display, screen);
317 0 : *dheight = DisplayHeight(display, screen);
318 0 : XCloseDisplay(display);
319 : }
320 : else
321 : {
322 : /* Situation looks grim */
323 176 : *dwidth = 0;
324 176 : *dheight = 0;
325 : }
326 176 : *fwidth = 7;
327 176 : *fheight = 13;
328 176 : }
329 :
330 : void
331 176 : gp_get_plot(PARI_plot *T)
332 : {
333 176 : gp_get_plot_generic(T,gp_get_display_sizes);
334 176 : T->draw = &draw;
335 176 : }
|