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