Sources/MSWindow.c

// MSWindow.c
//
// Original version by Jon Lansdell and Nigel Humphreys.
// 4.0 and 3.1 updates by Greg Sutton.
// ©Apple Computer Inc 1996, all rights reserved.
 
/*
    Changes for 3.1 :
    
    12-Oct-95 : CW : Cleaned up DoContent and added call to DoWindowContentDrag
                     Clean up CloseMyWindow and added call to RemoveDragHandlers
                     Added InstallDragHandlers call to NewDocument
                     Use HiliteControl on suspend/resume instead of Show/HideControl
    1-Nov-95  : DS : Made Changes for GX Printing.
 
    Changes for 4.0 :
 
    17-Apr-96 : GS : Changed pascal calling conventions to C where possible.
*/
 
#include <Scrap.h>
#include <Packages.h>
#ifdef THINK_C
    #include "PLStrs.h"
#else
    #include <PLStringFuncs.h>
#endif
#include <GXPrinting.h>
#include <PrintingMessages.h>
 
#include "MSWindow.h"
#include "MSMain.h"
#include "MSDrag.h"
#include "MSAERecording.h"
#include "MSGXPrinting.h"
#include "MSResultWind.h"
#include "MSAEWindowUtils.h"
 
#define kControlInvisible       0
#define kControlVisible         0xFF            
#define kScrollbarWidth         16
#define kScrollbarAdjust        (kScrollbarWidth - 1)
#define kScrollTweek            2
#define kTextOffset             5 
#define kButtonScroll           10
            
#define kHOffset                20   // Stagger window offsets
#define kVOffset                20
            
#define kTBarHeight             20
#define kMBarHeight             20
 
#pragma segment Window
 
DPtr    DPtrFromWindowPtr(WindowPtr theWindow)
{
    if ( theWindow && IsDocumentWindow( theWindow ) )
        return((DPtr)GetWRefCon(theWindow));
    else
        return(NULL);
} // DPtrFromWindowPtr
 
    
#pragma segment main
 
 
//  Scroll the TERec around to match up to the potentially updated scrollbar
//  values. This is really useful when the window resizes such that the
//  scrollbars become inactive and the TERec had been previously scrolled.
 
void    AdjustTE( DPtr theDoc )
{
    short    h;
    short    v;
    TEHandle myText;
    
    myText = theDoc->theText;
    h = ((*myText)->viewRect.left - (*myText)->destRect.left) -
    GetCtlValue(theDoc->hScrollBar) + kTextOffset;
             
    v = ((*myText)->viewRect.top - (*myText)->destRect.top) - 
    GetCtlValue(theDoc->vScrollBar) + kTextOffset;
                     
    if (h || v)
    {
        TEScroll(h, v, theDoc->theText);
        DrawPageExtras(theDoc);
    }
} // AdjustTE
    
    
// Calculate the new control maximum value and current value, whether it is the horizontal or
// vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
// vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
// width to the width of the viewRect. The current values are set by comparing the offset between
// the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
// calling ShowControl.
 
// TEStyleSample-vertical max originally used line by line calculations-lineheight was a
// constant value so it was easy to figure out what the range should be and pin the value
// within range. Now we need to use max and min values in pixels rather than in nlines.
 
#pragma segment main
 
void    AdjustHV( Boolean isVert, ControlHandle control, DPtr theDoc, Boolean canRedraw )
{
    TEHandle    docTE;
    short       value;
    short       max;
    short       oldValue;
    short       oldMax;
    Rect        sizeRect;
    
    GetRectOfPage( theDoc, &sizeRect );
    docTE    = theDoc->theText;
    
    oldValue = GetCtlValue(control);
    oldMax   = GetCtlMax(control);
    if (isVert)
    {
        // new for TEStyleSample
        max = TEGetHeight((*docTE)->nLines, 0, docTE) -
                   ((*docTE)->viewRect.bottom - (*docTE)->viewRect.top);
    
    }
    else
        max = sizeRect.right - ((*docTE)->viewRect.right - (*docTE)->viewRect.left);
            
    max += kTextOffset + kTextOffset; // Allow over scroll by kTextOffset
            
    if (max < 0)
    max = 0; // check for negative values
        
    SetCtlMax(control, max);
    
    if (isVert)
        value = (*docTE)->viewRect.top - (*docTE)->destRect.top;
    else
        value = (*docTE)->viewRect.left - (*docTE)->destRect.left;
                
    value += kTextOffset;
            
    if (value < 0)
        value = 0;
    else
        if (value > max)
            value = max; // pin the value to within range
                    
    SetCtlValue(control, value);
    if (canRedraw && ((max != oldMax) || (value != oldValue)))
        ShowControl(control); // check to see if the control can be re-drawn
} // AdjustHV
 
 
#pragma segment Main
 
