home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2005 March / Macworld CD March 2005 - Marathon Trilogy.iso / Shareware World / Text Processing / HexEdit Release.sit / HexEdit Release / Project / Source / EditScrollbar.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-10-30  |  10.3 KB  |  362 lines  |  [TEXT/CWIE]

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is Copyright 1993 Jim Bumgardner.
  13.  * 
  14.  * The Initial Developer of the Original Code is Jim Bumgardner
  15.  * Portions created by Lane Roathe are
  16.  * Copyright (C) Copyright © 1996-2002.
  17.  * All Rights Reserved.
  18.  *
  19.  * Modified: $Date: 2002/04/21 18:53:41 $
  20.  * Revision: $Id: EditScrollbar.c,v 1.13 2002/04/21 18:53:41 raving Exp $
  21.  *
  22.  * Contributor(s):
  23.  *        Lane Roathe
  24.  *        Nick Shanks
  25.  *      Brian Bergstrand
  26.  */
  27.  
  28. // 05/10/01 - GAB: MPW environment support
  29. #ifdef __MPW__
  30. #include "MPWIncludes.h"
  31. #endif
  32.  
  33. #include "EditScrollbar.h"
  34. #include "EditRoutines.h"
  35. #include "HexEdit.h" //BB: bring in globals g;
  36.  
  37. static ControlActionUPP _trackActionUPP = NULL;        //LR 1.73 -- properly local, must be NULL ast startup!
  38.  
  39. #define GET_LINE(x) ((x + kBytesPerLine - 1) / kBytesPerLine) 
  40. #define TOTAL_LINES GET_LINE(dWin->fileSize)
  41. #define NON_VIEWABLE_LINES (TOTAL_LINES - dWin->linesPerPage)
  42. #define LIMIT_CALC (NON_VIEWABLE_LINES * kBytesPerLine)
  43.  
  44. #define S_INT16_MAX    0x7FFF    // maximum value to be used in an SInt16
  45.  
  46. /*** Calc Scroll Position ***/
  47. //LR 1.73 -- simplify some code
  48. static long _calcScrollPosition( EditWindowPtr dWin )
  49. {
  50.     long    newPos, h;
  51.     Rect    winRect;
  52.     short    vPos = GetControlValue( dWin->vScrollBar );
  53.     float    numer;
  54.     float    result;
  55.  
  56.     GetWindowPortBounds( dWin->oWin.theWin, &winRect );
  57.     h = winRect.bottom - winRect.top - (kGrowIconSize - 1) - (kHeaderHeight - 1);
  58.  
  59.     if (NON_VIEWABLE_LINES < S_INT16_MAX)
  60.         newPos = vPos * kBytesPerLine;
  61.     else
  62.     {    numer = vPos;
  63.         result = numer / (float)S_INT16_MAX;
  64.         newPos = (long)(result * NON_VIEWABLE_LINES * kBytesPerLine);
  65.         newPos -= newPos % kBytesPerLine;    //LR 180 -- always start at the beginning of a line!
  66.     }
  67.  
  68.     return( newPos );
  69. }
  70.  
  71.  
  72. /*** MY SCROLL ACTION ***/
  73. static pascal void _scrollAction( ControlHandle theControl, short thePart )
  74. {
  75.     long            curPos, newPos;
  76.     short            pageWidth;
  77.     EditWindowPtr    dWin;        //LR 1.73 -- need window info for live scrolling
  78. //1.72    Rect        myRect;
  79.  
  80.     dWin = (EditWindowPtr)GetControlReference( theControl );    //LR 1.73 -- get owning window
  81.  
  82.     curPos = dWin->editOffset;
  83.     newPos = curPos;
  84.  
  85. /*LR 1.72 -- not used!
  86.     GetWindowPortBounds( dWin->oWin.theWin, &myRect );
  87.  
  88.     myRect.right -= kSBarSize-1;
  89.     myRect.bottom -= kSBarSize-1;
  90. */
  91.     pageWidth = (dWin->linesPerPage - 1) * kBytesPerLine;
  92.  
  93.     switch( thePart )
  94.     {
  95.         case kControlUpButtonPart:        newPos = curPos - kBytesPerLine;        break;    // LR: -- UH compliant
  96.         case kControlDownButtonPart:    newPos = curPos + kBytesPerLine;        break;
  97.         case kControlPageUpPart:        newPos = curPos - pageWidth;    break;
  98.         case kControlPageDownPart:        newPos = curPos + pageWidth;    break;
  99.         case kControlIndicatorPart:        newPos = _calcScrollPosition( dWin );    break;    //LR 1.73 -- live scrolling
  100.     }
  101.  
  102.     ScrollToPosition( dWin, newPos );
  103. }
  104.  
  105. /*** SETUP SCROLL BARS ***/
  106. void SetupScrollBars( EditWindowPtr dWin )
  107. {
  108.     Rect    sRect, r;
  109.  
  110.     //LR 1.73 -- setup track action proc if not already done
  111.     if( !_trackActionUPP )
  112.         _trackActionUPP = NewControlActionUPP( _scrollAction );
  113.  
  114.     GetWindowPortBounds( dWin->oWin.theWin, &r );
  115.  
  116.     sRect.left = r.right - ( kSBarSize - 1 );
  117.     sRect.top = r.top + kHeaderHeight;    // NS: move to below header
  118.     sRect.right = r.right + 1;
  119.     sRect.bottom = r.bottom    - kGrowIconSize;
  120.     // BB: detect Appearance manager, and create a live scroll bar if we do
  121.     dWin->vScrollBar = NewControl( dWin->oWin.theWin, &sRect, "\p", true, 0, 0, sRect.bottom - sRect.top, g.useAppearance ? kControlScrollBarLiveProc : scrollBarProc, 1L );
  122.     AdjustScrollBars( dWin->oWin.theWin, 1 );
  123.  
  124.     //LR 1.73 -- save window for callback procedure
  125.     SetControlReference( dWin->vScrollBar, (SInt32)dWin );
  126. }
  127.  
  128. // Adjust scroll bars when they need to be redrawn for some reason.
  129. // resizeFlag is an optimization to avoid extra work when you aren't resizing.
  130.  
  131. /*** ADJUST SCROLL BARS ***/
  132. void AdjustScrollBars( WindowRef theWin, short resizeFlag )
  133. {
  134.     short            h;
  135.     GrafPtr            savePort;
  136.     long            limit;
  137.     Rect            r;
  138.     EditWindowPtr    dWin = (EditWindowPtr) GetWRefCon( theWin );
  139.     short            maxValue;
  140.     unsigned long    curLine;
  141.     short            curValue;
  142.     float            ratio;
  143.     float            numer;
  144.     float            denom;
  145.  
  146.     GetWindowPortBounds( theWin, &r );
  147.  
  148.     GetPort( &savePort );
  149.     
  150.     h = (r.bottom - r.top) - (kGrowIconSize - 1) - (kHeaderHeight - 1);
  151.  
  152.     if( resizeFlag )
  153.     {
  154.         // Adjust Lines Per Page
  155. //LR: 1.7 -fix lpp calculation!        dWin->linesPerPage = ( ( ( r.bottom - kSBarSize ) - ( kHeaderHeight + 1 ) - TopMargin - BotMargin ) / kLineHeight );
  156.         dWin->linesPerPage = (((r.bottom - r.top - (kLineHeight - 1)) + kLineHeight - kHeaderHeight) / kLineHeight);
  157.  
  158.         // Move sliders to new position
  159.         // LR: per Shanks, control below theWin's header
  160.         MoveControl( dWin->vScrollBar, r.right - (kSBarSize - 1), r.top + (kHeaderHeight - 1) );    
  161.  
  162.         // Change their sizes to fit new theWin dimensions
  163.         SizeControl( dWin->vScrollBar, kSBarSize, h );
  164.     }
  165.  
  166.     // Reposition painting if you have resized or scrolled past the legal
  167.     // bounds    Note: this call will usually be followed by an update
  168.     limit = LIMIT_CALC;
  169. //LR 1.72    limit = ((dWin->fileSize + 15) & 0xFFFFFFF0) - (dWin->linesPerPage / kBytesPerLine);
  170.     if( dWin->editOffset > limit )
  171.         dWin->editOffset = limit;
  172.     if( dWin->editOffset < 0 )
  173.         dWin->editOffset = 0;
  174.         
  175.  
  176.     // Set the value of the sliders accordingly
  177.     if( limit > 0 )
  178.     {
  179.         curLine = GET_LINE(dWin->editOffset);
  180.         
  181.         if (NON_VIEWABLE_LINES > S_INT16_MAX)
  182.         {
  183.             numer = curLine;
  184.             denom = NON_VIEWABLE_LINES;
  185.             ratio = numer / denom;
  186.             maxValue = (NON_VIEWABLE_LINES > S_INT16_MAX) ? S_INT16_MAX : NON_VIEWABLE_LINES;
  187.             
  188.             curValue = (ratio * maxValue);
  189.         }
  190.         else
  191.         {
  192.             maxValue = NON_VIEWABLE_LINES;
  193.             curValue = curLine;
  194.         }
  195.         
  196.         SetControlMaximum( dWin->vScrollBar, maxValue);
  197.             
  198. #if !defined(__MC68K__) && !defined(__SC__)        //LR 1.73 -- not available for 68K (won't even link!)
  199.         // BB: Set up proportional scroll bar if we can
  200.         if (SetControlViewSize != (void*)kUnresolvedCFragSymbolAddress)
  201.             SetControlViewSize( dWin->vScrollBar, dWin->linesPerPage);
  202. #endif
  203.         SetControlValue( dWin->vScrollBar, curValue);
  204.     }
  205.     else
  206.     {
  207.         SetControlMaximum( dWin->vScrollBar, 0 );
  208.         SetControlValue( dWin->vScrollBar, 0 );
  209.     }
  210.         
  211.     SetPort( savePort );
  212. }
  213.  
  214. // Intercept Handler for scroll bars
  215. // Returns true if user clicked on scroll bar
  216.  
  217. /*** HANDLE SCROLL BAR CLICK ***/
  218. Boolean MyHandleControlClick( WindowRef window, Point mouseLoc )
  219. {
  220.     short             controlPart;
  221.     ControlRef        control;
  222.     EditWindowPtr    dWin = (EditWindowPtr) GetWRefCon( window );
  223.  
  224.     // NS: v1.6.6, new scrolling code to enable live scrolling on post-Appearance systems
  225.     controlPart = FindControl( mouseLoc, window, &control );
  226.     if( control == nil ) return false;
  227.     
  228.     // scroll the window    -- use old bits for now
  229. /*    if( controlPart == kControlIndicatorPart && !g.useAppearance )    // in thumb (129)
  230.     {
  231.         TrackControl( control, mouseLoc, nil );
  232.         ::DrawBody( window );
  233.     }
  234.     else                                        // in arrows or page up/down
  235.     {
  236.         scrollAction = NewControlActionProc( FileScrollAction );
  237.         TrackControl( control, mouseLoc, scrollAction );
  238.         DisposeRoutineDescriptor( scrollAction );
  239.     }
  240. */
  241.  
  242.     // Use default behavior for thumb, program will crash if you don't!!
  243.     if( kControlIndicatorPart == controlPart && !g.useAppearance )
  244.     {
  245.         // BB: Perform scrollbar tracking
  246.         controlPart = TrackControl( control, mouseLoc, 0L );
  247.         if( !controlPart )
  248.             return false;
  249.  
  250.         if( controlPart == kControlIndicatorPart )
  251.         {
  252.             ScrollToPosition( dWin, _calcScrollPosition( dWin ) );
  253.         }
  254.     }
  255.     else
  256.     {
  257.         // Perform scrollbar tracking
  258.         controlPart = TrackControl( control, mouseLoc, _trackActionUPP );
  259.         if( !controlPart )
  260.             return false;
  261.         // BB: all scrolling handled by _scrollAction()
  262.     }                        
  263.  
  264.     return true;
  265. }
  266.  
  267. /*** SCROLL TO SELECTION ***/
  268. //LR 180 -- removed forceUpdate flag, we always do a full  update as we
  269. //            no longer have an offscreen buffer for each window!
  270. void ScrollToSelection( EditWindowPtr dWin, long pos, Boolean centerFlag )
  271. {
  272.     long    curAddr;
  273.     curAddr = dWin->editOffset;
  274.  
  275.     if( pos >= curAddr && pos < curAddr + (dWin->linesPerPage * kBytesPerLine) )
  276.     {
  277. /*LR 180
  278.         if( forceUpdate )
  279.         {
  280.             DrawPage( dWin );
  281.         }
  282. */
  283.         UpdateOnscreen( dWin->oWin.theWin );
  284.         AdjustScrollBars( dWin->oWin.theWin, false );
  285.         return;
  286.     }
  287.  
  288.     if( centerFlag )
  289.     {
  290.         curAddr = pos - ( pos % kBytesPerLine );
  291.         curAddr -= kBytesPerLine * ((dWin->linesPerPage / 2) - 1);
  292.         // No need to adjust for limits, will be done by scroll routine
  293.     }
  294.     else
  295.     {
  296.         if( pos < curAddr )
  297.         {
  298.             // Scroll Up
  299.             curAddr = pos;
  300.             curAddr -= (curAddr % kBytesPerLine);
  301.         }
  302.         else
  303.         {
  304.             // Scroll Down
  305.             curAddr = pos - (dWin->linesPerPage - 1) * kBytesPerLine;
  306.             curAddr -= (curAddr % kBytesPerLine);
  307.         }
  308.     }
  309.     ScrollToPosition( dWin, curAddr );
  310. }
  311.  
  312. /*** SCROLL TO POSITION ***/
  313. void ScrollToPosition( EditWindowPtr dWin, long newPos )
  314. {
  315.     long    limit;
  316.  
  317.     SetPortWindowPort( dWin->oWin.theWin );
  318.  
  319.     // Constrain scrolling position to legal limits
  320.         limit = LIMIT_CALC;
  321. //LR 1.72    limit = ((dWin->fileSize + (kBytesPerLine - 1)) & 0xFFFFFFF0) - (dWin->linesPerPage / kBytesPerLine);
  322.     if( newPos > limit )
  323.         newPos = limit;
  324.     if( newPos < 0 )
  325.         newPos = 0;
  326.  
  327.     // LR: v1.6.5 reduce auto-scroll flicker (Max Horn)
  328.     if( newPos != dWin->editOffset )
  329.     {
  330.         dWin->editOffset = newPos;
  331.         
  332.         // Adjust Scrollbars
  333.         AdjustScrollBars( dWin->oWin.theWin, false );
  334.  
  335.         // 12/10/93 - Optimize Drawing
  336.         SetCurrentChunk( dWin, dWin->editOffset );
  337.  
  338. //LR 180        DrawPage( dWin );
  339.         UpdateOnscreen( dWin->oWin.theWin );
  340.     }
  341. }
  342.  
  343. /*** AUTO SCROLL ***/
  344. //LR 180 -- adjust scroll amount by pos from top/bottom of window
  345.  
  346. void AutoScroll( EditWindowPtr dWin, Point pos )
  347. {
  348.     short offset;
  349.  
  350.     if( pos.v < (kHeaderHeight + 1) )    // off top?
  351.     {
  352.         offset = kBytesPerLine * (((pos.v - (kHeaderHeight + 3)) / 2) + 1);        // an extra 2 to avoid scrolling down!
  353.     }
  354.     else if( pos.v >= (kHeaderHeight + 1) + dWin->linesPerPage * kLineHeight )    // of bottom?
  355.     {
  356.         offset = kBytesPerLine * (((pos.v - ((kHeaderHeight + 1) + dWin->linesPerPage * kLineHeight)) / 2) + 1);
  357.     }
  358.     else
  359.         return;    // was not off top or bottom.
  360.  
  361.     ScrollToPosition( dWin, dWin->editOffset+offset );
  362. }