home *** CD-ROM | disk | FTP | other *** search
- /*
- WASTE Demo Project:
- Window Handling
-
- Copyright © 1993-1997 Marco Piovanelli
- All Rights Reserved
-
- C port by John C. Daub
- */
-
-
- #ifndef __ALIASES__
- #include <Aliases.h>
- #endif
-
- #ifndef __TOOLUTILS__
- #include <ToolUtils.h>
- #endif
-
- #ifndef __FILETYPESANDCREATORS__
- #include <FileTypesAndCreators.h>
- #endif
-
- #ifndef _LongCoords_
- #include "LongCoords.h"
- #endif
-
- #ifndef __WEDEMOAPP__
- #include "WEDemoIntf.h"
- #endif
-
- #ifndef __SMARTSCROLLAPI__
- #include "SmartScroll.h"
- #endif
-
- // some consts used by DoGrow()
-
- enum {
- kMinWindowWidth = 200,
- kMinWindowHeight = 80
- };
-
- // static variables
-
- static SInt32 sScrollStep; // how many pixels to scroll (used by ScrollProc)
-
-
- static void CalcGrowIconRect( WindowRef window, Rect *iconRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- iconRect->top = portRect.bottom - (kBarWidth - 2);
- iconRect->left = portRect.right - (kBarWidth - 2);
- iconRect->bottom = portRect.bottom;
- iconRect->right = portRect.right;
- }
-
- static void CalcTextRect( WindowRef window, Rect *textRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- textRect->top = 0;
- textRect->left = 0;
- textRect->bottom = portRect.bottom - (kBarWidth - 1);
- textRect->right = portRect.right - (kBarWidth - 1);
- InsetRect( textRect, kTextMargin, kTextMargin );
- }
-
- static void CalcScrollBarRect( WindowRef window, VHSelect axis, Rect *barRect )
- {
- Rect portRect = GetWindowPort( window )->portRect;
-
- switch ( axis )
- {
- case v:
- {
- barRect->top = -1;
- barRect->left = portRect.right - (kBarWidth - 1);
- barRect->bottom = portRect.bottom - (kBarWidth - 2);
- barRect->right = portRect.right + 1;
- break;
- }
-
- case h:
- {
- barRect->top = portRect.bottom - (kBarWidth - 1);
- barRect->left = -1;
- barRect->bottom = portRect.bottom + 1;
- barRect->right = portRect.right - (kBarWidth - 2 );
- break;
- }
- }
- }
-
- /*
- the standard Toolbox trap _DrawGrowIcon draws two lines from the grow icon
- to the left and top margins of the window's content area
- these additional lines may create ugly dirt, so we use this routine to temporarily
- set the clip region to the grow icon rect.
-
- in addition, if validate is true, we call _ValidRect on the icon rect
- */
-
- static void MyDrawGrowIcon( WindowRef window, Boolean validate )
- {
- GrafPtr savePort;
- RgnHandle saveClip;
- Rect r;
-
- // save port and set thePort to wind
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- // save the clip region
-
- saveClip = NewRgn();
- GetClip( saveClip );
-
- // calculate the grow icon rect
-
- CalcGrowIconRect( window, &r );
-
- // set clip region to grow icon rect
-
- ClipRect( &r );
-
- // call _DrawGrowIcon
-
- DrawGrowIcon( window );
-
- // if validate is true, remove the grow icon rect from the update region
-
- if ( validate )
- ValidRect( &r );
-
- // restore old clip region
-
- SetClip( saveClip );
- DisposeRgn( saveClip );
-
- // restore old port
-
- SetPort( savePort );
- }
-
- static void ScrollBarChanged( WindowRef window )
- {
- // scroll text to reflect new scroll bar setting
-
- DocumentHandle hDocument = GetWindowDocument( window );
- WEReference we;
- LongRect viewRect, destRect;
-
- we = (*hDocument)->we;
- WEGetViewRect( &viewRect, we );
- WEGetDestRect( &destRect, we );
- WEScroll
- (
- viewRect.left - destRect.left - LCGetValue( (*hDocument)->scrollBars[ h ] ),
- viewRect.top - destRect.top - LCGetValue( (*hDocument)->scrollBars[ v ] ),
- we
- );
- }
-
- static void AdjustBars ( WindowRef window )
- {
- DocumentHandle hDocument ;
- WEReference we ;
- GrafPtr savePort ;
- LongRect viewRect, destRect ;
- SInt32 visible, total, value, max ;
- ControlRef bar ;
-
- GetPort ( & savePort ) ;
- SetPortWindowPort ( window ) ;
-
- hDocument = GetWindowDocument ( window ) ;
- we = ( * hDocument ) -> we ;
-
- // get the view and destination rectangle
- WEGetViewRect ( & viewRect, we ) ;
- WEGetDestRect ( & destRect, we ) ;
-
- // do the vertical axis
-
- // get scroll bar handle
- bar = ( * hDocument ) -> scrollBars [ v ] ;
-
- // calculate new scroll bar settings
-
- // NOTE: (destRect.bottom - destRect.top) always equals the total text height because
- // WASTE automatically updates destRect.bottom whenever line breaks are recalculated
-
- total = destRect . bottom - destRect . top ; // total pixel height
- visible = viewRect . bottom - viewRect . top ; // visible pixel height
- max = total - visible ; // scrollable range (in pixels)
- value = viewRect . top - destRect . top ; // thumb location within scrollable range
-
- // make sure max is always non-negative
- if ( max <= 0 ) max = 0 ;
-
- // notify SmartScroll
- SetSmartScrollInfo ( bar, visible, total ) ;
-
- // reset the scroll bar
- LCSetMax ( bar, max ) ;
- LCSetValue ( bar, value ) ;
-
- // if value exceeds max then the bottom of the destRect is above
- // the bottom of the view rectangle: we need to scroll the text downward
- if ( value > max )
- {
- ScrollBarChanged ( window ) ;
- }
-
- // now do the horizontal axis
-
- // get scroll bar handle
- bar = ( * hDocument ) -> scrollBars [ h ] ;
-
- // calculate new scroll bar settings
- total = destRect . right - destRect . left ; // total pixel width
- visible = viewRect . right - viewRect . left ; // visible pixel width
- max = total - visible ; // scrollable range (in pixels)
- value = viewRect . left - destRect . left ; // thumb location within scrollable range
-
- // make sure max is always non-negative
- if ( max <= 0 ) max = 0 ;
-
- // notify SmartScroll
- SetSmartScrollInfo ( bar, visible, total ) ;
-
- // reset the scroll bar
- LCSetMax ( bar, max ) ;
- LCSetValue ( bar, value ) ;
-
- SetPort ( savePort ) ;
- }
-
- static void ViewChanged( WindowRef window )
- {
- DocumentHandle hDocument;
- GrafPtr savePort;
- ControlRef bar;
- Rect r;
- LongRect viewRect;
- VHSelect axis;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument( window );
-
- // resize the text area
-
- CalcTextRect( window, &r );
- WERectToLongRect( &r, &viewRect );
- WESetViewRect( &viewRect, (*hDocument)->we );
-
- // move and resize the control bars
-
- for ( axis = v; axis <= h; axis++ )
- {
- bar = (*hDocument)->scrollBars[ axis ];
- CalcScrollBarRect( window, axis, &r );
- MoveControl( bar, r.left, r.top );
- SizeControl( bar, r.right - r.left, r.bottom - r.top );
- ValidRect( &r );
- }
-
- // reset the thumb positions and the max values of the control bars
- AdjustBars( window );
-
- // redraw the control bars
-
- ShowControl( (*hDocument)->scrollBars[ v ] );
- ShowControl( (*hDocument)->scrollBars[ h ] );
-
- SetPort( savePort );
- }
-
- /*
- This is a deviation from the original Pascal WASTE Demo App code.
-
- This "morally correct" code for window dragging is per an article in MacTech
- Magazine (July 1994, Vol 10, No. 7). by Eric Shapiro (of Rock Ridge Enterprises)
- called "Multiple Monitors vs. Your Application"
-
- Eric addressed numerous things to allow your app to deal nicely with multiple
- monitor setups, one of them is dragging.
-
- According to Eric, many apps don't let you drag windows to second monitors, and
- though holding down the cmd/opt keys often overrides this problem, it should
- still be updated. And the only reason qd.screenBits.bounds works to allow
- you to drag to second monitors is because of a kludge Apple put in the Window Manager
-
- So, this is some code from Eric to make our app be "morally correct" :)
- */
-
- void DoDrag ( Point thePoint, WindowRef window )
- {
- Rect desktopBounds ;
-
- if ( gHasColorQD )
- {
- desktopBounds = ( * GetGrayRgn ( ) ) -> rgnBBox ;
- }
- else
- {
- desktopBounds = qd . screenBits . bounds ;
- }
-
- DragWindow ( window, thePoint, & desktopBounds ) ;
- }
-
- void Resize ( Point newSize, WindowRef window )
- {
- DocumentHandle hDocument ;
- GrafPtr savePort ;
- Rect r ;
- RgnHandle tempRgn, dirtyRgn ;
-
- // set up the port
- GetPort( & savePort ) ;
- SetPortWindowPort ( window ) ;
-
- hDocument = GetWindowDocument ( window ) ;
-
- // create temporary regions for calculations
- tempRgn = NewRgn ( ) ;
- dirtyRgn = NewRgn ( ) ;
-
- // save old text region
- CalcTextRect ( window, & r ) ;
- RectRgn ( tempRgn, & r ) ;
-
- // erase the old grow icon rect
- CalcGrowIconRect ( window, & r ) ;
- EraseRect ( & r ) ;
-
- // hide the scroll bars
- HideControl ( ( * hDocument ) -> scrollBars [ v ] ) ;
- HideControl ( ( * hDocument ) -> scrollBars [ h ] ) ;
-
- // perform the actual resizing of the window, redraw scroll bars and grow icon
- SizeWindow ( window, newSize . h, newSize . v, false ) ;
- ViewChanged ( window ) ;
- MyDrawGrowIcon ( window, true ) ;
-
- // calculate the dirty region (to be updated)
- CalcTextRect ( window, & r );
- RectRgn ( dirtyRgn, & r ) ;
- XorRgn ( dirtyRgn, tempRgn, dirtyRgn ) ;
- InsetRect ( & r, - kTextMargin, - kTextMargin ) ;
- RectRgn ( tempRgn, & r ) ;
- SectRgn ( dirtyRgn, tempRgn, dirtyRgn ) ;
-
- // mark the dirty region as invalid
- InvalRgn ( dirtyRgn ) ;
-
- // throw away temporary regions
- DisposeRgn ( tempRgn ) ;
- DisposeRgn ( dirtyRgn ) ;
-
- // restore the port
- SetPort ( savePort ) ;
- }
-
- void DoGrow ( Point hitPt, WindowRef window )
- {
- Rect sizeRect ;
- SInt32 newSize ;
-
- SetRect( & sizeRect, kMinWindowWidth, kMinWindowHeight, SHRT_MAX, SHRT_MAX ) ;
- if ( ( newSize = GrowWindow ( window, hitPt, & sizeRect ) ) != 0L )
- {
- // for some reason, GrowWindow( ) returns a long value,
- // but it's really a Point
-
- Resize ( * ( Point * ) & newSize, window ) ;
- }
- }
-
- void DoZoom ( SInt16 partCode, WindowRef window )
- {
- DocumentHandle hDocument;
- GrafPtr savePort;
- Rect r;
-
- GetPort( &savePort );
- SetPortWindowPort( window );
-
- hDocument = GetWindowDocument(window);
-
- r = GetWindowPort( window )->portRect;
- EraseRect( &r );
- HideControl( (*hDocument)->scrollBars[ v ] );
- HideControl( (*hDocument)->scrollBars[ h ] );
-
- ZoomWindow( window, partCode, false );
-
- ViewChanged( window );
- CalcTextRect( window, &r );
- InvalRect( &r );
-
- SetPort( savePort );
- }
-
- // this is a callback tourine called by the Toolbox Control Manager
- // move the scroll bar thumb and scroll the text accordingly
-
- static pascal void ScrollProc ( ControlRef bar, ControlPartCode partCode )
- {
- SInt32 value, step ;
-
- if ( partCode == kControlNoPart )
- {
- return ;
- }
-
- value = LCGetValue ( bar ) ;
- step = sScrollStep ;
-
- if ( ( ( value < LCGetMax ( bar ) ) && ( step > 0 ) ) ||
- ( ( value > 0 ) && ( step < 0 ) ) )
- {
- LCSetValue ( bar, value + step ) ;
- ScrollBarChanged ( FrontWindow ( ) ) ;
- }
- }
-
- static SInt32 SendControlMessage ( ControlRef inControl, SInt16 inMessage, SInt32 inParam )
- {
- GrafPtr savePort ;
- Handle cdef ;
- SInt32 result ;
- SInt8 saveState ;
-
- // get a handle to the control definition procedure
- cdef = ( * inControl ) -> contrlDefProc ;
-
- // make sure the CDEF is loaded
- if ( * cdef == nil )
- {
- LoadResource ( cdef ) ;
- if ( * cdef == nil )
- {
- return 0 ; // emergency exit (couldn't load CDEF)
- }
- }
-
- // lock it down
- saveState = HGetState ( cdef ) ;
- HLock ( cdef ) ;
-
- // set up the port
- GetPort ( & savePort ) ;
- SetPortWindowPort ( ( * inControl ) -> contrlOwner ) ;
-
- // call the CDEF
- result = CallControlDefProc ( ( ControlDefUPP ) StripAddress ( * cdef ),
- GetControlVariant ( inControl ), inControl, inMessage, inParam ) ;
-
- // unlock the CDEF
- HSetState ( cdef, saveState ) ;
-
- // restore the port
- SetPort ( savePort ) ;
-
- // return result code
- return result ;
- }
-
- static void LiveScroll ( ControlRef inControl, Point inHitPt, WindowRef inWindow )
- {
- IndicatorDragConstraint constraint ;
- Point mouseLoc ;
- SInt32 initialValue, oldValue, curValue, max ;
- SInt16 scrollRange, delta ;
- VHSelect orientation ;
-
- // hilite the control thumb
- // this does nothing with the standard System 7.x scroll bar, but is required for
- // correct visual feedback with the Apple Grayscale Appearance (as implemented by
- // the Appearance control panel in MacOS 8, or by Aaron/Kaleidoscope)
- HiliteControl ( inControl, kControlIndicatorPart ) ;
-
- // get limit & slop rects that should be used for dragging the indicator
- // (see IM: Mac Toolbox Essentials, page 5-114)
- * ( Point * ) & constraint . limitRect = inHitPt ;
- SendControlMessage ( inControl, thumbCntl, ( SInt32 ) & constraint ) ;
-
- // determine the orientation of the scroll bar
- orientation = ( constraint . axis == kVerticalConstraint ) ? h : v ;
-
- // calculate the area in which the thumb can travel
- if ( orientation == v )
- {
- scrollRange = ( constraint . limitRect . bottom - constraint . limitRect . top ) ;
- }
- else
- {
- scrollRange = ( constraint . limitRect . right - constraint . limitRect . left ) ;
- }
-
- // get current value & max
- initialValue = oldValue = curValue = LCGetValue ( inControl ) ;
- max = LCGetMax ( inControl ) ;
-
- // mouse tracking loop
- while ( StillDown ( ) )
- {
- // get current mouse location
- GetMouse ( & mouseLoc ) ;
-
- // do nothing if the mouse is outside the slop rectangle
- if ( PtInRect ( mouseLoc, & constraint . slopRect ) )
- {
- // calculate pixel offset relative to initial hit point
- if ( orientation == v )
- {
- delta = mouseLoc . v - inHitPt . v ;
- }
- else
- {
- delta = mouseLoc . h - inHitPt . h ;
- }
-
- // calculate new control value
- curValue = initialValue + FixMul ( max, FixRatio ( delta, scrollRange ) ) ;
- if ( curValue < 0 ) curValue = 0 ;
- if ( curValue > max ) curValue = max ;
- }
-
- if ( curValue != oldValue )
- {
- // set new control value
- LCSetValue ( inControl, curValue ) ;
- ScrollBarChanged ( inWindow ) ;
- oldValue = curValue ;
- }
- }
-
- // unhighlight the thumb
- HiliteControl ( inControl, kControlNoPart ) ;
- }
-
- static void DoScrollBar ( Point hitPt, EventModifiers modifiers, WindowRef window )
- {
- DocumentHandle hDocument;
- ControlRef bar = nil;
- LongRect viewRect;
- ControlPartCode partCode;
- SInt32 pageSize;
- SInt32 step = 0;
-
- #ifdef __cplusplus
- static ControlActionUPP sScrollerUPP = NewControlActionProc( ScrollProc );
- #else
- static ControlActionUPP sScrollerUPP = nil;
- if (sScrollerUPP == nil)
- {
- sScrollerUPP = NewControlActionProc( ScrollProc );
- }
- #endif
-
- hDocument = GetWindowDocument( window );
- WEGetViewRect( &viewRect, (*hDocument)->we );
-
- // find out which control was hit (if any) and in which part
- partCode = FindControl( hitPt, window, &bar );
-
- // if any control was hit, it must be one of our two scroll bars:
- // find out which and calculate the page size for it
- if ( bar == (*hDocument)->scrollBars[ v ] )
- {
- pageSize = viewRect.bottom - viewRect.top;
- }
- else if ( bar == (*hDocument)->scrollBars[ h ] )
- {
- pageSize = viewRect.right - viewRect.left;
- }
- else
- {
- return; // return immediately if none of our scrollbars was hit
- }
-
- // dispatch on partCode
- switch ( partCode )
- {
- case kControlIndicatorPart:
- {
- // click in thumb
- if ( modifiers & optionKey )
- {
- // call TrackControl with no actionProc and adjust text
- TrackControl ( bar, hitPt, nil ) ;
- LCSynch ( bar ) ;
- ScrollBarChanged ( window ) ;
- }
- else
- {
- LiveScroll ( bar, hitPt, window ) ;
- }
- return;
- }
-
- case kControlUpButtonPart:
- {
- step = - ( ( modifiers & optionKey ) ? 1 : kScrollDelta ) ;
- break ;
- }
-
- case kControlDownButtonPart:
- {
- step = + ( ( modifiers & optionKey ) ? 1 : kScrollDelta ) ;
- break ;
- }
-
- case kControlPageUpPart:
- {
- step = - ( pageSize - kScrollDelta ) ;
- break ;
- }
-
- case kControlPageDownPart:
- {
- step = + ( pageSize - kScrollDelta ) ;
- break ;
- }
-
- } // switch
-
- // save step in a static variable for our ScrollProc callback
- sScrollStep = step ;
-
- // track the mouse
- TrackControl ( bar, hitPt, sScrollerUPP ) ;
- }
-
- /*
- This is a callback routine called whenever the text is scrolled automaticall.
- Since auto-scrolling is enabled, WEScroll may be invoked internally by WASTE
- in many different circumstances, and we want to be notified when this happens
- so we can adjust the scroll bars
- */
-
- static pascal void TextScrolled ( WEReference we )
- {
- WindowRef window = nil ;
-
- // retrieve the window pointer stored in the WE instance as a "reference constant"
- if ( WEGetInfo( weRefCon, & window, we ) != noErr )
- {
- return ;
- }
-
- // make sure the scroll bars are in synch with the destination rectangle
- AdjustBars ( window ) ;
- }
-
- Boolean DoContent ( Point hitPt, const EventRecord * event, WindowRef window )
- {
- WEReference we = GetWindowWE ( window ) ;
- Rect textRect ;
- GrafPtr savePort ;
- Boolean isMyClick = false ;
-
- // set up the port
- GetPort ( & savePort ) ;
- SetPortWindowPort ( window ) ;
-
- // convert the point to local coordinates
- GlobalToLocal ( & hitPt ) ;
-
- // a click in an inactive window should normally activate it,
- // but the availability of the Drag Manager introduces an exception to this rule:
- // a click in the background selection may start a drag gesture,
- // without activating the window
-
- if ( IsWindowHilited ( window ) )
- {
- isMyClick = true ; // active window -> always handle click
- }
- else if ( gHasDragAndDrop )
- {
- SInt32 selStart, selEnd ;
- RgnHandle selRgn ;
-
- WEGetSelection ( & selStart, & selEnd, we ) ;
- selRgn = WEGetHiliteRgn ( selStart, selEnd, we ) ;
- isMyClick = PtInRgn ( hitPt, selRgn ) && WaitMouseMoved ( event -> where ) ;
- DisposeRgn ( selRgn ) ;
- }
-
- if ( isMyClick )
- {
- CalcTextRect ( window, & textRect ) ;
-
- if ( PtInRect ( hitPt, & textRect ) )
- {
- WEClick ( hitPt, event -> modifiers, event -> when, we ) ;
- }
- else
- {
- DoScrollBar ( hitPt, event -> modifiers, window ) ;
- }
- }
-
- // restore the port
- SetPort ( savePort ) ;
-
- // return true if the click should activate this window
- return ! isMyClick ;
- }
-
- static void DoScrollKey ( SInt16 keyCode, WindowRef window )
- {
- DocumentHandle hDocument ;
- ControlRef bar ;
- SInt32 value ;
- LongRect viewRect ;
-
- hDocument = GetWindowDocument ( window ) ;
- bar = ( * hDocument ) -> scrollBars [ v ] ;
-
- // get current scroll bar value
- value = LCGetValue ( bar ) ;
-
- // get text view rect
- WEGetViewRect ( & viewRect, ( * hDocument ) -> we ) ;
-
- switch ( keyCode )
- {
-
- case keyPgUp:
- {
- value -= ( viewRect . bottom - viewRect . top ) - kScrollDelta ;
- break ;
- }
-
- case keyPgDn:
- {
- value += ( viewRect . bottom - viewRect . top ) - kScrollDelta ;
- break ;
- }
-
- case keyHome:
- {
- value = 0 ;
- break ;
- }
-
- case keyEnd:
- {
- value = LONG_MAX ;
- break ;
- }
- } // switch
-
- // set the new scroll bar value and scroll the text pane accordingly
-
- LCSetValue ( bar, value ) ;
- ScrollBarChanged ( window ) ;
- }
-
- void DoKey ( SInt16 key, const EventRecord * event )
- {
- WindowRef window ;
- SInt16 keyCode ;
-
- // do nothing if no window is active
- if ( ( window = FrontWindow ( ) ) == nil )
- return;
-
- // extract virtual key code from event record
- keyCode = ( event->message & keyCodeMask ) >> 8 ;
-
- // page movement keys are handled by DoScrollKey()
- switch ( keyCode )
- {
- case keyPgUp:
- case keyPgDn:
- case keyHome:
- case keyEnd:
- {
- DoScrollKey ( keyCode, window ) ;
- break ;
- }
-
- default:
- {
- WEKey ( key, event -> modifiers, GetWindowWE (window) ) ;
- break ;
- }
- }
- }
-
- void DoUpdate ( WindowRef window )
- {
- GrafPtr savePort ;
- RgnHandle updateRgn ;
-
- // if we have no windows, there's nothing to update!
- if ( window == nil )
- {
- return ;
- }
-
- // save the old drawing port
- GetPort ( & savePort ) ;
- SetPortWindowPort ( window ) ;
-
- // notify everything that we're doing an update.
- BeginUpdate ( window ) ;
-
- // BeginUpdate sets the window port visRgn to the region to update
- updateRgn = GetWindowPort ( window ) -> visRgn ;
-
- if ( ! EmptyRgn ( updateRgn ) ) // if it's not an empty region, let's update it!
- {
- // erase the update region
- EraseRgn ( updateRgn ) ;
-
- // draw scroll bars
- UpdateControls ( window, updateRgn ) ;
-
- // draw grow icon
- MyDrawGrowIcon ( window, false ) ;
-
- // draw text
- WEUpdate ( updateRgn, GetWindowWE ( window ) ) ;
- }
-
- // tell everything we're done updating
- EndUpdate ( window ) ;
-
- // restore the old graphics port
- SetPort ( savePort ) ;
- }
-
- void DoActivate ( Boolean isActivating, WindowRef window )
- {
- DocumentHandle hDocument ;
- WEReference we ;
- GrafPtr savePort ;
- Rect barRect ;
- ControlPartCode barHilite ;
- SInt16 menuID ;
- VHSelect axis ;
-
- // if this is not one of our document windows, nothing to do here...
- if ( ( hDocument = GetWindowDocument ( window ) ) == nil )
- {
- return ;
- }
- we = ( * hDocument ) -> we ;
-
- // sanity check: do nothing if required activation state
- // is the same as the current activation state
- if ( isActivating == WEIsActive ( we ) )
- {
- return ;
- }
-
- // set up the port
- GetPort ( & savePort ) ;
- SetPortWindowPort ( window ) ;
-
- // activate or deactivate the text (and any other relevant stuff) depending on just
- // what we're doing here...
- if ( isActivating )
- {
- WEActivate ( we ) ;
- barHilite = kControlNoPart ;
- }
- else
- {
- WEDeactivate ( we ) ;
- barHilite = kControlDisabledPart ;
- }
-
- // redraw the grow icon (and validate its rect)
- MyDrawGrowIcon ( window, true ) ;
-
- // redraw the scroll bars with the new highlighting (and validate their rects)
- for ( axis = v ; axis <= h ; axis ++ )
- {
- HiliteControl ( ( * hDocument ) -> scrollBars [ axis ], barHilite ) ;
- CalcScrollBarRect ( window, axis, & barRect ) ;
- ValidRect ( & barRect ) ;
- }
-
- // if activating, undim text-related menus
- if ( isActivating )
- {
- for ( menuID = kMenuEdit ; menuID <= kMenuFeatures ; menuID ++ )
- {
- EnableItem ( GetMenuHandle ( menuID ), 0 ) ;
- }
- }
-
- // invalidate the menu bar
- InvalMenuBar ( ) ;
-
- // restore the old graphics port..
- SetPort ( savePort ) ;
- }
-
- OSErr CreateWindow ( const FSSpec * pFileSpec )
- {
- DocumentHandle hDocument = nil ;
- WindowRef window = nil ;
- AliasHandle alias = nil ;
- WEReference we = nil ;
- ControlRef bar = nil ;
- FInfo fileInfo ;
- Rect textRect ;
- LongRect lr ;
- VHSelect axis ;
- OSErr err ;
-
- #ifdef __cplusplus
- static WEScrollUPP sScrollerUPP = NewWEScrollProc ( TextScrolled ) ;
- #else
- static WEScrollUPP sScrollerUPP = nil ;
- if ( sScrollerUPP == nil )
- {
- sScrollerUPP = NewWEScrollProc ( TextScrolled ) ;
- }
- #endif
-
- // allocate a relocateable block to hold a document record
- hDocument = ( DocumentHandle ) NewHandleClear ( sizeof ( DocumentRecord ) ) ;
- if ( ( err = MemError( ) ) != noErr )
- {
- goto cleanup ;
- }
-
- // create the window from a 'WIND' template: the window is initially invisible
- // if ColorQuickDraw is available, create a color window
- if ( gHasColorQD )
- {
- window = GetNewCWindow ( kWindowTemplateID, nil, ( WindowRef ) -1L ) ;
- }
- else
- {
- window = GetNewWindow ( kWindowTemplateID, nil, ( WindowRef ) -1L ) ;
- }
-
- // make sure we got a window
- if ( window == nil )
- {
- err = memFullErr ;
- goto cleanup ;
- }
-
- // link the document record to the window and the other way around
- SetWRefCon ( window, ( SInt32 ) hDocument ) ;
- ( * hDocument ) -> owner = window ;
-
- // we got a window, so tell QuickDraw where to draw...
- SetPortWindowPort ( window ) ;
-
- // calculate the text rectangle
- CalcTextRect ( window, & textRect ) ;
- WERectToLongRect ( & textRect, & lr ) ;
-
- // create a new WASTE instance
- if ( ( err = WENew ( & lr, & lr, weDoAutoScroll +
- weDoOutlineHilite +
- weDoUndo +
- weDoIntCutAndPaste +
- weDoDragAndDrop +
- weDoUseTempMem +
- weDoDrawOffscreen, & we) ) != noErr )
- {
- goto cleanup ;
- }
-
- // save a reference to the window in the WE instance
- if ( ( err = WESetInfo ( weRefCon, & window, we ) ) != noErr )
- {
- goto cleanup ;
- }
-
- // now the other way around: save the WE reference in the document record
- ( * hDocument ) -> we = we ;
-
- // set up our scroll callback
- if ( ( err = WESetInfo ( weScrollProc, & sScrollerUPP, we ) ) != noErr )
- {
- goto cleanup ;
- }
-
- // create the scroll bars from a control template
- for ( axis = v ; axis <= h; axis ++ )
- {
- if ( ( bar = GetNewControl ( kScrollBarTemplateID, window ) ) == nil )
- {
- err = memFullErr ;
- goto cleanup ;
- }
- HiliteControl ( bar, kControlDisabledPart ) ;
-
- // attach a LongControl record to the scroll bar: this allows us to use long
- // settings and thus scroll text taller than 32,767 pixels
- if ( ( err = LCAttach ( bar ) ) != noErr )
- {
- goto cleanup;
- }
-
- // save control handle in the document record
- ( * hDocument ) -> scrollBars [ axis ] = bar ;
-
- } // for
-
- // ViewChanged adjusts the scroll bars rectangles to the window frame
- ViewChanged ( window ) ;
-
- // if pFileSpec is not nil, it points to a file to read, so let's read it!
- if ( pFileSpec != nil )
- {
- // turn the cursor into a wristwatch because this can be a lengthy operation
- SetCursor ( * GetCursor ( watchCursor ) ) ;
-
- // retrieve file infomation
- if ( ( err = FSpGetFInfo ( pFileSpec, & fileInfo ) ) != noErr )
- {
- goto cleanup ;
- }
-
- // make sure we recognize the file type
- if ( ( fileInfo . fdType != kTypeText ) && ( fileInfo . fdType != ftSimpleTextDocument ) )
- {
- err = badFileFormat ;
- goto cleanup ;
- }
-
- // read in the file
- if ( ( err = ReadTextFile ( pFileSpec, we ) ) != noErr )
- {
- goto cleanup ;
- }
-
- // set the window title to the file name
- SetWTitle ( window, pFileSpec -> name ) ;
-
- // create an alias to keep track of the file
- if ( ( err = NewAlias ( nil, pFileSpec, & alias ) ) != noErr )
- {
- goto cleanup ;
- }
- ( * hDocument ) -> fileAlias = ( Handle ) alias ;
-
- // if the file is a read-only file, go ahead and enable those flags
- if ( fileInfo . fdType == ftSimpleTextDocument )
- {
- WEFeatureFlag ( weFReadOnly, weBitSet, we ) ;
- }
-
- // let's make sure the cursor is happy...
- SetCursor ( & qd . arrow ) ;
- }
-
- // adjust scroll bar settings based on the total text height
- AdjustBars ( window ) ;
-
- // finally! show the document window
- ShowWindow ( window ) ;
-
- cleanup:
- if ( err != noErr )
- {
- ErrorAlert ( err ) ;
- }
- return err ;
- }
-
- void DestroyWindow ( WindowRef window )
- {
- DocumentHandle hDocument ;
- SInt16 menuID ;
-
- hDocument = GetWindowDocument ( window ) ;
-
- // destroy the WASTE instance
- WEDispose ( ( * hDocument ) -> we ) ;
-
- // destory the LongControl records attached to the scroll bars
- LCDetach ( ( * hDocument ) -> scrollBars [ v ] ) ;
- LCDetach ( ( * hDocument ) -> scrollBars [ h ] ) ;
-
- // dispose of the file alias, if any
- ForgetHandle ( & ( ( * hDocument ) -> fileAlias ) ) ;
-
- // destroy the window record and all associated data structures
- DisposeWindow ( window ) ;
-
- // finally, dispose of the document record
- DisposeHandle ( ( Handle ) hDocument ) ;
-
- // adjust the menus to suit
- for ( menuID = kMenuFont ; menuID <= kMenuFeatures ; menuID ++ )
- {
- DisableItem ( GetMenuHandle ( menuID ), 0 ) ;
- }
- InvalMenuBar ( ) ;
- }
-