home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Sample Applications / MenuScripter 1.0d4.1 / MenuScripter Source / MSWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-24  |  25.5 KB  |  1,012 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSWindow.c
  3.     
  4.     Version 1.0d4
  5.     
  6.     Copyright © Apple Computer UK Ltd. 1992
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : UK Developer Technical Support
  11.     AppleLink   : UK.DTS
  12. */
  13.     
  14. #include <Scrap.h>
  15. #include <Packages.h>
  16. #include <PLStringFuncs.h>
  17. #include "MSWindow.h"
  18. #include "MSEditions.h"
  19.  
  20. #define       kControlInvisible    0
  21. #define       kControlVisible      0xFF             
  22. #define       kScrollbarWidth        16
  23. #define       kScrollbarAdjust        (kScrollbarWidth - 1)
  24. #define       kScrollTweek              2
  25. #define             kTextOffset                   5 
  26. #define       kButtonScroll             10
  27.             
  28. #define             kMaxPages              1000 /* Assumes pages > 32 pixels high */
  29.             
  30. #define             kHOffset                        20   /* Stagger window offsets */
  31. #define             kVOffset                        20
  32.             
  33. #define             kTBarHeight                20
  34. #define             kMBarHeight                20
  35.             
  36. typedef short    PageEndsArray[kMaxPages];
  37.  
  38. #pragma segment Window
  39.  
  40. pascal DPtr DPtrFromWindowPtr(WindowPtr w)
  41.   {
  42.     if (w)
  43.           return((DPtr)GetWRefCon(w));
  44.         else
  45.           return(nil);
  46.     } /* DPtrFromWindowPtr */
  47.     
  48. #pragma segment main
  49.  
  50. /* 
  51.   Scroll the TERec around to match up to the potentially updated scrollbar
  52.   values. This is really useful when the window resizes such that the
  53.   scrollbars become inactive and the TERec had been previously scrolled.
  54. */
  55. pascal void AdjustTE(DPtr theDoc)
  56.   {
  57.        short    h;
  58.          short    v;
  59.          TEHandle myText;
  60.          
  61.          myText = theDoc->theText;
  62.        h = ((*myText)->viewRect.left - (*myText)->destRect.left) -
  63.           GetCtlValue(theDoc->hScrollBar) + kTextOffset;
  64.                          
  65.          v = ((*myText)->viewRect.top - (*myText)->destRect.top) - 
  66.               GetCtlValue(theDoc->vScrollBar) + kTextOffset;
  67.                                  
  68.      if (h || v)
  69.              {
  70.                TEScroll(h, v, theDoc->theText);
  71.                DrawPageExtras(theDoc);
  72.              }
  73.                     
  74.     }  /* AdjustTE */
  75.     
  76.     
  77. /*Calculate the new control maximum value and current value, whether it is the horizontal or
  78. vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
  79. vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
  80. width to the width of the viewRect. The current values are set by comparing the offset between
  81. the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
  82. calling ShowControl.*/
  83.  
  84. /*TEStyleSample-vertical max originally used line by line calculations-lineheight was a
  85. constant value so it was easy to figure out what the range should be and pin the value
  86. within range. Now we need to use max and min values in pixels rather than in nlines*/
  87.  
  88. #pragma segment main
  89.  
  90. pascal void AdjustHV(Boolean        isVert,
  91.                      ControlHandle  control,
  92.                          DPtr           theDoc,
  93.                                          Boolean        canRedraw)
  94.   {
  95.       TEHandle    docTE;
  96.     short       value;
  97.         short           max;
  98.         short           oldValue;
  99.         short           oldMax;
  100.         Rect             sizeRect;
  101.  
  102.       sizeRect = theDoc->pageSize;
  103.         docTE    = theDoc->theText;
  104.     
  105.         oldValue = GetCtlValue(control);
  106.     oldMax   = GetCtlMax(control);
  107.     if (isVert)
  108.       {
  109.             /* new for TEStyleSample */
  110.                  max = TEGetHeight((*docTE)->nLines, 0, docTE) -
  111.                        ((*docTE)->viewRect.bottom - (*docTE)->viewRect.top);
  112.  
  113.        }
  114.     else
  115.       max = sizeRect.right - ((*docTE)->viewRect.right - (*docTE)->viewRect.left);
  116.                 
  117.         max += kTextOffset + kTextOffset; /* Allow over scroll by kTextOffset */
  118.                 
  119.     if (max < 0)
  120.       max = 0; /* check for negative values */
  121.             
  122.     SetCtlMax(control, max);
  123.         
  124.       if (isVert)
  125.             value = (*docTE)->viewRect.top - (*docTE)->destRect.top;
  126.         else
  127.             value = (*docTE)->viewRect.left - (*docTE)->destRect.left;
  128.                     
  129.         value += kTextOffset;
  130.                 
  131.         if (value < 0)
  132.             value = 0;
  133.         else
  134.             if (value > max)
  135.                 value = max; /* pin the value to within range */
  136.                         
  137.         SetCtlValue(control, value);
  138.         if (canRedraw && ((max != oldMax) || (value != oldValue)))
  139.             ShowControl(control); /* check to see if the control can be re-drawn */
  140.             
  141.     } /* AdjustHV */
  142.  
  143. #pragma segment Main
  144.  
  145. pascal void AdjustScrollValues(DPtr theDoc, Boolean canRedraw)
  146.  
  147. /* Simply call the common adjust routine for the vertical and horizontal scrollbars. */
  148.  
  149.   {        
  150.         AdjustHV(true,  theDoc->vScrollBar, theDoc, canRedraw);
  151.         AdjustHV(false, theDoc->hScrollBar, theDoc, canRedraw);
  152.     }        /* AdjustScrollValues */
  153.  
  154. pascal void GetTERect(WindowPtr window,
  155.                       Rect  *teRect)
  156.  
  157. /*   return a rectangle that is inset from the portRect by the size of
  158.      the scrollbars and a little extra margin. */
  159.  
  160.   {
  161.     *teRect = window->portRect;
  162.     (*teRect).bottom -= kScrollbarAdjust; /* and for the scrollbars */
  163.         (*teRect).right  -= kScrollbarAdjust;
  164.   }         /* GetTERect */
  165.  
  166. pascal void AdjustScrollSizes(DPtr theDoc)
  167.  
  168. /* Re-calculate the position and size of the viewRect and the scrollbars.
  169.   kScrollTweek compensates for off-by-one requirements of the scrollbars
  170.   to have borders coincide with the growbox. */
  171.  
  172.  {  
  173.    Rect    teRect;
  174.      Rect    myPortRect;
  175.  
  176.    GetTERect(theDoc->theWindow, &teRect); /*start with teRect*/
  177.      myPortRect = theDoc->theWindow->portRect;
  178.      
  179.      (*(theDoc->theText))->viewRect = teRect;
  180.  
  181.    MoveControl(theDoc->vScrollBar, myPortRect.right - kScrollbarAdjust, - 1);
  182.    SizeControl(theDoc->vScrollBar, 
  183.                  kScrollbarWidth, 
  184.                  (myPortRect.bottom - myPortRect.top) - (kScrollbarAdjust - kScrollTweek));
  185.             
  186.     MoveControl(theDoc->hScrollBar, - 1, myPortRect.bottom - kScrollbarAdjust);
  187.     SizeControl(theDoc->hScrollBar,
  188.                 (myPortRect.right - myPortRect.left) - (kScrollbarAdjust - kScrollTweek),
  189.                             kScrollbarWidth);
  190. }        /* AdjustScrollSizes */
  191.  
  192. #pragma segment Window
  193.  
  194. pascal void AdjustScrollbars(DPtr theDoc, Boolean  needsResize)
  195.  
  196. /* Turn off the controls by jamming a zero into their contrlVis fields
  197.   (HideControl erases them and we don't want that). If the controls are to
  198.   be resized as well, call the procedure to do that, then call the procedure
  199.   to adjust the maximum and current values. Finally reset the controls
  200.   to be visible if not in background. */
  201.   {
  202.  
  203.         (*(theDoc->vScrollBar))->contrlVis = kControlInvisible; /* turn them off */
  204.         (*(theDoc->hScrollBar))->contrlVis = kControlInvisible;
  205.  
  206.         if (needsResize) /* move and size if needed */
  207.             AdjustScrollSizes(theDoc);
  208.  
  209.         AdjustScrollValues(theDoc, !needsResize); /* fool with max and current value */
  210.  
  211.     /* Now, restore visibility in case we never had to ShowControl during adjustment */
  212.  
  213.         if (!gInBackground)
  214.             {
  215.                 (*(theDoc->vScrollBar))->contrlVis = kControlVisible; /* turn them on */
  216.                 (*(theDoc->hScrollBar))->contrlVis = kControlVisible;
  217.             }
  218.         else
  219.             { /* make sure they stay invisible */
  220.                 if ((*(theDoc->vScrollBar))->contrlVis)
  221.                     HideControl(theDoc->vScrollBar);
  222.                 if ((*(theDoc->vScrollBar))->contrlVis)
  223.                     HideControl(theDoc->hScrollBar);
  224.             }
  225.     }        /* AdjustScrollbars */
  226.  
  227. #pragma segment Window
  228.  
  229. pascal void GetWinContentRect(WindowPtr theWindow, Rect *r)
  230.     {
  231.         *r         = theWindow->portRect;
  232.         r->right  -= kScrollbarAdjust;
  233.         r->bottom -= kScrollbarAdjust;
  234.     }  /* GetWinContentRect */
  235.             
  236. #pragma segment Window
  237.         
  238. pascal void InvalidateDocument(DPtr theDoc)
  239.     {
  240.         GrafPtr oldPort;
  241.             
  242.     GetPort(&oldPort);
  243.         SetPort(theDoc->theWindow);
  244.         InvalRect(&theDoc->theWindow->portRect);
  245.         SetPort(oldPort);
  246.     } 
  247.                         
  248. pascal void ResizeWindow(DPtr theDoc)
  249.  
  250. /* Called when the window has been resized to fix up the controls and content */
  251.  
  252.     {
  253.         AdjustScrollbars(theDoc, true);
  254.         AdjustTE(theDoc);
  255.         InvalidateDocument(theDoc);
  256.     }         /* ResizeWindow */
  257.  
  258. pascal void ResizePageSetupForDocument(DPtr theDoc)
  259.  
  260.     /* Called when the window has been resized to fix up the controls and content */
  261.  
  262.   {
  263.         theDoc->pageSize = (*(theDoc->thePrintSetup))->prInfo.rPage;
  264.         
  265.         OffsetRect(&(theDoc->pageSize), -theDoc->pageSize.left, -theDoc->pageSize.top);
  266.                 
  267.         (*(theDoc->theText))->destRect.right = (*(theDoc->theText))->destRect.left +
  268.                                                theDoc->pageSize.right;
  269.         
  270.         TECalText(theDoc->theText);
  271.         
  272.         ResizeWindow(theDoc);
  273.     }         /* ResizePageSetupForDocument */
  274.  
  275. #pragma segment Main
  276.  
  277. pascal void CommonAction(ControlHandle control,
  278.                                                short *amount)
  279.  
  280. /* Common algorithm for setting the new value of a control. It returns the actual amount
  281. the value of the control changed. Note the pinning is done for the sake of returning
  282. the amount the control value changed. */
  283.  
  284.     {
  285.         short   value;
  286.         short   max;
  287.  
  288.         value   = GetCtlValue(control); /* get current value */
  289.         max     = GetCtlMax(control); /* and max value */
  290.         *amount = value - *amount;
  291.         if (*amount < 0)
  292.           *amount = 0;
  293.         else
  294.             if (*amount > max)
  295.                 *amount = max;
  296.         
  297.         SetCtlValue(control, *amount);
  298.         *amount = value - *amount; /* calculate true change */
  299.     }         /* CommonAction */
  300.  
  301. #pragma segment Main
  302.  
  303. pascal void VActionProc(ControlHandle control, short part)
  304.  
  305. /* Determines how much to change the value of the vertical scrollbar by and how
  306.   much to scroll the TE record. */
  307.  
  308.   {
  309.         short           amount;
  310.         WindowPtr       window;
  311.         DPtr            theDoc;
  312.         
  313.     if (part)
  314.       {
  315.         window = (*control)->contrlOwner;
  316.                 theDoc = DPtrFromWindowPtr(window);
  317.                 switch (part) {
  318.                   case inUpButton:
  319.                     case inDownButton : amount = 24;
  320.                                         break;
  321.                   case inPageUp:
  322.                     case inPageDown   : amount = (*(theDoc->theText))->viewRect.bottom - 
  323.                                                  (*(theDoc->theText))->viewRect.top;
  324.                                         break;
  325.                                                             
  326.                 }   /* case */
  327.                 
  328.                 if (part == inDownButton || part == inPageDown)
  329.           amount = -amount; /* reverse direction */
  330.             
  331.               CommonAction(control, &amount);
  332.             
  333.                 if (amount)
  334.                     {
  335.                         TEScroll(0, amount, theDoc->theText);
  336.                         DrawPageExtras(theDoc);
  337.                     }
  338.             }     /* if */
  339.     }  /* VActionProc */
  340.  
  341. #pragma segment Main
  342.  
  343. pascal void HActionProc(ControlHandle control, short part)
  344.  
  345. /* Determines how much to change the value of the horizontal scrollbar by and how
  346.   much to scroll the TE record. */
  347.  
  348.  {
  349.    short      amount;
  350.    WindowPtr  window;
  351.    DPtr       theDoc;
  352.  
  353.         if  (part)
  354.             {
  355.                 window = (*control)->contrlOwner;
  356.                 theDoc = DPtrFromWindowPtr(window);
  357.                 switch (part) {
  358.                   case  inUpButton   :
  359.                     case  inDownButton : amount = kButtonScroll; /* a few pixels */
  360.                                          break;
  361.                   case  inPageUp   :
  362.                     case  inPageDown :   amount = (*(theDoc->theText))->viewRect.right - 
  363.                                                   (*(theDoc->theText))->viewRect.left; /* a page */
  364.                                          break;
  365.                 }   /* switch */
  366.                 if (part == inDownButton || part == inPageDown)
  367.                     amount = - amount; /* reverse direction */
  368.                     
  369.                 CommonAction(control, &amount);
  370.                 if (amount)
  371.                     {
  372.                         TEScroll(amount, 0, theDoc->theText);
  373.                         DrawPageExtras(theDoc);
  374.                     }
  375.             }     /* if */
  376.     }         /* HActionProc */
  377.  
  378. /**-----------------------------------------------------------------------
  379.         Name:             ShowSelect
  380.         Purpose:        Scrolls the text selection into view.
  381.     -----------------------------------------------------------------------**/
  382.  
  383. #pragma segment Window
  384.  
  385. pascal void ShowSelect(DPtr theDoc)
  386.   {
  387.     AdjustScrollbars(theDoc, false);
  388.  
  389.         /*
  390.             Let TextEdit do the hard work of keeping the selection visible…
  391.         */
  392.  
  393.         TEAutoView(true, theDoc->theText);
  394.         TESelView(theDoc->theText);
  395.         TEAutoView(false, theDoc->theText);
  396.  
  397.         /*
  398.             Now rematch the text and the scrollbars…
  399.         */
  400.  
  401.         SetCtlValue(theDoc->hScrollBar,
  402.                                 (*(theDoc->theText))->viewRect.left - 
  403.                                 (*(theDoc->theText))->destRect.left + kTextOffset);
  404.  
  405.         SetCtlValue(theDoc->vScrollBar,
  406.                                 (*(theDoc->theText))->viewRect.top - 
  407.                                 (*(theDoc->theText))->destRect.top  + kTextOffset);
  408.  
  409.   }  /* ShowSelect */
  410.  
  411. #pragma segment Window
  412.  
  413. pascal void OffsetWindow(WindowPtr aWindow)
  414.   {
  415.      short theWidth;
  416.      short theHeight;
  417.      short theHScreen;
  418.      short theVScreen;
  419.      short xWidth;
  420.      short xHeight;
  421.      short hMax;
  422.      short vMax;
  423.      short wLeft;
  424.      short wTop;
  425.          
  426.      theWidth  = aWindow->portRect.right - aWindow->portRect.left;
  427.      theHeight = aWindow->portRect.bottom - aWindow->portRect.top + kTBarHeight;
  428.  
  429.      theHScreen = qd.screenBits.bounds.right  - qd.screenBits.bounds.left;
  430.      theVScreen = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
  431.  
  432.      xWidth  = theHScreen - theWidth;
  433.      xHeight = theVScreen - (theHeight + kMBarHeight);
  434.  
  435.      hMax = (xWidth / kVOffset) + 1;
  436.      vMax = (xHeight / kVOffset) + 1;
  437.  
  438.          gWCount++;
  439.  
  440.      wLeft = (gWCount % hMax) * kVOffset;
  441.      wTop  = ((gWCount % vMax) * kVOffset) + kTBarHeight + kMBarHeight;
  442.  
  443.      MoveWindow(aWindow, wLeft, wTop, false);
  444.     }
  445.  
  446. pascal void GetLocalUpdateRgn(WindowPtr window,
  447.                               RgnHandle localRgn)
  448.  
  449.     /* Returns the update region in local coordinates */
  450.  
  451.     {
  452.         CopyRgn(((WindowPeek)window)->updateRgn, localRgn); /* save old update region */
  453.         OffsetRgn(localRgn, 
  454.                             window->portBits.bounds.left, 
  455.                             window->portBits.bounds.top); /* convert to local coords */
  456.     }          /* GetLocalUpdateRgn */
  457.  
  458. #pragma segment Window
  459.  
  460. pascal void IssueZoomCommand(WindowPtr whichWindow, short whichPart);
  461. pascal void IssueSizeWindow(WindowPtr whichWindow,short newHSize, short newVSize);
  462.  
  463. pascal void MyGrowWindow(WindowPtr w, Point p)
  464.     {
  465.         GrafPtr savePort;
  466.     long    theResult;
  467.     Rect    r;
  468.  
  469.     GetPort(&savePort);
  470.     SetPort(w);
  471.     SetRect(&r, 80, 80, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom);
  472.     theResult = GrowWindow(w, p, &r);
  473.         if (theResult)
  474.             IssueSizeWindow(w, LoWord(theResult), HiWord(theResult));
  475.  
  476.     SetPort(savePort);
  477.     }
  478.  
  479. #pragma segment Window
  480.  
  481. pascal void DoZoom(WindowPtr w,
  482.                    short     c,
  483.                    Point     p)
  484.  
  485.  {
  486.    GrafPtr savePort;
  487.  
  488.      GetPort(&savePort);
  489.    SetPort(w);
  490.      if (TrackBox(w, p, c))
  491.          {
  492.              EraseRect(&w->portRect);
  493.              IssueZoomCommand(w, c);
  494.          }
  495.     }
  496.  
  497. #pragma segment Window
  498.  
  499. pascal void DoContent(WindowPtr    theWindow,
  500.                       EventRecord  theEvent)
  501.  
  502.   {
  503.       short         cntlCode;
  504.       short         part;
  505.       ControlHandle theControl;
  506.       GrafPtr       savePort;
  507.       Boolean       extend;
  508.       DPtr          theDoc;
  509.       short         value;
  510.  
  511.     GetPort(&savePort);
  512.     SetPort(theWindow);
  513.     theDoc = DPtrFromWindowPtr(theWindow);
  514.  
  515.     GlobalToLocal(&theEvent.where);
  516.     cntlCode = FindControl(theEvent.where, theWindow, &theControl);
  517.     if (cntlCode == 0)
  518.       {
  519.               /*only extend the selection if the shiftkey is down*/
  520.         extend = (theEvent.modifiers & shiftKey);
  521.  
  522.                 if (PtInRect(theEvent.where, &(*(theDoc->theText))->viewRect))
  523.                     TEClick(theEvent.where, extend, theDoc->theText);
  524.             }
  525.     else
  526.       if (cntlCode == inThumb)
  527.         {
  528.                     value = GetCtlValue(theControl);
  529.                     part  = TrackControl(theControl, theEvent.where, nil);
  530.                     if (part)
  531.                         {
  532.                             value -= GetCtlValue(theControl);
  533.                             if (value)
  534.                                 {
  535.                                     if (theControl == theDoc->vScrollBar)
  536.                                         TEScroll(0, value, theDoc->theText);
  537.                                     else
  538.                                         TEScroll(value, 0, theDoc->theText);
  539.                                     DrawPageExtras(theDoc);
  540.                                 }
  541.                         } /* if */
  542.                 }
  543.             else
  544.                 if (theControl == theDoc->vScrollBar)
  545.                     part = TrackControl(theControl, theEvent.where, (ProcPtr)VActionProc);
  546.                 else
  547.                     part = TrackControl(theControl, theEvent.where, (ProcPtr)HActionProc);
  548.  
  549.         SetPort(savePort);
  550.     }
  551.  
  552. #pragma segment Window
  553.  
  554. pascal OSErr DoActivate(WindowPtr theWindow,
  555.                                               Boolean   activate)
  556.         {
  557.             OSErr err;
  558.             Rect  r;
  559.             DPtr  theDoc;
  560.             
  561.       err = noErr;
  562.             
  563.             if (theWindow)
  564.                 {
  565.                     theDoc = DPtrFromWindowPtr(theWindow);
  566.                     SetPort(theWindow);
  567.                     DrawGrowIcon(theWindow);
  568.                     GetWinContentRect(theWindow, &r);
  569.                     InvalRect(&r);
  570.                     if (activate)
  571.                         {
  572.                             TEActivate(theDoc->theText);
  573.                             ShowControl(theDoc->vScrollBar);
  574.                             ShowControl(theDoc->hScrollBar);
  575.                             DisableItem(myMenus[editM], undoCommand);
  576.                             err = TEFromScrap();
  577.                             if (gWCount == 0)
  578.                                 SetShortMenus();
  579.                         }
  580.                     else
  581.                         {
  582.                             TEDeactivate(theDoc->theText);
  583.                             HideControl(theDoc->vScrollBar);
  584.                             HideControl(theDoc->hScrollBar);
  585.                             err = ZeroScrap();
  586.                             err = TEToScrap();
  587.                         }
  588.                 }
  589.           return(err);
  590.         }
  591.  
  592. #pragma segment Window
  593.  
  594. pascal void GetPageEnds(short          pageHeight,
  595.                                               TEHandle       theText,
  596.                                               PageEndsArray  pageBounds,
  597.                                               short          *nPages)
  598.     {
  599.       short  pageBase;      /* total pixel offset of pages so far */
  600.       short  thisLine;
  601.       short  lastLine;
  602.       short  pageSoFar;
  603.       short  thisPage;      /* Current page being calced */
  604.       short  thisLineH;     /* Height of text line */
  605.       short  pageFirstLine; /* Line # of top of page */
  606.             
  607.         pageBase   = 0;
  608.         thisLine   = 1;
  609.         lastLine   = (*theText)->nLines;
  610.         
  611.         thisPage   = 0;
  612.         pageSoFar  = 0;
  613.         while ((thisLine <= lastLine) || (pageSoFar!=0))
  614.             {
  615.                 pageFirstLine = thisLine;
  616.                 thisLineH     = TEGetHeight(thisLine, thisLine, theText);
  617.                 
  618.                 while ((thisLineH+pageSoFar<pageHeight) && (thisLine <= lastLine))
  619.                     {
  620.                         pageSoFar += thisLineH;
  621.                         thisLine++;
  622.                         thisLineH = TEGetHeight(thisLine, thisLine, theText);
  623.                     }
  624.                     
  625.                 if (pageSoFar)
  626.                     {
  627.                         pageBounds[thisPage] = pageSoFar+pageBase;
  628.                         pageBase  = pageBounds[thisPage];
  629.                         thisPage++;
  630.                         pageSoFar = 0;
  631.                     }
  632.                     
  633.                 /*
  634.                     Special case text line taller than page
  635.                 */
  636.                 
  637.                 if ((thisLine  == pageFirstLine) &&
  638.                      (thisLineH > pageHeight))
  639.                     {
  640.                         do {
  641.                             pageBounds[thisPage] = pageBase+pageHeight;
  642.                             pageBase   = pageBounds[thisPage];
  643.                             thisPage  += 1;
  644.                             thisLineH -= pageHeight;
  645.                         } while (thisLineH >= pageHeight);
  646.                         pageSoFar = thisLineH; /* Carry bottom of large line to next page */
  647.                         thisLine += 1; /* carry xs on as pageSoFar and start measuring next line */
  648.                     }
  649.             }
  650.             
  651.         *nPages = thisPage;
  652.         
  653.     }  /* GetPageEnds */
  654.         
  655. pascal void DrawPageBreaks(DPtr theDoc)
  656.     {
  657.         PageEndsArray    pageEnds;
  658.         short           nPages;
  659.         short           ctr;
  660.         short           lineBase;
  661.         short           pageHeight;
  662.         Rect            viewRect;
  663.                     
  664.         pageHeight = theDoc->pageSize.bottom - theDoc->pageSize.top;
  665.                 
  666.         GetPageEnds(pageHeight,
  667.                                 theDoc->theText,
  668.                                 pageEnds,
  669.                                 &nPages);
  670.                                             
  671.         lineBase = (*(theDoc->theText))->destRect.top;
  672.         viewRect = (*(theDoc->theText))->viewRect;
  673.  
  674.         PenPat(&qd.gray);
  675.         for (ctr = 0; ctr<nPages-1; ctr++)
  676.             {
  677.                 MoveTo(viewRect.left, lineBase+pageEnds[ctr]);
  678.                 LineTo(viewRect.right,lineBase+pageEnds[ctr]);
  679.             }
  680.         PenNormal();
  681.     } /*    DrawPageBreaks */
  682.             
  683. pascal void DrawPageExtras(DPtr theDoc)
  684. {
  685.     GrafPtr   oldPort;
  686.     RgnHandle    oldClip;
  687.     Rect          rectToClip;
  688.             
  689.     GetPort(&oldPort);
  690.     SetPort(theDoc->theWindow);
  691.                 
  692.     oldClip = NewRgn();
  693.     GetClip(oldClip);
  694.                 
  695.     GetWinContentRect(theDoc->theWindow,&rectToClip);
  696.     ClipRect(&rectToClip);
  697.                 
  698.     /* draw the borders */
  699.  
  700.     if (theDoc->showBorders)
  701.         ShowSectionBorders(theDoc);
  702.         
  703.     /* and then the page breaks */
  704.     
  705.     DrawPageBreaks(theDoc);
  706.     
  707.     SetClip(oldClip);
  708.     
  709.     DisposeRgn(oldClip);
  710.     
  711.     SetPort(oldPort);
  712. }  /* DrawPageExtras */
  713.  
  714. pascal void DoUpdate(DPtr theDoc)
  715.   {
  716.         WindowPtr aWindow;
  717.         GrafPtr   savePort;
  718.         Rect            rectClip;
  719.  
  720.         aWindow = theDoc->theWindow;
  721.         GetPort(&savePort);
  722.         SetPort(aWindow);
  723.         BeginUpdate(aWindow);
  724.  
  725.         ClipRect(&aWindow->portRect);
  726.         EraseRect(&aWindow->portRect);
  727.         DrawControls(aWindow);
  728.         DrawGrowIcon(aWindow);
  729.  
  730.         GetWinContentRect(aWindow, &rectClip);
  731.         ClipRect(&rectClip);
  732.  
  733.         TEUpdate(&aWindow->portRect, theDoc->theText);
  734.  
  735.         DrawPageExtras(theDoc);
  736.         
  737.         EndUpdate(aWindow);
  738.         ClipRect(&aWindow->portRect);
  739.  
  740.         SetPort(savePort);
  741.     } /* DoUpdate */
  742.  
  743. #pragma segment Window
  744.  
  745. pascal DPtr NewDocument(Boolean isForOldDoc)
  746.   {
  747.           Rect           destRect;
  748.           Rect           viewRect;
  749.           Rect           vScrollRect;
  750.           Rect           hScrollRect;
  751.           DPtr           myDoc;
  752.           WindowPtr      myWindow;
  753.           ControlHandle  vScroll;
  754.           ControlHandle  hScroll;
  755.             Str255         theName;
  756.             Str255         newNumber;
  757.  
  758.           if (!gWCount)
  759.               SetLongMenus();
  760.  
  761.             myDoc = nil;
  762.       myWindow = GetNewWindow(WindowID, nil, (WindowPtr)-1);
  763.             if (myWindow)
  764.                 {
  765.                     if (isForOldDoc==false)
  766.                         {
  767.                             GetWTitle(myWindow, theName);
  768.                             NumToString(++gNewDocCount, newNumber);
  769.                             if (gNewDocCount>1)
  770.                                 {
  771.                                     PLstrcat(theName, "\p #");
  772.                                     PLstrcat(theName, newNumber);
  773.                                     SetWTitle(myWindow, theName);
  774.                                 }
  775.                         }
  776.                         
  777.                     OffsetWindow(myWindow);
  778.  
  779.                     SetPort(myWindow);
  780.  
  781.                     myDoc = (DPtr)NewPtr(sizeof(DocRec));
  782.  
  783.                     SetWRefCon(myWindow, (long)myDoc);
  784.  
  785.                     myDoc->theWindow = myWindow;
  786.  
  787.                     vScrollRect = myWindow->portRect;
  788.  
  789.                     vScrollRect.left  = vScrollRect.right - kScrollbarAdjust;
  790.                     vScrollRect.right = vScrollRect.left  + kScrollbarWidth;
  791.  
  792.                     vScrollRect.bottom = vScrollRect.bottom - 14;
  793.                     vScrollRect.top    = vScrollRect.top - 1;
  794.                     
  795.                     vScroll = NewControl(myWindow, &vScrollRect, "", true, 0, 0, 0, scrollBarProc, 0);
  796.  
  797.                     hScrollRect = myWindow->portRect;
  798.                     hScrollRect.top = hScrollRect.bottom - kScrollbarAdjust;
  799.                     hScrollRect.bottom = hScrollRect.top + kScrollbarWidth;
  800.  
  801.                     hScrollRect.right = hScrollRect.right - 14;
  802.                     hScrollRect.left  = hScrollRect.left - 1;
  803.                     hScroll = NewControl(myWindow, &hScrollRect, "", true, 0, 0, 0, scrollBarProc, 0);
  804.  
  805.                     myDoc->vScrollBar = vScroll;
  806.                     myDoc->hScrollBar = hScroll;
  807.                     myDoc->lastID = 0;
  808.                     
  809.                     myDoc->firstSection = nil;
  810.                     myDoc->lastSection  = nil;
  811.                     myDoc->numSections  = 0;
  812.                     
  813.                     myDoc->dirty = false;
  814.  
  815.                     GetTERect(myWindow, &viewRect);
  816.                     destRect = viewRect;
  817.  
  818.                     myDoc->theFont  = times;
  819.                     myDoc->theStyle = 0;
  820.                     myDoc->theSize  = 12;
  821.  
  822.                     myDoc->thePrintSetup = (THPrint)NewHandle(sizeof(TPrint));
  823.                     
  824.                     PrOpen();
  825.                     PrintDefault(myDoc->thePrintSetup);
  826.                     PrClose();
  827.                     
  828.                     myDoc->pageSize = (*(myDoc->thePrintSetup))->prInfo.rPage;
  829.                     OffsetRect(&myDoc->pageSize, -myDoc->pageSize.left, -myDoc->pageSize.top);
  830.                     
  831.                     destRect.right = destRect.left + myDoc->pageSize.right;
  832.                     
  833.                     OffsetRect(&destRect, kTextOffset, kTextOffset);
  834.                     
  835.                     TextFont(times);
  836.                     TextSize(12);
  837.                     TextFace(0);
  838.  
  839.                     myDoc->theText = TEStylNew(&destRect, &viewRect);
  840.  
  841.         /*
  842.         SetClikLoop(@AutoScroll, myDoc->theText);
  843.         */
  844.  
  845.                     myDoc->theFileName[0] = 0;
  846.                     myDoc->everSaved      = false;
  847.                     myDoc->theWindow      = myWindow;
  848.                     myDoc->showBorders    = false;
  849.  
  850.                     ResizeWindow(myDoc);
  851.                 }
  852.         return(myDoc);
  853.       }
  854.  
  855. #pragma segment Window
  856.  
  857. pascal void CloseMyWindow(WindowPtr aWindow)
  858.     {
  859.     DPtr     aDocument;
  860.     TEHandle theText;
  861.  
  862.         HideWindow(aWindow);
  863.         aDocument = DPtrFromWindowPtr(aWindow);
  864.         
  865.         theText   = aDocument->theText;
  866.         TEDispose(theText);
  867.         
  868.         if (aDocument->thePrintSetup)
  869.             DisposHandle((Handle)aDocument->thePrintSetup);
  870.             
  871.         DisposPtr((Ptr)aDocument);
  872.         DisposeWindow(aWindow);
  873.  
  874.         gWCount--;
  875.  
  876.         /*if there are no more windows open, set up the short menus*/
  877.         if (gWCount == 0)
  878.             SetShortMenus();
  879.             
  880.     }
  881.             
  882.     /*
  883.         Name     : PrintWindow
  884.         Function : Prints the document supplied in theDoc. askUser controls interaction
  885.                    with the user.
  886.                              
  887.                              Uses extra memory equal to the size of the textedit use in the 
  888.                              printed document.
  889.     */
  890.     
  891. pascal void PrintWindow(DPtr theDoc, Boolean askUser)
  892.     {
  893.       GrafPtr         oldPort;
  894.     TEHandle        printerTE;
  895.     TPPrPort             printerPort;
  896.         Rect                     printView;
  897.         StScrpHandle    printerTextStyles;
  898.          PageEndsArray     pageBounds;
  899.          short                  nPages;
  900.          short                   oldSelStart;
  901.          short                   oldSelEnd;
  902.          short                   pageCtr;
  903.          Boolean                 abort;
  904.          Rect                     rectToClip;
  905.         TPrStatus           thePrinterStatus;
  906.          DialogPtr             progressDialog;
  907.                 
  908.         abort = false;
  909.             
  910.         /*
  911.             Preserve the current port
  912.         */
  913.         GetPort(&oldPort);
  914.         PrOpen();
  915.             
  916.             
  917.       if (askUser)
  918.             abort = !PrJobDialog(theDoc->thePrintSetup);
  919.                 
  920.         if (abort)
  921.             {
  922.                     PrClose();
  923.                     return;
  924.             }
  925.             
  926.         progressDialog = GetNewDialog(1005, nil, (WindowPtr)-1);
  927.             
  928.         DrawDialog(progressDialog);
  929.             
  930.         printerPort = PrOpenDoc(theDoc->thePrintSetup, nil, nil);
  931.         SetPort((GrafPtr)printerPort);
  932.             
  933.         /*
  934.             Put the window text into the printer port
  935.         */
  936.             
  937.         printView = (*(theDoc->thePrintSetup))->prInfo.rPage;
  938.         printerTE = TEStylNew(&printView, &printView);
  939.  
  940.         oldSelStart = (*(theDoc->theText))->selStart;
  941.         oldSelEnd   = (*(theDoc->theText))->selEnd;
  942.         
  943.         TESetSelect(0,(*(theDoc->theText))->teLength, theDoc->theText);
  944.  
  945.         printerTextStyles = GetStylScrap(theDoc->theText);
  946.  
  947.         TESetSelect(oldSelStart, oldSelEnd, theDoc->theText);
  948.         
  949.         HLock((Handle)((*(theDoc->theText))->hText));
  950.         
  951.         TEStylInsert(    (Ptr)*((*(theDoc->theText))->hText),
  952.                                     (*(theDoc->theText))->teLength,
  953.                                     printerTextStyles,
  954.                                     printerTE);
  955.                                                 
  956.         HUnlock((Handle)((*(theDoc->theText))->hText));
  957.  
  958.         /*
  959.             Work out the offsets
  960.         */
  961.         (*printerTE)->destRect = printView; /* GetPageEnds calls TECalText */
  962.             
  963.         GetPageEnds(printView.bottom-printView.top,
  964.                                 printerTE,
  965.                                 pageBounds,
  966.                                 &nPages);
  967.             
  968.         TEDeactivate(printerTE);
  969.  
  970.         for (pageCtr = 0; pageCtr <= nPages-1; pageCtr++)
  971.             if (!abort)
  972.                 {
  973.                     PrOpenPage(printerPort, nil);
  974.                                                 
  975.                     rectToClip = printView;
  976.                     
  977.                     if (pageCtr > 0)
  978.                         rectToClip.bottom = rectToClip.top + (pageBounds[pageCtr]-pageBounds[pageCtr-1]);
  979.                     else
  980.                         rectToClip.bottom = rectToClip.top + pageBounds[pageCtr];
  981.                         
  982.                     ClipRect(&rectToClip);
  983.                     
  984.                     if (PrError() == iPrAbort)
  985.                         abort = true;
  986.                         
  987.                     if (! abort)
  988.                         TEUpdate(&printView, printerTE);
  989.                                             
  990.                     if (PrError() == iPrAbort)
  991.                         abort = true;
  992.                         
  993.                     PrClosePage(printerPort);
  994.                     
  995.                     TEScroll(0,rectToClip.top-rectToClip.bottom, printerTE);
  996.                 }
  997.  
  998.         TEDispose(printerTE);
  999.         PrCloseDoc(printerPort);
  1000.  
  1001.         if (( (*(theDoc->thePrintSetup))->prJob.bJDocLoop == bSpoolLoop ) && 
  1002.                 ( PrError() == noErr )  &&
  1003.                 (! abort))
  1004.             PrPicFile( theDoc->thePrintSetup, nil, nil, nil, &thePrinterStatus);
  1005.         
  1006.         PrClose();
  1007.         
  1008.         DisposDialog(progressDialog);
  1009.         
  1010.         SetPort(oldPort);
  1011.         InvalRect(&oldPort->portRect);
  1012.     }