[net.sources] GNUPLOT 1.1: part 6 of 6

williams@vu-vlsi.UUCP (01/28/87)

GNUPLOT 1.1: part 6 of 6

This shar file contains two VMS-specific files (compile.com, link.com)
and a bunch of PC-specific files.  You can ignore these files if your
installing GNUPLOT on a UNIX machine.

-------------------------------CUT HERE--------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	compile.com
#	link.com
#	buildhlp.c
#	corgraph.asm
#	corplot.c
#	header.mac
#	help.c
#	help.hlm
#	hrcgraph.asm
#	lineproc.mac
#	link.opt
#	make.msc
#	pcgraph.asm
# This archive created: Wed Jan 28 12:04:30 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'compile.com'" '(560 characters)'
if test -f 'compile.com'
then
	echo shar: will not over-write existing file "'compile.com'"
else
cat << \SHAR_EOF > 'compile.com'
$! make sure you SET TERM/NOWRAP before running GNUPLOT!
$ CFLAGS = "NOTHING"
$ TERMFLAGS = "AED,HP26,HP75,POSTSCRIPT,QMS,REGIS,TEK,V384"
$ set verify
$ cc/define=('CFLAGS') command.c
$ cc/define=('CFLAGS') eval.c
$ cc/define=('CFLAGS') graphics.c
$ cc/define=('CFLAGS') internal.c
$ cc/define=('CFLAGS') misc.c
$ cc/define=('CFLAGS') parse.c
$ cc/define=('CFLAGS') plot.c
$ cc/define=('CFLAGS') scanner.c
$ cc/define=('CFLAGS') standard.c
$ cc/define=('CFLAGS','TERMFLAGS') term.c
$ cc/define=('CFLAGS') util.c
$ cc/define=('CFLAGS') version.c
$ set noverify
SHAR_EOF
if test 560 -ne "`wc -c < 'compile.com'`"
then
	echo shar: error transmitting "'compile.com'" '(should have been 560 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'link.com'" '(130 characters)'
if test -f 'link.com'
then
	echo shar: will not over-write existing file "'link.com'"
else
cat << \SHAR_EOF > 'link.com'
$ link/exe=gnuplot command,eval,graphics,internal,misc,parse,plot,scanner, -
standard,[]term,util,version,sys$library:vaxcrtl/lib
SHAR_EOF
if test 130 -ne "`wc -c < 'link.com'`"
then
	echo shar: error transmitting "'link.com'" '(should have been 130 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'buildhlp.c'" '(2366 characters)'
if test -f 'buildhlp.c'
then
	echo shar: will not over-write existing file "'buildhlp.c'"
else
cat << \SHAR_EOF > 'buildhlp.c'
/*
 * buildhlp.c  -- a program to build an MS-DOS help tree from a VMS .HLP file
 * Colin Kelley
 * January 1987
 */

#include <stdio.h>
#include <ctype.h>

#define TRUE 1
#define FALSE 0

#define HELPMAIN "HELP.HLM"
#define EXT ".HLP"

char cwd[80];
char buffer[10000];

int currlevel, nextlevel;
char currname[13], nextname[13];

int line = 1;

main(argc,argv)
int argc;
char *argv[];
{
register char *bptr;
register int c;
FILE *f;
int done = FALSE;

	if (argc != 2) {
		fprintf(stderr,"usage:  %s start-dir < helpfile\n\n",argv[0]);
		fprintf(stderr,"  where <start-dir> is the directory in which to start building the tree\n");
		fprintf(stderr,"  and <helpfile> is in VMS help file format\n");
		exit(1);
	}

	getcwd(cwd,sizeof(cwd));
	if (chdir(argv[1]) == -1) {
		perror("can't chdir() to starting directory");
		exit_err(argv[1]);
	}


	if (scanf("%d %8s",&currlevel,currname) != 2)
		exit_err("scanf() error");

	do {
		for (c = currlevel*2 - 1; --c;)
			putchar(' ');
		puts(currname);

		strcat(currname,EXT);

		while ((c = getchar()) != EOF && c != '\n')
			;
		if (c == '\n')
			line++;

		if ((c = getchar()) != EOF && c != ' ')
			ungetc(c,stdin);

		bptr = buffer;
		while ((c = getchar()) != EOF) {
			*bptr++ = c;
			if (c == '\n') {
				line++;
				if ((c = getchar()) != EOF) {
					if (c != ' ')
						ungetc(c,stdin);		/* push it back */
					if (isdigit(c))
						break;
				}
			}
		}
		*bptr = '\0';

		if (c == EOF) {
			done = TRUE;
			nextlevel = 1;
		}
		else {
			if (scanf("%d %8s",&nextlevel,nextname) != 2)
				exit_err("scanf() error");
		}

		if (!done && nextlevel > currlevel) {	/* have a subtopic */
			if (chdir(currname) == -1) {	/* does it already exist? */
				if (mkdir(currname) == -1) {
					perror("mkdir()");
					exit_err(currname);
				}
				if (chdir(currname) == -1) {
					perror("chdir()");
					exit_err(currname);
				}
			}
			f = fopen(HELPMAIN,"w");
		}
		else
			f = fopen(currname,"w");

		while (nextlevel <= --currlevel)
			if (chdir("..") == -1) {
				perror("chdir()");
				exit_err("..");
			}

		if (f == NULL) {
			perror("fopen()");
			exit_err(currname);
		}
		fputs(buffer,f);
		fclose(f);

		currlevel = nextlevel;
		strcpy(currname,nextname);

	} while (!done);

	chdir(cwd);
	exit(0);
}

exit_err(msg)
char msg[];
{
	fprintf(stderr,"%s (input line %d)\n",msg,line);
	chdir(cwd);
	exit(1);
}
SHAR_EOF
if test 2366 -ne "`wc -c < 'buildhlp.c'`"
then
	echo shar: error transmitting "'buildhlp.c'" '(should have been 2366 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'corgraph.asm'" '(2272 characters)'
if test -f 'corgraph.asm'
then
	echo shar: will not over-write existing file "'corgraph.asm'"
else
cat << \SHAR_EOF > 'corgraph.asm'
TITLE	Corona graphics module
;	Colin Kelley
;	January 1987

include header.mac

if1
include lineproc.mac
endif


_text	segment

public	_GrInit,_GrReset,_GrOnly,_TxOnly,_GrandTx,_Cor_line,_Cor_mask

corpixel proc near
	ror word ptr linemask,1
	jc cont
	ret
cont:	push bp
	mov bp,sp
	push ax
	push bx
	push cx
	mov es,ScSeg
	shl bx,1			; y
	mov bx,word ptr LookUp[bx] ; bx has y mem address
	mov cl,al			; x
	and cl,7
	shr ax,1
	shr ax,1
	shr ax,1			; ax /= 8
	add bx,ax
	mov al,1
	shl al,cl			; al contains bit mask
	or byte ptr es:[bx],al
	pop cx
	pop bx
	pop ax
	pop bp
	ret

