ftp.nice.ch/pub/next/unix/editor/me.3.10.N.bs.tar.gz#/me-3.10.N.bs/src/ibmpc.c

This is ibmpc.c in view mode; [Download] [Up]

/*
 * The routines in this file provide support for the IBM-PC and other
 * compatible terminals. It goes directly to the graphics RAM to do
 * screen output. It compiles into nothing if not an IBM-PC driver
 * Supported monitor cards include CGA, MONO and EGA.
 */

#define	termdef	1			/* don't define "term" external */

#include        <stdio.h>
#include	"estruct.h"
#include	"etype.h"
#include        "edef.h"
#include	"elang.h"

#if     IBMPC
#define NROW	50			/* Max Screen size.		*/
#define NCOL    80                      /* Edit if you want to.         */
#define	MARGIN	8			/* size of minimim margin and	*/
#define	SCRSIZ	64			/* scroll size for extended lines */
#define	NPAUSE	200			/* # times thru update to pause */
#define BEL     0x07                    /* BEL character.               */
#define ESC     0x1B                    /* ESC character.               */
#define	SPACE	32			/* space character		*/

#define	SCADC	0xb8000000L		/* CGA address of screen RAM	*/
#define	SCADM	0xb0000000L		/* MONO address of screen RAM	*/
#define SCADE	0xb8000000L		/* EGA/VGA address of screen RAM*/

#define MONOCRSR 0x0B0D			/* monochrome cursor		*/
#define CGACRSR 0x0607			/* CGA cursor			*/
#define EGACRSR 0x0709			/* EGA/VGA cursor		*/

#define	CDCGA	0			/* color graphics card		*/
#define	CDMONO	1			/* monochrome text card		*/
#define	CDEGA	2			/* EGA color adapter		*/
#define	CDVGA	3			/* VGA color adapter		*/
#define	CDSENSE	9			/* detect the card type		*/

#define NDRIVE	4			/* number of screen drivers	*/

int dtype = -1;				/* current display type		*/
char drvname[][8] = {			/* screen resolution names	*/
	"CGA", "MONO", "EGA", "VGA"
};
long scadd;				/* address of screen ram	*/
int *scptr[NROW];			/* pointer to screen lines	*/
unsigned int sline[NCOL];		/* screen line image		*/
int egaexist = FALSE;			/* is an EGA card available?	*/
int vgaexist = FALSE;			/* is video graphics array available? */
extern union REGS rg;			/* cpu register for use of DOS calls */

PASCAL NEAR ibmmove();
PASCAL NEAR ibmeeol();
PASCAL NEAR ibmputc();
PASCAL NEAR ibmeeop();
PASCAL NEAR ibmrev();
PASCAL NEAR ibmcres();
PASCAL NEAR spal();
PASCAL NEAR ibmbeep();
PASCAL NEAR ibmopen();
PASCAL NEAR ibmclose();
PASCAL NEAR ibmkopen();
PASCAL NEAR ibmkclose();
PASCAL NEAR scinit();
int PASCAL NEAR getboard();
PASCAL NEAR egaopen();
PASCAL NEAR egaclose();
PASCAL NEAR fnclabel();

#if	COLOR
PASCAL NEAR ibmfcol();
PASCAL NEAR ibmbcol();
int	cfcolor = -1;		/* current forground color */
int	cbcolor = -1;		/* current background color */
int	ctrans[] =		/* ansi to ibm color translation table */
	{0, 4, 2, 6, 1, 5, 3, 7,
	 8, 12, 10, 14, 9, 13, 11, 15};
#endif

/*
 * Standard terminal interface dispatch table. Most of the fields point into
 * "termio" code.
 */
TERM    term    = {
	NROW-1,
        NROW-1,
        NCOL,
        NCOL,
	MARGIN,
	SCRSIZ,
	NPAUSE,
        ibmopen,
        ibmclose,
	ibmkopen,
	ibmkclose,
        ttgetc,
	ibmputc,
        ttflush,
        ibmmove,
        ibmeeol,
        ibmeeop,
        ibmbeep,
	ibmrev,
	ibmcres
#if	COLOR
	, ibmfcol,
	ibmbcol
#endif
};

