view glib/X.c @ 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
line wrap: on
line source

/*
    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
    ===========================================================================

    Permission to use, copy, modify, and distribute this software without fee
    is hereby granted for research purposes, provided that this copyright
    notice appears in all copies and in all supporting documentation, and that
    the software is not redistributed for any fee (except for a nominal shipping
    charge). Anyone wanting to incorporate all or part of this software in a
    commercial product must obtain a license from the Medical Research Council.

    The MRC makes no representations about the suitability of this
    software for any purpose.  It is provided "as is" without express or implied
    warranty.
*/

/*******************************************************************************************

 X.c      A GENERIC X-WINDOWS REAR-END FOR THE WINDOWS.H INTERFACE.


 This module is derived from the x10.c module, written by John Holdsworth, and the subsequent
 x11.c module, which was ported by Paul Manson. It attempts to combine the x10/x11 code in
 such a way as to provide a single uniform application with the minimal amount of #ifdef
 "noise". It expects to have either X10 or X11 defined as symbols by the preprocessor -- in the
 event that neither of these is defined, it produces an error message and causes the compiler
 to exit; ie. there is NO DEFAULT.

 Written: May 3rd. by Paul Manson (but see credits above)

 Edited:

 15   May   1989  (Paul Manson) -- Altered the <pixels> argument to use <pixels>-1 in the
                                   newDisplay window call. On X11, pixels of 0 means "use
                                   thin lines", which always work correctly. Values greater
                                   than 0 imply "thick lines", which appear to over-write
                                   each other.

 05  June   1989  (Paul Manson) -- Removed the offending "warning" message from axes();.

 27  July   1989  (Johh Holdsworth) -- put in addition loops to segment line drawing
				   operations for very long lines and put XFlush() in
				   before pausing. A bug remains in the segentation of
				   hidden line removal. The Fill operation Paint to hide
				   lines lower than that just drawn can remove part of
				   that line - very tricky to avoid. The same problem
				   seem to be present in ps.c.

 18 August  1989  (Paul Manson) -- Altered to accomodate the Pixmap/newWindowWindow entry
                                   which forces un-resizable windows on us with X11.

 21 August  1989  (Paul Manson) -- Also altered "Clear" so that it does a FillRectangle in
                                   preference to a ClearWindow. The latter call doesn't work
				   for Pixmaps (see newWindowWindow, etc).

 22 August  1989  (Paul Manson) -- In a similar vein to the above, I have altered X.c so that
                                   two global variables Foreground and Background are used to
				   determine the colours for drawing and filling.

 04 September 1989 (Paul Manson) - Altered so that the GXmodes are used to modify the GC for
                                   clear, draw, etc operations. This seems to be a much more
				   reliable way in which to manipulate these settings.

 31 July 1990 (John Holdsworth)  - Extensive changes to remove previous change. GXcopy
				   now used with foreground appropiately set. This has
				   proved more portable particularly for Multiplane displays.


 26th May 1993 (Mitch d'Souza & M Akeroyd) - added an extra include - sys/types.h - so that the
                                   gcc would work on a decstation.

 3rd August 1993 (M. Akeroyd)   - Removed the 'XAllPlanes' bist of the XGetImage routines,
                                  so that monochrome bitmaps could be made on colour 
				  computers.
				  Also included new SilentOptions :
				      mono_ctn
				      colour_ctn
				      planemask_ctn

 20th August 1993 (M.Akeroyd)  - First attempt at colour images: two new options fg_col and 
                                 bg_col, and a complementary procedure define_colour().
				 These do NOT work with view=grayscale.

                                 ********************************************************************************************/


#if !defined(X11) && !defined(X10)
#define X11
#endif

#if !defined(X10) && !defined(X11)
#include "-- YOU MUST DEFINE EITHER X10 or X11 TO USE THIS MODULE"
#endif

#include <stdio.h>
#include <malloc.h>
#include <sys/types.h>
#include "options.h"        /* Added: MAA 3-8-1993 */
#if defined(X11)
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>  /* MAA: 20-8-1993. For colour */
#include <X11/Xos.h>    /* MAA: 20-8-1993. For colour */


#else
#if defined(X10)
#include <X/Xlib.h>
#endif
#endif

#include "windows.h"
#include "grey.h"

#define FALSE (0)
#define TRUE  (1)
#define MAX_FILES   (20)
#define MAX_SEGMENT (5000)
#define MAX_ROW     (100)
#define MAX_COL     (1000)
#define MAX_IMAGE   (1500)
#define DITHER_SIZE (8)

extern char *monostr, *colourstr, *planemaskstr;  /* Added: MAA 3-8-1993 */
int planemask;

static Display *theDisplay = (Display *) 0;   /* The Display Variable */
static int      theWidth, theHeight;   /* The Width and Height of the Screen in Pixels     */

#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))

#define USE_PIXMAPS

#if defined(X11)
static int      theScreen                 ;   /* The associated screen no. */
static int      synchronous = FALSE ;
static unsigned long theForeground, theBackground;
#else
static char *marker_font_name = "6x10" ;
static FontInfo *marker_font = ( FontInfo * ) 0 ;
#endif

