Import Wine-20041201 vendor drop Added: vendor/wine/dlls/comctl32/ Added: vendor/wine/dlls/comctl32/current/ Added: vendor/wine/dlls/comctl32/current/Makefile.in Added: vendor/wine/dlls/comctl32/current/animate.c Added: vendor/wine/dlls/comctl32/current/comboex.c Added: vendor/wine/dlls/comctl32/current/comctl32.h Added: vendor/wine/dlls/comctl32/current/comctl32.spec Added: vendor/wine/dlls/comctl32/current/comctl32undoc.c Added: vendor/wine/dlls/comctl32/current/comctl_Cn.rc Added: vendor/wine/dlls/comctl32/current/comctl_Cs.rc Added: vendor/wine/dlls/comctl32/current/comctl_De.rc Added: vendor/wine/dlls/comctl32/current/comctl_En.rc Added: vendor/wine/dlls/comctl32/current/comctl_Es.rc Added: vendor/wine/dlls/comctl32/current/comctl_Fr.rc Added: vendor/wine/dlls/comctl32/current/comctl_It.rc Added: vendor/wine/dlls/comctl32/current/comctl_Ja.rc Added: vendor/wine/dlls/comctl32/current/comctl_Ko.rc Added: vendor/wine/dlls/comctl32/current/comctl_Nl.rc Added: vendor/wine/dlls/comctl32/current/comctl_Pl.rc Added: vendor/wine/dlls/comctl32/current/comctl_Pt.rc Added: vendor/wine/dlls/comctl32/current/comctl_Ru.rc Added: vendor/wine/dlls/comctl32/current/comctl_Si.rc Added: vendor/wine/dlls/comctl32/current/comctl_Th.rc Added: vendor/wine/dlls/comctl32/current/comctl_Uk.rc Added: vendor/wine/dlls/comctl32/current/commctrl.c Added: vendor/wine/dlls/comctl32/current/datetime.c Added: vendor/wine/dlls/comctl32/current/draglist.c Added: vendor/wine/dlls/comctl32/current/flatsb.c Added: vendor/wine/dlls/comctl32/current/header.c Added: vendor/wine/dlls/comctl32/current/hotkey.c Added: vendor/wine/dlls/comctl32/current/imagelist.c Added: vendor/wine/dlls/comctl32/current/imagelist.h Added: vendor/wine/dlls/comctl32/current/ipaddress.c Added: vendor/wine/dlls/comctl32/current/listview.c Added: vendor/wine/dlls/comctl32/current/monthcal.c Added: vendor/wine/dlls/comctl32/current/nativefont.c Added: vendor/wine/dlls/comctl32/current/pager.c Added: vendor/wine/dlls/comctl32/current/progress.c Added: vendor/wine/dlls/comctl32/current/propsheet.c Added: vendor/wine/dlls/comctl32/current/rebar.c Added: vendor/wine/dlls/comctl32/current/rsrc.rc Added: vendor/wine/dlls/comctl32/current/smoothscroll.c Added: vendor/wine/dlls/comctl32/current/status.c Added: vendor/wine/dlls/comctl32/current/string.c Added: vendor/wine/dlls/comctl32/current/syslink.c Added: vendor/wine/dlls/comctl32/current/tab.c Added: vendor/wine/dlls/comctl32/current/toolbar.c Added: vendor/wine/dlls/comctl32/current/tooltips.c Added: vendor/wine/dlls/comctl32/current/trackbar.c Added: vendor/wine/dlls/comctl32/current/treeview.c Added: vendor/wine/dlls/comctl32/current/updown.c _____
Added: vendor/wine/dlls/comctl32/current/Makefile.in --- vendor/wine/dlls/comctl32/current/Makefile.in 2004-12-31 14:06:09 UTC (rev 12444) +++ vendor/wine/dlls/comctl32/current/Makefile.in 2004-12-31 14:06:44 UTC (rev 12445) @@ -0,0 +1,64 @@
+EXTRADEFS = -D_COMCTL32_ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = comctl32.dll +IMPORTS = user32 gdi32 advapi32 kernel32 +DELAYIMPORTS = winmm +EXTRALIBS = $(LIBUNICODE) + +C_SRCS = \ + animate.c \ + comboex.c \ + comctl32undoc.c \ + commctrl.c \ + datetime.c \ + draglist.c \ + flatsb.c \ + header.c \ + hotkey.c \ + imagelist.c \ + ipaddress.c \ + listview.c \ + monthcal.c \ + nativefont.c \ + pager.c \ + progress.c \ + propsheet.c \ + rebar.c \ + smoothscroll.c \ + string.c \ + status.c \ + syslink.c \ + tab.c \ + toolbar.c \ + tooltips.c \ + trackbar.c \ + treeview.c \ + updown.c + +RC_SRCS = rsrc.rc +RC_BINSRC = rsrc.rc +RC_BINARIES = \ + idb_hist_large.bmp \ + idb_hist_small.bmp \ + idb_std_large.bmp \ + idb_std_small.bmp \ + idb_view_large.bmp \ + idb_view_small.bmp \ + idc_copy.cur \ + idc_divider.cur \ + idc_divideropen.cur \ + idc_movebutton.cur \ + idi_dragarrow.ico \ + idi_tt_error_sm.ico \ + idi_tt_info_sm.ico \ + idi_tt_warn_sm.ico \ + idt_check.bmp + +SUBDIRS = tests + +@MAKE_DLL_RULES@ + +### Dependencies: _____
Added: vendor/wine/dlls/comctl32/current/animate.c --- vendor/wine/dlls/comctl32/current/animate.c 2004-12-31 14:06:09 UTC (rev 12444) +++ vendor/wine/dlls/comctl32/current/animate.c 2004-12-31 14:06:44 UTC (rev 12445) @@ -0,0 +1,972 @@
+/* -*- tab-width: 8; c-basic-offset: 4 -*- */ +/* + * Animation control + * + * Copyright 1998, 1999 Eric Kohl + * 1999 Eric Pouech + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTES + * I will only improve this control once in a while. + * Eric ekohl@abo.rhein-zeitung.de + * + * TODO: + * - check for the 'rec ' list in some AVI files + * - concurrent access to infoPtr + */ + +#define COM_NO_WINDOWS_H +#include <stdarg.h> +#include <string.h> +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "commctrl.h" +#include "vfw.h" +#include "mmsystem.h" +#include "comctl32.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(animate); + +static struct { + HMODULE hModule; + HIC (WINAPI *fnICOpen)(DWORD, DWORD, UINT); + LRESULT (WINAPI *fnICClose)(HIC); + LRESULT (WINAPI *fnICSendMessage)(HIC, UINT, DWORD, DWORD); + DWORD (WINAPIV *fnICDecompress)(HIC,DWORD,LPBITMAPINFOHEADER,LPVOID,LPBITMAPINFOHEADER, LPVOID); +} fnIC; + +typedef struct +{ + /* reference to input stream (file or resource) */ + HGLOBAL hRes; + HMMIO hMMio; /* handle to mmio stream */ + HWND hwndSelf; + HWND hwndNotify; + /* information on the loaded AVI file */ + MainAVIHeader mah; + AVIStreamHeader ash; + LPBITMAPINFOHEADER inbih; + LPDWORD lpIndex; + /* data for the decompressor */ + HIC hic; + LPBITMAPINFOHEADER outbih; + LPVOID indata; + LPVOID outdata; + /* data for the background mechanism */ + CRITICAL_SECTION cs; + HANDLE hStopEvent; + HANDLE hThread; + DWORD threadId; + UINT uTimer; + /* data for playing the file */ + int nFromFrame; + int nToFrame; + int nLoop; + int currFrame; + /* tranparency info*/ + COLORREF transparentColor; + HBRUSH hbrushBG; + HBITMAP hbmPrevFrame; +} ANIMATE_INFO; + +#define ANIMATE_GetInfoPtr(hWnd) ((ANIMATE_INFO *)GetWindowLongPtrW(hWnd, 0)) +#define ANIMATE_COLOR_NONE 0xffffffff + +static void ANIMATE_Notify(ANIMATE_INFO* infoPtr, UINT notif) +{ + SendMessageA(infoPtr->hwndNotify, WM_COMMAND, + MAKEWPARAM(GetDlgCtrlID(infoPtr->hwndSelf), notif), + (LPARAM)infoPtr->hwndSelf); +} + +static BOOL ANIMATE_LoadResA(ANIMATE_INFO *infoPtr, HINSTANCE hInst, LPSTR lpName) +{ + HRSRC hrsrc; + MMIOINFO mminfo; + LPVOID lpAvi; + + hrsrc = FindResourceA(hInst, lpName, "AVI"); + if (!hrsrc) + return FALSE; + + infoPtr->hRes = LoadResource(hInst, hrsrc); + if (!infoPtr->hRes) + return FALSE; + + lpAvi = LockResource(infoPtr->hRes); + if (!lpAvi) + return FALSE; + + memset(&mminfo, 0, sizeof(mminfo)); + mminfo.fccIOProc = FOURCC_MEM; + mminfo.pchBuffer = (LPSTR)lpAvi; + mminfo.cchBuffer = SizeofResource(hInst, hrsrc); + infoPtr->hMMio = mmioOpenA(NULL, &mminfo, MMIO_READ); + if (!infoPtr->hMMio) { + FreeResource(infoPtr->hRes); + return FALSE; + } + + return TRUE; +} + + +static BOOL ANIMATE_LoadFileA(ANIMATE_INFO *infoPtr, LPSTR lpName) +{ + infoPtr->hMMio = mmioOpenA((LPSTR)lpName, NULL, + MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE); + + if (!infoPtr->hMMio) + return FALSE; + + return TRUE; +} + + +static LRESULT ANIMATE_DoStop(ANIMATE_INFO *infoPtr) +{ + EnterCriticalSection(&infoPtr->cs); + + /* should stop playing */ + if (infoPtr->hThread) + { + HANDLE handle = infoPtr->hThread; + + TRACE("stopping animation thread\n"); + infoPtr->hThread = 0; + SetEvent( infoPtr->hStopEvent ); + + if (infoPtr->threadId != GetCurrentThreadId()) + { + LeaveCriticalSection(&infoPtr->cs); /* leave it a chance to run */ + WaitForSingleObject( handle, INFINITE ); + TRACE("animation thread stopped\n"); + EnterCriticalSection(&infoPtr->cs); + } + + CloseHandle( handle ); + CloseHandle( infoPtr->hStopEvent ); + infoPtr->hStopEvent = 0; + } + if (infoPtr->uTimer) { + KillTimer(infoPtr->hwndSelf, infoPtr->uTimer); + infoPtr->uTimer = 0; + } + + LeaveCriticalSection(&infoPtr->cs); + + ANIMATE_Notify(infoPtr, ACN_STOP); + + return TRUE; +} + + +static void ANIMATE_Free(ANIMATE_INFO *infoPtr) +{ + if (infoPtr->hMMio) { + ANIMATE_DoStop(infoPtr); + mmioClose(infoPtr->hMMio, 0); + if (infoPtr->hRes) { + FreeResource(infoPtr->hRes); + infoPtr->hRes = 0; + } + if (infoPtr->lpIndex) { + HeapFree(GetProcessHeap(), 0, infoPtr->lpIndex); + infoPtr->lpIndex = NULL; + } + if (infoPtr->hic) { + fnIC.fnICClose(infoPtr->hic); + infoPtr->hic = 0; + } + if (infoPtr->inbih) { + HeapFree(GetProcessHeap(), 0, infoPtr->inbih); + infoPtr->inbih = NULL; + } + if (infoPtr->outbih) { + HeapFree(GetProcessHeap(), 0, infoPtr->outbih); + infoPtr->outbih = NULL; + } + if( infoPtr->indata ) + { + HeapFree(GetProcessHeap(), 0, infoPtr->indata); + infoPtr->indata = NULL; + } + if( infoPtr->outdata ) + { + HeapFree(GetProcessHeap(), 0, infoPtr->outdata); + infoPtr->outdata = NULL; + } + if( infoPtr->hbmPrevFrame ) + { + DeleteObject(infoPtr->hbmPrevFrame); + infoPtr->hbmPrevFrame = 0; + } + infoPtr->indata = infoPtr->outdata = NULL; + infoPtr->hwndSelf = 0; + infoPtr->hMMio = 0; + + memset(&infoPtr->mah, 0, sizeof(infoPtr->mah)); + memset(&infoPtr->ash, 0, sizeof(infoPtr->ash)); + infoPtr->nFromFrame = infoPtr->nToFrame = infoPtr->nLoop = infoPtr->currFrame = 0; + } + infoPtr->transparentColor = ANIMATE_COLOR_NONE; +} + +static void ANIMATE_TransparentBlt(ANIMATE_INFO* infoPtr, HDC hdcDest, HDC hdcSource) +{ + HDC hdcMask; + HBITMAP hbmMask; + HBITMAP hbmOld; + + /* create a transparency mask */ + hdcMask = CreateCompatibleDC(hdcDest); + hbmMask = CreateBitmap(infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, 1,1,NULL); + hbmOld = SelectObject(hdcMask, hbmMask); + + SetBkColor(hdcSource,infoPtr->transparentColor); + BitBlt(hdcMask,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCCOPY); + + /* mask the source bitmap */ + SetBkColor(hdcSource, RGB(0,0,0)); + SetTextColor(hdcSource, RGB(255,255,255)); + BitBlt(hdcSource, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + + /* mask the destination bitmap */ + SetBkColor(hdcDest, RGB(255,255,255)); + SetTextColor(hdcDest, RGB(0,0,0)); + BitBlt(hdcDest, 0, 0, infoPtr->inbih->biWidth, infoPtr->inbih->biHeight, hdcMask, 0, 0, SRCAND); + + /* combine source and destination */ + BitBlt(hdcDest,0,0,infoPtr->inbih->biWidth, infoPtr->inbih->biHeight,hdcSource,0,0,SRCPAINT); + + SelectObject(hdcMask, hbmOld); + DeleteObject(hbmMask); + DeleteDC(hdcMask); +} + +static LRESULT ANIMATE_PaintFrame(ANIMATE_INFO* infoPtr, HDC hDC) +{ + void* pBitmapData = NULL; + LPBITMAPINFO pBitmapInfo = NULL; + + HDC hdcMem; + HBITMAP hbmOld; + + int nOffsetX = 0; + int nOffsetY = 0; + + int nWidth; + int nHeight; + + if (!hDC || !infoPtr->inbih) + return TRUE; + + if (infoPtr->hic ) + { + pBitmapData = infoPtr->outdata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->outbih; + + nWidth = infoPtr->outbih->biWidth; + nHeight = infoPtr->outbih->biHeight; + } else + { + pBitmapData = infoPtr->indata; + pBitmapInfo = (LPBITMAPINFO)infoPtr->inbih; + + nWidth = infoPtr->inbih->biWidth; + nHeight = infoPtr->inbih->biHeight; + } + + if(!infoPtr->hbmPrevFrame) + { + infoPtr->hbmPrevFrame=CreateCompatibleBitmap(hDC, nWidth,nHeight ); + } + + SetDIBits(hDC, infoPtr->hbmPrevFrame, 0, nHeight, pBitmapData, (LPBITMAPINFO)pBitmapInfo, DIB_RGB_COLORS); + + hdcMem = CreateCompatibleDC(hDC); + hbmOld = SelectObject(hdcMem, infoPtr->hbmPrevFrame); + + /* + * we need to get the transparent color even without ACS_TRANSPARENT, + * because the style can be changed later on and the color should always + * be obtained in the first frame + */ + if(infoPtr->transparentColor == ANIMATE_COLOR_NONE) + { + infoPtr->transparentColor = GetPixel(hdcMem,0,0); + } + + if(GetWindowLongA(infoPtr->hwndSelf, GWL_STYLE) & ACS_TRANSPARENT) + { + HDC hdcFinal = CreateCompatibleDC(hDC); + HBITMAP hbmFinal = CreateCompatibleBitmap(hDC,nWidth, nHeight); + HBITMAP hbmOld2 = SelectObject(hdcFinal, hbmFinal); + RECT rect; + + rect.left = 0; + rect.top = 0; + rect.right = nWidth; + rect.bottom = nHeight; + + if(!infoPtr->hbrushBG) + infoPtr->hbrushBG = GetCurrentObject(hDC, OBJ_BRUSH); + + FillRect(hdcFinal, &rect, infoPtr->hbrushBG); + ANIMATE_TransparentBlt(infoPtr, hdcFinal, hdcMem); + + SelectObject(hdcFinal, hbmOld2); + SelectObject(hdcMem, hbmFinal); + DeleteDC(hdcFinal); + DeleteObject(infoPtr->hbmPrevFrame); + infoPtr->hbmPrevFrame = hbmFinal; + } + + if (GetWindowLongA(infoPtr->hwndSelf, GWL_STYLE) & ACS_CENTER) + { + RECT rect; + + GetWindowRect(infoPtr->hwndSelf, &rect); + nOffsetX = ((rect.right - rect.left) - nWidth)/2; + nOffsetY = ((rect.bottom - rect.top) - nHeight)/2; + } + BitBlt(hDC, nOffsetX, nOffsetY, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY); + + SelectObject(hdcMem, hbmOld); + DeleteDC(hdcMem); + return TRUE; +} + +static LRESULT ANIMATE_DrawFrame(ANIMATE_INFO* infoPtr) +{ + HDC hDC; + + TRACE("Drawing frame %d (loop %d)\n", infoPtr->currFrame, infoPtr->nLoop); + + EnterCriticalSection(&infoPtr->cs); + + mmioSeek(infoPtr->hMMio, infoPtr->lpIndex[infoPtr->currFrame], SEEK_SET); + mmioRead(infoPtr->hMMio, infoPtr->indata, infoPtr->ash.dwSuggestedBufferSize); + + if (infoPtr->hic && + fnIC.fnICDecompress(infoPtr->hic, 0, infoPtr->inbih, infoPtr->indata, + infoPtr->outbih, infoPtr->outdata) != ICERR_OK) { + LeaveCriticalSection(&infoPtr->cs); + WARN("Decompression error\n"); + return FALSE; + } + + if ((hDC = GetDC(infoPtr->hwndSelf)) != 0) { + ANIMATE_PaintFrame(infoPtr, hDC); + ReleaseDC(infoPtr->hwndSelf, hDC); + } + + if (infoPtr->currFrame++ >= infoPtr->nToFrame) { + infoPtr->currFrame = infoPtr->nFromFrame; + if (infoPtr->nLoop != -1) { + if (--infoPtr->nLoop == 0) { + ANIMATE_DoStop(infoPtr); + } + } + } + LeaveCriticalSection(&infoPtr->cs); + + return TRUE; +} + +static DWORD CALLBACK ANIMATE_AnimationThread(LPVOID ptr_) +{ + ANIMATE_INFO* infoPtr = (ANIMATE_INFO*)ptr_; + HANDLE event; + DWORD timeout; + + while(1) + { + EnterCriticalSection(&infoPtr->cs); + ANIMATE_DrawFrame(infoPtr); + timeout = infoPtr->mah.dwMicroSecPerFrame; + event = infoPtr->hStopEvent; + LeaveCriticalSection(&infoPtr->cs); + + /* time is in microseconds, we should convert it to milliseconds */ + if ((event == 0) || WaitForSingleObject( event, (timeout+500)/1000) == WAIT_OBJECT_0) + break; + } + return TRUE; +} + +static LRESULT ANIMATE_Play(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); + + /* nothing opened */ + if (!infoPtr->hMMio) + return FALSE; + + if (infoPtr->hThread || infoPtr->uTimer) { + TRACE("Already playing\n"); + return TRUE; + } + + infoPtr->nFromFrame = (INT)LOWORD(lParam); + infoPtr->nToFrame = (INT)HIWORD(lParam); + infoPtr->nLoop = (INT)wParam; + + if (infoPtr->nToFrame == 0xFFFF) + infoPtr->nToFrame = infoPtr->mah.dwTotalFrames - 1; + + TRACE("(repeat=%d from=%d to=%d);\n", + infoPtr->nLoop, infoPtr->nFromFrame, infoPtr->nToFrame); + + if (infoPtr->nFromFrame >= infoPtr->nToFrame || + infoPtr->nToFrame >= infoPtr->mah.dwTotalFrames) + return FALSE; + + infoPtr->currFrame = infoPtr->nFromFrame; + + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TIMER) { + TRACE("Using a timer\n"); + /* create a timer to display AVI */ + infoPtr->uTimer = SetTimer(hWnd, 1, infoPtr->mah.dwMicroSecPerFrame / 1000, NULL); + } else { + if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, 0, (LPARAM)hWnd); + } + + TRACE("Using an animation thread\n"); + infoPtr->hStopEvent = CreateEventW( NULL, TRUE, FALSE, NULL ); + infoPtr->hThread = CreateThread(0,0,ANIMATE_AnimationThread,(LPVOID)infoPtr, 0, &infoPtr->threadId); + if(!infoPtr->hThread) + { + ERR("Could not create animation thread!\n"); + return FALSE; + } + + } + + ANIMATE_Notify(infoPtr, ACN_START); + + return TRUE; +} + + +static BOOL ANIMATE_GetAviInfo(ANIMATE_INFO *infoPtr) +{ + MMCKINFO ckMainRIFF; + MMCKINFO mmckHead; + MMCKINFO mmckList; + MMCKINFO mmckInfo; + DWORD numFrame; + DWORD insize; + + if (mmioDescend(infoPtr->hMMio, &ckMainRIFF, NULL, 0) != 0) { + WARN("Can't find 'RIFF' chunk\n"); + return FALSE; + } + + if ((ckMainRIFF.ckid != FOURCC_RIFF) || + (ckMainRIFF.fccType != mmioFOURCC('A', 'V', 'I', ' '))) { + WARN("Can't find 'AVI ' chunk\n"); + return FALSE; + } + + mmckHead.fccType = mmioFOURCC('h', 'd', 'r', 'l'); + if (mmioDescend(infoPtr->hMMio, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) { + WARN("Can't find 'hdrl' list\n"); + return FALSE; + } + + mmckInfo.ckid = mmioFOURCC('a', 'v', 'i', 'h'); + if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) { + WARN("Can't find 'avih' chunk\n"); + return FALSE; + } + + mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->mah, sizeof(infoPtr->mah)); + + TRACE("mah.dwMicroSecPerFrame=%ld\n", infoPtr->mah.dwMicroSecPerFrame); + TRACE("mah.dwMaxBytesPerSec=%ld\n", infoPtr->mah.dwMaxBytesPerSec); + TRACE("mah.dwPaddingGranularity=%ld\n", infoPtr->mah.dwPaddingGranularity); + TRACE("mah.dwFlags=%ld\n", infoPtr->mah.dwFlags); + TRACE("mah.dwTotalFrames=%ld\n", infoPtr->mah.dwTotalFrames); + TRACE("mah.dwInitialFrames=%ld\n", infoPtr->mah.dwInitialFrames); + TRACE("mah.dwStreams=%ld\n", infoPtr->mah.dwStreams); + TRACE("mah.dwSuggestedBufferSize=%ld\n", infoPtr->mah.dwSuggestedBufferSize); + TRACE("mah.dwWidth=%ld\n", infoPtr->mah.dwWidth); + TRACE("mah.dwHeight=%ld\n", infoPtr->mah.dwHeight); + + mmioAscend(infoPtr->hMMio, &mmckInfo, 0); + + mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); + if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) { + WARN("Can't find 'strl' list\n"); + return FALSE; + } + + mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'h'); + if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { + WARN("Can't find 'strh' chunk\n"); + return FALSE; + } + + mmioRead(infoPtr->hMMio, (LPSTR)&infoPtr->ash, sizeof(infoPtr->ash)); + + TRACE("ash.fccType='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccType)), + HIBYTE(LOWORD(infoPtr->ash.fccType)), + LOBYTE(HIWORD(infoPtr->ash.fccType)), + HIBYTE(HIWORD(infoPtr->ash.fccType))); + TRACE("ash.fccHandler='%c%c%c%c'\n", LOBYTE(LOWORD(infoPtr->ash.fccHandler)), + HIBYTE(LOWORD(infoPtr->ash.fccHandler)), + LOBYTE(HIWORD(infoPtr->ash.fccHandler)), + HIBYTE(HIWORD(infoPtr->ash.fccHandler))); + TRACE("ash.dwFlags=%ld\n", infoPtr->ash.dwFlags); + TRACE("ash.wPriority=%d\n", infoPtr->ash.wPriority); + TRACE("ash.wLanguage=%d\n", infoPtr->ash.wLanguage); + TRACE("ash.dwInitialFrames=%ld\n", infoPtr->ash.dwInitialFrames); + TRACE("ash.dwScale=%ld\n", infoPtr->ash.dwScale); + TRACE("ash.dwRate=%ld\n", infoPtr->ash.dwRate); + TRACE("ash.dwStart=%ld\n", infoPtr->ash.dwStart); + TRACE("ash.dwLength=%ld\n", infoPtr->ash.dwLength); + TRACE("ash.dwSuggestedBufferSize=%ld\n", infoPtr->ash.dwSuggestedBufferSize); + TRACE("ash.dwQuality=%ld\n", infoPtr->ash.dwQuality); + TRACE("ash.dwSampleSize=%ld\n", infoPtr->ash.dwSampleSize); + TRACE("ash.rcFrame=(%d,%d,%d,%d)\n", infoPtr->ash.rcFrame.top, infoPtr->ash.rcFrame.left, + infoPtr->ash.rcFrame.bottom, infoPtr->ash.rcFrame.right); + + mmioAscend(infoPtr->hMMio, &mmckInfo, 0); + + mmckInfo.ckid = mmioFOURCC('s', 't', 'r', 'f'); + if (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, MMIO_FINDCHUNK) != 0) { + WARN("Can't find 'strh' chunk\n"); + return FALSE; + } + + infoPtr->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize); + if (!infoPtr->inbih) { + WARN("Can't alloc input BIH\n"); + return FALSE; + } + + mmioRead(infoPtr->hMMio, (LPSTR)infoPtr->inbih, mmckInfo.cksize); + + TRACE("bih.biSize=%ld\n", infoPtr->inbih->biSize); + TRACE("bih.biWidth=%ld\n", infoPtr->inbih->biWidth); + TRACE("bih.biHeight=%ld\n", infoPtr->inbih->biHeight); + TRACE("bih.biPlanes=%d\n", infoPtr->inbih->biPlanes); + TRACE("bih.biBitCount=%d\n", infoPtr->inbih->biBitCount); + TRACE("bih.biCompression=%ld\n", infoPtr->inbih->biCompression); + TRACE("bih.biSizeImage=%ld\n", infoPtr->inbih->biSizeImage); + TRACE("bih.biXPelsPerMeter=%ld\n", infoPtr->inbih->biXPelsPerMeter); + TRACE("bih.biYPelsPerMeter=%ld\n", infoPtr->inbih->biYPelsPerMeter); + TRACE("bih.biClrUsed=%ld\n", infoPtr->inbih->biClrUsed); + TRACE("bih.biClrImportant=%ld\n", infoPtr->inbih->biClrImportant); + + mmioAscend(infoPtr->hMMio, &mmckInfo, 0); + + mmioAscend(infoPtr->hMMio, &mmckList, 0); + +#if 0 + /* an AVI has 0 or 1 video stream, and to be animated should not contain + * an audio stream, so only one strl is allowed + */ + mmckList.fccType = mmioFOURCC('s', 't', 'r', 'l'); + if (mmioDescend(infoPtr->hMMio, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) { + WARN("There should be a single 'strl' list\n"); + return FALSE; + } +#endif + + mmioAscend(infoPtr->hMMio, &mmckHead, 0); + + /* no need to read optional JUNK chunk */ + + mmckList.fccType = mmioFOURCC('m', 'o', 'v', 'i'); + if (mmioDescend(infoPtr->hMMio, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) { + WARN("Can't find 'movi' list\n"); + return FALSE; + } + + /* FIXME: should handle the 'rec ' LIST when present */ + + infoPtr->lpIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + infoPtr->mah.dwTotalFrames * sizeof(DWORD)); + if (!infoPtr->lpIndex) { + WARN("Can't alloc index array\n"); + return FALSE; + } + + numFrame = insize = 0; + while (mmioDescend(infoPtr->hMMio, &mmckInfo, &mmckList, 0) == 0 && + numFrame < infoPtr->mah.dwTotalFrames) { + infoPtr->lpIndex[numFrame] = mmckInfo.dwDataOffset; + if (insize < mmckInfo.cksize) + insize = mmckInfo.cksize; + numFrame++; + mmioAscend(infoPtr->hMMio, &mmckInfo, 0); + } + if (numFrame != infoPtr->mah.dwTotalFrames) { + WARN("Found %ld frames (/%ld)\n", numFrame, infoPtr->mah.dwTotalFrames); + return FALSE; + } + if (insize > infoPtr->ash.dwSuggestedBufferSize) { + WARN("insize=%ld suggestedSize=%ld\n", insize, infoPtr->ash.dwSuggestedBufferSize); + infoPtr->ash.dwSuggestedBufferSize = insize; + } + + infoPtr->indata = HeapAlloc(GetProcessHeap(), 0, infoPtr->ash.dwSuggestedBufferSize); + if (!infoPtr->indata) { + WARN("Can't alloc input buffer\n"); + return FALSE; + } + + return TRUE; +} + + +static BOOL ANIMATE_GetAviCodec(ANIMATE_INFO *infoPtr) +{ + DWORD outSize; + + /* check uncompressed AVI */ + if ((infoPtr->ash.fccHandler == mmioFOURCC('D', 'I', 'B', ' ')) || + (infoPtr->ash.fccHandler == mmioFOURCC('R', 'L', 'E', ' ')) || + (infoPtr->ash.fccHandler == mmioFOURCC(0, 0, 0, 0))) + { + infoPtr->hic = 0; + return TRUE; + } + + /* try to get a decompressor for that type */ + infoPtr->hic = fnIC.fnICOpen(ICTYPE_VIDEO, infoPtr->ash.fccHandler, ICMODE_DECOMPRESS); + if (!infoPtr->hic) { + WARN("Can't load codec for the file\n"); + return FALSE; + } + + outSize = fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, + (DWORD)infoPtr->inbih, 0L); + + infoPtr->outbih = HeapAlloc(GetProcessHeap(), 0, outSize); + if (!infoPtr->outbih) { + WARN("Can't alloc output BIH\n"); + return FALSE; + } + + if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_GET_FORMAT, + (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != outSize) { + WARN("Can't get output BIH\n"); + return FALSE; + } + + infoPtr->outdata = HeapAlloc(GetProcessHeap(), 0, infoPtr->outbih->biSizeImage); + if (!infoPtr->outdata) { + WARN("Can't alloc output buffer\n"); + return FALSE; + } + + if (fnIC.fnICSendMessage(infoPtr->hic, ICM_DECOMPRESS_BEGIN, + (DWORD)infoPtr->inbih, (DWORD)infoPtr->outbih) != ICERR_OK) { + WARN("Can't begin decompression\n"); + return FALSE; + } + + return TRUE; +} + +static LRESULT ANIMATE_OpenA(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); + HINSTANCE hInstance = (HINSTANCE)wParam; + + ANIMATE_Free(infoPtr); + infoPtr->hwndSelf = hWnd; + + if (!lParam) { + TRACE("Closing avi!\n"); + /* installer of thebat! v1.62 requires FALSE here */ + return (infoPtr->hMMio != 0); + } + + if (!hInstance) + hInstance = (HINSTANCE)GetWindowLongPtrW(hWnd, GWLP_HINSTANCE); + + if (HIWORD(lParam)) { + TRACE("("%s");\n", (LPSTR)lParam); + + if (!ANIMATE_LoadResA(infoPtr, hInstance, (LPSTR)lParam)) { + TRACE("No AVI resource found!\n"); + if (!ANIMATE_LoadFileA(infoPtr, (LPSTR)lParam)) { + WARN("No AVI file found!\n"); + return FALSE; + } + } + } else { + TRACE("(%u);\n", (WORD)LOWORD(lParam)); + + if (!ANIMATE_LoadResA(infoPtr, hInstance, + MAKEINTRESOURCEA((INT)lParam))) { + WARN("No AVI resource found!\n"); + return FALSE; + } + } + + if (!ANIMATE_GetAviInfo(infoPtr)) { + WARN("Can't get AVI information\n"); + ANIMATE_Free(infoPtr); + return FALSE; + } + + if (!ANIMATE_GetAviCodec(infoPtr)) { + WARN("Can't get AVI Codec\n"); + ANIMATE_Free(infoPtr); + return FALSE; + } + + if (!GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { + SetWindowPos(hWnd, 0, 0, 0, infoPtr->mah.dwWidth, infoPtr->mah.dwHeight, + SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER); + } + + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_AUTOPLAY) { + return ANIMATE_Play(hWnd, -1, (LPARAM)MAKELONG(0, infoPtr->mah.dwTotalFrames-1)); + } + + return TRUE; +} + + +/* << ANIMATE_Open32W >> */ + +static LRESULT ANIMATE_Stop(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); + + /* nothing opened */ + if (!infoPtr->hMMio) + return FALSE; + + ANIMATE_DoStop(infoPtr); + return TRUE; +} + + +static LRESULT ANIMATE_Create(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO* infoPtr; + + if (!fnIC.hModule) /* FIXME: not thread safe */ + { + /* since there's a circular dep between msvfw32 and comctl32, we could either: + * - fix the build chain to allow this circular dep + * - handle it by hand + * AJ wants the latter :-( + */ + fnIC.hModule = LoadLibraryA("msvfw32.dll"); + if (!fnIC.hModule) return FALSE; + + fnIC.fnICOpen = (void*)GetProcAddress(fnIC.hModule, "ICOpen"); + fnIC.fnICClose = (void*)GetProcAddress(fnIC.hModule, "ICClose"); + fnIC.fnICSendMessage = (void*)GetProcAddress(fnIC.hModule, "ICSendMessage"); + fnIC.fnICDecompress = (void*)GetProcAddress(fnIC.hModule, "ICDecompress"); + } + + /* allocate memory for info structure */ + infoPtr = (ANIMATE_INFO *)Alloc(sizeof(ANIMATE_INFO)); + if (!infoPtr) { + ERR("could not allocate info memory!\n"); + return 0; + } + + /* store crossref hWnd <-> info structure */ + SetWindowLongPtrW(hWnd, 0, (DWORD_PTR)infoPtr); + infoPtr->hwndSelf = hWnd; + infoPtr->hwndNotify = ((LPCREATESTRUCTA)lParam)->hwndParent; + infoPtr->transparentColor = ANIMATE_COLOR_NONE; + infoPtr->hbmPrevFrame = 0; + + TRACE("Animate style=0x%08lx, parent=%p\n", GetWindowLongA(hWnd, GWL_STYLE), infoPtr->hwndNotify); + + InitializeCriticalSection(&infoPtr->cs); + + return TRUE; +} + + +static LRESULT ANIMATE_Destroy(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); + + + /* free avi data */ + ANIMATE_Free(infoPtr); + + /* free animate info data */ + Free(infoPtr); + SetWindowLongPtrW(hWnd, 0, 0); + + return 0; +} + + +static LRESULT ANIMATE_EraseBackground(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(hWnd); + RECT rect; + HBRUSH hBrush = 0; + + if(GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + hBrush = (HBRUSH)SendMessageA(infoPtr->hwndNotify,WM_CTLCOLORSTATIC, + wParam, (LPARAM)hWnd); + } + + GetClientRect(hWnd, &rect); + FillRect((HDC)wParam, &rect, hBrush ? hBrush : GetCurrentObject((HDC)wParam, OBJ_BRUSH)); + + return TRUE; +} + +static LRESULT WINAPI ANIMATE_Size(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_CENTER) { + InvalidateRect(hWnd, NULL, TRUE); + } + return TRUE; +} + +static LRESULT WINAPI ANIMATE_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hWnd, uMsg, wParam, lParam); + if (!ANIMATE_GetInfoPtr(hWnd) && (uMsg != WM_NCCREATE)) + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + switch (uMsg) + { + case ACM_OPENA: + return ANIMATE_OpenA(hWnd, wParam, lParam); + + case ACM_OPENW: + FIXME("ACM_OPENW: stub!\n"); + /* return ANIMATE_Open32W(hWnd, wParam, lParam); */ + return 0; + + case ACM_PLAY: + return ANIMATE_Play(hWnd, wParam, lParam); + + case ACM_STOP: + return ANIMATE_Stop(hWnd, wParam, lParam); + + case WM_NCCREATE: + return ANIMATE_Create(hWnd, wParam, lParam); + + case WM_NCHITTEST: + return HTTRANSPARENT; + + case WM_DESTROY: + return ANIMATE_Destroy(hWnd, wParam, lParam); + + case WM_ERASEBKGND: + return ANIMATE_EraseBackground(hWnd, wParam, lParam); + + /* case WM_STYLECHANGED: FIXME shall we do something ?? */ + + case WM_TIMER: + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + { + ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); + infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, + wParam, (LPARAM)hWnd); + } + return ANIMATE_DrawFrame(ANIMATE_GetInfoPtr(hWnd)); + + case WM_PAINT: + { + ANIMATE_INFO* infoPtr = ANIMATE_GetInfoPtr(hWnd); + + /* the animation isn't playing, or has not decompressed + * (and displayed) the first frame yet, don't paint + */ + if ((!infoPtr->uTimer && !infoPtr->hThread) || + !infoPtr->hbmPrevFrame) + { + /* default paint handling */ + return DefWindowProcA(hWnd, uMsg, wParam, lParam); + } + + if (GetWindowLongA(hWnd, GWL_STYLE) & ACS_TRANSPARENT) + infoPtr->hbrushBG = (HBRUSH)SendMessageA(infoPtr->hwndNotify, + WM_CTLCOLORSTATIC, + wParam, (LPARAM)hWnd); + + if (wParam) + { + EnterCriticalSection(&infoPtr->cs); + ANIMATE_PaintFrame(infoPtr, (HDC)wParam); + LeaveCriticalSection(&infoPtr->cs); + } + else [truncated at 1000 lines; 65230 more skipped]