home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Graphics
/
graphics-16000.iso
/
msdos
/
viewers
/
pcshow
/
options.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-01
|
52KB
|
1,471 lines
/*
* options.c
*
* This set of routines takes care of the image and palette manipulations
* after an image has been read in and displayed.
*
* National Center for Supercomputing Applications, University of Illinois
* 153 Computing Applications Building
* 605 E. Springfield Ave.
* Champaign, IL 61820 (217)244-0072
*
* Quincey Koziol August 1988
*
*/
#include "showext.h"
/**********************************************************************
* Function : strsfn
* Purpose : split a file name into its component parts
* Parameters :
* file - the file name to split up
* drive - pointer to the drive code
* path - directory path pointer
* node - node pointer
* ext - extension pointer
* Returns : none
* Calls : none
* Called by :
**********************************************************************/
void strsfn(file,drive,path,node,ext)
char *file,
*drive,
*path,
*node,
*ext;
{
char *temp, /* temporary pointer to things */
*offset; /* the offset info the file name */
int len; /* the length of various fields */
offset=file; /* start at the beginning of the filename to split */
temp=strrchr(offset,(int)':'); /* find the colon for the drive name */
if(temp!=NULL) {
len=temp-offset+1; /* find the length of the drive specifier */
memmove(drive,offset,len); /* copy the drive specifier */
*(drive+len)=0; /* terminate the string */
offset+=len; /* move the offset to the next protion of the string to search for */
} /* end if */
else /* there is no drive name specified */
strcpy(drive,""); /* copy in a null */
temp=strrchr(offset,(int)'\\'); /* find the last slash */
if(temp!=NULL) {
len=temp-offset; /* find the length of the path specifier minus the final path slash*/
memmove(path,offset,len); /* copy the drive specifier */
*(path+len)=0; /* terminate the string */
offset+=(len+1); /* move the offset to the next protion of the string to search for */
} /* end if */
else /* no path name specified */
strcpy(path,""); /* copy in a null */
temp=strrchr(offset,(int)'.'); /* find the last period */
if(temp!=NULL) {
len=temp-offset; /* find the length of the node specifier minus the final period */
memmove(node,offset,len); /* copy the node specifier */
*(node+len)=0; /* terminate the string */
offset+=(len+1); /* move the offset to the next protion of the string to search for */
len=strlen(offset); /* get the length of the extension */
strcpy(ext,offset); /* copy the extension into it's place */
} /* end if */
else { /* there is no extension specified */
len=strlen(offset); /* get the length of the extension */
strcpy(node,offset); /* copy the filename into it's place */
strcpy(ext,""); /* copy a null string into the extension */
} /* end else */
} /* end strsfn() */
/**********************************************************************
* Function : getfnl
* Purpose : get a file name list
* Parameters :
* fnp - the file name pattern
* fna - the file name array
* fnasize - the size of the file name array
* attr - the attributes of the files to search for
* Returns : -1 for bad file name, or the number of file names put into list
* Calls : _dos_getdrive(), _dos_getdrive(), _dos_findfirst(),
* _dos_findnext(),
* Called by : ()
**********************************************************************/
int getfnl(fnp,fna,fnasize,attr)
char *fnp,
*fna;
unsigned int fnasize;
unsigned int attr;
{
struct find_t *buffer; /* pointer to a findfirst structure */
char *temp, /* temporary buffer pointer */
*def_name, /* the name to place in front of all the names generated */
*cwd, /* the current directory */
*ext, /* the extension for the file name */
*node, /* node for the file name */
*curr_drive, /* drive of the file name */
*new_name, /* the name to search for minus the drive and path stuff */
*path; /* path of a file name */
int len, /* the length of a string */
error, /* the error return from findfirst and findnext */
new_drive, /* the drive to change into */
num_copied=0, /* the number of file copied into the file name array */
total_size=0, /* the number of bytes copied so far */
drive; /* the current drive */
cwd=(char *)malloc(64); /* allocate room for the current directory */
curr_drive=(char *)malloc(3); /* allocate room for the dirve */
path=(char *)malloc(64); /* allocate room for the path */
node=(char *)malloc(9); /* allocate room for the node */
ext=(char *)malloc(4); /* allocaet room for the file extension */
buffer=(struct find_t *)malloc(sizeof(struct find_t)); /* allocate room for the buffer */
getcwd(cwd,64); /* get the current directory */
strcpy(cwd,cwd+2); /* insert the slash in front of the directory */
_dos_getdrive(&drive); /* get the current drive */
strsfn(fnp,curr_drive,path,node,ext); /* split the file into it's components */
if(*curr_drive>='A') /* check for a real drive */
new_drive=*curr_drive-'A'+1; /* get the drive to change to */
_dos_setdrive(new_drive,&error);
chdir(path); /* change to the new directory */
def_name=(char *)malloc(75); /* allocate space for the default name to begin all the file names with */
strcpy(def_name,curr_drive); /* copy the drive over */
strcat(def_name,path); /* and append the path */
new_name=(char *)malloc(16); /* allocate room for the name to search for */
strcpy(new_name,node); /* copy the node into the new name */
strcat(new_name,"."); /* add a period to it */
strcat(new_name,ext); /* and finally the period */
if((error=_dos_findfirst(new_name,attr,buffer))==0) {
num_copied=1;
temp=fna; /* start at the beginning of the file name array */
if(strlen((*buffer).name)+1<=fnasize) { /* size of array is large enough to hold the name */
strcpy(temp,(*buffer).name); /* copy the name over */
total_size+=(strlen(temp)+1); /* increment the number of bytes we have copied so far */
temp+=(strlen(temp)+1); /* increment the pointer for the next string */
while((error=_dos_findnext(buffer))==0 && num_copied!=0) { /* copy until we run out of the files to copy */
if(strlen((*buffer).name)+1+total_size<=fnasize) { /* make sure we don't run over the total size for the file name array */
strcpy(temp,(*buffer).name); /* copy the name over */
total_size+=(strlen(temp)+1); /* increment the number of bytes we have copied so far */
temp+=(strlen(temp)+1); /* increment the pointer for the next string */
num_copied++; /* increment the number of files copied into the buffer */
} /* end if */
else
num_copied=0;
} /* end while */
if(num_copied==0)
error=-1;
else {
*temp=0; /* put the final null terminating byte on the good strings */
error=num_copied; /* get the proper value to return */
} /* end else */
} /* end if */
else
error=-1;
} /* end if */
else
error=-1;
_dos_setdrive(drive,&len);
chdir(cwd); /* change back to the old directory */
free((char *)curr_drive); /* free the current drive area */
free((char *)path); /* free the path name area */
free((char *)node); /* free the node area */
free((char *)ext); /* free the extension area */
free((char *)cwd);
free((char *)def_name); /* free the default name */
free((char *)new_name); /* free the new name to search for */
free((char *)buffer); /* free the space used for the findfirst buffer */
return(error); /* return the error code */
} /* end getfnl() */
/**********************************************************************
* Function : draw_mouse()
* Purpose : draw the mouse cursor on the screen
* Parameters : none
* Returns : none
* Calls : mousecml(), makecur9()
* Called by : mousefunc(), parse(), window(),
**********************************************************************/
void draw_mouse()
{
if(mode==NO9)
makecur9(mx,my);
else {
m1=1;
mousecml(&m1,&m2,&m3,&m4);
} /* end else */
} /* end draw_mouse() */
/**********************************************************************
* Function : erase_mouse()
* Purpose : erase the mouse cursor from the screen
* Parameters : none
* Returns : none
* Calls : mousecml(), makecur9()
* Called by : mousefunc(), parse(), window(),
**********************************************************************/
void erase_mouse()
{
if(mode==NO9)
makecur9(mx,my);
else {
m1=2;
mousecml(&m1,&m2,&m3,&m4);
} /* end else */
} /* end erase_mouse() */
/**********************************************************************
* Function : read_mouse()
* Purpose : read the mouse position and button status and scale for correct
* display mode
* Parameters : none
* Returns : none
* Calls : mousecml()
* Called by : mousefunc(), parse(), window(),
**********************************************************************/
void read_mouse()
{
m1=3; /* get mouse position and button status */
mousecml(&m1,&m2,&m3,&m4);
leftbutton=rightbutton=0;
leftbutton=m2&1; /* get left button bit from mouse variable */
rightbutton=(m2&2)>>1; /* get right button bit from mouse variable */
if(mode!=EGA)
m3=m3>>1; /* compensate for the mouse */
if(mode==NO9) { /* if no9 then compensate the mouse more */
m3=m3>>2;
m4=m4>>3;
} /* end if */
} /* end read_mouse()*/
/**********************************************************************
* Function : readstr
* Purpose : get a simple set of characters from stdin
* Parameters :
* charstr - pointer to the character string to be read in
* Returns : none
* Calls : getch()
* Called by : parse()
**********************************************************************/
void readstr(charstr)
unsigned char *charstr;
{
charstr--;
do {
charstr++;
*charstr=getch();
if(*charstr==0)
*charstr=getch()|(unsigned char)128; /* set high bit to indicate extended code */
printf("%c",*charstr);
} while(*charstr!=13); /* end while */
*charstr=0;
}
/**********************************************************************
* Function : swapint
* Purpose : swap two integer values
* Parameters :
* x,y - pointers to the two values to swap
* Returns : none
* Calls : none
* Called by : mousefunc()
**********************************************************************/
void swapint(x,y)
int *x,*y; /* values to exchange */
{
int t; /* temporary variable */
t=*x;
*x=*y;
*y=t;
} /* end swapint() */
/**********************************************************************
* Function : swap
* Purpose : swap two character values
* Parameters :
* x,y - pointers to the two values to swap
* Returns : none
* Calls : none
* Called by : options()
**********************************************************************/
void swap(x,y)
unsigned char *x,*y; /* values to exchange */
{
unsigned char t; /* temporary variable */
t=*x;
*x=*y;
*y=t;
} /* end swap() */
/**********************************************************************
* Function : findpal
* Purpose : loads in a new palette from an HDF file after the first one
* Parameters : none
* Returns : none
* Calls : DFfind(), DFgetelement(), palloc(), palloce(), select_pal()
* Called by : options()
**********************************************************************/
void findpal()
{
int i, /* local counting variable */
palold; /* last palmax value */
char *pi; /* pointer to character array of palette read in */
DFsetfind(dff,DFTG_IP8,DFREF_WILDCARD); /* set the HDF file to a palette */
palold=palmax;
if (!DFfind(dff,&ddstr)) { /* HDF file should be set for palettes */
if(DFgetelement(dff,ddstr.tag,ddstr.ref,pal)>=0) {
pi = pal;
for (i=0; i<256; i++) {
rmap[i] = *pi++;
gmap[i] = *pi++;
bmap[i] = *pi++;
} /* end for */
palmax++;
} /* end if */
} /* end if */
/* see if there is enough space for another palette */
if(palmax!=palold) {
if(mode!=EGA) {
if(!palloc(palmax)) { /* if no space available then go back to last one */
palmax--;
displayerr("No Room For Another Palette");
memcpy(rmap,rpal[palnum],256);
memcpy(gmap,gpal[palnum],256);
memcpy(bmap,bpal[palnum],256);
} /* end if */
else /* palloc() was ok, so switch to the palette */
palnum=palmax;
} /* end if */
else {
if(!palloce(palmax)) { /* no space, so switch to old palette */
displayerr("No Room For Another Palette");
palmax--;
memcpy(regrs,egapals[palnum],16);
} /* end if */
else { /* enough space for a palette, so use it */
palnum=palmax;
select_pal(xdim,ydim,1); /* do a frequency count and set up the ega palette */
} /* end else */
} /* end else */
} /* end if */
} /* end findpal() */
/**********************************************************************
* Function : showpal
* Purpose : display the current palette on the screen. EGA monitors
* directly change to data in memory, whereas VGA and NO9 monitors
* just change the data on the screen.
* Parameters : none
* Returns : none
* Calls : showpalv(), showpal9(), egaline()
* Called by : options()
**********************************************************************/
void showpal()
{
#ifdef MOUSE
if(mouse)
erase_mouse();
#endif
switch (mode) { /* different methods for showing the palette on the screen */
case VGA:
showpalv(palstore,pal_xoff,pal_yoff);
break;
case NO9:
showpal9(palstore,pal_xoff,pal_yoff);
break;
case EGA:
default:
for(i=0; i<16; i++)
for(k=0; k<16; k++)
palstore[0][i*16+k]=i;
for(j=0; j<8; j++) /* for no. 9 and vga, direct memory copies are used in assembly, but ega must be done 'by hand' */
egaline(xwhere+pal_xoff,ywhere+j+pal_yoff,&palstore[0][0],0,256);
break;
} /* end switch(mode) */
#ifdef MOUSE
if(mouse)
draw_mouse();
#endif
} /* end showpal() */
/**********************************************************************
* Function : nopal
* Purpose : replace the palette on the screen with the image under it.
* Once again, EGA mode changes the data in memory, whereas VGA
* NO9 change it only on the screen.
* Parameters :
* xoff,yoff - the x & y offsets into the image where the screen is
* positioned
* Returns : none
* Calls : nopalv(), nopal9(), egaline()
* Called by : options()
**********************************************************************/
void nopal(xoff,yoff)
int xoff,yoff; /* the x & y offset into the image being displayed */
{
#ifdef MOUSE
if(mouse)
erase_mouse();
#endif
switch(mode){ /* different routines to restore the screen */
case VGA:
nopalv(palstore,pal_xoff,pal_yoff);
break;
case NO9:
nopal9(palstore,pal_xoff,pal_yoff);
break;
case EGA:
default:
if(pal_yoff<(ydim-pal_height))
for(j=0; j<8; j++) /* just re plot that section of the screen */
egaline(xwhere+pal_xoff,ywhere+j+pal_yoff,store[j+pal_yoff+yoff],xoff+pal_xoff,min(256,xdim-pal_xoff));
break;
} /* end switch(mode) */
#ifdef MOUSE
if(mouse)
draw_mouse();
#endif
} /* end nopal() */
/**********************************************************************
* Function : waitq
* Purpose : wait for a keypress
* Parameters : none
* Returns : none
* Calls : none
* Called by : many places...
**********************************************************************/
void waitq()
{
unsigned char c; /* temporary variable to hold the character read in */
c='!';
while (c=='!') {
if(kbhit()) { /* get the next command */
c=getch();
if(c==0)
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
} /* end while */
} /* waitq() */
/**********************************************************************
* Function : printdir
* Purpose : print out a listing of files ending in '.pal' in the
* current local directory
* Parameters : none
* Returns : none
* Calls : textmode()
* Called by : options()
**********************************************************************/
void printdir()
{
unsigned char palnames[4096]; /* array to store palette names */
char *p, /* pointer to position if names file */
*fnp="*.pal"; /* pattern to look for */
int n, /* number of matching file names */
attr=0; /* look for normal files */
if((n=getfnl(fnp,palnames,sizeof(palnames),attr))<=0) /* load the names of the palettes into an array */
printf("No Palettes In The Current Directory\n");
else
for(p=palnames; *p!='\0'; p+=strlen(p)+1) /* write out all the names */
printf("%s\n",p);
printf("\nHit Any Key To Continue");
waitq();
textmode();
} /* end printdir() */
#ifdef QAK
/**********************************************************************
* Function : slidepal
* Purpose : rotate the palette an arbitary amount
* Parameters :
* offset - the amount to slide the palette
* Returns : none
* Calls : none
* Called by : options()
**********************************************************************/
void slidepal(x)
int x; /* amount of positive or negative offset to slide the palette */
{
if(mode!=EGA){
if(x<0){
memcpy(rmap,rpal[palnum]-x,256+x); /* shift palettes down x bytes */
memcpy(gmap,gpal[palnum]-x,256+x);
memcpy(bmap,bpal[palnum]-x,256+x);
for(j=255+x; j<=255; j++){ /* fill in the leftover places */
rmap[j]=rmap[j-1];
gmap[j]=gmap[j-1];
bmap[j]=bmap[j-1];
} /* end for */
} /* end if */
else{
memcpy(rmap+x,rpal[palnum],256-x); /* shift palettes up x bytes */
memcpy(gmap+x,gpal[palnum],256-x);
memcpy(bmap+x,bpal[palnum],256-x);
for(j=x; j>=0; j--){ /* fill in the leftover places */
rmap[j]=rmap[j+1];
gmap[j]=gmap[j+1];
bmap[j]=bmap[j+1];
} /* end for */
} /* end else */
} /* end if */
} /* end slidepal() */
#endif
/**********************************************************************
* Function : squishpal
* Purpose : compress the palette an arbitrary amount
* Parameters :
* slope - the slope of the line to compress palette with
* offset - the amount to slide the palette
* Returns : none
* Calls : abs()
* Called by : options()
**********************************************************************/
void squishpal(x,y)
int x, /* the slope of the line to squish the palette with */
y; /* the offset to slide the palette by when the squishing is done */
{
int j,k, /* temporary counting variables */
lox, /* the value of the x-intercept if y=0 */
hix; /* the value of the x-intercept if y=255 */
if(x!=0){
lox=(10*((-127)-y)/x)+127;
hix=(10*(128-y)/x)+127;
} /* end if */
else{
lox=127;
hix=127;
} /* end else */
if(lox!=0) /* check for the beginning value not on the beginning of the palette */
if(lox<0)
lox=0; /* if i=it is before the palette then set it to beginning of the palette */
else{
for(j=lox-1; j>=0; j--){ /* if it is after the beginning of the palette then fill to beginning */
rmap[j]=rpal[palnum][lox-1];
gmap[j]=gpal[palnum][lox-1];
bmap[j]=bpal[palnum][lox-1];
} /* end for j */
} /* end else */
if(hix!=255) /* check for end value not exactly on the end of the palette */
if(hix>255) /* if it is after the end of the palette then set it to the end of the palette */
hix=255;
else{
for(j=hix+1; j<=255; j++){ /* if it is before the end of the palette then fill to the end */
rmap[j]=rpal[palnum][hix+1];
gmap[j]=gpal[palnum][hix+1];
bmap[j]=bpal[palnum][hix+1];
} /* end for j */
} /* end else */
if(hix<lox) /* make sure it increments in correct fashion */
swap(&lox,&hix);
for(j=lox; j<=hix; j++){
k=x*(j-127)/10+127+y; /* y = mx+b equation of a line */
rmap[j]=rpal[palnum][k];
gmap[j]=gpal[palnum][k];
bmap[j]=bpal[palnum][k];
} /* end for j */
} /* end squishpal() */
#ifdef QAK
/**********************************************************************
* Function : pixelcolor
* Purpose : returns the color of a specified pixel
* Parameters :
* x - the x coor. of the pixel
* y - the y coor. of the pixel
* Returns : the color of the pixel as a char
* Calls : none
* Called by : mousefunc()
**********************************************************************/
unsigned char pixelcolor(x,y)
int x,y; /* the x and y coor. of the pixel whose color is returned */
{
if(show && ((x>=pal_xoff && x<=(pal_xoff+255)) && (y>=pal_yoff && y<=(pal_yoff+pal_height))))
switch(mode) { /* return different values for different screen types */
case VGA:
case NO9:
return((unsigned char) (x-pal_xoff));
break;
case EGA:
default:
return((unsigned char) ((x-pal_xoff)/16));
break;
} /* end switch */
else /* if not in the color bar then return the normal value */
return((unsigned char) store[y+yoff][x+xoff]);
} /* end pixelcolor() */
#endif
/**********************************************************************
* Function : updatescrn
* Purpose : updates the screen with the current image, color bar,
* and the mouse cursor
* Parameters : none
* Returns : none
* Calls : showpic(), showpal(), pixelcolor()
* Called by : options()
**********************************************************************/
void updatescrn()
{
showpic();
if(show)
showpal();
#ifdef MOUSE
if(mouse) /* if the mouse is on then replace the mouse cursor */
draw_mouse();
#endif
} /* end updatescrn() */
/**********************************************************************
* Function : scroll
* Purpose : move the image around the screen
* Parameters :
* func - the scrolling function to be performed
* Returns : none
* Calls : updatescrn()
* Called by : options(), mousefunc()
**********************************************************************/
void scroll(func)
unsigned char func; /* the function to be performed on the screen */
{
int i; /* temporary variables to hold the old xoff and yoff */
#ifdef MOUSE
if(mouse) /* if the mouse is on then hide the cursor while moving */
erase_mouse();
#endif
switch(func) { /* switch to perform the appropriate scroll */
case 'l': /* scroll left */
i=xoff;
xoff-=10;
if(xoff<0)
xoff=0;
if(xoff!=i)
updatescrn();
break;
case 'r': /* scroll right */
i=xoff;
xoff+=10;
if(xdim-maxx<0)
xoff=0;
else
if(xoff>xdim-maxx)
xoff=xdim-maxx;
if(i!=xoff)
updatescrn();
break;
case 'u': /* scroll up */
i=yoff;
yoff-=10;
if(yoff<0)
yoff=0;
if(yoff!=i)
updatescrn();
break;
case 'd': /* scroll down */
i=yoff;
yoff+=10;
if(ydim-maxy<0)
yoff=0;
else
if(yoff>ydim-maxy)
yoff=ydim-maxy;
if(i!=yoff)
updatescrn();
break;
case 'H': /* Move to upper left hand corner of image */
if(yoff!=0||xoff!=0) {
xoff=0;
yoff=0;
updatescrn();
} /* end if */
break;
case 'E': /* Move to lower right hand corner of image */
if(yoff!=ydim-maxy||xoff!=xdim-maxx) {
xoff=xdim-maxx;
if(xoff<0)
xoff=0;
yoff=ydim-maxy;
if(yoff<0)
yoff=0;
updatescrn();
} /* end if */
break;
case 'U': /* page image up */
i=yoff;
yoff-=maxy;
if(yoff<0)
yoff=0;
if(yoff!=i)
updatescrn();
break;
case 'D': /* page image down */
i=yoff;
yoff+=maxy;
if(ydim-maxy<0)
yoff=0;
else
if(yoff>ydim-maxy)
yoff=ydim-maxy;
if(i!=yoff)
updatescrn();
break;
} /* end switch */
#ifdef MOUSE
if(mouse) /* if the mouse is on then replace the cursor after moving */
draw_mouse();
#endif
} /* end scroll() */
/**********************************************************************
* Function : rotate
* Purpose : rotate the palette left or right
* Parameters :
* func - character to determine which direction to rotate
* Returns : none
* Calls : putpal(), memcpy()
* Called by : options(), mousefunc()
**********************************************************************/
void rotate(func)
unsigned char func; /* parameter to determine which way to rotate the palette */
{
switch(func) { /* switch for what to do to the palette */
case 'l': /* rotate the palette left */
if(mode!=EGA) {
i=rmap[255];
j=gmap[255];
k=bmap[255];
memcpy(rmap+1,rmap,255); /* shift palettes up one byte */
memcpy(gmap+1,gmap,255);
memcpy(bmap+1,bmap,255);
rmap[0]=i;
gmap[0]=j;
bmap[0]=k;
} /* end if */
else {
i=regrs[15];
for(j=15; j>=1; j--)
regrs[j]=regrs[j-1];
regrs[0]=i;
} /* end else */
putpal();
break;
case 'r': /* rotate the palette right */
if(mode!=EGA) {
i=rmap[0];
j=gmap[0];
k=bmap[0];
memcpy(rmap,rmap+1,255); /* shift palettes down one byte */
memcpy(gmap,gmap+1,255);
memcpy(bmap,bmap+1,255);
rmap[255]=i;
gmap[255]=j;
bmap[255]=k;
} /*end if */
else {
i=regrs[0];
for(j=0; j<=14; j++)
regrs[j]=regrs[j+1];
regrs[15]=i;
} /* end else */
putpal();
break;
} /* end switch */
} /* end rotate() */
/**********************************************************************
* Function : expand
* Purpose : routine to blow up a section of the screen
* Parameters :
* x1,y1 - location of the upper left hand corner of the box to blow up
* x2,y2 - location of the lower right hand corner of the box to blow up
* Returns :
* 1 - if routine was successfully finished
* 0 - if routine was interupted
* Calls : vgaline1()
* Called by : mousefunc()
**********************************************************************/
int expand(x1,y1,x2,y2)
int x1,y1, /* location of the upper left hand corner of the box to blow up */
x2,y2; /* location of the lower right hand corner of the box to blow up */
{
unsigned char line[640]; /* a line to blow a line of the box up into */
float xdiff,ydiff, /* the differences between the x and y corners */
maxxf,maxyf; /* a float variable for maxx and maxy */
int i,j,k,l,m;
xdiff=x2-x1; /* find difference between endpoints */
ydiff=y2-y1;
maxxf=maxx;
maxyf=maxy;
l=-1; /* preset the line counter to calculate the first line */
for(i=0; i<maxy; i++) { /* go through all the lines in the image */
k=(int)((i/maxyf)*ydiff)+y1;
if(k!=l) { /* if this line is not the same as the previous then re-calculate it */
for(j=0; j<maxx; j++) /* go through each line and magnify */
line[j]=store[k][(int)((j/maxxf)*xdiff)+x1];
l=k; /* set the line */
} /* end if */
switch(mode) { /* use different line drawing routines for different screens */
case VGA:
vgaline1(0,i,line,0,maxx); /* send each line out to the screen */
break;
case NO9:
no9line(0,i,line,0,maxx);
break;
case EGA:
default:
egaline(0,i,line,0,maxx);
break;
} /* end switch */
if(kbhit()) { /* break out if the keyboard is hit */
m=getch(); /* clear the keyboard buffer */
if(m==0) /* get extended code if necessary */
m=getch()|(unsigned char)128; /* set high bit to indicate extended code */
return(0);
} /* end if */
} /* end for */
return(1);
} /* end expand() */
/**********************************************************************
* Function : interpolation
* Purpose : routine to blow up a section of the screen and interpolate
* data to a smooth image
* Parameters :
* x1,y1 - location of the upper left hand corner of the box to blow up
* x2,y2 - location of the lower right hand corner of the box to blow up
* Returns :
* 1 - if routine was successfully finished
* 0 - if routine was interupted
* Calls : vgaline1(), egaline(), no9line(), interdata()
* Called by : mousefunc()
**********************************************************************/
int interpolate(x1,y1,x2,y2)
int x1,y1, /* location of the upper left hand corner of the box to blow up */
x2,y2; /* location of the lower right hand corner of the box to blow up */
{
unsigned char line[640]; /* a line to blow a line of the box up into */
float hpercent,vpercent, /* the percentage of the distance the pixel is towards the hi value */
vdata1,vdata2, /* the data for the vertical interpolation */
hfinal, /* the final result for horizontal interpolation */
hdata1,hdata2, /* the data for horizontal interpolation */
vfinal, /* the final result for vertical interpolation */
xdiff,ydiff, /* the differences between the x and y corners */
tempy,tempx, /* temporary floating value */
maxxf,maxyf; /* a float variable for maxx and maxy */
int i,j,hix,lox,hiy,loy; /* integer values for the coor. in the images around the current pixel */
xdiff=x2-x1; /* find difference between endpoints */
ydiff=y2-y1;
maxxf=maxx;
maxyf=maxy;
for(i=0; i<maxy; i++) { /* go through all the lines in the image */
tempy=((i/maxyf)*ydiff)+(float)y1; /* calculate the fractional pixel position in the image */
loy=tempy; /* calculate the address of the lower y bound */
hiy=ceil(tempy); /* calculate the address of the upper y bound */
vpercent=(tempy-(float)loy)/((float)hiy-(float)loy);
for(j=0; j<maxx; j++) { /* go through each line and interpolate */
tempx=((j/maxxf)*xdiff)+(float)x1; /* calculate the fractional pixel position in the image */
lox=tempx; /* calculate the lower x bound */
hix=ceil(tempx); /* calculate the upper x bound */
vdata1=(store[hiy][lox]-store[loy][lox])*vpercent+store[loy][lox];
vdata2=(store[hiy][hix]-store[loy][hix])*vpercent+store[loy][hix];
hpercent=(tempx-(float)lox)/((float)hix-(float)lox);
hfinal=(vdata2-vdata1)*hpercent+vdata1;
hdata1=(store[loy][hix]-store[loy][lox])*hpercent+store[loy][lox];
hdata2=(store[hiy][hix]-store[hiy][lox])*hpercent+store[hiy][lox];
vfinal=(hdata2-hdata1)*vpercent+hdata1;
line[j]=(hfinal+vfinal)/2.0;
} /* end for */
switch(mode) { /* use different line drawing routines for different screens */
case VGA:
vgaline1(0,i,line,0,maxx); /* send each line out to the screen */
break;
case NO9:
no9line(0,i,line,0,maxx);
break;
case EGA:
default:
egaline(0,i,line,0,maxx);
break;
} /* end switch */
if(kbhit()) { /* break out if the keyboard is hit */
i=getch();
if(i==0) /* get extended code if necessary */
i=getch()|(unsigned char)128; /* set high bit to indicate extended code */
return(0);
} /* end if */
} /* end for */
return(1);
} /* end interpolation() */
#ifdef MOUSE
/**********************************************************************
* Function : makehex
* Purpose : convert an ascii string of binary digits into an integer
* Parameters :
* binstr - string of binary digits
* Returns : integer value of binary string
* Calls : pow(), strlen()
* Called by : makemouse()
**********************************************************************/
int makehex(binstr)
char *binstr;
{
int i,j,k; /* local counting variables */
double pow(); /* pow(x,y) returns x to the y power */
k=strlen(binstr); /* find the length of the binary string */
i=0;
for(j=k-1; j>=0; j--) /* make a binary string into a hex number */
i+=((int)pow((double)2,(double)j))*((int)*(binstr++)-48);
return(i);
}
/**********************************************************************
* Function : makemouse
* Purpose : make the mouse cursor into a crosshair for vga and ega modes
* Parameters : none
* Returns : none
* Calls : mousecml()
* Called by : options()
**********************************************************************/
void makemouse()
{
int cursor[2][16]; /* array for screen and cursor bit masks */
if(mode!=NO9) { /* only do this for vga and ega modes */
/* screen mask */
cursor[0][0]= makehex("1001111111111111");
cursor[0][1]= makehex("1010111111111111");
cursor[0][2]= makehex("1011011111111111");
cursor[0][3]= makehex("1011101111111111");
cursor[0][4]= makehex("1011110111111111");
cursor[0][5]= makehex("1011111011111111");
cursor[0][6]= makehex("1011111101111111");
cursor[0][7]= makehex("1011111011111111");
cursor[0][8]= makehex("1010011011111111");
cursor[0][9]= makehex("1001101101111111");
cursor[0][10]=makehex("1111101101111111");
cursor[0][11]=makehex("1111110011111111");
cursor[0][12]=makehex("1111111111111111");
cursor[0][13]=makehex("1111111111111111");
cursor[0][14]=makehex("1111111111111111");
cursor[0][15]=makehex("1111111111111111");
/* cursor mask */
for(i=0; i<16; i++) /* set the entire cursor mask to inverse of the screen mask */
cursor[1][i]=~cursor[0][i];
m1=9; /* function to define cursor shape and hot spot */
m2=0; /* horizontal hot spot */
m3=0; /* vertical hot spot */
mousecml(&m1,&m2,&m3,&cursor[0][0]);
m1=1; /* function to show the cursor */
mousecml(&m1,&m2,&m3,&m4);
} /* end if */
} /* end makemouse() */
#endif
#ifdef QAK
/**********************************************************************
* Function : bounce
* Purpose : bounce a ball on the screen
* Parameters : none
* Returns : none
* Calls : drand48(), ball()
* Called by : options()
**********************************************************************/
void bounce()
{
int x1[5],x2[5],y1[5],y2[5], /* variables to keep track of the balls position */
j, /* timing variable */
i, /* local counting variable */
maxball=0, /* number of balls on the screen */
ballsize, /* size of the ball in pixels */
xspeed[5],yspeed[5]; /* variables to keep track of the balls speed */
double drand48(); /* random number function */
long time(),l; /* the system time for seeding the random pointer */
void parse(),srand48(); /* command parsing function */
srand48(time(&l)); /* seed the random number generator */
if(mode==NO9) /* set the ball sizes for different screens */
ballsize=8;
else
ballsize=4;
x1[0]=(int)(drand48()*(double)(maxx-ballsize-1))+1; /* randomize starting position */
x2[0]=x1[0];
y1[0]=(int)(drand48()*(double)(maxy-ballsize-1))+1;
y2[0]=y1[0];
xspeed[0]=0;
while(xspeed[0]==0) /* randomize speed, not allowing 0 speed in a direction */
xspeed[0]=(int)(drand48()*(double)11)-6;
yspeed[0]=0;
while(yspeed[0]==0)
yspeed[0]=(int)(drand48()*(double)11)-6;
#ifdef MOUSE
m1=11; /* reset the mouse position counters */
mousecml(&m1,&m2,&m3,&m4);
#endif
m3=m4=0;
if(mode==NO9) /* plot the ball */
ball9(x1[0],y1[0]);
else
ball(x1[0],y1[0]);
while(!kbhit() && !m3 && !m4) { /* bounce the ball until a key is pressed */
for(i=maxball; i>=0; i--) { /* check through all the balls */
if(mode==NO9)
ball9(x1[i],y1[i]);
else
ball(x1[i],y1[i]); /* remove the ball */
x2[i]+=xspeed[i]; /* move the ball */
y2[i]+=yspeed[i];
if(x2[i]<0 || x2[i]>(maxx-ballsize-1)) { /* check for off screen in the x direction */
xspeed[i]=-(xspeed[i]); /* reverse the direction of the movement */
x2[i]+=xspeed[i];
} /* end if */
if(y2[i]<0 || y2[i]>(maxy-ballsize-1)) { /* check for off screen in the y direction */
yspeed[i]=-(yspeed[i]);
y2[i]+=yspeed[i];
} /* end if */
if(mode==NO9)
ball9(x2[i],y2[i]);
else
ball(x2[i],y2[i]); /* plot the ball in it's new position */
x1[i]=x2[i]; /* update the balls position */
y1[i]=y2[i];
if((int)(drand48()*(double)10000)==0) /* on very rare occasions change the ball speed */
switch ((int)(drand48()*4)) { /* choose which speed to change */
case 0:
xspeed[i]++;
break;
case 1:
xspeed[i]--;
break;
case 2:
yspeed[i]++;
break;
case 3:
yspeed[i]--;
break;
} /* end switch */
} /* end for */
for(j=0; j<(5-maxball)*600+2000; j++); /* waiting loop */
if(maxball<4) /* if not at the maximum amount of balls then check for addition of a ball */
if((int)(drand48()*(double)1000)==0) { /* less than one in a hundred chance */
maxball++;
x1[maxball]=(int)(drand48()*(double)(maxx-ballsize-1))+1; /* randomize starting position */
x2[maxball]=x1[maxball];
y1[maxball]=(int)(drand48()*(double)(maxy-ballsize-1))+1;
y2[maxball]=y1[maxball];
xspeed[maxball]=0;
while(xspeed[maxball]==0) /* randomize speed, not allowing 0 speed in a direction */
xspeed[maxball]=(int)(drand48()*(double)11)-6;
yspeed[maxball]=0;
while(yspeed[maxball]==0)
yspeed[maxball]=(int)(drand48()*(double)11)-6;
if(mode==NO9)
ball9(x1[maxball],y1[maxball]);
else
ball(x1[maxball],y1[maxball]); /* plot the new ball */
} /* end if */
#ifdef MOUSE
m1=11; /* check for the mouse moving */
mousecml(&m1,&m2,&m3,&m4);
#endif
} /* end while */
for(i=maxball; i>=0; i--)
if(mode==NO9)
ball9(x1[i],y1[i]);
else
ball(x1[i],y1[i]); /* erase balls from screen */
if(kbhit()) { /* if it was the keyboard and not the mouse */
j=getch(); /* flush the keyboard buffer */
if(j==0) /* get extended code if necessary */
j=getch()|(unsigned char)128; /* set high bit to indicate extended code */
parse((unsigned char)j);
} /* end if */
} /* end bounce() */
#endif
/**********************************************************************
* Function : outlinee
* Purpose : draw an outlined box on the ega screen
* Parameters :
* x1,y1 - the x & y coor. of the upper left hand corner
* x2,y2 - the x & y coor. of the lower right hand corner
* Returns : none
* Calls : lineega()
* Called by : outline()
**********************************************************************/
void outlinee(x1,y1,x2,y2)
int x1,y1,x2,y2;
{
int i,j; /* temporary counting variables */
if(x2<x1)
swapint(&x1,&x2);
if(y2<y1)
swapint(&y1,&y2);
if(x2>=xdim) /* clip the box if it is outside the image */
x2=xdim-1;
if(x1>=xdim)
x1=xdim-1;
if(y2>=ydim)
y2=ydim-1;
if(y1>=ydim)
y1=ydim-1;
for(i=x1+xoff; i<=x2+xoff; i++) /* go through each pixel in the top line */
*(store[y1+yoff]+i)=~*(store[y1+yoff]+i);
for(i=x1+xoff; i<=x2+xoff; i++) /* go through each pixel in the bottom line */
*(store[y2+yoff]+i)=~*(store[y2+yoff]+i);
for(j=y1+1+yoff; j<y2+yoff; j++) { /* go thru and fix all the lines in between */
*(store[j]+x1+xoff)=~*(store[j]+x1+xoff);
*(store[j]+x2+xoff)=~*(store[j]+x2+xoff);
} /* end for */
for(i=y1; i<=y2; i++) { /* output the lines to the screen */
egaline(xwhere+x1,ywhere+i,store[i+yoff],x1+xoff,x2-x1+1);
} /* end for */
}
/**********************************************************************
* Function : outline
* Purpose : call routines to put an outlined box on the screen
* Parameters :
* x1,y1 - the x & y coor. of the upper left hand corner
* x2,y2 - the x & y coor. of the lower right hand corner
* Returns : none
* Calls : outline9(), outlinev(), outlinee()
* Called by : mousefunc()
**********************************************************************/
void outline(x1,y1,x2,y2)
int x1,y1,x2,y2;
{
switch(mode) { /* switch to call different outline routines depending on monitor type */
case NO9:
outline9(x1,y1,x2,y2);
break;
case VGA:
outlinev(x1,y1,x2,y2);
break;
case EGA:
default:
outlinee(x1,y1,x2,y2); /* need offsets because ega has to modify the image data */
break;
} /* end switch */
}
#ifdef MOUSE
/**********************************************************************
* Function : mousefunc
* Purpose : perform all of the mouse functions
* Parameters : none
* Returns : none
* Calls : mousecml(), pixelcolor()
* Called by : options()
**********************************************************************/
void mousefunc()
{
int off_x,off_y, /* the offset the mouse cursor is inside the color bar */
firstx,firsty; /* the location of the first corner plotted in drawing a box */
read_mouse(); /* get mouse position and button status */
if(mx!=m3 || my!=m4) { /* the mouse has been moved so update the screen */
if(mode==NO9) { /* update the mouse position for no9 screen */
makecur9(mx,my);
mx=m3;
my=m4;
makecur9(mx,my);
} /* end if */
else {
mx=m3; /* update the old mouse positions */
my=m4;
} /* end else */
} /* end if */
if(rightbutton && show && (mx>=pal_xoff && mx<=(pal_xoff+255))) /* if inside the color bar when the right button is pressed, then move color bar */
if(my>=pal_yoff && my<=(pal_yoff+pal_height)) { /* if mouse cursor is in the color bar then move it */
nopal(xoff,yoff); /* erase the color bar */
if(mode==NO9) {
makecur9(mx,my);
off_x=mx-pal_xoff; /* set the offset in the color bar */
off_y=my-pal_yoff;
} /* end if */
else {
m1=2; /* erase the cursor */
mousecml(&m1,&m2,&m3,&m4);
off_x=mx-pal_xoff; /* set the offset in the color bar */
off_y=my-pal_yoff;
} /* end else */
outline(pal_xoff,pal_yoff,pal_xoff+255,pal_yoff+pal_height); /* plot the outline of the color bar */
do { /* keep moving the palette until the button is let up */
read_mouse(); /* get mouse position and button status */
if((m3+256-off_x)>maxx) /* if trying to move the color bar off the left side of the screen */
m3=maxx-256+off_x;
if((m3-off_x)<0) /* if trying to move off the right side of the screen */
m3=off_x;
if((m4+pal_height+1-off_y)>maxy) /* if trying to move off the bottom of the screen */
m4=maxy-pal_height-1+off_y;
if((m4-off_y)<0) /* if trying to move off the top of the screen */
m4=off_y;
if(m3!=mx || m4!=my) { /* if mouse is moved then move outline of color bar */
outline(mx-off_x,my-off_y,mx-off_x+255,my-off_y+pal_height);
mx=m3;
my=m4;
outline(mx-off_x,my-off_y,mx-off_x+255,my-off_y+pal_height);
} /* end if */
} while(rightbutton);
pal_xoff=mx-off_x; /* find to upper left hand corner for the color bar */
pal_yoff=my-off_y;
outline(pal_xoff,pal_yoff,pal_xoff+255,pal_yoff+pal_height);
draw_mouse();
showpal(); /* put the color bar back on the screen */
} /* end if */
if(rightbutton) { /* rightbutton functions */
erase_mouse();
if(mx>9 && mx<(maxx-9)) { /* if not within the active region in the x dir. */
if(my<10) /* if within 10 pixels of top then scroll up */
scroll('u');
if(my>(maxy-10)) /* if within 10 pixels of bottn then scroll down */
scroll('d');
} /* end if */
if(mx>(maxx-10)) /* if within 10 pixels of edge of screen then do something */
if(my<10 || my>(maxy-10)) /* if in one of the corners then page */
if(my<10) /* page up */
scroll('U');
else /* page down */
scroll('D');
else /* scroll right */
scroll('r');
if(mx<10) /* if within 10 pixels of edge of the screen then do something */
if(my<10 || my>(maxy-10)) /* if in one of the corners then home/end */
if(my<10) /* Home */
scroll('H');
else /* End */
scroll('E');
else /* scroll left */
scroll('l');
draw_mouse();
} /* end if */
if(leftbutton) { /* leftbutton functions */
if(show && (mx>=pal_xoff && mx<=(pal_xoff+255)) && (my>=pal_yoff && my<=(pal_yoff+pal_height))) {
if((mx-pal_xoff)<128) { /* if on the left side then rotate that way */
rotate('r');
for(j=abs(mx-pal_xoff)*10; j>=0; j--);
} /* end if */
else { /* must be on right side so rotate that way */
rotate('l');
for(j=(255-abs(mx-pal_xoff))*10; j>=0; j--);
} /* end else */
} /* end if */
else { /* draw an outlined box on the screen */
erase_mouse();
firstx=mx;
firsty=my;
outline(firstx,firsty,mx,my);
do { /* keep changing the size of the outline until the button is let up */
read_mouse(); /* get mouse position and button status */
if(m3!=mx || m4!=my) { /* if mouse is moved then move outline of color bar */
outline(firstx,firsty,mx,my); /* erase the outline */
mx=m3;
my=m4;
outline(firstx,firsty,mx,my); /* re plot the outline */
} /* end if */
} while(leftbutton);
outline(firstx,firsty,mx,my);
if(firstx>mx) /* if square is defined backwards then flip ends */
swapint(&firstx,&mx);
if(firsty>my)
swapint(&firsty,&my);
if(mx>xdim-xoff) /* prevent the box from being outside the image */
mx=xdim;
if(my>ydim-yoff)
my=ydim;
if(firstx<xdim-xoff && firsty<ydim-yoff) { /* if the box is actually in the image on the screen then expand */
grafmode(); /* clear the screen */
if(expandit) { /* if preference is to expand the image */
if(expand(firstx+xoff,firsty+yoff,mx+xoff,my+yoff)==1) /* expand chosen area to fill screen */
waitq(); /* wait for keypress */
} /* end if */
else { /* if preference is to interpolate the image */
if(interpolate(firstx+xoff,firsty+yoff,mx+xoff,my+yoff)==1) /* expand and smooth the chosen area to fill the screen */
waitq(); /* wait for keypress */
} /* end else */
} /* end if */
updatescrn(); /* go back to old display */
} /* end else */
} /* end if */
} /* end mousefunc() */
#endif
/**********************************************************************
* Function : options
* Purpose : do all the fancy run-time things to the image
* Parameters : none
* Returns : none
* Calls : parse(), mousecml(), mousefunc(), bounce()
* Called by : main()
**********************************************************************/
void options()
{
palnum=0; /* start out at the first palette */
#ifdef MOUSE
if(mouse) /* if the mouse is already on then put it on the screen */
draw_mouse();
#endif
c='!';
if(kbhit()) {
c=getch();
if(c==0) /* check for extended character code */
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
while(c!='q' && !(c=='a' && animate) && c!='Q') { /* continue until 'q' */
c='!';
#ifdef QAK
waitcount=0;
#endif
while (c=='!') {
if(kbhit()) { /* get the next command */
c=getch();
if(c==0)
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
#ifdef MOUSE
if(mouse) { /* if the mouse is active then perform some functions */
mousefunc();
#ifdef QAK
waitcount=0; /* reset the counter to time out */
#endif
} /* end if */
#endif
#ifdef QAK
if(waitcount>100000) { /* if timed out then bounce the ball */
if(mode==VGA || mode==NO9)
bounce();
waitcount=0; /* reset the timed out counter */
} /* end if */
waitcount++;
#endif
} /* end while */
if(c=='?') { /* if help is requisitioned */
if(mouse && mode==NO9)
makecur9(mx,my);
textmode();
printf("General Help Screen\n\n");
printf("i\t\t - Show Information About Image\n");
printf("a\t\t - Show Animation Again\n");
printf("k\t\t - End Animation Mode\n");
printf("o\t\t - Turn VGA Screen Off Or On\n");
printf("m\t\t - Activate/Deactivate Mouse\n");
printf(",\t\t - Magnify\Interpolate A Portion Of The Screen\n");
printf("w\t\t - Switch Between Magnifying And Interpolating\n");
printf("/\t\t - Slow Down Animation Speed\n");
printf("*\t\t - Speed Up Animation Speed\n");
printf("q\t\t - Quit Viewing Current Image\n");
printf("Q\t\t - Exit Program\n");
printf("?\t\t - Show This Help Sequence\n\n");
printf("Hit <enter> For More Help, Or Any Key to Return to Graphics Mode");
c='!';
while (c=='!') {
if(kbhit()) { /* get the next command */
c=getch();
if(c==0)
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
} /* end while */
printf("\n");
if(c==13){ /* if enter is hit for next help screen */
textmode();
printf("Palette Help Screen\n\n");
printf("f\t\t - Rotate Palette Continuously Forward\n");
printf("b\t\t - Rotate Palette Continuously Backward\n");
printf("+\t\t - Speed Up Palette Rotation\n");
printf("-\t\t - Slow Down Palette Rotation\n");
printf("space bar\t - Stop Rotation Of Palette Or Animation\n");
printf("e\t\t - Rotate Palette Once Forward\n");
printf("v\t\t - Rotate Palette Once Backward\n");
printf("r\t\t - Reset Palette To Original Settings\n");
printf("c\t\t - Toggle Color Bar On Or Off The Screen\n");
printf("l\t\t - Load In A New Palette From Disk\n");
printf("n\t\t - Display Next Palette In Memory\n");
printf("s\t\t - Store Palette On Disk\n");
printf("u\t\t - Swap The Red, Green, And Blue Components Of Palettes\n");
printf("t\t\t - Transpose Palette\n");
printf("g\t\t - Invert Palette Bitwise\n");
printf("h\t\t - Enter Fiddle Mode\n");
printf("p\t\t - Move Color Bar On The Screen\n");
printf("d\t\t - Make Current Palette The Default Values\n\n");
printf("Hit <enter> For More Help, Or Any Key to Return to Graphics Mode");
c='!';
while (c=='!') {
if(kbhit()) { /* get the next command */
c=getch();
if(c==0)
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
} /* end while */
printf("\n");
if(c==13) {
textmode();
printf("Image Help Screen\n\n");
printf("left arrow\t - Move Image Left Ten Pixels\n");
printf("up arrow\t - Move Image Up Ten Pixels\n");
printf("down arrow\t - Move Image Down Ten Pixels\n");
printf("right arrow\t - Move Image Right Ten Pixels\n");
printf("page up\t - Page Image Up A Full Screen\n");
printf("page down\t - Page Image Down A Full Screen\n");
printf("home\t\t - Move To The Upper Left Hand Corner Of The Image\n");
printf("end\t\t - Move To The Lower Right Hand Corner Of The Image\n");
printf("x\t\t - Input X and Y Coor. For Upper Left Hand Corner\n");
printf("Hit Any Key to Return To Graphics Mode");
c='!';
while (c=='!') {
if(kbhit()) { /* get the next command */
c=getch();
if(c==0)
c=getch()|(unsigned char)128; /* set high bit to indicate extended code */
} /* end if */
} /* end while */
printf("\n");
} /* end if */
} /* end if */
grafmode();
updatescrn();
} /* end if */
parse(c);
} /* end while */
#ifdef MOUSE
if(mouse) /* if the mouse is on then remove the cursor before leaving */
erase_mouse();
#endif
} /* end options() */