#if	COLOR
PASCAL NEAR ibmfcol(color)	/* set the current output color */

int color;	/* color to set */

{
	cfcolor = ctrans[color];
}

PASCAL NEAR ibmbcol(color)	/* set the current background color */

int color;	/* color to set */

{
        cbcolor = ctrans[color];
}
#endif

PASCAL NEAR ibmmove(row, col)
{
	rg.h.ah = 2;		/* set cursor position function code */
	rg.h.dl = col;
	rg.h.dh = row;
	rg.h.bh = 0;		/* set screen page number */
	int86(0x10, &rg, &rg);
}

PASCAL NEAR ibmeeol()	/* erase to the end of the line */

{
	unsigned int attr;	/* attribute byte mask to place in RAM */
	unsigned int *lnptr;	/* pointer to the destination line */
	int i;
	int ccol;	/* current column cursor lives */
	int crow;	/*	   row	*/

	/* find the current cursor position */
	rg.h.ah = 3;		/* read cursor position function code */
	rg.h.bh = 0;		/* current video page */
	int86(0x10, &rg, &rg);
	ccol = rg.h.dl;		/* record current column */
	crow = rg.h.dh;		/* and row */

	/* build the attribute byte and setup the screen pointer */
#if	COLOR
	if (dtype != CDMONO)
		attr = (((cbcolor & 15) << 4) | (cfcolor & 15)) << 8;
	else
		attr = 0x0700;
#else
	attr = 0x0700;
#endif
	lnptr = &sline[0];
	for (i=0; i < term.t_ncol; i++)
		*lnptr++ = SPACE | attr;

	if (flickcode && (dtype == CDCGA)) {
		/* wait for vertical retrace to be off */
		while ((inp(0x3da) & 8))
			;
	
		/* and to be back on */
		while ((inp(0x3da) & 8) == 0)
			;
	}			

	/* and send the string out */
	movmem(&sline[0], scptr[crow]+ccol, (term.t_ncol-ccol)*2);

}

PASCAL NEAR ibmputc(ch) /* put a character at the current position in the
		   current colors */

int ch;

{
	/* if its a newline, we have to move the cursor */
	if (ch == '\n' || ch == '\r') {
		rg.h.ah = 3;
		int86(0x10, &rg, &rg);
		if (rg.h.dh == 24) {
			ibmmove(20, 0);
			/* we must scroll the screen */
			rg.h.ah = 6;	/* scroll up */
			rg.h.al = 1;	/* # of lines to scroll by */
#if	COLOR
			rg.h.bh = cfcolor; /* attribute for blank line */
#endif
			rg.x.cx = 0;	/* upper left corner of scroll */
			rg.x.dx = 0x184f;/* lower right */
			int86(0x10, &rg, &rg);
			rg.h.dh = 23;
		}
		ibmmove(rg.h.dh + 1, 0);
		return;
	}

	rg.h.ah = 14;		/* write char to screen with current attrs */
	rg.h.al = ch;
#if	COLOR
	if (dtype != CDMONO)
		rg.h.bl = cfcolor;
	else
		rg.h.bl = 0x07;
#else
	rg.h.bl = 0x07;
#endif
	int86(0x10, &rg, &rg);
}

PASCAL NEAR ibmeeop()
{
	int attr;		/* attribute to fill screen with */

	rg.h.ah = 6;		/* scroll page up function code */
	rg.h.al = 0;		/* # lines to scroll (clear it) */
	rg.x.cx = 0;		/* upper left corner of scroll */
	rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1);
				/* lower right corner of scroll */
#if	COLOR
	if (dtype != CDMONO)
		attr = ((ctrans[gbcolor] & 15) << 4) | (ctrans[gfcolor] & 15);
	else
		attr = 0;
#else
	attr = 0;
#endif
	rg.h.bh = attr;
	int86(0x10, &rg, &rg);
}

PASCAL NEAR ibmrev(state)	/* change reverse video state */