// Simply call the common adjust routine for the vertical and horizontal scrollbars.
 
void    AdjustScrollValues( DPtr theDoc, Boolean canRedraw )
{        
    AdjustHV(true,  theDoc->vScrollBar, theDoc, canRedraw);
    AdjustHV(false, theDoc->hScrollBar, theDoc, canRedraw);
} // AdjustScrollValues
 
 
// Return a rectangle that is inset from the portRect by the size of
//  the scrollbars and a little extra margin.
 
void    GetTERect( WindowPtr window, Rect *teRect )
{
    *teRect = window->portRect;
    (*teRect).bottom -= kScrollbarAdjust; // and for the scrollbars
    (*teRect).right  -= kScrollbarAdjust;
} // GetTERect
 
 
// Re-calculate the position and size of the viewRect and the scrollbars.
//  kScrollTweek compensates for off-by-one requirements of the scrollbars
//  to have borders coincide with the growbox.
 
void    AdjustScrollSizes( DPtr theDoc )
{  
    Rect    teRect;
    Rect    myPortRect;
    
    GetTERect(theDoc->theWindow, &teRect); // start with teRect
    myPortRect = theDoc->theWindow->portRect;
    
    (*(theDoc->theText))->viewRect = teRect;
    
    MoveControl(theDoc->vScrollBar, myPortRect.right - kScrollbarAdjust, - 1);
    SizeControl(theDoc->vScrollBar, 
                 kScrollbarWidth, 
                    (myPortRect.bottom - myPortRect.top) - (kScrollbarAdjust - kScrollTweek));
        
    MoveControl(theDoc->hScrollBar, - 1, myPortRect.bottom - kScrollbarAdjust);
    SizeControl(theDoc->hScrollBar,
                    (myPortRect.right - myPortRect.left) - (kScrollbarAdjust - kScrollTweek),
                        kScrollbarWidth);
} // AdjustScrollSizes
 
#pragma segment Window
 
// Turn off the controls by jamming a zero into their contrlVis fields
//  (HideControl erases them and we don't want that). If the controls are to
//  be resized as well, call the procedure to do that, then call the procedure
//  to adjust the maximum and current values. Finally reset the controls
//  to be visible if not in background.
 
void    AdjustScrollbars( DPtr theDoc, Boolean  needsResize )
{
    (*(theDoc->vScrollBar))->contrlVis = kControlInvisible; // turn them off
    (*(theDoc->hScrollBar))->contrlVis = kControlInvisible;
    
    if (needsResize) // move and size if needed
    AdjustScrollSizes(theDoc);
    
    AdjustScrollValues(theDoc, !needsResize); // fool with max and current value
    
    // Now, restore visibility in case we never had to ShowControl during adjustment
    
    if (!gInBackground)
    {
        (*(theDoc->vScrollBar))->contrlVis = kControlVisible; // turn them on
        (*(theDoc->hScrollBar))->contrlVis = kControlVisible;
    }
    else
    {       // make sure they stay invisible
        if ((*(theDoc->vScrollBar))->contrlVis)
            HideControl(theDoc->vScrollBar);
        if ((*(theDoc->vScrollBar))->contrlVis)
            HideControl(theDoc->hScrollBar);
    }
} // AdjustScrollbars
 
 
#pragma segment Window
 
