Category : C Source Code
Archive   : TEL2307S.ZIP
Filename : RGC.C

 
Output of file : RGC.C contained in archive : TEL2307S.ZIP

/*
* rgc.c by Aaron Contorer for NCSA
* graphics routines for drawing on CGA
* Input coordinate space = 0..4095 by 0..4095
* MUST BE COMPILED WITH LARGE MEMORY MODEL!
*/

#include /* used for debugging only */
#include
#include /* for the FP_SEG & FP_OFF macros */
#include "externs.h"

#define TRUE 1
#define FALSE 0
#define INXMAX 4096
#define INXSHIFT 12
#define INYMAX 4096
#define INYSHIFT 12
#define MAGNIFY 1000
#define SCRNXHI 639
#define SCRNYHI 199
#define MAXRW 32 /* max. number of real windows */
#define CGAxmax 640 /* max. number of pixels in the x direction */
#define CGAymax 200 /* max. number of pixels in the y direction */
#define CGAbytes 80 /* number of bytes per line */

static int CGAactive; /* number of currently CGAactive window */
static char *CGAvidram;
static unsigned char CGApbit[SCRNXHI+1];
#ifdef OLD_WAY
static unsigned char power2[8] = {1,2,4,8,16,32,64,128};
#endif
static char *CGAname = "Color Graphics Adaptor, 640 x 200";

static void CGAsetup(void );

/* Current status of an CGA window */
struct CGAWIN {
char inuse; /* true if window in use */
int pencolor, rotation, size;
int winbot,winleft,wintall,winwide;
/* position of the window in virtual space */
};

static struct CGAWIN CGAwins[MAXRW];

/* prepare variables for use in other functions */
static void CGAsetup(void )
{
int x;
CGApbit[0]=128;
CGApbit[1]=64;
CGApbit[2]=32;
CGApbit[3]=16;
CGApbit[4]=8;
CGApbit[5]=4;
CGApbit[6]=2;
CGApbit[7]=1;
for(x=8; x<=SCRNXHI; x++)
CGApbit[x]=CGApbit[x&7];
#if defined(MSC) && !defined(__TURBOC__) && !defined(__WATCOMC__)
FP_SEG(CGAvidram) = 0xB800;
FP_OFF(CGAvidram) = 0;
#else
CGAvidram=MK_FP(0xB800,0);
#endif
}

/* go into CGA graphics mode */
void RGCgmode(void)
{
n_gmode(6); /* 640x200 BW */
}

/* go into CGA 80x25 color text mode */
void RGCtmode(void)
{
n_gmode(3); /* 80x25 color text */
CGAactive=-1;
}