lineproc _Cor_line, corpixel

beginproc _GrInit
	push bp
	mov bp,sp
	push di
	mov ax, [bp+X]			; screen number (0 - 7)
	mov cl,11
	shl ax,cl			; multiply by 2048 to get segment
	mov ScSeg,ax			; save segment for later
	push ax
	mov es, ax
	xor ax,ax
	mov di,ax
	mov cx, 4000h
	cld
	rep stosw
	pop cx
	call near ptr GrAddr
	mov ax,es
	pop di
	pop bp
	ret
_GrInit	endp

beginproc _GrReset
	mov cx, 0
	call near ptr GrAddr
	ret
_GrReset endp

GrAddr	proc near
	mov dx,3b4h			; address of 6845
	mov al,0ch			; register 12
	out dx,al
	inc dx
	mov al,ch			; Graphics Segment High
	out dx,al
	dec dx
	mov al,0dh			; register 13
	out dx,al
	mov al,cl			; Graphics Segment Low
	inc dx
	out dx,al
	ret
GrAddr	endp

beginproc _GrOnly
	mov dx,3b8h
	mov al,0a0h
	out dx,al
	ret
_GrOnly	endp

beginproc _TxOnly
	mov dx,3b8h
	mov al,28h
	out dx,al
	ret
_TxOnly	endp

beginproc _GrandTx
	mov dx,3b8h
	mov al,0a8h
	out dx,al
	ret
_GrandTx endp

beginproc _Cor_mask
	push bp
	mov bp,sp
	mov ax,[bp+x]			; mask
	mov linemask,ax
	pop bp
	ret
_Cor_mask endp

corpixel endp

_text	ends
 

_data	segment
linemask dw -1
ScSeg	dw 0
_data	ends

const	segment

K	equ 1024

mem_mac	MACRO x
	dw x,2*K+x,4*K+x,6*K+x,8*K+x,10*K+x,12*K+x,14*K+x,16*K+x
	dw 18*K+x,20*K+x,22*K+x,24*K+x
	ENDM
LookUp	equ $
	mem_mac 0
	mem_mac 80
	mem_mac (80*2)
	mem_mac (80*3)
	mem_mac (80*4)
	mem_mac (80*5)
	mem_mac (80*6)
	mem_mac (80*7)
	mem_mac (80*8)
	mem_mac (80*9)
	mem_mac (80*10)
	mem_mac (80*11)
	mem_mac (80*12)
	mem_mac (80*13)
	mem_mac (80*14)
	mem_mac (80*15)
	mem_mac (80*16)
	mem_mac (80*17)
	mem_mac (80*18)
	mem_mac (80*19)
	mem_mac (80*20)
	mem_mac (80*21)
	mem_mac (80*22)
	mem_mac (80*23)
	mem_mac (80*24)

const	ends

	end
SHAR_EOF
if test 2272 -ne "`wc -c < 'corgraph.asm'`"
then
	echo shar: error transmitting "'corgraph.asm'" '(should have been 2272 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'corplot.c'" '(839 characters)'
if test -f 'corplot.c'
then
	echo shar: will not over-write existing file "'corplot.c'"
else
cat << \SHAR_EOF > 'corplot.c'
#include <stdio.h>
#include <process.h>
#include <dos.h>

#define BOUNDARY 32768
#define segment(addr) (FP_SEG(m) + ((FP_OFF(m)+15) >> 4));
#define round(value,boundary) (((value) + (boundary) - 1) & ~((boundary) - 1))

char *malloc(),*realloc();

char prog[] = "gnuplot";
char corscreen[] = "CORSCREEN=0";

main()
{
register unsigned int segm,start;
char *m;
	if (!(m = malloc(BOUNDARY))) {
		printf("malloc() failed\n");
		exit(1);
	}
	segm = segment(m);
	start = round(segm,BOUNDARY/16);

	if (realloc(m,BOUNDARY+(start-segm)*16) != m) {
		printf("can't realloc() memory\n");
		exit(2);
	}

	if ((segm = start >> 11) >= 8) {
		printf("not enough room in first 256K\n");
		exit(3);
	}

	corscreen[sizeof(corscreen)-2] = '0' + segm;
	if (putenv(corscreen))
		perror("putenv");

	if (spawnlp(P_WAIT,prog,prog,NULL))
		perror("spawnlp");
}
SHAR_EOF
if test 839 -ne "`wc -c < 'corplot.c'`"
then
	echo shar: error transmitting "'corplot.c'" '(should have been 839 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'header.mac'" '(920 characters)'
if test -f 'header.mac'
then
	echo shar: will not over-write existing file "'header.mac'"
else
cat << \SHAR_EOF > 'header.mac'
if1
COMPACT	equ 1			; define your memory model here

ifdef	SMALL
	; default, so do nothing
	else

ifdef	MEDIUM
	LARGE_CODE equ 1
	else

ifdef	COMPACT
	LARGE_DATA equ 1
	else

ifdef	LARGE
	LARGE_DATA equ 1
	LARGE_CODE equ 1

else
	%out No memory model defined--assuming SMALL

endif	; LARGE
endif	; COMPACT
endif	; MEDIUM
endif	; SMALL


beginproc macro procname

ifdef	LARGE_CODE
	procname proc far
else
	procname proc near
endif	; LARGE_CODE

	endm	; beginproc


endif	; if1


_TEXT	SEGMENT	BYTE PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT WORD PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT WORD PUBLIC 'BSS'
_BSS	ENDS

DGROUP	GROUP	CONST, _BSS, _DATA
	assume cs:_text, ds:dgroup, ss:dgroup, es:dgroup

; define X as the offset of first argument on stack frame

ifdef LARGE_CODE
	X	equ 6			; return offset and segment + old BP
else
	X	equ 4			; return offset + old BP
endif	; LARGE_CODE
SHAR_EOF
if test 920 -ne "`wc -c < 'header.mac'`"
then
	echo shar: error transmitting "'header.mac'" '(should have been 920 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'help.c'" '(19751 characters)'
if test -f 'help.c'
then
	echo shar: will not over-write existing file "'help.c'"
else
cat << \SHAR_EOF > 'help.c'
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <conio.h>
#include <signal.h>
#include <ctype.h>
#include <direct.h>
#include <process.h>
#include <string.h>
#include <dos.h>
 