void    GetWinContentRect( WindowPtr theWindow, Rect *r )
{
    *r         = theWindow->portRect;
    r->right  -= kScrollbarAdjust;
    r->bottom -= kScrollbarAdjust;
} // GetWinContentRect
 
    
#pragma segment Window
        
void    InvalidateDocument( DPtr theDoc )
{
    GrafPtr oldPort;
        
    GetPort(&oldPort);
    SetPort(theDoc->theWindow);
    InvalRect(&theDoc->theWindow->portRect);
    SetPort(oldPort);
} 
                        
 
// Called when the window has been resized to fix up the controls and content.
 
void    ResizeWindow( DPtr theDoc )
{
    AdjustScrollbars(theDoc, true);
    AdjustTE(theDoc);
    InvalidateDocument(theDoc);
} // ResizeWindow
 
 
// Called when the window has been resized to fix up the controls and content
 
void    ResizePageSetupForDocument( DPtr theDoc )
{
    Rect pageRect;
    
    GetRectOfPage( theDoc, &pageRect );
    (*(theDoc->theText))->destRect.right = (*(theDoc->theText))->destRect.left + pageRect.right;
    TECalText(theDoc->theText);
    
    ResizeWindow(theDoc);
} // ResizePageSetupForDocument
 
 
#pragma segment Main
 
// Common algorithm for setting the new value of a control. It returns the actual amount
//  the value of the control changed. Note the pinning is done for the sake of returning
//  the amount the control value changed.
 
void    CommonAction( ControlHandle control, short *amount )
{
    short   value;
    short   max;
    
    value   = GetCtlValue(control); // get current value
    max     = GetCtlMax(control);   // and max value
    *amount = value - *amount;
    if (*amount < 0)
        *amount = 0;
    else if (*amount > max)
        *amount = max;
    
    SetCtlValue(control, *amount);
    *amount = value - *amount;      // calculate true change
} // CommonAction
 
 
#pragma segment Main
 
// Determines how much to change the value of the vertical scrollbar by and how
//  much to scroll the TE record.
 
pascal void VActionProc( ControlHandle control, short part )
{
    short           amount;
    WindowPtr       window;
    DPtr            theDoc;
    
    if ( part )
    {
        window = (*control)->contrlOwner;
        theDoc = DPtrFromWindowPtr(window);
        switch (part)
        {
            case inUpButton:
            case inDownButton:
                amount = 24;
                break;
                
            case inPageUp:
            case inPageDown:
                amount = (*(theDoc->theText))->viewRect.bottom - 
                                 (*(theDoc->theText))->viewRect.top;
                break;
        } // case
        
        if (part == inDownButton || part == inPageDown)
        amount = -amount; // reverse direction
        
        CommonAction(control, &amount);
        
        if (amount)
        {
            TEScroll(0, amount, theDoc->theText);
            DrawPageExtras(theDoc);
        }
    } // if
} // VActionProc
 
 
#pragma segment Main
 
// Determines how much to change the value of the horizontal scrollbar by and how
//  much to scroll the TE record.
 
pascal void HActionProc(ControlHandle control, short part)
{
    short      amount;
    WindowPtr  window;
    DPtr       theDoc;
    
    if ( part )
    {
        window = (*control)->contrlOwner;
        theDoc = DPtrFromWindowPtr(window);
        switch ( part )
        {
            case inUpButton:
            case inDownButton:
                amount = kButtonScroll; // a few pixels
                break;
                
            case inPageUp:
            case inPageDown:
                amount = (*(theDoc->theText))->viewRect.right - 
                            (*(theDoc->theText))->viewRect.left; // a page
                break;
        } // switch
 
        if (part == inDownButton || part == inPageDown)
        amount = - amount; // reverse direction
        
        CommonAction(control, &amount);
        if (amount)
        {
            TEScroll(amount, 0, theDoc->theText);
            DrawPageExtras(theDoc);
        }
    } // if
} // HActionProc
 
 
//      Name:           ShowSelect
//      Purpose:        Scrolls the text selection into view.
 
#pragma segment Window
 