typedef struct {
  windowEntries *entries ;
  Window w ;
  int pixels, width, height, hide ;
  int x, y ;
#if defined(X11)
  GC foregroundGC ;
  GC backgroundGC ;
  int isMapped ;
#ifdef USE_PIXMAPS
  Pixmap imageData[ MAX_IMAGE ];
#else
  XImage *imageData[ MAX_IMAGE ];
#endif
  XImage *theImage;                  /* Used only for Read operations; The wind__write */
                                     /* entry point actually creates & destroys images */
  XImage *rowImage, *colImage ;
#else
  int foreground, background ;
  short *imageData[ MAX_IMAGE ];
  short *theImage              ;
#endif
  struct _lookup *lookup       ;    /* Dithering */
  int   **diths                ;    /* Dithering */
  short  *data                 ;    /* Dithering */
  int     greylength ;
  int     imageNum ;
  int     imageSize;
} *XWindowObject ;

#ifndef  lint
static char *sccs_id = "@(#)X.c	1.38 Paul Manson, John Holdsworth (MRC-APU) 5/31/91" ;
#endif

#if defined(X11)




/* MAA: Added 20-8-1993 
* Colour ....
* Copied off example 7.2 of Xlib Vol 1. 
*/

extern char *fgcolourstr;
extern char *bgcolourstr;

void define_colours()
{
  int default_depth;
  Visual *default_visual;
  XColor exact_def;
  Colormap default_cmap;
  int i=5;
  XVisualInfo visual_info;


  default_depth = DefaultDepth(theDisplay, theScreen);
  default_visual = DefaultVisual(theDisplay, theScreen);
  default_cmap = DefaultColormap(theDisplay, theScreen);

/* MAA: Removed this. */
/*  if (default_depth == 1) {*/
    /* Black-White Only */
/*    theForeground = BlackPixel(theDisplay, theScreen);*/
/*    theBackground = WhitePixel(theDisplay, theScreen);}*/

  /* i = visual class */
  while (!XMatchVisualInfo(theDisplay, theScreen, default_depth, i--, &visual_info))
    ;

  if (i<StaticColor) {
    theForeground = BlackPixel(theDisplay, theScreen);
    theBackground = WhitePixel(theDisplay, theScreen);}

  else {

    /* Foreground */
    if (!XParseColor(theDisplay, default_cmap, fgcolourstr, &exact_def)){
      fprintf(stderr, "Unable to find colour %s in database. Using Black instead. \n", fgcolourstr);
      theForeground = BlackPixel(theDisplay, theScreen);}
    else 
      if (XAllocColor(theDisplay, default_cmap, &exact_def))
        theForeground = exact_def.pixel;
      else {
        fprintf(stderr, "Unable to alloc colour %s. Using Black instead. \n", fgcolourstr);
        theForeground = BlackPixel(theDisplay, theScreen);}
    
    /* Background */
    if (!XParseColor(theDisplay, default_cmap, bgcolourstr, &exact_def)){
      fprintf(stderr, "Unable to find colour %s in database. Using White instead. \n", bgcolourstr);
      theBackground = WhitePixel(theDisplay, theScreen);}
    else 
      if (XAllocColor(theDisplay, default_cmap, &exact_def))
        theBackground = exact_def.pixel;
      else {
        fprintf(stderr, "Unable to alloc colour %s. Using White instead. \n", bgcolourstr);
        theBackground = WhitePixel(theDisplay, theScreen);}
  }
}




extern void InitializeX(display, screen, foreground, background)
     Display      *display   ;
     int           screen    ;
     unsigned long foreground;
     unsigned long background;
{
  if (theDisplay == (Display *) 0) {
    theDisplay    = display   ;
    theScreen     = screen    ;
    theForeground = foreground;
    theBackground = background;
  }
  else {
    (void) fprintf(stderr, "Error! The X.c Display Variable has already been set...\nIt is invalid to call InitializeX after this has happened (eg. by a call to newDisplayWindow).\n");
    exit(1);
  }
}

/* not a nice routine to wait untill window is actually mapped before returning it's size */

static void waitTillMapped( info )
XWindowObject info ;
{
    XWindowAttributes at ;

    if( !info->isMapped ) {
	do
	    XGetWindowAttributes( theDisplay, info->w, &at ) ;
	while ( at.map_state == IsUnmapped ) ;

	info->isMapped = 1 ;

	info->width  = at.width  ;
	info->height = at.height ;
    }

    return ;
}

/* ---------------- Beware! This function may be the most dangerous thing ---------------
   ----------------         to ever appear on a DecStation... it makes    ---------------
   ----------------         sweeping assumptions about the way that data  ---------------
   ----------------         is stored in the X server. If it EVER happens ---------------
   ----------------         that the X Consortium write routines for I/O  ---------------
   ----------------         of Screen Images, THROW THIS AWAY!            --------------- */
static int ImageSizeInBytes(image)
     XImage *image;
{

   /* Cribbed from X11R3/.../xwd.c */

   return(image->bytes_per_line * image->height * image->depth);

}


static setupImage( w )
XWindowObject w ;
{
    if( w->theImage == ( XImage * ) 0 ) {
	w->theImage = XGetImage(theDisplay, w->w, 0, 0, w->entries->width(w),
			       w->entries->height(w), planemask, XYPixmap);
	w->imageSize = ImageSizeInBytes(w->theImage);
    }
}



#endif

static short window__x( info )
XWindowObject info ;
{
#if defined(OldX11)
    XWindowAttributes winfo;

    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );

    return ((short) winfo.x);
#else
#if defined(X11)
    return ((short) info->x);
#else
    WindowInfo winfo;

    XQueryWindow(info->w, &winfo);

    return (winfo.x);
#endif
#endif
}

static short window__y( info )
XWindowObject info ;
{
#if defined(OldX11)
    XWindowAttributes winfo;

    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );

    return ((short) winfo.y);
#else
#if defined(X11)
    return ((short) info->y);