/*****************************************************************************
 *  HELP
 *
 *  This program provides a HELP environment similar to the VMS help facility.
 *  Instead of using a help library, however, this version uses a directory 
 *  tree of text files.  This was done primarily to allow easy editing and 
 *  addition of help entries.
 *
 *  The set of arguments passed from DOS is first scanned for switches.  Then 
 *  the remaining arguments are passed to the main help routine as a single
 *  string which is reparsed.  This was done to allow easy recursion.
 *
 *  Similar to the public domain help utility found on many UNIX systems, a 
 *  help directory contains five possible entries in it.
 *        main help text:          HELP.HLM
 *        manual page name:        HELP.MAN
 *        subtopic texts:          <topicname>.HLP
 *        subtopic directories:    <topicname>
 *
 *  Due to the filename size limitation of DOS, command line tokens are
 *  limited to eight characters.
 */

#define HELPVER         "HELP - VMS-like help utility\nVersion 1.0.014NL  -  6 January 1986\nRobert P. Scott\nDTS Engineering & Consulting\n29 Heritage Circle\nHudson, NH  03051-3427\n(603)886-1383\n"

#define STDDELIM        " \r\n\t;"          /* delimiters for parsing */
#define HELPMAIN        "HELP.HLM"          /* main help text filename */
#define MAXENT          128                 /* maximum number of help entries*/
#define HELPEX          ".HLP"              /* help extension */
#define SWITCHR1        '-'                 /* unix like switch char */
#define SWITCHR2        '/'                 /* PC/MS-DOS std switch char */
#define PROMPT          "Topic? "
#define DEFSEARCH       "*.HLP"             /* Default search string */
#define R_OK            04
#define MAXLINELEN      90
#define MAXNAMELEN      13                  /* max length of NAME */
#define COLUMNSPACE     4
#define TERMWID         76
#define HELPDIR         "."
#define ALL             0x37
#define DEFSCRLEN       17

int         scrnlen;
int         status;
int         olddisk;
char        dent[MAXENT][MAXNAMELEN];
char        lent1[MAXENT][MAXLINELEN];
char        lent2[MAXENT][MAXLINELEN];
char        progname[MAXNAMELEN+4];
char        olddir[MAXLINELEN];
char        newdir[MAXLINELEN];
char        currdir[MAXLINELEN];
char        prompt[MAXLINELEN];
char        *helpdir;
char        dta[80];

int help(char *);
int outhelp(char *);
int allsel(void);
void set_dta(char *);
void select_disk(int);
int dir_get(char *,int );
char *gettok(char *,char *,char *,char *);
int isdelim(char ,char *);
int more(char *);
int pgbrk(void);
void stripnl(char *);
void setprompt(void);
void fstobs(char *);
void handler(void);
int kget(void);

void main(argc, argv)
int argc;
char *argv[];
    {
    char        inbuf[MAXLINELEN];
    int         il;                         /* input buffer length */
    int         sl;                         /* token length */
    int         done;                       /* temporary flag */
    char        c;                          /* temporary char holder */
    char        *op;                        /* single argument pointer */
        
    strcpy( progname,*argv++ );         /* Always save the program name */

    helpdir = getenv( "HELP" );         /* use EV for directory if set */    
	olddisk = curr_disk();				/* save our starting disk */
    getcwd( olddir, MAXLINELEN );       /* save our starting directory */

    if ( signal( SIGINT, handler ) < 0 )    /* uh oh */
        {
        fprintf( stderr, "%s could not set SIGINT.  Action undefined upon INT\n", progname );
        }
        
    argc--;
    while (( argc ) && ( ( c = *(*argv) ) == SWITCHR1 ) || ( c == SWITCHR2 ))
        {        /* must be options */
        for (op = *argv; *op != '\0'; op++) 
            {
            switch(*op) 
                {
                case SWITCHR1 :    /* ignore first and extras */
                case SWITCHR2 :
                    break;
 
                case 'd' :    /* specifying help directory path explicitly */
                    helpdir = *++argv;
                    break;
 
                case 'h' :
                case 'v' :      /* show version number */
                    fprintf( stdout, HELPVER );
                    bye( 0 );
                    
                default:
                    fprintf(stderr,"%s: %c: bad option.\n",
                    progname,*op);
                    break;
                }   /* switch */
            }   /* for ( steps through token ) */
        argc--; argv++;
        }   /* while ( loops on argv arguments ) */
 
    if (helpdir == NULL)        /* if all else fails, use default */
        helpdir = HELPDIR;
 
    fstobs( helpdir );           /* normalize to dos directory seps */

	if (isalpha(helpdir[0]) && helpdir[1] == ':')
		select_disk(helpdir[0] - 'A');
    if (chdir(helpdir) < 0)     /* move to the help root */
        {
        fprintf(stderr,"%s: %s: help directory not found.\n",
            progname,helpdir);
        bye(1);
        }
 
    done = il = 0;                             /* reset input length */
    inbuf[0] = 0;                       /* start with a null buffer */
    while ( ( argc ) && ( *argv ) && !done )   /* concat. all remaining args */
        {
        sl = strlen( *argv );           /* new token length */
        if ( ( il + sl ) < MAXLINELEN ) /* if enough room for added token */
            {
            if ( il && ( il < MAXLINELEN ) )    /* if not the first token */
                {
                strcat( inbuf, " " );   /* add a space */
                strcat( inbuf, *argv ); /* and add the token */
                }
            else                        /* the first token */
                strcpy( inbuf, *argv ); /* copy in the first token */
            il += sl + 1;               /* adjust the inbuf length ctr */
            }
        else                            /* no more room for added tokens */
            done = 1;                   /* and we don't want junk added */            
        argv++;
        argc--;
        }

    strupr( inbuf );                    /* convert to upper case */    
    help( inbuf );
         
	bye(0);
    }
 

/****************************************************************************
 */
help( buf )
char    *buf;
    {
    enum {BOTH, JUSTMENU, NONE} subj;	/* choice of .HLM and menu */
    int     done = 0;
    char    lbuf[MAXLINELEN];           /* local temporary copy */
    char    tbuf[MAXLINELEN];           /* local token buffer */
	char	*bufptr;
    int     lbufl, bufl;                /* buffer lengths */

	subj = BOTH;
    for( ;; )                      /* loop until user is tired */
        {
        if ( !buf || !*buf ) /* was input specified? */
            {
			switch (subj) {
				case BOTH:
	                more( HELPMAIN );
					/* no break; ! */
				case JUSTMENU:
		            allsel();
				/* case NONE: does none of this */
			}
            subj = JUSTMENU;
            setprompt();
            fputs( prompt, stdout );        /* prompt user for input */
            if ( fgets( buf, MAXLINELEN, stdin ) == NULL )   /* EOF or error */
                return( -1 );
            }
        strupr( buf );                      /* convert to upper case */
        stripnl( buf );                     /* get rid of new line */
        if ( gettok( buf, STDDELIM, tbuf, lbuf ) == NULL ) /* no input token */
            return( 0 );

        strcpy( buf, lbuf );                /* for next pass */
        if ( tbuf[0] == '?' )           /* redisplay current main help */
            {
			subj = BOTH;
            }
        else
            {
/* go ahead and assume the input is a request for more help! */

			bufptr = tbuf;
			while (( status = outhelp( bufptr ) ) != -1 )
				{
				bufptr = NULL;				/* flag for next iteration */
	            if ( status == 1 )
	                {                       /* it was a subdir! */
	                if ( ( status = help( buf ) ) < 0) /* parse further... */
	                    return( status );	/* EOF or error */
	                else
	                    {
	                    chdir( ".." );      /* go back up for dos */
						subj = NONE;	/* suppress printing of .HLM and menu */
	                    }
	                }
	          /*  else	bottom-level help was found */
	            }
			}
        }
    }