void    ShowSelect( DPtr theDoc )
{
    AdjustScrollbars(theDoc, false);
    
        //  Let TextEdit do the hard work of keeping the selection visibleÉ
    
    TEAutoView(true, theDoc->theText);
    TESelView(theDoc->theText);
    TEAutoView(false, theDoc->theText);
    
        //  Now rematch the text and the scrollbarsÉ
    
    SetCtlValue(theDoc->hScrollBar,
                    (*(theDoc->theText))->viewRect.left - 
                        (*(theDoc->theText))->destRect.left + kTextOffset);
    
    SetCtlValue(theDoc->vScrollBar,
                    (*(theDoc->theText))->viewRect.top - 
                        (*(theDoc->theText))->destRect.top  + kTextOffset);
} // ShowSelect
 
 
#pragma segment Window
 
void    OffsetWindow( WindowPtr aWindow )
{
    short   theWidth;
    short   theHeight;
    short   theHScreen;
    short   theVScreen;
    short   xWidth;
    short   xHeight;
    short   hMax;
    short   vMax;
    short   wLeft;
    short   wTop;
    long    docCount;
     
    theWidth  = aWindow->portRect.right - aWindow->portRect.left;
    theHeight = aWindow->portRect.bottom - aWindow->portRect.top + kTBarHeight;
    
    theHScreen = qd.screenBits.bounds.right  - qd.screenBits.bounds.left;
    theVScreen = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
    
    xWidth  = theHScreen - theWidth;
    xHeight = theVScreen - (theHeight + kMBarHeight);
    
    hMax = (xWidth / kVOffset) + 1;
    vMax = (xHeight / kVOffset) + 1;
    
    docCount = CountDocuments( );
    if ( ! IsVisible( aWindow ) )
        docCount++;     // Offset has been called on a window still hidden
    
    wLeft = ( docCount % hMax ) * kVOffset;
    wTop  = ( ( docCount % vMax ) * kVOffset ) + kTBarHeight + kMBarHeight;
    
    MoveWindow(aWindow, wLeft, wTop, false);
}
 
/*
// Returns the update region in local coordinates.
 
void    GetLocalUpdateRgn( WindowPtr window, RgnHandle localRgn )
{
    CopyRgn(((WindowPeek)window)->updateRgn, localRgn); // save old update region
    OffsetRgn(localRgn,
                window->portBits.bounds.left, 
                    window->portBits.bounds.top); // convert to local coords
} // GetLocalUpdateRgn
*/
 
#pragma segment Window
 
void    MyGrowWindow( WindowPtr w, Point p )
{
    GrafPtr savePort;
    long    theResult;
    Rect    r;
    
    GetPort(&savePort);
    SetPort(w);
    SetRect(&r, 80, 80, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom);
    theResult = GrowWindow(w, p, &r);
    if (theResult)
        IssueSizeWindow(w, LoWord(theResult), HiWord(theResult));
    
    SetPort(savePort);
}
 
 
#pragma segment Window
 
// Because windows can be hidden we must check for menu changes
 
void ShowMSWindow( WindowPtr theWindow )
{
    ShowWindow( theWindow );
    if ( FrontWindow( ) == theWindow )
    {
        DoActivate( GetNthWindow( 2 ), false );
        DoActivate( theWindow, true );
    }
    CheckMenus( );
}
 
void HideMSWindow( WindowPtr theWindow )
{
    Boolean     fActivate;
 
    fActivate = ( FrontWindow( ) == theWindow );
    HideWindow( theWindow );
    if ( fActivate )
    {
        DoActivate( theWindow, false );
        DoActivate( GetNthWindow( 1 ), true );
    }
    
    CheckMenus( );
}
 
#pragma segment Window
 
void    DoZoom( WindowPtr w, short c, Point p )
{
    GrafPtr savePort;
    
    GetPort(&savePort);
    SetPort(w);
    if (TrackBox(w, p, c))
    {
        EraseRect(&w->portRect);
        IssueZoomCommand(w, c);
    }
}
 
#pragma segment Window
 
