home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libDIVE.cpp < prev    next >
C/C++ Source or Header  |  2002-06-24  |  34KB  |  1,221 lines

  1. /*
  2.     OS/2 DIVE class library
  3.     Copyright (C) 1997 by Andrew Zabolotny <bit@eltech.ru>
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19.  
  20. #define INCL_DOS
  21. #define INCL_WIN
  22. #define INCL_GPI
  23. #define INCL_OS2MM
  24.  
  25. #include <os2.h>
  26. #include <os2me.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <limits.h>
  30. #include <malloc.h>
  31. #include "libDIVE.h"
  32.  
  33. static long MAX_PHYS_COLORS = -1;
  34. static bool DEVICE_HAS_PALETTE = FALSE;
  35.  
  36. void CalcFrame(long PicW, long PicH, long WinW, long WinH, long *OutW, long *OutH)
  37. {
  38.     ULONG Koeff;
  39.  
  40.     Koeff = (PicW * 1000) / (PicH);
  41.  
  42.     *OutW = WinW;
  43.     *OutH = (WinW * 1000) / Koeff;
  44.  
  45.     if (*OutH > WinH)
  46.     {
  47.         *OutW = (WinH * Koeff) / 1000;
  48.         *OutH = WinH;
  49.     }
  50.  
  51.     return;
  52. }
  53.  
  54. diveApp::diveApp ()
  55. {
  56.   appWNlength = 0;
  57.   AB = WinInitialize (0);
  58.   MQ = WinCreateMsgQueue (AB, 0);
  59. }
  60.  
  61. diveApp::~diveApp ()
  62. {
  63.   while (appWNlength--)
  64.     WinDestroyWindow (appWN[appWNlength]);
  65.   WinDestroyMsgQueue (MQ);
  66.   WinTerminate (AB);
  67. }
  68.  
  69. void diveApp::Run ()
  70. {
  71.   QMSG qmsg;
  72.  
  73.   while (WinGetMsg (AB, &qmsg, 0, 0, 0))
  74.     WinDispatchMsg (AB, &qmsg);
  75. }
  76.  
  77. bool diveApp::ProcessQueuedMessages ()
  78. {
  79. #define MSG_MASK (QS_KEY | QS_MOUSE | QS_TIMER | QS_PAINT | QS_POSTMSG)
  80.   QMSG qmsg;
  81.  
  82.   while ((WinQueryQueueStatus (MQ) & MSG_MASK) != 0)
  83.   {
  84.     if (WinGetMsg (AB, &qmsg, 0, 0, 0))
  85.       WinDispatchMsg (AB, &qmsg);
  86.     else
  87.       return FALSE;
  88.   }
  89.   return TRUE;
  90. }
  91.  
  92. HWND diveApp::CreateWindow (PSZ Title, HMODULE ModID, ULONG ResID, ULONG Flags)
  93. {
  94. #define DIVE_WINDOW_CLASS (PSZ)"diveView"
  95.   ULONG flStyle;
  96.   HWND diveFR, diveCL;
  97.  
  98.   if (!WinRegisterClass (AB, DIVE_WINDOW_CLASS, NULL,
  99.          CS_SIZEREDRAW | CS_MOVENOTIFY, sizeof (void *)))
  100.     return 0;
  101.  
  102.   flStyle = Flags | FCF_SIZEBORDER | FCF_AUTOICON;
  103.   if (flStyle & FCF_SYSMENU)
  104.     flStyle = flStyle | FCF_MENU;
  105.   if (flStyle & FCF_TITLEBAR)
  106.     flStyle = flStyle | FCF_SYSMENU | FCF_MINMAX;
  107.   if (Title)
  108.     flStyle = flStyle | FCF_TASKLIST;
  109.  
  110.   diveFR = WinCreateStdWindow (HWND_DESKTOP, FS_NOBYTEALIGN, &flStyle,
  111.     DIVE_WINDOW_CLASS, Title, 0, ModID, ResID, &diveCL);
  112.  
  113.   if (diveFR)
  114.   {
  115.     // Keep track of all windows we created
  116.     appWN[appWNlength++] = diveFR;
  117.  
  118.     if(Flags & FCF_SYSMENU) // Replace system menu by 1st submenu under menu bar
  119.     {
  120.       MENUITEM mi, smi;
  121.       HWND hMenu = WinWindowFromID(diveFR, FID_MENU);
  122.  
  123.       // Find handle of first submenu in menu bar
  124.       WinSendMsg (hMenu, MM_QUERYITEM, MPFROM2SHORT (
  125.           SHORT1FROMMR (WinSendMsg (hMenu, MM_ITEMIDFROMPOSITION, NULL, NULL)),
  126.           FALSE), MPFROMP (&mi));
  127.       // Change menu ID so it will not appear below title bar
  128.       WinSetWindowUShort (hMenu, QWS_ID, 0);
  129.  
  130.       // Find System Menu and pull-down menu handles
  131.       HWND hSysMenu = WinWindowFromID (diveFR, FID_SYSMENU);
  132.  
  133.       if (hMenu && hSysMenu)
  134.       {
  135.         // Find the handle of first submenu in system menu
  136.         WinSendMsg (hSysMenu, MM_QUERYITEM, MPFROM2SHORT (
  137.             SHORT1FROMMR (WinSendMsg (hSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL)),
  138.             FALSE), MPFROMP (&smi));
  139.         HWND hSysSubMenu = smi.hwndSubMenu;
  140.  
  141.         smi.hwndSubMenu = mi.hwndSubMenu;
  142.  
  143.         // Add separator line to that submenu
  144.         memset (&mi, 0, sizeof (mi));
  145.         mi.iPosition = MIT_END;
  146.         mi.afStyle = MIS_SEPARATOR;
  147.         WinSendMsg (smi.hwndSubMenu, MM_INSERTITEM, (MPARAM) & mi, NULL);
  148.         // Add a submenu link to previous window submenu
  149.         mi.afStyle = MIS_SUBMENU;
  150.         mi.hwndSubMenu = hSysSubMenu;
  151.         WinSendMsg (smi.hwndSubMenu, MM_INSERTITEM, (MPARAM) & mi, (MPARAM) "~Window");
  152.  
  153.         // Replace system menu by this submenu
  154.         WinSendMsg (hSysMenu, MM_SETITEM, MPFROM2SHORT (0, FALSE), MPFROMP (&smi));
  155.       }
  156.     }
  157.   }
  158.   return diveFR;
  159. }
  160.  
  161. diveWindow::diveWindow (long Width, long Height, FOURCC Format, long SrcWidth, long SrcHeight, long nBuff)
  162. {
  163.   CLUT = NULL;
  164.   hDive = NULLHANDLE;
  165.   lastError = derrOK;
  166.   fFullScreen = FALSE;
  167.   fMinimized = FALSE;
  168.   fPhysCLUT = FALSE;
  169.   fAspect = TRUE;
  170.   fPause = TRUE;
  171.   fMouseVisible = TRUE;
  172.   MouseCursorID = SPTR_ARROW;
  173.   FailedCount = 0;
  174.   ActiveBuffer = 0;
  175.   VisibleBuffer = 0;
  176.   MouseButtonMask = 0;
  177.   MouseCaptured = FALSE;
  178.   MaintainAspectRatio (FALSE);
  179.   Pause (FALSE);
  180.   OldClientWindowProc = NULL;
  181.   OldFrameWindowProc = NULL;
  182.   nBuffers = nBuff;
  183.   BufferW = Width;
  184.   BufferH = Height;
  185.   BufferF = Format;
  186.   SourceWidth = SrcWidth;
  187.   SourceHeight = SrcHeight;
  188.   diveCL = NULLHANDLE;
  189.   diveFR = NULLHANDLE;
  190.   diveMN = NULLHANDLE;
  191.   hKeyboard = NULL;
  192.   hTerminate = NULL;
  193.   hMouse = NULL;
  194.   hFocus = NULL;
  195.   hCmd   = NULL;
  196.  
  197.   for(int ctl = 0; ctl < NUM_EXCTLS; ctl++)
  198.     hCtl[ctl] = 0;
  199.  
  200.   ScreenW = WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN);
  201.   ScreenH = WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN);
  202.   for (int i = 0; i < DIVE_MAXBUFFERS; i++)
  203.     hBuffer[i] = NULLHANDLE;
  204.   DirtyRect.xLeft = 1;
  205.   DirtyRect.xRight = -1;
  206.  
  207.   if (nBuff > DIVE_MAXBUFFERS || nBuff < 1)
  208.   {
  209.     lastError = derrBadNBuffers;
  210.     return;
  211.   }
  212.   if (MAX_PHYS_COLORS == -1)            // Query physical screen parameters
  213.   {
  214.     HPS hps = WinGetScreenPS (HWND_DESKTOP);
  215.     HDC hdc = GpiQueryDevice (hps);
  216.  
  217.     DevQueryCaps (hdc, CAPS_PHYS_COLORS, 1L, &MAX_PHYS_COLORS);
  218.     DevQueryCaps (hdc, CAPS_ADDITIONAL_GRAPHICS, 1L, (LONG *) & DEVICE_HAS_PALETTE);
  219.     DEVICE_HAS_PALETTE =  DEVICE_HAS_PALETTE && CAPS_PALETTE_MANAGER;
  220.     WinReleasePS (hps);
  221.   }
  222.   if (DiveOpen (&hDive, FALSE, NULL) != DIVE_SUCCESS)
  223.   {
  224.     lastError = derrCannotOpen;
  225.     return;
  226.   }
  227.   if (DosCreateEventSem (NULLHANDLE, &sRedrawComplete, 0, FALSE))
  228.   {
  229.     lastError = derrCreateSem;
  230.     return;
  231.   }
  232. }
  233.  
  234. diveWindow::~diveWindow ()
  235. {
  236.   Unbind (FALSE);
  237.   DosCloseEventSem (sRedrawComplete);   // Destroy redraw semaphore
  238.   for (int i = 0; i <= nBuffers; i++)   // Free image buffers
  239.     DiveFreeImageBuffer (hDive, hBuffer[i]);
  240.   DiveClose (hDive);
  241.   ResetPhysCLUT ();
  242. }
  243.  
  244. bool diveWindow::Bind (HWND winHandle)
  245. {
  246.   diveFR = winHandle;
  247.   diveCL = WinWindowFromID (diveFR, FID_CLIENT);
  248.   if (diveCL == NULLHANDLE)
  249.   {
  250.     diveCL = diveFR;
  251.     diveFR = NULLHANDLE;
  252.     diveMN = NULLHANDLE;
  253.   } else
  254.   {
  255.     diveMN = WinWindowFromID (diveFR, FID_MENU);
  256.     if (!diveMN)
  257.       diveMN = WinWindowFromID (diveFR, FID_SYSMENU);
  258.     MouseVisible (fMouseVisible);
  259.     Pause (fPause);
  260.   }
  261.  
  262.   if (!WinSetWindowPtr (diveCL, QWL_USER, this))
  263.   {
  264.     lastError = derrBadWindow;
  265.     return FALSE;
  266.   }
  267.   if (diveFR && !WinSetWindowPtr (diveFR, QWL_USER, this))
  268.   {
  269.     lastError = derrBadWindow;
  270.     return FALSE;
  271.   }
  272.   // Query current window width and height
  273.   SWP swp;
  274.  
  275.   WinQueryWindowPos (diveCL, &swp);
  276.   WindowW = swp.cx;
  277.   WindowH = swp.cy;
  278.  
  279.   OldClientWindowProc = WinSubclassWindow (diveCL, &ClientHandler);
  280.   OldFrameWindowProc = WinSubclassWindow (diveFR, &FrameHandler);
  281.  
  282.   if (!WinSetVisibleRegionNotify (diveCL, TRUE))
  283.   {
  284.     lastError = derrBadWindow;
  285.     return FALSE;
  286.   }
  287.   if (!ResizeBuffer (BufferW, BufferH, BufferF))
  288.   {
  289.     lastError = derrAllocBuffer;
  290.     return FALSE;
  291.   }
  292.   if (!SetupPalette ())
  293.   {
  294.     lastError = derrPalette;
  295.     return FALSE;
  296.   }
  297.   return TRUE;
  298. }
  299.  
  300. bool diveWindow::Unbind (bool Destroy)
  301. {
  302.   if (!diveCL)
  303.     return FALSE;
  304.   DiveSetupBlitter (hDive, NULL);
  305.   oldDirtyRect.xLeft = -9999;
  306.   if (Destroy)
  307.     if (diveFR)
  308.       WinDestroyWindow (diveFR);
  309.     else
  310.       WinDestroyWindow (diveCL);
  311.   else
  312.   {
  313.     // Restore initial window state
  314.     WinSetVisibleRegionNotify (diveCL, FALSE);
  315.     if (OldClientWindowProc)
  316.       WinSubclassWindow (diveCL, OldClientWindowProc);
  317.     if (OldFrameWindowProc)
  318.       WinSubclassWindow (diveFR, OldFrameWindowProc);
  319.   }
  320.   diveCL = NULLHANDLE;
  321.   diveFR = NULLHANDLE;
  322.   diveMN = NULLHANDLE;
  323.   return TRUE;
  324. }
  325.  
  326. bool diveWindow::DisableAccelTable ()
  327. {
  328.   return WinSetAccelTable (WinQueryAnchorBlock (diveFR), NULLHANDLE, NULLHANDLE);
  329. }
  330.  
  331. void diveWindow::MouseVisible (bool State)
  332. {
  333.   fMouseVisible = State;
  334.   WinPostMsg (diveMN, MM_SETITEMATTR, MPFROM2SHORT (cmdToggleMouse, TRUE),
  335.     MPFROM2SHORT(MIA_CHECKED, fMouseVisible ? MIA_CHECKED : 0));
  336.   /* Send a pseudo mouse-move message to get mouse pointer updated */
  337.   POINTL mouse;
  338.   WinQueryPointerPos (HWND_DESKTOP, &mouse);
  339.   WinMapWindowPoints (HWND_DESKTOP, diveCL, &mouse, 1);
  340.   RECTL winpos;
  341.   WinQueryWindowRect (diveCL, &winpos);
  342.   if ((mouse.x >= winpos.xLeft) && (mouse.x < winpos.xRight)
  343.    && (mouse.y >= winpos.yBottom) && (mouse.y < winpos.yTop))
  344.     WinPostMsg (diveCL, WM_MOUSEMOVE, MPFROM2SHORT (mouse.x, mouse.y),
  345.       MPFROM2SHORT (HT_NORMAL, KC_NONE));
  346. }
  347.  
  348. u_char *diveWindow::BeginPaint (ULONG * BytesPerLine, long BufferNo)
  349. {
  350.   unsigned char *buff;
  351.   ULONG TotalLines;
  352.  
  353.   if (fPause)
  354.   {
  355.     DosSleep (1);
  356.     return NULL;
  357.   }
  358.   if (BufferNo == DIVE_NEXTBUFFER)
  359.   {
  360.     ActiveBuffer++;
  361.     if (ActiveBuffer >= nBuffers)
  362.       ActiveBuffer = 0;
  363.   } else
  364.     ActiveBuffer = BufferNo;
  365.   if (DiveBeginImageBufferAccess (hDive, hBuffer[ActiveBuffer],
  366.       (PBYTE *)&buff, BytesPerLine, &TotalLines) != DIVE_SUCCESS)
  367.     return (NULL);
  368.   return (buff);
  369. }
  370.  
  371. void diveWindow::EndPaint ()
  372. {
  373.   DiveEndImageBufferAccess (hDive, hBuffer[ActiveBuffer]);
  374. }
  375.  
  376. bool diveWindow::SetupBlitter ()
  377. {
  378.   if (fMinimized || !diveCL)
  379.     return TRUE;                        // Don`t setup blitter when minimized
  380.  
  381.   if ((oldDirtyRect.xLeft == DirtyRect.xLeft)
  382.     && (oldDirtyRect.xRight == DirtyRect.xRight)
  383.     && (oldDirtyRect.yTop == DirtyRect.yTop)
  384.     && (oldDirtyRect.yBottom == DirtyRect.yBottom))
  385.     return TRUE;                        // Blitter already set up
  386.  
  387.   oldDirtyRect.xLeft = DirtyRect.xLeft;
  388.   oldDirtyRect.xRight = DirtyRect.xRight;
  389.   oldDirtyRect.yBottom = DirtyRect.yBottom;
  390.   oldDirtyRect.yTop = DirtyRect.yTop;
  391.  
  392.   HPS hps = WinGetPS (diveCL);
  393.   HRGN hrgn = GpiCreateRegion (hps, 0, NULL);
  394.  
  395.   WinQueryVisibleRegion (diveCL, hrgn);
  396.  
  397.   // First, get the rectangles and window coordinates:
  398.   RECTL rctls[256];                     // Rectangles for visible rgn
  399.   RGNRECT rgnCtl;                       // Region control struct
  400.   SETUP_BLITTER SetupBlitter;           // DiveSetupBlitter struct
  401.   POINTL pointl;
  402.   SWP swp;
  403.  
  404.   // Get rectangles for the visible region
  405.   rgnCtl.ircStart = 0;                  // Enumerate rectangles
  406.   rgnCtl.crc = sizeof (rctls) / sizeof (RECTL); // Max number of rectangles
  407.   rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
  408.   if (GpiQueryRegionRects (hps, hrgn, NULL, &rgnCtl, rctls))
  409.   {
  410.     // Now goes the tricky part: scan all rectangles returned by
  411.     // GpiQueryRegionRects and intersect them with DirtyRect. This way,
  412.     // we'll get updated only the part of screen that has been changed.
  413.     for (int i = rgnCtl.crcReturned - 1; i >= 0; i--)
  414.     {
  415.       if (DirtyRect.xLeft > rctls[i].xLeft)
  416.         rctls[i].xLeft = DirtyRect.xLeft;
  417.       if (DirtyRect.xRight < rctls[i].xRight)
  418.         rctls[i].xRight = DirtyRect.xRight;
  419.       if (DirtyRect.yBottom > rctls[i].yBottom)
  420.         rctls[i].yBottom = DirtyRect.yBottom;
  421.       if (DirtyRect.yTop < rctls[i].yTop)
  422.         rctls[i].yTop = DirtyRect.yTop;
  423.  
  424.       if ((rctls[i].xLeft >= rctls[i].xRight)
  425.         || (rctls[i].yBottom >= rctls[i].yTop))
  426.       {
  427.         // the rectangle became empty: we should remove it from the list
  428.         rgnCtl.crcReturned--;
  429.         memmove (&rctls[i], &rctls[i + 1], (rgnCtl.crcReturned - i) * sizeof (RECTL));
  430.       }                                 /* endif */
  431.     }                                   /* endfor */
  432.  
  433.  
  434.     // Find the window position relative to its parent.
  435.     WinQueryWindowPos (diveCL, &swp);
  436.     WindowW = swp.cx;
  437.     WindowH = swp.cy;
  438.  
  439.     CalcFrame(BufferW, BufferH, WindowW, WindowH, &FrameW, &FrameH);
  440.  
  441.     // Map window position to the desktop.
  442. //    pointl.x = swp.x;
  443. //    pointl.y = swp.y;
  444.     pointl.x = swp.x + (WindowW - FrameW)/2;
  445.     pointl.y = swp.y + (WindowH - FrameH)/2;
  446.  
  447.     WinMapWindowPoints (WinQueryWindow (diveCL, QW_PARENT), HWND_DESKTOP, &pointl, 1);
  448.  
  449.     // Tell DIVE about the new settings.
  450.     SetupBlitter.ulStructLen = sizeof (SETUP_BLITTER);
  451.     SetupBlitter.fInvert = 0;
  452.     SetupBlitter.fccSrcColorFormat = BufferF;
  453.     SetupBlitter.ulSrcPosX = 0;
  454.     SetupBlitter.ulSrcPosY = 0;
  455.     SetupBlitter.ulSrcWidth = SourceWidth;
  456.     SetupBlitter.ulSrcHeight = SourceHeight;
  457.     SetupBlitter.ulDitherType = 1;
  458.     SetupBlitter.fccDstColorFormat = FOURCC_SCRN;
  459. //    SetupBlitter.ulDstWidth = swp.cx;
  460. //    SetupBlitter.ulDstHeight = swp.cy;
  461.     SetupBlitter.ulDstWidth = swp.cx - (WindowW - FrameW);
  462.     SetupBlitter.ulDstHeight = swp.cy - (WindowH - FrameH);
  463.     SetupBlitter.lDstPosX = 0;
  464.     SetupBlitter.lDstPosY = 0;
  465.     SetupBlitter.lScreenPosX = pointl.x;
  466.     SetupBlitter.lScreenPosY = pointl.y;
  467.     SetupBlitter.ulNumDstRects = rgnCtl.crcReturned;
  468.     SetupBlitter.pVisDstRects = rctls;
  469.     DiveSetupBlitter (hDive, &SetupBlitter);
  470.   } else
  471.     DiveSetupBlitter (hDive, NULL);
  472.   WinReleasePS (hps);
  473.   GpiDestroyRegion (hps, hrgn);
  474.   return TRUE;
  475. }
  476.  
  477. bool diveWindow::SetupPalette ()
  478. {
  479.   if (BufferF != FOURCC_LUT8)
  480.     return TRUE;                        // Only LUT8 buffers needs palette
  481.   DiveSetDestinationPalette (hDive, 0, MAX_PHYS_COLORS, DIVE_PALETTE_PHYSICAL);
  482.   return TRUE;
  483. }
  484.  
  485. bool diveWindow::SetCLUT (ULONG * NewCLUT, int Count)
  486. {
  487.   if (Count > MAX_PHYS_COLORS)
  488.     return FALSE;
  489.  
  490.   if (CLUT == NULL)
  491.   {
  492.     CLUT = (ULONG *) malloc (MAX_PHYS_COLORS * sizeof (ULONG));
  493.     if (!CLUT)
  494.       return FALSE;
  495.     memset (CLUT, 0, sizeof (CLUT));
  496.   }
  497.   memcpy (CLUT, NewCLUT, Count * sizeof (LONG));
  498.   DiveSetSourcePalette (hDive, 0, Count, (BYTE *) CLUT);
  499.   return TRUE;
  500. }
  501.  
  502. bool diveWindow::SetPhysCLUT ()
  503. {
  504.   if (!CLUT)
  505.     return FALSE;
  506.   HPS hps = WinGetScreenPS (HWND_DESKTOP);
  507.   HDC hdc = GpiQueryDevice (hps);
  508.  
  509.   if (DEVICE_HAS_PALETTE)
  510.   {
  511.     ULONG *tmpCLUT = (ULONG *) alloca (MAX_PHYS_COLORS * sizeof (ULONG));
  512.     ULONG *CurCol = tmpCLUT;
  513.     int Count = 0;
  514.  
  515.     for (int i = 0; i < MAX_PHYS_COLORS; i++)
  516.       if (CLUT[i] != 0xffffffff)
  517.       {
  518.         *CurCol++ = CLUT[i];
  519.         Count++;
  520.       }
  521.     if (Count)
  522.     {
  523.       // Reset palette first
  524.       Gre32Entry3 (hdc, 0L, 0x000060C7L);
  525.       // Create a logical color table
  526.       int StartIndex = (MAX_PHYS_COLORS - Count) / 2;
  527.  
  528.       GpiCreateLogColorTable (hps, LCOL_PURECOLOR | LCOL_REALIZABLE,
  529.         LCOLF_CONSECRGB, StartIndex, Count, (LONG *) tmpCLUT);
  530.       Gre32Entry3 (hdc, 0L, 0x000060C6L);
  531.       WinInvalidateRect (HWND_DESKTOP, (PRECTL) NULL, TRUE);
  532.       fPhysCLUT = TRUE;
  533.     }
  534.   }
  535.   WinReleasePS (hps);
  536.   SetupPalette ();
  537.   return TRUE;
  538. }
  539.  
  540. bool diveWindow::ResetPhysCLUT ()
  541. {
  542.   if (fPhysCLUT)
  543.   {
  544.     HPS hps = WinGetScreenPS (HWND_DESKTOP);
  545.     HDC hdc = GpiQueryDevice (hps);
  546.  
  547.     if (DEVICE_HAS_PALETTE)
  548.     {
  549.       Gre32Entry3 (hdc, 0L, 0x000060C7L);
  550.       WinInvalidateRect (HWND_DESKTOP, (PRECTL) NULL, TRUE);
  551.     }
  552.     WinReleasePS (hps);
  553.     SetupPalette ();
  554.   }
  555.   return TRUE;
  556. }
  557.  
  558. bool diveWindow::Show (bool Visible)
  559. {
  560.   bool rc = WinSetWindowPos (diveFR, NULLHANDLE, 0, 0, 0, 0,
  561.     Visible ? SWP_SHOW + SWP_ACTIVATE : SWP_HIDE);
  562.  
  563.   DirtyRect.xLeft = 0;
  564.   DirtyRect.xRight = WindowWidth();
  565.   DirtyRect.yBottom = 0;
  566.   DirtyRect.yTop = WindowHeight ();
  567.   SetupBlitter ();
  568.   return rc;
  569. }
  570.  
  571. MRESULT diveWindow::ClientHandler (HWND Handle, ULONG Message, MPARAM MsgParm1, MPARAM MsgParm2)
  572. {
  573.   diveWindow *win = (diveWindow *) WinQueryWindowPtr (Handle, QWL_USER);
  574.  
  575.   if (win)
  576.     return win->ClientMessage (Message, MsgParm1, MsgParm2);
  577.   else
  578.     return NULL;
  579. }
  580.  
  581. MRESULT diveWindow::FrameHandler (HWND Handle, ULONG Message, MPARAM MsgParm1, MPARAM MsgParm2)
  582. {
  583.   diveWindow *win = (diveWindow *) WinQueryWindowPtr (Handle, QWL_USER);
  584.  
  585.   if (win)
  586.     return win->FrameMessage (Message, MsgParm1, MsgParm2);
  587.   else
  588.     return NULL;
  589. }
  590.  
  591. MRESULT diveWindow::ClientMessage (ULONG Message, MPARAM MsgParm1, MPARAM MsgParm2)
  592. {
  593.   SWP swp;
  594.   bool m_down;
  595.   int m_button;
  596.   int m_capture;
  597.   MRESULT res = 0;
  598.  
  599.   switch (Message)
  600.   {
  601.     case WM_PAINT:
  602.     {
  603.       // Obtain the rectangle that should be repainted
  604.       HPS hps = WinBeginPaint (diveCL, NULLHANDLE, &DirtyRect);
  605.  
  606.       if (FrameH < WindowH)
  607.       {
  608.           // Down
  609.           RealRect.xLeft = DirtyRect.xLeft;
  610.           RealRect.yBottom = DirtyRect.yBottom;
  611.           RealRect.xRight = DirtyRect.xRight;
  612.           RealRect.yTop = (WindowH - FrameH) / 2;
  613.           WinFillRect(hps, &RealRect, CLR_BLACK);
  614.  
  615.           // Up
  616.           RealRect.yTop = DirtyRect.yTop;
  617.           RealRect.yBottom = DirtyRect.yTop - (WindowH - FrameH) / 2 - 1;
  618.           WinFillRect(hps, &RealRect, CLR_BLACK);
  619.       }
  620.  
  621.       if (FrameW < WindowW)
  622.       {
  623.           // Left
  624.           RealRect.xLeft = 0;
  625.           RealRect.yBottom = DirtyRect.yBottom;
  626.           RealRect.xRight = (WindowW - FrameW) / 2;
  627.           RealRect.yTop = DirtyRect.yTop;
  628.           WinFillRect(hps, &RealRect, CLR_BLACK);
  629.  
  630.           // Right
  631.           RealRect.xLeft = DirtyRect.xRight - (WindowW - FrameW) / 2;
  632.           RealRect.yBottom = DirtyRect.yBottom;
  633.           RealRect.xRight = DirtyRect.xRight;
  634.           RealRect.yTop = DirtyRect.yTop;
  635.           WinFillRect(hps, &RealRect, CLR_BLACK);
  636.       }
  637.  
  638.       SetupBlitter ();
  639.       if (DiveBlitImage (hDive, hBuffer[VisibleBuffer], DIVE_BUFFER_SCREEN) != DIVE_SUCCESS)
  640.         FailedCount++;
  641.  
  642.       WinEndPaint (hps);
  643.       FrameCount++;
  644.       DosPostEventSem (sRedrawComplete);
  645.       return (MRESULT)0;
  646.     }
  647.  
  648.     case WM_VRNDISABLED:
  649.       FailedCount = 0;
  650.       DiveSetupBlitter (hDive, NULL);
  651.       oldDirtyRect.xLeft = -9999;
  652.       return 0;
  653.  
  654.     case WM_VRNENABLED:
  655.       // Query current window width and height
  656.       if(WinQueryWindowPos (diveCL, &swp) &&
  657.          ((WindowW != swp.cx) || (WindowH != swp.cy)))
  658.       {
  659.         WinQueryWindowPos (diveCL, &swp);
  660.         DirtyRect.xRight = WindowW = swp.cx;
  661.         DirtyRect.yTop = WindowH = swp.cy;
  662.         DirtyRect.xLeft = 0;
  663.         DirtyRect.yBottom = 0;
  664.         FailedCount = 1;
  665.       }
  666.  
  667.       SetupBlitter ();
  668.  
  669.       if (FailedCount > 0)
  670.         Switch(VisibleBuffer);
  671.  
  672.       return 0;
  673.  
  674.     case WM_REALIZEPALETTE:
  675.       SetupPalette ();
  676.       return 0;
  677.  
  678.     case WM_COMMAND:
  679.       if(hCmd)
  680.         MsgParm1 = hCmd(this, paramCmd, diveFR, MsgParm1, MsgParm2, 0); //Pre-action
  681.  
  682.       switch ((ULONG) MsgParm1)
  683.       {
  684.         case cmdAlignLeft:
  685.           if (WinQueryWindowPos (diveFR, &swp))
  686.             WinSetWindowPos (diveFR, NULLHANDLE, 0, swp.y, 0, 0, SWP_MOVE);
  687.           break;
  688.  
  689.         case cmdAlignRight:
  690.           if (WinQueryWindowPos (diveFR, &swp))
  691.             WinSetWindowPos (diveFR, NULLHANDLE, ScreenW - swp.cx, swp.y, 0, 0, SWP_MOVE);
  692.           break;
  693.  
  694.         case cmdAlignBottom:
  695.           if (WinQueryWindowPos (diveFR, &swp))
  696.             WinSetWindowPos (diveFR, NULLHANDLE, swp.x, 0, 0, 0, SWP_MOVE);
  697.           break;
  698.  
  699.         case cmdAlignTop:
  700.           if (WinQueryWindowPos (diveFR, &swp))
  701.             WinSetWindowPos (diveFR, NULLHANDLE, swp.x, ScreenH - swp.cy, 0, 0, SWP_MOVE);
  702.           break;
  703.  
  704.         case cmdAlignCenter:
  705.           Resize (-1, -1, TRUE);
  706.           break;
  707.  
  708.         case cmdSnap1to1:
  709.           Resize (BufferW * 1, BufferH * 1, FALSE);
  710.           break;
  711.  
  712.         case cmdSnap2to1:
  713.           Resize (BufferW * 2, BufferH * 2, FALSE);
  714.           break;
  715.  
  716.         case cmdSnap3to1:
  717.           Resize (BufferW * 3, BufferH * 3, FALSE);
  718.           break;
  719.  
  720.         case cmdSnap4to1:
  721.           Resize (BufferW * 4, BufferH * 4, FALSE);
  722.           break;
  723.  
  724.         case cmdFullScreen:
  725.           FullScreen (!fFullScreen);
  726.           break;
  727.  
  728.         case cmdToggleAspect:
  729.           MaintainAspectRatio (!fAspect);
  730.  
  731.           if (fAspect)
  732.             if (WinQueryWindowPos (diveCL, &swp))
  733.               Resize (swp.cx, swp.cy, FALSE);
  734.  
  735.           break;
  736.  
  737.         case cmdPause:
  738.           Pause(!fPause);
  739.           break;
  740.  
  741.         case cmdToggleMouse:
  742.           MouseVisible(!fMouseVisible);
  743.           break;
  744.  
  745.         case cmdClose:
  746.           WinPostMsg(diveFR, WM_QUIT, 0L, 0L);
  747.           break;
  748.  
  749.         case cmdIgnore:
  750.           break;
  751.  
  752.         default:
  753.           res = OldClientWindowProc(diveCL, Message, MsgParm1, MsgParm2);
  754.           break;
  755.       }
  756.  
  757.       //Note: returned value is ignored in postprocessing mode
  758.  
  759.       if(hCmd)
  760.         hCmd(this, paramCmd, diveFR, MsgParm1, MsgParm2, 1); //Post-action
  761.  
  762.       return res;
  763.  
  764.     case WM_CHAR:
  765.       {
  766.         // err.... for some strange reasons '/' on numeric keypad
  767.         // emits very strange codes for me ...
  768.         unsigned short flags = SHORT1FROMMP (MsgParm1);
  769.         if ((flags & (KC_CHAR | KC_SCANCODE)) == KC_CHAR && flags == 0x7f)
  770.           MsgParm1 = MPARAM (int (MsgParm1) | 0x6f000000 | KC_SCANCODE);
  771.         // Also ESC does not set KC_CHAR flag...
  772.         if ((flags & KC_SCANCODE) && ((SHORT2FROMMP (MsgParm1) >> 8) == 1))
  773.         {
  774.           flags |= KC_CHAR;
  775.           MsgParm2 = MPARAM (int (MsgParm2) | 0x1b000000);
  776.         }
  777.         if (hKeyboard && (flags & (KC_SCANCODE | KC_CHAR)))
  778.         {
  779.           unsigned short ScanCode = (flags & KC_SCANCODE) ? SHORT2FROMMP (MsgParm1) : 0;
  780.           unsigned short CharCode = (flags & KC_CHAR) ? SHORT1FROMMP (MsgParm2) : 0;
  781.           int RepeatCount = (ScanCode & 0xFF);
  782.           ScanCode >>= 8;
  783.  
  784.           if (ScanCode < 128)
  785.             if (flags & KC_KEYUP)
  786.             {
  787.               if (!CharCode)
  788.                 CharCode = lastKeyCode [ScanCode];
  789.             }
  790.             else
  791.               lastKeyCode [ScanCode] = CharCode;
  792.  
  793.           hKeyboard(this, paramKeyboard, ScanCode, CharCode, !(flags & KC_KEYUP),
  794.             RepeatCount, (flags & KC_SHIFT ? KF_SHIFT : 0) |
  795.             (flags & KC_ALT ? KF_ALT : 0) | (flags & KC_CTRL ? KF_CTRL : 0));
  796.           return (MRESULT) TRUE;
  797.         }
  798.         return (MRESULT) FALSE;
  799.       }
  800.  
  801.     case WM_MOUSEMOVE:
  802.       if (fActive)
  803.         WinSetPointer(HWND_DESKTOP, fMouseVisible ? WinQuerySysPointer (HWND_DESKTOP,
  804.           MouseCursorID, FALSE) : NULL);
  805.       m_down = FALSE;
  806.       m_button = 0;
  807.       goto ProcessMouse;
  808.  
  809.     case WM_BUTTON1DOWN:
  810.     case WM_BUTTON1DBLCLK:
  811.       m_down = TRUE;
  812.       m_button = 1;
  813.       MouseButtonMask |= 1;
  814.       goto ProcessMouse;
  815.  
  816.     case WM_BUTTON2DOWN:
  817.     case WM_BUTTON2DBLCLK:
  818.       m_down = TRUE;
  819.       m_button = 2;
  820.       MouseButtonMask |= 2;
  821.       goto ProcessMouse;
  822.  
  823.     case WM_BUTTON3DOWN:
  824.     case WM_BUTTON3DBLCLK:
  825.       m_down = TRUE;
  826.       m_button = 3;
  827.       MouseButtonMask |= 4;
  828.       goto ProcessMouse;
  829.  
  830.     case WM_BUTTON1UP:
  831.       m_down = FALSE;
  832.       m_button = 1;
  833.       MouseButtonMask &= ~1;
  834.       goto ProcessMouse;
  835.  
  836.     case WM_BUTTON2UP:
  837.       m_down = FALSE;
  838.       m_button = 2;
  839.       m_capture = 2;
  840.       MouseButtonMask &= ~2;
  841.       goto ProcessMouse;
  842.  
  843.     case WM_BUTTON3UP:
  844.       m_down = FALSE;
  845.       m_button = 3;
  846.       m_capture = 2;
  847.       MouseButtonMask &= ~4;
  848. ProcessMouse:
  849.       if (!fActive)
  850.         return OldClientWindowProc (diveCL, Message, MsgParm1, MsgParm2);
  851.       if (hMouse)
  852.       {
  853.         unsigned short flags = SHORT2FROMMP (MsgParm2);
  854.         hMouse(this, diveCL, paramMouse, m_button, m_down, (short)SHORT1FROMMP (MsgParm1),
  855.           (short)SHORT2FROMMP (MsgParm1), (flags & KC_SHIFT ? KF_SHIFT : 0) |
  856.           (flags & KC_ALT ? KF_ALT : 0) | (flags & KC_CTRL ? KF_CTRL : 0));
  857.       }
  858.  
  859.       if(m_down)
  860.         WinSetActiveWindow (HWND_DESKTOP, diveCL);
  861.  
  862.       if(MouseButtonMask && !MouseCaptured)
  863.         MouseCaptured = WinSetCapture (HWND_DESKTOP, diveCL);
  864.  
  865.       if(!MouseButtonMask && MouseCaptured)
  866.         MouseCaptured = !WinSetCapture (HWND_DESKTOP, NULLHANDLE);
  867.  
  868.       return (MRESULT) TRUE;
  869.   }
  870.  
  871.   return OldClientWindowProc (diveCL, Message, MsgParm1, MsgParm2);
  872. }
  873.  
  874. MRESULT diveWindow::FrameMessage (ULONG Message, MPARAM MsgParm1, MPARAM MsgParm2)
  875. {
  876.   switch (Message)
  877.   {
  878. #if 0
  879.     case WM_QUERYFRAMECTLCOUNT:
  880.       {
  881.         ULONG itemCount = (ULONG)OldFrameWindowProc(diveFR, Message,
  882.                                                     MsgParm1, MsgParm2);
  883.  
  884.         for(int i = 0; i < NUM_EXCTLS; i++)
  885.             if(hCtl[i])
  886.                 itemCount++;
  887.  
  888.         return MRFROMLONG(itemCount);
  889.       }
  890.     case WM_FORMATFRAME:
  891.       {
  892.         PSWP   pSWP     = 0;
  893.         USHORT usClient = 0;
  894.  
  895.         ULONG itemCount = (ULONG)OldFrameWindowProc(diveFR, Message,
  896.                                                     MsgParm1, MsgParm2);
  897.  
  898.         pSWP = (PSWP)PVOIDFROMMP(MsgParm1);
  899.  
  900.         while(pSWP[usClient].hwnd != WinWindowFromID(diveFR, FID_CLIENT))
  901.             usClient++;
  902.         return MRFROMSHORT(itemCount);
  903.       }
  904. #endif
  905.  
  906.     case WM_ADJUSTWINDOWPOS:
  907.       PSWP swp;
  908.       SWP oldpos;
  909.       MRESULT res;
  910.       bool cLS, cRS, cBS, cTS;
  911.       RECTL r;
  912.  
  913.       swp = (PSWP) MsgParm1;
  914.  
  915.       if (swp->fl & (SWP_MAXIMIZE | SWP_MINIMIZE | SWP_RESTORE))
  916.         FullScreen (FALSE);
  917.  
  918.       if (fFullScreen)
  919.       {
  920.         r.xLeft = 0;
  921.         r.xRight = ScreenW;
  922.         r.yBottom = 0;
  923.         r.yTop = ScreenH;
  924.         if (WinCalcFrameRect (diveFR, &r, FALSE))
  925.         {
  926.           if (swp->fl & SWP_SIZE)
  927.           {
  928.             swp->cx = r.xRight - r.xLeft;
  929.             swp->cy = r.yTop - r.yBottom;
  930.           }
  931.           if (swp->fl & SWP_MOVE)
  932.           {
  933.             swp->x = r.xLeft;
  934.             swp->y = r.yBottom;
  935.           }
  936.         }
  937.       }
  938.       if ((swp->fl & SWP_SIZE) && !fMinimized)
  939.       {
  940.         WinQueryWindowPos (diveFR, &oldpos);
  941.         cLS = (oldpos.x == swp->x);
  942.         cRS = ((oldpos.x + oldpos.cx) == (swp->x + swp->cx));
  943.         cBS = (oldpos.y == swp->y);
  944.         cTS = ((oldpos.y + oldpos.cy) == (swp->y + swp->cy));
  945.       }
  946.       else
  947.       {
  948.         cLS = FALSE;
  949.         cRS = FALSE;
  950.         cBS = FALSE;
  951.         cTS = FALSE;
  952.       }
  953.  
  954.       res = OldFrameWindowProc (diveFR, Message, MsgParm1, MsgParm2);
  955.  
  956.       if (long (res) & AWP_MAXIMIZED)
  957.       {
  958.         fMinimized = FALSE;
  959.         cLS = FALSE;
  960.         cRS = FALSE;
  961.         cBS = FALSE;
  962.         cTS = FALSE;
  963.         WinEnableMenuItem (diveMN, cmdScale, FALSE);
  964.       }
  965.       if (long (res) & AWP_MINIMIZED)
  966.       {
  967.         fMinimized = TRUE;
  968.         DiveSetupBlitter (hDive, NULL);
  969.         oldDirtyRect.xLeft = -9999;
  970.       }
  971.       if (long (res) & AWP_RESTORED)
  972.       {
  973.         fMinimized = FALSE;
  974.         cLS = FALSE;
  975.         cRS = FALSE;
  976.         cBS = FALSE;
  977.         cTS = FALSE;
  978.         WinEnableMenuItem (diveMN, cmdScale, TRUE);
  979.       }
  980.       if ((swp->fl & SWP_SIZE) && !fMinimized)
  981.       {
  982.         // Adjust window aspect ratio
  983.         if (fAspect && !fFullScreen)
  984.         {
  985.           r.xLeft = 0;
  986.           r.xRight = swp->cx;
  987.           r.yBottom = 0;
  988.           r.yTop = swp->cy;
  989.           WinCalcFrameRect (diveFR, &r, TRUE);
  990.           r.xRight -= r.xLeft;
  991.           r.yTop -= r.yBottom;
  992.           AdjustAspectRatio (&r.xRight, &r.yTop);
  993.           r.xLeft = 0;
  994.           r.yBottom = 0;
  995.           WinCalcFrameRect (diveFR, &r, FALSE);
  996.           swp->cx = r.xRight - r.xLeft;
  997.           swp->cy = r.yTop - r.yBottom;
  998.         }
  999.         // Check for lowest size limit
  1000.         r.xLeft = swp->x;
  1001.         r.xRight = swp->x + swp->cx;
  1002.         r.yBottom = swp->y;
  1003.         r.yTop = swp->y + swp->cy;
  1004.         WinCalcFrameRect (diveFR, &r, TRUE);
  1005.  
  1006.         r.xRight -= r.xLeft;
  1007.         if (r.xRight < BufferW / 2 && r.xRight > 0)
  1008.           r.xRight = BufferW / 2;
  1009.         r.xRight += r.xLeft;
  1010.  
  1011.         r.yTop -= r.yBottom;
  1012.         if (r.yTop < BufferH / 2 && r.yTop > 0)
  1013.           r.yTop = BufferH / 2;
  1014.         r.yTop += r.yBottom;
  1015.  
  1016.         WinCalcFrameRect (diveFR, &r, FALSE);
  1017.         swp->x = r.xLeft;
  1018.         swp->cx = r.xRight - r.xLeft;
  1019.         swp->y = r.yBottom;
  1020.         swp->cy = r.yTop - r.yBottom;
  1021.  
  1022.         // Check for unmovable bounds
  1023.         if (cLS)
  1024.           swp->x = oldpos.x;
  1025.         else if (cRS)
  1026.           swp->x = oldpos.x + oldpos.cx - swp->cx;
  1027.  
  1028.         if (cBS)
  1029.           swp->y = oldpos.y;
  1030.         else if (cTS)
  1031.           swp->y = oldpos.y + oldpos.cy - swp->cy;
  1032.       }
  1033.       return res;
  1034.  
  1035.     case WM_ACTIVATE:
  1036.       // If we`re in full-screen mode, maintain palette on activation/deactivation
  1037.       if (fFullScreen)
  1038.       {
  1039.         if ((HWND) MsgParm2 == diveFR)
  1040.           if ((ULONG) MsgParm1)
  1041.             SetPhysCLUT ();
  1042.           else
  1043.             ResetPhysCLUT ();
  1044.       }
  1045.       if ((HWND) MsgParm2 == diveFR)
  1046.       {
  1047.         fActive = (int) MsgParm1;
  1048.         if (hFocus)
  1049.           hFocus(this, paramFocus, fActive);
  1050.       }
  1051.       return OldFrameWindowProc (diveFR, Message, MsgParm1, MsgParm2);
  1052.  
  1053.     case WM_QUERYTRACKINFO:
  1054.       if (fFullScreen)
  1055.         return (MRESULT) FALSE;
  1056.       else
  1057.         return OldFrameWindowProc (diveFR, Message, MsgParm1, MsgParm2);
  1058.  
  1059.     case WM_DESTROY:
  1060.       lastError = derrDestroyed;
  1061.       if (hTerminate)
  1062.         hTerminate(this, paramTerminate);
  1063.       return FALSE;
  1064.  
  1065.     default:
  1066.       return OldFrameWindowProc (diveFR, Message, MsgParm1, MsgParm2);
  1067.   }
  1068. }
  1069.  
  1070. bool diveWindow::AdjustAspectRatio (long *Width, long *Height)
  1071. {
  1072.  
  1073.   if (!fAspect || fFullScreen)
  1074.     return TRUE;
  1075.   ULONG K = ((*Width << 16) / BufferW + (*Height << 16) / BufferH) / 2;
  1076.  
  1077.   *Width = (BufferW * K) >> 16;
  1078.   *Height = (BufferH * K) >> 16;
  1079.  
  1080.   if (*Width > ScreenW)
  1081.   {
  1082.     *Height = (*Height * ScreenW) / *Width;
  1083.     *Width = ScreenW;
  1084.   }
  1085.   if (*Height > ScreenH)
  1086.   {
  1087.     *Width = (*Width * ScreenH) / *Height;
  1088.     *Height = ScreenH;
  1089.   }
  1090.   return TRUE;
  1091. }
  1092.  
  1093. bool diveWindow::SetPos (long X, long Y)
  1094. {
  1095.   SWP swp;
  1096.   RECTL r;
  1097.  
  1098.   if (!WinQueryWindowPos (diveFR, &swp))
  1099.     return FALSE;
  1100.   r.xLeft = swp.x;
  1101.   r.xRight = swp.x + swp.cx;
  1102.   r.yBottom = swp.y;
  1103.   r.yTop = swp.y + swp.cy;
  1104.   if (!WinCalcFrameRect (diveFR, &r, TRUE))
  1105.     memset (&r, 0, sizeof (r));
  1106.  
  1107.   if (X != LONG_MIN)
  1108.   {
  1109.     long deltaX = X - r.xLeft;
  1110.     r.xLeft += deltaX;
  1111.     r.xRight += deltaX;
  1112.   }
  1113.   if (Y != LONG_MIN)
  1114.   {
  1115.     long deltaY = Y - r.yBottom;
  1116.     r.yTop += deltaY;
  1117.     r.yBottom += deltaY;
  1118.   }
  1119.   if (!WinCalcFrameRect (diveFR, &r, FALSE))
  1120.     return FALSE;
  1121.  
  1122.   return WinSetWindowPos (diveFR, NULLHANDLE, r.xLeft, r.yBottom,
  1123.     r.xRight - r.xLeft, r.yTop - r.yBottom,
  1124.     SWP_SIZE | SWP_MOVE);
  1125. }
  1126.  
  1127. bool diveWindow::Resize (long Width, long Height, bool Center)
  1128. {
  1129.   SWP swp;
  1130.   RECTL r;
  1131.  
  1132.   if (!WinQueryWindowPos (diveFR, &swp))
  1133.     return FALSE;
  1134.   r.xLeft = swp.x;
  1135.   r.xRight = swp.x + swp.cx;
  1136.   r.yBottom = swp.y;
  1137.   r.yTop = swp.y + swp.cy;
  1138.   if (!WinCalcFrameRect (diveFR, &r, TRUE))
  1139.     memset (&r, 0, sizeof (r));
  1140.  
  1141.   if (!fFullScreen)
  1142.   {
  1143.     if ((Width >= 0) && (Height >= 0))
  1144.     {
  1145.       AdjustAspectRatio (&Width, &Height);
  1146.       r.xRight = r.xLeft + Width;
  1147.       r.yTop = r.yBottom + Height;
  1148.     }
  1149.     if (Center)
  1150.     {
  1151.       swp.cx = r.xRight - r.xLeft;
  1152.       swp.cy = r.yTop - r.yBottom;
  1153.       r.xLeft = (ScreenW - swp.cx) / 2;
  1154.       r.yBottom = (ScreenH - swp.cy) / 2;
  1155.       r.xRight = r.xLeft + swp.cx;
  1156.       r.yTop = r.yBottom + swp.cy;
  1157.     }
  1158.     if (!WinCalcFrameRect (diveFR, &r, FALSE))
  1159.       return FALSE;
  1160.   }
  1161.   return WinSetWindowPos (diveFR, NULLHANDLE, r.xLeft, r.yBottom,
  1162.     r.xRight - r.xLeft, r.yTop - r.yBottom,
  1163.     SWP_SIZE | SWP_MOVE);
  1164. }
  1165.  
  1166. bool diveWindow::FullScreen (bool State)
  1167. {
  1168.   if (fFullScreen != State)
  1169.     switch (State)
  1170.     {
  1171.       case FALSE:
  1172.         ResetPhysCLUT ();
  1173.         fFullScreen = FALSE;
  1174.         WinSetWindowPos (diveFR, NULLHANDLE, swpFullScreen.x, swpFullScreen.y,
  1175.           swpFullScreen.cx, swpFullScreen.cy, SWP_MOVE | SWP_SIZE);
  1176.         break;
  1177.       case TRUE:
  1178.         WinQueryWindowPos (diveFR, &swpFullScreen);
  1179.         fFullScreen = TRUE;
  1180.         Resize (-1, -1, FALSE);
  1181.         SetPhysCLUT ();
  1182.         break;
  1183.     }
  1184.   return TRUE;
  1185. }
  1186.  
  1187. bool diveWindow::ResizeBuffer (long Width, long Height, FOURCC Format)
  1188. {
  1189.   SWP swp;
  1190.   int i;
  1191.   // Free image buffers
  1192.   for (i = 0; i < DIVE_MAXBUFFERS; i++)
  1193.     DiveFreeImageBuffer (hDive, hBuffer[i]);
  1194.  
  1195.   CalcFrame(Width, Height, WindowW, WindowH, &FrameW, &FrameH);
  1196.  
  1197.   // Allocate image buffers
  1198.   BufferW = Width;
  1199.   BufferH = Height;
  1200.   BufferF = Format;
  1201.   for (i = 0; i < nBuffers; i++)
  1202.     if (DiveAllocImageBuffer (hDive, &hBuffer[i], BufferF,
  1203.         BufferW, BufferH, 0, NULL) != DIVE_SUCCESS)
  1204.     {
  1205.       for (i--; i >= 0; i--)
  1206.         DiveFreeImageBuffer (hDive, hBuffer[i]);
  1207.       return FALSE;
  1208.     }
  1209.  
  1210.   WinQueryWindowPos (diveCL, &swp);
  1211.  
  1212.   DirtyRect.xLeft = 0;
  1213.   DirtyRect.xRight = WindowWidth();
  1214.   DirtyRect.yBottom = 0;
  1215.   DirtyRect.yTop = WindowHeight ();
  1216.   oldDirtyRect.xLeft = -9999;
  1217.  
  1218.   SetupBlitter ();
  1219.   return TRUE;
  1220. }
  1221.