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

#define NC  64
#define NW  256
#define NH  256
#define NBW 5

void main(int argc, char *argv[])
{
  int kep[NH][NW];
  int i, j, k, e;
  double x, y, z;
  Display *display;
  int screen;
  Colormap color_map;
  Window window, root_window;
  GC gc;
  XColor color[NC];
  XSizeHints size_hints;
  XWMHints wm_hints;
  XClassHint class_hints;
  XPoint point;
  XEvent event;

  for (i = 0; i < NH; i++) {
    for (j = 0; j < NW; j++) {
      x = 5.0 * M_PI * i / (NH - 1.0);
      y = 5.0 * M_PI * j / (NW - 1.0);
      z = 32.0 * (1.0 + sin(x) * sin(y));
      if (z > 64.0) z = 64.0;
      if (z < 0.0) z = 0.0;
      kep[i][j] = (int) z;
    }
  }

  display = XOpenDisplay(NULL);
  if (display == NULL) exit;
  screen = DefaultScreen(display);
  root_window = RootWindow(display, screen);
  gc = DefaultGC(display, screen);
  color_map = DefaultColormap(display, screen);

  for (i = 0; i < NC; i++) {
    color[i].flags = DoRed | DoGreen | DoBlue;
    color[i].red = (i + 1) * 0xffff / NC;
    color[i].green = (i + 1) * 0xffff / NC;
    color[i].blue = (i + 1) * 0xffff / NC;
    if (!XAllocColor(display, color_map, &color[i])) exit;
  }

  window = XCreateSimpleWindow(
    display, root_window,
    0, 0, NW, NH, NBW,
    WhitePixel(display, screen),
    BlackPixel(display, screen));

  size_hints.flags = PPosition | PSize | PMinSize;
  size_hints.min_width = NW;
  size_hints.min_height = NH;

  wm_hints.initial_state = NormalState;
  wm_hints.input = False;
  wm_hints.flags = StateHint | InputHint;

  class_hints.res_name = argv[0];
  class_hints.res_class = "XWinTest";

  XSetWMProperties(display, window,
    NULL, NULL, argv, argc,
    &size_hints, &wm_hints, &class_hints);

  XSelectInput(display, window, ButtonPressMask | ExposureMask);
  XMapWindow(display, window);

  e = False;
  while (!e) {
    XNextEvent(display, &event);
    switch (event.type) {
    case Expose:
      XSetForeground(display, gc, color[NC - 1].pixel);
      XSetBackground(display, gc, color[0].pixel);
      XFillRectangle(display, window, gc, 0, 0, NW, NH);
      for (i = 0; i < NH; i++) {
        for (j = 0; j < NW; j++) {
            k = kep[i][j];
            point.x = i;
            point.y = j;
            XSetForeground(display, gc, color[k].pixel);
            XDrawPoint(display, window, gc, point.x, point.y);
          }
      }
      XSync(display, True);
      break;
    case ButtonPress:
      e = True;
      break;
    }
  }
  XUnmapWindow(display, window);
  XDestroyWindow(display, window);
  XCloseDisplay(display);
}