void    DoContent( WindowPtr theWindow, EventRecord theEvent )
{
    short           cntlCode;
    short           part;
    short           value;
    ControlHandle   theControl;
    GrafPtr         savePort;
    Boolean         extend;
    DPtr            theDoc;
    Point           localPt;
    
    
    GetPort ( &savePort );
    SetPort ( theWindow );
    theDoc = DPtrFromWindowPtr ( theWindow );
    
    localPt = theEvent.where;
    GlobalToLocal ( &localPt );
    cntlCode = FindControl ( localPt, theWindow, &theControl );
    if ( cntlCode == 0 )
    {
        if ( UserWantsToDrag ( theWindow, theEvent.where ) )
        {
            if ( DoWindowContentDrag ( theWindow, &theEvent ) )
                TEClick ( localPt, false, theDoc->theText );
        }
        else
        {
            // only extend the selection if the shiftkey is down
            extend = (theEvent.modifiers & shiftKey);
            if ( PtInDocument ( localPt, theDoc ) )
                TEClick ( localPt, extend, theDoc->theText );
        }
    }
    else if ( cntlCode == inThumb )
    {
        value = GetCtlValue(theControl);
        part  = TrackControl(theControl, localPt, nil);
        if (part)
        {
            value -= GetCtlValue(theControl);
            if (value)
            {
                if (theControl == theDoc->vScrollBar)
                    TEScroll(0, value, theDoc->theText);
                else
                    TEScroll(value, 0, theDoc->theText);
                DrawPageExtras(theDoc);
            }
        }
    }
    else
    {
        if (theControl == theDoc->vScrollBar)
            part = TrackControl(theControl, localPt, (ControlActionUPP) gVScrollActionUPP);
        else
            part = TrackControl(theControl, localPt, (ControlActionUPP) gHScrollActionUPP);
    }
 
    SetPort(savePort);
}
 
 
 
void    DoBackgroundContent( WindowPtr theWindow, EventRecord theEvent)
{
    Point           thePoint;
    GrafPtr         savePort;
    RgnHandle       dragRgn;
    DPtr            theDoc;
 
    GetPort ( &savePort );
    SetPort ( theWindow );
    theDoc = DPtrFromWindowPtr ( theWindow );
    thePoint = theEvent.where;
    GlobalToLocal ( &thePoint );
    
    
    dragRgn = NewRgn ( );
    GetSelectedTextRgn ( theDoc, dragRgn );
    if ( PtInRgn ( thePoint, dragRgn ) )
    {
        if ( DoWindowContentDrag ( theWindow, &theEvent ) )
            SelectWindow (theWindow );
    }
    else
        SelectWindow ( theWindow );
    
    SetPort ( savePort );
 
    return;
}
 
#pragma segment Window
 
 
OSErr   DoActivate( WindowPtr theWindow, Boolean activate )
{
    Rect  r;
    DPtr  theDoc;
    OSErr err = noErr;
        
    if (theWindow)
        if (Ours(theWindow))
        {
            theDoc = DPtrFromWindowPtr(theWindow);
            SetPort(theWindow);
            DrawGrowIcon(theWindow);
            GetWinContentRect(theWindow, &r);
            InvalRect(&r);
            if ( activate )
            {
                if ( theDoc->windowType == kOrdinaryWind )                      
                    TEActivate(theDoc->theText);
                HiliteControl ( theDoc->vScrollBar, 0 );
                HiliteControl ( theDoc->hScrollBar, 0 );
                
                SetMenuItemState ( false, myMenus[editM], undoCommand );
                err = TEFromScrap();
                CheckMenus( );
            }
            else
            {
                TEDeactivate( theDoc->theText );
                HiliteControl ( theDoc->vScrollBar, 255 );
                HiliteControl ( theDoc->hScrollBar, 255 );
                
                err = ZeroScrap();
                err = TEToScrap();
            }
        }
 
    return err;
}
 
#pragma segment Window
 
