home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / t / triq.zip / DIB.C < prev    next >
C/C++ Source or Header  |  1992-05-06  |  43KB  |  1,720 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   Routines for dealing with Device independent bitmaps                       |
  3. |                                           |
  4. |                                                                              |
  5. \*----------------------------------------------------------------------------*/
  6.  
  7. /*
  8.      (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  9.  
  10.      You have a royalty-free right to use, modify, reproduce and 
  11.      distribute the Sample Files (and/or any modified version) in 
  12.      any way you find useful, provided that you agree that 
  13.      Microsoft has no warranty obligations or liability for any 
  14.      Sample Application Files which are modified. 
  15.  */
  16.  
  17. #include <windows.h>
  18. #include "gmem.h"
  19. #include "dib.h"
  20.  
  21. void FAR * FAR PASCAL lmemcpy(LPSTR dest, LPSTR source, WORD count);
  22. //void FAR * FAR PASCAL hmemcpy(char huge *dest, char huge *source, LONG count);
  23. //#include "errprop.h"
  24.  
  25. //extern BOOL fErrProp;
  26. //extern BOOL bMonoBitmap;
  27.  
  28. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
  29.  
  30. DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
  31. DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul);
  32.  
  33. /* flags for _lseek */
  34. #define  SEEK_CUR 1
  35. #define  SEEK_END 2
  36. #define  SEEK_SET 0
  37.  
  38. /*
  39.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  40.  *
  41.  *   BITMAP INFO    bi
  42.  *   palette data
  43.  *   bits....
  44.  *
  45.  */
  46. HANDLE OpenDIB(LPSTR szFile)
  47. {
  48.     unsigned            fh;
  49.     BITMAPINFOHEADER    bi;
  50.     LPBITMAPINFOHEADER  lpbi;
  51.     DWORD               dwLen;
  52.     DWORD               dwBits;
  53.     HANDLE              hdib;
  54.     HANDLE              h;
  55.     OFSTRUCT            of;
  56.  
  57.     if (HIWORD((DWORD)szFile) == 0)
  58.     {
  59.         fh = LOWORD((DWORD)szFile);
  60.     }
  61.     else
  62.     {
  63.         fh = OpenFile(szFile, &of, OF_READ);
  64.     }
  65.  
  66.     if (fh == -1)
  67.         return NULL;
  68.  
  69.     hdib = ReadDibBitmapInfo(fh);
  70.  
  71.     if (!hdib)
  72.         return NULL;
  73.  
  74.     DibInfo(hdib,&bi);
  75.  
  76.     /* How much memory do we need to hold the DIB */
  77.  
  78.     dwBits = bi.biSizeImage;
  79.     dwLen  = bi.biSize + PaletteSize(&bi) + dwBits;
  80.  
  81.     /* Can we get more memory? */
  82.  
  83.     h = GReAlloc(hdib,dwLen);
  84.  
  85.     if (!h)
  86.     {
  87.         GFree(hdib);
  88.         hdib = NULL;
  89.     }
  90.     else
  91.     {
  92.         hdib = h;
  93.     }
  94.  
  95.     if (hdib)
  96.     {
  97.         lpbi = GLock(hdib);
  98.  
  99.         /* read in the bits */
  100.         lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
  101.  
  102.         GUnlock(hdib);
  103.     }
  104.  
  105. exit:
  106.     if (HIWORD((DWORD)szFile) != 0)
  107.         _lclose(fh);
  108.  
  109.     return hdib;
  110. }
  111.  
  112. /*
  113.  *   Write a global handle in CF_DIB format to a file.
  114.  *
  115.  */
  116. BOOL WriteDIB(LPSTR szFile,HANDLE hdib)
  117. {
  118.     BITMAPFILEHEADER    hdr;
  119.     LPBITMAPINFOHEADER  lpbi;
  120.     BITMAPINFOHEADER    bi;
  121.     int                 fh;
  122.     OFSTRUCT            of;
  123.     DWORD               dwSize;
  124.  
  125.     if (!hdib)
  126.         return FALSE;
  127.  
  128.     if (HIWORD((DWORD)szFile) == 0)
  129.     {
  130.         fh = LOWORD((DWORD)szFile);
  131.     }
  132.     else
  133.     {
  134.         fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
  135.     }
  136.  
  137.     if (fh == -1)
  138.         return FALSE;
  139.  
  140.     DibInfo(hdib,&bi);
  141.  
  142.     dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  143.  
  144.     lpbi = GLock(hdib);
  145.  
  146.     hdr.bfType          = BFT_BITMAP;
  147.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  148.     hdr.bfReserved1     = 0;
  149.     hdr.bfReserved2     = 0;
  150.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  151.                           PaletteSize(lpbi);
  152.  
  153.     _lwrite(fh,(LPVOID)&hdr,sizeof(BITMAPFILEHEADER));
  154.     lwrite(fh,(LPVOID)lpbi,dwSize);
  155.  
  156.     GUnlock(hdib);
  157.  
  158.     if (HIWORD((DWORD)szFile) != 0)
  159.         _lclose(fh);
  160.  
  161.     return TRUE;
  162. }
  163.  
  164. /*
  165.  *  DibInfo(hbi, lpbi)
  166.  *
  167.  *  retrives the DIB info associated with a CF_DIB format memory block.
  168.  */
  169. BOOL DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
  170. {
  171.     if (hbi)
  172.     {
  173.         *lpbi = *(LPBITMAPINFOHEADER)GLock(hbi);
  174.         GUnlock(hbi);
  175.  
  176.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  177.         {
  178.             BITMAPCOREHEADER bc;
  179.  
  180.             bc = *(LPBITMAPCOREHEADER)lpbi;
  181.  
  182.             lpbi->biSize               = sizeof(BITMAPINFOHEADER);
  183.             lpbi->biWidth              = (DWORD)bc.bcWidth;
  184.             lpbi->biHeight             = (DWORD)bc.bcHeight;
  185.             lpbi->biPlanes             =  (WORD)bc.bcPlanes;
  186.             lpbi->biBitCount           =  (WORD)bc.bcBitCount;
  187.             lpbi->biCompression        = BI_RGB;
  188.             lpbi->biSizeImage          = 0;
  189.             lpbi->biXPelsPerMeter      = 0;
  190.             lpbi->biYPelsPerMeter      = 0;
  191.             lpbi->biClrUsed            = 0;
  192.             lpbi->biClrImportant       = 0;
  193.         }
  194.  
  195.         /*
  196.          * fill in the default fields
  197.          */
  198.         if (lpbi->biSizeImage == 0L)
  199.             lpbi->biSizeImage = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  200.  
  201.         if (lpbi->biClrUsed == 0L)
  202.             lpbi->biClrUsed = DibNumColors(lpbi);
  203.  
  204.         return TRUE;
  205.     }
  206.     return FALSE;
  207. }
  208.  
  209. /*
  210.  *  CreateBIPalette()
  211.  *
  212.  *  Given a Pointer to a BITMAPINFO struct will create a
  213.  *  a GDI palette object from the color table.
  214.  *
  215.  *  works with "old" and "new" DIB's
  216.  *
  217.  */
  218. HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
  219. {
  220.     LOGPALETTE          *pPal;
  221.     HPALETTE            hpal = NULL;
  222.     WORD                nNumColors;
  223.     BYTE                red;
  224.     BYTE                green;
  225.     BYTE                blue;
  226.     int                 i;
  227.     RGBQUAD        FAR *pRgb;
  228.     BOOL                fCoreHeader;
  229.  
  230.     if (!lpbi)
  231.         return NULL;
  232.  
  233.     fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
  234.  
  235.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  236.     nNumColors = DibNumColors(lpbi);
  237.  
  238.     if (nNumColors)
  239.     {
  240.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  241.  
  242.         if (!pPal)
  243.             goto exit;
  244.  
  245.         pPal->palNumEntries = nNumColors;
  246.         pPal->palVersion    = PALVERSION;
  247.  
  248.         for (i = 0; i < nNumColors; i++)
  249.         {
  250.             pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  251.             pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  252.             pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  253.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  254.  
  255.             if (fCoreHeader)
  256.                 ((LPSTR)pRgb) += sizeof(RGBTRIPLE) ;
  257.             else
  258.                 pRgb++;
  259.         }
  260.  
  261.         hpal = CreatePalette(pPal);
  262.         LocalFree((HANDLE)pPal);
  263.     }
  264.     else if (lpbi->biBitCount == 24)
  265.     {
  266.         hpal = CreateColorPalette();
  267.     }
  268.  
  269. exit:
  270.     return hpal;
  271. }
  272.  
  273.  
  274. /*
  275.  *  CreateDibPalette()
  276.  *
  277.  *  Given a Global HANDLE to a BITMAPINFO Struct
  278.  *  will create a GDI palette object from the color table.
  279.  *
  280.  *  works with "old" and "new" DIB's
  281.  *
  282.  */
  283. HPALETTE CreateDibPalette(HANDLE hbi)
  284. {
  285.     HPALETTE hpal;
  286.  
  287.     if (!hbi)
  288.         return NULL;
  289.  
  290.     hpal = CreateBIPalette((LPBITMAPINFOHEADER)GLock(hbi));
  291.     GUnlock(hbi);
  292.     return hpal;
  293. }
  294.  
  295. //
  296. // create a 6*6*6 rainbow palette
  297. //
  298. HPALETTE CreateColorPalette()
  299. {
  300.     LOGPALETTE          *pPal;
  301.     PALETTEENTRY        *ppe;
  302.     HPALETTE            hpal = NULL;
  303.     WORD                nNumColors;
  304.     BYTE                r,g,b;
  305.  
  306.     nNumColors = 6*6*6;
  307.     pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  308.  
  309.     if (!pPal)
  310.     goto exit;
  311.  
  312.     pPal->palNumEntries = nNumColors;
  313.     pPal->palVersion    = PALVERSION;
  314.  
  315.     ppe = pPal->palPalEntry;
  316.  
  317.     for (r=0; r<6; r++)
  318.         for (g=0; g<6; g++)
  319.             for (b=0; b<6; b++)
  320.             {
  321.                 ppe->peRed   = (BYTE)((WORD)r * 255 / 6);
  322.                 ppe->peGreen = (BYTE)((WORD)g * 255 / 6);
  323.                 ppe->peBlue  = (BYTE)((WORD)b * 255 / 6);
  324.                 ppe->peFlags = (BYTE)0;
  325.                 ppe++;
  326.             }
  327.  
  328.     hpal = CreatePalette(pPal);
  329.     LocalFree((HANDLE)pPal);
  330.  
  331. exit:
  332.     return hpal;
  333. }
  334.  
  335. HPALETTE CreateExplicitPalette(void)
  336. {
  337.     PLOGPALETTE ppal;
  338.     HPALETTE    hpal;
  339.     int         i;
  340.     #define     NPAL   256
  341.  
  342.     ppal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
  343.  
  344.     ppal->palVersion    = 0x300;
  345.     ppal->palNumEntries = NPAL;
  346.  
  347.     for (i=0; i<NPAL; i++)
  348.     {
  349.         ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
  350.         ppal->palPalEntry[i].peRed   = (BYTE)i;
  351.         ppal->palPalEntry[i].peGreen = (BYTE)0;
  352.         ppal->palPalEntry[i].peBlue  = (BYTE)0;
  353.     }
  354.  
  355.     hpal = CreatePalette(ppal);
  356.     LocalFree((HANDLE)ppal);
  357.     return hpal;
  358. }
  359.  
  360. /* CreateSystemPalette()
  361.  *
  362.  * Return a palette which represents the system (physical) palette.
  363.  * By selecting this palette into a screen DC and realizing the palette,
  364.  * the exact physical mapping will be restored
  365.  *
  366.  * one use for this is when "snaping" the screen as a bitmap
  367.  *
  368.  * On error (e.g. out of memory), NULL is returned.
  369.  */
  370. HPALETTE CreateSystemPalette(void)
  371. {
  372.     HDC             hdc;                    // DC onto the screen
  373.     int             iSizePalette;           // size of entire palette
  374.     int             iFixedPalette;          // number of reserved colors
  375.     NPLOGPALETTE    pLogPal = NULL;
  376.     HPALETTE        hpal = NULL;
  377.     int             i;
  378.  
  379.     hdc = GetDC(NULL);
  380.  
  381.     iSizePalette = GetDeviceCaps(hdc, SIZEPALETTE);
  382.  
  383.     //
  384.     // determine the number of 'static' system colors that
  385.     // are currently reserved
  386.     //
  387.     
  388. // this is the correct number of parms... bug in windows.h    
  389.     if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
  390.         iFixedPalette = GetDeviceCaps(hdc, NUMCOLORS);
  391.     else
  392.         iFixedPalette = 2;
  393.  
  394.     //
  395.     // create a logical palette containing the system colors;
  396.     // this palette has all entries except fixed (system) colors
  397.     // flagged as PC_NOCOLLAPSE
  398.     //
  399.     pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
  400.             + iSizePalette * sizeof(PALETTEENTRY));
  401.  
  402.     if (pLogPal)
  403.     {
  404.         pLogPal->palVersion = 0x300;
  405.         pLogPal->palNumEntries = iSizePalette;
  406.  
  407.         GetSystemPaletteEntries(hdc, 0, iSizePalette, pLogPal->palPalEntry);
  408.  
  409.         for (i = iFixedPalette/2; i < iSizePalette-iFixedPalette/2; i++)
  410.             pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  411.  
  412.         hpal = CreatePalette(pLogPal);
  413.     LocalFree((HANDLE)pLogPal);
  414.     }
  415.  
  416.     ReleaseDC(NULL,hdc);
  417.     return hpal;
  418. }
  419.  
  420.  
  421.  
  422.  
  423. /*
  424.  *  ReadDibBitmapInfo()
  425.  *
  426.  *  Will read a file in DIB format and return a global HANDLE to it's
  427.  *  BITMAPINFO.  This function will work with both "old" and "new"
  428.  *  bitmap formats, but will allways return a "new" BITMAPINFO
  429.  *
  430.  */
  431. HANDLE ReadDibBitmapInfo(int fh)
  432. {
  433.     DWORD     off;
  434.     HANDLE    hbi = NULL;
  435.     int       size;
  436.     int       i;
  437.     WORD      nNumColors;
  438.  
  439.     RGBQUAD FAR       *pRgb;
  440.     BITMAPINFOHEADER   bi;
  441.     BITMAPCOREHEADER   bc;
  442.     LPBITMAPINFOHEADER lpbi;
  443.     BITMAPFILEHEADER   bf;
  444.  
  445.     if (fh == -1)
  446.         return NULL;
  447.  
  448.     off = _llseek(fh,0L,SEEK_CUR);
  449.  
  450.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  451.         return FALSE;
  452.  
  453.     /*
  454.      *  do we have a RC HEADER?
  455.      */
  456.     if (!ISDIB(bf.bfType))
  457.     {
  458.         bf.bfOffBits = 0L;
  459.         _llseek(fh,off,SEEK_SET);
  460.     }
  461.  
  462.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  463.         return FALSE;
  464.  
  465.     nNumColors = DibNumColors(&bi);
  466.  
  467.     /*
  468.      *  what type of bitmap info is this?
  469.      */
  470.     switch (size = (int)bi.biSize)
  471.     {
  472.         case sizeof(BITMAPINFOHEADER):
  473.             break;
  474.  
  475.         case sizeof(BITMAPCOREHEADER):
  476.             bc = *(LPBITMAPCOREHEADER)&bi;
  477.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  478.             bi.biWidth              = (DWORD)bc.bcWidth;
  479.             bi.biHeight             = (DWORD)bc.bcHeight;
  480.             bi.biPlanes             =  (WORD)bc.bcPlanes;
  481.             bi.biBitCount           =  (WORD)bc.bcBitCount;
  482.             bi.biCompression        = BI_RGB;
  483.             bi.biSizeImage          = 0;
  484.             bi.biXPelsPerMeter      = 0;
  485.             bi.biYPelsPerMeter      = 0;
  486.             bi.biClrUsed            = nNumColors;
  487.             bi.biClrImportant       = nNumColors;
  488.  
  489.             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  490.  
  491.             break;
  492.  
  493.         default:
  494.             return NULL;       /* not a DIB */
  495.     }
  496.  
  497.     /*
  498.      *    fill in some default values!
  499.      */
  500.     if (bi.biSizeImage == 0)
  501.     {
  502.         bi.biSizeImage = bi.biHeight * DIBWIDTHBYTES(bi);
  503.  
  504.     }
  505.  
  506.     if (bi.biXPelsPerMeter == 0)
  507.     {
  508.         bi.biXPelsPerMeter = 0;         // ??????????????
  509.     }
  510.  
  511.     if (bi.biYPelsPerMeter == 0)
  512.     {
  513.         bi.biYPelsPerMeter = 0;         // ??????????????
  514.     }
  515.  
  516.     if (bi.biClrUsed == 0)
  517.     {
  518.         bi.biClrUsed = DibNumColors(&bi);
  519.     }
  520.  
  521.     hbi = GAlloc((LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  522.     if (!hbi)
  523.         return NULL;
  524.  
  525.     lpbi = (VOID FAR *)GLock(hbi);
  526.     *lpbi = bi;
  527.  
  528.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
  529.  
  530.     if (nNumColors)
  531.     {
  532.         if (size == sizeof(BITMAPCOREHEADER))
  533.         {
  534.             /*
  535.              * convert a old color table (3 byte entries) to a new
  536.              * color table (4 byte entries)
  537.              */
  538.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBTRIPLE));
  539.  
  540.             for (i=nNumColors-1; i>=0; i--)
  541.             {
  542.                 RGBQUAD rgb;
  543.  
  544.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  545.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  546.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  547.                 rgb.rgbReserved = (BYTE)0;
  548.  
  549.                 pRgb[i] = rgb;
  550.             }
  551.         }
  552.         else
  553.         {
  554.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
  555.         }
  556.     }
  557.  
  558.     if (bf.bfOffBits != 0L)
  559.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  560.  
  561.     GUnlock(hbi);
  562.     return hbi;
  563. }
  564.  
  565. /*  How big is the palette? if bits per pel not 24
  566.  *  no of bytes to read is 6 for 1 bit, 48 for 4 bits
  567.  *  256*3 for 8 bits and 0 for 24 bits
  568.  */
  569. WORD PaletteSize(VOID FAR * pv)
  570. {
  571.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  572.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  573.  
  574.     WORD    NumColors;
  575.  
  576.     NumColors = DibNumColors(lpbi);
  577.  
  578.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  579.         return NumColors * sizeof(RGBTRIPLE);
  580.     else
  581.         return NumColors * sizeof(RGBQUAD);
  582.  
  583.     #undef lpbi
  584.     #undef lpbc
  585. }
  586.  
  587. /*  How Many colors does this DIB have?
  588.  *  this will work on both PM and Windows bitmap info structures.
  589.  */
  590. WORD DibNumColors(VOID FAR * pv)
  591. {
  592.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  593.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  594.  
  595.     int bits;
  596.  
  597.     /*
  598.      *  with the new format headers, the size of the palette is in biClrUsed
  599.      *  else is dependent on bits per pixel
  600.      */
  601.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  602.     {
  603.         if (lpbi->biClrUsed != 0)
  604.             return (WORD)lpbi->biClrUsed;
  605.  
  606.         bits = lpbi->biBitCount;
  607.     }
  608.     else
  609.     {
  610.         bits = lpbc->bcBitCount;
  611.     }
  612.  
  613.     switch (bits)
  614.     {
  615.     case 1:
  616.             return 2;
  617.     case 4:
  618.             return 16;
  619.     case 8:
  620.             return 256;
  621.     default:
  622.             return 0;
  623.     }
  624.  
  625.     #undef lpbi
  626.     #undef lpbc
  627. }
  628.  
  629. /*
  630.  *  DibFromBitmap()
  631.  *
  632.  *  Will create a global memory block in DIB format that represents the DDB
  633.  *  passed in
  634.  *
  635.  */
  636. HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  637. {
  638.     BITMAP               bm;
  639.     BITMAPINFOHEADER     bi;
  640.     BITMAPINFOHEADER FAR *lpbi;
  641.     DWORD                dwLen;
  642.     int                  nColors;
  643.     HANDLE               hdib;
  644.     HANDLE               h;
  645.     HDC                  hdc;
  646.  
  647.     if (wUsage == 0)
  648.         wUsage = DIB_RGB_COLORS;
  649.  
  650.     if (!hbm)
  651.         return NULL;
  652.  
  653.     if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
  654.         return CreateLogicalDib(hbm,biBits,hpal);
  655.  
  656.     if (hpal == NULL)
  657.         hpal = GetStockObject(DEFAULT_PALETTE);
  658.  
  659.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  660.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  661.  
  662.     if (biBits == 0)
  663.         biBits = bm.bmPlanes * bm.bmBitsPixel;
  664.  
  665.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  666.     bi.biWidth              = bm.bmWidth;
  667.     bi.biHeight             = bm.bmHeight;
  668.     bi.biPlanes             = 1;
  669.     bi.biBitCount           = biBits;
  670.     bi.biCompression        = biStyle;
  671.     bi.biSizeImage          = 0;
  672.     bi.biXPelsPerMeter      = 0;
  673.     bi.biYPelsPerMeter      = 0;
  674.     bi.biClrUsed            = 0;
  675.     bi.biClrImportant       = 0;
  676.  
  677.     dwLen  = bi.biSize + PaletteSize(&bi);
  678.  
  679.     hdc = CreateCompatibleDC(NULL);
  680.     hpal = SelectPalette(hdc,hpal,FALSE);
  681.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  682.  
  683.     hdib = GAlloc(dwLen);
  684.  
  685.     if (!hdib)
  686.         goto exit;
  687.  
  688.     lpbi = GLock(hdib);
  689.  
  690.     *lpbi = bi;
  691.  
  692.     /*
  693.      *  call GetDIBits with a NULL lpBits param, so it will calculate the
  694.      *  biSizeImage field for us
  695.      */
  696.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  697.         NULL, (LPBITMAPINFO)lpbi, wUsage);
  698.  
  699.     bi = *lpbi;
  700.     GUnlock(hdib);
  701.  
  702.     /*
  703.      * HACK! if the driver did not fill in the biSizeImage field, make one up
  704.      */
  705.     if (bi.biSizeImage == 0)
  706.     {
  707.         bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  708.  
  709.         if (biStyle != BI_RGB)
  710.             bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  711.     }
  712.  
  713.     /*
  714.      *  realloc the buffer big enough to hold all the bits
  715.      */
  716.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  717.     if (h = GReAlloc(hdib,dwLen))
  718.     {
  719.         hdib = h;
  720.     }
  721.     else
  722.     {
  723.         GFree(hdib);
  724.         hdib = NULL;
  725.         goto exit;
  726.     }
  727.  
  728.     /*
  729.      *  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  730.      *  bits this time
  731.      */
  732.     lpbi = GLock(hdib);
  733.  
  734.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  735.         (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
  736.         (LPBITMAPINFO)lpbi, wUsage);
  737.  
  738.     bi = *lpbi;
  739.     GUnlock(hdib);
  740.  
  741. exit:
  742.     SelectPalette(hdc,hpal,FALSE);
  743.     DeleteDC(hdc);
  744.     return hdib;
  745. }
  746.  
  747. /*
  748.  *  BitmapFromDib()
  749.  *
  750.  *  Will create a DDB (Device Dependent Bitmap) given a global handle to
  751.  *  a memory block in CF_DIB format
  752.  *
  753.  */
  754. HBITMAP BitmapFromDib(HANDLE hdib, HPALETTE hpal, WORD wUsage)
  755. {
  756.     LPBITMAPINFOHEADER lpbi;
  757.     HPALETTE    hpalT;
  758.     HDC         hdc;
  759.     HBITMAP     hbm;
  760.     WORD        dx,dy,bits;
  761.  
  762.     if (!hdib)
  763.         return NULL;
  764.  
  765.     if (wUsage == 0)
  766.         wUsage = DIB_RGB_COLORS;
  767.  
  768.     lpbi = GLock(hdib);
  769.  
  770.     if (!lpbi)
  771.         return NULL;
  772.  
  773.     hdc = GetDC(NULL);
  774. //  hdc = CreateCompatibleDC(NULL);
  775.  
  776.     if (hpal)
  777.     {
  778.         hpalT = SelectPalette(hdc,hpal,FALSE);
  779.         RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  780.     }
  781.  
  782. #if 0
  783.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  784.     {
  785.         dx   = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  786.         dy   = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  787.         bits = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  788.     }
  789.     else
  790.     {
  791.         dx   = (WORD)lpbi->biWidth;
  792.         dy   = (WORD)lpbi->biHeight;
  793.         bits = (WORD)lpbi->biBitCount;
  794.     }
  795.  
  796.     if (bMonoBitmap /* || bits == 1 */)
  797.     {
  798.         hbm = CreateBitmap(dx,dy,1,1,NULL);
  799.     }
  800.     else
  801.     {
  802.         HDC hdcScreen = GetDC(NULL);
  803.         hbm = CreateCompatibleBitmap(hdcScreen,dx,dy);
  804.         ReleaseDC(NULL,hdcScreen);
  805.     }
  806.  
  807.     if (hbm)
  808.     {
  809.         if (fErrProp)
  810.             SetDIBitsErrProp(hdc,hbm,0,dy,
  811.                (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  812.                (LPBITMAPINFO)lpbi,wUsage);
  813.         else
  814.             SetDIBits(hdc,hbm,0,dy,
  815.                (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  816.                (LPBITMAPINFO)lpbi,wUsage);
  817.     }
  818.  
  819. #else
  820.     hbm = CreateDIBitmap(hdc,
  821.                 (LPBITMAPINFOHEADER)lpbi,
  822.                 (LONG)CBM_INIT,
  823.                 (LPSTR)lpbi + (int)lpbi->biSize + PaletteSize(lpbi),
  824.                 (LPBITMAPINFO)lpbi,
  825.                 wUsage );
  826. #endif
  827.  
  828.     if (hpal && hpalT)
  829.         SelectPalette(hdc,hpalT,FALSE);
  830.  
  831. //  DeleteDC(hdc);
  832.     ReleaseDC(NULL,hdc);
  833.  
  834.     GUnlock(hdib);
  835.     return hbm;
  836. }
  837.  
  838. /*
  839.  *  DibFromDib()
  840.  *
  841.  *  Will convert a DIB in 1 format to a DIB in the specifed format
  842.  *
  843.  */
  844. HANDLE DibFromDib(HANDLE hdib, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  845. {
  846.     BITMAPINFOHEADER bi;
  847.     HBITMAP     hbm;
  848.     BOOL        fKillPalette=FALSE;
  849.  
  850.     if (!hdib)
  851.         return NULL;
  852.  
  853.     DibInfo(hdib,&bi);
  854.  
  855.     /*
  856.      *  do we have the requested format already?
  857.      */
  858.     if (bi.biCompression == biStyle && bi.biBitCount == biBits)
  859.         return hdib;
  860.  
  861.     if (hpal == NULL)
  862.     {
  863.         hpal = CreateDibPalette(hdib);
  864.         fKillPalette++;
  865.     }
  866.  
  867.     hbm = BitmapFromDib(hdib,hpal,wUsage);
  868.  
  869.     if (hbm == NULL)
  870.     {
  871.         hdib = NULL;
  872.     }
  873.     else
  874.     {
  875.         hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
  876.         DeleteObject(hbm);
  877.     }
  878.  
  879.     if (fKillPalette && hpal)
  880.         DeleteObject(hpal);
  881.  
  882.     return hdib;
  883. }
  884.  
  885. /*
  886.  *  CreateLogicalDib
  887.  *
  888.  *  Given a DDB and a HPALETTE create a "logical" DIB
  889.  *
  890.  *  if the HBITMAP is NULL create a DIB from the system "stock" bitmap
  891.  *      This is used to save a logical palette to a disk file as a DIB
  892.  *
  893.  *  if the HPALETTE is NULL use the system "stock" palette (ie the
  894.  *      system palette)
  895.  *
  896.  *  a "logical" DIB is a DIB where the DIB color table *exactly* matches
  897.  *  the passed logical palette.  There will be no system colors in the DIB
  898.  *  block, and a pixel value of <n> in the DIB will correspond to logical
  899.  *  palette index <n>.
  900.  *
  901.  *  This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
  902.  *  option then converting the palindexes returned in the color table
  903.  *  from palette indexes to logical RGB values.  The entire passed logical
  904.  *  palette is always copied to the DIB color table.
  905.  *
  906.  *  The DIB color table will have exactly the same number of entries as
  907.  *  the logical palette.  Normaly GetDIBits() will always set biClrUsed to
  908.  *  the maximum colors supported by the device regardless of the number of
  909.  *  colors in the logical palette
  910.  *
  911.  *  Why would you want to do this?  The major reason for a "logical" DIB
  912.  *  is so when the DIB is written to a disk file then reloaded the logical
  913.  *  palette created from the DIB color table will be the same as one used
  914.  *  originaly to create the bitmap.  It also will prevent GDI from doing
  915.  *  nearest color matching on PC_RESERVED palettes.
  916.  *
  917.  *  ** What do we do if the logical palette has more than 256 entries!!!!!
  918.  *  ** GetDIBits() may return logical palette index's that are greater than
  919.  *  ** 256, we cant represent these colors in the "logical" DIB
  920.  *  **
  921.  *  ** for now hose the caller?????
  922.  *
  923.  */
  924.  
  925. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
  926. {
  927.     BITMAP              bm;
  928.     BITMAPINFOHEADER    bi;
  929.     LPBITMAPINFOHEADER  lpDib;      // pointer to DIB
  930.     LPBITMAPINFOHEADER  lpbi;       // temp pointer to BITMAPINFO
  931.     DWORD               dwLen;
  932.     DWORD               dw;
  933.     int                 n;
  934.     int                 nColors;
  935.     HANDLE              hdib;
  936.     HDC                 hdc;
  937.     BYTE FAR *          lpBits;
  938.     WORD FAR *          lpCT;
  939.     RGBQUAD FAR *       lpRgb;
  940.     PALETTEENTRY        peT;
  941.     HPALETTE            hpalT;
  942.  
  943.     if (hpal == NULL)
  944.         hpal = GetStockObject(DEFAULT_PALETTE);
  945.  
  946.     if (hbm == NULL)
  947.         hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
  948.  
  949.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  950.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  951.  
  952.     if (biBits == 0)
  953.         biBits = nColors > 16 ? 8 : 4;
  954.  
  955.     if (nColors > 256)      // ACK!
  956.         ;                   // How do we handle this????
  957.  
  958.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  959.     bi.biWidth              = bm.bmWidth;
  960.     bi.biHeight             = bm.bmHeight;
  961.     bi.biPlanes             = 1;
  962.     bi.biBitCount           = biBits;
  963.     bi.biCompression        = BI_RGB;
  964.     bi.biSizeImage          = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  965.     bi.biXPelsPerMeter      = 0;
  966.     bi.biYPelsPerMeter      = 0;
  967.     bi.biClrUsed            = nColors;
  968.     bi.biClrImportant       = 0;
  969.  
  970.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  971.  
  972.     hdib = GAlloc(dwLen);
  973.  
  974.     if (!hdib)
  975.         return NULL;
  976.  
  977.     lpbi = GAllocPtr(bi.biSize + 256 * sizeof(RGBQUAD));
  978.  
  979.     if (!lpbi)
  980.     {
  981.         GFree(hdib);
  982.         return NULL;
  983.     }
  984.  
  985.     hdc = GetDC(NULL);
  986.     hpalT = SelectPalette(hdc,hpal,FALSE);
  987.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  988.  
  989.     lpDib = GLock(hdib);
  990.  
  991.     *lpbi  = bi;
  992.     *lpDib = bi;
  993.     lpCT   = (WORD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  994.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpDib + (WORD)lpDib->biSize);
  995.     lpBits = (LPSTR)lpDib + (WORD)lpDib->biSize + PaletteSize(lpDib);
  996.  
  997.     /*
  998.      *  call GetDIBits to get the DIB bits and fill the color table with
  999.      *  logical palette index's
  1000.      */
  1001.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  1002.         lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
  1003.  
  1004.     /*
  1005.      *  Now convert the DIB bits into "real" logical palette index's
  1006.      *
  1007.      *  lpCT        points to the DIB color table wich is a WORD array of
  1008.      *              logical palette index's
  1009.      *
  1010.      *  lpBits      points to the DIB bits, each DIB pixel is a index into
  1011.      *              the DIB color table.
  1012.      *
  1013.      */
  1014.  
  1015.     if (biBits == 8)
  1016.     {
  1017.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  1018.             *lpBits = (BYTE)lpCT[*lpBits];
  1019.     }
  1020.     else // biBits == 4
  1021.     {
  1022.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  1023.             *lpBits = lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4);
  1024.     }
  1025.  
  1026.     /*
  1027.      *  Now copy the RGBs in the logical palette to the dib color table
  1028.      */
  1029.     for (n=0; n<nColors; n++,lpRgb++)
  1030.     {
  1031.         GetPaletteEntries(hpal,n,1,&peT);
  1032.  
  1033.         lpRgb->rgbRed      = peT.peRed;
  1034.         lpRgb->rgbGreen    = peT.peGreen;
  1035.         lpRgb->rgbBlue     = peT.peBlue;
  1036.         lpRgb->rgbReserved = (BYTE)0;
  1037.     }
  1038.  
  1039.     GUnlock(hdib);
  1040.     GFreePtr(lpbi);
  1041.  
  1042.     SelectPalette(hdc,hpalT,FALSE);
  1043.     ReleaseDC(NULL,hdc);
  1044.  
  1045.     return hdib;
  1046. }
  1047.  
  1048. void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1049. {
  1050.     DWORD dw;
  1051.  
  1052.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  1053.         *pb = xlat[*pb];
  1054. }
  1055.  
  1056. void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1057. {
  1058.     DWORD dw;
  1059.  
  1060.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  1061.         *pb = xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4);
  1062. }
  1063.  
  1064. #define RLE_ESCAPE  0
  1065. #define RLE_EOL     0
  1066. #define RLE_EOF     1
  1067. #define RLE_JMP     2
  1068.  
  1069. void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1070. {
  1071.     BYTE    cnt;
  1072.     BYTE    b;
  1073.     BYTE huge *prle = pb;
  1074.  
  1075.     for(;;)
  1076.     {
  1077.         cnt = *prle++;
  1078.         b   = *prle;
  1079.  
  1080.         if (cnt == RLE_ESCAPE)
  1081.         {
  1082.             prle++;
  1083.  
  1084.             switch (b)
  1085.             {
  1086.                 case RLE_EOF:
  1087.                     return;
  1088.  
  1089.                 case RLE_EOL:
  1090.                     break;
  1091.  
  1092.                 case RLE_JMP:
  1093.                     prle++;     // skip dX
  1094.                     prle++;     // skip dY
  1095.                     break;
  1096.  
  1097.                 default:
  1098.                     cnt = b;
  1099.                     for (b=0; b<cnt; b++,prle++)
  1100.                         *prle = xlat[*prle];
  1101.  
  1102.                     if (cnt & 1)
  1103.                         prle++;
  1104.  
  1105.                     break;
  1106.             }
  1107.         }
  1108.         else
  1109.         {
  1110.             *prle++ = xlat[b];
  1111.         }
  1112.     }
  1113. }
  1114.  
  1115. void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1116. {
  1117. }
  1118.  
  1119. //
  1120. // MapDib - map the given DIB so it matches the specifed palette
  1121. //
  1122. BOOL MapDib(HANDLE hdib, HPALETTE hpal)
  1123. {
  1124.     LPBITMAPINFOHEADER  lpbi;
  1125.     PALETTEENTRY        pe;
  1126.     int                 n;
  1127.     int                 nDibColors;
  1128.     int                 nPalColors;
  1129.     BYTE FAR *          lpBits;
  1130.     WORD FAR *          lpCT;
  1131.     RGBQUAD FAR *       lpRgb;
  1132.     BYTE                xlat[256];
  1133.     DWORD               dw;
  1134.     DWORD               dwSize;
  1135.  
  1136.     if (!hpal || !hdib)
  1137.         return FALSE;
  1138.  
  1139.     lpbi   = GLock(hdib);
  1140.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1141.     lpBits = DibXY(lpbi,0,0);
  1142.  
  1143.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  1144.     nDibColors = DibNumColors(lpbi);
  1145.  
  1146.     if (nPalColors > nDibColors)
  1147.     {
  1148.         //
  1149.         // This is bad, we need to grow the dib!  punt for now
  1150.         //
  1151.         nPalColors = nDibColors;
  1152.     }
  1153.  
  1154.     //
  1155.     //  build a xlat table. from the current DIB colors to the given
  1156.     //  palette.
  1157.     //
  1158.     for (n=0; n<nDibColors; n++)
  1159.         xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  1160.  
  1161.     //
  1162.     // translate the DIB bits
  1163.     //
  1164.     if ((dwSize = lpbi->biSizeImage) == 0)
  1165.         dwSize = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  1166.  
  1167.     switch ((WORD)lpbi->biCompression)
  1168.     {
  1169.         case BI_RLE8:
  1170.             xlatRle8(lpBits, dwSize, xlat);
  1171.             break;
  1172.  
  1173.         case BI_RLE4:
  1174.             xlatRle4(lpBits, dwSize, xlat);
  1175.             break;
  1176.  
  1177.         case BI_RGB:
  1178.             if (lpbi->biBitCount == 8)
  1179.                 xlatClut8(lpBits, dwSize, xlat);
  1180.             else
  1181.                 xlatClut4(lpBits, dwSize, xlat);
  1182.             break;
  1183.     }
  1184.  
  1185.     //
  1186.     //  Now copy the RGBs in the logical palette to the dib color table
  1187.     //
  1188.     for (n=0; n<nPalColors; n++)
  1189.     {
  1190.         GetPaletteEntries(hpal,n,1,&pe);
  1191.  
  1192.         lpRgb[n].rgbRed      = pe.peRed;
  1193.         lpRgb[n].rgbGreen    = pe.peGreen;
  1194.         lpRgb[n].rgbBlue     = pe.peBlue;
  1195.         lpRgb[n].rgbReserved = (BYTE)0;
  1196.     }
  1197.  
  1198.     for (n=nPalColors; n<nDibColors; n++)
  1199.     {
  1200.         lpRgb[n].rgbRed      = (BYTE)0;
  1201.         lpRgb[n].rgbGreen    = (BYTE)0;
  1202.         lpRgb[n].rgbBlue     = (BYTE)0;
  1203.         lpRgb[n].rgbReserved = (BYTE)0;
  1204.     }
  1205.  
  1206.     GUnlock(hdib);
  1207.     return TRUE;
  1208. }
  1209.  
  1210. /*
  1211.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1212.  *
  1213.  */
  1214. BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
  1215. {
  1216.     HDC hdcBits;
  1217.     BITMAP bm;
  1218.     HPALETTE hpal,hpalT;
  1219.     BOOL f;
  1220.  
  1221.     if (!hdc || !hbm)
  1222.         return FALSE;
  1223.  
  1224.     hpal = SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),FALSE);
  1225.     SelectPalette(hdc,hpal,FALSE);
  1226.  
  1227.     hdcBits = CreateCompatibleDC(hdc);
  1228.     SelectObject(hdcBits,hbm);
  1229.     hpalT = SelectPalette(hdcBits,hpal,FALSE);
  1230.     RealizePalette(hdcBits);
  1231.     f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop);
  1232.     SelectPalette(hdcBits,hpalT,FALSE);
  1233.     DeleteDC(hdcBits);
  1234.  
  1235.     return f;
  1236. }
  1237.  
  1238. /*
  1239.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1240.  *
  1241.  */
  1242. BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
  1243. {
  1244.     HDC hdcBits;
  1245.     BITMAP bm;
  1246.     HPALETTE hpalT;
  1247.     BOOL f;
  1248.  
  1249.     if (!hdc || !hbm)
  1250.         return FALSE;
  1251.  
  1252.     hdcBits = CreateCompatibleDC(hdc);
  1253.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  1254.     SelectObject(hdcBits,hbm);
  1255.     f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  1256.     DeleteDC(hdcBits);
  1257.  
  1258.     return f;
  1259. }
  1260.  
  1261. /*
  1262.  *  Draws HDIB <hdib> at the specifed position in DC <hdc>
  1263.  *
  1264.  */
  1265. BOOL DrawDib(HDC hdc, int x, int y, HANDLE hdib, HPALETTE hpal, WORD wUsage)
  1266. {
  1267.     HPALETTE hpalT;
  1268.  
  1269.     if (hpal)
  1270.     {
  1271.         hpalT = SelectPalette(hdc,hpal,FALSE);
  1272.         RealizePalette(hdc);
  1273.     }
  1274.  
  1275.     DibBlt(hdc,x,y,-1,-1,hdib,0,0,SRCCOPY,wUsage);
  1276.  
  1277.     if (hpal)
  1278.     {
  1279.         SelectPalette(hdc,hpalT,FALSE);
  1280.     }
  1281. }
  1282.  
  1283. /*
  1284.  *  SetDibUsage(hdib,hpal,wUsage)
  1285.  *
  1286.  *  Modifies the color table of the passed DIB for use with the wUsage
  1287.  *  parameter specifed.
  1288.  *
  1289.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  1290.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  1291.  *      in the passed palette
  1292.  *
  1293.  */
  1294. BOOL SetDibUsage(HANDLE hdib, HPALETTE hpal,WORD wUsage)
  1295. {
  1296.     LPBITMAPINFOHEADER lpbi;
  1297.     PALETTEENTRY       ape[MAXPALETTE];
  1298.     RGBQUAD FAR *      pRgb;
  1299.     WORD FAR *         pw;
  1300.     int                nColors;
  1301.     int                n;
  1302.  
  1303.     if (hpal == NULL)
  1304.         hpal = GetStockObject(DEFAULT_PALETTE);
  1305.  
  1306.     if (!hdib)
  1307.         return FALSE;
  1308.  
  1309.     lpbi = GLock(hdib);
  1310.  
  1311.     if (!lpbi)
  1312.         return FALSE;
  1313.  
  1314.     nColors = DibNumColors(lpbi);
  1315.  
  1316.     if (nColors > 0)
  1317.     {
  1318.         pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1319.  
  1320.         switch (wUsage)
  1321.         {
  1322.             //
  1323.             // Set the DIB color table to palette indexes
  1324.             //
  1325.             case DIB_PAL_COLORS:
  1326.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  1327.                     *pw = n;
  1328.                 break;
  1329.  
  1330.             //
  1331.             // Set the DIB color table to RGBQUADS
  1332.             //
  1333.             default:
  1334.             case DIB_RGB_COLORS:
  1335.                 nColors = min(nColors,MAXPALETTE);
  1336.  
  1337.                 GetPaletteEntries(hpal,0,nColors,ape);
  1338.  
  1339.                 for (n=0; n<nColors; n++)
  1340.                 {
  1341.                     pRgb[n].rgbRed      = ape[n].peRed;
  1342.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  1343.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  1344.                     pRgb[n].rgbReserved = 0;
  1345.                 }
  1346.                 break;
  1347.         }
  1348.     }
  1349.     GUnlock(hdib);
  1350.     return TRUE;
  1351. }
  1352.  
  1353. /*
  1354.  *  SetPalFlags(hpal,iIndex, cnt, wFlags)
  1355.  *
  1356.  *  Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
  1357.  *  to the parameter specifed.
  1358.  *
  1359.  */
  1360. BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, WORD wFlags)
  1361. {
  1362.     int     i;
  1363.     BOOL    f;
  1364.     PALETTEENTRY FAR *lppe;
  1365.  
  1366.     if (hpal == NULL)
  1367.         return FALSE;
  1368.  
  1369.     if (cntEntries < 0)
  1370.         GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  1371.  
  1372.     lppe = GAllocPtr((LONG)cntEntries * sizeof(PALETTEENTRY));
  1373.  
  1374.     if (!lppe)
  1375.         return FALSE;
  1376.  
  1377.     GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1378.  
  1379.     for (i=0; i<cntEntries; i++)
  1380.     {
  1381.         lppe[i].peFlags = (BYTE)wFlags;
  1382.     }
  1383.  
  1384.     f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1385.  
  1386.     GFreePtr(lppe);
  1387.     return f;
  1388. }
  1389.  
  1390. /*
  1391.  *  PalEq(hpal1,hpal2)
  1392.  *
  1393.  *  return TRUE if the palette's are the same
  1394.  *
  1395.  */
  1396. BOOL PalEq(HPALETTE hpal1, HPALETTE hpal2)
  1397. {
  1398.     BOOL    f;
  1399.     int     i;
  1400.     int     nPal1,nPal2;
  1401.     PALETTEENTRY FAR *ppe;
  1402.  
  1403.     if (hpal1 == hpal2)
  1404.         return TRUE;
  1405.  
  1406.     if (!hpal1 || !hpal2)
  1407.         return FALSE;
  1408.  
  1409.     GetObject(hpal1,sizeof(int),(LPSTR)&nPal1);
  1410.     GetObject(hpal2,sizeof(int),(LPSTR)&nPal2);
  1411.  
  1412.     if (nPal1 != nPal2)
  1413.         return FALSE;
  1414.  
  1415.     ppe = GAllocPtr(nPal1 * 2 * sizeof(PALETTEENTRY));
  1416.  
  1417.     if (!ppe)
  1418.         return FALSE;
  1419.  
  1420.     GetPaletteEntries(hpal1, 0, nPal1, ppe);
  1421.     GetPaletteEntries(hpal2, 0, nPal2, ppe+nPal1);
  1422.  
  1423.     for (f=TRUE,i=0; f && i<nPal1; i++)
  1424.     {
  1425.         f &= (ppe[i].peRed   == ppe[i+nPal1].peRed   &&
  1426.               ppe[i].peBlue  == ppe[i+nPal1].peBlue  &&
  1427.               ppe[i].peGreen == ppe[i+nPal1].peGreen);
  1428.     }
  1429.  
  1430.     GFreePtr(ppe);
  1431.     return f;
  1432. }
  1433.  
  1434. /*
  1435.  *  StretchDibBlt()
  1436.  *
  1437.  *  draws a bitmap in CF_DIB format, using StretchDIBits()
  1438.  *
  1439.  *  takes the same parameters as StretchBlt()
  1440.  */
  1441. BOOL StretchDibBlt(HDC hdc, int x, int y, int dx, int dy, HANDLE hdib, int x0, int y0, int dx0, int dy0, LONG rop, WORD wUsage)
  1442. {
  1443.     LPBITMAPINFOHEADER lpbi;
  1444.     LPSTR        pBuf;
  1445.     BOOL         f;
  1446.  
  1447.     if (!hdib)
  1448.         return PatBlt(hdc,x,y,dx,dy,rop);
  1449.  
  1450.     if (wUsage == 0)
  1451.         wUsage = DIB_RGB_COLORS;
  1452.  
  1453.     lpbi = GLock(hdib);
  1454.  
  1455.     if (!lpbi)
  1456.         return FALSE;
  1457.  
  1458.     if (dx0 == -1 && dy0 == -1)
  1459.     {
  1460.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1461.         {
  1462.             dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1463.             dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1464.         }
  1465.         else
  1466.         {
  1467.             dx0 = (int)lpbi->biWidth;
  1468.             dy0 = (int)lpbi->biHeight;
  1469.         }
  1470.     }
  1471.  
  1472.     if (dx < 0 && dy < 0)
  1473.     {
  1474.         dx = dx0 * -dx;
  1475.         dy = dy0 * -dy;
  1476.     }
  1477.  
  1478.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1479.  
  1480.     f = StretchDIBits (
  1481.         hdc,
  1482.         x,y,
  1483.         dx,dy,
  1484.         x0,y0,
  1485.         dx0,dy0,
  1486.         pBuf, (LPBITMAPINFO)lpbi,
  1487.         wUsage,
  1488.         rop);
  1489.  
  1490.     GUnlock(hdib);
  1491.     return f;
  1492. }
  1493.  
  1494. /*
  1495.  *  DibBlt()
  1496.  *
  1497.  *  draws a bitmap in CF_DIB format, using SetDIBits to device.
  1498.  *
  1499.  *  takes the same parameters as BitBlt()
  1500.  */
  1501. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, WORD wUsage)
  1502. {
  1503.     LPBITMAPINFOHEADER lpbi;
  1504.     LPSTR       pBuf;
  1505.     BOOL        f;
  1506.  
  1507.     if (!hdib)
  1508.         return PatBlt(hdc,x0,y0,dx,dy,rop);
  1509.  
  1510.     if (wUsage == 0)
  1511.         wUsage = DIB_RGB_COLORS;
  1512.  
  1513.     lpbi = GLock(hdib);
  1514.  
  1515.     if (!lpbi)
  1516.         return FALSE;
  1517.  
  1518.     if (dx == -1 && dy == -1)
  1519.     {
  1520.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1521.         {
  1522.             dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1523.             dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1524.         }
  1525.         else
  1526.         {
  1527.             dx = (int)lpbi->biWidth;
  1528.             dy = (int)lpbi->biHeight;
  1529.         }
  1530.     }
  1531.  
  1532.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1533.  
  1534. #if 0
  1535.     f = SetDIBitsToDevice(hdc, x0, y0, dx, dy,
  1536.         x1,y1,
  1537.         x1,
  1538.         dy,
  1539.         pBuf, (LPBITMAPINFO)lpbi,
  1540.         wUsage );
  1541. #else
  1542.     f = StretchDIBits (
  1543.         hdc,
  1544.         x0,y0,
  1545.         dx,dy,
  1546.         x1,y1,
  1547.         dx,dy,
  1548.         pBuf, (LPBITMAPINFO)lpbi,
  1549.         wUsage,
  1550.         rop);
  1551. #endif
  1552.  
  1553.     GUnlock(hdib);
  1554.     return f;
  1555. }
  1556.  
  1557. LPVOID DibLock(HANDLE hdib,int x, int y)
  1558. {
  1559.     return DibXY((LPBITMAPINFOHEADER)GLock(hdib),x,y);
  1560. }
  1561.  
  1562. VOID DibUnlock(HANDLE hdib)
  1563. {
  1564.     GUnlock(hdib);
  1565. }
  1566.  
  1567. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1568. {
  1569.     BYTE huge *pBits;
  1570.     DWORD ulWidthBytes;
  1571.  
  1572.     pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1573.  
  1574.     ulWidthBytes = DIBWIDTHBYTES(*lpbi);
  1575.  
  1576.     pBits += (ulWidthBytes * (long)y) + (x * (int)lpbi->biBitCount / 8);
  1577.  
  1578.     return (LPVOID)pBits;
  1579. }
  1580.  
  1581. HANDLE CreateDib(int bits, int dx, int dy)
  1582. {
  1583.     HANDLE              hdib;
  1584.     BITMAPINFOHEADER    bi;
  1585.     LPBITMAPINFOHEADER  lpbi;
  1586.     DWORD FAR *         pRgb;
  1587.     int                 i;
  1588.  
  1589.     //
  1590.     // These are the standard VGA colors, we will be stuck with until the
  1591.     // end of time!
  1592.     //
  1593.     static DWORD CosmicColors[16] = {
  1594.          0x00000000        // 0000  black
  1595.         ,0x00800000        // 0001  dark red
  1596.         ,0x00008000        // 0010  dark green
  1597.         ,0x00808000        // 0011  mustard
  1598.         ,0x00000080        // 0100  dark blue
  1599.         ,0x00800080        // 0101  purple
  1600.         ,0x00008080        // 0110  dark turquoise
  1601.         ,0x00C0C0C0        // 1000  gray
  1602.         ,0x00808080        // 0111  dark gray
  1603.         ,0x00FF0000        // 1001  red
  1604.         ,0x0000FF00        // 1010  green
  1605.         ,0x00FFFF00        // 1011  yellow
  1606.         ,0x000000FF        // 1100  blue
  1607.         ,0x00FF00FF        // 1101  pink (magenta)
  1608.         ,0x0000FFFF        // 1110  cyan
  1609.         ,0x00FFFFFF        // 1111  white
  1610.         };
  1611.  
  1612.     if (bits <= 0)
  1613.         bits = 8;
  1614.  
  1615.     bi.biSize           = sizeof(BITMAPINFOHEADER);
  1616.     bi.biPlanes         = 1;
  1617.     bi.biBitCount       = bits;
  1618.     bi.biWidth          = dx;
  1619.     bi.biHeight         = dy;
  1620.     bi.biCompression    = BI_RGB;
  1621.     bi.biSizeImage      = 0;
  1622.     bi.biXPelsPerMeter  = 0;
  1623.     bi.biYPelsPerMeter  = 0;
  1624.     bi.biClrUsed    = 0;
  1625.     bi.biClrImportant   = 0;
  1626.     bi.biClrUsed    = DibNumColors(&bi);
  1627.  
  1628.     hdib = GAllocF(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER)
  1629.         + (long)bi.biClrUsed * sizeof(RGBQUAD)
  1630.         + (long)dy * DIBWIDTHBYTES(bi));
  1631.  
  1632.     if (hdib)
  1633.     {
  1634.         lpbi  = GLock(hdib);
  1635.         *lpbi = bi;
  1636.  
  1637.         pRgb  = (LPVOID)((LPSTR)lpbi + (int)lpbi->biSize);
  1638.  
  1639.         //
  1640.         //  setup the color table
  1641.         //
  1642.         if (bits == 1)
  1643.         {
  1644.             pRgb[0] = CosmicColors[0];
  1645.             pRgb[1] = CosmicColors[15];
  1646.         }
  1647.         else
  1648.         {
  1649.             for (i=0; i<bi.biClrUsed; i++)
  1650.                 pRgb[i] = CosmicColors[i % 16];
  1651.         }
  1652.  
  1653.         GUnlock(hdib);
  1654.     }
  1655.  
  1656.     return hdib;
  1657. }
  1658.  
  1659. HANDLE CopyDib (HANDLE hdib)
  1660. {
  1661.     BYTE huge *ps;
  1662.     BYTE huge *pd;
  1663.     HANDLE h;
  1664.     DWORD cnt;
  1665.  
  1666.     if (h = GAlloc(cnt = GSize(hdib)))
  1667.     {
  1668.         ps = GLock(hdib);
  1669.         pd = GLock(h);
  1670. #if 1
  1671.     hmemcpy(pd,ps,cnt);
  1672. #else
  1673.         while (cnt-- > 0)
  1674.            *pd++ = *ps++;
  1675. #endif
  1676.  
  1677.         GUnlock(hdib);
  1678.         GUnlock(h);
  1679.     }
  1680.     return h;
  1681. }
  1682.  
  1683. /*
  1684.  * Private routines to read/write more than 64k
  1685.  */
  1686.  
  1687. #define MAXREAD (WORD)(32 * 1024)
  1688.  
  1689. DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul)
  1690. {
  1691.     DWORD  ulT = ul;
  1692.     BYTE huge *hp = pv;
  1693.  
  1694.     while (ul > MAXREAD) {
  1695.         if (_lread(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1696.             return 0;
  1697.         ul -= MAXREAD;
  1698.         hp += MAXREAD;
  1699.     }
  1700.     if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1701.         return 0;
  1702.     return ulT;
  1703. }
  1704.  
  1705. DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
  1706. {
  1707.     DWORD  ulT = ul;
  1708.     BYTE huge *hp = pv;
  1709.  
  1710.     while (ul > MAXREAD) {
  1711.         if (_lwrite(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1712.             return 0;
  1713.         ul -= MAXREAD;
  1714.         hp += MAXREAD;
  1715.     }
  1716.     if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1717.         return 0;
  1718.     return ulT;
  1719. }
  1720.