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

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

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


The "gl" collection of routines provides graphic device support for a 
number of video adapters and printers for PC/AT class computers running
under Microport System V/AT, Xenix or MS-DOS.    The routines emulate
the BSD plot(3) library, as well as provide new routines.  It runs
under MSDOS/ System V/AT, SCO Xenix 286, and with Hercules, CGA, EGA,
and Epson printer devices.

# To recover, type "sh archive"
echo restoring Readme
sed 's/^X//' > Readme <<XxX--EOF--XxX
X
XGraphics Library for AT Computers Running UNIX (System V/AT, Xenix) and DOS
X---------------------------------------------------------------------------
X
XThe "gl" collection of routines provides graphic device support for a 
Xnumber of video adapters and printers for PC/AT class computers running
Xunder Microport System V/AT, Xenix or MS-DOS.  
X
XVarious output devices are supported.  For each type of device, one or
Xmore graphics "modes" is defined in modes.h, and the corresponding bitmaps
Xare defined in bitmaps.h.  These modes roughly correspond to the BIOS
Xvideo modes defined for MS-DOS, with additional modes defined for Hercules
Xcompatible modes and for printer output.  The gl.h file should be included 
Xinto user code to declare the graphics routines.  The config.h file may 
Xalso be included for user programs when needed (the other header files are 
Xintended to be used only by the gl routines). 
X
XTested system configurations include the following:
X
XOS		Compiler		Device
X--------------- ----------------------- -----------------------------------
XSystem V/AT	cc			Hercules compatible
XSystem V/AT	cc			CGA compatible
XSystem V/AT	cc			EGA compatible
XSystem V/AT	cc			IBM or Epson compatible printer
XSCO Xenix 286	Microsoft C		EGA compatible (including CGA modes)
XMS-DOS		Microsoft C (Xenix)	EGA compatible (including CGA modes)
XMS-DOS		Microsoft C (DOS)	EGA compatible (including CGA modes)
XMS-DOS		Borland Turbo-C		EGA compatible (including CGA modes)
X
XOther combinations of systems, compilers and output devices should work with 
Xlittle or no modification.  
X
XCurrently supported video adapters include:
X
X-Hercules compatible monochrome (page 0 and page 1)
X-CGA (modes 4 and 6)
X-EGA (no color in EGA mode 16)
X-VGA (EGA and CGA modes only)
X
XCurrently supported printers include:
X
X-IBM graphics printer
X-IBM Proprinter
X-Epson FX85, 
X-Epson LQ1500
X-Star10X
X-Tandy DMP130
X-HP Laserjet+
X
XAdditional device support is straightforward, as all routines call 
Xp_wr_pix() to do output.
X
XThe routines are:
X
X	g_init()	Initialize device, buffers, variables.  Attach
X			to shared memory segment or malloc'ed buffers.
X	g_finish()	Release resources, detach segments.
X	g_clear()	Clear screen.
X	p_wr_pix()	Write one pixel.
X	n_movepen()	Move logical cursor in 32768 x 32768 address space.
X	n_point()	Draw point in 32768 x 32768 address space.
X	n_draw()	Draw vector.	
X	n_line()	Draw line.
X	n_box()		Draw box.
X	n_ellipse()	Draw ellipse.
X	n_arc()		Draw elliptical arc.
X	n_grafchar()	Display a vectorized text character (stroke font).
X	n_grafstr()	Display a character string, stroke font.
X	g_fontctl()	Control size, aspect ratio, spacing, angle and slant 
X			of stroke font.
X	c_cellchar()	Display a bit mapped character.
X	c_cellstr()	Display a string, bit mapped characters.
X	c_cursor()	Move to character column and row for c_cellstr().
X	g_pix_mode()	Establish OR mode or XOR mode pixel setting, returns
X			previous mode value.
X	g_pix_color()	Set pixel color, returns previous color value.
X	g_weight()	Set line thickness, returns previous value.
X	g_style()	Set line style (e.g. dot-dash), returns previous value.
X
XAdditional routines:
X
X	plot(3)		Emulation of the BSD plot(3) library:  openpl(), 
X			erase(), label(), line(), circle(), arc(), move(), 
X			cont(), point(), linemod(), space(), closepl().
X
XRequirements:
X-------------
X
X1)  A graphics capable video adapter and/or printer (see above for supported
Xdevices).  
X
X2)  Access to video memory.  For System V/AT, this requires an entry in 
X/etc/rc.d/shm.rc to define the shared memory key for your graphics board 
XA sample entry for EGA is:
X
X	/etc/shmcreate 0xa0000 a0000 65535		# ega high res
X
XXenix requires only the appropriate device driver (/dev/EGA), and MS-DOS
Xhas nothing to worry about.  Requirements for 386 UNIX are unknown at this
Xtime.  MS-DOS has no special requirements.
X
X3)  A program or shell script which will cause the graphics adapter to
Xswitch from text to graphics modes, and vice versa (not required for DOS,
Xbut handy nonetheless).  For most configurations, this can be just a shell 
Xscript which echoes the appropriate escape sequences to the console.  The 
Xmode.sh and mode.xenix scripts are supplied for this purpose, but should 
Xbe tested and modified as needed for your system.  The program mode.c is 
Xalso supplied for use with the Everex Edge.  This program can be modified 
Xto support various other video adapters which may not respond to the 
Xconsole escape sequences (mode.c probably works with a Hercules board, 
Xalso, but this is not tested).  For System V/AT, mode.c needs to be suid 
Xto root and placed in an appropriate safe directory, but a simple shell 
Xscript (for most video boards on System V/AT or Xenix) will need no special 
Xtreatment.  For MS-DOS, mode switching is done with BIOS calls.
X
X4)  For graphics printing, the printer driver must be in "transparency"
Xmode, to allow binary data to be sent to the printer without modifications
X(such as conversion of <lf> to <cr><lf>).  
X
XFor System V/AT, this is done with the "lpget" and "lpset" commands.  
XThe plotting routines do not set this for you, since the printer is on a 
Xqueue and is assumed to be a shared device.  If more than one person uses 
Xthe printer, it may be a good idea to leave the driver in transparency
Xmode, and write a filter for normal text line printer output to handle
Xconversion of <cr> to <cr><lf> along with any other output formatting
Xthat may be required for text.  An alternative method, based on an
Xundocumented feature of the System V/AT lp driver, is to use minor
Xnumbers 128 and 129 of the lp driver, rather than 0 and 1.  This device
Xwill correspond to the transparent mode of the lp device driver.  The
Xcommands "mknod /dev/lpt0 c 0 128", "link /dev/lpt0 /dev/lpt",
X"lpadmin -plpt -v/dev/lpt -elp", "enable lpt" and "/usr/lib/accept lpt"
Xmay be used to set this up (you may need to use "mknod /dev/lpt1 c 0 129"
Xand "link /dev/lpt0 /dev/lpt", depending on which printer port you are
Xusing.  The lp command then becomes "lp -dlp" (set PRINTPROG in config.h
Xaccordingly).  If the environment variable "PLOTDEV" is defined, it will be
Xused as the name of the output printer (e.g. "PLOTDEV=lpt; export PLOTDEV"
Xto use the transparent printer device).
X
XFor Xenix, you should configure a printer interface program for transparent
Xprinting (see lpadmin(C) and parallel(HW), along with the section on 
X"Printer Interface Programs" in the "Xenix Operations Guide).  This can
Xbe done by modifying one of the supplied printer interface programs (such
Xas /usr/spool/lp/crnlmap.sh) to include the command "stty -onlcr 0<&1".
X
XFor MS-DOS versions, printing is done with BIOS calls, so no special setups
Xare required.  However, graphics printing may not be done through the
Xnormal MS-DOS print spooler or MS-DOS "PRN:" device, due to unwanted
Xcharacter conversion.
X
XSee the "INSTALL" file for specific instructions for installing on Microport 
XSystem V/AT, Xenix System V 286, or MS-DOS.
X
XHow it works:
X-------------
X
XFor System V/AT, g_init() attaches the shared memory segment for your video
Xboard to your process address space.  For Xenix, g_init opens a device file
Xand obtains a pointer to video memory.  The pointer to the video memory
Xsegment is used for direct read and write access to bit mapped graphics.
X
XIn the case of a printer, g_init() simply allocates some memory buffers which
Xit treats as the bit map for the printer, then adds some escape codes and
Xspools the whole mess off to the lp program.
X
XThe screen (or printer page) is represented by a normalized address
Xspace of 32768 by 32768.  This gives a reasonable amount of resolution,
Xand allows valid addresses to be represented by non-negative short integers,
Xgiving efficient calculations and easy checking for addresses that would
Xbe "off the edge of the screen."  All of the output routines, except
Xp_wr_pix(), use this normalized address space, regardless of the pixel
Xaspect ratio or the aspect ratio of the physical screen.  
X
XThe p_wr_pix() routine uses physical pixel coordinates (row,col)
Xto access one pixel on the graphics device.  All output, whether lines,
Xdots or text, use the p_wr_pix() routine at the lowest level.  In
Xthis way, all knowledge of the display bit map, interleaving and 
Xsegmentation are localized to the p_wr_pix() routine.  To add 
Xsupport for a new device type, only p_wr_pix() is changed, along 
Xwith the appropriate parameters in bitmaps.h and the g_init() and 
Xg_finish() routines (for initializing and releasing graphics resources, 
Xrespectively).
X
XPositioning on the screen is done with a "graphics cursor" (not visible
Xon the screen), which is used to position all graphics and text output.
XThe cursor is positioned in normalized coordinates using the n_movepen()
Xroutine.  Routines such as n_draw() cause the cursor to be moved to new
Xpositions.
X
XThe n_box(), n_line(), n_ellipse() and n_arc() routines, as well as the
Xstroke font text, call n_movepen() and n_draw() to position the cursor
Xand draw a vector, respectively.  This is the basis of all the graphical
Xoutput, with the low level output handled by p_wr_pix(). 
X
XTwo types of text output are supported.  A stroke font is invoked by
Xn_grafstr(), and a bit cell font is invoked by c_cellstr().  N_grafchar()
Xand c_cellchar() are single character versions which should normally
Xnot be directly called (just use the n_grafstr() and c_cellstr() versions).
XC_cursor() is used to position the graphics cursor in terms of character
Xrows and columns, as if it were a text cursor.  G_fontctl() is used to
Xcontrol attributes of the stroke font.
X
XThe g_finish() routine detaches shared memory, frees resources, and 
Xsends any output to the print queue.
X
XAll routines are written in C (no assembler at all) and use short integer
Xarithmetic wherever possible.  Long integers are used when more accuracy
Xis required, and floats and doubles are avoided wherever possible.  Trig
Xfunctions may be done with tables and integer math (if NOFLOAT is defined
Xin config.h).  The overall performance is quite acceptable, even for text 
Xoutput, and is in fact considerably faster than similar code under MS-DOS 
Xusing BIOS rather than p_wr_pix().  The development machine for this 
Xcode is a 6 MHz Zenith 241 with no 80287 coprocessor, hence the avoidance 
Xof floating point math.
X
XBugs:
X-----
X
X-Pix_mode() does not set XOR mode for EGA high res graphics.  
X-Pix_color() does not do anything for EGA high res graphics.
X-G_weight() does not do anything (not yet implemented).
X-The arc() routine in plot(3) varies slightly from the BSD version in its 
X calculation of the second arc endpoint.
X-G_init() sets a signal handler to clean up the screen before exiting, and
X-g_finish() restores the handler to its previous value.  This may interfere
X with an application's intended signal handling (the DO_CLEANUP macro in
X config.h can eliminate this behavior).
X-For MS-DOS versions, graphics printer output must be done with BIOS calls.  
X Therefore, the default system printer device must be used, and the 
X PLOTDEV environment variable has no meaning.
X
XLimitations:
X------------
X
XNo checking is done to control ownership of the console output.  The
Xuser of the program is assumed to be at the console.  Any checks for
Xthis would have to be done by an application program using these
Xroutines.
X
XThe EGA and VGA adapters control color and writing modes (OR or XOR)
Xwith output to port addresses on the EGA/VGA card.  On System V/AT,
Xthis requires use of the outb() subroutine with write access to /dev/mem.
XSince this would require the application program to be suid to root,
Xsupport for color and writing modes has not yet been implemented.
X
XThe graphics.h file has declarations for parameters that will be used
Xfor various coordinate transformations.  However, none of this is
Ximplemented at the present time (except for the plot(3) interface, with
Xits "space()" routine).  The only coordinate system which the application 
Xprogram should refer to is the normalized 2-D space used to represent 
Xthe screen.
X
XCredits:
X--------
X
XThanks to John Antypas, Denis Fortin and Bill Rankin for assistance in
Xtesting and developing the code.  
X
XThe font.h and cellfont.h files contain data for stroke fonts and bit cell
Xfonts, respectively.  Copyright status of this data is uncertain.  Data 
Xfor the stroke font are derived from listings in _Advanced_Graphics_in_C_, 
Xby Nelson Johnson (McGraw-Hill, 1987).  The copyright notice for this book
Xspecifically allows copying of the code, but does not say if you need to
Xhave purchased the book to be so entitled.  I recommend the book, in any
Xcase, so you may wish to buy a copy.  The bit cell font was received third
Xor fourth hand, and is presumed public domain unless I hear otherwise.  The
Xname at the head of the data file is:
X
X	/* RAM-Loadable Character Sets for the IBM PC
X	 Richard Wilton
X	 July 1986 */
X
XIn any case, if you can locate the font data in your machine's BIOS, you
Xcan use that instead, and you are presumably licenced to do so by virtue
Xhaving bought the machine.
X
XThe setmode.c code comes from Jeff Turner, and was posted to Usenet
Xa while back.  It has been modified by me for Everex Edge and Hercules
Xgraphics, and is presumed in the public domain.  
X
XThe rest of the material is copyrighted by me, but may be used and
Xcopied by anybody, as long as it is not used for commercial profit.
XI would very much appreciate hearing about any bug fixes and new 
Xdevice support that may be forthcoming.  Thanks. 
X
X
X				David T. Lewis  
X				umix!m-net!dtlewis!lewis
X				122 S. Seventh
X				Ann Arbor MI  48103
X
X				system5 dtlewis 2 2.4.0-U AT
X				Tue Feb 21 05:44:01 EST 1989
X
XxX--EOF--XxX
echo restoring c_cellch.c
sed 's/^X//' > c_cellch.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) c_cellch.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/* Write a graphics character to the screen.				*/
X/* This routine uses bit mapped character cell fonts.			*/
X/* The character will be drawn such that the current graphics cursor	*/
X/* denotes the upper left corner of the character cell.  The graphics	*/
X/* cursor will be incremented in the X direction by an amount corres-	*/
X/* ponding to one character cell.  The location of the graphics cursor	*/
X/* may be set by calls to either c_cursor() or p_movepen() prior	*/
X/* calling this routine.	 					*/
X
X/* Tue Mar 15 22:46:31 EST 1988						*/
X/* system5 dtlewis 2 2.3.0-U AT						*/
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X#include "cellfont.h"
X
Xextern struct GL_graphics graphics;
Xextern int p_wr_pix(), n_movepen();
X
Xint c_cellchar(asc_char)  
Xunsigned char asc_char;
X{
X	int x, y, i, j;
X	int istat = 0;
X
X	char *bits; 
X
X	/* Get the pixel location.					*/
X	x = n_to_p_x(graphics.x_cursor);
X	y = n_to_p_y(graphics.y_cursor);
X
X	/* Check for x or y off the screen.			*/
X#if INT16
X	/* 16 bit integers, use simple check.			*/
X        if (x < 0 ) return(1);
X        if (y < 0 ) return(1);
X#else
X	/* Use explicit check.					*/
X        if ((x < 0) || (x > NRM_X_RANGE)) return(1);
X        if ((y < 0) || (y > NRM_X_RANGE)) return(1);
X#endif /* INT16 */
X
X	/* Increment the graphics cursor.				*/
X
X	if (n_movepen(graphics.x_cursor + graphics.cellfont.xtic,
X		graphics.y_cursor)) istat = 1;
X
X	/* Point at the character bit map to print.			*/
X	bits = (char *) &(charcell[asc_char * Y_CELL_BITS]);
X
X	/* Write the character.						*/
X	for (i=y; i < y + Y_CELL_BITS; i++, bits++) {
X		j=x;
X		if (*bits & 0x80) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x40) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x20) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x10) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x08) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x04) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x02) if (p_wr_pix(j,i)) istat = 1; j++;
X		if (*bits & 0x01) if (p_wr_pix(j,i)) istat = 1; j++;
X	}
X
X	return(istat);
X}
XxX--EOF--XxX
echo restoring c_cellst.c
sed 's/^X//' > c_cellst.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) c_cellst.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/* Write string of a graphics characters to the screen.			*/
X/* Sat Mar 19 23:56:46 EST 1988						*/
X/* system5 dtlewis 2 2.3.0-U AT						*/
X
X/* Routine to display cell mode text string with upper left corner of	*/
X/* first character located at the current graphics cursor.  The		*/
X/* graphics cursor is incremented as characters are written.		*/
X
X#include <stdio.h>
X#include "config.h"
Xextern int c_cellchar();
X
Xint c_cellstr(strng)  
Xchar strng[];
X{
X	int i;
X	for(i=0; strng[i] != 0; i++)  {
X		if (c_cellchar(strng[i])) return(1);
X	}
X	return(0);
X}
X
XxX--EOF--XxX
echo restoring c_cursor.c
sed 's/^X//' > c_cursor.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) c_cursor.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/* Move the graphics cursor as if it were a text cursor.  The cursor	*/
X/* is positioned such that a cell character may be drawn at the		*/
X/* specified character row and column.					*/
X/* This routine uses bit mapped character cell fonts.			*/
X/* The character will be drawn such that the current graphics cursor	*/
X/* denotes the upper left corner of the character cell.			*/
X
X/* Columns and rows are numbered 1 through N, not 0 through N !!!!	*/
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
Xextern int n_movepen();
X
Xint c_cursor(row, col)
Xint row, col;
X{
X	long xval, yval;
X
X	/* Check valid range for this screen type.			*/
X	if (col <= 0 || col > graphics.cellfont.chars_per_line) return(1);
X	if (row <= 0 || row > graphics.cellfont.lines_per_screen) return(1);
X
X	/* Move the graphics cursor.					*/
X
X	/* Calculate size of pixel, and move cursor accordingly.  The	*/
X	/* calculations are rearranged for computational accuracy, and	*/
X	/* the results rounded up to put us on the correct pixel.	*/
X
X	xval = NRM_X_RANGE * X_CELL_BITS * (col-1) / graphics.x_extent;
X	xval++;	/* Round up.	*/
X
X	yval = NRM_Y_RANGE * Y_CELL_BITS * (row-1) / graphics.y_extent;
X	yval++;
X
X	if (n_movepen((int)xval, (int)yval)) return(1);
X
X	return(0);
X}
XxX--EOF--XxX
echo restoring g_clear.c
sed 's/^X//' > g_clear.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) g_clear.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/*
X *	Routine to clear video memory (or print buffer memory).  
X *	dtlewis 6-28-87
X *	Sun Mar 13 21:13:59 EST 1988
X */
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X#include "modes.h"
X
Xextern int g_init(), g_finish();
X
Xint g_clear()  
X{
X	extern struct GL_graphics graphics;
X	int i, j;
X	int istat;
X
X#if MIX_C
X	/* No long pointers with this compiler.  Cheat and use BIOS.	*/
X	g_setmod(graphics.grafmode);
X	return(0);
X#endif /* MIX_C */
X
X	switch (graphics.grafmode) {
X		case CGA_COLOR_MODE:
X			for(i=0; i<100; i++)  {
X				for(j=0; j<80; j++)  {
X					(graphics.cgamem)->page1[i][j] = 0x0;
X					(graphics.cgamem)->page2[i][j] = 0x0;
X				}
X			}
X			break;
X
X		case CGA_HI_RES_MODE:
X			for(i=0; i<100; i++)  {
X				for(j=0; j<80; j++)  {
X					(graphics.cgamem)->page1[i][j] = 0x0;
X					(graphics.cgamem)->page2[i][j] = 0x0;
X				}
X			}
X			break;
X
X		case EGA_COLOR_MODE:
X			for (i=0 ; i<350 ; i++) {
X				for (j=0 ; j<80 ; j++) {
X					(graphics.egamem)->mem[i][j] = 0x0;
X				}
X			}
X			break;
X
X		case HERC_P0_MODE:
X		case HERC_P1_MODE:
X			for(i=0; i<87; i++)  {
X				for(j=0; j<90; j++)  {
X					(graphics.hercmem)->page1[i][j] = 0x0;
X					(graphics.hercmem)->page2[i][j] = 0x0;
X					(graphics.hercmem)->page3[i][j] = 0x0;
X					(graphics.hercmem)->page4[i][j] = 0x0;
X				}
X			}
X			break;
X
X		/* For hard copy, there is no point in clearing	*/
X		/* memory.  We will interpret this call as	*/
X		/* "done with this page; send it to the printer	*/
X		/* and get ready for another."			*/
X
X		case IBM_PRINTER:
X			if ((istat=g_finish()) != 0) return(istat);
X			if ((istat=g_init(IBM_PRINTER)) != 0) return(istat);
X			break;
X
X		case LJ_PRINTER:
X			if ((istat=g_finish()) != 0) return(istat);
X			if ((istat=g_init(LJ_PRINTER)) != 0) return(istat);
X			break;
X
X		default:
X			return(1);
X
X	}
X	return(0);
X}
XxX--EOF--XxX
echo restoring n_box.c
sed 's/^X//' > n_box.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_box.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/* Fri Jul  3 23:43:36 EDT 1987
X * dtlewis
X * Routine to draw a box.
X */
X
Xextern int n_movepen(), n_draw();
X
Xint n_box(x1,y1,x2,y2)  
X	int x1, y1, x2, y2;
X{
X	int n_movepen(), n_draw();
X	if (n_movepen(x1,y1)) return(1);
X	if (n_draw(x2,y1)) return(1);
X	if (n_draw(x2,y2)) return(1);
X	if (n_draw(x1,y2)) return(1);
X	if (n_draw(x1,y1)) return(1);
X	return(0);
X}
XxX--EOF--XxX
echo restoring n_draw.c
sed 's/^X//' > n_draw.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_draw.c 5.1 89/02/20";
X#endif
X
X/*
X *	Copyright (c) David T. Lewis 1987, 1988, 1989
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/*  Sat Mar 21 22:59:10 EST 1987 */
X/*  dtl 2-8-87
X**
X**	Write a line on the CGA or Hercules adapter.
X**	This routine assumes that the current graphics cursor position is
X**	set, and draws a line to the indicated point.
X*/
X
X#include "config.h"
X#include "bitmaps.h"
X#include "graphics.h"
X#include "gf_types.h"
X
X#define ROT_MASK (0x80000000L)
X
Xextern struct GL_graphics graphics;
Xextern int (*p_do_pix)();
X
Xn_draw(new_x_cursor,new_y_cursor)  
X	int new_x_cursor, new_y_cursor;
X{
X
X        /* Draw line from current cursor to new position. */
X        /* Parameters are in normalized 2-D coordinates. */
X
X        int x_dist;     /* Pixel coordinates */
X        int y_dist;     /* Pixel coordinates */
X        int x_start;    /* Pixel coordinates */
X        int y_start;    /* Pixel coordinates */
X        int x_final; 	/* Pixel coordinates */
X        int y_final; 	/* Pixel coordinates */
X        int x_current;  /* Pixel coordinates */
X        int y_current;  /* Pixel coordinates */
X	int x_pixels;	/* X distance in pixels */
X	int y_pixels;	/* Y distance in pixels */
X        long int slope;
X        int offset;
X        long int idx;
X
X	/* Check for out of range.  If either the start or end	*/
X	/* point would be off the screen, then we have a	*/
X	/* problem.						*/
X
X#if INT16
X	/* 16 bit integers, use simple check.			*/
X	if (graphics.x_cursor < 0 || graphics.y_cursor < 0 || 
X		new_x_cursor < 0 || new_y_cursor < 0)
X#else
X	/* Use explicit check.					*/
X	if (	(graphics.x_cursor < 0) 
X		|| (graphics.x_cursor > NRM_X_RANGE) 
X		|| (graphics.y_cursor < 0) 
X		|| (graphics.y_cursor > NRM_Y_RANGE) 
X		|| (new_x_cursor < 0)
X		|| (new_x_cursor > NRM_X_RANGE)
X		|| (new_y_cursor < 0)
X		|| (new_y_cursor > NRM_Y_RANGE))
X#endif /* INT16 */
X	{
X		/* Advance the cursor to the new position, even if	*/
X		/* it is not a valid location.  In the case where the	*/
X		/* current cursor is invalid but the new value is good,	*/
X		/* this will correct the problem.  In the case where	*/
X		/* the new value is bad, we will want to leave it that	*/
X		/* way for the next invocation of n_draw().		*/
X		graphics.x_cursor = new_x_cursor;
X		graphics.y_cursor = new_y_cursor;
X		return(1);
X	}
X
X        /* Find the starting point in pixel coordinates. */
X  
X        x_current = x_start = n_to_p_x(graphics.x_cursor);
X        y_current = y_start = n_to_p_y(graphics.y_cursor);
X
X        /* Find the end point in pixel coordinates. */
X  
X        x_final = n_to_p_x(new_x_cursor);
X        y_final = n_to_p_y(new_y_cursor);
X
X	/* Find the distances in pixel coordinates. */
X
X        x_dist = x_final - x_start;
X        y_dist = y_final - y_start;
X
X	/* Find the number of pixels to travel in the x any y directions. */
X
X	x_pixels = abs(x_dist);
X	y_pixels = abs(y_dist);
X
X        /* Step across the screen pixel by pixel.  Do this in the x 	*/
X        /* direction if x_dist is greater than y_dist; else, do it in	*/
X        /* the y direction.						*/
X
X        if (x_pixels > y_pixels) {
X                /* Stepwise in x direction. */
X
X                /* Calculate the slope to use (rise over run). */
X                /* Shift left 16 bits for precision. */
X                if (x_dist != 0) slope = (long)y_dist * 0x010000L / 
X                (long)x_dist;
X                else slope = 0x7FFFFFFFL; /* Infinity */
X
X                /* Figure a fudge factor to be used in offsetting the */
X                /* pixels by 1/2 pixel. */
X                if (slope > 0) offset = 1;
X                else if (slope < 0) offset = -1;
X                else offset = 0;
X
X                /* Write the line on the screen. */
X
X                if (x_final - x_start >= 0)  {
X                        if (slope==0)  {
X                                while (x_current <= x_final)
X					if ((*p_do_pix)(x_current++, 
X						y_current)) return(1);
X                        }
X                        else for (idx=0; idx <= x_pixels; idx++, x_current++)  {
X                                y_current = y_start + (idx*slope/0x08000L 
X                                + offset)/2;
X                                if ((*p_do_pix)(x_current, y_current))
X					return(1);
X                        }
X                }
X                else  {
X                        if (slope==0)  {
X				while (x_current >= x_final)
X                                        if ((*p_do_pix)(x_current--, 
X						y_current)) return(1);
X                        }
X                        else for (idx=0; idx <= x_pixels; idx++, x_current--)  {
X                                y_current = y_start - (idx*slope/0x08000L 
X                                + offset)/2;
X                                if ((*p_do_pix)(x_current, y_current)) 
X					return(1);
X                        }
X                }
X        }
X        else  {
X                /* Stepwise in y direction. */
X
X                /* Calculate the inverse slope to use (run over rise). */
X                /* Shift left 16 bits for precision. */
X                if (y_dist != 0) slope = (long)x_dist * 0x010000L / 
X                (long)y_dist;
X                else slope = 0x7FFFFFFF; /* Infinity */
X
X                /* Figure a fudge factor to be used in offsetting the */
X                /* pixels by 1/2 pixel. */
X                if (slope > 0) offset = 1;
X                else if (slope < 0) offset = -1;
X                else offset = 0;
X
X               /* Write the line on the screen. */
X
X                if (y_final - y_start >= 0)  {
X                        if (slope==0)  {
X                                while (y_current <= y_final)
X                                        if ((*p_do_pix)(x_current, 
X						y_current++)) return(1);
X                        }
X                        else for (idx=0; idx <= y_pixels; idx++, y_current++)  {
X                                x_current = x_start + (idx*slope/0x08000L 
X                                + offset)/2;
X                                if ((*p_do_pix)(x_current, y_current))
X					return(1);
X                        }
X                }
X                else  {
X                        if (slope==0)  {
X				while (y_current >= y_final)
X                                        if ((*p_do_pix)(x_current, 
X						y_current--)) return(1);
X                        }
X                        else for (idx=0; idx <= y_pixels; idx++, y_current--)  {
X                                x_current = x_start - (idx*slope/0x08000L 
X                                + offset)/2;
X                                if ((*p_do_pix)(x_current, y_current))
X					return(1);
X                        }
X                }
X        }
X        /* Advance the cursor to the new position. */
X        graphics.x_cursor = new_x_cursor;
X        graphics.y_cursor = new_y_cursor;
X	return(0);
X}
XxX--EOF--XxX
echo restoring n_gfchar.c
sed 's/^X//' > n_gfchar.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_gfchar.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/* Adapted from a routine in _Advanced_Graphics_in_C_, by Nelson	*/
X/* Johnson, McGraw-Hill, 1987.						*/
X
X/* Write a graphics character to the screen; advance cursor.		*/
X/* Sat Dec 12 12:51:27 EST 1987						*/
X/* system5 dtlewis 2 2.2-U AT						*/
X
X#include "config.h"
X#if MIX_C
X#else
X#include <math.h>
X#endif /* MIX_C */
X#include "font.h"
X#include "bitmaps.h"
X#include "graphics.h"
X
Xextern struct GL_graphics graphics;
X
Xextern int i_rot_2d_s();
Xextern int n_line(), n_movepen();
Xextern long longsin();
X
Xint n_grafchar(asc_char)
Xunsigned char asc_char;
X{
X	int x, y, x_1, y_1, x_2, y_2, i;
X	int istat = 0;
X	double theta;
X	float sin_slant;
X	long l_sin_slant;
X	int xscale, yscale, xinc, yinc;
X	int tempval;
X
X	union  
X		{
X		struct  
X			{
X			unsigned xval_2 : 4;
X			unsigned yval_2 : 4;
X			unsigned xval_1 : 4;
X			unsigned yval_1 : 4;
X			}  nibble;
X		struct
X			{
X			unsigned word;
X			}  whole;
X		}  fontline;
X
X	x = graphics.x_cursor;
X	y = graphics.y_cursor;
X
X	xscale = graphics.strokefont.xsize;
X	yscale = graphics.strokefont.ysize;
X	xinc = graphics.strokefont.xtic;
X	yinc = 0;
X
X	/* Calculate rotation angle for text and cursor motion.		*/
X
X	if (graphics.strokefont.angle_flag)  {
X
X		theta = - (double)(graphics.strokefont.angle);
X		i_rot_2d_s( &xinc, &yinc, theta);
X	}
X
X	for (i=0; i<=35; i++)  {
X		if ((fontline.whole.word = stroke[asc_char][i]) != 0xFFFF) {
X
X			/* Get the endpoints for this stroke line.	*/
X
X			x_1 = fontline.nibble.xval_1 * xscale;
X			y_1 = fontline.nibble.yval_1 * yscale;
X			x_2 = fontline.nibble.xval_2 * xscale;
X			y_2 = fontline.nibble.yval_2 * yscale;
X
X			/* Slant characters if necessary.		*/
X
X			if (graphics.strokefont.slant_flag)  {
X
X				/* We want to slant the top of the 	*/
X				/* character to the right, rather than	*/
X				/* slanting the bottom to the left.	*/
X				/* Use tempval as an offset.		*/
X
X				tempval = yscale * FONTSIZE;
X
X#if NOFLOAT  /* Use integer math for speed.	*/
X
X				l_sin_slant
X					= longsin(graphics.strokefont.slant);
X
X				x_1 += (int)((l_sin_slant * (tempval - y_1))
X					/ TRIG_SCALE);
X				x_2 += (int)((l_sin_slant * (tempval - y_2))
X					/ TRIG_SCALE);
X
X#else  /* Use normal math library.	*/
X
X				sin_slant
X					= (float)sin(graphics.strokefont.slant);
X
X				x_1 += (int)(sin_slant * (float)(tempval - y_1));
X				x_2 += (int)(sin_slant * (float)(tempval - y_2));
X
X#endif /* NOFLOAT */
X			}
X
X			/* If necessary, rotate vectors based on angle.	*/
X
X			if (graphics.strokefont.angle_flag)  {
X
X				i_rot_2d_s( &x_1, &y_1, theta);
X				i_rot_2d_s( &x_2, &y_2, theta);
X			}
X
X			/* Translate to screen location.		*/
X
X			x_1 += x;
X			y_1 += y;
X			x_2 += x;
X			y_2 += y;
X
X			/* Draw the line.				*/
X
X			if (n_line( x_1, y_1, x_2, y_2)) istat = 1;
X		}
X	}
X
X	/* Move the cursor.						*/
X
X	if (n_movepen(x + xinc, y + yinc)) istat = 1;
X
X	return(istat);
X}
X
XxX--EOF--XxX
echo restoring n_gfstr.c
sed 's/^X//' > n_gfstr.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) n_gfstr.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/* Write string of a graphics characters to the screen.			*/
X/* Sat Dec 12 12:51:27 EST 1987						*/
X/* system5 dtlewis 2 2.2-U AT						*/
X
X#include <stdio.h>
X
Xextern int n_grafchar();
X
Xint n_grafstr(strng)  
Xchar strng[];
X{
X	int i;
X	for(i=0; strng[i] != 0; i++)  {
X		if (n_grafchar(strng[i])) return(1);
X	}
X	return(0);
X}
X
XxX--EOF--XxX


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