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

#define BITMAPDEPTH     1
#define TOO_SMALL       0
#define BIG_ENOUGH      1

#define icon_bitmap_width 40
#define icon_bitmap_height 40
static char icon_bitmap_bits[] = {
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3,
   0xff, 0xff, 0xff, 0xff, 0xcb, 0xff, 0xff, 0xff, 0xff, 0xb9, 0xff, 0xff,
   0xff, 0xff, 0x3d, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xfe, 0xff, 0xff, 0xff,
   0x9d, 0xfc, 0xff, 0xff, 0xff, 0xdd, 0x7d, 0xff, 0xff, 0xff, 0xcd, 0x93,
   0xff, 0xff, 0xff, 0xeb, 0xcf, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff,
   0xff, 0xe7, 0xff, 0xff, 0xff, 0xe3, 0xef, 0xff, 0xff, 0xff, 0xcb, 0xcf,
   0xff, 0xff, 0x1f, 0xda, 0xcf, 0xff, 0xff, 0xdf, 0xb8, 0xff, 0xff, 0xff,
   0xff, 0x3d, 0xef, 0xff, 0xff, 0xff, 0x7b, 0xee, 0xff, 0xff, 0xff, 0xf3,
   0xe0, 0xff, 0xff, 0xff, 0xf7, 0xf3, 0xff, 0x9f, 0xff, 0xe7, 0xff, 0xff,
   0x5f, 0xfe, 0xcf, 0xff, 0xff, 0xcf, 0xfd, 0x9f, 0xff, 0xff, 0xef, 0xf9,
   0xbf, 0xff, 0xff, 0xef, 0xf1, 0xff, 0xff, 0xff, 0xef, 0xe4, 0xff, 0xff,
   0xff, 0xef, 0xee, 0xf7, 0xff, 0xff, 0x6f, 0x9e, 0xf9, 0xff, 0xff, 0x5f,
   0x7f, 0xfc, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff,
   0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff,
   0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

 typedef unsigned char byte;
 int	xerrors;
 /*---------------------------------------------------------------------*/
int xerr(display, err)	/* our own non-fatal X window error routine */
 /* essentially copied from manual */
 Display *display;
 XErrorEvent     *err;
 {
 char    msg[80];
 XGetErrorText( display, err->error_code, msg, 80);
 printf("X window error: %s\n", msg);
 xerrors += 1;
 }
 /*-------------------------------------------------------------------------*/

void main()

{
 Display *dpy;
 int     screen;
 Window  win;
 unsigned        int     width, height;
 int     x,y;
 unsigned        int     border_width = 0;
 unsigned        int     display_width, display_height;
 unsigned        int     icon_width, icon_height, valuemask=0, class;
 char    *window_name = "test window";
 char    *icon_name = "ana";
 XTextProperty window, icon;
 Pixmap  icon_pixmap;
 XSizeHints      size_hints;
 XIconSize       *size_list;
 XWMHints        wm_hints;
 XClassHint      class_hints;
 unsigned	int     count;
 XEvent  report;
 GC      gc;
 XGCValues gc_val;

 XImage  *xi;
 Colormap        colormap;
 int     default_depth, depth, default_planes;
 XVisualInfo     visual_info, vinfo;
 XVisualInfo     vTemplate;
 XVisualInfo     *visualList;
 Visual		*vis;
 XSetWindowAttributes    attributes;
 int     vs, *depths;
 char    *display_name = NULL;
 int     window_size = 0;
 byte    xim[512*512];
 unsigned short	xim16[1024*1024];
 int	xim24[512*512], xim32[512*512];
 int     i;
 short	lookup16truecolor[256];
 XColor  colorcell;

                                                /* start execution here */
if ((dpy = XOpenDisplay(display_name)) == NULL) {
        printf("can't connect\n");  exit(-1); }
//XSetErrorHandler(xerr);
screen = DefaultScreen(dpy);
display_width = DisplayWidth(dpy, screen);
display_height = DisplayHeight(dpy, screen);
printf("display_width, display_height = %d %d\n",display_width, display_height);
printf("screen = %d\n", screen);
depths = XListDepths(dpy, screen, &count);
printf("# of available depths = %d\n", count);
for (i=0;i<count;i++) { printf("depth: %d\n", depths[i]); }
default_depth = DefaultDepth(dpy, screen);
default_planes = DisplayPlanes(dpy, screen);
printf(" default depth, planes = %d %d\n", default_depth,default_planes);

XFree(depths);

vTemplate.screen = screen;
printf("choose a depth\n");
scanf("%d", &vTemplate.depth);

visualList = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask,
        &vTemplate, &count);
depth = vTemplate.depth;
printf("visual count = %d\n",count);
if (count <= 0) { printf("no match for that depth\n");  exit(0); }
for (i=0;i<count;i++) {
printf("match # %d, ID = %#x\n",i, visualList[i].visualid);
printf("screen, class,depth,colormap_size, bits_per_rgb %d %d %d %d %d\n",
 visualList[i].screen, visualList[i].class,
 visualList[i].depth,visualList[i].colormap_size, visualList[i].bits_per_rgb);
}
printf("choose one\n");
scanf("%d", &vs);
printf("visual id = %d\n", visualList[vs].visualid);
printf("visual address = %d\n", visualList[vs].visual);
vis = visualList[vs].visual;
vinfo = visualList[vs];
/* about this visual */
printf("visual parameters\nID:\t%d\nscreen:\t%d\ndepth:\t%d\nclass:\t%d\n",
	vinfo.visualid, vinfo.screen,vinfo.depth, vinfo.class);
printf("red mask:\t%#x\ngreen mask:\t%#x\nblue mask:\t%#x\ncolormap size:\t%d\nbits:\t%d\n",
	vinfo.red_mask, vinfo.green_mask, vinfo.blue_mask, vinfo.colormap_size,
	vinfo.bits_per_rgb);
colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
	vinfo.visual, AllocNone);