#else
    WindowInfo winfo;

    XQueryWindow(info->w, &winfo);

    return (winfo.y);
#endif
#endif
}

static short window__width( info )
XWindowObject info ;
{
#if defined(X11)
    waitTillMapped(info) ;
#endif

    return( info->width ) ;
}

static short window__height( info )
XWindowObject info ;
{
#if defined(X11)
    waitTillMapped(info) ;
#endif

    return( info->height ) ;
}

static void window__draw( info, xs, ys, pointsFlag )
XWindowObject info ;
short xs[], ys[] ;
int pointsFlag ;
{
#if defined(X11)
    XPoint vs[MAX_SEGMENT], *vptr;
#else
    Vertex vs[MAX_SEGMENT], *vptr;
#endif
    register int point, count ;
    register int points = abs( pointsFlag ) ;
    register short h ;

#if defined(X11)
    if (synchronous) {
      (void) XSynchronize(theDisplay, FALSE);
      XFlush(theDisplay);
      synchronous = FALSE;
    }

    waitTillMapped(info) ;
#else
    int i ;
#endif

    h = info->entries->height( info );

    for( point = 0 ; point < points - 1 ; point += count - 1 ) {

	vptr = vs ;

	for( count=0 ; count < MAX_SEGMENT && point + count < points ; count++ ) {

	    vptr->x =     xs[ point+count ] ;
	    vptr->y = h - ys[ point+count ] ;
#if defined(X10)
	    vptr->flags = pointsFlag > 0 ? 0 : 0 ;
#endif
	    vptr++;
	}

	if( info->hide && pointsFlag > 0 && vs[0].x == vptr[-1].x &&
					    vs[0].y == vptr[-1].y )
#if defined(X11)
	    XFillPolygon( theDisplay, info->w, info->backgroundGC, vs, vptr-vs, Complex, CoordModeOrigin);

	if( pointsFlag > 0 )
	    XDrawLines( theDisplay, info->w, info->foregroundGC, vs, vptr-vs, CoordModeOrigin);
	else
	    XDrawPoints(theDisplay, info->w, info->foregroundGC, vs, vptr-vs, CoordModeOrigin);

	XFlush(theDisplay);
#else
	    XDrawFilled( info->w, vs, vptr-vs, info->background, GXcopy, AllPlanes ) ;

	if( pointsFlag > 0 )
	    XDraw(info->w, vs, vptr-vs, info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes);
	else
	    for( i=0 ; i<count ; i++ )
		XPixSet( info->w, vs[i].x, vs[i].y, info->pixels, info->pixels, info->foreground ) ;
#endif
    }

    return;
}

static void checkGeometry( info )
XWindowObject info ;
{
#if defined(X11)
    return;
#else
#if defined(OldX11)
    XWindowAttributes winfo;

    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );
#else
    WindowInfo winfo;

    XQueryWindow(info->w, &winfo);
#endif

    info->width  = winfo.width ;
    info->height = winfo.height ;

    return ;
#endif
}

static void window__clear( info )
XWindowObject info ;
{

    checkGeometry( info ) ;

#if defined(OldX11)
    XClearWindow(theDisplay, info->w);
    XFlush(theDisplay);
#else
#if defined(X11)
    XFlush(theDisplay);
    XFillRectangle( theDisplay, info->w, info->backgroundGC, 0, 0, info->width, info->height ) ;
    XFlush(theDisplay);
#else
    XClear(info->w);
#endif
#endif

    return ;
}

static void window__close( info )
XWindowObject info ;
{
    if (info != (XWindowObject )0)
#if defined(X11)
	XFreeGC( theDisplay, info->foregroundGC ) ;
	XFreeGC( theDisplay, info->backgroundGC ) ;
        XDestroyWindow(theDisplay, info->w);
#else
        XDestroyWindow(info->w);
#endif
    free( (char *) info ) ;

    return ;
}

static int window__store( info )
XWindowObject info ;
{
    if (info->imageNum > MAX_IMAGE) {
      (void) fprintf(stderr,
		     "windows: Sorry, you can currently store only %i images per window.\n",
		     MAX_IMAGE);
      return(FALSE);
    }
#if defined(X11)
    if (!synchronous) {
      (void) XSynchronize(theDisplay, TRUE);
      XFlush(theDisplay);
      synchronous = TRUE;
    }

    waitTillMapped(info) ;

#ifdef USE_PIXMAPS
    info->imageData[ info->imageNum ] = XCreatePixmap(theDisplay, info->w, Width( info ), Height( info ), DisplayPlanes( theDisplay, theScreen ) ) ;
    XCopyArea( theDisplay, info->w, info->imageData[ info->imageNum ], info->foregroundGC, 0, 0, Width( info), Height( info ), 0, 0 ) ;
#else
    info->imageData[ info->imageNum ] = XGetImage(theDisplay, info->w, 0, 0,
					  info->entries->width(info),
					  info->entries->height(info),
					  planemask,
					  XYPixmap);
#endif
#else
    if((info->imageData[info->imageNum] = (short *) malloc(info->imageSize)) == (short *) 0) {
	(void) fprintf(stderr, "Insufficient memory to store %dth image of size %d\n",
		       info->imageNum+1, info->imageSize);
	return(FALSE);
      }
    else
	XPixmapGetXY( info->w, 0, 0, info->entries->width(info),
		     info->entries->height(info), info->imageData[ info->imageNum ] ) ;
#endif
    info->imageNum++;

    return ( info->imageNum ) ;
}

