home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / rleapp / rleapp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-04  |  51.9 KB  |  1,974 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   rleapp.c - RLE Sample Application. Multimedia Systems Group                |
  3. |                                                                              |
  4. \*----------------------------------------------------------------------------*/
  5.  
  6. /*
  7.      (C) Copyright Microsoft Corp. 1991, 1992.  All rights reserved.
  8.  
  9.      You have a royalty-free right to use, modify, reproduce and 
  10.      distribute the Sample Files (and/or any modified version) in 
  11.      any way you find useful, provided that you agree that 
  12.      Microsoft has no warranty obligations or liability for any 
  13.      Sample Application Files which are modified. 
  14.      
  15.      If you did not get this from Microsoft Sources, then it may not be the
  16.      most current version.  This sample code in particular will be updated
  17.      and include more documentation.  
  18.  
  19.      Sources are:
  20.          The MM Sys BBS: The phone number is 206 936-4082.
  21.     CompuServe: WINSDK forum, MDK section.
  22. */
  23.  
  24. #include <windows.h>
  25. #include <mmsystem.h>
  26. #include <commdlg.h>
  27.  
  28. #include "gmem.h"
  29. #include "rleapp.h"
  30. #include "rle.h"
  31. #include "dib.h"
  32.  
  33. //
  34. // DisplayDib API
  35. //
  36. #define DISPLAYDIB_MODE             0x000F
  37. #define DISPLAYDIB_NOPALETTE        0x0010
  38. #define DISPLAYDIB_NOCENTER         0x0020
  39. #define DISPLAYDIB_BEGIN            0x8000
  40. #define DISPLAYDIB_END              0x4000
  41. #define DISPLAYDIB_MODE_DEFAULT     0x0000
  42. #define DISPLAYDIB_MODE_320x200x8   0x0001
  43. #define DISPLAYDIB_MODE_320x400x8   0x0002
  44. #define DISPLAYDIB_MODE_360x480x8   0x0003
  45. #define DISPLAYDIB_MODE_320x480x8   0x0004
  46. #define DISPLAYDIB_MODE_320x240x8   0x0005
  47.  
  48. WORD (FAR PASCAL *DisplayDib)(LPBITMAPINFOHEADER lpbi, LPSTR lpBits, WORD wFlags);
  49.  
  50. char    szDisplayDibDll[] = "DISPDIB.DLL";
  51. HANDLE  hDisplayDibDll;
  52.  
  53. /*----------------------------------------------------------------------------*\
  54. |                                                                              |
  55. |   g l o b a l   v a r i a b l e s                                            |
  56. |                                                                              |
  57. \*----------------------------------------------------------------------------*/
  58.  
  59. HANDLE  hAccTable;                              /* handle to accelerator table */
  60.  
  61. static  char    szAppName[]="RLE";
  62. static  char    gszCurFilespec[128];         /* used for File Revert */
  63. static  HANDLE  hInstApp;
  64. static  HWND    hwndApp;
  65. static  int     tmHeight;
  66.  
  67. int          gChannels;                  // Info about the Wave data
  68. DWORD        gSamplesPerSec;
  69. DWORD        gdwBufferLength = 0L;       // start and len of movie's 1st wave
  70. BYTE huge  * glpData = NULL;
  71. LPWAVEFORMAT pWaveFormat;
  72. LPWAVEHDR    pwhMovie;
  73. HWAVEOUT     hWaveOut;
  74.  
  75. char        szFilters[] = "Rle Files\0*.rle;*.rl0\0"
  76.                           "Bitmaps\0*.bmp;*.dib\0"
  77.                           "Wave Files\0*.wav\0"
  78.                           "All Files\0*.*\0"
  79.                           "";
  80.  
  81. FRAME        far *arFrames;
  82. int         curFrame;
  83. int         curWave;
  84. int         numFrames;
  85. int         totFrames = 0;
  86. int         numWaves;    // how many frames have wave data
  87. int         lastWave;    // the first frame without wave data (zero based)
  88. HPALETTE    hpalApp;
  89. POINT       ptFrame = {0,0};
  90. POINT       ptSizeFrame = {0,0};
  91. BOOL        fDirty;
  92.  
  93. WORD        gDisplayMode = 0;
  94. BOOL        fPlay       = FALSE;
  95. BOOL        fActive     = FALSE;
  96. BOOL        fLoading    = FALSE;
  97. BOOL        fStatus     = TRUE;
  98. BOOL        fPaint      = TRUE;
  99.  
  100. BOOL        fFullPaint  = FALSE;
  101. BOOL        fSkipFrames = FALSE;
  102.  
  103. WORD        wPalFlags   = 0;    // PC_NOCOLLAPSE;
  104.  
  105. long        RealFramesSec;
  106. long        FramesSec = (15 * FramesSecScale);
  107.  
  108. LONG        msFrameBase = 0L;
  109. int         nFramesPlayed = 0;
  110.  
  111. OPENFILENAME ofn;
  112.  
  113. /*----------------------------------------------------------------------------*\
  114. |                                                                              |
  115. |   f u n c t i o n   d e f i n i t i o n s                                    |
  116. |                                                                              |
  117. \*----------------------------------------------------------------------------*/
  118.  
  119. LONG EXPORT AppWndProc (HWND hwnd, unsigned uiMessage, WORD wParam, LONG lParam);
  120.  
  121. HPALETTE CopyPalette(HPALETTE hpal);
  122. BOOL QueryClose(HWND hwnd);
  123.  
  124. void PlayFrame(HDC hdc, int iFrame, int x, int y, BOOL fIgnoreFlags);
  125. void PaintStatus(HWND hwnd, HDC hdc);
  126.  
  127. void RleFrames(void);
  128. void RleAllFrames(HWND hwnd);
  129. BOOL RealizeFrames(void);
  130.  
  131. LONG  NEAR PASCAL AppCommand(HWND hwnd, unsigned msg, WORD wParam, LONG lParam);
  132. void  NEAR PASCAL AppPaint(HWND hwnd, HDC hdc);
  133.  
  134. /*----------------------------------------------------------------------------*\
  135. \*----------------------------------------------------------------------------*/
  136.  
  137. HCURSOR hcurSave;
  138. int     fWait = 0;
  139.  
  140. void StartWait()
  141. {
  142.     if (fWait++ == 0)
  143.     {
  144.         SetCursor(LoadCursor(NULL,IDC_WAIT));
  145.     }
  146. }
  147.  
  148. void EndWait()
  149. {
  150.     if (--fWait == 0)
  151.     {
  152.         SetCursor(LoadCursor(NULL,IDC_ARROW));
  153.         InvalidateRect(hwndApp, NULL, TRUE);
  154.     }
  155. }
  156.  
  157. BOOL WinYield()
  158. {
  159.     MSG msg;
  160.     BOOL fAbort=FALSE;
  161.  
  162.     while(fWait > 0 && PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  163.     {
  164.     if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)
  165.             fAbort = TRUE;
  166.     if (msg.message == WM_SYSCOMMAND && (msg.wParam & 0xFFF0) == SC_CLOSE)
  167.         fAbort = TRUE;
  168.     TranslateMessage(&msg);
  169.     DispatchMessage(&msg);
  170.     }
  171.     return fAbort;
  172. }
  173.  
  174. void SoundPlay(int iFrame, int iCount) 
  175. {
  176.     LPWAVEHDR pwh;
  177.     DWORD dwFirstSample, dwLenSegment;
  178.  
  179.     if (hWaveOut && pwhMovie)
  180.     {
  181.         pwh = pwhMovie;
  182.  
  183.         if (!(pwh->dwFlags & WHDR_DONE))
  184.         {
  185.             waveOutReset(hWaveOut);
  186.             pwh->dwFlags &= ~WHDR_DONE;
  187.         }
  188.  
  189.         dwFirstSample = muldiv32(iFrame,FramesSecScale*gSamplesPerSec*gChannels,FramesSec);
  190.         dwLenSegment  = muldiv32(iCount,FramesSecScale*gSamplesPerSec*gChannels,FramesSec);
  191.  
  192.     if (dwLenSegment > (gdwBufferLength - dwFirstSample))
  193.         dwLenSegment = gdwBufferLength - dwFirstSample;
  194.  
  195.     if (dwFirstSample < gdwBufferLength)
  196.     {
  197.         (BYTE huge *)(pwh->lpData) = (BYTE huge *)glpData + dwFirstSample;
  198.         pwh->dwBufferLength = dwLenSegment;
  199.     }
  200.  
  201.         if (dwLenSegment > 0)
  202.         {
  203.             waveOutWrite(hWaveOut,pwh, sizeof(WAVEHDR));
  204.         }
  205.     }
  206. }
  207.  
  208. void SoundOpen()
  209. {
  210.     WORD err;
  211.     char ach[80];
  212.  
  213.     if (!hWaveOut && pWaveFormat && pwhMovie)
  214.     {
  215.         err = waveOutOpen(&hWaveOut, WAVE_MAPPER, pWaveFormat, hwndApp, 0, CALLBACK_WINDOW);
  216.  
  217.     if (err)
  218.         {
  219.             if (waveOutGetNumDevs() > 0)
  220.             {
  221.                 waveOutGetErrorText(err, ach, sizeof(ach));
  222.                 ErrMsg("Unable to open wave device!\n%ls", (LPSTR)ach);
  223.             }
  224.             hWaveOut = NULL;
  225.             return;
  226.         }
  227.  
  228.         pwhMovie->dwBufferLength=gdwBufferLength;
  229.         pwhMovie->lpData = glpData;
  230.  
  231.         waveOutPrepareHeader(hWaveOut,pwhMovie,sizeof(WAVEHDR));
  232.     }
  233. }
  234.  
  235. void SoundClose()
  236. {
  237.     if (hWaveOut)
  238.     {
  239.         pwhMovie->dwBufferLength=gdwBufferLength;
  240.         pwhMovie->lpData = glpData;
  241.  
  242.         waveOutReset(hWaveOut);
  243.         waveOutUnprepareHeader(hWaveOut,pwhMovie,sizeof(WAVEHDR));
  244.  
  245.     waveOutClose(hWaveOut);
  246.         hWaveOut = NULL;
  247.     }
  248. }
  249.  
  250. /*----------------------------------------------------------------------------*\
  251. |                                                                              |
  252. \*----------------------------------------------------------------------------*/
  253. #define FRAME_NEXT      -1
  254. #define FRAME_PREV      -2
  255. void ShowFrame(int nFrame)
  256. {
  257.     HDC hdc;
  258.  
  259.     if (numFrames == 0)
  260.     {
  261.     InvalidateRect(hwndApp,NULL,TRUE);
  262.     return;
  263.     }
  264.  
  265.     switch (nFrame)
  266.     {
  267.     case FRAME_NEXT:
  268.         curFrame = (curFrame+1) % numFrames;
  269.         break;
  270.  
  271.     case FRAME_PREV:
  272.         if (curFrame-- == 0)
  273.         curFrame = numFrames-1;
  274.         break;
  275.  
  276.     default:
  277.             curFrame = nFrame % numFrames;
  278.         InvalidateRect(hwndApp,NULL,FALSE);
  279.         UpdateWindow(hwndApp);
  280.         return;
  281.     }
  282.  
  283.     hdc = GetDC(hwndApp);
  284.  
  285.     PaintStatus(hwndApp,hdc);
  286.     PlayFrame(hdc, curFrame, ptFrame.x, ptFrame.y, FALSE);
  287.  
  288.     ReleaseDC(hwndApp,hdc);
  289. }
  290.  
  291. void FreeFrame(int iFrame)
  292. {
  293.     if (iFrame < 0 || iFrame >= numFrames)
  294.     return;
  295.  
  296.     if (arFrames[iFrame].hpal && !(arFrames[iFrame].f & F_PALSHARED))
  297.     DeleteObject(arFrames[iFrame].hpal);
  298.     if (arFrames[iFrame].hdib)
  299.     GFree(arFrames[iFrame].hdib);
  300.     if (arFrames[iFrame].hrle && arFrames[iFrame].hdib != arFrames[iFrame].hrle)
  301.     GFree(arFrames[iFrame].hrle);
  302.  
  303.     arFrames[iFrame].hdib = NULL;
  304.     arFrames[iFrame].hrle = NULL;
  305.     arFrames[iFrame].hpal = NULL;
  306.     arFrames[iFrame].f    = 0;
  307. }
  308.  
  309. void FreeFrames()
  310. {
  311.     int i;
  312.  
  313.     SoundClose();
  314.  
  315.     for (i=0; i<numFrames; i++)
  316.         FreeFrame(i);
  317.  
  318.     numFrames = 0;
  319.     curFrame  = 0;
  320.     numWaves  = 0;
  321.     lastWave  = 0;
  322.     curWave   = 0;
  323.     fPaint    = TRUE;
  324.     fDirty    = FALSE;
  325.  
  326.     if (pWaveFormat)            // Free the movie's wave header
  327.         GFreePtr(pWaveFormat);
  328.  
  329.     if (pwhMovie)                       // Free the movie's wave data
  330.         GFreePtr(pwhMovie);
  331.  
  332.     pWaveFormat = NULL;
  333.     pwhMovie  = NULL;
  334.  
  335.     ShowFrame(0);
  336. }
  337.  
  338. /* This routine will play the movie in full screen VGA mode using DISPDIB */
  339.  
  340. void PlayVga(HWND hwnd)
  341. {
  342.     MSG      msg;
  343.     HANDLE   hdib;
  344.     HPALETTE hpal;
  345.     WORD     f;
  346.     long     msTime;
  347.     int      iFrame;
  348.  
  349.     if (numFrames == 0)
  350.     return;
  351.  
  352.     curFrame = 0;
  353.     hdib = FrameRle(curFrame);
  354.     hpal = FramePalette(curFrame);
  355.     f    = FrameFlags(curFrame);
  356.     // We must use RGB colours so the right palette is used
  357.  
  358.     SetDibUsage(hdib, hpal, DIB_RGB_COLORS);
  359.     DisplayDib(GLock(hdib), NULL, DISPLAYDIB_BEGIN | gDisplayMode);
  360.     DisplayDib(GLock(hdib), NULL, NULL);
  361.     SetDibUsage(hdib, hpal, DIB_PAL_COLORS);
  362.  
  363.     SetTimer(hwnd,1,2000,NULL);    // Wait 2 seconds so VGA can sync
  364.     GetMessage(&msg, NULL, WM_TIMER, WM_TIMER);
  365.     KillTimer(hwnd,1);
  366.  
  367.     GetAsyncKeyState(VK_ESCAPE);    // If ESC was hit, use it up now
  368.  
  369.     SoundOpen();
  370.     SoundPlay(0, numFrames);
  371.     msFrameBase = timeGetTime();
  372.  
  373.     while (GetAsyncKeyState(VK_ESCAPE) == 0)
  374.     {
  375.     if(PeekMessage(&msg,hwnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOYIELD | PM_REMOVE))
  376.         break;
  377.     
  378.     //
  379.     // wait until it is time for next frame.
  380.         //
  381.         do
  382.     {
  383.         msTime = timeGetTime() - msFrameBase;
  384.         iFrame = (int)(msTime * FramesSec / 1000 / FramesSecScale);
  385.     } while (iFrame == curFrame);
  386.  
  387.     if (fSkipFrames)
  388.         curFrame = iFrame;
  389.     else
  390.         curFrame++;
  391.  
  392.     if (curFrame >= numFrames)
  393.     {
  394.         curFrame = 0;
  395.         SoundPlay(0, numFrames);
  396.         msFrameBase = timeGetTime();
  397.     }
  398.  
  399.     hdib = FrameRle(curFrame);
  400.     hpal = FramePalette(curFrame);
  401.     f    = FrameFlags(curFrame);
  402.  
  403.  
  404.     // New palette for this frame, so use RGB colours
  405.  
  406.     if (!(f & F_PALSHARED)) // palette changed?
  407.     {
  408.         SetDibUsage(hdib, hpal, DIB_RGB_COLORS);
  409.         DisplayDib(GLock(hdib), NULL, NULL);
  410.         SetDibUsage(hdib, hpal, DIB_PAL_COLORS);
  411.     }
  412.     else      // same palette as last time, use PAL colours
  413.     {
  414.         DisplayDib(GLock(hdib), NULL, DISPLAYDIB_NOPALETTE);
  415.     }
  416.     }
  417.  
  418.     DisplayDib(NULL, NULL, DISPLAYDIB_END);
  419.     SoundClose();
  420. }
  421.  
  422.  
  423. HANDLE RenderFrame(int iFrame)
  424. {
  425.     HANDLE   hdib;
  426.     int      i;
  427.  
  428.     if (iFrame<0 || iFrame>=numFrames)
  429.     return NULL;
  430.  
  431.     //
  432.     // if we have a DIB for this frame, return it!
  433.     //
  434.     if (arFrames[iFrame].hdib)
  435.         return arFrames[iFrame].hdib;
  436.  
  437.     StartWait();
  438.  
  439.     //
  440.     // Search for the 'nearest' full frame (or the first frame)
  441.     //
  442.     for (i=iFrame; i>0 && arFrames[i].hdib==NULL; i--)
  443.     ;
  444.  
  445.     //
  446.     //  Create a DIB of the last full frame found
  447.     //
  448.     if (arFrames[i].hdib == NULL)
  449.     {
  450.     LPBITMAPINFOHEADER prle;
  451.     LPBITMAPINFOHEADER pdib;
  452.  
  453.     prle = GLock(arFrames[i].hrle);
  454.     hdib = CreateDib(8, (int)prle->biWidth, (int)prle->biHeight);
  455.     if (!hdib) 
  456.     {
  457.         ErrMsg("Out of Memory Error");
  458.         goto exit;
  459.     }
  460.         
  461.     pdib = GLock(hdib);
  462.  
  463.     //
  464.     //  copy over the color table from the RLE to the empty DIB
  465.     //
  466.         MemCopy((LPSTR)pdib+(int)pdib->biSize,
  467.         (LPSTR)prle+(int)prle->biSize, 256*sizeof(RGBQUAD));
  468.  
  469.     }
  470.     else
  471.     {
  472.     hdib = CopyDib(arFrames[i].hdib);
  473.     i++;
  474.     }
  475.  
  476.     if (!hdib) 
  477.     {
  478.     ErrMsg("Out of Memory Error");
  479.     goto exit;
  480.     }
  481.  
  482.     //
  483.     //  Create the frame from 'scratch' (by playing each frame from zero)
  484.     //
  485.     for (; i<=iFrame; i++)
  486.     PlayRleDib(hdib, 0, 0, arFrames[i].hrle);
  487.  
  488.     arFrames[iFrame].hdib = hdib;
  489.  
  490. exit:
  491.     EndWait();
  492.     return hdib;
  493. }
  494.  
  495. void NukeRle(int i)                     // Erase the RLE if a DIB exists
  496. {
  497.     if ((i < 0) || (i >= numFrames))
  498.     return;
  499.     if (arFrames[i].hdib && arFrames[i].hrle && 
  500.        arFrames[i].hdib != arFrames[i].hrle) 
  501.     {
  502.     GFree(arFrames[i].hrle);
  503.     arFrames[i].hrle = NULL;
  504.         arFrames[i].f &= ~(F_RLE);
  505.     }
  506. }
  507.  
  508. void NukeDib(int i)            // Erase the DIB if an RLE exists
  509. {
  510.     if ((i < 0) || (i >= numFrames))
  511.     return;
  512.     if (arFrames[i].hdib && arFrames[i].hrle && 
  513.        arFrames[i].hdib != arFrames[i].hrle) 
  514.     {
  515.     GFree(arFrames[i].hdib);
  516.     arFrames[i].hdib = NULL;
  517.     }
  518. }
  519.  
  520. /* RleFrame - Rle the given frame - and maybe update the DIB copy, too
  521.    ========            */
  522.  
  523. HANDLE RleFrame(int i, BOOL fUpdateDib)
  524. {
  525.     HPALETTE hpal;
  526.     HANDLE   hrle;
  527.     HANDLE   hdib, hdibT;
  528.  
  529.     if (i < 0 || i >= numFrames)
  530.     return NULL;
  531.  
  532.     hrle = arFrames[i].hrle;
  533.  
  534.     if (hrle)            /* Return the one we've got already */
  535.     return hrle;
  536.     
  537.     hpal = arFrames[i].hpal;
  538.     
  539.     if (i == 0) 
  540.     {
  541.     if (arFrames[i].hdib) 
  542.     {
  543.         fDirty = TRUE;
  544.             arFrames[i].hrle = RleDeltaFrame(NULL,NULL,arFrames[i].hdib,0,0,0);
  545.  
  546.         if (!arFrames[i].hrle)
  547.                 ErrMsg("Out of Memory Error");
  548.             else
  549.                 arFrames[i].f |= F_RLE;
  550.     }
  551.     return arFrames[i].hrle;
  552.     } 
  553.     else 
  554.     {
  555.     if (arFrames[i].hdib) 
  556.     {
  557.         fDirty = TRUE;
  558.  
  559. // We need a DIB of the previous frame in order to Delta-RLE this frame
  560.  
  561.         hdib = arFrames[i-1].hdib;
  562.         hdibT = RenderFrame(i-1); /* Un-RLE's the previous frame */
  563.         if (!hdibT) 
  564.         {
  565.         ErrMsg("Out of Memory Error");
  566.         return NULL;
  567.         }
  568.             arFrames[i].hrle = RleDeltaFrame(NULL,arFrames[i-1].hdib,
  569.                     arFrames[i].hdib,0,0,0);
  570.  
  571.         if (!arFrames[i].hrle)
  572.                 ErrMsg("Out of Memory Error");
  573.             else
  574.                 arFrames[i].f |= F_RLE;
  575.     }
  576.     }
  577.  
  578. // Now, change the DIB copy to reflect what will actually be on the screen
  579. // at this point in the movie, since the RLE may have lost some detail.
  580.  
  581.     if (fUpdateDib && arFrames[i].hrle) 
  582.     {
  583.     NukeDib(i);
  584.     RenderFrame(i);
  585.     }
  586.     ShowFrame(i);
  587.  
  588.     return arFrames[i].hrle;
  589. }
  590.  
  591. void PurgeFrames()
  592. {
  593.     int i;
  594.  
  595.     //
  596.     // Delete all HDIBs we don't need to save memory
  597.     //
  598.     for (i=0; i<numFrames; i++)
  599.     NukeDib(i);
  600. }
  601.  
  602. BOOL RealizeFrames()
  603. {
  604.     int i;
  605.     int curSave = curFrame;
  606.     
  607.     StartWait();
  608.     for (i = 0; i < numFrames; i++) 
  609.     {
  610.     if (!arFrames[i].hdib)
  611.         if (!RenderFrame(i))
  612.         goto realizebarf;
  613.     
  614.     NukeRle(i);
  615.     fDirty = TRUE;
  616.     ShowFrame(i);
  617.     if (WinYield())
  618.         goto realizebarf;
  619.     }
  620.     EndWait();
  621.     ShowFrame(curSave);
  622.     return TRUE;
  623.     
  624. realizebarf:
  625.     EndWait();
  626.     ShowFrame(curSave);
  627.     return FALSE;
  628. }
  629.  
  630. //
  631. // Make all of the frames have a palette that is an identity mapping to the
  632. // "real" palette.
  633. //
  634. void MapIdentFrames()
  635. {
  636.     int i;
  637.     int curSave = curFrame;
  638.     HANDLE hdib;
  639.     HPALETTE hpalFrame=NULL;
  640.     HPALETTE hpal;
  641.     HDC      hdc;
  642.     HWND     hwndT;
  643.     
  644.     StartWait();
  645.     for (i=0; i<numFrames; i++)
  646.     {
  647.         ShowFrame(i);
  648.  
  649.     hdib = FrameRle(i);
  650.  
  651.     // For each palette change, we must give our window the focus and
  652.     // do the mapping, and give focus back again
  653.  
  654.     if (!(FrameFlags(i) & F_PALSHARED))
  655.     {
  656.         hwndT = GetActiveWindow();    // who is the active window?
  657.         SetActiveWindow(hwndApp);    // make it us.
  658.  
  659.         if (hpalFrame)
  660.         DeleteObject(hpalFrame);
  661.  
  662.         hpalFrame = FramePalette(i);
  663.  
  664.         hdc = GetDC(hwndApp);
  665.         SelectPalette(hdc, hpalFrame, FALSE);
  666.         RealizePalette(hdc);
  667.         ReleaseDC(hwndApp,hdc);
  668.  
  669.         hpal = CreateSystemPalette();
  670.  
  671.  
  672.             SetActiveWindow(hwndT);     // Put the old window back in focus
  673.     }
  674.  
  675.     SetDibUsage(hdib,hpalFrame,DIB_RGB_COLORS);
  676.  
  677.     MapDib(hdib, hpal);
  678.     FramePalette(i) = hpal;
  679.  
  680.     SetDibUsage(hdib,hpal,DIB_PAL_COLORS);
  681.  
  682.     if (WinYield())
  683.         break;
  684.     }
  685.     EndWait();
  686.  
  687.     if (hpalFrame)
  688.     DeleteObject(hpalFrame);
  689.  
  690.     ShowFrame(curSave);
  691. }
  692.  
  693. //
  694. // make all frames relative to a given palette
  695. //
  696. void MapPalFrames(HPALETTE hpalMap)
  697. {
  698.     int i;
  699.     HANDLE hdib;
  700.     HPALETTE hpal;
  701.     StartWait();
  702.     for (i=0; i<numFrames; i++)
  703.     {
  704.     ShowFrame(i);
  705.  
  706.         hdib = FrameRle(i);
  707.     hpal = FramePalette(i);
  708.  
  709.     SetDibUsage(hdib,hpal,DIB_RGB_COLORS);
  710.     MapDib(hdib, hpalMap);
  711.     SetDibUsage(hdib,hpalMap,DIB_PAL_COLORS);
  712.  
  713.     if (WinYield())
  714.         break;
  715.     }
  716.  
  717.     for (i=0; i<numFrames; i++)
  718.     {
  719.     if (!(arFrames[i].f & F_PALSHARED))
  720.         DeleteObject(arFrames[i].hpal);
  721.  
  722.     arFrames[i].f   |= F_PALSHARED;
  723.     arFrames[i].hpal = hpalMap;
  724.     }
  725.     arFrames[0].f &= ~F_PALSHARED;
  726.  
  727.     EndWait();
  728.     ShowFrame(0);
  729. }
  730.  
  731.  
  732. /*  This routine will make RLE copies of all of the frames, instead of DIB
  733.     copies (RLEs are usually much smaller).  It then erases the DIB copies.
  734.     However, we don't want to keep 2 bitmaps for each frame until the end
  735.     of this routine, and then erase the DIB copy because that wastes memory.
  736.     BUT:  We don't want to erase each DIB copy as an RLE copy is made, either,
  737.     because that makes this routine take HOURS to run.  Why, you ask?  Because
  738.     in order to RLE a frame, you need DIB copies of that frame and the one
  739.     before it, so you must make a DIB copy of both of those frames.  If you
  740.     don't have any DIBs in your movie, you will have to start at frame one
  741.     and play the movie up to the current frame to get those DIBs.  Plus, you
  742.     will have to do this for EVERY FRAME in the movie as this code runs.
  743.     For the last frames of a very long movie, this will take many minutes,
  744.     and the routine will start running slower and slower as it gets further
  745.     and further into the movie.
  746.  
  747.     The solution is to make a note of each frame that had a DIB and was
  748.     RLE'd.  Then, the next time a frame is RLE'd, it will only have to go
  749.     back to the last frame and play forward from that spot to get the DIBs that
  750.     it needs to RLE the frame.  It won't need to go back to the beginning of
  751.     the movie.  Then the DIB copy of the previous frame is erased, but the
  752.     one of the current frame is kept and remembered.  Thus, there will always
  753.     be one frame in the movie earlier than the current frame that has a DIB
  754.     copy, and you will never have to go back and play all the frames from
  755.     the beginning of the movie.
  756.                                     */
  757.  
  758.  
  759. void RleAllFrames(HWND hwnd)
  760. {
  761.     int curSave = curFrame;
  762.     HPALETTE hpal = NULL;
  763.     int         i;
  764.     HANDLE    hrle, hrleT;
  765.     int        wLastRle = -1;      // Last frame that was RLE-d
  766.  
  767.     {
  768.     fDirty=TRUE;
  769.     
  770.     StartWait();
  771.  
  772.     for (i = 0; i < numFrames; i++) 
  773.     {
  774.         hrleT = arFrames[i].hrle;    // Remember the HRLE of this frame
  775.         if ((hrle = RleFrame(i, TRUE)) == NULL)    /* RLE that frame */
  776.         goto barf;        // something went wrong
  777.             
  778.         ShowFrame(i);
  779.         if (WinYield())
  780.         goto barf;
  781.  
  782.         if (hrle != hrleT) 
  783.         {    // This frame was just RLE'd.      
  784.         NukeDib(wLastRle);    // Erase the DIB of the last frame.
  785.         wLastRle = i;        // Mark this frame as the next one
  786.                              // to be deleted.
  787.         }
  788.     }
  789.  
  790. barf:
  791.     PurgeFrames();  /* Delete the DIB copy of frames that are RLE'd */
  792.  
  793.     EndWait();
  794.     ShowFrame(curSave);
  795.     }
  796. }
  797.     
  798. void PlayFrame(HDC hdc, int iFrame, int x, int y, BOOL fIgnoreFlags)
  799. {
  800.     HPALETTE hpal,hpalT;
  801.     HANDLE   hdib;
  802.  
  803.     if (numFrames == 0)
  804.     return;
  805.  
  806.     if (iFrame == 0)        // Validate the first frame
  807.     fPaint = FALSE;
  808.  
  809.     hdib = FrameRle(iFrame);
  810.     hpal = FramePalette(iFrame);
  811.  
  812.     if (iFrame == 0)
  813.     {
  814.     SoundPlay(0, numFrames);
  815.     nFramesPlayed = 0;
  816.     msFrameBase = timeGetTime();
  817.     }
  818.  
  819.     if (hpal)
  820.     {
  821.     hpalT = SelectPalette(hdc,hpal,FALSE);
  822.     RealizePalette(hdc);
  823.     }
  824.  
  825.     DibBlt(hdc,x,y,-1,-1,
  826.         hdib,0,0,
  827.         SRCCOPY,DIB_PAL_COLORS);
  828.  
  829.     if (hpal)
  830.     SelectPalette(hdc,hpalT,FALSE);
  831. }
  832.  
  833. //
  834. // Delete a given frame
  835. //
  836. BOOL DeleteFrame(int iFrame)
  837. {
  838.     int i;
  839.  
  840.     if (iFrame < 0 || iFrame >= numFrames)
  841.     return FALSE;
  842.  
  843.     if (iFrame < numFrames-1)
  844.     {
  845.     if (!RenderFrame(iFrame+1))     // Render the frame after it
  846.         return FALSE;
  847.  
  848.     NukeRle(iFrame + 1);
  849.  
  850.     // if the next frame is using the same palette, make sure we
  851.     // don't destroy the palette.
  852.  
  853.     if (!(arFrames[iFrame].f   & F_PALSHARED) &&
  854.          (arFrames[iFrame+1].f & F_PALSHARED))
  855.     {
  856.         arFrames[iFrame+1].f &= ~F_PALSHARED;
  857.         arFrames[iFrame].f   |=  F_PALSHARED;
  858.     }
  859.  
  860.     }
  861.     
  862.     FreeFrame(iFrame);
  863.  
  864.     for (i=iFrame; i<numFrames-1; i++)
  865.     arFrames[i] = arFrames[i+1];
  866.  
  867.     numFrames--;
  868.     
  869.     if (iFrame == numFrames)
  870.     iFrame--;
  871.  
  872.     fDirty = TRUE;
  873.  
  874.     ShowFrame(iFrame);
  875.     return TRUE;
  876. }
  877.  
  878. //
  879. // Insert a new frame before the given frame, iff iFrame is < 0 then
  880. // the frame will be appended
  881. // Normally we must render the frame after the one we insert, because if it's
  882. // a delta from its previous frame, that delta will be incorrect after another
  883. // frame is stuck in between them.  Sometimes, if we know that problem won't
  884. // occur (eg. Convert Frames/Sec) we don't need to do this. That is the function
  885. // of the fRender flag.
  886. //
  887.  
  888. BOOL InsertFrame(HANDLE hdib, int iFrame, BOOL fRender)
  889. {
  890.     HANDLE hdibT;
  891.     HPALETTE hpal, hpalT;
  892.     BITMAPINFOHEADER bi;
  893.     WORD f = 0;
  894.     int  i, j;
  895.     BOOL fAppend;
  896.  
  897.     if (numFrames >= MAXFRAMES || hdib == NULL)
  898.     return FALSE;
  899.  
  900.     fAppend = (iFrame < 0 || iFrame >= numFrames);
  901.  
  902.     DibInfo(hdib,&bi);
  903.  
  904.     //
  905.     // we need a 8 bpp dib
  906.     //
  907.     if (bi.biCompression == BI_RGB && bi.biBitCount != 8)
  908.     {
  909.     hdibT = hdib;
  910.  
  911.     hdib = DibFromDib(hdib,BI_RGB,8,NULL,DIB_RGB_COLORS);
  912.  
  913.     if (hdib != hdibT)
  914.         GFree(hdibT);
  915.  
  916.     if (!hdib) 
  917.     {
  918.         ErrMsg("Out of Memory Error");
  919.         return FALSE;
  920.     }
  921.     }
  922.  
  923.     // We must be given a DIB with RGB colours.  Now switch it to
  924.     // PAL colours.
  925.  
  926.     hpal = CreateDibPalette(hdib);
  927.     SetPalFlags(hpal, 0,-1,wPalFlags);
  928.     SetDibUsage(hdib,hpal,DIB_PAL_COLORS);
  929.  
  930.     //
  931.     // alocate a slot for the frame.
  932.     //
  933.     if (fAppend)
  934.     {
  935.     iFrame = numFrames++;
  936.     }
  937.     else
  938.     {
  939.     if (fRender) 
  940.     {
  941.         if (!RenderFrame(iFrame))    // Render the frame after this one
  942.         return FALSE;        // or we'll screw up the deltas
  943.         NukeRle(iFrame);
  944.     }
  945.  
  946.     for (i=numFrames; i>iFrame; i--)
  947.         arFrames[i] = arFrames[i-1];
  948.  
  949.     numFrames++;
  950.  
  951.     // If frame i's palette is different from i+1, mark i+1 as UNshared, and
  952.     // replace the run of palettes starting at i+1 with a new palette
  953.  
  954.     if (!PalEq(hpal,FramePalette(iFrame+1)) && 
  955.     (FrameFlags(iFrame+1) & F_PALSHARED))
  956.     {
  957.         hpalT = CopyPalette(FramePalette(iFrame+1));
  958.         arFrames[iFrame+1].f   &= ~F_PALSHARED;
  959.         arFrames[iFrame+1].hpal = hpalT;
  960.         for (j=iFrame+2; j<numFrames && (FrameFlags(j) & F_PALSHARED); j++)
  961.         arFrames[j].hpal = hpalT;
  962.     }
  963.  
  964.     }
  965.  
  966.     //
  967.     // If frame i's palette is the same as the one before it, mark frame i's
  968.     // palette as shared, and erase it's copy.
  969.     //
  970.     if (iFrame > 0 && PalEq(hpal,FramePalette(iFrame-1)))
  971.     {
  972.     DeleteObject(hpal);
  973.     hpal = FramePalette(iFrame-1);
  974.     f   |= F_PALSHARED;
  975.     }
  976.  
  977.  
  978.     if (bi.biCompression == BI_RGB)
  979.     {
  980.     arFrames[iFrame].hpal   = hpal;
  981.     arFrames[iFrame].f      = f;
  982.     arFrames[iFrame].hdib   = hdib;
  983.     arFrames[iFrame].hrle   = NULL;
  984.  
  985.     }
  986.     else // RLE DIB, just append it.
  987.     {
  988.         if (bi.biCompression == BI_RLE8)
  989.             f |= F_RLE;
  990.  
  991.     arFrames[iFrame].hpal   = hpal;
  992.     arFrames[iFrame].f      = f;
  993.     arFrames[iFrame].hdib   = NULL;
  994.     arFrames[iFrame].hrle   = hdib;
  995.     }
  996.  
  997.     ShowFrame(iFrame);
  998.     return TRUE;
  999. }
  1000.  
  1001.  
  1002. void GetFramesSec(HWND hwnd)
  1003. {
  1004.     if(fDialog(FRAMEDLG, hwnd, FrameDlgProc))
  1005.     fDirty=TRUE;
  1006. }
  1007.  
  1008. void GotoFrame(HWND hwnd)
  1009. {
  1010.     RANGEDIALOGPARAM rdp;
  1011.     
  1012.     rdp.lpCaption = (LPSTR) "Goto Frame";
  1013.     rdp.min = 1;
  1014.     rdp.max = numFrames;
  1015.     rdp.current = curFrame + 1;
  1016.     
  1017.     ShowFrame(fDialogParam(DLG_RANGE,hwnd,
  1018.             fnRangeDlg,(DWORD) (LPRANGEDIALOGPARAM) &rdp) - 1);
  1019. }
  1020.  
  1021.  
  1022. void DeleteFrames(HWND hwnd)
  1023. {
  1024.     RANGEDIALOGPARAM rdp;
  1025.     int iDelete;
  1026.     int saveCur = curFrame;
  1027.     
  1028.     rdp.lpCaption = (LPSTR) "# Frames to Delete:";
  1029.     rdp.min = 0;
  1030.     rdp.max = numFrames - curFrame;
  1031.     rdp.current = 0;
  1032.     
  1033.     iDelete = fDialogParam(DLG_RANGE,hwnd,
  1034.             fnRangeDlg,(DWORD) (LPRANGEDIALOGPARAM) &rdp);
  1035.  
  1036.     if (iDelete) 
  1037.     {
  1038.     StartWait();
  1039.     while (iDelete-- > 0) 
  1040.     {
  1041.         DeleteFrame(saveCur + iDelete);
  1042.     }
  1043.     EndWait();
  1044.     }
  1045. }
  1046.  
  1047. /*----------------------------------------------------------------------------*\
  1048. |   AppInit( hInst, hPrev)                                                     |
  1049. |                                                                              |
  1050. |   Description:                                                               |
  1051. |       This is called when the application is first loaded into               |
  1052. |       memory.  It performs all initialization that doesn't need to be done   |
  1053. |       once per instance.                                                     |
  1054. |                                                                              |
  1055. |   Arguments:                                                                 |
  1056. |       hInstance       instance handle of current instance                    |
  1057. |       hPrev           instance handle of previous instance                   |
  1058. |                                                                              |
  1059. |   Returns:                                                                   |
  1060. |       TRUE if successful, FALSE if not                                       |
  1061. |                                                                              |
  1062. \*----------------------------------------------------------------------------*/
  1063. BOOL AppInit(HANDLE hInst,HANDLE hPrev,WORD sw,LPSTR szCmdLine)
  1064. {
  1065.     WNDCLASS    cls;
  1066.     int         dx,dy;
  1067.     HDC         hdc;
  1068.     TEXTMETRIC  tm;
  1069.     WORD        w;
  1070.  
  1071.     arFrames = (FRAME far *)GAllocPtr((long)MAXFRAMES * sizeof(FRAME));
  1072.  
  1073.     if (!arFrames)
  1074.     return FALSE;
  1075.     
  1076.     arFrames[0].hdib = NULL;
  1077.     arFrames[0].hrle = NULL;
  1078.     arFrames[0].hpal = NULL;
  1079.     arFrames[0].f    = NULL;
  1080.  
  1081.     w = SetErrorMode(0x8000);
  1082.     hDisplayDibDll = LoadLibrary(szDisplayDibDll);
  1083.     SetErrorMode(w);
  1084.  
  1085.     if (hDisplayDibDll > 32)
  1086.     DisplayDib = GetProcAddress(hDisplayDibDll, "DisplayDib");
  1087.     else
  1088.     hDisplayDibDll = NULL;
  1089.  
  1090.     /* Save instance handle for DialogBoxs */
  1091.     hInstApp = hInst;
  1092.  
  1093.     if (!hPrev) 
  1094.     {
  1095.     /*
  1096.      *  Register a class for the main application window
  1097.      */
  1098.     cls.hCursor        = LoadCursor(NULL,IDC_ARROW);
  1099.         cls.hIcon          = LoadIcon(hInst,"AppIcon");
  1100.         cls.lpszMenuName   = "AppMenu";
  1101.         cls.lpszClassName  = szAppName;
  1102.     cls.hbrBackground  = (HBRUSH)COLOR_APPWORKSPACE + 1;
  1103.     cls.hInstance      = hInst;
  1104.     cls.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
  1105.         cls.lpfnWndProc    = (LPWNDPROC)AppWndProc;
  1106.     cls.cbWndExtra     = 0;
  1107.     cls.cbClsExtra     = 0;
  1108.  
  1109.     if (!RegisterClass(&cls))
  1110.         return FALSE;
  1111.     }
  1112.  
  1113.     hAccTable = LoadAccelerators(hInstApp, "AppAcc");
  1114.  
  1115.     hdc = GetDC(NULL);
  1116.     GetTextMetrics(hdc,&tm);
  1117.     tmHeight = tm.tmHeight;
  1118.     ReleaseDC(NULL,hdc);
  1119.  
  1120.     dx = GetSystemMetrics (SM_CXSCREEN);
  1121.     dy = GetSystemMetrics (SM_CYSCREEN);
  1122.  
  1123.     hwndApp = CreateWindow (szAppName,              // Class name
  1124.                 szAppName,              // Caption
  1125.                 WS_OVERLAPPEDWINDOW,    // Style bits
  1126.                 CW_USEDEFAULT, 0,       // Position
  1127.                 CW_USEDEFAULT, 0,       // Size
  1128.                 (HWND)NULL,             // Parent window (no parent)
  1129.                 (HMENU)NULL,            // use class menu
  1130.                 (HANDLE)hInst,          // handle to window instance
  1131.                 (LPSTR)NULL             // no params to pass on
  1132.                );
  1133.     ShowWindow(hwndApp,sw);
  1134.     UpdateWindow(hwndApp);
  1135.  
  1136.     SetCursor(cls.hCursor);
  1137.     if (szCmdLine[0] != 0) 
  1138.     PostMessage(hwndApp,WM_COMMAND,MENU_OPENRLE,(LONG)(LPSTR)szCmdLine);
  1139. }
  1140.  
  1141. /*----------------------------------------------------------------------------*\
  1142. |   WinMain( hInst, hPrev, lpszCmdLine, cmdShow )                              |
  1143. |                                                                              |
  1144. |   Description:                                                               |
  1145. |       The main procedure for the App.  After initializing, it just goes      |
  1146. |       into a message-processing loop until it gets a WM_QUIT message         |
  1147. |       (meaning the app was closed).                                          |
  1148. |                                                                              |
  1149. |   Arguments:                                                                 |
  1150. |       hInst           instance handle of this instance of the app            |
  1151. |       hPrev           instance handle of previous instance, NULL if first    |
  1152. |       szCmdLine       ->null-terminated command line                         |
  1153. |       cmdShow         specifies how the window is initially displayed        |
  1154. |                                                                              |
  1155. |   Returns:                                                                   |
  1156. |       The exit code as specified in the WM_QUIT message.                     |
  1157. |                                                                              |
  1158. \*----------------------------------------------------------------------------*/
  1159. int PASCAL WinMain(HANDLE hInst, HANDLE hPrev, LPSTR szCmdLine, WORD sw)
  1160. {
  1161.     MSG     msg;
  1162.     LONG    msTime = 0L;
  1163.     int     iFrame;
  1164.  
  1165.     if(GetWinFlags() & WF_CPU286)
  1166.     {
  1167.         ErrMsg("This program only works on an i386 or above.");
  1168.         return 0;
  1169.     }
  1170.     
  1171.     /* Call initialization procedure */
  1172.     if (!AppInit(hInst,hPrev,sw,szCmdLine))
  1173.     return FALSE;
  1174.  
  1175.     for (;;)
  1176.     {
  1177. peek_again:
  1178.     while (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
  1179.     {
  1180.         if (msg.message == WM_QUIT)
  1181.         goto exit;
  1182.  
  1183.         if (!TranslateAccelerator(hwndApp, hAccTable, &msg))
  1184.         {
  1185.         TranslateMessage(&msg);
  1186.         DispatchMessage(&msg);
  1187.         }
  1188.     }
  1189.  
  1190.     // a typical do-something-as-fast-as-possible loop
  1191.     // note the all-important WaitMessage() call if nothing is
  1192.     // to be done.  This gives up the CPU instead of hogging it.
  1193.         
  1194.     // app could/should also not do operation if it is not in the
  1195.     // foreground. (see WM_ACTIVATEAPP message)
  1196.         if (fPlay)
  1197.     {
  1198.         
  1199.         // example of how to do-something-exactly-so-often
  1200.         
  1201.             msTime = timeGetTime() - msFrameBase;
  1202.         
  1203.             iFrame = (int)(msTime * FramesSec / 1000 / FramesSecScale);
  1204.  
  1205.             if (iFrame <= curFrame)
  1206.                 goto peek_again;
  1207.  
  1208.             if (fSkipFrames && iFrame > curFrame+1)
  1209.             {
  1210.                 if (iFrame > numFrames)
  1211.                     iFrame = numFrames;
  1212.  
  1213.                 nFramesPlayed = iFrame-1;
  1214.                 curFrame = iFrame-1;
  1215.             }
  1216.  
  1217.             nFramesPlayed++;
  1218.             ShowFrame(FRAME_NEXT);
  1219.             RealFramesSec = (long)nFramesPlayed*FramesSecScale*1000/msTime;
  1220.     }
  1221.     else
  1222.         WaitMessage();
  1223.     }
  1224. exit:
  1225.     if (hDisplayDibDll)
  1226.     FreeLibrary(hDisplayDibDll);
  1227.  
  1228.     SoundClose();
  1229.  
  1230.     return msg.wParam;
  1231. }
  1232.  
  1233. void PaintStatus(HWND hwnd, HDC hdc)
  1234. {
  1235.     RECT    rc;
  1236.     char    buf[128];
  1237.     char *  pch;
  1238.     WORD    f;
  1239.     long    fps;
  1240.     BOOL    fGetDC;
  1241.  
  1242.     if ((fStatus || fLoading) && numFrames > 0)
  1243.     {
  1244.         if (fGetDC = (hdc == NULL))
  1245.             hdc = GetDC(hwnd);
  1246.  
  1247.     GetClientRect(hwnd,&rc);
  1248.     rc.bottom = tmHeight;
  1249.  
  1250.         pch = buf;
  1251.  
  1252.         f = arFrames[curFrame].f;
  1253.  
  1254.         if (fPlay)
  1255.         {
  1256.             fps = RealFramesSec;
  1257.  
  1258.             pch += wsprintf(pch,"Frame: %d/%d fps=%d.%03d",
  1259.                 curFrame+1, numFrames,
  1260.                 (int)(fps/FramesSecScale),
  1261.                 (int)(fps%FramesSecScale) );
  1262.         }
  1263.         else
  1264.         {
  1265.             pch += wsprintf(pch,"Frame: %d/%d  Size=%ld",
  1266.                 curFrame+1, (fLoading ? totFrames : numFrames),
  1267.                 DIBSIZE(FrameRle(curFrame)));
  1268.  
  1269.             if (arFrames[curFrame].hdib)
  1270.                 pch += wsprintf(pch," DIB");
  1271.  
  1272.             if (f & F_RLE)
  1273.                 pch += wsprintf(pch," RLE");
  1274.             if (!(f & F_PALSHARED))
  1275.                 pch += wsprintf(pch," PAL");
  1276.             if (f & F_KEYFRAME)
  1277.                 pch += wsprintf(pch," KEY");
  1278.  
  1279.             fps = FramesSec;
  1280.  
  1281.             pch += wsprintf(pch, " fps=%d.%03d",
  1282.                 (int)(fps/FramesSecScale),
  1283.                 (int)(fps%FramesSecScale) );
  1284.         }
  1285.  
  1286.         ExtTextOut(hdc,0,0,ETO_OPAQUE,&rc,buf,lstrlen(buf),NULL);
  1287.         PatBlt(hdc,0,rc.bottom,rc.right,1,BLACKNESS);
  1288.  
  1289.         if (fGetDC)
  1290.             ReleaseDC(hwnd, hdc);
  1291.     }
  1292. }
  1293.  
  1294. /*----------------------------------------------------------------------------*\
  1295. |   AppPaint(hwnd, hdc)                                                        |
  1296. |                                                                              |
  1297. |   Description:                                                               |
  1298. |       The paint function.                                                    |
  1299. |                                                                              |
  1300. |   Arguments:                                                                 |
  1301. |       hwnd             window painting into                                  |
  1302. |       hdc              display context to paint to                           |
  1303. |                                                                              |
  1304. |   Returns:                                                                   |
  1305. |       nothing                                                                |
  1306. |                                                                              |
  1307. \*----------------------------------------------------------------------------*/
  1308. void NEAR PASCAL AppPaint (HWND hwnd, HDC hdc)
  1309. {
  1310.     RECT rc;
  1311.  
  1312.     PaintStatus(hwnd, hdc);
  1313.  
  1314.     if (!numFrames || fWait || fLoading || GetClipBox(hdc,&rc) == NULLREGION)
  1315.     return;
  1316.  
  1317.     if (fFullPaint)
  1318.     DrawDib(hdc, ptFrame.x, ptFrame.y, RenderFrame(curFrame), FramePalette(curFrame), DIB_PAL_COLORS);
  1319.     else
  1320.     PlayFrame(hdc, curFrame, ptFrame.x, ptFrame.y, FALSE);
  1321. }
  1322.  
  1323. /*----------------------------------------------------------------------------*\
  1324. |   AppWndProc( hwnd, uiMessage, wParam, lParam )                              |
  1325. |                                                                              |
  1326. |   Description:                                                               |
  1327. |       The window proc for the app's main (tiled) window.  This processes all |
  1328. |       of the parent window's messages.                                       |
  1329. |                                                                              |
  1330. |   Arguments:                                                                 |
  1331. |       hwnd            window handle for the window                           |
  1332. |       uiMessage       message number                                         |
  1333. |       wParam          message-dependent                                      |
  1334. |       lParam          message-dependent                                      |
  1335. |                                                                              |
  1336. |   Returns:                                                                   |
  1337. |       0 if processed, nonzero if ignored                                     |
  1338. |                                                                              |
  1339. \*----------------------------------------------------------------------------*/
  1340. LONG EXPORT AppWndProc(hwnd, msg, wParam, lParam)
  1341.     HWND     hwnd;
  1342.     unsigned msg;
  1343.     WORD     wParam;
  1344.     long     lParam;
  1345. {
  1346.     PAINTSTRUCT ps;
  1347.     BOOL        f;
  1348.     HDC         hdc;
  1349.     HPALETTE    hpal,hpalT;
  1350.     RECT        rc;
  1351.     BITMAPINFOHEADER bi;
  1352.  
  1353.     switch (msg) 
  1354.     {
  1355.     case WM_CREATE:
  1356.         break;
  1357.  
  1358.     case WM_ERASEBKGND:
  1359.         break;
  1360.  
  1361.     case WM_NCHITTEST:
  1362.         if (fWait)
  1363.         {
  1364.         lParam = DefWindowProc(hwnd,msg,wParam,lParam);
  1365.  
  1366.         if (lParam == HTMENU)
  1367.             lParam = HTCLIENT;
  1368.  
  1369.         return lParam;
  1370.         }
  1371.         break;
  1372.  
  1373.         case WM_SETCURSOR:
  1374.             if (fWait && LOWORD(lParam) == HTCLIENT)
  1375.             {
  1376.                 SetCursor(LoadCursor(NULL, IDC_WAIT));
  1377.                 return TRUE;
  1378.             }
  1379.         break;
  1380.  
  1381.     case WM_SIZE:
  1382.         GetClientRect(hwnd, &rc);
  1383.  
  1384.         if (fStatus)
  1385.         rc.top += tmHeight+1;
  1386.  
  1387.         DibInfo(FrameRle(0),&bi);
  1388.  
  1389.             ptFrame.x = rc.left + (rc.right-rc.left-(int)bi.biWidth)  / 2;
  1390.             ptFrame.y = rc.top  + (rc.bottom-rc.top-(int)bi.biHeight) / 2;
  1391.  
  1392.         if (ptFrame.y < rc.top)
  1393.         ptFrame.y = rc.top;
  1394.  
  1395.         if (ptFrame.x < rc.left)
  1396.         ptFrame.x = rc.left;
  1397.  
  1398.         break;
  1399.  
  1400.     case WM_KEYDOWN:
  1401.             switch(wParam)
  1402.             {
  1403.                 case VK_RIGHT:                      // next frame
  1404.                     ShowFrame(FRAME_NEXT);
  1405.                     break;
  1406.  
  1407.                 case VK_LEFT:                       // previous frame
  1408.                     ShowFrame(FRAME_PREV);
  1409.                     break;
  1410.  
  1411.                 case VK_HOME:
  1412.                     ShowFrame(0);
  1413.                     break;
  1414.  
  1415.                 case VK_END:
  1416.                     ShowFrame(numFrames-1);
  1417.                     break;
  1418.  
  1419.                 case VK_NEXT:
  1420.                     if (numFrames)
  1421.                     {
  1422.                         curFrame += 10;
  1423.                         if (curFrame > numFrames - 1)
  1424.                             curFrame = numFrames - 1;
  1425.                     }
  1426.                     ShowFrame(curFrame);
  1427.                     break;
  1428.  
  1429.                 case VK_PRIOR:
  1430.                     if (numFrames)
  1431.                     {
  1432.                         curFrame -= 10;
  1433.                         if (curFrame < 0)
  1434.                             curFrame = 0;
  1435.                     }
  1436.                     ShowFrame(curFrame);
  1437.                     break;
  1438.             }
  1439.  
  1440.         break;
  1441.  
  1442.     case WM_ACTIVATEAPP:
  1443.         fActive = wParam;
  1444.         break;
  1445.  
  1446.     case WM_TIMER:
  1447.         if (!fWait)
  1448.         ShowFrame(FRAME_NEXT);
  1449.         break;
  1450.  
  1451.     case WM_INITMENU:
  1452.         f = (IsClipboardFormatAvailable(CF_DIB)||
  1453.          IsClipboardFormatAvailable(CF_BITMAP))
  1454.          ? MF_ENABLED : MF_GRAYED;
  1455.  
  1456.         EnableMenuItem (wParam,MENU_PASTE_APPEND ,f);
  1457.         EnableMenuItem (wParam,MENU_PASTE_INSERT ,f);
  1458.         EnableMenuItem (wParam,MENU_PASTE_REPLACE,f);
  1459.  
  1460.         f = IsClipboardFormatAvailable(CF_PALETTE) ? MF_ENABLED : MF_GRAYED;
  1461.  
  1462.         EnableMenuItem (wParam,MENU_PASTE_PALETTE ,f);
  1463.         EnableMenuItem (wParam,MENU_REVERT, gszCurFilespec[0] != '\0'
  1464.         ? MF_ENABLED : MF_GRAYED);
  1465.  
  1466.         f = (numFrames > 0 ) ? MF_ENABLED : MF_GRAYED;
  1467.  
  1468.             EnableMenuItem(wParam, MENU_SAVE_RLE,  f);
  1469.             EnableMenuItem(wParam, MENU_SAVE_RL0,  f);
  1470.             EnableMenuItem(wParam, MENU_SAVE_FRAMES,  f);
  1471.             EnableMenuItem(wParam, MENU_COPY,  f);
  1472.             EnableMenuItem(wParam, MENU_CUT,   f);
  1473.             EnableMenuItem(wParam, MENU_DELETE_FRAME,f);
  1474.             EnableMenuItem(wParam, MENU_DELETE_FRAMES,f);
  1475.             EnableMenuItem(wParam, MENU_GOTO_FRAME,f);
  1476.             EnableMenuItem(wParam, MENU_RLEFRAMES,f);
  1477.             EnableMenuItem(wParam, MENU_IDENTITY,f);
  1478.  
  1479.             f = (pWaveFormat && pwhMovie) ? MF_ENABLED : MF_GRAYED;
  1480.         EnableMenuItem (wParam,MENU_SAVE_WAVE, f);
  1481.  
  1482.             CheckMenuItem(wParam,MENU_WINDOW, gDisplayMode ? MF_UNCHECKED : MF_CHECKED);
  1483.  
  1484.         if (hDisplayDibDll) 
  1485.         {
  1486.         CheckMenuItem(wParam,MENU_320x240, 
  1487.             gDisplayMode == DISPLAYDIB_MODE_320x240x8 
  1488.             ? MF_CHECKED : MF_UNCHECKED);
  1489.         CheckMenuItem(wParam,MENU_320x200, 
  1490.             gDisplayMode == DISPLAYDIB_MODE_320x200x8 
  1491.             ? MF_CHECKED : MF_UNCHECKED);
  1492.         } else 
  1493.         {
  1494.         EnableMenuItem(wParam,MENU_320x240, MF_GRAYED);
  1495.         EnableMenuItem(wParam,MENU_320x200, MF_GRAYED);
  1496.         }
  1497.  
  1498.             CheckMenuItem  (wParam,MENU_STATUS,     fStatus     ? MF_CHECKED : MF_UNCHECKED);
  1499.             CheckMenuItem  (wParam,MENU_FULLPAINT,  fFullPaint  ? MF_CHECKED : MF_UNCHECKED);
  1500.             CheckMenuItem  (wParam,MENU_SKIPFRAMES, fSkipFrames ? MF_CHECKED : MF_UNCHECKED);
  1501.  
  1502.         break;
  1503.  
  1504.     case WM_COMMAND:
  1505.         return AppCommand(hwnd,msg,wParam,lParam);
  1506.  
  1507.     case WM_DESTROY:
  1508.         FreeFrames();
  1509.         PostQuitMessage(0);
  1510.         break;
  1511.  
  1512.     case WM_QUERYENDSESSION:
  1513.         if (!QueryClose(hwnd))
  1514.         return 0L;
  1515.         break;
  1516.  
  1517.     case WM_CLOSE:
  1518.         if (fWait || !QueryClose(hwnd))
  1519.         return 0L;
  1520.         break;
  1521.  
  1522.     case WM_LBUTTONDBLCLK:
  1523.         PostMessage(hwnd,WM_COMMAND,MENU_PLAY,0L);
  1524.         break;
  1525.  
  1526.     case WM_PALETTECHANGED:
  1527.         if (wParam == hwnd)
  1528.         break;
  1529.  
  1530.         // fall through
  1531.  
  1532.     case WM_QUERYNEWPALETTE:
  1533.         /* if palette realization causes a palette change,
  1534.         ** we need to do a full redraw.
  1535.         */
  1536.  
  1537.         if ((numFrames) && (hpal = FramePalette(curFrame)))
  1538.         {
  1539.         hdc = GetDC(hwnd);
  1540.         hpalT = SelectPalette (hdc, hpal, FALSE);
  1541.  
  1542.         f = RealizePalette(hdc);
  1543.  
  1544.         SelectPalette (hdc, hpalT, FALSE);
  1545.         ReleaseDC(hwnd, hdc);
  1546.  
  1547.         if (f)
  1548.             InvalidateRect(hwnd, NULL, TRUE);
  1549.  
  1550.         return (LONG)f;
  1551.         }
  1552.         return 0L;
  1553.  
  1554.     case WM_PAINT:
  1555.         BeginPaint(hwnd,&ps);
  1556.         fPaint = TRUE;
  1557.         AppPaint (hwnd,ps.hdc);
  1558.         EndPaint(hwnd,&ps);
  1559.         return 0L;
  1560.     }
  1561.     return DefWindowProc(hwnd,msg,wParam,lParam);
  1562. }
  1563.  
  1564. LONG NEAR PASCAL AppCommand (hwnd, msg, wParam, lParam)
  1565.     HWND     hwnd;
  1566.     unsigned msg;
  1567.     WORD     wParam;
  1568.     long     lParam;
  1569. {
  1570.     char    szFile[128];
  1571.     char    ach[128];
  1572.     HANDLE  hdib;
  1573.     HBITMAP hbm;
  1574.     HPALETTE hpal;
  1575.     int     iFrame;
  1576.     LPSTR   pch;
  1577.  
  1578.     switch(wParam)
  1579.     {
  1580.     case MENU_ABOUT:
  1581.         fDialog(ABOUTBOX,hwnd,AppAbout);
  1582.         break;
  1583.  
  1584.     case MENU_EXIT:
  1585.         PostMessage(hwnd,WM_CLOSE,0,0L);
  1586.         break;
  1587.  
  1588.     case MENU_FRAMES_SEC:
  1589.         GetFramesSec(hwnd);
  1590.             PaintStatus(hwnd, NULL);
  1591.         break;
  1592.  
  1593.         case MENU_SKIPFRAMES:
  1594.             fSkipFrames = !fSkipFrames;
  1595.         break;
  1596.  
  1597.     case MENU_RLEFRAMES:
  1598.         RleAllFrames(hwnd);
  1599.         break;
  1600.  
  1601.     case MENU_NEXT:
  1602.         ShowFrame(FRAME_NEXT);
  1603.         break;
  1604.  
  1605.     case MENU_PREV:
  1606.         ShowFrame(FRAME_PREV);
  1607.         break;
  1608.  
  1609.         case MENU_WINDOW:
  1610.             gDisplayMode = 0;
  1611.         break;
  1612.  
  1613.     case MENU_320x240:
  1614.             gDisplayMode = DISPLAYDIB_MODE_320x240x8;
  1615.         break;
  1616.  
  1617.     case MENU_320x200:
  1618.             gDisplayMode = DISPLAYDIB_MODE_320x200x8;
  1619.         break;
  1620.  
  1621.     case MENU_NEW:
  1622.         if (!QueryClose(hwnd))
  1623.         break;
  1624.  
  1625.         StartWait();
  1626.         gszCurFilespec[0] = '\0';
  1627.         SetWindowText(hwnd, szAppName);
  1628.         FreeFrames();
  1629.         InvalidateRect(hwnd,NULL,TRUE);
  1630.         UpdateWindow(hwnd);
  1631.         EndWait();
  1632.         break;
  1633.  
  1634.         case MENU_PLAY:
  1635.             if (gDisplayMode)
  1636.             {
  1637.                 PlayVga(hwnd);
  1638.                 return 0L;
  1639.             }
  1640.  
  1641.             if (fPlay = !fPlay)
  1642.             {
  1643.                 SoundOpen();
  1644.  
  1645.                 // movie starts NOW
  1646.                 msFrameBase = timeGetTime()-curFrame*FramesSecScale*1000/FramesSec;
  1647.                 nFramesPlayed = curFrame;
  1648.  
  1649.                 SoundPlay(curFrame, numFrames - curFrame);
  1650.             }
  1651.             else
  1652.             {
  1653.                 SoundClose();
  1654.                 PaintStatus(hwnd, NULL);
  1655.             }
  1656.             break;
  1657.  
  1658.     case MENU_STATUS:
  1659.         fStatus = !fStatus;
  1660.         SendMessage(hwnd,WM_SIZE,0,0L);
  1661.         InvalidateRect(hwnd,NULL,TRUE);
  1662.         break;
  1663.  
  1664.     case MENU_FULLPAINT:
  1665.         fFullPaint = !fFullPaint;
  1666.         InvalidateRect(hwnd, NULL, FALSE);
  1667.         break;
  1668.  
  1669.     case MENU_PURGE:
  1670.         PurgeFrames();
  1671.         break;
  1672.  
  1673.     case MENU_DELETE_FRAME:
  1674.         DeleteFrame(curFrame);
  1675.         break;
  1676.         
  1677.     case MENU_DELETE_FRAMES:
  1678.         DeleteFrames(hwnd);
  1679.         break;
  1680.         
  1681.     case MENU_GOTO_FRAME:
  1682.         GotoFrame(hwnd);
  1683.         break;
  1684.  
  1685.     case MENU_PASTE_REPLACE:
  1686.         iFrame = curFrame;
  1687.         DeleteFrame(curFrame);
  1688.         goto do_insert;
  1689.  
  1690.     case MENU_PASTE_APPEND:
  1691.         iFrame = -1;
  1692.         goto do_insert;
  1693.  
  1694.     case MENU_PASTE_INSERT:
  1695.         iFrame = curFrame;
  1696.  
  1697. do_insert:
  1698.         if (OpenClipboard(hwnd))
  1699.         {
  1700.         if (hdib = GetClipboardData(CF_DIB))
  1701.         {
  1702.             hdib = GSelector(hdib);
  1703.             InsertFrame(CopyDib(hdib), iFrame, TRUE);
  1704.         }
  1705.         else if (hbm = GetClipboardData(CF_BITMAP))
  1706.         {
  1707.             hpal = GetClipboardData(CF_PALETTE);
  1708.  
  1709.             if (!hpal)
  1710.             hpal = GetStockObject(DEFAULT_PALETTE);
  1711.  
  1712.             hdib = DibFromBitmap(hbm,BI_RGB,8,hpal,DIB_RGB_COLORS);
  1713.  
  1714.             InsertFrame(hdib, iFrame, TRUE);
  1715.         }
  1716.         CloseClipboard();
  1717.         }
  1718.         break;
  1719.  
  1720.     case MENU_COPY:
  1721.     case MENU_CUT:
  1722.         if (OpenClipboard(hwnd))
  1723.         {
  1724.         StartWait();
  1725.         EmptyClipboard();
  1726.         if (hdib = CopyDib(RenderFrame(curFrame)))
  1727.         {
  1728.             hpal = CopyPalette(FramePalette(curFrame));
  1729.             hbm = BitmapFromDib(hdib, hpal, DIB_PAL_COLORS);
  1730.  
  1731.             SetDibUsage(hdib,hpal,DIB_RGB_COLORS);
  1732.             SetClipboardData(CF_DIB,hdib);
  1733.             SetClipboardData(CF_PALETTE,hpal);
  1734.             SetClipboardData(CF_BITMAP,hbm);
  1735.         }
  1736.         CloseClipboard();
  1737.  
  1738.         if (wParam == MENU_CUT)
  1739.             DeleteFrame(curFrame);
  1740.  
  1741.         EndWait();
  1742.         }
  1743.         break;
  1744.  
  1745.     case MENU_REVERT:
  1746.         lstrcpy(szFile,(LPSTR)gszCurFilespec);
  1747.         goto open_it;
  1748.  
  1749.     case MENU_OPENRLE:
  1750.         lstrcpy(szFile,(LPSTR)lParam);
  1751.         goto open_it;
  1752.  
  1753.     case MENU_OPEN:
  1754.     case MENU_LOAD_APPEND:
  1755.         case MENU_LOAD_INSERT:
  1756.  
  1757.             szFile[0] = 0;
  1758.             ofn.lStructSize         = sizeof(ofn);
  1759.             ofn.hwndOwner           = hwnd;
  1760.             ofn.hInstance           = hInstApp;
  1761.             ofn.lpstrFilter         = szFilters;
  1762.             ofn.nFilterIndex        = 1;
  1763.             ofn.lpstrCustomFilter   = NULL;
  1764.             ofn.nMaxCustFilter      = 0;
  1765.             ofn.lpstrFile           = szFile;
  1766.             ofn.nMaxFile            = sizeof(szFile);
  1767.             ofn.lpstrFileTitle      = NULL;
  1768.             ofn.nMaxFileTitle       = 0;
  1769.             ofn.lpstrInitialDir     = NULL;
  1770.             ofn.lpstrTitle          = "Open File";
  1771.             ofn.Flags               = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  1772.             ofn.lCustData           = 0;
  1773.             ofn.nFileOffset         = 0;
  1774.             ofn.nFileExtension      = 0;
  1775.             ofn.lpstrDefExt         = NULL;
  1776.             ofn.lpfnHook            = NULL;
  1777.             ofn.lpTemplateName      = NULL;
  1778.  
  1779.             if (!GetOpenFileName(&ofn))
  1780.                 return 0L;
  1781. open_it:
  1782.         if (fPlay)            // Stop the movie!
  1783.         SendMessage(hwnd,WM_COMMAND,MENU_PLAY,0L);
  1784.         switch (wParam)
  1785.         {
  1786.         case MENU_REVERT:
  1787.  
  1788.         if (fDirty) 
  1789.         {
  1790.         if (MessageBox(hwnd,"Revert to last copy saved?",
  1791.             szAppName,MB_OKCANCEL|MB_ICONQUESTION|MB_TASKMODAL)
  1792.             == IDCANCEL)
  1793.             break;
  1794.         fDirty = FALSE;
  1795.         }
  1796.  
  1797.         case MENU_OPENRLE:
  1798.         case MENU_OPEN:
  1799.                 if (OpenWavFile(szFile))        // See if its a wave file
  1800.             break;            // and don't call FILE_NEW
  1801.         SendMessage(hwnd,WM_COMMAND,MENU_NEW,0L);
  1802.         SetWindowText(hwnd, szAppName);
  1803.                 if (OpenMovieFile(szFile, -1))     // remember filespec for revert
  1804.         {                // and update window title
  1805.             wsprintf(ach, "%ls - %ls", (LPSTR)szAppName, (LPSTR)szFile);
  1806.             SetWindowText(hwnd, ach);
  1807.             lstrcpy(gszCurFilespec, szFile);
  1808.         }
  1809.         SendMessage(hwnd,WM_SIZE,0,0L);
  1810.         ShowFrame(0);
  1811.         break;
  1812.  
  1813.         case MENU_LOAD_APPEND:
  1814.                 OpenMovieFile(szFile, -1);
  1815.         fDirty = TRUE;
  1816.         InvalidateRect(hwnd,NULL,TRUE);
  1817.         break;
  1818.  
  1819.         case MENU_LOAD_INSERT:
  1820.                 OpenMovieFile(szFile, curFrame);
  1821.         fDirty = TRUE;
  1822.         InvalidateRect(hwnd,NULL,TRUE);
  1823.         break;
  1824.         }
  1825.         break;
  1826.  
  1827.         case MENU_SAVE_RL0:
  1828.     case MENU_SAVE_WAVE:
  1829.         case MENU_SAVE_RLE:
  1830.         if (fPlay)            // STOP THE MOVIE!!!
  1831.         SendMessage(hwnd,WM_COMMAND,MENU_PLAY,0L);
  1832.  
  1833.             switch(wParam)
  1834.             {
  1835.                 case MENU_SAVE_RLE:     pch = "*.rle"; break;
  1836.                 case MENU_SAVE_RL0:     pch = "*.rl0"; break;
  1837.                 case MENU_SAVE_WAVE:    pch = "*.wav"; break;
  1838.             }
  1839.  
  1840.             szFile[0] = 0;
  1841.             ofn.lStructSize         = sizeof(ofn);
  1842.             ofn.hwndOwner           = hwnd;
  1843.             ofn.hInstance           = hInstApp;
  1844.             ofn.lpstrFilter         = szFilters;
  1845.             ofn.nFilterIndex        = 1;
  1846.             ofn.lpstrCustomFilter   = NULL;
  1847.             ofn.nMaxCustFilter      = 0;
  1848.             ofn.lpstrFile           = szFile;
  1849.             ofn.nMaxFile            = sizeof(szFile);
  1850.             ofn.lpstrFileTitle      = NULL;
  1851.             ofn.nMaxFileTitle       = 0;
  1852.             ofn.lpstrInitialDir     = NULL;
  1853.             ofn.lpstrTitle          = "Save File";
  1854.             ofn.Flags               = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  1855.             ofn.lCustData           = 0;
  1856.             ofn.nFileOffset         = 0;
  1857.             ofn.nFileExtension      = 0;
  1858.             ofn.lpstrDefExt         = NULL;
  1859.             ofn.lpfnHook            = NULL;
  1860.             ofn.lpTemplateName      = NULL;
  1861.  
  1862.             if (!GetSaveFileName(&ofn))
  1863.                 break;
  1864.  
  1865.             switch(wParam)
  1866.             {
  1867.                 case MENU_SAVE_RLE:
  1868.                     SaveRleFile(szFile,0,numFrames);
  1869.                     break;
  1870.  
  1871.                 case MENU_SAVE_RL0:
  1872.                     SaveRl0File(szFile,0,numFrames);
  1873.                     AnsiLower(szFile);
  1874.                     wsprintf(ach, "%ls - %ls",
  1875.                         (LPSTR)szAppName, (LPSTR)szFile);
  1876.                     SetWindowText(hwnd, ach);
  1877.                     lstrcpy(gszCurFilespec, szFile);
  1878.                     break;
  1879.  
  1880.                 case MENU_SAVE_WAVE:
  1881.                     SaveWavFile(szFile,0,numFrames);
  1882.                     break;
  1883.             }
  1884.  
  1885.             fDirty = FALSE;
  1886.         break;
  1887.         
  1888.     case MENU_REDRAW:
  1889.         InvalidateRect(hwnd,NULL,TRUE);
  1890.         break;
  1891.         
  1892.     case MENU_REALIZE:
  1893.         RealizeFrames();
  1894.         break;
  1895.  
  1896.     case MENU_IDENTITY:
  1897.         MapIdentFrames();
  1898.         break;
  1899.  
  1900.     case MENU_PASTE_PALETTE:
  1901.         if (OpenClipboard(hwnd))
  1902.         {
  1903.         PurgeFrames();    // if a frame has both a hdib & hrle, this
  1904.                 // could screw up when we RLE the movie
  1905.         hpal = GetClipboardData(CF_PALETTE);
  1906.         CloseClipboard();
  1907.  
  1908.         MapPalFrames(CopyPalette(hpal));
  1909.         }
  1910.         break;
  1911.     }
  1912.     return 0L;
  1913. }
  1914.  
  1915. /*----------------------------------------------------------------------------*\
  1916. |   QueryClose - Ask user to save
  1917. \*----------------------------------------------------------------------------*/
  1918. BOOL QueryClose(HWND hwnd)
  1919. {
  1920.     int i;
  1921.  
  1922.     if (fDirty)
  1923.     {
  1924.     i = MessageBox(hwnd,"RLE file has changed.\nSave changes?",
  1925.         szAppName,MB_YESNOCANCEL|MB_ICONQUESTION|MB_TASKMODAL);
  1926.  
  1927.     switch(i)
  1928.     {
  1929.         case IDYES:
  1930.         SendMessage(hwnd, WM_COMMAND, MENU_SAVE_RL0, 0L);
  1931.         return TRUE;
  1932.         case IDNO:
  1933.         return TRUE;
  1934.         default:
  1935.         case IDCANCEL:
  1936.         return FALSE;
  1937.     }
  1938.     }
  1939.     return TRUE;
  1940. }
  1941.  
  1942. /*
  1943.  * CopyPalette, makes a copy of a GDI logical palette
  1944.  */
  1945. HPALETTE CopyPalette(HPALETTE hpal)
  1946. {
  1947.     PLOGPALETTE ppal;
  1948.     int         nNumEntries;
  1949.  
  1950.     if (!hpal)
  1951.     return NULL;
  1952.  
  1953.     GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
  1954.  
  1955.     if (nNumEntries == 0)
  1956.     return NULL;
  1957.  
  1958.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
  1959.         nNumEntries * sizeof(PALETTEENTRY));
  1960.  
  1961.     if (!ppal)
  1962.     return NULL;
  1963.  
  1964.     ppal->palVersion    = PALVERSION;
  1965.     ppal->palNumEntries = nNumEntries;
  1966.  
  1967.     GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
  1968.  
  1969.     hpal = CreatePalette(ppal);
  1970.  
  1971.     LocalFree((HANDLE)ppal);
  1972.     return hpal;
  1973. }
  1974.