home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Science / Science.zip / imdisp79.zip / PALUTIL.C < prev    next >
C/C++ Source or Header  |  1993-08-03  |  32KB  |  990 lines

  1. /***  IMDISP module PALUTIL.C
  2.  
  3.       Palette manipulation Routines
  4.  
  5.     Contains high level palette routines such as interactive palette
  6.     adjustment, palette reading and writing.
  7.  
  8.     Separate module - 1/91 by A. Warnock, ST Systems Corp
  9. ***/
  10.  
  11. #define __MSC
  12.  
  13. /* * * * INCLUDE files * * * */
  14.  
  15. #include <conio.h>
  16. #include <dos.h>
  17. #ifdef __TURBOC__
  18. #include <graphics.h>
  19. #else
  20. #include <graph.h>
  21. #endif
  22. #include <io.h>
  23. #include <math.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <time.h>
  28. #include "imdef.h"
  29. #include "imdisp.h"
  30. #include "imdutil.h"
  31. #include "dispio.h"
  32. #include "disputil.h"
  33. #include "dispsub.h"
  34. #include "fileio.h"
  35. #include "fileutil.h"
  36. #include "keywutil.h"
  37. #include "imagutil.h"
  38. #include "textutil.h"
  39. #include "ativga.h"
  40. #include "ev629.h"
  41.  
  42. /* * * * External functions * * * */
  43. extern void pascal far mouses( int *, int *, int *, int * );
  44.  
  45. /* * * * Function declarations * * * */
  46.  
  47. int    LoadPalette (char *);
  48. int    ReadPalette (Color *);
  49. int    WritePalette (Color *);
  50. int    DiddlePalette (int);
  51. void   ShowPalette (int);
  52. void   ErasePalette (int);
  53. void   GetPalette(void);
  54. int    CyclePalette (int);
  55. void   VAXFloat2Char(unsigned char *, unsigned char *, int);
  56.  
  57. /* * * * Global Variables * * * */
  58.  
  59.  
  60. int LoadPalette(char * palettefile)
  61. /* LoadPalette reads in the color palette from the given palette filename
  62.    (palettefile).  This code originally resided in the DoPalette routine,
  63.    but was moved into its own routine to accomodate detached palette
  64.    processing -- Ron Baalke -- 07/27/90 */
  65. {
  66.     int    i, n, r, g, b, result;
  67.     unsigned char color[768];
  68.     char   buffer[1024];
  69.     char   filedata[133];
  70.     FILE   *unit;
  71.  
  72.     if (Palette != 0L)
  73.     {
  74.        lseek(FCB[0].handle, Palette, SEEK_SET);
  75.        read(FCB[0].handle, color, 768);
  76.        for (i=0;i<256;i++)
  77.           CT[i].r = color[i];
  78.        for (i=0;i<256;i++)
  79.           CT[i].g = color[256+i];
  80.        for (i=0;i<256;i++)
  81.           CT[i].b = color[512+i];
  82.        WritePalette (CT);
  83.        Palette = 0L; /* reset value to zero */
  84.        return(0);
  85.     }
  86.     if ((unit = fopen (palettefile, "r")) == NULL)
  87.     {
  88.            StatusLine(0,"Palette file not found.");
  89.            return(1);
  90.     }
  91.  
  92.     fgets(filedata,132,unit);
  93.  
  94.    /* zero out palette but make highest value white */
  95.     memset( &CT[0], 0,  3*255);
  96.     if (numDN == 256)
  97.            CT[255].r = CT[255].g = CT[255].b = 255;
  98.     else
  99.            CT[15].r  = CT[15].g  = CT[15].b  = 255;
  100.  
  101. /*  handle palettes with headers */
  102.     if (strnicmp(filedata,"CCSD",4) == 0 || strnicmp(filedata,"NJPL",4) == 0)
  103.     {
  104.        do
  105.        {
  106.            fgets(filedata,132,unit);
  107.            if (strnicmp(filedata,"END",3) == 0 &&
  108.               (strlen(filedata) <= 5 || filedata[3] == ' '))
  109.                    break;
  110.        } while (!feof(unit));
  111.        fgets (filedata, 132, unit);
  112.        i = 0;
  113.        do
  114.        {
  115.            result = sscanf(filedata, "%d %d %d %d", &n,&r,&g,&b);
  116.            if (result == 1) /* try comma separated value */
  117.                result = sscanf(filedata, "%d,%d,%d,%d", &n,&r,&g,&b);
  118.            if (result == 3) /* no index value on line */
  119.                {CT[i].r = n; CT[i].g = r; CT[i].b = g;}
  120.            else if (result == 4 && (n >= 0 && n <= 256))
  121.                {
  122.                 if (i==n-1) n = i; /* patch to handle old palettes */
  123.                                    /* with values from 1 to 256    */
  124.                 CT[n].r = r; CT[n].g = g; CT[n].b = b;}
  125.            else
  126.            {
  127.                StatusLine (0,"Invalid Palette file format.");
  128.                fclose(unit); return(1);
  129.            }
  130.            i++;
  131.            fgets (filedata, 132, unit);
  132.        } while (! feof(unit) && i < 256);
  133.        if (numDN == 16 && i > 15)
  134.            for (i=0;i<16;i++)
  135.            {
  136.               CT[i].r = CT[i*16+8].r;
  137.               CT[i].g = CT[i*16+8].g;
  138.               CT[i].b = CT[i*16+8].b;
  139.            }
  140.     }
  141.  
  142.     /* Handle VICAR color palettes - Ron Baalke 04/07/91 */
  143.  
  144.     else if (strnicmp(filedata,"LBLS",4) == 0)
  145.     {
  146.        fclose(unit);
  147.        if ((unit = fopen (palettefile, "r+b")) == NULL)
  148.        {
  149.               StatusLine(0,"Palette file not found.");
  150.               return(1);
  151.        }
  152.        fseek(unit,1024L,SEEK_SET);
  153.        fread(buffer,1024,1,unit);
  154.        VAXFloat2Char(buffer,color,256);
  155.        for (i=0; i<256; i++)
  156.           CT[i].r = color[i];
  157.        fread(buffer,1024,1,unit);
  158.        VAXFloat2Char(buffer,color,256);
  159.        for (i=0; i<256; i++)
  160.           CT[i].g = color[i];
  161.        fread(buffer,1024,1,unit);
  162.        VAXFloat2Char(buffer,color,256);
  163.        for (i=0; i<256; i++)
  164.           CT[i].b = color[i];
  165.  
  166.        if (numDN == 16)
  167.            for (i=0;i<16;i++)
  168.            {
  169.               CT[i].r = CT[i*16+8].r;
  170.               CT[i].g = CT[i*16+8].g;
  171.               CT[i].b = CT[i*16+8].b;
  172.            }
  173.     }
  174.  
  175.     else /* handle naked palettes */
  176.     {
  177.        fgets (filedata, 132, unit);
  178.        i = 0;
  179.        do
  180.        {
  181.            result = sscanf(filedata, "%d %d %d %d", &n,&r,&g,&b);
  182.            if (result == 1) /* try comma separated value */
  183.                result = sscanf(filedata, "%d,%d,%d,%d", &n,&r,&g,&b);
  184.            if (result == 3) /* no index value on line */
  185.                {CT[i].r = n; CT[i].g = r; CT[i].b = g;}
  186.            else if (result == 4 && (n >= 0 && n <= 256))
  187.                {
  188.                 if (i==n-1) n = i; /* patch to handle old palettes */
  189.                                    /* with values from 1 to 256    */
  190.                 CT[n].r = r; CT[n].g = g; CT[n].b = b;}
  191.            else
  192.            {
  193.                StatusLine (0,"Invalid Palette file format.");
  194.                fclose(unit); return(1);
  195.            }
  196.            i++;
  197.            fgets (filedata, 132, unit);
  198.        } while (! feof(unit) && i < 256);
  199.        if (numDN == 16 && i > 15)
  200.            for (i=0;i<16;i++)
  201.            {
  202.               CT[i].r = CT[i*16+8].r;
  203.               CT[i].g = CT[i*16+8].g;
  204.               CT[i].b = CT[i*16+8].b;
  205.            }
  206.     }
  207.  
  208.     WritePalette (CT);
  209.     fclose (unit);
  210. }
  211.  
  212. int ReadPalette (Color * coltab)
  213. /* int ReadPalette (struct Color * coltab) */
  214.  
  215. /***  ReadPalette returns the current color palette in coltab.
  216.       coltab is of type Color.
  217. ***/
  218.  
  219. {
  220.     int  i;
  221.  
  222.     memmove( &coltab[0], &PaletteTable[0], 3*numDN);
  223. /*
  224.     for (i = 0; i < numDN; i++)
  225.     {
  226.         coltab[i].r = PaletteTable[i].r;
  227.         coltab[i].g = PaletteTable[i].g;
  228.         coltab[i].b = PaletteTable[i].b;
  229.     }
  230. */
  231. }
  232.  
  233. int WritePalette (Color * coltab)
  234. /* int WritePalette (struct Color * coltab) */
  235.  
  236. /***
  237.     WritePalette updates the display device palette with the
  238.     palette passed in coltab.  coltab must be of type Color.
  239. ***/
  240.  
  241. {
  242.     int   i;
  243.     unsigned char   cmd[5],  red, green, blue;
  244.     long  pal_color;
  245.     union  REGS  inreg, outreg;
  246.     struct SREGS segregs;
  247.     Color    DP[256];
  248.     unsigned int   x,y;
  249.     unsigned char *colors, palbuf[256][3];
  250.  
  251.     memmove( &PaletteTable[0], &coltab[0], 3*numDN);
  252.  
  253.     switch (DisplayDevice)
  254.     {
  255.     case EGA350 :     /* for ega displays */
  256.     case EGA480 :     /* for ega displays */
  257.     case EVGA800 :   /* for Everex EVGA */
  258.  
  259.           for (i = 0; i <= 15; i++)
  260.           {
  261.                red   = (coltab[i].r >> 2) & 0x3f;
  262.                green = (coltab[i].g >> 2) & 0x3f;
  263.                blue  = (coltab[i].b >> 2) & 0x3f;
  264.                pal_color = ( ((long)blue)  << 16)
  265.                          | ( ((long)green) <<  8)
  266.              |   ((long)red) ;
  267. #ifdef __TURBOC__
  268.            setpalette( i, pal_color);
  269. #else
  270.            _remappalette( i, pal_color) ;
  271. #endif
  272.           }
  273.           return(0);
  274.  
  275.     case VGA480 :      /* for vga displays */
  276.  
  277.           for (i = 0; i <= 15; i++)
  278.           {
  279.               palbuf[i][0] = (coltab[i].r >> 2) & 0xff;
  280.               palbuf[i][1] = (coltab[i].g >> 2) & 0xff;
  281.               palbuf[i][2] = (coltab[i].b >> 2) & 0xff;
  282.           }
  283.           colors = &palbuf[0][0];
  284.           segregs.es = FP_SEG( colors );
  285.           inreg.x.dx = FP_OFF( colors );
  286.           inreg.x.ax = 0x1012;
  287.           inreg.x.bx = 0x0;
  288.           inreg.x.cx = 16;
  289.           int86x(0x10, &inreg, &outreg, &segregs);
  290.           return(0);
  291.  
  292. #ifndef __TURBOC__
  293.     case BIOS :     /* for vga displays */
  294.  
  295.           for (i = 0; i <= 15; i++)
  296.           {
  297.                red   = (coltab[i].r >> 2) & 0x3f;
  298.                green = (coltab[i].g >> 2) & 0x3f;
  299.                blue  = (coltab[i].b >> 2) & 0x3f;
  300.                pal_color = ( ((long)blue)  << 16)
  301.                          | ( ((long)green) <<  8)
  302.                          |   ((long)red) ;
  303.                _remappalette( i, pal_color) ;
  304.           }
  305.           return(0);
  306. #endif
  307.  
  308.     case VGA200 :       /* for vga displays */
  309.     case ORCHID480 :    /* for Orchid Designer */
  310.     case ORCHID600 :    /* for Orchid Designer */
  311.     case ORCHID768 :    /* for Orchid Designer */
  312.     case EVGA640 :      /* for Everex EVGA */
  313.     case EVGA512 :      /* for Everex EVGA */
  314.     case PARADISE :
  315.     case TRIDENT :
  316.     case VESA :
  317.     case VESA800 :
  318.     case VESA640 :
  319.  
  320.           for (i = 0; i <= 255; i++)
  321.           {
  322.  
  323.               palbuf[i][0] = (coltab[i].r >> 2) & 0xff;
  324.               palbuf[i][1] = (coltab[i].g >> 2) & 0xff;
  325.               palbuf[i][2] = (coltab[i].b >> 2) & 0xff;
  326.           }
  327.           colors = &palbuf[0][0];
  328.           segregs.es = FP_SEG( colors );
  329.           inreg.x.dx = FP_OFF( colors );
  330.           inreg.x.ax = 0x1012;
  331.           inreg.x.bx = 0x0;
  332.           inreg.x.cx = 256;
  333.           int86x(0x10, &inreg, &outreg, &segregs);
  334.           return(0);
  335.  
  336.     case PGA :    /* for pga display */
  337.           for (i = 0; i <= 255; i++)
  338.           {
  339.               cmd[0] = 0x0EE;
  340.               cmd[1] = i;
  341.               cmd[2] = coltab[i].r >> 4;
  342.               cmd[3] = coltab[i].g >> 4;
  343.               cmd[4] = coltab[i].b >> 4;
  344.               PGAsend (cmd, 5);        /* 'LUT numcol red green blue' */
  345.           }
  346.           return(0);
  347.  
  348.     case ATI640 :   /* for ATI VGA Wonder */
  349.     case ATI800 :   /* for ATI VGA Wonder */
  350.     case ATI1024:   /* for ATI VGA Wonder */
  351.  
  352.          for(i=0;i<256;i++)
  353.          {
  354.               palbuf[i][0] = (coltab[i].r >> 2) & 0xff;
  355.               palbuf[i][1] = (coltab[i].g >> 2) & 0xff;
  356.               palbuf[i][2] = (coltab[i].b >> 2) & 0xff;
  357.          }
  358.          ATI_WritePalette(palbuf,0,256);
  359.          return(0) ;
  360.  
  361.     case EV629 :
  362.  
  363.          for(i=0;i<256;i++)
  364.          {
  365.               palbuf[i][0] = (coltab[i].r >> 2) & 0xff;
  366.               palbuf[i][1] = (coltab[i].g >> 2) & 0xff;
  367.               palbuf[i][2] = (coltab[i].b >> 2) & 0xff;
  368.          }
  369.          loadmp(palbuf);
  370.          return(0);
  371.     }
  372. }
  373.  
  374. void ShowPalette( int numdiddle)
  375. {
  376.     int    samp, box, line, i;
  377.     int    numbox, DNperbox, boxns, boxnl;
  378.     unsigned char   PaletteLine[MAXDISPNS];
  379.  
  380. /*  Set up some constants */
  381.     numbox = min (numDN, numdiddle);
  382.     DNperbox = numDN / numbox;
  383.     boxns = dispns / numbox;
  384.     boxnl = dispnl / 10;
  385.     samp = 0;
  386.  
  387.     for (box = 0; box < numbox;  box++)
  388.         for (i = 0;  i < boxns; i++)
  389.             PaletteLine[samp++] = box*DNperbox;
  390.  
  391.     for (line = dispnl-boxnl;  line <= dispnl;  line++)
  392.         DisplayLine (PaletteLine, line, 1, numbox*boxns);
  393. }
  394.  
  395.  
  396. void ErasePalette( int numdiddle)
  397. {
  398.     int    samp, box, line, i;
  399.     int    numbox, DNperbox, boxns, boxnl;
  400.     unsigned char   PaletteLine[MAXDISPNS];
  401.  
  402. /*  Set up some constants */
  403.     numbox = min (numDN, numdiddle);
  404.     DNperbox = numDN / numbox;
  405.     boxns = dispns / numbox;
  406.     boxnl = dispnl / 10;
  407.     samp = 0;
  408.  
  409.     for (box = 0; box < numbox;  box++)
  410.         for (i = 0;  i < boxns; i++)
  411.             PaletteLine[samp++] = 0;
  412.  
  413.     for (line = dispnl-boxnl;  line <= dispnl;  line++)
  414.         DisplayLine (PaletteLine, line, 1, numbox*boxns);
  415. }
  416.  
  417. int DiddlePalette( int numdiddle)
  418.  
  419. /***  DiddlePalette performs interactive adjustment of the color
  420.     palette.  A wedge of numdiddle DN values, from 0 to the maximum,
  421.     is displayed at the bottom of the screen, and the palette is
  422.     changed to have only numdiddle distinct shades.  Then a loop
  423.     for user input is entered.  The active color is the one in the
  424.     wedge with the small black box inside it.
  425.  
  426.     The following is a list of commands:
  427.        Character      Action
  428.          7 (HOME)   move to first color in wedge
  429.          4 (6)      move to next lower (higher) color in wedge
  430.         ^4 (^6)     move 8 steps lower (higher) in wedge
  431.          r (R)      decrease (increase) amount of red one notch
  432.          g (G)      decrease (increase) amount of green one notch
  433.          b (B)      decrease (increase) amount of blue one notch
  434.          S          scroll palette right
  435.          s          scroll palette left
  436.          2 (8)      decrease (increase) amount of all colors one notch
  437.          1 (END)    move to last color in wedge
  438.          x (X)      invert color wedge
  439.          .          exit from palette diddle mode
  440.  
  441.     The wedge is erased after the user exits.
  442.  
  443.     Parameter   Type   Description
  444.      numdiddle   int   number of colors in the wedge and resulting palette
  445.  
  446. ***/
  447.  
  448. {
  449.     int  line, samp, i, box, DN, numbox, DNperbox, shade, numcol;
  450.     int  boxnl, boxns,  linepos, samppos, h_marksize, v_marksize, len;
  451.     int  colornum, m1, m2, m3, m4;
  452.     unsigned char  ch;                      /* mdm 10/6/87 */
  453.     unsigned char   PaletteLine[MAXDISPNS];
  454.     unsigned char   hold;
  455.     Color  coltab[256], hold_Color;
  456.     char dispstr[60];
  457.  
  458. /*  Set up some constants */
  459.     numbox = min (numDN, numdiddle);
  460.     DNperbox = numDN / numbox;
  461.     boxns = dispns / numbox;
  462.     boxnl = dispnl / 10;
  463.     v_marksize = 8;
  464.     h_marksize = min(boxns, v_marksize);
  465.     linepos = dispnl - (boxnl / 2) - (h_marksize / 2);
  466.  
  467. /* Draw the palette on the bottom of the screen */
  468.     ShowPalette( numdiddle );
  469.  
  470. /* Reduce the number of colors in the palette to numbox */
  471.     ReadPalette (coltab);
  472.     for (box = 0;  box < numbox; box++)
  473.     {
  474.         DN = box*DNperbox;
  475.         for (i = DN;  i < DN+DNperbox;  i++)
  476.         {   coltab[i].r = coltab[DN].r;
  477.             coltab[i].g = coltab[DN].g;
  478.             coltab[i].b = coltab[DN].b;
  479.         }
  480.     }
  481.     WritePalette (coltab);
  482.  
  483.     if ( use_mouse )
  484.     {                                            /* Mouse? */
  485.        m1 = 11;                                  /* Motion function */
  486.        mouses( &m1, &m2, &m3, &m4 );             /* Clear */
  487.        m1 = 5;                                   /* Button function */
  488.        m2 = 0;
  489.        mouses( &m1, &m2, &m3, &m4 );             /* Clear left */
  490.        m1 = 5;
  491.        m2 = 1;
  492.        mouses( &m1, &m2, &m3, &m4 );             /* Clear right */
  493.     }
  494.  
  495. /* Draw the marker box on top of the palette */
  496.     box = numbox / 2;
  497.     samppos =  box*boxns - (boxns / 2) - (h_marksize / 2);
  498.     DrawBox (linepos, samppos, v_marksize, h_marksize, 0);
  499.     shade =  256 / numshades ;
  500.  
  501. /* Interactively adjust the palette */
  502.     do
  503.     {
  504.     /* Save EGA settings in colornun: (red) (grn) (blue) */
  505.        if (DisplayDevice == EGA350 || DisplayDevice == EGA480
  506.         || DisplayDevice == VGA480)
  507.        {
  508.            colornum = (int)(coltab[DN].r/64);
  509.            colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].g/64));
  510.            colornum = (colornum << 2) | (0x03 & (int)(coltab[DN].b/64));
  511.        }
  512.        if ( use_mouse )
  513.        {                                         /* Mouse? */
  514.            ch = 0x00;                            /* Clear char */
  515.            do
  516.            {                                     /* Loop */
  517.                m1 = 11;                          /* Motion function */
  518.                mouses( &m1, &m2, &m3, &m4 );     /* Read motion */
  519.                if ( m3 != 0 )
  520.                {                                 /* Motion? */
  521.                    DN = (box-1)*DNperbox;        /* Yes clear box */
  522.                    DrawBox (linepos, samppos, v_marksize, h_marksize, DN);
  523.                    if ( m3 > 0 )                 /* Right? */
  524.                        box = min( box+m3, numbox );          /* Yes */
  525.                    else                          /* Left? */
  526.                        box = max( box+m3, 1 );   /* Yes */
  527.                    goto Skip;
  528.                }
  529.                m1 = 3;                           /* Button function */
  530.                mouses( &m1, &m2, &m3, &m4 );     /* Check button */
  531.                if ( m2 == 3 )                    /* Both? */
  532.                    ch = '.';                     /* Yes - set end char */
  533.                else if ( m2 == 1 )               /* Left? */
  534.                    ch = '2';                     /* Yes - set down char */
  535.                else if ( m2 == 2 )               /* Right? */
  536.                ch = '8';                         /* Yes - set up char */
  537.            } while ( ( ch == 0x00) && ( !kbhit() ) );     /* Until key or function */
  538.        }
  539.  
  540.        if ( ( !use_mouse ) || ( kbhit() ) )
  541.        {
  542.            if ((ch = getch()) == 0)    /* mdm 10/9/87 */
  543.            ch = 0x80 | getch();
  544.        }
  545.  
  546.        DN = (box-1)*DNperbox;
  547.        DrawBox (linepos, samppos, v_marksize, h_marksize, DN);
  548.  
  549.        switch (ch)
  550.        {
  551.        case 'r' :
  552.                  coltab[DN].r = coltab[DN].r - shade;
  553.                  if (coltab[DN].r < 0) coltab[DN].r = 255;
  554.                  break;
  555.  
  556.        case 'R' :
  557.                  coltab[DN].r = (coltab[DN].r + shade)%256;
  558.                  break;
  559.  
  560.        case 'g' :
  561.                  coltab[DN].g = coltab[DN].g - shade;
  562.                  if (coltab[DN].g < 0) coltab[DN].g = 255;
  563.                  break;
  564.  
  565.        case 'G' :
  566.                  coltab[DN].g = (coltab[DN].g + shade)%256;
  567.                  break;
  568.  
  569.        case 'b' :
  570.                  coltab[DN].b = max (coltab[DN].b - shade,0);
  571.                  if (coltab[DN].b < 0) coltab[DN].b = 255;
  572.                  break;
  573.  
  574.        case 'B' :
  575.                  coltab[DN].b = (coltab[DN].b + shade)%256;
  576.                  break;
  577.  
  578.        case 'X' :        /* xchange color table values */
  579.        case 'x' :
  580.                  for (i = 1; i <= numbox/2;  i++)
  581.                  {    hold               = coltab[numbox-i].r;
  582.                       coltab[numbox-i].r = coltab[i-1].r;
  583.                       coltab[i-1].r      = hold;
  584.                  
  585.                       hold               = coltab[numbox-i].g;
  586.                       coltab[numbox-i].g = coltab[i-1].g;
  587.                       coltab[i-1].g      = hold;
  588.                  
  589.                       hold               = coltab[numbox-i].b;
  590.                       coltab[numbox-i].b = coltab[i-1].b;
  591.                       coltab[i-1].b      = hold;
  592.                  }
  593.                  break;
  594.  
  595.        case 'S' :        /* shift color table one right */
  596.                  memcpy ( &hold_Color, &coltab[numbox-1], sizeof(hold_Color) );
  597.                  memmove( &coltab[1], &coltab[0], sizeof(hold_Color)*(numbox-1) );
  598.                  memcpy ( &coltab[0], &hold_Color, sizeof(hold_Color) );
  599.                  break;
  600.  
  601.        case 's' :        /* shift color table one left */
  602.                  memcpy ( &hold_Color, &coltab[0], sizeof(hold_Color) );
  603.                  memmove( &coltab[0], &coltab[1], sizeof(hold_Color)*(numbox-1) );
  604.                  memcpy ( &coltab[numbox-1], &hold_Color, sizeof(hold_Color) );
  605.                  break;
  606.  
  607.        case DOWN_ARROW:
  608.        case '2' :
  609.          if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
  610.             && numshades == 4)
  611.          {
  612.                --colornum;
  613.                coltab[DN].b = 64 * (colornum & 0x03);
  614.                coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
  615.                coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
  616.          }
  617.          else
  618.          {
  619.                      coltab[DN].r = coltab[DN].r - shade;
  620.                      coltab[DN].g = coltab[DN].g - shade;
  621.                      coltab[DN].b = coltab[DN].b - shade;
  622.          }
  623.                  break;
  624.  
  625.         case UP_ARROW:
  626.         case '8' :
  627.          if ( (DisplayDevice == EGA350 || DisplayDevice == EGA480)
  628.             && numshades == 4)
  629.          {
  630.                ++colornum;
  631.                coltab[DN].b = 64 * (colornum & 0x03);
  632.                coltab[DN].g = 64 * ((colornum >> 2) & 0x03);
  633.                coltab[DN].r = 64 * ((colornum >> 4) & 0x03);
  634.          } else {
  635.                      coltab[DN].r = (coltab[DN].r + shade) % 256;
  636.                      coltab[DN].g = (coltab[DN].g + shade) % 256;
  637.                      coltab[DN].b = (coltab[DN].b + shade) % 256;
  638.             }
  639.                  break;
  640.  
  641.         case RIGHT_ARROW:
  642.         case '6' :
  643.                  box = min (box+1, numbox);
  644.                  /* goto Skip; */
  645.                  break;
  646.  
  647.         case LEFT_ARROW:
  648.         case '4' :
  649.                  box = max (box-1, 1);
  650.                  /* goto Skip; */
  651.                  break;
  652.  
  653.         case CONTROL_RIGHT_ARROW:
  654.                  box = min (box+(numDN>>3), numbox);
  655.                  /* goto Skip; */
  656.                  break;
  657.  
  658.         case CONTROL_LEFT_ARROW:
  659.                  box = max (box-(numDN>>3), 1);
  660.                  /* goto Skip; */
  661.                  break;
  662.  
  663.         case HOME:
  664.         case '7' :
  665.                  box = 1;
  666.                  /* goto Skip; */
  667.                  break;
  668.  
  669.         case END:
  670.         case '1' :
  671.                  box = numbox;
  672.                  /* goto Skip; */
  673.                  break;
  674.         }
  675.  
  676.         for (i = DN; i < DN+DNperbox;  i++)
  677.         {
  678.              coltab[i].r = coltab[DN].r;
  679.              coltab[i].g = coltab[DN].g;
  680.              coltab[i].b = coltab[DN].b;
  681.         }
  682.         WritePalette (coltab);
  683.  
  684. Skip:
  685.         samppos =  box*boxns - (boxns / 2) - (h_marksize / 2);
  686.         DrawBox (linepos, samppos, v_marksize, h_marksize, 0);
  687.         DN = (box-1)*DNperbox;
  688.  
  689.         sprintf( dispstr, "color = %2d red = %3d green = %3d blue = %3d",
  690.                 DN, coltab[DN].r, coltab[DN].g, coltab[DN].b);
  691.  
  692.         LengthText( dispstr, TextHeight, &len);
  693.         EraseText( TextLine, 1, TextHeight, len, 0);
  694.  
  695.         DrawText( dispstr, TextLine, 1, TextHeight, 0, numDN-1);
  696.  
  697.         if (ch == RETURN || ch == ESCAPE) ch = '.';
  698.     }
  699.     while (ch != '.');
  700.  
  701.  
  702. /* Erase the palette on the screen */
  703.     ErasePalette( numdiddle );
  704.  
  705. }
  706.  
  707. void GetPalette(void)
  708. /* GetPalette will put up a directory selection menu, exactly the same one
  709.    as with the FIL command, but will select a palette instead.
  710.  
  711.    Written by Ron Baalke, 02/03/91
  712. */
  713.  
  714. {
  715.     char filename[128];
  716.  
  717.     filename[0] = '\0';
  718.  
  719.     ChangeDir(PalettePath);    /* Move to default palette directory */
  720.  
  721.     FileSel(filename,2);       /* Get the palette file */
  722.  
  723.     if (filename[0] != '\0')   /* If a palette is selected, load it in */
  724.     {
  725.        strcpy(CommandString,"PAL LOAD ");
  726.        strcat(CommandString,filename);
  727.        DoPalette();
  728.     }
  729.     DoRefresh();            /* Refresh the image */
  730. }
  731.  
  732.  
  733. int CyclePalette(int cycle)
  734. /*  Cycle Palette will through the color palette a number of interesting
  735.     ways.  Any key will abort the cycling, a 'S' or 's' key will save the
  736.     palette in its current setting, any other key will restore the
  737.     palette.
  738.  
  739.     Written by Ron Baalke, 02/04/91
  740.     Added FAST and TIME options - Ron Baalke, 07/91
  741. */
  742. {
  743.     Color  coltab[256], hold_Color;
  744.     unsigned char hold;
  745.     int i;
  746.     int j=0;
  747.     int k=0;
  748.     int temp;
  749.     int fast_flag, time_flag;
  750.     int seconds;
  751.     double total_seconds=0;
  752.     char dummy[40];
  753.  
  754.     GetKeywordInteger (CommandString, "TIM", 20, &seconds, &time_flag);
  755.     GetKeywordString (CommandString, "FAS", "",dummy, &fast_flag);
  756.     if (fast_flag != -1)
  757.        fast_flag = TRUE;
  758.     else
  759.        fast_flag = FALSE;
  760.  
  761.     ReadPalette (coltab);
  762.  
  763.     srand( (unsigned)time( NULL ) );        /* Seed random number generator */
  764.  
  765.     while (!kbhit())
  766.     {
  767.        switch (cycle)
  768.        {
  769.           case 0:                      /* "Blink" the palette */
  770.              DoNegative();
  771.              if (fast_flag)
  772.                 Sleep(0.1);
  773.              else
  774.                 Sleep(0.3);
  775.              break;
  776.  
  777.           case 1 :                     /* Blink 4 times */
  778.            for (i=0; i<numDN/4; i++)
  779.              {
  780.                 hold                = coltab[i].r;
  781.                 coltab[i].r         = coltab[i+numDN/4].r;
  782.                 coltab[i+numDN/4].r = coltab[i+numDN/2].r;
  783.                 coltab[i+numDN/2].r = coltab[i+(numDN*3)/4].r;
  784.                 coltab[i+(numDN*3)/4].r = hold;
  785.  
  786.                 hold                = coltab[i].g;
  787.                 coltab[i].g         = coltab[i+numDN/4].g;
  788.                 coltab[i+numDN/4].g = coltab[i+numDN/2].g;
  789.                 coltab[i+numDN/2].g = coltab[i+(numDN*3)/4].g;
  790.                 coltab[i+(numDN*3)/4].g = hold;
  791.  
  792.                 hold                = coltab[i].b;
  793.                 coltab[i].b         = coltab[i+numDN/4].b;
  794.                 coltab[i+numDN/4].b = coltab[i+numDN/2].b;
  795.                 coltab[i+numDN/2].b = coltab[i+(numDN*3)/4].b;
  796.                 coltab[i+(numDN*3)/4].b = hold;
  797.              }
  798.              WritePalette(coltab);
  799.              if (fast_flag)
  800.                 Sleep(0.1);
  801.              else
  802.                 Sleep(0.3);
  803.              break;
  804.  
  805.           case 2:                    /* Rotate Palette left - AW */
  806.              memcpy ( &hold_Color, &coltab[0], 3 );
  807.              memmove( &coltab[0], &coltab[1], (numDN-1)*3 );
  808.              memcpy ( &coltab[numDN-1], &hold_Color, 3 );
  809.              WritePalette( coltab );
  810.              if (fast_flag)
  811.                 Delay(50);
  812.              else
  813.                 Delay(300);
  814.              break;
  815.  
  816.           case 3:                    /* Rotate Palette right - AW */
  817.              memcpy ( &hold_Color, &coltab[numDN-1], 3 );
  818.              memmove( &coltab[1], &coltab[0], (numDN-1)*3 );
  819.              memcpy ( &coltab[0], &hold_Color, 3 );
  820.              WritePalette(coltab);
  821.              if (fast_flag)
  822.                 Delay(50);
  823.              else
  824.                 Delay(300);
  825.              break;
  826.  
  827.           case 4:               /* Rotate pallete & feed in a random color */
  828.              hold = coltab[0].r;
  829.              for (i=0; i<numDN-1; i++)
  830.                 coltab[i].r = coltab[i+1].r;
  831.              coltab[numDN-1].r = hold;
  832.  
  833.              hold = coltab[0].g;
  834.              for (i=0; i<numDN-1; i++)
  835.                 coltab[i].g = coltab[i+1].g;
  836.              coltab[numDN-1].g = hold;
  837.  
  838.              hold = coltab[0].b;
  839.              for (i=0; i<numDN-1; i++)
  840.                 coltab[i].b = coltab[i+1].b;
  841.              coltab[numDN-1].b = hold;
  842.  
  843.              if (j == 2 * numDN)
  844.              {
  845.                 WritePalette(CT);
  846.                 ReadPalette(coltab);
  847.                 j = 0;
  848.              }
  849.              else
  850.              {
  851.                 coltab[numDN-1].r = (rand() % numDN);
  852.                 coltab[numDN-1].g = (rand() % numDN);
  853.                 coltab[numDN-1].b = (rand() % numDN);
  854.                 WritePalette(coltab);
  855.                 j++;
  856.              }
  857.              if (fast_flag)
  858.                 Sleep(0.1);
  859.              else
  860.                 Sleep(0.3);
  861.              break;
  862.  
  863.            case 5:                    /* Randomize the palette */
  864.              for (i=0; i<numDN; i++)
  865.              {
  866.                 temp = (rand() % numDN);
  867.                 coltab[i].r = (coltab[i].r + temp)/2;
  868.                 temp = (rand() % numDN);
  869.                 coltab[i].b = (coltab[i].b + temp)/2;
  870.                 temp = (rand() % numDN);
  871.                 coltab[i].g = (coltab[i].g + temp)/2;
  872.              }
  873.              WritePalette(coltab);
  874.              if (fast_flag)
  875.                 Sleep(0.1);
  876.              else
  877.                 Sleep(0.3);
  878.              break;
  879.  
  880.            case 6:                   /* Double rotate the palette */
  881.              hold = coltab[numDN/2].r;
  882.              for (i=numDN/2; i<numDN-1; i++)
  883.                 coltab[i].r = coltab[i+1].r;
  884.              coltab[numDN-1].r = hold;
  885.  
  886.              hold = coltab[numDN/2].b;
  887.              for (i=numDN/2; i<numDN-1; i++)
  888.                 coltab[i].b = coltab[i+1].b;
  889.              coltab[numDN-1].b = hold;
  890.  
  891.              hold = coltab[numDN/2].g;
  892.              for (i=numDN/2; i<numDN-1; i++)
  893.                 coltab[i].g = coltab[i+1].g;
  894.              coltab[numDN-1].g = hold;
  895.  
  896.              hold = coltab[numDN/2-1].r;
  897.              for (i=numDN/2-1; i > 0; i--)
  898.                 coltab[i].r = coltab[i-1].r;
  899.              coltab[0].r = hold;
  900.  
  901.              hold = coltab[numDN/2-1].g;
  902.              for (i=numDN/2-1; i > 0; i--)
  903.                 coltab[i].g = coltab[i-1].g;
  904.              coltab[0].g = hold;
  905.  
  906.              hold = coltab[numDN/2-1].b;
  907.              for (i=numDN/2-1; i > 0; i--)
  908.                 coltab[i].b = coltab[i-1].b;
  909.              coltab[0].b = hold;
  910.  
  911.              WritePalette(coltab);
  912.              if (fast_flag)
  913.                 Sleep(0.1);
  914.              else
  915.                 Sleep(0.3);
  916.              break;
  917.  
  918.           case 7:                   /* Random swaps of the palette */
  919.              i = (rand() % numDN);
  920.              j = (rand() % numDN);
  921.  
  922.              hold = coltab[i].r;
  923.              coltab[i].r = coltab[j].r;
  924.              coltab[j].r = hold;
  925.              hold = coltab[i].b;
  926.              coltab[i].b = coltab[j].b;
  927.              coltab[j].b = hold;
  928.              hold = coltab[i].g;
  929.              coltab[i].g = coltab[j].g;
  930.              coltab[j].g = hold;
  931.  
  932.              WritePalette(coltab);
  933.              if (fast_flag)
  934.                 Sleep(0.1);
  935.              else
  936.                 Sleep(0.3);
  937.              break;
  938.  
  939.           default:
  940.              return(TRUE);
  941.          break;
  942.  
  943.        } /* end switch */
  944.  
  945.        if (time_flag != -1)
  946.        {
  947.           if (fast_flag)
  948.              total_seconds += 0.06;
  949.           else
  950.              total_seconds += 0.3;
  951.           if ((int)total_seconds >= seconds) return(FALSE);
  952.        }
  953.     } /* end while */
  954.  
  955.     i = getch();
  956.     if ((i == 83) || (i == 115))          /* If 'S' or 's' */
  957.        return(TRUE);
  958.     else
  959.        return(FALSE);
  960. }
  961. /**************************************************************/
  962. /* VAXFloat2Char                                              */
  963. /*                                                            */
  964. /* Converts VAX floating point number to char                 */
  965. /*                                                            */
  966. /* Ron Baalke 04/07/91                                        */
  967. /**************************************************************/
  968. void   VAXFloat2Char(unsigned char *vFloatBuf, unsigned char *charBuf,
  969.        int length)
  970. /*
  971.   unsigned char    vFloatBuf[];    in: buffer holding 32 bit VAX F_floating
  972.   unsigned char    charBuf[];      out: converted buffer
  973.   int              length;         in: number of numbers to convert
  974. */
  975. {
  976.     int        i, j;
  977.     unsigned char exp;        /* binary exponent            */
  978.     short      fraction;
  979.  
  980.     for (i = 0, j = 0; i < length; i++, j += 4)
  981.     {
  982.        fraction = 0x0080 | vFloatBuf[j];        /* lst sig byte of frac    */
  983.        exp = (vFloatBuf[j + 1] << 1) | (vFloatBuf[j] >> 7);
  984.        exp = 8 - (exp & 0x7F);    /* convert from left shift to right shift */
  985.        charBuf[i] = fraction >> exp;
  986.     }
  987.     return;
  988. }
  989.  
  990.