/*-----------------------------------------------------------------------------+ | RIFFDISP.C | | | | (C) Copyright Microsoft Corporation 1991. All rights reserved. | | | | Revision History | | Oct-1992 MikeTri Ported to WIN32 / WIN16 common code | | | +-----------------------------------------------------------------------------*/ #include #include #include #include #ifdef WIN16 #include "port16.h" #endif #include "mplayer.h" #include "riffdisp.h" static HWND hwndPreview; static HANDLE hdibPreview; static TCHAR achPreview[80]; static HFONT hfontPreview; static HINSTANCE hMSVideo; typedef HANDLE HDRAWDIB; typedef HDRAWDIB (FAR PASCAL *PFNDRAWDIBOPEN)(void); typedef BOOL (FAR PASCAL *PFNDRAWDIBCLOSE)(HDRAWDIB hdd); typedef BOOL (FAR PASCAL *PFNDRAWDIBDRAW)(HDRAWDIB hdd,HDC hdc,int xDst,int yDst,int dxDst,int dyDst,LPBITMAPINFOHEADER lpbi,LPVOID lpBits,int xSrc,int ySrc,int dxSrc,int dySrc,UINT wFlags); static HDRAWDIB hdd; static PFNDRAWDIBOPEN pfnDrawDibOpen; static PFNDRAWDIBCLOSE pfnDrawDibClose; static PFNDRAWDIBDRAW pfnDrawDibDraw; #define GetHInstance() (HINSTANCE)(SELECTOROF((LPVOID)&hwndPreview)) /*************************************************************************** * ****************************************************************************/ //#define FOURCC_RIFF mmioFOURCC('R','I','F','F') #define FOURCC_INFO mmioFOURCC('I','N','F','O') #define FOURCC_DISP mmioFOURCC('D','I','S','P') #define FOURCC_INAM mmioFOURCC('I','N','A','M') #define FOURCC_ISBJ mmioFOURCC('I','S','B','J') BOOL PreviewOpen(HWND hwnd); BOOL PreviewFile(HWND hwnd, LPTSTR szFile); BOOL PreviewPaint(HWND hwnd); BOOL PreviewClose(HWND hwnd); HANDLE ReadDisp(LPTSTR lpszFile, int cf, LPTSTR pv, int iLen); HANDLE ReadInfo(LPTSTR lpszFile, FOURCC fcc, LPTSTR pv, int iLen); HANDLE GetRiffDisp(LPTSTR lpszFile, LPTSTR szText, int iLen); /*************************************************************************** * ****************************************************************************/ BOOL PreviewOpen(HWND hwnd) { LOGFONT lf; UINT w; if (hwndPreview) return FALSE; hwndPreview = hwnd; w = SetErrorMode(SEM_NOOPENFILEERRORBOX); hMSVideo = LoadLibrary(TEXT("MSVIDEO.DLL")); SetErrorMode(w); #ifdef WIN32 if (hMSVideo != NULL) #else if (hMSVideo > HINSTANCE_ERROR) #endif { pfnDrawDibOpen = (PFNDRAWDIBOPEN)GetProcAddress(hMSVideo, ANSI_TEXT("DrawDibOpen")); pfnDrawDibClose = (PFNDRAWDIBCLOSE)GetProcAddress(hMSVideo, ANSI_TEXT("DrawDibClose")); pfnDrawDibDraw = (PFNDRAWDIBDRAW)GetProcAddress(hMSVideo, ANSI_TEXT("DrawDibDraw")); if (pfnDrawDibOpen) hdd = pfnDrawDibOpen(); } SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0); hfontPreview = CreateFontIndirect(&lf); } /*************************************************************************** * ****************************************************************************/ BOOL PreviewClose(HWND hwnd) { if (hwndPreview != hwnd) return FALSE; if (hdibPreview) GlobalFree(hdibPreview); if (hfontPreview) DeleteObject(hfontPreview); if (hdd) pfnDrawDibClose(hdd); #ifdef WIN32 if (hMSVideo != NULL) #else if (hMSVideo >= HINSTANCE_ERROR) #endif FreeLibrary(hMSVideo); achPreview[0] = 0; hdd = NULL; hMSVideo = NULL; hwndPreview = NULL; hdibPreview = NULL; hfontPreview = NULL; } /*************************************************************************** * ****************************************************************************/ BOOL PreviewFile(HWND hwnd, LPTSTR szFile) { if (hwndPreview != hwnd) return FALSE; achPreview[0] = 0; if (hdibPreview) GlobalFree(hdibPreview); hdibPreview = NULL; if (szFile) { hdibPreview = GetRiffDisp(szFile, achPreview, BYTE_COUNT(achPreview)); } PreviewPaint(hwnd); return TRUE; } /*************************************************************************** * ****************************************************************************/ BOOL PreviewPaint(HWND hwnd) { RECT rc; RECT rcPreview; RECT rcImage; RECT rcText; HDC hdc; HBRUSH hbr; int dx; int dy; LPBITMAPINFOHEADER lpbi; if (hwndPreview != hwnd) return FALSE; // // locate the preview in the lower corner of the dialog (below the // cancel button) // GetClientRect(hwnd, &rcPreview); GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc); ScreenToClient(hwnd, (LPPOINT)&rc); ScreenToClient(hwnd, (LPPOINT)&rc+1); rcPreview.top = rc.bottom + (rc.bottom - rc.top) + 12; rcPreview.left = rc.left; rcPreview.right = rc.right; rcPreview.bottom -= 4; // leave a little room at the bottom hdc = GetDC(hwnd); #ifdef WIN32 hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hwnd); #else hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hwnd, CTLCOLOR_DLG)); #endif SelectObject(hdc, hfontPreview); SetStretchBltMode(hdc, COLORONCOLOR); InflateRect(&rcPreview, 4, 1); FillRect(hdc, &rcPreview, hbr); IntersectClipRect(hdc, rcPreview.left, rcPreview.top, rcPreview.right, rcPreview.bottom); InflateRect(&rcPreview, -4, -1); // // compute the text rect, using DrawText // rcText = rcPreview; rcText.bottom = rcText.top; DrawText(hdc, achPreview, -1, &rcText, DT_CALCRECT|DT_LEFT|DT_WORDBREAK); // // compute the image size // if (hdibPreview && hdd) { lpbi = GlobalLock(hdibPreview); // // DISP(CF_DIB) chunks are messed up they contain a DIB file! not // a CF_DIB, skip over the header if it is there. // if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) lpbi = (LPBITMAPINFOHEADER)((LPBYTE)lpbi + sizeof(BITMAPFILEHEADER)); rcImage = rcPreview; // // if wider than preview area scale to fit // if ((int)lpbi->biWidth > rcImage.right - rcImage.left) { rcImage.bottom = rcImage.top + MulDiv((int)lpbi->biHeight,rcImage.right-rcImage.left,(int)lpbi->biWidth); } // // if x2 will fit then use it // else if ((int)lpbi->biWidth * 2 < rcImage.right - rcImage.left) { rcImage.right = rcImage.left + (int)lpbi->biWidth*2; rcImage.bottom = rcImage.top + (int)lpbi->biHeight*2; } // // else center the image in the preview area // else { rcImage.right = rcImage.left + (int)lpbi->biWidth; rcImage.bottom = rcImage.top + (int)lpbi->biHeight; } if (rcImage.bottom > rcPreview.bottom - (rcText.bottom - rcText.top)) { rcImage.bottom = rcPreview.bottom - (rcText.bottom - rcText.top); rcImage.right = rcPreview.left + MulDiv((int)lpbi->biWidth, rcImage.bottom-rcImage.top, (int)lpbi->biHeight); rcImage.left = rcPreview.left; } } else { SetRectEmpty(&rcImage); } // // now center // dx = ((rcPreview.right - rcPreview.left) - (rcText.right - rcText.left))/2; OffsetRect(&rcText, dx, 0); dx = ((rcPreview.right - rcPreview.left) - (rcImage.right - rcImage.left))/2; OffsetRect(&rcImage, dx, 0); dy = rcPreview.bottom - rcPreview.top; dy -= rcImage.bottom - rcImage.top; dy -= rcText.bottom - rcText.top; if (dy < 0) dy = 0; else dy = dy / 2; OffsetRect(&rcImage, 0, dy); OffsetRect(&rcText, 0, dy + rcImage.bottom - rcImage.top + 2); // // now draw // DrawText(hdc, achPreview, -1, &rcText, DT_LEFT|DT_WORDBREAK); if (hdibPreview && hdd) { pfnDrawDibDraw(hdd, hdc, rcImage.left, rcImage.top, rcImage.right - rcImage.left, rcImage.bottom - rcImage.top, lpbi, NULL, 0, 0, -1, -1, 0); InflateRect(&rcImage, 1, 1); FrameRect(hdc, &rcImage, GetStockObject(BLACK_BRUSH)); } ReleaseDC(hwnd, hdc); return TRUE; } /*************************************************************************** * ****************************************************************************/ static UINT (FAR PASCAL *lpfnOldHook)(HWND, unsigned, WPARAM, LPARAM); /* Combo boxes */ #define cmb1 0x0470 #define cmb2 0x0471 /* Listboxes */ #define lst1 0x0460 #define lst2 0x0461 /* Edit controls */ #define edt1 0x0480 #define ID_TIMER 1234 #define PREVIEWWAIT 1000 UINT FAR PASCAL _EXPORT GetFileNamePreviewHook(HWND hwnd, unsigned msg, WPARAM wParam, LPARAM lParam) { int i; TCHAR ach[80]; UINT Code; switch (msg) { case WM_COMMAND: Code = GET_WM_COMMAND_CMD(wParam,lParam); switch (LOWORD(wParam)) { case lst1: if (Code == LBN_SELCHANGE) { KillTimer(hwnd, ID_TIMER); SetTimer(hwnd, ID_TIMER, PREVIEWWAIT, NULL); } break; case IDOK: case IDCANCEL: KillTimer(hwnd, ID_TIMER); PreviewFile(hwnd, NULL); break; case cmb1: case cmb2: case lst2: if (Code == LBN_SELCHANGE) { KillTimer(hwnd, ID_TIMER); PreviewFile(hwnd, NULL); } break; } break; case WM_TIMER: if (wParam == ID_TIMER) { KillTimer(hwnd, ID_TIMER); ach[0] = 0; i = (int)SendDlgItemMessage(hwnd, lst1, LB_GETCURSEL, 0, 0L); SendDlgItemMessage(hwnd, lst1, LB_GETTEXT, i, (LONG)(LPTSTR)ach); PreviewFile(hwnd, ach); return TRUE; } break; case WM_QUERYNEWPALETTE: case WM_PALETTECHANGED: case WM_PAINT: PreviewPaint(hwnd); break; case WM_INITDIALOG: PreviewOpen(hwnd); break; case WM_DESTROY: PreviewClose(hwnd); break; } if (lpfnOldHook) return (*lpfnOldHook)(hwnd, msg, wParam, lParam); else return FALSE; } /*************************************************************************** * ****************************************************************************/ BOOL FAR PASCAL GetOpenFileNamePreview(LPOPENFILENAME lpofn) { BOOL fHook; BOOL f; if (hwndPreview) return GetOpenFileName(lpofn); fHook = (BOOL)(lpofn->Flags & OFN_ENABLEHOOK); if (fHook) lpfnOldHook = lpofn->lpfnHook; lpofn->lpfnHook = (LPOFNHOOKPROC)MakeProcInstance((FARPROC)GetFileNamePreviewHook, GetHInstance()); lpofn->Flags |= OFN_ENABLEHOOK; f = GetOpenFileName(lpofn); #ifndef WIN32 FreeProcInstance((FARPROC)lpofn->lpfnHook); #endif if (fHook) lpofn->lpfnHook = lpfnOldHook; else lpofn->Flags &= ~OFN_ENABLEHOOK; return f; } /**************************************************************************** * * get both the DISP(CF_DIB) and the DISP(CF_TEXT) info in one pass, this is * much faster than doing multiple passes over the file. * ****************************************************************************/ HANDLE GetRiffDisp(LPTSTR lpszFile, LPTSTR szText, int iLen) { HMMIO hmmio; MMCKINFO ck; MMCKINFO ckINFO; MMCKINFO ckRIFF; HANDLE h = NULL; LONG lSize; DWORD dw; HCURSOR hcur = NULL; if (szText) szText[0] = 0; /* 20/9/92 - reverse engineering... (Laurie Griffiths) | This routine ACTUALLY only ever gets called from PreviewFile. That's | in this file, so this routine should have been PRIVATE or STATIC. | PreviewFile is itself called from only 3 places, also all in this file. | Of these, two have NULL as the lpszFile (which is passed straight through | to here) and the other one has text derived from | SendDlgItemMessage(..., LB_GETTEXT, ...lpszFile) | So if HIWORD(lpszFile) is ever zero, it's hard to see what good it does | to take the LOWORD and cast it as an HMMIO (which would be even sillier | in 32 bit land). I reckon it will just always return. */ #ifdef WIN32 if (lpszFile == NULL) return NULL; hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ); #else // 16 bit idio[syncra]cy? /* Open the file */ if (HIWORD(lpszFile)) hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ); else hmmio = (HMMIO)LOWORD(lpszFile); #endif if (hmmio == NULL) return NULL; mmioSeek(hmmio, 0, SEEK_SET); /* descend the input file into the RIFF chunk */ if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0) goto error; if (ckRIFF.ckid != FOURCC_RIFF) goto error; while (!mmioDescend(hmmio, &ck, &ckRIFF, 0)) { if (ck.ckid == FOURCC_DISP) { if (hcur == NULL) hcur = SetCursor(LoadCursor(NULL, IDC_WAIT)); /* Read dword into dw, break if read unsuccessful */ if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw)) goto error; /* Find out how much memory to allocate */ lSize = ck.cksize - sizeof(dw); if ((int)dw == CF_DIB && h == NULL) { /* get a handle to memory to hold the description and lock it down */ if ((h = GlobalAlloc(GHND, lSize+4)) == NULL) goto error; if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize) goto error; } else if ((int)dw == CF_TEXT && szText[0] == 0) { if (lSize > iLen-1) lSize = iLen-1; szText[lSize] = 0; if (mmioRead(hmmio, (LPSTR)szText, lSize) != lSize) goto error; } } else if (ck.ckid == FOURCC_LIST && ck.fccType == FOURCC_INFO && szText[0] == 0) { while (!mmioDescend(hmmio, &ckINFO, &ck, 0)) { switch (ckINFO.ckid) { case FOURCC_INAM: // case FOURCC_ISBJ: lSize = ck.cksize; if (lSize > iLen-1) lSize = iLen-1; szText[lSize] = 0; if (mmioRead(hmmio, (LPSTR)szText, lSize) != lSize) goto error; break; } if (mmioAscend(hmmio, &ckINFO, 0)) break; } } // // if we have both a picture and a title, then exit. // if (h != NULL && szText[0] != 0) break; /* Ascend so that we can descend into next chunk */ if (mmioAscend(hmmio, &ck, 0)) break; } goto exit; error: if (h) GlobalFree(h); h = NULL; exit: #ifdef WIN32 if (hmmio != NULL) mmioClose(hmmio, 0); #else if (hmmio && HIWORD(lpszFile)) mmioClose(hmmio, 0); #endif if (hcur) SetCursor(hcur); return h; } #if 0 * * /*************************************************************************** * * * ****************************************************************************/ * * HANDLE FAR PASCAL GetRiffPicture(LPTSTR szFile) * { * return ReadDisp(szFile, CF_DIB, NULL, 0); * } * * * /*************************************************************************** * * * * * ****************************************************************************/ * * * * BOOL FAR PASCAL GetRiffTitle(LPSTR szFile, LPSTR szTitle, int iLen) * * { * * return ReadDisp(szFile, CF_TEXT, szTitle, iLen) || * * ReadInfo(szFile, FOURCC_INAM, szTitle, iLen) || * * ReadInfo(szFile, FOURCC_ISBJ, szTitle, iLen) ; * * } * /**************************************************************************** * * * ****************************************************************************/ * * HANDLE ReadDisp(LPSTR lpszFile, int cf, LPSTR pv, int iLen) * { * HMMIO hmmio; * MMCKINFO ckinfo; * MMCKINFO ckRIFF; * HANDLE h = NULL; * DWORD dwSize; * DWORD dw; * * if (pv) * ((LPSTR)pv)[0] = 0; * * /* Open the file */ * if (HIWORD(lpszFile)) * hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ); * else * hmmio = (HMMIO)LOWORD(lpszFile); * * if (hmmio == NULL) * return NULL; * * mmioSeek(hmmio, 0, SEEK_SET); * * /* descend the input file into the RIFF chunk */ * if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0) * goto error; * * if (ckRIFF.ckid != FOURCC_RIFF) * goto error; * * /* search the file for a 'DISP' chunk */ * ckinfo.ckid = FOURCC_DISP; * while (!mmioDescend(hmmio, &ckinfo, &ckRIFF, MMIO_FINDCHUNK)) * { * /* Read dword into dw, break if read unsuccessful */ * if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw)) * goto error; * * /* Check to see if the type is right */ * if ((int)dw == cf) * { * /* Find out how much memory to allocate */ * dwSize = ckinfo.cksize - sizeof(dw); * * if (pv == NULL) * { * /* get a handle to memory to hold the description and lock it down */ * h = GlobalAlloc(GHND, dwSize+1); * * if (!h) * goto error; * * pv = GlobalLock(h); * } * else * { * if (dwSize > (DWORD)iLen-1) * dwSize = (DWORD)iLen-1; * * ((LPSTR)pv)[(int)dwSize] = 0; * } * * if (mmioRead(hmmio, pv, (LONG)dwSize) != (LONG)dwSize) * goto error; * * if (HIWORD(lpszFile)) * mmioClose(hmmio, 0); * * return h ? h : (HANDLE)(UINT)dwSize; * } * * /* Ascend so that we can descend into next chunk * */ * if(mmioAscend(hmmio, &ckinfo, 0)) * break; * } * * error: * if (hmmio && HIWORD(lpszFile)) * mmioClose(hmmio, 0); * * if (h) * GlobalFree(h); * * return NULL; * } * * /**************************************************************************** * * * ****************************************************************************/ * * HANDLE ReadInfo(LPSTR lpszFile, FOURCC fcc, LPSTR pv, int iLen) * { * HMMIO hmmio; * HANDLE h=NULL; * MMCKINFO ckinfo; * MMCKINFO ckLIST; * MMCKINFO ckRIFF; * DWORD dwSize; * * if (pv) * ((LPSTR)pv)[0] = 0; * * /* Open the file */ * if (HIWORD(lpszFile)) * hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ); * else * hmmio = (HMMIO)LOWORD(lpszFile); * * if (hmmio == NULL) * return NULL; * * mmioSeek(hmmio, 0, SEEK_SET); * * /* descend the input file into the RIFF chunk */ * if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0) * goto error; * * if (ckRIFF.ckid != FOURCC_RIFF) * goto error; * * ckLIST.fccType = FOURCC_INFO; * if (mmioDescend(hmmio, &ckLIST, &ckRIFF, MMIO_FINDLIST) != 0) * goto error; * * ckinfo.ckid = fcc; * if (mmioDescend(hmmio, &ckinfo, &ckLIST, MMIO_FINDCHUNK) != 0) * goto error; * * /* Find out how much memory to allocate/read */ * dwSize = ckinfo.cksize; * * if (pv == NULL) * { * /* get a handle to memory to hold the description and lock it down */ * h = GlobalAlloc(GHND, dwSize+1); * * if (!h) * goto error; * * pv = GlobalLock(h); * } * else * { * if (dwSize > (DWORD)iLen-1) * dwSize = (DWORD)iLen-1; * * ((LPSTR)pv)[(int)dwSize] = 0; * } * * /* read the description into the allocated memory */ * if (mmioRead(hmmio, pv, (LONG)dwSize) != (LONG)dwSize) * goto error; * * if (HIWORD(lpszFile)) * mmioClose(hmmio, 0); * * return h ? h : (HANDLE)(UINT)dwSize; * * error: * if (hmmio && HIWORD(lpszFile)) * mmioClose(hmmio, 0); * * if (h) * GlobalFree(h); * * return NULL; * } * #endif