Always draw the main item in full row select.
[wine] / dlls / msvideo / drawdib.c
1 /*
2  * Copyright 2000 Bradley Baetz
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * FIXME: Some flags are ignored
19  *
20  * Handle palettes
21  */
22
23 #include <string.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "wine/winbase16.h"
29 #include "wine/debug.h"
30 #include "vfw.h"
31 #include "vfw16.h"
32 #include "windef.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(msvideo);
35
36 typedef struct {
37         HDC hdc;
38         INT dxDst;
39         INT dyDst;
40         LPBITMAPINFOHEADER lpbi;
41         INT dxSrc;
42         INT dySrc;
43         HPALETTE hpal;                          /* Palette to use for the DIB */
44         BOOL begun;                                     /* DrawDibBegin has been called */
45         LPBITMAPINFOHEADER lpbiOut;     /* Output format */
46         HIC hic;                                        /* HIC for decompression */
47         HDC hMemDC;                                     /* DC for buffering */
48         HBITMAP hOldDib;                        /* Original Dib */
49         HBITMAP hDib;                           /* DibSection */
50         LPVOID lpvbits;                         /* Buffer for holding decompressed dib */
51 } WINE_HDD;
52
53 int num_colours(LPBITMAPINFOHEADER lpbi)
54 {
55         if(lpbi->biClrUsed)
56                 return lpbi->biClrUsed;
57         if(lpbi->biBitCount<=8)
58                 return 1<<lpbi->biBitCount;
59         return 0;
60 }
61
62 /***********************************************************************
63  *              DrawDibOpen             [MSVFW32.@]
64  */
65 HDRAWDIB VFWAPI DrawDibOpen(void) {
66         HDRAWDIB hdd;
67
68         TRACE("(void)\n");
69         hdd = HDRAWDIB_32(GlobalAlloc16(GHND,sizeof(WINE_HDD)));
70         TRACE("=> %p\n",hdd);
71         return hdd;
72 }
73
74 /***********************************************************************
75  *              DrawDibClose            [MSVFW32.@]
76  */
77 BOOL VFWAPI DrawDibClose(HDRAWDIB hdd) {
78         WINE_HDD *whdd = GlobalLock16(HDRAWDIB_16(hdd));
79
80         TRACE("(%p)\n",hdd);
81
82         if (!whdd)
83                 return FALSE;
84
85         if (whdd->begun)
86                 DrawDibEnd(hdd);
87
88         GlobalUnlock16(HDRAWDIB_16(hdd));
89         GlobalFree16(HDRAWDIB_16(hdd));
90         return TRUE;
91 }
92
93 /***********************************************************************
94  *              DrawDibEnd              [MSVFW32.@]
95  */
96 BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd) {
97         BOOL ret = TRUE;
98         WINE_HDD *whdd = GlobalLock16(HDRAWDIB_16(hdd));
99
100         TRACE("(%p)\n",hdd);
101
102         whdd->hpal = 0; /* Do not free this */
103         whdd->hdc = 0;
104         if (whdd->lpbi) {
105                 HeapFree(GetProcessHeap(),0,whdd->lpbi);
106                 whdd->lpbi = NULL;
107         }
108         if (whdd->lpbiOut) {
109                 HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
110                 whdd->lpbiOut = NULL;
111         }
112
113         whdd->begun = FALSE;
114
115         /*if (whdd->lpvbits)
116           HeapFree(GetProcessHeap(),0,whdd->lpvbuf);*/
117
118         if (whdd->hMemDC) {
119                 SelectObject(whdd->hMemDC,whdd->hOldDib);
120                 DeleteDC(whdd->hMemDC);
121         }
122
123         if (whdd->hDib)
124                 DeleteObject(whdd->hDib);
125
126         if (whdd->hic) {
127                 ICDecompressEnd(whdd->hic);
128                 ICClose(whdd->hic);
129         }
130
131         whdd->lpvbits = NULL;
132
133         GlobalUnlock16(HDRAWDIB_16(hdd));
134         return ret;
135 }
136
137 /***********************************************************************
138  *              DrawDibBegin            [MSVFW32.@]
139  */
140 BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
141                                                  HDC      hdc,
142                                                  INT      dxDst,
143                                                  INT      dyDst,
144                                                  LPBITMAPINFOHEADER lpbi,
145                                                  INT      dxSrc,
146                                                  INT      dySrc,
147                                                  UINT     wFlags) {
148         BOOL ret = TRUE;
149         WINE_HDD *whdd;
150
151         TRACE("(%p,%p,%d,%d,%p,%d,%d,0x%08lx)\n",
152                 hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,(DWORD)wFlags
153         );
154         TRACE("lpbi: %ld,%ld/%ld,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld\n",
155                   lpbi->biSize, lpbi->biWidth, lpbi->biHeight, lpbi->biPlanes,
156                   lpbi->biBitCount, lpbi->biCompression, lpbi->biSizeImage,
157                   lpbi->biXPelsPerMeter, lpbi->biYPelsPerMeter, lpbi->biClrUsed,
158                   lpbi->biClrImportant);
159
160         if (wFlags & ~(DDF_BUFFER))
161                 FIXME("wFlags == 0x%08x not handled\n", wFlags & ~(DDF_BUFFER));
162
163         whdd = (WINE_HDD*)GlobalLock16(HDRAWDIB_16(hdd));
164         if (!whdd) return FALSE;
165
166         if (whdd->begun)
167                 DrawDibEnd(hdd);
168
169         if (lpbi->biCompression) {
170                 DWORD size = 0;
171
172                 whdd->hic = ICOpen(ICTYPE_VIDEO,lpbi->biCompression,ICMODE_DECOMPRESS);
173                 if (!whdd->hic) {
174                         WARN("Could not open IC. biCompression == 0x%08lx\n",lpbi->biCompression);
175                         ret = FALSE;
176                 }
177
178                 if (ret) {
179                         size = ICDecompressGetFormat(whdd->hic,lpbi,NULL);
180                         if (size == ICERR_UNSUPPORTED) {
181                                 WARN("Codec doesn't support GetFormat, giving up.\n");
182                                 ret = FALSE;
183                         }
184                 }
185
186                 if (ret) {
187                         whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,size);
188
189                         if (ICDecompressGetFormat(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
190                                 ret = FALSE;
191                 }
192
193                 if (ret) {
194                         /* FIXME: Use Ex functions if available? */
195                         if (ICDecompressBegin(whdd->hic,lpbi,whdd->lpbiOut) != ICERR_OK)
196                                 ret = FALSE;
197
198                         TRACE("biSizeImage == %ld\n",whdd->lpbiOut->biSizeImage);
199                         TRACE("biCompression == %ld\n",whdd->lpbiOut->biCompression);
200                         TRACE("biBitCount == %d\n",whdd->lpbiOut->biBitCount);
201                 }
202         } else {
203                 DWORD dwSize;
204                 /* No compression */
205                 TRACE("Not compressed!\n");
206                 dwSize = lpbi->biSize + num_colours(lpbi)*sizeof(RGBQUAD);
207                 whdd->lpbiOut = HeapAlloc(GetProcessHeap(),0,dwSize);
208                 memcpy(whdd->lpbiOut,lpbi,dwSize);
209         }
210
211         if (ret) {
212                 /*whdd->lpvbuf = HeapAlloc(GetProcessHeap(),0,whdd->lpbiOut->biSizeImage);*/
213
214                 whdd->hMemDC = CreateCompatibleDC(hdc);
215                 TRACE("Creating: %ld,%p\n",whdd->lpbiOut->biSize,whdd->lpvbits);
216                 whdd->hDib = CreateDIBSection(whdd->hMemDC,(BITMAPINFO *)whdd->lpbiOut,DIB_RGB_COLORS,&(whdd->lpvbits),0,0);
217                 if (!whdd->hDib) {
218                         TRACE("Error: %ld\n",GetLastError());
219                 }
220                 TRACE("Created: %p,%p\n",whdd->hDib,whdd->lpvbits);
221                 whdd->hOldDib = SelectObject(whdd->hMemDC,whdd->hDib);
222         }
223
224         if (ret) {
225                 whdd->hdc = hdc;
226                 whdd->dxDst = dxDst;
227                 whdd->dyDst = dyDst;
228                 whdd->lpbi = HeapAlloc(GetProcessHeap(),0,lpbi->biSize);
229                 memcpy(whdd->lpbi,lpbi,lpbi->biSize);
230                 whdd->dxSrc = dxSrc;
231                 whdd->dySrc = dySrc;
232                 whdd->begun = TRUE;
233                 whdd->hpal = 0;
234         } else {
235                 if (whdd->hic)
236                         ICClose(whdd->hic);
237                 if (whdd->lpbiOut) {
238                         HeapFree(GetProcessHeap(),0,whdd->lpbiOut);
239                         whdd->lpbiOut = NULL;
240                 }
241         }
242
243         GlobalUnlock16(HDRAWDIB_16(hdd));
244
245         return ret;
246 }
247
248 /**********************************************************************
249  *              DrawDibDraw             [MSVFW32.@]
250  */
251 BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd, HDC hdc,
252         INT xDst, INT yDst, INT dxDst, INT dyDst,
253         LPBITMAPINFOHEADER lpbi,
254         LPVOID lpBits,
255         INT xSrc, INT ySrc, INT dxSrc, INT dySrc,
256         UINT wFlags
257 ) {
258         WINE_HDD *whdd;
259         BOOL ret = TRUE;
260
261         TRACE("(%p,%p,%d,%d,%d,%d,%p,%p,%d,%d,%d,%d,0x%08lx)\n",
262                   hdd,hdc,xDst,yDst,dxDst,dyDst,lpbi,lpBits,xSrc,ySrc,dxSrc,dySrc,(DWORD)wFlags
263         );
264
265         if (wFlags & ~(DDF_SAME_HDC | DDF_SAME_DRAW | DDF_NOTKEYFRAME |
266                                    DDF_UPDATE | DDF_DONTDRAW))
267                 FIXME("wFlags == 0x%08lx not handled\n",(DWORD)wFlags);
268
269         if (!lpBits) {
270                 /* Undocumented? */
271                 lpBits = (LPSTR)lpbi + (WORD)(lpbi->biSize) + (WORD)(num_colours(lpbi)*sizeof(RGBQUAD));
272         }
273
274         whdd = GlobalLock16(HDRAWDIB_16(hdd));
275
276 #define CHANGED(x) (whdd->x != x)
277
278         if ((!whdd->begun) || (!(wFlags & DDF_SAME_HDC) && CHANGED(hdc)) || (!(wFlags & DDF_SAME_DRAW) &&
279                  (CHANGED(lpbi) || CHANGED(dxSrc) || CHANGED(dySrc) || CHANGED(dxDst) || CHANGED(dyDst)))) {
280                 TRACE("Something changed!\n");
281                 ret = DrawDibBegin(hdd,hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,0);
282         }
283
284 #undef CHANGED
285
286         if ((dxDst == -1) && (dyDst == -1)) {
287                 dxDst = dxSrc;
288                 dyDst = dySrc;
289         }
290
291         if (!(wFlags & DDF_UPDATE)) {
292             /* biSizeImage may be set to 0 for BI_RGB (uncompressed) bitmaps */
293             if ((lpbi->biCompression == BI_RGB) && (lpbi->biSizeImage == 0))
294                     lpbi->biSizeImage = ((lpbi->biWidth * lpbi->biBitCount + 31) / 32) * 4 * lpbi->biHeight;
295
296                 if (lpbi->biCompression) {
297                     DWORD flags = 0;
298
299                         TRACE("Compression == 0x%08lx\n",lpbi->biCompression);
300
301                         if (wFlags & DDF_NOTKEYFRAME)
302                             flags |= ICDECOMPRESS_NOTKEYFRAME;
303
304                         ICDecompress(whdd->hic,flags,lpbi,lpBits,whdd->lpbiOut,whdd->lpvbits);
305                 } else {
306                     memcpy(whdd->lpvbits,lpBits,lpbi->biSizeImage);
307                 }
308         }
309         if (!(wFlags & DDF_DONTDRAW) && whdd->hpal)
310             SelectPalette(hdc,whdd->hpal,FALSE);
311
312         if (!(StretchBlt(whdd->hdc,xDst,yDst,dxDst,dyDst,whdd->hMemDC,xSrc,ySrc,dxSrc,dySrc,SRCCOPY)))
313             ret = FALSE;
314
315         GlobalUnlock16(HDRAWDIB_16(hdd));
316         return ret;
317 }
318
319 /*************************************************************************
320  *              DrawDibStart            [MSVFW32.@]
321  */
322 BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate) {
323         FIXME("(%p,%ld), stub\n",hdd,rate);
324         return TRUE;
325 }
326
327 /*************************************************************************
328  *              DrawDibStop             [MSVFW32.@]
329  */
330 BOOL VFWAPI DrawDibStop(HDRAWDIB hdd) {
331         FIXME("(%p), stub\n",hdd);
332         return TRUE;
333 }
334
335 /***********************************************************************
336  *              DrawDibSetPalette       [MSVFW32.@]
337  */
338 BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal) {
339         WINE_HDD *whdd;
340
341         TRACE("(%p,%p)\n",hdd,hpal);
342
343         whdd = GlobalLock16(HDRAWDIB_16(hdd));
344         whdd->hpal = hpal;
345
346         if (whdd->begun) {
347                 SelectPalette(whdd->hdc,hpal,0);
348                 RealizePalette(whdd->hdc);
349         }
350         GlobalUnlock16(HDRAWDIB_16(hdd));
351         return TRUE;
352 }
353
354 /***********************************************************************
355  *              DrawDibGetPalette       [MSVFW32.@]
356  */
357 HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd) {
358         WINE_HDD *whdd;
359         HPALETTE ret;
360
361         TRACE("(%p)\n",hdd);
362
363         whdd = GlobalLock16(HDRAWDIB_16(hdd));
364         ret = whdd->hpal;
365         GlobalUnlock16(HDRAWDIB_16(hdd));
366         return ret;
367 }
368
369 /***********************************************************************
370  *              DrawDibRealize          [MSVFW32.@]
371  */
372 UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground) {
373         WINE_HDD *whdd;
374         HPALETTE oldPal;
375         UINT ret = 0;
376
377         FIXME("(%p,%p,%d), stub\n",hdd,hdc,fBackground);
378
379         whdd = GlobalLock16(HDRAWDIB_16(hdd));
380
381         if (!whdd || !(whdd->begun)) {
382                 ret = 0;
383                 goto out;
384         }
385
386         if (!whdd->hpal)
387                 whdd->hpal = CreateHalftonePalette(hdc);
388
389         oldPal = SelectPalette(hdc,whdd->hpal,fBackground);
390         ret = RealizePalette(hdc);
391
392  out:
393         GlobalUnlock16(HDRAWDIB_16(hdd));
394
395         TRACE("=> %u\n",ret);
396         return ret;
397 }