home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / apps.to.go / DTS.Lib / Window2.c < prev   
Encoding:
C/C++ Source or Header  |  1994-07-14  |  96.6 KB  |  3,852 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:     DTS.Lib
  5. ** File:        window2.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1993 Apple Computer, Inc.
  9. ** All rights reserved.
  10. */
  11.  
  12. /* You may incorporate this sample code into your applications without
  13. ** restriction, though the sample code has been provided "AS IS" and the
  14. ** responsibility for its operation is 100% yours.  However, what you are
  15. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  16. ** after having made changes. If you're going to re-distribute the source,
  17. ** we require that you make it clear in the source that the code was
  18. ** descended from Apple Sample Code, but that you've made changes. */
  19.  
  20.  
  21.  
  22. /*****************************************************************************/
  23.  
  24.  
  25.  
  26. #include "DTS.Lib2.h"
  27. #include "DTS.Lib.protos.h"
  28.  
  29. #ifndef __BALLOONS__
  30. #include <Balloons.h>
  31. #endif
  32.  
  33. #ifndef __DESK__
  34. #include <Desk.h>
  35. #endif
  36.  
  37. #ifndef __ERRORS__
  38. #include <Errors.h>
  39. #endif
  40.  
  41. #ifndef __FONTS__
  42. #include <Fonts.h>
  43. #endif
  44.  
  45. #ifndef __CLPROCS__
  46. #include "ListControlProcs.h"
  47. #endif
  48.  
  49. #ifndef __LOWMEM__
  50. #include <LowMem.h>
  51. #endif
  52.  
  53. #ifndef __MOVIES__
  54. #include <Movies.h>
  55. #endif
  56.  
  57. #ifndef __RESOURCES__
  58. #include <Resources.h>
  59. #endif
  60.  
  61. #ifndef __SCRIPT__
  62. #include <Script.h>
  63. #endif
  64.  
  65. #ifndef __TOOLUTILS__
  66. #include <ToolUtils.h>
  67. #endif
  68.  
  69. #ifndef __UTILITIES__
  70. #include "Utilities.h"
  71. #endif
  72.  
  73.  
  74.  
  75. /*****************************************************************************/
  76.  
  77.  
  78. #ifdef powerc
  79. #pragma options align=mac68k
  80. #endif
  81. typedef struct {
  82.     Rect            contrlRect;
  83.     short            contrlValue;
  84.     unsigned char    contrlVis;
  85.     short            contrlMax;
  86.     short            contrlMin;
  87.     short            procID;
  88.     long            contrlRfCon;
  89.     Str255            contrlTitle;
  90. } CtlTemplate;
  91. #ifdef powerc
  92. #pragma options align=reset
  93. #endif
  94.  
  95. extern short    gTECtl;
  96. extern short    gListCtl;
  97. extern short    gCIconCtl;
  98. extern short    gPICTCtl;
  99. extern short    gDataCtl;
  100.  
  101. extern Handle    gPopupProc;
  102.  
  103. extern short            gPrintPage;                    /* Non-zero means we are printing. */
  104. extern short            gMinVersion, gMaxVersion;
  105. extern Boolean            gInBackground;
  106. extern WindowTemplate    gWindowTemplate, gOpenedWindowTemplate;
  107.  
  108. extern short            gTypeListLen;
  109. extern SFTypeList        gTypeList;
  110. extern long                gAppWindowAttr;
  111. extern OSType            gAppWindowType;
  112. extern Boolean            gNoDefaultDocument;
  113. extern OSErr            gGetWindowErr;
  114.  
  115. OSType                *gTypeListPtr = gTypeList;
  116. short                gBeginUpdateNested;
  117. TreeObjHndl            gWindowFormats;
  118. OSErr                gDialogErr;
  119. HideWindowProcPtr    gHideWindowProc;
  120.  
  121. static RgnHandle    gKeepUpdateRgn;
  122. static WindowPtr    gOldPort;
  123.  
  124. RgnHandle    gCursorRgn;
  125.     /* The current cursor region.  The initial cursor region is an empty
  126.     ** region, which will cause WaitNextEvent to generate a mouse-moved
  127.     ** event, which will cause us to set the cursor for the first time. */
  128.  
  129. static Cursor    gCursor;
  130. CursPtr            gCursorPtr;
  131.     /* The current cursor that applies to gCursorRgn.  These values
  132.     ** are here to shorten the re-processing time for determining the
  133.     ** correct cursor after an event.  This is specifically so that characters
  134.     ** can be typed into the TextEdit control faster.  If we spend a great
  135.     ** deal of time per-event recalculating the cursor region, text entry for
  136.     ** the TextEdit control slows down considerably.  If you want to override
  137.     ** the time savings because you are changing the cursor directly, either
  138.     ** set gCursorPtr to nil, or call DoSetCursor to set the cursor.
  139.     ** DoSetCursor simply sets gCursorPtr to nil, as well as setting
  140.     ** the cursor. */
  141.  
  142. static Rect                    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo);
  143. static PositionWndProcPtr    gOldLocProc;
  144.  
  145. static pascal void    DefaultScrollAction(ControlHandle scrollCtl, short part);
  146. static Boolean        DefaultScroll(ControlHandle ctl, short part, EventRecord *event);
  147.  
  148.  
  149.  
  150. /*****************************************************************************/
  151. /*****************************************************************************/
  152.  
  153.  
  154.  
  155. /* This function creates a new application window.  An application window
  156. ** contains a document which is referenced by a handle in the refCon field. */
  157.  
  158. #pragma segment Window
  159. OSErr    DoNewWindow(FileRecHndl frHndl, WindowPtr *retWindow, WindowPtr relatedWindow, WindowPtr behind)
  160. {
  161.     WindowPtr            oldPort, window;
  162.     FileRecHndl            ffrHndl;
  163.     ControlHandle        ctl;
  164.     Rect                ctlRect, contRect, userState, sizeInfo, rct, rct2, msrct, oldPlaceRct;
  165.     short                h, v, hDocSize, vDocSize;
  166.     long                wkind, wwkind, attributes;
  167.     OSErr                err;
  168.     PositionWndProcPtr    proc;
  169.     GDHandle            device;
  170.     PixMapHandle        pmap;
  171.  
  172.     gCursorPtr = nil;        /* Force recalc of cursor. */
  173.  
  174.     if (!frHndl) return(noErr);
  175.     attributes = (*frHndl)->fileState.attributes;
  176.  
  177.     err = noErr;
  178.     GetPort(&oldPort);
  179.  
  180.     proc = (*frHndl)->fileState.getDocWindow;
  181.  
  182.     if (attributes & kwStaggerWindow) proc = StaggerWindow;
  183.     if (attributes & kwCenterWindow)  proc = CenterWindow;
  184.  
  185.     gOldLocProc = proc;
  186.     if (attributes & kwOpenAtOldLoc)  proc = OldLocWindow;            /* Try to open window at old location. */
  187.  
  188.     SetRect(&sizeInfo, 0, 0, 0, 0);
  189.     if ((proc == StaggerWindow) || (proc == OldLocWindow)) {
  190.         hDocSize = (*frHndl)->d.doc.fhInfo.hDocSize;
  191.         vDocSize = (*frHndl)->d.doc.fhInfo.vDocSize;
  192.         if (hDocSize) {
  193.             hDocSize += (*frHndl)->fileState.leftSidebar;
  194.             if (attributes & kwHScroll)
  195.                 if (vDocSize)
  196.                     vDocSize += 15;
  197.         }
  198.         if (vDocSize) {
  199.             vDocSize += (*frHndl)->fileState.topSidebar;
  200.             if (attributes & kwVScroll)
  201.                 if (hDocSize)
  202.                     hDocSize += 15;
  203.         }
  204.         SetRect(&sizeInfo, hDocSize, vDocSize, hDocSize, vDocSize);
  205.     }
  206.  
  207.     wkind = (attributes & (kwIsPalette | kwIsModalDialog));
  208.     if (behind) {
  209.         for (;;) {
  210.             if (!(behind = GetNextWindow(behind, 0))) break;
  211.                 /* break if behind all windows.  behind is nil, so that's what we have. */
  212.             if (!((WindowPeek)behind)->visible) continue;
  213.  
  214.             wwkind = kwIsDocument;
  215.             if (IsAppWindow(behind)) {
  216.                 ffrHndl = (FileRecHndl)GetWRefCon(behind);
  217.                 if (ffrHndl)
  218.                     wwkind  = ((*ffrHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog));
  219.             }
  220.  
  221.             if (wkind >= wwkind) {
  222.                 for (;;) {
  223.                     behind = GetPreviousWindow(behind);
  224.                     if (behind == (WindowPtr)-1)       break;
  225.                     if (((WindowPeek)behind)->visible) break;
  226.                 }
  227.                 break;
  228.             }
  229.         }
  230.     }
  231.  
  232.     oldPlaceRct = SetWindowPlacementRect(nil);
  233.     if (EmptyRect(&oldPlaceRct)) {
  234.  
  235.         if (attributes & kwSameMonitor) {
  236.             relatedWindow = nil;
  237.             for (; (relatedWindow = GetNextWindow(relatedWindow, (*frHndl)->fileState.sfType)) != nil;)
  238.                 if (((WindowPeek)relatedWindow)->visible) break;
  239.             if (!relatedWindow) {
  240.                 for (; (relatedWindow = GetNextWindow(relatedWindow, 0)) != nil;) {
  241.                     if (!((WindowPeek)relatedWindow)->visible) continue;
  242.                     if (((WindowPeek)relatedWindow)->windowKind >= 1000) {
  243.                         ffrHndl = (FileRecHndl)GetWRefCon(relatedWindow);
  244.                         if (ffrHndl) {
  245.                             wwkind = (*ffrHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  246.                             if (wkind == wwkind) break;
  247.                         }
  248.                     }
  249.                 }
  250.             }
  251.         }
  252.  
  253.         if ((!(attributes & kwSameMonitor)) || (!relatedWindow)) {
  254.             if (attributes & (kwColorMonitor | kwSecondaryMonitor)) {
  255.     
  256.                 if (gQDVersion > kQDOriginal) {
  257.                     rct = msrct = GetMainScreenRect();
  258.                     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  259.                         rct2 = (*device)->gdRect;
  260.                         if (TestDeviceAttribute(device, screenDevice) &&
  261.                             TestDeviceAttribute(device, screenActive)
  262.                         ) {
  263.                             pmap = (*device)->gdPMap;
  264.                             if (attributes & kwColorMonitor) {
  265.                                 if ((*pmap)->pixelSize > 1) {
  266.                                     rct = rct2;
  267.                                     if (!(rct.top | rct.left)) break;
  268.                                 }
  269.                             }
  270.                             else {
  271.                                 if (!EqualRect(&rct2, &msrct)) {
  272.                                     rct = rct2;
  273.                                     break;
  274.                                 }
  275.                             }
  276.                         }
  277.                     }
  278.                     if (EqualRect(&rct, &msrct))
  279.                         rct.top += GetMBarHeight();
  280.                     SetWindowPlacementRect(&rct);
  281.                 }
  282.             }
  283.         }
  284.     }
  285.  
  286.     window = GetSomeKindOfWindow(proc, (*frHndl)->fileState.windowID, nil, false, relatedWindow,
  287.                                  behind, true, sizeInfo, (long)frHndl);
  288.  
  289.     SetWindowPlacementRect(&oldPlaceRct);
  290.  
  291.     if (window) {
  292.         ((WindowPeek)window)->windowKind = 1000;        /* ID it as an AppsToGo window. */
  293.  
  294.         SetPort(window);
  295.         NewWindowTitle(window, nil);
  296.  
  297.         (*frHndl)->fileState.window = window;
  298.  
  299.         (*frHndl)->fileState.hArrowVal = 16;    /* Default arrow value is 16. */
  300.         (*frHndl)->fileState.vArrowVal = 16;
  301.  
  302.         if (!(*frHndl)->d.doc.fhInfo.hDocSize) {
  303.             h  = gOpenedWindowTemplate.boundsRect.right - gOpenedWindowTemplate.boundsRect.left;
  304.             h -= (*frHndl)->fileState.leftSidebar;    /* Default document size is */
  305.             if (attributes & kwVScroll)                /* content less leftSidebar */
  306.                 h -= 15;                            /* value less scrollbars.   */
  307.             (*frHndl)->d.doc.fhInfo.hDocSize = h;
  308.         }
  309.         if (!(*frHndl)->d.doc.fhInfo.vDocSize) {
  310.             v  = gOpenedWindowTemplate.boundsRect.bottom - gOpenedWindowTemplate.boundsRect.top;
  311.             v -= (*frHndl)->fileState.topSidebar;    /* We don't have to initialize the page */
  312.             if (attributes & kwHScroll)                /* values since the scrollbars won't be */
  313.                 v -= 15;                            /* active until the window is resized   */
  314.             (*frHndl)->d.doc.fhInfo.vDocSize = v;    /* or these values are set elsewhere.   */
  315.         }
  316.  
  317.         if (attributes & kwHScroll) {        /* Caller wants a horizontal scrollbar... */
  318.             ctlRect = window->portRect;
  319.             ctlRect.left += (*frHndl)->fileState.leftSidebar;
  320.             ctlRect.left += (*frHndl)->fileState.hScrollIndent;
  321.             --ctlRect.left;
  322.             ++ctlRect.right;
  323.             ctlRect.top = ++ctlRect.bottom - 16;
  324.             if (attributes & (kwHScrollLessGrow - kwHScroll +  kwGrowIcon))
  325.                 ctlRect.right -= 15;
  326.             OffsetRect(&ctlRect, 0, -16384);
  327.             ctl = NewControl(window, &ctlRect, "\p", true, 0, 0, 0, scrollBarProc, 0L);
  328.             if (ctl)
  329.                 (*frHndl)->fileState.hScroll = ctl;
  330.             else
  331.                 err = memFullErr;
  332.         }
  333.  
  334.         if (!err) {
  335.             if (attributes & kwVScroll) {        /* Caller wants a vertical scrollbar... */
  336.                 ctlRect = window->portRect;
  337.                 ctlRect.top += (*frHndl)->fileState.topSidebar;
  338.                 ctlRect.top += (*frHndl)->fileState.vScrollIndent;
  339.                 --ctlRect.top;
  340.                 ++ctlRect.bottom;
  341.                 ctlRect.left = ++ctlRect.right - 16;
  342.                 if (attributes & (kwVScrollLessGrow - kwVScroll +  kwGrowIcon))
  343.                     ctlRect.bottom -= 15;
  344.                 OffsetRect(&ctlRect, 0, -16384);
  345.                 ctl = NewControl(window, &ctlRect, "\p", true, 0, 0, 0, scrollBarProc, 0L);
  346.                 if (ctl)
  347.                     (*frHndl)->fileState.vScroll = ctl;
  348.                 else
  349.                     err = memFullErr;
  350.             }
  351.         }
  352.  
  353.         if (!err) {
  354.             err = DoInitContent(frHndl, window);
  355.             if (!err) {
  356.                 if (!((WindowPeek)window)->visible) {
  357.                     contRect = GetWindowContentRect(window);
  358.                     if (((WindowPeek)window)->spareFlag)
  359.                         userState = mDerefWStateData(window)->userState;
  360.                             /* Cache this.  ShowWindow offscreen messes it up.  We want to keep
  361.                             ** whatever it is because some other function may be tweeking stdState
  362.                             ** and userState so that window position and zoom state can be saved
  363.                             ** along with a document. */
  364.  
  365.                     MoveWindow(window, 16384, 16384, false);
  366.                         /* When an invisible window is added, it isn't the frontmost window.
  367.                         ** This causes a problem when we make it visible.  By moving it
  368.                         ** offscreen, we can make it visible without the user seeing that it
  369.                         ** isn't the top window. */
  370.  
  371.                     if (gPrintPage) {
  372.                         ShowWindow(window);                            /* Window now visible. */
  373.                         MoveWindow(window, 16384, 16384, true);        /* Window now on top.  */
  374.                     }    /* If we are printing, we want to leave the window offscreen, since we
  375.                         ** don't want it seen.  We do need a visible window when printing so
  376.                         ** PrintMonitor can get the document name. */
  377.  
  378.                     if (!gPrintPage) {
  379.                         if (attributes & kwVisible)
  380.                             ShowHide(window, true);
  381.                         CleanSendBehind(window, behind);
  382.                         MoveWindow(window, contRect.left, contRect.top, false);
  383.                     }
  384.  
  385.                     if (((WindowPeek)window)->spareFlag)
  386.                         mDerefWStateData(window)->userState = userState;
  387.                             /* The ShowWindow metrics we did cause the userState to change.  Put it
  388.                             ** back the way it was before we started messing around with the window. */
  389.  
  390.                     AdjustScrollBars(window);
  391.                 }
  392.             }
  393.         }
  394.         if (err) {
  395.             DisposeAnyWindow(window);
  396.             (*frHndl)->fileState.window = window = nil;
  397.         }
  398.     }
  399.     else err = gGetWindowErr;
  400.  
  401.     SetPort(oldPort);
  402.     if (retWindow)
  403.         *retWindow = window;
  404.  
  405.     return(err);
  406. }
  407.  
  408.  
  409.  
  410. /*****************************************************************************/
  411.  
  412.  
  413.  
  414. /* This function updates the window title to reflect the new document name.
  415. ** The new document name is stored in the fileState portion of the document.
  416. ** This is automatically set to 'Untitled # N' for new documents, and is
  417. ** updated when a user does a save-as.  If the window that is being opened
  418. ** should have the resource name, then set the new document name to an
  419. ** empty string prior to calling DoNewWindow.  When this is called by
  420. ** DoNewWindow, the SetWTitle will be suppressed. */
  421.  
  422. #pragma segment Window
  423. void    NewWindowTitle(WindowPtr window, StringPtr altTitle)
  424. {
  425.     FileRecHndl    frHndl;
  426.     Str255        wTitle;
  427.  
  428.     if (window) {
  429.         if (altTitle) {
  430.             pcpy(wTitle, altTitle);
  431.             SetWTitle(window, wTitle);
  432.         }
  433.         else {
  434.             frHndl = (FileRecHndl)GetWRefCon(window);
  435.             if (frHndl) {
  436.                 if (((WindowPeek)window)->windowKind >= 1000) {
  437.                     pcpy(wTitle, (*frHndl)->fileState.fss.name);
  438.                     if (*wTitle)
  439.                         SetWTitle(window, wTitle);
  440.                     else {
  441.                         if ((*frHndl)->fileState.refNum == kInvalRefNum) {
  442.                             GetWTitle(window, wTitle);
  443.                             if (*wTitle > 63) *wTitle = 63;
  444.                             pcpy((*frHndl)->fileState.fss.name, wTitle);
  445.                         }
  446.                     }
  447.                 }
  448.             }
  449.         }
  450.     }
  451. }
  452.  
  453.  
  454.  
  455. /*****************************************************************************/
  456.  
  457.  
  458.  
  459. /* Close all the windows.  This is called prior to quitting the application.
  460. ** This function returns true if all windows were closed.  The user may decide
  461. ** to abort a save, thus stopping the closing of the windows.  If the user
  462. ** does this, false will be returned, indicating that all windows were not
  463. ** closed after all. */
  464.  
  465. #pragma segment Window
  466. Boolean    DisposeAllWindows(void)
  467. {
  468.     WindowPtr    window;
  469.     FileRecHndl    frHndl;
  470.     long        attr;
  471.  
  472.     gCursorPtr = nil;        /* Force recalc of cursor. */
  473.  
  474.     for (window = nil;;) {
  475.  
  476.         if (!window)
  477.             window = FrontWindow();
  478.         else
  479.             window = (WindowPtr)(((WindowPeek)window)->nextWindow);
  480.  
  481.         if (!window) break;        /* All out of windows to get rid of. */
  482.  
  483.         if (!((WindowPeek)window)->visible) continue;
  484.             /* Invisible windows shouldn't be disposed of, since the user may cancel the quit,
  485.             ** and therefore the user will want windows around.  If a "hide on close" window
  486.             ** was closed, it was simply made invisible, so these windows are still actually
  487.             ** intact.  The user will have to show them again, but they still exist. */
  488.  
  489.         if (!IsDAWindow(window)) {
  490.             if (((WindowPeek)window)->windowKind >= 1000) {
  491.                 frHndl = (FileRecHndl)GetWRefCon(window);
  492.                 if (frHndl) {
  493.                     attr   = (*frHndl)->fileState.attributes;
  494.                     if (attr & kwIsPalette) continue;
  495.                         /* Closing of all of the windows may be stopped at a
  496.                         ** dirty document, so don't close the palettes. */
  497.                 }
  498.             }
  499.         }
  500.  
  501.         if (!DisposeOneWindow(window, kQuit)) return(false);
  502.             /* When DisposeOneWindow returns false, this means that the window
  503.             ** didn't close.  The only cause of this is if the window had a
  504.             ** document that needed saving, and the user cancelled the save.
  505.             ** If the windows succeed in getting closed, then we are
  506.             ** returned true. */
  507.  
  508.         window = nil;
  509.             /* The close of a window may have caused other window to close, so
  510.             ** start looking at windows from the beginning of the list.  This
  511.             ** guarantees that we are always looking at valid window records. */
  512.     }
  513.  
  514.     return(true);
  515. }
  516.  
  517.  
  518.  
  519. /*****************************************************************************/
  520.  
  521.  
  522.  
  523. /* Closes one window.  This window may be an application window, or it may be
  524. ** a system window.  If it is an application window, it may have a document
  525. ** that needs saving. */
  526.  
  527. #pragma segment Window
  528. Boolean    DisposeOneWindow(WindowPtr window, short saveMode)
  529. {
  530.     FileRecHndl    frHndl;
  531.     long        attr;
  532.     OSErr        err;
  533.  
  534.     gCursorPtr = nil;        /* Force recalc of cursor. */
  535.  
  536.     if (window) {
  537.         if (!IsDAWindow(window)) {
  538.             /* First, if the window is an application window, try saving
  539.             ** the document.  Remember that the user may cancel the save. */
  540.  
  541.             if (((WindowPeek)window)->windowKind >= 1000) {
  542.                 frHndl = (FileRecHndl)GetWRefCon(window);
  543.                 if (frHndl) {
  544.  
  545.                     attr = (*frHndl)->fileState.attributes;
  546.                     if (attr & kwHideOnClose) {
  547.                         if (gHideWindowProc) {
  548.                             err = (*gHideWindowProc)(frHndl, window);
  549.                             if (err)
  550.                                 return(false);
  551.                         }
  552.                         HideWindow(window);
  553.                         HiliteWindows();
  554.                         WindowGoneFixup(window);
  555.                         return(true);
  556.                     }
  557.  
  558.                     if (!((*frHndl)->fileState.attributes & kwRuntimeOnlyDoc)) {
  559.                         if (IsAppWindow(window)) {
  560.                             err = SaveDocument(frHndl, window, saveMode);
  561.                             if (err) {
  562.                                 if (err != userCanceledErr) {
  563.                                     gDialogErr = err;
  564.                                     NewDocumentWindow(nil, 'ERR#', false);
  565.                                 }
  566.                                 return(false);
  567.                             }        /* Stop closing windows on error or user cancel. */
  568.                         }
  569.                     }
  570.  
  571.                     err = DoFreeWindow(frHndl, window);
  572.                     if (err) return(false);
  573.  
  574.                     DisposeDocument(frHndl);
  575.                         /* If everything is cool, dispose of the document. */
  576.                 }
  577.             }
  578.         }
  579.  
  580.         DisposeAnyWindow(window);
  581.         HiliteWindows();
  582.         WindowGoneFixup(window);
  583.             /* Give the application a chance to do any related tasks. */
  584.     }
  585.  
  586.     return(true);
  587. }
  588.  
  589.  
  590.  
  591. /*****************************************************************************/
  592.  
  593.  
  594.  
  595. #pragma segment Window
  596. WindowPtr    SetFilePort(FileRecHndl frHndl)
  597. {
  598.     WindowPtr    oldPort;
  599.  
  600.     GetPort(&oldPort);
  601.     if (frHndl)
  602.         SetPort((*frHndl)->fileState.window);
  603.     return(oldPort);
  604. }
  605.  
  606.  
  607.  
  608. /*****************************************************************************/
  609.  
  610.  
  611.  
  612. #pragma segment Window
  613. void    DoResizeWindow(WindowPtr window, short oldh, short oldv)
  614. {
  615.     FileRecHndl        frHndl;
  616.     WindowPtr        oldPort;
  617.     long            attributes;
  618.     Boolean            growIconSpace;
  619.     Rect            portRct, rct;
  620.     ControlHandle    hScroll, vScroll;
  621.     RgnHandle        updateRgn;
  622.     short            i;
  623.  
  624.     gCursorPtr = nil;        /* Force recalc of cursor. */
  625.  
  626.     if (!window)                                     return;
  627.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  628.  
  629.     oldPort       = SetFilePort(frHndl);
  630.     attributes    = (*frHndl)->fileState.attributes;
  631.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  632.         /* growIconSpace true if window has grow icon or a blank space for one. */
  633.  
  634.     SetOrigin(0, 0);
  635.     portRct = window->portRect;
  636.  
  637.     if (growIconSpace) {
  638.         rct.left = (rct.right  = oldh) - 15;
  639.         rct.top  = (rct.bottom = oldv) - 15;
  640.         EraseRect(&rct);
  641.         InvalRect(&rct);
  642.         rct = portRct;
  643.         rct.left = rct.right  - 15;
  644.         rct.top  = rct.bottom - 15;
  645.         EraseRect(&rct);
  646.     }
  647.  
  648.     SetOrigin(0, -16384);
  649.     hScroll = (*frHndl)->fileState.hScroll;
  650.     if (hScroll) {
  651.         HideControl(hScroll);
  652.         rct = (*hScroll)->contrlRect;
  653.         MoveControl(hScroll, rct.left, portRct.bottom - 15 - 16384);
  654.         SizeControl(hScroll, rct.right - rct.left + (portRct.right - portRct.left - oldh), 16);
  655.     }
  656.     vScroll = (*frHndl)->fileState.vScroll;
  657.     if (vScroll) {
  658.         HideControl(vScroll);
  659.         rct = (*vScroll)->contrlRect;
  660.         MoveControl(vScroll, portRct.right - 15, rct.top);
  661.         SizeControl(vScroll, 16, rct.bottom - rct.top + (portRct.bottom - portRct.top - oldv));
  662.     }
  663.  
  664.     i = (*frHndl)->fileState.hScrollIndent;
  665.     if (i) {
  666.         rct       = window->portRect;
  667.         rct.right = --i;
  668.         rct.top   = rct.bottom - 15;
  669.         InvalRect(&rct);
  670.         rct.bottom = window->portRect.top + oldv;
  671.         rct.top    = rct.bottom - 15;
  672.         EraseRect(&rct);
  673.         InvalRect(&rct);
  674.     }
  675.  
  676.     i = (*frHndl)->fileState.vScrollIndent;
  677.     if (i) {
  678.         rct        = window->portRect;
  679.         rct.bottom = --i;
  680.         rct.left   = rct.right - 15;
  681.         InvalRect(&rct);
  682.         rct.right  = window->portRect.left + oldh;
  683.         rct.left   = rct.right - 15;
  684.         EraseRect(&rct);
  685.         InvalRect(&rct);
  686.     }
  687.  
  688.     AdjustScrollBars(window);
  689.  
  690.     if (hScroll)
  691.         ShowControl(hScroll);
  692.     if (vScroll)
  693.         ShowControl(vScroll);
  694.  
  695.     SetOrigin(0, 0);
  696.     if (attributes & kwGrowIcon)
  697.         DoDrawGrowIcon(window, false, false);
  698.  
  699.     BeginContent(window);
  700.     DoResizeContent(window, oldh, oldv);
  701.     updateRgn = NewRgn();
  702.     CopyRgn(((WindowPeek)window)->updateRgn, updateRgn);
  703.     EndContent(window);
  704.     UnionRgn(updateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  705.     DisposeRgn(updateRgn);
  706.  
  707.     SetPort(oldPort);
  708. }
  709.  
  710.  
  711.  
  712. /*****************************************************************************/
  713.  
  714.  
  715.  
  716. /* This function returns the difference between the old window size and the new window
  717. ** size.  Pass in the old window size, and this function looks up the current size,
  718. ** gets the difference, and returns it. */
  719.  
  720. #pragma segment Window
  721. void    GetWindowChange(WindowPtr window, short oldh, short oldv, short *dx, short *dy)
  722. {
  723.     *dx = (window->portRect.right  - window->portRect.left) - oldh;
  724.     *dy = (window->portRect.bottom - window->portRect.top)  - oldv;
  725.  
  726. }
  727.  
  728.  
  729.  
  730. /*****************************************************************************/
  731.  
  732.  
  733.  
  734. #pragma segment Window
  735. void    DoUpdateSeparate(WindowPtr window, RgnHandle *contRgn, RgnHandle *frameRgn)
  736. {
  737.     RgnHandle    urgn, wrgn;
  738.  
  739.     *contRgn = *frameRgn = nil;
  740.     if (!window) return;
  741.  
  742.     urgn = DoCalcFrameRgn(window);
  743.     wrgn = NewRgn();
  744.  
  745.     DiffRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  746.     if (!EmptyRgn(wrgn)) {
  747.         *contRgn = wrgn;
  748.         wrgn = NewRgn();
  749.     }
  750.     SectRgn(((WindowPeek)window)->updateRgn, urgn, wrgn);
  751.  
  752.     if (!EmptyRgn(wrgn))
  753.         *frameRgn = wrgn;
  754.     else
  755.         DisposeRgn(wrgn);
  756.  
  757.     DisposeRgn(urgn);
  758. }
  759.  
  760.  
  761.  
  762. /*****************************************************************************/
  763.  
  764.  
  765.  
  766. #pragma segment Window
  767. void    BeginContent(WindowPtr window)
  768. {
  769.     RgnHandle    updateRgn, frameRgn;
  770.     Point        contOrg;
  771.  
  772.     if (!gBeginUpdateNested++) {
  773.         GetPort(&gOldPort);
  774.         CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
  775.         frameRgn = DoCalcFrameRgn(window);
  776.         DiffRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
  777.         DisposeRgn(frameRgn);
  778.         BeginUpdate(window);
  779.     }
  780.     SetPort(window);
  781.     GetContentOrigin(window, &contOrg);
  782.     SetOrigin(contOrg.h, contOrg.v);
  783. }
  784.  
  785.  
  786.  
  787. /*****************************************************************************/
  788.  
  789.  
  790.  
  791. #pragma segment Window
  792. void    EndContent(WindowPtr window)
  793. {
  794.     if (gBeginUpdateNested) {
  795.         if (!--gBeginUpdateNested) {
  796.             EndUpdate(window);
  797.             if (gKeepUpdateRgn) {
  798.                 UnionRgn(gKeepUpdateRgn, ((WindowPeek)window)->updateRgn, ((WindowPeek)window)->updateRgn);
  799.                 DisposeRgn(gKeepUpdateRgn);
  800.                 SetPort(gOldPort);
  801.                 gKeepUpdateRgn = nil;
  802.             }
  803.         }
  804.     }
  805. }
  806.  
  807.  
  808.  
  809. /*****************************************************************************/
  810.  
  811.  
  812.  
  813. #pragma segment Window
  814. void    BeginFrame(WindowPtr window)
  815. {
  816.     RgnHandle    updateRgn, frameRgn, scrollRgn;
  817.  
  818.     if (!gBeginUpdateNested++) {
  819.         GetPort(&gOldPort);
  820.         CopyRgn(updateRgn = ((WindowPeek)window)->updateRgn, gKeepUpdateRgn = NewRgn());
  821.         frameRgn  = DoCalcFrameRgn(window);
  822.         scrollRgn = DoCalcScrollRgn(window);
  823.         DiffRgn(frameRgn, scrollRgn, frameRgn);
  824.         DisposeRgn(scrollRgn);
  825.         SectRgn(((WindowPeek)window)->contRgn, frameRgn, updateRgn);
  826.         DisposeRgn(frameRgn);
  827.         BeginUpdate(window);
  828.     }
  829.     SetPort(window);
  830.     SetOrigin(-16384, 0);
  831. }
  832.  
  833.  
  834.  
  835. /*****************************************************************************/
  836.  
  837.  
  838.  
  839. #pragma segment Window
  840. void    EndFrame(WindowPtr window)
  841. {
  842.     EndContent(window);
  843. }
  844.  
  845.  
  846.  
  847. /*****************************************************************************/
  848.  
  849.  
  850.  
  851. #pragma segment Window
  852. void    AdjustScrollBars(WindowPtr window)
  853. {
  854.     FileRecHndl            frHndl;
  855.     WindowPtr            oldPort;
  856.     ControlHandle        hScroll, vScroll;
  857.     Rect                portRct;
  858.     Point                keepOrg;
  859.     short                h, v, maxVal, val;
  860.     DocScrollBarProc    proc;
  861.  
  862.     if (!window)                                     return;
  863.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  864.  
  865.     oldPort = SetFilePort(frHndl);
  866.     portRct = window->portRect;
  867.  
  868.     keepOrg.h = portRct.left;
  869.     keepOrg.v = portRct.top;
  870.  
  871.     portRct.left += (*frHndl)->fileState.leftSidebar;
  872.     portRct.top  += (*frHndl)->fileState.topSidebar;
  873.  
  874.     hScroll = (*frHndl)->fileState.hScroll;
  875.     vScroll = (*frHndl)->fileState.vScroll;
  876.  
  877.     SetOrigin(0, -16384);
  878.  
  879.     if ((maxVal = (*frHndl)->d.doc.fhInfo.hDocSize) > 0) {
  880.         h = portRct.right - portRct.left;
  881.         if (vScroll)
  882.             h -= 15;
  883.         maxVal -= h;
  884.         if (maxVal < 0)
  885.             maxVal = 0;
  886.         if (hScroll) {
  887.             proc = (DocScrollBarProc)GetControlReference(hScroll);
  888.             if (proc)
  889.                 (*proc)(frHndl, hScroll, kscrollHAdjust, h);
  890.             else {
  891.                 if (maxVal < (val = GetControlValue(hScroll)))
  892.                     maxVal = val;
  893.                 if ((*hScroll)->contrlMax != maxVal) {
  894.                     (*hScroll)->contrlMax = maxVal;
  895.                     DoDraw1Control(hScroll, true);
  896.                 }
  897.                 h -= (val = (*frHndl)->fileState.hArrowVal);
  898.                 if (h < val)
  899.                     h = val;
  900.                 (*frHndl)->fileState.hPageVal = h;
  901.             }
  902.         }
  903.     }
  904.  
  905.     if ((maxVal = (*frHndl)->d.doc.fhInfo.vDocSize) > 0) {
  906.         v = portRct.bottom - portRct.top;
  907.         if (hScroll)
  908.             v -= 15;
  909.         maxVal -= v;
  910.         if (maxVal < 0)
  911.             maxVal = 0;
  912.         if (vScroll) {
  913.             proc = (DocScrollBarProc)GetControlReference(vScroll);
  914.             if (proc)
  915.                 (*proc)(frHndl, vScroll, kscrollVAdjust, v);
  916.             else {
  917.                 if (maxVal < (val = GetControlValue(vScroll)))
  918.                     maxVal = val;
  919.                 if ((*vScroll)->contrlMax != maxVal) {
  920.                     (*vScroll)->contrlMax = maxVal;
  921.                     DoDraw1Control(vScroll, true);
  922.                 }
  923.                 v -= (val = (*frHndl)->fileState.vArrowVal);
  924.                 if (v < val)
  925.                     v = val;
  926.                 (*frHndl)->fileState.vPageVal = v;
  927.             }
  928.         }
  929.     }
  930.  
  931.     SetOrigin(keepOrg.h, keepOrg.v);
  932.     SetPort(oldPort);
  933. }
  934.  
  935.  
  936.  
  937. /*****************************************************************************/
  938.  
  939.  
  940.  
  941. #pragma segment Window
  942. void    GetContentOrigin(WindowPtr window, Point *contOrg)
  943. {
  944.     FileRecHndl            frHndl;
  945.     ControlHandle        ctl;
  946.     DocScrollBarProc    proc;
  947.  
  948.     contOrg->h = contOrg->v = 0;
  949.  
  950.     if (window) {
  951.         if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  952.         ctl = (*frHndl)->fileState.hScroll;
  953.         if (ctl) {
  954.             contOrg->h = GetControlValue(ctl);
  955.             proc = (DocScrollBarProc)GetControlReference(ctl);
  956.             if (proc)
  957.                 contOrg->h = (*proc)(frHndl, ctl, kscrollGetHOrigin, 0);
  958.         }
  959.         ctl = (*frHndl)->fileState.vScroll;
  960.         if (ctl) {
  961.             contOrg->v = GetControlValue(ctl);
  962.             proc = (DocScrollBarProc)GetControlReference(ctl);
  963.             if (proc)
  964.                 contOrg->v = (*proc)(frHndl, ctl, kscrollGetVOrigin, 0);
  965.         }
  966.         contOrg->h -= (*frHndl)->fileState.leftSidebar;
  967.         contOrg->v -= (*frHndl)->fileState.topSidebar;
  968.     }
  969. }
  970.  
  971.  
  972.  
  973. /*****************************************************************************/
  974.  
  975.  
  976.  
  977. #pragma segment Window
  978. void    SetContentOrigin(WindowPtr window, long newh, long newv)
  979. {
  980.     FileRecHndl        frHndl;
  981.     WindowPtr        oldPort;
  982.     ControlHandle    hScroll, vScroll;
  983.     short            topSide, leftSide, max, dh, dv;
  984.     Point            old, contOrg;
  985.     RgnHandle        updateRgn;
  986.     Rect            contRct;
  987.  
  988.     gCursorPtr = nil;        /* Force recalc of cursor. */
  989.  
  990.     if (!window)                                     return;
  991.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  992.  
  993.     oldPort = SetFilePort(frHndl);
  994.     hScroll = (*frHndl)->fileState.hScroll;
  995.     vScroll = (*frHndl)->fileState.vScroll;
  996.     GetContentOrigin(window, &old);
  997.     GetContentRect(window, &contRct);
  998.  
  999.     SetOrigin(0, -16384);
  1000.     topSide  = (*frHndl)->fileState.topSidebar;
  1001.     leftSide = (*frHndl)->fileState.leftSidebar;
  1002.  
  1003.     if (!hScroll)
  1004.         newh = kwNoChange;
  1005.     if (newh != kwNoChange) {
  1006.         if (newh != kwBotScroll)
  1007.             newh += leftSide;
  1008.         if (newh < 0)
  1009.             newh = 0;
  1010.         if (newh > (max = GetControlMaximum(hScroll)))
  1011.             newh = max;
  1012.         if ((*hScroll)->contrlValue != newh) {
  1013.             (*hScroll)->contrlValue = newh;
  1014.             DoDraw1Control(hScroll, true);
  1015.         }
  1016.         newh -= leftSide;
  1017.     }
  1018.  
  1019.     if (!vScroll)
  1020.         newv = kwNoChange;
  1021.     if (newv != kwNoChange) {
  1022.         if (newv != kwBotScroll)
  1023.             newv += topSide;
  1024.         if (newv < 0)
  1025.             newv = 0;
  1026.         if (newv > (max = GetControlMaximum(vScroll)))
  1027.             newv = max;
  1028.         if ((*vScroll)->contrlValue != newv) {
  1029.             (*vScroll)->contrlValue = newv;
  1030.             DoDraw1Control(vScroll, true);
  1031.         }
  1032.         newv -= topSide;
  1033.     }
  1034.  
  1035.     AdjustScrollBars(window);
  1036.  
  1037.     dh = dv = 0;
  1038.     if (newh != kwNoChange)
  1039.         dh = old.h - newh;
  1040.     if (newv != kwNoChange)
  1041.         dv = old.v - newv;
  1042.  
  1043.     BeginContent(window);
  1044.     ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  1045.     EndContent(window);
  1046.  
  1047.     OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  1048.         /* We want to add the scrolled-in area into the updateRgn.  We
  1049.         ** also want to keep the old area.  The old update area is
  1050.         ** no longer mapped to the same location, due to the scroll,
  1051.         ** so offset it by the amount scrolled.  Once it is offset, we
  1052.         ** can add our new update portion to the updateRgn. */
  1053.  
  1054.     GetContentOrigin(window, &contOrg);
  1055.     SetOrigin(contOrg.h, contOrg.v);
  1056.     InvalRgn(updateRgn);
  1057.     DisposeRgn(updateRgn);
  1058.  
  1059.     SetOrigin(old.h, old.v);
  1060.     SetPort(oldPort);                /* Put things back the way we found them. */
  1061.  
  1062.     DoScrollFrame(window, dh, dv);    /* There may be changes in the frame due to scrolling. */
  1063.  
  1064.     DoSetCursor(nil);                /* Cursor region may be invalid due to
  1065.                                     ** content being scrolled.  Force it to
  1066.                                     ** be recalculated. */
  1067. }
  1068.  
  1069.  
  1070.  
  1071. /*****************************************************************************/
  1072.  
  1073.  
  1074.  
  1075. #pragma segment Window
  1076. void    GetContentRect(WindowPtr window, Rect *contRct)
  1077. {
  1078.     FileRecHndl        frHndl;
  1079.  
  1080.     SetRect(contRct, 0, 0, 0, 0);
  1081.  
  1082.     if (window) {
  1083.         if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1084.         *contRct = window->portRect;
  1085.         if ((*frHndl)->fileState.hScroll)
  1086.             contRct->bottom -= 15;
  1087.         if ((*frHndl)->fileState.vScroll)
  1088.             contRct->right  -= 15;
  1089.         contRct->top  += (*frHndl)->fileState.topSidebar;
  1090.         contRct->left += (*frHndl)->fileState.leftSidebar;
  1091.     }
  1092. }
  1093.  
  1094.  
  1095.  
  1096. /*****************************************************************************/
  1097.  
  1098.  
  1099.  
  1100. #pragma segment Window
  1101. void    SetDocSize(FileRecHndl frHndl, long hSize, long vSize)
  1102. {
  1103.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1104.  
  1105.     if (frHndl) {
  1106.         if (hSize >= 0)
  1107.             (*frHndl)->d.doc.fhInfo.hDocSize = hSize;
  1108.         if (vSize >= 0)
  1109.             (*frHndl)->d.doc.fhInfo.vDocSize = vSize;
  1110.         AdjustScrollBars((*frHndl)->fileState.window);
  1111.     }
  1112. }
  1113.  
  1114.  
  1115.  
  1116. /*****************************************************************************/
  1117.  
  1118.  
  1119.  
  1120. #pragma segment Window
  1121. void    SetSidebarSize(FileRecHndl frHndl, short newLeft, short newTop)
  1122. {
  1123.     WindowPtr            oldPort, window;
  1124.     Rect                portRct, rct;
  1125.     Point                contOrg;
  1126.     short                oldLeft, oldTop, dh, dv;
  1127.     ControlHandle        ctl;
  1128.     RgnHandle            updateRgn;
  1129.     DrawFrameProcPtr    proc;
  1130.  
  1131.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1132.  
  1133.     window = (*frHndl)->fileState.window;
  1134.     if (window) {
  1135.         oldPort = SetFilePort(frHndl);
  1136.         portRct = window->portRect;
  1137.         SetOrigin(0, -16384);        /* Prepare to modify (redraw) document scrollbars. */
  1138.     }
  1139.  
  1140.     oldLeft = (*frHndl)->fileState.leftSidebar;
  1141.     oldTop  = (*frHndl)->fileState.topSidebar;
  1142.  
  1143.     dh = 0;
  1144.     if (newLeft != kwNoChange) {
  1145.         ctl = (*frHndl)->fileState.hScroll;
  1146.         if (ctl) {
  1147.             HideControl(ctl);
  1148.             rct = (*ctl)->contrlRect;
  1149.             rct.left += (newLeft - oldLeft);
  1150.             MoveControl(ctl, rct.left, rct.top);
  1151.             SizeControl(ctl, rct.right - rct.left, 16);
  1152.             ShowControl(ctl);
  1153.         }
  1154.         dh = newLeft - oldLeft;
  1155.     }
  1156.  
  1157.     dv = 0;
  1158.     if (newTop != kwNoChange) {
  1159.         ctl = (*frHndl)->fileState.vScroll;
  1160.         if (ctl) {
  1161.             HideControl(ctl);
  1162.             rct = (*ctl)->contrlRect;
  1163.             rct.top += (newTop - oldTop);
  1164.             MoveControl(ctl, rct.left, rct.top);
  1165.             SizeControl(ctl, 16, rct.bottom - rct.top);
  1166.             ShowControl(ctl);
  1167.         }
  1168.         dv = newTop - oldTop;
  1169.     }
  1170.  
  1171.     if (dh < 0)
  1172.         (*frHndl)->fileState.leftSidebar = newLeft;
  1173.     if (dv < 0)
  1174.         (*frHndl)->fileState.topSidebar  = newTop;
  1175.  
  1176.     if (window) {
  1177.         BeginContent(window);
  1178.         ScrollRect(&(window->portRect), dh, dv, updateRgn = NewRgn());
  1179.         EndContent(window);
  1180.     }
  1181.  
  1182.     if (dh)
  1183.         (*frHndl)->fileState.leftSidebar = newLeft;
  1184.     if (dv)
  1185.         (*frHndl)->fileState.topSidebar  = newTop;
  1186.  
  1187.     if (window) {
  1188.         AdjustScrollBars(window);
  1189.  
  1190.         proc = (*frHndl)->fileState.drawFrameProc;
  1191.         if (proc) {
  1192.             SetOrigin(-16384, 0);
  1193.             (*proc)(frHndl, window, false);        /* Draw the application's portion of the frame. */
  1194.         }
  1195.  
  1196.         OffsetRgn(((WindowPeek)window)->updateRgn, dh, dv);
  1197.             /* We want to add the scrolled-in area into the updateRgn.  We
  1198.             ** also want to keep the old area.  The old update area is
  1199.             ** no longer mapped to the same location, due to the scroll,
  1200.             ** so offset it by the amount scrolled.  Once it is offset, we
  1201.             ** can add our new update portion to the updateRgn. */
  1202.         GetContentOrigin(window, &contOrg);
  1203.         SetOrigin(contOrg.h, contOrg.v);
  1204.         InvalRgn(updateRgn);
  1205.         DisposeRgn(updateRgn);
  1206.  
  1207.         SetOrigin(portRct.left, portRct.top);
  1208.         SetPort(oldPort);
  1209.  
  1210.         DoScrollFrame(window, dh, dv);        /* There may be changes in the frame due to scrolling. */
  1211.     }
  1212. }
  1213.  
  1214.  
  1215.  
  1216. /*****************************************************************************/
  1217.  
  1218.  
  1219.  
  1220. #pragma segment Window
  1221. void    SetScrollIndentSize(FileRecHndl frHndl, short newh, short newv)
  1222. {
  1223.     WindowPtr            oldPort, window;
  1224.     Rect                portRct, rct;
  1225.     short                oldh, oldv;
  1226.     ControlHandle        ctl;
  1227.     DrawFrameProcPtr    proc;
  1228.  
  1229.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1230.  
  1231.     oldPort = SetFilePort(frHndl);
  1232.     GetPort(&window);
  1233.     portRct = window->portRect;
  1234.     SetOrigin(0, -16384);
  1235.  
  1236.     oldh = (*frHndl)->fileState.hScrollIndent;
  1237.     oldv = (*frHndl)->fileState.vScrollIndent;
  1238.  
  1239.     if (newh != kwNoChange) {
  1240.         ctl = (*frHndl)->fileState.hScroll;
  1241.         if (ctl) {
  1242.             HideControl(ctl);
  1243.             rct = (*ctl)->contrlRect;
  1244.             rct.left += (newh - oldh);
  1245.             MoveControl(ctl, rct.left, rct.top);
  1246.             SizeControl(ctl, rct.right - rct.left, 16);
  1247.             ShowControl(ctl);
  1248.         }
  1249.         (*frHndl)->fileState.hScrollIndent = newh;
  1250.     }
  1251.  
  1252.     if (newv != kwNoChange) {
  1253.         ctl = (*frHndl)->fileState.vScroll;
  1254.         if (ctl) {
  1255.             HideControl(ctl);
  1256.             rct = (*ctl)->contrlRect;
  1257.             rct.top += (newv - oldv);
  1258.             MoveControl(ctl, rct.left, rct.top);
  1259.             SizeControl(ctl, 16, rct.bottom - rct.top);
  1260.             ShowControl(ctl);
  1261.         }
  1262.         (*frHndl)->fileState.vScrollIndent = newv;
  1263.     }
  1264.  
  1265.     proc = (*frHndl)->fileState.drawFrameProc;
  1266.     if (proc) {
  1267.         SetOrigin(-16384, 0);
  1268.         (*proc)(frHndl, window, false);        /* Draw the application's portion of the frame. */
  1269.     }
  1270.  
  1271.     SetOrigin(portRct.left, portRct.top);
  1272.     SetPort(oldPort);
  1273. }
  1274.  
  1275.  
  1276.  
  1277. /*****************************************************************************/
  1278.  
  1279.  
  1280.  
  1281. #pragma segment Window
  1282. FileRecHndl    GetNextDocument(WindowPtr window, OSType sftype)
  1283. {
  1284.     if (!(window = GetNextWindow(window, sftype))) return(nil);
  1285.     if (IsDAWindow(window))                           return(nil);
  1286.  
  1287.     return((FileRecHndl)GetWRefCon(window));
  1288. }
  1289.  
  1290.  
  1291.  
  1292. /*****************************************************************************/
  1293.  
  1294.  
  1295.  
  1296. #pragma segment Window
  1297. WindowPtr    GetNextWindow(WindowPtr window, OSType sftype)
  1298. {
  1299.     WindowPeek    wpeek;
  1300.     FileRecHndl    frHndl;
  1301.  
  1302.     if (window == (WindowPtr)-1)
  1303.         window = nil;
  1304.  
  1305.     if (!window)
  1306.         wpeek = LMGetWindowList();
  1307.     else
  1308.         wpeek = ((WindowPeek)window)->nextWindow;
  1309.  
  1310.     for (; wpeek; wpeek = wpeek->nextWindow) {
  1311.  
  1312.         if (IsDAWindow((WindowPtr)wpeek))
  1313.             if (!sftype)
  1314.                 return((WindowPtr)wpeek);
  1315.  
  1316.         if (wpeek->windowKind < 1000) continue;
  1317.  
  1318.         if (!sftype) break;
  1319.             /* Request is for any window.  We have a window, so break. */
  1320.  
  1321.         frHndl = (FileRecHndl)GetWRefCon((WindowPtr)wpeek);
  1322.         if (!frHndl) continue;
  1323.  
  1324.         if ((*frHndl)->fileState.sfType == sftype) break;        /* Bingo. */
  1325.             /* The sfType field is the first 4 bytes in the refcon handle.  If you don't
  1326.             ** want to use the application framework completely, but you still want this
  1327.             ** function, then all you have to do is place an identifier in the first 4
  1328.             ** bytes of the refcon handle. */
  1329.     }
  1330.  
  1331.     return((WindowPtr)wpeek);
  1332. }
  1333.  
  1334.  
  1335.  
  1336. /*****************************************************************************/
  1337.  
  1338.  
  1339.  
  1340. #pragma segment Window
  1341. WindowPtr    GetPreviousWindow(WindowPtr window)
  1342. {
  1343.     WindowPeek    wpeek;
  1344.     WindowPtr    lastWindow;
  1345.  
  1346.     if (window == (WindowPtr)-1) return((WindowPtr)-1);
  1347.     wpeek = LMGetWindowList();
  1348.  
  1349.     for (lastWindow = (WindowPtr)-1; wpeek; wpeek = wpeek->nextWindow) {
  1350.         if (window == (WindowPtr)wpeek) break;
  1351.         lastWindow = (WindowPtr)wpeek;
  1352.     }
  1353.  
  1354.     return(lastWindow);
  1355. }
  1356.  
  1357.  
  1358.  
  1359. /*****************************************************************************/
  1360.  
  1361.  
  1362.  
  1363. #pragma segment Window
  1364. void    DoZoomWindow(WindowPtr window, EventRecord *event, short zoomDir)
  1365. {
  1366.     Boolean        doit;
  1367.     Rect        old;
  1368.     FileRecHndl    frHndl;
  1369.     short        hDocSize, vDocSize;
  1370.  
  1371.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1372.  
  1373.     if (!window)                                     return;
  1374.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return;
  1375.  
  1376.     doit = true;
  1377.     if (event)
  1378.         doit = TrackBox(window, event->where, zoomDir);
  1379.  
  1380.     if (doit) {
  1381.         old       = GetWindowContentRect(window);
  1382.         hDocSize  = (*frHndl)->d.doc.fhInfo.hDocSize;
  1383.         hDocSize += (*frHndl)->fileState.leftSidebar;
  1384.         if ((*frHndl)->fileState.vScroll)
  1385.             hDocSize += 15;
  1386.         vDocSize  = (*frHndl)->d.doc.fhInfo.vDocSize;
  1387.         vDocSize += (*frHndl)->fileState.topSidebar;
  1388.         if ((*frHndl)->fileState.hScroll)
  1389.             vDocSize += 15;
  1390.  
  1391.         if (hDocSize < (*frHndl)->fileState.windowSizeBounds.left)
  1392.             hDocSize = (*frHndl)->fileState.windowSizeBounds.left;
  1393.         if (vDocSize < (*frHndl)->fileState.windowSizeBounds.top)
  1394.             vDocSize = (*frHndl)->fileState.windowSizeBounds.top;
  1395.  
  1396.         ZoomToWindowDevice(window, hDocSize, vDocSize, zoomDir, false);
  1397.         DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1398.     }
  1399. }
  1400.  
  1401.  
  1402.  
  1403. /*****************************************************************************/
  1404. /*****************************************************************************/
  1405.  
  1406.  
  1407.  
  1408. #pragma segment Window
  1409. RgnHandle    DoCalcFrameRgn(WindowPtr window)
  1410. {
  1411.     FileRecHndl            frHndl;
  1412.     WindowPtr            oldPort;
  1413.     RgnHandle            urgn, wrgn;
  1414.     short                i;
  1415.     Rect                rct;
  1416.     Point                l2g;
  1417.     CalcFrameRgnProcPtr    proc;
  1418.  
  1419.     urgn = NewRgn();
  1420.     if (!window)                                     return(urgn);
  1421.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return(urgn);
  1422.  
  1423.     oldPort = SetFilePort(frHndl);
  1424.     SetOrigin(0, 0);
  1425.  
  1426.     proc = (*frHndl)->fileState.calcFrameRgnProc;
  1427.     if (proc)
  1428.         (*proc)(frHndl, window, urgn);
  1429.  
  1430.     wrgn = NewRgn();
  1431.     for (i = 0; i < 2; ++i) {
  1432.         rct = window->portRect;
  1433.         if (i)
  1434.             rct.bottom = (*frHndl)->fileState.topSidebar;
  1435.         else
  1436.             rct.right  = (*frHndl)->fileState.leftSidebar;
  1437.         RectRgn(wrgn, &rct);
  1438.         UnionRgn(urgn, wrgn, urgn);
  1439.     }
  1440.     DisposeRgn(wrgn);
  1441.  
  1442.     l2g.h = l2g.v = 0;
  1443.     LocalToGlobal(&l2g);
  1444.     OffsetRgn(urgn, l2g.h, l2g.v);
  1445.  
  1446.     wrgn = DoCalcScrollRgn(window);
  1447.     UnionRgn(urgn, wrgn, urgn);
  1448.     DisposeRgn(wrgn);
  1449.  
  1450.     SetPort(oldPort);
  1451.     return(urgn);
  1452. }
  1453.  
  1454.  
  1455.  
  1456. /*****************************************************************************/
  1457.  
  1458.  
  1459.  
  1460. #pragma segment Window
  1461. RgnHandle    DoCalcScrollRgn(WindowPtr window)
  1462. {
  1463.     FileRecHndl            frHndl;
  1464.     WindowPtr            oldPort;
  1465.     RgnHandle            urgn, wrgn;
  1466.     short                i;
  1467.     long                attributes;
  1468.     Boolean                growIconSpace;
  1469.     Rect                rct;
  1470.     Point                l2g;
  1471.     ControlHandle        ctl;
  1472.  
  1473.     urgn = NewRgn();
  1474.     if (!window) return(urgn);
  1475.     if (!window)                                     return(urgn);
  1476.     if (!(frHndl = (FileRecHndl)GetWRefCon(window))) return(urgn);
  1477.  
  1478.     oldPort = SetFilePort(frHndl);
  1479.     SetOrigin(0, 0);
  1480.  
  1481.     attributes    = (*frHndl)->fileState.attributes;
  1482.     growIconSpace = (attributes & (kwGrowIcon | (kwHScrollLessGrow - kwHScroll) | (kwVScrollLessGrow - kwVScroll)));
  1483.         /* growIconSpace true if window has grow icon or a blank space for one. */
  1484.  
  1485.     wrgn = NewRgn();
  1486.     if (growIconSpace) {
  1487.         rct = window->portRect;
  1488.         rct.left = rct.right  - 15;
  1489.         rct.top  = rct.bottom - 15;
  1490.         RectRgn(wrgn, &rct);
  1491.         UnionRgn(urgn, wrgn, urgn);
  1492.     }
  1493.     for (i = 0; i < 2; ++i) {
  1494.         ctl = (i) ? (*frHndl)->fileState.vScroll : (*frHndl)->fileState.hScroll;
  1495.         if (ctl) {
  1496.             rct = (*ctl)->contrlRect;
  1497.             if (i)
  1498.                 rct.top  -= (*frHndl)->fileState.vScrollIndent;
  1499.             else
  1500.                 rct.left -= (*frHndl)->fileState.hScrollIndent;
  1501.             OffsetRect(&rct, 0, 16384);
  1502.             RectRgn(wrgn, &rct);
  1503.             UnionRgn(urgn, wrgn, urgn);
  1504.         }
  1505.     }
  1506.     DisposeRgn(wrgn);
  1507.  
  1508.     l2g.h = l2g.v = 0;
  1509.     LocalToGlobal(&l2g);
  1510.     OffsetRgn(urgn, l2g.h, l2g.v);
  1511.  
  1512.     SetPort(oldPort);
  1513.     return(urgn);
  1514. }
  1515.  
  1516.  
  1517.  
  1518. /*****************************************************************************/
  1519.  
  1520.  
  1521.  
  1522. #pragma segment Window
  1523. void    DoContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  1524. {
  1525.     FileRecHndl            frHndl;
  1526.     ContentClickProcPtr    proc;
  1527.  
  1528.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1529.  
  1530.     if (!IsDAWindow(window)) {
  1531.         frHndl = (FileRecHndl)GetWRefCon(window);
  1532.         if (frHndl) {
  1533.             proc = (*frHndl)->fileState.contentClickProc;
  1534.             if (proc)
  1535.                 (*proc)(window, event, firstClick);
  1536.         }
  1537.     }
  1538. }
  1539.  
  1540.  
  1541.  
  1542. /*****************************************************************************/
  1543.  
  1544.  
  1545.  
  1546. #pragma segment Window
  1547. void    DoDragWindow(WindowPtr window, EventRecord *event, Rect bounds)
  1548. {
  1549.     WindowPtr    oldPort, fwindow;
  1550.     GrafPort    bigPort;
  1551.     WindowPeek    wpeek;
  1552.     FileRecHndl    frHndl;
  1553.     RgnHandle    dragRgn;
  1554.     Point        offset, windOrg;
  1555.     long        wkind;
  1556.  
  1557.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1558.  
  1559.     if (!StillDown()) return;
  1560.  
  1561.     GetPort(&oldPort);
  1562.  
  1563.     OpenPort(&bigPort);
  1564.     CopyRgn(GetGrayRgn(), bigPort.visRgn);
  1565.     bigPort.portRect = (*bigPort.visRgn)->rgnBBox;
  1566.  
  1567.     if (gSystemVersion >= 0x0700) {
  1568.         HMGetBalloonWindow(&fwindow);
  1569.         if (fwindow)
  1570.             DiffRgn(bigPort.visRgn, ((WindowPeek)fwindow)->strucRgn, bigPort.visRgn);
  1571.     }
  1572.  
  1573.     fwindow = (WindowPtr)-1;
  1574.     wkind = kwIsDocument;
  1575.     frHndl = (FileRecHndl)GetWRefCon(window);
  1576.     if (frHndl)
  1577.         if (((WindowPeek)window)->windowKind >= 1000)
  1578.             wkind = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1579.     fwindow = FrontWindowOfType(wkind, true);
  1580.     for (wpeek = (WindowPeek)FrontWindow(); wpeek; wpeek = wpeek->nextWindow) {
  1581.         if (fwindow == (WindowPtr)wpeek) break;
  1582.         DiffRgn(bigPort.visRgn, wpeek->strucRgn, bigPort.visRgn);
  1583.     }
  1584.  
  1585.     CopyRgn(((WindowPeek)window)->strucRgn, dragRgn = NewRgn());
  1586.     *(long *)&offset = DragGrayRgn(dragRgn, event->where, &bounds, &bounds, noConstraint, nil);
  1587.  
  1588.     DisposeRgn(dragRgn);
  1589.     ClosePort(&bigPort);
  1590.  
  1591.     if ((offset.h != (short)0x8000) || (offset.v != (short)0x8000)) {
  1592.         windOrg.h = window->portRect.left;
  1593.         windOrg.v = window->portRect.top;
  1594.         SetPort(window);
  1595.         LocalToGlobal(&windOrg);
  1596.         MoveWindow(window, windOrg.h + offset.h, windOrg.v + offset.v, false);
  1597.     }
  1598.  
  1599.     SetPort(oldPort);
  1600.  
  1601.     if (!(event->modifiers & cmdKey))
  1602.         CleanSendInFront(window, fwindow);
  1603. }
  1604.  
  1605.  
  1606.  
  1607. /*****************************************************************************/
  1608.  
  1609.  
  1610.  
  1611. #pragma segment Window
  1612. void    DoDrawFrame(WindowPtr window, Boolean activate)
  1613. {
  1614.     FileRecHndl            frHndl;
  1615.     WindowPtr            oldPort;
  1616.     Rect                worg;
  1617.     long                attributes;
  1618.     DrawFrameProcPtr    proc;
  1619.  
  1620.     if (window) {
  1621.         frHndl = (FileRecHndl)GetWRefCon(window);
  1622.         if (frHndl) {
  1623.             oldPort = SetFilePort(frHndl);
  1624.             worg    = window->portRect;
  1625.             SetOrigin(0, 0);
  1626.     
  1627.             attributes = (*frHndl)->fileState.attributes;
  1628.             if (attributes & kwGrowIcon)
  1629.                 DoDrawGrowIcon(window, false, false);
  1630.  
  1631.             SetOrigin(0, -16384);
  1632.             DoDrawControls(window, true);
  1633.             SetOrigin(-16384, 0);
  1634.             proc = (*frHndl)->fileState.drawFrameProc;
  1635.             if (proc)
  1636.                 (*proc)(frHndl, window, activate);
  1637.     
  1638.             SetOrigin(worg.left, worg.top);
  1639.             SetPort(oldPort);
  1640.         }
  1641.     }
  1642. }
  1643.  
  1644.  
  1645.  
  1646. /*****************************************************************************/
  1647.  
  1648.  
  1649.  
  1650. #pragma segment Window
  1651. OSErr    DoFreeDocument(FileRecHndl frHndl)
  1652. {
  1653.     FreeDocumentProcPtr    proc;
  1654.     OSErr                err;
  1655.  
  1656.     err = noErr;
  1657.     proc = (*frHndl)->fileState.freeDocumentProc;
  1658.     if (proc)
  1659.         err = (*proc)(frHndl);
  1660.     return(err);
  1661. }
  1662.  
  1663.  
  1664.  
  1665. /*****************************************************************************/
  1666.  
  1667.  
  1668.  
  1669. #pragma segment Window
  1670. OSErr    DoFreeWindow(FileRecHndl frHndl, WindowPtr window)
  1671. {
  1672.     FreeWindowProcPtr    proc;
  1673.     OSErr                err;
  1674.  
  1675.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1676.  
  1677.     err = noErr;
  1678.     proc = (*frHndl)->fileState.freeWindowProc;
  1679.     if (proc)
  1680.         err = (*proc)(frHndl, window);
  1681.     return(err);
  1682. }
  1683.  
  1684.  
  1685.  
  1686. /*****************************************************************************/
  1687.  
  1688.  
  1689.  
  1690. #pragma segment Window
  1691. OSErr    DoImageDocument(FileRecHndl frHndl)
  1692. {
  1693.     ImageProcPtr    proc;
  1694.     OSErr            err;
  1695.  
  1696.     err = noErr;
  1697.     proc = (*frHndl)->fileState.imageProc;
  1698.     if (proc)
  1699.         err = (*proc)(frHndl);
  1700.     return(err);
  1701. }
  1702.  
  1703.  
  1704.  
  1705. /*****************************************************************************/
  1706.  
  1707.  
  1708.  
  1709. #pragma segment Window
  1710. OSErr    DoInitContent(FileRecHndl frHndl, WindowPtr window)
  1711. {
  1712.     InitContentProcPtr    proc;
  1713.     OSErr                err;
  1714.  
  1715.     err = noErr;
  1716.     proc = (*frHndl)->fileState.initContentProc;
  1717.     if (proc)
  1718.         err = (*proc)(frHndl, window);
  1719.     return(err);
  1720. }
  1721.  
  1722.  
  1723.  
  1724. /*****************************************************************************/
  1725.  
  1726.  
  1727.  
  1728. #pragma segment Window
  1729. Boolean    DoKeyDown(EventRecord *event)
  1730. {
  1731.     char                key;
  1732.     WindowPtr            window, fwindow;
  1733.     FileRecHndl            frHndl;
  1734.     ContentKeyProcPtr    proc;
  1735.     Boolean                passThrough;
  1736.     short                menuID, menuItem, menuItem2, charsUsed;
  1737.     long                menuVal, attr, wkind;
  1738.     Str32                str;
  1739.     OSType                sftype;
  1740.     OSErr                err;
  1741.     DoMenuItemProcPtr    mproc, mp;
  1742.  
  1743.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1744.  
  1745.     key = event->message & charCodeMask;
  1746.     if (event->modifiers & cmdKey) {        /* If command key down... */
  1747.         if (event->what == keyDown) {
  1748.             DoAdjustMenus();                /* Prepare menus properly. */
  1749.             menuVal   = MenuKey(key);
  1750.             menuID    = HiWord(menuVal);
  1751.             menuItem  = LoWord(menuVal);
  1752.             menuItem2 = MapMItem(menuID, menuItem);
  1753.             if (menuID) {
  1754.                 mproc = DoMenuItem;
  1755.                 if (IsAppWindow(window = FrontWindow())) {
  1756.                     mp = (*(FileRecHndl)GetWRefCon(window))->fileState.doMenuItemProc;
  1757.                     if (mp)
  1758.                         mproc = mp;
  1759.                 }
  1760.                 if (!(*mproc)(window, menuID, menuItem2)) {
  1761.                     GetIndString(str, menuID, menuItem);
  1762.                     if (str[0]) {
  1763.                         p2dec(str, &charsUsed);
  1764.                         if (str[0] > charsUsed + 2) {
  1765.                             if (str[charsUsed + 2] == '\'') {
  1766.                                 BlockMove(str + charsUsed + 3, (Ptr)&sftype, sizeof(OSType));
  1767.                                 window = GetNextWindow(nil, sftype);
  1768.                                 if (window) {
  1769.                                     frHndl = (FileRecHndl)GetWRefCon(window);
  1770.                                     attr   = (*frHndl)->fileState.attributes;
  1771.                                     if (attr & kwHideOnClose) {
  1772.                                         if (!((WindowPeek)window)->visible)
  1773.                                             ShowHide(window, true);
  1774.                                         wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1775.                                         if (!(fwindow = FrontWindowOfType(wkind, false)))
  1776.                                             fwindow = (WindowPtr)-1;
  1777.                                         CleanSendInFront(window, fwindow);
  1778.                                     }
  1779.                                     else window = nil;
  1780.                                 }
  1781.                                 if (!window) {
  1782.                                     DoSetResCursor(watchCursor);
  1783.                                     err = NewDocumentWindow(&frHndl, sftype, true);
  1784.                                     if (!err) {
  1785.                                         if (frHndl) {
  1786.                                             window = (*frHndl)->fileState.window;
  1787.                                             attr   = (*frHndl)->fileState.attributes;
  1788.                                             if (!((WindowPeek)window)->visible)
  1789.                                                 ShowHide(window, true);
  1790.                                             wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1791.                                             if (!(fwindow = FrontWindowOfType(wkind, false)))
  1792.                                                 fwindow = (WindowPtr)-1;
  1793.                                             CleanSendInFront(window, fwindow);
  1794.                                         }
  1795.                                     }
  1796.                                     else {
  1797.                                         gDialogErr = err;
  1798.                                         NewDocumentWindow(nil, 'ERR#', false);
  1799.                                     }
  1800.                                 }
  1801.                             }
  1802.                         }
  1803.                     }
  1804.                 }
  1805.                 HiliteMenu(0);        /* Unhighlight what MenuKey hilited. */
  1806.                 DoSetCursor(nil);
  1807.                 return(false);
  1808.             }
  1809.         }
  1810.         else return(false);
  1811.     }
  1812.  
  1813.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  1814.         if (!((WindowPeek)window)->visible) continue;
  1815.         if (((WindowPeek)window)->windowKind >= 1000) {
  1816.             frHndl = (FileRecHndl)GetWRefCon(window);
  1817.             if (frHndl) {
  1818.                 proc = (*frHndl)->fileState.contentKeyProc;
  1819.                 if (proc) {
  1820.                     passThrough = false;
  1821.                     if ((*proc)(window, event, &passThrough)) return(true);
  1822.                     if (!passThrough) break;
  1823.                 }
  1824.             }
  1825.         }
  1826.     }
  1827.  
  1828.     return(false);
  1829. }
  1830.  
  1831.  
  1832.  
  1833. /*****************************************************************************/
  1834.  
  1835.  
  1836.  
  1837. #pragma segment Window
  1838. void    DoMouseDown(EventRecord *event)
  1839. {
  1840.     WindowPtr            window, fwindow, dlog, ww;
  1841.     FileRecHndl            frHndl;
  1842.     Rect                contentRct, old, growLimits, tearRect;
  1843.     Point                pt;
  1844.     short                part, menuID, menuItem, menuItem2, charsUsed;
  1845.     long                menuVal, size, wkind, attr;
  1846.     Str63                str;
  1847.     OSType                sftype;
  1848.     OSErr                err;
  1849.     DoMenuItemProcPtr    mproc, mp;
  1850.  
  1851.     gCursorPtr = nil;        /* Force recalc of cursor. */
  1852.  
  1853.     part = FindWindow(event->where, &window);
  1854.  
  1855.     frHndl = nil;
  1856.     if (window)
  1857.         if (((WindowPeek)window)->windowKind >= 1000)
  1858.             frHndl = (FileRecHndl)GetWRefCon(window);
  1859.  
  1860.     if (part != inContent)
  1861.         DoSetCursor(&qd.arrow);
  1862.  
  1863.     dlog = FrontWindowOfType(kwIsModalDialog, true);
  1864.     if ((dlog) && (window != dlog)) {
  1865.         if (part != inMenuBar) {
  1866.             SysBeep(1);
  1867.             return;
  1868.         }
  1869.     }
  1870.  
  1871.     switch(part) {
  1872.  
  1873.         case inContent:
  1874.  
  1875.             if (!IsAppWindow(window)) {
  1876.                 if (window != FrontWindow()) {
  1877.                     SelectWindow(window);
  1878.                     HiliteWindows();
  1879.                 }
  1880.                 break;
  1881.             }
  1882.  
  1883.             wkind   = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  1884.             fwindow = FrontWindowOfType(wkind, true);
  1885.                 /* fwindow guaranteed, since worst case we find ourself. */
  1886.  
  1887.             if (window == fwindow) {
  1888.                 DoContentClick(window, event, false);
  1889.                 break;
  1890.             }        /* The window is the frontmost of this type, so handle the click. */
  1891.  
  1892.             CleanSendInFront(window, fwindow);
  1893.  
  1894.             if ((*frHndl)->fileState.attributes & kwDoFirstClick) {
  1895.                 DoUpdate(window);
  1896.                 contentRct = GetWindowContentRect(window);
  1897.                 if (PtInRect(event->where, &contentRct))
  1898.                     DoContentClick(window, event, true);
  1899.             }
  1900.             break;
  1901.  
  1902.         case inDrag:
  1903.             DoDragWindow(window, event, qd.screenBits.bounds);
  1904.             break;        /* Pass screenBits.bounds to get all gDevices. */
  1905.  
  1906.         case inGoAway:
  1907.             if (TrackGoAway(window, event->where))
  1908.                 DisposeOneWindow(window, kClose);
  1909.             break;
  1910.  
  1911.         case inGrow:
  1912.             old = GetWindowContentRect(window);
  1913.             growLimits = (*frHndl)->fileState.windowSizeBounds;
  1914.             ++growLimits.right;
  1915.             ++growLimits.bottom;
  1916.             size = GrowWindow(window, event->where, &growLimits);
  1917.             if (size) {
  1918.                 pt = *(Point *)&size;
  1919.                 SizeWindow(window, pt.h, pt.v, true);
  1920.                 DoResizeWindow(window, old.right - old.left, old.bottom - old.top);
  1921.             }
  1922.             break;
  1923.  
  1924.         case inMenuBar:        /* Process mouse menu command (if any). */
  1925.             DoAdjustMenus();
  1926.             DoSetCursor(&qd.arrow);
  1927.             menuVal  = MenuSelect(event->where);
  1928.             menuID   = HiWord(menuVal);
  1929.             menuItem = LoWord(menuVal);
  1930.             if (menuItem == -1)
  1931.                 menuItem = CountMItems(GetMenuHandle(menuID));
  1932.             menuItem2 = MapMItem(menuID, menuItem);
  1933.             mproc = DoMenuItem;
  1934.             if (IsAppWindow(window = FrontWindow())) {
  1935.                 mp = (*(FileRecHndl)GetWRefCon(window))->fileState.doMenuItemProc;
  1936.                 if (mp)
  1937.                     mproc = mp;
  1938.             }
  1939.             if (!(*mproc)(window, menuID, menuItem2)) {
  1940.                 GetIndString(str, menuID, menuItem);
  1941.                 if (str[0]) {
  1942.                     p2dec(str, &charsUsed);
  1943.                     if (str[0] > charsUsed + 2) {
  1944.                         if (str[charsUsed + 2] == '\'') {
  1945.                             BlockMove(str + charsUsed + 3, (Ptr)&sftype, sizeof(OSType));
  1946.                             window = GetNextWindow(nil, sftype);
  1947.                             if (window) {
  1948.                                 frHndl = (FileRecHndl)GetWRefCon(window);
  1949.                                 attr   = (*frHndl)->fileState.attributes;
  1950.                                 if (attr & kwHideOnClose) {
  1951.                                     if (menuItem2 == -1) {
  1952.                                         GetMenuItemText(GetMenuHandle(menuID), menuItem, str);
  1953.                                         BlockMove(str + 1, &tearRect, sizeof(Rect));
  1954.                                         MoveWindow(window, tearRect.left, tearRect.top, false);
  1955.                                     }
  1956.                                     if (!((WindowPeek)window)->visible)
  1957.                                         ShowHide(window, true);
  1958.                                     wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1959.                                     if (!(fwindow = FrontWindowOfType(wkind, false)))
  1960.                                         fwindow = (WindowPtr)-1;
  1961.                                     CleanSendInFront(window, fwindow);
  1962.                                 }
  1963.                                 else window = nil;
  1964.                             }
  1965.                             if (!window) {
  1966.                                 DoSetResCursor(watchCursor);
  1967.                                 err = NewDocumentWindow(&frHndl, sftype, true);
  1968.                                 if (!err) {
  1969.                                     if (frHndl) {
  1970.                                         window = (*frHndl)->fileState.window;
  1971.                                         attr   = (*frHndl)->fileState.attributes;
  1972.                                         if (!((WindowPeek)window)->visible)
  1973.                                             ShowHide(window, true);
  1974.                                         wkind = (attr & (kwIsPalette | kwIsModalDialog));
  1975.                                         if (!(fwindow = FrontWindowOfType(wkind, false)))
  1976.                                             fwindow = (WindowPtr)-1;
  1977.                                         CleanSendInFront(window, fwindow);
  1978.                                     }
  1979.                                 }
  1980.                                 else {
  1981.                                     gDialogErr = err;
  1982.                                     NewDocumentWindow(nil, 'ERR#', false);
  1983.                                 }
  1984.                             }
  1985.                         }
  1986.                     }
  1987.                 }
  1988.             }
  1989.             HiliteMenu(0);        /* Unhighlight what MenuSelect hilited. */
  1990.             break;
  1991.  
  1992.         case inSysWindow:    /* Let the system handle the mouseDown. */
  1993.             SystemClick(event, window);
  1994.             for (ww = FrontWindow(); ww; ww = (WindowPtr)(((WindowPeek)ww)->nextWindow))
  1995.                 if (ww == window) break;
  1996.                     /* We have to go find out if the window was closed ourselves.  Silly, huh. */
  1997.             if (!ww) WindowGoneFixup(window);
  1998.             break;
  1999.  
  2000.         case inZoomIn:
  2001.         case inZoomOut:
  2002.             DoZoomWindow(window, event, part);
  2003.             break;
  2004.  
  2005.     }
  2006. }
  2007.  
  2008.  
  2009.  
  2010. /*****************************************************************************/
  2011.  
  2012.  
  2013.  
  2014. /* This function converts a menu item hard-id (one returned by the toolbox) to a
  2015. ** soft-id (defined in the 'STR#' resource associated with the menu.  If there is
  2016. ** a 'STR#' resource defined with the same id as the menu, it is assumed to be
  2017. ** for the purpose of converting hard-id values to soft-id values. */
  2018.  
  2019. #pragma segment Window
  2020. short    MapMItem(short menuID, short menuItem)
  2021. {
  2022.     Str32    str;
  2023.  
  2024.     if (menuID == 128)
  2025.         return(menuItem);
  2026.  
  2027.     GetIndString(str, menuID, menuItem);
  2028.     if (str[0])
  2029.         menuItem = p2dec(str, nil);
  2030.  
  2031.     return(menuItem);
  2032. }
  2033.  
  2034.  
  2035.  
  2036. /*****************************************************************************/
  2037.  
  2038.  
  2039.  
  2040. /* This function is the logical reverse of MapMItem(). */
  2041.  
  2042. #pragma segment Window
  2043. short    UnmapMItem(short menuID, short menuItem)
  2044. {
  2045.     Str32    str;
  2046.     short    i, j;
  2047.  
  2048.     if (menuID == 128)                   return(menuItem);
  2049.     if (!Get1Resource('STR#', menuID)) return(menuItem);
  2050.         /* No such table, so don't convert it. */
  2051.  
  2052.     if (menuItem) {
  2053.         for (i = 1;; ++i) {
  2054.             GetIndString(str, menuID, i);
  2055.             if (!str[0]) return(32767);        /* No such entry found.  Return something invalid. */
  2056.             j = p2dec(str, nil);
  2057.             if (menuItem == j) return(i);
  2058.         }
  2059.     }
  2060.  
  2061.     return(menuItem);
  2062. }
  2063.  
  2064.  
  2065.  
  2066. /*****************************************************************************/
  2067.  
  2068.  
  2069.  
  2070. #pragma segment Window
  2071. OSErr    DoReadDocument(FileRecHndl frHndl)
  2072. {
  2073.     ReadDocumentProcPtr    proc;
  2074.     OSErr                err;
  2075.  
  2076.     err = noErr;
  2077.     proc = (*frHndl)->fileState.readDocumentProc;
  2078.     if (proc)
  2079.         err = (*proc)(frHndl);
  2080.     return(err);
  2081. }
  2082.  
  2083.  
  2084.  
  2085. /*****************************************************************************/
  2086.  
  2087.  
  2088.  
  2089. #pragma segment Window
  2090. OSErr    DoReadDocumentHeader(FileRecHndl frHndl)
  2091. {
  2092.     ReadDocumentHeaderProcPtr    proc;
  2093.     OSErr                        err;
  2094.  
  2095.     err = noErr;
  2096.     if ((*frHndl)->fileState.refNum) {
  2097.         proc = (*frHndl)->fileState.readDocumentHeaderProc;
  2098.         if (proc)
  2099.             err = (*proc)(frHndl);
  2100.     }
  2101.     return(err);
  2102. }
  2103.  
  2104.  
  2105.  
  2106. /*****************************************************************************/
  2107.  
  2108.  
  2109.  
  2110. #pragma segment Window
  2111. OSErr    DefaultReadDocumentHeader(FileRecHndl frHndl)
  2112. {
  2113.     short    refNum, vers, resAlreadyOpen, oldRes;
  2114.     OSErr    err;
  2115.     char    hstate;
  2116.     Ptr        ptr1, ptr2;
  2117.     long    count, attr;
  2118.     OSType    sftype;
  2119.     Handle    hndl;
  2120.  
  2121.     err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0);
  2122.     if (err) return(err);
  2123.  
  2124.     attr   = (*frHndl)->fileState.attributes;
  2125.     sftype = (*frHndl)->fileState.sfType;
  2126.  
  2127.     if (attr & kwDefaultDocHeader) {
  2128.         if (sftype != MovieFileType) {
  2129.             if (attr & kwHeaderIsResource) {
  2130.                 resAlreadyOpen = (*frHndl)->fileState.resRefNum;
  2131.                 UseDocResFile(frHndl, &oldRes, fsRdWrPerm);
  2132.                 hndl = Get1Resource('DFDH', 128);
  2133.                 err  = ResError();
  2134.                 if (!err)
  2135.                     if (!hndl)
  2136.                         err = resNotFound;
  2137.                 if (!err) {
  2138.                     ptr1   = (Ptr)&((*frHndl)->d.doc);
  2139.                     ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2140.                     count  = (long)ptr2 - (long)ptr1;
  2141.                     BlockMove(*hndl, ptr1, count);
  2142.                 }
  2143.                 if (hndl)
  2144.                     ReleaseResource(hndl);
  2145.                 if (!resAlreadyOpen)
  2146.                     CloseDocResFile(frHndl);
  2147.                 UseResFile(oldRes);
  2148.             }
  2149.             else {
  2150.                 if (!err) {        /* Read header info from file. */
  2151.                     hstate = HGetState((Handle)frHndl);
  2152.                     HLock((Handle)frHndl);
  2153.                     ptr1   = (Ptr)&((*frHndl)->d.doc);
  2154.                     ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2155.                     count  = (long)ptr2 - (long)ptr1;
  2156.                     err    = FSRead(refNum, &count, ptr1);
  2157.                     HSetState((Handle)frHndl, hstate);
  2158.                 }
  2159.             }
  2160.             if (!err) {
  2161.                 vers = (*frHndl)->d.doc.fhInfo.version;
  2162.                 if ((vers < gMinVersion) || (vers > gMaxVersion))
  2163.                     err = kWrongVersion;
  2164.             }
  2165.         }
  2166.     }
  2167.  
  2168.     return(err);
  2169. }
  2170.  
  2171.  
  2172.  
  2173. /*****************************************************************************/
  2174.  
  2175.  
  2176.  
  2177. #pragma segment Window
  2178. OSErr    DoWriteDocument(FileRecHndl frHndl)
  2179. {
  2180.     WriteDocumentProcPtr    proc;
  2181.     OSErr                    err;
  2182.  
  2183.     err = noErr;
  2184.     proc = (*frHndl)->fileState.writeDocumentProc;
  2185.     if (proc)
  2186.         err = (*proc)(frHndl);
  2187.     return(err);
  2188. }
  2189.  
  2190.  
  2191.  
  2192. /*****************************************************************************/
  2193.  
  2194.  
  2195.  
  2196. #pragma segment Window
  2197. OSErr    DoWriteDocumentHeader(FileRecHndl frHndl)
  2198. {
  2199.     WriteDocumentHeaderProcPtr    proc;
  2200.     OSErr                        err;
  2201.  
  2202.     err = noErr;
  2203.     if ((*frHndl)->fileState.refNum) {
  2204.         proc = (*frHndl)->fileState.writeDocumentHeaderProc;
  2205.         if (proc)
  2206.             err = (*proc)(frHndl);
  2207.     }
  2208.     return(err);
  2209. }
  2210.  
  2211.  
  2212.  
  2213. /*****************************************************************************/
  2214.  
  2215.  
  2216.  
  2217. #pragma segment Window
  2218. OSErr    DefaultWriteDocumentHeader(FileRecHndl frHndl)
  2219. {
  2220.     short        refNum, resAlreadyOpen, oldRes;
  2221.     OSErr        err;
  2222.     WindowPtr    window;
  2223.     char        hstate;
  2224.     Ptr            ptr1, ptr2;
  2225.     long        count, attr;
  2226.     OSType        sftype;
  2227.     Handle        hndl;
  2228.  
  2229.     err = SetFPos(refNum = (*frHndl)->fileState.refNum, fsFromStart, 0);
  2230.     if (err) return(err);
  2231.  
  2232.     attr   = (*frHndl)->fileState.attributes;
  2233.     sftype = (*frHndl)->fileState.sfType;
  2234.  
  2235.     if (attr & kwDefaultDocHeader) {
  2236.         if (sftype != MovieFileType) {
  2237.             window = (*frHndl)->fileState.window;
  2238.             if (window) {
  2239.                 if (!(*frHndl)->fileState.readOnly) {
  2240.                     (*frHndl)->d.doc.fhInfo.structureRect = GetWindowStructureRect(window);
  2241.                     (*frHndl)->d.doc.fhInfo.contentRect   = GetWindowContentRect(window);
  2242.                     (*frHndl)->d.doc.fhInfo.stdState      = mDerefWStateData(window)->stdState;
  2243.                     if (((WindowPeek)window)->spareFlag)
  2244.                         (*frHndl)->d.doc.fhInfo.userState = mDerefWStateData(window)->userState;
  2245.                 }
  2246.             }
  2247.             else SetRect(&(*frHndl)->d.doc.fhInfo.structureRect, 0, 0, 0, 0);
  2248.             if (attr & kwHeaderIsResource) {
  2249.                 resAlreadyOpen = (*frHndl)->fileState.resRefNum;
  2250.                 UseDocResFile(frHndl, &oldRes, fsRdWrPerm);
  2251.                 ptr1   = (Ptr)&((*frHndl)->d.doc);
  2252.                 ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2253.                 count  = (long)ptr2 - (long)ptr1;
  2254.                 hndl = Get1Resource('DFDH', 128);
  2255.                 if (hndl) {
  2256.                     RemoveResource(hndl);
  2257.                     DisposeHandle(hndl);
  2258.                 }
  2259.                 hndl = NewHandle(count);
  2260.                 if (hndl) {
  2261.                     ptr1 = (Ptr)&((*frHndl)->d.doc);
  2262.                     BlockMove(ptr1, *hndl, count);
  2263.                     AddResource(hndl, 'DFDH', 128, nil);
  2264.                     ChangedResource(hndl);
  2265.                     WriteResource(hndl);
  2266.                     UpdateResFile(CurResFile());
  2267.                     DetachResource(hndl);
  2268.                     DisposeHandle(hndl);
  2269.                 }
  2270.                 else err = memFullErr;
  2271.                 if (!resAlreadyOpen)
  2272.                     CloseDocResFile(frHndl);
  2273.                 UseResFile(oldRes);
  2274.             }
  2275.             else {
  2276.                 hstate = HGetState((Handle)frHndl);
  2277.                 HLock((Handle)frHndl);
  2278.                 ptr1   = (Ptr)&((*frHndl)->d.doc);
  2279.                 ptr2   = (Ptr)&((*frHndl)->d.doc.fhInfo.endDocHeaderInfo);
  2280.                 count  = (long)ptr2 - (long)ptr1;
  2281.                 err    = FSWrite(refNum, &count, ptr1);
  2282.                 HSetState((Handle)frHndl, hstate);
  2283.             }
  2284.         }
  2285.     }
  2286.  
  2287.     return(err);
  2288. }
  2289.  
  2290.  
  2291.  
  2292. /*****************************************************************************/
  2293.  
  2294.  
  2295.  
  2296. #pragma segment Window
  2297. void    DoResizeContent(WindowPtr window, short oldh, short oldv)
  2298. {
  2299.     FileRecHndl                frHndl;
  2300.     ResizeContentProcPtr    proc;
  2301.  
  2302.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2303.  
  2304.     if (IsAppWindow(window)) {
  2305.         frHndl = (FileRecHndl)GetWRefCon(window);
  2306.         if (frHndl) {
  2307.             proc = (*frHndl)->fileState.resizeContentProc;
  2308.             if (proc)
  2309.                 (*proc)(window, oldh, oldv);
  2310.         }
  2311.     }
  2312. }
  2313.  
  2314.  
  2315.  
  2316. /*****************************************************************************/
  2317.  
  2318.  
  2319.  
  2320. #pragma segment Window
  2321. void    DoScrollFrame(WindowPtr window, long dh, long dv)
  2322. {
  2323.     FileRecHndl            frHndl;
  2324.     ScrollFrameProcPtr    proc;
  2325.  
  2326.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2327.  
  2328.     if (IsAppWindow(window)) {
  2329.         frHndl = (FileRecHndl)GetWRefCon(window);
  2330.         if (frHndl) {
  2331.             proc = (*frHndl)->fileState.scrollFrameProc;
  2332.             if (proc)
  2333.                 (*proc)(frHndl, window, dh, dv);
  2334.         }
  2335.     }
  2336. }
  2337.  
  2338.  
  2339.  
  2340. /*****************************************************************************/
  2341.  
  2342.  
  2343.  
  2344. #pragma segment Window
  2345. void    DoUndoFixup(FileRecHndl frHndl, Point contOrg, Boolean afterUndo)
  2346. {
  2347.     UndoFixupProcPtr    proc;
  2348.  
  2349.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2350.  
  2351.     proc = (*frHndl)->fileState.undoFixupProc;
  2352.     if (proc)
  2353.         (*proc)(frHndl, contOrg, afterUndo);
  2354. }
  2355.  
  2356.  
  2357.  
  2358. /*****************************************************************************/
  2359. /*****************************************************************************/
  2360.  
  2361.  
  2362.  
  2363. /* Open a window where it was stored at.  This would be simple, except for the
  2364. ** complication that the user may be opening the document on a different Mac
  2365. ** that doesn't have the same monitor configuration.  Due to this, we need to
  2366. ** make sure that the window doesn't open completely out of view. */
  2367.  
  2368. #pragma segment Window
  2369. static Rect    OldLocWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  2370. {
  2371.     FileRecHndl    frHndl;
  2372.     RgnHandle    rgn;
  2373.     Rect        rct, bbox, srct, crct;
  2374.     short        dh, dv, h, v;
  2375.     long        attributes;
  2376.  
  2377.     frHndl     = (FileRecHndl)GetWRefCon(window);
  2378.     attributes = (*frHndl)->fileState.attributes;
  2379.  
  2380.     srct = (*frHndl)->d.doc.fhInfo.structureRect;
  2381.     crct = (*frHndl)->d.doc.fhInfo.contentRect;
  2382.     if (EmptyRect(&srct)) {
  2383.         if (!gOldLocProc) return(window->portRect);
  2384.         return((*gOldLocProc)(window, relatedWindow, sizeInfo));
  2385.     }
  2386.  
  2387.     rct = srct;
  2388.     rct.bottom = crct.top;
  2389.  
  2390.     RectRgn(rgn = NewRgn(), &rct);
  2391.     SectRgn(rgn, GetGrayRgn(), rgn);
  2392.     bbox = (*rgn)->rgnBBox;
  2393.     DisposeRgn(rgn);
  2394.  
  2395.     if (EqualRect(&rct, &bbox)) {
  2396.         rct = (*frHndl)->d.doc.fhInfo.contentRect;
  2397.         SizeWindow(window, rct.right - rct.left, rct.bottom - rct.top, false);
  2398.         MoveWindow(window, rct.left, rct.top, false);
  2399.         mDerefWStateData(window)->stdState  = (*frHndl)->d.doc.fhInfo.stdState;
  2400.         if (((WindowPeek)window)->spareFlag)
  2401.             mDerefWStateData(window)->userState = (*frHndl)->d.doc.fhInfo.userState;
  2402.         return(rct);
  2403.     }
  2404.  
  2405.     rct = srct;
  2406.     if (!(dh = bbox.left - rct.left))
  2407.         dh = bbox.right  - rct.right;
  2408.     if (!(dv = bbox.top  - rct.top))
  2409.         dv = bbox.bottom - rct.bottom;
  2410.     OffsetRect(&rct, dh, dv);
  2411.  
  2412.     RectRgn(rgn = NewRgn(), &rct);
  2413.     SectRgn(rgn, GetGrayRgn(), rgn);
  2414.     bbox = (*rgn)->rgnBBox;
  2415.     DisposeRgn(rgn);
  2416.  
  2417.     if (EqualRect(&rct, &bbox)) {
  2418.         h = crct.right  - crct.left;
  2419.         v = crct.bottom - crct.top;
  2420.         SetRect(&sizeInfo, h, v, h, v);
  2421.             /* Force window big as possible for this screen and data size. */
  2422.     }
  2423.  
  2424.     if (!gOldLocProc) return(window->portRect);
  2425.     return((*gOldLocProc)(window, relatedWindow, sizeInfo));
  2426. }
  2427.  
  2428.  
  2429.  
  2430. /*****************************************************************************/
  2431.  
  2432.  
  2433.  
  2434. #pragma segment Window
  2435. void    CleanSendBehind(WindowPtr window, WindowPtr afterWindow)
  2436. {
  2437.     WindowPtr    oldPort;
  2438.     Point        offset;
  2439.     RgnHandle    contRgn, keepContRgn, visRgn;
  2440.  
  2441.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2442.  
  2443.     if (afterWindow == (WindowPtr)-1) {
  2444.         BringToFront(window);
  2445.         HiliteWindows();
  2446.         return;
  2447.     }
  2448.  
  2449.     GetPort(&oldPort);
  2450.     SetPort(window);
  2451.     offset.h = offset.v = 0;
  2452.     LocalToGlobal(&offset);
  2453.     SetPort(oldPort);
  2454.  
  2455.     CopyRgn(contRgn = ((WindowPeek)window)->contRgn, keepContRgn = NewRgn());
  2456.     OffsetRgn(visRgn = window->visRgn, offset.h, offset.v);
  2457.     DiffRgn(contRgn, visRgn, contRgn);
  2458.     OffsetRgn(visRgn, -offset.h, -offset.v);
  2459.         /* Don't allow PaintOne to touch the part of the window already visible. */
  2460.  
  2461.     SendBehind(window, afterWindow);
  2462.         /* Do the SendBehind.  Since the content region is way off the
  2463.         ** screen(s), no erasing of the content of the window will occur. */
  2464.  
  2465.     CopyRgn(keepContRgn, contRgn);
  2466.     DisposeRgn(keepContRgn);
  2467.  
  2468.     CalcVis((WindowPeek)window);
  2469.         /* One negative to the content region games is that the visRgn gets
  2470.         ** calculated incorrectly when SendBehind() is called.  The call to
  2471.         ** CalcVis() fixes this problem. */
  2472.  
  2473.     HiliteWindows();
  2474. }
  2475.  
  2476.  
  2477.  
  2478. /*****************************************************************************/
  2479.  
  2480.  
  2481.  
  2482. #pragma segment Window
  2483. void    CleanSendInFront(WindowPtr window, WindowPtr beforeWindow)
  2484. {
  2485.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2486.  
  2487.     beforeWindow = GetPreviousWindow(beforeWindow);
  2488.     if (beforeWindow)
  2489.         CleanSendBehind(window, beforeWindow);
  2490. }
  2491.  
  2492.  
  2493.  
  2494. /*****************************************************************************/
  2495.  
  2496.  
  2497.  
  2498. #pragma segment Window
  2499. void    HiliteWindows(void)
  2500. {
  2501.     WindowPtr    window, ww;
  2502.     FileRecHndl    frHndl, ff;
  2503.     long        thisKind, lastKind;
  2504.     Boolean        haveModal;
  2505.     short        hilited;
  2506.  
  2507.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2508.  
  2509.     lastKind = -1;            /* No such kind. */
  2510.  
  2511.     haveModal = false;
  2512.     for (window = FrontWindow(); window; window = (WindowPtr)(((WindowPeek)window)->nextWindow)) {
  2513.  
  2514.         if (!((WindowPeek)window)->visible)          continue;
  2515.         if (((WindowPeek)window)->windowKind < 1000) continue;
  2516.  
  2517.         thisKind = kwIsDocument;
  2518.         if (IsAppWindow(window)) {
  2519.             frHndl   = (FileRecHndl)GetWRefCon(window);
  2520.             thisKind = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2521.         }
  2522.  
  2523.         if (gInBackground)
  2524.             lastKind = thisKind;
  2525.                 /* If application moved to background, we want to turn all hilighting off
  2526.                 ** for all windows.  This is accomplished by pretending that the kind of
  2527.                 ** the current window is the same as the kind of the last window. */
  2528.  
  2529.         if (haveModal)
  2530.             lastKind = thisKind;
  2531.                 /* If we have a modal dialog in front, then turn off the hilighting for
  2532.                 ** all the other windows. */
  2533.  
  2534.         if (thisKind != lastKind) {
  2535.             for (ww = window; (ww = (WindowPtr)(((WindowPeek)ww)->nextWindow)) != nil;) {
  2536.                 if (!((WindowPeek)ww)->visible) continue;
  2537.                 if ((IsAppWindow(ww)) || (IsDAWindow(window))) {
  2538.                     ff = (FileRecHndl)GetWRefCon(ww);
  2539.                     if (thisKind == ((*ff)->fileState.attributes & (kwIsPalette | kwIsModalDialog))) {
  2540.                         hilited = ((WindowPeek)ww)->hilited & 0x01;
  2541.                         if (thisKind == kwIsPalette) {
  2542.                             if (!hilited) {
  2543.                                 HiliteWindow(ww, true);
  2544.                                 DoActivate(ww);
  2545.                             }
  2546.                         }
  2547.                         else {
  2548.                             if (hilited) {
  2549.                                 HiliteWindow(ww, false);
  2550.                                 DoActivate(ww);
  2551.                             }
  2552.                         }
  2553.                     }
  2554.                     else break;
  2555.                 }
  2556.             }
  2557.             hilited = ((WindowPeek)window)->hilited & 0x01;
  2558.             if (!hilited) {
  2559.                 HiliteWindow(window, true);
  2560.                 DoActivate(window);
  2561.             }
  2562.             lastKind = thisKind;
  2563.         }
  2564.         else {
  2565.             hilited = ((WindowPeek)window)->hilited & 0x01;
  2566.             if (hilited) {
  2567.                 HiliteWindow(window, false);
  2568.                 DoActivate(window);
  2569.             }
  2570.         }
  2571.  
  2572.         if (thisKind == kwIsModalDialog)
  2573.             haveModal = true;
  2574.     }
  2575. }
  2576.  
  2577.  
  2578.  
  2579. /*****************************************************************************/
  2580.  
  2581.  
  2582.  
  2583. #pragma segment Window
  2584. void    UnhiliteWindows(void)
  2585. {
  2586.     WindowPtr    window;
  2587.     short        hilited;
  2588.  
  2589.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2590.  
  2591.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  2592.         if (!((WindowPeek)window)->visible) continue;
  2593.         if (IsAppWindow(window))
  2594.             if (((WindowPeek)window)->windowKind <= dialogKind)
  2595.                 continue;
  2596.         hilited = ((WindowPeek)window)->hilited & 0x01;
  2597.         if (hilited) {
  2598.             HiliteWindow(window, false);
  2599.             DoActivate(window);
  2600.         }
  2601.     }
  2602. }
  2603.  
  2604.  
  2605.  
  2606. /*****************************************************************************/
  2607.  
  2608.  
  2609.  
  2610. /* This is called when an update event is received for a window.  First, the
  2611. ** updateRgn is separated into two parts.  Part 1 holds the window frame area,
  2612. ** if any.  This is the area that might hold the scrollbars, grow icon, and
  2613. ** any other application-specific frame parts.  This is drawn first.  Once
  2614. ** this is done, the remainder of the updateRgn is drawn.  This allows us to
  2615. ** handle all of the frame clipping without using the clipRgn.  By freeing up
  2616. ** the clipRgn, we allow the application to use it without having to share. */
  2617.  
  2618. #pragma segment Window
  2619. void    DoUpdate(WindowPtr window)
  2620. {
  2621.     RgnHandle    contPart, framePart;
  2622.     Point        contOrg;
  2623.     FileRecHndl    frHndl;
  2624.  
  2625.     SetPort(window);
  2626.  
  2627.     if (IsAppWindow(window)) {
  2628.  
  2629.         DoUpdateSeparate(window, &contPart, &framePart);
  2630.  
  2631.         if (framePart) {        /* Update the document frame, if any. */
  2632.             CopyRgn(framePart, ((WindowPeek)window)->updateRgn);
  2633.             DisposeRgn(framePart);
  2634.             ++gBeginUpdateNested;
  2635.             BeginUpdate(window);
  2636.             DoDrawFrame(window, false);
  2637.             if (gBeginUpdateNested) {
  2638.                 EndUpdate(window);
  2639.                 --gBeginUpdateNested;
  2640.             }
  2641.         }
  2642.         if (contPart) {            /* Update the rest of the content. */
  2643.             CopyRgn(contPart, ((WindowPeek)window)->updateRgn);
  2644.             DisposeRgn(contPart);
  2645.             ++gBeginUpdateNested;
  2646.             BeginUpdate(window);
  2647.             GetContentOrigin(window, &contOrg);
  2648.             SetOrigin(contOrg.h, contOrg.v);
  2649.             frHndl = (FileRecHndl)GetWRefCon(window);
  2650.             DoImageDocument(frHndl);
  2651.             SetOrigin(0, 0);
  2652.             if (gBeginUpdateNested) {
  2653.                 EndUpdate(window);
  2654.                 --gBeginUpdateNested;
  2655.             }
  2656.         }
  2657.     }
  2658. }
  2659.  
  2660.  
  2661.  
  2662. /*****************************************************************************/
  2663.  
  2664.  
  2665.  
  2666. #pragma segment Window
  2667. void    DoSetCursor(Cursor *cursor)
  2668. {
  2669.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2670.  
  2671.     if (cursor)
  2672.         SetCursor(cursor);
  2673.  
  2674.     if (!cursor)
  2675.         DoCursor();
  2676. }
  2677.  
  2678.  
  2679.  
  2680. /*****************************************************************************/
  2681.  
  2682.  
  2683.  
  2684. #pragma segment Window
  2685. CursPtr    DoSetResCursor(short crsrID)
  2686. {
  2687.     CursHandle    crsr;
  2688.  
  2689.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2690.  
  2691.     crsr = GetCursor(crsrID);
  2692.     if (crsr) {
  2693.         gCursor = **crsr;
  2694.         DoSetCursor(&gCursor);
  2695.         return(&gCursor);
  2696.     }
  2697.  
  2698.     SetCursor(&qd.arrow);
  2699.     return(&qd.arrow);
  2700. }
  2701.  
  2702.  
  2703.  
  2704. /*****************************************************************************/
  2705.  
  2706.  
  2707.  
  2708. #pragma segment Window
  2709. void    DoWindowCursor(void)
  2710. {
  2711.     WindowPeek            wpeek;
  2712.     WindowPtr            window;
  2713.     Point                mouseLoc;
  2714.     FileRecHndl            frHndl;
  2715.     RgnHandle            srgn;
  2716.     WindowCursorProcPtr    proc;
  2717.  
  2718.     if (gInBackground) return;
  2719.         /* Don't change cursors if we aren't the front application. */
  2720.  
  2721.     if (!gCursorRgn)
  2722.         gCursorRgn = NewRgn();
  2723.  
  2724.     mouseLoc = GetGlobalMouse();
  2725.  
  2726.     if (!(wpeek = (WindowPeek)FrontWindow())) {
  2727.         SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2728.         WindowCursor(nil, nil, mouseLoc);
  2729.         return;
  2730.     }
  2731.  
  2732.     if (!IsAppWindow((WindowPtr)wpeek)) {
  2733.         SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2734.         SetCursor(gCursorPtr = &qd.arrow);
  2735.     }        /* Non-application windows get an arrow cursor. */
  2736.  
  2737.     if (gCursorPtr) {                            /* Do we already have a cursor... */
  2738.         if (PtInRgn(mouseLoc, gCursorRgn)) {    /* Are we still in the cursor area... */
  2739.             SetCursor(gCursorPtr);                /* Then set it to that. */
  2740.             return;
  2741.         }
  2742.     }
  2743.  
  2744.     SetRectRgn(gCursorRgn, -30000, -30000, 30000, 30000);
  2745.  
  2746.     for (wpeek = (WindowPeek)FrontWindow();; wpeek = wpeek->nextWindow) {
  2747.  
  2748.         if (!IsAppWindow((WindowPtr)wpeek)) break;
  2749.  
  2750.         if (!wpeek->visible) continue;        /* No cursors for invisible windows. */
  2751.  
  2752.         window = (WindowPtr)wpeek;
  2753.         srgn   = wpeek->strucRgn;
  2754.         frHndl = (FileRecHndl)GetWRefCon(window);
  2755.  
  2756.         proc = (frHndl) ? (*frHndl)->fileState.windowCursorProc : nil;
  2757.         if (!proc) {
  2758.             if (PtInRgn(mouseLoc, srgn)) {
  2759.                 SectRgn(gCursorRgn, srgn, gCursorRgn);
  2760.                 SetCursor(gCursorPtr = &qd.arrow);
  2761.                 return;
  2762.             }
  2763.         }
  2764.         else if ((*proc)(frHndl, window, mouseLoc)) return;
  2765.  
  2766.         DiffRgn(gCursorRgn, srgn, gCursorRgn);
  2767.     }
  2768.  
  2769.     SetCursor(gCursorPtr = &qd.arrow);
  2770. }
  2771.  
  2772.  
  2773.  
  2774. /*****************************************************************************/
  2775.  
  2776.  
  2777.  
  2778. #pragma segment Window
  2779. WindowPtr    FrontWindowOfType(long wkind, Boolean firstVis)
  2780. {
  2781.     WindowPtr    window;
  2782.     FileRecHndl    frHndl;
  2783.     long        wk;
  2784.  
  2785.     wkind &= (kwIsPalette | kwIsModalDialog);
  2786.     for (window = nil; (window = GetNextWindow(window, 0)) != nil;) {
  2787.         if (firstVis)
  2788.             if (!(((WindowPeek)window)->visible))
  2789.                 continue;
  2790.         if (IsDAWindow(window))
  2791.             if (wkind == kwIsDocument)
  2792.                 return(window);
  2793.         if (((WindowPeek)window)->windowKind >= 1000) {
  2794.             frHndl = (FileRecHndl)GetWRefCon(window);
  2795.             if (frHndl) {
  2796.                 wk = (*frHndl)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  2797.                 if (wk < wkind)  break;
  2798.                 if (wk == wkind) return(window);
  2799.             }
  2800.         }
  2801.     }
  2802.  
  2803.     return(nil);
  2804. }
  2805.  
  2806.  
  2807.  
  2808. /*****************************************************************************/
  2809.  
  2810.  
  2811.  
  2812. /* This function gets an alert, and handles hiliting of windows correctly.
  2813. ** The reason for this function is that there may be more than one hilited
  2814. ** window due to the possibility of floating palettes.  The calls to UnhiliteWindows
  2815. ** and HiliteWindows make sure that while the alert is up, there are no other
  2816. ** hilited windows. */
  2817.  
  2818. #pragma segment Window
  2819. short    HCenteredAlert(short alertID, WindowPtr relatedWindow, ModalFilterUPP filter)
  2820. {
  2821.     short    itemHit;
  2822.  
  2823.     gCursorPtr = nil;        /* Force recalc of cursor. */
  2824.  
  2825.     UnhiliteWindows();
  2826.     itemHit = CenteredAlert(alertID, relatedWindow, filter);
  2827.     HiliteWindows();
  2828.     return(itemHit);
  2829. }
  2830.  
  2831.  
  2832.  
  2833. /*****************************************************************************/
  2834. /*****************************************************************************/
  2835.  
  2836.  
  2837.  
  2838. /* This function gets the application window formats that were created with
  2839. ** the AppsToGo application editor.  The window formats are stored in the resource
  2840. ** 'WFMT' id #128.  They are first read in, and then they are unflattened
  2841. ** by calling HReadWindowFormats(). */
  2842.  
  2843. #pragma segment Window
  2844. OSErr    GetWindowFormats(void)
  2845. {
  2846.     Handle    wfmt;
  2847.     OSErr    err;
  2848.  
  2849.     if (!(wfmt = GetAppResource('WFMT', 128, nil))) return(ResError());
  2850.     DetachResource(wfmt);
  2851.  
  2852.     err = HReadWindowFormats(wfmt);
  2853.     DisposeHandle(wfmt);
  2854.  
  2855.     return(err);
  2856. }
  2857.  
  2858.  
  2859.  
  2860. /*****************************************************************************/
  2861.  
  2862.  
  2863.  
  2864. /* This function is called to unflatten a window-format handle into separate
  2865. ** hierarchical document objects.  The assumption is that there is only one
  2866. ** of these multiple window definitions, and therefore if there is already
  2867. ** one in the global gWindowFormats, it is disposed of.  This is exactly the
  2868. ** behavior needed by the AppsToGo application editor. */
  2869.  
  2870. #pragma segment Window
  2871. OSErr    HReadWindowFormats(Handle wfmt)
  2872. {
  2873.     TreeObjHndl        wobj;
  2874.     long            attr;
  2875.     short            i, j;
  2876.     OSErr            err;
  2877.     static OSType    *lastTypeListPtr;
  2878.  
  2879.     err = noErr;
  2880.     NewDocument(nil, 0, 0);        /* This resets the doc.increment value. */
  2881.  
  2882.     if (wfmt) {
  2883.         if (gWindowFormats)
  2884.             DisposeObjAndOffspring(gWindowFormats);
  2885.         if (!(gWindowFormats = NewRootObj(WFMTOBJ, 0))) return(memFullErr);
  2886.         err = HReadTree(gWindowFormats, wfmt);
  2887.     }
  2888.  
  2889.     if (!err) {
  2890.         gTypeListLen       = 0;
  2891.         gAppWindowAttr     = 0;
  2892.         gAppWindowType     = 0;
  2893.         gNoDefaultDocument = true;
  2894.         for (i = 0; i < (*gWindowFormats)->numChildren; ++i) {
  2895.             wobj = GetChildHndl(gWindowFormats, i);
  2896.             attr = mDerefWFMT(wobj)->attributes;
  2897.             if (!(attr & kwRuntimeOnlyDoc))
  2898.                 ++gTypeListLen;
  2899.             if (attr & kwDefaultDocType) {
  2900.                 gAppWindowAttr     = attr;
  2901.                 gAppWindowType     = mDerefWFMT(wobj)->sfType;
  2902.                 gNoDefaultDocument = false;
  2903.             }
  2904.         }
  2905.         if (gTypeListLen) {
  2906.             if (lastTypeListPtr)
  2907.                 DisposePtr((Ptr)lastTypeListPtr);
  2908.             gTypeListPtr = lastTypeListPtr = (OSType *)NewPtr(gTypeListLen * sizeof(OSType));
  2909.             if (!gTypeListPtr)
  2910.                 return(memFullErr);
  2911.             for (i = j = 0; i < (*gWindowFormats)->numChildren; ++i) {
  2912.                 wobj = GetChildHndl(gWindowFormats, i);
  2913.                 attr = mDerefWFMT(wobj)->attributes;
  2914.                 if (!(attr & kwRuntimeOnlyDoc))
  2915.                     gTypeListPtr[j++] = mDerefWFMT(wobj)->sfType;
  2916.             }
  2917.         }
  2918.     }
  2919.  
  2920.     return(err);
  2921. }
  2922.  
  2923.  
  2924.  
  2925. /*****************************************************************************/
  2926.  
  2927.  
  2928.  
  2929. /* This function is called to add a named 'WFMT' resource that isn't included in
  2930. ** the 'WFMT' id #128 standard resource.  The purpose for not including all of
  2931. ** the 'WFMT' resources into the id #128 is for speed reasons.  For really complex
  2932. ** applications, the number of items in the various windows and dialogs can cause
  2933. ** a huge number of handled to be created, thus slowing down the application.
  2934. ** By separating out one or more window definitions and saving them off, the size
  2935. ** of the main 'WFMT' resource can be reduced.  Named 'WFMT' resources should be
  2936. ** named with the document type used to reference them.  They are read in, used,
  2937. ** and then disposed of automatically. */
  2938.  
  2939. #pragma segment Window
  2940. OSErr    GetSeparateWFMT(OSType sftype, short *numAdded)
  2941. {
  2942.     short            i, nadd, *naddptr;
  2943.     TreeObjHndl        wfmt;
  2944.     OSErr            err;
  2945.     Handle            hndl;
  2946.     Str15            str;
  2947.  
  2948.     nadd    = 0;
  2949.     naddptr = (numAdded) ? numAdded : &nadd;
  2950.  
  2951.     if (!sftype) {
  2952.         while (*naddptr)
  2953.             DisposeChild(NO_EDIT, gWindowFormats, --*naddptr);
  2954.         return(noErr);
  2955.     }
  2956.  
  2957.     *naddptr = 0;
  2958.     for (i = (*gWindowFormats)->numChildren; i;) {
  2959.         wfmt = GetChildHndl(gWindowFormats, --i);
  2960.         if (mDerefWFMT(wfmt)->sfType == sftype) return(noErr);
  2961.     }
  2962.  
  2963.     str[0] = 4;
  2964.     BlockMove(&sftype, str + 1, sizeof(OSType));
  2965.     hndl = GetNamedResource('WFMT', str);
  2966.     err = ResError();
  2967.     if (!err)
  2968.         if (!hndl)
  2969.             err = resNotFound;
  2970.     if (err) return(err);
  2971.  
  2972.     if (hndl) {
  2973.         DetachResource(hndl);
  2974.         wfmt = NewChild(NO_EDIT, gWindowFormats, *naddptr, WFMTOBJ, 0);
  2975.         if (!wfmt) {
  2976.             DisposeHandle(hndl);
  2977.             DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  2978.             return(memFullErr);
  2979.         }
  2980.  
  2981.         err = HReadTree(wfmt, hndl);        /* Unflatten the WFMT resource into the place-holder */
  2982.         DisposeHandle(hndl);
  2983.  
  2984.         if (err) {
  2985.             DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  2986.             return(err);
  2987.         }
  2988.  
  2989.         for (; (*wfmt)->numChildren;)
  2990.             MoveChild(NO_EDIT, wfmt, 0, gWindowFormats, (*naddptr)++);
  2991.  
  2992.         DisposeChild(NO_EDIT, gWindowFormats, *naddptr);
  2993.     }
  2994.  
  2995.     return(noErr);
  2996. }
  2997.  
  2998.  
  2999.  
  3000. /*****************************************************************************/
  3001. /*****************************************************************************/
  3002.  
  3003.  
  3004.  
  3005. /* This function adds a set of controls (and sets referenced by that set) to the
  3006. ** window.  The control sets are created with the AppsToGo application editor. */
  3007.  
  3008. #pragma segment Window
  3009. OSErr    AddControlSet(WindowPtr window, OSType sftype, short visMode,
  3010.                       short xoffset, short yoffset, CObjCtlHndl retcoc)
  3011. {
  3012.     WindowPtr            oldPort;
  3013.     ControlHandle        ctl, dataCtl;
  3014.     CObjCtlHndl            coc;
  3015.     short                cocnum, i, j, len, ii, jj, vm, xo, yo, numAdded;
  3016.     OSType                sft;
  3017.     long                ofst, oldSize, newSize;
  3018.     TreeObjHndl            wfmt, cobj;
  3019.     char                str[256];
  3020.     OSErr                err;
  3021.     Rect                rct;
  3022.  
  3023.     if (!gWindowFormats) return(noErr);
  3024.  
  3025.     SetRect(&rct, 0, 0, 0, 0);
  3026.     dataCtl = NewControl(window, &rct, "\p", false, 0,0,0, gDataCtl + 7, sftype);
  3027.     if (!dataCtl) return(memFullErr);
  3028.  
  3029.     if (!(coc = (CObjCtlHndl)NewHandle(0x100))) return(memFullErr);
  3030.  
  3031.     err = GetSeparateWFMT(sftype, &numAdded);
  3032.     if (err) return(err);
  3033.  
  3034.     GetPort(&oldPort);
  3035.     SetPort(window);
  3036.  
  3037.     (*dataCtl)->contrlData = (Handle)coc;
  3038.     cocnum = 0;
  3039.  
  3040.     for (i = (*gWindowFormats)->numChildren; i;) {
  3041.         wfmt = GetChildHndl(gWindowFormats, --i);
  3042.         if (mDerefWFMT(wfmt)->sfType == sftype) {
  3043.             for (j = 0; j < (*wfmt)->numChildren; ++j) {
  3044.                 cobj = GetChildHndl(wfmt, j);
  3045.                 ctl  = MakeControl(window, cobj, visMode, xoffset, yoffset);
  3046.                 if (ctl) {
  3047.                     SetHandleSize((Handle)coc, (((++cocnum * sizeof(CObjCtl)) | 0xFF) + 1));
  3048.                     (**coc)[--cocnum].ctlObj  = cobj;    /* The handle was already big enough. */
  3049.                     (**coc)[cocnum  ].ctl     = ctl;
  3050.                     (**coc)[cocnum  ].visible = mDerefCtl(cobj)->visible;
  3051.                     (**coc)[cocnum++].procID  = mDerefCtl(cobj)->procID;
  3052.                     err = MemError();
  3053.                 }
  3054.                 if (!ctl) err = memFullErr;
  3055.                 if (err) {
  3056.                     SetHandleSize((Handle)coc, cocnum * sizeof(CObjCtl));
  3057.                     SetPort(oldPort);
  3058.                     GetSeparateWFMT(0, &numAdded);
  3059.                     return(err);
  3060.                 }
  3061.             }
  3062.  
  3063.             ofst = GetDataOffset(wfmt, offsetof(WFMTObj,title), kPStr, 1);
  3064.             GetPData(wfmt, ofst, (StringPtr)str);
  3065.             len = str[0];
  3066.             p2c((StringPtr)str);
  3067.             for (ii = 0; ii < len;) {
  3068.                 BlockMove(str + ii + 1, &sft, sizeof(OSType));
  3069.                 ii += sizeof(OSType) + 3;
  3070.                 vm = c2dec(str + ii, &jj);
  3071.                 ii += ++jj;
  3072.                 xo = c2dec(str + ii, &jj);
  3073.                 ii += ++jj;
  3074.                 yo = c2dec(str + ii, &jj);
  3075.                 ii += ++jj;
  3076.                 mDerefWFMT(wfmt)->sfType = 0;
  3077.                     /* Prevent self-references, which cause infinite recursion (boom). */
  3078.                 err = AddControlSet(window, sft, vm, xoffset + xo, yoffset + yo, retcoc);
  3079.                 mDerefWFMT(wfmt)->sfType = sftype;
  3080.                 if (err) {
  3081.                     SetHandleSize((Handle)coc, cocnum * sizeof(CObjCtl));
  3082.                     SetPort(oldPort);
  3083.                     GetSeparateWFMT(0, &numAdded);
  3084.                     return(err);
  3085.                 }
  3086.             }
  3087.         }
  3088.     }
  3089.  
  3090.     newSize = cocnum * sizeof(CObjCtl);
  3091.     SetHandleSize((Handle)coc, newSize);
  3092.  
  3093.     SetPort(oldPort);
  3094.  
  3095.     GetSeparateWFMT(0, &numAdded);
  3096.  
  3097.     if (retcoc) {
  3098.         oldSize = GetHandleSize((Handle)retcoc);
  3099.         SetHandleSize((Handle)retcoc, oldSize + newSize);
  3100.         err = MemError();
  3101.         if (err) return(err);
  3102.         BlockMove(*coc, (*(Handle)retcoc) + oldSize, newSize);
  3103.     }
  3104.  
  3105.     return(noErr);
  3106. }
  3107.  
  3108.  
  3109.  
  3110. /*****************************************************************************/
  3111.  
  3112.  
  3113.  
  3114. #pragma segment Window
  3115.  
  3116. static pascal void    DefaultScrollAction(ControlHandle ctl, short part);
  3117. static pascal void    DefaultScrollAction(ControlHandle ctl, short part)
  3118. {
  3119.     short                delta, value;
  3120.     short                oldValue, min, max;
  3121.     ControlStyleInfo    cinfo;
  3122.     Boolean                vert;
  3123.     short                hArrowVal = 1;
  3124.     short                vArrowVal = 1;
  3125.     short                hPageVal = 10;
  3126.     short                vPageVal = 10;
  3127.  
  3128.     cinfo.scrollProc = nil;
  3129.     if (GetControlStyle(ctl, &cinfo)) {
  3130.         if (cinfo.hArrowVal) hArrowVal = cinfo.hArrowVal;
  3131.         if (cinfo.vArrowVal) vArrowVal = cinfo.vArrowVal;
  3132.         if (cinfo.hPageVal)  hPageVal  = cinfo.hPageVal;
  3133.         if (cinfo.vPageVal)  vPageVal  = cinfo.vPageVal;
  3134.     }
  3135.  
  3136.     vert = (((*ctl)->contrlRect.right - (*ctl)->contrlRect.left) == 16);
  3137.  
  3138.     if (part) {                        /* If it was actually in the control. */
  3139.  
  3140.         switch (part) {
  3141.             case inUpButton:
  3142.             case inDownButton:        /* One line. */
  3143.                 delta = (vert) ? vArrowVal : hArrowVal;
  3144.                 break;
  3145.             case inPageUp:            /* One page. */
  3146.             case inPageDown:
  3147.                 delta = (vert) ? vPageVal : hPageVal;
  3148.                 break;
  3149.         }
  3150.  
  3151.         if ( (part == inUpButton) || (part == inPageUp) )
  3152.             delta = -delta;        /* Reverse direction for an upper. */
  3153.  
  3154.         value = (oldValue = GetControlValue(ctl)) + delta;
  3155.         if (value < (min = GetControlMinimum(ctl))) value = min;
  3156.         if (value > (max = GetControlMaximum(ctl))) value = max;
  3157.  
  3158.         if (value != oldValue)
  3159.             SetControlValue(ctl, value);
  3160.  
  3161.         if (cinfo.scrollProc) (*cinfo.scrollProc)(ctl, part, oldValue, value);
  3162.     }
  3163. }
  3164.  
  3165. static Boolean    DefaultScroll(ControlHandle ctl, short part, EventRecord *event);
  3166. static Boolean    DefaultScroll(ControlHandle ctl, short part, EventRecord *event)
  3167. {
  3168.     short                oldValue, newValue;
  3169.     ControlStyleInfo    cinfo;
  3170.  
  3171.     static ControlActionUPP    cupp;
  3172.  
  3173.     oldValue = newValue = GetControlValue(ctl);
  3174.     switch (part) {
  3175.         case inThumb:
  3176.             if (TrackControl(ctl, event->where, nil)) {
  3177.                 newValue = GetControlValue(ctl);
  3178.                 if (oldValue != newValue) {
  3179.                     if (GetControlStyle(ctl, &cinfo))
  3180.                         if (cinfo.scrollProc)
  3181.                             (*cinfo.scrollProc)(ctl, part, oldValue, newValue);
  3182.                 }
  3183.             }
  3184.             break;
  3185.         default:
  3186.             if (!cupp) cupp = NewControlActionProc(DefaultScrollAction);
  3187.             TrackControl(ctl, event->where, cupp);
  3188.             newValue = GetControlValue(ctl);
  3189.             break;
  3190.     }
  3191.  
  3192.     return((oldValue != newValue) ? true : false);
  3193. }
  3194.  
  3195. static void    AddRect(Rect *r1, Rect *r2, Rect *r3);
  3196. static void    AddRect(Rect *r1, Rect *r2, Rect *r3)
  3197. {
  3198.     Rect    r;
  3199.  
  3200.     r = *r1;    
  3201.     r.top    += r2->top;
  3202.     r.left   += r2->left;
  3203.     r.bottom += r2->bottom;
  3204.     r.right  += r2->right;
  3205.     if ((r.left >= r.right) || (r.top >= r.bottom)) SetRect(&r, 0, 0, 0, 0);
  3206.     *r3 = r;
  3207. }
  3208.  
  3209. /* This function is used to create a control based on the control definition object.
  3210. ** The control definition objects are created with the AppsToGo application editor. */
  3211.  
  3212. #pragma segment Window
  3213. ControlHandle    MakeControl(WindowPtr window, TreeObjHndl cobj, short visMode, short xoffset, short yoffset)
  3214. {
  3215.     WindowPtr            oldPort;
  3216.     ControlHandle        ctl;
  3217.     short                cctbID, tlen, slen, vis, maxTextLen;
  3218.     short                variant, rr, cc, ll, procID, mode;
  3219.     long                ofst;
  3220.     ControlStyleInfo    cinfo;
  3221.     CCTabHandle            cctbHndl;
  3222.     TEHandle            te;
  3223.     ListHandle            list;
  3224.     Handle                txt;
  3225.     StScrpHandle        styl;
  3226.     Ptr                    ptr;
  3227.     Point                cell;
  3228.     Rect                destRct, viewRct, brdrRct;
  3229.     char                hstate;
  3230.     CtlTemplate            **crsrc;
  3231.     short                txFont, txSize, fnum;
  3232.     Style                txFace;
  3233.  
  3234.     GetPort(&oldPort);
  3235.     SetPort(window);
  3236.  
  3237.     HLock((Handle)cobj);
  3238.     OffsetRect(&mDerefCtl(cobj)->rect, xoffset, yoffset);
  3239.  
  3240.     variant = (mDerefCtl(cobj)->procID & 0x0F);
  3241.     ctl = nil;
  3242.     vis  = mDerefCtl(cobj)->visible;
  3243.     vis |= visMode;
  3244.     vis ^= (visMode > 1);
  3245.     vis &= 0x01;
  3246.  
  3247.     cinfo.ctlID       = mDerefCtl(cobj)->ctlID;
  3248.     cinfo.trackProc   = nil;
  3249.     cinfo.scrollProc  = nil;
  3250.     cinfo.hArrowVal   = 0;
  3251.     cinfo.vArrowVal   = 0;
  3252.     cinfo.hPageVal    = 0;
  3253.     cinfo.vPageVal    = 0;
  3254.     cinfo.drawControl = nil;
  3255.     cinfo.fontSize    = mDerefCtl(cobj)->fontSize;
  3256.     cinfo.fontStyle   = mDerefCtl(cobj)->fontStyle;
  3257.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 1);
  3258.     GetPData(cobj, ofst, cinfo.keyEquivs);
  3259.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 2);
  3260.     GetPData(cobj, ofst, cinfo.font);
  3261.     ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 3);
  3262.     GetPData(cobj, ofst, cinfo.balloonHelp);
  3263.     txFont = window->txFont;
  3264.     txSize = window->txSize;
  3265.     txFace = window->txFace;
  3266.     procID = mDerefCtl(cobj)->procID;
  3267.     if (procID & 0x08) {
  3268.         TextFace(cinfo.fontStyle);
  3269.         fnum = 0;
  3270.         if (cinfo.font[0])
  3271.             GetFNum(cinfo.font, &fnum);
  3272.         TextFont(fnum);
  3273.         TextSize(cinfo.fontSize);
  3274.     }
  3275.  
  3276.     switch (procID & 0xFFF0) {
  3277.         case rTECtl:
  3278.             destRct = mDerefCtl(cobj)->extCtl.ctenew.destRct;
  3279.             viewRct = mDerefCtl(cobj)->extCtl.ctenew.viewRct;
  3280.             brdrRct = mDerefCtl(cobj)->extCtl.ctenew.brdrRct;
  3281.             maxTextLen = mDerefCtl(cobj)->extCtl.ctenew.maxTextLen;
  3282.             if (maxTextLen < 1) {
  3283.                 maxTextLen = -maxTextLen;
  3284.                 AddRect(&mDerefCtl(cobj)->rect, &destRct, &destRct);
  3285.                 AddRect(&mDerefCtl(cobj)->rect, &viewRct, &viewRct);
  3286.                 AddRect(&mDerefCtl(cobj)->rect, &brdrRct, &brdrRct);
  3287.             }
  3288.             else {
  3289.                 OffsetRect(&destRct, xoffset, yoffset);
  3290.                 OffsetRect(&viewRct, xoffset, yoffset);
  3291.                 OffsetRect(&brdrRct, xoffset, yoffset);
  3292.             }
  3293.             CTENew(gTECtl + variant,
  3294.                    false, window, &te,
  3295.                   &mDerefCtl(cobj)->rect,
  3296.                   &destRct, &viewRct, &brdrRct,
  3297.                    maxTextLen, mDerefCtl(cobj)->extCtl.ctenew.mode
  3298.             );
  3299.             if (te) {
  3300.                 UseControlStyle(ctl = CTEViewFromTE(te));
  3301.                 ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 4);
  3302.                 BlockMove((char *)GetDataPtr(cobj) + ofst, &tlen, sizeof(short));
  3303.                 txt = NewHandle(tlen);
  3304.                 if (txt) {
  3305.                     ptr = GetDataPtr(cobj);
  3306.                     BlockMove(ptr + ofst + sizeof(short), *txt, tlen);
  3307.                     slen = 0;
  3308.                     styl = nil;
  3309.                     if (mDerefCtl(cobj)->extCtl.ctenew.mode & cteStyledTE) {
  3310.                         ofst = GetDataOffset(cobj, ofst, kSDataBlock, 1);
  3311.                         BlockMove((char *)GetDataPtr(cobj) + ofst, &slen, sizeof(short));
  3312.                         if (slen)
  3313.                             styl = (StScrpHandle)NewHandle(slen);
  3314.                         if (styl) {
  3315.                             ptr = GetDataPtr(cobj);
  3316.                             BlockMove(ptr + ofst + sizeof(short), (Ptr)*styl, slen);
  3317.                         }
  3318.                     }
  3319.                     DisposeHandle(CTESwapText(te, txt, styl, false));
  3320.                     if (styl)
  3321.                         DisposeHandle((Handle)styl);
  3322.                     if (!(*ctl)->contrlHilite)
  3323.                          if (mDerefCtl(cobj)->extCtl.ctenew.mode & cteActive)
  3324.                             if (!CTEReadOnly(te))
  3325.                                 CTESetSelect(mDerefCtl(cobj)->min, mDerefCtl(cobj)->max, te);
  3326.                 }
  3327.                 UseControlStyle(nil);
  3328.             }
  3329.             break;
  3330.         case rListCtl:
  3331.             mode = mDerefCtl(cobj)->extCtl.clnew.mode;
  3332.             if (!gclvVariableSizeCells)
  3333.                 mode &= (0xFFFF - clVariable);
  3334.             list = CLNew(gListCtl + variant,
  3335.                          false,
  3336.                         &mDerefCtl(cobj)->rect,
  3337.                          mDerefCtl(cobj)->extCtl.clnew.numRows,
  3338.                          mDerefCtl(cobj)->extCtl.clnew.numCols,
  3339.                          mDerefCtl(cobj)->extCtl.clnew.cellHeight,
  3340.                          mDerefCtl(cobj)->extCtl.clnew.cellWidth,
  3341.                          mDerefCtl(cobj)->refCon,
  3342.                          window,
  3343.                          (mode & (0xFFFF - clVariable))
  3344.             );
  3345.             if (list) {
  3346.                 (*list)->listFlags |= 0x08;
  3347.                 ctl  = CLViewFromList(list);
  3348.                 ofst = GetDataOffset(cobj, offsetof(CtlObj,title), kPStr, 4);
  3349.                 BlockMove((char *)GetDataPtr(cobj) + ofst, &tlen, sizeof(short));
  3350.                 txt = NewHandle(tlen);
  3351.                 if (txt) {
  3352.                     ptr = GetDataPtr(cobj);
  3353.                     BlockMove(ptr + ofst + sizeof(short), *txt, tlen);
  3354.                     ofst = 0;
  3355.                     HLock(txt);
  3356.                     for (rr = 0; rr < mDerefCtl(cobj)->extCtl.clnew.numRows; ++rr) {
  3357.                         if (ofst >= tlen) break;
  3358.                         for (cc = 0; cc < mDerefCtl(cobj)->extCtl.clnew.numCols; ++cc) {
  3359.                             if (ofst >= tlen) break;
  3360.                             cell.h = cc;
  3361.                             cell.v = rr;
  3362.                             ll = ((unsigned char *)*txt)[ofst];
  3363.                             LSetCell(*txt + ofst + 1, ll, cell, list);
  3364.                             ofst += ++ll;
  3365.                         }
  3366.                     }
  3367.                     DisposeHandle(txt);
  3368.                 }
  3369.                 if (mode & clVariable)
  3370.                     (*gclvVariableSizeCells)(list);
  3371.                 else
  3372.                     if ((mDerefCtl(cobj)->extCtl.clnew.mode) & clDrawIt)
  3373.                         (*list)->listFlags &= (0xFFFF - 0x08);
  3374.             }
  3375.             break;
  3376.         case rCIconCtl:
  3377.             ctl = CCIconNew(window,
  3378.                            &mDerefCtl(cobj)->rect,
  3379.                  (StringPtr)mDerefCtl(cobj)->title,
  3380.                             false,
  3381.                             mDerefCtl(cobj)->value,
  3382.                             mDerefCtl(cobj)->min,
  3383.                             mDerefCtl(cobj)->max,
  3384.                             gCIconCtl + variant,
  3385.                             mDerefCtl(cobj)->refCon
  3386.             );
  3387.             break;
  3388.         case rPICTCtl:
  3389.             ctl = CPICTNew(window,
  3390.                           &mDerefCtl(cobj)->rect,
  3391.                 (StringPtr)mDerefCtl(cobj)->title,
  3392.                            false,
  3393.                            mDerefCtl(cobj)->value,
  3394.                            mDerefCtl(cobj)->min,
  3395.                            mDerefCtl(cobj)->max,
  3396.                            gPICTCtl + variant,
  3397.                            mDerefCtl(cobj)->refCon
  3398.             );
  3399.             break;
  3400.         default:
  3401.             procID = mDerefCtl(cobj)->procID;
  3402.             if (procID == -1) {
  3403.                 crsrc = (CtlTemplate **)GetResource('CNTL', mDerefCtl(cobj)->refCon);
  3404.                 if (crsrc) {
  3405.                     hstate = HGetState((Handle)crsrc);
  3406.                     HLock((Handle)crsrc);
  3407.                     ctl = NewControl(window,
  3408.                               &mDerefCtl(cobj)->rect,
  3409.                     (StringPtr)(*crsrc)->contrlTitle,
  3410.                                false,
  3411.                                (*crsrc)->contrlValue,
  3412.                                (*crsrc)->contrlMin,
  3413.                                (*crsrc)->contrlMax,
  3414.                                (*crsrc)->procID,
  3415.                                (*crsrc)->contrlRfCon
  3416.                     );
  3417.                     HSetState((Handle)crsrc, hstate);
  3418.                     if (((*crsrc)->procID & 0xFFF0) == popupMenuProc)
  3419.                         gPopupProc = (*ctl)->contrlDefProc;
  3420.                 }
  3421.                 if (ctl) break;
  3422.                 procID = 0;
  3423.             }
  3424.             if ((procID > rPICTCtl) && (procID < rDataCtl + 16))
  3425.                     procID += (gDataCtl - rDataCtl);
  3426.                         /* For AppsToGo to be able to use the target's CDEF's,
  3427.                         ** we have to have unique numbers for the extended controls.
  3428.                         ** AppsToGo has added a constant to all of the extended
  3429.                         ** controls for this reason.  We have to do the same for
  3430.                         ** these extra extended controls so that the contrlDefProc
  3431.                         ** is constant for compare purposes. */
  3432.             ctl = NewControl(window,
  3433.                       &mDerefCtl(cobj)->rect,
  3434.             (StringPtr)mDerefCtl(cobj)->title,
  3435.                        false,
  3436.                        mDerefCtl(cobj)->value,
  3437.                        mDerefCtl(cobj)->min,
  3438.                        mDerefCtl(cobj)->max,
  3439.                        procID,
  3440.                        mDerefCtl(cobj)->refCon
  3441.             );
  3442.             if (procID == scrollBarProc) cinfo.trackProc = DefaultScroll;
  3443.             break;
  3444.     }
  3445.  
  3446.     TextFont(txFont);
  3447.     TextSize(txSize);
  3448.     TextFace(txFace);
  3449.  
  3450.     OffsetRect(&mDerefCtl(cobj)->rect, -xoffset, -yoffset);
  3451.     HUnlock((Handle)cobj);
  3452.  
  3453.     if (ctl) {
  3454.         HiliteControl(ctl, mDerefCtl(cobj)->hilite);
  3455.         SetControlStyle(ctl, &cinfo);
  3456.         cctbID = mDerefCtl(cobj)->cctbID;
  3457.         if (cctbID) {
  3458.             if (gQDVersion > kQDOriginal) {
  3459.                 cctbHndl = (CCTabHandle)GetResource('cctb', cctbID);
  3460.                 if (cctbHndl)
  3461.                     SetControlColor(ctl, cctbHndl);
  3462.             }
  3463.         }
  3464.  
  3465.         if (vis) {
  3466.             switch (mDerefCtl(cobj)->procID & 0xFFF0) {
  3467.                 case rTECtl:
  3468.                     CTEShow((TEHandle)GetControlReference(ctl));
  3469.                     break;
  3470.                 case rListCtl:
  3471.                     CLShow((ListHandle)GetControlReference(ctl));
  3472.                     break;
  3473.                 default:
  3474.                     ShowControl(ctl);
  3475.                     break;
  3476.             }
  3477.         }
  3478.     }
  3479.  
  3480.     SetPort(oldPort);
  3481.     return(ctl);
  3482. }
  3483.  
  3484.  
  3485.  
  3486. /*****************************************************************************/
  3487.  
  3488.  
  3489.  
  3490. /* This function is called to return the handle of the Data control that has
  3491. ** a reference to all of the controls in the control set.  Once you get the
  3492. ** Data control, you can then look at the data in the control to get the handle
  3493. ** of the controls within the control set. */
  3494.  
  3495. #pragma segment Window
  3496. CObjCtlHndl    GetControlSet(WindowPtr window, OSType sftype, ControlHandle *retDataCtl)
  3497. {
  3498.     ControlHandle    dataCtl;
  3499.     CObjCtlHndl        coc;
  3500.  
  3501.     for (dataCtl = nil; (dataCtl = CDataNext(window, dataCtl)) != nil;) {
  3502.         if ((*dataCtl)->contrlRfCon != sftype) continue;
  3503.         if (GetControlVariant(dataCtl) != 7)   continue;
  3504.         coc = (CObjCtlHndl)(*dataCtl)->contrlData;
  3505.         if (coc) {
  3506.             if (retDataCtl) *retDataCtl = dataCtl;
  3507.             return(coc);
  3508.         }
  3509.     }
  3510.  
  3511.     if (retDataCtl) *retDataCtl = nil;
  3512.     return(nil);
  3513. }
  3514.  
  3515.  
  3516.  
  3517. /*****************************************************************************/
  3518.  
  3519.  
  3520.  
  3521. /* This function is used to show or hide a set of controls. */
  3522.  
  3523. #pragma segment Window
  3524. void    DisplayControlSet(WindowPtr window, OSType sftype, short visMode)
  3525. {
  3526.     WindowPtr        curPort;
  3527.     CObjCtlHndl        coc;
  3528.     short            i, vis;
  3529.     ControlHandle    ctl;
  3530.     Rect            rct;
  3531.  
  3532.     GetPort(&curPort);
  3533.     SetPort(window);
  3534.     coc = GetControlSet(window, sftype, nil);
  3535.     if (coc) {
  3536.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3537.             ctl = (**coc)[--i].ctl;
  3538.             vis = (**coc)[  i].visible;
  3539.             vis = ((vis | visMode) ^ (visMode > 1)) & 0x01;
  3540.             if (vis) {
  3541.                 switch ((**coc)[i].procID & 0xFFF0) {
  3542.                     case rTECtl:
  3543.                         CTEShow((TEHandle)GetControlReference(ctl));
  3544.                         break;
  3545.                     case rListCtl:
  3546.                         CLShow((ListHandle)GetControlReference(ctl));
  3547.                         break;
  3548.                     default:
  3549.                         ShowStyledControl(ctl);
  3550.                         break;
  3551.                 }
  3552.             }
  3553.             else {
  3554.                 switch ((**coc)[i].procID & 0xFFF0) {
  3555.                     case rTECtl:
  3556.                         rct = CTEHide((TEHandle)GetControlReference(ctl));
  3557.                         if (!(visMode & kwInvalOnHide)) ValidRect(&rct);
  3558.                         break;
  3559.                     case rListCtl:
  3560.                         rct = CLHide((ListHandle)GetControlReference(ctl));
  3561.                         if (!(visMode & kwInvalOnHide)) ValidRect(&rct);
  3562.                         break;
  3563.                     default:
  3564.                         HideStyledControl(ctl);
  3565.                         if (!(visMode & kwInvalOnHide)) {
  3566.                             rct = (*ctl)->contrlRect;
  3567.                             if (GetButtonVariant(ctl) == pushButProc)
  3568.                                 if ((*ctl)->contrlValue)
  3569.                                     InsetRect(&rct, kButtonFrameInset, kButtonFrameInset);
  3570.                             ValidRect(&rct);
  3571.                         }
  3572.                         break;
  3573.                 }
  3574.             }
  3575.         }
  3576.     }
  3577.     SetPort(curPort);
  3578. }
  3579.  
  3580.  
  3581.  
  3582. /*****************************************************************************/
  3583.  
  3584.  
  3585.  
  3586. /* This function is used to draw a set of controls. */
  3587.  
  3588. #pragma segment Window
  3589. void    DrawControlSet(WindowPtr window, OSType sftype)
  3590. {
  3591.     CObjCtlHndl        coc;
  3592.     short            i, j;
  3593.     ControlHandle    ctl, cc;
  3594.     ListHandle        list;
  3595.  
  3596.     coc = GetControlSet(window, sftype, nil);
  3597.     if (coc) {
  3598.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3599.             ctl = (**coc)[--i].ctl;
  3600.             DoDraw1Control(ctl, false);
  3601.             switch ((**coc)[i].procID & 0xFFF0) {
  3602.                 case rTECtl:
  3603.                     for (j = 0; j < 2; ++j) {
  3604.                         cc = CTEScrollFromView(ctl, j);
  3605.                         if (cc) DoDraw1Control(cc, false);
  3606.                     }
  3607.                     break;
  3608.                 case rListCtl:
  3609.                     list = (ListHandle)GetControlReference(ctl);
  3610.                     if (list) {
  3611.                         if ((*list)->vScroll) DoDraw1Control((*list)->vScroll, false);
  3612.                         if ((*list)->hScroll) DoDraw1Control((*list)->hScroll, false);
  3613.                     }
  3614.                     break;
  3615.             }
  3616.         }
  3617.     }
  3618. }
  3619.  
  3620.  
  3621.  
  3622. /*****************************************************************************/
  3623.  
  3624.  
  3625.  
  3626. /* This function is used to dispose a set of controls. */
  3627.  
  3628. #pragma segment Window
  3629. void    DisposeControlSet(WindowPtr window, OSType sftype)
  3630. {
  3631.     CObjCtlHndl        coc;
  3632.     ControlHandle    dataCtl;
  3633.     short            i;
  3634.  
  3635.     coc = GetControlSet(window, sftype, &dataCtl);
  3636.     if (coc) {
  3637.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3638.             HideStyledControl((**coc)[--i].ctl);
  3639.             DisposeControl((**coc)[i].ctl);
  3640.         }
  3641.         DisposeControl(dataCtl);
  3642.     }
  3643. }
  3644.  
  3645.  
  3646.  
  3647. /*****************************************************************************/
  3648.  
  3649.  
  3650.  
  3651. /* This function is used to dispose a set of controls. */
  3652.  
  3653. #pragma segment Window
  3654. void    DisposeControlFromSet(ControlHandle ctl, OSType sftype)
  3655. {
  3656.     WindowPtr        window;
  3657.     CObjCtlHndl        coc;
  3658.     ControlHandle    dataCtl;
  3659.     short            i, s, o;
  3660.     Ptr                p;
  3661.  
  3662.     window = (*ctl)->contrlOwner;
  3663.     coc = GetControlSet(window, sftype, &dataCtl);
  3664.     if (coc) {
  3665.         for (i = GetHandleSize((Handle)coc) / sizeof(CObjCtl); i;) {
  3666.             if (ctl == (**coc)[--i].ctl) {
  3667.                 DisposeControl(ctl);
  3668.                 s = GetHandleSize((Handle)coc);
  3669.                 o = i * sizeof(CObjCtl);
  3670.                 p = (Ptr)*coc;
  3671.                 BlockMove(p + o + sizeof(CObjCtl), p + o, s - o - sizeof(CObjCtl));
  3672.                 SetHandleSize((Handle)coc, s - sizeof(CObjCtl));
  3673.                 if (s == sizeof(CObjCtl)) DisposeControl(dataCtl);
  3674.                 return;
  3675.             }
  3676.         }
  3677.     }
  3678. }
  3679.  
  3680.  
  3681.  
  3682. /*****************************************************************************/
  3683.  
  3684.  
  3685.  
  3686. /* This fuction is called to adjust all of the menus in the designated MBAR. 
  3687. ** The functions gets each menu handle, and then disables all of the menu items
  3688. ** for that menu.  It then calls the application to give the application the
  3689. ** chance to enable the appropriate menu items. */
  3690.  
  3691. #pragma segment Window
  3692. Boolean    DoAdjustMBARMenus(WindowPtr window, short menuBarID)
  3693. {
  3694.     FileRecHndl                frHndl;
  3695.     short                    **mbar, i;
  3696.     long                    oldFlags;
  3697.     AdjustMenuItemsProcPtr    proc;
  3698.     Boolean                    redrawMenuBar;
  3699.     MenuHandle                menu;
  3700.  
  3701.     redrawMenuBar = false;
  3702.  
  3703.     proc = AdjustMenuItems;
  3704.     if (window) {
  3705.         if (((WindowPeek)window)->windowKind >= 1000) {
  3706.             frHndl = (FileRecHndl)GetWRefCon(window);
  3707.             if (frHndl)
  3708.                 proc = (*frHndl)->fileState.adjustMenuItemsProc;
  3709.         }
  3710.     }
  3711.  
  3712.     mbar = (short **)GetAppResource('MBAR', menuBarID, nil);
  3713.     if (mbar) {
  3714.         for (i = **mbar; i; --i) {
  3715.             menu = GetMenuHandle((*mbar)[i]);
  3716.             if (menu) {
  3717.                 oldFlags             = (*menu)->enableFlags;
  3718.                 (*menu)->enableFlags = oldFlags & 0x01;
  3719.                 redrawMenuBar       |= (*proc)(window, (*mbar)[i]);
  3720.                 if ((*menu)->enableFlags & 0xFFFFFFFEL) EnableItem(menu, 0);
  3721.                 else                                    DisableItem(menu, 0);
  3722.                 if ((oldFlags & 0x01) != ((*menu)->enableFlags & 0x01))
  3723.                     redrawMenuBar = true;
  3724.             }
  3725.         }
  3726.     }
  3727.  
  3728.     return(redrawMenuBar);
  3729. }
  3730.  
  3731.  
  3732.  
  3733. /*****************************************************************************/
  3734.  
  3735.  
  3736.  
  3737. /* This function is used to open all of the windows that are correctly designated
  3738. ** with the AppsToGo application editor.  You should call this in your application
  3739. ** at startup time if your application is editable with the AppsToGo application editor. */
  3740.  
  3741. #pragma segment Window
  3742. OSErr    OpenRuntimeOnlyAutoNewWindows(void)
  3743. {
  3744.     FileRecHndl    frHndl;
  3745.     OSErr        err;
  3746.     short        i;
  3747.     TreeObjHndl    wobj;
  3748.     long        attr;
  3749.  
  3750.     err = noErr;
  3751.     if (gWindowFormats) {
  3752.         for (i = (*gWindowFormats)->numChildren; i;) {
  3753.             wobj = GetChildHndl(gWindowFormats, --i);
  3754.             attr = mDerefWFMT(wobj)->attributes;
  3755.             if (attr & kwRuntimeOnlyDoc) {
  3756.                 if (attr & kwAutoNew) {
  3757.                     err = NewDocumentWindow(&frHndl, mDerefWFMT(wobj)->sfType, true);
  3758.                     if (err) break;
  3759.                 }
  3760.             }
  3761.         }
  3762.     }
  3763.     return(err);
  3764. }
  3765.  
  3766.  
  3767.  
  3768. /*****************************************************************************/
  3769.  
  3770.  
  3771.  
  3772. /* This call can be done as two separate calls.  However, this function does both
  3773. ** functions of creating the document, and then giving the document a window.  It
  3774. ** also handles errors and puts up an error window if something goes wrong. */
  3775.  
  3776. #pragma segment Window
  3777. OSErr    NewDocumentWindow(FileRecHndl *frHndl, OSType sftype, Boolean incTitleNum)
  3778. {
  3779.     FileRecHndl    ff, *ffp;
  3780.     OSErr        err;
  3781.     short        i, numAdded;
  3782.  
  3783.     gCursorPtr = nil;        /* Force recalc of cursor. */
  3784.  
  3785.     ffp = (frHndl) ? frHndl : &ff;
  3786.     *ffp = nil;
  3787.  
  3788.     if (!gWindowFormats) return(noErr);
  3789.  
  3790.     err = GetSeparateWFMT(sftype, &numAdded);
  3791.     if (!err) {
  3792.         for (i = (*gWindowFormats)->numChildren; i;) {
  3793.             if (sftype == mDerefWFMT(GetChildHndl(gWindowFormats, --i))->sfType) {
  3794.                 err = NewDocument(ffp, sftype, incTitleNum);
  3795.                 if (!err) {
  3796.                     err = DoNewWindow(*ffp, nil, FrontWindowOfType(kwIsDocument, true), (WindowPtr)-1);
  3797.                     if (err) DisposeDocument(*ffp);
  3798.                 }
  3799.                 break;
  3800.             }
  3801.         }
  3802.     }
  3803.     GetSeparateWFMT(0, &numAdded);
  3804.  
  3805.     return(err);
  3806. }
  3807.  
  3808.  
  3809.  
  3810. /*****************************************************************************/
  3811.  
  3812.  
  3813.  
  3814. /* This call can be done as two separate calls.  However, this function does both
  3815. ** functions of creating the document, and then giving the document a window.  It
  3816. ** also handles errors and puts up an error window if something goes wrong. */
  3817.  
  3818. #pragma segment Window
  3819. OSErr    OpenDocumentWindow(FileRecHndl *frHndl, FSSpecPtr fileToOpen, char permission)
  3820. {
  3821.     FileRecHndl    ff, *ffp;
  3822.     WindowPtr    window, fwindow;
  3823.     OSErr        err;
  3824.     long        wkind;
  3825.  
  3826.     gCursorPtr = nil;        /* Force recalc of cursor. */
  3827.  
  3828.     ffp = (frHndl) ? frHndl : &ff;
  3829.     *ffp = nil;
  3830.  
  3831.     if (!gWindowFormats) return(noErr);
  3832.  
  3833.     err = OpenDocument(ffp, fileToOpen, permission);
  3834.     if (!err) {
  3835.         window = (**ffp)->fileState.window;
  3836.         if (!window) {
  3837.             err = DoNewWindow(*ffp, nil, FrontWindowOfType(kwIsDocument, true), (WindowPtr)-1);
  3838.             if (err) DisposeDocument(*ffp);
  3839.         }
  3840.         else {
  3841.             wkind   = (**ffp)->fileState.attributes & (kwIsPalette | kwIsModalDialog);
  3842.             fwindow = FrontWindowOfType(wkind, true);
  3843.             CleanSendInFront(window, fwindow);
  3844.         }
  3845.     }
  3846.  
  3847.     return(err);
  3848. }
  3849.  
  3850.  
  3851.  
  3852.