#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	X
#	X.d
#	X.c
# This archive created: Fri Sep 15 09:42:47 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(951 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X
X		An X Version 11 Graphics Driver for S
X
XINCLUDED FILES
X
XX.c     C code implementing an S graphics driver for the X Window System.
X	It makes direct calls to Xlib.
X
XX	A S function which provides the interface to the C code in X.c
X
XX.d	Documentation for the driver.
X
X
XINSTALLATION
X
XThis description applies to X11r3 on Sun 3 workstations running SunOS
X3.3 (yeah I know, but memory is expensive).  You may have to change
Xthis on other systems.
X
XThis device driver must be statically loaded.  To create a private
Xversion of S which includes this driver, unbundle these files and
Xthen try something like (substitute your own SHOME)
X
X	# use cp on SysV
X	ln -s /usr/dolphin/s/src/qpe/device.h device.h
X	ln -s /usr/dolphin/s/src/qpe/structure.h structure.h
X	S LOAD X.c -lX
X	S
X	X <- source("X")
X	X()
X
XTo install a system wide copy of this driver follow the pattern for
Xother drivers in the $SHOME/src/qpe directory.
X	
XEnjoy,
X	Ross Ihaka
X	ihaka@dolphin.mit.edu
SHAR_EOF
if test 951 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 951 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'X'" '(323 characters)'
if test -f 'X'
then
	echo shar: will not over-write existing file "'X'"
else
sed 's/^X//' << \SHAR_EOF > 'X'
Xfunction( width = 7, height = 7, ask = F,
X	  display = "",
X	  font = "9x15", xbias = -1, ybias = 3 )
X{
X	graphics.off()
X	z <- .C("X_Graphics",
X		as.single(width),
X		as.single(height),
X		as.logical(ask),
X		as.character(display),
X		as.character(font),
X		as.integer(xbias),
X		as.integer(ybias))
X	Device.Default("X_Graphics")
X}
SHAR_EOF
if test 323 -ne "`wc -c < 'X'`"
then
	echo shar: error transmitting "'X'" '(should have been 323 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'X.d'" '(1889 characters)'
if test -f 'X.d'
then
	echo shar: will not over-write existing file "'X.d'"