int state;	/* TRUE = reverse, FALSE = normal */

{
	/* This never gets used under the IBM-PC driver */
}

PASCAL NEAR ibmcres(res) /* change screen resolution */

char *res;	/* resolution to change to */

{
	int i;		/* index */

	for (i = 0; i < NDRIVE; i++)
		if (strcmp(res, drvname[i]) == 0) {
			scinit(i);
			return(TRUE);
		}
	return(FALSE);
}

PASCAL NEAR spal()	/* reset the pallette registers */

{
	/* nothin here now..... */
}

PASCAL NEAR ibmbeep()
{
#if	MWC
	ttputc(BEL);
#else
	bdos(6, BEL, 0);
#endif
}

PASCAL NEAR ibmopen()
{
	scinit(CDSENSE);
	revexist = TRUE;
        ttopen();
}

PASCAL NEAR ibmclose()

{
#if	COLOR
	ibmfcol(7);
	ibmbcol(0);
#endif
	/* if we had the EGA open... close it */
	if (dtype == CDEGA || dtype == CDVGA)
		egaclose();

	ttclose();
}

static CtrlC_State;						   /* -- ZU */

PASCAL NEAR ibmkopen()	/* open the keyboard */

{
	rg.x.ax = 0x3300;					   /* -- ZU */
	intdos( &rg, &rg );					   /*     . */
	CtrlC_State = rg.h.dl;					   /* -- UZ */
	rg.x.ax = 0x3301;
	rg.h.dl = 0x00;
	intdos(&rg, &rg);
}

PASCAL NEAR ibmkclose() /* close the keyboard */

{
	rg.x.ax = 0x3301;					   /* -- ZU */
	rg.h.dl = CtrlC_State;					   /*     . */
	intdos(&rg, &rg);					   /* -- UZ */
}

PASCAL NEAR scinit(type) /* initialize the screen head pointers */

int type;	/* type of adapter to init for */

{
	union {
		long laddr;	/* long form of address */
		int *paddr;	/* pointer form of address */
	} addr;
	int i;

	/* if asked...find out what display is connected */
	if (type == CDSENSE)
		type = getboard();

	/* if we have nothing to do....don't do it */
	if (dtype == type)
		return(TRUE);

	/* if we try to switch to EGA and there is none, don't */
	if (type == CDEGA && !egaexist)
		return(FALSE);

	/* if we try to switch to VGA and there is none, don't */
	if (type == CDVGA && !vgaexist )
		return(FALSE);

	/* if we had the EGA or VGA open... close it */
	if (dtype == CDEGA || dtype == CDVGA)
		egaclose();

	/* and set up the various parameters as needed */
	switch (type) {
		case CDMONO:	/* Monochrome adapter */
				scadd = SCADM;
				newsize(TRUE, 25);
				maxlines(25);
				break;

		case CDCGA:	/* Color graphics adapter */
				scadd = SCADC;
				newsize(TRUE, 25);
				maxlines(25);
				break;

		case CDEGA:	/* Enhanced graphics adapter */
				scadd = SCADE;
				egaopen();
				newsize(TRUE, 43);
				maxlines(43);
				break;

		case CDVGA:	/* video graphics array - acts as EGA but more lines */
				scadd = SCADE;
				egaopen();
				newsize(TRUE, 50);
				maxlines(50);
				break;
	}

	/* reset the $sres environment variable */
	strcpy(sres, drvname[type]);
	dtype = type;

	/* initialize the screen pointer array */
	for (i = 0; i < NROW; i++) {
		addr.laddr = scadd + (long)(NCOL * i * 2);
		scptr[i] = addr.paddr;
	}
	return(TRUE);
}

/* getboard:	Determine which type of display board is attached.
		Current known types include:

		CDMONO	Monochrome graphics adapter
		CDCGA	Color Graphics Adapter
		CDEGA	Extended graphics Adapter
		CDVGA	Vidio Graphics Array

		if MONO	set to MONO
		   CGA	set to CGA	EGAexist = FALSE VGAexist = FALSE
		   EGA	set to CGA	EGAexist = TRUE  VGAexist = FALSE
		   VGA	set to CGA	EGAexist = TRUE  VGAexist = TRUE
*/