/****************************************************************************
 *  outhelp( filename )      -   Output the given help file or ...
 *  char    *filename;           A text file name or directory name
 *
 */
outhelp( filename )
char    *filename;
    {
	static int counter;
	char fullname[MAXLINELEN];

	if (filename) {			/* new filename (not a repeat) */
		strcat(strcpy(fullname,filename),"*.HLP");
		if ( !wildcard(fullname) ) {
			fprintf( stdout, "\nSorry, no help found on '%s'\n", filename );
		    return( -1 );                           /* no help available */
		}
		counter = 0;
	} else if ( !dent[++counter][0] )			/* end of repeat search */
		return( -1 );

    if ( chdir(dent[counter]) == 0 )			/* see if it is a subdir by */
        {                                   /* trying to go to it */
        return( 1 );                        /* tell caller we are there */
        }
	else {
        more( dent[counter] );                   /* output the file */
        return( 0 );
	}
    }
 

/****************************************************************************
 * allsel()                     print the topics available in this directory
 *
 *  This function prints a directory of the help files and dirs within this
 *  dir.  Extensions are stripped off.
 *    
 */
allsel()
	{
    int      		totalnames;
    int             counter;
    int             j;
    int             longlen;
    int             rowcnt;
    int             colcnt;
    int             namewidth;
    char            *s1;
    char            row[TERMWID+1];

	if ( !(totalnames = wildcard( DEFSEARCH )) )
		return( 0 );

	for (counter = 0; counter < totalnames; counter++) {
		s1 = dent[counter];
		while (*s1 && *s1 != '.')
			s1++;
		*s1 = '\0';					/* get rid of extension */
	}

/* this next section will be made into a subroutine */
/* rebuild code from here --\/ */
    longlen = 0;
    for(counter=0; counter < totalnames; counter++ )
        longlen = ((j=strlen(dent[counter]))>longlen)?j:longlen;
 
    /* here print the names out in nice columns */
    namewidth = longlen + COLUMNSPACE;
    rowcnt = TERMWID / namewidth;
    colcnt = (totalnames + (rowcnt-1)) / rowcnt ;
    if (colcnt <= 0) 
        colcnt = 1;
    
/*    if (col_flag && rowcnt > 1)   */
    if ( rowcnt > 1 ) 
        {
        fprintf( stdout, "\n Topics:\n\n");
        for(counter=0; counter < colcnt ; counter++ ) 
            {
            for(j=0; j < TERMWID; row[j++] = ' ');
            row[j] = '\0';
            for(j=0, s1 = row; (counter+j) < totalnames; j += colcnt) 
                {
                row[strlen(row)] = ' ';
                strcpy(s1,dent[counter+j]);
                s1 = s1 + namewidth;
                }
            fprintf( stdout, "    %s\n",row);
            }
        putchar('\n');
        }
    else 
        {
        for(counter=0; counter < totalnames; counter++)
            fprintf( stdout, "%s\n", dent[counter] );
        }
/*                to here --/\ */
 
    return( 0 );
    }
 

/*
 * wildcard( filename ) searches out all wildcard matches for filename
 *   and puts them in dent[][]
 */
wildcard( filename )
char *filename;
{
	register int j, counter, totalnames = 0;
    static char tmpbuf[MAXLINELEN];

    set_dta( dta );

	while( ( dir_get( filename, ALL ) == 0 ) && ( totalnames < (MAXENT-1) ) )
		{
		filename = NULL;
		strcpy(dent[totalnames++],&dta[30]);
		}
	dent[totalnames][0] = '\0';           /* terminating entry */

	/* sort the names in ascending order with exchange algorithm */
	for (counter = 0; counter < totalnames - 1; counter++)
		for (j = counter+1; j <totalnames; j++)
			if (strcmp(dent[counter],dent[j]) > 0) 
				{
				strcpy( tmpbuf, dent[counter] );
				strcpy( dent[counter], dent[j] );
				strcpy( dent[j], tmpbuf );
				}
	return( totalnames );
}



int curr_disk()
{
	union REGS rg;
	rg.h.ah = 0x19;

	int86( 0x21, &rg, &rg);
	return( rg.h.al );
}

void select_disk(num)
int num;
{
	union REGS rg;
	rg.h.ah = 0x0e;
	rg.h.dl = num;

	int86( 0x21, &rg, &rg);
}

void set_dta( dta )
char    *dta;
    {
    union REGS rg;

    rg.h.ah = 0x1a;
    rg.x.dx = ( unsigned int )dta;

    int86( 0x21, &rg, &rg );
    }  

dir_get( fn, type )
char    *fn;
int     type;
    {
    union REGS rg;

    if ( fn )
        {
        rg.x.dx = ( unsigned int )fn;
        rg.x.cx = type;
        rg.h.ah = 0x4e;

        int86( 0x21, &rg, &rg );
        if ( rg.x.cflag & 0x01 )
            return( rg.x.ax );
        }
    else
        {
        rg.h.ah = 0x4f;
            
        int86( 0x21, &rg, &rg );
        if ( rg.x.cflag & 0x01 )
            return( rg.x.ax );
        }
    return( 0 );
    }
    

/****************************************************************************
 *  gettok( is, delim, tb, rb )     - Find token in input string        
 *  char    *is;        Pointer to input string
 *  char    *delim;     Pointer to set of delimiting characters
 *  tb      *tb         Pointer to buffer to place token
 *  rb      *rb         Pointer to buffer to place ( input string - token )
 *
 *  This function reads the input string looking for a token delimited by
 *  the beginning of the input buffer or a character in the delimiting set
 *  on the leading edge, and the end of the input buffer or a delimiting 
 *  character on the trailing edge.  The first character of the buffer 
 *  which is not a character in the set of delimiting characters is taken as
 *  the first character of the token.
 *
 *  If a pointer is passed in tb and/or rb, it is assumed to be a buffer of
 *  adequate size to hold the resultant string.  A NULL may be passed in these
 *  variables if the result is not desired.
 *
 *  Returns:    A pointer to the first not delimiting character.
 */