/* fiddle with colormap */
if (vinfo.depth == 16 || vinfo.depth == 15) {
 for (i=0; i<256; i++) {
 colorcell.red = (unsigned short) (0);
 colorcell.blue = (unsigned short) (i*256);
 colorcell.green = (unsigned short) (0);
 if (XAllocColor(dpy,colormap, &colorcell) == 0)
 	{ printf("XAllocColor failed at i = %d\n", i);  exit(0); }
 lookup16truecolor[i] = colorcell.pixel;
 //printf("pixel(%d) = %d\n", i, colorcell.pixel);
 }
 }

//XInstallColormap(dpy, colormap);

valuemask = CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity;
attributes.colormap = colormap;
attributes.background_pixel = 0;
attributes.border_pixel = 0;
attributes.bit_gravity = NorthWestGravity;
attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask|
	ExposureMask;

printf("valuemask = 0x%x\n",valuemask);
printf("depth = %d\n", depth);
x = y = 0;	width = 512;	height = 512;
win = XCreateWindow(dpy, RootWindow(dpy,screen),x,y,
        width,height,border_width, depth, InputOutput,
	vis, valuemask, &attributes);
printf("window created\n");

XSetWindowColormap(dpy, win, colormap);

/* look at window parameters */

XFlush(dpy);
printf("flushed\n");
XFree(visualList);


icon_pixmap = XCreateBitmapFromData(dpy, win, icon_bitmap_bits,
        icon_bitmap_width, icon_bitmap_height);
size_hints.flags = PPosition | PSize | PMinSize;
size_hints.min_width = 300;
size_hints.min_height = 300;

wm_hints.initial_state = NormalState;
wm_hints.input = True;
wm_hints.icon_pixmap = icon_pixmap;
wm_hints.flags = StateHint | IconPixmapHint | InputHint;


XStringListToTextProperty ( &icon_name, 1, &icon);
XStringListToTextProperty ( &window_name, 1, &window);

XSetWMProperties(dpy, win, &window, &icon, NULL ,NULL ,NULL ,&wm_hints ,NULL);

XFlush(dpy);
printf("flushed\n");

XSelectInput( dpy, win, ExposureMask | KeyPressMask | ButtonPressMask |
        StructureNotifyMask );

gc_val.foreground = (int) (pow(2,depth)-1);
gc_val.background = 0;
gc = XCreateGC(dpy, win, GCForeground|GCBackground, &gc_val);

XMapWindow(dpy, win);
printf("window mapped\n");
XFlush(dpy);
printf("flushed\n");

while (1) {             /*wait for an expose event before drawing */
XNextEvent( dpy, &report);
printf("got an event\n");
if ( report.type == Expose ) {
        printf("got an expose, the count is %d\n", report.xexpose.count);
        if ( report.xexpose.count == 0 ) break;  }
}

printf("escaped from event loop\n");