int PASCAL NEAR getboard()

{
	int type;	/* board type to return */

	type = CDCGA;
	int86(0x11, &rg, &rg);
	if ((((rg.x.ax >> 4) & 3) == 3))
		type = CDMONO;

	/* test if EGA present */
	rg.x.ax = 0x1200;
	rg.x.bx = 0xff10;
	int86(0x10,&rg, &rg);		/* If EGA, bh=0-1 and bl=0-3 */
	egaexist = !(rg.x.bx & 0xfefc);	/* Yes, it's EGA */
	if (egaexist) {
		/* Adapter says it's an EGA. We'll get the same response
		   from a VGA, so try to tell the two apart */
		rg.x.ax = 0x1a00;	/* read display combination */
		int86(0x10,&rg,&rg);
		if (rg.h.al == 0x1a && (rg.h.bl == 7 || rg.h.bl == 8)) {
			/* Function is supported and it's a PS/2 50,60,80 with
			   analog display, so it's VGA (I hope!) */
			vgaexist = TRUE;
		} else {
			/* Either BIOS function not supported or something
			   other then VGA so set it to be EGA */
			vgaexist = FALSE;
		}
	}
	return(type);
}

PASCAL NEAR egaopen()	/* init the computer to work with the EGA or VGA */

{
	/* put the beast into EGA 43/VGA 50 line mode */
	rg.x.ax = 3;
	int86(16, &rg, &rg);

	rg.h.ah = 17;		/* set char. generator function code */
	rg.h.al = 18;		/*  to 8 by 8 double dot ROM         */
	rg.h.bl = 0;		/* block 0                           */
	int86(16, &rg, &rg);

	rg.h.ah = 18;		/* alternate select function code    */
	rg.h.al = 0;		/* clear AL for no good reason       */
	rg.h.bl = 32;		/* alt. print screen routine         */
	int86(16, &rg, &rg);

	rg.h.ah = 1;		/* set cursor size function code */
	rg.x.cx = 0x0607;	/* turn cursor on code */
	int86(0x10, &rg, &rg);

	outp(0x3d4, 10);	/* video bios bug patch */
	outp(0x3d5, 6);
}

PASCAL NEAR egaclose()

{
	/* put the beast into 80 column mode */
	rg.x.ax = 3;
	int86(16, &rg, &rg);
}

PASCAL NEAR scwrite(row, outstr, forg, bacg)	/* write a line out*/

int row;	/* row of screen to place outstr on */
char *outstr;	/* string to write out (must be term.t_ncol long) */
int forg;	/* forground color of string to write */
int bacg;	/* background color */

{
	unsigned int attr;	/* attribute byte mask to place in RAM */
	unsigned int *lnptr;	/* pointer to the destination line */
	int i;

	/* build the attribute byte and setup the screen pointer */
#if	COLOR
	if (dtype != CDMONO)
		attr = (((ctrans[bacg] & 15) << 4) | (ctrans[forg] & 15)) << 8;
	else
		if (bacg != 0)
			attr = 0x7000;
		else
			attr = 0x0700;
#else
	attr = (((bacg & 15) << 4) | (forg & 15)) << 8;
#endif
	lnptr = &sline[0];
	for (i=0; i<term.t_ncol; i++)
		*lnptr++ = (outstr[i] & 255) | attr;

	if (flickcode && (dtype == CDCGA)) {
		/* wait for vertical retrace to be off */
		while ((inp(0x3da) & 8))
			;
	
		/* and to be back on */
		while ((inp(0x3da) & 8) == 0)
			;
	}

	/* and send the string out */
	movmem(&sline[0], scptr[row],term.t_ncol*2);
}

#if	FLABEL
PASCAL NEAR fnclabel(f, n)	/* label a function key */

int f,n;	/* default flag, numeric argument [unused] */

{
	/* on machines with no function keys...don't bother */
	return(TRUE);
}
#endif
#else
ibmhello()
{
}
#endif

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.