/* draw a line from (x0,y0) to (x1,y1) */
/* uses Bresenham's Line Algorithm */
void RGCdrawline(int w,int x0,int y0,int x1,int y1)
{
int x,y,dx,dy,d,temp,
dx2,dy2, /* 2dx and 2dy */
direction; /*+1 or-1, used for slope */
char transpose; /* true if switching x and y for vertical-ish line */

if (w!=CGAactive)
return;
x0=(int)(((long)x0*CGAxmax)>>INXSHIFT);
y0=CGAymax-1-(int)(((long)y0*CGAymax)>>INYSHIFT);
x1=(int)(((long)x1*CGAxmax)>>INXSHIFT);
y1=CGAymax-1-(int)(((long)y1*CGAymax)>>INYSHIFT);
if(abs(y1-y0)>abs(x1-x0)) { /* transpose vertical-ish to horizontal-ish */
temp=x1;
x1=y1;
y1=temp;
temp=x0;
x0=y0;
y0=temp;
transpose=TRUE;
}
else
transpose=FALSE;
/* make sure line is left to right */
if(x1 temp=x1;
x1=x0;
x0=temp;
temp=y1;
y1=y0;
y0=temp;
}
/* SPECIAL CASE: 1 POINT */
if(x1==x0&&y1==y0) {
CGAvidram[(y1&1)*8192+(y1>>1)*80+(x1>>3)]|=CGApbit[x1];
return;
}
/* ANY LINE > 1 POINT */
x=x0;
y=y0;
dx=x1-x0;
if(y1>=y0) {
dy=y1-y0;
direction=1;
}
else {
dy=y0-y1;
direction=-1;
}
dx2=dx<<1;
dy2=dy<<1;
d=(dy<<1)-dx;
if(transpose) {
/* CASE OF VERTICALISH (TRANSPOSED) LINES */
while(x<=x1) {
if(y>=0&&y=0&&x CGAvidram[(x&1)*8192+(x>>1)*80+(y>>3)]|=CGApbit[y];
while(d>=0) {
y+=direction;
d -=dx2;
}
d+=dy2;
x++;
}
}
else {
/* CASE OF HORIZONTALISH LINES */
while (x <= x1) {
if(x>=0&&x=0&&y CGAvidram[(y&1)*8192+(y>>1)*80+(x>>3)]|=CGApbit[x];
while(d>=0) {
y+=direction;
d-=dx2;
}
d+=dy2;
x++;
}
} /* end horizontalish */
} /* end CGArasline() */

/*
* Clear the screen.
*/
void RGCclrscr(int w)
{
if(w==CGAactive) {
CGAsetup();
RGCgmode();
}
}

/*
* Set up a new window; return its number.
* Returns -1 if cannot create window.
*/
int RGCnewwin(void)
{
int w=0;

while(w w++;
if(w==MAXRW)
return(-1); /* no windows available */
CGAwins[w].pencolor=7;
CGAwins[w].winbot=0;
CGAwins[w].wintall=3120;
CGAwins[w].winleft=0;
CGAwins[w].winwide=4096;
CGAwins[w].inuse=TRUE;
return(w);
}

void RGCclose(int w)
{
if(CGAactive==w) {
RGCclrscr(w);
CGAactive=-1;
}
CGAwins[w].inuse=FALSE;
}

/* set pixel at location (x,y) -- no range checking performed */
void RGCpoint(int w,int x,int y)
{
int x2,y2; /* on-screen coordinates */

if(w==CGAactive) {
x2=(int)(((long)x*CGAxmax)>>INXSHIFT);
y2=SCRNYHI-(int)(((long)y*CGAymax)>>INYSHIFT);
#ifdef OLD_WAY
CGAvidram[y2*80+(x2>>3)]|=CGApbit[x2];
#else
CGAvidram[(y&1)*8192+(y>>1)*80+(x>>3)]|=CGApbit[x2];
#endif
}
}

/*
Do whatever has to be done when the drawing is all done.
(For printers, that means eject page.)
*/
void RGCpagedone(int w)
{
/* do nothing for CGA */
w=w;
}

/*
Copy 'count' bytes of data to screen starting at current
cursor location.
*/
void RGCdataline(int w,char *data,int count)
{
/* Function not supported yet. */
w=w;
data=data;
count=count;
}

/*
Change pen color to the specified color.
*/
void RGCpencolor(int w,int color)
{
/* Function not supported. */
w=w;
color=color;
}

/*
Set description of future device-supported graphtext.
Rotation=quadrant.
*/
void RGCcharmode(int w,int rotation,int size)
{
/* No rotatable device-supported graphtext is available on CGA. */
w=w;
rotation=rotation;
size=size;
}

/* Not yet supported: */
void RGCshowcur(void) {}
void RGClockcur(void) {}
void RGChidecur(void) {}

/* Ring bell in window w */
void RGCbell(int w)
{
if(w==CGAactive)
putchar(7);
}

/* return name of device that this RG supports */
char *RGCdevname(void)
{
return(CGAname);
}

/* initialize all RGC variables */
void RGCinit(void)
{
int i;
CGAsetup();
for(i=0; i CGAwins[i].inuse=FALSE;
CGAactive=-1;
}

/*
* Make this window visible, hiding all others.
* Caller should follow this with clrscr and redraw to show the current
* contents of the window.
*/
void RGCuncover(int w)
{
CGAactive=w;
}

/* Needed for possible future functionality */
void RGCinfo(int w,int a,int b,int c,int d,int v)
{
w=w;
a=a;
b=b;
c=c;
d=d;
v=v;
}