#include <stdio.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

Display *dpy;
int screen;
Window root;
Visual *visual;
int depth;
int fg, bg;

/*
    This program crashes my Xfbdev server.

    scottg@mantatest.com
*/
main ()
{
  Window win;
  int width = 640, height = 480;
  XSetWindowAttributes xswa;
  XEvent report;
  int done = 0;
  GC basegc;			/* this one is created at startup */
  GC gc;			/* this one is created and destroyed each repaint */
  XGCValues gcvalues;
  Pixmap db;
  int i, j;

  if ((dpy = XOpenDisplay (NULL)) == NULL)
    {
      fprintf (stderr, "XOpenDisplay error: can't cannect to %s\n",
	       XDisplayName (NULL));
      exit (-1);
    }

  screen = DefaultScreen (dpy);
  root = DefaultRootWindow (dpy);
  visual = DefaultVisual (dpy, screen);
  depth = DefaultDepth (dpy, screen);
  fg = BlackPixel (dpy, screen);
  bg = WhitePixel (dpy, screen);

  db = XCreatePixmap (dpy, root, width, height, depth);

  gcvalues.foreground = fg;
  gcvalues.background = bg;
  /* create the base GC, from which we'll clone a new GC each paint (like libgcj) */
  basegc = XCreateGC (dpy, RootWindow (dpy, screen),
		      (GCForeground | GCBackground), &gcvalues);
  xswa.background_pixel = bg;
  xswa.event_mask =
    ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
    KeyPressMask;
  xswa.background_pixel = bg;
  xswa.border_pixel = fg;

  win = XCreateWindow (dpy, root,
		       0, 0, width, height, 0,
		       depth,
		       InputOutput,
		       visual,
		       CWEventMask | CWBorderPixel | CWBackPixel, &xswa);

  XMapWindow (dpy, win);

  while (!done)
    {
      XNextEvent (dpy, &report);
      switch (report.type)
	{
	case Expose:
	  break;
	case ButtonPress:

	  switch (report.xbutton.button)
	    {
	    case Button1:
	      /* do an infinite double-buffered animation */
	      for (j = 0; 1; j++)
		{
		  /* create temporary gc and copy the base gc to it 
		     like libgcj xlib peers do
		   */
		  gc = XCreateGC (dpy, RootWindow (dpy, screen), 0, 0);
		  XCopyGC (dpy, basegc, ~0, gc);
		  /* draw into the temporary gc like libgcj xlib peers do */
		  XSetForeground (dpy, gc, bg);
		  XFillRectangle (dpy, db, gc, 0, 0, width, height);
		  XSetForeground (dpy, gc, fg);

		  for (i = 0; i < 40; i += 4)
		    {
		      int x = (report.xbutton.x + j) % width;
		      int y = (report.xbutton.y + j) % height;
		      int sz = 5 * (i + 1);
		      XDrawArc (dpy, db, gc, x, y, sz, sz, 0, 23040);
		    }

		  XCopyArea (dpy, db, win, gc, 0, 0, width, height, 0, 0);
		  XFlush (dpy);
		  /* free the temporary gc like libgcj xlib peers do */
		  XFreeGC (dpy, gc);
		}

	      break;
	    }
	  break;
	case KeyPress:
	  done = 1;
	  break;
	case ConfigureNotify:
	  break;
	}
    }

  XFreeGC (dpy, basegc);
  XCloseDisplay (dpy);
}