else
sed 's/^X//' << \SHAR_EOF > 'X.d'
X.BG
X.FN X
X.TL
XX: Graphics Device Driver for the X Window System
X.CS
XX(width,height,ask,display,font,xbias,ybias)
X.PP
X.AG width
X.AG height
Xreal, the dimensions (in inches) of the window to be opened for S graphics.
X.AG ask
Xlogical, should device driver ask before clearing 
Xgraphic display for a new figure?
XDefault TRUE.
X.AG display
Xcharacter, the name of the display the graphics window is to be opened on.
XThe default is to use the value of the DISPLAY environment item.
X.AG font
Xcharacter, the name of the font to be used in the graphs.
XThe default is 9x15.
X.AG xbias
X.AG ybias
XMany of the X fonts place the asterisk high
Xin comparison with other characters.
XThese parameters allow the specification of biases (in pixels)
Xto ensure that the asterisk is exactly centered on the right
Xpoint.
XFor example, the correct offsets for the `helvR14' font are
Xxbias=1 and ybias=7.  A little experimentation
Xusually yields the right values.
X.SH COMMENTS
XThe function `X' is the device driver for bitmapped displays
Xrunning under Version 11 of the X Window System.
XWhen the driver starts users must position and size a
Xwindow for the graphics to appear in.
XThe default window is placed in the upper right of the display.
XThe graphics window can be resized in the usual X fashion.
X.PP
XIf `ask' is TRUE,
Xthen whenever a new plot is about to be produced the message "GO?" appears.
XThis allows further viewing,
Xbefore the graphics screen is erased.  When ready
Xto proceed, simply hit carriage return.
X.PP
XFor graphic input, position the cursor with your pointing device push the left button.
XPressing the middle button terminates graphic input.
X.PP
XThe X driver allows a color specification in graphical functions.
XThis has no effect on line drawing, but will cause areas to
Xbe shaded (in barplots for example).
X.PP
XA device must be specified before any graphics functions can be used.
X.KW device*
X.WR
SHAR_EOF
if test 1889 -ne "`wc -c < 'X.d'`"
then
	echo shar: error transmitting "'X.d'" '(should have been 1889 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'X.c'" '(20082 characters)'
if test -f 'X.c'
then
	echo shar: will not over-write existing file "'X.c'"
else
sed 's/^X//' << \SHAR_EOF > 'X.c'
X/*
X *	X Version 11 - S Graphics Device Driver
X *
X *	Copyright 1988, 1989 by The Massachusetts Institute of Technology
X *
X *	Permission to use, copy, modify, and distribute this software
X *	and its documentation for any purpose and without fee is hereby
X *	granted, provided that the above copyright notice appear in all
X *	copies and that both that copyright notice and this permission
X *	notice appear in supporting documentation, and that the name of
X *	M.I.T. not be used in advertising or publicity pertaining to
X *	distribution of the software without specific, written prior
X *	permission.  M.I.T. makes no representations about the
X *	suitability of this software for any purpose.  It is provided
X *	"as is" without express or implied warranty.
X *
X */
X
X	/* Drawing multiple lines kills the R3 Sun server */
X	/* Your mileage may vary */
X
X#define BRAIN_DEAD_SERVER
X
X#include <X11/X.h>
X#include <X11/Xlib.h>
X#include <X11/Xatom.h>
X#include <X11/cursorfont.h>
X#include <stdio.h>
X#include <math.h>
X
X#undef Complex
X#include "cdefs.h"
X#include "structure.h"
X#include "device.h"
X
X#define Bitmap_width 16
X#define Bitmap_height 16
X
Xtypedef char Shade16[32];
XShade16 Shades[] = {
X	/* White */
X	{
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
X	},
X
X	/* Black */
X	{
X	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
X	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
X	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
X	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
X	},
X
X	/* Diag2 */
X	{
X	0xEE, 0xEE, 0x55, 0x55, 0xBB, 0xBB, 0x55, 0x55,
X	0xEE, 0xEE, 0x55, 0x55, 0xBB, 0xBB, 0x55, 0x55,
X	0xEE, 0xEE, 0x55, 0x55, 0xBB, 0xBB, 0x55, 0x55,
X	0xEE, 0xEE, 0x55, 0x55, 0xBB, 0xBB, 0x55, 0x55,
X	},
X
X	/* DarkGrey */
X	{
X	0xEE, 0xEE, 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xFF,
X	0xEE, 0xEE, 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xFF,
X	0xEE, 0xEE, 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xFF,
X	0xEE, 0xEE, 0xFF, 0xFF, 0xBB, 0xBB, 0xFF, 0xFF
X	},
X
X	/* Grey */
X	{
X	0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
X	0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
X	0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
X	0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
X	},
X
X	/* 2 Pixel Checkerboard */
X	{
X	0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
X	0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
X	0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
X	0xCC, 0xCC, 0xCC, 0xCC, 0x33, 0x33, 0x33, 0x33,
X	},
X
X	/* Diag1 */
X	{
X	0x11, 0x11, 0xAA, 0xAA, 0x44, 0x44, 0xAA, 0xAA,
X	0x11, 0x11, 0xAA, 0xAA, 0x44, 0x44, 0xAA, 0xAA,
X	0x11, 0x11, 0xAA, 0xAA, 0x44, 0x44, 0xAA, 0xAA,
X	0x11, 0x11, 0xAA, 0xAA, 0x44, 0x44, 0xAA, 0xAA,
X	},
X
X	/* LightGrey */
X	{
X	0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
X	0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
X	0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
X	0x11, 0x11, 0x44, 0x44, 0x11, 0x11, 0x44, 0x44,
X	},
X
X	/* VeryLightGrey */
X	{
X	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
X	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
X	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
X	0x11, 0x11, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
X	},
X	
X	/* X Background Inverted */
X	{
X	0x11, 0x11, 0x22, 0x22, 0x88, 0x88, 0x44, 0x44,
X	0x11, 0x11, 0x22, 0x22, 0x88, 0x88, 0x44, 0x44,
X	0x11, 0x11, 0x22, 0x22, 0x88, 0x88, 0x44, 0x44,
X	0x11, 0x11, 0x22, 0x22, 0x88, 0x88, 0x44, 0x44,
X	},
X	
X	/* X Background */
X	{
X	0xee, 0xee, 0xdd, 0xdd, 0x77, 0x77, 0xbb, 0xbb,
X	0xee, 0xee, 0xdd, 0xdd, 0x77, 0x77, 0xbb, 0xbb,
X	0xee, 0xee, 0xdd, 0xdd, 0x77, 0x77, 0xbb, 0xbb,
X	0xee, 0xee, 0xdd, 0xdd, 0x77, 0x77, 0xbb, 0xbb,
X	},
X};
X
X#define NSHADES sizeof(Shades)/sizeof(Shade16)
XPixmap ShadePixmap[NSHADES];
X
Xstatic int		window_width;
Xstatic int		window_height;
Xstatic int		ask;
Xstatic char*		display_name;
Xstatic char*		font_name;
Xstatic int		star_xbias;
Xstatic int		star_ybias;
Xstatic int		resize = 0;
X
Xstatic Display*		display = NULL;	/* Display */
Xstatic int		screen;		/* Screen */
Xstatic int		depth;		/* Pixmap depth */
Xstatic Window		root_window;	/* Root Window */
Xstatic Window		window;		/* Current Graphics Window */
Xstatic Window*		window_list;	/* Graphics Window List */
Xstatic Cursor		gcursor;	/* Graphics Cursor */
Xstatic GC		gc_erase;	/* for Rotated Text */
Xstatic GC		gc_text;	/* for drawing Text */
Xstatic GC		gc_lines;	/* for drawing lines */
Xstatic GC		gc_solid;	/* for drawing lines */
Xstatic GC		gc_fill;	/* for area fills */
Xstatic GC		gc_dashes;	/* for drawing lines */
Xstatic XEvent		event;		/* Event */
Xstatic Font		font_id;	/* Font */
Xstatic XFontStruct*	font_str;	/* Font info */
Xstatic int		blackpixel;	/* Black */
Xstatic int		whitepixel;	/* White */
X 
X#define am(i)		F77_COM(bgrp)[(i)-1]
X#define UxR(i)		((i)*am(37)+am(36)+0.5)
X#define UyR(i)		(window_height-((i)*am(39)+am(38)+0.5))
X
Xlong			F77_COM(reshap);
Xextern float		F77_COM(bgrp)[];
Xchar*			malloc();
Xvector*			X_Graphics();
X
X
X		/* S Entry Points */
X
Xstatic vector	*wrap(),
X		*flush(),
X		*signalled(),
X		*points(),
X		*lines(),
X		*polygon(),
X		*text(),
X		*segments(),
X		*clear(),
X		*readpen();
X
X		/* Internally Used Functions */
X
Xstatic		event_handler(),
X		font_orientation(),
X		init_display(),
X		init_graphics(),
X		init_text(),
X		init_window(),
X		rotchar(),
X		set_clip_region(),
X		set_line_style();
X
Xstatic double	pixelHeight(),
X		pixelWidth();
X
Xstatic device d_X = {
X	FALSE, 0, NULL, 0, NULL,
X	{
X	X_Graphics, wrap, flush, signalled, points, lines,
X	polygon, text, segments, clear, readpen, NULL,
X	NULL, NULL, NULL, NULL, NULL, NULL
X	}
X};
X
X
Xvector *X_Graphics(width,height,pask,pdisplay_name,pfont_name,pstar_xbias,pstar_ybias)
Xfloat*	width;
Xfloat*	height;
Xlong*	pask;
Xchar**	pdisplay_name;
Xchar**	pfont_name;
Xlong*	pstar_xbias;
Xlong*	pstar_ybias;
X{
X	device *d, *new_device();
X	double pixelWidth();
X	double pixelHeight();
X	int i;
X
X	ask = *pask;
X	display_name = *pdisplay_name;
X	font_name = *pfont_name;
X	star_xbias = *pstar_xbias;
X	star_ybias = *pstar_ybias;
X
X	d = new_device(&d_X,0L);
X	set_device(d->which);
X
X	init_display();
X	init_text();
X	init_graphics();
X
X	window_width = *width/pixelWidth();
X	window_height = *height/pixelHeight();
X
X	init_window();
X
X	for( i=0 ; i<40 ; i++ ) am(i) = 0.0;
X
X		/* nominal character extents */
X
X	am(20) = font_str->max_bounds.width;
X	am(21) = font_str->max_bounds.ascent+font_str->max_bounds.descent;
X
X		/* display extents */
X
X	am(22) = 0.0;
X	am(23) = window_width;
X	am(24) = 0.0;
X	am(25) = window_height;
X
X		/* character addressing offsets */
X
X	am(26) = 0.0;
X	am(27) = 0.5;
X
X		/* raster size in inches */
X
X	am(28) = pixelWidth();
X	am(29) = pixelHeight();
X
X		/* device ID */
X
X	am(30) = -1954;
X	am(1) = 0.0;		/* fixed size characters */
X	am(31) = 1.0;		/* allow character rotation */
X
X	F77_SUB(defltz)();
X
X	return S_void;
X}
X
X
Xstatic init_display()
X{
X		/* open the default display */
X
X	if( strlen(display_name) )
X		display=XOpenDisplay(display_name);
X	else 
X		display=XOpenDisplay(NULL);
X
X	if(display==NULL)
X		Recover("Couldn't open X display",S_void);
X
X		/* Default Screen and Root Window */
X
X	screen = XDefaultScreen(display);
X	/*
X	if( XDoesBackingStore(screen)==NotUseful ) {
X		fprintf(stderr,"Warning: window contents will not be maintained by the X server\n");
X		fflush(stderr);
X	}
X	*/
X	depth = XDefaultDepth(display,screen);
X	root_window = XDefaultRootWindow(display);
X
X		/* Get black and white pixel values */
X
X	blackpixel = BlackPixel(display,screen);
X	whitepixel = WhitePixel(display,screen);
X}
X
X
Xstatic init_window()
X{
X	XWindowAttributes	getattr;
X	XSetWindowAttributes	attributes;
X
X		/* Try to create a simple window */
X		/* Want to know about exposures */
X		/* and window-resizes and locations */
X
X	attributes.background_pixel = whitepixel;
X	attributes.border_pixel = blackpixel;
X	attributes.backing_store = Always;
X	attributes.event_mask = ButtonPressMask
X			      | ExposureMask
X			      | StructureNotifyMask;
X
X	if((window = XCreateWindow( display, root_window,
X		DisplayWidth(display,screen)-window_width-10,		/* window coordinates */
X		10,
X		window_width, window_height, 1,
X		DefaultDepth(display,screen), InputOutput,
X		DefaultVisual(display,screen),
X		CWEventMask | CWBackPixel | CWBorderPixel | CWBackingStore,
X		&attributes ))==0)
X			Recover("couldn't create graphics window",S_void);
X
X	gcursor = XCreateFontCursor(display,XC_crosshair);
X	XChangeProperty( display, window,
X		XA_WM_NAME, XA_STRING, 8, PropModeReplace, "S Graphics", 10);
X
X	XDefineCursor(display,window,gcursor);
X
X	XSelectInput( display, window,
X		ExposureMask|ButtonPressMask|StructureNotifyMask);
X
X		/* Map the window */
X
X	XMapWindow(display, window);
X	XNextEvent(display,&event);
X	while( event.type != ConfigureNotify )
X		XNextEvent(display,&event);
X	window_width = event.xconfigure.width;
X	window_height = event.xconfigure.height;
X}
X
X
X	/* Structures used in character rotation */
X
Xstatic Pixmap c_pixmap;
Xstatic XImage *c_image;
Xstatic XPoint *c_points;
Xstatic int c_width = 32;
Xstatic int c_height = 32;
X
X
Xstatic init_text()
X{
X	if( !(font_str=XLoadQueryFont(display,font_name)) )
X		Recover("couldn't load graphics font",S_void);
X	font_id = font_str->fid;
X
X	gc_text= XCreateGC(display,root_window,0,NULL);
X	XSetState(display,gc_text,blackpixel,whitepixel,GXcopy,AllPlanes);
X	XSetFont(display,gc_text,font_id);
X
X	c_pixmap = XCreatePixmap(display,root_window,c_width,c_height,depth);
X	c_points = (XPoint*)malloc((unsigned)(c_width*c_height*sizeof(XPoint)));
X	gc_erase = XCreateGC(display,root_window,0,NULL);
X	XSetState(display,gc_erase,whitepixel,whitepixel,GXcopy,AllPlanes);
X}
X
X
Xstatic int dash_mode;
X
Xstatic unsigned char
X	short_dash[] = { 4, 4 },
X	dotted[]     = { 1, 3 },
X	dot_dash[]   = { 4, 3, 1, 3 },
X	long_dash[]  = { 7, 4};
X
X
Xstatic init_graphics()
X{
X	int i;
X
X	gc_solid = XCreateGC( display, root_window, 0, NULL);
X	XSetState( display, gc_solid, blackpixel, whitepixel, GXcopy, AllPlanes);
X	gc_lines = gc_solid;
X
X	gc_dashes = XCreateGC( display, root_window, 0, NULL);
X	XSetState( display, gc_dashes, blackpixel, whitepixel, GXcopy, AllPlanes);
X	XSetLineAttributes(display, gc_dashes, 0, LineOnOffDash, CapButt, JoinMiter);
X	XSetDashes( display, gc_dashes, 0, short_dash, 2 );
X	dash_mode = 2;
X
X	gc_fill = XCreateGC( display, root_window, 0, NULL );
X	XSetState( display, gc_fill, blackpixel, whitepixel, GXcopy, AllPlanes);
X
X	for( i=0 ; i<NSHADES ; i++ )
X		ShadePixmap[i] = XCreateBitmapFromData(display,root_window,
X					Shades[i],Bitmap_width,Bitmap_height);
X	XSetFillStyle(display,gc_fill,FillStippled);
X}
X
X
Xint olty = 1; /* solid */
X
Xstatic set_line_style()
X{
X	int lty = am(8);
X
X	if( lty != olty ) {
X		switch( lty ) {
X			case 1:
X				gc_lines = gc_solid;
X				break;
X			case 2:
X				XSetDashes( display, gc_dashes, 0, dotted, 2 );
X				gc_lines = gc_dashes;
X				break;
X			case 3:
X				XSetDashes( display, gc_dashes, 0, long_dash, 2 );
X				gc_lines = gc_dashes;
X				break;
X			case 4:
X				XSetDashes( display, gc_dashes, 0, short_dash, 2 );
X				gc_lines = gc_dashes;
X				break;
X			case 5:
X				XSetDashes( display, gc_dashes, 0, dot_dash, 4 );
X				gc_lines = gc_dashes;
X				break;
X		}
X		olty = lty;
X	}
X}
X
X
Xstatic vector *points(x,y,n)
Xfloat *x, *y;
Xlong *n;
X{
X	XCharStruct inf;
X	int dret, asc, desc;
X	int i, ix, iy, ixoffset, iyoffset;
X	long lch;
X	char ch;
X
X	lch = ch = am(15);
X	if( lch<32 ) {
X		F77_SUB(dmarkz)(x,y,n,&lch);
X	}
X	else {
X		XQueryTextExtents(display,font_id,&ch,1,&dret,&asc,&desc,&inf);
X		ixoffset = -0.5*inf.width;
X		iyoffset =  0.5*(inf.ascent+inf.descent);
X		if( ch=='*' ) {
X			iyoffset += star_ybias;
X			ixoffset += star_xbias;
X		}
X		for( i=0 ; i<*n ; i++ ) {
X			ix = UxR(x[i])+ixoffset;
X			iy = UyR(y[i])+iyoffset;
X			XDrawString(display,window,gc_text,ix,iy,&ch,1);
X		}
X	}
X	XSync(display,0);
X	return S_void;
X}
X
X
Xstatic vector *lines(x,y,pn)
Xfloat *x, *y;
Xlong *pn;
X{
X	int i, n = *pn;
X#ifdef BRAIN_DEAD_SERVER
X	int ix0, ix1, iy0, iy1;
X
X	set_line_style();
X	set_clip_region();
X	for( i=1 ; i<n ; i++ ) {
X		ix0 = UxR(x[i-1]);
X		iy0 = UyR(y[i-1]);
X		ix1 = UxR(x[i]);
X		iy1 = UyR(y[i]);
X		XDrawLine(display,window,gc_lines,ix0,iy0,ix1,iy1);
X	}
X#else
X	XPoint *points;
X
X	set_line_style();
X	set_clip_region();
X	points = (XPoint *)malloc((unsigned)(n*sizeof(XPoint)));
X	for( i=0 ; i<n ; i++ ) {
X		points[i].x = UxR(x[i]);
X		points[i].y = UyR(y[i]);
X	}
X	XDrawLines(display,window,gc_lines,points,n,CoordModeOrigin);
X	free((char*)points);
X#endif
X	XSync(display,0);
X	return S_void;
X}
X
X
Xstatic set_clip_region()
X{
X	XRectangle cliprect;
X
X	if( am(65)>0.5 ) {
X		cliprect.x = 0;
X		cliprect.width = window_width;
X		cliprect.y = 0;
X		cliprect.height = window_height;
X	}
X	else {
X		cliprect.x = UxR(am(61));
X		cliprect.width = UxR(am(62))-cliprect.x+1.0;
X		cliprect.y = UyR(am(64));
X		cliprect.height = UyR(am(63))-cliprect.y+1.0;
X	}
X	XSetClipRectangles(display,gc_lines,0,0,&cliprect,1,Unsorted);
X}
X
X
Xstatic vector *segments(x0,y0,x1,y1,pn)
Xfloat *x0, *y0, *x1, *y1;
Xlong *pn;
X{
X	int ix0, ix1, iy0, iy1;
X	int i, n = *pn;
X
X	set_line_style();
X	set_clip_region();
X	for( i=0 ; i<n ; i++ ) {
X		ix0 = UxR(x0[i]);
X		iy0 = UyR(y0[i]);
X		ix1 = UxR(x1[i]);
X		iy1 = UyR(y1[i]);
X		XDrawLine(display,window,gc_lines,ix0,iy0,ix1,iy1);
X	}
X	XSync(display,0);
X	return S_void;
X}
X
X
Xint tile = -1;
X
X
Xstatic vector *polygon(x,y,pn)
Xfloat *x, *y;
Xlong *pn;
X{
X	XPoint *points;
X	int i;
X	int n = *pn;
X	int col = am(10);
X
X	if( n<=1 )
X		return S_void;
X
X	points = (XPoint *)malloc((unsigned)(n*sizeof(XPoint)));
X	for( i=0 ; i<n ; i++ ) {
X		points[i].x = UxR(x[i]);
X		points[i].y = UyR(y[i]);
X	}
X
X	if( col>=0 && col<NSHADES ) {
X		if( tile!=col )
X			XSetStipple(display,gc_fill,ShadePixmap[col]);
X		XFillPolygon(display,window,gc_fill,points,n,Nonconvex,CoordModeOrigin);
X	}
X
X	free((char*)points);
X	XSync(display,0);
X
X
X	return S_void;
X}
X
X
Xstatic vector *clear()
X{
X	long x0, x1, y0, y1;
X	extern zzdevz_();
X
X	if( ask ) {
X		(void)fprintf(stderr,"GO? ");
X		fflush(stderr);
X		while( getchar()!='\n' );
X	}
X	XClearWindow(display,window);
X	/* or init_window(); */
X	event_handler();
X	if( resize ) {
X		am(22) = x0 = 0;
X		am(23) = x1 = window_width;
X		am(24) = y0 = 0;
X		am(25) = y1 = window_height;
X		F77_COM(reshap) = 1;
X		zzdevz_(&x0,&x1,&y0,&y1);
X		resize = 0;
X	}
X	XSync(display,0);
X	return S_void;
X}
X
X
Xstatic vector *wrap()
X{
X	int i;
X
X	free(c_points);
X	XFreeCursor(display,gcursor);
X	XFreeFont(display,font_str);
X	XFreeGC(display,gc_text);
X	XFreeGC(display,gc_erase);
X	XFreeGC(display,gc_solid);
X	XFreeGC(display,gc_dashes);
X	XFreeGC(display,gc_fill);
X	XFreePixmap(display,c_pixmap);
X	for( i=0 ; i<NSHADES ; i++ )
X		XFreePixmap(display,ShadePixmap[i]);
X	XDestroyWindow(display,window);
X	XCloseDisplay(display);
X	return S_void;
X}
X
X
Xstatic vector *flush()
X{
X	return S_void;
X}
X
X
Xstatic vector *signalled()
X{
X	return S_void;
X}
X
X
X#define MM_PER_INCH 25.4
X
X
Xstatic double pixelWidth()
X{
X	double width, widthMM;
X	width = DisplayWidth(display,screen);
X	widthMM = DisplayWidthMM(display,screen);
X	return (widthMM/width)/MM_PER_INCH;
X}
X
Xstatic double pixelHeight()
X{
X	double height, heightMM;
X	height = DisplayHeight(display,screen);
X	heightMM = DisplayHeightMM(display,screen);
X	return (heightMM/height)/MM_PER_INCH;
X}
X
X
Xstatic event_handler()
X{
X	while( XPending(display) ) {
X		XNextEvent(display,&event);
X		if( event.xany.type==Expose ) {
X			while( event.xexpose.count ) {
X				XNextEvent(display,&event);
X			}
X		}
X		else if( event.type==ConfigureNotify ) {
X			window_width = event.xconfigure.width;
X			window_height = event.xconfigure.height;
X			resize = 1;
X		}
X	}
X}
X
X/*
X *    o	Ideal String Placement
X * 
X *	String origins are taken to be at the lower left corner.  If
X *	the string extents are (len,hgt) the rotated string is offset
X *	by:
X *
X *		-adj * ( len, hgt ) * (  cos_rot  sin_rot )
X *				      ( -sin_rot  cos_rot )
X *
X *	before drawing (the reversal of sign on the y-axis must be
X *	dealt with separately).
X *
X *
X *    o	Practical Difficulty
X *
X *	Because characters cannot be rotated arbitrarily the the above
X *	description doesn't quite work.  For example consider "rot" in
X *	the quadrant [-45,45].  To avoid characters getting squished
X *	together as rotation occurs we have to arrange that the width
X *	of the string projected on the x-axis is constant.  This means
X *	that the top right coordinate of the rotated string (before
X *	adjustment) is in fact at
X *		( len,  len * tan(rot) + hgt )
X *	Thus when we adjust the string, we offset the origin by an
X *	amount
X *		adj * ( len,  len * tan(rot) + hgt )
X *	A similar kludge must be applied in the other quadrants.
X *	I agree, its as clear as mud, but its the right thing to do.
X */
X
X
X#define DEG_TO_RAD	0.01745329251994329576		/* 2 Pi / 360 */
X#define TANDEG(x)	tan((x)*DEG_TO_RAD)
X
Xstatic vector *text(x,y,str,pl,padj)
Xfloat *x, *y, *padj;
Xchar *str;
Xlong *pl;
X{
X	int i, orientation, l, len, hgt;
X	double t, rot;
X	int xloc, yloc;
X	double adj = *padj;
X
X	rot = am(48);
X	orientation = font_orientation(rot);
X	l = *pl;
X	xloc = UxR(*x);
X	yloc = UyR(*y);
X	len = XTextWidth(font_str,str,l);
X	hgt = font_str->max_bounds.ascent;
X
X	switch( orientation ) {
X		case 0:
X			xloc -= adj*len;
X			yloc += adj*(len*TANDEG(rot)+hgt);
X			break;
X		case 1:
X			xloc += adj*(len*TANDEG(rot-90.0)+hgt);
X			yloc += adj*len;
X			break;
X		case 2:
X			xloc += adj*len;
X			yloc -= adj*(len*TANDEG(rot-180.0)+hgt);
X			break;
X		case 3:
X			xloc -= adj*(len*TANDEG(rot-270.0)+hgt);
X			yloc -= adj*len;
X			break;
X	}
X
X	for( i=0 ; i<l ; i++ ) {
X		rotchar(str[i],xloc,yloc,orientation);
X		t = XTextWidth(font_str,&str[i],1);
X		switch( orientation ) {
X			case 0:
X				xloc += t;
X				yloc -= t*TANDEG(rot);
X				break;
X			case 1:
X				xloc -= t*TANDEG(rot-90.0);
X				yloc -= t;
X				break;
X			case 2:
X				xloc -= t;
X				yloc += t*TANDEG(rot-180.0);
X				break;
X			case 3:
X				xloc += t*TANDEG(rot-270.0);
X				yloc += t;
X				break;
X		}
X	}
X	XSync(display,0);
X	return S_void;
X}
X
X
Xstatic font_orientation( angle )
Xdouble angle;
X{
X	while( angle<0.0 ) angle += 360.0;
X	while( angle>360.0 ) angle -= 360.0;
X
X	/* bias toward horizontal is deliberate */
X
X	if(  45.0<angle && angle<135.0 )
X		return 1;
X	if( 135.0<=angle && angle<=225.0 )
X		return 2;
X	if( 225.0<angle && angle<315.0 )
X		return 3;
X	return 0;
X}
X
X
X	/* Draw a rotated character - idea lifted from xlispstat */
X	/* Write the character into a pixmap in the server */
X	/* Transfer the bits to the client using XGetImage */
X	/* Record the rotated coordinates of the black pixels */
X	/* Draw these coordinates using XDrawPoints */
X	/* God help network administrators when X gets loose */
X
Xstatic rotchar(ch, x, y, orientation)
Xchar ch;
Xint x, y;
Xint orientation;
X{
X	int i, j, n;
X	int ascent = font_str->max_bounds.ascent;
X	int width = font_str->max_bounds.width;
X	int height = font_str->max_bounds.ascent + font_str->max_bounds.descent;
X
X	if( orientation ) {
X		XFillRectangle( display, c_pixmap, gc_erase, 0, 0, width, height);
X		XDrawString( display, c_pixmap, gc_text, 0, ascent, &ch, 1);
X		c_image = XGetImage( display, c_pixmap, 0, 0, width, height,
X			AllPlanes, ZPixmap);
X		switch( orientation ) {
X		case 1:
X			for(i = 0, n = 0; i < width; i++)
X				for(j = 0; j < height; j++)
X					if(blackpixel==XGetPixel(c_image,i,j)) {
X						c_points[n].x = x - ascent + j;
X						c_points[n].y = y - i;
X						n++;
X					}
X			break;
X		case 2:
X			for(i = 0, n = 0; i < width; i++)
X				for(j = 0; j < height; j++)
X					if(blackpixel==XGetPixel(c_image,i,j)) {
X						c_points[n].x = x - i;
X						c_points[n].y = y + ascent - j;
X						n++;
X					}
X			break;
X		case 3:
X			for(i = 0, n = 0; i < width; i++)
X				for(j = 0; j < height; j++)
X					if(blackpixel==XGetPixel(c_image,i,j)) {
X						c_points[n].x = x + ascent - j;
X						c_points[n].y = y + i;
X						n++;
X					}
X			break;
X		}
X		XDrawPoints(display,window,gc_text,c_points,n,CoordModeOrigin);
X		XDestroyImage(c_image);
X	}
X	else
X		XDrawString(display,window,gc_text,x,y,&ch,1);
X}
X
X
Xstatic vector *readpen(x,y,n,nxy)
Xfloat *x, *y;
Xlong *n, *nxy;
X{
X	int i;
X
X	event_handler();
X	XSync(display,1);
X
X	for( i=0 ; i<*nxy ; i++ ) {
X		XNextEvent(display,&event);
X		if( event.xbutton.button==Button1 ) {
X			x[i] = (event.xbutton.x-am(36))/am(37);
X			y[i] = (window_height-event.xbutton.y-am(38))/am(39);
X			(void)fprintf(stderr,"\07");
X			(void)fflush(stderr);
X		}
X		else
X			break;
X	}
X	*n = i;
X	XSync(display,0);
X	return S_void;
X}
SHAR_EOF
if test 20082 -ne "`wc -c < 'X.c'`"
then
	echo shar: error transmitting "'X.c'" '(should have been 20082 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0