void    GetPageEnds( short pageHeight, TEHandle theText,
                                PageEndsArray  pageBounds, short *nPages)
{
    short  pageBase;      // total pixel offset of pages so far
    short  thisLine;
    short  lastLine;
    short  pageSoFar;
    short  thisPage;      // Current page being calced
    short  thisLineH;     // Height of text line
    short  pageFirstLine; // Line # of top of page
        
    pageBase   = 0;
    thisLine   = 1;
    lastLine   = (*theText)->nLines;
    
    thisPage   = 0;
    pageSoFar  = 0;
    while ((thisLine <= lastLine) || (pageSoFar!=0))
    {
        pageFirstLine = thisLine;
        thisLineH     = TEGetHeight(thisLine, thisLine, theText);
        
        while ((thisLineH+pageSoFar<pageHeight) && (thisLine <= lastLine))
        {
            pageSoFar += thisLineH;
            thisLine++;
            thisLineH = TEGetHeight(thisLine, thisLine, theText);
        }
            
        if (pageSoFar)
        {
            pageBounds[thisPage] = pageSoFar+pageBase;
            pageBase  = pageBounds[thisPage];
            thisPage++;
            pageSoFar = 0;
        }
            
        //  Special case text line taller than page
        
        if ((thisLine  == pageFirstLine) &&
             (thisLineH > pageHeight))
            {
                do {
                    pageBounds[thisPage] = pageBase+pageHeight;
                    pageBase   = pageBounds[thisPage];
                    thisPage  += 1;
                    thisLineH -= pageHeight;
                } while (thisLineH >= pageHeight);
                pageSoFar = thisLineH;  // Carry bottom of large line to next page
                thisLine += 1;          // carry xs on as pageSoFar and start measuring next line
            }
    }
        
    *nPages = thisPage;
} // GetPageEnds
 
 
void    DrawPageBreaks( DPtr theDoc )
{
    PageEndsArray   pageEnds;
    short           nPages;
    short           ctr;
    short           lineBase;
    short           pageHeight;
    Rect            viewRect;
    Rect            pageRect;
                
    GetRectOfPage( theDoc, &pageRect );
    pageHeight = pageRect.bottom - pageRect.top;
            
    GetPageEnds(pageHeight, theDoc->theText, pageEnds, &nPages);
                                        
    lineBase = (*(theDoc->theText))->destRect.top;
    viewRect = (*(theDoc->theText))->viewRect;
    
    PenPat(&qd.gray);
    for (ctr = 0; ctr<nPages-1; ctr++)
    {
        MoveTo(viewRect.left, lineBase+pageEnds[ctr]);
        LineTo(viewRect.right,lineBase+pageEnds[ctr]);
    }
 
    PenNormal();
} // DrawPageBreaks
 
        
void    DrawPageExtras( DPtr theDoc )
{
    GrafPtr   oldPort;
    RgnHandle   oldClip;
    Rect          rectToClip;
        
    GetPort(&oldPort);
    SetPort(theDoc->theWindow);
            
    oldClip = NewRgn();
    GetClip(oldClip);
            
    GetWinContentRect(theDoc->theWindow,&rectToClip);
    ClipRect(&rectToClip);
                    
        // and then the page breaks
    DrawPageBreaks(theDoc);
    
    SetClip(oldClip);
    
    DisposeRgn(oldClip);
    
    SetPort(oldPort);
} // DrawPageExtras
 
 
void    DoUpdate( WindowPtr theWindow )
{
    GrafPtr     savePort;
    Rect        rectClip;
    DPtr        theDocument;
    
    
    theDocument = DPtrFromWindowPtr ( theWindow );
    if ( Ours ( theWindow ) )
    {
        GetPort ( &savePort );
        SetPort ( theWindow );
        BeginUpdate ( theWindow );
        
        ClipRect(&theWindow->portRect);
        EraseRect(&theWindow->portRect);
        DrawControls(theWindow);
        DrawGrowIcon(theWindow);
        
        GetWinContentRect(theWindow, &rectClip);
        ClipRect(&rectClip);
        
        TEUpdate(&theWindow->portRect, theDocument->theText);
        
        DrawPageExtras(theDocument);
        
        EndUpdate(theWindow);
        ClipRect(&theWindow->portRect);
        
        SetPort ( savePort );
    }
    
    return;
} // DoUpdate
 
 
#pragma segment Window
 
