Mercurial > hg > aim92
diff 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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/glib/X.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,1459 @@ + +/* + 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