home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / MacSource / ScreenUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-29  |  9.1 KB  |  291 lines  |  [TEXT/CWIE]

  1. /*
  2. ==============================================================================
  3. Project:    POV-Ray
  4.  
  5. Version:    3
  6.  
  7. File Name:    ScreenUtils.c
  8.  
  9. Description:
  10.     General-purpose screen/device routines.
  11.  
  12.     This is the main source file, containing the private definitions and
  13.     code to implement all the needed external and internal support functions.
  14.  
  15. Related Files:
  16.     ScreenUtils.h    - Header for these routines
  17. ------------------------------------------------------------------------------
  18. Author:
  19.     Eduard [esp] Schwan
  20. ------------------------------------------------------------------------------
  21.     from Persistence of Vision(tm) Ray Tracer
  22.     Copyright 1996 Persistence of Vision Team
  23. ------------------------------------------------------------------------------
  24.     NOTICE: This source code file is provided so that users may experiment
  25.     with enhancements to POV-Ray and to port the software to platforms other 
  26.     than those supported by the POV-Ray Team.  There are strict rules under
  27.     which you are permitted to use this file.  The rules are in the file
  28.     named POVLEGAL.DOC which should be distributed with this file. If 
  29.     POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  30.     Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  31.     Forum.  The latest version of POV-Ray may be found there as well.
  32.  
  33.     This program is based on the popular DKB raytracer version 2.12.
  34.     DKBTrace was originally written by David K. Buck.
  35.     DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  36. ------------------------------------------------------------------------------
  37. Change History:
  38.     920826    [esp]    Created
  39.     920903    [esp]    Major cleanup to PositionWindow
  40.     931001    [esp]    version 2.0 finished (Released on 10/4/93)
  41.     931006    [esp]    Fixed ForceRectOnScreen to not let window dangle off lower left
  42.     950522    [esp]    Fixed ForceRectOnScreen bug if main screen is not FIRST device!
  43.     951106    [esp]    Fixed ForceRectOnScreen bug to not allow slivers of windows
  44. ==============================================================================
  45. */
  46.  
  47. #include "ScreenUtils.h"    // our defs
  48.  
  49. /* Macintosh-specific headers */
  50. #include <QuickDraw.h>
  51. #include <menus.h>            // GetMBarHeight()
  52. #include <Windows.h>        // MoveWindow()
  53.  
  54.  
  55. // ==============================================
  56. void GetGlobalWindowRect(WindowPtr theWindow, Rect *theRect)
  57. {
  58.     Rect    windRect;
  59.  
  60.     windRect = theWindow->portRect;
  61.  
  62.     // yah, but where is it really?
  63.     SetPort(theWindow);
  64.     LocalToGlobal((Point*)&windRect.top);
  65.     LocalToGlobal((Point*)&windRect.bottom);
  66.  
  67.     *theRect = windRect;
  68. } // GetGlobalWindowRect
  69.  
  70.  
  71. // ==============================================
  72. void ForceRectOnScreen(Rect *aGlobalRect)
  73. {
  74.     long        foundArea;
  75.     GDHandle    aDevice;
  76.     GDHandle    foundDevice;
  77.     Rect        aDeviceRect;
  78.     Rect        foundDeviceRect;
  79.     Rect        intersectRect;
  80.  
  81.     /* initialize the found device to main device */
  82.     /* in case none found, we default to main device */
  83.     foundArea = 0;
  84.     foundDevice = GetMainDevice();
  85.     foundDeviceRect = (**foundDevice).gdRect;
  86.     foundDeviceRect.top += GetMBarHeight();
  87.  
  88.     for (aDevice = GetDeviceList(); aDevice != NULL; aDevice = GetNextDevice(aDevice))
  89.     {
  90.         /* If we found an active screen device that intersects some of the rect.. */
  91.         aDeviceRect = (**aDevice).gdRect;
  92.  
  93.         /* See if its the main screen.  If so, take menu bar into account! */
  94.         if ( (**aDevice).gdFlags & (1<<mainScreen) )
  95.         {
  96.             aDeviceRect.top += GetMBarHeight();
  97.         }
  98.  
  99.         /* if it is an active screen... */
  100.         if (TestDeviceAttribute(aDevice, screenDevice)
  101.             && TestDeviceAttribute(aDevice, screenActive)
  102.             && SectRect(aGlobalRect, &aDeviceRect, &intersectRect))
  103.         {
  104.             /* find out how much it intersects */
  105.             long area =
  106.                 ((long)intersectRect.right  - (long)intersectRect.left) *
  107.                 ((long)intersectRect.bottom - (long)intersectRect.top);
  108.             /* if intersects more than the last device of intersection, use this instead */
  109.             /* this therefore finds the screen of greatest intersection. */
  110.             if (area > foundArea)
  111.             {
  112.                 // If there are more than 4 pixels across or high, it's found.
  113.                 // This keeps us from allowing a large window that only has a few
  114.                 // pixels showing.
  115.                 if    (
  116.                     (intersectRect.right - intersectRect.left > 4) ||
  117.                     (intersectRect.bottom - intersectRect.top > 4)
  118.                     )
  119.                 {
  120.                     foundDevice = aDevice;
  121.                     foundDeviceRect = aDeviceRect;
  122.                     foundArea = area;
  123.                 }
  124.             }
  125.         }
  126.     }
  127.  
  128.     /* OK, we have now travelled through all the devices, and 'foundDevice' */
  129.     /* will have the best device to use, or the main device if there were    */
  130.     /* no intersecting screens at all.. Make sure it fits on the screen        */
  131.  
  132.     /* If there is not enough area showing, then move the window to better    */
  133.     /* position on 'foundDevice' (width<40> X height<40> pixels).            */
  134.     /* Also do this if the top of the window (minus 18 for the title bar)    */
  135.     /* extends above the top of the window (user can't get ahold of it.)    */
  136.     if ( (foundArea < 40*40) || ((aGlobalRect->top-18) < foundDeviceRect.top) )
  137.     {
  138.         /* offset its upper left corner a little from top of screen */
  139.         aDeviceRect = foundDeviceRect;
  140.         OffsetRect(&aDeviceRect, 4, 18+4);
  141.  
  142.         /* figure out what its lower left corner would be */
  143.         aDeviceRect.right = aDeviceRect.left + (aGlobalRect->right - aGlobalRect->left);
  144.         aDeviceRect.bottom = aDeviceRect.top + (aGlobalRect->bottom - aGlobalRect->top);
  145.  
  146.         /* Return this rect as the one to use */
  147.         *aGlobalRect = aDeviceRect;
  148.     }
  149.  
  150.     /* If rect bottom/right sides are still off the screen, inset them to fit */
  151.     if    (aGlobalRect->right > foundDeviceRect.right)
  152.         aGlobalRect->right = foundDeviceRect.right-4;
  153.     if    (aGlobalRect->bottom > foundDeviceRect.bottom)
  154.         aGlobalRect->bottom = foundDeviceRect.bottom-4;
  155.  
  156. } // ForceRectOnScreen
  157.  
  158.  
  159. // ==============================================
  160. GDHandle GetClosestGDevice(Rect * sourceRectp)
  161. {
  162.     GDHandle    theGDevice;
  163.  
  164.     // find max device this rect intersects
  165.     theGDevice = GetMaxDevice(sourceRectp);
  166.     if (theGDevice == NULL)
  167.     {    // didn't work for some reason, get the regular screen
  168.         theGDevice = GetMainDevice();
  169.     }
  170.  
  171.     return theGDevice;
  172.  
  173. } // GetClosestGDevice
  174.  
  175.  
  176. // ==============================================
  177. void GetMaxGrowRect(WindowPtr wind2Grow, Rect * growRectp)
  178. {
  179.     Rect         rw, rs;
  180.     GDHandle    theGDevice;
  181.  
  182.     // find true/global window pos.
  183.     GetGlobalWindowRect(wind2Grow, &rw);
  184.     // make a teeny rect at the mouse pos, so we can
  185.     // find the GDevice at this point
  186.     rs = rw;
  187.     rs.left = rs.right-1;
  188.     rs.top = rs.bottom-1;
  189.     theGDevice = GetClosestGDevice(&rs);
  190.     // now find the rect bounds of the screen that the grow box is on
  191.     rs = (**theGDevice).gdRect;
  192.     // set max size allowed (upper corner of window to bottom corner of screen)
  193.     // this allows the window to grow just to the bottom corner of the screen
  194.     rw.right    = rs.right - rw.left - 4;
  195.     rw.bottom    = rs.bottom - rw.top - 4;
  196.     // set minimum size allowed
  197.     rw.left        = 40;
  198.     rw.top        = 40;
  199.     // let caller know what we finally decided on
  200.     *growRectp    = rw;
  201. } // GetMaxGrowRect
  202.  
  203.  
  204. // ==============================================
  205. void CenterWindInRect(WindowPtr    wind2Center, Rect outerRect)
  206. {
  207.     short    x, y;
  208.     Rect    windRect;
  209.  
  210.     // figure center of outer rect
  211.     x = (outerRect.left + outerRect.right)  >> 1;
  212.     y = (outerRect.top  + outerRect.bottom) >> 1;
  213.  
  214.     // figure out window's rect
  215.     GetGlobalWindowRect(wind2Center, &windRect);
  216.  
  217.     // now center window around x,y (offset by half window size)
  218.     x = x - ((windRect.right - windRect.left) >> 1);
  219.     y = y - ((windRect.bottom - windRect.top) >> 1);
  220.     MoveWindow(wind2Center, x, y, true);
  221.  
  222. } // CenterWindInRect
  223.  
  224.  
  225. // ==============================================
  226. void PositionWindow(WindowPtr wind2Position, WindCentering_t doCentering, WindPositioning_t whereToShow, WindowPtr passedWindow)
  227. {
  228.     Point        upperCorner;
  229.     Rect        mainRect;
  230.     Rect        windRect;
  231.     Rect        deviceRect;
  232.     Rect        maxDragBounds;
  233.     GDHandle    theGDevice;
  234.  
  235.     if (wind2Position == NULL)
  236.         return;
  237.  
  238.     // Set up bounds for all devices
  239.     SetRect(&maxDragBounds, -32000, -32000, 32000, 32000);
  240.  
  241.     // Find main device bounds
  242.     theGDevice = GetMainDevice();
  243.     mainRect = (**theGDevice).gdRect;
  244.  
  245.     // find the device rectangle to show window on
  246.     switch (whereToShow)
  247.     {
  248.         case eSameAsPassedWindow:
  249.             if (passedWindow)
  250.             {
  251.                 // where's the passed window
  252.                 GetGlobalWindowRect(passedWindow, &windRect);
  253.                 theGDevice = GetClosestGDevice(&windRect);
  254.                 deviceRect = (**theGDevice).gdRect;
  255.                 break;
  256.             }
  257.             // otherwise fall through to main device
  258.  
  259.         case eMainDevice:
  260.             deviceRect = mainRect;
  261.             break;
  262.  
  263.         case eDeepestDevice:
  264.             theGDevice = GetMaxDevice(&maxDragBounds);
  265.             deviceRect = (**theGDevice).gdRect;
  266.             break;
  267.     } // switch
  268.  
  269.     // See if its the main screen.  If so, take menu bar into account!
  270.     if ( (**theGDevice).gdFlags & (1<<mainScreen) )
  271.         deviceRect.top += GetMBarHeight();
  272.  
  273.     // if centering, center on screen using that rect
  274.     // otherwise put in relatively same spot on screen
  275.     if (doCentering == ewcDoCentering)
  276.         CenterWindInRect(wind2Position, deviceRect);
  277.     else
  278.     {
  279.         // where's the window, relative to main screen
  280.         GetGlobalWindowRect(wind2Position, &windRect);
  281.         // find relative spot on new device
  282.         upperCorner.h = windRect.left;
  283.         upperCorner.v = windRect.top;
  284.         // now relative to new screen
  285.         upperCorner.h = upperCorner.h + deviceRect.left;
  286.         upperCorner.v = upperCorner.v + deviceRect.top;
  287.         // move it there
  288.         MoveWindow(wind2Position, upperCorner.h, upperCorner.v, true);
  289.     }
  290. } // PositionWindow
  291.