DPtr    NewDocument( Boolean isForOldDoc, WindowPtr behindWindow )
{
    Rect           destRect;
    Rect           viewRect;
    Rect           vScrollRect;
    Rect           hScrollRect;
    DPtr           myDoc;
    WindowPtr      myWindow;
    ControlHandle  vScroll;
    ControlHandle  hScroll;
    Str255         theName;
    Str255         newNumber;
    Rect           pageRect;
 
    myDoc = nil;
    myWindow = GetNewWindow(WindowID, nil, behindWindow);
    if (myWindow)
    {
        if (isForOldDoc==false)
        {
            GetWTitle(myWindow, theName);
            NumToString(++gNewDocCount, newNumber);
            if (gNewDocCount>1)
            {
                PLstrcat(theName, (unsigned char *)"\p #");
                PLstrcat(theName, newNumber);
                SetWTitle(myWindow, theName);
            }
        }
            
        OffsetWindow(myWindow);
 
        SetPort(myWindow);
 
        myDoc = (DPtr)NewPtr(sizeof(DocRec));
 
        SetWRefCon(myWindow, (long)myDoc);
 
        myDoc->theWindow  = myWindow;
        myDoc->windowType = kOrdinaryWind;
 
        vScrollRect = myWindow->portRect;
 
        vScrollRect.left  = vScrollRect.right - kScrollbarAdjust;
        vScrollRect.right = vScrollRect.left  + kScrollbarWidth;
 
        vScrollRect.bottom = vScrollRect.bottom - 14;
        vScrollRect.top    = vScrollRect.top - 1;
        
        vScroll = NewControl(myWindow, &vScrollRect, (unsigned char *)"\pScrollBar", true, 0, 0, 0, scrollBarProc, 0);
 
        hScrollRect = myWindow->portRect;
        hScrollRect.top = hScrollRect.bottom - kScrollbarAdjust;
        hScrollRect.bottom = hScrollRect.top + kScrollbarWidth;
 
        hScrollRect.right = hScrollRect.right - 14;
        hScrollRect.left  = hScrollRect.left - 1;
        hScroll = NewControl(myWindow, &hScrollRect, (unsigned char *)"\pScrollBar", true, 0, 0, 0, scrollBarProc, 0);
 
        myDoc->vScrollBar = vScroll;
        myDoc->hScrollBar = hScroll;
    
        myDoc->dirty = false;
 
        GetTERect(myWindow, &viewRect);
        destRect = viewRect;
 
        myDoc->theFont  = times;
        myDoc->theStyle = 0;
        myDoc->theSize  = 12;
 
        myDoc->documentJob   = nil;
        myDoc->thePrintSetup = nil;
        
        if (gGXIsPresent)
        {
            if (GXNewJob(&(myDoc->documentJob)) == noErr)
                GXInstallApplicationOverride(myDoc->documentJob,
                                             gxPrintingEventMsg,
                                             NewGXPrintingEventProc(GXPrintingEventOverride));
        }
        else
        {
            myDoc->thePrintSetup = (THPrint)NewHandle(sizeof(TPrint));
            
            PrOpen();
            PrintDefault(myDoc->thePrintSetup);
            PrClose();
        }
    
    
        GetRectOfPage( myDoc, &pageRect );
        destRect.right = destRect.left + pageRect.right;
        
        OffsetRect(&destRect, kTextOffset, kTextOffset);
        
        TextFont(times);
        TextSize(12);
        TextFace(0);
 
        myDoc->theText = TEStylNew(&destRect, &viewRect);
 
// SetClikLoop(@AutoScroll, myDoc->theText);
 
        myDoc->theFileName[0] = 0;
        myDoc->everSaved      = false;
        myDoc->theWindow      = myWindow;
        ResizeWindow(myDoc);
        
        InstallDragHandlers ( myWindow );
        
        myDoc->theScriptID = kOSANullScript;
    }
 
    return(myDoc);
}
 
 
#pragma segment Window
 
