[comp.sources.bugs] Fixes to xps

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