
Graphics Library for AT Computers Running UNIX (System V/AT, Xenix) and DOS
---------------------------------------------------------------------------

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.  

Various output devices are supported.  For each type of device, one or
more graphics "modes" is defined in modes.h, and the corresponding bitmaps
are defined in bitmaps.h.  These modes roughly correspond to the BIOS
video modes defined for MS-DOS, with additional modes defined for Hercules
compatible modes and for printer output.  The gl.h file should be included 
into user code to declare the graphics routines.  The config.h file may 
also be included for user programs when needed (the other header files are 
intended to be used only by the gl routines). 

Tested system configurations include the following:

OS		Compiler		Device
--------------- ----------------------- -----------------------------------
System V/AT	cc			Hercules compatible
System V/AT	cc			CGA compatible
System V/AT	cc			EGA compatible
System V/AT	cc			IBM or Epson compatible printer
SCO Xenix 286	Microsoft C		EGA compatible (including CGA modes)
MS-DOS		Microsoft C (Xenix)	EGA compatible (including CGA modes)
MS-DOS		Microsoft C (DOS)	EGA compatible (including CGA modes)
MS-DOS		Borland Turbo-C		EGA compatible (including CGA modes)

Other combinations of systems, compilers and output devices should work with 
little or no modification.  

Currently supported video adapters include:

-Hercules compatible monochrome (page 0 and page 1)
-CGA (modes 4 and 6)
-EGA (no color in EGA mode 16)
-VGA (EGA and CGA modes only)

Currently supported printers include:

-IBM graphics printer
-IBM Proprinter
-Epson FX85, 
-Epson LQ1500
-Star10X
-Tandy DMP130
-HP Laserjet+

Additional device support is straightforward, as all routines call 
p_wr_pix() to do output.

The routines are:

	g_init()	Initialize device, buffers, variables.  Attach
			to shared memory segment or malloc'ed buffers.
	g_finish()	Release resources, detach segments.
	g_clear()	Clear screen.
	p_wr_pix()	Write one pixel.
	n_movepen()	Move logical cursor in 32768 x 32768 address space.
	n_point()	Draw point in 32768 x 32768 address space.
	n_draw()	Draw vector.	
	n_line()	Draw line.
	n_box()		Draw box.
	n_ellipse()	Draw ellipse.
	n_arc()		Draw elliptical arc.
	n_grafchar()	Display a vectorized text character (stroke font).
	n_grafstr()	Display a character string, stroke font.
	g_fontctl()	Control size, aspect ratio, spacing, angle and slant 
			of stroke font.
	c_cellchar()	Display a bit mapped character.
	c_cellstr()	Display a string, bit mapped characters.
	c_cursor()	Move to character column and row for c_cellstr().
	g_pix_mode()	Establish OR mode or XOR mode pixel setting, returns
			previous mode value.
	g_pix_color()	Set pixel color, returns previous color value.
	g_weight()	Set line thickness, returns previous value.
	g_style()	Set line style (e.g. dot-dash), returns previous value.

Additional routines:

	plot(3)		Emulation of the BSD plot(3) library:  openpl(), 
			erase(), label(), line(), circle(), arc(), move(), 
			cont(), point(), linemod(), space(), closepl().

Requirements:
-------------

1)  A graphics capable video adapter and/or printer (see above for supported
devices).  

2)  Access to video memory.  For System V/AT, this requires an entry in 
/etc/rc.d/shm.rc to define the shared memory key for your graphics board 
A sample entry for EGA is:

	/etc/shmcreate 0xa0000 a0000 65535		# ega high res

Xenix requires only the appropriate device driver (/dev/EGA), and MS-DOS
has nothing to worry about.  Requirements for 386 UNIX are unknown at this
time.  MS-DOS has no special requirements.

3)  A program or shell script which will cause the graphics adapter to
switch from text to graphics modes, and vice versa (not required for DOS,
but handy nonetheless).  For most configurations, this can be just a shell 
script which echoes the appropriate escape sequences to the console.  The 
mode.sh and mode.xenix scripts are supplied for this purpose, but should 
be tested and modified as needed for your system.  The program mode.c is 
also supplied for use with the Everex Edge.  This program can be modified 
to support various other video adapters which may not respond to the 
console escape sequences (mode.c probably works with a Hercules board, 
also, but this is not tested).  For System V/AT, mode.c needs to be suid 
to root and placed in an appropriate safe directory, but a simple shell 
script (for most video boards on System V/AT or Xenix) will need no special 
treatment.  For MS-DOS, mode switching is done with BIOS calls.