void    CloseMyWindow( WindowPtr aWindow )
{
    DPtr     aDocument;
    TEHandle theText;
 
    if (IsThisResultWind(aWindow))
        CloseResultWind(aWindow);
    else
    {
        HideMSWindow(aWindow);
        aDocument = DPtrFromWindowPtr(aWindow);
        
        theText = aDocument->theText;
        TEDispose(theText);
        
        if (aDocument->thePrintSetup)
            DisposHandle((Handle)aDocument->thePrintSetup);
        
        if (aDocument->documentJob)
            GXDisposeJob(aDocument->documentJob);
        
        RemoveDragHandlers ( aWindow );
        
        DisposPtr((Ptr)aDocument);
    
        DisposeWindow(aWindow);
    }
}
 
            
//      Name     :  PrintWindow
//      Function :  Prints the document supplied in theDoc. askUser controls interaction
//                   with the user.
//                           
//                  Uses extra memory equal to the size of the textedit use in the 
//                   printed document.
    
void    PrintWindow( DPtr theDoc, Boolean askUser )
{
    GrafPtr         oldPort;
    TEHandle        printerTE;
    TPPrPort        printerPort;
    Rect            printView;
    PageEndsArray   pageBounds;
    short           nPages;
    short           pageCtr;
    Boolean         abort;
    Rect            rectToClip;
    TPrStatus       thePrinterStatus;
    DialogPtr       progressDialog;
    WindowPtr       tempWind;                 // Temp window to create TERec in 
    Rect            tempWindRect = {0,0,0,0}; // Bounds for temp window
    abort = false;
        
 
    //  Preserve the current port
 
    GetPort(&oldPort);
    PrOpen();
        
    if (askUser)
        abort = !PrJobDialog(theDoc->thePrintSetup);
            
    if (abort)
    {
        PrClose();
        return;
    }
        
    progressDialog = GetNewDialog(1005, nil, (WindowPtr)-1);
        
    DrawDialog(progressDialog);
        
    printerPort = PrOpenDoc(theDoc->thePrintSetup, nil, nil);
    SetPort((GrafPtr)printerPort);
        
    // Create a temporary window(which is not shown)
    
    tempWind = NewWindow( nil, &tempWindRect, "\p",
                                false, documentProc, (WindowPtr)-1, false, 0);
    
    // Duplicate the text edit rec
    printView = (*(theDoc->thePrintSetup))->prInfo.rPage;
    DuplicateStyleTERec ( theDoc->theText, &printerTE, &printView, (GrafPtr)tempWind );
    
    // Work out the offsets
    
    (*printerTE)->destRect = printView; // GetPageEnds calls TECalText
        
    GetPageEnds(printView.bottom-printView.top,
                            printerTE,
                            pageBounds,
                            &nPages);
        
    TEDeactivate(printerTE);
    
    // Set the TERec to the printer port
    (*printerTE)->inPort = (GrafPtr)printerPort;
    
    for (pageCtr = 0; pageCtr <= nPages-1; pageCtr++)
        if (!abort)
        {
            PrOpenPage(printerPort, nil);
                                        
            rectToClip = printView;
            
            if (pageCtr > 0)
                rectToClip.bottom = rectToClip.top + (pageBounds[pageCtr]-pageBounds[pageCtr-1]);
            else
                rectToClip.bottom = rectToClip.top + pageBounds[pageCtr];
                
            ClipRect(&rectToClip);
            
            if (PrError() == iPrAbort)
                abort = true;
                
            if (! abort)
                TEUpdate(&printView, printerTE);
                                    
            if (PrError() == iPrAbort)
                abort = true;
                
            PrClosePage(printerPort);
            
            TEScroll(0,rectToClip.top-rectToClip.bottom, printerTE);
        }
    
    TEDispose(printerTE);
    DisposeWindow ( tempWind );
    PrCloseDoc(printerPort);
    
    if (( (*(theDoc->thePrintSetup))->prJob.bJDocLoop == bSpoolLoop ) && 
            ( PrError() == noErr ) && (! abort))
        PrPicFile( theDoc->thePrintSetup, nil, nil, nil, &thePrinterStatus);
    
    PrClose();
    
    DisposDialog(progressDialog);
    
    SetPort(oldPort);
    InvalRect(&oldPort->portRect);
}