char *gettok( is, delim, tb, rb )
char    *is;     
char    *delim;  
char    *tb;
char    *rb;
    {
    char    *fc;                    /* pointer to first character of token */

    fc = NULL;                      /* default no token found */
        
    if ( tb )                       /* if user gave us a token buffer */
        *tb = 0;                    /* terminate the token buffer */        
    if ( rb )                       /* if user gave us a remainder buffer */
        *rb = 0;                    /* terminate the token buffer */        

    if ( is == NULL )               /* oops, got a 2001 */
        return( NULL );
        
    while ( *is && isdelim( *is, delim ) ) /* while leading delimiter */
        is++;                       /* skip it */
    if ( !*is )
        return( NULL );
    fc = is;                        /* save the pointer the first char */
    while ( *is && !isdelim( *is, delim ) )    /* while not a delimiter */
        {
        if ( tb )                   /* if user gave us a token buffer */
            {
            *tb = *is;              /* move the character */
            tb++;                   /* increment token buffer ptr */
            }
        is++;
        }
    if ( tb )                       /* if user gave us a token buffer */
        *tb = 0;                    /* terminate the token buffer */        

    if ( rb )                       /* if user gave us a remainder buffer */
        strcpy( rb, is );           /* copy the remainder */

    return( fc );
    }
            
isdelim( c, delim )
char    c;
char    *delim;
    {
    int     dc;                     /* delimiter count */
    int     i;                      /* temporary counter */
    char    *tc;                    /* termporary pointer */
    
    tc = delim;                     /* time to count the donuts */
    dc = 0;
    while  ( *tc++ )    
        dc++;

    for ( i=0; i<dc; i++ )          /* loop through the delimiters */
        {
        if ( c == delim[i] )        /* if a delimiter */
            return( 1 );            /* return found */
        }
    return( 0 );                    /* return not found */
    }            


more( fn )
char    *fn;
    {
    FILE    *sfd;
    char    buf[512];
    int     lct;
        
    lct = 0;
    scrnlen = DEFSCRLEN;
    
    if ( ( sfd = fopen( fn, "r" ) ) != NULL ) /* got a file */
        {
		putchar('\n');
        while( fgets( buf, 512, sfd ) )
            {
            if ( lct == scrnlen )
                {
                lct = 0;
                if ( pgbrk() )
                    {
                    fclose( sfd );
                    return( 1 );
                    }
                }
            fputs( buf, stdout );
            lct++;
            }
	    fclose( sfd );
        }
    return( 0 );
    }

pgbrk()
    {
    register int c,i;
	static char moreprompt[] = "More? ";
    
    printf( moreprompt );
    c = kget();

    putchar( '\r' );
	for (i = sizeof(moreprompt); i--;)				/* erase the prompt */
		putchar( ' ' );
    putchar( '\r' );

	return ( c == 'N' );
    }

void stripnl( buf )
char    *buf;
    {
    while ( *buf )
        {
        if ( *buf == '\n' )
            *buf = 0;
        buf++;
        }
    }    
    

void setprompt()
    {
    char    *hs;                        /* pointer to the first / in helpdir */
    char    *cs;                        /* pointer to first / in current dir */
    char    *pp;                        /* pointer into prompt */
    
    getcwd( currdir, MAXLINELEN );

    hs = strchr( helpdir, '\\' );       /* ignore drive names */
    cs = strchr( currdir, '\\' );       /* ignore drive names */

    while ( *hs && ( *hs == *cs ) )     /* skip help directory root */
        {
        hs++;
        cs++;
        }

    pp = prompt;
    while ( *cs )                       /* use the rest for the prompt */
        {
		switch (*cs) {
			case '\\':					/* convert to spaces for readability */
	            *pp++ = ' ';
				cs++;
				break;
			case '.':
				while (*++cs && *cs != '\\')
					;
				break;
			default:
		        *pp++ = *cs++;
        }
        }
  /*  if ( pp != prompt )                 /* not at root... */
        *pp++ = ' ';                    /* add a pleasing space */

    *pp = '\0';                         /* terminate the string */
    
    strcat( prompt, PROMPT );           /* and the default ending */
    }
      
void fstobs( str )                   
char    *str;
    {
    strupr( str );                  /* dos only understands one case */
    while ( *str )
        {
        if ( *str == '/' )          /* convert UNIX to MSDOS seps */
            *str = '\\';
        str++;
        }
    }
    
void handler()
    {
    int    c;
    
    if ( signal( SIGINT, handler ) < 0 )    /* uh oh */
        {
        fprintf( stderr, "%s could not set SIGINT.  Action undefined upon INT\n", progname );
        }

    fprintf( stdout, "Terminate process [y|N]" );
    c = kget();    
    fputc( '\n', stdout );
    if ( c == 'Y' )
		bye(0);
    }
    
kget()
    {
    char c;
    
    while ( kbhit() == 0 )
        {
        }

    c = ( char )getche();
    c = toupper( c );

    return( c );
    }

bye(status)
	{
	select_disk( olddisk );
	chdir( olddir );                    /* go back to our origin */
	exit(status);
	}
SHAR_EOF
if test 19751 -ne "`wc -c < 'help.c'`"
then
	echo shar: error transmitting "'help.c'" '(should have been 19751 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'help.hlm'" '(344 characters)'
if test -f 'help.hlm'
then
	echo shar: will not over-write existing file "'help.hlm'"
else
cat << \SHAR_EOF > 'help.hlm'
GNUPLOT is a command-driven interactive function plotting program.  It
is case sensitive (commands and function names written in lowercase
are not the same as those written in CAPS).  All command names may be
abbreviated, as long as the abbreviation is not ambiguous.  Any number
of commands may appear on a line, separated by semicolons (;). 
SHAR_EOF
if test 344 -ne "`wc -c < 'help.hlm'`"
then
	echo shar: error transmitting "'help.hlm'" '(should have been 344 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'hrcgraph.asm'" '(7858 characters)'
if test -f 'hrcgraph.asm'
then
	echo shar: will not over-write existing file "'hrcgraph.asm'"
else
cat << \SHAR_EOF > 'hrcgraph.asm'
TITLE	Hercules graphics module

;	Michael Gordon - 8-Dec-86
;
; Certain routines were taken from the Hercules BIOS of	Dave Tutelman - 8/86
; Others came from pcgraph.asm included in GNUPLOT by Colin Kelley
;
; modified slightly by Colin Kelley - 22-Dec-86
;	added junk below for MSC compact model, although it's probably not all
;	  necessary...

