| /* | 
 |  *  ImageList implementation | 
 |  * | 
 |  *  Copyright 1998 Eric Kohl | 
 |  *            2000 Jason Mawdsley. | 
 |  * | 
 |  *  TODO: | 
 |  *    - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop). | 
 |  *    - Fix ImageList_GetIcon. | 
 |  *    - Fix drag functions. | 
 |  *    - Fix ImageList_Write. | 
 |  *    - Fix ImageList_SetFilter (undocumented). | 
 |  *      BTW does anybody know anything about this function??? | 
 |  *        - It removes 12 Bytes from the stack (3 Parameters). | 
 |  *        - First parameter SHOULD be a HIMAGELIST. | 
 |  *        - Second parameter COULD be an index????? | 
 |  *        - Third parameter.... ????????????????????? | 
 |  * | 
 |  *  Comments: | 
 |  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use | 
 |  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still | 
 |  *      partially implemented, the functions mentioned above will be  | 
 |  *      limited in functionality too. | 
 |  */ | 
 |  | 
 | #include "winerror.h" | 
 | #include "winbase.h" | 
 | #include "wine/obj_base.h" | 
 | #include "wine/obj_storage.h" | 
 | #include "commctrl.h" | 
 | #include "imagelist.h" | 
 | #include "debugtools.h" | 
 |  | 
 | DEFAULT_DEBUG_CHANNEL(imagelist); | 
 |  | 
 |  | 
 | #define _MAX(a,b) (((a)>(b))?(a):(b)) | 
 | #define _MIN(a,b) (((a)>(b))?(b):(a)) | 
 |  | 
 | #define MAX_OVERLAYIMAGE 15 | 
 |  | 
 |  | 
 | /* internal image list data used for Drag & Drop operations */ | 
 |  | 
 | static HIMAGELIST himlInternalDrag = NULL; | 
 | static INT      nInternalDragHotspotX = 0; | 
 | static INT      nInternalDragHotspotY = 0; | 
 |  | 
 | static HWND     hwndInternalDrag = 0; | 
 | static INT      xInternalPos = 0; | 
 | static INT      yInternalPos = 0; | 
 |  | 
 | static HDC      hdcBackBuffer = 0; | 
 | static HBITMAP  hbmBackBuffer = 0; | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalExpandBitmaps [Internal]  | 
 |  * | 
 |  * Expands the bitmaps of an image list by the given number of images. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl        [I] handle to image list | 
 |  *     nImageCount [I] number of images to add | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This function can NOT be used to reduce the number of images. | 
 |  */ | 
 | static VOID | 
 | IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy) | 
 | { | 
 |     HDC     hdcImageList, hdcBitmap; | 
 |     HBITMAP hbmNewBitmap; | 
 |     INT     nNewWidth, nNewCount; | 
 |  | 
 |     if ((himl->cCurImage + nImageCount < himl->cMaxImage) | 
 |         && (himl->cy >= cy)) | 
 | 	return; | 
 |  | 
 |     if (cy == 0) cy = himl->cy; | 
 |     nNewCount = himl->cCurImage + nImageCount + himl->cGrow; | 
 |     nNewWidth = nNewCount * himl->cx; | 
 |  | 
 |     TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount); | 
 |     hdcImageList = CreateCompatibleDC (0); | 
 |     hdcBitmap = CreateCompatibleDC (0); | 
 |  | 
 |     hbmNewBitmap = | 
 |         CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL); | 
 |     if (hbmNewBitmap == 0) | 
 |         ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy); | 
 |  | 
 |     SelectObject (hdcImageList, himl->hbmImage); | 
 |     SelectObject (hdcBitmap, hbmNewBitmap); | 
 |     BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, | 
 |               hdcImageList, 0, 0, SRCCOPY); | 
 |  | 
 |     DeleteObject (himl->hbmImage); | 
 |     himl->hbmImage = hbmNewBitmap; | 
 |  | 
 |     if (himl->hbmMask) { | 
 |         hbmNewBitmap =  | 
 |             CreateBitmap (nNewWidth, cy, 1, 1, NULL); | 
 |  | 
 |         if (hbmNewBitmap == 0) | 
 |             ERR("creating new mask bitmap!\n"); | 
 |  | 
 |         SelectObject (hdcImageList, himl->hbmMask); | 
 |         SelectObject (hdcBitmap, hbmNewBitmap); | 
 |         BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy, | 
 |                   hdcImageList, 0, 0, SRCCOPY); | 
 |         DeleteObject (himl->hbmMask); | 
 |         himl->hbmMask = hbmNewBitmap; | 
 |     } | 
 |  | 
 |     himl->cMaxImage = nNewCount; | 
 |  | 
 |     DeleteDC (hdcImageList); | 
 |     DeleteDC (hdcBitmap); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalDraw [Internal]  | 
 |  * | 
 |  * Draws the image in the ImageList (without the mask) | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  *     cx            [I] the width of the image to display | 
 |  *     cy............[I] the height of the image to display | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This functions is used by ImageList_DrawIndirect, when it is  | 
 |  *     required to draw only the Image (without the mask) to the screen. | 
 |  * | 
 |  *     Blending and Overlays styles are accomplised by another function | 
 |  */ | 
 | static VOID | 
 | IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy) | 
 | { | 
 |     HDC hImageDC; | 
 |     HBITMAP hOldBitmap; | 
 |  | 
 |     hImageDC = CreateCompatibleDC(0); | 
 |     hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage); | 
 |     BitBlt(pimldp->hdcDst,  | 
 |         pimldp->x, pimldp->y, cx, cy, | 
 |         hImageDC,  | 
 |         pimldp->himl->cx * pimldp->i, 0,  | 
 |         SRCCOPY); | 
 |  | 
 |     SelectObject(hImageDC, hOldBitmap); | 
 |     DeleteDC(hImageDC); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalDrawMask [Internal]  | 
 |  * | 
 |  * Draws the image in the ImageList witht the mask | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  *     cx            [I] the width of the image to display | 
 |  *     cy............[I] the height of the image to display | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This functions is used by ImageList_DrawIndirect, when it is  | 
 |  *     required to draw the Image with the mask to the screen. | 
 |  * | 
 |  *     Blending and Overlays styles are accomplised by another function. | 
 |  */ | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalDrawMask [Internal]  | 
 |  * | 
 |  * Draws the image in the ImageList witht the mask | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  *     cx            [I] the width of the image to display | 
 |  *     cy............[I] the height of the image to display | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This functions is used by ImageList_DrawIndirect, when it is  | 
 |  *     required to draw the Image with the mask to the screen. | 
 |  * | 
 |  *     Blending and Overlays styles are accomplised by another function. | 
 |  */ | 
 | static VOID | 
 | IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy) | 
 | { | 
 |     BOOL bUseCustomBackground, bBlendFlag; | 
 |     HBRUSH hBrush, hOldBrush; | 
 |     HDC     hMaskDC, hImageDC; | 
 |     HBITMAP hOldBitmapImage, hOldBitmapMask; | 
 |     HIMAGELIST himlLocal = pimldp->himl; | 
 |     COLORREF oldBkColor, oldFgColor; | 
 |     UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK); | 
 |  | 
 |     /*  | 
 |      * We need a dc and bitmap to draw on that is  | 
 |      * not on the screen. | 
 |      */ | 
 |     HDC hOffScreenDC = 0; | 
 |     HBITMAP hOffScreenBmp = 0; | 
 |  | 
 |     bUseCustomBackground = (himlLocal->clrBk != CLR_NONE); | 
 |     bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25); | 
 |  | 
 |     hImageDC = CreateCompatibleDC(0); | 
 |     hMaskDC = CreateCompatibleDC(0); | 
 |  | 
 |     /* Create a compatible DC. */ | 
 |     hOffScreenDC = CreateCompatibleDC( pimldp->hdcDst ); | 
 |  | 
 |     if ( hOffScreenDC )  | 
 |     { | 
 |         hOffScreenBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy ); | 
 |  | 
 |         if ( hOffScreenBmp )  | 
 |             SelectObject( hOffScreenDC, hOffScreenBmp  ); | 
 |         else | 
 |             goto cleanup; | 
 |     } | 
 |     else | 
 |         goto cleanup; | 
 |  | 
 |     hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage); | 
 |     hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask); | 
 |      | 
 |     /*  | 
 |      * Get a copy of the image for the masking operations.  | 
 |      * We will use the copy, and this dc for all the various | 
 |      * blitting, and then do one final blit to the screen dc. | 
 |      * This should clean up most of the flickering. | 
 |      */ | 
 |     BitBlt( hOffScreenDC, 0, 0, cx, cy, pimldp->hdcDst, pimldp->x,  | 
 |             pimldp->y, SRCCOPY); | 
 |  | 
 |     /*  | 
 |      * Draw the Background for the appropriate Styles | 
 |      */ | 
 |     if( bUseCustomBackground && (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE  | 
 |          || bBlendFlag) ) | 
 |     { | 
 |          | 
 |         hBrush = CreateSolidBrush (himlLocal->clrBk); | 
 |         hOldBrush = SelectObject (pimldp->hdcDst, hBrush); | 
 |          | 
 |         PatBlt( hOffScreenDC, pimldp->x, pimldp->y, cx, cy, PATCOPY ); | 
 |  | 
 |         DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush)); | 
 |     } | 
 |  | 
 |     /*  | 
 |      * Draw Image Transparently over the current background | 
 |      */ | 
 |     if(fStyle == ILD_NORMAL || (fStyle & ILD_TRANSPARENT) ||  | 
 |        ((fStyle & ILD_IMAGE) && bUseCustomBackground) || bBlendFlag)  | 
 |     {   /*  | 
 |          * To obtain a transparent look, background color should be set | 
 |          * to white and foreground color to black when blting the  | 
 |          * monochrome mask.  | 
 |          */ | 
 |          | 
 |         oldBkColor = SetBkColor( hOffScreenDC, RGB( 0xff, 0xff, 0xff ) );  | 
 |         oldFgColor = SetTextColor( hOffScreenDC, RGB( 0, 0, 0 ) ); | 
 |  | 
 |         BitBlt( hOffScreenDC, 0, 0, cx, cy,hMaskDC, himlLocal->cx * pimldp->i, | 
 |                 0, SRCAND ); | 
 |  | 
 |         BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,himlLocal->cx * pimldp->i, | 
 |                 0, SRCPAINT ); | 
 |      | 
 |     } | 
 |      | 
 |     /* | 
 |      * Draw the image when no Background is specified | 
 |      */ | 
 |     else if((fStyle & ILD_IMAGE) && !bUseCustomBackground) | 
 |     { | 
 |         BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,  | 
 |                 himlLocal->cx * pimldp->i, 0, SRCCOPY); | 
 |     } | 
 |     /*  | 
 |      * Draw the mask with or without a background | 
 |      */ | 
 |     else if(fStyle & ILD_MASK) | 
 |     { | 
 |         BitBlt( hOffScreenDC, 0, 0, cx, cy, hMaskDC, himlLocal->cx * pimldp->i, | 
 |                 0, bUseCustomBackground ? SRCCOPY : SRCAND); | 
 |     } | 
 |      | 
 |     /* | 
 |      * Blit the bitmap to the screen now. | 
 |      */ | 
 |     BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, | 
 |             hOffScreenDC, 0, 0, SRCCOPY); | 
 |  | 
 |      | 
 |     SelectObject(hImageDC, hOldBitmapImage); | 
 |     SelectObject(hMaskDC, hOldBitmapMask); | 
 |      | 
 | cleanup: | 
 |      | 
 |     DeleteDC(hImageDC); | 
 |     DeleteDC(hMaskDC); | 
 |      | 
 |     DeleteDC( hOffScreenDC ); | 
 |     DeleteObject( hOffScreenBmp ); | 
 |      | 
 |     return; | 
 | } | 
 |  | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalDrawBlend [Internal]  | 
 |  * | 
 |  * Draws the Blend over the current image  | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  *     cx            [I] the width of the image to display | 
 |  *     cy............[I] the height of the image to display | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This functions is used by ImageList_DrawIndirect, when it is  | 
 |  *     required to add the blend to the current image.   | 
 |  *      | 
 |  */ | 
 | static VOID | 
 | IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy) | 
 | { | 
 |  | 
 |     HDC         hBlendMaskDC,hMaskDC; | 
 |     HBRUSH      hBlendColorBrush, hBlendBrush, hOldBrush; | 
 |     HBITMAP     hBlendMaskBitmap, hOldBitmap; | 
 |     COLORREF    clrBlend, OldTextColor, OldBkColor; | 
 |     HIMAGELIST  himlLocal = pimldp->himl; | 
 |  | 
 |     clrBlend = GetSysColor (COLOR_HIGHLIGHT); | 
 |     if (!(pimldp->rgbFg == CLR_DEFAULT)) | 
 |     { | 
 |         clrBlend = pimldp->rgbFg; | 
 |     } | 
 |     /* Create the blend Mask | 
 |     */ | 
 |     hBlendMaskDC = CreateCompatibleDC(0); | 
 |     hBlendBrush = pimldp->fStyle & ILD_BLEND50 ? | 
 |         himlLocal->hbrBlend50 : himlLocal->hbrBlend25; | 
 |  | 
 |     hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL); | 
 |     hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap); | 
 |  | 
 |     hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush); | 
 |     PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY); | 
 |     SelectObject(hBlendMaskDC, hOldBrush); | 
 |  | 
 |     /* Modify the blend mask if an Image Mask exist | 
 |     */ | 
 |     if(pimldp->himl->hbmMask != 0) | 
 |     { | 
 |         HBITMAP hOldMaskBitmap; | 
 |         hMaskDC = CreateCompatibleDC(0); | 
 |         hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask); | 
 |  | 
 |         BitBlt(hBlendMaskDC, | 
 |             0,0, cx, cy,  | 
 |             hMaskDC, | 
 |             himlLocal->cx * pimldp->i,0, | 
 |             0x220326); /* NOTSRCAND */ | 
 |  | 
 |         BitBlt(hBlendMaskDC, | 
 |             0,0, cx, cy,  | 
 |             hBlendMaskDC, | 
 |             0,0,  | 
 |             NOTSRCCOPY); | 
 |  | 
 |         SelectObject(hMaskDC, hOldMaskBitmap); | 
 |         DeleteDC(hMaskDC); | 
 |  | 
 |     } | 
 |     /* Apply blend to the current image given the BlendMask | 
 |     */ | 
 |     OldTextColor = SetTextColor(pimldp->hdcDst, 0); | 
 |     OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255)); | 
 |     hBlendColorBrush = CreateSolidBrush(clrBlend); | 
 |     hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush); | 
 |  | 
 |     BitBlt (pimldp->hdcDst,  | 
 |         pimldp->x, pimldp->y, cx, cy,  | 
 |         hBlendMaskDC,  | 
 |         0, 0,  | 
 |         0xB8074A); /* PSDPxax */ | 
 |  | 
 |     SelectObject(pimldp->hdcDst, hOldBrush); | 
 |     SetTextColor(pimldp->hdcDst, OldTextColor); | 
 |     SetBkColor(pimldp->hdcDst, OldBkColor); | 
 |     SelectObject(hBlendMaskDC, hOldBitmap); | 
 |     DeleteDC(hBlendMaskDC); | 
 |     DeleteObject(hBlendMaskBitmap); | 
 |     DeleteObject(hBlendColorBrush); | 
 | } | 
 |  | 
 | /************************************************************************* | 
 |  * IMAGELIST_InternalDrawOverlay [Internal]  | 
 |  * | 
 |  * Draws the overlay image  | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  *     cx            [I] the width of the image to display | 
 |  *     cy............[I] the height of the image to display | 
 |  * | 
 |  * RETURNS | 
 |  *     nothing | 
 |  * | 
 |  * NOTES | 
 |  *     This functions is used by ImageList_DrawIndirect, when it is  | 
 |  *     required to draw the overlay | 
 |  * | 
 |  *      | 
 |  */ | 
 | static VOID  | 
 | IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy) | 
 | { | 
 |     INT     nOvlIdx; | 
 |     HDC     hImageDC; | 
 |     HBITMAP hOldBitmap; | 
 |  | 
 |     nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8; | 
 |     if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) | 
 |     { | 
 |         nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1]; | 
 |         if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage)) | 
 |         { | 
 |             hImageDC = CreateCompatibleDC(0); | 
 |             if (pimldp->himl->hbmMask) | 
 |             { | 
 |                 hOldBitmap = (HBITMAP) SelectObject (hImageDC,  | 
 |                     pimldp->himl->hbmMask); | 
 |  | 
 |                 BitBlt (pimldp->hdcDst,  | 
 |                     pimldp->x, pimldp->y, cx, cy, | 
 |                     hImageDC, pimldp->himl->cx * nOvlIdx, 0, | 
 |                     SRCAND); | 
 |  | 
 |                 SelectObject(hImageDC, hOldBitmap); | 
 |             } | 
 |             hOldBitmap = (HBITMAP) SelectObject (hImageDC,  | 
 |                 pimldp->himl->hbmImage); | 
 |  | 
 |             BitBlt (pimldp->hdcDst,  | 
 |                 pimldp->x, pimldp->y, cx, cy,  | 
 |                 hImageDC, | 
 |                 pimldp->himl->cx * nOvlIdx, 0, | 
 |                 SRCPAINT); | 
 |  | 
 |             SelectObject(hImageDC, hOldBitmap); | 
 |             DeleteDC(hImageDC); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Add [COMCTL32.39] | 
 |  * | 
 |  * Add an image or images to an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl     [I] handle to image list | 
 |  *     hbmImage [I] handle to image bitmap | 
 |  *     hbmMask  [I] handle to mask bitmap | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Index of the first new image. | 
 |  *     Failure: -1 | 
 |  */ | 
 |  | 
 | INT WINAPI | 
 | ImageList_Add (HIMAGELIST himl,	HBITMAP hbmImage, HBITMAP hbmMask) | 
 | { | 
 |     HDC     hdcImage, hdcBitmap; | 
 |     INT     nFirstIndex, nImageCount; | 
 |     INT     nStartX; | 
 |     BITMAP  bmp; | 
 |     HBITMAP hOldBitmapImage, hOldBitmap; | 
 |  | 
 |     TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask); | 
 |     if (!himl || !hbmImage) | 
 |         return -1; | 
 |  | 
 |     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp); | 
 |     nImageCount = bmp.bmWidth / himl->cx; | 
 |  | 
 |     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight); | 
 |  | 
 |     nStartX = himl->cCurImage * himl->cx; | 
 |  | 
 |     hdcImage  = CreateCompatibleDC(0); | 
 |     hdcBitmap = CreateCompatibleDC(0); | 
 |  | 
 |     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage); | 
 |     hOldBitmap = SelectObject(hdcBitmap, hbmImage); | 
 |  | 
 |     /* Copy result to the imagelist | 
 |     */ | 
 |     BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight, | 
 |         hdcBitmap, 0, 0, SRCCOPY); | 
 |  | 
 |     if(himl->hbmMask) | 
 |     { | 
 |         HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp; | 
 |  | 
 |         hdcMask   = CreateCompatibleDC (0); | 
 |         hdcTemp   = CreateCompatibleDC(0); | 
 |         hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask); | 
 |         hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask); | 
 |  | 
 |         BitBlt (hdcMask,  | 
 |             nStartX, 0, bmp.bmWidth, bmp.bmHeight, | 
 |             hdcTemp,  | 
 |             0, 0,  | 
 |             SRCCOPY); | 
 |  | 
 |         SelectObject(hdcTemp, hOldBitmapTemp); | 
 |         DeleteDC(hdcTemp); | 
 |  | 
 |         /* Remove the background from the image | 
 |         */ | 
 |         BitBlt (hdcImage,  | 
 |             nStartX, 0, bmp.bmWidth, bmp.bmHeight, | 
 |             hdcMask,  | 
 |             nStartX, 0,  | 
 |             0x220326); /* NOTSRCAND */ | 
 |  | 
 |         SelectObject(hdcMask, hOldBitmapMask); | 
 |         DeleteDC(hdcMask); | 
 |     } | 
 |  | 
 |     SelectObject(hdcImage, hOldBitmapImage); | 
 |     SelectObject(hdcBitmap, hOldBitmap); | 
 |     DeleteDC(hdcImage); | 
 |     DeleteDC(hdcBitmap); | 
 |  | 
 |     nFirstIndex = himl->cCurImage; | 
 |     himl->cCurImage += nImageCount; | 
 |  | 
 |     return nFirstIndex; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_AddIcon [COMCTL32.40] | 
 |  * | 
 |  * Adds an icon to an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl  [I] handle to image list | 
 |  *     hIcon [I] handle to icon | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: index of the new image | 
 |  *     Failure: -1 | 
 |  */ | 
 |  | 
 | INT WINAPI | 
 | ImageList_AddIcon (HIMAGELIST himl, HICON hIcon) | 
 | { | 
 |     return ImageList_ReplaceIcon (himl, -1, hIcon); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_AddMasked [COMCTL32.41]  | 
 |  * | 
 |  * Adds an image or images to an image list and creates a mask from the | 
 |  * specified bitmap using the mask color. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl    [I] handle to image list. | 
 |  *     hBitmap [I] handle to bitmap | 
 |  *     clrMask [I] mask color. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Index of the first new image. | 
 |  *     Failure: -1 | 
 |  */ | 
 |  | 
 | INT WINAPI | 
 | ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask) | 
 | { | 
 |     HDC    hdcImage, hdcMask, hdcBitmap; | 
 |     INT    nIndex, nImageCount, nMaskXOffset=0; | 
 |     BITMAP bmp; | 
 |     HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage; | 
 |     HBITMAP hMaskBitmap=0; | 
 |     COLORREF bkColor; | 
 |  | 
 |     TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask); | 
 |     if (himl == NULL) | 
 |         return -1; | 
 |  | 
 |     if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp)) | 
 |         return -1; | 
 |  | 
 |     nImageCount = bmp.bmWidth / himl->cx; | 
 |  | 
 |     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight); | 
 |  | 
 |     nIndex = himl->cCurImage; | 
 |     himl->cCurImage += nImageCount; | 
 |  | 
 |     hdcMask   = CreateCompatibleDC (0); | 
 |     hdcImage  = CreateCompatibleDC(0); | 
 |     hdcBitmap = CreateCompatibleDC(0); | 
 |  | 
 |  | 
 |     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage); | 
 |     hOldBitmap = SelectObject(hdcBitmap, hBitmap); | 
 |     if(himl->hbmMask) | 
 |     { | 
 |         hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask); | 
 |         nMaskXOffset = nIndex * himl->cx; | 
 |     } | 
 |     else | 
 |     { | 
 |         /* | 
 |             Create a temp Mask so we can remove the background of | 
 |             the Image (Windows does this even if there is no mask) | 
 |         */ | 
 |         hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL); | 
 |         hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap); | 
 |         nMaskXOffset = 0; | 
 |     } | 
 |     /* create monochrome image to the mask bitmap */ | 
 |     bkColor = (clrMask != CLR_DEFAULT) ? clrMask : | 
 |         GetPixel (hdcBitmap, 0, 0); | 
 |     SetBkColor (hdcBitmap, bkColor); | 
 |     BitBlt (hdcMask,  | 
 |         nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight, | 
 |         hdcBitmap, 0, 0,  | 
 |         SRCCOPY); | 
 |  | 
 |     SetBkColor(hdcBitmap, RGB(255,255,255)); | 
 |     /*Remove the background from the image | 
 |     */ | 
 |     /* | 
 |         WINDOWS BUG ALERT!!!!!! | 
 |         The statement below should not be done in common practice | 
 |         but this is how ImageList_AddMasked works in Windows. | 
 |         It overwrites the original bitmap passed, this was discovered | 
 |         by using the same bitmap to itterated the different styles | 
 |         on windows where it failed (BUT ImageList_Add is OK) | 
 |         This is here in case some apps really on this bug | 
 |     */ | 
 |     BitBlt(hdcBitmap,  | 
 |         0, 0, bmp.bmWidth, bmp.bmHeight, | 
 |         hdcMask,  | 
 |         nMaskXOffset, 0,  | 
 |         0x220326); /* NOTSRCAND */ | 
 |     /* Copy result to the imagelist | 
 |     */ | 
 |     BitBlt (hdcImage,  | 
 |         nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight, | 
 |         hdcBitmap,  | 
 |         0, 0,  | 
 |         SRCCOPY); | 
 |     /* Clean up | 
 |     */ | 
 |     SelectObject(hdcMask,hOldBitmapMask); | 
 |     SelectObject(hdcImage, hOldBitmapImage); | 
 |     SelectObject(hdcBitmap, hOldBitmap); | 
 |     DeleteDC(hdcMask); | 
 |     DeleteDC(hdcImage); | 
 |     DeleteDC(hdcBitmap); | 
 |     if(!himl->hbmMask) | 
 |     { | 
 |         DeleteObject(hMaskBitmap); | 
 |     } | 
 |  | 
 |     return nIndex; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_BeginDrag [COMCTL32.42]  | 
 |  * | 
 |  * Creates a temporary image list that contains one image. It will be used | 
 |  * as a drag image. | 
 |  * | 
 |  * PARAMS | 
 |  *     himlTrack [I] handle to the source image list | 
 |  *     iTrack    [I] index of the drag image in the source image list | 
 |  *     dxHotspot [I] X position of the hot spot of the drag image | 
 |  *     dyHotspot [I] Y position of the hot spot of the drag image | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack, | 
 | 	             INT dxHotspot, INT dyHotspot) | 
 | { | 
 |     HDC hdcSrc, hdcDst; | 
 |  | 
 |     FIXME("partially implemented!\n"); | 
 |  | 
 |     if (himlTrack == NULL) | 
 | 	return FALSE; | 
 |  | 
 |     if (himlInternalDrag) | 
 |         ImageList_EndDrag (); | 
 |  | 
 |     himlInternalDrag = | 
 | 	ImageList_Create (himlTrack->cx, himlTrack->cy, | 
 | 			  himlTrack->flags, 1, 1); | 
 |     if (himlInternalDrag == NULL) { | 
 |         ERR("Error creating drag image list!\n"); | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     nInternalDragHotspotX = dxHotspot; | 
 |     nInternalDragHotspotY = dyHotspot; | 
 |  | 
 |     hdcSrc = CreateCompatibleDC (0); | 
 |     hdcDst = CreateCompatibleDC (0); | 
 |  | 
 |     /* copy image */ | 
 |     SelectObject (hdcSrc, himlTrack->hbmImage); | 
 |     SelectObject (hdcDst, himlInternalDrag->hbmImage); | 
 |     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc, | 
 |                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY); | 
 |  | 
 |     /* copy mask */ | 
 |     SelectObject (hdcSrc, himlTrack->hbmMask); | 
 |     SelectObject (hdcDst, himlInternalDrag->hbmMask); | 
 |     StretchBlt (hdcDst, 0, 0, himlInternalDrag->cx, himlInternalDrag->cy, hdcSrc, | 
 |                   iTrack * himlTrack->cx, 0, himlTrack->cx, himlTrack->cy, SRCCOPY); | 
 |  | 
 |     DeleteDC (hdcSrc); | 
 |     DeleteDC (hdcDst); | 
 |  | 
 |     himlInternalDrag->cCurImage = 1; | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Copy [COMCTL32.43]  | 
 |  * | 
 |  *  Copies an image of the source image list to an image of the  | 
 |  *  destination image list. Images can be copied or swapped. | 
 |  * | 
 |  * PARAMS | 
 |  *     himlDst [I] handle to the destination image list | 
 |  *     iDst    [I] destination image index. | 
 |  *     himlSrc [I] handle to the source image list | 
 |  *     iSrc    [I] source image index | 
 |  *     uFlags  [I] flags for the copy operation | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     Copying from one image list to another is possible. The original | 
 |  *     implementation just copies or swapps within one image list. | 
 |  *     Could this feature become a bug??? ;-) | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Copy (HIMAGELIST himlDst, INT iDst,	HIMAGELIST himlSrc, | 
 | 		INT iSrc, INT uFlags) | 
 | { | 
 |     HDC hdcSrc, hdcDst;     | 
 |  | 
 |     TRACE("iDst=%d  iSrc=%d\n", iDst, iSrc); | 
 |  | 
 |     if ((himlSrc == NULL) || (himlDst == NULL)) | 
 | 	return FALSE; | 
 |     if ((iDst < 0) || (iDst >= himlDst->cCurImage)) | 
 | 	return FALSE; | 
 |     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage)) | 
 | 	return FALSE; | 
 |  | 
 |     hdcSrc = CreateCompatibleDC (0); | 
 |     if (himlDst == himlSrc) | 
 |         hdcDst = hdcSrc; | 
 |     else | 
 |         hdcDst = CreateCompatibleDC (0); | 
 |  | 
 |     if (uFlags & ILCF_SWAP) { | 
 |         /* swap */ | 
 |         HBITMAP hbmTempImage, hbmTempMask; | 
 |  | 
 |         /* create temporary bitmaps */ | 
 |         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1, | 
 |                                        himlSrc->uBitsPixel, NULL); | 
 |         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1, | 
 | 				      1, NULL); | 
 |  | 
 |         /* copy (and stretch) destination to temporary bitmaps.(save) */ | 
 |         /* image */ | 
 |         SelectObject (hdcSrc, himlDst->hbmImage); | 
 |         SelectObject (hdcDst, hbmTempImage); | 
 |         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy, | 
 |                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       SRCCOPY); | 
 |         /* mask */ | 
 |         SelectObject (hdcSrc, himlDst->hbmMask); | 
 |         SelectObject (hdcDst, hbmTempMask); | 
 |         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy, | 
 |                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       SRCCOPY); | 
 |  | 
 |         /* copy (and stretch) source to destination */ | 
 |         /* image */ | 
 |         SelectObject (hdcSrc, himlSrc->hbmImage); | 
 |         SelectObject (hdcDst, himlDst->hbmImage); | 
 |         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                       SRCCOPY); | 
 |         /* mask */ | 
 |         SelectObject (hdcSrc, himlSrc->hbmMask); | 
 |         SelectObject (hdcDst, himlDst->hbmMask); | 
 |         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                       SRCCOPY); | 
 |  | 
 |         /* copy (without stretching) temporary bitmaps to source (restore) */ | 
 |         /* image */ | 
 |         SelectObject (hdcSrc, hbmTempImage); | 
 |         SelectObject (hdcDst, himlSrc->hbmImage); | 
 |         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                   hdcSrc, 0, 0, SRCCOPY); | 
 |         /* mask */ | 
 |         SelectObject (hdcSrc, hbmTempMask); | 
 |         SelectObject (hdcDst, himlSrc->hbmMask); | 
 |         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                   hdcSrc, 0, 0, SRCCOPY); | 
 |  | 
 |         /* delete temporary bitmaps */ | 
 |         DeleteObject (hbmTempMask); | 
 |         DeleteObject (hbmTempImage); | 
 |     } | 
 |     else { | 
 |         /* copy image */ | 
 |         SelectObject (hdcSrc, himlSrc->hbmImage); | 
 |         if (himlSrc == himlDst) | 
 |             hdcDst = hdcSrc; | 
 |         else | 
 |             SelectObject (hdcDst, himlDst->hbmImage); | 
 |         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                       SRCCOPY); | 
 |  | 
 |         /* copy mask */ | 
 |         SelectObject (hdcSrc, himlSrc->hbmMask); | 
 |         if (himlSrc == himlDst) | 
 |             hdcDst = hdcSrc; | 
 |         else | 
 |             SelectObject (hdcDst, himlDst->hbmMask); | 
 |         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy, | 
 |                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy, | 
 |                       SRCCOPY); | 
 |     } | 
 |  | 
 |     DeleteDC (hdcSrc); | 
 |     if (himlSrc != himlDst) | 
 |         DeleteDC (hdcDst); | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Create [COMCTL32.44]  Creates a new image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     cx       [I] image height | 
 |  *     cy       [I] image width | 
 |  *     flags    [I] creation flags | 
 |  *     cInitial [I] initial number of images in the image list | 
 |  *     cGrow    [I] number of images by which image list grows | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Handle to the created image list | 
 |  *     Failure: NULL | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_Create (INT cx, INT cy, UINT flags, | 
 | 		  INT cInitial, INT cGrow) | 
 | { | 
 |     HIMAGELIST himl; | 
 |     HDC      hdc; | 
 |     INT      nCount; | 
 |     HBITMAP  hbmTemp; | 
 |     static WORD aBitBlend25[] =  | 
 |         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00}; | 
 |  | 
 |     static WORD aBitBlend50[] = | 
 |         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA}; | 
 |  | 
 |     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow); | 
 |  | 
 |     himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST)); | 
 |     if (!himl) | 
 |         return NULL; | 
 |  | 
 |     himl->cx        = cx; | 
 |     himl->cy        = cy; | 
 |     himl->flags     = flags; | 
 |     himl->cMaxImage = cInitial + cGrow; | 
 |     himl->cInitial  = cInitial; | 
 |     himl->cGrow     = cGrow; | 
 |     himl->cCurImage = 0; | 
 |     himl->clrFg     = CLR_DEFAULT; | 
 |     himl->clrBk     = CLR_NONE; | 
 |  | 
 |     /* initialize overlay mask indices */ | 
 |     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) | 
 |         himl->nOvlIdx[nCount] = -1; | 
 |  | 
 |     hdc = CreateCompatibleDC (0); | 
 |     himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL); | 
 |     DeleteDC (hdc); | 
 |  | 
 |     TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel); | 
 |  | 
 |     if (himl->cMaxImage > 0) { | 
 |         himl->hbmImage = | 
 | 	  CreateBitmap (himl->cx * himl->cMaxImage, himl->cy, | 
 |                         1, himl->uBitsPixel, NULL); | 
 | 	if (himl->hbmImage == 0) { | 
 | 	    ERR("Error creating image bitmap!\n"); | 
 | 	    return NULL; | 
 | 	} | 
 |     } | 
 |     else | 
 |         himl->hbmImage = 0; | 
 |      | 
 |     if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) { | 
 |         himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy, | 
 | 					1, 1, NULL); | 
 |         if (himl->hbmMask == 0) { | 
 |             ERR("Error creating mask bitmap!\n"); | 
 |             if (himl->hbmImage) | 
 |                 DeleteObject (himl->hbmImage); | 
 |             return NULL; | 
 |         } | 
 |     } | 
 |     else | 
 |         himl->hbmMask = 0; | 
 |  | 
 |     /* create blending brushes */ | 
 |     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25); | 
 |     himl->hbrBlend25 = CreatePatternBrush (hbmTemp); | 
 |     DeleteObject (hbmTemp); | 
 |  | 
 |     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50); | 
 |     himl->hbrBlend50 = CreatePatternBrush (hbmTemp); | 
 |     DeleteObject (hbmTemp); | 
 |  | 
 |     TRACE("created imagelist %p\n", himl); | 
 |     return himl; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Destroy [COMCTL32.45]  | 
 |  * | 
 |  * Destroys an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] handle to image list | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Destroy (HIMAGELIST himl) | 
 | {  | 
 |     if (!himl) | 
 | 	return FALSE; | 
 |  | 
 |     /* delete image bitmaps */ | 
 |     if (himl->hbmImage) | 
 |         DeleteObject (himl->hbmImage); | 
 |     if (himl->hbmMask) | 
 |         DeleteObject (himl->hbmMask); | 
 |  | 
 |     /* delete blending brushes */ | 
 |     if (himl->hbrBlend25) | 
 |         DeleteObject (himl->hbrBlend25); | 
 |     if (himl->hbrBlend50) | 
 |         DeleteObject (himl->hbrBlend50); | 
 |          | 
 |     COMCTL32_Free (himl); | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DragEnter [COMCTL32.46]  | 
 |  * | 
 |  * Locks window update and displays the drag image at the given position. | 
 |  * | 
 |  * PARAMS | 
 |  *     hwndLock [I] handle of the window that owns the drag image. | 
 |  *     x        [I] X position of the drag image. | 
 |  *     y        [I] Y position of the drag image. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     The position of the drag image is relative to the window, not | 
 |  *     the client area. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DragEnter (HWND hwndLock, INT x, INT y) | 
 | { | 
 |     if (himlInternalDrag == NULL) | 
 | 	return FALSE; | 
 |  | 
 |     if (hwndLock) | 
 | 	hwndInternalDrag = hwndLock; | 
 |     else | 
 | 	hwndInternalDrag = GetDesktopWindow (); | 
 |  | 
 |     xInternalPos = x; | 
 |     yInternalPos = y; | 
 |  | 
 |     hdcBackBuffer = CreateCompatibleDC (0); | 
 |     hbmBackBuffer = CreateCompatibleBitmap (hdcBackBuffer, | 
 | 		himlInternalDrag->cx, himlInternalDrag->cy); | 
 |  | 
 |     ImageList_DragShowNolock (TRUE); | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DragLeave [COMCTL32.47]  | 
 |  * | 
 |  * Unlocks window update and hides the drag image. | 
 |  * | 
 |  * PARAMS | 
 |  *     hwndLock [I] handle of the window that owns the drag image. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DragLeave (HWND hwndLock) | 
 | { | 
 |     if (hwndLock) | 
 | 	hwndInternalDrag = hwndLock; | 
 |     else | 
 | 	hwndInternalDrag = GetDesktopWindow (); | 
 |  | 
 |     ImageList_DragShowNolock (FALSE); | 
 |  | 
 |     DeleteDC (hdcBackBuffer); | 
 |     DeleteObject (hbmBackBuffer); | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DragMove [COMCTL32.48]  | 
 |  * | 
 |  * Moves the drag image. | 
 |  * | 
 |  * PARAMS | 
 |  *     x [I] X position of the drag image. | 
 |  *     y [I] Y position of the drag image. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     The position of the drag image is relative to the window, not | 
 |  *     the client area. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DragMove (INT x, INT y) | 
 | { | 
 |     ImageList_DragShowNolock (FALSE); | 
 |  | 
 |     xInternalPos = x; | 
 |     yInternalPos = y; | 
 |  | 
 |     ImageList_DragShowNolock (TRUE); | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DragShowNolock [COMCTL32.49]  | 
 |  * | 
 |  * Shows or hides the drag image. | 
 |  * | 
 |  * PARAMS | 
 |  *     bShow [I] TRUE shows the drag image, FALSE hides it. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * FIXME | 
 |  *     semi-stub. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DragShowNolock (BOOL bShow) | 
 | { | 
 |     HDC hdcDrag; | 
 |  | 
 |     FIXME("semi-stub!\n"); | 
 |     TRACE("bShow=0x%X!\n", bShow); | 
 |  | 
 |     hdcDrag = GetDCEx (hwndInternalDrag, 0, | 
 | 			 DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE); | 
 |  | 
 |     if (bShow) { | 
 | 	/* show drag image */ | 
 |  | 
 | 	/* save background */ | 
 |  | 
 | 	/* draw drag image */ | 
 |  | 
 |     } | 
 |     else { | 
 | 	/* hide drag image */ | 
 |  | 
 | 	/* restore background */ | 
 |  | 
 |     } | 
 |  | 
 |     ReleaseDC (hwndInternalDrag, hdcDrag); | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Draw [COMCTL32.50] Draws an image. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl   [I] handle to image list | 
 |  *     i      [I] image index | 
 |  *     hdc    [I] handle to device context | 
 |  *     x      [I] x position | 
 |  *     y      [I] y position | 
 |  *     fStyle [I] drawing flags | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     Calls ImageList_DrawIndirect. | 
 |  * | 
 |  * SEE | 
 |  *     ImageList_DrawIndirect. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, | 
 | 		INT x, INT y, UINT fStyle) | 
 | { | 
 |     IMAGELISTDRAWPARAMS imldp; | 
 |  | 
 |     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS); | 
 |     imldp.himl    = himl; | 
 |     imldp.i       = i; | 
 |     imldp.hdcDst  = hdc, | 
 |     imldp.x       = x; | 
 |     imldp.y       = y; | 
 |     imldp.cx      = 0; | 
 |     imldp.cy      = 0; | 
 |     imldp.xBitmap = 0; | 
 |     imldp.yBitmap = 0; | 
 |     imldp.rgbBk   = CLR_DEFAULT; | 
 |     imldp.rgbFg   = CLR_DEFAULT; | 
 |     imldp.fStyle  = fStyle; | 
 |     imldp.dwRop   = 0; | 
 |  | 
 |     return ImageList_DrawIndirect (&imldp); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DrawEx [COMCTL32.51] | 
 |  * | 
 |  * Draws an image and allows to use extended drawing features. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl   [I] handle to image list | 
 |  *     i      [I] image index | 
 |  *     hdc    [I] handle to device context | 
 |  *     x      [I] X position | 
 |  *     y      [I] Y position | 
 |  *     xOffs  [I] X offset | 
 |  *     yOffs  [I] Y offset | 
 |  *     rgbBk  [I] background color | 
 |  *     rgbFg  [I] foreground color | 
 |  *     fStyle [I] drawing flags | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     Calls ImageList_DrawIndirect. | 
 |  * | 
 |  * SEE | 
 |  *     ImageList_DrawIndirect. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, | 
 | 		  INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg, | 
 | 		  UINT fStyle) | 
 | { | 
 |     IMAGELISTDRAWPARAMS imldp; | 
 |  | 
 |     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS); | 
 |     imldp.himl    = himl; | 
 |     imldp.i       = i; | 
 |     imldp.hdcDst  = hdc, | 
 |     imldp.x       = x; | 
 |     imldp.y       = y; | 
 |     imldp.cx      = dx; | 
 |     imldp.cy      = dy; | 
 |     imldp.xBitmap = 0; | 
 |     imldp.yBitmap = 0; | 
 |     imldp.rgbBk   = rgbBk; | 
 |     imldp.rgbFg   = rgbFg; | 
 |     imldp.fStyle  = fStyle; | 
 |     imldp.dwRop   = 0; | 
 |  | 
 |     return ImageList_DrawIndirect (&imldp); | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_DrawIndirect [COMCTL32.52]  | 
 |  * | 
 |  * Draws an image using ... | 
 |  * | 
 |  * PARAMS | 
 |  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp) | 
 | { | 
 |     INT      cx, cy;     | 
 |     /*  | 
 |         Do some Error Checking | 
 |     */ | 
 |     if (pimldp == NULL) | 
 |         return FALSE; | 
 |     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS)) | 
 |         return FALSE; | 
 |     if (pimldp->himl == NULL) | 
 |         return FALSE; | 
 |     if ((pimldp->i < 0) || (pimldp->i > pimldp->himl->cCurImage)) { | 
 | 	ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage); | 
 |         return FALSE; | 
 |     } | 
 |     /* | 
 |         Get the Height and Width to display | 
 |     */ | 
 |     cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx; | 
 |     cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy; | 
 |     /* | 
 |         Draw the image | 
 |     */ | 
 |     if(pimldp->himl->hbmMask != 0) | 
 |     { | 
 |         IMAGELIST_InternalDrawMask(pimldp, cx, cy); | 
 |     } | 
 |     else | 
 |     { | 
 |         IMAGELIST_InternalDraw(pimldp, cx, cy); | 
 |     } | 
 |     /*  | 
 |         Apply the blend if needed to the Image | 
 |     */ | 
 |     if((pimldp->fStyle & ILD_BLEND50) | 
 |         || (pimldp->fStyle & ILD_BLEND25)) | 
 |     { | 
 |         IMAGELIST_InternalDrawBlend(pimldp, cx, cy); | 
 |     } | 
 |     /* | 
 |         Apply the Overlay if needed | 
 |     */ | 
 |     if (pimldp->fStyle & ILD_OVERLAYMASK) | 
 |     { | 
 |         IMAGELIST_InternalDrawOverlay(pimldp, cx, cy); | 
 |     } | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Duplicate [COMCTL32.53] Duplicates an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himlSrc [I] source image list handle | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Handle of duplicated image list. | 
 |  *     Failure: NULL | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_Duplicate (HIMAGELIST himlSrc) | 
 | { | 
 |     HIMAGELIST himlDst; | 
 |     HDC hdcSrc, hdcDst; | 
 |  | 
 |     if (himlSrc == NULL) { | 
 |         ERR("Invalid image list handle!\n"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags, | 
 |                                 himlSrc->cInitial, himlSrc->cGrow); | 
 |  | 
 |     if (himlDst) | 
 |     { | 
 |         hdcSrc = CreateCompatibleDC (0); | 
 |         hdcDst = CreateCompatibleDC (0); | 
 |         SelectObject (hdcSrc, himlSrc->hbmImage); | 
 |         SelectObject (hdcDst, himlDst->hbmImage); | 
 |         BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy, | 
 |                   hdcSrc, 0, 0, SRCCOPY); | 
 |  | 
 |         if (himlDst->hbmMask) | 
 |         { | 
 |             SelectObject (hdcSrc, himlSrc->hbmMask); | 
 |             SelectObject (hdcDst, himlDst->hbmMask); | 
 |             BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, | 
 |                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY); | 
 |         } | 
 |  | 
 |         DeleteDC (hdcDst); | 
 |         DeleteDC (hdcSrc); | 
 |  | 
 | 	himlDst->cCurImage = himlSrc->cCurImage; | 
 | 	himlDst->cMaxImage = himlSrc->cMaxImage; | 
 |     } | 
 |     return himlDst; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_EndDrag [COMCTL32.54] Finishes a drag operation. | 
 |  * | 
 |  * Finishes a drag operation. | 
 |  * | 
 |  * PARAMS | 
 |  *     no Parameters | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * BUGS | 
 |  *     semi-stub. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_EndDrag (void) | 
 | { | 
 |     FIXME("semi-stub!\n"); | 
 |  | 
 |     if (himlInternalDrag) | 
 |     { | 
 |  | 
 |         ImageList_Destroy (himlInternalDrag); | 
 |         himlInternalDrag = NULL; | 
 |  | 
 |         nInternalDragHotspotX = 0; | 
 |         nInternalDragHotspotY = 0; | 
 |  | 
 |     } | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetBkColor [COMCTL32.55] | 
 |  * | 
 |  * Returns the background color of an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] Image list handle. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: background color | 
 |  *     Failure: CLR_NONE | 
 |  */ | 
 |  | 
 | COLORREF WINAPI | 
 | ImageList_GetBkColor (HIMAGELIST himl) | 
 | { | 
 |     if (himl == NULL) | 
 | 	return CLR_NONE; | 
 |  | 
 |     return himl->clrBk; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetDragImage [COMCTL32.56] | 
 |  * | 
 |  * Returns the handle to the internal drag image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     ppt        [O] Pointer to the drag position. Can be NULL. | 
 |  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Handle of the drag image list. | 
 |  *     Failure: NULL. | 
 |  * | 
 |  * BUGS | 
 |  *     semi-stub. | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot) | 
 | { | 
 |     FIXME("semi-stub!\n"); | 
 |  | 
 |     if (himlInternalDrag) | 
 |         return (himlInternalDrag); | 
 |  | 
 |     return NULL; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetIcon [COMCTL32.57]  | 
 |  * | 
 |  * Creates an icon from a masked image of an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl  [I] handle to image list | 
 |  *     i     [I] image index | 
 |  *     flags [I] drawing style flags | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: icon handle | 
 |  *     Failure: NULL | 
 |  */ | 
 |  | 
 | HICON WINAPI | 
 | ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle) | 
 | { | 
 |     ICONINFO ii; | 
 |     HICON  hIcon; | 
 |     HBITMAP hOldSrcBitmap,hOldDstBitmap; | 
 |     HDC    hdcSrc, hdcDst; | 
 |  | 
 |     if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) { | 
 | 	FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle); | 
 | 	return 0; | 
 |    } | 
 |  | 
 |     hdcSrc = CreateCompatibleDC(0); | 
 |     hdcDst = CreateCompatibleDC(0); | 
 |  | 
 |     ii.fIcon = TRUE; | 
 |     ii.hbmMask  = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy); | 
 |  | 
 |     /* draw mask*/ | 
 |     hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask); | 
 |     if (himl->hbmMask) { | 
 | 	SelectObject (hdcSrc, himl->hbmMask); | 
 | 	BitBlt (hdcDst, 0, 0, himl->cx, himl->cy, | 
 | 		  hdcSrc, i * himl->cx, 0, SRCCOPY); | 
 |     } | 
 |     else | 
 | 	PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS); | 
 |  | 
 |     /* draw image*/ | 
 |     hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage); | 
 |     ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy); | 
 |     SelectObject (hdcDst, ii.hbmColor); | 
 |     BitBlt (hdcDst, 0, 0, himl->cx, himl->cy, | 
 | 	      hdcSrc, i * himl->cx, 0, SRCCOPY); | 
 |  | 
 |     /* | 
 |      * CreateIconIndirect requires us to deselect the bitmaps from | 
 |      * the DCs before calling  | 
 |      */ | 
 |     SelectObject(hdcSrc, hOldSrcBitmap); | 
 |     SelectObject(hdcDst, hOldDstBitmap); | 
 |  | 
 |     hIcon = CreateIconIndirect (&ii);     | 
 |  | 
 |     DeleteDC (hdcSrc); | 
 |     DeleteDC (hdcDst); | 
 |     DeleteObject (ii.hbmMask); | 
 |     DeleteObject (ii.hbmColor); | 
 |  | 
 |     return hIcon; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetIconSize [COMCTL32.58] | 
 |  * | 
 |  * Retrieves the size of an image in an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] handle to image list | 
 |  *     cx   [O] pointer to the image width. | 
 |  *     cy   [O] pointer to the image height. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     All images in an image list have the same size. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy) | 
 | { | 
 |     if (himl == NULL) | 
 | 	return FALSE; | 
 |     if ((himl->cx <= 0) || (himl->cy <= 0)) | 
 | 	return FALSE; | 
 |  | 
 |     if (cx) | 
 | 	*cx = himl->cx; | 
 |     if (cy) | 
 | 	*cy = himl->cy; | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetImageCount [COMCTL32.59] | 
 |  * | 
 |  * Returns the number of images in an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] handle to image list | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: Number of images. | 
 |  *     Failure: 0 | 
 |  */ | 
 |  | 
 | INT WINAPI | 
 | ImageList_GetImageCount (HIMAGELIST himl) | 
 | { | 
 |     if (himl == NULL) | 
 | 	return 0; | 
 |  | 
 |     return himl->cCurImage; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetImageInfo [COMCTL32.60] | 
 |  * | 
 |  * Returns information about an image in an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl       [I] handle to image list | 
 |  *     i          [I] image index | 
 |  *     pImageInfo [O] pointer to the image information | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo) | 
 | { | 
 |     if ((himl == NULL) || (pImageInfo == NULL)) | 
 | 	return FALSE; | 
 |     if ((i < 0) || (i >= himl->cCurImage)) | 
 | 	return FALSE; | 
 |  | 
 |     pImageInfo->hbmImage = himl->hbmImage; | 
 |     pImageInfo->hbmMask  = himl->hbmMask; | 
 |      | 
 |     pImageInfo->rcImage.top    = 0; | 
 |     pImageInfo->rcImage.bottom = himl->cy; | 
 |     pImageInfo->rcImage.left   = i * himl->cx; | 
 |     pImageInfo->rcImage.right  = (i+1) * himl->cx; | 
 |      | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_GetImageRect [COMCTL32.61]  | 
 |  * | 
 |  * Retrieves the rectangle of the specified image in an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl   [I] handle to image list | 
 |  *     i      [I] image index | 
 |  *     lpRect [O] pointer to the image rectangle | 
 |  * | 
 |  * RETURNS | 
 |  *    Success: TRUE | 
 |  *    Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *    This is an UNDOCUMENTED function!!! | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect) | 
 | { | 
 |     if ((himl == NULL) || (lpRect == NULL)) | 
 | 	return FALSE; | 
 |     if ((i < 0) || (i >= himl->cCurImage)) | 
 | 	return FALSE; | 
 |  | 
 |     lpRect->left   = i * himl->cx; | 
 |     lpRect->top    = 0; | 
 |     lpRect->right  = lpRect->left + himl->cx; | 
 |     lpRect->bottom = himl->cy; | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_LoadImageA [COMCTL32.63][COMCTL32.62] | 
 |  * | 
 |  * Creates an image list from a bitmap, icon or cursor. | 
 |  * | 
 |  * PARAMS | 
 |  *     hi      [I] instance handle | 
 |  *     lpbmp   [I] name or id of the image | 
 |  *     cx      [I] width of each image | 
 |  *     cGrow   [I] number of images to expand | 
 |  *     clrMask [I] mask color | 
 |  *     uType   [I] type of image to load | 
 |  *     uFlags  [I] loading flags | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: handle to the loaded image list | 
 |  *     Failure: NULL | 
 |  * | 
 |  * SEE | 
 |  *     LoadImage () | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx,	INT cGrow, | 
 | 			COLORREF clrMask, UINT uType,	UINT uFlags) | 
 | { | 
 |     HIMAGELIST himl = NULL; | 
 |     HANDLE   handle; | 
 |     INT      nImageCount; | 
 |  | 
 |     handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags); | 
 |     if (!handle) { | 
 |         ERR("Error loading image!\n"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (uType == IMAGE_BITMAP) { | 
 |         BITMAP bmp; | 
 |         GetObjectA (handle, sizeof(BITMAP), &bmp); | 
 |  | 
 |         /* To match windows behavior, if cx is set to zero and | 
 |          the flag DI_DEFAULTSIZE is specified, cx becomes the | 
 |          system metric value for icons. If the flag is not specified | 
 |          the function sets the size to the height of the bitmap */ | 
 |         if (cx == 0) | 
 |         { | 
 |             if (uFlags & DI_DEFAULTSIZE) | 
 |                 cx = GetSystemMetrics (SM_CXICON); | 
 |             else | 
 |                 cx = bmp.bmHeight; | 
 |         } | 
 |  | 
 |         nImageCount = bmp.bmWidth / cx; | 
 |  | 
 |         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR, | 
 |                                  nImageCount, cGrow); | 
 |         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask); | 
 |     } | 
 |     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) { | 
 |         ICONINFO ii; | 
 |         BITMAP bmp; | 
 |  | 
 |         GetIconInfo (handle, &ii); | 
 |         GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp); | 
 |         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,  | 
 |                                  ILC_MASK | ILC_COLOR, 1, cGrow); | 
 |         ImageList_Add (himl, ii.hbmColor, ii.hbmMask); | 
 |         DeleteObject (ii.hbmColor); | 
 |         DeleteObject (ii.hbmMask); | 
 |     } | 
 |  | 
 |     DeleteObject (handle); | 
 |      | 
 |     return himl; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_LoadImageW [COMCTL32.64] | 
 |  * | 
 |  * Creates an image list from a bitmap, icon or cursor. | 
 |  * | 
 |  * PARAMS | 
 |  *     hi      [I] instance handle | 
 |  *     lpbmp   [I] name or id of the image | 
 |  *     cx      [I] width of each image | 
 |  *     cGrow   [I] number of images to expand | 
 |  *     clrMask [I] mask color | 
 |  *     uType   [I] type of image to load | 
 |  *     uFlags  [I] loading flags | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: handle to the loaded image list | 
 |  *     Failure: NULL | 
 |  * | 
 |  * SEE | 
 |  *     LoadImage () | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow, | 
 | 			COLORREF clrMask, UINT uType,	UINT uFlags) | 
 | { | 
 |     HIMAGELIST himl = NULL; | 
 |     HANDLE   handle; | 
 |     INT      nImageCount; | 
 |  | 
 |     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags); | 
 |     if (!handle) { | 
 |         ERR("Error loading image!\n"); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (uType == IMAGE_BITMAP) { | 
 |         BITMAP bmp; | 
 |         GetObjectA (handle, sizeof(BITMAP), &bmp); | 
 |         nImageCount = bmp.bmWidth / cx; | 
 |  | 
 |         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR, | 
 |                                  nImageCount, cGrow); | 
 |         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask); | 
 |     } | 
 |     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) { | 
 |         ICONINFO ii; | 
 |         BITMAP bmp; | 
 |  | 
 |         GetIconInfo (handle, &ii); | 
 |         GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); | 
 |         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,  | 
 |                                  ILC_MASK | ILC_COLOR, 1, cGrow); | 
 |         ImageList_Add (himl, ii.hbmColor, ii.hbmMask); | 
 |         DeleteObject (ii.hbmColor); | 
 |         DeleteObject (ii.hbmMask); | 
 |     } | 
 |  | 
 |     DeleteObject (handle); | 
 |      | 
 |     return himl; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Merge [COMCTL32.65]  | 
 |  * | 
 |  * Creates a new image list that contains a merged image from the specified | 
 |  * images of both source image lists. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl1 [I] handle to first image list | 
 |  *     i1    [I] first image index | 
 |  *     himl2 [I] handle to second image list | 
 |  *     i2    [I] second image index | 
 |  *     dx    [I] X offset of the second image relative to the first. | 
 |  *     dy    [I] Y offset of the second image relative to the first. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: handle of the merged image list. | 
 |  *     Failure: NULL | 
 |  */ | 
 |  | 
 | HIMAGELIST WINAPI | 
 | ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2, | 
 | 		 INT dx, INT dy) | 
 | { | 
 |     HIMAGELIST himlDst = NULL; | 
 |     HDC      hdcSrcImage, hdcDstImage; | 
 |     INT      cxDst, cyDst; | 
 |     INT      xOff1, yOff1, xOff2, yOff2; | 
 |     INT      nX1, nX2; | 
 |  | 
 |     if ((himl1 == NULL) || (himl2 == NULL)) | 
 | 	return NULL; | 
 |  | 
 |     /* check indices */ | 
 |     if ((i1 < 0) || (i1 >= himl1->cCurImage)) { | 
 |         ERR("Index 1 out of range! %d\n", i1); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if ((i2 < 0) || (i2 >= himl2->cCurImage)) { | 
 |         ERR("Index 2 out of range! %d\n", i2); | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (dx > 0) { | 
 |         cxDst = _MAX (himl1->cx, dx + himl2->cx); | 
 |         xOff1 = 0; | 
 |         xOff2 = dx; | 
 |     } | 
 |     else if (dx < 0) { | 
 |         cxDst = _MAX (himl2->cx, himl1->cx - dx); | 
 |         xOff1 = -dx; | 
 |         xOff2 = 0; | 
 |     } | 
 |     else { | 
 |         cxDst = _MAX (himl1->cx, himl2->cx); | 
 |         xOff1 = 0; | 
 |         xOff2 = 0; | 
 |     } | 
 |  | 
 |     if (dy > 0) { | 
 |         cyDst = _MAX (himl1->cy, dy + himl2->cy); | 
 |         yOff1 = 0; | 
 |         yOff2 = dy; | 
 |     } | 
 |     else if (dy < 0) { | 
 |         cyDst = _MAX (himl2->cy, himl1->cy - dy); | 
 |         yOff1 = -dy; | 
 |         yOff2 = 0; | 
 |     } | 
 |     else { | 
 |         cyDst = _MAX (himl1->cy, himl2->cy); | 
 |         yOff1 = 0; | 
 |         yOff2 = 0; | 
 |     } | 
 |  | 
 |     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1); | 
 |  | 
 |     if (himlDst) { | 
 |         hdcSrcImage = CreateCompatibleDC (0); | 
 |         hdcDstImage = CreateCompatibleDC (0); | 
 |         nX1 = i1 * himl1->cx; | 
 |         nX2 = i2 * himl2->cx; | 
 |          | 
 |         /* copy image */ | 
 |         SelectObject (hdcSrcImage, himl1->hbmImage); | 
 |         SelectObject (hdcDstImage, himlDst->hbmImage); | 
 |         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,  | 
 |                   hdcSrcImage, 0, 0, BLACKNESS); | 
 |         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,  | 
 |                   hdcSrcImage, nX1, 0, SRCCOPY); | 
 |  | 
 |         SelectObject (hdcSrcImage, himl2->hbmMask); | 
 |         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,  | 
 |                   hdcSrcImage, nX2, 0, SRCAND); | 
 |  | 
 |         SelectObject (hdcSrcImage, himl2->hbmImage); | 
 |         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,  | 
 |                   hdcSrcImage, nX2, 0, SRCPAINT); | 
 |  | 
 |         /* copy mask */ | 
 |         SelectObject (hdcSrcImage, himl1->hbmMask); | 
 |         SelectObject (hdcDstImage, himlDst->hbmMask); | 
 |         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst,  | 
 |                   hdcSrcImage, 0, 0, WHITENESS); | 
 |         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy,  | 
 |                   hdcSrcImage, nX1, 0, SRCCOPY); | 
 |  | 
 |         SelectObject (hdcSrcImage, himl2->hbmMask); | 
 |         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy,  | 
 |                   hdcSrcImage, nX2, 0, SRCAND); | 
 |  | 
 |         DeleteDC (hdcSrcImage); | 
 |         DeleteDC (hdcDstImage); | 
 |     } | 
 |     | 
 |     return himlDst; | 
 | } | 
 |  | 
 |  | 
 | /* helper for _read_bitmap currently unused */ | 
 | #if 0 | 
 | static int may_use_dibsection(HDC hdc) { | 
 |     int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES); | 
 |     if (bitspixel>8) | 
 | 	return TRUE; | 
 |     if (bitspixel<=4) | 
 | 	return FALSE; | 
 |     return GetDeviceCaps(hdc,94) & 0x10; | 
 | } | 
 | #endif | 
 |  | 
 | /* helper for ImageList_Read, see comments below */ | 
 | static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) { | 
 |     HDC			xdc = 0; | 
 |     BITMAPFILEHEADER	bmfh; | 
 |     BITMAPINFOHEADER	bmih; | 
 |     int			bitsperpixel,palspace,longsperline,width,height; | 
 |     LPBITMAPINFOHEADER	bmihc = NULL; | 
 |     int			result = 0; | 
 |     HBITMAP		hbitmap = 0; | 
 |     LPBYTE		bits = NULL,nbits = NULL; | 
 |     int			nbytesperline,bytesperline; | 
 |  | 
 |     if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL))	|| | 
 |     	(bmfh.bfType != (('M'<<8)|'B'))					|| | 
 |     	!SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL))	|| | 
 |     	(bmih.biSize != sizeof(bmih)) | 
 |     ) | 
 | 	return 0; | 
 |  | 
 |     bitsperpixel = bmih.biPlanes * bmih.biBitCount; | 
 |     if (bitsperpixel<=8) | 
 |     	palspace = (1<<bitsperpixel)*sizeof(RGBQUAD); | 
 |     else | 
 |     	palspace = 0; | 
 |     width = bmih.biWidth; | 
 |     height = bmih.biHeight; | 
 |     bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace); | 
 |     memcpy(bmihc,&bmih,sizeof(bmih)); | 
 |     longsperline	= ((width*bitsperpixel+31)&~0x1f)>>5; | 
 |     bmihc->biSizeImage	= (longsperline*height)<<2; | 
 |  | 
 |     /* read the palette right after the end of the bitmapinfoheader */ | 
 |     if (palspace) | 
 | 	if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL))) | 
 | 	    goto ret1; | 
 |  | 
 |     xdc = GetDC(0); | 
 | #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */ | 
 |     if ((bitsperpixel>1) && | 
 | 	((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc))) | 
 |      ) { | 
 | 	hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0); | 
 | 	if (!hbitmap) | 
 | 	    goto ret1; | 
 | 	if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL))) | 
 | 	    goto ret1; | 
 | 	result = 1; | 
 |     } else | 
 | #endif | 
 |     { | 
 | 	int i,nwidth,nheight; | 
 |  | 
 | 	nwidth	= width*(height/cy); | 
 | 	nheight	= cy; | 
 |  | 
 | 	if (bitsperpixel==1) | 
 | 	    hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL); | 
 | 	else | 
 | 	    hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight); | 
 |  | 
 | 	/* Might be a bit excessive memory use here */ | 
 | 	bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage); | 
 | 	nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage); | 
 | 	if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL))) | 
 | 		goto ret1; | 
 |  | 
 | 	/* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */ | 
 | 	/* Do not forget that windows bitmaps are bottom->top */ | 
 | 	bytesperline	= longsperline*4; | 
 | 	nbytesperline	= (height/cy)*bytesperline; | 
 | 	for (i=0;i<height;i++) { | 
 | 	    memcpy( | 
 | 		nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline, | 
 | 		bits+bytesperline*(height-1-i), | 
 | 		bytesperline | 
 | 	    ); | 
 | 	} | 
 | 	bmihc->biWidth	= nwidth; | 
 | 	bmihc->biHeight	= nheight; | 
 | 	if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0)) | 
 | 		goto ret1; | 
 | 	LocalFree((HLOCAL)nbits); | 
 | 	LocalFree((HLOCAL)bits); | 
 | 	result = 1; | 
 |     } | 
 | ret1: | 
 |     if (xdc)	ReleaseDC(0,xdc); | 
 |     if (bmihc)	LocalFree((HLOCAL)bmihc); | 
 |     if (!result) { | 
 | 	if (hbitmap) { | 
 | 	    DeleteObject(hbitmap); | 
 | 	    hbitmap = 0; | 
 | 	} | 
 |     } | 
 |     return hbitmap; | 
 | } | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Read [COMCTL32.66] | 
 |  * | 
 |  * Reads an image list from a stream. | 
 |  * | 
 |  * PARAMS | 
 |  *     pstm [I] pointer to a stream | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: handle to image list | 
 |  *     Failure: NULL | 
 |  * | 
 |  * The format is like this: | 
 |  * 	ILHEAD 			ilheadstruct; | 
 |  * | 
 |  * for the color image part: | 
 |  * 	BITMAPFILEHEADER	bmfh;  | 
 |  * 	BITMAPINFOHEADER	bmih; | 
 |  * only if it has a palette: | 
 |  *	RGBQUAD		rgbs[nr_of_paletted_colors];  | 
 |  * | 
 |  *	BYTE			colorbits[imagesize]; | 
 |  * | 
 |  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags: | 
 |  *	BITMAPFILEHEADER	bmfh_mask; | 
 |  *	BITMAPINFOHEADER	bmih_mask; | 
 |  * only if it has a palette (it usually does not): | 
 |  *	RGBQUAD		rgbs[nr_of_paletted_colors];  | 
 |  * | 
 |  *	BYTE			maskbits[imagesize]; | 
 |  * | 
 |  * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect. | 
 |  *         _read_bitmap needs to convert them. | 
 |  */ | 
 | HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm) | 
 | { | 
 |     ILHEAD	ilHead; | 
 |     HIMAGELIST	himl; | 
 |     HBITMAP	hbmColor=0,hbmMask=0; | 
 |     int		i; | 
 |  | 
 |     if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL))) | 
 |     	return NULL; | 
 |     if (ilHead.usMagic != (('L' << 8) | 'I')) | 
 | 	return NULL; | 
 |     if (ilHead.usVersion != 0x101) /* probably version? */ | 
 | 	return NULL; | 
 |  | 
 | #if 0 | 
 |     FIXME("	ilHead.cCurImage = %d\n",ilHead.cCurImage); | 
 |     FIXME("	ilHead.cMaxImage = %d\n",ilHead.cMaxImage); | 
 |     FIXME("	ilHead.cGrow = %d\n",ilHead.cGrow); | 
 |     FIXME("	ilHead.cx = %d\n",ilHead.cx); | 
 |     FIXME("	ilHead.cy = %d\n",ilHead.cy); | 
 |     FIXME("	ilHead.flags = %x\n",ilHead.flags); | 
 |     FIXME("	ilHead.ovls[0] = %d\n",ilHead.ovls[0]); | 
 |     FIXME("	ilHead.ovls[1] = %d\n",ilHead.ovls[1]); | 
 |     FIXME("	ilHead.ovls[2] = %d\n",ilHead.ovls[2]); | 
 |     FIXME("	ilHead.ovls[3] = %d\n",ilHead.ovls[3]); | 
 | #endif | 
 |  | 
 |     hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy); | 
 |     if (!hbmColor) | 
 | 	return NULL; | 
 |     if (ilHead.flags & ILC_MASK) { | 
 | 	hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy); | 
 | 	if (!hbmMask) { | 
 | 	    DeleteObject(hbmColor); | 
 | 	    return NULL; | 
 | 	} | 
 |     } | 
 |  | 
 |     himl = ImageList_Create ( | 
 | 		    ilHead.cx, | 
 | 		    ilHead.cy, | 
 | 		    ilHead.flags, | 
 | 		    1,		/* initial */ | 
 | 		    ilHead.cGrow | 
 |     ); | 
 |     if (!himl) { | 
 | 	DeleteObject(hbmColor); | 
 | 	DeleteObject(hbmMask); | 
 | 	return NULL; | 
 |     } | 
 |     himl->hbmImage = hbmColor; | 
 |     himl->hbmMask = hbmMask; | 
 |     himl->cCurImage = ilHead.cCurImage; | 
 |     himl->cMaxImage = ilHead.cMaxImage; | 
 |  | 
 |     ImageList_SetBkColor(himl,ilHead.bkcolor); | 
 |     for (i=0;i<4;i++) | 
 |     	ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1); | 
 |     return himl; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Remove [COMCTL32.67] Removes an image from an image list | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] image list handle | 
 |  *     i    [I] image index | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Remove (HIMAGELIST himl, INT i) | 
 | { | 
 |     HBITMAP hbmNewImage, hbmNewMask; | 
 |     HDC     hdcSrc, hdcDst; | 
 |     INT     cxNew, nCount; | 
 |  | 
 |     if ((i < -1) || (i >= himl->cCurImage)) { | 
 |         ERR("index out of range! %d\n", i); | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     if (himl->cCurImage == 0) { | 
 |         ERR("image list is already empty!\n"); | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     if (i == -1) { | 
 |         /* remove all */ | 
 |         TRACE("remove all!\n"); | 
 |  | 
 |         himl->cMaxImage = himl->cInitial + himl->cGrow; | 
 |         himl->cCurImage = 0; | 
 |         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) | 
 |              himl->nOvlIdx[nCount] = -1; | 
 |  | 
 |         DeleteObject (himl->hbmImage); | 
 |         himl->hbmImage = | 
 |             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, | 
 |                             1, himl->uBitsPixel, NULL); | 
 |  | 
 |         if (himl->hbmMask) { | 
 |             DeleteObject (himl->hbmMask); | 
 |             himl->hbmMask = | 
 |                 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, | 
 |                                 1, 1, NULL); | 
 |         } | 
 |     } | 
 |     else { | 
 |         /* delete one image */ | 
 |         TRACE("Remove single image! %d\n", i); | 
 |  | 
 |         /* create new bitmap(s) */ | 
 |         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx; | 
 |  | 
 |         TRACE(" - Number of images: %d / %d (Old/New)\n", | 
 |                  himl->cCurImage, himl->cCurImage - 1); | 
 |         TRACE(" - Max. number of images: %d / %d (Old/New)\n", | 
 |                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1); | 
 |          | 
 |         hbmNewImage = | 
 |             CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL); | 
 |  | 
 |         if (himl->hbmMask) | 
 |             hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL); | 
 |         else | 
 |             hbmNewMask = 0;  /* Just to keep compiler happy! */ | 
 |  | 
 |         hdcSrc = CreateCompatibleDC (0); | 
 |         hdcDst = CreateCompatibleDC (0); | 
 |  | 
 |         /* copy all images and masks prior to the "removed" image */ | 
 |         if (i > 0) { | 
 |             TRACE("Pre image copy: Copy %d images\n", i); | 
 |         | 
 |             SelectObject (hdcSrc, himl->hbmImage); | 
 |             SelectObject (hdcDst, hbmNewImage); | 
 |             BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy, | 
 |                       hdcSrc, 0, 0, SRCCOPY); | 
 |  | 
 |             if (himl->hbmMask) { | 
 |                 SelectObject (hdcSrc, himl->hbmMask); | 
 |                 SelectObject (hdcDst, hbmNewMask); | 
 |                 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy, | 
 |                           hdcSrc, 0, 0, SRCCOPY); | 
 |             } | 
 |         } | 
 |  | 
 |         /* copy all images and masks behind the removed image */ | 
 |         if (i < himl->cCurImage - 1) { | 
 |             TRACE("Post image copy!\n"); | 
 |             SelectObject (hdcSrc, himl->hbmImage); | 
 |             SelectObject (hdcDst, hbmNewImage); | 
 |             BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx, | 
 |                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY); | 
 |  | 
 |             if (himl->hbmMask) { | 
 |                 SelectObject (hdcSrc, himl->hbmMask); | 
 |                 SelectObject (hdcDst, hbmNewMask); | 
 |                 BitBlt (hdcDst, i * himl->cx, 0, | 
 |                           (himl->cCurImage - i - 1) * himl->cx, | 
 |                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY); | 
 |             } | 
 |         } | 
 |  | 
 |         DeleteDC (hdcSrc); | 
 |         DeleteDC (hdcDst); | 
 |  | 
 |         /* delete old images and insert new ones */ | 
 |         DeleteObject (himl->hbmImage); | 
 |         himl->hbmImage = hbmNewImage; | 
 |         if (himl->hbmMask) { | 
 |             DeleteObject (himl->hbmMask); | 
 |             himl->hbmMask = hbmNewMask; | 
 |         } | 
 |  | 
 |         himl->cCurImage--; | 
 |         himl->cMaxImage = himl->cCurImage + himl->cGrow; | 
 |     } | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Replace [COMCTL32.68]  | 
 |  * | 
 |  * Replaces an image in an image list with a new image. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl     [I] handle to image list | 
 |  *     i        [I] image index | 
 |  *     hbmImage [I] handle to image bitmap | 
 |  *     hbmMask  [I] handle to mask bitmap. Can be NULL. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage, | 
 | 		   HBITMAP hbmMask) | 
 | { | 
 |     HDC hdcImageList, hdcImage; | 
 |     BITMAP bmp; | 
 |  | 
 |     if (himl == NULL) { | 
 |         ERR("Invalid image list handle!\n"); | 
 |         return FALSE; | 
 |     } | 
 |      | 
 |     if ((i >= himl->cMaxImage) || (i < 0)) { | 
 |         ERR("Invalid image index!\n"); | 
 |         return FALSE; | 
 |     } | 
 |  | 
 |     hdcImageList = CreateCompatibleDC (0); | 
 |     hdcImage = CreateCompatibleDC (0); | 
 |     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp); | 
 |  | 
 |     /* Replace Image */ | 
 |     SelectObject (hdcImageList, himl->hbmImage); | 
 |     SelectObject (hdcImage, hbmImage); | 
 |  | 
 |     StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy, | 
 |                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); | 
 |  | 
 |     if (himl->hbmMask) | 
 |     { | 
 |         /* Replace Mask */ | 
 |         SelectObject (hdcImageList, himl->hbmMask); | 
 |         SelectObject (hdcImage, hbmMask); | 
 |  | 
 |         StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy, | 
 |                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); | 
 |  | 
 |  | 
 |         /* Remove the background from the image | 
 |         */ | 
 |         SelectObject (hdcImageList, himl->hbmImage); | 
 |         StretchBlt (hdcImageList,  | 
 |             i*himl->cx, 0, himl->cx, himl->cy, | 
 |             hdcImage,  | 
 |             0, 0, bmp.bmWidth, bmp.bmHeight,  | 
 |             0x220326); /* NOTSRCAND */ | 
 |     } | 
 |  | 
 |     DeleteDC (hdcImage); | 
 |     DeleteDC (hdcImageList); | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_ReplaceIcon [COMCTL32.69] | 
 |  * | 
 |  * Replaces an image in an image list using an icon. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl  [I] handle to image list | 
 |  *     i     [I] image index | 
 |  *     hIcon [I] handle to icon | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: index of the replaced image | 
 |  *     Failure: -1 | 
 |  */ | 
 |  | 
 | INT WINAPI | 
 | ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon) | 
 | { | 
 |     HDC     hdcImageList, hdcImage; | 
 |     INT     nIndex; | 
 |     HICON   hBestFitIcon; | 
 |     HBITMAP hbmOldSrc, hbmOldDst; | 
 |     ICONINFO  ii; | 
 |     BITMAP  bmp; | 
 |  | 
 |     TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon); | 
 |  | 
 |     if (himl == NULL) | 
 | 	return -1; | 
 |     if ((i >= himl->cMaxImage) || (i < -1)) | 
 | 	return -1; | 
 |  | 
 |     hBestFitIcon = CopyImage( | 
 |         hIcon, IMAGE_ICON,  | 
 |         himl->cx, himl->cy,  | 
 |         LR_COPYFROMRESOURCE); | 
 |  | 
 |     GetIconInfo (hBestFitIcon, &ii); | 
 |     if (ii.hbmMask == 0) | 
 | 	ERR("no mask!\n"); | 
 |     if (ii.hbmColor == 0) | 
 | 	ERR("no color!\n"); | 
 |     GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp); | 
 |  | 
 |     if (i == -1) { | 
 |         if (himl->cCurImage + 1 >= himl->cMaxImage) | 
 |             IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0); | 
 |  | 
 |         nIndex = himl->cCurImage; | 
 |         himl->cCurImage++; | 
 |     } | 
 |     else | 
 |         nIndex = i; | 
 |  | 
 |     hdcImageList = CreateCompatibleDC (0); | 
 |     TRACE("hdcImageList=0x%x!\n", hdcImageList); | 
 |     if (hdcImageList == 0) | 
 | 	ERR("invalid hdcImageList!\n"); | 
 |  | 
 |     hdcImage = CreateCompatibleDC (0); | 
 |     TRACE("hdcImage=0x%x!\n", hdcImage); | 
 |     if (hdcImage == 0) | 
 | 	ERR("invalid hdcImage!\n"); | 
 |  | 
 |     hbmOldDst = SelectObject (hdcImageList, himl->hbmImage); | 
 |     SetTextColor( hdcImageList, RGB(0,0,0)); | 
 |     SetBkColor( hdcImageList, RGB(255,255,255)); | 
 |     hbmOldSrc = SelectObject (hdcImage, ii.hbmColor); | 
 |     StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy, | 
 |                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); | 
 |  | 
 |     if (himl->hbmMask) { | 
 |         SelectObject (hdcImageList, himl->hbmMask); | 
 |         SelectObject (hdcImage, ii.hbmMask); | 
 |         StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy, | 
 |                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY); | 
 |     } | 
 |  | 
 |     SelectObject (hdcImage, hbmOldSrc); | 
 |     SelectObject (hdcImageList, hbmOldDst); | 
 |  | 
 |     if(hBestFitIcon) | 
 | 	DestroyIcon(hBestFitIcon); | 
 |     if (hdcImageList) | 
 | 	DeleteDC (hdcImageList); | 
 |     if (hdcImage) | 
 | 	DeleteDC (hdcImage); | 
 |     if (ii.hbmColor) | 
 | 	DeleteObject (ii.hbmColor); | 
 |     if (ii.hbmMask) | 
 | 	DeleteObject (ii.hbmMask); | 
 |  | 
 |     return nIndex; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetBkColor [COMCTL32.70]  | 
 |  * | 
 |  * Sets the background color of an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl  [I] handle to image list | 
 |  *     clrBk [I] background color | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: previous background color | 
 |  *     Failure: CLR_NONE | 
 |  */ | 
 |  | 
 | COLORREF WINAPI | 
 | ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk) | 
 | { | 
 |     COLORREF clrOldBk; | 
 |  | 
 |     if (himl == NULL) | 
 | 	return CLR_NONE; | 
 |  | 
 |     clrOldBk = himl->clrBk; | 
 |     himl->clrBk = clrBk; | 
 |     return clrOldBk; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetDragCursorImage [COMCTL32.75] | 
 |  * | 
 |  * Combines the specified image with the current drag image | 
 |  * | 
 |  * PARAMS | 
 |  *     himlDrag  [I] handle to drag image list | 
 |  *     iDrag     [I] drag image index | 
 |  *     dxHotspot [I] X position of the hot spot | 
 |  *     dyHotspot [I] Y position of the hot spot | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * BUGS | 
 |  *     semi-stub. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag, | 
 | 			      INT dxHotspot, INT dyHotspot) | 
 | { | 
 |     HIMAGELIST himlTemp; | 
 |  | 
 |     FIXME("semi-stub!\n"); | 
 |  | 
 |     if (himlInternalDrag == NULL) | 
 | 	return FALSE; | 
 |  | 
 |     TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n", | 
 | 	   dxHotspot, dyHotspot, nInternalDragHotspotX, nInternalDragHotspotY); | 
 |  | 
 |     himlTemp = ImageList_Merge (himlInternalDrag, 0, himlDrag, iDrag, | 
 | 				dxHotspot, dyHotspot); | 
 |  | 
 |     ImageList_Destroy (himlInternalDrag); | 
 |     himlInternalDrag = himlTemp; | 
 |  | 
 |     nInternalDragHotspotX = dxHotspot; | 
 |     nInternalDragHotspotY = dyHotspot; | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetFilter [COMCTL32.76]  | 
 |  * | 
 |  * Sets a filter (or does something completely different)!!??? | 
 |  * | 
 |  * PARAMS | 
 |  *     himl     [I] handle to image list | 
 |  *     i        [I] ??? | 
 |  *     dwFilter [I] ??? | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE ??? | 
 |  *     Failure: FALSE ??? | 
 |  * | 
 |  * BUGS | 
 |  *     This is an UNDOCUMENTED function!!!! | 
 |  *     empty stub. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter) | 
 | { | 
 |     FIXME("(%p 0x%x 0x%lx):empty stub!\n", | 
 | 	   himl, i, dwFilter); | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetIconSize [COMCTL32.77] | 
 |  * | 
 |  * Sets the image size of the bitmap and deletes all images. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] handle to image list | 
 |  *     cx   [I] image width | 
 |  *     cy   [I] image height | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy) | 
 | { | 
 |     INT nCount; | 
 |  | 
 |     if (!himl) | 
 | 	return FALSE; | 
 |  | 
 |     /* remove all images */ | 
 |     himl->cMaxImage = himl->cInitial + himl->cGrow; | 
 |     himl->cCurImage = 0; | 
 |     himl->cx        = cx; | 
 |     himl->cy        = cy; | 
 |  | 
 |     /* initialize overlay mask indices */ | 
 |     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++) | 
 |         himl->nOvlIdx[nCount] = -1; | 
 |  | 
 |     DeleteObject (himl->hbmImage); | 
 |     himl->hbmImage = | 
 |         CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, | 
 |                         1, himl->uBitsPixel, NULL); | 
 |  | 
 |     if (himl->hbmMask) { | 
 |         DeleteObject (himl->hbmMask); | 
 |         himl->hbmMask = | 
 |             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy, | 
 |                             1, 1, NULL); | 
 |     } | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetImageCount [COMCTL32.78] | 
 |  * | 
 |  * Resizes an image list to the specified number of images. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl        [I] handle to image list | 
 |  *     iImageCount [I] number of images in the image list | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount) | 
 | { | 
 |     HDC     hdcImageList, hdcBitmap; | 
 |     HBITMAP hbmNewBitmap; | 
 |     INT     nNewCount, nCopyCount; | 
 |  | 
 |     if (!himl) | 
 | 	return FALSE; | 
 |     if (himl->cCurImage >= iImageCount) | 
 | 	return FALSE; | 
 |     if (himl->cMaxImage > iImageCount) | 
 | 	return TRUE; | 
 |  | 
 |     nNewCount = iImageCount + himl->cGrow; | 
 |     nCopyCount = _MIN(himl->cCurImage, iImageCount); | 
 |  | 
 |     hdcImageList = CreateCompatibleDC (0); | 
 |     hdcBitmap = CreateCompatibleDC (0); | 
 |  | 
 |     hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy, | 
 |                                    1, himl->uBitsPixel, NULL); | 
 |     if (hbmNewBitmap != 0) | 
 |     { | 
 |         SelectObject (hdcImageList, himl->hbmImage); | 
 |         SelectObject (hdcBitmap, hbmNewBitmap); | 
 |  | 
 | 	/* copy images */ | 
 |         BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy, | 
 |                   hdcImageList, 0, 0, SRCCOPY); | 
 | #if 0 | 
 | 	/* delete 'empty' image space */ | 
 | 	SetBkColor (hdcBitmap, RGB(255, 255, 255)); | 
 | 	SetTextColor (hdcBitmap, RGB(0, 0, 0)); | 
 | 	PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0,  | 
 | 		  (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS); | 
 | #endif | 
 | 	DeleteObject (himl->hbmImage); | 
 | 	himl->hbmImage = hbmNewBitmap; | 
 |     } | 
 |     else | 
 | 	ERR("Could not create new image bitmap !\n"); | 
 |  | 
 |     if (himl->hbmMask) | 
 |     { | 
 |         hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy, | 
 |                                        1, 1, NULL); | 
 |         if (hbmNewBitmap != 0) | 
 |         { | 
 |             SelectObject (hdcImageList, himl->hbmMask); | 
 |             SelectObject (hdcBitmap, hbmNewBitmap); | 
 |  | 
 | 	    /* copy images */ | 
 |             BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy, | 
 |                       hdcImageList, 0, 0, SRCCOPY); | 
 | #if 0 | 
 | 	    /* delete 'empty' image space */ | 
 | 	    SetBkColor (hdcBitmap, RGB(255, 255, 255)); | 
 | 	    SetTextColor (hdcBitmap, RGB(0, 0, 0)); | 
 |             PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0,  | 
 | 		      (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS); | 
 | #endif | 
 |             DeleteObject (himl->hbmMask); | 
 |             himl->hbmMask = hbmNewBitmap; | 
 |         } | 
 |         else | 
 |             ERR("Could not create new mask bitmap!\n"); | 
 |     } | 
 |  | 
 |     DeleteDC (hdcImageList); | 
 |     DeleteDC (hdcBitmap); | 
 |  | 
 |     /* Update max image count and current image count */ | 
 |     himl->cMaxImage = nNewCount; | 
 |     if (himl->cCurImage > nCopyCount) | 
 |         himl->cCurImage = nCopyCount; | 
 |  | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_SetOverlayImage [COMCTL32.79] | 
 |  * | 
 |  * Assigns an overlay mask index to an existing image in an image list. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl     [I] handle to image list | 
 |  *     iImage   [I] image index | 
 |  *     iOverlay [I] overlay mask index | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay) | 
 | { | 
 |     if (!himl) | 
 | 	return FALSE; | 
 |     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) | 
 | 	return FALSE; | 
 |     if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage))) | 
 | 	return FALSE; | 
 |     himl->nOvlIdx[iOverlay - 1] = iImage; | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /************************************************************************* | 
 |  * ImageList_Write [COMCTL32.80] | 
 |  * | 
 |  * Writes an image list to a stream. | 
 |  * | 
 |  * PARAMS | 
 |  *     himl [I] handle to image list | 
 |  *     pstm [O] Pointer to a stream. | 
 |  * | 
 |  * RETURNS | 
 |  *     Success: TRUE | 
 |  *     Failure: FALSE | 
 |  * | 
 |  * NOTES | 
 |  *     This function can not be implemented yet, because | 
 |  *     IStream32::Write is not implemented. | 
 |  * | 
 |  * BUGS | 
 |  *     empty stub. | 
 |  */ | 
 |  | 
 | BOOL WINAPI | 
 | ImageList_Write (HIMAGELIST himl, LPSTREAM pstm) | 
 | { | 
 |     if (!himl) | 
 | 	return FALSE; | 
 |  | 
 |     FIXME("empty stub!\n"); | 
 |  | 
 |     return FALSE; | 
 | } | 
 |  |