WindowImage window__current_image( info )
XWindowObject info ;
{
    static struct _window_image image_info ;
#if defined(X11)
#if !defined( USE_PIXMAPS)
    XImage *image_ptr = info->imageData[ info->imageNum-1 ] ;

    image_info.data           = image_ptr->data ;
    image_info.bytes_per_line = image_ptr->bytes_per_line ;
    image_info.height         = image_ptr->height ;

    image_info.left_bit  = 1<<0 ;
    image_info.right_bit = 1<<7  ;
    image_info.start_bit = image_info.left_bit<<image_ptr->xoffset ;
#endif
#else
    short *image_ptr = info->imageData[ info->imageNum-1 ] ;

    image_info.data = ( char *) image_ptr ;
    image_info.height = info->height ;
    image_info.bytes_per_line = ( info->width + 15 ) / 16 * sizeof (*image_ptr) ;

    image_info.left_bit  = 1<<0 ;
    image_info.right_bit = 1<<7  ;
    image_info.start_bit = image_info.left_bit ;

#endif

    return ( &image_info ) ;
}

static void window__recall( info, which )
XWindowObject info ;
int which ;
{

#if defined(X11)
    if (synchronous) {
      (void) XSynchronize(theDisplay, FALSE);
      XFlush(theDisplay);
      synchronous = FALSE;
    }
#endif
    if( which > info->imageNum )
	(void) fprintf( stderr, "Invalid Pixmap number %d(%d)\n", which, info->imageNum ) ;
    else
#if defined(X11)
#ifdef USE_PIXMAPS
        XCopyArea( theDisplay, info->imageData[ which-1 ], info->w, info->foregroundGC, 
		0, 0, Width( info), Height( info ), 0, 0 ) ;
#else
	XPutImage(theDisplay, info->w, info->foregroundGC, info->imageData[which-1], 0, 0, 0, 0,
		  info->entries->width(info), info->entries->height(info));
#endif  
	XFlush(theDisplay) ;
#else
	XPixmapBitsPutXY(info->w, 0, 0, info->entries->width(info), info->entries->height(info),
			 info->imageData[ which-1 ], (Bitmap) 0, GXcopy, AllPlanes);
#endif
    return  ;
}

#define MAX_COLORS 62

static char *cmap( npixels )
int *npixels ;
{
    int plane_masks[1], pix_num ;
    char *pixvals ;
#if defined(X11)
	Visual *visual = DefaultVisual( theDisplay, theScreen ) ;
    Colormap theColormap = DefaultColormap( theDisplay, theScreen ) ;
    XColor exact_defs[MAX_COLORS] ;
    unsigned long colors[MAX_COLORS] ;

	switch( visual->class ) {	
		case StaticGray :
		
			*npixels = 1 << DisplayPlanes( theDisplay, theScreen ) ;
		    pixvals = malloc( (unsigned) *npixels ) ;

    		for( pix_num=0 ; pix_num < *npixels ; pix_num++ )
				pixvals[pix_num] = pix_num ;

			break ;
			
		case PseudoColor :
		
    for( *npixels=MAX_COLORS; *npixels > 2 ; (*npixels)-- ) 
        if( XAllocColorCells( theDisplay, theColormap, False, plane_masks, 0, colors, *npixels ) ) 
            break ;

    pixvals = malloc( (unsigned) *npixels + 2 ) ;
    
    pixvals[0] = BlackPixel( theDisplay, theScreen ) ;
    
    for( pix_num=0 ; pix_num < *npixels ; pix_num++ ) {
        pixvals[pix_num+1] = 
        exact_defs[pix_num].pixel = colors[ pix_num ] ;
 
        exact_defs[pix_num].red   = 
        exact_defs[pix_num].green = 
        exact_defs[pix_num].blue  = 65535 * ( pix_num + 1 ) / ( *npixels + 1 ) ;

        exact_defs[pix_num].flags = DoRed | DoGreen | DoBlue ;
   }
    
    pixvals[*npixels+1] = WhitePixel( theDisplay, theScreen ) ;

    XStoreColors( theDisplay, theColormap, exact_defs, *npixels ) ;

    XFreeColors( theDisplay, theColormap, colors, *npixels, 0l ) ;

    *npixels += 2 ;
	
	break ;
	}
#else
    Color defs[256] ;
    int pixels[256] ;
    int planes ;
    
    *npixels = ( 1 << DisplayPlanes() ) - 2 ;

    while( !XGetColorCells( 0, *npixels, 0, & planes, pixels ) && *npixels > 0 )
    	*npixels-- ;
	
    pixvals = malloc( (unsigned) *npixels + 2 ) ;

    pixvals[ 0 ] = BlackPixel ;
           
    for( pix_num=0 ; pix_num < *npixels ; pix_num++ ) {

	pixvals[pix_num+1]  =

	defs[pix_num].pixel = pixels[pix_num] ;

	defs[pix_num].red   = 0 ;
	defs[pix_num].green = 65535 * (pix_num+1) / (*npixels+1) ;
	defs[pix_num].blue  = 0 ;

    }

    pixvals[ *npixels+1 ] = WhitePixel ;

    XStoreColors( *npixels, defs ) ;

    XFreeColors( pixels, *npixels, planes ) ;

    XFlush() ;

    *npixels += 2 ;
#endif
    return ( pixvals ) ;
}