printf("start image\n");
if (vinfo.depth == 8) {
for (i=0;i<(512*512);i++) xim[i] = (byte) (i % 256);
xi = XCreateImage(dpy, vinfo.visual, vinfo.depth, ZPixmap, 0, (char *) xim,
 511, 512, 8, 0);
printf("bits_per_pixel: %d\nred mask:\t%#x\ngreen mask:\t%#x\nblue mask:\t%#x\n"
	, xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
printf("width:\t%d\nheight:\t%d\nformat:\t%d\ndepth:\t%d\n", xi->width,
	xi->height, xi->format, xi->depth);
printf("bitmap_unit:\t%d\nbitmap_pad:\t%d\nbytes_per_line:\t%d\n",
	xi->bitmap_unit, xi->bitmap_pad, xi->bytes_per_line);
XPutImage(dpy, win, gc, xi, 0,0,0,0, 512,512);
 }

if (vinfo.depth == 16 || vinfo.depth == 15) {
//for (i=0;i<(512*512);i++) xim16[i] = lookup16truecolor[i%256];
for (i=0;i<(512*512);i++) xim16[i] = (short) (i % 32768);
xi = XCreateImage(dpy, vinfo.visual, vinfo.depth, ZPixmap, 0, (char *) xim16,
 512, 512, XBitmapPad(dpy), 0);
/* show some of the attributes */
printf("bits_per_pixel: %d\nred mask:\t%#x\ngreen mask:\t%#x\nblue mask:\t%#x\n"
	, xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
printf("width:\t%d\nheight:\t%d\nformat:\t%d\ndepth:\t%d\n", xi->width,
	xi->height, xi->format, xi->depth);
printf("bitmap_unit:\t%d\nbitmap_pad:\t%d\nbytes_per_line:\t%d\n",
	xi->bitmap_unit, xi->bitmap_pad, xi->bytes_per_line);
XPutImage(dpy, win, gc, xi, 0,0,0,0, 512, 512);
printf("PutImage done\n");
}

if (vinfo.depth == 24) {
for (i=0;i<(512*512);i++) xim32[i] = (unsigned int) ((i*64) % 16777216);
xi = XCreateImage(dpy, vinfo.visual, vinfo.depth, ZPixmap, 0, (char *) xim32,
 512, 512, XBitmapPad(dpy), 0);
/* show some of the attributes */
printf("bits_per_pixel: %d\nred mask:\t%#x\ngreen mask:\t%#x\nblue mask:\t%#x\n"
	, xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
printf("width:\t%d\nheight:\t%d\nformat:\t%d\ndepth:\t%d\n", xi->width,
	xi->height, xi->format, xi->depth);
printf("bitmap_unit:\t%d\nbitmap_pad:\t%d\nbytes_per_line:\t%d\n",
	xi->bitmap_unit, xi->bitmap_pad, xi->bytes_per_line);
/* check for 24 bit pixels, we don't know until after we create an XImage
structure */
printf("address of xim32 = %d, xi->data = %d\n", xim32, xi->data);
if (xi->bits_per_pixel == 24) {
 int	n, nd4, nr;
 int	x1, x2, x3, x4;
 int	*pin, *pout;
 printf("pixels are 24 bits\n");
 n = xi->width * xi->height;
 nd4 = n/4;
 nr = n - nd4*4;
 pin = xim32;
 pout = xim24;
 while (nd4--) {
   x1 = *pin++;
   x2 = *pin++;
   *pout++ = x1 + ((x2 & 0xff) << 24);
   x3 = *pin++;
   *pout++ = (x2 >> 8) + ( x3 << 16);
   x4 = *pin++;
   *pout++ = (x3 >> 16) + (x4 << 8);
 }
 xi->data = (char *) xim24;
}
XPutImage(dpy, win, gc, xi, 0,0,0,0, 512, 512);
printf("PutImage done\n");
}

if (vinfo.depth == 32) {
for (i=0;i<(512*512);i++) xim32[i] = (unsigned int) ((i*64) % 16777216);
xi = XCreateImage(dpy, vinfo.visual, vinfo.depth, ZPixmap, 0, (char *) xim32,
 512, 512, XBitmapPad(dpy), 0);
/* show some of the attributes */
printf("bits_per_pixel: %d\nred mask:\t%#x\ngreen mask:\t%#x\nblue mask:\t%#x\n"
	, xi->bits_per_pixel, xi->red_mask, xi->green_mask, xi->blue_mask);
printf("width:\t%d\nheight:\t%d\nformat:\t%d\ndepth:\t%d\n", xi->width,
	xi->height, xi->format, xi->depth);
printf("bitmap_unit:\t%d\nbitmap_pad:\t%d\nbytes_per_line:\t%d\n",
	xi->bitmap_unit, xi->bitmap_pad, xi->bytes_per_line);

XPutImage(dpy, win, gc, xi, 0,0,0,0, 512, 512);
printf("PutImage done\n");
}

getchar();

getchar();
exit();
}
