home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
t
/
turtlegr.zip
/
scm
/
turtlegr.c
< prev
Wrap
C/C++ Source or Header
|
1992-10-27
|
42KB
|
1,303 lines
/* file turtlegr.c *
* Copyright (C) 1992 sjm@ee.tut.fi *
* jtl@cc.tut.fi *
* *
* Turtlegraphics primitives for the *
* SCM interpreter by Aubrey Jaffer *
* *
* Last modification: 13.10.1992 *
* *
* Versions: *
* 12.3.1992 The first version. *
* 13.3.1992 Added the possibility to pass *
* floating point args. *
* 15.3.1992 Graphics cards other than EGA *
* are now supported. *
* 9.4.1992 The internal representation *
* of X & Y is now float. *
* 13.10.1992 Added X11 support. *
* A major rewrite of certain *
* parts. *
* Put -DX11 -DFLOATS to CFLAGS *
* in Makefile to get it. *
* *
* REMEMBER to define INITS=init_turtlegr() *
* in the Makefile. *
* */
/* *
* This code tries to compromise between two very different *
* systems: MSDOS and UNIX with the X11 windowing system. *
* The MSDOS version was build first and it really shows. :) *
* The X port is a partial rewrite of the old MSDOS stuff *
* and plays around with #ifdef's a lot. The result is, *
* eventually, a C source which is expected to compile *
* under both MSDOS and UNIX (X11). *
* The X code handles colors emulating CGA palette. It tries *
* to act sensibly even on a monochrome screen and when the *
* color palette is full. *
* X event handling is implemented with polling whenever *
* appropriate. This is not The Right Way to do it in X, but *
* it was easiest to adopt in this case. *
* Another solution would have been to make the X graphics *
* a separate process, but I didn't want to because I wanted *
* to keep it simple. I can't tell how good an example of porting *
* MSDOS software to X this is, but it works. *
* *
* This has been tested with SunOs 4.1.2 with X11R5, Linux 0.98.1 *
* with Xfree86 1.1 (X11R5 port) and in MSDOS with BC 3.1. *
* Because the code uses only the basic Xlib calls, it should *
* compile without problems under _any_ UNIX with X11R4 or newer. *
* *
* Please send bugreports to sjm@ee.tut.fi. *
* I'm especially interested in hearing about ports to other *
* platforms than those tested by me. *
* *
* - sjm *
* */
/****************************************************/
/***** GENERIC includes & defines *****/
/****************************************************/
#include "scm.h" /* includes config.h as well */
#include "patchlvl.h" /* Guess... */
#include <math.h> /* sin(), cos(), fmod() */
#include <stdlib.h> /* atexit() */
/****************************************************/
/***** X11 specific includes & defines *****/
/****************************************************/
#ifdef X11
/* Xlib include files */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include "turtle"
#define BITMAPDEPTH 1
#define PROGNAME "scm"
#define CLASSNAME "Scm"
#define WINDOWNAME "TurtleSCM graphics window"
#define ICONNAME "TurtleSCM"
#define GR_MAX_XSIZE 1024
#define GR_MAX_YSIZE 1024
#define GR_DEF_XSIZE 640
#define GR_DEF_YSIZE 480
#define GR_MIN_XSIZE 64
#define GR_MIN_YSIZE 64
/* Fake CGA colormap with X - yuk! */
#define GR_COLORS 16 /* CGA/EGA counterpart */
#define GR_COLOR00 "black" /* black */
#define GR_COLOR01 "blue2" /* blue */
#define GR_COLOR02 "green2" /* green */
#define GR_COLOR03 "cyan2" /* cyan */
#define GR_COLOR04 "red3" /* red */
#define GR_COLOR05 "magenta2" /* magenta */
#define GR_COLOR06 "yellow2" /* brown */
#define GR_COLOR07 "light gray" /* white */
#define GR_COLOR08 "gray" /* gray */
#define GR_COLOR09 "blue1" /* light blue */
#define GR_COLOR10 "green1" /* light green */
#define GR_COLOR11 "cyan1" /* light cyan */
#define GR_COLOR12 "red1" /* light red */
#define GR_COLOR13 "magenta1" /* light magenta */
#define GR_COLOR14 "yellow1" /* yellow */
#define GR_COLOR15 "white" /* bright white */
#ifdef __STDC__
static void gr_events( int );
#else
static void gr_events();
#endif
#else
/****************************************************/
/***** PC specific includes & defines *****/
/****************************************************/
#include <graphics.h>
#include <stdlib.h> /* for getenv() */
#include <stdio.h> /* for fputs() */
#define BGIDIR_ENVSTRING "BGIDIR"
#endif
/********************************************/
/***** GENERIC code, declarations *****/
/********************************************/
#define SIN( x ) \
sin( ((x)/180.0) * M_PI )
#define COS( x ) \
cos( ((x)/180.0) * M_PI )
static int gr_graphicsavail = 0;
static int gr_grmode_on = 0;
static float gr_dir = 0.0;
static int gr_max_x=0, gr_max_y=0, gr_max_color=0;
static float gr_x=0.0, gr_y=0.0;
static int gr_color = 0;
static char s_gr_draw[] = "draw";
static char s_gr_move[] = "move";
static char s_gr_setcolor[] = "set-color!";
static char s_gr_turnright[] = "turn-right";
static char s_gr_turnleft[] = "turn-left";
static char s_gr_turnto[] = "turn-to!";
static char s_gr_getdot[] = "get-dot";
static char s_gr_drawTo[] = "draw-to!";
static char s_gr_drawto[] = "draw-to";
static char s_gr_moveTo[] = "move-to!";
static char s_gr_setdot[] = "set-dot!";
static char s_gr_validXYC[] = "valid-xyc?";
#ifdef __GNUC__
inline
#else
static
#endif
int valid_XYC( x, y, color )
int x, y, color;
{
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
if( (x <= gr_max_x) && (y <= gr_max_y) && (color <= gr_max_color)
&& (x >= 0) && (y >= 0) && (color >= 0) )
return( 1 );
else
return( 0 );
} /* valid_XYC() */
/********************************************************************/
/***** X11 specific variable and function declarations *****/
/********************************************************************/
#ifdef X11
static Display *gr_display; /* The X display */
static int gr_screen; /* The X screen number */
static Window gr_win; /* The drawable Window */
static GC gr_gc; /* Graphics Context */
static unsigned long gr_colortbl[GR_COLORS]; /* Color table */
static XEvent gr_event; /* Event structure */
/* These are needed for XSetWMProperties */
static char *gr_windowname = WINDOWNAME;
static char *gr_iconname = ICONNAME;
static char gr_progname[] = PROGNAME;
static char gr_classname[] = CLASSNAME;
static int gr_argc = 1;
static char *gr_argv[] = { gr_progname, NULL };
static void gr_eventhandler( event )
XEvent event;
{
switch( event.type ) {
case ConfigureNotify:
#ifdef TESTING
fputs( "Received ConfigureNotify event\n", stderr );
#endif
gr_max_x = event.xconfigure.width - 1;
gr_max_y = event.xconfigure.height - 1;
break;
case MapNotify:
#ifdef TESTING
fputs( "Received MapNotify event\n", stderr );
#endif
break;
case DestroyNotify:
#ifdef TESTING
fputs( "Received DestroyNotify event\n", stderr );
#endif
break;
case UnmapNotify:
#ifdef TESTING
fputs( "Received UnmapNotify event\n", stderr );
#endif
break;
case Expose:
#ifdef TESTING
fputs( "Received Expose event\n", stderr );
#endif
if( event.xexpose.count != 0 )
break;
break;
case ClientMessage:
#ifdef TESTING
fputs( "Received ClientMessage event\n", stderr );
#endif
break;
default:
/* Throw away any unknown events */
break;
} /* switch */
}
static void gr_events( expected )
int expected;
{
int i;
/* Get at least 'expected' events */
for( i = 0; i < expected; ++i ) {
XNextEvent( gr_display, &gr_event );
gr_eventhandler( gr_event );
}
/* Handle all remaining events if there are any */
/* XPending will call XFlush() if it doesn't find events at once */
while( XPending(gr_display) ) {
XNextEvent( gr_display, &gr_event );
gr_eventhandler( gr_event );
} /* while */
} /* gr_events() */
static void gr_typedevent( type )
int type;
{
do {
XNextEvent( gr_display, &gr_event );
gr_eventhandler( gr_event );
} while( gr_event.type != type );
/* Handle all remaining events if there are any */
/* XPending will call XFlush() if it doesn't find events at once */
while( XPending(gr_display) ) {
XNextEvent( gr_display, &gr_event );
gr_eventhandler( gr_event );
} /* while */
}
/********************************************************************/
/***** PC specific variable and function declarations *****/
/********************************************************************/
#else
static int gr_max_display_mode;
static int gr_drivernum;
#endif
/********************************************************************/
/********************************************************************/
/*** User callable SCM routines begin here ***
*** ***
*** ***/
SCM gr_helpgr()
{
fputs( "\
Ret Name nargs args returns\n\
---------------------------------------------------------\n\
B graphics-avail? 0 - #t if graphics available\n\
B graphics-mode! 0 - #f if no graphics\n\
B text-mode! 0 - #t on success\n\
B clear-graphics! 0 - #f if not in graphics mode\n\
i max-x 0 - maximum value of x\n\
i max-y 0 - maximum value of y\n\
i max-color 0 - maximum value of color\n\
B valid-xyc? 3 x y color #t if valid\n\
B set-dot! 3 x y color #t on success\n\
i get-dot 2 x y color of the dot in (x,y)\n\
or #f if (x,y) not legal\n\
\n\
NOTE: Origin (0,0) is in the upper left corner.\n\n\
", stdout );
return BOOL_T;
} /* gr_helpgr() */
SCM gr_helpturtlegr()
{
fputs( "\
Ret Name nargs args returns\n\
---------------------------------------------------------\n\
B goto-home! 0 - #f if not in graphics mode\n\
B goto-center! 0 - #f if not in graphics mode\n\
B goto-nw! 0 - #f if not in graphics mode\n\
B goto-ne! 0 - #f if not in graphics mode\n\
B goto-sw! 0 - #f if not in graphics mode\n\
B goto-se! 0 - #f if not in graphics mode\n\
B draw 1 length #t if target within drawing area\n\
B draw-to 2 x y #t if (x,y) within drawing area\n\
B draw-to! 2 x y #t if (x,y) within drawing area\n\
B move 1 length #t if target within drawing area\n\
B move-to! 2 x y #t if (x,y) within drawing area\n\
i where-x 0 - current x-coordinate\n\
i where-y 0 - current y-coordinate\n\
i turn-right 1 angle drawing direction in degrees\n\
i turn-left 1 angle drawing direction in degrees\n\
i turn-to! 1 angle drawing direction in degrees\n\
i what-direction 0 - drawing direction in degrees\n\
B set-color! 1 color #t if color valid\n\
i what-color 0 - current drawing color\n\n\
", stdout );
return BOOL_T;
} /* gr_helpturtlegr() */
SCM gr_available()
{
if( gr_graphicsavail )
return BOOL_T;
else
return BOOL_F;
} /* gr_available() */
SCM gr_maxx()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
return MAKINUM( (long)gr_max_x );
} /* gr_maxx() */
SCM gr_maxy()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
return MAKINUM( (long)gr_max_y );
} /* gr_maxy() */
SCM gr_maxc()
{
if( !gr_grmode_on )
return BOOL_F;
return MAKINUM( (long)gr_max_color );
} /* gr_maxc() */
SCM gr_validXYC( x, y, c )
SCM x, y, c;
{
int xi, yi, ci;
ASSERT( NUMBERP(x),x,ARG1,s_gr_validXYC );
ASSERT( NUMBERP(y),y,ARG2,s_gr_validXYC );
ASSERT( NUMBERP(c),c,ARG3,s_gr_validXYC );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xi = (int)(INUM(x));
else
xi = (int)(REALPART(x));
if( INUMP(y) )
yi = (int)(INUM(y));
else
yi = (int)(REALPART(y));
if( INUMP(c) )
ci = (int)(INUM(c));
else
ci = (int)(REALPART(c));
/* valid_XYC() calls gr_events() */
if( valid_XYC( xi, yi, ci ) )
return BOOL_T;
else
return BOOL_F;
} /* gr_validXYC() */
SCM gr_grmode()
{
if( !gr_graphicsavail )
return BOOL_F;
#ifdef X11
/* bwuah... but it works :) */
if( !gr_grmode_on ) {
XMapWindow( gr_display, gr_win );
gr_typedevent( MapNotify );
}
#else /* PC version */
setgraphmode( gr_max_display_mode );
#endif
gr_grmode_on = 1;
return BOOL_T;
} /* gr_grmode() */
SCM gr_txtmode()
{
if( !gr_graphicsavail )
return BOOL_F;
#ifdef X11
/* bwuah... but it works :) */
if( gr_grmode_on ) {
XUnmapWindow( gr_display, gr_win );
gr_typedevent( UnmapNotify );
}
#else /* PC version */
restorecrtmode();
#endif
gr_grmode_on = 0;
return BOOL_T;
} /* gr_txtmode() */
SCM gr_cleargraph()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
XClearWindow( gr_display, gr_win );
gr_events(0);
#else /* PC version */
cleardevice();
#endif
return BOOL_T;
} /* gr_cleargraph() */
SCM gr_setdot( x, y, c )
SCM x, y, c;
{
int xi, yi, ci;
ASSERT( NUMBERP(x),x,ARG1,s_gr_setdot );
ASSERT( NUMBERP(y),y,ARG2,s_gr_setdot );
ASSERT( NUMBERP(c),c,ARG3,s_gr_setdot );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xi = (int)(INUM(x));
else
xi = (int)(REALPART(x));
if( INUMP(y) )
yi = (int)(INUM(y));
else
yi = (int)(REALPART(y));
if( INUMP(c) )
ci = (int)(INUM(c));
else
ci = (int)(REALPART(c));
#ifdef TESTING
fprintf( stderr, "set-dot! called (%d,%d,%d)\n", xi, yi, ci );
#endif
if( !valid_XYC( xi, yi, ci ) )
return BOOL_F;
#ifdef X11
/* Set the drawing color */
XSetForeground( gr_display, gr_gc, gr_colortbl[ ci ] );
XDrawPoint( gr_display, gr_win, gr_gc, xi, yi );
/* Restore the drawing color */
XSetForeground( gr_display, gr_gc, gr_colortbl[ gr_color ] );
gr_events(0);
#else /* PC version */
putpixel( xi, yi, ci );
#endif
return BOOL_T;
} /* gr_setdot() */
SCM gr_getdot( x, y )
SCM x, y;
{
int xi, yi;
#ifdef X11
XImage *xim;
XWindowAttributes wattr;
unsigned long dot;
int i;
#endif
ASSERT( NUMBERP(x),x,ARG1,s_gr_getdot );
ASSERT( NUMBERP(y),y,ARG2,s_gr_getdot );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xi = (int)(INUM(x));
else
xi = (int)(REALPART(x));
if( INUMP(y) )
yi = (int)(INUM(y));
else
yi = (int)(REALPART(y));
#ifdef TESTING
fprintf( stderr, "get-dot called (%d,%d)\n", xi, yi );
#endif
if( !valid_XYC( xi, yi, 0 ) )
return BOOL_F;
#ifdef X11
/* Now, this IS ugly. But it's there if you need it. */
/* Have to make sure that the window is mapped. Tough... */
XGetWindowAttributes( gr_display, gr_win, &wattr );
if( wattr.map_state == IsUnmapped ) {
XMapWindow( gr_display, gr_win );
gr_typedevent( MapNotify );
}
/* I KNOW this sucks. */
xim = XGetImage( gr_display,gr_win, xi,yi, 1,1, AllPlanes, XYPixmap );
dot = XGetPixel( xim, 0,0 );
for( i = 0; i < GR_COLORS; ++i ) {
if( gr_colortbl[i] == dot )
return MAKINUM( (long)i );
}
/* This should never happen. There's garbage in the window! */
fprintf( stderr, "%s: %s: Got an illegal pixel value %lu. \
Is there garbage?\n", gr_progname, s_gr_getdot, dot );
return BOOL_F;
#else /* PC version */
return MAKINUM( (long)getpixel( xi, yi ) );
#endif
} /* gr_getdot() */
SCM gr_draw( S )
SCM S;
{
float xf, yf;
float sf;
int ok;
ASSERT( NUMBERP(S),S,ARG1,s_gr_draw );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(S) )
sf = (float)(INUM(S));
else
sf = REALPART(S);
#ifdef TESTING
fprintf( stderr, "draw called (%f)\n", sf );
#endif
ok = 1;
xf = gr_x + ( COS( gr_dir ) * sf );
yf = gr_y + ( SIN( gr_dir ) * sf );
if( (int)xf > gr_max_x ) {
xf = (float)gr_max_x;
ok = 0;
}
else if( xf < 0.0 ) {
xf = 0.0;
ok = 0;
}
if( (int)yf > gr_max_y ) {
yf = (float)gr_max_y;
ok = 0;
}
else if( yf < 0.0 ) {
yf = 0.0;
ok = 0;
}
#ifdef X11
XDrawLine( gr_display, gr_win, gr_gc,
(int)gr_x,(int)gr_y,
(int)xf,(int)yf );
gr_events(0);
#else /* PC version */
line( (int)gr_x,(int)gr_y, (int)xf,(int)yf );
#endif
gr_x = xf;
gr_y = yf;
if( ok )
return BOOL_T;
else
return BOOL_F;
} /* gr_draw() */
SCM gr_move( S )
SCM S;
{
float xf, yf;
float sf;
int ok;
ASSERT( NUMBERP(S),S,ARG1,s_gr_move );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(S) )
sf = (float)(INUM(S));
else
sf = REALPART(S);
#ifdef TESTING
fprintf( stderr, "move called (%f)\n", sf );
#endif
ok = 1;
xf = gr_x + ( COS( gr_dir ) * sf );
yf = gr_y + ( SIN( gr_dir ) * sf );
if( (int)xf > gr_max_x ) {
xf = (float)gr_max_x;
ok = 0;
}
else if( xf < 0.0 ) {
xf = 0.0;
ok = 0;
}
if( (int)yf > gr_max_y ) {
yf = (float)gr_max_y;
ok = 0;
}
else if( yf < 0.0 ) {
yf = 0.0;
ok = 0;
}
gr_x = xf;
gr_y = yf;
if( ok )
return BOOL_T;
else
return BOOL_F;
} /* gr_move() */
SCM gr_drawto( x, y )
SCM x, y;
{
int xi, yi;
ASSERT( NUMBERP(x),x,ARG1,s_gr_drawto );
ASSERT( NUMBERP(y),y,ARG2,s_gr_drawto );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xi = (int)(INUM(x));
else
xi = (int)(REALPART(x));
if( INUMP(y) )
yi = (int)(INUM(y));
else
yi = (int)(REALPART(y));
#ifdef TESTING
fprintf( stderr, "draw-to called (%d,%d)\n", xi, yi );
#endif
if( !valid_XYC( xi,yi, 0 ) )
return BOOL_F;
#ifdef X11
XDrawLine( gr_display, gr_win, gr_gc,
(int)gr_x,(int)gr_y, xi,yi );
gr_events(0);
#else /* PC version */
line( (int)gr_x,(int)gr_y, xi,yi );
#endif
return BOOL_T;
} /* gr_drawto() */
SCM gr_drawTo( x, y )
SCM x, y;
{
float xf, yf;
ASSERT( NUMBERP(x),x,ARG1,s_gr_drawTo );
ASSERT( NUMBERP(y),y,ARG2,s_gr_drawTo );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xf = (float)(INUM(x));
else
xf = (REALPART(x));
if( INUMP(y) )
yf = (float)(INUM(y));
else
yf = (REALPART(y));
#ifdef TESTING
fprintf( stderr, "draw-to! called (%d,%d)\n", (int)xf, (int)yf );
#endif
if( !valid_XYC( (int)xf,(int)yf, 0 ) )
return BOOL_F;
#ifdef X11
XDrawLine( gr_display, gr_win, gr_gc,
(int)gr_x,(int)gr_y,
(int)xf,(int)yf );
gr_events(0);
#else /* PC version */
line( (int)gr_x,(int)gr_y, (int)xf,(int)yf );
#endif
gr_x = xf;
gr_y = yf;
return BOOL_T;
} /* gr_drawTo() */
SCM gr_moveTo( x, y )
SCM x, y;
{
float xf, yf;
ASSERT( NUMBERP(x),x,ARG1,s_gr_moveTo );
ASSERT( NUMBERP(y),y,ARG2,s_gr_moveTo );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(x) )
xf = (float)(INUM(x));
else
xf = (REALPART(x));
if( INUMP(y) )
yf = (float)(INUM(y));
else
yf = (REALPART(y));
#ifdef TESTING
fprintf( stderr, "move-to! called (%d,%d)\n", (int)xf, (int)yf );
#endif
if( !valid_XYC( (int)xf,(int)yf, 0 ) )
return BOOL_F;
gr_x = xf;
gr_y = yf;
return BOOL_T;
} /* gr_moveTo() */
SCM gr_setcolor( c )
SCM c;
{
int color;
ASSERT( NUMBERP(c),c,ARG1,s_gr_setcolor );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(c) )
color = (int)(INUM(c));
else
color = (int)(REALPART(c));
#ifdef TESTING
fprintf( stderr, "set-color! called (%d)\n", color );
#endif
if( !valid_XYC( 0,0, color ) )
return BOOL_F;
gr_color = color;
#ifdef X11
/* Set the drawing color */
XSetForeground( gr_display, gr_gc, gr_colortbl[ gr_color ] );
gr_events(0);
#else /* PC version */
setcolor( gr_color );
#endif
return BOOL_T;
} /* gr_setcolor() */
SCM gr_turnright( d )
SCM d;
{
float df;
ASSERT( NUMBERP(d),d,ARG1,s_gr_turnright );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(d) )
df = (float)(INUM(d));
else
df = REALPART(d);
df = fmod( df, 360.0 );
gr_dir -= df;
gr_dir = fmod( gr_dir, 360.0 );
return MAKINUM( (long)(gr_dir+.5) );
} /* gr_turnright() */
SCM gr_turnleft( d )
SCM d;
{
float df;
ASSERT( NUMBERP(d),d,ARG1,s_gr_turnleft );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(d) )
df = (float)(INUM(d));
else
df = REALPART(d);
df = fmod( df, 360.0 );
gr_dir += df;
gr_dir = fmod( gr_dir, 360.0 );
return MAKINUM( (long)(gr_dir+.5) );
} /* gr_turnleft() */
SCM gr_turnto( d )
SCM d;
{
float df;
ASSERT( NUMBERP(d),d,ARG1,s_gr_turnto );
if( !gr_grmode_on )
return BOOL_F;
if( INUMP(d) )
df = (float)(INUM(d));
else
df = REALPART(d);
df = fmod( df, 360.0 );
gr_dir = df;
return MAKINUM( (long)(gr_dir+.5) );
} /* gr_turnto() */
SCM gr_gotohome()
{
if( !gr_grmode_on )
return BOOL_F;
gr_x = gr_y = 0.0;
return BOOL_T;
} /* gr_gotohome() */
SCM gr_gotocenter()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
gr_x = ((float)gr_max_x+1.0) / 2.0;
gr_y = ((float)gr_max_y+1.0) / 2.0;
return BOOL_T;
} /* gr_gotocenter() */
SCM gr_gotonw()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
gr_x = 0.0;
gr_y = 0.0;
return BOOL_T;
} /* gr_gotonw() */
SCM gr_gotosw()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
gr_x = 0.0;
gr_y = (float)gr_max_y;
return BOOL_T;
} /* gr_gotosw() */
SCM gr_gotone()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
gr_x = (float)gr_max_x;
gr_y = 0.0;
return BOOL_T;
} /* gr_gotone() */
SCM gr_gotose()
{
if( !gr_grmode_on )
return BOOL_F;
#ifdef X11
/* Check for changed window size */
gr_events(0);
#endif
gr_x = (float)gr_max_x;
gr_y = (float)gr_max_y;
return BOOL_T;
} /* gr_gotose() */
SCM gr_whatcolor()
{
if( !gr_grmode_on )
return BOOL_F;
return MAKINUM( (long)gr_color );
} /* gr_whatcolor() */
SCM gr_whatdirection()
{
if( !gr_grmode_on )
return BOOL_F;
return MAKINUM( (long)(gr_dir+.5) );
} /* gr_whatdirection() */
SCM gr_wherex()
{
if( !gr_grmode_on )
return BOOL_F;
return MAKINUM( (long)gr_x );
} /* gr_wherex() */
SCM gr_wherey()
{
if( !gr_grmode_on )
return BOOL_F;
return MAKINUM( (long)gr_y );
} /* gr_wherey() */
static iproc graph0[] = {
{ "help-gr", gr_helpgr },
{ "help-turtlegr", gr_helpturtlegr },
{ "graphics-mode!", gr_grmode },
{ "text-mode!", gr_txtmode },
{ "clear-graphics!", gr_cleargraph },
{ "graphics-avail?", gr_available },
{ "max-x", gr_maxx },
{ "max-y", gr_maxy },
{ "max-color", gr_maxc },
{ "what-color", gr_whatcolor },
{ "what-direction", gr_whatdirection },
{ "where-x", gr_wherex },
{ "where-y", gr_wherey },
{ "goto-home!", gr_gotohome },
{ "goto-center!", gr_gotocenter },
{ "goto-nw!", gr_gotonw },
{ "goto-sw!", gr_gotosw },
{ "goto-ne!", gr_gotone },
{ "goto-se!", gr_gotose },
{0,0}
};
static iproc graph1[] = {
{ s_gr_draw, gr_draw },
{ s_gr_move, gr_move },
{ s_gr_setcolor, gr_setcolor },
{ s_gr_turnright, gr_turnright },
{ s_gr_turnleft, gr_turnleft },
{ s_gr_turnto, gr_turnto },
{0,0}
};
static iproc graph2[] = {
{ s_gr_getdot, gr_getdot },
{ s_gr_drawTo, gr_drawTo },
{ s_gr_drawto, gr_drawto },
{ s_gr_moveTo, gr_moveTo },
{0,0}
};
static iproc graph3[] = {
{ s_gr_setdot, gr_setdot },
{ s_gr_validXYC, gr_validXYC },
{0,0}
};
#if defined __STDC__ || defined __TURBOC__
void close_turtlegr()
{
#ifdef X11
gr_events(0);
XFreeColors( gr_display, DefaultColormap(gr_display,gr_screen),
gr_colortbl, GR_COLORS, AllPlanes );
XFreeGC( gr_display, gr_gc );
XUnmapWindow( gr_display, gr_win );
XDestroyWindow( gr_display, gr_win );
#else /* PC version */
closegraph();
#endif
} /* close_turtlegr() */
#endif
void init_turtlegr() /* detects if graphics is available; must be
called among program initializations */
{
#ifdef X11
char *display_name = NULL; /* Server to connect to */
Pixmap icon_pixmap; /* Icon */
XSizeHints size_hints; /* Preferred sizes */
XSetWindowAttributes win_attribs; /* Window attributes */
XWMHints wm_hints; /* Window manager hints */
XClassHint class_hints; /* Class hints */
XTextProperty window_name, icon_name; /* Names for Icon & Window */
XGCValues gc_values; /* Graphics Context values */
static char *colorname[GR_COLORS] = {
GR_COLOR00, GR_COLOR01, GR_COLOR02, GR_COLOR03,
GR_COLOR04, GR_COLOR05, GR_COLOR06, GR_COLOR07,
GR_COLOR08, GR_COLOR09, GR_COLOR10, GR_COLOR11,
GR_COLOR12, GR_COLOR13, GR_COLOR14, GR_COLOR15
};
XColor x_color; /* X11 Color structure */
unsigned long mask; /* Mask for selections */
int i; /* loop counter variable */
#else /* PC version */
int errcode;
#endif
/***************************/
/* generic initializations */
/***************************/
gr_x = gr_y = gr_dir = 0.0;
gr_max_x = gr_max_y = gr_max_color = 0;
gr_graphicsavail = 0; /* DEFAULT is no graphics - you can do without */
/********************************************/
/***** Initialize X11 turtlegraphics *****/
/********************************************/
#ifdef X11
/* connect to X server */
if( (gr_display = XOpenDisplay(display_name)) != NULL )
{
/*****************************/
/* connection to X server OK */
/*****************************/
gr_screen = DefaultScreen( gr_display ); /* X screen number */
/* Create a window with Black background and border */
gr_win
= XCreateSimpleWindow( gr_display,
RootWindow( gr_display, gr_screen),
0, 0, /* initial placement */
GR_DEF_XSIZE, GR_DEF_YSIZE,
3, /* border width */
/* border pixel value */
BlackPixel(gr_display,gr_screen),
/* background pixel value */
BlackPixel(gr_display,gr_screen) );
/* Select input (events) for the window */
XSelectInput( gr_display, gr_win,
StructureNotifyMask|ExposureMask );
/* Check for backing store capability */
if( !DoesBackingStore(DefaultScreenOfDisplay(gr_display)) )
{
fprintf( stderr, "%s: Warning: \
X server does not offer backing store capability.\n\
Window cannot be redrawn if obscured. Sorry...\n", gr_progname );
}
else
{
/* Enable the backing store feature of X server
and set bit gravity */
win_attribs.bit_gravity = NorthWestGravity;
win_attribs.backing_store = Always;
mask = CWBitGravity | CWBackingStore;
XChangeWindowAttributes( gr_display, gr_win, mask, &win_attribs );
}
/* Make names of Window and Icon for window manager */
if( XStringListToTextProperty(&gr_windowname,1,&window_name) == 0 ) {
(void)fprintf( stderr, "%s: Structure allocation for windowName\
failed.\n", gr_progname );
exit( 42 );
}
if( XStringListToTextProperty(&gr_iconname,1,&icon_name) == 0 ) {
(void)fprintf( stderr, "%s: Structure allocation for iconName\
failed.\n", gr_progname );
exit( 42 );
}
/* Create the icon */
icon_pixmap = XCreateBitmapFromData( gr_display, gr_win, turtle_bits,
turtle_width, turtle_height );
/* Window size, state, icon etc. hints for the window manager */
size_hints.flags = PPosition | PMaxSize | PMinSize | USSize;
/* position and desired size are given to XCreateSimpleWindow call */
size_hints.min_width = GR_MIN_XSIZE;
size_hints.min_height = GR_MIN_YSIZE;
size_hints.max_width = GR_MAX_XSIZE;
size_hints.max_height = GR_MAX_YSIZE;
wm_hints.flags = StateHint | IconPixmapHint | InputHint;
wm_hints.initial_state = NormalState;
wm_hints.input = False;
wm_hints.icon_pixmap = icon_pixmap;
class_hints.res_name = gr_progname;
class_hints.res_class = gr_classname;
XSetWMProperties( gr_display, gr_win, &window_name, &icon_name,
gr_argv, gr_argc,
&size_hints, &wm_hints, &class_hints );
/* Handle colors; this is quite complicated in X11 */
if( DefaultDepth( gr_display, gr_screen ) == 1 )
{
/* Only 1 bitplane, BW screen */
/* Emulate colors with 0 as Black and 1-15 White */
gr_colortbl[0] = BlackPixel( gr_display, gr_screen );
for( i = 1; i < GR_COLORS; ++i )
gr_colortbl[i] = WhitePixel( gr_display, gr_screen );
#ifdef TESTING
fprintf( stderr, "%s: 1-plane system, substituting White for \
colors 1-15.\n", gr_progname );
fprintf( stderr, "%s: Pixel value is %lu for Black, \
%lu for White\n", gr_progname, gr_colortbl[0], gr_colortbl[1] );
#endif
}
else
{
/* more than 1 bitplane */
for( i = 0; i < GR_COLORS; ++i )
{
/* Initialize the colortable using named colors */
if( XParseColor( gr_display,
DefaultColormap(gr_display,gr_screen),
colorname[ i ], &x_color ) )
{
if( !XAllocColor( gr_display,
DefaultColormap(gr_display,gr_screen),
&x_color ) )
{
fprintf( stderr, "%s: Can't allocate color \
\"%s\" (%d). Substituting White.\n",
gr_progname,
colorname[ i ], i );
gr_colortbl[i] = WhitePixel( gr_display, gr_screen );
}
else
{
/* succeeded in allocating color */
gr_colortbl[ i ] = x_color.pixel;
#ifdef TESTING
fprintf( stderr, "%s: Pixel value is %lu for %s.\n",
gr_progname, gr_colortbl[i], colorname[i] );
#endif
}
}
else
{
/* could not parse color */
fprintf( stderr,
"%s: Color name \"%s\" (%d) not in database. \
Substituting White.\n",
gr_progname, colorname[i], i );
gr_colortbl[i] = WhitePixel( gr_display, gr_screen );
}
} /* for */
} /* else */
gr_max_color = GR_COLORS - 1;
/* Create and initialize a default GC */
gr_gc = XCreateGC( gr_display, gr_win, 0L, &gc_values );
/* Initialize the drawing color, default's black */
XSetForeground( gr_display, gr_gc, gr_colortbl[ 0 ] );
XSetBackground( gr_display, gr_gc, gr_colortbl[ 0 ] );
gr_color = 0;
/* OK, we _do_ have graphics available */
gr_graphicsavail = 1;
#ifdef __STDC__
/* Let's do the Right Thing if possible :) */
atexit( close_turtlegr );
#endif
} /* if */
else {
gr_graphicsavail = 0;
}
/********************************************/
/***** Initialize PC turtlegraphics *****/
/********************************************/
#else /* PC version */
gr_drivernum = DETECT;
detectgraph( &gr_drivernum, &gr_max_display_mode );
if( gr_drivernum != grNotDetected ) {
if( !getenv( BGIDIR_ENVSTRING ) )
fprintf( stderr,
"You really should set the %s environment variable.\n",
BGIDIR_ENVSTRING );
initgraph( &gr_drivernum, &gr_max_display_mode,
getenv( BGIDIR_ENVSTRING ) );
errcode = graphresult();
if( errcode != grOk ) {
fputs( "Graphics error: ", stderr );
fputs( grapherrormsg( errcode ), stderr );
exit( 1 );
}
moveto( 0,0 );
gr_x = gr_y = 0.0;
setcolor( 0 );
gr_color = 0;
gr_max_x = getmaxx();
gr_max_y = getmaxy();
gr_max_color = getmaxcolor();
gr_max_display_mode = getmaxmode();
restorecrtmode();
gr_graphicsavail = 1;
atexit( close_turtlegr );
}
else {
gr_graphicsavail = 0;
}
#endif
/* generic */
init_iprocs( graph0, tc7_subr_0 );
init_iprocs( graph1, tc7_subr_1 );
init_iprocs( graph2, tc7_subr_2 );
init_iprocs( graph3, tc7_subr_3 );
gr_grmode_on = 0;
#ifndef X11
/* PC version clears screen so this must be repeated */
fputs("SCM version ",stdout);
fputs(SCMVERSION,stdout);
intprint((long)PATCHLEVEL,10,stdout);
puts(", Copyright (C) 1990, 1991, 1992 Aubrey Jaffer.\n\
SCM comes with ABSOLUTELY NO WARRANTY; for details type `(terms)'.\n\
This is free software, and you are welcome to redistribute it\n\
under certain conditions; type `(terms)' for details.");
#endif
puts( "\nSCM Turtlegraphics Copyright (C) 1992 sjm@cc.tut.fi, jtl@cc.tut.fi\n\
Type `(help-gr)' or `(help-turtlegr)' for a quick reference of\n\
the new primitives.\n" );
if( !gr_graphicsavail ) {
#ifdef X11
fprintf( stderr, "%s: No X server found. \
Turtlegraphics not available.\n", gr_progname );
#else
fputs( "No graphics adapter detected. \
Turtlegraphics not available.\n", stderr );
#endif
}
else {
#ifdef X11
gr_events(0);
#else
;
#endif
}
} /* init_turtlegr() */