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