//===============================================================
// vicon.cpp - icon class
//
// Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
//
// This file is part of the V C++ GUI Framework, and is covered
// under the terms of the GNU Library General Public License,
// Version 2. This library has NO WARRANTY. See the source file
// vapp.cxx for more complete information about license terms.
//===============================================================
#include <v/v_defs.h>
#include <v/vos2.h>		// for OS/2 stuff
#include <v/vapp.h>
#include <v/vicon.h>

//=============================>>> vIcon::vIcon <<<=====================
  vIcon::vIcon()
  {
    _hbm = 0;
    _hmsk = 0;
    _currentDC = 0;
    _trColor = 0;
  }

//=============================>>> vIcon::vIcon  <<<=====================
  vIcon::vIcon(unsigned char* ic, int h, int w, int d, IconType it)
  {
    icon = ic; height = h; width = w; depth = d; iType = it;
    _hbm = 0;
    _currentDC = 0;
    _trColor = 0;
  }

//=============================>>> vIcon::~vIcon <<<=====================
  vIcon::~vIcon()
  {
    if (_hbm != 0)
      GpiDeleteBitmap(_hbm);
    if (_hmsk != 0)
      GpiDeleteBitmap(_hmsk);
  }

//=============================>>> vIcon::NeedBMPBytes <<<==================
  int vIcon::NeedBMPBytes() VCONST
  {
    // calculate how many bytes of storage pixel data will take
    // includes allowance for mandatory word boundary alignment of rows
    // note: does not include color map storage

    int needWords = height*((depth*width+31)/32);
    return (needWords * 4);	// convert to bytes
  }

