weening@Gang-of-Four.Stanford.EDU (Joe Weening) (09/21/89)
Here are a few fixes to the "xps" program (a Postscript previewer for X11) that was posted to comp.sources.unix and is also available on expo.lcs.mit.edu for anonymous ftp in the "contrib" directory. I'm not completely sure these fixes are the best ones, so please followup to this message if you see a better way. Here is an explanation of the problems that are fixed. 1. In stroke.c, the function LineSegment() could call atan2(0.0,0.0), which is meaningless and causes an error on some systems. I have it check for this case and return 0.0 instead of calling atan2. 2. In X11.c, the program seems to expect that black = 1 and white = 0 on the display. There is a comment by the author that "it's OK on Suns" but this isn't a help for those of us who have the colors reversed. (Note that the comment gets them backwards but the meaning is clear.) I think I've fixed this below, but perhaps not in the most elegant way. What causes the problem is that the program uses some boolean operations (such as AND and OR), whose effect depends on whether black and white are 0 and 1 or vice versa. E.g., if the background is white and black is 1, then an OR of a black pixel and the background will be black, while if black is 0, the result of the OR will be white. As far as I can see, a program that wants to use boolean functions must decide which ones to use based on the numerical values of the black and white pixels. This seems ugly to me. Does X11 have a less machine-dependent way of doing this? 3. The program doesn't have a real event loop; it calls XNextEvent just once to get the initial expose event. This doesn't work when using twm because of the window manager's reparenting of the window, so I stuck in a sleep(1) to wait for this. (An ugly kludge; is there a better way?) Here are the diffs: diff -c2 stroke.c.old stroke.c *** stroke.c.old Sat Oct 22 16:35:31 1988 --- stroke.c Wed Sep 20 13:32:46 1989 *************** *** 316,321 **** float LineSegment (p, new, ehere, enow, width, last_angle, last_type) Path p, new; Point ehere, enow; float width, last_angle; enum pelem_type last_type; { ! float angle = atan2 (enow.y - ehere.y, enow.x - ehere.x), ! length = sqrt ((enow.y - ehere.y) * (enow.y - ehere.y) + (enow.x - ehere.x) * (enow.x - ehere.x)); Matrix old; --- 316,323 ---- float LineSegment (p, new, ehere, enow, width, last_angle, last_type) Path p, new; Point ehere, enow; float width, last_angle; enum pelem_type last_type; { ! float dy = enow.y - ehere.y, ! dx = enow.x - ehere.x, ! angle = (dx == 0.0 && dy == 0.0) ? 0.0 : atan2 (dy, dx), ! length = sqrt (dy * dy + dx * dx); Matrix old; diff -c2 X11.c.old X11.c *** X11.c.old Tue Jul 4 01:00:08 1989 --- X11.c Wed Sep 20 13:39:24 1989 *************** *** 122,125 **** --- 122,132 ---- XGCValues values; int i; + /* The program expects black = 1, white = 0. This is the array of + boolean functions to use if they are reversed. */ + static char inv_rop[16] = { + ROP_TRUE, ROP_OR, ROP_ORNOT, ROP_SOURCE, + ROP_NOTOR, ROP_DEST, ROP_NXOR, ROP_AND, + ROP_NAND, ROP_XOR, ROP_NOTDEST, ROP_ANDNOT, + ROP_NOTSOURCE, ROP_NOTAND, ROP_NOR, ROP_FALSE }; if ((dpy = XOpenDisplay(dpy)) == NULL) Punt("Could not open display"); *************** *** 127,136 **** /* This defines our screen as being 11 inches high, no matter what its */ /* real size. What a hack. */ ! values.foreground = AllPlanes; for (i=0 ; i<16 ; i++) { ! values.function = i; fillgc[i] = XCreateGC(dpy, RootWindow(dpy, SCREEN), ! GCFunction | GCForeground, &values); } } /* --- 134,146 ---- /* This defines our screen as being 11 inches high, no matter what its */ /* real size. What a hack. */ ! values.foreground = BlackPixel(dpy, SCREEN); ! values.background = WhitePixel(dpy, SCREEN); for (i=0 ; i<16 ; i++) { ! values.function = (values.background == 0) ? i : inv_rop[i]; fillgc[i] = XCreateGC(dpy, RootWindow(dpy, SCREEN), ! GCFunction | GCForeground | GCBackground, ! &values); } + return NULL; } /* *************** *** 218,221 **** --- 228,234 ---- XSelectInput(dpy, hard->w, ExposureMask); XMapWindow(dpy, hard->w); + /* Give the window manager time to reparent and reexpose our window. */ + XFlush(dpy); + sleep(1); XNextEvent(dpy, &event); XSelectInput(dpy, hard->w, 0); *************** *** 606,610 **** void HardUpdate () { ! XFlush(dpy, 0); } /* --- 619,623 ---- void HardUpdate () { ! XFlush(dpy); } /* Joe Weening Computer Science Dept. weening@Gang-of-Four.Stanford.EDU Stanford University