#include <stdio.h>
#include <stdlib.h>
#include "giflib.h"

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

void draw_picture(Display *display, Window win, GC gc, XImage *image);
int  pick_visual(Display *display, XVisualInfo *visual_info);
void do_x_stuff (imageinfo *iinfo);
void initialize(int CTlength, color *CT);

extern int  ImageX, ImageY; 
extern char *ImageData;
extern unsigned long ImageP;


void draw_picture(Display *display, Window win, GC gc, XImage *image) {
  XPutImage(display, win, gc, image, 0, 0, 0, 0, ImageX, ImageY);
}

int pick_visual(Display *display, XVisualInfo *visual_info) {
  /*
   * return value of 0 indicates failure to allocate a color visual.
   * return value of 1 indicates success in allocation of a color visual.
   */

  /*
   * Much of this code borrowed from O'Reilly Xlib book (vol. 1) p.195
   */

  int defaultdepth;
  int i = 5;

  static char *visual_class[] = {
    "StaticGray",
    "GrayScale",
    "StaticColor",
    "PseudoColor",
    "TrueColor",
    "DirectColor"
  };

  defaultdepth = DefaultDepth(display, 0);

  while (!XMatchVisualInfo(display, 0, defaultdepth,
			   /* visual class */ i--, visual_info))
    ;

  printf("Found a %s class visual at default depth(%i).\n",
	 visual_class[++i], defaultdepth);

  if (i < StaticColor) { /* color visual classes are 2 to 5 */
    return(0);
  }
  return(1);
}

#define CMAPS 1
#define Boolean int
Colormap cmap[CMAPS], dmap;
int *staticmap[CMAPS];
int lowcolor, hicolor; 
Boolean staticvis, colorvis;
int screenint, screendepth;
Visual *visual;
Display *myDisplay;
Window  toplevelWin;

void do_x_stuff (imageinfo *iinfo) {
  int       myScreen;
  /*  Display   *myDisplay; */
  Window    win;
  XEvent    report;
  GC        gc;
  XGCValues values;
  XVisualInfo          visual_info;
  XSetWindowAttributes trashxattr;
  int exiteventloop, xtmp, ytmp;
  XImage    *myimage;
  char      *tmpdisp;
  int       CTlength;
  color     *CT;

  CTlength = iinfo->ct_length;
  CT       = iinfo->colortable;

  ImageX = iinfo->width;
  ImageY = iinfo->height;

  if (ImageData == 0) {
    printf("Oh no! Not enough memory!\n");
  }

  if (!(tmpdisp = getenv("DISPLAY"))) {
    myDisplay = XOpenDisplay(":0.0");
  } else {
    myDisplay = XOpenDisplay(tmpdisp);
  }
    
  myScreen  = DefaultScreen(myDisplay);

  if (!pick_visual(myDisplay, &visual_info)) {
    fprintf(stderr, "Cannot allocate a color visual. Aborting.\n");
    exit(-1);
  }

  if (visual_info.class < 5) {
    fprintf(stderr, "Cannot allocate a DirectColor class visual. Aborting.\n");
    exit(-1);
  }

  win = XCreateWindow(myDisplay, RootWindow(myDisplay, 0), 10, 40,
 		      ImageX, ImageY, 2, CopyFromParent, InputOutput,
 		      CopyFromParent, 0, &trashxattr);
  toplevelWin = win;
  initialize(CTlength, CT);

  XMapWindow(myDisplay, win);

  XSetWindowColormap(myDisplay, win, cmap[0]);

  XSelectInput(myDisplay, win, ExposureMask | KeyPressMask | ButtonPressMask |
	       StructureNotifyMask);
  gc = XCreateGC(myDisplay, win, 0, &values);
  XSetForeground(myDisplay, gc, BlackPixel(myDisplay, 0));
  XSetBackground(myDisplay, gc, WhitePixel(myDisplay, 0));

  /*
   * myimage = XCreateImage(myDisplay, visual, screendepth, FORMAT, 0,
   *		 ImageData, ImageX, ImageY, 8, 0);
   */

  myimage = XCreateImage(myDisplay, visual, screendepth, ZPixmap,
			 0, NULL, ImageX, ImageY, 32, 0);

  myimage->data = (char *) malloc(ImageY * myimage->bytes_per_line);
  if (myimage->data == NULL) {
    printf("Cannot malloc memory for XImage. Aborting.\n");
    exit(-1);
  }

  for(xtmp = 0; xtmp <= ImageX; xtmp++) {
    for(ytmp = 0; ytmp <= ImageY; ytmp++) {
      XPutPixel(myimage, xtmp, ytmp,
		(lowcolor + ImageData[xtmp + ytmp*ImageX]));
    }
  }

  exiteventloop = 0;
  while (!exiteventloop) {
    XNextEvent(myDisplay, &report);
    printf("Yo.\n");
    switch (report.type) {
    case Expose:
      if (report.xexpose.count != 0) {
	break;
      }
      draw_picture(myDisplay, win, gc, myimage);
      break;
    case ConfigureNotify:
      /* might want to do something. */
      break;
    case ButtonPress:
    case KeyPress:
      XCloseDisplay(myDisplay);
      exiteventloop = 1;
    default:
      break;
    }
  }
}