static void ColorColumn( info, col, input, black, white, match, length, row_flag )
XWindowObject info ;
int col ;
short *input ;
int black, white ;
int *match, length ;
int row_flag ;
{
    register int i ;
    char *data ;

    if( info->lookup == 0 || length != info->greylength ) {

	if( info->lookup != 0 )
	    freeLookup( info->lookup ) ;

	info->lookup = makeLookup( cmap, black, white, length ) ;

#if defined(X11)
        if( row_flag )
            info->rowImage = XGetImage( theDisplay, info->w, 0, 0, Width(info),  1, planemask, ZPixmap );
	else
            info->colImage = XGetImage( theDisplay, info->w, 0, 0, 1, Height(info), planemask, ZPixmap );

	info->greylength = length ;
#endif
    }

    data = Lookup( col, info->lookup, input, match, length ) ;

#if defined(X11)
     if( row_flag ) {
	 for( i=0 ; i<Width(info) ; i++ )
             XPutPixel( info->rowImage, i, 0, (unsigned long) data[i] ) ;

        XPutImage(theDisplay, info->w, info->foregroundGC, info->rowImage, 0, 0, 0, col-1, Width(info), 1 );
     }
     else {
   	 for( i=0 ; i<Height(info) ; i++) 
            XPutPixel( info->colImage, 0, i, (unsigned long) data[i] ) ;

         XPutImage(theDisplay, info->w, info->foregroundGC, info->colImage, 0, 0, col-1, 0, 1, Height(info) );
     }
#else
    if( row_flag )
	XPixmapBitsPutZ( info->w, 0, col, length, 1, data, (Bitmap) 0, GXcopy, AllPlanes ) ;
    else
	XPixmapBitsPutZ( info->w, col, 0, 1, length, data, (Bitmap) 0, GXcopy, AllPlanes ) ;
    XFlush() ;
#endif
        return ;
}

static void DitherColumn( info, col, input, black, white, match, length, row_flag )
XWindowObject info ;
int col ;
short *input ;
int black, white ;
int *match, length ;
int row_flag ;
{
    register int *mptr = match ;
    register int *mend = match + length ;
    register int x, bit, *dptr ;
#if defined(X11)
    XPoint pts[2000] ;
    int count = 0 ;
#endif

    if( info->data == ( short * ) 0 || length != info->greylength ) {

	if( info->data != ( short * ) 0 ) {
	    free( ( char * ) info->data ) ;
	    FreeDithers( info->diths, DITHER_SIZE ) ;
	}

	info->data  = (short *) malloc( (unsigned) length * sizeof( *info->data ) ) ;
	info->diths = Dithers( DITHER_SIZE, length, black, white ) ;

	info->greylength = length ;
    }

    dptr = info->diths[ col%DITHER_SIZE ] ;

#if defined(X11)
    if( row_flag ) {
	while( mptr < mend )
	    if( input[ *mptr++ ] > *dptr++ ) {
		pts[count].x = mptr - match ;
		pts[count].y = col-1 ;
		count++ ;
	    }
    }
    else {
	while( mptr < mend )
	    if( input[ *mptr++ ] > *dptr++ ) {
		pts[count].x = col-1 ;
		pts[count].y = mptr - match ;
		count++ ;
	    }
    }

    XDrawPoints(theDisplay, info->w, info->foregroundGC, pts, count, CoordModeOrigin ) ;
#else
    if( row_flag ) {
	while( mptr < mend ) {

	    x = mptr - match ;

	    if( x%16 == 0 )
		info->data[x/16] = 0 ;

	    if( input[ *mptr++ ] <= *dptr++ )
		info->data[x/16] |= 1<<x%16 ;
	}

	XPixmapBitsPutXY( info->w, 0, col, length, 1, info->data, (Bitmap) 0, GXcopy, AllPlanes ) ;
    }
    else {
	while( mptr < mend )
	    info->data[mptr-match] = input[ *mptr++ ] <= *dptr++ ;

	XPixmapBitsPutXY( info->w, col, 0, 1, length, info->data, (Bitmap) 0, GXcopy, AllPlanes ) ;
    }
#endif

    return ;
}


static void window__fill( info, col, input, black, white, match, length, row_flag )
XWindowObject info ;
int col;
short *input;
int black, white ;
int *match, length ;
int row_flag ;
{
    int chans, chan, y, blacky;

#if defined(X11)
    waitTillMapped(info) ;
#endif

    if (info->pixels == 0 || 1 )

#if !defined(X11)
     if (DisplayPlanes() > 1)
#else
     if( DisplayPlanes( theDisplay, theScreen ) > 1 && 
	     DisplayPlanes( theDisplay, theScreen ) != 4 )
#endif
	ColorColumn(  info, col, input, black, white, match, length, row_flag );
      else
	DitherColumn( info, col, input, black, white, match, length, row_flag );

    else { /* old line drawing simulation code to be removed */
      chans = match[length - 1] + 1;

      blacky = length;

      for (chan = 0; chan < chans; chan++) {
	y = length - length * chan / chans;
	y -= (input[chan] - black) * length / (white - black) / chans;

	if( y < blacky || !info->hide ) {
#if defined(X11)
	  XDrawPoint(theDisplay, info->w, info->foregroundGC, col, y);
#else
	  XPixSet(info->w, col, y, info->pixels, info->pixels, info->foreground ) ;
#endif
	  blacky = y;
	}
      }
    }

    return;
}

static void window__fillCol( info, col, input, black, white, match, length)
XWindowObject info ;
int col;
short *input ;
int black, white ;
int *match, length ;
{
    window__fill( info, col, input, black, white, match, length, 0 ) ;

    return ;
}

static void window__fillRow( info, col, input, black, white, match, length)
XWindowObject info ;
int col;
short *input;
int black, white ;
int *match, length ;
{
    window__fill( info, col, input, black, white, match, length, 1 ) ;

    return ;
}

