
Well, this reads a file of boundaries and draws them...

-------------------------------------------------------------------------------
static char sccsid[] = "@(#)viewdes.cxx 1.2 91/12/13";

//
// viewdes.cxx -- graphically display a descriptions file.
//

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <memory.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "libgenutils/genutils.hxx"
#include "libdesc2/desc.hxx"

#define ClassOfVisual( visual ) ((visual)->c_class)

typedef unsigned long Color;

//
// Global Variables
//
int verbose;
Display * display;
Window window;
GC gc;
int depth;
int color_display;
Color black,white;
int width,height;
char geometry[100];

//
// Functions
//
void exit_silently()
{
  exit(0);
}

void open_window(char * display_name, char * filename)
{
  display = XOpenDisplay( display_name );
  if (!display)
    {
      fprintf(stderr, "Unable to open X display.\n" );
      exit(1);
    }

  int screen_num = DefaultScreen( display );
  Visual * visual = DefaultVisual( display, screen_num ) ;
  black = BlackPixel( display, screen_num ) ;
  white = WhitePixel( display, screen_num ) ;
  Colormap colormap = DefaultColormap( display, screen_num ) ;
  int vclass = ClassOfVisual( visual ) ;
  switch (vclass) {
  case StaticGray:
  case GrayScale:
    color_display = 0;
    break;
  case StaticColor:
  case PseudoColor:
  case TrueColor:
  case DirectColor:
    color_display = 1;
    break;
  default:
    fprintf(stderr, "Unrecognized X visual class.\n" ) ;
    exit(1);
  }
  
  depth = DefaultDepth( display, screen_num ) ;
  gc = DefaultGC( display, screen_num ) ;
  Window parent = DefaultRootWindow( display ) ;

  char default_geom[100];
  sprintf(default_geom, "%dx%d", width, height);
  int xloc,yloc;
  int gflags = XGeometry(display, screen_num, 	// where 
			 geometry, default_geom,// user and default geometries 
			 4, 1, 1,		// border, and unit width in pix 
			 0, 0,			// don't pad 
			 &xloc, &yloc,		// put it where? 
			 &width, &height);	// make it how big? 

  //  signal(SIGPIPE, (SIG_PFV)exit_silently);
  //  XSetErrorHandler ((XErrorHandler)exit_silently);
  //  XSetIOErrorHandler ((XIOErrorHandler)exit_silently);
    
  window = XCreateSimpleWindow(display, parent,
			       xloc, yloc,
			       width, height,
			       4, black, white);
  
  if (gflags & (XValue | YValue))
    {
      XSizeHints sizehints;
      sizehints.x = xloc;
      sizehints.y = yloc;
      sizehints.flags = USPosition;
      XSetNormalHints(display, window, &sizehints);
    }
  
  XWMHints wm_hints;
  wm_hints.flags = InputHint;
  wm_hints.input = True;
  XSetWMProperties(display, window, 0, 0, 0, 0, 0, &wm_hints, 0);
  
  XStoreName(display, window, filename);
  XSelectInput(display, window,
	       StructureNotifyMask | LeaveWindowMask | KeyPressMask | PointerMotionMask);
  XMapWindow( display, window ) ;
  XFlush( display ) ;
}

void fill_image(DataSurfaceList * deslist, /*XImage * image*/
		Pixmap pixmap, int width, int height,
		float xmin, float xmax, float ymin, float ymax)
//
// This is where the lines are drawn...
//
{
  XSetForeground(display,gc,black);
  int border = 8;
  DataSurfaceListIter dli(deslist);
  DataSurface * ds;
  while (ds = dli++)
    {
      PixelListListIter pl_iter(ds->boundary());
      PixelList * pl;
      while (pl = pl_iter++)
	{
	  PixelListIter pli(pl);
	  Pixel * pix;
	  int ox = -1;
	  int oy = -1;
	  while (pix = pli++)
	    {
	      int x = border + (int)((width - 2*border) * (pix->get_x() - xmin) /
				     (xmax - xmin));
	      int y = height - border - (int)((height - 2*border) * (pix->get_y() - ymin) /
				     (ymax - ymin));
	      if (ox != -1)
		XDrawLine(display, pixmap, gc, ox,oy, x,y);
	      ox = x;
	      oy = y;
	    }
	}
    }
}


