home *** CD-ROM | disk | FTP | other *** search
/ Graphics 16,000 / graphics-16000.iso / msdos / viewers / pcshow / options.c < prev    next >
C/C++ Source or Header  |  1991-07-01  |  52KB  |  1,471 lines

  1. /*
  2. *    options.c
  3. *
  4. *    This set of routines takes care of the image and palette manipulations
  5. *  after an image has been read in and displayed.
  6. *
  7. *  National Center for Supercomputing Applications, University of Illinois
  8. *  153 Computing Applications Building
  9. *  605 E. Springfield Ave.
  10. *  Champaign, IL  61820     (217)244-0072
  11. *
  12. *  Quincey Koziol            August 1988
  13. *
  14. */
  15.  
  16. #include "showext.h"
  17.  
  18. /**********************************************************************
  19. *  Function    :    strsfn
  20. *  Purpose    :    split a file name into its component parts
  21. *  Parameters    :
  22. *            file - the file name to split up
  23. *            drive - pointer to the drive code
  24. *            path - directory path pointer
  25. *            node - node pointer
  26. *            ext - extension pointer
  27. *  Returns    :    none
  28. *  Calls    :    none
  29. *  Called by    :    
  30. **********************************************************************/
  31. void strsfn(file,drive,path,node,ext)
  32. char *file,
  33.     *drive,
  34.     *path,
  35.     *node,
  36.     *ext;
  37. {
  38.     char *temp,                    /* temporary pointer to things */
  39.         *offset;                /* the offset info the file name */
  40.     int    len;                    /* the length of various fields */
  41.  
  42.     offset=file;                /* start at the beginning of the filename to split */
  43.     temp=strrchr(offset,(int)':');    /* find the colon for the drive name */
  44.     if(temp!=NULL) {
  45.         len=temp-offset+1;        /* find the length of the drive specifier */
  46.         memmove(drive,offset,len);    /* copy the drive specifier */
  47.         *(drive+len)=0;        /* terminate the string */
  48.         offset+=len;            /* move the offset to the next protion of the string to search for */
  49.       }    /* end if */
  50.     else                        /* there is no drive name specified */
  51.         strcpy(drive,"");        /* copy in a null */
  52.     temp=strrchr(offset,(int)'\\');    /* find the last slash */
  53.     if(temp!=NULL) {
  54.         len=temp-offset;        /* find the length of the path specifier minus the final path slash*/
  55.         memmove(path,offset,len);    /* copy the drive specifier */
  56.         *(path+len)=0;        /* terminate the string */
  57.         offset+=(len+1);        /* move the offset to the next protion of the string to search for */
  58.       }    /* end if */
  59.     else                        /* no path name specified */
  60.         strcpy(path,"");        /* copy in a null */
  61.     temp=strrchr(offset,(int)'.');    /* find the last period */
  62.     if(temp!=NULL) {
  63.         len=temp-offset;        /* find the length of the node specifier minus the final period */
  64.         memmove(node,offset,len);    /* copy the node specifier */
  65.         *(node+len)=0;        /* terminate the string */
  66.         offset+=(len+1);        /* move the offset to the next protion of the string to search for */
  67.         len=strlen(offset);        /* get the length of the extension */
  68.         strcpy(ext,offset);        /* copy the extension into it's place */
  69.       }    /* end if */
  70.     else {                    /* there is no extension specified */
  71.         len=strlen(offset);        /* get the length of the extension */
  72.         strcpy(node,offset);    /* copy the filename into it's place */
  73.         strcpy(ext,"");            /* copy a null string into the extension */
  74.       }    /* end else */
  75. }    /* end strsfn() */
  76.  
  77. /**********************************************************************
  78. *  Function    :    getfnl
  79. *  Purpose    :    get a file name list
  80. *  Parameters    :
  81. *            fnp - the file name pattern
  82. *            fna - the file name array
  83. *            fnasize - the size of the file name array
  84. *            attr - the attributes of the files to search for
  85. *  Returns    :    -1 for bad file name, or the number of file names put into list
  86. *  Calls    :    _dos_getdrive(), _dos_getdrive(), _dos_findfirst(),
  87. *             _dos_findnext(),
  88. *  Called by    :    ()
  89. **********************************************************************/
  90. int getfnl(fnp,fna,fnasize,attr)
  91. char *fnp,
  92.     *fna;
  93. unsigned int fnasize;
  94. unsigned int attr;
  95. {
  96.     struct find_t *buffer;    /* pointer to a findfirst structure */
  97.     char *temp,                    /* temporary buffer pointer */
  98.         *def_name,                /* the name to place in front of all the names generated */
  99.         *cwd,                    /* the current directory */
  100.         *ext,                    /* the extension for the file name */
  101.         *node,                    /* node for the file name */
  102.         *curr_drive,            /* drive of the file name */
  103.         *new_name,                /* the name to search for minus the drive and path stuff */
  104.         *path;                    /* path of a file name */
  105.     int len,                    /* the length of a string */
  106.         error,                    /* the error return from findfirst and findnext */
  107.         new_drive,                /* the drive to change into */
  108.         num_copied=0,            /* the number of file copied into the file name array */
  109.         total_size=0,            /* the number of bytes copied so far */
  110.         drive;                    /* the current drive */
  111.  
  112.     cwd=(char *)malloc(64);            /* allocate room for the current directory */
  113.     curr_drive=(char *)malloc(3);    /* allocate room for the dirve */
  114.     path=(char *)malloc(64);        /* allocate room for the path */
  115.     node=(char *)malloc(9);            /* allocate room for the node */
  116.     ext=(char *)malloc(4);            /* allocaet room for the file extension */
  117.     buffer=(struct find_t *)malloc(sizeof(struct find_t));    /* allocate room for the buffer */
  118.     getcwd(cwd,64);                    /* get the current directory */
  119.     strcpy(cwd,cwd+2);                /* insert the slash in front of the directory */
  120.     _dos_getdrive(&drive);            /* get the current drive */
  121.     strsfn(fnp,curr_drive,path,node,ext);            /* split the file into it's components */
  122.     if(*curr_drive>='A')            /* check for a real drive */
  123.         new_drive=*curr_drive-'A'+1;        /* get the drive to change to */
  124.     _dos_setdrive(new_drive,&error);
  125.     chdir(path);                    /* change to the new directory */
  126.     def_name=(char *)malloc(75);    /* allocate space for the default name to begin all the file names with */
  127.     strcpy(def_name,curr_drive);    /* copy the drive over */
  128.     strcat(def_name,path);            /* and append the path */
  129.     new_name=(char *)malloc(16);    /* allocate room for the name to search for */
  130.     strcpy(new_name,node);            /* copy the node into the new name */
  131.     strcat(new_name,".");            /* add a period to it */
  132.     strcat(new_name,ext);            /* and finally the period */
  133.     if((error=_dos_findfirst(new_name,attr,buffer))==0) {
  134.         num_copied=1;
  135.         temp=fna;                    /* start at the beginning of the file name array */
  136.         if(strlen((*buffer).name)+1<=fnasize) {    /* size of array is large enough to hold the name */
  137.             strcpy(temp,(*buffer).name);    /* copy the name over */
  138.             total_size+=(strlen(temp)+1);    /* increment the number of bytes we have copied so far */
  139.             temp+=(strlen(temp)+1);            /* increment the pointer for the next string */
  140.             while((error=_dos_findnext(buffer))==0 && num_copied!=0) {        /* copy until we run out of the files to copy */
  141.                 if(strlen((*buffer).name)+1+total_size<=fnasize) {        /* make sure we don't run over the total size for the file name array */
  142.                     strcpy(temp,(*buffer).name);    /* copy the name over */
  143.                     total_size+=(strlen(temp)+1);    /* increment the number of bytes we have copied so far */
  144.                     temp+=(strlen(temp)+1);            /* increment the pointer for the next string */
  145.                     num_copied++;                    /* increment the number of files copied into the buffer */
  146.                   }    /* end if */
  147.                 else
  148.                     num_copied=0;
  149.               }    /* end while */
  150.             if(num_copied==0)
  151.                 error=-1;
  152.             else {
  153.                 *temp=0;                        /* put the final null terminating byte on the good strings */
  154.                 error=num_copied;            /* get the proper value to return */
  155.               }    /* end else */
  156.           }    /* end if */
  157.         else
  158.             error=-1;
  159.       }    /* end if */
  160.     else
  161.         error=-1;
  162.     _dos_setdrive(drive,&len);
  163.     chdir(cwd);                        /* change back to the old directory */
  164.     free((char *)curr_drive);        /* free the current drive area */
  165.     free((char *)path);                /* free the path name area */
  166.     free((char *)node);                /* free the node area */
  167.     free((char *)ext);                /* free the extension area */
  168.     free((char *)cwd);
  169.     free((char *)def_name);            /* free the default name */
  170.     free((char *)new_name);            /* free the new name to search for */
  171.     free((char *)buffer);            /* free the space used for the findfirst buffer */
  172.     return(error);                    /* return the error code */
  173. }    /* end getfnl() */
  174.  
  175. /**********************************************************************
  176. *  Function    :    draw_mouse()
  177. *  Purpose    :    draw the mouse cursor on the screen
  178. *  Parameters    :    none
  179. *  Returns    :    none
  180. *  Calls    :    mousecml(), makecur9()
  181. *  Called by    :    mousefunc(), parse(), window(),
  182. **********************************************************************/
  183. void draw_mouse()
  184. {
  185.     if(mode==NO9)
  186.         makecur9(mx,my);
  187.     else {
  188.         m1=1;
  189.         mousecml(&m1,&m2,&m3,&m4);
  190.       }    /* end else */
  191. }    /* end draw_mouse() */
  192.  
  193. /**********************************************************************
  194. *  Function    :    erase_mouse()
  195. *  Purpose    :    erase the mouse cursor from the screen
  196. *  Parameters    :    none
  197. *  Returns    :    none
  198. *  Calls    :    mousecml(), makecur9()
  199. *  Called by    :    mousefunc(), parse(), window(),
  200. **********************************************************************/
  201. void erase_mouse()
  202. {
  203.     if(mode==NO9)
  204.         makecur9(mx,my);
  205.     else {
  206.         m1=2;
  207.         mousecml(&m1,&m2,&m3,&m4);
  208.       }    /* end else */
  209. }    /* end erase_mouse() */
  210.  
  211. /**********************************************************************
  212. *  Function    :    read_mouse()
  213. *  Purpose    :    read the mouse position and button status and scale for correct
  214. *        display mode
  215. *  Parameters    :    none
  216. *  Returns    :    none
  217. *  Calls    :    mousecml()
  218. *  Called by    :    mousefunc(), parse(), window(),
  219. **********************************************************************/
  220. void read_mouse()
  221. {
  222.     m1=3;        /* get mouse position and button status */
  223.     mousecml(&m1,&m2,&m3,&m4);
  224.     leftbutton=rightbutton=0;
  225.     leftbutton=m2&1;        /* get left button bit from mouse variable */
  226.     rightbutton=(m2&2)>>1;        /* get right button bit from mouse variable */
  227.     if(mode!=EGA)
  228.         m3=m3>>1;                /* compensate for the mouse */
  229.     if(mode==NO9) {            /* if no9 then compensate the mouse more */
  230.         m3=m3>>2;
  231.         m4=m4>>3;
  232.       }    /* end if */
  233. }    /* end read_mouse()*/
  234.  
  235. /**********************************************************************
  236. *  Function    :    readstr
  237. *  Purpose    :    get a simple set of characters from stdin
  238. *  Parameters    :
  239. *            charstr -    pointer to the character string to be read in
  240. *  Returns    :    none
  241. *  Calls    :    getch()
  242. *  Called by    :    parse()
  243. **********************************************************************/
  244. void readstr(charstr)
  245. unsigned char *charstr;
  246. {
  247.     charstr--;
  248.     do {
  249.         charstr++;
  250.         *charstr=getch();
  251.         if(*charstr==0)
  252.             *charstr=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  253.         printf("%c",*charstr);
  254.       }    while(*charstr!=13);        /* end while */
  255.     *charstr=0;
  256. }
  257.  
  258. /**********************************************************************
  259. *  Function    :    swapint
  260. *  Purpose    :    swap two integer values
  261. *  Parameters    :
  262. *            x,y - pointers to the two values to swap
  263. *  Returns    :    none
  264. *  Calls    :    none
  265. *  Called by    :    mousefunc()
  266. **********************************************************************/
  267. void swapint(x,y)
  268. int    *x,*y;        /* values to exchange */
  269. {
  270.     int    t;        /* temporary variable */
  271.  
  272.     t=*x;
  273.     *x=*y;
  274.     *y=t;
  275. } /* end swapint() */
  276.  
  277. /**********************************************************************
  278. *  Function    :    swap
  279. *  Purpose    :    swap two character values
  280. *  Parameters    :
  281. *            x,y - pointers to the two values to swap
  282. *  Returns    :    none
  283. *  Calls    :    none
  284. *  Called by    :    options()
  285. **********************************************************************/
  286. void swap(x,y)
  287. unsigned char *x,*y;        /* values to exchange */
  288. {
  289.     unsigned char t;        /* temporary variable */
  290.  
  291.     t=*x;
  292.     *x=*y;
  293.     *y=t;
  294. } /* end swap() */
  295.  
  296. /**********************************************************************
  297. *  Function    :    findpal
  298. *  Purpose    :    loads in a new palette from an HDF file after the first one
  299. *  Parameters    :    none
  300. *  Returns    :    none
  301. *  Calls    :    DFfind(), DFgetelement(), palloc(), palloce(), select_pal()
  302. *  Called by    :    options()
  303. **********************************************************************/
  304. void findpal()
  305. {
  306.     int i,    /* local counting variable */
  307.         palold;        /* last palmax value */
  308.     char *pi; /* pointer to character array of palette read in */
  309.  
  310.     DFsetfind(dff,DFTG_IP8,DFREF_WILDCARD);    /* set the HDF file to a palette */
  311.  
  312.     palold=palmax;
  313.     if (!DFfind(dff,&ddstr)) {    /* HDF file should be set for palettes */
  314.         if(DFgetelement(dff,ddstr.tag,ddstr.ref,pal)>=0) {
  315.             pi = pal;
  316.             for (i=0; i<256; i++) {
  317.                 rmap[i] = *pi++;
  318.                 gmap[i] = *pi++;
  319.                 bmap[i] = *pi++;
  320.               } /* end for */
  321.             palmax++;
  322.           }    /* end if */
  323.     } /* end if */
  324.  
  325. /* see if there is enough space for another palette */
  326.  
  327.     if(palmax!=palold) {
  328.         if(mode!=EGA) {
  329.             if(!palloc(palmax)) {    /* if no space available then go back to last one */
  330.                 palmax--;
  331.                 displayerr("No Room For Another Palette");
  332.                 memcpy(rmap,rpal[palnum],256);
  333.                 memcpy(gmap,gpal[palnum],256);
  334.                 memcpy(bmap,bpal[palnum],256);
  335.               } /* end if */
  336.             else                /* palloc() was ok, so switch to the palette */
  337.                 palnum=palmax;
  338.           } /* end if */
  339.         else {
  340.             if(!palloce(palmax)) {    /* no space, so switch to old palette */
  341.                 displayerr("No Room For Another Palette");
  342.                 palmax--;
  343.                 memcpy(regrs,egapals[palnum],16);
  344.               } /* end if */
  345.             else {            /* enough space for a palette, so use it */
  346.                 palnum=palmax;
  347.                 select_pal(xdim,ydim,1);    /* do a frequency count and set up the ega palette */
  348.               } /* end else */
  349.           }    /* end else */
  350.       }    /* end if */
  351. } /* end findpal() */
  352.  
  353. /**********************************************************************
  354. *  Function    :    showpal
  355. *  Purpose    :    display the current palette on the screen.  EGA monitors
  356. *            directly change to data in memory, whereas VGA and NO9 monitors
  357. *            just change the data on the screen.
  358. *  Parameters    :    none
  359. *  Returns    :    none
  360. *  Calls    :    showpalv(), showpal9(), egaline()
  361. *  Called by    :    options()
  362. **********************************************************************/
  363. void showpal()
  364. {
  365. #ifdef MOUSE
  366.     if(mouse)
  367.         erase_mouse();
  368. #endif
  369.     switch (mode) {        /* different methods for showing the palette on the screen */
  370.         case VGA:
  371.             showpalv(palstore,pal_xoff,pal_yoff);
  372.             break;
  373.  
  374.         case NO9:
  375.             showpal9(palstore,pal_xoff,pal_yoff);
  376.             break;
  377.  
  378.         case EGA:
  379.         default:
  380.             for(i=0; i<16; i++)
  381.                 for(k=0; k<16; k++)
  382.                     palstore[0][i*16+k]=i;
  383.             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' */
  384.                 egaline(xwhere+pal_xoff,ywhere+j+pal_yoff,&palstore[0][0],0,256);
  385.             break;
  386.       }    /* end switch(mode) */
  387. #ifdef MOUSE
  388.     if(mouse)
  389.         draw_mouse();
  390. #endif
  391. } /* end showpal() */
  392.  
  393. /**********************************************************************
  394. *  Function    :    nopal
  395. *  Purpose    :    replace the palette on the screen with the image under it.
  396. *            Once again, EGA mode changes the data in memory, whereas VGA
  397. *            NO9 change it only on the screen.
  398. *  Parameters    :
  399. *        xoff,yoff - the x & y offsets into the image where the screen is
  400. *            positioned
  401. *  Returns    :    none
  402. *  Calls    :    nopalv(), nopal9(), egaline()
  403. *  Called by    :    options()
  404. **********************************************************************/
  405. void nopal(xoff,yoff)
  406. int xoff,yoff;    /* the x & y offset into the image being displayed */
  407. {
  408. #ifdef MOUSE
  409.     if(mouse)
  410.         erase_mouse();
  411. #endif
  412.     switch(mode){        /* different routines to restore the screen */
  413.         case VGA:
  414.             nopalv(palstore,pal_xoff,pal_yoff);
  415.             break;
  416.  
  417.         case NO9:
  418.             nopal9(palstore,pal_xoff,pal_yoff);
  419.             break;
  420.  
  421.         case EGA:
  422.         default:
  423.             if(pal_yoff<(ydim-pal_height))
  424.                 for(j=0; j<8; j++)        /* just re plot that section of the screen */
  425.                     egaline(xwhere+pal_xoff,ywhere+j+pal_yoff,store[j+pal_yoff+yoff],xoff+pal_xoff,min(256,xdim-pal_xoff));
  426.             break;
  427.       }    /* end switch(mode) */
  428. #ifdef MOUSE
  429.     if(mouse)
  430.         draw_mouse();
  431. #endif
  432. } /* end nopal() */
  433.         
  434. /**********************************************************************
  435. *  Function    :    waitq
  436. *  Purpose    :    wait for a keypress
  437. *  Parameters    :    none
  438. *  Returns    :    none
  439. *  Calls    :    none
  440. *  Called by    :    many places...
  441. **********************************************************************/
  442. void waitq()
  443. {
  444.     unsigned char c;    /* temporary variable to hold the character read in */
  445.  
  446.     c='!';
  447.     while (c=='!') {
  448.         if(kbhit()) {    /* get the next command */
  449.             c=getch();
  450.             if(c==0)
  451.                 c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  452.           }    /* end if */
  453.        }    /* end while */
  454. }    /* waitq() */
  455.  
  456. /**********************************************************************
  457. *  Function    :    printdir
  458. *  Purpose    :    print out a listing of files ending in '.pal' in the 
  459. *            current local directory
  460. *  Parameters    :    none
  461. *  Returns    :    none
  462. *  Calls    :    textmode()
  463. *  Called by    :    options()
  464. **********************************************************************/
  465. void printdir()
  466. {
  467.     unsigned char    palnames[4096];        /* array to store palette names */
  468.     char *p,                /* pointer to position if names file */
  469.         *fnp="*.pal";        /* pattern to look for */
  470.     int    n,                    /* number of matching file names */
  471.         attr=0;                /* look for normal files */
  472.     
  473.     if((n=getfnl(fnp,palnames,sizeof(palnames),attr))<=0)    /* load the names of the palettes into an array */
  474.         printf("No Palettes In The Current Directory\n");
  475.     else
  476.         for(p=palnames; *p!='\0'; p+=strlen(p)+1)    /* write out all the names */
  477.             printf("%s\n",p);
  478.     printf("\nHit Any Key To Continue");
  479.     waitq();
  480.     textmode();
  481. } /* end printdir() */
  482.  
  483. #ifdef QAK
  484. /**********************************************************************
  485. *  Function :    slidepal
  486. *  Purpose    :    rotate the palette an arbitary amount
  487. *  Parameters    :
  488. *        offset - the amount to slide the palette
  489. *  Returns    :    none
  490. *  Calls    :    none
  491. *  Called by    :    options()
  492. **********************************************************************/
  493. void slidepal(x)
  494. int    x;    /* amount of positive or negative offset to slide the palette */
  495. {
  496.     if(mode!=EGA){
  497.         if(x<0){
  498.             memcpy(rmap,rpal[palnum]-x,256+x);        /* shift palettes down x bytes */
  499.             memcpy(gmap,gpal[palnum]-x,256+x);
  500.             memcpy(bmap,bpal[palnum]-x,256+x);
  501.             for(j=255+x; j<=255; j++){    /* fill in the leftover places */
  502.                 rmap[j]=rmap[j-1];
  503.                 gmap[j]=gmap[j-1];
  504.                 bmap[j]=bmap[j-1];
  505.               }    /* end for */
  506.           }    /* end if */
  507.         else{
  508.             memcpy(rmap+x,rpal[palnum],256-x);        /* shift palettes up x bytes */
  509.             memcpy(gmap+x,gpal[palnum],256-x);
  510.             memcpy(bmap+x,bpal[palnum],256-x);
  511.             for(j=x; j>=0; j--){        /* fill in the leftover places */
  512.                 rmap[j]=rmap[j+1];
  513.                 gmap[j]=gmap[j+1];
  514.                 bmap[j]=bmap[j+1];
  515.               }    /* end for */
  516.           } /* end else */
  517.       }    /* end if */
  518. } /* end slidepal() */
  519. #endif
  520.  
  521. /**********************************************************************
  522. *  Function :    squishpal
  523. *  Purpose    :    compress the palette an arbitrary amount
  524. *  Parameters    :
  525. *        slope  - the slope of the line to compress palette with
  526. *        offset - the amount to slide the palette
  527. *  Returns    :    none
  528. *  Calls    :    abs()
  529. *  Called by    :    options()
  530. **********************************************************************/
  531. void squishpal(x,y)
  532. int    x,        /* the slope of the line to squish the palette with */
  533.     y;        /* the offset to slide the palette by when the squishing is done */
  534. {
  535.     int        j,k,    /* temporary counting variables */
  536.             lox,    /* the value of the x-intercept if y=0 */
  537.             hix;    /* the value of the x-intercept if y=255 */
  538.  
  539.     if(x!=0){
  540.         lox=(10*((-127)-y)/x)+127;
  541.         hix=(10*(128-y)/x)+127;
  542.       }    /* end if */
  543.     else{
  544.         lox=127;
  545.         hix=127;
  546.       }    /* end else */
  547.     if(lox!=0)        /* check for the beginning value not on the beginning of the palette */
  548.         if(lox<0)
  549.             lox=0;    /* if i=it is before the palette then set it to beginning of the palette */
  550.         else{
  551.             for(j=lox-1; j>=0; j--){    /* if it is after the beginning of the palette then fill to beginning */
  552.                 rmap[j]=rpal[palnum][lox-1];
  553.                 gmap[j]=gpal[palnum][lox-1];
  554.                 bmap[j]=bpal[palnum][lox-1];
  555.               }    /* end for j */
  556.           }    /* end else */
  557.     if(hix!=255)    /* check for end value not exactly on the end of the palette */
  558.         if(hix>255)    /* if it is after the end of the palette then set it to the end of the palette */
  559.             hix=255;
  560.         else{
  561.             for(j=hix+1; j<=255; j++){    /* if it is before the end of the palette then fill to the end */
  562.                 rmap[j]=rpal[palnum][hix+1];
  563.                 gmap[j]=gpal[palnum][hix+1];
  564.                 bmap[j]=bpal[palnum][hix+1];
  565.               }    /* end for j */
  566.           }    /* end else */
  567.     if(hix<lox)        /* make sure it increments in correct fashion */
  568.         swap(&lox,&hix);
  569.     for(j=lox; j<=hix; j++){
  570.         k=x*(j-127)/10+127+y;    /* y = mx+b equation of a line */
  571.         rmap[j]=rpal[palnum][k];
  572.         gmap[j]=gpal[palnum][k];
  573.         bmap[j]=bpal[palnum][k];
  574.       }    /* end for j */
  575. } /* end squishpal() */
  576.  
  577. #ifdef QAK
  578. /**********************************************************************
  579. *  Function    :    pixelcolor
  580. *  Purpose    :    returns the color of a specified pixel
  581. *  Parameters    :
  582. *            x - the x coor. of the pixel
  583. *            y - the y coor. of the pixel
  584. *  Returns    :    the color of the pixel as a char
  585. *  Calls    :    none
  586. *  Called by    :    mousefunc()
  587. **********************************************************************/
  588. unsigned char pixelcolor(x,y)
  589. int    x,y;    /* the x and y coor. of the pixel whose color is returned */
  590. {
  591.     if(show && ((x>=pal_xoff && x<=(pal_xoff+255)) && (y>=pal_yoff && y<=(pal_yoff+pal_height))))
  592.         switch(mode) {    /* return different values for different screen types */
  593.             case VGA:
  594.             case NO9:
  595.                 return((unsigned char) (x-pal_xoff));
  596.                 break;
  597.  
  598.             case EGA:
  599.             default:
  600.                 return((unsigned char) ((x-pal_xoff)/16));
  601.                 break;
  602.           }    /* end switch */
  603.     else    /* if not in the color bar then return the normal value */
  604.         return((unsigned char) store[y+yoff][x+xoff]);
  605. }    /* end pixelcolor() */
  606. #endif
  607.  
  608. /**********************************************************************
  609. *  Function    :    updatescrn
  610. *  Purpose    :    updates the screen with the current image, color bar,
  611. *                    and the mouse cursor
  612. *  Parameters    :    none
  613. *  Returns    :    none
  614. *  Calls    :    showpic(), showpal(), pixelcolor()
  615. *  Called by    :    options()
  616. **********************************************************************/
  617. void updatescrn()
  618. {
  619.     showpic();
  620.     if(show)
  621.         showpal();
  622. #ifdef MOUSE
  623.     if(mouse)            /* if the mouse is on then replace the mouse cursor */
  624.         draw_mouse();
  625. #endif
  626. }    /* end updatescrn() */
  627.  
  628. /**********************************************************************
  629. *  Function    :    scroll
  630. *  Purpose    :    move the image around the screen
  631. *  Parameters    :
  632. *            func -    the scrolling function to be performed
  633. *  Returns    :    none
  634. *  Calls    :    updatescrn()
  635. *  Called by    :    options(), mousefunc()
  636. **********************************************************************/
  637. void scroll(func)
  638. unsigned char    func;    /* the function to be performed on the screen */
  639. {
  640.     int    i;                /* temporary variables to hold the old xoff and yoff */
  641.  
  642. #ifdef MOUSE
  643.     if(mouse)            /* if the mouse is on then hide the cursor while moving */
  644.         erase_mouse();
  645. #endif
  646.     switch(func) {    /* switch to perform the appropriate scroll */
  647.         case 'l':    /* scroll left */
  648.             i=xoff;
  649.             xoff-=10;
  650.             if(xoff<0) 
  651.                 xoff=0;
  652.             if(xoff!=i)
  653.                 updatescrn();
  654.             break;
  655.         
  656.         case 'r':    /* scroll right */
  657.             i=xoff;
  658.             xoff+=10;
  659.             if(xdim-maxx<0)
  660.                 xoff=0;
  661.             else
  662.                 if(xoff>xdim-maxx)
  663.                     xoff=xdim-maxx;
  664.             if(i!=xoff)
  665.                 updatescrn();
  666.             break;
  667.  
  668.         case 'u':    /* scroll up */
  669.             i=yoff;
  670.             yoff-=10;
  671.             if(yoff<0)
  672.                 yoff=0;
  673.             if(yoff!=i)
  674.                 updatescrn();
  675.             break;
  676.  
  677.         case 'd':    /* scroll down */
  678.             i=yoff;
  679.             yoff+=10;
  680.             if(ydim-maxy<0)
  681.                 yoff=0;
  682.             else
  683.                 if(yoff>ydim-maxy)
  684.                     yoff=ydim-maxy;
  685.             if(i!=yoff)
  686.                 updatescrn();
  687.             break;
  688.  
  689.         case 'H':    /* Move to upper left hand corner of image */
  690.             if(yoff!=0||xoff!=0) {
  691.                 xoff=0;
  692.                 yoff=0;
  693.                 updatescrn();
  694.               } /* end if */
  695.             break;
  696.  
  697.         case 'E':    /* Move to lower right hand corner of image */
  698.             if(yoff!=ydim-maxy||xoff!=xdim-maxx) {
  699.                 xoff=xdim-maxx;
  700.                 if(xoff<0)
  701.                     xoff=0;
  702.                 yoff=ydim-maxy;
  703.                 if(yoff<0)
  704.                     yoff=0;
  705.                 updatescrn();
  706.               } /* end if */
  707.             break;
  708.  
  709.         case 'U':    /* page image up */
  710.             i=yoff;
  711.             yoff-=maxy;
  712.             if(yoff<0)
  713.                 yoff=0;
  714.             if(yoff!=i)
  715.                 updatescrn();
  716.             break;
  717.  
  718.         case 'D':    /* page image down */
  719.             i=yoff;
  720.             yoff+=maxy;
  721.             if(ydim-maxy<0)
  722.                 yoff=0;
  723.             else
  724.                 if(yoff>ydim-maxy)
  725.                     yoff=ydim-maxy;
  726.             if(i!=yoff)
  727.                 updatescrn();
  728.             break;
  729.       }    /* end switch */
  730. #ifdef MOUSE
  731.     if(mouse)            /* if the mouse is on then replace the cursor after moving */
  732.         draw_mouse();
  733. #endif
  734. }    /* end scroll() */
  735.  
  736. /**********************************************************************
  737. *  Function    :    rotate
  738. *  Purpose    :    rotate the palette left or right
  739. *  Parameters    :
  740. *            func -    character to determine which direction to rotate
  741. *  Returns    :    none
  742. *  Calls    :    putpal(), memcpy()
  743. *  Called by    :    options(), mousefunc()
  744. **********************************************************************/
  745. void rotate(func)
  746. unsigned char    func;    /* parameter to determine which way to rotate the palette */
  747. {
  748.     switch(func) {        /* switch for what to do to the palette */
  749.         case 'l':        /* rotate the palette left */
  750.             if(mode!=EGA) {
  751.                 i=rmap[255];
  752.                 j=gmap[255];
  753.                 k=bmap[255];
  754.                 memcpy(rmap+1,rmap,255);        /* shift palettes up one byte */
  755.                 memcpy(gmap+1,gmap,255);
  756.                 memcpy(bmap+1,bmap,255);
  757.                 rmap[0]=i;
  758.                 gmap[0]=j;
  759.                 bmap[0]=k;
  760.               } /* end if */
  761.             else {
  762.                 i=regrs[15];
  763.                 for(j=15; j>=1; j--)
  764.                     regrs[j]=regrs[j-1];
  765.                 regrs[0]=i;
  766.               } /* end else */
  767.             putpal();
  768.             break;
  769.  
  770.         case 'r':        /* rotate the palette right */
  771.             if(mode!=EGA) {
  772.                 i=rmap[0];
  773.                 j=gmap[0];
  774.                 k=bmap[0];
  775.                 memcpy(rmap,rmap+1,255);        /* shift palettes down one byte */
  776.                 memcpy(gmap,gmap+1,255);
  777.                 memcpy(bmap,bmap+1,255);
  778.                 rmap[255]=i;
  779.                 gmap[255]=j;
  780.                 bmap[255]=k;
  781.               } /*end if */
  782.             else {
  783.                 i=regrs[0];
  784.                 for(j=0; j<=14; j++)
  785.                     regrs[j]=regrs[j+1];
  786.                 regrs[15]=i;
  787.               } /* end else */
  788.             putpal();
  789.             break;
  790.       }    /* end switch */
  791. }    /* end rotate() */
  792.  
  793. /**********************************************************************
  794. *  Function    :    expand
  795. *  Purpose    :    routine to blow up a section of the screen
  796. *  Parameters    :
  797. *            x1,y1 -    location of the upper left hand corner of the box to blow up
  798. *            x2,y2 -    location of the lower right hand corner of the box to blow up
  799. *  Returns    :    
  800. *            1 - if routine was successfully finished
  801. *            0 - if routine was interupted
  802. *  Calls    :    vgaline1()
  803. *  Called by    :    mousefunc()
  804. **********************************************************************/
  805. int expand(x1,y1,x2,y2)
  806. int    x1,y1,                    /* location of the upper left hand corner of the box to blow up */
  807.     x2,y2;                    /* location of the lower right hand corner of the box to blow up */
  808.  
  809. {
  810.     unsigned char line[640];    /* a line to blow a line of the box up into */
  811.     float    xdiff,ydiff,            /* the differences between the x and y corners */
  812.             maxxf,maxyf;            /* a float variable for maxx and maxy */
  813.     int        i,j,k,l,m;
  814.  
  815.     xdiff=x2-x1;                    /* find difference between endpoints */
  816.     ydiff=y2-y1;
  817.     maxxf=maxx;
  818.     maxyf=maxy;
  819.     l=-1;                            /* preset the line counter to calculate the first line */
  820.     for(i=0; i<maxy; i++) {        /* go through all the lines in the image */
  821.         k=(int)((i/maxyf)*ydiff)+y1;
  822.         if(k!=l) {                /* if this line is not the same as the previous then re-calculate it */
  823.             for(j=0; j<maxx; j++)        /* go through each line and magnify */
  824.                 line[j]=store[k][(int)((j/maxxf)*xdiff)+x1];
  825.             l=k;                        /* set the line */
  826.           }    /* end if */
  827.         switch(mode) {        /* use different line drawing routines for different screens */
  828.             case VGA:
  829.                 vgaline1(0,i,line,0,maxx);        /* send each line out to the screen */
  830.                 break;
  831.  
  832.             case NO9:
  833.                 no9line(0,i,line,0,maxx);
  834.                 break;
  835.  
  836.             case EGA:
  837.             default:
  838.                 egaline(0,i,line,0,maxx);
  839.                 break;
  840.          }    /* end switch */
  841.         if(kbhit())    {            /* break out if the keyboard is hit */
  842.             m=getch();            /* clear the keyboard buffer */
  843.             if(m==0)            /* get extended code if necessary */
  844.                 m=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  845.             return(0);
  846.           }    /* end if */
  847.       }    /* end for */
  848.     return(1);
  849. }    /* end expand() */
  850.  
  851. /**********************************************************************
  852. *  Function    :    interpolation
  853. *  Purpose    :    routine to blow up a section of the screen and interpolate
  854. *                    data to a smooth image
  855. *  Parameters    :
  856. *            x1,y1 -    location of the upper left hand corner of the box to blow up
  857. *            x2,y2 -    location of the lower right hand corner of the box to blow up
  858. *  Returns    :    
  859. *            1 - if routine was successfully finished
  860. *            0 - if routine was interupted
  861. *  Calls    :    vgaline1(), egaline(), no9line(), interdata()
  862. *  Called by    :    mousefunc()
  863. **********************************************************************/
  864. int interpolate(x1,y1,x2,y2)
  865. int    x1,y1,                    /* location of the upper left hand corner of the box to blow up */
  866.     x2,y2;                    /* location of the lower right hand corner of the box to blow up */
  867.  
  868. {
  869.     unsigned char line[640];    /* a line to blow a line of the box up into */
  870.     float    hpercent,vpercent,    /* the percentage of the distance the pixel is towards the hi value */
  871.             vdata1,vdata2,        /* the data for the vertical interpolation */
  872.             hfinal,                /* the final result for horizontal interpolation */
  873.             hdata1,hdata2,        /* the data for horizontal interpolation */
  874.             vfinal,                /* the final result for vertical interpolation */
  875.             xdiff,ydiff,        /* the differences between the x and y corners */
  876.             tempy,tempx,        /* temporary floating value */
  877.             maxxf,maxyf;        /* a float variable for maxx and maxy */
  878.     int        i,j,hix,lox,hiy,loy;    /* integer values for the coor. in the images around the current pixel */
  879.  
  880.     xdiff=x2-x1;                    /* find difference between endpoints */
  881.     ydiff=y2-y1;
  882.     maxxf=maxx;
  883.     maxyf=maxy;
  884.     for(i=0; i<maxy; i++) {        /* go through all the lines in the image */
  885.         tempy=((i/maxyf)*ydiff)+(float)y1;    /* calculate the fractional pixel position in the image */
  886.         loy=tempy;        /* calculate the address of the lower y bound */
  887.         hiy=ceil(tempy);        /* calculate the address of the upper y bound */
  888.         vpercent=(tempy-(float)loy)/((float)hiy-(float)loy);
  889.         for(j=0; j<maxx; j++) {        /* go through each line and interpolate */
  890.             tempx=((j/maxxf)*xdiff)+(float)x1;    /* calculate the fractional pixel position in the image */
  891.             lox=tempx;                /* calculate the lower x bound */
  892.             hix=ceil(tempx);        /* calculate the upper x bound */
  893.             vdata1=(store[hiy][lox]-store[loy][lox])*vpercent+store[loy][lox];
  894.             vdata2=(store[hiy][hix]-store[loy][hix])*vpercent+store[loy][hix];
  895.             hpercent=(tempx-(float)lox)/((float)hix-(float)lox);
  896.             hfinal=(vdata2-vdata1)*hpercent+vdata1;
  897.             hdata1=(store[loy][hix]-store[loy][lox])*hpercent+store[loy][lox];
  898.             hdata2=(store[hiy][hix]-store[hiy][lox])*hpercent+store[hiy][lox];
  899.             vfinal=(hdata2-hdata1)*vpercent+hdata1;
  900.             line[j]=(hfinal+vfinal)/2.0;
  901.           }    /* end for */
  902.         switch(mode) {        /* use different line drawing routines for different screens */
  903.             case VGA:
  904.                 vgaline1(0,i,line,0,maxx);        /* send each line out to the screen */
  905.                 break;
  906.  
  907.             case NO9:
  908.                 no9line(0,i,line,0,maxx);
  909.                 break;
  910.  
  911.             case EGA:
  912.             default:
  913.                 egaline(0,i,line,0,maxx);
  914.                 break;
  915.          }    /* end switch */
  916.         if(kbhit()) {                /* break out if the keyboard is hit */
  917.             i=getch();
  918.             if(i==0)                /* get extended code if necessary */
  919.                 i=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  920.             return(0);
  921.           }    /* end if */
  922.       }    /* end for */
  923.     return(1);
  924. }    /* end interpolation() */
  925.  
  926. #ifdef MOUSE
  927. /**********************************************************************
  928. *  Function    :    makehex
  929. *  Purpose    :    convert an ascii string of binary digits into an integer
  930. *  Parameters    :
  931. *                binstr -    string of binary digits
  932. *  Returns    :    integer value of binary string
  933. *  Calls    :    pow(), strlen()
  934. *  Called by    :    makemouse()
  935. **********************************************************************/
  936. int makehex(binstr)
  937. char *binstr;
  938. {
  939.     int i,j,k;        /* local counting variables */
  940.     double pow();    /* pow(x,y) returns x to the y power */
  941.  
  942.     k=strlen(binstr);    /* find the length of the binary string */
  943.     i=0;
  944.     for(j=k-1; j>=0; j--)        /* make a binary string into a hex number */
  945.         i+=((int)pow((double)2,(double)j))*((int)*(binstr++)-48);
  946.     return(i);
  947. }
  948.  
  949. /**********************************************************************
  950. *  Function    :    makemouse
  951. *  Purpose    :    make the mouse cursor into a crosshair for vga and ega modes
  952. *  Parameters    :    none
  953. *  Returns    :    none
  954. *  Calls    :    mousecml()
  955. *  Called by    :    options()
  956. **********************************************************************/
  957. void makemouse()
  958. {
  959.     int    cursor[2][16];        /* array for screen and cursor bit masks */
  960.  
  961.     if(mode!=NO9) {            /* only do this for vga and ega modes */
  962.         /* screen mask */
  963.         cursor[0][0]= makehex("1001111111111111");
  964.         cursor[0][1]= makehex("1010111111111111");
  965.         cursor[0][2]= makehex("1011011111111111");
  966.         cursor[0][3]= makehex("1011101111111111");
  967.         cursor[0][4]= makehex("1011110111111111");
  968.         cursor[0][5]= makehex("1011111011111111");
  969.         cursor[0][6]= makehex("1011111101111111");
  970.         cursor[0][7]= makehex("1011111011111111");
  971.         cursor[0][8]= makehex("1010011011111111");
  972.         cursor[0][9]= makehex("1001101101111111");
  973.         cursor[0][10]=makehex("1111101101111111");
  974.         cursor[0][11]=makehex("1111110011111111");
  975.         cursor[0][12]=makehex("1111111111111111");
  976.         cursor[0][13]=makehex("1111111111111111");
  977.         cursor[0][14]=makehex("1111111111111111");
  978.         cursor[0][15]=makehex("1111111111111111");
  979.  
  980.         /* cursor mask */
  981.         for(i=0; i<16; i++)        /* set the entire cursor mask to inverse of the screen mask */
  982.             cursor[1][i]=~cursor[0][i];
  983.         m1=9;                    /* function to define cursor shape and hot spot */
  984.         m2=0;                    /* horizontal hot spot */
  985.         m3=0;                    /* vertical hot spot */
  986.         mousecml(&m1,&m2,&m3,&cursor[0][0]);
  987.         m1=1;                    /* function to show the cursor */
  988.         mousecml(&m1,&m2,&m3,&m4);
  989.       }    /* end if */
  990. }    /* end makemouse() */
  991. #endif
  992.  
  993. #ifdef QAK
  994. /**********************************************************************
  995. *  Function    :    bounce
  996. *  Purpose    :    bounce a ball on the screen
  997. *  Parameters    :    none
  998. *  Returns    :    none
  999. *  Calls    :    drand48(), ball()
  1000. *  Called by    :    options()
  1001. **********************************************************************/
  1002. void bounce()
  1003. {
  1004.     int    x1[5],x2[5],y1[5],y2[5],        /* variables to keep track of the balls position */
  1005.         j,                    /* timing variable */
  1006.         i,                    /* local counting variable */
  1007.         maxball=0,            /* number of balls on the screen */
  1008.         ballsize,            /* size of the ball in pixels */
  1009.         xspeed[5],yspeed[5];        /* variables to keep track of the balls speed */
  1010.  
  1011.     double    drand48();        /* random number function */
  1012.     long    time(),l;            /* the system time for seeding the random pointer */
  1013.     void    parse(),srand48();        /* command parsing function */
  1014.  
  1015.     srand48(time(&l));        /* seed the random number generator */
  1016.     if(mode==NO9)            /* set the ball sizes for different screens */
  1017.         ballsize=8;
  1018.     else
  1019.         ballsize=4;
  1020.     x1[0]=(int)(drand48()*(double)(maxx-ballsize-1))+1;        /* randomize starting position */
  1021.     x2[0]=x1[0];
  1022.     y1[0]=(int)(drand48()*(double)(maxy-ballsize-1))+1;
  1023.     y2[0]=y1[0];
  1024.     xspeed[0]=0;
  1025.     while(xspeed[0]==0)                /* randomize speed, not allowing 0 speed in a direction */
  1026.         xspeed[0]=(int)(drand48()*(double)11)-6;
  1027.     yspeed[0]=0;
  1028.     while(yspeed[0]==0)
  1029.         yspeed[0]=(int)(drand48()*(double)11)-6;
  1030. #ifdef MOUSE
  1031.     m1=11;                        /* reset the mouse position counters */
  1032.     mousecml(&m1,&m2,&m3,&m4);
  1033. #endif
  1034.     m3=m4=0;
  1035.     if(mode==NO9)                /* plot the ball */
  1036.         ball9(x1[0],y1[0]);
  1037.     else
  1038.         ball(x1[0],y1[0]);
  1039.     while(!kbhit() && !m3 && !m4) {    /* bounce the ball until a key is pressed */
  1040.         for(i=maxball; i>=0; i--) {        /* check through all the balls */
  1041.             if(mode==NO9)
  1042.                 ball9(x1[i],y1[i]);
  1043.             else
  1044.                 ball(x1[i],y1[i]);    /* remove the ball */
  1045.             x2[i]+=xspeed[i];        /* move the ball */
  1046.             y2[i]+=yspeed[i];
  1047.             if(x2[i]<0 || x2[i]>(maxx-ballsize-1)) {    /* check for off screen in the x direction */
  1048.                 xspeed[i]=-(xspeed[i]);    /* reverse the direction of the movement */
  1049.                 x2[i]+=xspeed[i];
  1050.               }    /* end if */
  1051.             if(y2[i]<0 || y2[i]>(maxy-ballsize-1)) {    /* check for off screen in the y direction */
  1052.                 yspeed[i]=-(yspeed[i]);
  1053.                 y2[i]+=yspeed[i];
  1054.               }    /* end if */
  1055.             if(mode==NO9)
  1056.                 ball9(x2[i],y2[i]);
  1057.             else
  1058.                 ball(x2[i],y2[i]);        /* plot the ball in it's new position */
  1059.             x1[i]=x2[i];                /* update the balls position */
  1060.             y1[i]=y2[i];
  1061.             if((int)(drand48()*(double)10000)==0)    /* on very rare occasions change the ball speed */
  1062.                 switch ((int)(drand48()*4)) {        /* choose which speed to change */
  1063.                     case 0:
  1064.                         xspeed[i]++;
  1065.                         break;
  1066.  
  1067.                     case 1:
  1068.                         xspeed[i]--;
  1069.                         break;
  1070.  
  1071.                     case 2:
  1072.                         yspeed[i]++;
  1073.                         break;
  1074.  
  1075.                     case 3:
  1076.                         yspeed[i]--;
  1077.                         break;
  1078.                   }    /* end switch */
  1079.           }    /* end for */
  1080.         for(j=0; j<(5-maxball)*600+2000; j++);    /* waiting loop */
  1081.         if(maxball<4)        /* if not at the maximum amount of balls then check for addition of a ball */
  1082.             if((int)(drand48()*(double)1000)==0) {    /* less than one in a hundred chance */
  1083.                 maxball++;
  1084.                 x1[maxball]=(int)(drand48()*(double)(maxx-ballsize-1))+1;        /* randomize starting position */
  1085.                 x2[maxball]=x1[maxball];
  1086.                 y1[maxball]=(int)(drand48()*(double)(maxy-ballsize-1))+1;
  1087.                 y2[maxball]=y1[maxball];
  1088.                 xspeed[maxball]=0;
  1089.                 while(xspeed[maxball]==0)                /* randomize speed, not allowing 0 speed in a direction */
  1090.                     xspeed[maxball]=(int)(drand48()*(double)11)-6;
  1091.                 yspeed[maxball]=0;
  1092.                 while(yspeed[maxball]==0)
  1093.                     yspeed[maxball]=(int)(drand48()*(double)11)-6;
  1094.                 if(mode==NO9)
  1095.                     ball9(x1[maxball],y1[maxball]);
  1096.                 else
  1097.                     ball(x1[maxball],y1[maxball]);        /* plot the new ball */
  1098.               }    /* end if */
  1099. #ifdef MOUSE
  1100.         m1=11;                /* check for the mouse moving */
  1101.         mousecml(&m1,&m2,&m3,&m4);
  1102. #endif
  1103.       }    /* end while */
  1104.     for(i=maxball; i>=0; i--)
  1105.         if(mode==NO9)
  1106.             ball9(x1[i],y1[i]);
  1107.         else
  1108.             ball(x1[i],y1[i]);            /* erase balls from screen */
  1109.     if(kbhit()) {                    /* if it was the keyboard and not the mouse */
  1110.         j=getch();                    /* flush the keyboard buffer */
  1111.         if(j==0)                    /* get extended code if necessary */
  1112.             j=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1113.         parse((unsigned char)j);
  1114.       }    /* end if */
  1115. } /* end bounce() */
  1116. #endif
  1117.  
  1118. /**********************************************************************
  1119. *  Function    :    outlinee
  1120. *  Purpose    :    draw an outlined box on the ega screen
  1121. *  Parameters    :
  1122. *                x1,y1    - the x & y coor. of the upper left hand corner
  1123. *                x2,y2    - the x & y coor. of the lower right hand corner
  1124. *  Returns    :    none
  1125. *  Calls    :    lineega()
  1126. *  Called by    :    outline()
  1127. **********************************************************************/
  1128. void outlinee(x1,y1,x2,y2)
  1129. int    x1,y1,x2,y2;
  1130. {
  1131.     int    i,j;            /* temporary counting variables */
  1132.  
  1133.     if(x2<x1)
  1134.         swapint(&x1,&x2);
  1135.     if(y2<y1)
  1136.         swapint(&y1,&y2);
  1137.     if(x2>=xdim)            /* clip the box if it is outside the image */
  1138.         x2=xdim-1;
  1139.     if(x1>=xdim)
  1140.         x1=xdim-1;
  1141.     if(y2>=ydim)
  1142.         y2=ydim-1;
  1143.     if(y1>=ydim)
  1144.         y1=ydim-1;
  1145.     for(i=x1+xoff; i<=x2+xoff; i++)        /* go through each pixel in the top line */
  1146.         *(store[y1+yoff]+i)=~*(store[y1+yoff]+i);
  1147.     for(i=x1+xoff; i<=x2+xoff; i++)        /* go through each pixel in the bottom line */
  1148.         *(store[y2+yoff]+i)=~*(store[y2+yoff]+i);
  1149.     for(j=y1+1+yoff; j<y2+yoff; j++) {        /* go thru and fix all the lines in between */
  1150.         *(store[j]+x1+xoff)=~*(store[j]+x1+xoff);
  1151.         *(store[j]+x2+xoff)=~*(store[j]+x2+xoff);
  1152.       }    /* end for */
  1153.     for(i=y1; i<=y2; i++) {        /* output the lines to the screen */
  1154.         egaline(xwhere+x1,ywhere+i,store[i+yoff],x1+xoff,x2-x1+1);
  1155.       }    /* end for */
  1156. }
  1157.  
  1158. /**********************************************************************
  1159. *  Function    :    outline
  1160. *  Purpose    :    call routines to put an outlined box on the screen
  1161. *  Parameters    :
  1162. *                x1,y1    - the x & y coor. of the upper left hand corner
  1163. *                x2,y2    - the x & y coor. of the lower right hand corner
  1164. *  Returns    :    none
  1165. *  Calls    :    outline9(), outlinev(), outlinee()
  1166. *  Called by    :    mousefunc()
  1167. **********************************************************************/
  1168. void outline(x1,y1,x2,y2)
  1169. int    x1,y1,x2,y2;
  1170. {
  1171.     switch(mode) {            /* switch to call different outline routines depending on monitor type */
  1172.         case NO9:
  1173.             outline9(x1,y1,x2,y2);
  1174.             break;
  1175.  
  1176.         case VGA:
  1177.             outlinev(x1,y1,x2,y2);
  1178.             break;
  1179.  
  1180.         case EGA:
  1181.         default:
  1182.             outlinee(x1,y1,x2,y2);    /* need offsets because ega has to modify the image data */
  1183.             break;
  1184.       }    /* end switch */
  1185. }
  1186.  
  1187. #ifdef MOUSE
  1188. /**********************************************************************
  1189. *  Function    :    mousefunc
  1190. *  Purpose    :    perform all of the mouse functions
  1191. *  Parameters    :    none
  1192. *  Returns    :    none
  1193. *  Calls    :    mousecml(), pixelcolor()
  1194. *  Called by    :    options()
  1195. **********************************************************************/
  1196. void mousefunc()
  1197. {
  1198.     int    off_x,off_y,            /* the offset the mouse cursor is inside the color bar */
  1199.         firstx,firsty;            /* the location of the first corner plotted in drawing a box */
  1200.  
  1201.     read_mouse();        /* get mouse position and button status */
  1202.     if(mx!=m3 || my!=m4) {    /* the mouse has been moved so update the screen */
  1203.         if(mode==NO9) {            /* update the mouse position for no9 screen */
  1204.             makecur9(mx,my);
  1205.             mx=m3;
  1206.             my=m4;
  1207.             makecur9(mx,my);
  1208.           }    /* end if */
  1209.         else {
  1210.             mx=m3;                /* update the old mouse positions */
  1211.             my=m4;
  1212.           }    /* end else */
  1213.       }    /* end if */
  1214.     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 */
  1215.         if(my>=pal_yoff && my<=(pal_yoff+pal_height)) {    /* if mouse cursor is in the color bar then move it */
  1216.             nopal(xoff,yoff);        /* erase the color bar */
  1217.             if(mode==NO9) {
  1218.                 makecur9(mx,my);
  1219.                 off_x=mx-pal_xoff;        /* set the offset in the color bar */
  1220.                 off_y=my-pal_yoff;
  1221.               }    /* end if */
  1222.             else {
  1223.                 m1=2;                /* erase the cursor */
  1224.                 mousecml(&m1,&m2,&m3,&m4);
  1225.                 off_x=mx-pal_xoff;        /* set the offset in the color bar */
  1226.                 off_y=my-pal_yoff;
  1227.               }    /* end else */
  1228.             outline(pal_xoff,pal_yoff,pal_xoff+255,pal_yoff+pal_height);        /* plot the outline of the color bar */
  1229.             do {        /* keep moving the palette until the button is let up */
  1230.                 read_mouse();        /* get mouse position and button status */
  1231.                 if((m3+256-off_x)>maxx)    /* if trying to move the color bar off the left side of the screen */
  1232.                     m3=maxx-256+off_x;
  1233.                 if((m3-off_x)<0)        /* if trying to move off the right side of the screen */
  1234.                     m3=off_x;
  1235.                 if((m4+pal_height+1-off_y)>maxy)    /* if trying to move off the bottom of the screen */
  1236.                     m4=maxy-pal_height-1+off_y;
  1237.                 if((m4-off_y)<0)        /* if trying to move off the top of the screen */
  1238.                     m4=off_y;
  1239.                 if(m3!=mx || m4!=my) {    /* if mouse is moved then move outline of color bar */
  1240.                     outline(mx-off_x,my-off_y,mx-off_x+255,my-off_y+pal_height);
  1241.                     mx=m3;
  1242.                     my=m4;
  1243.                     outline(mx-off_x,my-off_y,mx-off_x+255,my-off_y+pal_height);
  1244.                   }    /* end if */
  1245.             } while(rightbutton);
  1246.             pal_xoff=mx-off_x;            /* find to upper left hand corner for the color bar */
  1247.             pal_yoff=my-off_y;
  1248.             outline(pal_xoff,pal_yoff,pal_xoff+255,pal_yoff+pal_height);
  1249.             draw_mouse();
  1250.             showpal();                    /* put the color bar back on the screen */
  1251.           }    /* end if */
  1252.     if(rightbutton) {        /* rightbutton functions */
  1253.         erase_mouse();
  1254.         if(mx>9 && mx<(maxx-9)) {    /* if not within the active region in the x dir. */
  1255.             if(my<10)            /* if within 10 pixels of top then scroll up */
  1256.                 scroll('u');
  1257.             if(my>(maxy-10))    /* if within 10 pixels of bottn then scroll down */
  1258.                 scroll('d');
  1259.           }    /* end if */
  1260.         if(mx>(maxx-10))     /* if within 10 pixels of edge of screen then do something */
  1261.             if(my<10 || my>(maxy-10))    /* if in one of the corners then page */
  1262.                 if(my<10)                /* page up */
  1263.                     scroll('U');
  1264.                 else                    /* page down */
  1265.                     scroll('D');
  1266.             else                        /* scroll right */
  1267.                 scroll('r');
  1268.         if(mx<10)            /* if within 10 pixels of edge of the screen then do something */
  1269.             if(my<10 || my>(maxy-10))    /* if in one of the corners then home/end */
  1270.                 if(my<10)                /* Home */
  1271.                     scroll('H');
  1272.                 else                    /* End */
  1273.                     scroll('E');
  1274.             else                        /* scroll left */
  1275.                 scroll('l');
  1276.         draw_mouse();
  1277.       }    /* end if */
  1278.     if(leftbutton) {    /* leftbutton functions */
  1279.         if(show && (mx>=pal_xoff && mx<=(pal_xoff+255)) && (my>=pal_yoff && my<=(pal_yoff+pal_height))) {
  1280.             if((mx-pal_xoff)<128) {            /* if on the left side then rotate that way */
  1281.                 rotate('r');
  1282.                 for(j=abs(mx-pal_xoff)*10; j>=0; j--);
  1283.               }    /* end if */
  1284.             else {                            /* must be on right side so rotate that way */
  1285.                 rotate('l');
  1286.                 for(j=(255-abs(mx-pal_xoff))*10; j>=0; j--);
  1287.               }    /* end else */
  1288.           }    /* end if */
  1289.         else {            /* draw an outlined box on the screen */
  1290.             erase_mouse();
  1291.             firstx=mx;
  1292.             firsty=my;
  1293.             outline(firstx,firsty,mx,my);
  1294.             do {        /* keep changing the size of the outline until the button is let up */
  1295.                 read_mouse();        /* get mouse position and button status */
  1296.                 if(m3!=mx || m4!=my) {    /* if mouse is moved then move outline of color bar */
  1297.                     outline(firstx,firsty,mx,my);        /* erase the outline */
  1298.                     mx=m3;
  1299.                     my=m4;
  1300.                     outline(firstx,firsty,mx,my);        /* re plot the outline */
  1301.                   }    /* end if */
  1302.               } while(leftbutton);
  1303.             outline(firstx,firsty,mx,my);
  1304.             if(firstx>mx)                    /* if square is defined backwards then flip ends */
  1305.                 swapint(&firstx,&mx);
  1306.             if(firsty>my)
  1307.                 swapint(&firsty,&my);
  1308.             if(mx>xdim-xoff)                        /* prevent the box from being outside the image */
  1309.                 mx=xdim;
  1310.             if(my>ydim-yoff)
  1311.                 my=ydim;
  1312.             if(firstx<xdim-xoff && firsty<ydim-yoff) {    /* if the box is actually in the image on the screen then expand */
  1313.                 grafmode();                                    /* clear the screen */
  1314.                 if(expandit) {                /* if preference is to expand the image */
  1315.                     if(expand(firstx+xoff,firsty+yoff,mx+xoff,my+yoff)==1)            /* expand chosen area to fill screen */
  1316.                         waitq();    /* wait for keypress */
  1317.                   }    /* end if */
  1318.                 else {                        /* if preference is to interpolate the image */
  1319.                     if(interpolate(firstx+xoff,firsty+yoff,mx+xoff,my+yoff)==1)            /* expand and smooth the chosen area to fill the screen */
  1320.                         waitq();    /* wait for keypress */
  1321.                   }    /* end else */
  1322.               }    /* end if */
  1323.             updatescrn();                                /* go back to old display */
  1324.           }    /* end else */    
  1325.       }    /* end if */
  1326. }    /* end mousefunc() */
  1327. #endif
  1328.  
  1329. /**********************************************************************
  1330. *  Function    :    options
  1331. *  Purpose    :    do all the fancy run-time things to the image
  1332. *  Parameters    :    none
  1333. *  Returns    :    none
  1334. *  Calls    :    parse(), mousecml(), mousefunc(), bounce()
  1335. *  Called by    :    main()
  1336. **********************************************************************/
  1337. void options()
  1338. {
  1339.     palnum=0;        /* start out at the first palette */
  1340. #ifdef MOUSE
  1341.     if(mouse)        /* if the mouse is already on then put it on the screen */
  1342.         draw_mouse();
  1343. #endif
  1344.     c='!';
  1345.     if(kbhit()) {
  1346.         c=getch();
  1347.         if(c==0)        /* check for extended character code */
  1348.             c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1349.       }    /* end if */
  1350.  
  1351.     while(c!='q' && !(c=='a' && animate) && c!='Q') {                   /* continue until 'q' */
  1352.         c='!';
  1353. #ifdef QAK
  1354.         waitcount=0;
  1355. #endif
  1356.         while (c=='!') {
  1357.             if(kbhit()) {        /* get the next command */
  1358.                 c=getch();
  1359.                 if(c==0)
  1360.                     c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1361.               }    /* end if */
  1362. #ifdef MOUSE
  1363.             if(mouse) {        /* if the mouse is active then perform some functions */
  1364.                 mousefunc();
  1365. #ifdef QAK
  1366.                 waitcount=0;        /* reset the counter to time out */
  1367. #endif
  1368.               }    /* end if */
  1369. #endif
  1370. #ifdef QAK
  1371.             if(waitcount>100000) {        /* if timed out then bounce the ball */
  1372.                 if(mode==VGA || mode==NO9)
  1373.                     bounce();
  1374.                 waitcount=0;        /* reset the timed out counter */
  1375.               }    /* end if */
  1376.             waitcount++;
  1377. #endif
  1378.           }    /* end while */
  1379.         if(c=='?') {                /* if help is requisitioned */
  1380.             if(mouse && mode==NO9)
  1381.                 makecur9(mx,my);
  1382.             textmode();
  1383.             printf("General Help Screen\n\n");
  1384.             printf("i\t\t - Show Information About Image\n");
  1385.             printf("a\t\t - Show Animation Again\n");
  1386.             printf("k\t\t - End Animation Mode\n");
  1387.             printf("o\t\t - Turn VGA Screen Off Or On\n");
  1388.             printf("m\t\t - Activate/Deactivate Mouse\n");
  1389.             printf(",\t\t - Magnify\Interpolate A Portion Of The Screen\n");
  1390.             printf("w\t\t - Switch Between Magnifying And Interpolating\n");
  1391.             printf("/\t\t - Slow Down Animation Speed\n");
  1392.             printf("*\t\t - Speed Up Animation Speed\n");
  1393.             printf("q\t\t - Quit Viewing Current Image\n");
  1394.             printf("Q\t\t - Exit Program\n");
  1395.             printf("?\t\t - Show This Help Sequence\n\n");
  1396.             printf("Hit <enter> For More Help, Or Any Key to Return to Graphics Mode");
  1397.             c='!';
  1398.             while (c=='!') {
  1399.                 if(kbhit()) {    /* get the next command */
  1400.                     c=getch();
  1401.                     if(c==0)
  1402.                         c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1403.                   }    /* end if */
  1404.               }    /* end while */
  1405.             printf("\n");
  1406.             if(c==13){    /* if enter is hit for next help screen */
  1407.                 textmode();
  1408.                 printf("Palette Help Screen\n\n");
  1409.                 printf("f\t\t - Rotate Palette Continuously Forward\n");
  1410.                 printf("b\t\t - Rotate Palette Continuously Backward\n");
  1411.                 printf("+\t\t - Speed Up Palette Rotation\n");
  1412.                 printf("-\t\t - Slow Down Palette Rotation\n");
  1413.                 printf("space bar\t - Stop Rotation Of Palette Or Animation\n");
  1414.                 printf("e\t\t - Rotate Palette Once Forward\n");
  1415.                 printf("v\t\t - Rotate Palette Once Backward\n");
  1416.                 printf("r\t\t - Reset Palette To Original Settings\n");
  1417.                 printf("c\t\t - Toggle Color Bar On Or Off The Screen\n");
  1418.                 printf("l\t\t - Load In A New Palette From Disk\n");
  1419.                 printf("n\t\t - Display Next Palette In Memory\n");
  1420.                 printf("s\t\t - Store Palette On Disk\n");
  1421.                 printf("u\t\t - Swap The Red, Green, And Blue Components Of Palettes\n");
  1422.                 printf("t\t\t - Transpose Palette\n");
  1423.                 printf("g\t\t - Invert Palette Bitwise\n");
  1424.                 printf("h\t\t - Enter Fiddle Mode\n");
  1425.                 printf("p\t\t - Move Color Bar On The Screen\n");
  1426.                 printf("d\t\t - Make Current Palette The Default Values\n\n");
  1427.                 printf("Hit <enter> For More Help, Or Any Key to Return to Graphics Mode");
  1428.                 c='!';
  1429.                 while (c=='!') {
  1430.                     if(kbhit()) {    /* get the next command */
  1431.                         c=getch();
  1432.                         if(c==0)
  1433.                             c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1434.                       }    /* end if */
  1435.                   }    /* end while */
  1436.                 printf("\n");
  1437.                 if(c==13) {
  1438.                     textmode();
  1439.                     printf("Image Help Screen\n\n");
  1440.                     printf("left arrow\t - Move Image Left Ten Pixels\n");
  1441.                     printf("up arrow\t - Move Image Up Ten Pixels\n");
  1442.                     printf("down arrow\t - Move Image Down Ten Pixels\n");
  1443.                     printf("right arrow\t - Move Image Right Ten Pixels\n");
  1444.                     printf("page up\t - Page Image Up A Full Screen\n");
  1445.                     printf("page down\t - Page Image Down A Full Screen\n");
  1446.                     printf("home\t\t - Move To The Upper Left Hand Corner Of The Image\n");
  1447.                     printf("end\t\t - Move To The Lower Right Hand Corner Of The Image\n");
  1448.                     printf("x\t\t - Input X and Y Coor. For Upper Left Hand Corner\n");
  1449.                     printf("Hit Any Key to Return To Graphics Mode");
  1450.                     c='!';
  1451.                     while (c=='!') {
  1452.                         if(kbhit()) {    /* get the next command */
  1453.                             c=getch();
  1454.                             if(c==0)
  1455.                                 c=getch()|(unsigned char)128;    /* set high bit to indicate extended code */
  1456.                           }    /* end if */
  1457.                        }    /* end while */
  1458.                     printf("\n");
  1459.                     }    /* end if */
  1460.               }    /* end if */
  1461.             grafmode();
  1462.             updatescrn();
  1463.           }    /* end if */
  1464.         parse(c);
  1465.       } /* end while */
  1466. #ifdef MOUSE
  1467.     if(mouse)                    /* if the mouse is on then remove the cursor before leaving */
  1468.         erase_mouse();
  1469. #endif
  1470. } /* end options() */
  1471.