include header.mac

if1
include lineproc.mac
endif


GPg1_Base equ 0B800h	; Graphics page 1 base address

_text	segment

	public _H_line, _H_color, _H_mask, _HVmode, _H_puts

hpixel	proc near
	ror word ptr bmask,1
	jc cont
	ret
cont:
	push ax
	push bx
	push cx
	push dx
	push si
	mov cx,ax		; x
	mov dx,bx		; y
;
; [couldn't this be done faster with a lookup table? -cdk]
;
	; first compute the address of byte to be modified
	; = 90*[row/4] + [col/8] + 2^D*[row/4] + 2^F*page
	mov	bh,cl		; col (low order) in BH
	mov	bl,dl		; row (low order) in BL
	and	bx,0703H	; mask the col & row remainders
IFDEF iAPX286
	shr	cx,3		; col / 8
	shr	dx,2		; row / 4
	mov	al,90
	mul	dx		; AX = 90*[ row/4 ]
	add	ax,cx		;  ... + col/8
	shl	bl,5		; align row remainder
ELSE			; same as above, obscure but fast for 8086
	shr	cx,1		; divide col by 8
	shr	cx,1
	shr	cx,1
	shr	dx,1		; divide row by 4
	shr	dx,1
	shl	dx,1		; begin fast multiply by 90 (1011010 B)
	mov	ax,dx
	shl	dx,1
	shl	dx,1
	add	ax,dx
	shl	dx,1
	add	ax,dx
	shl	dx,1
	shl	dx,1
	add	ax,dx		; end fast multiply by 90
	add	ax,cx		; add on the col/8
	shl	bl,1		; align row remainder
	shl	bl,1
	shl	bl,1
	shl	bl,1
	shl	bl,1
ENDIF
	add	ah,bl		; use aligned row remainder
end_adr_calc:			; address of byte is now in AX
	mov	dx,GPg1_Base	; base of pixel display to DX
	mov	es,dx		; ...and thence to segment reg
	mov	si,ax		; address of byte w/ pixel to index reg
	mov	cl,bh		; bit addr in byte
	mov	al,80H		; '1000 0000' in AL 
	shr	al,cl		; shift mask to line up with bit to read/write
set_pix:			; set the pixel
	or	es:[si],al	; or the mask with the right byte
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
	ret
hpixel endp

lineproc _H_line, hpixel

;
; clear - clear page 1 of the screen buffer to zero (effectively, blank
;	the screen)
;
clear   proc near
	push es
	push ax
	push cx
	push di
	mov ax, GPg1_Base
	mov es, ax
	xor di, di
	mov cx, 4000h
	xor ax, ax
	cld
	rep stosw			; zero out screen page
	pop di
	pop cx
	pop ax
	pop es
	ret
clear	endp

beginproc _H_color
	push bp
	mov bp,sp
	mov al,[bp+X]			; color
	mov byte ptr color,al
	pop bp
	ret
_H_color endp

beginproc _H_mask
	push bp
	mov bp,sp
	mov ax,[bp+X]			; mask
	mov word ptr bmask,ax
	pop bp
	ret
_H_mask endp

HCtrl_Port	equ	03B8H	; Hercules 6845 control port IO addr
HIndx_Port	equ	03B4H	; Hercules 6845 index port IO addr
HScrn_Enable	equ	008h	; Control port bit to enable video
HCh_Mode	equ	020h	; Character output mode
HGr_Mode	equ	082h	; Graphics output mode page 1

parm_count equ 12

beginproc _HVmode
	push bp
	mov bp, sp
	push si
	mov ax, [bp+X]
	or ah, al
	mov al, HCh_Mode		; Assume character mode is wanted
	mov si, offset HCh_Parms
	cmp ah, 0			; nonzero means switch to graphics
	jz vmode_ok
	call near ptr clear		; clear the graphics page
	mov al, HGr_Mode
	mov si, offset HGr_Parms
vmode_ok:
	mov dx, HCtrl_Port
	out dx, al			; Set Hercules board to proper mode
	call near ptr setParms		; Set the 6845 parameters
	or al, HScrn_Enable		; Enable the video output
	out dx, al
	pop si
	pop bp
	ret
_HVmode	endp

setParms proc near		; Send 6845 parms to Hercules board
	push ax
	push dx
	push si			
	mov dx, HIndx_Port	; Index port addr -> DX
	mov ah, 0		; 0 -> parameter counter
sp_loop:
	mov al, ah
	out dx, al		; output to 6845 addr register
	inc dx			; next output to data register
	mov al, [si]		; next control byte -> al
	inc si
	out dx, al		; output control byte
	dec dx			; 6845 index addr -> dx
	inc ah			; bump addr
	cmp ah, parm_count
	jnz sp_loop
	pop si
	pop dx
	pop ax
	ret
setParms endp

; H_puts - print text in graphics mode
;
;	cx = row
;	bx = column
;	si = address of string (null terminated) to print

beginproc _H_puts
	push bp
	mov bp, sp
	push si
	push ds
	mov si, [bp+X]			; string offset

ifdef LARGE_DATA
	mov ds, [bp+X+2]		; string segment
	mov cx, [bp+X+4]		; row
	mov bx, [bp+X+6]		; col
else
	mov cx, [bp+X+2]		; row
	mov bx, [bp+X+4]		; col
endif

ploop:	lodsb				; get next char
	or	al, al			; end of display?
	je	pdone
	call near ptr display
	inc	bx			; bump to next column
	jmp	ploop
pdone:	pop ds
	pop si
	pop bp
	ret
_H_puts	endp

;
; display - output an 8x8 character from the IBM ROM to the Herc board
;
; AX = char, BX = column (0-89), CX = row(0-42)  ** all preserved **
;
CON8	db	8
CON180	db	180
IBMROM	equ	0F000h
CHARTAB	equ	0FA6Eh

display	proc near
	push	ds			; save the lot
	push	es
	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di

; setup ds -> IBM ROM, and si -> index into IBM ROM character table located
;	at 0fa6eh in the ROM

	and	ax, 07fh
	mul	cs:CON8			; mult by 8 bytes of table per char
	mov	si, ax
	mov	ax, IBMROM
	mov	ds, ax
	assume	ds:nothing
	add	si, CHARTAB		; add offset of character table

; compute index into Hercules screen memory for scan line 0.  The remaining
;	seven scan lines are all at fixed offsets from the first.
;
;	Since graphics mode treats the screen as sets of 16x4 "characters",
;	we need to map an 8x8 real character onto the front or back of
;	a pair of graphics "characters".  The first four scan lines of our
;	8x8 character will map to the top graphics "character", and the second
;	four scan lines map to the graphics character on the "line" (4 scan
;	lines high) below it.
;
;	For some exotic hardware reason (probably speed), all scan line 0
;	bits (i.e. every fourth scan line) are stored in memory locations
;	0-2000h in the screen buffer.  All scan line 1 bits are stored
;	2000h-4000h.  Within these banks, they are stored by rows.  The first
;	scan line on the screen (scan line 0 of graphics character row 0)
;	is the first 45 words of memory in the screen buffer.  The next 45
;	words are the first scan line graphics row 1, and since graphics
;	"characters" are 4 bits high, this second scan line is physically
;	the fifth scan line displayed on the screen.
;
;	SO, to display an 8x8 character, the 1st and 5th rows of dots are
;	both scan line 0 of the graphics "character", the 2nd and 6th are
;	scan line 1, and so on.
;
;	The column (0-89) tells which byte in a scan line we need to load.
;	Since it takes two rows of graphics characters to hold one row of
;	our characters, column+90 is a index to scan line 4 rows of pixels
;	higher (n+4).  Thus 180 bytes of screen memory in any bank (0h, 2000h,
;	4000h, 6000h) represent a row of 8x8 characters.
;	
;	The starting location in screen memory for the first scan line of
;	a character to be displayed will be:  	(row*180)+column
;	The 5th scan line will be at:		(row*180)+column+90
;
;	The second and 6th scan lines will be at the above offsets plus
;	the bank offset of 2000h.  The third and 7th, add 4000h and finally
;	the 4th and 8th, add 6000h.
;
	mov	ax, GPg1_Base
	mov	es, ax			; es = hercules page 0
	mov	ax, cx			; get row
	mul	cs:CON180		; mult by 180(10)
	mov	di, ax			; di = index reg
	cld				; insure right direction

;output 8 segments of character to video ram

	lodsb				; line 0
	mov	es:[di+bx], al
	lodsb
	mov	es:[di+bx+2000h], al	; line 1
	lodsb
	mov	es:[di+bx+4000h], al	; line 2
	lodsb
	mov	es:[di+bx+6000h], al	; line 3
	lodsb
	mov	es:[di+bx+90], al	; line 4
	lodsb
	mov	es:[di+bx+2000h+90], al	; line 5
	lodsb
	mov	es:[di+bx+4000h+90], al	; line 6
	lodsb
	mov	es:[di+bx+6000h+90], al	; line 7

	pop	di
	pop	si
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	pop	es
	pop	ds
	ret
display	endp

_text	ends

_data	segment
bmask	dw -1
color	db 1
_data	ends

const	segment
HCh_Parms db 	61H, 50H, 52H, 0FH, 19H, 06H, 19H, 19H, 02H, 0DH, 0BH, 0CH
HGr_Parms db	35H, 2DH, 2EH, 07H, 5BH, 02H, 57H, 57H, 02H, 03H, 00H, 00H
const	ends

	end
SHAR_EOF
if test 7858 -ne "`wc -c < 'hrcgraph.asm'`"
then
	echo shar: error transmitting "'hrcgraph.asm'" '(should have been 7858 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'lineproc.mac'" '(1980 characters)'
if test -f 'lineproc.mac'
then
	echo shar: will not over-write existing file "'lineproc.mac'"
else
cat << \SHAR_EOF > 'lineproc.mac'
; lineproc.mac
; MASM macro definition for Bresenham line-drawing routine
; Colin Kelley
; January 13, 1987


INCAX	equ 40h			; for Self-Modifying Code
INCBX	equ 43h
DECAX	equ 48h
DECBX	equ 4bh

; usage:
;   lineproc linename, pixelname
;
; where linemane is the name you want for the proc, and pixelname is the
;   name of the routine that linename is to call to set pixels
;

lineproc macro linename, pixelname
beginproc linename

	push bp
	mov bp,sp
	push si
	push di
	mov ax,[bp+X]		; x1
	mov bx,[bp+X+2]		; y1
	mov cx,[bp+X+4]		; x2
	mov si,[bp+X+6]		; y2

	cmp ax,cx		; x1,x2
	jne i19
	cmp bx,si		; y1,y2
	jne i19

	call pixelname

	jmp i28
i19:
	mov dx,ax		; dx,x1
	sub dx,cx		; x2
	jnc noabsx
	neg dx
noabsx:
	mov di,bx		; dy,y1
	sub di,si		; y2
	jnc noabsy
	neg di			; dy
noabsy:
	cmp dx,di		; dx,dy
	jb i21			; go iterate y's
;
; iterate x's
;
	cmp bx,si		; y1,y2
	jb forwardy
	mov byte ptr cs:yinc1,DECBX
	jmp short i22
forwardy:
	mov byte ptr cs:yinc1,INCBX
i22:
	cmp ax,cx		; x1,x2
	jae l20004
	mov byte ptr cs:xinc1,INCAX
	jmp short l20005
l20004:
	mov byte ptr cs:xinc1,DECAX
l20005:
	mov bp,dx		; sum,dx
	shr bp,1		; sum
d23:
	cmp ax,cx		; x1,x2
	je i28			; done
xinc1:	inc ax			; may become inc or dec
	add bp,di		; sum,dy
	cmp bp,dx
	jb i27
	sub bp,dx		; sum,dx
yinc1:	inc bx			; may become inc or dec
i27:
	call pixelname
	jmp short d23

;
; else iterate y's
;
i21:
	cmp ax,cx		; x1,x2
	jae l20006
	mov byte ptr cs:xinc2,INCAX
	jmp short l20007
l20006:
	mov byte ptr cs:xinc2,DECAX
l20007:
	cmp bx,si		; y1,y2
	jb forwardy2
	mov byte ptr cs:yinc2,DECBX
	jmp short i29
forwardy2:
	mov byte ptr cs:yinc2,INCBX
i29:
	mov bp,di		; sum,dy
	shr bp,1		; sum,1
d30:
	cmp bx,si		; y1,y2
	je i28
yinc2:	inc bx			; may become inc or dec
	add bp,dx		; sum,dx
	cmp bp,di		; sum,dy
	jb i34
	sub bp,di		; sum,dy
xinc2:	inc ax			; may become inc or dec
i34:
	call near ptr pixelname
	jmp short d30
;
; clean up and exit
;
i28:
	pop di
	pop si
	pop bp
	ret

linename endp
	endm
SHAR_EOF
if test 1980 -ne "`wc -c < 'lineproc.mac'`"
then
	echo shar: error transmitting "'lineproc.mac'" '(should have been 1980 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'link.opt'" '(125 characters)'
if test -f 'link.opt'
then
	echo shar: will not over-write existing file "'link.opt'"
else
cat << \SHAR_EOF > 'link.opt'
command+eval+graphics+internal+misc+parse+plot+scanner+standard+term+util+version+pcgraph+corgraph+hrcgraph,gnuplot,nul,ega;
SHAR_EOF
if test 125 -ne "`wc -c < 'link.opt'`"
then
	echo shar: error transmitting "'link.opt'" '(should have been 125 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'make.msc'" '(1136 characters)'
if test -f 'make.msc'
then
	echo shar: will not over-write existing file "'make.msc'"
else
cat << \SHAR_EOF > 'make.msc'
OBJS = 	command.obj eval.obj graphics.obj internal.obj misc.obj parse.obj plot.obj scanner.obj standard.obj term.obj util.obj version.obj pcgraph.asm corgraph.asm hrcgraph.asm

# /AC means use compact model (small code, large data)
CFLAGS = /AC /DPC #/Zi #/Od

TERMFLAGS = /DHERCULES /DATT6300 /DCORONA /DPOSTSCRIPT /DHP75 /DTEK /DV384 /DEGALIB

LINKFLAGS = #/codeview

# default rules
.c.obj:
	msc $(CFLAGS) $*;

.asm.obj:
	masm $*;

pcgraph.obj: pcgraph.asm header.mac lineproc.mac

corgraph.obj: corgraph.asm header.mac lineproc.mac

hrcgraph.obj: hrcgraph.asm header.mac lineproc.mac

command.obj: command.c plot.h

eval.obj: eval.c plot.h

graphics.obj: graphics.c plot.h

internal.obj: internal.c plot.h

misc.obj: misc.c plot.h

parse.obj: parse.c plot.h

plot.obj: plot.c plot.h

scanner.obj: scanner.c plot.h

standard.obj: standard.c plot.h

term.obj: term.c plot.h
	msc $(CFLAGS) $(TERMFLAGS) term;

util.obj: util.c plot.h

version.obj: version.c


# use link.opt to avoid command-line overflow

gnuplot.exe: $(OBJS)
 link$(LINKFLAGS) @link.opt
 exepack gnuplot.exe gnupack.exe
 del gnuplot.exe
 ren gnupack.exe gnuplot.exe
SHAR_EOF
if test 1136 -ne "`wc -c < 'make.msc'`"
then
	echo shar: error transmitting "'make.msc'" '(should have been 1136 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pcgraph.asm'" '(3165 characters)'
if test -f 'pcgraph.asm'
then
	echo shar: will not over-write existing file "'pcgraph.asm'"
else
cat << \SHAR_EOF > 'pcgraph.asm'
TITLE	PC graphics module
;	Colin Kelley
;	December 22, 1986
;	modified January 1987 to use LINEPROC.MAC

include header.mac

if1
include lineproc.mac
endif


_text	segment

	public _PC_line, _PC_color, _PC_mask, _PC_curloc, _PC_puts, _Vmode
	public _save_stack, _ss_interrupt
	extrn _interrupt:near

pcpixel proc near
	ror word ptr linemask,1
	jc cont
	ret
cont:
	push ax
	push bx
	push cx
	push dx
	push bp
	mov cx,ax		; x
	mov dx,bx		; y
	mov ah,0ch		; ah = write pixel
	mov al,byte ptr color

	mov bh, 0		; page 0
	int 10h
	pop bp
	pop dx
	pop cx
	pop bx
	pop ax
	ret
pcpixel endp

lineproc _PC_line, pcpixel

_PC_color proc near
	push bp
	mov bp,sp
	mov al,[bp+X]			; color
	mov byte ptr color,al
	pop bp
	ret
_PC_color endp

_PC_mask proc near
	push bp
	mov bp,sp
	mov ax,[bp+X]			; mask
	mov word ptr linemask,ax
	pop bp
	ret
_PC_mask endp

_Vmode	proc near
	push bp
	mov bp,sp
	push si
	push di
	mov ax,[bp+X]
	int 10h
	pop di
	pop si
	pop bp
	ret
_Vmode	endp

_PC_curloc proc near
	push bp
	mov bp,sp
	mov dh, byte ptr [bp+X] ; row number
	mov dl, byte ptr [bp+X+2] ; col number
	mov bh, 0
	mov ah, 2
	int 10h
	pop bp
	ret
_PC_curloc endp

;
; thanks to watale!broehl for finding a bug here--I wasn't pushing BP
;   and reloading AH before INT 10H, which is necessary on genuine IBM
;   boards...
;
_PC_puts proc near
	push bp
	mov bp,sp
	push si
	mov bl,byte ptr color
	mov si,[bp+X]		; offset

ifdef LARGE_DATA
	mov es,[bp+X+2]		; segment if large or compact data model
endif

puts2:

ifdef LARGE_DATA
	mov al,es:[si]
else
	mov al,[si]
endif
	or al,al
	jz puts3
	mov ah,0eh		; write TTY char
	int 10h
	inc si
	jmp short puts2
puts3:	pop si
	pop bp
	ret
_PC_puts endp


; int kbhit();
;   for those without MSC 4.0
; Use BIOS interrupt 16h to determine if a key is waiting in the buffer.
; Return nonzero if so.
;

beginproc _kbhit
	mov ah, 1		; function code 1 is keyboard test
	int 16h			; keyboard functions
	jnz kbfin		; Exit if char available
	xor ax, ax		; No char:  return zero.
kbfin:	ret
_kbhit	endp


; _save_stack and _ss_interrupt are needed due to a bug in the MSC 4.0
; code when run under MS-DOS 3.x.  Starting with 3.0, MS-DOS automatically
; switches to an internal stack during system calls.  This leaves SS:SP
; pointing at MS-DOS's stack when the ^C interrupt (INT 23H) is triggered.
; MSC should restore its own stack before calling the user signal() routine,
; but it doesn't.
;
; Presumably this code will be unnecessary in later releases of the compiler.
;

; _save_stack saves the current SS:SP to be loaded later by _ss_interrupt.
;

beginproc _save_stack
	mov ax,ss
	mov cs:save_ss,ax
	mov ax,sp
	mov cs:save_sp,ax
	ret
_save_stack endp


; _ss_interrupt is called on ^C (INT 23H).  It restores SS:SP as saved in
; _save_stack and then jumps to the C routine interrupt().
;
beginproc _ss_interrupt
	cli			; no interrupts while the stack is changed!
	mov ax,-1		; self-modifying code again
save_ss	equ this word - 2
	mov ss,ax
	mov sp,-1		; here too
save_sp equ this word - 2
	sti
	jmp _interrupt		; now it's safe to call the real routine
_ss_interrupt endp


_text	ends


const	segment
linemask dw -1
color	db 1
const	ends

	end
SHAR_EOF
if test 3165 -ne "`wc -c < 'pcgraph.asm'`"
then
	echo shar: error transmitting "'pcgraph.asm'" '(should have been 3165 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0