4)  For graphics printing, the printer driver must be in "transparency"
mode, to allow binary data to be sent to the printer without modifications
(such as conversion of <lf> to <cr><lf>).  

For System V/AT, this is done with the "lpget" and "lpset" commands.  
The plotting routines do not set this for you, since the printer is on a 
queue and is assumed to be a shared device.  If more than one person uses 
the printer, it may be a good idea to leave the driver in transparency
mode, and write a filter for normal text line printer output to handle
conversion of <cr> to <cr><lf> along with any other output formatting
that may be required for text.  An alternative method, based on an
undocumented feature of the System V/AT lp driver, is to use minor
numbers 128 and 129 of the lp driver, rather than 0 and 1.  This device
will correspond to the transparent mode of the lp device driver.  The
commands "mknod /dev/lpt0 c 0 128", "link /dev/lpt0 /dev/lpt",
"lpadmin -plpt -v/dev/lpt -elp", "enable lpt" and "/usr/lib/accept lpt"
may be used to set this up (you may need to use "mknod /dev/lpt1 c 0 129"
and "link /dev/lpt0 /dev/lpt", depending on which printer port you are
using.  The lp command then becomes "lp -dlp" (set PRINTPROG in config.h
accordingly).  If the environment variable "PLOTDEV" is defined, it will be
used as the name of the output printer (e.g. "PLOTDEV=lpt; export PLOTDEV"
to use the transparent printer device).

For Xenix, you should configure a printer interface program for transparent
printing (see lpadmin(C) and parallel(HW), along with the section on 
"Printer Interface Programs" in the "Xenix Operations Guide).  This can
be done by modifying one of the supplied printer interface programs (such
as /usr/spool/lp/crnlmap.sh) to include the command "stty -onlcr 0<&1".

For MS-DOS versions, printing is done with BIOS calls, so no special setups
are required.  However, graphics printing may not be done through the
normal MS-DOS print spooler or MS-DOS "PRN:" device, due to unwanted
character conversion.

See the "INSTALL" file for specific instructions for installing on Microport 
System V/AT, Xenix System V 286, or MS-DOS.

How it works:
-------------

For System V/AT, g_init() attaches the shared memory segment for your video
board to your process address space.  For Xenix, g_init opens a device file
and obtains a pointer to video memory.  The pointer to the video memory
segment is used for direct read and write access to bit mapped graphics.

In the case of a printer, g_init() simply allocates some memory buffers which
it treats as the bit map for the printer, then adds some escape codes and
spools the whole mess off to the lp program.

The screen (or printer page) is represented by a normalized address
space of 32768 by 32768.  This gives a reasonable amount of resolution,
and allows valid addresses to be represented by non-negative short integers,
giving efficient calculations and easy checking for addresses that would
be "off the edge of the screen."  All of the output routines, except
p_wr_pix(), use this normalized address space, regardless of the pixel
aspect ratio or the aspect ratio of the physical screen.  

The p_wr_pix() routine uses physical pixel coordinates (row,col)
to access one pixel on the graphics device.  All output, whether lines,
dots or text, use the p_wr_pix() routine at the lowest level.  In
this way, all knowledge of the display bit map, interleaving and 
segmentation are localized to the p_wr_pix() routine.  To add 
support for a new device type, only p_wr_pix() is changed, along 
with the appropriate parameters in bitmaps.h and the g_init() and 
g_finish() routines (for initializing and releasing graphics resources, 
respectively).

Positioning on the screen is done with a "graphics cursor" (not visible
on the screen), which is used to position all graphics and text output.
The cursor is positioned in normalized coordinates using the n_movepen()
routine.  Routines such as n_draw() cause the cursor to be moved to new
positions.

The n_box(), n_line(), n_ellipse() and n_arc() routines, as well as the
stroke font text, call n_movepen() and n_draw() to position the cursor
and draw a vector, respectively.  This is the basis of all the graphical
output, with the low level output handled by p_wr_pix(). 

Two types of text output are supported.  A stroke font is invoked by
n_grafstr(), and a bit cell font is invoked by c_cellstr().  N_grafchar()
and c_cellchar() are single character versions which should normally
not be directly called (just use the n_grafstr() and c_cellstr() versions).
C_cursor() is used to position the graphics cursor in terms of character
rows and columns, as if it were a text cursor.  G_fontctl() is used to
control attributes of the stroke font.

The g_finish() routine detaches shared memory, frees resources, and 
sends any output to the print queue.

All routines are written in C (no assembler at all) and use short integer
arithmetic wherever possible.  Long integers are used when more accuracy
is required, and floats and doubles are avoided wherever possible.  Trig
functions may be done with tables and integer math (if NOFLOAT is defined
in config.h).  The overall performance is quite acceptable, even for text 
output, and is in fact considerably faster than similar code under MS-DOS 
using BIOS rather than p_wr_pix().  The development machine for this 
code is a 6 MHz Zenith 241 with no 80287 coprocessor, hence the avoidance 
of floating point math.

Bugs:
-----

-Pix_mode() does not set XOR mode for EGA high res graphics.  
-Pix_color() does not do anything for EGA high res graphics.
-G_weight() does not do anything (not yet implemented).
-The arc() routine in plot(3) varies slightly from the BSD version in its 
 calculation of the second arc endpoint.
-G_init() sets a signal handler to clean up the screen before exiting, and
-g_finish() restores the handler to its previous value.  This may interfere
 with an application's intended signal handling (the DO_CLEANUP macro in
 config.h can eliminate this behavior).
-For MS-DOS versions, graphics printer output must be done with BIOS calls.  
 Therefore, the default system printer device must be used, and the 
 PLOTDEV environment variable has no meaning.

Limitations:
------------

No checking is done to control ownership of the console output.  The
user of the program is assumed to be at the console.  Any checks for
this would have to be done by an application program using these
routines.

The EGA and VGA adapters control color and writing modes (OR or XOR)
with output to port addresses on the EGA/VGA card.  On System V/AT,
this requires use of the outb() subroutine with write access to /dev/mem.
Since this would require the application program to be suid to root,
support for color and writing modes has not yet been implemented.

The graphics.h file has declarations for parameters that will be used
for various coordinate transformations.  However, none of this is
implemented at the present time (except for the plot(3) interface, with
its "space()" routine).  The only coordinate system which the application 
program should refer to is the normalized 2-D space used to represent 
the screen.

Credits:
--------

Thanks to John Antypas, Denis Fortin and Bill Rankin for assistance in
testing and developing the code.  

The font.h and cellfont.h files contain data for stroke fonts and bit cell
fonts, respectively.  Copyright status of this data is uncertain.  Data 
for the stroke font are derived from listings in _Advanced_Graphics_in_C_, 
by Nelson Johnson (McGraw-Hill, 1987).  The copyright notice for this book
specifically allows copying of the code, but does not say if you need to
have purchased the book to be so entitled.  I recommend the book, in any
case, so you may wish to buy a copy.  The bit cell font was received third
or fourth hand, and is presumed public domain unless I hear otherwise.  The
name at the head of the data file is:

	/* RAM-Loadable Character Sets for the IBM PC
	 Richard Wilton
	 July 1986 */

In any case, if you can locate the font data in your machine's BIOS, you
can use that instead, and you are presumably licenced to do so by virtue
having bought the machine.

The setmode.c code comes from Jeff Turner, and was posted to Usenet
a while back.  It has been modified by me for Everex Edge and Hercules
graphics, and is presumed in the public domain.  

The rest of the material is copyrighted by me, but may be used and
copied by anybody, as long as it is not used for commercial profit.
I would very much appreciate hearing about any bug fixes and new 
device support that may be forthcoming.  Thanks. 


				David T. Lewis  
				umix!m-net!dtlewis!lewis
				122 S. Seventh
				Ann Arbor MI  48103

				system5 dtlewis 2 2.4.0-U AT
				Tue Feb 21 05:44:01 EST 1989