static void window__function( info, ys, segment, skip, offset, yspan, start, points )
XWindowObject info ;
short *ys ;
int segment, skip ;
double offset, yspan ;
int start, points ;
{
#if defined(X11)
    XPoint vs[ MAX_SEGMENT+4 ], *vptr ;
#else
    Vertex vs[ MAX_SEGMENT+4 ], *vptr ;
#endif
    register long x, dx, yscale ;
    register int yoffset, point, count ;
    register short *yptr ;
    static long shift = 16 ;
    static long round = 1l << 15 ;

#if defined(X11)
    if (synchronous) {
      (void) XSynchronize(theDisplay, FALSE);
      XFlush(theDisplay);
      synchronous = FALSE;
    }

    waitTillMapped(info) ;
#endif

    points = abs(points);

    if( points <= 1 )
	return ;

    yoffset = info->entries->height( info ) - offset ;

    dx = (  double ) ( ( info->entries->width(  info ) - 1 ) << shift ) / ( points - 1 ) + 0.5 ;
    x  = dx * start + ( 1 << shift ) + round ;

    yscale =         ( ( info->entries->height( info )     ) << shift ) / yspan  + 0.5 ;

    yptr = ys ;

    for( point=0 ; point < segment-1 ; point += count-1 ) {

	vptr = vs ;

	for( count=0 ; count < MAX_SEGMENT && point + count < segment ; count++ ) {

	    vptr->x = x >> shift ;
	    vptr->y = yoffset - ( *yptr * yscale + round >> shift ) ;
#if defined(X10)
	    vptr->flags = 0;
#endif
	    vptr++ ;

	    if( count+1 < MAX_SEGMENT && point + count+1 < segment ) {
		x    += dx   ;
		yptr += skip ;
	    }
	}

	if( info->hide ) {

	    vptr->x = vptr[-1].x ;
	    vptr->y = 1 + yoffset ;
#if defined(X10)
	    vptr->flags = 0 ;
#endif
	    vptr++ ;

	    vptr->x = vs[0].x ;
	    vptr->y = vptr[-1].y ;
#if defined(X10)
	    vptr->flags = 0 ;
#endif
	    vptr++ ;

	    vptr->x = vs[0].x ;
	    vptr->y = vs[0].y ;
#if defined(X10)
	    vptr->flags = 0 ;
#endif
	    vptr++ ;

#if defined(X11)
	    XFillPolygon(   theDisplay, info->w, info->backgroundGC, vs, vptr-vs, Complex, CoordModeOrigin);
	}

	XDrawLines(theDisplay, info->w, info->foregroundGC, vs, count, CoordModeOrigin);
	XFlush(theDisplay);
#else
	    XDrawFilled( info->w, vs, vptr-vs, info->background, GXcopy, AllPlanes ) ;
	}

	XDraw( info->w, vs, count, info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes ) ;
#endif
    }

    return ;
}

typedef struct {
    FILE *imageFilePtr                ;     /* The File Pointer       */
    int   imageFilePreviousFrame      ;     /* The last image read    */
} ReadingData;

static ReadingData readingFiles[MAX_FILES], *current;
static int         numReadingFiles = 0              ;
static int         window__writing = 1              ;

/* --------------------------------------------------------------------

   Search in the readingFiles[] array for the given filePtr. If found,
   return its index; otherwise return FAILURE (-1).

   -------------------------------------------------------------------- */

static int findReadingFile( filePtr )
FILE *filePtr;
{
	int i;

    for (i = 0; i < numReadingFiles; i++)
    	if (readingFiles[i].imageFilePtr == filePtr)
    		return (i);

	return (-1);

}