//=============================>>> vIcon::vIconToBMP  <<<=====================
  void vIcon::vIconToBMP(HPS iDC) VCONST
  {
    // We use _currentDC to track whether the current _hbm is valid
    // for the requesting DC.  If it is, we can improve performance
    // by just returning the _hbm without recreating it again.  If it
    // is not the same, we need to destroy the _hbm and recreate it
    // with the appropriate compatible memory PS

    // The inline code for GetIconHBM checks to see if the (iDC/HBM)
    // pair is valid.  If we get this far then the pair must be invalid
    // (or undefined) and thus we need to create a new bitmap.

    if (_currentDC != 0)
    {
      GpiDeleteBitmap(_hbm);

      if (_hmsk != 0)
      {
        GpiDeleteBitmap(_hmsk);
        _trColor = 0;
      }
    }

    _currentDC = iDC;

    // bitmap data structures
    PVBYTE vbytes = (PVBYTE) icon;
    PVBYTE bmbits;
    PBITMAPINFO2 pbmi;
    LONG trIndex;
    HDC DevCxtComp, DevCxtMem;
    HPS hdcMem;

    // build a memory PS compatible with calling PS
    DevCxtComp = GpiQueryDevice(iDC);
    DevCxtMem = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, DevCxtComp);
    SIZEL size = {width, height};
    hdcMem = GpiCreatePS (theApp->AppHab(), DevCxtMem, &size,
                          PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );

    // set the PS to RGB mode
    GpiCreateLogColorTable(hdcMem, 0L, LCOLF_RGB, 0L, 0L, NULL);

    // First, create a blank bitmap compatible with the
    // current context that is size of bitmap.
    BITMAPINFOHEADER2 bmih;
    memset(&bmih, 0, sizeof(BITMAPINFOHEADER2));
    bmih.cbFix = sizeof(BITMAPINFOHEADER2);
    bmih.cx = width;
    bmih.cy = height;
    bmih.ulColorEncoding = BCE_RGB;
    bmih.cPlanes = 1;         // always 1 for OS/2
    bmih.cBitCount = depth;   // bits of color per pixel

    _hbm = GpiCreateBitmap(hdcMem, &bmih, 0L, NULL, NULL);

    // now we need to load the bitmap with data by associating
    // with a memory PS and setting each pel
    GpiSetBitmap(hdcMem, _hbm);

    // now we need to load the bitmap with data
    if (depth == 8)		// 8 bit icons
    {
      // 8 bit vicon structure:
      // header:     [n][rgb0][rgb1][...][rgbn]
      // pixel data: [p1][p2][...][phxw]

      // we first need to create the bitmapinfo structure and
      // color table
      // get the total number of entries in color table
      unsigned int numColors = (unsigned int) *vbytes++ + 1;

      // allocate space for header and color table
      LONG colorTableSize = numColors*sizeof(RGB2);
      pbmi = (PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = NeedBMPBytes();
      pbmi->cclrUsed = numColors ;

      // create the color table
      PRGB2 ColorEntry = pbmi->argbColor;
      for (unsigned int ix = 0 ; ix < numColors ; ++ix) // map the colors
      {
        ColorEntry->bRed = *vbytes++;
        ColorEntry->bGreen = *vbytes++;
        ColorEntry->bBlue = *vbytes++;
        ColorEntry->fcOptions = 0;
        ColorEntry++;
      }

      // Colors mapped, vbytes now points to beginning of data
      // The lower left hand pixel of the bitmap is reserved for the
      // transparent color. Any pixel in the bitmap which matches that
      // lower left hand pixel will be transparent (for Transparent icons)
      if (iType == Transparent)
      {
        trIndex = vbytes[ ( height - 1 ) * width ];
        RGB2 trColor = pbmi->argbColor[ trIndex ];
        _trColor = SETRGB(trColor.bRed, trColor.bGreen, trColor.bBlue);
      }

      // allocate space for bitmap data
      bmbits = new VBYTE[NeedBMPBytes()];

      // Now need to copy pixel data over from V icon format
      // The V format is essentially based on the X way of
      // defining a bitmap.  To fix it up, we need to
      // pad rows to even words.
      //
      // Although OS/2 row order is upsidedown in OS/2 compared
      // to X, since we invert the DC using the model space transform
      // it all works out in the end.

      int rowwords = (width+3) / 4;     // number of words (for OS/2 bitmap data)
//      PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
      PVBYTE to = bmbits;                           // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        int col;
        for (col = 0 ; col < width ; ++col)   // do each V byte per row
        {
          *to++ = *vbytes++;
        }
        // Finished a row, need to pad to a word boundary
        while (col < 4*rowwords)
        {
          *to++ = 0x00;           // pad with 0's
          col++;
        }
        // now jump back to the row previous to the row just written
        // since we are writing rows from back to front
//      to -= rowwords*8;
      }
    }
    else if (depth > 8)		// 24 bit icons
    {
      // We first need to create the bitmapinfo structure
      // (a color table is not needed for 24 bit bitmaps)
      // allocate space for header
      pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = width*height*4;   // image size (bytes)
      pbmi->cclrUsed = 0 ;              // no color table needed

      // vbytes points to beginning of data
      // The lower left hand pixel of the bitmap is reserved for the
      // transparent color. Any pixel in the bitmap which matches that
      // lower left hand pixel will be transparent (for Transparent icons)
      if (iType == Transparent)
      {
        _trColor = SETRGB( vbytes[ ( height - 1 ) * width * 3 ],
                           vbytes[ ( height - 1 ) * width * 3 + 1],
                           vbytes[ ( height - 1 ) * width * 3 + 2] );
printf("_trcolor= %x (%u) \n", _trColor, _trColor);
      }

      // Now need to copy pixel data over from V icon format
      // The V format is essentially based on the X way of
      // defining a bitmap. To fix it up, we need to
      // swap row order in the data.
      VBYTE R, G, B;
      bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
      int rowwords = ((width*3)+3) / 4;   // number of words (for OS/2 bitmap data)
//    PVBYTE to = bmbits + (height-1)*rowwords*4;  // set to last row of pixel data
      PVBYTE to = bmbits;                          // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        int col;
        for (col = 0 ; col < width ; ++col)   // do each V pixel per row
        {
          // R G B
          // careful with the order here!
          R = *vbytes++; G = *vbytes++; B = *vbytes++;
          *to++ = B; *to++ = G; *to++ = R;
        }
        // Finished a row, need to pad to a word boundary
        while ( (col*3)<(4*rowwords) )
        {
          *to++ = 0x00;           // pad with 0's
          col++;
        }
        // now jump back to the row previous to the row just written
        // since we are writing rows from back to front
//      to -= rowwords*8;
      }
    }
    else
    {
      // We will use depth == 1 as the default case since if the
      // depth isn't legal, we will at least get some kind of picture
      // of the right size.

      // We first need to create the bitmapinfo structure and
      // color table

      // allocate space for header and color table
      LONG colorTableSize=(1<<depth)*sizeof(RGB2);
      pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = NeedBMPBytes();
      pbmi->cclrUsed = 1<<depth ;

      // create the color table
      // for monochrome bitmaps the color choice here
      // will affect which bits become foreground and which
      // are background color in the target canvas.  We choose
      // colors here that will map (1) bits to the foreground
      // color in the target (the expected result)
      PLONG colorTableEntry = (PLONG) pbmi->argbColor;
      *colorTableEntry++ = SETRGB2(0,0,0,0);
      *colorTableEntry = SETRGB2(0,255,255,255);

      static VBYTE Xmask[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
      static VBYTE Wmask[] = {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
      bmbits = new VBYTE[NeedBMPBytes()];	// allocate space

      // Now need to copy pixel data over from V icon format
      // The V format is essentially based on the X way of
      // defining a bitmap which is completely orthogonal to
      // the OS/2 way.  To fix it up, we need to swap byte bit order
      // pad rows to even words, and swap row order in the data, yuck!

      int rowbytes = (width+7) / 8;        // number of bytes (for V icon data)
      int rowwords = (rowbytes+3) / 4;     // number of words (for OS/2 bitmap data)
//    PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
      PVBYTE to = bmbits;                           // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        int col;
        for (col = 0 ; col < rowbytes ; ++col)   // do each V byte per row
        {
          VBYTE X = *vbytes++;            // source V-icon byte
          VBYTE W = 0;                  // target OS/2 byte
          for (int ix = 0 ; ix < 8 ; ++ix) // reverse bits
          {
            if (X & Xmask[ix])   // is there a better way to do this?
              W |= Wmask[ix];
          }
	  *to++ = W;             // save the pixel data in the row
	}
	// Finished a row, need to pad to a word boundary
	while (col < 4*rowwords)
	{
	  *to++ = 0x00;           // pad with 0's
	  col++;
	}
	// now jump back to the row previous to the row just written
	// since we are writing rows from back to front
//	to -= rowwords*8;
      }
    }

    // Now, create the bitmap
    GpiSetBitmapBits(hdcMem, 0L, pbmi->cy, (PBYTE) bmbits, pbmi);
    // free up resources and we are done
    delete [] bmbits;
    delete [] pbmi;

    GpiSetBitmap (hdcMem, NULLHANDLE);
    GpiAssociate (hdcMem, NULLHANDLE);
    GpiDestroyPS (hdcMem);
    DevCloseDC (DevCxtMem);
  }