void usage(char * msg)
{
  fprintf(stderr,"%s\n",msg);
  fprintf(stderr,"usage: viewdes [filename[.des]]\n");
}

main(int argc, char ** argv)
{
  //
  // Process arguments
  //
  width = 256;
  height = 256;
  char * filestem = 0;
  verbose = 1;
  while (++argv,--argc)
    if (**argv == '-')
      // Option
      switch((*argv)[1]) {
      case 'g':
	if (strcmp(*argv,"-geometry") == 0)
	  strcpy(geometry,*argv++);
	break;
      case 'v':
	verbose = 2;
	break;
      case 'q':
	verbose = 0;
	break;
      default:
	usage("Unknown option");
	return 0;
      }
    else
      // Filename -- do input file first
      if (!filestem)
	filestem = *argv;
      else
	{
	  usage("Extra argument");
	  return 0;
	}

  //
  // Read descriptions file
  //
  DataSurfaceList * deslist = 0;
  char * filename;
  {
    FILE * inf;
    if (!filestem)
      {
	inf = stdin;
	filename = "<stdin>";
      }
    else
      {
	filename = add_suffix_if_necessary(filestem,".des");
	inf = fopen(filename,"r");
	if (!inf)
	  {
	    perror(filename);
	    return 0;
	  }
      }
    
    if (!fread(inf,deslist))
      return 1;
  }

  //
  // Get bounding box
  //
  double xmin = 1e10;
  double xmax = -1e10;
  double ymin = xmin;
  double ymax = xmax;
  {
    DataSurfaceListIter dli(deslist);
    DataSurface * ds;
    while (ds = dli++)
      {
	PixelListListIter pl_iter(ds->boundary());
	PixelList * pl;
	while (pl = pl_iter++)
	  {
	    PixelListIter pix_iter(pl);
	    Pixel * pix;
	    while (pix = pix_iter++)
	      {
		float x = pix->get_x();
		if (x < xmin) xmin = x;
		if (x > xmax) xmax = x;
		float y = pix->get_y();
		if (y < ymin) ymin = y;
		if (y > ymax) ymax = y;
	      }
	  }
      }
  }

  //
  // Open Xwindow
  //
  open_window(":0.0",filename);

  XImage * image = XCreateImage(display,
				(Visual *)0,
				depth, 	// Depth
				ZPixmap,// Format
				0,	// x-offset
				0,	// data ptr to be assigned later
				width, height,
				8, 	// scanline alignment
				0);	// bytes per line
  if (!image)
    {
      fprintf(stderr,"XCreateImage failed.\n");
      exit(1);
    }

  image->data = new char[image->bytes_per_line * width];
  memset(image->data,0,image->bytes_per_line * width);

  //
  // Fill image data
  // 
  Pixmap pixmap = XCreatePixmap( display, window, width, height, depth ) ;
  XSetForeground(display,gc,white);
  XFillRectangle(display, pixmap, gc, 0,0, width, height);
  fill_image(deslist,pixmap,width,height,xmin,xmax,ymin,ymax);
  //
  // Start event loop
  //

  XSetWindowBackgroundPixmap( display, window, pixmap ) ;
  XClearWindow( display, window ) ;
  XFlush( display ) ;

  int done = 0;
  do {
    XEvent event;
    XNextEvent( display, &event ) ;
    switch (event.type) {
    case DestroyNotify : 
      done = 1;
      break;
    case EnterNotify:
      break;
    case LeaveNotify:
      break;
#ifdef SILLINESS
    case MotionNotify:
      int x,y;
      int ox = x;
      int oy = y;
      x = event.xbutton.x;
      y = event.xbutton.y;
      XDrawLine(display, pixmap, gc, ox,oy, x,y);
      XClearArea( display, window, ox,oy, ox-x,oy-y, False) ;
      XFlush( display ) ;
      break;
#endif
    case KeyPress:
      {
	char buf[10];
	char c;
	int count = XLookupString((XKeyEvent*)&event, buf, 10, 0, 0);
	if (count == 1)
	  c = buf[0];
	else
	  c = '\0';
	if (c == 'q' || c == 'Q')
	  done = 1;
	break;
      }
    case MappingNotify :
      XRefreshKeyboardMapping((XMappingEvent*)&event);
      break;
    }
  } while ( !done );
  XDestroyWindow(display, window);
  XCloseDisplay(display) ;

  return 0;
}

