/*
 * x11.c
 * kirk johnson
 * july 1993
 *
 * RCS $Id: x11.c,v 1.4 1993/07/23 05:25:02 tuna Exp $
 *
 * Copyright 1993 by Kirk Lauritz Johnson (see the included file
 * "kljcpyrt.h" for complete copyright information)
 */

#include "xearth.h"
#include "Xlib.h"
#include "Xatom.h"
#include "kljcpyrt.h"

typedef unsigned long Pixel;

static void   draw_label();
static Window GetVRoot();

static uchar  *dith;
static uchar  *xbuf;
static int     idx;
static XImage *xim;
static Pixmap  pix;

Display     *dpy;               /* display connection */
int          scrn;              /* screen number      */
Window       root;              /* root window        */
Colormap     cmap;              /* default colormap   */
Visual      *visl;              /* default visual     */
int          dpth;              /* default depth      */
Pixel        white;             /* white pixel        */
Pixel        black;             /* black pixel        */
GC           gc;                /* graphics context   */
Pixel       *pels;              /* allocated colors   */
XFontStruct *font;              /* basic text font    */

void x11_resources()
{
  int    i;
  XColor xc;
  uchar *tmp;

  dpy = XOpenDisplay(dpyname);
  if (dpy == NULL)
    fatal("unable to open display");

  scrn = DefaultScreen(dpy);
  root = RootWindow(dpy, scrn);
  cmap = DefaultColormap(dpy, scrn);
  visl = DefaultVisual(dpy, scrn);
  dpth = DefaultDepth(dpy, scrn);

  if ((visl->class != PseudoColor) || (dpth != 8))
    fatal("visual class and depth not supported yet");

  white = WhitePixel(dpy, scrn);
  black = BlackPixel(dpy, scrn);
  gc = XCreateGC(dpy, root, 0, NULL);
  XSetState(dpy, gc, white, black, GXcopy, AllPlanes);

  wdth = DisplayWidth(dpy, scrn);
  hght = DisplayHeight(dpy, scrn);

  dither_setup(64);
  pels = (Pixel *) malloc(sizeof(Pixel) * dither_ncolors);
  assert(pels != NULL);

  tmp = dither_colormap;
  for (i=0; i<dither_ncolors; i++)
  {
    xc.red   = (tmp[0] << 8) + tmp[0];
    xc.green = (tmp[1] << 8) + tmp[1];
    xc.blue  = (tmp[2] << 8) + tmp[2];

    if (XAllocColor(dpy, cmap, &xc) == 0)
      fatal("unable to allocate enough colors");
    pels[i] = xc.pixel;

    tmp += 3;
  }

  font = XLoadQueryFont(dpy, "variable");
  assert(font != NULL);
  XSetFont(dpy, gc, font->fid);
}


void x11_setup()
{
  dith = (uchar *) malloc(wdth);
  assert(dith != NULL);

  xbuf = (uchar *) malloc(wdth);
  assert(xbuf != NULL);

  xim = XCreateImage(dpy, visl, dpth, ZPixmap, 0, xbuf, wdth, 1, 8, wdth);
  pix = XCreatePixmap(dpy, root, wdth, hght, dpth);
  idx = 0;
}


void x11_row(row)
     uchar *row;
{
  int i;

  dither_row(row, dith);
  for (i=0; i<wdth; i++)
    xbuf[i] = pels[dith[i]];

  XPutImage(dpy, pix, gc, xim, 0, 0, 0, idx, wdth, 1);
  idx += 1;
}


void x11_cleanup()
{
  Window win;

  XDestroyImage(xim);
  free(dith);

  if (label) draw_label();

  win = GetVRoot(dpy);
  XSetWindowBackgroundPixmap(dpy, win, pix);
  XClearWindow(dpy, win);
  XFreePixmap(dpy, pix);
  XSync(dpy, 0);
}


static void draw_label()
{
  int         len;
  int         direction;
  int         ascent;
  int         descent;
  int         x, y;
  char        buf[128];
  XCharStruct extents;

  sprintf(buf, "sun %.1lf %c %.1lf %c",
          fabs(sun_lat), ((sun_lat < 0) ? 'S' : 'N'),
          fabs(sun_lon), ((sun_lon < 0) ? 'W' : 'E'));
  len = strlen(buf);

  XTextExtents(font, buf, len, &direction, &ascent, &descent, &extents);
  x = wdth - extents.rbearing - 10;
  y = hght - descent - 10;
  XDrawString(dpy, pix, gc, x, y, buf, len);

  sprintf(buf, "view %.1lf %c %.1lf %c",
          fabs(view_lat), ((view_lat < 0) ? 'S' : 'N'),
          fabs(view_lon), ((view_lon < 0) ? 'W' : 'E'));
  len = strlen(buf);

  XTextExtents(font, buf, len, &direction, &ascent, &descent, &extents);
  x = wdth - extents.rbearing - 10;
  y = hght - ascent - 2*descent - 12;
  XDrawString(dpy, pix, gc, x, y, buf, len);
}


/* Function Name: GetVRoot
 * Description: Gets the root window, even if it's a virtual root
 * Arguments: the display and the screen
 * Returns: the root window for the client
 *
 * (taken nearly verbatim from the june 1993 comp.windows.x FAQ, item 148)
 */
static Window GetVRoot(dpy)
     Display *dpy;
{
  int          i;
  Window       rootReturn, parentReturn, *children;
  unsigned int numChildren;
  Atom         __SWM_VROOT = None;
  Window       rslt = root;

  __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
  XQueryTree(dpy, root, &rootReturn, &parentReturn, &children, &numChildren);
  for (i=0; i<numChildren; i++)
  {
    Atom    actual_type;
    int     actual_format;
    long    nitems, bytesafter;
    Window *newRoot = NULL;

    if ((XGetWindowProperty(dpy, children[i], __SWM_VROOT, 0, 1,
                            False, XA_WINDOW, &actual_type,
                            &actual_format, &nitems, &bytesafter,
                            (unsigned char **) &newRoot) == Success)
        && newRoot)
    {
      rslt = *newRoot;
      break;
    }
  }

  return rslt;
}
