ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/x11.c
Revision: 2.17
Committed: Mon Sep 12 15:57:55 1994 UTC (29 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.16: +79 -28 lines
Log Message:
added "x11d" driver for using stdin & stdout instead of command line

File Contents

# Content
1 /* Copyright (c) 1992 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * x11.c - driver for X-windows version 11
9 *
10 * Jan 1990
11 */
12
13 #include <stdio.h>
14 #include <math.h>
15 #include <sys/ioctl.h>
16
17 #include <X11/Xlib.h>
18 #include <X11/cursorfont.h>
19 #include <X11/Xutil.h>
20
21 #include "color.h"
22 #include "driver.h"
23 #include "x11twind.h"
24 #include "x11icon.h"
25
26 #define GAMMA 2.2 /* default exponent correction */
27
28 #define MINWIDTH (32*COMCW) /* minimum graphics window width */
29 #define MINHEIGHT (MINWIDTH/2) /* minimum graphics window height */
30
31 #define BORWIDTH 5 /* border width */
32 #define COMHEIGHT (COMLH*COMCH) /* command line height (pixels) */
33
34 #define COMFN "8x13" /* command line font name */
35 #define COMLH 3 /* number of command lines */
36 #define COMCW 8 /* approx. character width (pixels) */
37 #define COMCH 14 /* approx. character height (pixels) */
38
39 #define ourscreen DefaultScreen(ourdisplay)
40 #define ourroot RootWindow(ourdisplay,ourscreen)
41
42 #define levptr(etype) ((etype *)&currentevent)
43
44 static XEvent currentevent; /* current event */
45
46 static int ncolors = 0; /* color table size */
47 static int mapped = 0; /* window is mapped? */
48 static unsigned long *pixval = NULL; /* allocated pixels */
49 static unsigned long ourblack=0, ourwhite=1;
50
51 static Display *ourdisplay = NULL; /* our display */
52
53 static XVisualInfo ourvinfo; /* our visual information */
54
55 static Window gwind = 0; /* our graphics window */
56
57 static Cursor pickcursor = 0; /* cursor used for picking */
58
59 static int gwidth, gheight; /* graphics window size */
60
61 static int comheight; /* desired comline height */
62 static TEXTWIND *comline = NULL; /* our command line */
63
64 static char c_queue[64]; /* input queue */
65 static int c_first = 0; /* first character in queue */
66 static int c_last = 0; /* last character in queue */
67
68 static GC ourgc = 0; /* our graphics context for drawing */
69
70 static Colormap ourmap = 0; /* our color map */
71
72 extern char *malloc(), *getcombuf();
73
74 static int x11_close(), x11_clear(), x11_paintr(), x11_errout(),
75 x11_getcur(), x11_comout(), x11_comin(), x11_flush();
76
77 static int std_comin(), std_comout();
78
79 static struct driver x11_driver = {
80 x11_close, x11_clear, x11_paintr, x11_getcur,
81 NULL, NULL, x11_flush, 1.0
82 };
83
84 static int getpixels(), xnewcolr(), freepixels(), resizewindow(),
85 getevent(), getkey(), fixwindow(), x11_getc();
86 static unsigned long true_pixel();
87
88
89 struct driver *
90 x11_init(name, id) /* initialize driver */
91 char *name, *id;
92 {
93 extern char *getenv();
94 char *gv;
95 int nplanes;
96 XSetWindowAttributes ourwinattr;
97 XWMHints ourxwmhints;
98 XSizeHints oursizhints;
99 /* open display server */
100 ourdisplay = XOpenDisplay(NULL);
101 if (ourdisplay == NULL) {
102 stderr_v("cannot open X-windows; DISPLAY variable set?\n");
103 return(NULL);
104 }
105 /* find a usable visual */
106 nplanes = DisplayPlanes(ourdisplay, ourscreen);
107 if (XMatchVisualInfo(ourdisplay,ourscreen,
108 24,TrueColor,&ourvinfo) ||
109 XMatchVisualInfo(ourdisplay,ourscreen,
110 24,DirectColor,&ourvinfo)) {
111 ourblack = 0;
112 ourwhite = ourvinfo.red_mask |
113 ourvinfo.green_mask |
114 ourvinfo.blue_mask ;
115 } else {
116 if (nplanes < 4) {
117 stderr_v("not enough colors\n");
118 return(NULL);
119 }
120 if (!XMatchVisualInfo(ourdisplay,ourscreen,
121 nplanes,PseudoColor,&ourvinfo) &&
122 !XMatchVisualInfo(ourdisplay,ourscreen,
123 nplanes,GrayScale,&ourvinfo)) {
124 stderr_v("unsupported visual type\n");
125 return(NULL);
126 }
127 ourblack = BlackPixel(ourdisplay,ourscreen);
128 ourwhite = WhitePixel(ourdisplay,ourscreen);
129 }
130 /* set gamma */
131 if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL
132 || (gv = getenv("GAMMA")) != NULL)
133 make_gmap(atof(gv));
134 else
135 make_gmap(GAMMA);
136 /* X11 command line or no? */
137 if (!strcmp(name, "x11"))
138 comheight = COMHEIGHT;
139 else /* "x11d" */
140 comheight = 0;
141 /* open window */
142 ourwinattr.background_pixel = ourblack;
143 ourwinattr.border_pixel = ourblack;
144 /* this is stupid */
145 ourwinattr.colormap = XCreateColormap(ourdisplay, ourroot,
146 ourvinfo.visual, AllocNone);
147 gwind = XCreateWindow(ourdisplay, ourroot, 0, 0,
148 DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH,
149 DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH,
150 BORWIDTH, ourvinfo.depth, InputOutput, ourvinfo.visual,
151 CWBackPixel|CWBorderPixel|CWColormap, &ourwinattr);
152 if (gwind == 0) {
153 stderr_v("cannot create window\n");
154 return(NULL);
155 }
156 XStoreName(ourdisplay, gwind, id);
157 /* create a cursor */
158 pickcursor = XCreateFontCursor(ourdisplay, XC_diamond_cross);
159 ourgc = XCreateGC(ourdisplay, gwind, 0, NULL);
160 ourxwmhints.flags = InputHint|IconPixmapHint;
161 ourxwmhints.input = True;
162 ourxwmhints.icon_pixmap = XCreateBitmapFromData(ourdisplay,
163 gwind, x11icon_bits, x11icon_width, x11icon_height);
164 XSetWMHints(ourdisplay, gwind, &ourxwmhints);
165 oursizhints.min_width = MINWIDTH;
166 oursizhints.min_height = MINHEIGHT+comheight;
167 oursizhints.flags = PMinSize;
168 XSetNormalHints(ourdisplay, gwind, &oursizhints);
169 XSelectInput(ourdisplay, gwind, ExposureMask);
170 XMapWindow(ourdisplay, gwind);
171 XWindowEvent(ourdisplay, gwind, ExposureMask, levptr(XEvent));
172 gwidth = levptr(XExposeEvent)->width;
173 gheight = levptr(XExposeEvent)->height - comheight;
174 x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth;
175 x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight;
176 x11_driver.inpready = 0;
177 mapped = 1;
178 /* set i/o vectors */
179 if (comheight) {
180 x11_driver.comin = x11_comin;
181 x11_driver.comout = x11_comout;
182 cmdvec = x11_comout;
183 if (wrnvec != NULL)
184 wrnvec = x11_errout;
185 } else {
186 x11_driver.comin = std_comin;
187 x11_driver.comout = std_comout;
188 cmdvec = std_comout;
189 }
190 return(&x11_driver);
191 }
192
193
194 static
195 x11_close() /* close our display */
196 {
197 cmdvec = NULL; /* reset error vectors */
198 if (wrnvec != NULL)
199 wrnvec = stderr_v;
200 if (ourdisplay == NULL)
201 return;
202 if (comline != NULL) {
203 xt_close(comline);
204 comline = NULL;
205 }
206 freepixels();
207 XFreeGC(ourdisplay, ourgc);
208 XDestroyWindow(ourdisplay, gwind);
209 gwind = 0;
210 ourgc = 0;
211 XFreeCursor(ourdisplay, pickcursor);
212 XCloseDisplay(ourdisplay);
213 ourdisplay = NULL;
214 }
215
216
217 static
218 x11_clear(xres, yres) /* clear our display */
219 int xres, yres;
220 {
221 /* check limits */
222 if (xres < MINWIDTH)
223 xres = MINWIDTH;
224 if (yres < MINHEIGHT)
225 yres = MINHEIGHT;
226 /* resize window */
227 if (xres != gwidth || yres != gheight) {
228 XSelectInput(ourdisplay, gwind, 0);
229 XResizeWindow(ourdisplay, gwind, xres, yres+comheight);
230 gwidth = xres;
231 gheight = yres;
232 XFlush(ourdisplay);
233 sleep(2); /* wait for window manager */
234 XSync(ourdisplay, 1); /* discard input */
235 }
236 XClearWindow(ourdisplay, gwind);
237 /* reinitialize color table */
238 if (ourvinfo.class == PseudoColor || ourvinfo.class == GrayScale)
239 if (getpixels() == 0)
240 stderr_v("cannot allocate colors\n");
241 else
242 new_ctab(ncolors);
243 /* get new command line */
244 if (comline != NULL)
245 xt_close(comline);
246 if (comheight) {
247 comline = xt_open(ourdisplay, gwind, 0, gheight, gwidth,
248 comheight, 0, ourblack, ourwhite, COMFN);
249 if (comline == NULL) {
250 stderr_v("Cannot open command line window\n");
251 quit(1);
252 }
253 XSelectInput(ourdisplay, comline->w, ExposureMask);
254 /* remove earmuffs */
255 XSelectInput(ourdisplay, gwind,
256 StructureNotifyMask|ExposureMask|KeyPressMask|ButtonPressMask);
257 } else /* remove earmuffs */
258 XSelectInput(ourdisplay, gwind,
259 StructureNotifyMask|ExposureMask|ButtonPressMask);
260 }
261
262
263 static
264 x11_paintr(col, xmin, ymin, xmax, ymax) /* fill a rectangle */
265 COLOR col;
266 int xmin, ymin, xmax, ymax;
267 {
268 unsigned long pixel;
269
270 if (!mapped)
271 return;
272 if (ncolors > 0)
273 pixel = pixval[get_pixel(col, xnewcolr)];
274 else
275 pixel = true_pixel(col);
276 XSetForeground(ourdisplay, ourgc, pixel);
277 XFillRectangle(ourdisplay, gwind,
278 ourgc, xmin, gheight-ymax, xmax-xmin, ymax-ymin);
279 }
280
281
282 static
283 x11_flush() /* flush output */
284 {
285 int n;
286 /* check for input */
287 XNoOp(ourdisplay);
288 n = XPending(ourdisplay); /* from X server */
289 while (n-- > 0)
290 getevent();
291 if (x11_driver.comin == std_comin) { /* from stdin */
292 if (ioctl(fileno(stdin), FIONREAD, &n) < 0) {
293 stderr_v("ioctl error on stdin\n");
294 quit(1);
295 }
296 x11_driver.inpready += n;
297 }
298 }
299
300
301 static
302 x11_comin(inp, prompt) /* read in a command line */
303 char *inp, *prompt;
304 {
305 if (prompt != NULL) {
306 x11_flush(); /* make sure we get everything */
307 if (fromcombuf(inp, &x11_driver))
308 return;
309 xt_puts(prompt, comline);
310 }
311 xt_cursor(comline, TBLKCURS);
312 editline(inp, x11_getc, x11_comout);
313 xt_cursor(comline, TNOCURS);
314 }
315
316
317 static
318 x11_comout(outp) /* output a string to command line */
319 char *outp;
320 {
321 if (comline == NULL)
322 return;
323 xt_puts(outp, comline);
324 if (outp[strlen(outp)-1] == '\n')
325 XFlush(ourdisplay);
326 }
327
328
329 static
330 x11_errout(msg) /* output an error message */
331 char *msg;
332 {
333 stderr_v(msg); /* send to stderr also! */
334 x11_comout(msg);
335 }
336
337
338 static
339 std_comin(inp, prompt) /* read in command line from stdin */
340 char *inp, *prompt;
341 {
342 extern char *gets();
343
344 if (prompt != NULL) {
345 if (fromcombuf(inp, &x11_driver))
346 return;
347 if (!x11_driver.inpready)
348 fputs(prompt, stdout);
349 }
350 if (gets(inp) == NULL) {
351 strcpy(inp, "quit");
352 return;
353 }
354 x11_driver.inpready -= strlen(inp) + 1;
355 if (x11_driver.inpready < 0)
356 x11_driver.inpready = 0;
357 }
358
359
360 static
361 std_comout(outp) /* write out string to stdout */
362 char *outp;
363 {
364 fputs(outp, stdout);
365 }
366
367
368 static int
369 x11_getcur(xp, yp) /* get cursor position */
370 int *xp, *yp;
371 {
372 while (XGrabPointer(ourdisplay, gwind, True, ButtonPressMask,
373 GrabModeAsync, GrabModeAsync, None, pickcursor,
374 CurrentTime) != GrabSuccess)
375 sleep(2);
376
377 do
378 getevent();
379 while (c_last <= c_first && levptr(XEvent)->type != ButtonPress);
380 *xp = levptr(XButtonPressedEvent)->x;
381 *yp = gheight-1 - levptr(XButtonPressedEvent)->y;
382 XUngrabPointer(ourdisplay, CurrentTime);
383 XFlush(ourdisplay); /* insure release */
384 if (c_last > c_first) /* key pressed */
385 return(x11_getc());
386 /* button pressed */
387 if (levptr(XButtonPressedEvent)->button == Button1)
388 return(MB1);
389 if (levptr(XButtonPressedEvent)->button == Button2)
390 return(MB2);
391 if (levptr(XButtonPressedEvent)->button == Button3)
392 return(MB3);
393 return(ABORT);
394 }
395
396
397 static
398 xnewcolr(ndx, r, g, b) /* enter a color into hardware table */
399 int ndx;
400 int r, g, b;
401 {
402 XColor xcolor;
403
404 xcolor.pixel = pixval[ndx];
405 xcolor.red = r << 8;
406 xcolor.green = g << 8;
407 xcolor.blue = b << 8;
408 xcolor.flags = DoRed|DoGreen|DoBlue;
409
410 XStoreColor(ourdisplay, ourmap, &xcolor);
411 }
412
413
414 static int
415 getpixels() /* get the color map */
416 {
417 XColor thiscolor;
418 register int i, j;
419
420 if (ncolors > 0)
421 return(ncolors);
422 if (ourvinfo.visual == DefaultVisual(ourdisplay,ourscreen)) {
423 ourmap = DefaultColormap(ourdisplay,ourscreen);
424 goto loop;
425 }
426 newmap:
427 ourmap = XCreateColormap(ourdisplay,gwind,ourvinfo.visual,AllocNone);
428 loop:
429 for (ncolors = ourvinfo.colormap_size;
430 ncolors > ourvinfo.colormap_size/3;
431 ncolors = ncolors*.937) {
432 pixval = (unsigned long *)malloc(ncolors*sizeof(unsigned long));
433 if (pixval == NULL)
434 return(ncolors = 0);
435 if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors))
436 break;
437 free((char *)pixval);
438 pixval = NULL;
439 }
440 if (pixval == NULL) {
441 if (ourmap == DefaultColormap(ourdisplay,ourscreen))
442 goto newmap; /* try it with our map */
443 else
444 return(ncolors = 0); /* failed */
445 }
446 if (ourmap != DefaultColormap(ourdisplay,ourscreen))
447 for (i = 0; i < ncolors; i++) { /* reset black and white */
448 if (pixval[i] != ourblack && pixval[i] != ourwhite)
449 continue;
450 thiscolor.pixel = pixval[i];
451 thiscolor.flags = DoRed|DoGreen|DoBlue;
452 XQueryColor(ourdisplay,
453 DefaultColormap(ourdisplay,ourscreen),
454 &thiscolor);
455 XStoreColor(ourdisplay, ourmap, &thiscolor);
456 for (j = i; j+1 < ncolors; j++)
457 pixval[j] = pixval[j+1];
458 ncolors--;
459 i--;
460 }
461 XSetWindowColormap(ourdisplay, gwind, ourmap);
462 return(ncolors);
463 }
464
465
466 static
467 freepixels() /* free our pixels */
468 {
469 if (ncolors == 0)
470 return;
471 XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L);
472 free((char *)pixval);
473 pixval = NULL;
474 ncolors = 0;
475 if (ourmap != DefaultColormap(ourdisplay,ourscreen))
476 XFreeColormap(ourdisplay, ourmap);
477 ourmap = 0;
478 }
479
480
481 static unsigned long
482 true_pixel(col) /* return true pixel value for color */
483 COLOR col;
484 {
485 unsigned long rval;
486 BYTE rgb[3];
487
488 map_color(rgb, col);
489 rval = ourvinfo.red_mask*rgb[RED]/255 & ourvinfo.red_mask;
490 rval |= ourvinfo.green_mask*rgb[GRN]/255 & ourvinfo.green_mask;
491 rval |= ourvinfo.blue_mask*rgb[BLU]/255 & ourvinfo.blue_mask;
492 return(rval);
493 }
494
495
496 static int
497 x11_getc() /* get a command character */
498 {
499 while (c_last <= c_first) {
500 c_first = c_last = 0; /* reset */
501 getevent(); /* wait for key */
502 }
503 x11_driver.inpready--;
504 return(c_queue[c_first++]);
505 }
506
507
508 static
509 getevent() /* get next event */
510 {
511 XNextEvent(ourdisplay, levptr(XEvent));
512 switch (levptr(XEvent)->type) {
513 case ConfigureNotify:
514 resizewindow(levptr(XConfigureEvent));
515 break;
516 case UnmapNotify:
517 mapped = 0;
518 freepixels();
519 break;
520 case MapNotify:
521 if (ourvinfo.class == PseudoColor ||
522 ourvinfo.class == GrayScale)
523 if (getpixels() == 0)
524 stderr_v("Cannot allocate colors\n");
525 else
526 new_ctab(ncolors);
527 mapped = 1;
528 break;
529 case Expose:
530 fixwindow(levptr(XExposeEvent));
531 break;
532 case KeyPress:
533 getkey(levptr(XKeyPressedEvent));
534 break;
535 case ButtonPress:
536 break;
537 }
538 }
539
540
541 static
542 getkey(ekey) /* get input key */
543 register XKeyPressedEvent *ekey;
544 {
545 register int n;
546
547 n = XLookupString(ekey, c_queue+c_last, sizeof(c_queue)-c_last,
548 NULL, NULL);
549 c_last += n;
550 x11_driver.inpready += n;
551 }
552
553
554 static
555 fixwindow(eexp) /* repair damage to window */
556 register XExposeEvent *eexp;
557 {
558 if (eexp->window == gwind) {
559 sprintf(getcombuf(&x11_driver), "repaint %d %d %d %d\n",
560 eexp->x, gheight - eexp->y - eexp->height,
561 eexp->x + eexp->width, gheight - eexp->y);
562 } else if (eexp->window == comline->w) {
563 if (eexp->count == 0)
564 xt_redraw(comline);
565 }
566 }
567
568
569 static
570 resizewindow(ersz) /* resize window */
571 register XConfigureEvent *ersz;
572 {
573 if (ersz->width == gwidth && ersz->height-comheight == gheight)
574 return;
575
576 gwidth = ersz->width;
577 gheight = ersz->height-comheight;
578 x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth;
579 x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight;
580
581 strcpy(getcombuf(&x11_driver), "new\n");
582 }