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