Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

611 lines
16 KiB

  1. /****************************************************************************
  2. *
  3. * MODULE : RIFFDISP.C
  4. *
  5. ****************************************************************************/
  6. #include <windows.h>
  7. #include <win32.h>
  8. #include <mmsystem.h>
  9. #include <commdlg.h>
  10. #include <drawdib.h>
  11. #include "riffdisp.h"
  12. #include "avifile.h"
  13. static HWND hwndPreview;
  14. static HANDLE hdibPreview;
  15. static char achPreview[80];
  16. static HFONT hfontPreview;
  17. static HDRAWDIB hdd;
  18. #define GetHInstance() (HINSTANCE)(SELECTOROF((LPVOID)&hwndPreview))
  19. #define DibSizeImage(lpbi) (\
  20. (DWORD)(UINT)((((int)lpbi->biBitCount*(int)lpbi->biWidth+31)&~31)>>3) * \
  21. (DWORD)(UINT)lpbi->biHeight)
  22. #define DibSize(lpbi) \
  23. (lpbi->biSize + ((int)lpbi->biClrUsed * sizeof(RGBQUAD)) + lpbi->biSizeImage)
  24. #define DibNumColors(lpbi) \
  25. (lpbi->biBitCount <= 8 ? (1 << (int)lpbi->biBitCount) : 0)
  26. /***************************************************************************
  27. *
  28. ****************************************************************************/
  29. //#define FOURCC_RIFF mmioFOURCC('R','I','F','F')
  30. #define FOURCC_AVI mmioFOURCC('A','V','I',' ')
  31. #define FOURCC_INFO mmioFOURCC('I','N','F','O')
  32. #define FOURCC_DISP mmioFOURCC('D','I','S','P')
  33. #define FOURCC_INAM mmioFOURCC('I','N','A','M')
  34. #define FOURCC_ISBJ mmioFOURCC('I','S','B','J')
  35. BOOL PreviewOpen(HWND hwnd);
  36. BOOL PreviewFile(HWND hwnd, LPSTR szFile);
  37. BOOL PreviewPaint(HWND hwnd);
  38. BOOL PreviewClose(HWND hwnd);
  39. HANDLE ReadDisp(LPSTR lpszFile, int cf, LPSTR pv, int iLen);
  40. HANDLE ReadInfo(LPSTR lpszFile, FOURCC fcc, LPSTR pv, int iLen);
  41. HANDLE GetRiffDisp(LPSTR lpszFile, LPSTR szText, int iLen);
  42. /***************************************************************************
  43. *
  44. ****************************************************************************/
  45. BOOL PreviewOpen(HWND hwnd)
  46. {
  47. LOGFONT lf;
  48. if (hwndPreview)
  49. return FALSE;
  50. hwndPreview = hwnd;
  51. hdd = DrawDibOpen();
  52. SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0);
  53. hfontPreview = CreateFontIndirect(&lf);
  54. }
  55. /***************************************************************************
  56. *
  57. ****************************************************************************/
  58. BOOL PreviewClose(HWND hwnd)
  59. {
  60. if (hwndPreview != hwnd)
  61. return FALSE;
  62. if (hdibPreview)
  63. GlobalFree(hdibPreview);
  64. if (hfontPreview)
  65. DeleteObject(hfontPreview);
  66. if (hdd)
  67. DrawDibClose(hdd);
  68. achPreview[0] = 0;
  69. hdd = NULL;
  70. hwndPreview = NULL;
  71. hdibPreview = NULL;
  72. hfontPreview = NULL;
  73. }
  74. /***************************************************************************
  75. *
  76. ****************************************************************************/
  77. BOOL PreviewFile(HWND hwnd, LPSTR szFile)
  78. {
  79. if (hwndPreview != hwnd)
  80. return FALSE;
  81. achPreview[0] = 0;
  82. if (hdibPreview)
  83. GlobalFree(hdibPreview);
  84. hdibPreview = NULL;
  85. if (szFile)
  86. {
  87. hdibPreview = GetRiffDisp(szFile, achPreview, sizeof(achPreview));
  88. }
  89. PreviewPaint(hwnd);
  90. return TRUE;
  91. }
  92. /***************************************************************************
  93. *
  94. ****************************************************************************/
  95. BOOL PreviewPaint(HWND hwnd)
  96. {
  97. RECT rc;
  98. RECT rcPreview;
  99. RECT rcImage;
  100. RECT rcText;
  101. HDC hdc;
  102. HBRUSH hbr;
  103. int dx;
  104. int dy;
  105. LPBITMAPINFOHEADER lpbi;
  106. if (hwndPreview != hwnd)
  107. return FALSE;
  108. //
  109. // locate the preview in the lower corner of the dialog (below the
  110. // cancel button)
  111. //
  112. //////!!! find a better way to do this.
  113. GetClientRect(hwnd, &rcPreview);
  114. GetWindowRect(GetDlgItem(hwnd, IDCANCEL), &rc);
  115. ScreenToClient(hwnd, (LPPOINT)&rc);
  116. ScreenToClient(hwnd, (LPPOINT)&rc+1);
  117. rcPreview.top = rc.bottom + (rc.bottom - rc.top) + 12;
  118. rcPreview.left = rc.left;
  119. rcPreview.right = rc.right;
  120. rcPreview.bottom -= 4; // leave a little room at the bottom
  121. //////
  122. hdc = GetDC(hwnd);
  123. hbr = (HBRUSH)DefWindowProc(hwnd, WM_CTLCOLOR, (WPARAM)hdc, MAKELONG(hwnd, CTLCOLOR_DLG));
  124. SelectObject(hdc, hfontPreview);
  125. SetStretchBltMode(hdc, COLORONCOLOR);
  126. InflateRect(&rcPreview, 4, 1);
  127. FillRect(hdc, &rcPreview, hbr);
  128. IntersectClipRect(hdc, rcPreview.left, rcPreview.top, rcPreview.right, rcPreview.bottom);
  129. InflateRect(&rcPreview, -4, -1);
  130. //
  131. // compute the text rect, using DrawText
  132. //
  133. rcText = rcPreview;
  134. rcText.bottom = rcText.top;
  135. DrawText(hdc, achPreview, -1, &rcText, DT_CALCRECT|DT_LEFT|DT_WORDBREAK);
  136. //
  137. // compute the image size
  138. //
  139. if (hdibPreview && hdd)
  140. {
  141. lpbi = (LPVOID)GlobalLock(hdibPreview);
  142. #if 0
  143. //
  144. // DISP(CF_DIB) chunks are messed up they contain a DIB file! not
  145. // a CF_DIB, skip over the header if it is there.
  146. //
  147. if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
  148. (LPSTR)lpbi += sizeof(BITMAPFILEHEADER);
  149. #endif
  150. rcImage = rcPreview;
  151. //
  152. // if wider than preview area scale to fit
  153. //
  154. if ((int)lpbi->biWidth > rcImage.right - rcImage.left)
  155. {
  156. rcImage.bottom = rcImage.top + MulDiv((int)lpbi->biHeight,rcImage.right-rcImage.left,(int)lpbi->biWidth);
  157. }
  158. //
  159. // if x2 will fit then use it
  160. //
  161. else if ((int)lpbi->biWidth * 2 < rcImage.right - rcImage.left)
  162. {
  163. rcImage.right = rcImage.left + (int)lpbi->biWidth*2;
  164. rcImage.bottom = rcImage.top + (int)lpbi->biHeight*2;
  165. }
  166. //
  167. // else center the image in the preview area
  168. //
  169. else
  170. {
  171. rcImage.right = rcImage.left + (int)lpbi->biWidth;
  172. rcImage.bottom = rcImage.top + (int)lpbi->biHeight;
  173. }
  174. if (rcImage.bottom > rcPreview.bottom - (rcText.bottom - rcText.top))
  175. {
  176. rcImage.bottom = rcPreview.bottom - (rcText.bottom - rcText.top);
  177. rcImage.right = rcPreview.left + MulDiv((int)lpbi->biWidth,rcImage.bottom-rcImage.top,(int)lpbi->biHeight);
  178. rcImage.left = rcPreview.left;
  179. }
  180. }
  181. else
  182. {
  183. SetRectEmpty(&rcImage);
  184. }
  185. //
  186. // now center
  187. //
  188. dx = ((rcPreview.right - rcPreview.left) - (rcText.right - rcText.left))/2;
  189. OffsetRect(&rcText, dx, 0);
  190. dx = ((rcPreview.right - rcPreview.left) - (rcImage.right - rcImage.left))/2;
  191. OffsetRect(&rcImage, dx, 0);
  192. dy = rcPreview.bottom - rcPreview.top;
  193. dy -= rcImage.bottom - rcImage.top;
  194. dy -= rcText.bottom - rcText.top;
  195. if (dy < 0)
  196. dy = 0;
  197. else
  198. dy = dy / 2;
  199. OffsetRect(&rcImage, 0, dy);
  200. OffsetRect(&rcText, 0, dy + rcImage.bottom - rcImage.top + 2);
  201. //
  202. // now draw
  203. //
  204. DrawText(hdc, achPreview, -1, &rcText, DT_LEFT|DT_WORDBREAK);
  205. if (hdibPreview && hdd)
  206. {
  207. DrawDibDraw(hdd,
  208. hdc,
  209. rcImage.left,
  210. rcImage.top,
  211. rcImage.right - rcImage.left,
  212. rcImage.bottom - rcImage.top,
  213. lpbi,
  214. NULL,
  215. 0,
  216. 0,
  217. -1,
  218. -1,
  219. 0);
  220. InflateRect(&rcImage, 1, 1);
  221. FrameRect(hdc, &rcImage, GetStockObject(BLACK_BRUSH));
  222. }
  223. ReleaseDC(hwnd, hdc);
  224. return TRUE;
  225. }
  226. /***************************************************************************
  227. *
  228. ****************************************************************************/
  229. static UINT (CALLBACK *lpfnOldHook)(HWND, UINT, WPARAM, LPARAM);
  230. /* Combo boxes */
  231. #define cmb1 0x0470
  232. #define cmb2 0x0471
  233. /* Listboxes */
  234. #define lst1 0x0460
  235. #define lst2 0x0461
  236. /* Edit controls */
  237. #define edt1 0x0480
  238. #define ID_TIMER 1234
  239. #define PREVIEWWAIT 1000
  240. WORD FAR PASCAL _export GetFileNamePreviewHook(HWND hwnd, unsigned msg, WORD wParam, LONG lParam)
  241. {
  242. int i;
  243. char ach[80];
  244. switch (msg) {
  245. case WM_COMMAND:
  246. switch (wParam)
  247. {
  248. case lst1:
  249. if (HIWORD(lParam) == LBN_SELCHANGE)
  250. {
  251. KillTimer(hwnd, ID_TIMER);
  252. SetTimer(hwnd, ID_TIMER, PREVIEWWAIT, NULL);
  253. }
  254. break;
  255. case IDOK:
  256. case IDCANCEL:
  257. KillTimer(hwnd, ID_TIMER);
  258. PreviewFile(hwnd, NULL);
  259. break;
  260. case cmb1:
  261. case cmb2:
  262. case lst2:
  263. if (HIWORD(lParam) == LBN_SELCHANGE)
  264. {
  265. KillTimer(hwnd, ID_TIMER);
  266. PreviewFile(hwnd, NULL);
  267. }
  268. break;
  269. }
  270. break;
  271. case WM_TIMER:
  272. if (wParam == ID_TIMER)
  273. {
  274. KillTimer(hwnd, ID_TIMER);
  275. ach[0] = 0;
  276. i = (int)SendDlgItemMessage(hwnd, lst1, LB_GETCURSEL, 0, 0L);
  277. SendDlgItemMessage(hwnd, lst1, LB_GETTEXT, i, (LONG)(LPSTR)ach);
  278. PreviewFile(hwnd, ach);
  279. return TRUE;
  280. }
  281. break;
  282. case WM_QUERYNEWPALETTE:
  283. case WM_PALETTECHANGED:
  284. case WM_PAINT:
  285. PreviewPaint(hwnd);
  286. break;
  287. case WM_INITDIALOG:
  288. PreviewOpen(hwnd);
  289. if (!lpfnOldHook)
  290. return TRUE;
  291. break;
  292. case WM_DESTROY:
  293. PreviewClose(hwnd);
  294. break;
  295. }
  296. if (lpfnOldHook)
  297. return (*lpfnOldHook)(hwnd, msg, wParam, lParam);
  298. else
  299. return FALSE;
  300. }
  301. /**************************************************************************
  302. * @doc EXTERNAL AVIGetStream
  303. *
  304. * @api BOOL | GetOpenFileNamePreview | This function is similar
  305. * to <f GetOpenFileName> defined in COMMDLG.DLL except that
  306. * it has a preview window to display the movie about to be opened.
  307. *
  308. * @parm LPOPENFILENAME | lpofn | Points to an <t OPENFILENAME> structure
  309. * used to initialize the dialog box. On return, the structure
  310. * contains information about the user's file selection.
  311. *
  312. * @rdesc Returns true if a file was opened.
  313. *
  314. * @comm For more information on this function, see the description for
  315. * <f GetOpenFileName>.
  316. *
  317. * @xref <f GetOpenFileName>
  318. *
  319. *************************************************************************/
  320. BOOL FAR PASCAL GetOpenFileNamePreview(LPOPENFILENAME lpofn)
  321. {
  322. BOOL fHook;
  323. BOOL f;
  324. if (hwndPreview)
  325. return GetOpenFileName(lpofn);
  326. fHook = (BOOL)(lpofn->Flags & OFN_ENABLEHOOK);
  327. if (fHook)
  328. lpfnOldHook = lpofn->lpfnHook;
  329. (FARPROC)lpofn->lpfnHook = MakeProcInstance((FARPROC)GetFileNamePreviewHook, GetHInstance());
  330. lpofn->Flags |= OFN_ENABLEHOOK;
  331. f = GetOpenFileName(lpofn);
  332. FreeProcInstance((FARPROC)lpofn->lpfnHook);
  333. if (fHook)
  334. lpofn->lpfnHook = lpfnOldHook;
  335. else
  336. lpofn->Flags &= ~OFN_ENABLEHOOK;
  337. return f;
  338. }
  339. HANDLE AVIFirstFrame(LPSTR szFile)
  340. {
  341. HANDLE h = NULL;
  342. LPBITMAPINFOHEADER lpbi;
  343. DWORD dwSize;
  344. PAVISTREAM pavi;
  345. PGETFRAME pg;
  346. if (AVIStreamOpenFromFile(&pavi, szFile, streamtypeVIDEO, 0, OF_READ, NULL) == AVIERR_OK)
  347. {
  348. pg = AVIStreamGetFrameOpen(pavi, NULL);
  349. if (pg) {
  350. lpbi = AVIStreamGetFrame(pg, 0);
  351. if (lpbi)
  352. {
  353. dwSize = lpbi->biSize + lpbi->biSizeImage + lpbi->biClrUsed * sizeof(RGBQUAD);
  354. h = GlobalAlloc(GHND, dwSize);
  355. if (h)
  356. hmemcpy(GlobalLock(h), lpbi, dwSize);
  357. }
  358. AVIStreamGetFrameClose(pg);
  359. }
  360. AVIStreamClose(pavi);
  361. }
  362. return h;
  363. }
  364. /****************************************************************************
  365. *
  366. * get both the DISP(CF_DIB) and the DISP(CF_TEXT) info in one pass, this is
  367. * much faster than doing multiple passes over the file.
  368. *
  369. ****************************************************************************/
  370. HANDLE GetRiffDisp(LPSTR lpszFile, LPSTR szText, int iLen)
  371. {
  372. HMMIO hmmio;
  373. MMCKINFO ck;
  374. MMCKINFO ckINFO;
  375. MMCKINFO ckRIFF;
  376. HANDLE h = NULL;
  377. LONG lSize;
  378. DWORD dw;
  379. HCURSOR hcur = NULL;
  380. if (szText)
  381. szText[0] = 0;
  382. /* Open the file */
  383. hmmio = mmioOpen(lpszFile, NULL, MMIO_ALLOCBUF | MMIO_READ);
  384. if (hmmio == NULL)
  385. return NULL;
  386. mmioSeek(hmmio, 0, SEEK_SET);
  387. /* descend the input file into the RIFF chunk */
  388. if (mmioDescend(hmmio, &ckRIFF, NULL, 0) != 0)
  389. goto error;
  390. if (ckRIFF.ckid != FOURCC_RIFF)
  391. goto error;
  392. while (!mmioDescend(hmmio, &ck, &ckRIFF, 0))
  393. {
  394. if (ck.ckid == FOURCC_DISP)
  395. {
  396. if (hcur == NULL)
  397. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  398. /* Read dword into dw, break if read unsuccessful */
  399. if (mmioRead(hmmio, (LPVOID)&dw, sizeof(dw)) != sizeof(dw))
  400. goto error;
  401. /* Find out how much memory to allocate */
  402. lSize = ck.cksize - sizeof(dw);
  403. if ((int)dw == CF_DIB && h == NULL)
  404. {
  405. /* get a handle to memory to hold the description and lock it down */
  406. if ((h = GlobalAlloc(GHND, lSize+4)) == NULL)
  407. goto error;
  408. if (mmioRead(hmmio, GlobalLock(h), lSize) != lSize)
  409. goto error;
  410. }
  411. else if ((int)dw == CF_TEXT && szText[0] == 0)
  412. {
  413. if (lSize > iLen-1)
  414. lSize = iLen-1;
  415. szText[lSize] = 0;
  416. if (mmioRead(hmmio, szText, lSize) != lSize)
  417. goto error;
  418. }
  419. }
  420. else if (ck.ckid == FOURCC_LIST &&
  421. ck.fccType == FOURCC_INFO &&
  422. szText[0] == 0)
  423. {
  424. while (!mmioDescend(hmmio, &ckINFO, &ck, 0))
  425. {
  426. switch (ckINFO.ckid)
  427. {
  428. case FOURCC_INAM:
  429. // case FOURCC_ISBJ:
  430. lSize = ck.cksize;
  431. if (lSize > iLen-1)
  432. lSize = iLen-1;
  433. szText[lSize] = 0;
  434. if (mmioRead(hmmio, szText, lSize) != lSize)
  435. goto error;
  436. break;
  437. }
  438. if (mmioAscend(hmmio, &ckINFO, 0))
  439. break;
  440. }
  441. }
  442. //
  443. // if we have both a picture and a title, then exit.
  444. //
  445. if (h != NULL && szText[0] != 0)
  446. break;
  447. /* Ascend so that we can descend into next chunk
  448. */
  449. if (mmioAscend(hmmio, &ck, 0))
  450. break;
  451. }
  452. goto exit;
  453. error:
  454. if (h)
  455. GlobalFree(h);
  456. h = NULL;
  457. ckRIFF.fccType = 0;
  458. exit:
  459. mmioClose(hmmio, 0);
  460. //
  461. // !!!we need a way to preview other file types!
  462. // !!!what about text.
  463. //
  464. if (h == NULL && ckRIFF.fccType == FOURCC_AVI)
  465. {
  466. if (hcur == NULL)
  467. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  468. h = AVIFirstFrame(lpszFile);
  469. }
  470. //
  471. // verify and correct the DIB
  472. //
  473. if (h)
  474. {
  475. LPBITMAPINFOHEADER lpbi;
  476. lpbi = (LPVOID)GlobalLock(h);
  477. if (lpbi->biSize < sizeof(BITMAPINFOHEADER))
  478. goto error;
  479. if (lpbi->biClrUsed == 0)
  480. lpbi->biClrUsed = DibNumColors(lpbi);
  481. if (lpbi->biSizeImage == 0)
  482. lpbi->biSizeImage = DibSizeImage(lpbi);
  483. if (DibSize(lpbi) > GlobalSize(h))
  484. goto error;
  485. }
  486. if (hcur)
  487. SetCursor(hcur);
  488. return h;
  489. }