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 DrawRectangle(void *data, long x, long y, long w, long h)
103 : {
104 0 : struct data_x *dx = (struct data_x *) data;
105 0 : XDrawRectangle(dx->display,dx->win,dx->gc, x,y, w,h);
106 0 : }
107 :
108 0 : static void FillRectangle(void *data, long x, long y, long w, long h)
109 : {
110 0 : struct data_x *dx = (struct data_x *) data;
111 0 : XFillRectangle(dx->display,dx->win,dx->gc, x,y, w,h);
112 0 : }
113 :
114 0 : static void DrawPoints(void *data, long nb, struct plot_points *p)
115 : {
116 0 : struct data_x *dx = (struct data_x *) data;
117 0 : XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb);
118 : long i;
119 0 : for (i=0;i<nb;i++)
120 : {
121 0 : xp[i].x=p[i].x;
122 0 : xp[i].y=p[i].y;
123 : }
124 0 : XDrawPoints(dx->display,dx->win,dx->gc, xp, nb, 0);
125 0 : pari_free(xp);
126 0 : }
127 :
128 0 : static void DrawLines(void *data, long nb, struct plot_points *p)
129 : {
130 0 : struct data_x *dx = (struct data_x *) data;
131 0 : XPoint *xp=(XPoint*)pari_malloc(sizeof(xp)*nb);
132 : long i;
133 0 : for (i=0;i<nb;i++)
134 : {
135 0 : xp[i].x=p[i].x;
136 0 : xp[i].y=p[i].y;
137 : }
138 0 : XDrawLines(dx->display,dx->win,dx->gc, xp, nb, 0);
139 0 : pari_free(xp);
140 0 : }
141 :
142 0 : static void DrawString(void *data, long x, long y, char *text, long numtext)
143 : {
144 0 : struct data_x *dx = (struct data_x *) data;
145 0 : XDrawString(dx->display,dx->win,dx->gc, x,y, text, numtext);
146 0 : }
147 :
148 : #define MAX_BUF 256
149 :
150 : static int
151 0 : Xerror(Display *d, XErrorEvent *pari_err) {
152 : char buf[MAX_BUF];
153 0 : XGetErrorText(d,pari_err->error_code,buf,MAX_BUF);
154 0 : exiterr(buf); return 0;
155 : }
156 :
157 : static int
158 0 : IOerror(Display *d) {
159 : char buf[MAX_BUF];
160 0 : sprintf(buf, "lost display on %s", DisplayString(d));
161 0 : exiterr(buf); return 0;
162 : }
163 :
164 : static void
165 76 : draw(PARI_plot *T, GEN w, GEN x, GEN y)
166 : {
167 : long oldwidth,oldheight;
168 : struct plot_eng plotX;
169 : struct data_x dx;
170 76 : double xs = 1, ys = 1;
171 : int screen, keystate;
172 : Display *display;
173 : GC gc;
174 : Window win;
175 : XEvent event;
176 : XSizeHints size_hints;
177 : XFontStruct *font_info;
178 : XSetWindowAttributes attrib;
179 : Atom wm_delete_window, wm_protocols;
180 :
181 76 : if (pari_daemon()) return; /* parent process returns */
182 :
183 0 : display = XOpenDisplay(NULL);
184 0 : if (!display) exiterr("cannot open Display");
185 0 : font_info = XLoadQueryFont(display, "7x13");
186 0 : if (!font_info) exiterr("cannot open 7x13 font");
187 0 : XSetErrorHandler(Xerror);
188 0 : XSetIOErrorHandler(IOerror);
189 0 : PARI_Colormap = DefaultColormap(display, 0);
190 :
191 0 : screen = DefaultScreen(display);
192 0 : win = XCreateSimpleWindow
193 0 : (display, RootWindow(display, screen), 0, 0,
194 0 : T->width, T->height, 4,
195 0 : colormapindex_to_pixel(display, 1),
196 0 : colormapindex_to_pixel(display, 0));
197 :
198 0 : size_hints.flags = PPosition | PSize;
199 0 : size_hints.x = 0;
200 0 : size_hints.y = 0;
201 0 : size_hints.width = T->width;
202 0 : size_hints.height = T->height;
203 0 : XSetStandardProperties
204 : (display, win, "PARI plot", NULL, None, NULL, 0, &size_hints);
205 :
206 0 : wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
207 0 : wm_protocols = XInternAtom(display, "WM_PROTOCOLS", False);
208 0 : XSetWMProtocols(display,win,&wm_delete_window, 1);
209 :
210 0 : XSelectInput (display, win,
211 : ExposureMask | ButtonPressMask | KeyReleaseMask | StructureNotifyMask);
212 :
213 : /* enable backing-store */
214 0 : attrib.backing_store = Always;
215 0 : attrib.backing_planes = AllPlanes;
216 0 : XChangeWindowAttributes(display,win,CWBackingStore|CWBackingPlanes,&attrib);
217 :
218 0 : gc = XCreateGC(display, win, 0, NULL);
219 0 : XSetFont(display, gc, font_info->fid);
220 :
221 0 : XClearWindow(display, win);
222 0 : XMapWindow(display, win);
223 0 : oldwidth = T->width;
224 0 : oldheight = T->height;
225 0 : dx.display= display;
226 0 : dx.win = win;
227 0 : dx.numcolors = lg(GP_DATA->colormap)-1;
228 0 : dx.gc = gc;
229 0 : plotX.sc = &SetForeground;
230 0 : plotX.pt = &DrawPoint;
231 0 : plotX.ln = &DrawLine;
232 0 : plotX.bx = &DrawRectangle;
233 0 : plotX.fb = &FillRectangle;
234 0 : plotX.mp = &DrawPoints;
235 0 : plotX.ml = &DrawLines;
236 0 : plotX.st = &DrawString;
237 0 : plotX.pl = T;
238 0 : plotX.data = (void*)&dx;
239 :
240 0 : if (mt_is_thread())
241 0 : pari_thread_close();
242 : else
243 0 : pari_close();
244 : for(;;)
245 : {
246 0 : XNextEvent(display, &event);
247 0 : switch(event.type)
248 : {
249 0 : case ClientMessage:
250 0 : if (event.xclient.message_type != wm_protocols ||
251 0 : (Atom)event.xclient.data.l[0] != wm_delete_window) break;
252 : case ButtonPress:
253 : case DestroyNotify:
254 0 : EXIT:
255 0 : XUnloadFont(display,font_info->fid);
256 0 : XFreeGC(display,gc);
257 0 : XCloseDisplay(display); _exit(0);
258 :
259 0 : case KeyRelease:
260 : /* Mod4 == Super on "std" Linux */
261 0 : keystate = event.xkey.state & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask);
262 0 : switch (XkbKeycodeToKeysym(display, event.xkey.keycode, 0,0))
263 : {
264 0 : case XK_q:
265 0 : if (!keystate || keystate == ControlMask) goto EXIT;
266 0 : break;
267 0 : case XK_c:
268 0 : if (keystate == ControlMask) goto EXIT;
269 0 : break;
270 : }
271 0 : break;
272 :
273 0 : case ConfigureNotify:
274 : {
275 0 : int width = event.xconfigure.width;
276 0 : int height = event.xconfigure.height;
277 :
278 0 : if (width == oldwidth && height == oldheight) break;
279 0 : oldwidth = width;
280 0 : oldheight = height;
281 :
282 : /* recompute scale */
283 0 : xs = ((double)width)/T->width;
284 0 : ys = ((double)height)/T->height;
285 0 : XClearWindow(display, win);
286 : }
287 0 : case Expose:
288 0 : gen_draw(&plotX, w, x, y, xs, ys);
289 : }
290 0 : }
291 : }
292 :
293 : INLINE void
294 176 : gp_get_display_sizes(long *dwidth, long *dheight, long *fwidth, long *fheight)
295 : {
296 : Display *display;
297 :
298 176 : display = XOpenDisplay(NULL);
299 176 : if (display)
300 : {
301 0 : int screen = DefaultScreen(display);
302 0 : *dwidth = DisplayWidth(display, screen);
303 0 : *dheight = DisplayHeight(display, screen);
304 0 : XCloseDisplay(display);
305 : }
306 : else
307 : {
308 : /* Situation looks grim */
309 176 : *dwidth = 0;
310 176 : *dheight = 0;
311 : }
312 176 : *fwidth = 7;
313 176 : *fheight = 13;
314 176 : }
315 :
316 : void
317 176 : gp_get_plot(PARI_plot *T)
318 : {
319 176 : gp_get_plot_generic(T,gp_get_display_sizes);
320 176 : T->draw = &draw;
321 176 : }
|