Graphics Library (part 1 of 5)

Dave Lewis lewis at m2-net.UUCP
Fri Jul 1 13:56:58 AEST 1988


> 
> A library of graphics primitives for System V/AT (and probably any
> other Intel unix, with a bit of hacking) is now available, supporting
> common video cards and printers.  Demonstration programs are included
> with the code.
> 
> Please contact me by e-mail if you would like a copy.  If there is 
> sufficient interest, I will post source (about 130K bytes).
> 
> 	-Dave Lewis
> 

I have received enough requests to justify posting the code for this.
The code is pretty well tested on various uPort 286 configurations
(with CGA, EGA, Hercules, and dot matrix printers).  I would particularly
appreciate it if any users of Xenix 286, Venix, and the various 386 unices 
could try this out and send me the needed changes.  As soon as we have
this running on several flavors of Intel Unix, it may be appropriate
to post to the archives (yes? no? comments?).  Thanks.

			Dave Lewis
			Ann Arbor, MI
			...![ itivax umix ]!m-net!dtlewis!lewis

------------------------------  cut here  ------------------------------
# To recover, type "sh archive"
echo restoring Readme
sed 's/^X//' > Readme <<XxX--EOF--XxX
X
XGraphics library for System V/AT
X--------------------------------
X
XThis collection of routines is designed to provide graphic output to
Xa number of video adapters and printers for PC/AT class computers running
Xunder Microport System V/AT (r).  Various output devices are supported.
XFor each type of device, one or more graphics "modes" is defined in
Xgraphics.h, and the corresponding bitmaps are defined in bitmaps.h.
XThese modes roughly correspond to the BIOS video modes defined for MS-DOS,
Xwith additional modes defined for Hercules (r) and for printer output.
X
XThe routines are:
X
X	init()		Initialize device, buffers, variables.  Attach
X			to shared memory segment or malloc'ed buffers.
X	finish()	Release resources, detach segments.
X	clear()		Clear screen.
X	write_pix()	Turn one pixel on.
X	movpen()	Move logical cursor in 32768 x 32768 address space.
X	draw()		Draw vector.	
X	linedraw()	Draw line.
X	box()		Draw box.
X	grafchar()	Display a vectorized text character (stroke font).
X	grafstr()	Display a character string, stroke font.
X	cellchar()	Display a bit mapped character.
X	cellstr()	Display a string, bit mapped characters.
X	cursor()	Move to character column and row for cellstr().
X	pix_mode()	Establish OR mode or XOR mode pixel setting, returns
X			previous mode value.
X	pix_color()	Set pixel color, returns previous color value.
X
XCurrently supported devices are Hercules mono, CGA, EGA (currently mono only),
Xand dot matrix printers (IBM, IBM Proprinter, Epson FX85, Star10X, Tandy 
XDMP130, and probably others).  Additional device support is straightforward, 
Xas all routines call write_pix() to do output.
X
X
XRequirements:
X-------------
X
X1)  A graphics capable video adapter and/or printer (see above for supported
Xdevices).  
X
X2)  An entry in /etc/rc.d/shm.rc to define the shared memory key for your
Xgraphics board.  A sample entry for EGA is:
X
X	/etc/shmcreate 0xa0000 a0000 65535		# ega high res
X
X3)  A program or shell script which will cause the graphics adapter to
Xswitch from text to graphics modes, and vice versa.  For most configurations,
Xthis can be just a shell script which echoes the appropriate escape sequences
Xto the console.  The mode.sh script is supplied for this purpose, but
Xshould be tested and modified as needed for your system. The program
Xmode.c is also supplied for use with the Everex Edge.  This program can
Xbe modified to support various other video adapters which may not respond
Xto the console escape sequences (mode.c probably works with a Hercules
Xboard, also, but this is not tested).  Mode.c needs to be suid to root
Xand placed in an appropriate safe directory, but a simple shell script
Xwill need no special treatment.    
X
X4)  For graphics printing, the printer driver must be in "transparency"
Xmode.  This is done with the "lpget" and "lpset" commands.  The plotting
Xroutines do not set this for you, since the printer is on a queue and
Xis assumed to be a shared device.  If more than one person uses the
Xprinter, it would 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 <lf> to <cr><lf> along with any other output formatting that 
Xmay be required for text.  An alternative method, based on an undocumented
Xfeature of the lp driver, is to use minor numbers 128 and 129 of the lp
Xdriver, rather than 0 and 1.  This device will correspond to the transparent
Xmode of the lp device driver.  The commands "mknod /dev/lpt0 c 0 128",
X"link /dev/lpt0 /dev/lpt", "lpadmin -plpt -v/dev/lpt -elp", "enable lpt"
Xand "/usr/lib/accept lpt" may be used to set this up (you may need to
Xuse "mknod /dev/lpt1 c 0 129" and "link /dev/lpt0 /dev/lpt", depending on
Xwhich printer port you are using.  The lp command then becomes "lp -dlp"
X(set PRINTPROG in graphics.h accordingly).  If the environment variable
X"PLOTDEV" is defined, it will be used as the name of the output printer
X(e.g. "PLOTDEV=lpt; export PLOTDEV" to use the transparent printer device).
X
X
XHow it works:
X-------------
X
XInit() attaches the shared memory segment for your video board to your
Xprocess address space.  The pointer to this memory segment is used for
Xdirect read and write access to bit mapped graphics.  In the case of
Xa printer, init() simply allocates some memory buffers which it 
Xtreats like the bit map for the printer, then adds some escape codes
Xand spools 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
Xwrite_pix(), use this normalized address space, regardless of the pixel
Xaspect ratio or the aspect ratio of the physical screen.  
X
XThe write_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 write_pix() routine at the lowest level.  In
Xthis way, all knowledge of the display bit map, interleaving and 
Xsegmentation are localized to the write_pix() routine.  To add support
Xfor a new device type, only write_pix() is changed, along with the
Xappropriate parameters in bitmaps.h and the init() and finish() routines
X(for initializing and releasing graphics resources, respectively).
X
XPositioning on the screen is done with a "graphics cursor," which
Xis used to position all graphics and text output.  The cursor is
Xpositioned in normalized coordinates using the movepen() routine.
XRoutines such as draw() cause the cursor to be moved to new positions.
X
XThe box() and linedraw() routines, as well as the stroke font text,
Xcall movepen() and draw() to position the cursor and draw a vector, 
Xrespectively.  This is the basis of all the graphical output, with
Xthe low level output handled by write_pix().
X
XTwo types of text output are supported.  A stroke font is invoked by
Xgrafstr(), and a bit cell font is invoked by cellstr().  Grafchar()
Xand cellchar() are single character versions which should normally
Xnot be directly called (just use the grafstr() and cellstr() versions).
XCursor() is used to position the graphics cursor in terms of character
Xrows and columns, as if it were a text cursor.
X
XThe 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.  The
Xoverall performance is quite acceptable, even for text output, and is 
Xin fact considerably faster than similar code under MS-DOS using BIOS
Xrather than write_pix().  The development machine for this code is a
X6 MHz Zenith 241 with no 80287 coprocessor, hence the avoidance of floating
Xpoint math.
X
XBugs:
X-----
X
XPix_mode() does not set XOR mode for EGA high res graphics.  
XPix_color() does not do anything for EGA high res graphics.
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
XThese routines have been tested by the author only on an Everex Edge
Xvideo card, emulating CGA modes 4 and 6, and Hercules graphics.  Printer
Xoutput has been tested only on a Tandy DMP 130 (IBM printer mode).  
XOther users have verified EGA mode and various printers.
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.  The only coordinate system which the
Xapplication program should refer to is the normalized 2-D space used
Xto represent the screen.  It is important to realize that even an object
Xas simple as a circle will require additional coordinate transformations
Xto handle aspect ratio.
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.  The copyright status of this data is uncertain.
XThe stroke font is taken from _Advanced_Graphics_in_C_, by Nelson
XJohnson (McGraw-Hill, 1987).  The copyright notice for this book specifically
Xallows copying of the code, but does not say if you need to have purchased
Xthe book to be so entitled.  I recommend the book, in any case, so you may
Xwish to buy a copy.  The bit cell font was received third or fourth hand,
Xand is presumed public domain unless I hear otherwise.  The name at the
Xhead 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 the net
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.3.0-U AT
X				Wed Jun 29 23:48:47 EDT 1988
X
X
X
XxX--EOF--XxX
echo restoring Things_to_do
sed 's/^X//' > Things_to_do <<XxX--EOF--XxX
XThings that need to be added to enhance the graphics routines:
X
X
XVolunteers needed:
X------------------
X
X-Test and/or port to uPort 386 unix.  I don't know if this works
Xlike the 286 version or not.  
X
X-Port to Xenix 286 and 386.  This will require someone with a Xenix
Xsystem to figure out how to get a pointer to video memory (this is
Xreputedly explained in the screen(HW) section of the manual), and add
Xsome suitable #ifdef code in init.c and finish.c.  We also will need 
Xto make an appropriate mode changing script (using the stty command, 
XI think).  
X
X-Add additional device support (VGA, Laserjet, enhanced EGA boards).
X
X
XThings I'll probably get around to doing myself:
X------------------------------------------------
X
X-Add XOR and color support to EGA.
X
X-Add polygon fill routines.
X
X-Add circle/ellipse routines.
X
X-Get plot(3) and plot(1) working.
X
X-Add windows, viewports, 3-D transforms, etc.
X
X
X
X			Wed Jun 29 23:53:34 EDT 1988 dtl
X
XxX--EOF--XxX
echo restoring graphics.1
sed 's/^X//' > graphics.1 <<XxX--EOF--XxX
X.\" dummy line
X.TH GRAPHICS 3 "29 June 1988"
X.UC 4
X.SH NAME
Xinit, finish, clear, write_pix, movpen, draw, linedraw, box,
Xgrafchar, grafstr, cellchar, cellstr, cursor, pix_mode, pix_color
X\- graphics primitives for pc clone unix systems.
X.SH SYNOPSIS
X.nf
X.B int init(mode)
Xint mode;
X.PP
X.B int finish()
X.PP
X.B int clear()
X.PP
X.B int write_pix(x,y)
Xint x, y;
X.PP
X.B int movpen(x,y)
Xint x, y;
X.PP
X.B int draw(x,y)
Xint x, y;
X.PP
X.B int linedraw(x1,y1,x2,y2)
Xint x1, y1, x2, y2;
X.PP
X.B int box(x1, y1, x2, y2)
Xint x1, y1, x2, y2;
X.PP
X.B int grafchar(asc_char,x,y,vsize,hsize)
Xunsigned char asc_char;
Xint x, y, vsize, hisize;
X.PP
X.B int grafstr(strng,x,y,vsize,hsize,spacing)  
Xchar strng[];
Xint x, y, vsize, hsize, spacing;
X.PP
X.B int cellchar(asc_char)
Xunsigned char asc_char;
X.PP
X.B int cellstr(strng)
Xchar strng[];
X.PP
X.B int cursor(row,col)
Xint row, col;
X.PP
X.B enum PIX_MODE {OR, XOR} pix_mode(mode_val)
Xenum PIX_MODE mode_val;
X.PP
X.B int pix_color(color)
Xint color;
X.br
X.SH DESCRIPTION
XThis collection of routines is designed to provide graphic output
Xto a number of video adapters and printers for PC clone computers
Xrunning unix operating systems.  
X.PP
XVarious output devices are supported, including CGA, EGA, Hercules 
Xand dot matrix printers.  For each type of device, one or more 
Xgraphics "modes" is defined in graphics.h, and the corresponding 
Xbitmaps are defined in bitmaps.h.  These modes roughly correspond 
Xto the BIOS video modes defined for MS-DOS, with additional modes 
Xdefined for Hercules and for printer output.
X.PP
XThe
X.I init
Xroutine initializes device, buffers, variables, and attaches 
Xshared memory segment or malloc'ed buffers to the calling process.
X.PP
XThe
X.I finish
Xroutine releases resources and detaches memory segments.
X.PP
XThe
X.I clear
Xroutine clears the screen (or printer buffer area). 
X.PP
XThe
X.I write_pix
Xroutine activates a pixel.  If the current writing mode is OR, 
Xthe pixel is turned on (set to the currently active color).  If 
Xthe current writing mode is XOR, the pixel value (color) is XORed 
Xwith its current value.
X.PP
XThe
X.I movpen
Xroutine moves the logical cursor in normalized 32768 x 32768 
Xaddress space, where (0,0) is the upper left corner of the screen
Xor printed page.
X.PP
XThe
X.I draw
Xroutine draws a vector from the current address to (x,y) in 
Xnormalized address space.
X.PP
XThe
X.I linedraw
Xroutine draws a line from (x1,y1) to (x2,y2) in normalized address 
Xspace.
X.PP
XThe
X.I box
Xroutine draws a box with corners at (x1, y1) and (x2, y2) in 
Xnormalized address space.
X.PP
XThe
X.I grafchar
Xroutine displays a vectorized (stroke font) text character 
Xasc_char located at (x,y), of height vsize by width hsize.
X.PP
XThe
X.I grafstr
Xroutine displays a character string using a stroke font.
X.PP
XThe
X.I cellchar
Xroutine displays a bit mapped character at the current location.
X.PP
XThe
X.I cellstr
Xroutine displays a string at the current location, using bit mapped 
Xcharacters.
X.PP
XThe
X.I cursor
Xroutine moves the graphics cursor to a position corresponding to
Xa character row and column.  This is used for easy positioning of text
Xdrawn with the 
X.I cellstr 
Xroutine.
X.PP
XThe
X.I pix_mode
Xroutine establishes the active OR mode or XOR mode pixel 
Xsetting mode, and returns the previous mode value.
X.PP
XThe
X.I pix_color
Xroutine sets the active pixel color, and returns previous color 
Xvalue.
X.SH AUTHOR
XDavid T Lewis, Ann Arbor, MI, USA
X.br
X(...!m-net!dtlewis!lewis)
X.SH BUGS
XThe 
X.I pix_mode
Xroutine does not set XOR mode for EGA high res graphics.  
X.PP
XThe
X.I pix_color 
Xroutine does not do anything for EGA high res graphics.
X.SH CAVEATS
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 must be done by the application program.
X.PP
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() routine 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
XxX--EOF--XxX
echo restoring xdemo.c
sed 's/^X//' > xdemo.c <<XxX--EOF--XxX
X#ifndef lint
Xstatic char sccsid[] = "@(#) xdemo.c 1.9 88/06/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 <signal.h>
X#include <stdio.h>
X#include <time.h>
X#include "graphics.h"
X#define MAXINT 32767
X#define NUMLINES 32
X
X#define MSG_COUNT 20
X
Xint init();
Xint linedraw();
Xint finish();
Xenum PIX_MODE pix_mode();
Xint pix_color();
Xint clear();
Xint grafstr();
X
Xvoid sig_catch() {
X	/* Clean up and exit. */
X	finish();
X	system("mode 2");
X	exit(0);
X}
X
Xstatic int msg_count = 0;
Xvoid message()  {
X	/* Write a cute message every time we get a time signal. */
X	int save_color;
X	enum PIX_MODE save_pix_mode;
X	save_color = pix_color(3);
X	save_pix_mode = pix_mode(XOR);
X	cursor(2,2);
X	cellstr("Press <Del> to quit...");
X	pix_color(save_color);
X	pix_mode(save_pix_mode);
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}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
Xchar buffer[80];
Xint mode = 8;
Xlong x1;
Xlong y1;
Xlong x2;
Xlong y2;
Xint x1rate;
Xint y1rate;
Xint x2rate;
Xint y2rate;
Xlong timeval;
Xlong time();
Xstruct tm *timestruct;
Xstruct tm *gmtime();
Xvoid srand();
Xint rand();
Xint (*signal ())();
X
Xstruct endpoints {
X	int x1;
X	int x2;
X	int y1;
X	int y2;
X} buff[NUMLINES]; 
X
Xint idx_to_buff, idx;
X
X/* Initialize the line buffer to invalid values (so they don't get plotted). */
X
Xfor (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	}
Xidx_to_buff = 0;
X
X/* Get the mode to use. */
Xif (argc == 2)  {
X	mode = 0;
X	mode = *(argv[1]) - '0';
X	init(mode);
X	strcpy(buffer,"mode ");
X	strcat(buffer,argv[1]);
X	system(buffer);
X	}
Xelse {
X	printf("usage:  xdemo mode\n\n	mode = {4,6,8,16}\n\nAssuming CGA hi-res graphics mode...",0);
X	init(6);
X	system("mode 6");
X	}
X
X/* Clear the video display. */
Xclear();
X
X/* Get the current time, and use it as a seed value for the rand() function. */
Xtimeval = time((long *) 0);
Xtimestruct = gmtime(&timeval);
Xsrand((unsigned)timestruct->tm_sec);
X
X/* Modify the slopes and starting location of the endpoint motion, to give */
X/* different patterns every time we run the program.	*/
Xx1 = rand();
Xy1 = rand();
Xx2 = rand();
Xy2 = rand();
Xx1rate = rand() & 0x0FF + 256;
Xy1rate = rand() & 0x0FF + 256;
Xx2rate = rand() & 0x0FF + 256;
Xy2rate = rand() & 0x0FF + 256;
Xif (rand() & 0x01) x1rate *= -1;
Xif (rand() & 0x01) y1rate *= -1;
Xif (rand() & 0x01) x2rate *= -1;
Xif (rand() & 0x01) y2rate *= -1;
X
X/* Draw a border and a text message. */
Xpix_color(3);
Xbox(0,0,32767,32767);
Xgrafstr("XOR Write Mode",10000,31000,220,120,800);
Xpix_color(1);
Xlinedraw(16383,6000,16383,26767);
Xlinedraw(6000,16383,26767,16383);
Xpix_color(2);
X
X/* Set for XOR mode. */
Xpix_mode(XOR);
X
X/* Fork and start flashing a cute message. */
Xif (fork())  {
X	/* Child process here. */
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
X/* Catch interrupt signals. */
Xsignal (SIGINT, sig_catch);
X
X/* Loop for a while. */
Xwhile (msg_count < MSG_COUNT)  {
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	linedraw( 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	linedraw( 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/* Restart the pattern. */
X
Xfor (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
Xidx_to_buff = 0;
X
Xclear();
X
X/* Loop until <del> key is pressed. */
Xfor (;;)  {
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	linedraw( 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	linedraw( 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}
XxX--EOF--XxX
-- 
Dave Lewis
Ann Arbor, MI
...![ itivax umix ]!m-net!dtlewis!lewis



More information about the Comp.unix.xenix mailing list