Removed some useless wingdi.h includes.
[wine] / dlls / comctl32 / imagelist.c
1 /*
2  *  ImageList implementation
3  *
4  *  Copyright 1998 Eric Kohl
5  *            2000 Jason Mawdsley.
6  *            2001 Michael Stefaniuc
7  *
8  *  TODO:
9  *    - Fix ImageList_DrawIndirect (xBitmap, yBitmap, rgbFg, rgbBk, dwRop).
10  *    - Fix ImageList_GetIcon.
11  *    - Fix ImageList_Write.
12  *    - Fix ImageList_SetFilter (undocumented).
13  *      BTW does anybody know anything about this function???
14  *        - It removes 12 Bytes from the stack (3 Parameters).
15  *        - First parameter SHOULD be a HIMAGELIST.
16  *        - Second parameter COULD be an index?????
17  *        - Third parameter.... ?????????????????????
18  *
19  *  Comments:
20  *    - ImageList_Draw, ImageList_DrawEx and ImageList_GetIcon use
21  *      ImageList_DrawIndirect. Since ImageList_DrawIndirect is still
22  *      partially implemented, the functions mentioned above will be 
23  *      limited in functionality too.
24  */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include "winerror.h"
29 #include "winbase.h"
30 #include "wine/obj_base.h"
31 #include "wine/obj_storage.h"
32 #include "commctrl.h"
33 #include "imagelist.h"
34 #include "debugtools.h"
35
36 DEFAULT_DEBUG_CHANNEL(imagelist);
37
38
39 #define MAX_OVERLAYIMAGE 15
40
41 /* internal image list data used for Drag & Drop operations */
42 typedef struct
43 {
44     HWND        hwnd;
45     HIMAGELIST  himl;
46     /* position of the drag image relative to the window */
47     INT         x;
48     INT         y;
49     /* offset of the hotspot relative to the origin of the image */
50     INT         dxHotspot;
51     INT         dyHotspot;
52     /* is the drag image visible */
53     BOOL        bShow;
54     /* saved background */
55     HBITMAP     hbmBg;
56 } INTERNALDRAG;
57
58 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
59
60
61
62 /*************************************************************************
63  * IMAGELIST_InternalExpandBitmaps [Internal] 
64  *
65  * Expands the bitmaps of an image list by the given number of images.
66  *
67  * PARAMS
68  *     himl        [I] handle to image list
69  *     nImageCount [I] number of images to add
70  *
71  * RETURNS
72  *     nothing
73  *
74  * NOTES
75  *     This function can NOT be used to reduce the number of images.
76  */
77 static VOID
78 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
79 {
80     HDC     hdcImageList, hdcBitmap;
81     HBITMAP hbmNewBitmap;
82     INT     nNewWidth, nNewCount;
83
84     if ((himl->cCurImage + nImageCount <= himl->cMaxImage)
85         && (himl->cy >= cy))
86         return;
87
88     if (cy == 0) cy = himl->cy;
89     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
90     nNewWidth = nNewCount * himl->cx;
91
92     TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, nNewWidth, cy, nNewCount);
93     hdcImageList = CreateCompatibleDC (0);
94     hdcBitmap = CreateCompatibleDC (0);
95
96     hbmNewBitmap =
97         CreateBitmap (nNewWidth, cy, 1, himl->uBitsPixel, NULL);
98     if (hbmNewBitmap == 0)
99         ERR("creating new image bitmap (x=%d y=%d)!\n", nNewWidth, cy);
100
101     SelectObject (hdcImageList, himl->hbmImage);
102     SelectObject (hdcBitmap, hbmNewBitmap);
103     BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
104               hdcImageList, 0, 0, SRCCOPY);
105
106     DeleteObject (himl->hbmImage);
107     himl->hbmImage = hbmNewBitmap;
108
109     if (himl->hbmMask) {
110         hbmNewBitmap = 
111             CreateBitmap (nNewWidth, cy, 1, 1, NULL);
112
113         if (hbmNewBitmap == 0)
114             ERR("creating new mask bitmap!\n");
115
116         SelectObject (hdcImageList, himl->hbmMask);
117         SelectObject (hdcBitmap, hbmNewBitmap);
118         BitBlt (hdcBitmap, 0, 0, himl->cCurImage * himl->cx, cy,
119                   hdcImageList, 0, 0, SRCCOPY);
120         DeleteObject (himl->hbmMask);
121         himl->hbmMask = hbmNewBitmap;
122     }
123
124     himl->cMaxImage = nNewCount;
125
126     DeleteDC (hdcImageList);
127     DeleteDC (hdcBitmap);
128 }
129
130
131 /*************************************************************************
132  * IMAGELIST_InternalDraw [Internal] 
133  *
134  * Draws the image in the ImageList (without the mask)
135  *
136  * PARAMS
137  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
138  *     cx            [I] the width of the image to display
139  *     cy............[I] the height of the image to display
140  *
141  * RETURNS
142  *     nothing
143  *
144  * NOTES
145  *     This function is used by ImageList_DrawIndirect, when it is 
146  *     required to draw only the Image (without the mask) to the screen.
147  *
148  *     Blending and Overlays styles are accomplished by another function
149  */
150 static VOID
151 IMAGELIST_InternalDraw(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
152 {
153     HDC hImageDC;
154     HBITMAP hOldBitmap;
155
156     hImageDC = CreateCompatibleDC(0);
157     hOldBitmap = SelectObject(hImageDC, pimldp->himl->hbmImage);
158     BitBlt(pimldp->hdcDst, 
159         pimldp->x, pimldp->y, cx, cy,
160         hImageDC, 
161         pimldp->himl->cx * pimldp->i, 0, 
162         SRCCOPY);
163
164     SelectObject(hImageDC, hOldBitmap);
165     DeleteDC(hImageDC);
166 }
167
168
169 /*************************************************************************
170  * IMAGELIST_InternalDrawMask [Internal] 
171  *
172  * Draws the image in the ImageList with the mask
173  *
174  * PARAMS
175  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
176  *     cx            [I] the width of the image to display
177  *     cy............[I] the height of the image to display
178  *
179  * RETURNS
180  *     nothing
181  *
182  * NOTES
183  *     This function is used by ImageList_DrawIndirect, when it is 
184  *     required to draw the Image with the mask to the screen.
185  *
186  *     Blending and Overlays styles are accomplished by another function.
187  */
188 static VOID
189 IMAGELIST_InternalDrawMask(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
190 {
191     BOOL bUseCustomBackground, bBlendFlag;
192     HBRUSH hBrush, hOldBrush;
193     HDC     hMaskDC, hImageDC;
194     HBITMAP hOldBitmapImage, hOldBitmapMask;
195     HIMAGELIST himlLocal = pimldp->himl;
196     COLORREF oldBkColor, oldFgColor;
197     UINT fStyle = pimldp->fStyle & (~ILD_OVERLAYMASK);
198
199     /* 
200      * We need a dc and bitmap to draw on that is 
201      * not on the screen.
202      */
203     HDC hOffScreenDC = 0;
204     HBITMAP hOffScreenBmp = 0;
205
206     bUseCustomBackground = (himlLocal->clrBk != CLR_NONE);
207     bBlendFlag = (fStyle & ILD_BLEND50 ) || (fStyle & ILD_BLEND25);
208
209     hImageDC = CreateCompatibleDC(0);
210     hMaskDC = CreateCompatibleDC(0);
211
212     /* Create a compatible DC. */
213     hOffScreenDC = CreateCompatibleDC( pimldp->hdcDst );
214
215     if ( hOffScreenDC ) 
216     {
217         hOffScreenBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
218
219         if ( hOffScreenBmp ) 
220             SelectObject( hOffScreenDC, hOffScreenBmp  );
221         else
222             goto cleanup;
223     }
224     else
225         goto cleanup;
226
227     hOldBitmapImage = SelectObject(hImageDC, himlLocal->hbmImage);
228     hOldBitmapMask = SelectObject(hMaskDC, himlLocal->hbmMask);
229     
230     /* 
231      * Get a copy of the image for the masking operations. 
232      * We will use the copy, and this dc for all the various
233      * blitting, and then do one final blit to the screen dc.
234      * This should clean up most of the flickering.
235      */
236     BitBlt( hOffScreenDC, 0, 0, cx, cy, pimldp->hdcDst, pimldp->x, 
237             pimldp->y, SRCCOPY);
238
239     /* 
240      * Draw the Background for the appropriate Styles
241      */
242     if( bUseCustomBackground && (fStyle == ILD_NORMAL || fStyle & ILD_IMAGE 
243          || bBlendFlag) )
244     {
245         
246         hBrush = CreateSolidBrush (himlLocal->clrBk);
247         hOldBrush = SelectObject (pimldp->hdcDst, hBrush);
248         
249         PatBlt( hOffScreenDC, pimldp->x, pimldp->y, cx, cy, PATCOPY );
250
251         DeleteObject (SelectObject (pimldp->hdcDst, hOldBrush));
252     }
253
254     /* 
255      * Draw Image Transparently over the current background
256      */
257     if(fStyle == ILD_NORMAL || (fStyle & ILD_TRANSPARENT) || 
258        ((fStyle & ILD_IMAGE) && bUseCustomBackground) || bBlendFlag) 
259     {   /* 
260          * To obtain a transparent look, background color should be set
261          * to white and foreground color to black when blting the 
262          * monochrome mask. 
263          */
264         
265         oldBkColor = SetBkColor( hOffScreenDC, RGB( 0xff, 0xff, 0xff ) ); 
266         oldFgColor = SetTextColor( hOffScreenDC, RGB( 0, 0, 0 ) );
267
268         BitBlt( hOffScreenDC, 0, 0, cx, cy,hMaskDC, himlLocal->cx * pimldp->i,
269                 0, SRCAND );
270
271         BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC,himlLocal->cx * pimldp->i,
272                 0, SRCPAINT );
273     
274     }
275     
276     /*
277      * Draw the image when no Background is specified
278      */
279     else if((fStyle & ILD_IMAGE) && !bUseCustomBackground)
280     {
281         BitBlt( hOffScreenDC, 0, 0, cx, cy, hImageDC, 
282                 himlLocal->cx * pimldp->i, 0, SRCCOPY);
283     }
284     /* 
285      * Draw the mask with or without a background
286      */
287     else if(fStyle & ILD_MASK)
288     {
289         BitBlt( hOffScreenDC, 0, 0, cx, cy, hMaskDC, himlLocal->cx * pimldp->i,
290                 0, bUseCustomBackground ? SRCCOPY : SRCAND);
291     }
292     
293     /*
294      * Blit the bitmap to the screen now.
295      */
296     BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
297             hOffScreenDC, 0, 0, SRCCOPY);
298
299     
300     SelectObject(hImageDC, hOldBitmapImage);
301     SelectObject(hMaskDC, hOldBitmapMask);
302     
303 cleanup:
304     
305     DeleteDC(hImageDC);
306     DeleteDC(hMaskDC);
307     
308     DeleteDC( hOffScreenDC );
309     DeleteObject( hOffScreenBmp );
310     
311     return;
312 }
313
314 /*************************************************************************
315  * IMAGELIST_InternalDrawBlend [Internal] 
316  *
317  * Draws the Blend over the current image 
318  *
319  * PARAMS
320  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
321  *     cx            [I] the width of the image to display
322  *     cy............[I] the height of the image to display
323  *
324  * RETURNS
325  *     nothing
326  *
327  * NOTES
328  *     This functions is used by ImageList_DrawIndirect, when it is 
329  *     required to add the blend to the current image.  
330  *     
331  */
332 static VOID
333 IMAGELIST_InternalDrawBlend(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
334 {
335
336     HDC         hBlendMaskDC,hMaskDC;
337     HBRUSH      hBlendColorBrush, hBlendBrush, hOldBrush;
338     HBITMAP     hBlendMaskBitmap, hOldBitmap;
339     COLORREF    clrBlend, OldTextColor, OldBkColor;
340     HIMAGELIST  himlLocal = pimldp->himl;
341
342     clrBlend = GetSysColor (COLOR_HIGHLIGHT);
343     if (!(pimldp->rgbFg == CLR_DEFAULT))
344     {
345         clrBlend = pimldp->rgbFg;
346     }
347     /* Create the blend Mask
348     */
349     hBlendMaskDC = CreateCompatibleDC(0);
350     hBlendBrush = pimldp->fStyle & ILD_BLEND50 ?
351         himlLocal->hbrBlend50 : himlLocal->hbrBlend25;
352
353     hBlendMaskBitmap = CreateBitmap(cx, cy, 1, 1, NULL);
354     hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBitmap);
355
356     hOldBrush = (HBRUSH) SelectObject(hBlendMaskDC, hBlendBrush);
357     PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
358     SelectObject(hBlendMaskDC, hOldBrush);
359
360     /* Modify the blend mask if an Image Mask exist
361     */
362     if(pimldp->himl->hbmMask != 0)
363     {
364         HBITMAP hOldMaskBitmap;
365         hMaskDC = CreateCompatibleDC(0);
366         hOldMaskBitmap = (HBITMAP) SelectObject(hMaskDC, himlLocal->hbmMask);
367
368         BitBlt(hBlendMaskDC,
369             0,0, cx, cy, 
370             hMaskDC,
371             himlLocal->cx * pimldp->i,0,
372             0x220326); /* NOTSRCAND */
373
374         BitBlt(hBlendMaskDC,
375             0,0, cx, cy, 
376             hBlendMaskDC,
377             0,0, 
378             NOTSRCCOPY);
379
380         SelectObject(hMaskDC, hOldMaskBitmap);
381         DeleteDC(hMaskDC);
382
383     }
384     /* Apply blend to the current image given the BlendMask
385     */
386     OldTextColor = SetTextColor(pimldp->hdcDst, 0);
387     OldBkColor = SetBkColor(pimldp->hdcDst, RGB(255,255,255));
388     hBlendColorBrush = CreateSolidBrush(clrBlend);
389     hOldBrush = (HBRUSH) SelectObject (pimldp->hdcDst, hBlendColorBrush);
390
391     BitBlt (pimldp->hdcDst, 
392         pimldp->x, pimldp->y, cx, cy, 
393         hBlendMaskDC, 
394         0, 0, 
395         0xB8074A); /* PSDPxax */
396
397     SelectObject(pimldp->hdcDst, hOldBrush);
398     SetTextColor(pimldp->hdcDst, OldTextColor);
399     SetBkColor(pimldp->hdcDst, OldBkColor);
400     SelectObject(hBlendMaskDC, hOldBitmap);
401     DeleteDC(hBlendMaskDC);
402     DeleteObject(hBlendMaskBitmap);
403     DeleteObject(hBlendColorBrush);
404 }
405
406 /*************************************************************************
407  * IMAGELIST_InternalDrawOverlay [Internal] 
408  *
409  * Draws the overlay image 
410  *
411  * PARAMS
412  *     pimldp        [I] pointer to IMAGELISTDRAWPARAMS structure.
413  *     cx            [I] the width of the image to display
414  *     cy............[I] the height of the image to display
415  *
416  * RETURNS
417  *     nothing
418  *
419  * NOTES
420  *     This functions is used by ImageList_DrawIndirect, when it is 
421  *     required to draw the overlay
422  *
423  *     
424  */
425 static VOID 
426 IMAGELIST_InternalDrawOverlay(IMAGELISTDRAWPARAMS *pimldp, INT cx, INT cy)
427 {
428     INT     nOvlIdx;
429     HDC     hImageDC;
430     HBITMAP hOldBitmap;
431
432     nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
433     if ((nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE))
434     {
435         nOvlIdx = pimldp->himl->nOvlIdx[nOvlIdx - 1];
436         if ((nOvlIdx >= 0) && (nOvlIdx <= pimldp->himl->cCurImage))
437         {
438             hImageDC = CreateCompatibleDC(0);
439             if (pimldp->himl->hbmMask)
440             {
441                 hOldBitmap = (HBITMAP) SelectObject (hImageDC, 
442                     pimldp->himl->hbmMask);
443
444                 BitBlt (pimldp->hdcDst, 
445                     pimldp->x, pimldp->y, cx, cy,
446                     hImageDC, pimldp->himl->cx * nOvlIdx, 0,
447                     SRCAND);
448
449                 SelectObject(hImageDC, hOldBitmap);
450             }
451             hOldBitmap = (HBITMAP) SelectObject (hImageDC, 
452                 pimldp->himl->hbmImage);
453
454             BitBlt (pimldp->hdcDst, 
455                 pimldp->x, pimldp->y, cx, cy, 
456                 hImageDC,
457                 pimldp->himl->cx * nOvlIdx, 0,
458                 SRCPAINT);
459
460             SelectObject(hImageDC, hOldBitmap);
461             DeleteDC(hImageDC);
462         }
463     }
464 }
465
466
467 /*************************************************************************
468  * ImageList_Add [COMCTL32.40]
469  *
470  * Add an image or images to an image list.
471  *
472  * PARAMS
473  *     himl     [I] handle to image list
474  *     hbmImage [I] handle to image bitmap
475  *     hbmMask  [I] handle to mask bitmap
476  *
477  * RETURNS
478  *     Success: Index of the first new image.
479  *     Failure: -1
480  */
481
482 INT WINAPI
483 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
484 {
485     HDC     hdcImage, hdcBitmap;
486     INT     nFirstIndex, nImageCount;
487     INT     nStartX;
488     BITMAP  bmp;
489     HBITMAP hOldBitmapImage, hOldBitmap;
490
491     TRACE("himl=%p hbmimage=%x hbmmask=%x\n", himl, hbmImage, hbmMask);
492     if (!himl || !hbmImage)
493         return -1;
494
495     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
496     nImageCount = bmp.bmWidth / himl->cx;
497
498     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
499
500     nStartX = himl->cCurImage * himl->cx;
501
502     hdcImage  = CreateCompatibleDC(0);
503     hdcBitmap = CreateCompatibleDC(0);
504
505     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
506     hOldBitmap = SelectObject(hdcBitmap, hbmImage);
507
508     /* Copy result to the imagelist
509     */
510     BitBlt (hdcImage, nStartX, 0, bmp.bmWidth, bmp.bmHeight,
511         hdcBitmap, 0, 0, SRCCOPY);
512
513     if(himl->hbmMask)
514     {
515         HDC hdcMask, hdcTemp, hOldBitmapMask, hOldBitmapTemp;
516
517         hdcMask   = CreateCompatibleDC (0);
518         hdcTemp   = CreateCompatibleDC(0);
519         hOldBitmapMask = (HBITMAP) SelectObject(hdcMask, himl->hbmMask);
520         hOldBitmapTemp = (HBITMAP) SelectObject(hdcTemp, hbmMask);
521
522         BitBlt (hdcMask, 
523             nStartX, 0, bmp.bmWidth, bmp.bmHeight,
524             hdcTemp, 
525             0, 0, 
526             SRCCOPY);
527
528         SelectObject(hdcTemp, hOldBitmapTemp);
529         DeleteDC(hdcTemp);
530
531         /* Remove the background from the image
532         */
533         BitBlt (hdcImage, 
534             nStartX, 0, bmp.bmWidth, bmp.bmHeight,
535             hdcMask, 
536             nStartX, 0, 
537             0x220326); /* NOTSRCAND */
538
539         SelectObject(hdcMask, hOldBitmapMask);
540         DeleteDC(hdcMask);
541     }
542
543     SelectObject(hdcImage, hOldBitmapImage);
544     SelectObject(hdcBitmap, hOldBitmap);
545     DeleteDC(hdcImage);
546     DeleteDC(hdcBitmap);
547
548     nFirstIndex = himl->cCurImage;
549     himl->cCurImage += nImageCount;
550
551     return nFirstIndex;
552 }
553
554
555 /*************************************************************************
556  * ImageList_AddIcon [COMCTL32.41]
557  *
558  * Adds an icon to an image list.
559  *
560  * PARAMS
561  *     himl  [I] handle to image list
562  *     hIcon [I] handle to icon
563  *
564  * RETURNS
565  *     Success: index of the new image
566  *     Failure: -1
567  */
568
569 INT WINAPI
570 ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
571 {
572     return ImageList_ReplaceIcon (himl, -1, hIcon);
573 }
574
575
576 /*************************************************************************
577  * ImageList_AddMasked [COMCTL32.42] 
578  *
579  * Adds an image or images to an image list and creates a mask from the
580  * specified bitmap using the mask color.
581  *
582  * PARAMS
583  *     himl    [I] handle to image list.
584  *     hBitmap [I] handle to bitmap
585  *     clrMask [I] mask color.
586  *
587  * RETURNS
588  *     Success: Index of the first new image.
589  *     Failure: -1
590  */
591
592 INT WINAPI
593 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
594 {
595     HDC    hdcImage, hdcMask, hdcBitmap;
596     INT    nIndex, nImageCount, nMaskXOffset=0;
597     BITMAP bmp;
598     HBITMAP hOldBitmap, hOldBitmapMask, hOldBitmapImage;
599     HBITMAP hMaskBitmap=0;
600     COLORREF bkColor;
601
602     TRACE("himl=%p hbitmap=%x clrmask=%lx\n", himl, hBitmap, clrMask);
603     if (himl == NULL)
604         return -1;
605
606     if (!GetObjectA (hBitmap, sizeof(BITMAP), &bmp))
607         return -1;
608
609     nImageCount = bmp.bmWidth / himl->cx;
610
611     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
612
613     nIndex = himl->cCurImage;
614     himl->cCurImage += nImageCount;
615
616     hdcMask   = CreateCompatibleDC (0);
617     hdcImage  = CreateCompatibleDC(0);
618     hdcBitmap = CreateCompatibleDC(0);
619
620
621     hOldBitmapImage = SelectObject(hdcImage, himl->hbmImage);
622     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
623     if(himl->hbmMask)
624     {
625         hOldBitmapMask = SelectObject(hdcMask, himl->hbmMask);
626         nMaskXOffset = nIndex * himl->cx;
627     }
628     else
629     {
630         /*
631             Create a temp Mask so we can remove the background of
632             the Image (Windows does this even if there is no mask)
633         */
634         hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
635         hOldBitmapMask = SelectObject(hdcMask, hMaskBitmap);
636         nMaskXOffset = 0;
637     }
638     /* create monochrome image to the mask bitmap */
639     bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
640         GetPixel (hdcBitmap, 0, 0);
641     SetBkColor (hdcBitmap, bkColor);
642     BitBlt (hdcMask, 
643         nMaskXOffset, 0, bmp.bmWidth, bmp.bmHeight,
644         hdcBitmap, 0, 0, 
645         SRCCOPY);
646
647     SetBkColor(hdcBitmap, RGB(255,255,255));
648     /*Remove the background from the image
649     */
650     /*
651         WINDOWS BUG ALERT!!!!!!
652         The statement below should not be done in common practice
653         but this is how ImageList_AddMasked works in Windows.
654         It overwrites the original bitmap passed, this was discovered
655         by using the same bitmap to iterate the different styles
656         on windows where it failed (BUT ImageList_Add is OK)
657         This is here in case some apps rely on this bug
658     */
659     BitBlt(hdcBitmap, 
660         0, 0, bmp.bmWidth, bmp.bmHeight,
661         hdcMask, 
662         nMaskXOffset, 0, 
663         0x220326); /* NOTSRCAND */
664     /* Copy result to the imagelist
665     */
666     BitBlt (hdcImage, 
667         nIndex * himl->cx, 0, bmp.bmWidth, bmp.bmHeight,
668         hdcBitmap, 
669         0, 0, 
670         SRCCOPY);
671     /* Clean up
672     */
673     SelectObject(hdcMask,hOldBitmapMask);
674     SelectObject(hdcImage, hOldBitmapImage);
675     SelectObject(hdcBitmap, hOldBitmap);
676     DeleteDC(hdcMask);
677     DeleteDC(hdcImage);
678     DeleteDC(hdcBitmap);
679     if(!himl->hbmMask)
680     {
681         DeleteObject(hMaskBitmap);
682     }
683
684     return nIndex;
685 }
686
687
688 /*************************************************************************
689  * ImageList_BeginDrag [COMCTL32.43] 
690  *
691  * Creates a temporary image list that contains one image. It will be used
692  * as a drag image.
693  *
694  * PARAMS
695  *     himlTrack [I] handle to the source image list
696  *     iTrack    [I] index of the drag image in the source image list
697  *     dxHotspot [I] X position of the hot spot of the drag image
698  *     dyHotspot [I] Y position of the hot spot of the drag image
699  *
700  * RETURNS
701  *     Success: TRUE
702  *     Failure: FALSE
703  */
704
705 BOOL WINAPI
706 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
707                      INT dxHotspot, INT dyHotspot)
708 {
709     HDC hdcSrc, hdcDst;
710     INT cx, cy;
711
712     TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
713           dxHotspot, dyHotspot);
714
715     if (himlTrack == NULL)
716         return FALSE;
717
718     if (InternalDrag.himl)
719         ImageList_EndDrag ();
720
721     cx = himlTrack->cx;
722     cy = himlTrack->cy;
723
724     InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
725     if (InternalDrag.himl == NULL) {
726         ERR("Error creating drag image list!\n");
727         return FALSE;
728     }
729
730     InternalDrag.dxHotspot = dxHotspot;
731     InternalDrag.dyHotspot = dyHotspot;
732
733     hdcSrc = CreateCompatibleDC (0);
734     hdcDst = CreateCompatibleDC (0);
735
736     /* copy image */
737     SelectObject (hdcSrc, himlTrack->hbmImage);
738     SelectObject (hdcDst, InternalDrag.himl->hbmImage);
739     BitBlt (hdcDst, 0, 0, cx, cy, hdcSrc, iTrack * cx, 0, SRCCOPY);
740
741     /* copy mask */
742     SelectObject (hdcSrc, himlTrack->hbmMask);
743     SelectObject (hdcDst, InternalDrag.himl->hbmMask);
744     BitBlt (hdcDst, 0, 0, cx, cy, hdcSrc, iTrack * cx, 0, SRCCOPY);
745
746     DeleteDC (hdcSrc);
747     DeleteDC (hdcDst);
748
749     InternalDrag.himl->cCurImage = 1;
750
751     return TRUE;
752 }
753
754
755 /*************************************************************************
756  * ImageList_Copy [COMCTL32.44] 
757  *
758  *  Copies an image of the source image list to an image of the 
759  *  destination image list. Images can be copied or swapped.
760  *
761  * PARAMS
762  *     himlDst [I] handle to the destination image list
763  *     iDst    [I] destination image index.
764  *     himlSrc [I] handle to the source image list
765  *     iSrc    [I] source image index
766  *     uFlags  [I] flags for the copy operation
767  *
768  * RETURNS
769  *     Success: TRUE
770  *     Failure: FALSE
771  *
772  * NOTES
773  *     Copying from one image list to another is possible. The original
774  *     implementation just copies or swaps within one image list.
775  *     Could this feature become a bug??? ;-)
776  */
777
778 BOOL WINAPI
779 ImageList_Copy (HIMAGELIST himlDst, INT iDst,   HIMAGELIST himlSrc,
780                 INT iSrc, INT uFlags)
781 {
782     HDC hdcSrc, hdcDst;    
783
784     TRACE("iDst=%d  iSrc=%d\n", iDst, iSrc);
785
786     if ((himlSrc == NULL) || (himlDst == NULL))
787         return FALSE;
788     if ((iDst < 0) || (iDst >= himlDst->cCurImage))
789         return FALSE;
790     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
791         return FALSE;
792
793     hdcSrc = CreateCompatibleDC (0);
794     if (himlDst == himlSrc)
795         hdcDst = hdcSrc;
796     else
797         hdcDst = CreateCompatibleDC (0);
798
799     if (uFlags & ILCF_SWAP) {
800         /* swap */
801         HBITMAP hbmTempImage, hbmTempMask;
802
803         /* create temporary bitmaps */
804         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
805                                        himlSrc->uBitsPixel, NULL);
806         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
807                                       1, NULL);
808
809         /* copy (and stretch) destination to temporary bitmaps.(save) */
810         /* image */
811         SelectObject (hdcSrc, himlDst->hbmImage);
812         SelectObject (hdcDst, hbmTempImage);
813         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
814                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
815                       SRCCOPY);
816         /* mask */
817         SelectObject (hdcSrc, himlDst->hbmMask);
818         SelectObject (hdcDst, hbmTempMask);
819         StretchBlt (hdcDst, 0, 0, himlSrc->cx, himlSrc->cy,
820                       hdcSrc, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
821                       SRCCOPY);
822
823         /* copy (and stretch) source to destination */
824         /* image */
825         SelectObject (hdcSrc, himlSrc->hbmImage);
826         SelectObject (hdcDst, himlDst->hbmImage);
827         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
828                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
829                       SRCCOPY);
830         /* mask */
831         SelectObject (hdcSrc, himlSrc->hbmMask);
832         SelectObject (hdcDst, himlDst->hbmMask);
833         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
834                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
835                       SRCCOPY);
836
837         /* copy (without stretching) temporary bitmaps to source (restore) */
838         /* image */
839         SelectObject (hdcSrc, hbmTempImage);
840         SelectObject (hdcDst, himlSrc->hbmImage);
841         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
842                   hdcSrc, 0, 0, SRCCOPY);
843         /* mask */
844         SelectObject (hdcSrc, hbmTempMask);
845         SelectObject (hdcDst, himlSrc->hbmMask);
846         BitBlt (hdcDst, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
847                   hdcSrc, 0, 0, SRCCOPY);
848
849         /* delete temporary bitmaps */
850         DeleteObject (hbmTempMask);
851         DeleteObject (hbmTempImage);
852     }
853     else {
854         /* copy image */
855         SelectObject (hdcSrc, himlSrc->hbmImage);
856         if (himlSrc == himlDst)
857             hdcDst = hdcSrc;
858         else
859             SelectObject (hdcDst, himlDst->hbmImage);
860         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
861                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
862                       SRCCOPY);
863
864         /* copy mask */
865         SelectObject (hdcSrc, himlSrc->hbmMask);
866         if (himlSrc == himlDst)
867             hdcDst = hdcSrc;
868         else
869             SelectObject (hdcDst, himlDst->hbmMask);
870         StretchBlt (hdcDst, iDst * himlDst->cx, 0, himlDst->cx, himlDst->cy,
871                       hdcSrc, iSrc * himlSrc->cx, 0, himlSrc->cx, himlSrc->cy,
872                       SRCCOPY);
873     }
874
875     DeleteDC (hdcSrc);
876     if (himlSrc != himlDst)
877         DeleteDC (hdcDst);
878
879     return TRUE;
880 }
881
882
883 /*************************************************************************
884  * ImageList_Create [COMCTL32.45]  Creates a new image list.
885  *
886  * PARAMS
887  *     cx       [I] image height
888  *     cy       [I] image width
889  *     flags    [I] creation flags
890  *     cInitial [I] initial number of images in the image list
891  *     cGrow    [I] number of images by which image list grows
892  *
893  * RETURNS
894  *     Success: Handle to the created image list
895  *     Failure: NULL
896  */
897
898 HIMAGELIST WINAPI
899 ImageList_Create (INT cx, INT cy, UINT flags,
900                   INT cInitial, INT cGrow)
901 {
902     HIMAGELIST himl;
903     HDC      hdc;
904     INT      nCount;
905     HBITMAP  hbmTemp;
906     static WORD aBitBlend25[] = 
907         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
908
909     static WORD aBitBlend50[] =
910         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
911
912     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
913
914     himl = (HIMAGELIST)COMCTL32_Alloc (sizeof(struct _IMAGELIST));
915     if (!himl)
916         return NULL;
917
918     himl->cx        = cx;
919     himl->cy        = cy;
920     himl->flags     = flags;
921     himl->cMaxImage = cInitial + cGrow;
922     himl->cInitial  = cInitial;
923     himl->cGrow     = cGrow;
924     himl->cCurImage = 0;
925     himl->clrFg     = CLR_DEFAULT;
926     himl->clrBk     = CLR_NONE;
927
928     /* initialize overlay mask indices */
929     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
930         himl->nOvlIdx[nCount] = -1;
931
932     hdc = CreateCompatibleDC (0);
933     himl->uBitsPixel = (UINT)GetDeviceCaps (hdc, BITSPIXEL);
934     DeleteDC (hdc);
935
936     TRACE("Image: %d Bits per Pixel\n", himl->uBitsPixel);
937
938     if (himl->cMaxImage > 0) {
939         himl->hbmImage =
940           CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
941                         1, himl->uBitsPixel, NULL);
942         if (himl->hbmImage == 0) {
943             ERR("Error creating image bitmap!\n");
944             return NULL;
945         }
946     }
947     else
948         himl->hbmImage = 0;
949     
950     if ( (himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
951         himl->hbmMask = CreateBitmap (himl->cx * himl->cMaxImage, himl->cy,
952                                         1, 1, NULL);
953         if (himl->hbmMask == 0) {
954             ERR("Error creating mask bitmap!\n");
955             if (himl->hbmImage)
956                 DeleteObject (himl->hbmImage);
957             return NULL;
958         }
959     }
960     else
961         himl->hbmMask = 0;
962
963     /* create blending brushes */
964     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend25);
965     himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
966     DeleteObject (hbmTemp);
967
968     hbmTemp = CreateBitmap (8, 8, 1, 1, &aBitBlend50);
969     himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
970     DeleteObject (hbmTemp);
971
972     TRACE("created imagelist %p\n", himl);
973     return himl;
974 }
975
976
977 /*************************************************************************
978  * ImageList_Destroy [COMCTL32.46] 
979  *
980  * Destroys an image list.
981  *
982  * PARAMS
983  *     himl [I] handle to image list
984  *
985  * RETURNS
986  *     Success: TRUE
987  *     Failure: FALSE
988  */
989
990 BOOL WINAPI
991 ImageList_Destroy (HIMAGELIST himl)
992
993     if (!himl)
994         return FALSE;
995
996     /* delete image bitmaps */
997     if (himl->hbmImage)
998         DeleteObject (himl->hbmImage);
999     if (himl->hbmMask)
1000         DeleteObject (himl->hbmMask);
1001
1002     /* delete blending brushes */
1003     if (himl->hbrBlend25)
1004         DeleteObject (himl->hbrBlend25);
1005     if (himl->hbrBlend50)
1006         DeleteObject (himl->hbrBlend50);
1007         
1008     COMCTL32_Free (himl);
1009
1010     return TRUE;
1011 }
1012
1013
1014 /*************************************************************************
1015  * ImageList_DragEnter [COMCTL32.47] 
1016  *
1017  * Locks window update and displays the drag image at the given position.
1018  *
1019  * PARAMS
1020  *     hwndLock [I] handle of the window that owns the drag image.
1021  *     x        [I] X position of the drag image.
1022  *     y        [I] Y position of the drag image.
1023  *
1024  * RETURNS
1025  *     Success: TRUE
1026  *     Failure: FALSE
1027  *
1028  * NOTES
1029  *     The position of the drag image is relative to the window, not
1030  *     the client area.
1031  */
1032
1033 BOOL WINAPI
1034 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
1035 {
1036     TRACE("(hwnd=%#x x=%d y=%d)\n", hwndLock, x, y);
1037
1038     if (InternalDrag.himl == NULL)
1039         return FALSE;
1040
1041     if (hwndLock)
1042         InternalDrag.hwnd = hwndLock;
1043     else
1044         InternalDrag.hwnd = GetDesktopWindow ();
1045
1046     InternalDrag.x = x;
1047     InternalDrag.y = y;
1048
1049     /* draw the drag image and save the background */
1050     if (!ImageList_DragShowNolock(TRUE)) {
1051         return FALSE;
1052     }
1053
1054     return TRUE;
1055 }
1056
1057
1058 /*************************************************************************
1059  * ImageList_DragLeave [COMCTL32.48] 
1060  *
1061  * Unlocks window update and hides the drag image.
1062  *
1063  * PARAMS
1064  *     hwndLock [I] handle of the window that owns the drag image.
1065  *
1066  * RETURNS
1067  *     Success: TRUE
1068  *     Failure: FALSE
1069  */
1070
1071 BOOL WINAPI
1072 ImageList_DragLeave (HWND hwndLock)
1073 {
1074     if (hwndLock)
1075         InternalDrag.hwnd = hwndLock;
1076     else
1077         InternalDrag.hwnd = GetDesktopWindow ();
1078
1079     ImageList_DragShowNolock (FALSE);
1080
1081     return TRUE;
1082 }
1083
1084
1085 /*************************************************************************
1086  * ImageList_DragMove [COMCTL32.49] 
1087  *
1088  * Moves the drag image.
1089  *
1090  * PARAMS
1091  *     x [I] X position of the drag image.
1092  *     y [I] Y position of the drag image.
1093  *
1094  * RETURNS
1095  *     Success: TRUE
1096  *     Failure: FALSE
1097  *
1098  * NOTES
1099  *     The position of the drag image is relative to the window, not
1100  *     the client area.
1101  *
1102  * BUGS
1103  *     The drag image should be drawn semitransparent.
1104  */
1105
1106 BOOL WINAPI
1107 ImageList_DragMove (INT x, INT y)
1108 {
1109     TRACE("(x=%d y=%d)\n", x, y);
1110
1111     if (!InternalDrag.himl) {
1112         return FALSE;
1113     }
1114
1115     /* draw/update the drag image */
1116     if (InternalDrag.bShow) {
1117         HDC hdcDrag;
1118         HDC hdcOffScreen;
1119         HDC hdcBg;
1120         HBITMAP hbmOffScreen;
1121         INT origNewX, origNewY;
1122         INT origOldX, origOldY;
1123         INT origRegX, origRegY;
1124         INT sizeRegX, sizeRegY;
1125         
1126
1127         /* calculate the update region */
1128         origNewX = x - InternalDrag.dxHotspot;
1129         origNewY = y - InternalDrag.dyHotspot;
1130         origOldX = InternalDrag.x - InternalDrag.dxHotspot;
1131         origOldY = InternalDrag.y - InternalDrag.dyHotspot;
1132         origRegX = min(origNewX, origOldX);
1133         origRegY = min(origNewY, origOldY);
1134         sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
1135         sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
1136
1137         hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
1138                           DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1139         hdcOffScreen = CreateCompatibleDC(hdcDrag);
1140         hdcBg = CreateCompatibleDC(hdcDrag);
1141
1142         hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
1143         SelectObject(hdcOffScreen, hbmOffScreen);
1144         SelectObject(hdcBg, InternalDrag.hbmBg);
1145
1146         /* get the actual background of the update region */
1147         BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
1148                origRegX, origRegY, SRCCOPY);
1149         /* erase the old image */
1150         BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
1151                InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
1152                SRCCOPY);
1153         /* save the background */
1154         BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1155                hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
1156         /* draw the image */
1157         /* FIXME: image should be drawn semitransparent */
1158         ImageList_Draw(InternalDrag.himl, 0, hdcOffScreen, origNewX - origRegX,
1159                        origNewY - origRegY, ILD_NORMAL);
1160         /* draw the update region to the screen */
1161         BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
1162                hdcOffScreen, 0, 0, SRCCOPY);
1163
1164         DeleteDC(hdcBg);
1165         DeleteDC(hdcOffScreen);
1166         DeleteObject(hbmOffScreen);
1167         ReleaseDC(InternalDrag.hwnd, hdcDrag);
1168     }
1169
1170     /* update the image position */
1171     InternalDrag.x = x;
1172     InternalDrag.y = y;
1173
1174     return TRUE;
1175 }
1176
1177
1178 /*************************************************************************
1179  * ImageList_DragShowNolock [COMCTL32.50] 
1180  *
1181  * Shows or hides the drag image.
1182  *
1183  * PARAMS
1184  *     bShow [I] TRUE shows the drag image, FALSE hides it.
1185  *
1186  * RETURNS
1187  *     Success: TRUE
1188  *     Failure: FALSE
1189  *
1190  * BUGS
1191  *     The drag image should be drawn semitransparent.
1192  */
1193
1194 BOOL WINAPI
1195 ImageList_DragShowNolock (BOOL bShow)
1196 {
1197     HDC hdcDrag;
1198     HDC hdcBg;
1199     INT x, y;
1200
1201     TRACE("bShow=0x%X!\n", bShow);
1202
1203     /* DragImage is already visible/hidden */
1204     if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
1205         return FALSE;
1206     }
1207
1208     /* position of the origin of the DragImage */
1209     x = InternalDrag.x - InternalDrag.dxHotspot;
1210     y = InternalDrag.y - InternalDrag.dyHotspot;
1211
1212     hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
1213                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1214     if (!hdcDrag) {
1215         return FALSE;
1216     }
1217
1218     hdcBg = CreateCompatibleDC(hdcDrag);
1219     if (!InternalDrag.hbmBg) {
1220         InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
1221                     InternalDrag.himl->cx, InternalDrag.himl->cy);
1222     }
1223     SelectObject(hdcBg, InternalDrag.hbmBg);
1224     
1225     if (bShow) {
1226         /* save the background */
1227         BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1228                hdcDrag, x, y, SRCCOPY);
1229         /* show the image */
1230         /* FIXME: this should be drawn semitransparent */
1231         ImageList_Draw(InternalDrag.himl, 0, hdcDrag, x, y, ILD_NORMAL);
1232     } else { 
1233         /* hide the image */
1234         BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
1235                hdcBg, 0, 0, SRCCOPY);
1236     }
1237
1238     InternalDrag.bShow = !InternalDrag.bShow;
1239
1240     DeleteDC(hdcBg);
1241     ReleaseDC (InternalDrag.hwnd, hdcDrag);
1242     return TRUE;
1243 }
1244
1245
1246 /*************************************************************************
1247  * ImageList_Draw [COMCTL32.51] Draws an image.
1248  *
1249  * PARAMS
1250  *     himl   [I] handle to image list
1251  *     i      [I] image index
1252  *     hdc    [I] handle to device context
1253  *     x      [I] x position
1254  *     y      [I] y position
1255  *     fStyle [I] drawing flags
1256  *
1257  * RETURNS
1258  *     Success: TRUE
1259  *     Failure: FALSE
1260  *
1261  * NOTES
1262  *     Calls ImageList_DrawIndirect.
1263  *
1264  * SEE
1265  *     ImageList_DrawIndirect.
1266  */
1267
1268 BOOL WINAPI
1269 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc,
1270                 INT x, INT y, UINT fStyle)
1271 {
1272     IMAGELISTDRAWPARAMS imldp;
1273
1274     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
1275     imldp.himl    = himl;
1276     imldp.i       = i;
1277     imldp.hdcDst  = hdc,
1278     imldp.x       = x;
1279     imldp.y       = y;
1280     imldp.cx      = 0;
1281     imldp.cy      = 0;
1282     imldp.xBitmap = 0;
1283     imldp.yBitmap = 0;
1284     imldp.rgbBk   = CLR_DEFAULT;
1285     imldp.rgbFg   = CLR_DEFAULT;
1286     imldp.fStyle  = fStyle;
1287     imldp.dwRop   = 0;
1288
1289     return ImageList_DrawIndirect (&imldp);
1290 }
1291
1292
1293 /*************************************************************************
1294  * ImageList_DrawEx [COMCTL32.52]
1295  *
1296  * Draws an image and allows to use extended drawing features.
1297  *
1298  * PARAMS
1299  *     himl   [I] handle to image list
1300  *     i      [I] image index
1301  *     hdc    [I] handle to device context
1302  *     x      [I] X position
1303  *     y      [I] Y position
1304  *     xOffs  [I] X offset
1305  *     yOffs  [I] Y offset
1306  *     rgbBk  [I] background color
1307  *     rgbFg  [I] foreground color
1308  *     fStyle [I] drawing flags
1309  *
1310  * RETURNS
1311  *     Success: TRUE
1312  *     Failure: FALSE
1313  *
1314  * NOTES
1315  *     Calls ImageList_DrawIndirect.
1316  *
1317  * SEE
1318  *     ImageList_DrawIndirect.
1319  */
1320
1321 BOOL WINAPI
1322 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1323                   INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1324                   UINT fStyle)
1325 {
1326     IMAGELISTDRAWPARAMS imldp;
1327
1328     imldp.cbSize  = sizeof(IMAGELISTDRAWPARAMS);
1329     imldp.himl    = himl;
1330     imldp.i       = i;
1331     imldp.hdcDst  = hdc,
1332     imldp.x       = x;
1333     imldp.y       = y;
1334     imldp.cx      = dx;
1335     imldp.cy      = dy;
1336     imldp.xBitmap = 0;
1337     imldp.yBitmap = 0;
1338     imldp.rgbBk   = rgbBk;
1339     imldp.rgbFg   = rgbFg;
1340     imldp.fStyle  = fStyle;
1341     imldp.dwRop   = 0;
1342
1343     return ImageList_DrawIndirect (&imldp);
1344 }
1345
1346
1347 /*************************************************************************
1348  * ImageList_DrawIndirect [COMCTL32.53] 
1349  *
1350  * Draws an image using ...
1351  *
1352  * PARAMS
1353  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1354  *
1355  * RETURNS
1356  *     Success: TRUE
1357  *     Failure: FALSE
1358  */
1359
1360 BOOL WINAPI
1361 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1362 {
1363     INT      cx, cy;    
1364     /* 
1365         Do some Error Checking
1366     */
1367     if (pimldp == NULL)
1368         return FALSE;
1369     if (pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS))
1370         return FALSE;
1371     if (pimldp->himl == NULL)
1372         return FALSE;
1373     if ((pimldp->i < 0) || (pimldp->i >= pimldp->himl->cCurImage)) {
1374         ERR("%d not within range (max %d)\n",pimldp->i,pimldp->himl->cCurImage-1);
1375         return FALSE;
1376     }
1377     /*
1378         Get the Height and Width to display
1379     */
1380     cx = (pimldp->cx == 0) ? pimldp->himl->cx : pimldp->cx;
1381     cy = (pimldp->cy == 0) ? pimldp->himl->cy : pimldp->cy;
1382     /*
1383         Draw the image
1384     */
1385     if(pimldp->himl->hbmMask != 0)
1386     {
1387         IMAGELIST_InternalDrawMask(pimldp, cx, cy);
1388     }
1389     else
1390     {
1391         IMAGELIST_InternalDraw(pimldp, cx, cy);
1392     }
1393     /* 
1394         Apply the blend if needed to the Image
1395     */
1396     if((pimldp->fStyle & ILD_BLEND50)
1397         || (pimldp->fStyle & ILD_BLEND25))
1398     {
1399         IMAGELIST_InternalDrawBlend(pimldp, cx, cy);
1400     }
1401     /*
1402         Apply the Overlay if needed
1403     */
1404     if (pimldp->fStyle & ILD_OVERLAYMASK)
1405     {
1406         IMAGELIST_InternalDrawOverlay(pimldp, cx, cy);
1407     }
1408
1409     return TRUE;
1410 }
1411
1412
1413 /*************************************************************************
1414  * ImageList_Duplicate [COMCTL32.54] Duplicates an image list.
1415  *
1416  * PARAMS
1417  *     himlSrc [I] source image list handle
1418  *
1419  * RETURNS
1420  *     Success: Handle of duplicated image list.
1421  *     Failure: NULL
1422  */
1423
1424 HIMAGELIST WINAPI
1425 ImageList_Duplicate (HIMAGELIST himlSrc)
1426 {
1427     HIMAGELIST himlDst;
1428     HDC hdcSrc, hdcDst;
1429
1430     if (himlSrc == NULL) {
1431         ERR("Invalid image list handle!\n");
1432         return NULL;
1433     }
1434
1435     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1436                                 himlSrc->cInitial, himlSrc->cGrow);
1437
1438     if (himlDst)
1439     {
1440         hdcSrc = CreateCompatibleDC (0);
1441         hdcDst = CreateCompatibleDC (0);
1442         SelectObject (hdcSrc, himlSrc->hbmImage);
1443         SelectObject (hdcDst, himlDst->hbmImage);
1444         BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx, himlSrc->cy,
1445                   hdcSrc, 0, 0, SRCCOPY);
1446
1447         if (himlDst->hbmMask)
1448         {
1449             SelectObject (hdcSrc, himlSrc->hbmMask);
1450             SelectObject (hdcDst, himlDst->hbmMask);
1451             BitBlt (hdcDst, 0, 0, himlSrc->cCurImage * himlSrc->cx,
1452                       himlSrc->cy, hdcSrc, 0, 0, SRCCOPY);
1453         }
1454
1455         DeleteDC (hdcDst);
1456         DeleteDC (hdcSrc);
1457
1458         himlDst->cCurImage = himlSrc->cCurImage;
1459         himlDst->cMaxImage = himlSrc->cMaxImage;
1460     }
1461     return himlDst;
1462 }
1463
1464
1465 /*************************************************************************
1466  * ImageList_EndDrag [COMCTL32.55] Finishes a drag operation.
1467  *
1468  * Finishes a drag operation.
1469  *
1470  * PARAMS
1471  *     no Parameters
1472  *
1473  * RETURNS
1474  *     Success: TRUE
1475  *     Failure: FALSE
1476  */
1477
1478 BOOL WINAPI
1479 ImageList_EndDrag (void)
1480 {
1481     /* cleanup the InternalDrag struct */
1482     InternalDrag.hwnd = 0;
1483     ImageList_Destroy (InternalDrag.himl);
1484     InternalDrag.himl = 0;
1485     InternalDrag.x= 0;
1486     InternalDrag.y= 0;
1487     InternalDrag.dxHotspot = 0;
1488     InternalDrag.dyHotspot = 0;
1489     InternalDrag.bShow = FALSE;
1490     DeleteObject(InternalDrag.hbmBg);
1491     InternalDrag.hbmBg = 0;
1492
1493     return TRUE;
1494 }
1495
1496
1497 /*************************************************************************
1498  * ImageList_GetBkColor [COMCTL32.56]
1499  *
1500  * Returns the background color of an image list.
1501  *
1502  * PARAMS
1503  *     himl [I] Image list handle.
1504  *
1505  * RETURNS
1506  *     Success: background color
1507  *     Failure: CLR_NONE
1508  */
1509
1510 COLORREF WINAPI
1511 ImageList_GetBkColor (HIMAGELIST himl)
1512 {
1513     if (himl == NULL)
1514         return CLR_NONE;
1515
1516     return himl->clrBk;
1517 }
1518
1519
1520 /*************************************************************************
1521  * ImageList_GetDragImage [COMCTL32.57]
1522  *
1523  * Returns the handle to the internal drag image list.
1524  *
1525  * PARAMS
1526  *     ppt        [O] Pointer to the drag position. Can be NULL.
1527  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1528  *
1529  * RETURNS
1530  *     Success: Handle of the drag image list.
1531  *     Failure: NULL.
1532  */
1533
1534 HIMAGELIST WINAPI
1535 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1536 {
1537     if (InternalDrag.himl) {
1538         if (ppt) {
1539             ppt->x = InternalDrag.x;
1540             ppt->y = InternalDrag.y;
1541         }
1542         if (pptHotspot) {
1543             pptHotspot->x = InternalDrag.dxHotspot;
1544             pptHotspot->y = InternalDrag.dyHotspot;
1545         }
1546         return (InternalDrag.himl);
1547     }
1548
1549     return NULL;
1550 }
1551
1552
1553 /*************************************************************************
1554  * ImageList_GetIcon [COMCTL32.59] 
1555  *
1556  * Creates an icon from a masked image of an image list.
1557  *
1558  * PARAMS
1559  *     himl  [I] handle to image list
1560  *     i     [I] image index
1561  *     flags [I] drawing style flags
1562  *
1563  * RETURNS
1564  *     Success: icon handle
1565  *     Failure: NULL
1566  */
1567
1568 HICON WINAPI
1569 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1570 {
1571     ICONINFO ii;
1572     HICON  hIcon;
1573     HBITMAP hOldSrcBitmap,hOldDstBitmap;
1574     HDC    hdcSrc, hdcDst;
1575
1576     if ((himl == NULL) || (i < 0) || (i >= himl->cCurImage)) {
1577         FIXME("(%p,%d,%x), params out of range!\n",himl,i,fStyle);
1578         return 0;
1579    }
1580
1581     hdcSrc = CreateCompatibleDC(0);
1582     hdcDst = CreateCompatibleDC(0);
1583
1584     ii.fIcon = TRUE;
1585     ii.hbmMask  = CreateCompatibleBitmap (hdcDst, himl->cx, himl->cy);
1586
1587     /* draw mask*/
1588     hOldDstBitmap = (HBITMAP)SelectObject (hdcDst, ii.hbmMask);
1589     if (himl->hbmMask) {
1590         SelectObject (hdcSrc, himl->hbmMask);
1591         BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1592                   hdcSrc, i * himl->cx, 0, SRCCOPY);
1593     }
1594     else
1595         PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1596
1597     /* draw image*/
1598     hOldSrcBitmap = (HBITMAP)SelectObject (hdcSrc, himl->hbmImage);
1599     ii.hbmColor = CreateCompatibleBitmap (hdcSrc, himl->cx, himl->cy);
1600     SelectObject (hdcDst, ii.hbmColor);
1601     BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1602               hdcSrc, i * himl->cx, 0, SRCCOPY);
1603
1604     /*
1605      * CreateIconIndirect requires us to deselect the bitmaps from
1606      * the DCs before calling 
1607      */
1608     SelectObject(hdcSrc, hOldSrcBitmap);
1609     SelectObject(hdcDst, hOldDstBitmap);
1610
1611     hIcon = CreateIconIndirect (&ii);    
1612
1613     DeleteDC (hdcSrc);
1614     DeleteDC (hdcDst);
1615     DeleteObject (ii.hbmMask);
1616     DeleteObject (ii.hbmColor);
1617
1618     return hIcon;
1619 }
1620
1621
1622 /*************************************************************************
1623  * ImageList_GetIconSize [COMCTL32.60]
1624  *
1625  * Retrieves the size of an image in an image list.
1626  *
1627  * PARAMS
1628  *     himl [I] handle to image list
1629  *     cx   [O] pointer to the image width.
1630  *     cy   [O] pointer to the image height.
1631  *
1632  * RETURNS
1633  *     Success: TRUE
1634  *     Failure: FALSE
1635  *
1636  * NOTES
1637  *     All images in an image list have the same size.
1638  */
1639
1640 BOOL WINAPI
1641 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1642 {
1643     if (himl == NULL)
1644         return FALSE;
1645     if ((himl->cx <= 0) || (himl->cy <= 0))
1646         return FALSE;
1647
1648     if (cx)
1649         *cx = himl->cx;
1650     if (cy)
1651         *cy = himl->cy;
1652
1653     return TRUE;
1654 }
1655
1656
1657 /*************************************************************************
1658  * ImageList_GetImageCount [COMCTL32.61]
1659  *
1660  * Returns the number of images in an image list.
1661  *
1662  * PARAMS
1663  *     himl [I] handle to image list
1664  *
1665  * RETURNS
1666  *     Success: Number of images.
1667  *     Failure: 0
1668  */
1669
1670 INT WINAPI
1671 ImageList_GetImageCount (HIMAGELIST himl)
1672 {
1673     if (himl == NULL)
1674         return 0;
1675
1676     return himl->cCurImage;
1677 }
1678
1679
1680 /*************************************************************************
1681  * ImageList_GetImageInfo [COMCTL32.62]
1682  *
1683  * Returns information about an image in an image list.
1684  *
1685  * PARAMS
1686  *     himl       [I] handle to image list
1687  *     i          [I] image index
1688  *     pImageInfo [O] pointer to the image information
1689  *
1690  * RETURNS
1691  *     Success: TRUE
1692  *     Failure: FALSE
1693  */
1694
1695 BOOL WINAPI
1696 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1697 {
1698     if ((himl == NULL) || (pImageInfo == NULL))
1699         return FALSE;
1700     if ((i < 0) || (i >= himl->cCurImage))
1701         return FALSE;
1702
1703     pImageInfo->hbmImage = himl->hbmImage;
1704     pImageInfo->hbmMask  = himl->hbmMask;
1705     
1706     pImageInfo->rcImage.top    = 0;
1707     pImageInfo->rcImage.bottom = himl->cy;
1708     pImageInfo->rcImage.left   = i * himl->cx;
1709     pImageInfo->rcImage.right  = (i+1) * himl->cx;
1710     
1711     return TRUE;
1712 }
1713
1714
1715 /*************************************************************************
1716  * ImageList_GetImageRect [COMCTL32.63] 
1717  *
1718  * Retrieves the rectangle of the specified image in an image list.
1719  *
1720  * PARAMS
1721  *     himl   [I] handle to image list
1722  *     i      [I] image index
1723  *     lpRect [O] pointer to the image rectangle
1724  *
1725  * RETURNS
1726  *    Success: TRUE
1727  *    Failure: FALSE
1728  *
1729  * NOTES
1730  *    This is an UNDOCUMENTED function!!!
1731  */
1732
1733 BOOL WINAPI
1734 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1735 {
1736     if ((himl == NULL) || (lpRect == NULL))
1737         return FALSE;
1738     if ((i < 0) || (i >= himl->cCurImage))
1739         return FALSE;
1740
1741     lpRect->left   = i * himl->cx;
1742     lpRect->top    = 0;
1743     lpRect->right  = lpRect->left + himl->cx;
1744     lpRect->bottom = himl->cy;
1745
1746     return TRUE;
1747 }
1748
1749
1750 /*************************************************************************
1751  * ImageList_LoadImage  [COMCTL32.64]
1752  * ImageList_LoadImageA [COMCTL32.65]
1753  *
1754  * Creates an image list from a bitmap, icon or cursor.
1755  *
1756  * PARAMS
1757  *     hi      [I] instance handle
1758  *     lpbmp   [I] name or id of the image
1759  *     cx      [I] width of each image
1760  *     cGrow   [I] number of images to expand
1761  *     clrMask [I] mask color
1762  *     uType   [I] type of image to load
1763  *     uFlags  [I] loading flags
1764  *
1765  * RETURNS
1766  *     Success: handle to the loaded image list
1767  *     Failure: NULL
1768  *
1769  * SEE
1770  *     LoadImage ()
1771  */
1772
1773 HIMAGELIST WINAPI
1774 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1775                         COLORREF clrMask, UINT uType, UINT uFlags)
1776 {
1777     HIMAGELIST himl = NULL;
1778     HANDLE   handle;
1779     INT      nImageCount;
1780
1781     handle = LoadImageA (hi, lpbmp, uType, 0, 0, uFlags);
1782     if (!handle) {
1783         ERR("Error loading image!\n");
1784         return NULL;
1785     }
1786
1787     if (uType == IMAGE_BITMAP) {
1788         BITMAP bmp;
1789         GetObjectA (handle, sizeof(BITMAP), &bmp);
1790
1791         /* To match windows behavior, if cx is set to zero and
1792          the flag DI_DEFAULTSIZE is specified, cx becomes the
1793          system metric value for icons. If the flag is not specified
1794          the function sets the size to the height of the bitmap */
1795         if (cx == 0)
1796         {
1797             if (uFlags & DI_DEFAULTSIZE)
1798                 cx = GetSystemMetrics (SM_CXICON);
1799             else
1800                 cx = bmp.bmHeight;
1801         }
1802
1803         nImageCount = bmp.bmWidth / cx;
1804
1805         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1806                                  nImageCount, cGrow);
1807         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1808     }
1809     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1810         ICONINFO ii;
1811         BITMAP bmp;
1812
1813         GetIconInfo (handle, &ii);
1814         GetObjectA (ii.hbmColor, sizeof(BITMAP), (LPVOID)&bmp);
1815         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1816                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1817         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1818         DeleteObject (ii.hbmColor);
1819         DeleteObject (ii.hbmMask);
1820     }
1821
1822     DeleteObject (handle);
1823     
1824     return himl;
1825 }
1826
1827
1828 /*************************************************************************
1829  * ImageList_LoadImageW [COMCTL32.66]
1830  *
1831  * Creates an image list from a bitmap, icon or cursor.
1832  *
1833  * PARAMS
1834  *     hi      [I] instance handle
1835  *     lpbmp   [I] name or id of the image
1836  *     cx      [I] width of each image
1837  *     cGrow   [I] number of images to expand
1838  *     clrMask [I] mask color
1839  *     uType   [I] type of image to load
1840  *     uFlags  [I] loading flags
1841  *
1842  * RETURNS
1843  *     Success: handle to the loaded image list
1844  *     Failure: NULL
1845  *
1846  * SEE
1847  *     LoadImage ()
1848  */
1849
1850 HIMAGELIST WINAPI
1851 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1852                         COLORREF clrMask, UINT uType,   UINT uFlags)
1853 {
1854     HIMAGELIST himl = NULL;
1855     HANDLE   handle;
1856     INT      nImageCount;
1857
1858     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1859     if (!handle) {
1860         ERR("Error loading image!\n");
1861         return NULL;
1862     }
1863
1864     if (uType == IMAGE_BITMAP) {
1865         BITMAP bmp;
1866         GetObjectA (handle, sizeof(BITMAP), &bmp);
1867         nImageCount = bmp.bmWidth / cx;
1868
1869         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1870                                  nImageCount, cGrow);
1871         ImageList_AddMasked (himl, (HBITMAP)handle, clrMask);
1872     }
1873     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1874         ICONINFO ii;
1875         BITMAP bmp;
1876
1877         GetIconInfo (handle, &ii);
1878         GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
1879         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight, 
1880                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1881         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1882         DeleteObject (ii.hbmColor);
1883         DeleteObject (ii.hbmMask);
1884     }
1885
1886     DeleteObject (handle);
1887     
1888     return himl;
1889 }
1890
1891
1892 /*************************************************************************
1893  * ImageList_Merge [COMCTL32.67] 
1894  *
1895  * Creates a new image list that contains a merged image from the specified
1896  * images of both source image lists.
1897  *
1898  * PARAMS
1899  *     himl1 [I] handle to first image list
1900  *     i1    [I] first image index
1901  *     himl2 [I] handle to second image list
1902  *     i2    [I] second image index
1903  *     dx    [I] X offset of the second image relative to the first.
1904  *     dy    [I] Y offset of the second image relative to the first.
1905  *
1906  * RETURNS
1907  *     Success: handle of the merged image list.
1908  *     Failure: NULL
1909  */
1910
1911 HIMAGELIST WINAPI
1912 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1913                  INT dx, INT dy)
1914 {
1915     HIMAGELIST himlDst = NULL;
1916     HDC      hdcSrcImage, hdcDstImage;
1917     INT      cxDst, cyDst;
1918     INT      xOff1, yOff1, xOff2, yOff2;
1919     INT      nX1, nX2;
1920
1921     TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
1922            i2, dx, dy);
1923
1924     if ((himl1 == NULL) || (himl2 == NULL))
1925         return NULL;
1926
1927     /* check indices */
1928     if ((i1 < 0) || (i1 >= himl1->cCurImage)) {
1929         ERR("Index 1 out of range! %d\n", i1);
1930         return NULL;
1931     }
1932
1933     if ((i2 < 0) || (i2 >= himl2->cCurImage)) {
1934         ERR("Index 2 out of range! %d\n", i2);
1935         return NULL;
1936     }
1937
1938     if (dx > 0) {
1939         cxDst = max (himl1->cx, dx + himl2->cx);
1940         xOff1 = 0;
1941         xOff2 = dx;
1942     }
1943     else if (dx < 0) {
1944         cxDst = max (himl2->cx, himl1->cx - dx);
1945         xOff1 = -dx;
1946         xOff2 = 0;
1947     }
1948     else {
1949         cxDst = max (himl1->cx, himl2->cx);
1950         xOff1 = 0;
1951         xOff2 = 0;
1952     }
1953
1954     if (dy > 0) {
1955         cyDst = max (himl1->cy, dy + himl2->cy);
1956         yOff1 = 0;
1957         yOff2 = dy;
1958     }
1959     else if (dy < 0) {
1960         cyDst = max (himl2->cy, himl1->cy - dy);
1961         yOff1 = -dy;
1962         yOff2 = 0;
1963     }
1964     else {
1965         cyDst = max (himl1->cy, himl2->cy);
1966         yOff1 = 0;
1967         yOff2 = 0;
1968     }
1969
1970     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1971
1972     if (himlDst) {
1973         hdcSrcImage = CreateCompatibleDC (0);
1974         hdcDstImage = CreateCompatibleDC (0);
1975         nX1 = i1 * himl1->cx;
1976         nX2 = i2 * himl2->cx;
1977         
1978         /* copy image */
1979         SelectObject (hdcSrcImage, himl1->hbmImage);
1980         SelectObject (hdcDstImage, himlDst->hbmImage);
1981         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1982                   hdcSrcImage, 0, 0, BLACKNESS);
1983         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
1984                   hdcSrcImage, nX1, 0, SRCCOPY);
1985
1986         SelectObject (hdcSrcImage, himl2->hbmMask);
1987         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1988                   hdcSrcImage, nX2, 0, SRCAND);
1989
1990         SelectObject (hdcSrcImage, himl2->hbmImage);
1991         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
1992                   hdcSrcImage, nX2, 0, SRCPAINT);
1993
1994         /* copy mask */
1995         SelectObject (hdcSrcImage, himl1->hbmMask);
1996         SelectObject (hdcDstImage, himlDst->hbmMask);
1997         BitBlt (hdcDstImage, 0, 0, cxDst, cyDst, 
1998                   hdcSrcImage, 0, 0, WHITENESS);
1999         BitBlt (hdcDstImage, xOff1, yOff1, himl1->cx, himl1->cy, 
2000                   hdcSrcImage, nX1, 0, SRCCOPY);
2001
2002         SelectObject (hdcSrcImage, himl2->hbmMask);
2003         BitBlt (hdcDstImage, xOff2, yOff2, himl2->cx, himl2->cy, 
2004                   hdcSrcImage, nX2, 0, SRCAND);
2005
2006         DeleteDC (hdcSrcImage);
2007         DeleteDC (hdcDstImage);
2008         himlDst->cCurImage = 1;
2009     }
2010    
2011     return himlDst;
2012 }
2013
2014
2015 /* helper for _read_bitmap currently unused */
2016 #if 0
2017 static int may_use_dibsection(HDC hdc) {
2018     int bitspixel = GetDeviceCaps(hdc,BITSPIXEL)*GetDeviceCaps(hdc,PLANES);
2019     if (bitspixel>8)
2020         return TRUE;
2021     if (bitspixel<=4)
2022         return FALSE;
2023     return GetDeviceCaps(hdc,CAPS1) & C1_DIBENGINE;
2024 }
2025 #endif
2026
2027 /* helper for ImageList_Read, see comments below */
2028 static HBITMAP _read_bitmap(LPSTREAM pstm,int ilcFlag,int cx,int cy) {
2029     HDC                 xdc = 0;
2030     BITMAPFILEHEADER    bmfh;
2031     BITMAPINFOHEADER    bmih;
2032     int                 bitsperpixel,palspace,longsperline,width,height;
2033     LPBITMAPINFOHEADER  bmihc = NULL;
2034     int                 result = 0;
2035     HBITMAP             hbitmap = 0;
2036     LPBYTE              bits = NULL,nbits = NULL;
2037     int                 nbytesperline,bytesperline;
2038
2039     if (!SUCCEEDED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL))     ||
2040         (bmfh.bfType != (('M'<<8)|'B'))                                 ||
2041         !SUCCEEDED(IStream_Read ( pstm, &bmih, sizeof(bmih), NULL))     ||
2042         (bmih.biSize != sizeof(bmih))
2043     )
2044         return 0;
2045
2046     bitsperpixel = bmih.biPlanes * bmih.biBitCount;
2047     if (bitsperpixel<=8)
2048         palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
2049     else
2050         palspace = 0;
2051     width = bmih.biWidth;
2052     height = bmih.biHeight;
2053     bmihc = (LPBITMAPINFOHEADER)LocalAlloc(LMEM_ZEROINIT,sizeof(bmih)+palspace);
2054     memcpy(bmihc,&bmih,sizeof(bmih));
2055     longsperline        = ((width*bitsperpixel+31)&~0x1f)>>5;
2056     bmihc->biSizeImage  = (longsperline*height)<<2;
2057
2058     /* read the palette right after the end of the bitmapinfoheader */
2059     if (palspace)
2060         if (!SUCCEEDED(IStream_Read ( pstm, bmihc+1, palspace, NULL)))
2061             goto ret1;
2062
2063     xdc = GetDC(0);
2064 #if 0 /* Magic for NxM -> 1x(N*M) not implemented for DIB Sections */
2065     if ((bitsperpixel>1) &&
2066         ((ilcFlag!=ILC_COLORDDB) && (!ilcFlag || may_use_dibsection(xdc)))
2067      ) {
2068         hbitmap = CreateDIBSection(xdc,(BITMAPINFO*)bmihc,0,(LPVOID*)&bits,0,0);
2069         if (!hbitmap)
2070             goto ret1;
2071         if (!SUCCEEDED(IStream_Read( pstm, bits, bmihc->biSizeImage, NULL)))
2072             goto ret1;
2073         result = 1;
2074     } else
2075 #endif
2076     {
2077         int i,nwidth,nheight;
2078
2079         nwidth  = width*(height/cy);
2080         nheight = cy;
2081
2082         if (bitsperpixel==1)
2083             hbitmap = CreateBitmap(nwidth,nheight,1,1,NULL);
2084         else
2085             hbitmap = CreateCompatibleBitmap(xdc,nwidth,nheight);
2086
2087         /* Might be a bit excessive memory use here */
2088         bits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2089         nbits = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,bmihc->biSizeImage);
2090         if (!SUCCEEDED(IStream_Read ( pstm, bits, bmihc->biSizeImage, NULL)))
2091                 goto ret1;
2092
2093         /* Copy the NxM bitmap into a 1x(N*M) bitmap we need, linewise */
2094         /* Do not forget that windows bitmaps are bottom->top */
2095         bytesperline    = longsperline*4;
2096         nbytesperline   = (height/cy)*bytesperline;
2097         for (i=0;i<height;i++) {
2098             memcpy(
2099                 nbits+((height-1-i)%cy)*nbytesperline+(i/cy)*bytesperline,
2100                 bits+bytesperline*(height-1-i),
2101                 bytesperline
2102             );
2103         }
2104         bmihc->biWidth  = nwidth;
2105         bmihc->biHeight = nheight;
2106         if (!SetDIBits(xdc,hbitmap,0,nheight,nbits,(BITMAPINFO*)bmihc,0))
2107                 goto ret1;
2108         LocalFree((HLOCAL)nbits);
2109         LocalFree((HLOCAL)bits);
2110         result = 1;
2111     }
2112 ret1:
2113     if (xdc)    ReleaseDC(0,xdc);
2114     if (bmihc)  LocalFree((HLOCAL)bmihc);
2115     if (!result) {
2116         if (hbitmap) {
2117             DeleteObject(hbitmap);
2118             hbitmap = 0;
2119         }
2120     }
2121     return hbitmap;
2122 }
2123
2124 /*************************************************************************
2125  * ImageList_Read [COMCTL32.68]
2126  *
2127  * Reads an image list from a stream.
2128  *
2129  * PARAMS
2130  *     pstm [I] pointer to a stream
2131  *
2132  * RETURNS
2133  *     Success: handle to image list
2134  *     Failure: NULL
2135  *
2136  * The format is like this:
2137  *      ILHEAD                  ilheadstruct;
2138  *
2139  * for the color image part:
2140  *      BITMAPFILEHEADER        bmfh; 
2141  *      BITMAPINFOHEADER        bmih;
2142  * only if it has a palette:
2143  *      RGBQUAD         rgbs[nr_of_paletted_colors]; 
2144  *
2145  *      BYTE                    colorbits[imagesize];
2146  *
2147  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2148  *      BITMAPFILEHEADER        bmfh_mask;
2149  *      BITMAPINFOHEADER        bmih_mask;
2150  * only if it has a palette (it usually does not):
2151  *      RGBQUAD         rgbs[nr_of_paletted_colors]; 
2152  *
2153  *      BYTE                    maskbits[imagesize];
2154  *
2155  * CAVEAT: Those images are within a NxM bitmap, not the 1xN we expect.
2156  *         _read_bitmap needs to convert them.
2157  */
2158 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
2159 {
2160     ILHEAD      ilHead;
2161     HIMAGELIST  himl;
2162     HBITMAP     hbmColor=0,hbmMask=0;
2163     int         i;
2164
2165     if (!SUCCEEDED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2166         return NULL;
2167     if (ilHead.usMagic != (('L' << 8) | 'I'))
2168         return NULL;
2169     if (ilHead.usVersion != 0x101) /* probably version? */
2170         return NULL;
2171
2172 #if 0
2173     FIXME("     ilHead.cCurImage = %d\n",ilHead.cCurImage);
2174     FIXME("     ilHead.cMaxImage = %d\n",ilHead.cMaxImage);
2175     FIXME("     ilHead.cGrow = %d\n",ilHead.cGrow);
2176     FIXME("     ilHead.cx = %d\n",ilHead.cx);
2177     FIXME("     ilHead.cy = %d\n",ilHead.cy);
2178     FIXME("     ilHead.flags = %x\n",ilHead.flags);
2179     FIXME("     ilHead.ovls[0] = %d\n",ilHead.ovls[0]);
2180     FIXME("     ilHead.ovls[1] = %d\n",ilHead.ovls[1]);
2181     FIXME("     ilHead.ovls[2] = %d\n",ilHead.ovls[2]);
2182     FIXME("     ilHead.ovls[3] = %d\n",ilHead.ovls[3]);
2183 #endif
2184
2185     hbmColor = _read_bitmap(pstm,ilHead.flags & ~ILC_MASK,ilHead.cx,ilHead.cy);
2186     if (!hbmColor)
2187         return NULL;
2188     if (ilHead.flags & ILC_MASK) {
2189         hbmMask = _read_bitmap(pstm,0,ilHead.cx,ilHead.cy);
2190         if (!hbmMask) {
2191             DeleteObject(hbmColor);
2192             return NULL;
2193         }
2194     }
2195
2196     himl = ImageList_Create (
2197                     ilHead.cx,
2198                     ilHead.cy,
2199                     ilHead.flags,
2200                     1,          /* initial */
2201                     ilHead.cGrow
2202     );
2203     if (!himl) {
2204         DeleteObject(hbmColor);
2205         DeleteObject(hbmMask);
2206         return NULL;
2207     }
2208     himl->hbmImage = hbmColor;
2209     himl->hbmMask = hbmMask;
2210     himl->cCurImage = ilHead.cCurImage;
2211     himl->cMaxImage = ilHead.cMaxImage;
2212
2213     ImageList_SetBkColor(himl,ilHead.bkcolor);
2214     for (i=0;i<4;i++)
2215         ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2216     return himl;
2217 }
2218
2219
2220 /*************************************************************************
2221  * ImageList_Remove [COMCTL32.69] Removes an image from an image list
2222  *
2223  * PARAMS
2224  *     himl [I] image list handle
2225  *     i    [I] image index
2226  *
2227  * RETURNS
2228  *     Success: TRUE
2229  *     Failure: FALSE
2230  */
2231
2232 BOOL WINAPI
2233 ImageList_Remove (HIMAGELIST himl, INT i)
2234 {
2235     HBITMAP hbmNewImage, hbmNewMask;
2236     HDC     hdcSrc, hdcDst;
2237     INT     cxNew, nCount;
2238
2239     if (himl == NULL) {
2240         ERR("Invalid image list handle!\n");
2241         return FALSE;
2242     }
2243     
2244     if ((i < -1) || (i >= himl->cCurImage)) {
2245         ERR("index out of range! %d\n", i);
2246         return FALSE;
2247     }
2248
2249     if (himl->cCurImage == 0) {
2250         ERR("image list is already empty!\n");
2251         return FALSE;
2252     }
2253
2254     if (i == -1) {
2255         /* remove all */
2256         TRACE("remove all!\n");
2257
2258         himl->cMaxImage = himl->cInitial + himl->cGrow;
2259         himl->cCurImage = 0;
2260         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2261              himl->nOvlIdx[nCount] = -1;
2262
2263         DeleteObject (himl->hbmImage);
2264         himl->hbmImage =
2265             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2266                             1, himl->uBitsPixel, NULL);
2267
2268         if (himl->hbmMask) {
2269             DeleteObject (himl->hbmMask);
2270             himl->hbmMask =
2271                 CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2272                                 1, 1, NULL);
2273         }
2274     }
2275     else {
2276         /* delete one image */
2277         TRACE("Remove single image! %d\n", i);
2278
2279         /* create new bitmap(s) */
2280         cxNew = (himl->cCurImage + himl->cGrow - 1) * himl->cx;
2281
2282         TRACE(" - Number of images: %d / %d (Old/New)\n",
2283                  himl->cCurImage, himl->cCurImage - 1);
2284         TRACE(" - Max. number of images: %d / %d (Old/New)\n",
2285                  himl->cMaxImage, himl->cCurImage + himl->cGrow - 1);
2286         
2287         hbmNewImage =
2288             CreateBitmap (cxNew, himl->cy, 1, himl->uBitsPixel, NULL);
2289
2290         if (himl->hbmMask)
2291             hbmNewMask = CreateBitmap (cxNew, himl->cy, 1, 1, NULL);
2292         else
2293             hbmNewMask = 0;  /* Just to keep compiler happy! */
2294
2295         hdcSrc = CreateCompatibleDC (0);
2296         hdcDst = CreateCompatibleDC (0);
2297
2298         /* copy all images and masks prior to the "removed" image */
2299         if (i > 0) {
2300             TRACE("Pre image copy: Copy %d images\n", i);
2301        
2302             SelectObject (hdcSrc, himl->hbmImage);
2303             SelectObject (hdcDst, hbmNewImage);
2304             BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2305                       hdcSrc, 0, 0, SRCCOPY);
2306
2307             if (himl->hbmMask) {
2308                 SelectObject (hdcSrc, himl->hbmMask);
2309                 SelectObject (hdcDst, hbmNewMask);
2310                 BitBlt (hdcDst, 0, 0, i * himl->cx, himl->cy,
2311                           hdcSrc, 0, 0, SRCCOPY);
2312             }
2313         }
2314
2315         /* copy all images and masks behind the removed image */
2316         if (i < himl->cCurImage - 1) {
2317             TRACE("Post image copy!\n");
2318             SelectObject (hdcSrc, himl->hbmImage);
2319             SelectObject (hdcDst, hbmNewImage);
2320             BitBlt (hdcDst, i * himl->cx, 0, (himl->cCurImage - i - 1) * himl->cx,
2321                       himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2322
2323             if (himl->hbmMask) {
2324                 SelectObject (hdcSrc, himl->hbmMask);
2325                 SelectObject (hdcDst, hbmNewMask);
2326                 BitBlt (hdcDst, i * himl->cx, 0,
2327                           (himl->cCurImage - i - 1) * himl->cx,
2328                           himl->cy, hdcSrc, (i + 1) * himl->cx, 0, SRCCOPY);
2329             }
2330         }
2331
2332         DeleteDC (hdcSrc);
2333         DeleteDC (hdcDst);
2334
2335         /* delete old images and insert new ones */
2336         DeleteObject (himl->hbmImage);
2337         himl->hbmImage = hbmNewImage;
2338         if (himl->hbmMask) {
2339             DeleteObject (himl->hbmMask);
2340             himl->hbmMask = hbmNewMask;
2341         }
2342
2343         himl->cCurImage--;
2344         himl->cMaxImage = himl->cCurImage + himl->cGrow;
2345     }
2346
2347     return TRUE;
2348 }
2349
2350
2351 /*************************************************************************
2352  * ImageList_Replace [COMCTL32.70] 
2353  *
2354  * Replaces an image in an image list with a new image.
2355  *
2356  * PARAMS
2357  *     himl     [I] handle to image list
2358  *     i        [I] image index
2359  *     hbmImage [I] handle to image bitmap
2360  *     hbmMask  [I] handle to mask bitmap. Can be NULL.
2361  *
2362  * RETURNS
2363  *     Success: TRUE
2364  *     Failure: FALSE
2365  */
2366
2367 BOOL WINAPI
2368 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2369                    HBITMAP hbmMask)
2370 {
2371     HDC hdcImageList, hdcImage;
2372     BITMAP bmp;
2373
2374     if (himl == NULL) {
2375         ERR("Invalid image list handle!\n");
2376         return FALSE;
2377     }
2378     
2379     if ((i >= himl->cMaxImage) || (i < 0)) {
2380         ERR("Invalid image index!\n");
2381         return FALSE;
2382     }
2383
2384     hdcImageList = CreateCompatibleDC (0);
2385     hdcImage = CreateCompatibleDC (0);
2386     GetObjectA (hbmImage, sizeof(BITMAP), (LPVOID)&bmp);
2387
2388     /* Replace Image */
2389     SelectObject (hdcImageList, himl->hbmImage);
2390     SelectObject (hdcImage, hbmImage);
2391
2392     StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2393                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2394
2395     if (himl->hbmMask)
2396     {
2397         /* Replace Mask */
2398         SelectObject (hdcImageList, himl->hbmMask);
2399         SelectObject (hdcImage, hbmMask);
2400
2401         StretchBlt (hdcImageList, i * himl->cx, 0, himl->cx, himl->cy,
2402                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2403
2404
2405         /* Remove the background from the image
2406         */
2407         SelectObject (hdcImageList, himl->hbmImage);
2408         StretchBlt (hdcImageList, 
2409             i*himl->cx, 0, himl->cx, himl->cy,
2410             hdcImage, 
2411             0, 0, bmp.bmWidth, bmp.bmHeight, 
2412             0x220326); /* NOTSRCAND */
2413     }
2414
2415     DeleteDC (hdcImage);
2416     DeleteDC (hdcImageList);
2417
2418     return TRUE;
2419 }
2420
2421
2422 /*************************************************************************
2423  * ImageList_ReplaceIcon [COMCTL32.75]
2424  *
2425  * Replaces an image in an image list using an icon.
2426  *
2427  * PARAMS
2428  *     himl  [I] handle to image list
2429  *     i     [I] image index
2430  *     hIcon [I] handle to icon
2431  *
2432  * RETURNS
2433  *     Success: index of the replaced image
2434  *     Failure: -1
2435  */
2436
2437 INT WINAPI
2438 ImageList_ReplaceIcon (HIMAGELIST himl, INT i, HICON hIcon)
2439 {
2440     HDC     hdcImageList, hdcImage;
2441     INT     nIndex;
2442     HICON   hBestFitIcon;
2443     HBITMAP hbmOldSrc, hbmOldDst;
2444     ICONINFO  ii;
2445     BITMAP  bmp;
2446
2447     TRACE("(0x%lx 0x%x 0x%x)\n", (DWORD)himl, i, hIcon);
2448
2449     if (himl == NULL)
2450         return -1;
2451     if ((i >= himl->cMaxImage) || (i < -1))
2452         return -1;
2453
2454     hBestFitIcon = CopyImage(
2455         hIcon, IMAGE_ICON, 
2456         himl->cx, himl->cy, 
2457         LR_COPYFROMRESOURCE);
2458
2459     GetIconInfo (hBestFitIcon, &ii);
2460     if (ii.hbmMask == 0)
2461         ERR("no mask!\n");
2462     if (ii.hbmColor == 0)
2463         ERR("no color!\n");
2464     GetObjectA (ii.hbmMask, sizeof(BITMAP), (LPVOID)&bmp);
2465
2466     if (i == -1) {
2467         if (himl->cCurImage + 1 > himl->cMaxImage)
2468             IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2469
2470         nIndex = himl->cCurImage;
2471         himl->cCurImage++;
2472     }
2473     else
2474         nIndex = i;
2475
2476     hdcImageList = CreateCompatibleDC (0);
2477     TRACE("hdcImageList=0x%x!\n", hdcImageList);
2478     if (hdcImageList == 0)
2479         ERR("invalid hdcImageList!\n");
2480
2481     hdcImage = CreateCompatibleDC (0);
2482     TRACE("hdcImage=0x%x!\n", hdcImage);
2483     if (hdcImage == 0)
2484         ERR("invalid hdcImage!\n");
2485
2486     hbmOldDst = SelectObject (hdcImageList, himl->hbmImage);
2487     SetTextColor( hdcImageList, RGB(0,0,0));
2488     SetBkColor( hdcImageList, RGB(255,255,255));
2489     hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2490     StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2491                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2492
2493     if (himl->hbmMask) {
2494         SelectObject (hdcImageList, himl->hbmMask);
2495         SelectObject (hdcImage, ii.hbmMask);
2496         StretchBlt (hdcImageList, nIndex * himl->cx, 0, himl->cx, himl->cy,
2497                       hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2498     }
2499
2500     SelectObject (hdcImage, hbmOldSrc);
2501     SelectObject (hdcImageList, hbmOldDst);
2502
2503     if(hBestFitIcon)
2504         DestroyIcon(hBestFitIcon);
2505     if (hdcImageList)
2506         DeleteDC (hdcImageList);
2507     if (hdcImage)
2508         DeleteDC (hdcImage);
2509     if (ii.hbmColor)
2510         DeleteObject (ii.hbmColor);
2511     if (ii.hbmMask)
2512         DeleteObject (ii.hbmMask);
2513
2514     return nIndex;
2515 }
2516
2517
2518 /*************************************************************************
2519  * ImageList_SetBkColor [COMCTL32.76] 
2520  *
2521  * Sets the background color of an image list.
2522  *
2523  * PARAMS
2524  *     himl  [I] handle to image list
2525  *     clrBk [I] background color
2526  *
2527  * RETURNS
2528  *     Success: previous background color
2529  *     Failure: CLR_NONE
2530  */
2531
2532 COLORREF WINAPI
2533 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2534 {
2535     COLORREF clrOldBk;
2536
2537     if (himl == NULL)
2538         return CLR_NONE;
2539
2540     clrOldBk = himl->clrBk;
2541     himl->clrBk = clrBk;
2542     return clrOldBk;
2543 }
2544
2545
2546 /*************************************************************************
2547  * ImageList_SetDragCursorImage [COMCTL32.77]
2548  *
2549  * Combines the specified image with the current drag image
2550  *
2551  * PARAMS
2552  *     himlDrag  [I] handle to drag image list
2553  *     iDrag     [I] drag image index
2554  *     dxHotspot [I] X position of the hot spot
2555  *     dyHotspot [I] Y position of the hot spot
2556  *
2557  * RETURNS
2558  *     Success: TRUE
2559  *     Failure: FALSE
2560  *
2561  * NOTES
2562  *     When this function is called and the drag image is visible, a
2563  *     short flickering occurs but this matches the Win9x behavior. It is
2564  *     possible to fix the flickering using code like in ImageList_DragMove.
2565  */
2566
2567 BOOL WINAPI
2568 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2569                               INT dxHotspot, INT dyHotspot)
2570 {
2571     HIMAGELIST himlTemp;
2572     INT dx, dy;
2573     BOOL visible;
2574
2575     if (InternalDrag.himl == NULL)
2576         return FALSE;
2577
2578     TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2579            dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2580
2581     visible = InternalDrag.bShow;
2582
2583     /* Calculate the offset between the origin of the old image and the
2584      * origin of the second image.
2585      * dxHotspot, dyHotspot is the offset of THE Hotspot (there is only one
2586      * hotspot) to the origin of the second image.
2587      * See M$DN for details */
2588     dx = InternalDrag.dxHotspot - dxHotspot;
2589     dy = InternalDrag.dyHotspot - dyHotspot;
2590     himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag, dx, dy);
2591
2592     if (visible) {
2593         /* hide the drag image */
2594         ImageList_DragShowNolock(FALSE);
2595     }
2596     if ((InternalDrag.himl->cx != himlTemp->cx) ||
2597            (InternalDrag.himl->cy != himlTemp->cy)) {
2598         /* the size of the drag image changed, invalidate the buffer */
2599         DeleteObject(InternalDrag.hbmBg);
2600         InternalDrag.hbmBg = 0;
2601     }
2602
2603     ImageList_Destroy (InternalDrag.himl);
2604     InternalDrag.himl = himlTemp;
2605
2606     /* update the InternalDragOffset, if the origin of the
2607      * DragImage was changed by ImageList_Merge. */
2608     if (dx > InternalDrag.dxHotspot) {
2609         InternalDrag.dxHotspot = dx;
2610     }
2611     if (dy > InternalDrag.dyHotspot) {
2612         InternalDrag.dyHotspot = dy;
2613     }
2614
2615     if (visible) {
2616         /* show the drag image */
2617         ImageList_DragShowNolock(TRUE);
2618     }
2619
2620     return TRUE;
2621 }
2622
2623
2624 /*************************************************************************
2625  * ImageList_SetFilter [COMCTL32.78] 
2626  *
2627  * Sets a filter (or does something completely different)!!???
2628  *
2629  * PARAMS
2630  *     himl     [I] handle to image list
2631  *     i        [I] ???
2632  *     dwFilter [I] ???
2633  *
2634  * RETURNS
2635  *     Success: TRUE ???
2636  *     Failure: FALSE ???
2637  *
2638  * BUGS
2639  *     This is an UNDOCUMENTED function!!!!
2640  *     empty stub.
2641  */
2642
2643 BOOL WINAPI
2644 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2645 {
2646     FIXME("(%p 0x%x 0x%lx):empty stub!\n",
2647            himl, i, dwFilter);
2648
2649     return FALSE;
2650 }
2651
2652
2653 /*************************************************************************
2654  * ImageList_SetIconSize [COMCTL32.80]
2655  *
2656  * Sets the image size of the bitmap and deletes all images.
2657  *
2658  * PARAMS
2659  *     himl [I] handle to image list
2660  *     cx   [I] image width
2661  *     cy   [I] image height
2662  *
2663  * RETURNS
2664  *     Success: TRUE
2665  *     Failure: FALSE
2666  */
2667
2668 BOOL WINAPI
2669 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2670 {
2671     INT nCount;
2672
2673     if (!himl)
2674         return FALSE;
2675
2676     /* remove all images */
2677     himl->cMaxImage = himl->cInitial + himl->cGrow;
2678     himl->cCurImage = 0;
2679     himl->cx        = cx;
2680     himl->cy        = cy;
2681
2682     /* initialize overlay mask indices */
2683     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2684         himl->nOvlIdx[nCount] = -1;
2685
2686     DeleteObject (himl->hbmImage);
2687     himl->hbmImage =
2688         CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2689                         1, himl->uBitsPixel, NULL);
2690
2691     if (himl->hbmMask) {
2692         DeleteObject (himl->hbmMask);
2693         himl->hbmMask =
2694             CreateBitmap (himl->cMaxImage * himl->cx, himl->cy,
2695                             1, 1, NULL);
2696     }
2697
2698     return TRUE;
2699 }
2700
2701
2702 /*************************************************************************
2703  * ImageList_SetImageCount [COMCTL32.81]
2704  *
2705  * Resizes an image list to the specified number of images.
2706  *
2707  * PARAMS
2708  *     himl        [I] handle to image list
2709  *     iImageCount [I] number of images in the image list
2710  *
2711  * RETURNS
2712  *     Success: TRUE
2713  *     Failure: FALSE
2714  */
2715
2716 BOOL WINAPI
2717 ImageList_SetImageCount (HIMAGELIST himl, INT iImageCount)
2718 {
2719     HDC     hdcImageList, hdcBitmap;
2720     HBITMAP hbmNewBitmap;
2721     INT     nNewCount, nCopyCount;
2722
2723     if (!himl)
2724         return FALSE;
2725     if (himl->cCurImage >= iImageCount)
2726         return FALSE;
2727     if (himl->cMaxImage > iImageCount)
2728         return TRUE;
2729
2730     nNewCount = iImageCount + himl->cGrow;
2731     nCopyCount = min(himl->cCurImage, iImageCount);
2732
2733     hdcImageList = CreateCompatibleDC (0);
2734     hdcBitmap = CreateCompatibleDC (0);
2735
2736     hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2737                                    1, himl->uBitsPixel, NULL);
2738     if (hbmNewBitmap != 0)
2739     {
2740         SelectObject (hdcImageList, himl->hbmImage);
2741         SelectObject (hdcBitmap, hbmNewBitmap);
2742
2743         /* copy images */
2744         BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2745                   hdcImageList, 0, 0, SRCCOPY);
2746 #if 0
2747         /* delete 'empty' image space */
2748         SetBkColor (hdcBitmap, RGB(255, 255, 255));
2749         SetTextColor (hdcBitmap, RGB(0, 0, 0));
2750         PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2751                   (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2752 #endif
2753         DeleteObject (himl->hbmImage);
2754         himl->hbmImage = hbmNewBitmap;
2755     }
2756     else
2757         ERR("Could not create new image bitmap !\n");
2758
2759     if (himl->hbmMask)
2760     {
2761         hbmNewBitmap = CreateBitmap (nNewCount * himl->cx, himl->cy,
2762                                        1, 1, NULL);
2763         if (hbmNewBitmap != 0)
2764         {
2765             SelectObject (hdcImageList, himl->hbmMask);
2766             SelectObject (hdcBitmap, hbmNewBitmap);
2767
2768             /* copy images */
2769             BitBlt (hdcBitmap, 0, 0, nCopyCount * himl->cx, himl->cy,
2770                       hdcImageList, 0, 0, SRCCOPY);
2771 #if 0
2772             /* delete 'empty' image space */
2773             SetBkColor (hdcBitmap, RGB(255, 255, 255));
2774             SetTextColor (hdcBitmap, RGB(0, 0, 0));
2775             PatBlt (hdcBitmap,  nCopyCount * himl->cx, 0, 
2776                       (nNewCount - nCopyCount) * himl->cx, himl->cy, BLACKNESS);
2777 #endif
2778             DeleteObject (himl->hbmMask);
2779             himl->hbmMask = hbmNewBitmap;
2780         }
2781         else
2782             ERR("Could not create new mask bitmap!\n");
2783     }
2784
2785     DeleteDC (hdcImageList);
2786     DeleteDC (hdcBitmap);
2787
2788     /* Update max image count and current image count */
2789     himl->cMaxImage = nNewCount;
2790     if (himl->cCurImage > nCopyCount)
2791         himl->cCurImage = nCopyCount;
2792
2793     return TRUE;
2794 }
2795
2796
2797 /*************************************************************************
2798  * ImageList_SetOverlayImage [COMCTL32.82]
2799  *
2800  * Assigns an overlay mask index to an existing image in an image list.
2801  *
2802  * PARAMS
2803  *     himl     [I] handle to image list
2804  *     iImage   [I] image index
2805  *     iOverlay [I] overlay mask index
2806  *
2807  * RETURNS
2808  *     Success: TRUE
2809  *     Failure: FALSE
2810  */
2811
2812 BOOL WINAPI
2813 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2814 {
2815     if (!himl)
2816         return FALSE;
2817     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2818         return FALSE;
2819     if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2820         return FALSE;
2821     himl->nOvlIdx[iOverlay - 1] = iImage;
2822     return TRUE;
2823 }
2824
2825
2826 /*************************************************************************
2827  * ImageList_Write [COMCTL32.83]
2828  *
2829  * Writes an image list to a stream.
2830  *
2831  * PARAMS
2832  *     himl [I] handle to image list
2833  *     pstm [O] Pointer to a stream.
2834  *
2835  * RETURNS
2836  *     Success: TRUE
2837  *     Failure: FALSE
2838  *
2839  * NOTES
2840  *     This function can not be implemented yet, because
2841  *     IStream32::Write is not implemented.
2842  *
2843  * BUGS
2844  *     empty stub.
2845  */
2846
2847 BOOL WINAPI
2848 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2849 {
2850     if (!himl)
2851         return FALSE;
2852
2853     FIXME("empty stub!\n");
2854
2855     return FALSE;
2856 }
2857