//=============================>>> vIcon::vIconToDLG  <<<=====================
  HBITMAP vIcon::GetIconDLG(CmdType ct, LONG bgColor)
  // this code is similar to vIconToBMP except it inverts the
  // bitmap image (right-side-up) for use in dialogs
  {
    if (_hDlgbm != 0 && ct != C_Icon)
      return(_hDlgbm);

    // bitmap data structures
    PVBYTE vbytes = (PVBYTE) icon;
    PVBYTE bmbits;
    PBITMAPINFO2 pbmi;
    LONG trIndex;
    HDC DevCxtMem, DevCxtMsk;
    HPS hdcMem, hdcMsk;

    // build a memory PS compatible with calling PS
    // using NULLHANDLE for compatible-device-context forces compatibility with screen
    // which is okay since this is only for dialogs
    DevCxtMem = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
    SIZEL size = {width, height};
    hdcMem = GpiCreatePS (theApp->AppHab(), DevCxtMem, &size,
                          PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );

    // set the PS to RGB mode
    GpiCreateLogColorTable(hdcMem, 0L, LCOLF_RGB, 0L, 0L, NULL);

    // First, create a blank bitmap compatible with the
    // current context that is size of bitmap.
    BITMAPINFOHEADER2 bmih;
    memset(&bmih, 0, sizeof(BITMAPINFOHEADER2));
    bmih.cbFix = sizeof(BITMAPINFOHEADER2);
    bmih.cx = width;
    bmih.cy = height;
    bmih.ulColorEncoding = BCE_RGB;
    bmih.cPlanes = 1;         // always 1 for OS/2
    if (depth == 1)
      bmih.cBitCount = 4;   // we treat monochromes as 4 bit due to OS/2 bug
    else
      bmih.cBitCount = depth;   // bits of color per pixel

    _hDlgbm = GpiCreateBitmap(hdcMem, &bmih, 0L, NULL, NULL);

    // now we need to load the bitmap with data by associating
    // with a memory PS and setting each pel
    GpiSetBitmap(hdcMem, _hDlgbm);

    // For Transparent icons,
    // create second 24bit bitmap with same dimensions for the transparent version
    if (iType == Transparent)
    {
      // build a memory PS compatible with calling PS

      DevCxtMsk = DevOpenDC(theApp->AppHab(), OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
      SIZEL size = {width, height};
      hdcMsk = GpiCreatePS (theApp->AppHab(), DevCxtMsk, &size,
                            PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC );

      // switch to RGB color mode
//      GpiCreateLogColorTable(hdcMsk, 0L, LCOLF_RGB, 0L, 0L, NULL);

      BITMAPINFOHEADER2 mskBmih;
      memset(&mskBmih, 0, sizeof(BITMAPINFOHEADER2));
      mskBmih.cbFix = sizeof(BITMAPINFOHEADER2);
      mskBmih.cx = width;
      mskBmih.cy = height;
      mskBmih.ulColorEncoding = BCE_RGB;
      mskBmih.cPlanes = 1;      // always 1 for OS/2
      mskBmih.cBitCount = 24;   // transparent icons are 24 bit
      mskBmih.cbImage = width*height*4;   // image size (bytes)
      mskBmih.cclrUsed = 0 ;              // no color table needed

      _hDlgmsk = GpiCreateBitmap(hdcMsk, &mskBmih, 0L, NULL, NULL);

      // now we need to load the bitmap with data by associating
      // with a memory PS and setting each pel
      GpiSetBitmap(hdcMsk, _hDlgmsk);
    }

    if (depth == 8)		// 8 bit icons
    {
      // 8 bit vicon structure:
      // header:     [n][rgb0][rgb1][...][rgbn]
      // pixel data: [p1][p2][...][phxw]

      // we first need to create the bitmapinfo structure and
      // color table
      // get the total number of entries in color table
      unsigned int numColors = (unsigned int) *vbytes++ + 1;

      // allocate space for header and color table
      LONG colorTableSize = numColors*sizeof(RGB2);
      pbmi = (PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = NeedBMPBytes();
      pbmi->cclrUsed = numColors ;

      // create the color table
      PRGB2 ColorEntry = pbmi->argbColor;
      for (unsigned int ix = 0 ; ix < numColors ; ++ix) // map the colors
      {
        ColorEntry->bRed = *vbytes++;
        ColorEntry->bGreen = *vbytes++;
        ColorEntry->bBlue = *vbytes++;
        ColorEntry->fcOptions = 0;
        ColorEntry++;
      }

      // Colors mapped, vbytes now points to beginning of data
      // The lower left hand pixel of the bitmap is reserved for the
      // transparent color. Any pixel in the bitmap which matches that
      // lower left hand pixel will be transparent (for Transparent icons)
      if (iType == Transparent)
      {
        trIndex = vbytes[ ( height - 1 ) * width ];
        RGB2 trColor = pbmi->argbColor[ trIndex ];
        _trColor = SETRGB(trColor.bRed, trColor.bGreen, trColor.bBlue);
      }

      bmbits = new VBYTE[NeedBMPBytes()];	// allocate space

      // Now need to copy pixel data over from V icon format
      // The V format is essentially based on the X way of
      // defining a bitmap.  To fix it up, we need to
      // pad rows to even words.
      // Although OS/2 row order is upsidedown in OS/2 compared
      // to X, since we invert the DC using the model space transform
      // it all works out in the end.

      int rowwords = (width+3) / 4;     // number of words (for OS/2 bitmap data)
      PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
//      PVBYTE to = bmbits;                           // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        int col;
        for (col = 0 ; col < width ; ++col)   // do each V byte per row
        {
          *to++ = *vbytes++;
        }
        // Finished a row, need to pad to a word boundary
        while (col < 4*rowwords)
        {
          *to++ = 0x00;           // pad with 0's
          col++;
        }
        // now jump back to the row previous to the row just written
        // since we are writing rows from back to front
        to -= rowwords*8;
      }
    }
    else if (depth > 8)		// 24 bit icons
    {

      // We first need to create the bitmapinfo structure
      // (a color table is not needed for 24 bit bitmaps)
      // allocate space for header
      pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = width*height*4;   // image size (bytes)
      pbmi->cclrUsed = 0 ;              // no color table needed

      // vbytes points to beginning of data
      // The lower left hand pixel of the bitmap is reserved for the
      // transparent color. Any pixel in the bitmap which matches that
      // lower left hand pixel will be transparent (for Transparent icons)
      if (iType == Transparent)
      {
	_trColor = SETRGB( vbytes[ ( height - 1 ) * width * 3 ],
		 	  vbytes[ ( height - 1 ) * width * 3 + 1],
			  vbytes[ ( height - 1 ) * width * 3 + 2] );
      }

      // Now need to copy pixel data over from V icon format
      // The V format is essentially based on the X way of
      // defining a bitmap. To fix it up, we need to
      // swap row order in the data.
      VBYTE R, G, B;
      bmbits = new VBYTE[NeedBMPBytes()];    // allocate space
      int rowwords = ((width*3)+3) / 4;   // number of words (for OS/2 bitmap data)
      PVBYTE to = bmbits + (height-1)*rowwords*4;  // set to last row of pixel data
//      PVBYTE to = bmbits;                          // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        int col;
        for (col = 0 ; col < width ; ++col)   // do each V pixel per row
        {
          // R G B
          // careful with the order here!
          R = *vbytes++; G = *vbytes++; B = *vbytes++;
          *to++ = B; *to++ = G; *to++ = R;
        }
        // Finished a row, need to pad to a word boundary
        while ( (col*3)<(4*rowwords) )
        {
          *to++ = 0x00;           // pad with 0's
          col++;
        }
        // now jump back to the row previous to the row just written
        // since we are writing rows from back to front
        to -= rowwords*8;
      }
    }
    else
    {
      // we really want a monochrome bitmap here, but the dialog
      // routines do not handle monochrome bitmaps properly (the
      // colors are off).  We will convert the monochrome bitmaps
      // to a 4 bit bitmap but only use 2 colors (ie. monochrome)
      LONG orgDepth = depth;
      depth = 4;    // temporary color depth

      // We first need to create the bitmapinfo structure and
      // color table

      // allocate space for header and color table
      ULONG numColors = 2;
      LONG colorTableSize=numColors * sizeof(RGB2);
      pbmi=(PBITMAPINFO2) new VBYTE [sizeof(BITMAPINFOHEADER2)+colorTableSize];

      // copy the header to the bitmap info structure
      memcpy(pbmi, &bmih, sizeof(BITMAPINFOHEADER2));
      pbmi->cbImage = NeedBMPBytes();
      pbmi->cclrUsed = numColors;

      // create the color table
      // for monochrome bitmaps the color choice here
      // will affect which bits become foreground and which
      // are background color in the target canvas.  We choose
      // colors here that will map (1) bits to the foreground
      // color in the target (the expected result)
      PLONG colorTableEntry = (PLONG) pbmi->argbColor;
      *colorTableEntry++ = WinQuerySysColor(HWND_DESKTOP, SYSCLR_BUTTONMIDDLE, 0L);
      *colorTableEntry = WinQuerySysColor(HWND_DESKTOP, SYSCLR_MENUTEXT, 0L);

      static VBYTE Xmask[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
      static VBYTE Wmask[] = {0x10,0x01,0x10,0x01,0x10,0x01,0x10,0x01};

      // Now need to copy pixel data over from V icon format.
      // Every byte in the original V monochrome icon data will
      // map exactly to one word (4 bytes) in the OS/2 bitmap data

      int rowwords = (width+7) / 8;     // number of words per row (OS/2 bitmap data)

      bmbits = new VBYTE[NeedBMPBytes()];	// allocate space

      PVBYTE to = bmbits + (height-1)*rowwords*4;   // set to last row of pixel data
//      PVBYTE to = bmbits;                           // set to first row of pixel data

      for (int row = 0 ; row < height ; ++row)        // copy by row
      {
        for (int col = 0 ; col < rowwords ; col++)   // do each OS/2 word per row
        {
          VBYTE X = *vbytes++;            // source V-icon byte
          for (int ix = 0 ; ix < 8 ; ++ix)
          {
            VBYTE W = 0;                  // target OS/2 byte
            if (X & Xmask[ix])
              W |= Wmask[ix];
	    ix++;
	    if (X & Xmask[ix])
	      W |= Wmask[ix];
	    *to++ = W;             // save the pixel data in the row
          }
        }
	// now jump back to the row previous to the row just written
	// since we are writing rows from back to front
	to -= rowwords*8;
      }
      depth = orgDepth;   // set back to original depth
    }

    // Now, create the bitmap
    GpiSetBitmapBits(hdcMem, 0L, pbmi->cy, (PBYTE) bmbits, pbmi);
    // free up resources and we are done
    delete [] bmbits;
    delete [] pbmi;

    GpiSetBitmap (hdcMem, NULLHANDLE);
    GpiAssociate (hdcMem, NULLHANDLE);
    GpiDestroyPS (hdcMem);
    DevCloseDC (DevCxtMem);

    // Create the transparent bitmap if required by
    // setting the PS background to the requested
    // background color for the dialog (bgColor) and copying the
    // icon to the _hDlgmsk bitmap using the BM_SRCTRANSPARENT option
    // on the PS
    if (iType == Transparent)
    {
      // switch to RGB color mode
      GpiCreateLogColorTable(hdcMsk, 0L, LCOLF_RGB, 0L, 0L, NULL);

      // first fill the PS with the desired background color
      RECTL rc = {0,0, width, height};
      WinFillRect(hdcMsk, &rc, bgColor);

      // (Note: Target is in World Coords, and Source is in Device Coords)
      POINTL cPoints[4] = {0,0,                   // lower left targ
			   width-1, height-1,     // upper right targ
			   0, 0,                  // lower left src
			   width, height};        // upper right src

      // set ownership of bitmap to canvas
      HBITMAP hbmr = GpiSetBitmap(hdcMsk, _hDlgbm);
      // now reset the tranparent bitmap
      GpiSetBitmap(hdcMsk, hbmr);

      // for transparent icons, we set the canvas background
      // color to the icon transparent color and then set
      // the background mix mode to BM_SRCTRANSPARENT, OS/2
      // takes care of the rest.

      GpiSetBackColor(hdcMsk, _trColor);
      GpiSetBackMix(hdcMsk,BM_SRCTRANSPARENT);

      // blit the image to the canvas
      GpiWCBitBlt(hdcMsk, _hDlgbm, 4, cPoints, ROP_SRCCOPY, BBO_IGNORE);

      GpiSetBackMix(hdcMsk,BM_DEFAULT);

      GpiSetBitmap (hdcMsk, NULLHANDLE);
      GpiAssociate (hdcMsk, NULLHANDLE);
      GpiDestroyPS (hdcMsk);
      DevCloseDC (DevCxtMsk);
      // destroy the source bitmap, we don't need it anymore

      if (_hDlgbm != 0)
      {
        GpiDeleteBitmap(_hDlgbm);
        _hDlgbm = 0;
      }

      SysDebug2(OS2Dev,"GetIconDLG (transparent) CmdType:%d _hDlgmsk:%x \n", ct, _hDlgmsk)
      return (_hDlgmsk);  // return the transparent version
    }

    SysDebug2(OS2Dev,"GetIconDLG CmdType:%d _hDlgbm:%x \n", ct, _hDlgbm)
    return(_hDlgbm);  // return the normal version
  }

