Source/SVEditWindow.c

/*
    File:       SVEditWindow.c
 
    Contains:   
 
    Written by: Original version by Jon Lansdell and Nigel Humphreys.
                3.1 updates by Greg Sutton. 
 
    Copyright:  Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                7/19/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1 and removed GX printing(now obsolete
                11/1/95     DS              Made Changes for GX Printing.
                10/12/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
                
 
*/
 
#include <Scrap.h>
#include <Packages.h>
#include <DriverServices.h>
#include <TextUtils.h>
 
#include "SVEditWindow.h"
#include "SVDrag.h"
#include "SVAERecording.h"
#include "SVEditPrinting.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)
        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.
*/
pascal void AdjustTE(DPtr theDoc)
  {
       short    h;
         short    v;
         TEHandle myText;
         
         myText = theDoc->theText;
       h = ((*myText)->viewRect.left - (*myText)->destRect.left) -
          GetControlValue(theDoc->hScrollBar) + kTextOffset;
                         
         v = ((*myText)->viewRect.top - (*myText)->destRect.top) - 
              GetControlValue(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
 
pascal 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 = GetControlValue(control);
    oldMax   = GetControlMaximum(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 */
            
    SetControlMaximum(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 */
                        
        SetControlValue(control, value);
        if (canRedraw && ((max != oldMax) || (value != oldValue)))
            ShowControl(control); /* check to see if the control can be re-drawn */
            
    } /* AdjustHV */
 
#pragma segment Main
 
pascal void AdjustScrollValues(DPtr theDoc, Boolean canRedraw)
 
/* Simply call the common adjust routine for the vertical and horizontal scrollbars. */
 
  {        
        AdjustHV(true,  theDoc->vScrollBar, theDoc, canRedraw);
        AdjustHV(false, theDoc->hScrollBar, theDoc, canRedraw);
    }        /* AdjustScrollValues */
 
 
pascal void GetTERect(WindowPtr window, Rect *teRect)
 
/*   return a rectangle that is inset from the portRect by the size of
     the scrollbars and a little extra margin. */
 
  {
    *teRect = window->portRect;
    (*teRect).bottom -= kScrollbarAdjust; /* and for the scrollbars */
        (*teRect).right  -= kScrollbarAdjust;
  }         /* GetTERect */
 
pascal void AdjustScrollSizes(DPtr theDoc)
 
/* 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. */
 
 {  
   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
 
pascal void AdjustScrollbars(DPtr theDoc, Boolean  needsResize)
 
/* 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. */
  {
 
        (*(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
 
pascal void GetWinContentRect(WindowPtr theWindow, Rect *r)
    {
        *r         = theWindow->portRect;
        r->right  -= kScrollbarAdjust;
        r->bottom -= kScrollbarAdjust;
    }  /* GetWinContentRect */
            
#pragma segment Window
        
pascal void InvalidateDocument(DPtr theDoc)
    {
        GrafPtr oldPort;
            
    GetPort(&oldPort);
        SetPort(theDoc->theWindow);
        InvalRect(&theDoc->theWindow->portRect);
        SetPort(oldPort);
    } 
                        
pascal void DoResizeWindow(DPtr theDoc)
 
/* Called when the window has been resized to fix up the controls and content */
 
    {
        AdjustScrollbars(theDoc, true);
        AdjustTE(theDoc);
        InvalidateDocument(theDoc);
    }         /* ResizeWindow */
 
pascal void ResizePageSetupForDocument(DPtr theDoc)
 
    /* Called when the window has been resized to fix up the controls and content */
 
  {
        Rect pageRect;
        
        GetRectOfPage( theDoc, &pageRect );
        (*(theDoc->theText))->destRect.right = (*(theDoc->theText))->destRect.left
                                                            + pageRect.right;
        TECalText(theDoc->theText);
        
        DoResizeWindow(theDoc);
    }         /* ResizePageSetupForDocument */
 
#pragma segment Main
 
pascal void CommonAction(ControlHandle control, short *amount)
 
/* 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. */
 
    {
        short   value;
        short   max;
 
        value   = GetControlValue(control); /* get current value */
        max     = GetControlMaximum(control); /* and max value */
        *amount = value - *amount;
        if (*amount < 0)
          *amount = 0;
        else
            if (*amount > max)
                *amount = max;
        
        SetControlValue(control, *amount);
        *amount = value - *amount; /* calculate true change */
    }         /* CommonAction */
 
#pragma segment Main
 
pascal void VActionProc(ControlHandle control, short part)
 
/* Determines how much to change the value of the vertical scrollbar by and how
  much to scroll the TE record. */
 
  {
        short           amount;
        WindowPtr       window;
        DPtr            theDoc;
        
    if (part)
      {
        window = (*control)->contrlOwner;
                theDoc = DPtrFromWindowPtr(window);
                switch (part) {
                  case kControlUpButtonPart:
                    case kControlDownButtonPart : amount = 24;
                                        break;
                  case kControlPageUpPart:
                    case kControlPageDownPart   : amount = (*(theDoc->theText))->viewRect.bottom - 
                                                 (*(theDoc->theText))->viewRect.top;
                                        break;
                                                            
                }   /* case */
                
                if (part == kControlDownButtonPart || part == kControlPageDownPart)
          amount = -amount; /* reverse direction */
            
              CommonAction(control, &amount);
            
                if (amount)
                    {
                        TEScroll(0, amount, theDoc->theText);
                        DrawPageExtras(theDoc);
                    }
            }     /* if */
    }  /* VActionProc */
 
#pragma segment Main
 
pascal void HActionProc(ControlHandle control, short part)
 
/* Determines how much to change the value of the horizontal scrollbar by and how
  much to scroll the TE record. */
 
 {
   short      amount;
   WindowPtr  window;
   DPtr       theDoc;
 
        if  (part)
            {
                window = (*control)->contrlOwner;
                theDoc = DPtrFromWindowPtr(window);
                switch (part) {
                  case  kControlUpButtonPart   :
                    case  kControlDownButtonPart : amount = kButtonScroll; /* a few pixels */
                                         break;
                  case  kControlPageUpPart   :
                    case  kControlPageDownPart :   amount = (*(theDoc->theText))->viewRect.right - 
                                                  (*(theDoc->theText))->viewRect.left; /* a page */
                                         break;
                }   /* switch */
                if (part == kControlDownButtonPart || part == kControlPageDownPart)
                    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
 
pascal 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É
        */
 
        SetControlValue(theDoc->hScrollBar,
                                (*(theDoc->theText))->viewRect.left - 
                                (*(theDoc->theText))->destRect.left + kTextOffset);
 
        SetControlValue(theDoc->vScrollBar,
                                (*(theDoc->theText))->viewRect.top - 
                                (*(theDoc->theText))->destRect.top  + kTextOffset);
 
  }  /* ShowSelect */
 
#pragma segment Window
 
pascal void OffsetWindow(WindowPtr aWindow)
  {
     short theWidth;
     short theHeight;
     short theHScreen;
     short theVScreen;
     short xWidth;
     short xHeight;
     short hMax;
     short vMax;
     short wLeft;
     short wTop;
         
     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;
 
         gWCount++;
 
     wLeft = (gWCount % hMax) * kVOffset;
     wTop  = ((gWCount % vMax) * kVOffset) + kTBarHeight + kMBarHeight;
 
     MoveWindow(aWindow, wLeft, wTop, false);
    }
 
pascal void GetLocalUpdateRgn(WindowPtr window, RgnHandle localRgn)
 
    /* Returns the update region in local coordinates */
 
    {
        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
 
 
 
pascal 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
 
pascal 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
 
pascal 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 == kControlIndicatorPart )
    {
        value = GetControlValue(theControl);
        part  = TrackControl(theControl, localPt, nil);
        if (part)
        {
            value -= GetControlValue(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;
}
 
 
 
/*
pascal void DoContent(WindowPtr    theWindow,
                      EventRecord  theEvent)
 
  {
      short         cntlCode;
      short         part;
      ControlHandle theControl;
      GrafPtr       savePort;
      Boolean       extend;
      DPtr          theDoc;
      short         value;
 
    GetPort(&savePort);
    SetPort(theWindow);
    theDoc = DPtrFromWindowPtr(theWindow);
 
    GlobalToLocal(&theEvent.where);
    cntlCode = FindControl(theEvent.where, theWindow, &theControl);
    if (cntlCode == 0)
      {
              //only extend the selection if the shiftkey is down
        extend = (theEvent.modifiers & shiftKey);
 
                if (PtInRect(theEvent.where, &(*(theDoc->theText))->viewRect))
                    TEClick(theEvent.where, extend, theDoc->theText);
            }
    else
      if (cntlCode == kControlIndicatorPart)
        {
                    value = GetCtlValue(theControl);
                    part  = TrackControl(theControl, theEvent.where, 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, theEvent.where, gVScrollActionUPP);
                else
                    part = TrackControl(theControl, theEvent.where, gHScrollActionUPP);
 
        SetPort(savePort);
    }
*/  
 
#pragma segment Window
 
 
pascal OSErr DoActivate(WindowPtr theWindow, Boolean   activate)
{
    OSErr err;
    Rect  r;
    DPtr  theDoc;
    
 
      err = noErr;
            
            if (theWindow)
                if (Ours(theWindow))
                    {
                        theDoc = DPtrFromWindowPtr(theWindow);
                        SetPort(theWindow);
                        DrawGrowIcon(theWindow);
                        GetWinContentRect(theWindow, &r);
                        InvalRect(&r);
                        if (activate)
                            {
                                TEActivate(theDoc->theText);
                                HiliteControl ( theDoc->vScrollBar, 0 );
                                HiliteControl ( theDoc->hScrollBar, 0 );
                                
                                DisableItem(myMenus[editM], undoCommand);
                                err = TEFromScrap();
                                if (gWCount == 0)
                                    SetShortMenus();
                            }
                        else
                            {
                                TEDeactivate(theDoc->theText);
                                HiliteControl ( theDoc->vScrollBar, 255 );
                                HiliteControl ( theDoc->hScrollBar, 255 );
                                
                                err = ZeroScrap();
                                err = TEToScrap();
                            }
                    }
          return(err);
        }
 
#pragma segment Window
 
pascal 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 */
        
pascal 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 */
            
pascal 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 */
 
pascal 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;
 
      if (!gWCount)
          SetLongMenus();
 
        myDoc = nil;
        myWindow = GetNewWindow(WindowID, nil, behindWindow);
        if (myWindow)
            {
                if (isForOldDoc==false)
                    {
                        GetWTitle(myWindow, theName);
                        NumToString(++gNewDocCount, newNumber);
                        if (gNewDocCount>1)
                            {
                                PStrCat(theName, (unsigned char *)"\p #");
                                PStrCat(theName, newNumber);
                                SetWTitle(myWindow, theName);
                            }
                    }
                    
                OffsetWindow(myWindow);
 
                SetPort(myWindow);
 
                myDoc = (DPtr)NewPtr(sizeof(DocRec));
 
                SetWRefCon(myWindow, (long)myDoc);
 
                myDoc->theWindow = myWindow;
 
                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->lastID = 0;
                
            
                myDoc->dirty = false;
 
                GetTERect(myWindow, &viewRect);
                destRect = viewRect;
 
                myDoc->theFont  = kFontIDTimes;
                myDoc->theStyle = 0;
                myDoc->theSize  = 12;
 
                myDoc->documentJob   = nil;
                myDoc->thePrintSetup = nil;
                
                
                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(kFontIDTimes);
                TextSize(12);
                TextFace(0);
 
                myDoc->theText = TEStyleNew(&destRect, &viewRect);
 
    /*
    SetClikLoop(@AutoScroll, myDoc->theText);
    */
 
                myDoc->theFileName[0] = 0;
                myDoc->everSaved      = false;
                myDoc->theWindow      = myWindow;
                DoResizeWindow(myDoc);
                
                InstallDragHandlers ( myWindow );
            }
    return(myDoc);
  }
 
#pragma segment Window
 
pascal void CloseMyWindow(WindowPtr aWindow)
{
    DPtr     aDocument;
    TEHandle theText;
 
    HideWindow(aWindow);
    aDocument = DPtrFromWindowPtr(aWindow);
    
    theText = aDocument->theText;
    TEDispose(theText);
    
    if (aDocument->thePrintSetup)
        DisposeHandle((Handle)aDocument->thePrintSetup);
    
    if (aDocument->documentJob)
        //GXDisposeJob(aDocument->documentJob);
    
    RemoveDragHandlers ( aWindow );
    
    DisposePtr((Ptr)aDocument);
    DisposeWindow(aWindow);
    
    gWCount--;
    
    /*if there are no more windows open, set up the short menus*/
    if (gWCount == 0)
        SetShortMenus();
    
}
 
            
    /*
        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.
    */
    
pascal 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();
        
        DisposeDialog(progressDialog);
        
        SetPort(oldPort);
        InvalRect(&oldPort->portRect);
    }