static int window__read(w, filePtr, which)
XWindowObject w    ;
FILE        *filePtr;
int          which  ;
{
  int    readingFileIndex ;
  long   filePosBeforeSeek;

#if defined(X11)
  if (!synchronous) {
    (void) XSynchronize(theDisplay, TRUE);
    XFlush(theDisplay);
    synchronous = TRUE;
  }

    waitTillMapped(w) ;

    setupImage( w ) ;
#else
    if( w->theImage == (short *) 0 ) {
	if((w->theImage = (short *) malloc(w->imageSize)) == NULL) {
	    (void) fprintf(stderr, "windows: Insufficient memory to malloc %i bytes for a Pixmap.\n",
		     w->imageSize);
	    exit(1);
	}
    }
#endif

  if (numReadingFiles == 0 || current->imageFilePtr != filePtr) {
    if (numReadingFiles > 0 &&
       (readingFileIndex = findReadingFile(filePtr)) >= 0)
    	current  = &readingFiles[readingFileIndex];
    else {
    	/* The First Read Operation (on this file) */
        if (numReadingFiles >= MAX_FILES) {
        	fprintf(stderr,
			"windows: Sorry, you can only have %i files open for reading at once.\n",
			MAX_FILES);
        	fprintf(stderr, "         Hit <return> to exit.\n");
        	getchar();
        	exit(1);
        }
        current = &readingFiles[numReadingFiles] ;
       	current->imageFilePtr           = filePtr;
       	current->imageFilePreviousFrame = 0      ;
     	numReadingFiles++;
    }
  }

  filePosBeforeSeek = ftell(current->imageFilePtr);

  /* Now Read and Display it */

  if (fseek(current->imageFilePtr,
          ((long) which - current->imageFilePreviousFrame - (long) 1) * w->imageSize, 1))
            return (FALSE);

#if defined(X11)
  if (fread(w->theImage->data, 1, w->imageSize, current->imageFilePtr) != w->imageSize) {
#else
  if (fread(w->theImage, 1, w->imageSize, current->imageFilePtr) != w->imageSize) {
#endif
        /* Reposition the filePointer to enable future Reads */
        if (fseek(current->imageFilePtr, filePosBeforeSeek, 0)) {
        	(void) fprintf(stderr,
			       "windows: Unable to reposition the file after a failed Read.\n");
        	exit(1);
        }
    	return (FALSE);
      }

#if defined(X11)
  XPutImage(theDisplay, w->w, w->foregroundGC, w->theImage, 0, 0, 0, 0, w->entries->width(w),
	    w->entries->height(w));
#else
  XPixmapBitsPutXY(w->w, 0, 0, w->entries->width(w), w->entries->height(w),
		   w->theImage, (Bitmap) 0, GXcopy, AllPlanes);
#endif

  current->imageFilePreviousFrame = which;

  return (TRUE);
}


static void window__write(w, filePtr)
XWindowObject w;
FILE        *filePtr;
{
#if defined(X11)
    int    imageSize;
    XImage *theImage;

    theImage = XGetImage(theDisplay, w->w, 0, 0, w->entries->width(w), w->entries->height(w),
			 planemask, XYPixmap);

    imageSize = ImageSizeInBytes(theImage);

    if (fwrite(theImage->data, 1, imageSize, filePtr) != imageSize) {
    	fprintf(stderr,
		"window: WARNING! Failed to write %i bytes to Image File as image number %i.\n",
     	        imageSize, window__writing);
    	fprintf(stderr, "        Hit <return> to continue.\n");
    	getchar();
    }

    window__writing++;

    (void) XDestroyImage(theImage);
#else
    if( w->theImage == ( short * ) 0 ) {
	if((w->theImage = (short *) malloc(w->imageSize)) == NULL) {
	    (void) fprintf(stderr, "windows: Insufficient memory to malloc %i bytes for a Pixmap.\n",
		     w->imageSize);
	    exit(1);
	}
    }

    XPixmapGetXY(w->w, 0, 0, w->entries->width(w), w->entries->height(w), w->theImage) ;

    (void) fwrite((char *) w->theImage, 1, (int) w->imageSize/DisplayPlanes(), filePtr) ;
#endif

    return;
}


static char window__pause(info)
XWindowObject info ;
{
  char line[256];

#if defined(X11)
    XFlush(theDisplay);
#else
    XFlush();
#endif

  (void) gets(line);

  if (line[0] == '\000' || line[0] == '\r' || line[0] == '\n')
    return (' ');
  else
    return (line[0]);
}

static void window__axes(info, title, xmin, xmax, xtitle, ymin, ymax, ytitle)
XWindowObject info;
     char *title, *xtitle, *ytitle;
     char *xmin, *xmax, *ymin, *ymax;
{
  return;
}

static void window__marker( info, label, p, points )
XWindowObject info ;
char *label ;
int p, points ;
{
    short pos = ( info->entries->width( info ) * p + points / 2 ) / points ;

#if defined( X11 )
    XDrawLine(theDisplay, info->w, info->foregroundGC, pos, 1, pos, info->entries->height(info));
#else
    XLine( info->w, pos, 1, pos, info->entries->height( info ), info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes ) ;

    if( marker_font == ( FontInfo * ) 0 )
	marker_font = XOpenFont( marker_font_name ) ;

    if( marker_font == ( FontInfo * ) 0 )
	(void) fprintf( stderr, "Unable to use font %s for marker %s\n", marker_font_name, label ) ;
    else
	XTextMaskPad( info->w, pos - 1 - XQueryWidth( label, marker_font->id ), 1,
	      label, strlen( label ), marker_font->id, 0, 0, info->foreground, GXxor, AllPlanes ) ;
#endif

    return ;
}

static int window__special( info, code, data )
XWindowObject info ;
int code ;
char *data ;
{
    return 0 ;
}


WindowObject newWindowWindow( window, default_x, default_y, default_width, default_height, pixels )
Window window ;
int default_x, default_y, default_width, default_height ;
int pixels ;
{
    static windowEntries entries = { window__x, window__y, window__width, window__height,
				     window__draw, window__clear, window__close, window__store,
				     window__recall, window__fillRow, window__fillCol,
				     window__function, window__read, window__write,
				     window__pause, window__axes, window__marker, window__special } ;
    XWindowObject info ;
#if defined( X11 )
    XGCValues GCTemplate;
#endif

    if ((info = (XWindowObject ) malloc( sizeof(*info) )) == (XWindowObject )0) {
      (void) fprintf(stderr, "windows: Insufficient memory to allocate WindowObject.\n");
      exit(1);
    }

    info->entries = &entries ;
    info->w       = window   ;

    if( pixels < 0 )
	info->pixels = -pixels ;
    else
	info->pixels = pixels ;

    info->hide    = pixels < 0 ;

#if defined(X11)
    info->isMapped = 1 ;

    /* Initialise a Graphics Context for lines and points */

    GCTemplate.function   = GXcopy ;

    GCTemplate.foreground = theForeground ;
    GCTemplate.background = theBackground ;

    GCTemplate.line_width = info->pixels ;

    if( GCTemplate.line_width == 1 )
	GCTemplate.line_width =  0 ; /* use "thin" lines */

    info->foregroundGC = XCreateGC( theDisplay, info->w,
	 GCFunction|GCForeground|GCBackground|GCLineWidth, &GCTemplate ) ;

    /* A second GC for clearing and hiding lines */

    GCTemplate.foreground = theBackground ;
    GCTemplate.background = theForeground ;

    info->backgroundGC = XCreateGC( theDisplay, info->w,
	 GCFunction|GCForeground|GCBackground|GCLineWidth, &GCTemplate ) ;

#else
    info->foreground = WhitePixel ;
    info->background = BlackPixel ;
    info->lookup = 0;
#endif

    info->data = (short *) 0 ;
    info->greylength = 0 ;

    /* update width and height fields */

    info->x      = default_x     ;
    info->y      = default_y     ;
    info->width  = default_width ;
    info->height = default_height;

    checkGeometry( info ) ;

    /* Initialise the Image Data Structure for later read operations */

#if defined(X11)
    info->theImage = info->rowImage = info->colImage = (XImage *) 0 ;
#else
    info->imageSize = XYPixmapSize(info->entries->width(info), info->entries->height(info), DisplayPlanes());
    info->theImage = ( short * ) 0 ;
#endif

    info->imageNum = 0 ;

    /* MAA: 3-8-1993 
     * The planemask bits might as well go here as anywhere else 
     */

    if ( isON(colourstr) ) 
      planemask = AllPlanes;
    else
      planemask = atoi(planemaskstr);

    return ( (WindowObject) info ) ;
}

    /* Since the <name> argument is always passed to newDisplayWindow as NULL, and
       the ASP modules don't have any concept of a configurable <display> option (the
       display is either ON or OFF), the <name> argument is redundant. The <name> argument
       still has a sensible use as the name of the Window which is being created, and
       its use has been modified as such in genbmm, revbmm, gensai and revsai... */


WindowObject newXWindow( name, default_x, default_y, default_width, default_height, pixels )
char *name ;
int default_x, default_y, default_width, default_height ;
int pixels ;
{
    Window w ;
    XWindowObject info;

#if defined(X11)

    if (theDisplay == (Display *) 0) {
      if ((theDisplay = XOpenDisplay(NULL)) == (Display *) 0) {  /* Was name */
	(void) fprintf(stderr, "X11: Unable to do XOpenDisplay of display %s.\n",
		       getenv("DISPLAY"));
	exit(1);
      }

      theScreen  = XDefaultScreen( theDisplay ) ;
      
      /* MAA: 20-8-1993 
       * lets put the colour bits here */
      
      define_colours();

#ifndef SLAVE
      if (!synchronous) {
        (void) XSynchronize(theDisplay, TRUE);
        XFlush(theDisplay);
        synchronous = TRUE;
      }
#endif
    }

    /* Need to reset these every time, in case the screen is initialized
       independently via InitializeX */

    theWidth  = XDisplayWidth (theDisplay, theScreen);
    theHeight = XDisplayHeight(theDisplay, theScreen);

    /* Perform "centering" calculations */

    if (default_x < 0) {
      /* Center in the x dimension */
      default_width = (MIN(default_width, theWidth));
      default_x     = (theWidth - default_width) / 2;
    }

    if (default_y < 0) {
      /* Center in the y dimension */
      default_height = (MIN(default_height, theHeight));
      default_y      = (theHeight - default_height) / 2;
    }

    /* End of "centering" calculations */
#else
    if( theDisplay == (Display *) 0 )
	if( ( theDisplay = XOpenDisplay(NULL) ) == (Display *) 0  ) {
	  (void) fprintf(stderr, "Could not open DISPLAY \"%s\"\n", getenv("DISPLAY"));
	  exit(1);
	}

#endif



#if defined(X11)
    if( default_width == 0 && default_height == 0 )
	w = XDefaultRootWindow(theDisplay);
    else
	if ((w = XCreateSimpleWindow(theDisplay, XDefaultRootWindow(theDisplay),
				 default_x, default_y,
				 (unsigned) default_width, (unsigned) default_height, 1,
				 theForeground, theBackground)) != (Window) 0) {
/*
         XSizeHints hints ;

	hints.flags = PPosition | PSize ;

	hints.x = default_x ;
	hints.y = default_y ;
	hints.width  = default_width ;
	hints.height = default_height ;	
	XSetStrandardProperties( theDisplay, w, name, name, None, name, 1, &hints ) ;
*/
	XStoreName(theDisplay, w, name);
	XMapRaised(theDisplay, w);
	XFlush(    theDisplay);
	}
#else
    if( default_width == 0 && default_height == 0 )
	w = RootWindow ;
    else
	if( ( w = XCreateWindow( RootWindow, abs( default_x ), abs( default_y ),
				      default_width, default_height, 0, WhitePixmap,
				      BlackPixmap ) ) != ( Window ) 0 ) {
	    XStoreName( w, name ) ;
	    XMapWindow( w ) ;
	    XFlush() ;
	}
#endif
	else {
		(void) fprintf( stderr,
			  "Could not create window of size %dx%d at position %d,%d\n",
			   default_width, default_height, default_x, default_y ) ;
	}

    info = (XWindowObject) newWindowWindow(w, default_x, default_y, default_width, default_height, pixels);
#if defined(X11)
    info->isMapped = 0 ;
#endif
    info->entries->clear(info);

    return((WindowObject)info);

}

#ifndef SLAVE
WindowObject newDisplayWindow( name, default_x, default_y, default_width, default_height, pixels )
char *name ;
int default_x, default_y, default_width, default_height ;
int pixels ;
{
    return ( newXWindow( name, default_x, default_y, default_width, default_height, pixels ) ) ;
}
#endif