[comp.sources.unix] v18i065: GL Graphics Library for AT-clone Unix, Part07/07

rsalz@uunet.uu.net (Rich Salz) (03/25/89)

Submitted-by: umix!m-net!dtlewis!lewis
Posting-number: Volume 18, Issue 65
Archive-name: gl_plot/part07

# To recover, type "sh archive"
echo restoring INSTALL
sed 's/^X//' > INSTALL <<XxX--EOF--XxX
XHOW TO BUILD THE GL LIBRARY
X
X1)  Edit the Makefile file for your system.  Microport System V/AT and 
XSCO Xenix for 286 machines, and MS-DOS for any PC, are currently supported.
XFor Microsoft C under MS-DOS, use the MSC.MAK file.  For Turbo-C under 
XMS-DOS, use the TCC.MAK file.
X
X2)  Edit the config.h file.  Define your target system and compiler, along 
Xwith other parameters that may be specific to your hardware and operating 
Xsystem.
X
X3)  Run make.  For UNIX, just type "make."  For Xenix, type "make xenix."
XTo compile an MS-DOS executable under Xenix, type "make dos."  For 
XMicrosoft C under MS-DOS, type "MAKE MSC.MAK".  For Turbo-C under MS-DOS, 
Xtype "MAKE -FTCC.MAK".
X
XHOW TO INSTALL THE GL LIBRARY
X
XBefore running the demonstration programs "demo" and "xdemo," you
Xmust do a few things.
X
XMicroport System V/AT:
X---------------------
X
X1)  Mode switch program:  The GL library will switch video graphics
Xmodes by executing a program or shell script.  The name of the program
Xis defined in config.h as follows:
X
X	#define MODEPROG "mode"
X
XYou must have a working script or program called "mode" in your
Xpath, or (if you prefer), you can use a different program name for your
Xsystem.  For most systems and video adapters (CGA and EGA compatible), 
Xyou can use the "mode.sh" script, and rename it to "mode" (use the
Xcommand "mv mode.sh mode").
X
XIf you have an Everex Edge (hercules compatible), use mode.c ("mv 
Xmodeprog mode").  For other adapters (possibly including actual 
XHercules boards), you may have to modify mode.c and setmode.c.  
X
XIf you use mode.c, you must make the executable (mode) suid and 
Xowned by root.  Put it in a safe path, of course.
XFor example, sign as root, then:
X
X  \$ mv mode /usr/bin/mode
X  \$ chmod 4555 /usr/bin/mode
X
XBe sure the mode program works before trying anything else.  You should,
Xfor example, be able to type "mode 4" and have your graphics adapter 
Xswitch to 640x200 color graphics mode, and type "mode" to return to 
Xnormal text mode.
X
X2)  Graphics shared memory:  The GL library must be able to attach to
Xa shared memory segment that corresponds to your graphics adapter.  You
Xmust use a kernel that has shared memory enabled.  The standard kernel
Xfor large memory systems should already be configured this way; if not,
Xuse the link kit (edit the last three lines of dfile.wini).
X
XNext, you must sign on as root, and run the shmcreate(1) program to 
Xcreate one or more shared memory keys.  Once you have the key or keys 
Xdefined correctly, you should put the shmcreate commands into your 
X/etc/rc.d/shm.rc file, so the keys will be defined each time the 
Xsystem is booted.
X
XThe key values are actually arbitrary, but have been chosen to match
Xthe physical memory addresses that they point to.  Thus the "b8000" 
Xkey is used for CGA graphics modes, and the "b0000" is used for 
Xhercules compatible adapters.  The "a0000" key can be used for EGA 
Xmodes.  Define keys for each mode you expect to use.
X
XFollowing is a sample shm.rc file for a system with a video adapter
Xwhich supports CGA modes and hercules compatible mode:  
X
X	#  Setup for shared memory segments used for graphics
X
X	# /etc/shmcreate 0xa0000 a0000 65535		# ega high res
X	/etc/shmcreate 0xb0000 b0000 65535		# ega low res
X	/etc/shmcreate 0xb8000 b8000 32768		# cga
X	# /etc/shmcreate 0xc6000 c6000  4096		# pga
X
X3)  Double check.  Use the ipcs(1) command to make sure your shared memory
Xkeys are installed.  Run the mode script (or program) with arguments
Xcorresponding to each mode you want to use.
X
X4)  If you want to be able to do graphics printing, be sure you have a
Xprinter device in the lp spooler which is capable of raw output.  The
Xname of this device should match the PRINTDEV macro in config.h.  See the
X"Readme" file for more information.
X
X5)  You should now be ready to run GL programs.  Try either "demo" or
X"xdemo."  If something is not set up correctly, the error messages should
Xgive a good indication of the problem.  
X
X
XXenix System V 286:
X------------------
X
X1)  Mode switch program:  The GL library will switch video graphics
Xmodes by executing a program or shell script.  The name of the program
Xis defined in config.h as follows:
X
X	#define MODEPROG "mode"
X
XYou must have a working script or program called "mode" in your
Xpath, or (if you prefer), you can use a different program name for your
Xsystem.  For most systems and video adapters (CGA and EGA compatible), 
Xyou can use the "mode.xenix" script, and rename it to "mode" (use the
Xcommand "mv mode.xenix mode").
X
X2)  Double check.  Run the mode script (or program) with arguments
Xcorresponding to each mode you want to use.
X
X3)  If you want to be able to do graphics printing, be sure you have a
Xprinter device in the lp spooler which is capable of raw output.  The
Xname of this device should match the PRINTDEV macro in config.h.  See the
X"Readme" file for more information.
X
X4)  You should now be ready to run GL programs.  Try either "demo" or
X"xdemo."  If something is not set up correctly, the error messages should
Xgive a good indication of the problem.  Note that as of this writing,
XGL has been tested ONLY on an EGA board for Xenix.  It will probably 
Xwork for CGA cards, but hercules compatibles may take some experimenting.  
XAny required modifications to the code will be in the g_init.c module.
X
X
XMS-DOS, cross compiled from Xenix System V 286:
X-----------------------------------------------
X
X1)  Mode switch program:  None required, unless a Hercules compatible
Xvideo board is used, in which case you will have to hack the code to
Xuse some or all of the mode.c and modeset.c routines.
X
X2)  Compile under Xenix, and copy to an MS-DOS disk or partition.
X
X3)  You should now be ready to run GL programs.  
X
X
XMS-DOS with Microsoft C
X-----------------------
X
XJust try running the DEMO.EXE and XDEMO.EXE programs ("DEMO 4" to run
Xthe demo in video mode 4).  Graphics modes 4, 6, and 16 (EGA) will work,
Xas will mode 256 for an IBM/Epson printer on PRN:.  Hercules support is
Xnot currently in the MS-DOS version, but all you need to do is borrow the 
Xmode switching code in SETMODE.C and add it to g_init.c module.
X
X
XMS-DOS with Turbo-C
X-------------------
XThis works the same as Microsoft C, although it compiles faster and runs
Xa little slower.
X
X
X					d t lewis
X					Mon Feb 20 20:09:41 EST 1989
X					system5 dtlewis 2 2.4.0-U AT
XxX--EOF--XxX
echo restoring demo.c
sed 's/^X//' > demo.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) demo.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1987, 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X#include "config.h"
X#include "gl.h"
X#include <stdio.h>
X#if MIX_C
X#else
X#include <time.h>
X#endif /* MIX_C */
X
Xextern int lines(), strings(), chars(), strokeset(), fillscreen();
Xextern int charset(), ellipses(), arcs(), testplot(), showcursor();
Xextern int linestyles(), curvestyles();
X
Xstatic int mode;
X
Xvoid usage(progname)  
Xchar *progname;
X{
X	fprintf (stderr,"Usage:  %s <mode>\n\n",progname);
X	fprintf (stderr,"Where <mode> is:\n",0);
X	fprintf (stderr,"\t4 (CGA 4 color 320 x 200)\n",0);
X	fprintf (stderr,"\t6 (CGA 2 color 640 x 200)\n",0);
X	fprintf (stderr,"\t8 (Hercules page 0, 720 x 348)\n",0);
X	fprintf (stderr,"\t9 (Hercules page 1, 720 x 348)\n",0);
X	fprintf (stderr,"\t16 (EGA color 640 x 350)\n",0);
X	fprintf (stderr,"\t256 (IBM / Epson compatible printer)\n",0);
X	fprintf (stderr,"\t257 (Laserjet+ printer)\n\n",0);
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	char str[80];
X	long time();
X	struct tm *gmtime();
X	void srand();
X
X	printf("\nThis demonstration will show the operation of the gl ",0);
X	printf("graphics functions.\n",0);
X	printf("The <delete> key stops the demo.  Press <return> ",0);
X	printf("to view each\n",0);
X	printf("successive screen.\n\n",0);
X	printf("Note: The GLMODE shell variable may be used to specify ",0);
X	printf("the graphics\n",0);
X	printf("mode to use.\n\n",0);
X	printf("Press <return> to continue...",0);
X	gets(str);
X
X	/* Get the mode to use. */
X
X	if (argc < 2) mode = ENV_MODE;
X	else if (argc == 2)  {
X		if (sscanf(argv[1],"%d",&(mode)) != 1)  {
X			usage(argv[0]);
X			exit (1);
X		}
X	}
X	else  {
X		usage(argv[0]);
X		exit (1);
X	}
X
X	/* Set video mode.	*/
X	if (g_init(mode))  {
X		usage(argv[0]);
X		fprintf(stderr,"WARNING:  Possible invalid shared memory ",0);
X		fprintf(stderr,"key for requested video mode.\n",0);
X		exit (1);
X	}
X
X	/* Draw patterns.	*/
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	if (lines()) fprintf(stderr,"Failed call to lines().\n");
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	if (linestyles()) fprintf(stderr,"Failed call to linestyles().\n");
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	if (strings()) fprintf(stderr,"Failed call to strings().\n");
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	slanttext();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	strokeset();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	if (chars()) fprintf(stderr,"Failed call to chars().\n");
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	fillscreen();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	charset();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	ellipses();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	curvestyles();
X	if (mode > MAXVIDEO)
X		printf("\nPress <Return> to send to printer...",0);
X	gets(str);
X
X	if (mode > MAXVIDEO) printf("\nRasterizing output...",0);
X	g_clear();
X	arcs();
X	showcursor();
X
X	g_finish();
X
X	printf("\n\n\n\nThe next demonstration screen will use the ",0);
X	printf("plot(3) interface, rather than\n",0);
X	printf("direct calls to the gl library.  The plot(3) interface ",0);
X	printf("determines graphic \n",0);
X	printf("mode from the GLMODE shell variable, or if GLMODE is not ",0);
X	printf("defined, uses a \n",0);
X	printf("default mode value (defined in config.h). \n\n",0);
X	printf("If you called this program with an argument on the ",0);
X	printf("command line, the \n",0);
X	printf("next screen may use a different graphics mode ",0);
X	printf("than you specified. \n\n",0);
X	printf("Press <return> to continue or <delete> to stop...",0);
X
X	gets(str);
X
X	testplot();
X	gets(str);
X}
XxX--EOF--XxX
echo restoring mode.sh
sed 's/^X//' > mode.sh <<XxX--EOF--XxX
X:
X#  Contributed by Denis Fortin, April 1988.
X#
X#  mode - This trivial little command file is used to set the graphics mode
X#	  of the console on Microport System V/AT.
X#
X#  Usage:
X#		mode [value]
X#
X# 	where: value is an integer used to select the current display
X#		     mode.  If it is omitted, the screen is returned to
X#		     normal text mode.
X#
X#  Examples:
X#	mode
X#		Returns to normal text mode
X#
X#	mode 16
X#		Puts an EGA card with Enhanced Display adapter in 640x350
X#		graphics mode.
X#
X#	mode 6
X#		Puts a CGA card in 640x200 graphics mode.
X#
Xif [ \$# -lt 1 ] 
Xthen
X	echo "\033[=h\c"
Xelse
X	echo "\033[=\${1}h\c"
Xfi
XxX--EOF--XxX
echo restoring mode.xenix
sed 's/^X//' > mode.xenix <<XxX--EOF--XxX
X:
X# d t lewis  11-20-1988
X# Script to set video mode using the stty command for Xenix 286.
X#
X# Pick a default (text) mode:
X
XDEFAULT_MODE=ENH_C80x25
X# DEFAULT_MODE=ENH_B80x25
X# DEFAULT_MODE=EGAMONO80x25
X# DEFAULT_MODE=C80x25
X# DEFAULT_MODE=B80x25
X
X	case \$# in
X		1)	;;	# Correct number of arguments is 1.
X		0)	stty \$DEFAULT_MODE
X			exit;;
X		\?)	echo "Usage: \$0 modenumber"
X			echo "where modenumber is an integer value"
X			;;
X		*)	echo "Usage: \$0 modenumber"
X			echo "where modenumber is an integer value"
X			;;
X	esac
X
X
X# These variables should correspond to the defines in graphics.h:
X
X	MONO_TEXT=2
X	COLOR_TEXT=3
X	CGA_COLOR_MODE=4
X	CGA_HI_RES_MODE=6
X	EGA_COLOR_MODE=16
X	HERC_GRAF_MODE=8
X	IBM_PRINTER=256
X
X	case \$1 in
X		\$MONO_TEXT)
X			stty ENH_B80x25
X			;;
X		\$COLOR_TEXT)
X			stty ENH_C80x25
X			;;
X		\$CGA_COLOR_MODE)
X			stty CG320
X			# Mode 4    -	320x200	4 color	graphics.
X			;;
X		\$CGA_HI_RES_MODE)
X			stty BG640
X			# Mode 6    -	640x200	2 color	graphics.
X			;;
X		\$EGA_COLOR_MODE)
X			stty ENH_CG640
X			;;
X		\$HERC_GRAF_MODE)
X			# stty ??????????  -don't know the value to use.
X			# Hercules  -	720x348	black &	white graphics.
X			;;
X		\$IBM_PRINTER)
X			;;
X		*)
X			stty \$DEFAULT_MODE
X			# Switch back	to normal text mode.
X			;;
X	esac
X	exit
X
XxX--EOF--XxX
echo restoring n_point.c
sed 's/^X//' > n_point.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_point.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* Sun Aug 21 21:59:55 EDT 1988
X** dtlewis
X** Routine to draw a point in normalized 2-d space.
X*/
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
Xextern int n_movepen();
Xextern int p_wr_pix();
X
Xint n_point(x,y)  
X	int x,y;
X{
X	if (n_movepen(x,y)) return(1);
X	if (p_wr_pix(n_to_p_x(x), n_to_p_y(y))) return(1);
X	return(0);
X}
XxX--EOF--XxX
echo restoring testpat.c
sed 's/^X//' > testpat.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) testpat.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X#include "config.h"
X#include <stdio.h>
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#if XEN2DOS
X#include <dos.h>
X#endif /* XEN2DOS */
X#if USOFT
X#include <dos.h>
X#endif /* USOFT */
X#include "gl.h"
X
X#ifndef M_PI_2
X#define M_PI_2	1.5707963268 
X#endif /* M_PI_2 */
X#ifndef M_PI_4
X#define M_PI_4	0.7853981634 
X#endif /* M_PI_4 */
X
Xstatic char str[20];
X
X/* Routines to put test patterns on the screen.	*/
X
Xint lines()  {
X
X	if (n_line(4000,4000,20000,20000)) return(1);
X
X        if (n_movepen(6000,6000)) return(1);
X        if (n_draw(12000,6000)) return(1);
X        if (n_draw(12000,12000)) return(1);
X        if (n_draw(6000,12000)) return(1);
X        if (n_draw(6000,6000)) return(1);
X
X        if (n_movepen(6000,6000)) return(1);
X        if (n_draw(12000,12000)) return(1);
X
X	g_pix_color(CYAN);
X
X	if (n_box(700,700,900,1200)) return(1);
X	if (n_box(900,1200,1100,1700)) return(1);
X	if (n_box(20000,20000,30000,30000)) return(1);
X
X	if (n_box(1000,10000,12000,12000)) return(1);
X	if (n_box(9000,9000,13000,13000)) return(1);
X	if (n_box(8000,8000,14000,14000)) return(1);
X	if (n_box(7000,7000,15000,15000)) return(1);
X	if (n_box(6000,6000,16000,16000)) return(1);
X
X        if (n_movepen(2000,13000)) return(1);
X        if (n_draw(4000,13000)) return(1);
X        if (n_movepen(4000,13300)) return(1);
X        if (n_draw(2000,13300)) return(1);
X
X	g_pix_color(GREEN);
X
X        if (n_movepen(2000,14000)) return(1);
X        if (n_draw(30000,14400)) return(1);
X        if (n_draw(2000,14800)) return(1);
X        if (n_draw(30000,15200)) return(1);
X        if (n_draw(2000,15600)) return(1);
X        if (n_draw(30000,16000)) return(1);
X        if (n_draw(2000,16400)) return(1);
X        if (n_draw(30000,16800)) return(1);
X        if (n_draw(2000,17200)) return(1);
X        if (n_draw(30000,17600)) return(1);
X        if (n_draw(2000,18000)) return(1);
X        if (n_draw(30000,18400)) return(1);
X        if (n_draw(0,18800)) return(1);
X        if (n_draw(32000,19200)) return(1);
X        if (n_draw(0,19600)) return(1);
X        if (n_draw(32000,20000)) return(1);
X        if (n_draw(0,20400)) return(1);
X        if (n_draw(32000,20800)) return(1);
X        if (n_draw(0,21200)) return(1);
X        if (n_draw(32000,21600)) return(1);
X        if (n_draw(0,22000)) return(1);
X        if (n_draw(32000,22400)) return(1);
X
X        if (n_movepen(6000,4000)) return(1);
X        if (n_draw(6200,30000)) return(1);
X        if (n_draw(6400,4000)) return(1);
X        if (n_draw(6600,30000)) return(1);
X        if (n_draw(6800,4000)) return(1);
X        if (n_draw(7000,30000)) return(1);
X        if (n_draw(7200,4000)) return(1);
X        if (n_draw(7400,30000)) return(1);
X        if (n_draw(7600,4000)) return(1);
X        if (n_draw(7800,30000)) return(1);
X        if (n_draw(8000,4000)) return(1);
X        if (n_draw(8200,30000)) return(1);
X        if (n_draw(8400,4000)) return(1);
X
X	g_pix_color(BLUE);
X
X        if (n_movepen(2000,2000)) return(1);
X        if (n_draw(32000,4000)) return(1);
X        if (n_draw(31000,32000)) return(1);
X        if (n_draw(1000,30000)) return(1);
X        if (n_draw(2000,2000)) return(1);
X        if (n_draw(31000,32000)) return(1);
X
X        if (n_movepen(0,0)) return(1);
X        if (n_draw(32767,0)) return(1);
X        if (n_draw(32767,32767)) return(1);
X        if (n_draw(0,32767)) return(1);
X        if (n_draw(0,0)) return(1);
X        if (n_draw(32767,32767)) return(1);
X        if (n_movepen(0,32767)) return(1);
X        if (n_draw(32767,0)) return(1);
X
X	return(0);
X}
X
Xint linestyles()  {
X	n_box(1000,1000,30000,30000);
X	g_style(DOTTED);
X	n_box(2000,2000,29000,29000);
X	g_style(DOTDASHED);
X	n_box(3000,3000,28000,28000);
X	g_style(DASHED);
X	n_box(4000,4000,27000,27000);
X	g_style(SHORTDASHED);
X	n_box(5000,5000,26000,26000);
X	g_style(LONGDASHED);
X	n_box(6000,6000,25000,25000);
X	g_style(SOLID);
X	n_box(7000,7000,24000,24000);
X	g_style(DASHED);
X	n_movepen(15500,7000);
X	n_draw(24000,15500);
X	n_draw(15500,24000);
X	n_draw(7000,15500);
X	n_draw(15500,7000);
X	g_style(SOLID);
X	n_movepen(12000,15000);
X	c_cellstr("Line Styles");
X
X	return(0);
X}
X
Xcurvestyles()  {
X	n_ellipse(15500,15500,15000,15000);
X	g_style(DOTTED);
X	n_ellipse(15500,15500,14000,13000);
X	g_style(DOTDASHED);
X	n_ellipse(15500,15500,13000,11000);
X	g_style(DASHED);
X	n_ellipse(15500,15500,12000,9000);
X	g_style(SHORTDASHED);
X	n_ellipse(15500,15500,11000,7000);
X	g_style(LONGDASHED);
X	n_ellipse(15500,15500,10000,5000);
X	g_style(SOLID);
X	n_ellipse(15500,15500,9000,3000);
X	n_movepen(12000,15000);
X	c_cellstr("Ellipses");
X
X	return(0);
X}
X
Xint strings()  {
X
X	n_movepen(10,5000);
X	if (n_grafstr("AbCdEfGhIjKlMnOpQrStUvWxYz")) 
X		return(1);
X
X	/* Don't worry about errors from here on out.  We will get	*/
X	/* an error return code each time we try to write off the edge	*/
X	/* of the screen.						*/
X
X	g_pix_color(MAGENTA);
X
X	g_fontctl(2.0, 1.0, 1.0, 0.0, 0.0);
X	n_movepen(100, 10000);
X	n_grafstr("AbCdEfGhIjKlMnOpQrStUvWxYz");
X	g_fontctl(4.0, 1.0, 1.0, 0.0, 0.0);
X	n_movepen(100, 15000);
X	n_grafstr("AbCdEfGhIjKlMnO");
X	g_fontctl(3.0, 1.0, 1.0, 0.0, 0.0);
X	n_movepen(100, 20000);
X	n_grafstr("Z#\$%^&*()+");
X	g_fontctl(3.0, 2.0, 1.0, 0.0, 0.0);
X	n_movepen(100, 24000);
X	n_grafstr("Z#\$%^&*()+");
X	g_fontctl(3.0, 2.0, 2.0, 0.0, 0.0);
X	n_movepen(100, 28000);
X	n_grafstr("Z#\$%^&*()+");
X
X	return (0);
X
X}
X
Xint chars()  {
X
X	int idx;
X	char string1[65];
X	char string2[65];
X	char string3[65];
X	char string4[65];
X
X	g_pix_color(RED);
X
X	if (c_cursor(1,1)) return(1);
X	if (c_cellstr("* <== This is (1,1)")) return(1);
X
X	/* Don't worry about errors from here on out.  We will get	*/
X	/* an error return code each time we try to write off the edge	*/
X	/* of the screen.						*/
X
X	c_cursor(2,30);
X	c_cellstr("* <== This is (2,30)");
X
X	c_cursor(3,60);
X	c_cellstr("* <== This is (3,60)");
X
X	c_cursor(10,40);
X	c_cellstr("* <== This is (10,40)");
X
X	c_cursor(25,40);
X	c_cellstr("X");
X
X	c_cursor(25,80);
X	c_cellstr("X");
X
X	c_cursor(43,90);
X	c_cellstr("X");
X
X	c_cursor(2,1); 
X	c_cellstr("This");
X	c_cursor(3,1); 
X	c_cellstr(" Is ");
X	c_cursor(4,1); 
X	c_cellstr("  A ");
X	c_cursor(5,1); 
X	c_cellstr("TEST");
X	c_cursor(6,1); 
X	c_cellstr("XXXX");
X	c_cursor(7,1); 
X	c_cellstr("XXXX");
X
X	for (idx=0;idx<64;idx++)  {
X		string1[idx]=idx;
X		string2[idx]=idx+64;
X		string3[idx]=idx+128;
X		string4[idx]=idx+192;
X	}
X	string1[64]=0;
X	string2[64]=0;
X	string3[64]=0;
X	string4[64]=0;
X
X	/* The first character of string1[] is a null, making it a	*/
X	/* null string.  No good.  Make it the same as the second.	*/
X
X	string1[0] = string1[1];
X
X	c_cursor(11,1);
X	c_cellstr(string1);
X	c_cursor(12,2);
X	c_cellstr(string2);
X	c_cursor(13,3);
X	c_cellstr(string3);
X	c_cursor(14,4);
X	c_cellstr(string4);
X	c_cursor(15,5);
X	c_cellstr(string1);
X	c_cursor(16,6);
X	c_cellstr(string2);
X	c_cursor(17,7);
X	c_cellstr(string3);
X	c_cursor(18,8);
X	c_cellstr(string4);
X
X	for (idx=1;idx<=10;idx++)  {
X		if (! c_cursor(idx,20)) c_cellstr("XHIHX");
X	}
X
X	return (0);
X}
X
Xint charset()  {
X	int x,y;
X
X	char cval = 0;
X	g_pix_color(CYAN);
X	for (y=1; y<=60; y++)  {
X		for (x=1; x<=140; x++)  {
X			if (! c_cursor(y,x))  {
X				c_cellchar(cval);
X				cval = (++cval) & 0xff;
X			}
X		}
X	}
X}
X
Xint strokeset()  {
X	int x,y;
X
X	char cval = 0;
X	g_pix_color(CYAN);
X	g_fontctl(2.0, 1.0, 1.0, 0.0, 0.0);
X	for (y=1; y<=60; y += 2)  {
X		for (x=1; x<=140; x += 2)  {
X			if (! c_cursor(y,x))  {
X				n_grafchar(cval);
X				cval = (++cval) & 0x7f;
X			}
X		}
X	}
X}
X
Xint slanttext()  {
X
X	g_pix_color(LT_CYAN);
X	n_movepen(6000,100);
X	g_fontctl(4.0, 1.0, 1.0, 0.0, 0.0);
X	n_grafstr("Text");
X
X	n_movepen(6000,4100);
X	n_grafstr("Can be");
X
X	g_pix_color(LT_GREEN);
X	n_movepen(6000,8100);
X	g_fontctl(4.0, 1.0, 1.0, 0.0, 0.2);
X	n_grafstr("Slanted!");
X
X	g_pix_color(YELLOW);
X	n_movepen(10,30000);
X	g_fontctl(4.0, 1.0, 1.0, M_PI_2, 0.0);
X	n_grafstr("Rotated!");
X
X	g_pix_color(LT_RED);
X	n_movepen(6000,28000);
X	g_fontctl(4.0, 1.0, 1.0, M_PI_4, 0.0);
X	n_grafstr("Or ");
X	g_fontctl(4.0, 1.0, 1.0, M_PI_4, 0.2);
X	n_grafstr("Both!");
X}
X
Xint fillscreen()  {
X	int x,y;
X	char cval;
X	g_pix_color(CYAN);
X	for (x=1; x<=140; x++)  {
X		for (y=1; y<=60; y++)  {
X			cval = ((x+y-1)%10+'0');
X			if (! c_cursor(y,x)) c_cellchar(cval);
X		}
X	}
X	n_box(0,0,32767,32767);
X}
X
Xellipses()  {
X	int idx;
X
X	g_pix_color(CYAN);
X	n_ellipse(10000,10000,4000,6000);
X	n_ellipse(24000,15000,5000,6000);
X	n_ellipse(20000,10000,6000,4000);
X	n_ellipse(18000,18000,4000,3000);
X	n_ellipse(10000,20000,7000,6000);
X	n_ellipse(15000,24000,8000,8000);
X	n_ellipse(10000,28000,5000,6000);
X
X	for (idx=10; idx< 20000; idx +=400)  {
X		n_ellipse(1000+idx,1000+idx,idx,idx);
X	}
X}
X
Xarcs()  {
X	int idx;
X
X	g_pix_color(RED);
X	for (idx=10; idx< 20000; idx +=200)  {
X		n_arc(15000,15000,1000+idx,1000+idx,(float)idx,(float)idx+0.4);
X	}
X}
X
Xplotpattern(size)
Xint size;
X{
X	/* Use the plot(3) interface to draw a bunch of junk, scaled 	*/
X	/* according to the value of size.				*/
X
X	space(0,0,size,size);
X	move(1000,1000);
X	label("This is the BSD plot(3) interface.");
X	circle(1000,1000,100);
X	circle(1000,1000,200);
X	circle(1000,1000,400);
X	circle(1000,1000,800);
X	cont(2000,2000);
X	move(0,0);
X	cont(0,3120);
X	cont(3120,3120);
X	cont(3120,0);
X	cont(0,0);
X}
X
Xplotcircles()  {
X	erase();
X
X	space(0,0,1000,1000);
X
X	move(0,0);
X	cont(999,0);
X	cont(999,999);
X	cont(0,999);
X	cont(0,0);
X
X	circle(500,500,100);
X	circle(500,500,200);
X	circle(500,500,300);
X	circle(500,500,400);
X	circle(500,500,500);
X	circle(500,500,600);
X	circle(500,500,700);
X	circle(500,500,800);
X}
X
Xplotarcs()  {
X	erase();
X
X	arc(500,500,600,500,400,400);
X	arc(500,500,700,500,400,400);
X	arc(500,500,800,500,400,400);
X	arc(500,500,900,500,400,400);
X	arc(500,500,1000,500,400,400);
X	arc(500,500,1100,500,400,400);
X	arc(500,500,1200,500,400,400);
X	arc(500,500,1300,500,400,400);
X}
X
Xint plotstyles()  {
X	space(0,0,1000,1000);
X	erase();
X	move(0,0);
X	cont(1000,0);
X	cont(1000,1000);
X	cont(0,1000);
X	cont(0,0);
X	linemod("dotdashed");
X	line(100,0,900,100);
X	linemod("solid");
X	line(100,100,900,100);
X	line(100,100,900,200);
X	linemod("dotted");
X	line(100,200,900,200);
X	line(100,200,900,300);
X	linemod("shortdashed");
X	line(100,300,900,300);
X	line(100,300,900,400);
X	linemod("longdashed");
X	line(100,400,900,400);
X	line(100,400,900,500);
X	linemod("dotdashed");
X	line(100,500,900,500);
X	line(100,500,900,600);
X	linemod("take the default (solid)");
X	line(100,600,900,600);
X	line(100,600,900,700);
X	linemod("dotted");
X	line(100,700,900,700);
X	line(100,700,900,800);
X	linemod("shortdashed");
X	line(100,800,900,800);
X	line(100,800,900,900);
X	linemod("longdashed");
X	line(100,900,900,900);
X	line(100,900,900,1000);
X}
X
Xtestplot()
X{
X	/* Exercise the plot(3) interface.				*/
X	openpl();
X	plotpattern(3120);
X	plotpattern(6240);
X	plotpattern(12480);
X	gets(str);
X	plotcircles();
X	gets(str);
X	plotarcs();
X	gets(str);
X	plotstyles();
X	gets(str);
X	closepl();
X	exit(0);
X}
X
Xint cursor(x,y)
Xint x, y;
X{
X	n_line(x-800,y,x+800,y);
X	n_line(x,y-1000,x,y+1000);
X	return(0);
X}
X
Xint showcursor()  {
X
X#define MAX_BOUND_ 28000
X#define MIN_BOUND 4000
X
X	int idx,i,j,xinc,yinc;
X
X	if (n_box(0,0,32767,32767)) return(1);
X	if (n_box(1000,1200,31767,31567)) return(1);
X	if (n_box(2000,2400,30767,30367)) return(1);
X
X	g_pix_mode(XOR);
X
X	xinc = 380;
X	yinc = 330;
X	i = 14300;
X	j = 17324;
X
X	cursor (i,j);
X
X	for (idx=0; idx<1600; idx++)  {
X		cursor (i,j);
X		if (i < MIN_BOUND || i > MAX_BOUND_) xinc = - xinc;
X		if (j > MAX_BOUND_) yinc = - yinc - 10;
X		if (j < MIN_BOUND) yinc = - yinc; 
X		i += xinc;
X		j += yinc;
X		cursor (i,j);
X	}
X
X	g_pix_mode(OR);
X
X	return(0);
X}
XxX--EOF--XxX
echo restoring xdemo.c
sed 's/^X//' > xdemo.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) xdemo.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* Cheap clone of an attention getting program I saw on a Xerox workstation.*/
X/* system5 dtlewis 2 2.3.0-U AT */
X/* Tue May 24 22:38:22 EDT 1988 */
X/* by Dave Lewis */
X
X#include <stdio.h>
X#include "config.h"
X#include "gl.h"
X#if MS_DOS
X#include <stdlib.h>
X#define DOS_GET_TIME 0x2c
X#define DOS_KBY_STAT 0x0b;
X#define DOS 0x21
X#endif /* MS_DOS */
X#if MIX_C
X#else
X#include <signal.h>
X#include <time.h>
X#if MS_DOS
X#include <dos.h>
X#endif /* MS_DOS */
X#endif /* MIX_C */
X
X#define MAXINT 32767
X#define NUMLINES 32
X
X#define MSG_COUNT 11
X
X#if MS_DOS
Xstatic REGISTERS inreg, outreg;
X#endif /* MS_DOS */
X
Xvoid border()  {
X	/* Draw a border and text message. */
X	int color;
X	color = g_pix_color(CYAN);
X	n_box(0,0,32767,32767);
X	n_movepen(2000,30000);
X	g_fontctl(2.5, 1.0, 1.0, 0.0, 0.0);
X	n_grafstr("XOR Write Mode");
X	g_pix_color(1);
X	n_line(16383,6000,16383,26767);
X	n_line(6000,16383,26767,16383);
X	g_pix_color(color);
X}
X
Xvoid usage(progname)  
Xchar *progname;
X{
X	fprintf (stderr,"Usage:  %s <mode>\n\n",progname);
X	fprintf (stderr,"Where <mode> is:\n",0);
X	fprintf (stderr,"\t4 (CGA 4 color 320 x 200)\n",0);
X	fprintf (stderr,"\t6 (CGA 2 color 640 x 200)\n",0);
X	fprintf (stderr,"\t8 (Hercules page 0, 720 x 348)\n",0);
X	fprintf (stderr,"\t9 (Hercules page 1, 720 x 348)\n",0);
X	fprintf (stderr,"\t16 (EGA color 640 x 350)\n",0);
X	fprintf (stderr,"\t256 (IBM / Epson compatible printer)\n",0);
X	fprintf (stderr,"\t257 (Laserjet+ printer)\n\n",0);
X}
X
Xvoid pattern()  {
X
X	long x1;
X	long y1;
X	long x2;
X	long y2;
X	int x1rate;
X	int y1rate;
X	int x2rate;
X	int y2rate;
X	int rand();
X	int idx_to_buff;
X	struct endpoints {
X		int x1;
X		int x2;
X		int y1;
X		int y2;
X	} buff[NUMLINES]; 
X
X	/* Initialize.	*/
X
X	/* Modify the slopes and starting location of the endpoint	*/
X	/* motion, to give different patterns every time we run the	*/
X	/* program.							*/
X	x1 = rand();
X	y1 = rand();
X	x2 = rand();
X	y2 = rand();
X	x1rate = rand() & 0x0FF + 256;
X	y1rate = rand() & 0x0FF + 256;
X	x2rate = rand() & 0x0FF + 256;
X	y2rate = rand() & 0x0FF + 256;
X	if (rand() & 0x01) x1rate *= -1;
X	if (rand() & 0x01) y1rate *= -1;
X	if (rand() & 0x01) x2rate *= -1;
X	if (rand() & 0x01) y2rate *= -1;
X
X	/* Initialize the line buffer to invalid values (so they don't	*/
X	/* get plotted).						*/
X
X	for (idx_to_buff=0; idx_to_buff < NUMLINES; idx_to_buff++)  {
X		buff[idx_to_buff].x1 = -1;
X		buff[idx_to_buff].y1 = -1;
X		buff[idx_to_buff].x2 = -1;
X		buff[idx_to_buff].y2 = -1;
X	}
X
X	idx_to_buff = 0;
X
X	/* Start the display pattern.	*/
X
X	/* Loop until <del> key is pressed. */
X	for (;;)  {
X
X#if MS_DOS
X		/* Call to get keyboard status, so DOS can check for	*/
X		/* interrupt signal (^C).				*/
X		inreg.AH = DOS_KBY_STAT;
X		DO_BIOS(DOS, &inreg, &outreg);
X#endif /* MS_DOS */
X
X		/* Increment buffer pointer, wrapping around buffer.	*/
X		++idx_to_buff;
X		idx_to_buff %= NUMLINES;
X
X		/* Erase (redraw in XOR mode) old line. */
X		n_line( buff[idx_to_buff].x1, 
X			buff[idx_to_buff].y1, 
X			buff[idx_to_buff].x2, 
X			buff[idx_to_buff].y2
X			);
X
X		/* Get coordinates of new line. */
X		if (((x1 += x1rate) < 0) || (x1 > MAXINT))  { 
X			x1rate *= -1;
X			x1 += (2 * x1rate);
X			}
X		if (((y1 += y1rate) < 0) || (y1 > MAXINT))  {
X			y1rate *= -1;
X			y1 += (2 * y1rate);
X			}
X		if (((x2 += x2rate) < 0) || (x2 > MAXINT))  {
X			x2rate *= -1;
X			x2 += (2 * x2rate);
X			}
X		if (((y2 += y2rate) < 0) || (y2 > MAXINT))  {
X			y2rate *= -1;
X			y2 += (2 * y2rate);
X			}
X
X		/* Store it in buffer. */
X		buff[idx_to_buff].x1 = x1;
X		buff[idx_to_buff].y1 = y1;
X		buff[idx_to_buff].x2 = x2;
X		buff[idx_to_buff].y2 = y2;
X
X		/* Draw new line. */
X		n_line( buff[idx_to_buff].x1, 
X			buff[idx_to_buff].y1, 
X			buff[idx_to_buff].x2, 
X			buff[idx_to_buff].y2
X			);
X	}
X}
X
Xvoid message()  {
X	/* Write a cute message every time we get a time signal. */
X
X#if MS_DOS
X#else
X	static int msg_count = 0;
X#endif /* MS_DOS */
X	int save_color;
X	int save_pix_mode;
X	save_color = g_pix_color(RED);
X	save_pix_mode = g_pix_mode(XOR);
X	c_cursor(2,2);
X	c_cellstr("Press <Del> to quit...");
X	g_pix_color(save_color);
X	g_pix_mode(save_pix_mode);
X#if MS_DOS
X#else
X	if (msg_count < MSG_COUNT)  {
X		/* Do it MSG_COUNT times, then stop. */
X		signal(SIGALRM,message);
X		alarm(1);
X		msg_count++;
X	}
X	else  {
X		/* Erase the border by redrawing it.	*/
X		border();
X	}
X#endif /* MS_DOS */
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int mode;
X	long timeval;
X	long time();
X	struct tm *timestruct;
X	struct tm *gmtime();
X	void srand();
X
X	/* Get the mode to use. */
X
X	if (argc < 2) mode = ENV_MODE;
X	else if (argc == 2)  {
X		if (sscanf(argv[1],"%d",&(mode)) != 1)  {
X			usage(argv[0]);
X			exit (1);
X		}
X	}
X	else  {
X		usage(argv[0]);
X		exit (1);
X	}
X
X	/* Set video mode.	*/
X	if (g_init(mode))  {
X		usage(argv[0]);
X		fprintf(stderr,"WARNING:  Possible invalid shared memory ",0);
X		fprintf(stderr,"key for requested video mode.\n",0);
X		exit (1);
X	}
X
X	/* Set for XOR mode. */
X	g_pix_mode(XOR);
X
X	/* Set pattern color.	*/
X	g_pix_color(GREEN);
X
X	/* Draw a border and a text message. */
X	border();
X
X#if MS_DOS
X	message();
X#else
X	/* Fork and start flashing a cute message. */
X	if (fork() == 0)  {
X		/* Child process here. */
X		/* Child should exit on receipt of a SIGINT signal	*/
X		signal(SIGINT, SIG_DFL);
X		/* Set a timer to post message. */
X		signal(SIGALRM,message);
X		alarm(3);
X		for(;;) pause();
X	}
X
X	/* Parent process continues here. */
X#endif /* MS_DOS */
X
X	/* Get the current time, and use it as a seed value for the 	*/
X	/* rand() function.						*/
X
X#if MS_DOS
X	/* Get the current time using DOS function 0x2c			*/
X	inreg.AH = DOS_GET_TIME;
X	DO_BIOS(DOS, &inreg, &outreg);
X	srand((unsigned)outreg.DL);
X#else
X	timeval = time((long *) 0);
X	timestruct = gmtime(&timeval);
X	srand((unsigned)timestruct->tm_sec);
X#endif /*MS_DOS */
X
X	/* Draw the pattern.	*/
X
X	pattern();
X}
XxX--EOF--XxX
echo restoring xform.c
sed 's/^X//' > xform.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) xform.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1988
X *	All rights reserved.
X *
X *	Permission is granted to use this for any personal noncommercial use.
X *	You may not distribute source or executable code for profit, nor
X *	may you distribute it with a commercial product without the written
X *	consent of the author.  Please send modifications to the author for
X *	inclusion in updates to the program.  Thanks.
X */
X
X/* Various geometric transformations.					*/
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
Xextern long longsin(), longcos();
X
X/* I_rot_2d_s rotates a point about the origin in two dimensions.	*/
X/* It operates on integer values, and is used used for text rotations	*/
X/* in normalized 2-D coordinate space.					*/
X/* Since this is intended for text, the y values will be scaled		*/
X/* according to the value of graphics.aspect_ratio.			*/
X/* Note that in this coordinate system, the angle is "backwards",	*/
X/* since the origin is in the upper left of the screen.  Since we	*/
X/* normally want a positive angle to appear counterclockwise on the	*/
X/* screen, the angle parameter will normally be negated prior to	*/
X/* calling this routine.						*/
X
Xint i_rot_2d_s(x, y, theta)
Xint *x, *y;
Xdouble theta;
X{
X
X#if NOFLOAT
X	long x_temp = (long)(*x);
X	long y_temp = (long)(*y);
X
X	/* Temporary variable is used to force explicit order of	*/
X	/* integer calculations.  This probably isn't really needed	*/
X	/* with most compilers, but better to be safe than sorry.	*/
X
X	long ltemp;
X
X	/* Scale the (floating point) aspect ratio up to a reasonable	*/
X	/* integer value.						*/
X
X	long lratio = (long)(graphics.aspect_ratio * 16.0);
X
X	/* Pre-calculate the sin and cos values (save calls to trig	*/
X	/* routines.)							*/
X
X	long lsinval = longsin(theta);
X	long lcosval = longcos(theta);
X
X	ltemp = y_temp * lsinval;
X	ltemp /= 16;	/* Scale down first to avoid overflow.		*/
X	ltemp *= lratio;
X
X	*x = (int)((x_temp * lcosval - ltemp) / TRIG_SCALE);
X
X	ltemp = x_temp * lsinval;
X	ltemp /= lratio;
X	ltemp *= 16;	/* Scale it back.	*/
X
X	*y = (int)((ltemp + y_temp * lcosval) / TRIG_SCALE);
X
X#else
X	double x_temp = (double)(*x);
X	double y_temp = (double)(*y);
X
X	/* Pre-calculate the sin and cos values (save calls to trig	*/
X	/* routines.)							*/
X
X	double sinval = sin(theta);
X	double cosval = cos(theta);
X
X	*x = (int)(x_temp * cosval
X		- y_temp * sinval * graphics.aspect_ratio);
X	*y = (int)(x_temp * sinval / graphics.aspect_ratio
X		+ y_temp * cosval);
X
X#endif /* NOFLOAT */
X
X	return(0);
X}
X
X/* I_rot_2d rotates a point about the origin in two dimensions.	*/
X/* It operates on integer values, and is used used for rotations in	*/ 
X/* normalized 2-D coordinate space.					*/
X/* Note that in this coordinate system, the angle is "backwards",	*/
X/* since the origin is in the upper left of the screen.  Since we	*/
X/* normally want a positive angle to appear counterclockwise on the	*/
X/* screen, the angle parameter will normally be negated prior to	*/
X/* calling this routine.						*/
X/* This routine does not account for aspect ratio.			*/
X
Xint i_rot_2d(x, y, theta)
Xint *x, *y;
Xdouble theta;
X{
X
X#if NOFLOAT
X	long x_temp = (long)(*x);
X	long y_temp = (long)(*y);
X
X	/* Pre-calculate the sin and cos values (save calls to trig	*/
X	/* routines.)							*/
X
X	long lsinval = longsin(theta);
X	long lcosval = longcos(theta);
X
X	*x = (int)((x_temp * lcosval - y_temp * lsinval)
X		/TRIG_SCALE);
X	*y = (int)((x_temp * lsinval + y_temp * lcosval)
X		/TRIG_SCALE);
X#else
X	double x_temp = (double)(*x);
X	double y_temp = (double)(*y);
X
X	/* Pre-calculate the sin and cos values (save calls to trig	*/
X	/* routines.)							*/
X
X	double sinval = sin(theta);
X	double cosval = cos(theta);
X
X	*x = (int)(x_temp * cosval - y_temp * sinval);
X	*y = (int)(x_temp * sinval + y_temp * cosval);
X#endif /* NOFLOAT */
X
X	return(0);
X}
X
X
XxX--EOF--XxX


-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.