home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / Scroll.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  21.8 KB  |  790 lines  |  [TEXT/KAHL]

  1. /* Scroll.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "Scroll.h"
  25. #include "Screen.h"
  26. #include "Memory.h"
  27.  
  28.  
  29. #define SCROLLDELAY (0.1)
  30.  
  31.  
  32. struct ScrollRec
  33.     {
  34.         long                        Total;
  35.         long                        Current;
  36.         OrdType                    X;
  37.         OrdType                    Y;
  38.         OrdType                    Length;
  39.         ScrollBarType        Direction;
  40.         MyBoolean                Enabled;
  41.         WinType*                Window;
  42.     };
  43.  
  44.  
  45. static unsigned char        RawUpArrow[] =
  46.     {
  47.         0xFF,0xFF,0x80,0x01,0x81,0x81,0x82,0x41,0x84,0x21,0x88,0x11,0x90,0x09,0x9C,0x39,
  48.         0x84,0x21,0x84,0x21,0x84,0x21,0x84,0x21,0x87,0xE1,0x80,0x01,0x80,0x01,0xFF,0xFF
  49.     };
  50.  
  51. static unsigned char        RawDownArrow[] =
  52.     {
  53.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x87,0xE1,0x84,0x21,0x84,0x21,0x84,0x21,0x84,0x21,
  54.         0x9C,0x39,0x90,0x09,0x88,0x11,0x84,0x21,0x82,0x41,0x81,0x81,0x80,0x01,0xFF,0xFF
  55.     };
  56.  
  57. static unsigned char        RawRightArrow[] =
  58.     {
  59.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x80,0xC1,0x80,0xA1,0x9F,0x91,0x90,0x09,0x90,0x05,
  60.         0x90,0x05,0x90,0x09,0x9F,0x91,0x80,0xA1,0x80,0xC1,0x80,0x01,0x80,0x01,0xFF,0xFF
  61.     };
  62.  
  63. static unsigned char        RawLeftArrow[] =
  64.     {
  65.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x83,0x01,0x85,0x01,0x89,0xF9,0x90,0x09,0xA0,0x09,
  66.         0xA0,0x09,0x90,0x09,0x89,0xF9,0x85,0x01,0x83,0x01,0x80,0x01,0x80,0x01,0xFF,0xFF
  67.     };
  68.  
  69. static unsigned char        RawUpArrowHilited[] =
  70.     {
  71.         0xFF,0xFF,0x80,0x01,0x81,0x81,0x83,0xC1,0x87,0xE1,0x8F,0xF1,0x9F,0xF9,0x9F,0xF9,
  72.         0x87,0xE1,0x87,0xE1,0x87,0xE1,0x87,0xE1,0x87,0xE1,0x80,0x01,0x80,0x01,0xFF,0xFF
  73.     };
  74.  
  75. static unsigned char        RawDownArrowHilited[] =
  76.     {
  77.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x87,0xE1,0x87,0xE1,0x87,0xE1,0x87,0xE1,0x87,0xE1,
  78.         0x9F,0xF9,0x9F,0xF9,0x8F,0xF1,0x87,0xE1,0x83,0xC1,0x81,0x81,0x80,0x01,0xFF,0xFF
  79.     };
  80.  
  81. static unsigned char        RawRightArrowHilited[] =
  82.     {
  83.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x80,0xC1,0x80,0xE1,0x9F,0xF1,0x9F,0xF9,0x9F,0xFD,
  84.         0x9F,0xFD,0x9F,0xF9,0x9F,0xF1,0x80,0xE1,0x80,0xC1,0x80,0x01,0x80,0x01,0xFF,0xFF
  85.     };
  86.  
  87. static unsigned char        RawLeftArrowHilited[] =
  88.     {
  89.         0xFF,0xFF,0x80,0x01,0x80,0x01,0x83,0x01,0x87,0x01,0x8F,0xF9,0x9F,0xF9,0xBF,0xF9,
  90.         0xBF,0xF9,0x9F,0xF9,0x8F,0xF9,0x87,0x01,0x83,0x01,0x80,0x01,0x80,0x01,0xFF,0xFF
  91.     };
  92.  
  93. static long                    ArrowReferenceCount = 0;
  94.  
  95. static Bitmap*            LeftArrow = NIL;
  96. static Bitmap*            RightArrow = NIL;
  97. static Bitmap*            UpArrow = NIL;
  98. static Bitmap*            DownArrow = NIL;
  99. static Bitmap*            LeftArrowHilited = NIL;
  100. static Bitmap*            RightArrowHilited = NIL;
  101. static Bitmap*            UpArrowHilited = NIL;
  102. static Bitmap*            DownArrowHilited = NIL;
  103.  
  104.  
  105. /* create a new scroll bar, returning a Ptr to the private data structure. */
  106. /* Length is the total number of pixels long the scroll bar is */
  107. /* The scrollbar is initially in a DISABLED state. */
  108. ScrollRec*            NewScrollBar(WinType* TheWindow, ScrollBarType Kind,
  109.                                     OrdType X, OrdType Y, OrdType Length)
  110.     {
  111.         ScrollRec*            Temp;
  112.  
  113.         if (ArrowReferenceCount == 0)
  114.             {
  115.                 LeftArrow = MakeBitmap(RawLeftArrow,16,16,2);
  116.                 if (LeftArrow == NIL)
  117.                     {
  118.                      FailurePoint1:
  119.                         return NIL;
  120.                     }
  121.                 RightArrow = MakeBitmap(RawRightArrow,16,16,2);
  122.                 if (RightArrow == NIL)
  123.                     {
  124.                      FailurePoint2:
  125.                         DisposeBitmap(LeftArrow);
  126.                         goto FailurePoint1;
  127.                     }
  128.                 UpArrow = MakeBitmap(RawUpArrow,16,16,2);
  129.                 if (UpArrow == NIL)
  130.                     {
  131.                      FailurePoint3:
  132.                         DisposeBitmap(RightArrow);
  133.                         goto FailurePoint2;
  134.                     }
  135.                 DownArrow = MakeBitmap(RawDownArrow,16,16,2);
  136.                 if (DownArrow == NIL)
  137.                     {
  138.                      FailurePoint4:
  139.                         DisposeBitmap(UpArrow);
  140.                         goto FailurePoint3;
  141.                     }
  142.                 LeftArrowHilited = MakeBitmap(RawLeftArrowHilited,16,16,2);
  143.                 if (LeftArrowHilited == NIL)
  144.                     {
  145.                      FailurePoint5:
  146.                         DisposeBitmap(DownArrow);
  147.                         goto FailurePoint4;
  148.                     }
  149.                 RightArrowHilited = MakeBitmap(RawRightArrowHilited,16,16,2);
  150.                 if (RightArrowHilited == NIL)
  151.                     {
  152.                      FailurePoint6:
  153.                         DisposeBitmap(LeftArrowHilited);
  154.                         goto FailurePoint5;
  155.                     }
  156.                 UpArrowHilited = MakeBitmap(RawUpArrowHilited,16,16,2);
  157.                 if (UpArrowHilited == NIL)
  158.                     {
  159.                      FailurePoint7:
  160.                         DisposeBitmap(RightArrowHilited);
  161.                         goto FailurePoint6;
  162.                     }
  163.                 DownArrowHilited = MakeBitmap(RawDownArrowHilited,16,16,2);
  164.                 if (DownArrowHilited == NIL)
  165.                     {
  166.                      FailurePoint8:
  167.                         DisposeBitmap(UpArrowHilited);
  168.                         goto FailurePoint7;
  169.                     }
  170.             }
  171.         ArrowReferenceCount += 1;
  172.         Temp = (ScrollRec*)AllocPtrCanFail(sizeof(ScrollRec),"ScrollRec");
  173.         if (Temp == NIL)
  174.             {
  175.                 ArrowReferenceCount -= 1;
  176.                 if (ArrowReferenceCount == 0)
  177.                     {
  178.                         DisposeBitmap(DownArrowHilited);
  179.                         goto FailurePoint8;
  180.                     }
  181.                  else
  182.                     {
  183.                         return NIL;
  184.                     }
  185.             }
  186.         Temp->Total = 1;
  187.         Temp->Current = 0;
  188.         Temp->X = X;
  189.         Temp->Y = Y;
  190.         Temp->Length = Length;
  191.         Temp->Direction = Kind;
  192.         Temp->Enabled = False;
  193.         Temp->Window = TheWindow;
  194.         return Temp;
  195.     }
  196.  
  197.  
  198. /* dispose the scroll bar record allocated by NewScrollBar */
  199. void                        DisposeScrollBar(ScrollRec* TheBar)
  200.     {
  201.         ArrowReferenceCount -= 1;
  202.         ERROR(ArrowReferenceCount < 0,PRERR(ForceAbort,
  203.             "DisposeScrollBar: negative reference count for scrollbar icons"));
  204.         if (ArrowReferenceCount == 0)
  205.             {
  206.                 DisposeBitmap(LeftArrow);
  207.                 DisposeBitmap(RightArrow);
  208.                 DisposeBitmap(UpArrow);
  209.                 DisposeBitmap(DownArrow);
  210.                 DisposeBitmap(LeftArrowHilited);
  211.                 DisposeBitmap(RightArrowHilited);
  212.                 DisposeBitmap(UpArrowHilited);
  213.                 DisposeBitmap(DownArrowHilited);
  214.             }
  215.         ReleasePtr((char*)TheBar);
  216.     }
  217.  
  218.  
  219. /* get the position on the screen of the scroll bar */
  220. OrdType                    GetScrollXPosition(ScrollRec* TheBar)
  221.     {
  222.         CheckPtrExistence(TheBar);
  223.         return TheBar->X;
  224.     }
  225.  
  226.  
  227. /* get the position on the screen of the scroll bar */
  228. OrdType                    GetScrollYPosition(ScrollRec* TheBar)
  229.     {
  230.         CheckPtrExistence(TheBar);
  231.         return TheBar->Y;
  232.     }
  233.  
  234.  
  235. /* get the position on the screen of the scroll bar */
  236. OrdType                    GetScrollLength(ScrollRec* TheBar)
  237.     {
  238.         CheckPtrExistence(TheBar);
  239.         return TheBar->Length;
  240.     }
  241.  
  242.  
  243. /* set the position of the scroll bar on the screen */
  244. void                        SetScrollLocation(ScrollRec* TheBar, OrdType NewX, OrdType NewY,
  245.                                     OrdType NewLength)
  246.     {
  247.         CheckPtrExistence(TheBar);
  248.         TheBar->X = NewX;
  249.         TheBar->Y = NewY;
  250.         TheBar->Length = NewLength;
  251.     }
  252.  
  253.  
  254. /* get the maximum number of indices the scroll bar can have */
  255. long                        GetMaxScrollIndex(ScrollRec* TheBar)
  256.     {
  257.         CheckPtrExistence(TheBar);
  258.         return TheBar->Total;
  259.     }
  260.  
  261.  
  262. /* get the current index for the scroll bar's position */
  263. long                        GetCurrentScrollIndex(ScrollRec* TheBar)
  264.     {
  265.         CheckPtrExistence(TheBar);
  266.         return TheBar->Current;
  267.     }
  268.  
  269.  
  270. /* set the maximum number of indices the scroll bar can have */
  271. void                        SetMaxScrollIndex(ScrollRec* TheBar, long NewMaxScrollIndex)
  272.     {
  273.         CheckPtrExistence(TheBar);
  274.         TheBar->Total = NewMaxScrollIndex;
  275.     }
  276.  
  277.  
  278. /* set the current index; NewIndex may be out of range */
  279. void                        SetScrollIndex(ScrollRec* TheBar, long NewIndex)
  280.     {
  281.         CheckPtrExistence(TheBar);
  282.         TheBar->Current = NewIndex;
  283.     }
  284.  
  285.  
  286. /* enable or disable the scroll bars (for inactive windows) */
  287. void                        EnableScrollBar(ScrollRec* TheBar)
  288.     {
  289.         CheckPtrExistence(TheBar);
  290.         TheBar->Enabled = True;
  291.         RedrawScrollBar(TheBar);
  292.     }
  293.  
  294.  
  295. /* enable or disable the scroll bars (for inactive windows) */
  296. void                        DisableScrollBar(ScrollRec* TheBar)
  297.     {
  298.         CheckPtrExistence(TheBar);
  299.         TheBar->Enabled = False;
  300.         RedrawScrollBar(TheBar);
  301.     }
  302.  
  303.  
  304. /* internal routine for drawing scrollbar */
  305. static void            InternalRedrawScrollBar(ScrollRec* TheBar,
  306.                                     MyBoolean MinusArrowHit, MyBoolean PlusArrowHit)
  307.     {
  308.         long                        Maximum;
  309.         long                        Position;
  310.         OrdType                    StartEdge;
  311.         OrdType                    EndEdge;
  312.         OrdType                    OtherCoordinate;
  313.         Bitmap*                    Arrow;
  314.         WinType*                Window;
  315.         ScrollBarType        Direction;
  316.         OrdType                    DohickyStartEdge;
  317.  
  318.         CheckPtrExistence(TheBar);
  319.         Maximum = TheBar->Total;
  320.         Position = TheBar->Current;
  321.         Window = TheBar->Window;
  322.         Direction = TheBar->Direction;
  323.         switch (Direction)
  324.             {
  325.                 case eVScrollBar:
  326.                     StartEdge = TheBar->Y;
  327.                     OtherCoordinate = TheBar->X;
  328.                     SetClipRect(Window,OtherCoordinate,StartEdge,OtherCoordinate + 16,
  329.                         StartEdge + TheBar->Length + 1);
  330.                     break;
  331.                 case eHScrollBar:
  332.                     StartEdge = TheBar->X;
  333.                     OtherCoordinate = TheBar->Y;
  334.                     SetClipRect(Window,StartEdge,OtherCoordinate,
  335.                         StartEdge + TheBar->Length + 1,OtherCoordinate + 16);
  336.                     break;
  337.             }
  338.         EndEdge = StartEdge + TheBar->Length;
  339.         if ((EndEdge - StartEdge < 16 + 16 + 16) || !TheBar->Enabled)
  340.             {
  341.                 /* either the scrollbar is too small to fit any pictures on */
  342.                 /* or it has been disabled (window deactivated), so we only draw */
  343.                 /* empty rectangles around the outline */
  344.                 switch (Direction)
  345.                     {
  346.                         case eVScrollBar:
  347.                             DrawBoxErase(Window,OtherCoordinate + 1,StartEdge + 1,
  348.                                 16 - 2,EndEdge - StartEdge - 2);
  349.                             DrawBoxFrame(Window,eBlack,OtherCoordinate,StartEdge,
  350.                                 16,EndEdge - StartEdge);
  351.                             break;
  352.                         case eHScrollBar:
  353.                             DrawBoxErase(Window,StartEdge + 1,OtherCoordinate + 1,
  354.                                 EndEdge - StartEdge - 2,16 - 2);
  355.                             DrawBoxFrame(Window,eBlack,StartEdge,OtherCoordinate,
  356.                                 EndEdge - StartEdge,16);
  357.                             break;
  358.                     }
  359.                 return;
  360.             }
  361.         switch (Direction)
  362.             {
  363.                 case eVScrollBar:
  364.                     if (MinusArrowHit)
  365.                         {
  366.                             Arrow = UpArrowHilited;
  367.                         }
  368.                      else
  369.                         {
  370.                             Arrow = UpArrow;
  371.                         }
  372.                     DrawBitmap(Window,OtherCoordinate,StartEdge,Arrow);
  373.                     if (PlusArrowHit)
  374.                         {
  375.                             Arrow = DownArrowHilited;
  376.                         }
  377.                      else
  378.                         {
  379.                             Arrow = DownArrow;
  380.                         }
  381.                     DrawBitmap(Window,OtherCoordinate,EndEdge - 16,Arrow);
  382.                     break;
  383.                 case eHScrollBar:
  384.                     if (MinusArrowHit)
  385.                         {
  386.                             Arrow = LeftArrowHilited;
  387.                         }
  388.                      else
  389.                         {
  390.                             Arrow = LeftArrow;
  391.                         }
  392.                     DrawBitmap(Window,StartEdge,OtherCoordinate,Arrow);
  393.                     if (PlusArrowHit)
  394.                         {
  395.                             Arrow = RightArrowHilited;
  396.                         }
  397.                      else
  398.                         {
  399.                             Arrow = RightArrow;
  400.                         }
  401.                     DrawBitmap(Window,EndEdge - 16,OtherCoordinate,Arrow);
  402.                     break;
  403.             }
  404.         StartEdge += 16;
  405.         EndEdge -= 16;
  406.         if (Maximum > 1)
  407.             {
  408.                 DohickyStartEdge = (((EndEdge - 16 - StartEdge)
  409.                     * Position) / (Maximum - 1)) + StartEdge;
  410.                 if (DohickyStartEdge < StartEdge)
  411.                     {
  412.                         DohickyStartEdge = StartEdge;
  413.                     }
  414.                 if (DohickyStartEdge > EndEdge - 16)
  415.                     {
  416.                         DohickyStartEdge = EndEdge - 16;
  417.                     }
  418.                 /* draw the dohicky thing */
  419.              RedrawPoint:
  420.                 switch (Direction)
  421.                     {
  422.                         case eVScrollBar:
  423.                             DrawBoxPaint(Window,eLightGrey,OtherCoordinate + 1,StartEdge,
  424.                                 16 - 2,EndEdge - StartEdge);
  425.                             DrawBoxFrame(Window,eBlack,OtherCoordinate,StartEdge - 1,
  426.                                 16,EndEdge - StartEdge + 2);
  427.                             DrawBoxErase(Window,OtherCoordinate + 1,DohickyStartEdge,14,16);
  428.                             DrawBoxFrame(Window,eBlack,OtherCoordinate + 1,DohickyStartEdge,14,16);
  429.                             break;
  430.                         case eHScrollBar:
  431.                             DrawBoxPaint(Window,eLightGrey,StartEdge,OtherCoordinate + 1,
  432.                                 EndEdge - StartEdge,16 - 2);
  433.                             DrawBoxFrame(Window,eBlack,StartEdge - 1,OtherCoordinate,
  434.                                 EndEdge - StartEdge + 2,16);
  435.                             DrawBoxErase(Window,DohickyStartEdge + 1,
  436.                                 OtherCoordinate + 2,16 - 2,14 - 2);
  437.                             DrawBoxFrame(Window,eBlack,DohickyStartEdge,OtherCoordinate + 1,16,14);
  438.                             break;
  439.                     }
  440.             }
  441.          else
  442.             {
  443.                 /* Maximum is either negative, 0, or 1. */
  444.                 if (Position < 0)
  445.                     {
  446.                         DohickyStartEdge = StartEdge;
  447.                         goto RedrawPoint;
  448.                     }
  449.                 else if (Position > 0)
  450.                     {
  451.                         DohickyStartEdge = EndEdge - 16;
  452.                         goto RedrawPoint;
  453.                     }
  454.                 else
  455.                     {
  456.                         switch (Direction)
  457.                             {
  458.                                 case eVScrollBar:
  459.                                     DrawBoxErase(Window,OtherCoordinate + 1,StartEdge + 1 - 1,
  460.                                         16 - 2,EndEdge - StartEdge - 2 + 2);
  461.                                     DrawBoxFrame(Window,eBlack,OtherCoordinate,StartEdge - 1,
  462.                                         16,EndEdge - StartEdge + 2);
  463.                                     break;
  464.                                 case eHScrollBar:
  465.                                     DrawBoxErase(Window,StartEdge + 1 - 1,OtherCoordinate + 1,
  466.                                         EndEdge - StartEdge - 2,16 - 2 + 2);
  467.                                     DrawBoxFrame(Window,eBlack,StartEdge - 1,OtherCoordinate,
  468.                                         EndEdge - StartEdge + 2,16);
  469.                                     break;
  470.                             }
  471.                     }
  472.             }
  473.         /* the end! */
  474.     }
  475.  
  476.  
  477. /* this is so that we don't redraw the bar incorrectly.  What might happen is that */
  478. /* the scrollbar gets redrawn from the scrollhook callback.  That would draw it */
  479. /* normally, which would turn off any hilighting of the arrows.  So we use this */
  480. /* variable to prevent that from happening.  We can get away with this because only */
  481. /* one scrollbar can be scrolling at any time. */
  482. static ScrollRec*                TheOneThatsScrolling = NIL;
  483.  
  484.  
  485. /* redraw the scroll bar normally */
  486. void                        RedrawScrollBar(ScrollRec* TheBar)
  487.     {
  488.         CheckPtrExistence(TheBar);
  489.         if (TheOneThatsScrolling != TheBar)
  490.             {
  491.                 InternalRedrawScrollBar(TheBar,False,False);
  492.             }
  493.     }
  494.  
  495.  
  496. /* internal states for tracking what part of the scrollbar was clicked in */
  497. typedef enum
  498.     {
  499.         eNoButton EXECUTE(= -134),
  500.         eMinusButton,
  501.         ePlusButton,
  502.         ePageMinus,
  503.         ePagePlus,
  504.         eDohickyBox
  505.     } States;
  506.  
  507. /* states for throttle control */
  508. typedef enum
  509.     {
  510.         eWaitThrottle1 EXECUTE(= -552),
  511.         eWaitThrottle2,
  512.         eNoThrottle
  513.     } Throttles;
  514.  
  515. /* call this when the mouse goes down in the scroll bar, providing the */
  516. /* information which came with the mouse down event.  ScrollHook is a routine */
  517. /* which actually performs the scrolling: */
  518. /* If How == eScrollToPosition, then scroll and redraw the image at the index */
  519. /* represented by Parameter */
  520. /* If How == eScrollPageMinus or eScrollPagePlus, then scroll as much of the */
  521. /* image is necessary to scroll a page worth */
  522. void                        ScrollHitProc(ScrollRec* TheBar, ModifierFlags Modifiers,
  523.                                     OrdType X, OrdType Y, void* Refcon,
  524.                                     void (*ScrollHook)(long Parameter, ScrollType How, void* Refcon))
  525.     {
  526.         long                        Maximum;
  527.         long                        Position;
  528.         OrdType                    StartEdge;
  529.         OrdType                    EndEdge;
  530.         OrdType                    OtherCoordinate;
  531.         WinType*                Window;
  532.         ScrollBarType        Direction;
  533.         OrdType                    DohickyStartEdge;
  534.         OrdType                    MouseInlineIndex;
  535.         OrdType                    MouseOtherIndex;
  536.         States                    State;
  537.         MyBoolean                DohickyEnabled;
  538.         Throttles                ThrottleState;
  539.  
  540.         State = eNoButton;
  541.         CheckPtrExistence(TheBar);
  542.         TheOneThatsScrolling = TheBar; /* prevent them from redrawing it; only we can */
  543.         ThrottleState = eWaitThrottle1;
  544.      LoopPoint:
  545.         if ((ThrottleState != eNoThrottle) && ((State == eMinusButton)
  546.             || (State == ePlusButton) || (State == ePageMinus) || (State == ePagePlus)))
  547.             {
  548.                 double                    When;
  549.  
  550.                 /* the first time through the loop, delay a bit */
  551.                 switch (ThrottleState)
  552.                     {
  553.                         default:
  554.                             EXECUTE(PRERR(AllowResume,"ScrollHitProc:  unknown throttle state"));
  555.                             break;
  556.                         case eWaitThrottle1:
  557.                             ThrottleState = eWaitThrottle2;
  558.                             break;
  559.                         case eWaitThrottle2:
  560.                             ThrottleState = eNoThrottle;
  561.                             When = ReadTimer();
  562.                             while (TimerDifference(ReadTimer(),When) < SCROLLDELAY)
  563.                                 {
  564.                                     if (GetAnEvent(&X,&Y,&Modifiers,NIL,NIL,NIL) == eMouseUp)
  565.                                         {
  566.                                             goto DoneScrollingExitPoint;
  567.                                         }
  568.                                 }
  569.                             break;
  570.                         case eNoThrottle:
  571.                             break;
  572.                     }
  573.             }
  574.         Maximum = TheBar->Total;
  575.         Position = TheBar->Current;
  576.         Window = TheBar->Window;
  577.         Direction = TheBar->Direction;
  578.         switch (Direction)
  579.             {
  580.                 case eVScrollBar:
  581.                     StartEdge = TheBar->Y;
  582.                     OtherCoordinate = TheBar->X;
  583.                     break;
  584.                 case eHScrollBar:
  585.                     StartEdge = TheBar->X;
  586.                     OtherCoordinate = TheBar->Y;
  587.                     break;
  588.             }
  589.         EndEdge = StartEdge + TheBar->Length;
  590.         switch (Direction)
  591.             {
  592.                 case eVScrollBar:
  593.                     MouseInlineIndex = Y;
  594.                     MouseOtherIndex = X;
  595.                     break;
  596.                 case eHScrollBar:
  597.                     MouseInlineIndex = X;
  598.                     MouseOtherIndex = Y;
  599.                     break;
  600.             }
  601.         if (Maximum != 1)
  602.             {
  603.                 DohickyStartEdge = ((((EndEdge - 16) - 16 - (StartEdge + 16))
  604.                     * Position) / (Maximum - 1)) + (StartEdge + 16);
  605.                 if (DohickyStartEdge < (StartEdge + 16))
  606.                     {
  607.                         DohickyStartEdge = (StartEdge + 16);
  608.                     }
  609.                 if (DohickyStartEdge > (EndEdge - 16) - 16)
  610.                     {
  611.                         DohickyStartEdge = (EndEdge - 16) - 16;
  612.                     }
  613.                 DohickyEnabled = True;
  614.             }
  615.          else
  616.             {
  617.                 DohickyEnabled = False;
  618.             }
  619.  
  620.         switch (State)
  621.             {
  622.                 case eMinusButton:
  623.                     /* only scroll if we are in the button */
  624.                     if ((MouseInlineIndex >= StartEdge)
  625.                         && (MouseInlineIndex < StartEdge + 16)
  626.                         && (MouseOtherIndex >= OtherCoordinate)
  627.                         && (MouseOtherIndex < OtherCoordinate + 16))
  628.                         {
  629.                             (*ScrollHook)(0,eScrollLineMinus,Refcon);
  630.                             InternalRedrawScrollBar(TheBar,True,False);
  631.                         }
  632.                      else
  633.                         {
  634.                             InternalRedrawScrollBar(TheBar,False,False);
  635.                         }
  636.                     break;
  637.                 case ePlusButton:
  638.                     if ((MouseInlineIndex < EndEdge)
  639.                         && (MouseInlineIndex >= EndEdge - 16)
  640.                         && (MouseOtherIndex >= OtherCoordinate)
  641.                         && (MouseOtherIndex < OtherCoordinate + 16))
  642.                         {
  643.                             /* hit in plus button */
  644.                             (*ScrollHook)(0,eScrollLinePlus,Refcon);
  645.                             InternalRedrawScrollBar(TheBar,False,True);
  646.                         }
  647.                      else
  648.                         {
  649.                             InternalRedrawScrollBar(TheBar,False,False);
  650.                         }
  651.                     break;
  652.                 case ePageMinus:
  653.                     if ((MouseInlineIndex >= StartEdge)
  654.                         && (MouseInlineIndex < DohickyStartEdge)
  655.                         && (MouseOtherIndex >= OtherCoordinate)
  656.                         && (MouseOtherIndex < OtherCoordinate + 16))
  657.                         {
  658.                             (*ScrollHook)(0,eScrollPageMinus,Refcon);
  659.                             InternalRedrawScrollBar(TheBar,False,False);
  660.                         }
  661.                     break;
  662.                 case ePagePlus:
  663.                     if ((MouseInlineIndex < EndEdge)
  664.                         && (MouseInlineIndex >= DohickyStartEdge + 16)
  665.                         && (MouseOtherIndex >= OtherCoordinate)
  666.                         && (MouseOtherIndex < OtherCoordinate + 16))
  667.                         {
  668.                             (*ScrollHook)(0,eScrollPagePlus,Refcon);
  669.                             InternalRedrawScrollBar(TheBar,False,False);
  670.                         }
  671.                     break;
  672.                 case eDohickyBox:
  673.                     if (DohickyEnabled)
  674.                         {
  675.                             Position = (((((MouseInlineIndex - 8)
  676.                                 - (StartEdge + 16)) * (Maximum - 1))
  677.                                 + (((EndEdge - 16) - (StartEdge + 16) - 16) / 2))
  678.                                 / ((EndEdge - 16) - (StartEdge + 16) - 16));
  679.                             if (Position < 0)
  680.                                 {
  681.                                     Position = 0;
  682.                                 }
  683.                             if (Position > Maximum - 1)
  684.                                 {
  685.                                     Position = Maximum - 1;
  686.                                 }
  687.                             if (Position != TheBar->Current)
  688.                                 {
  689.                                     (*ScrollHook)(Position,eScrollToPosition,Refcon);
  690.                                     InternalRedrawScrollBar(TheBar,False,False);
  691.                                 }
  692.                         }
  693.                     break;
  694.                 case eNoButton:
  695.                     /* we don't know where we are, so we hit test to find where we start */
  696.                     if ((MouseInlineIndex >= StartEdge)
  697.                         && (MouseInlineIndex < StartEdge + 16)
  698.                         && (MouseOtherIndex >= OtherCoordinate)
  699.                         && (MouseOtherIndex < OtherCoordinate + 16))
  700.                         {
  701.                             State = eMinusButton;
  702.                             goto LoopPoint;
  703.                         }
  704.                     if ((MouseInlineIndex < EndEdge)
  705.                         && (MouseInlineIndex >= EndEdge - 16)
  706.                         && (MouseOtherIndex >= OtherCoordinate)
  707.                         && (MouseOtherIndex < OtherCoordinate + 16))
  708.                         {
  709.                             State = ePlusButton;
  710.                             goto LoopPoint;
  711.                         }
  712.                     /* wasn't in a button, so it's somewhere in the grey area between them */
  713.                     EndEdge -= 16;
  714.                     StartEdge += 16;
  715.                     if (DohickyEnabled)
  716.                         {
  717.                          DohickyPoint:
  718.                             if ((MouseInlineIndex >= StartEdge)
  719.                                 && (MouseInlineIndex < DohickyStartEdge)
  720.                                 && (MouseOtherIndex >= OtherCoordinate)
  721.                                 && (MouseOtherIndex < OtherCoordinate + 16))
  722.                                 {
  723.                                     State = ePageMinus;
  724.                                     goto LoopPoint;
  725.                                 }
  726.                             if ((MouseInlineIndex < EndEdge)
  727.                                 && (MouseInlineIndex >= DohickyStartEdge + 16)
  728.                                 && (MouseOtherIndex >= OtherCoordinate)
  729.                                 && (MouseOtherIndex < OtherCoordinate + 16))
  730.                                 {
  731.                                     State = ePagePlus;
  732.                                     goto LoopPoint;
  733.                                 }
  734.                             if ((MouseInlineIndex >= DohickyStartEdge)
  735.                                 && (MouseInlineIndex < DohickyStartEdge + 16)
  736.                                 && (MouseOtherIndex >= OtherCoordinate)
  737.                                 && (MouseOtherIndex < OtherCoordinate + 16))
  738.                                 {
  739.                                     State = eDohickyBox;
  740.                                     goto LoopPoint;
  741.                                 }
  742.                         }
  743.                      else
  744.                         {
  745.                             /* no dohicky */
  746.                             if (Position < 0)
  747.                                 {
  748.                                     DohickyStartEdge = StartEdge;
  749.                                     MouseInlineIndex = DohickyStartEdge + 16;
  750.                                     goto DohickyPoint;
  751.                                 }
  752.                             else if (Position > 0)
  753.                                 {
  754.                                     DohickyStartEdge = EndEdge - 16;
  755.                                     MouseInlineIndex = DohickyStartEdge - 1;
  756.                                     goto DohickyPoint;
  757.                                 }
  758.                         }
  759.             }
  760.  
  761.         /* reading new mouse position */
  762.         if (GetAnEvent(&X,&Y,&Modifiers,NIL,NIL,NIL) == eMouseUp)
  763.             {
  764.              DoneScrollingExitPoint:
  765.                 InternalRedrawScrollBar(TheBar,False,False);
  766.                 TheOneThatsScrolling = NIL; /* they can redraw again */
  767.                 return; /* all done */
  768.             }
  769.         GetMousePosition(&X,&Y);
  770.         goto LoopPoint;
  771.     }
  772.  
  773.  
  774. /* see if the position is in the scrollbar box */
  775. MyBoolean                ScrollHitTest(ScrollRec* TheBar, OrdType X, OrdType Y)
  776.     {
  777.         switch (TheBar->Direction)
  778.             {
  779.                 default:
  780.                     EXECUTE(PRERR(ForceAbort,"ScrollHitTest:  bad internal scrollbar type"));
  781.                     break;
  782.                 case eVScrollBar:
  783.                     return (X >= TheBar->X) && (Y >= TheBar->Y)
  784.                         && (X < TheBar->X + 16) && (Y < TheBar->Y + TheBar->Length);
  785.                 case eHScrollBar:
  786.                     return (X >= TheBar->X) && (Y >= TheBar->Y)
  787.                         && (X < TheBar->X + TheBar->Length) && (Y < TheBar->Y + 16);
  788.             }
  789.     }
  790.