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

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Collection of Utilities for DTS Sample code
  5. **
  6. **    File:        Utilities.c
  7. **
  8. **    Copyright © 1988-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. #ifndef OBSOLETE
  21. #define OBSOLETE
  22. #endif
  23.  
  24. #ifndef __CONTROLS__
  25. #include <Controls.h>
  26. #endif
  27.  
  28. #ifndef __DESK__
  29. #include <Desk.h>
  30. #endif
  31.  
  32. #ifndef __DEVICES__
  33. #include <Devices.h>
  34. #endif
  35.  
  36. #ifndef __ERRORS__
  37. #include <Errors.h>
  38. #endif
  39.  
  40. #ifndef __EVENTS__
  41. #include <Events.h>
  42. #endif
  43.  
  44. #ifndef __FONTS__
  45. #include <Fonts.h>
  46. #endif
  47.  
  48. #ifndef __GWLAYERS__
  49. #include "GWLayers.h"
  50. #endif
  51.  
  52. #ifndef __LOWMEM__
  53. #include <LowMem.h>
  54. #endif
  55.  
  56. #ifndef __MENUS__
  57. #include <Menus.h>
  58. #endif
  59.  
  60. #ifndef __NOTIFICATION__
  61. #include <Notification.h>
  62. #endif
  63.  
  64. #ifndef __OSEVENTS__
  65. #include <OSEvents.h>
  66. #endif
  67.  
  68. #ifndef __PACKAGES__
  69. #include <Packages.h>
  70. #endif
  71.  
  72. #ifndef __RESOURCES__
  73. #include <Resources.h>
  74. #endif
  75.  
  76. #ifndef __SCRIPT__
  77. #include <Script.h>
  78. #endif
  79.  
  80. #ifndef __STDLIB__
  81. #include <StdLib.h>
  82. #endif
  83.  
  84. #ifndef __STRINGS__
  85. #include <Strings.h>
  86. #endif
  87.  
  88. #ifndef __TEXTEDIT__
  89. #include <TextEdit.h>
  90. #endif
  91.  
  92. #ifndef __TOOLUTILS__
  93. #include <ToolUtils.h>
  94. #endif
  95.  
  96. #ifndef __APPLEEVENTS__
  97. #include <AppleEvents.h>
  98. #endif
  99.  
  100. #ifndef __COMPONENTS__
  101. #include <Components.h>
  102. #endif
  103.  
  104. #ifndef __FIXMATH__
  105. #include <FixMath.h>
  106. #endif
  107.  
  108. #ifndef __GESTALTEQU__
  109. #include <GestaltEqu.h>
  110. #endif
  111.  
  112. #ifndef __FOLDERS__
  113. #include <Folders.h>
  114. #endif
  115.  
  116. #ifndef __MOVIES__
  117. #include <Movies.h>
  118. #endif
  119.  
  120. #ifndef __PALETTES__
  121. #include <Palettes.h>
  122. #endif
  123.  
  124. #ifndef __STRINGUTILS__
  125. #include "StringUtils.h"
  126. #endif
  127.  
  128. #ifndef __TRAPS__
  129. #include <Traps.h>
  130. #endif
  131.  
  132. #include "Utilities.h"
  133.  
  134.  
  135.  
  136. /*****************************************************************************/
  137.  
  138.  
  139.  
  140. /* Global variables -- See Utilities.h for more explanation. */
  141.  
  142. short            gMachineType;            /* which machine this is */
  143. short            gSystemVersion;            /* System version number */
  144. short            gProcessorType;            /* which CPU this is */
  145. Boolean            gHasFPU;                /* true if machine has an FPU */
  146. short            gQDVersion;                /* major QD version #; 0 for original,
  147.                                                     1 for color QD, 2 for 32-bit QD */
  148. short            gKeyboardType;            /* which type of keyboard is present */
  149. short            gAppleTalkVersion;        /* AppleTalk version number */
  150. Boolean            gHasPMMU;                /* true if machine has a PMMU or equivalent */
  151. short            gAUXVersion;            /* major A/UX version number (0 if not present) */
  152.  
  153. Boolean            gHasWaitNextEvent;
  154. short            gAppResRef;
  155. Boolean            gInBackground;
  156. Str255            gAppName;
  157. OSType            gSignature = '\?\?\?\?';
  158. Boolean            gHaveSystemInfo;
  159.  
  160. GrafPtr            gScreenPort;
  161.  
  162. long            gQTVersion;                    /* QuickTime version (0 means not available). */
  163. Component        gMovieControllerComponent;    /* QuickTime movie controller component reference. */
  164.                                             /* Call InitQuickTime to initialize these globals. */
  165.  
  166. OSErr            gGetWindowErr;
  167. WindowTemplate    gWindowTemplate;
  168. WindowTemplate    gOpenedWindowTemplate;
  169. ControlHandle    gWhichCtlHit;
  170. long            gWhichCtlWhen;
  171. Boolean            gWhichCtlDbl;
  172. Boolean            gWhichCtlTracking;
  173.  
  174. ModalFilterUPP    gAlertFilterUPP;
  175. ModalFilterUPP    gKeyEquivFilterUPP;
  176.  
  177. static Handle    gScrollProc;
  178. Handle            gPopupProc;
  179. static Handle    gButtonProcs[radioButProc + useWFont + 1];
  180. static Rect        gWindowPlacementRect;
  181.  
  182. static DrawControlProcPtr    gDrawControl;
  183. GetButtonVariantProcPtr        gGetButtonVariant;
  184.  
  185. /* For PowerPC, we must supply an instantiation of the qd globals - MPW does it for you */
  186. #ifdef powerc
  187. #ifndef __MWERKS__
  188. QDGlobals    qd;
  189. #endif
  190. #endif
  191.  
  192.  
  193.  
  194. /* The following creates global routine descriptors in our global address space.
  195. ** It saves us having to check at runtime whether or not they are initialized and
  196. ** then having to allocate them on the heap using NewRoutineDescriptor.
  197. ** But it has the disadvantage of requiring some conditional compilation. */
  198.  
  199. #if USESROUTINEDESCRIPTORS
  200. static RoutineDescriptor gAlertFilterRD        = BUILD_ROUTINE_DESCRIPTOR (uppModalFilterProcInfo, AlertFilter);
  201. static RoutineDescriptor gKeyEquivFilterRD    = BUILD_ROUTINE_DESCRIPTOR (uppModalFilterProcInfo, KeyEquivFilter);
  202. ModalFilterUPP    gAlertFilterUPP                = &gAlertFilterRD;
  203. ModalFilterUPP    gKeyEquivFilterUPP            = &gKeyEquivFilterRD;
  204. #else
  205. ModalFilterUPP    gAlertFilterUPP                = AlertFilter;
  206. ModalFilterUPP    gKeyEquivFilterUPP            = KeyEquivFilter;
  207. #endif
  208.  
  209.  
  210.  
  211. /*****************************************************************************/
  212.  
  213.  
  214.  
  215. #pragma segment UtilMain
  216. Rect    SetWindowPlacementRect(Rect *rct)
  217. {
  218.     Rect    r;
  219.  
  220.     r = gWindowPlacementRect;
  221.     if (rct) gWindowPlacementRect = *rct;
  222.     return(r);
  223. }
  224.  
  225.  
  226.  
  227. /*****************************************************************************/
  228.  
  229.  
  230.  
  231. /* Given an alert ID and a window pointer the alert relates to, this function
  232. ** will center the alert’s rectangle before showing it on the proper screen.
  233. ** This follows the Apple Human Interface Guidelines for where to place a
  234. ** centered window on the screen.  If the alert is not closely associated with
  235. ** another window, pass a nil for the window pointer of the related window.  If
  236. ** you pass a nil, the alert is simply displayed where the resource
  237. ** would indicate.  Note that if an error occurs when getting the resource for
  238. ** the alert, then the alert is not displayed, and the returned value is not
  239. ** the item hit, but is the error that occured when reading the resource. */
  240.  
  241. #pragma segment UtilMain
  242. short    CenteredAlert(short alertID, WindowPtr relatedWindow, ModalFilterUPP filter)
  243. {
  244.     AlertTHndl    alertHandle;
  245.     WindowPtr    tempWindow;
  246.     Rect        alertRect, sizeInfo;
  247.     short        itemHit;
  248.     char        hstate;
  249.     OSErr        err;
  250.  
  251.     itemHit = 1;
  252.  
  253.     if (!SimpleCanDialog()) {
  254.         alertHandle = (AlertTHndl)GetAppResource('ALRT', alertID, &err);
  255.         if (err) return((short)err);
  256.  
  257.         hstate = LockHandleHigh((Handle)alertHandle);
  258.             /* Do our part to help prevent fragmentation. */
  259.  
  260.         alertRect = (*alertHandle)->boundsRect;
  261.             /* Preserve the real alert bounding rectangle. */
  262.  
  263.         tempWindow = NewWindow(nil, &alertRect, "\p", false, dBoxProc, (WindowPtr)nil, false, 0);
  264.         if (tempWindow) {
  265.             /* Use an invisible temporary window to calculate where the alert will go. */
  266.  
  267.             SetRect(&sizeInfo, 0, 0, 0, 0);
  268.             (*alertHandle)->boundsRect = CenterWindow(tempWindow, relatedWindow, sizeInfo);
  269.             DisposeWindow(tempWindow);
  270.         }
  271.  
  272.         itemHit = Alert(alertID, filter);
  273.  
  274.         alertHandle = (AlertTHndl)GetAppResource('ALRT', alertID, &err);
  275.         if (alertHandle) {
  276.             (*alertHandle)->boundsRect = alertRect;
  277.             HSetState((Handle)alertHandle, hstate);
  278.         }        /* Restore the resource's bounding rect, so if this resource is ever used
  279.                 ** not through this function, it will open where the resource indicates. */
  280.  
  281.     }
  282.  
  283.     return(itemHit);
  284. }
  285.  
  286.  
  287.  
  288. /*****************************************************************************/
  289.  
  290.  
  291.  
  292. /* Given two rects, this function centers the second one within the first. */
  293.  
  294. #pragma segment UtilMain
  295. void    CenterRectInRect(Rect outerRect, Rect *innerRect)
  296. {
  297.     PositionRectInRect(outerRect, innerRect, FixRatio(1, 2), FixRatio(1, 2));
  298. }
  299.  
  300.  
  301.  
  302. /*****************************************************************************/
  303.  
  304.  
  305.  
  306. /* Center a window within a particular device.  The device to center the window
  307. ** within is determined by passing a related window.  This allows related
  308. ** windows to be kept on the same device.  This is useful if an alert is related
  309. ** to a specific window, for example. */
  310.  
  311. #pragma segment UtilMain
  312. Rect    CenterWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  313. {
  314.     WindowPtr    whichDevice;
  315.     Rect        deviceRect, oldWindowRect, newWindowRect, contentRect;
  316.     short        h, v, hh, vv;
  317.  
  318.     if (!(whichDevice = relatedWindow))
  319.         whichDevice = window;
  320.             /* If we have a window to center against, use the device for that window,
  321.             ** else use the device for the window that is getting centered. */
  322.  
  323.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  324.         /* We now have the rectangle of the device we want to center within. */
  325.  
  326.     if (!EmptyRect(&gWindowPlacementRect))
  327.         deviceRect = gWindowPlacementRect;
  328.  
  329.     contentRect = GetWindowContentRect(window);        /* Get where the window is now. */
  330.     h = hh = contentRect.right  - contentRect.left;
  331.     v = vv = contentRect.bottom - contentRect.top;
  332.     if (sizeInfo.left)
  333.         if (h < sizeInfo.left)
  334.             h = sizeInfo.left;
  335.     if (sizeInfo.right)
  336.         if (h > sizeInfo.right)
  337.             h = sizeInfo.right;
  338.     if (sizeInfo.top)
  339.         if (v < sizeInfo.top)
  340.             v = sizeInfo.top;
  341.     if (sizeInfo.bottom)
  342.         if (v > sizeInfo.bottom)
  343.             v = sizeInfo.bottom;
  344.     contentRect.right  = contentRect.left + h;
  345.     contentRect.bottom = contentRect.top  + v;
  346.  
  347.     oldWindowRect = GetWindowStructureRect(window);
  348.     oldWindowRect.right  += (h - hh);
  349.     oldWindowRect.bottom += (v - vv);
  350.     newWindowRect = oldWindowRect;
  351.  
  352.     PositionRectInRect(deviceRect, &newWindowRect, FixRatio(1, 2), FixRatio(1, 3));
  353.         /* Figure out the new window strucRect so we can compare it against
  354.         ** the old strucRect.  This will tell us how much to move the window. */
  355.  
  356.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  357.                             newWindowRect.top  - oldWindowRect.top);
  358.         /* Calculate the new content rect. */
  359.  
  360.     MoveWindow(window, contentRect.left, contentRect.top, false);
  361.         /* Move the window to the new location. */
  362.  
  363.     return(contentRect);
  364. }
  365.  
  366.  
  367.  
  368. /*****************************************************************************/
  369.  
  370.  
  371.  
  372. /* Close a window.  This handles desk accessory and application windows.  Use
  373. ** this call (instead of DisposeAnyWindow) if the memory for the window was
  374. ** allocated by you.  (Same as CloseWindow v.s. DisposeWindow.) */
  375.  
  376. #pragma segment UtilMain
  377. void    CloseAnyWindow(WindowPtr window)
  378. {
  379.     if (IsDAWindow(window))
  380.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  381.     else {
  382.         HideWindow(window);
  383.         if (IsAppWindow(window))
  384.             CloseWindow(window);
  385.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  386.             CloseDialog((DialogPtr)window);
  387.     }
  388. }
  389.  
  390.  
  391.  
  392. /*****************************************************************************/
  393.  
  394.  
  395.  
  396. /* Dispose a window.  This handles desk accessory and application windows.  Use
  397. ** this call (instead of CloseAnyWindow) if you want the memory for the window
  398. ** record to be disposed of.  (Same as CloseWindow v.s. DisposeWindow.) */
  399.  
  400. #pragma segment UtilMain
  401. void    DisposeAnyWindow(WindowPtr window)
  402. {
  403.     if (IsDAWindow(window))
  404.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  405.     else {
  406.         HideWindow(window);
  407.         if (IsAppWindow(window))
  408.             DisposeWindow(window);
  409.         else if (((WindowPeek)window)->windowKind >= dialogKind)
  410.             DisposeDialog((DialogPtr)window);
  411.     }
  412. }
  413.  
  414.  
  415.  
  416. /*****************************************************************************/
  417.  
  418.  
  419.  
  420. /* Display an alert that tells the user an error occurred, then exit the
  421. ** program.  This function is used as an ultimate bail-out for serious errors
  422. ** that prohibit the continuation of the application.  Errors that do not
  423. ** require the termination of the application should be handled in a different
  424. ** manner. */
  425.  
  426. #pragma segment UtilMain
  427. void    DeathAlert(short errResID, short errStringIndex)
  428. {
  429.     ErrorAlert(errResID, errStringIndex);
  430.     ExitToShell();
  431. }
  432.  
  433.  
  434.  
  435. /*****************************************************************************/
  436.  
  437.  
  438.  
  439. /* Display an alert that tells the user an error occurred, then exit the
  440. ** program.  This function is used as an ultimate bail-out for serious errors
  441. ** that prohibit the continuation of the application.  Errors that do not
  442. ** require the termination of the application should be handled in a different
  443. ** manner.  The message parameter is an error code that is to be displayed. */
  444.  
  445. #pragma segment UtilMain
  446. void    DeathAlertMessage(short errResID, short errStringIndex, short message)
  447. {
  448.     ErrorAlertMessage(errResID, errStringIndex, message);
  449.     ExitToShell();
  450. }
  451.  
  452.  
  453.  
  454. /*****************************************************************************/
  455.  
  456.  
  457.  
  458. /* Display an alert that tells the user an error occurred. */
  459.  
  460. #pragma segment UtilMain
  461. void    ErrorAlert(short errResID, short errStringIndex)
  462. {
  463.     ErrorAlertMessage(errResID, errStringIndex, 0);
  464. }
  465.  
  466.  
  467.  
  468. /*****************************************************************************/
  469.  
  470.  
  471.  
  472. /* Display an alert to inform the user of an error.  errStringIndex acts as an
  473. ** index into a STR# resource of error messages.  If no errStringIndex is
  474. ** given, i.e. = 0, then use a standard message.  If message is not noErr then
  475. ** display it as well.
  476. **
  477. ** BUG NOTE:  GetIndString returns a bogus String if the index is
  478. **            not positive. */
  479.  
  480. #pragma segment UtilMain
  481. void    ErrorAlertMessage(short errResID, short errStringIndex, short message)
  482. {
  483.     Str255    msg1, msg2;
  484.  
  485.     SetCursor(&qd.arrow);
  486.  
  487.     if (errStringIndex <= 0) {
  488.         errStringIndex = eStandardErr;
  489.         errResID = rUtilStrings;
  490.     }
  491.     GetIndString(msg1, errResID, errStringIndex);
  492.  
  493.     if (message == noErr) {
  494.         ParamText(msg1, "\p", "\p", "\p");
  495.         CenteredAlert(rUtilErrorAlert, nil, nil);
  496.     } else {
  497.         pcpydec(msg2, message);
  498.         ParamText(msg1, msg2, "\p", "\p");
  499.         CenteredAlert(rUtilErrorMessageAlert, nil, nil);
  500.     }
  501. }
  502.  
  503.  
  504.  
  505. /*****************************************************************************/
  506.  
  507.  
  508.  
  509. /* FindSysFolder returns the (real) vRefNum, and the DirID of the current
  510. ** system folder.  It uses the Folder Manager if present, otherwise it falls
  511. ** back to SysEnvirons.  It returns zero on success, otherwise a standard
  512. ** system error. */
  513.  
  514. #pragma segment UtilMain
  515. OSErr    FindSysFolder(short *foundVRefNum, long *foundDirID)
  516. {
  517.     long            gesResponse;
  518.     SysEnvRec        envRec;
  519.     WDPBRec            myWDPB;
  520.     unsigned char    volName[34];
  521.     OSErr            err;
  522.  
  523.     *foundVRefNum = 0;
  524.     *foundDirID = 0;
  525.     if (!Gestalt(gestaltFindFolderAttr, &gesResponse) &&
  526.         BTstQ(gesResponse, gestaltFindFolderPresent)) {        /* Does Folder Manager exist? */
  527.             err = FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
  528.                 foundVRefNum, foundDirID);
  529.     } else {
  530.         /* Gestalt can't give us the answer, so we resort to SysEnvirons */
  531.         if (!(err = SysEnvirons(curSysEnvVers, &envRec))) {
  532.             myWDPB.ioVRefNum = envRec.sysVRefNum;
  533.             volName[0] = '\000';                    /* Zero volume name */
  534.             myWDPB.ioNamePtr = volName;
  535.             myWDPB.ioWDIndex = 0;
  536.             myWDPB.ioWDProcID = 0;
  537.             if (!(err = PBGetWDInfo(&myWDPB, 0))) {
  538.                 *foundVRefNum = myWDPB.ioWDVRefNum;
  539.                 *foundDirID = myWDPB.ioWDDirID;
  540.             }
  541.         }
  542.     }
  543.     return(err);
  544. }
  545.  
  546.  
  547.  
  548. /*****************************************************************************/
  549.  
  550.  
  551.  
  552. /* GetAppIndResource gets a resource from the application's resource file
  553. ** by index. */
  554.  
  555. #pragma segment UtilMain
  556. Handle    GetAppIndResource(ResType theType, short index, OSErr *err)
  557. {
  558.     short    savedResFile;
  559.     Handle    returnHandle;
  560.  
  561.     savedResFile = CurResFile();
  562.     UseResFile(gAppResRef);
  563.     returnHandle = Get1IndResource(theType, index);
  564.     if (err) *err = ResError();
  565.     UseResFile(savedResFile);
  566.     return(returnHandle);
  567. }
  568.  
  569.  
  570.  
  571. /*****************************************************************************/
  572.  
  573.  
  574.  
  575. /* GetAppNamedResource gets a resource from the application's resource file
  576. ** by name. */
  577.  
  578. #pragma segment UtilMain
  579. Handle    GetAppNamedResource(ResType theType, StringPtr name, OSErr *err)
  580. {
  581.     short    savedResFile;
  582.     Handle    returnHandle;
  583.  
  584.     savedResFile = CurResFile();
  585.     UseResFile(gAppResRef);
  586.     returnHandle = Get1NamedResource(theType, name);
  587.     if (err) *err = ResError();
  588.     UseResFile(savedResFile);
  589.     return(returnHandle);
  590. }
  591.  
  592.  
  593.  
  594. /*****************************************************************************/
  595.  
  596.  
  597.  
  598. /* GetAppResource gets a resource from the application's resource file by
  599. ** resource ID. */
  600.  
  601. #pragma segment UtilMain
  602. Handle    GetAppResource(ResType theType, short theID, OSErr *err)
  603. {
  604.     short    savedResFile;
  605.     Handle    returnHandle;
  606.  
  607.     savedResFile = CurResFile();
  608.     UseResFile(gAppResRef);
  609.     returnHandle = Get1Resource(theType, theID);
  610.     if (err) *err = ResError();
  611.     UseResFile(savedResFile);
  612.     return(returnHandle);
  613. }
  614.  
  615.  
  616.  
  617. /*****************************************************************************/
  618.  
  619.  
  620.  
  621. /* Checks for the presence of A/UX by whatever means is appropriate.  Returns
  622. ** the major version number of A/UX (i.e. 0 if A/UX is not present, 1 for
  623. ** any 1.x.x version 2 for any 2.x version, etc.
  624. **
  625. ** This code should work for all past, present and future A/UX systems. */
  626.  
  627. #define HWCfgFlags    0xB22    /* Low memory global used to check if A/UX is running */
  628.  
  629. #pragma segment UtilMain
  630. short    GetAUXVersion(void)
  631. {
  632.     long    auxVersion;
  633.     short    err;
  634.     short    *flagPtr;
  635.  
  636.     /* This code assumes the Gestalt glue checks for the presence of the _Gestalt
  637.     ** trap and does something intelligent if the trap is unavailable, i.e.
  638.     ** return unknown selector. */
  639.  
  640.     auxVersion = 0;
  641.     err = Gestalt(gestaltAUXVersion, &auxVersion);
  642.  
  643.     /* If gestaltUnknownErr or gestaltUndefSelectorErr was returned, then either
  644.     ** we weren't running on A/UX, or the _Gestalt trap is unavailable so use
  645.     ** HWCfgFlags instead.
  646.     ** All other errors are ignored (implies A/UX not present). */
  647.  
  648.     if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {    /* Use HWCfgFlags */
  649.         flagPtr = (short *) HWCfgFlags;
  650.         if (BTstQ(*flagPtr, 9))
  651.             auxVersion = 0x100;            /* Do Have A/UX, so assume version 1.x.x */
  652.     }
  653.  
  654.     /* Now right shift auxVersion by 8 bits to get major version number. */
  655.  
  656.     auxVersion >>= 8;
  657.     return((short)auxVersion);
  658. }
  659.  
  660.  
  661.  
  662. /*****************************************************************************/
  663.  
  664.  
  665.  
  666. #pragma segment UtilMain
  667. OSErr    SimpleCanDialog(void)
  668. {
  669.     OSErr                err;
  670.     ProcessSerialNumber    cpsn, fpsn;
  671.     Boolean                procsSame;
  672.  
  673.     err = noErr;
  674.     if (gSystemVersion >= 0x0700) {
  675.         err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  676.             /* Ask the AppleEvent Manager if we can come forward */
  677.         GetCurrentProcess(&cpsn);        /* We may have been moved to the front. */
  678.         GetFrontProcess(&fpsn);
  679.         SameProcess(&cpsn, &fpsn, &procsSame);
  680.         gInBackground = !procsSame;
  681.     }
  682.  
  683. /* Three results are possible here....
  684. **   noErr
  685. **     If the call completes with noErr, you can assume that you are
  686. **     (or have been made) the frontmost application, and you are free
  687. **     to interact with the user as much as you'd like.  Put up dialogs,
  688. **     flash alerts, whatever.
  689. **     If you were already in the foreground, AEInteractWithUser
  690. **     immediatly returns with a noErr, so you _should_ always call it.
  691. **
  692. **   errAETimeout
  693. **     If you pass a timeout value, or kAEDefaultTimeout, it is possible
  694. **     for the AEInteractWithUser call to timeout and return control to
  695. **     you before any state change has happened, you are still in the background.
  696. **     What you do at this point is a design decision you'll have to make.
  697. **     You can re-post the AEInteract call, perhaps with a larger timeout
  698. **     or kNoTimeOut, and see if you come forward this time.
  699. **     Or, you can continue on knowing that you are in the background and
  700. **     not interact at all.
  701. **
  702. **   errAENoUserInteraction
  703. **     If you get this error code back, this means that you
  704. **     MUST NOT interact with the user.  Do NOT put up any dialogs, alerts,
  705. **     or cause any other action that requires direct user intervention.
  706. **     This error code will be returned, for example, if any application
  707. **     has used the AESetInteractionAllowed call to specify no interaction,
  708. **     or if there is a pending AppleEvent that has interaction denied.
  709. **     This will also be returned if your application is being run by
  710. **     a script system, since an AppleEvent script cannot press buttons.
  711. **     By the way, if this is the case the AEinteractWithUser call has
  712. **     also not posted the notification.
  713. */
  714.  
  715.     return(err);
  716. }
  717.  
  718.  
  719.  
  720. /*****************************************************************************/
  721.  
  722.  
  723.  
  724. /* Given a dialog ID and a window pointer the dialog relates to, this function
  725. ** will center the dialog’s rectangle before showing it on the proper screen.
  726. ** This follows the Apple Human Interface Guidelines for where to place a
  727. ** centered window on the screen.  If the dialog is not closely associated with
  728. ** another window, pass a nil for the window pointer of the related window.  If
  729. ** you pass a nil, the dialog is simply displayed where the resource
  730. ** would indicate. */
  731.  
  732. #pragma segment UtilMain
  733. DialogPtr    GetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind)
  734. {
  735.     DialogTHndl    dlogResource;
  736.     DialogPtr    dialog;
  737.     Boolean        oldVis;
  738.     char        hstate;
  739.     OSErr        err;
  740.     Rect        sizeInfo;
  741.  
  742.     dialog = nil;
  743.     if (!SimpleCanDialog()) {
  744.         dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err);
  745.         if (dlogResource) {
  746.             hstate = LockHandleHigh((Handle)dlogResource);
  747.             oldVis = (*dlogResource)->visible;
  748.             (*dlogResource)->visible = false;
  749.             dialog = GetNewDialog(id, storage, behind);
  750.             if (dialog) {
  751.                 SetRect(&sizeInfo, 0, 0, 0, 0);
  752.                 CenterWindow(dialog, relatedWindow, sizeInfo);
  753.                 if (oldVis)
  754.                     ShowWindow(dialog);
  755.             }
  756.             dlogResource = (DialogTHndl)GetAppResource('DLOG', id, &err);
  757.             if (dlogResource) {
  758.                 (*dlogResource)->visible = oldVis;
  759.                 HSetState((Handle)dlogResource, hstate);
  760.             }
  761.         }
  762.     }
  763.     return(dialog);
  764. }
  765.  
  766.  
  767.  
  768. /*****************************************************************************/
  769.  
  770.  
  771.  
  772. /* Given a window ID and a window pointer the window relates to, this function
  773. ** will center the window’s rectangle before showing it on the proper screen.
  774. ** This follows the Apple Human Interface Guidelines for where to place a
  775. ** centered window on the screen.  If the window is not closely associated with
  776. ** another window, pass a nil for the window pointer of the related window.  If
  777. ** you pass a nil, the window is simply displayed where the resource
  778. ** would indicate. */
  779.  
  780. #pragma segment UtilMain
  781. WindowPtr    GetCenteredWindow(short id, Ptr storage, Boolean vis, WindowPtr relWindow,
  782.                               WindowPtr behind, Boolean inColor, Rect sizeInfo, long refCon)
  783. {
  784.     return(GetSomeKindOfWindow(CenterWindow, id, storage, vis, relWindow,
  785.                                behind, inColor, sizeInfo, refCon));
  786. }
  787.  
  788.  
  789.  
  790. /*****************************************************************************/
  791.  
  792.  
  793.  
  794. /* GetGestaltResult returns the result value from Gestalt for the specified
  795. ** selector.  If Gestalt returned an error GetGestaltResult returns zero.
  796. ** Use of this function is only cool if we don't care whether Gestalt returned
  797. ** an error.  In many cases you may need to know the exact Gestalt error code
  798. ** so then this function would be inappropriate.
  799. ** See GetAUXVersion for an example. */
  800.  
  801. #pragma segment UtilMain
  802. long    GetGestaltResult(OSType gestaltSelector)
  803. {
  804.     long    gestaltResult;
  805.  
  806.     if (Gestalt(gestaltSelector, &gestaltResult) == noErr)
  807.         return(gestaltResult);
  808.     else
  809.         return(0);
  810. }
  811.  
  812.  
  813.  
  814. /*****************************************************************************/
  815.  
  816.  
  817.  
  818. /* Get the global coordinates of the mouse. */
  819.  
  820. #pragma segment UtilMain
  821. Point    GetGlobalMouse(void)
  822. {
  823.     WindowPtr    oldPort, wmPort;
  824.     Point        pt;
  825.  
  826.     GetPort(&oldPort);
  827.     GetWMgrPort(&wmPort);
  828.     SetPort(wmPort);
  829.     GetMouse(&pt);
  830.     LocalToGlobal(&pt);
  831.     SetPort(oldPort);
  832.     return(pt);
  833. }
  834.  
  835.  
  836.  
  837. /*****************************************************************************/
  838.  
  839.  
  840.  
  841. /* Given a window, this will return the top left point of the window’s port in
  842. ** global coordinates.  Something this doesn’t include is the window’s drag
  843. ** region (or title bar).  This returns the top left point of the window’s
  844. ** content area only. */
  845.  
  846. #pragma segment UtilMain
  847. Point    GetGlobalTopLeft(WindowPtr window)
  848. {
  849.     GrafPtr    oldPort;
  850.     Point    globalPt;
  851.  
  852.     GetPort(&oldPort);
  853.     SetPort(window);
  854.     globalPt = TopLeft(window->portRect);
  855.     LocalToGlobal(&globalPt);
  856.     SetPort(oldPort);
  857.     return(globalPt);
  858. }
  859.  
  860.  
  861.  
  862. /*****************************************************************************/
  863.  
  864.  
  865.  
  866. /* Return the amount of free space on the volume in KBytes. -1 is returned as
  867. ** the size if there is an error. */
  868.  
  869. #pragma segment UtilMain
  870. long    GetKFreeSpace(short vRefNum)
  871. {
  872.     HParamBlockRec    pb;
  873.     OSErr            err;
  874.  
  875.     pb.volumeParam.ioNamePtr = nil;            /* we don't care about the name */
  876.     pb.volumeParam.ioVRefNum = vRefNum;
  877.     pb.volumeParam.ioVolIndex = 0;            /* use ioVRefNum only */
  878.     err = PBHGetVInfo(&pb, false);
  879.  
  880.     if (err == noErr)
  881.         return((pb.volumeParam.ioVFrBlk * pb.volumeParam.ioVAlBlkSiz) / 1024);
  882.     else
  883.         return(-1);
  884. }
  885.  
  886.  
  887.  
  888. /*****************************************************************************/
  889.  
  890.  
  891.  
  892. #pragma segment UtilMain
  893. Rect    GetMainScreenRect(void)
  894. {
  895.     GDHandle    mainDevice;
  896.     GrafPtr        mainPort;
  897.  
  898.     if (gQDVersion > kQDOriginal) {
  899.         mainDevice = GetMainDevice();
  900.         return((*mainDevice)->gdRect);
  901.     }
  902.     else {
  903.         GetWMgrPort(&mainPort);
  904.         return(mainPort->portRect);
  905.     }
  906. }
  907.  
  908.  
  909.  
  910. /*****************************************************************************/
  911.  
  912.  
  913.  
  914. /* Find the greatest overlap device for the given global rectangle. */
  915.  
  916. #pragma segment UtilMain
  917. GDHandle    GetRectDevice(Rect globalRect)
  918. {
  919.     long        area, maxArea;
  920.     GDHandle    device, deviceToReturn;
  921.     Rect        intersection;
  922.  
  923.     deviceToReturn = GetMainDevice();            /* Use as default choice. */
  924.     maxArea = 0;
  925.  
  926.     for (device = GetDeviceList(); device; device = GetNextDevice(device)) {
  927.         if (TestDeviceAttribute(device, screenDevice)
  928.           && TestDeviceAttribute(device, screenActive)
  929.           && SectRect(&globalRect, &((*device)->gdRect), &intersection)) {
  930.             area = ((long)(intersection.right - intersection.left)) *
  931.                    ((long)(intersection.bottom - intersection.top));
  932.             if (area > maxArea) {
  933.                 deviceToReturn = device;
  934.                 maxArea = area;
  935.             }
  936.         }
  937.     }
  938.     return(deviceToReturn);
  939. }
  940.  
  941.  
  942.  
  943. /*****************************************************************************/
  944.  
  945.  
  946.  
  947. /* Find the rect of the greatest overlap device for the given global rect. */
  948.  
  949. #pragma segment UtilMain
  950. Rect    GetRectDeviceRect(Rect globalRect)
  951. {
  952.     if (gQDVersion > kQDOriginal)
  953.         return((*GetRectDevice(globalRect))->gdRect);
  954.     else
  955.         return(GetMainScreenRect());
  956. }
  957.  
  958.  
  959.  
  960. /*****************************************************************************/
  961.  
  962.  
  963.  
  964. /* Given a window positioning procedure pointer, a window ID and a window
  965. ** pointer the window relates to, this function open a new window by either
  966. ** a NewCWindow or a NewWindow call, depending on the value of inColor.  The
  967. ** window will be opened invisible, independent of what the resource says.
  968. ** Once the window is opened successfully, the positioning procedure is
  969. ** called.  The positioning procedure is passed a pointer to the just-opened
  970. ** invisible window and a pointer to the related window.  It is up to the
  971. ** positioning procedure to move the invisible window to the correct location
  972. ** on the correct device.  Once the positioning procedure returns, the window
  973. ** will be made visible if so indicated by the resource. */
  974.  
  975. #pragma segment UtilMain
  976. WindowPtr    GetSomeKindOfWindow(PositionWndProcPtr whatKind, short windID, Ptr storage,
  977.                                 Boolean vis, WindowPtr relatedWindow, WindowPtr behind,
  978.                                 Boolean inColor, Rect sizeInfo, long refCon)
  979. {
  980.     WindowTHndl        windowResource;
  981.     WindowTemplate    wt;
  982.     WindowPtr        window;
  983.     PaletteHandle    wpalette;
  984.     CTabHandle        wcolor;
  985.     Ptr                allocStg;
  986.     OSErr            err;
  987.  
  988.     gGetWindowErr = noErr;
  989.  
  990.     window = nil;        /* Assume we will fail.  (Good attitude.) */
  991.     SetRect(&gOpenedWindowTemplate.boundsRect, 0, 0, 0, 0);
  992.  
  993.     if (gQDVersion == kQDOriginal)
  994.         inColor = false;
  995.  
  996.     if (!(allocStg = storage))
  997.         if (!(allocStg = NewPtr(sizeof(WindowRecord))))
  998.             gGetWindowErr = memFullErr;
  999.  
  1000.     if (allocStg) {            /* If we have memory for the window record... */
  1001.  
  1002.         wt = gWindowTemplate;
  1003.         if (EmptyRect(&wt.boundsRect)) {
  1004.             windowResource = (WindowTHndl)GetAppResource('WIND', windID, &err);
  1005.             if (windowResource)
  1006.                 wt = **windowResource;        /* Make local copy of resource. */
  1007.             else
  1008.                 gGetWindowErr = resNotFound;
  1009.         }
  1010.  
  1011.         if (!EmptyRect(&wt.boundsRect)) {
  1012.             window = (inColor ? NewCWindow(allocStg, &wt.boundsRect,
  1013.                                            wt.title, false, wt.procID,
  1014.                                            behind, wt.goAwayFlag, wt.refCon)
  1015.                                : NewWindow(allocStg, &wt.boundsRect, wt.title,
  1016.                                            false, wt.procID,
  1017.                                            behind, wt.goAwayFlag, wt.refCon));
  1018.                 /* Open either a regular or color window. */
  1019.  
  1020.             if (window) {        /* If we were able to open a window... */
  1021.                 if (inColor) {
  1022.                     wpalette = GetNewPalette(windID);
  1023.                     if (wpalette)
  1024.                         SetPalette(window, wpalette, true);
  1025.                     wcolor = (CTabHandle)GetResource('wctb', windID);
  1026.                     if (wcolor)
  1027.                         SetWinColor(window, (WCTabHandle)wcolor);
  1028.                 }
  1029.  
  1030.                 SetWRefCon(window, refCon);
  1031.                 if (whatKind)
  1032.                     (*whatKind)(window, relatedWindow, sizeInfo);
  1033.                         /* Call the designated window positioning procedure. */
  1034.  
  1035.                 if (vis)
  1036.                     ShowWindow(window);
  1037.                         /* If caller says window should be visible, make it so. */
  1038.             }
  1039.         }
  1040.         if (!window) {
  1041.             if (allocStg != storage)
  1042.                 DisposePtr(storage);
  1043.         }            /* If we failed, then get rid of window record memory. */
  1044.         else
  1045.             gOpenedWindowTemplate = wt;
  1046.     }
  1047.  
  1048.     return(window);
  1049. }
  1050.  
  1051.  
  1052.  
  1053. /*****************************************************************************/
  1054.  
  1055.  
  1056.  
  1057. /* Given a window ID and a window pointer the window relates to, this function
  1058. ** will stagger the window’s rectangle before showing it on the proper screen.
  1059. ** This follows the Apple Human Interface Guidelines for where to place a
  1060. ** staggered window on the screen.  If the window is not closely associated
  1061. ** with another window, pass a nil for the window pointer of the related
  1062. ** window.  If you pass a nil, the window is simply displayed where the
  1063. ** resource would indicate. */
  1064.  
  1065. #pragma segment UtilMain
  1066. WindowPtr    GetStaggeredWindow(short id, Ptr storage, Boolean vis, WindowPtr relWindow,
  1067.                                WindowPtr behind, Boolean inColor, Rect sizeInfo, long refCon)
  1068. {
  1069.     return(GetSomeKindOfWindow(StaggerWindow, id, storage, vis, relWindow,
  1070.                                behind, inColor, sizeInfo, refCon));
  1071. }
  1072.  
  1073.  
  1074.  
  1075. /*****************************************************************************/
  1076.  
  1077.  
  1078.  
  1079. /*    Check the bits of a trap number to determine its type. */
  1080.  
  1081. #pragma segment UtilMain
  1082. TrapType    GetTrapType(short theTrap)
  1083. {
  1084.     /* OS traps start with A0, Tool with A8 or AA. */
  1085.     if ((theTrap & 0x0800) == 0)                    /* per D.A. */
  1086.         return(OSTrap);
  1087.     else
  1088.         return(ToolTrap);
  1089. }
  1090.  
  1091.  
  1092.  
  1093. /*****************************************************************************/
  1094.  
  1095.  
  1096.  
  1097. /* Given a window pointer, return the global rectangle that encloses the
  1098. ** content area of the window. */
  1099.  
  1100. #pragma segment UtilMain
  1101. Rect    GetWindowContentRect(WindowPtr window)
  1102. {
  1103.     WindowPtr    oldPort;
  1104.     Rect        contentRect;
  1105.  
  1106.     SetRect(&contentRect, 0, 0, 0, 0);
  1107.     if (window) {
  1108.         GetPort(&oldPort);
  1109.         SetPort(window);
  1110.         contentRect = window->portRect;
  1111.         LocalToGlobalRect(&contentRect);
  1112.         SetPort(oldPort);
  1113.     }
  1114.  
  1115.     return(contentRect);
  1116. }
  1117.  
  1118.  
  1119.  
  1120. /*****************************************************************************/
  1121.  
  1122.  
  1123.  
  1124. /* This procedure counts the number of windows in the application plane.
  1125. ** You have the choices of also including DAs and invisible windows in
  1126. ** this count. */
  1127.  
  1128. #pragma segment UtilMain
  1129. short    GetWindowCount(Boolean includeDAs, Boolean includeDLOGs, Boolean includeInvisibles)
  1130. {
  1131.     WindowPeek    window;
  1132.     short        count;
  1133.  
  1134.     for (count = 0, window = LMGetWindowList(); (window != nil); window = window->nextWindow) {
  1135.         if ((window->windowKind < 0) && (!includeDAs)) continue;
  1136.         if ((window->windowKind < userKind) && (!includeDLOGs)) continue;
  1137.         if ((window->visible) || (includeInvisibles))
  1138.             count++;
  1139.     }
  1140.     return(count);
  1141. }
  1142.  
  1143.  
  1144.  
  1145. /*****************************************************************************/
  1146.  
  1147.  
  1148.  
  1149. /* Find the greatest overlap device for the given window. */
  1150.  
  1151. #pragma segment UtilMain
  1152. GDHandle    GetWindowDevice(WindowPtr window)
  1153. {
  1154.     return(GetRectDevice(GetWindowStructureRect(window)));
  1155. }
  1156.  
  1157.  
  1158.  
  1159. /*****************************************************************************/
  1160.  
  1161.  
  1162.  
  1163. /* Given a window pointer, find the device that contains most of the window
  1164. ** and return the device's bounding rectangle. */
  1165.  
  1166. #pragma segment UtilMain
  1167. Rect    GetWindowDeviceRect(WindowPtr window)
  1168. {
  1169.     if (gQDVersion > kQDOriginal)
  1170.         return((*GetWindowDevice(window))->gdRect);
  1171.     else
  1172.         return(GetMainScreenRect());
  1173. }
  1174.  
  1175.  
  1176.  
  1177. /*****************************************************************************/
  1178.  
  1179.  
  1180.  
  1181. /* Given a window pointer, find the device that contains most of the window
  1182. ** and return the device's bounding rectangle.  If this device is the main
  1183. ** device, then remove the menubar area from the rectangle. */
  1184.  
  1185. #pragma segment UtilMain
  1186. Rect    GetWindowDeviceRectNMB(WindowPtr window)
  1187. {
  1188.     Rect    deviceRect, tempRect;
  1189.  
  1190.     SetRect(&deviceRect, 0, 0, 0, 0);
  1191.  
  1192.     if (window) {
  1193.         deviceRect = GetWindowDeviceRect(window);
  1194.         tempRect = GetMainScreenRect();
  1195.         if (EqualRect(&deviceRect, &tempRect))
  1196.             deviceRect.top += GetMBarHeight();
  1197.     }
  1198.  
  1199.     return(deviceRect);
  1200. }
  1201.  
  1202.  
  1203.  
  1204. /*****************************************************************************/
  1205.  
  1206.  
  1207.  
  1208. /* This procedure is used to get the rectangle that surrounds the entire
  1209. ** structure of a window.  This is true whether or not the window is visible.
  1210. ** If the window is visible, then it is a simple matter of using the bounding
  1211. ** rectangle of the structure region.  If the window is invisible, then the
  1212. ** strucRgn is not correct.  To make it correct, then window has to be moved
  1213. ** way off the screen and then made visible.  This generates a valid strucRgn,
  1214. ** although it is valid for the position that is way off the screen.  It still
  1215. ** needs to be offset back into the original position.  Once the bounding
  1216. ** rectangle for the strucRgn is obtained, the window can then be hidden again
  1217. ** and moved back to its correct location.  Note that ShowHide is used,
  1218. ** instead of ShowWindow and HideWindow.  HideWindow can change the plane of
  1219. ** the window.  Also, ShowHide does not affect the hiliting of windows.
  1220. ** Note that using ShowHide to make the window visible has the unfortunate
  1221. ** side-effect of changing the userState rect.  Since we make the window
  1222. ** invisible prior to moving it back, userState gets left funky.  Due to this,
  1223. ** we have to cache it prior to doing the ShowHide games. */
  1224.  
  1225. #pragma segment UtilMain
  1226. Rect    GetWindowStructureRect(WindowPtr window)
  1227. {
  1228. #define kOffscreenLoc 0x4000
  1229.  
  1230.     GrafPtr    oldPort;
  1231.     Rect    structureRect, userState;
  1232.     Point    windowLoc;
  1233.  
  1234.     SetRect(&structureRect, 0, 0, 0, 0);
  1235.  
  1236.     if (window) {
  1237.  
  1238.         if (((WindowPeek)window)->visible)
  1239.             structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1240.  
  1241.         else {
  1242.             GetPort(&oldPort);
  1243.             SetPort(window);
  1244.             windowLoc  = GetGlobalTopLeft(window);
  1245.             if (((WindowPeek)window)->spareFlag)
  1246.                 userState = (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->userState;
  1247.             MoveWindow(window, kOffscreenLoc, kOffscreenLoc, false);
  1248.             ShowHide(window, true);
  1249.             structureRect = (*(((WindowPeek)window)->strucRgn))->rgnBBox;
  1250.             ShowHide(window, false);
  1251.             MoveWindow(window, windowLoc.h, windowLoc.v, false);
  1252.             if (((WindowPeek)window)->spareFlag)
  1253.                 (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->userState = userState;
  1254.             SetPort(oldPort);
  1255.             OffsetRect(&structureRect, windowLoc.h - kOffscreenLoc, windowLoc.v - kOffscreenLoc);
  1256.         }
  1257.     }
  1258.  
  1259.     return(structureRect);
  1260. }
  1261.  
  1262.  
  1263.  
  1264. /*****************************************************************************/
  1265.  
  1266.  
  1267.  
  1268. #pragma segment UtilMain
  1269. void    GlobalToLocalRect(Rect *aRect)
  1270. {
  1271.     GlobalToLocal(&TopLeft(*aRect));
  1272.     GlobalToLocal(&BotRight(*aRect));
  1273. }
  1274.  
  1275.  
  1276.  
  1277. /*****************************************************************************/
  1278.  
  1279.  
  1280.  
  1281. #pragma segment UtilMain
  1282. void    InitToolBox(void)
  1283. {
  1284.     InitGraf((Ptr) &qd.thePort);
  1285.     InitFonts();
  1286.     InitWindows();
  1287.     InitMenus();
  1288.     TEInit();
  1289.     InitDialogs(0);
  1290.     InitCursor();
  1291. }
  1292.  
  1293.  
  1294.  
  1295. /*****************************************************************************/
  1296.  
  1297.  
  1298.  
  1299. /* GetSystemInfo sets up some global variables for use by the utilities
  1300. ** package and your application.  If you call StandardInitialization, you
  1301. ** don't need to call this, as it will do it for you. */
  1302.  
  1303. #pragma segment UtilMain
  1304. void    GetSystemInfo(void)
  1305. {
  1306.     Handle            bndlResource;
  1307.     OSErr            err;
  1308.     short            ignoreRefNum;
  1309. #ifndef powerc
  1310.     Handle            apParam;
  1311. #endif
  1312.  
  1313.     if (!gHaveSystemInfo) {
  1314.  
  1315.         /* Init all the Gestalt variables */
  1316.         gMachineType   = GetGestaltResult(gestaltMachineType);
  1317.         gSystemVersion = GetGestaltResult(gestaltSystemVersion);
  1318.         gProcessorType = GetGestaltResult(gestaltProcessorType);
  1319.  
  1320.         /* We only concern ourselves with there being an FPU, not which type it is. */
  1321.         gHasFPU = (GetGestaltResult(gestaltFPUType) != gestaltNoFPU);
  1322.  
  1323.         /* We only concern ourselves with the major QD version number
  1324.         ** 0 for original QD, 1 for 8-bit color QD, and 2 for 32-bit QD. */
  1325.  
  1326.         gQDVersion = (GetGestaltResult(gestaltQuickdrawVersion) >> 8) & 0xFF;
  1327.         gKeyboardType = GetGestaltResult(gestaltKeyboardType);
  1328.  
  1329.         if (!OpenDriver("\p.MPP", &ignoreRefNum))
  1330.             gAppleTalkVersion = GetGestaltResult(gestaltAppleTalkVersion);
  1331.                 /* Under system 6, the driver isn't necessarily open, so open it for sure.
  1332.                 ** If the driver isn't opened, then the gestalt selector isn't installed,
  1333.                 ** and therefore returns 0, which isn't really the case. */
  1334.  
  1335.         /* We only concern ourselves with there being an PMMU, not which type it is. */
  1336.         gHasPMMU = GetGestaltResult(gestaltMMUType) >= gestalt68851;
  1337.         gAUXVersion = GetAUXVersion();
  1338.  
  1339.         gHasWaitNextEvent = TrapExists(_WaitNextEvent);
  1340.         gInBackground = false;
  1341.  
  1342.         /* PowerPC doesn't support GetAppParms for native code (use AppleEvents!!!), so we find 
  1343.         ** the information in other ways. */
  1344. #ifdef powerc
  1345.         {
  1346.             ProcessSerialNumber        currentPSN;
  1347.             ProcessInfoRec            currentProcRec;
  1348.  
  1349.             /* It's safe to assume we have a Process Manager on PowerPC */
  1350.             GetCurrentProcess (¤tPSN);
  1351.             currentProcRec.processInfoLength = sizeof(currentProcRec);
  1352.             currentProcRec.processName = gAppName;
  1353.             currentProcRec.processAppSpec = nil;
  1354.             GetProcessInformation (¤tPSN, ¤tProcRec);
  1355.             gAppResRef = CurResFile();            /* This is lazy and assumes no one has mucked with the resource chain */
  1356.         }
  1357. #else
  1358.         GetAppParms(gAppName, &gAppResRef, &apParam);
  1359. #endif
  1360.  
  1361. #ifdef THINK_C
  1362.         gAppResRef = CurResFile();            /* returns refNum of .rsrc file */
  1363.             /* 10/16/90 pvh/MacDTS
  1364.             ** With GetAppParams(), THINK C in project mode returns the project resource
  1365.             ** file AND NOT the .rsrc file, which is what one really wants (trust me).
  1366.             ** If THINK is present we will return CurResFile() which will be the .rsrc
  1367.             ** file instead.  The name will still be the project name in project mode,
  1368.             ** so be aware of that. */
  1369. #endif
  1370.  
  1371.         bndlResource = GetAppIndResource('BNDL', 1, &err);
  1372.         if (bndlResource)
  1373.             gSignature = *(OSType *)(*bndlResource);
  1374.  
  1375.         gHaveSystemInfo = true;
  1376.     }
  1377. }
  1378.  
  1379.  
  1380.  
  1381. /*****************************************************************************/
  1382.  
  1383.  
  1384.  
  1385. /* Check to see if a window belongs to the application.  If the window pointer
  1386. ** passed was nil, then it could not be an application window.  WindowKinds
  1387. ** that are negative belong to the system and windowKinds less than userKind
  1388. ** are reserved by Apple except for windowKinds equal to dialogKind, which
  1389. ** mean it is a dialog. */
  1390.  
  1391. #pragma segment UtilMain
  1392. Boolean    IsAppWindow(WindowPtr window)
  1393. {
  1394.     if (window) return(((WindowPeek)window)->windowKind >= userKind);
  1395.     else        return(false);
  1396. }
  1397.  
  1398.  
  1399.  
  1400. /*****************************************************************************/
  1401.  
  1402.  
  1403.  
  1404. /* Check to see if a window belongs to a desk accessory. */
  1405.  
  1406. #pragma segment UtilMain
  1407. Boolean    IsDAWindow(WindowPtr window)
  1408. {
  1409.     if (window)    /* DA windows have negative windowKinds */
  1410.         return(((WindowPeek) window)->windowKind < 0);
  1411.     else
  1412.         return(false);
  1413. }
  1414.  
  1415.  
  1416.  
  1417. /*****************************************************************************/
  1418.  
  1419.  
  1420.  
  1421. #pragma segment UtilMain
  1422. void    LocalToGlobalRect(Rect *aRect)
  1423. {
  1424.     LocalToGlobal(&TopLeft(*aRect));
  1425.     LocalToGlobal(&BotRight(*aRect));
  1426. }
  1427.  
  1428.  
  1429.  
  1430. /*****************************************************************************/
  1431.  
  1432.  
  1433.  
  1434. #pragma segment UtilMain
  1435. char    LockHandleHigh(Handle theHandle)
  1436. {
  1437.     char    hstate;
  1438.  
  1439.     hstate = HGetState(theHandle);
  1440.     MoveHHi(theHandle);
  1441.     HLock(theHandle);
  1442.     return(hstate);
  1443. }
  1444.  
  1445.  
  1446.  
  1447. /*****************************************************************************/
  1448.  
  1449.  
  1450.  
  1451. /* InitGraf is always implemented (trap $A86E).  If the trap table is big
  1452. ** enough, trap $AA6E will always point to either Unimplemented or some other
  1453. ** trap, but will never be the same as InitGraf.  Thus, you can check the size
  1454. ** of the trap table by asking if the address of trap $A86E is the same as
  1455. ** $AA6E. */
  1456.  
  1457. #pragma segment UtilMain
  1458. short    NumToolboxTraps(void)
  1459. {
  1460.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  1461.         return(0x200);
  1462.     else
  1463.         return(0x400);
  1464. }
  1465.  
  1466.  
  1467.  
  1468. /*****************************************************************************/
  1469.  
  1470.  
  1471.  
  1472. /* Given two rectangles, this function positions the second within the first
  1473. ** one so that it maintains the spacing specified by the horzRatio and
  1474. ** vertRatio parameters.  In other words, to center an inner rectangle
  1475. ** hoizontally, but have its center be 1/3 from the top of the outer rectangle,
  1476. ** call this function with horzRatio = FixRatio(1, 2), vertRatio =
  1477. ** FixRatio(1, 3).  We use Fixed rather than floating point to avoid
  1478. ** complications when mixing MC68881/non-MC68881 versions of Utilities. */
  1479.  
  1480. #pragma segment UtilMain
  1481. void    PositionRectInRect(Rect outerRect, Rect *innerRect, Fixed horzRatio, Fixed vertRatio)
  1482. {
  1483.     short    outerRectHeight;
  1484.     short    outerRectWidth;
  1485.     short    innerRectHeight;
  1486.     short    innerRectWidth;
  1487.     short    yLocation;
  1488.     short    xLocation;
  1489.  
  1490.     outerRectHeight = outerRect.bottom - outerRect.top;
  1491.     outerRectWidth = outerRect.right - outerRect.left;
  1492.  
  1493.     innerRectHeight = innerRect->bottom - innerRect->top;
  1494.     innerRectWidth = innerRect->right - innerRect->left;
  1495.         yLocation = Fix2Long(FixMul(Long2Fix(outerRectHeight - innerRectHeight), vertRatio))
  1496.             + outerRect.top;
  1497.         xLocation = Fix2Long(FixMul(Long2Fix(outerRectWidth - innerRectWidth), horzRatio))
  1498.             + outerRect.left;
  1499.  
  1500.     innerRect->top = yLocation;
  1501.     innerRect->left = xLocation;
  1502.     innerRect->bottom = yLocation + innerRectHeight;
  1503.     innerRect->right = xLocation + innerRectWidth;
  1504. }
  1505.  
  1506.  
  1507.  
  1508. /*****************************************************************************/
  1509.  
  1510.  
  1511.  
  1512. #pragma segment UtilMain
  1513. void    PullApplicationToFront(void)
  1514. {
  1515. #define kBroughtToFront 3
  1516.  
  1517.     EventRecord event;
  1518.     short        count;
  1519.  
  1520.     for (count = 1; count <= kBroughtToFront; count++)
  1521.         EventAvail(everyEvent, &event);
  1522. }
  1523.  
  1524.  
  1525.  
  1526. /*****************************************************************************/
  1527.  
  1528.  
  1529.  
  1530. /* This algorithm for staggering windows does quite a good job.  It also is
  1531. ** quite gnarly.  Here's the deal:
  1532. ** There are pre-designated positions that we will try when positioning a
  1533. ** window.  These slots will be tried from the upper-left corner towards the
  1534. ** lower-right corner.  If there are other windows in that slot, then we will
  1535. ** consider that slot taken, and proceed to the next slot.  A slot is
  1536. ** determined to be taken by checking a point with a slop area.  This slop
  1537. ** area is diamond-shaped, not simply rectangular.  If there is no other
  1538. ** visible window with an upper-left corner within the slopt diamond, then
  1539. ** we are allowed to position our window there.
  1540. ** The above rule holds true unless this forces the window to be partly
  1541. ** off the screen.  If the window ends up partly off the screen, then we try
  1542. ** a new diagonal just below the first diagonal we tried.  We keep trying
  1543. ** lower and lower diagonals until we find a spot for the window, or the
  1544. ** diagonal doesn't fit on the screen at all.  If the diagonal doesn't fit,
  1545. ** then we try diagonals to the right of the first diagonal.  If even this
  1546. ** doesn't work, then we give up and put the window in the original spot
  1547. ** we tried. */
  1548.  
  1549. #pragma segment UtilMain
  1550. Rect    StaggerWindow(WindowPtr window, WindowPtr relatedWindow, Rect sizeInfo)
  1551. {
  1552.     WindowPtr    whichDevice, staggerFromWindow;
  1553.     Rect        deviceRect, oldWindowRect, newWindowRect, slot1;
  1554.     Rect        testRct1, testRct2, contentRect, staggerFromRect;
  1555.     Point        delta, absdelta;
  1556.     Boolean        contained, vertTry;
  1557.     short        diamondSize, diagNum, tryNum, h, v, hh, vv;
  1558.  
  1559.     if (!(whichDevice = relatedWindow))
  1560.         whichDevice = window;
  1561.             /* If we have a window to stagger from, use the device for that window,
  1562.             ** else use the device for the window that is getting staggered. */
  1563.  
  1564.     deviceRect = GetWindowDeviceRectNMB(whichDevice);
  1565.         /* We now have the rect of the device we want to stagger within. */
  1566.  
  1567.     if (!EmptyRect(&gWindowPlacementRect))
  1568.         deviceRect = gWindowPlacementRect;
  1569.  
  1570.     contentRect = GetWindowContentRect(window);        /* Get where the window is now. */
  1571.     h = hh = contentRect.right  - contentRect.left;
  1572.     v = vv = contentRect.bottom - contentRect.top;
  1573.     if (sizeInfo.left)
  1574.         if (h < sizeInfo.left)
  1575.             h = sizeInfo.left;
  1576.     if (sizeInfo.right)
  1577.         if (h > sizeInfo.right)
  1578.             h = sizeInfo.right;
  1579.     if (sizeInfo.top)
  1580.         if (v < sizeInfo.top)
  1581.             v = sizeInfo.top;
  1582.     if (sizeInfo.bottom)
  1583.         if (v > sizeInfo.bottom)
  1584.             v = sizeInfo.bottom;
  1585.     contentRect.right  = contentRect.left + h;
  1586.     contentRect.bottom = contentRect.top  + v;
  1587.  
  1588.     oldWindowRect = GetWindowStructureRect(window);
  1589.  
  1590.     newWindowRect.top    = deviceRect.top  + kStartPtV;
  1591.     newWindowRect.left   = deviceRect.left + kStartPtH;
  1592.     newWindowRect.bottom = newWindowRect.top  + oldWindowRect.bottom - oldWindowRect.top;
  1593.     newWindowRect.right  = newWindowRect.left + oldWindowRect.right  - oldWindowRect.left;
  1594.     newWindowRect.right  += (h - hh);
  1595.     newWindowRect.bottom += (v - vv);
  1596.         /* We now have a new rect for the first window position slot. */
  1597.  
  1598.     slot1 = newWindowRect;
  1599.         /* We keep this slot in case we find no acceptable slots.  If we
  1600.         ** don't find an acceptable one, we will use this one anyway. */
  1601.  
  1602.     diamondSize = (kStaggerH < kStaggerV) ? kStaggerH : kStaggerV;
  1603.     for (diagNum = 0, vertTry = true;;) {
  1604.         for (tryNum = 0;; ++tryNum) {
  1605.  
  1606.             SectRect(&newWindowRect, &deviceRect, &testRct1);
  1607.             if (!(contained = EqualRect(&newWindowRect, &testRct1))) break;
  1608.                 /* Break if the slot we are testing went off the device. */
  1609.  
  1610.             for (staggerFromWindow = FrontWindow(); staggerFromWindow;
  1611.                  staggerFromWindow = (WindowPtr)((WindowPeek)staggerFromWindow)->nextWindow) {
  1612.                 if (!((WindowPeek)staggerFromWindow)->visible) continue;
  1613.                     /* This window is invisible.  Staggering from an invisible
  1614.                     ** window is going to confuse the user, so don't do it. */
  1615.  
  1616.                 testRct1 = GetWindowDeviceRect(staggerFromWindow);
  1617.                 testRct2 = GetRectDeviceRect(deviceRect);
  1618.                 if (!EqualRect(&testRct1, &testRct2)) continue;
  1619.                     /* This window doesn't belong to the device we are trying to
  1620.                     ** stagger on, so skip it and go to the next window. */
  1621.  
  1622.                 staggerFromRect = GetWindowStructureRect(staggerFromWindow);
  1623.                 delta.v = staggerFromRect.top  - newWindowRect.top;
  1624.                 delta.h = staggerFromRect.left - newWindowRect.left;
  1625.                 if ((absdelta.v = delta.v) < 0)
  1626.                     absdelta.v = -delta.v;
  1627.                 if ((absdelta.h = delta.h) < 0)
  1628.                     absdelta.h = -delta.h;
  1629.                 if ((absdelta.h + absdelta.v) < diamondSize) {
  1630.                     if ((delta.h + delta.v) > 0)
  1631.                         OffsetRect(&newWindowRect, delta.h, delta.v);
  1632.                             /* If the window that took our slot is closer to
  1633.                             ** the lower-right corner than we are, then use
  1634.                             ** this window's location as the basis for the
  1635.                             ** slots from now on.  This will align new windows
  1636.                             ** with previous windows that are not gridded to
  1637.                             ** the default slot positions.  The check for > 0
  1638.                             ** is necessary to prevent bouncing between two
  1639.                             ** existing windows.  This check guarantees that
  1640.                             ** we are progressing with the evaluation. */
  1641.                     break;
  1642.                         /* Break because this slot is already used. */
  1643.                 }
  1644.             }
  1645.  
  1646.             if (!staggerFromWindow) break;
  1647.                 /* If the window pointer is nil, then we tried all the windows
  1648.                 ** and none of them occupied this slot.  This means that the
  1649.                 ** slot is available for the new window. */
  1650.  
  1651.                 OffsetRect(&newWindowRect, kStaggerH, kStaggerV);
  1652.                 /* Since this slot was taken, try the next slot and go through
  1653.                 ** the window list again. */
  1654.         }
  1655.  
  1656.         if (contained) break;
  1657.         newWindowRect = slot1;
  1658.         if (!tryNum) {
  1659.             if (!vertTry) break;        /* Nothing works.  No spots at all. */
  1660.             vertTry = false;            /* Try across for the next pass. */
  1661.             diagNum = 0;
  1662.         }
  1663.         ++diagNum;
  1664.         if (vertTry)
  1665.             OffsetRect(&newWindowRect, 0, diagNum * kStaggerV);
  1666.         else
  1667.             OffsetRect(&newWindowRect, diagNum * kStaggerH, 0);
  1668.     }
  1669.  
  1670.     OffsetRect(&contentRect, newWindowRect.left - oldWindowRect.left,
  1671.                             newWindowRect.top  - oldWindowRect.top);
  1672.         /* Calculate the new content rect. */
  1673.  
  1674.     MoveWindow(window, contentRect.left, contentRect.top, false);
  1675.         /* Move the window to the new location. */
  1676.  
  1677.     oldWindowRect = newWindowRect;
  1678.  
  1679.     if (newWindowRect.right > (deviceRect.right - 2))
  1680.         newWindowRect.right = (deviceRect.right - 2);
  1681.  
  1682.     if (newWindowRect.bottom > (deviceRect.bottom - 2))
  1683.         newWindowRect.bottom = (deviceRect.bottom - 2);
  1684.  
  1685.     h = newWindowRect.right  - oldWindowRect.right;
  1686.     v = newWindowRect.bottom - oldWindowRect.bottom;
  1687.  
  1688.     SizeWindow(window, contentRect.right  - contentRect.left + h,
  1689.                        contentRect.bottom - contentRect.top + v, false);
  1690.         /* The window may have also changed size, due to sizeInfo or not fitting on the screen. */
  1691.  
  1692.  
  1693.     return(contentRect);
  1694. }
  1695.  
  1696.  
  1697.  
  1698. /*****************************************************************************/
  1699.  
  1700.  
  1701.  
  1702. #pragma segment UtilMain
  1703. void    StandardAbout(short appNameStringID)
  1704. {
  1705.     StringHandle    apNameHndl;
  1706.     VersRecHndl        curVersion;
  1707.     Str255            apName;
  1708.     Str255            verNum = "\p????";
  1709.     Ptr                verNumLocation;
  1710.     OSErr            err;
  1711.  
  1712.     apNameHndl = (StringHandle)nil;
  1713.     if (appNameStringID != kUseRealAppName) {
  1714.         if (appNameStringID != kUseCreatorString)
  1715.             apNameHndl = GetString(appNameStringID);
  1716.         if (!apNameHndl)
  1717.             apNameHndl = (StringHandle)GetAppResource(gSignature, 0, &err);
  1718.     }
  1719.  
  1720.     if ((!apNameHndl) || (appNameStringID == kUseRealAppName))
  1721.         pcpy(apName, gAppName);
  1722.     else
  1723.         pcpy(apName, *apNameHndl);
  1724.  
  1725.     curVersion = (VersRecHndl) GetAppResource('vers', 1, &err);
  1726.     if (curVersion) {
  1727.         verNumLocation = (Ptr)((long)(*curVersion)->shortVersion +
  1728.                          (long)*(*curVersion)->shortVersion + 1);
  1729.         pcpy(verNum, (StringPtr)verNumLocation);
  1730.     }
  1731.  
  1732.     ParamText(apName, verNum, "\p", "\p");
  1733.  
  1734.     CenteredAlert(rStdAboutAlert, nil, nil);
  1735. }
  1736.  
  1737.  
  1738.  
  1739. /*****************************************************************************/
  1740.  
  1741.  
  1742.  
  1743. #pragma segment UtilMain
  1744. void    StandardInitialization(short callsToMoreMasters)
  1745. {
  1746.     InitToolBox();
  1747.  
  1748.     while (callsToMoreMasters--) MoreMasters();
  1749.  
  1750.     PullApplicationToFront();
  1751.     GetSystemInfo();
  1752. }
  1753.  
  1754.  
  1755.  
  1756. /*****************************************************************************/
  1757.  
  1758.  
  1759.  
  1760. #pragma segment UtilMain
  1761. void    StandardMenuSetup(short mbarID, short appleMenuID)
  1762. {
  1763.     Handle    mbar;
  1764.     short    i, id;
  1765.  
  1766.     mbar = GetNewMBar(mbarID);                            /* Read menus into menu bar. */
  1767.     if (!mbar) return;                                    /* Maybe we're faceless, so we're done. */
  1768.  
  1769.     SetMenuBar(mbar);                                    /* Install menus. */
  1770.     DisposeHandle(mbar);
  1771.     AppendResMenu(GetMenuHandle(appleMenuID), 'DRVR');    /* Add DA names to Apple menu. */
  1772.  
  1773.     mbar = GetResource('MBAR', mbarID);
  1774.     for (i = **(short **)mbar; i; --i) {
  1775.         mbar = GetResource('MBAR', mbarID);        /* Make sure it's in memory for dereference. */
  1776.         id   = (*(short **)mbar)[i];
  1777.         InsertHierMenus(GetMenuHandle(id));
  1778.     }
  1779.  
  1780.     DrawMenuBar();
  1781. }
  1782.  
  1783.  
  1784.  
  1785. /*****************************************************************************/
  1786.  
  1787.  
  1788.  
  1789. #pragma segment UtilMain
  1790. void    InsertHierMenus(MenuHandle menu)
  1791. {
  1792.     short        item, cmd, mark;
  1793.     MenuHandle    hier;
  1794.  
  1795.     for (item = CountMItems(menu); item; --item) {
  1796.         GetItemCmd(menu, item, &cmd);
  1797.         if (cmd == 0x1B) {
  1798.             GetItemMark(menu, item, &mark);
  1799.             hier = GetMenu(mark);
  1800.             if (hier) {
  1801.                 InsertMenu(hier, -1);
  1802.                 InsertHierMenus(hier);
  1803.             }
  1804.         }
  1805.     }
  1806. }
  1807.  
  1808.  
  1809.  
  1810. /*****************************************************************************/
  1811.  
  1812.  
  1813.  
  1814. /* Check to see if a given trap is implemented. */
  1815.  
  1816. #pragma segment UtilMain
  1817. Boolean TrapExists(short theTrap)
  1818. {
  1819.     TrapType    theTrapType;
  1820.  
  1821.     theTrapType = GetTrapType(theTrap);
  1822.     if ((theTrapType == ToolTrap) && ((theTrap &= 0x07FF) >= NumToolboxTraps()))
  1823.         theTrap = _Unimplemented;
  1824.  
  1825.     return(NGetTrapAddress(_Unimplemented, ToolTrap) != NGetTrapAddress(theTrap, theTrapType));
  1826. }
  1827.  
  1828.  
  1829.  
  1830. /*****************************************************************************/
  1831.  
  1832.  
  1833.  
  1834. /* Zoom the window to the size appropriate for the device that contains the
  1835. ** most of the window.  An additional feature is that you can state the
  1836. ** maximum that a window should be zoomed, either horizontally or vertically.
  1837. ** If you pass in a maximum of 0 for the zoom for either direction, then that
  1838. ** direction will be zoomed to fit the device. */
  1839.  
  1840. #pragma segment UtilMain
  1841. void    ZoomToWindowDevice(WindowPtr window, short maxWidth, short maxHeight,
  1842.                            short zoomDir, Boolean front)
  1843. {
  1844.      GrafPtr    oldPort;
  1845.     Rect    contentRect, structureRect, deviceRect, newRect;
  1846.     short    width, height, dx, dy;
  1847.  
  1848.     GetPort(&oldPort);
  1849.     SetPort(window);
  1850.     EraseRect(&window->portRect);         /* Recommended for cosmetic reasons. */
  1851.  
  1852.     /* If there is the possibility of multiple gDevices, then we must check them to
  1853.     ** make sure we are zooming onto the right display device when zooming out. */
  1854.  
  1855.     if (zoomDir == inZoomOut) {
  1856.  
  1857.         contentRect      = GetWindowContentRect(window);
  1858.         structureRect = GetWindowStructureRect(window);
  1859.         deviceRect      = GetWindowDeviceRectNMB(window);
  1860.  
  1861.         deviceRect.left   += (contentRect.left - structureRect.left + 2);
  1862.         deviceRect.top    += (contentRect.top - structureRect.top + 2);
  1863.         deviceRect.right  -= (structureRect.right - contentRect.right + 1);
  1864.         deviceRect.bottom -= (structureRect.bottom - contentRect.bottom + 1);
  1865.         newRect = deviceRect;
  1866.  
  1867.         if (maxWidth)
  1868.             if ((width = deviceRect.right - deviceRect.left) > maxWidth)
  1869.                 newRect.right = (newRect.left = contentRect.left) + maxWidth;
  1870.         if (maxHeight)
  1871.             if ((height = deviceRect.bottom - deviceRect.top) > maxHeight)
  1872.                 newRect.bottom = (newRect.top = contentRect.top) + maxHeight;
  1873.         if ((dx = deviceRect.left - newRect.left) < 0)
  1874.             if ((dx = deviceRect.right - newRect.right) > 0)
  1875.                 dx = 0;
  1876.         if ((dy = deviceRect.top - newRect.top) < 0)
  1877.             if ((dy = deviceRect.bottom - newRect.bottom) > 0)
  1878.                 dy = 0;
  1879.         OffsetRect(&newRect, dx, dy);
  1880.  
  1881.         (*(WStateDataHandle)(((WindowPeek)window)->dataHandle))->stdState = newRect;
  1882.             /* Set up the WStateData record for this window. */
  1883.     }
  1884.  
  1885.     ZoomWindow(window, zoomDir, front);
  1886.     SetPort(oldPort);
  1887. }
  1888.  
  1889.  
  1890.  
  1891. /*****************************************************************************/
  1892. /*****************************************************************************/
  1893. /*****************************************************************************/
  1894.  
  1895.  
  1896.  
  1897. #pragma segment UtilMain
  1898. void    DoDrawGrowIcon(WindowPtr window, Boolean horLine, Boolean verLine)
  1899. {
  1900.     WindowPtr    oldPort;
  1901.     Rect        rct;
  1902.     RgnHandle    oldClip, newClip;
  1903.  
  1904.     GetPort(&oldPort);
  1905.     SetPort(window);
  1906.  
  1907.     rct = window->portRect;
  1908.     rct.left = rct.right  - 15;
  1909.     rct.top  = rct.bottom - 15;
  1910.  
  1911.     if (!((WindowPeek)window)->hilited) {
  1912.         FrameRect(&rct);
  1913.         ++rct.top;
  1914.         ++rct.left;
  1915.         EraseRect(&rct);
  1916.         SetPort(oldPort);
  1917.         return;
  1918.     }
  1919.  
  1920.     oldClip = NewRgn();
  1921.     newClip = NewRgn();
  1922.  
  1923.     if (horLine)
  1924.         rct.left = window->portRect.left;
  1925.     if (verLine)
  1926.         rct.top  = window->portRect.top;
  1927.     RectRgn(newClip, &rct);
  1928.  
  1929.     GetClip(oldClip);
  1930.     SetClip(newClip);
  1931.     DrawGrowIcon(window);        /* Draw grow icon without scrollbar lines. */
  1932.  
  1933.     SetClip(oldClip);
  1934.     DisposeRgn(oldClip);
  1935.     DisposeRgn(newClip);
  1936.  
  1937.     SetPort(oldPort);
  1938. }
  1939.  
  1940.  
  1941.  
  1942. /*****************************************************************************/
  1943.  
  1944.  
  1945.  
  1946. /* This is used to "intelligently" insert a menu item into a menu.  Pass it
  1947. ** the menu to be modified, the text of the item being added, plus where the
  1948. ** item is to be inserted.  The location to be inserted is described by two
  1949. ** parameters:  section & where.
  1950. **
  1951. ** section:  Indicates which group of menu items you wish to add an item to.
  1952. **           Menu item section 1 is all of the items before the first
  1953. **           dividing line.  Menu item section 2 is all items after the
  1954. **           first dividing line and before the second, and so on.  If you
  1955. **           have no dividing lines, you have just 1 section so pass in 1.
  1956. **
  1957. ** where:    Indicates the item position relative to the section.  To add an
  1958. **           item such that it is the first item in a section, pass in a 1.
  1959. **           It will be added in front of the first item in the section.
  1960. **
  1961. **           NOTE:  You should never pass in a section or where parameter of 0.
  1962. **
  1963. ** Negative values for "where" are magic.  If where = kMenuItemTxtInsert, then
  1964. ** it inserts the item alphabetically into the section.  A where of
  1965. ** kMenuItemNumInsert works the same as kMenuItemTxtInsert, except it treats
  1966. ** the strings are numbers for comparison purposes.  If you want to add the
  1967. ** item to the end of a section, use kMenuItemSectionEnd.
  1968. **
  1969. ** As a final goodie, SmartInsMenuItem returns the menu item # from the
  1970. ** beginning of the menu, not section.
  1971. */
  1972.  
  1973. #pragma segment UtilMain
  1974. short    SmartInsMenuItem(MenuHandle theMenu, StringPtr theText, short section, short where)
  1975. {
  1976.     short    numItems, base, i;
  1977.     short    insertType, val;
  1978.     Str255    cmpTxt, txt;
  1979.  
  1980.     numItems = CountMItems(theMenu);    /* Total number of items in menu. */
  1981.  
  1982.     if (--section < 0)
  1983.         section = 0;                    /* We want section 0-based. */
  1984.  
  1985.     for (base = 0, i = 1; (section) && (i <= numItems); ++i) {
  1986.         GetMenuItemText(theMenu, base + i, txt);
  1987.         if (txt[1] == '-') {
  1988.             base = i;
  1989.             --section;
  1990.         }
  1991.     }        /* base now tells us our section starting offset. */
  1992.  
  1993.     if (where < 0) {        /* If magic mode... */
  1994.  
  1995.         InsertMenuItem(theMenu, theText, 0);            /* Take out meta characters */
  1996.         GetMenuItemText(theMenu, 1, cmpTxt);            /* for comparison purposes. */
  1997.         DeleteMenuItem(theMenu, 1);
  1998.  
  1999.         insertType = where;
  2000.         val = p2num(cmpTxt, 10, nil);
  2001.  
  2002.         for (where = 1; i <= (numItems - base); ++where) {
  2003.             GetMenuItemText(theMenu, where + base, txt);
  2004.             if (txt[1] == '-') break;
  2005.             if ((insertType == kMenuItemTxtInsert) && ((IUCompString(cmpTxt, txt) < 0))) break;
  2006.             if ((insertType == kMenuItemNumInsert) && (val < p2num(txt, 10, nil)))       break;
  2007.         }
  2008.     }
  2009.  
  2010.     where += base;
  2011.     InsertMenuItem(theMenu, theText, where - 1);        /* InsMenuItem does an insert-after. */
  2012.  
  2013.     return(where);
  2014. }
  2015.  
  2016.  
  2017.  
  2018. /*****************************************************************************/
  2019.  
  2020.  
  2021.  
  2022. #pragma segment UtilMain
  2023. short    CountMSections(MenuHandle theMenu)
  2024. {
  2025.     short    numItems, numSections, i;
  2026.     Str255    txt;
  2027.  
  2028.     numItems = CountMItems(theMenu);    /* Total number of items in menu. */
  2029.  
  2030.     for (numSections = i = 1; i <= numItems; ++i) {
  2031.         GetMenuItemText(theMenu, i, txt);
  2032.         if (txt[1] == '-')
  2033.             ++numSections;
  2034.     }
  2035.  
  2036.     return(numSections);
  2037. }
  2038.  
  2039.  
  2040.  
  2041. /*****************************************************************************/
  2042.  
  2043.  
  2044.  
  2045. #pragma segment UtilMain
  2046. short    FindMenuItem(MenuHandle theMenu, StringPtr cmpTxt)
  2047. {
  2048.     short    item;
  2049.     Str255    txt;
  2050.  
  2051.     for (item = CountMItems(theMenu); item; --item) {
  2052.         GetMenuItemText(theMenu, item, txt);
  2053.         if (!IUCompString(cmpTxt, txt)) break;
  2054.     }
  2055.  
  2056.     return(item);
  2057. }
  2058.  
  2059.  
  2060.  
  2061. /*****************************************************************************/
  2062.  
  2063.  
  2064.  
  2065. #pragma segment UtilMain
  2066. OSErr    PersistFSSpec(PFSSpecPtr pfss)
  2067. {
  2068.     OSErr            err;
  2069.     HParamBlockRec    pb;
  2070.     char            delim;
  2071.  
  2072.     SetMem(&pb, 0, sizeof(HParamBlockRec));        /* Make us a happy ParamBlock. */
  2073.     pb.volumeParam.ioNamePtr = pfss->volName;
  2074.  
  2075.     if (!(pfss->fss.name[0])) {                /* If no file name, then there's no file. */
  2076.         pfss->volName[0] = 0;                /* Zap all remnants of file specification. */
  2077.         pfss->fss.vRefNum = 0;
  2078.         return(noErr);
  2079.     }
  2080.  
  2081.     pb.volumeParam.ioVRefNum = pfss->fss.vRefNum;
  2082.     if (pb.volumeParam.ioVRefNum) {
  2083.         pfss->volName[0] = 0;    /* If we are passed in a vRefNum, then we are
  2084.                                 ** wanting the volume name.  This is what we are
  2085.                                 ** looking to get, so show it as currently missing. */
  2086.         err = PBHGetVInfo(&pb, false);
  2087.     }
  2088.     else {
  2089.         if (!(pfss->volName[0])) return(noErr);
  2090.  
  2091.         pb.volumeParam.ioVolIndex = -1;        /* Use the name to find the vRefNum. */
  2092.         delim = (gAUXVersion) ? '/' : ':';
  2093.         if (pfss->volName[pfss->volName[0]] != delim)
  2094.             pfss->volName[++(pfss->volName[0])] = delim;
  2095.                 /* Make sure that volume name ends with a delimiter. */
  2096.  
  2097.         if (!(err = PBHGetVInfo(&pb, false)))
  2098.             pfss->fss.vRefNum = pb.volumeParam.ioVRefNum;
  2099.     }
  2100.  
  2101.     return(err);
  2102. }
  2103.  
  2104.  
  2105.  
  2106. /*****************************************************************************/
  2107.  
  2108.  
  2109.  
  2110. #pragma segment UtilMain
  2111. StringPtr    PathNameFromDirID(long dirID, short vRefNum, StringPtr str)
  2112. {
  2113.     CInfoPBRec    block;
  2114.     Str255        directoryName;
  2115.  
  2116.     *str = 0;
  2117.     block.dirInfo.ioNamePtr = directoryName;
  2118.     block.dirInfo.ioDrParID = dirID;
  2119.  
  2120.     do {
  2121.         block.dirInfo.ioVRefNum   = vRefNum;
  2122.         block.dirInfo.ioFDirIndex = -1;
  2123.         block.dirInfo.ioDrDirID   = block.dirInfo.ioDrParID;
  2124.  
  2125.         if (PBGetCatInfo(&block, false)) {
  2126.             *str = 0;
  2127.             break;
  2128.         }
  2129.  
  2130.         if (gAUXVersion) {
  2131.             if (directoryName[1] != '/')
  2132.                 pcat(directoryName, "\p/");
  2133.                     /* If this isn't root (i.e. '/'), append a slash ('/'). */
  2134.         } else pcat(directoryName, "\p:");
  2135.             /* Append a Macintosh style colon (':'). */
  2136.  
  2137.         pcat(directoryName, str);
  2138.         pcpy(str, directoryName);
  2139.  
  2140.     } while (block.dirInfo.ioDrDirID != fsRtDirID);
  2141.  
  2142.     return(str);
  2143. }
  2144.  
  2145.  
  2146.  
  2147. /*****************************************************************************/
  2148.  
  2149.  
  2150.  
  2151. #pragma segment UtilMain
  2152. void    InitQuickTime(void)
  2153. {
  2154.     ComponentDescription    controllerDescriptor;
  2155. #ifdef powerc
  2156.     long                    qtFeatures;
  2157. #endif
  2158.  
  2159.     if (!gQTVersion) {
  2160.         if (!(Gestalt(gestaltQuickTime, &gQTVersion))) {
  2161. #ifdef powerc
  2162.             if ((!(Gestalt (gestaltQuickTimeFeatures, &qtFeatures)) &&
  2163.                 (qtFeatures & (1 << gestaltPPCQuickTimeLibPresent))))
  2164. #endif
  2165.                 if (EnterMovies())
  2166.                     gQTVersion = 0;
  2167.                 else {
  2168.                     controllerDescriptor.componentType         = 'play';
  2169.                     controllerDescriptor.componentSubType      = 0;
  2170.                     controllerDescriptor.componentManufacturer = 0;
  2171.                     controllerDescriptor.componentFlags        = 0;
  2172.                     controllerDescriptor.componentFlagsMask    = 0;
  2173.                     gMovieControllerComponent = FindNextComponent((Component)0, &controllerDescriptor);
  2174.             }
  2175.         }
  2176.     }
  2177. }
  2178.  
  2179.  
  2180.  
  2181. /*****************************************************************************/
  2182.  
  2183.  
  2184.  
  2185. #pragma segment Controls
  2186. RgnHandle    LocalScreenDepthRegion(short depth)
  2187. {
  2188.     RgnHandle    retRgn;
  2189.     GrafPtr        oldPort;
  2190.     Point        pt;
  2191.  
  2192.     retRgn = ScreenDepthRegion(depth);
  2193.     if (gScreenPort) {
  2194.         GetPort(&oldPort);
  2195.         SetPort(gScreenPort);
  2196.     }
  2197.  
  2198.     pt.h = pt.v = 0;
  2199.     GlobalToLocal(&pt);
  2200.     OffsetRgn(retRgn, pt.h, pt.v);
  2201.  
  2202.     if (gScreenPort) SetPort(oldPort);
  2203.     return(retRgn);
  2204. }
  2205.  
  2206.  
  2207.  
  2208. /*****************************************************************************/
  2209. /*****************************************************************************/
  2210. /*****************************************************************************/
  2211.  
  2212.  
  2213.  
  2214. #pragma segment Controls
  2215. pascal Boolean    AlertFilter(DialogPtr dlg, EventRecord *event, short *item)
  2216. {
  2217.     short    what, theChr, theMod, handled;
  2218.  
  2219.     what = event->what;
  2220.     if (event->what == keyDown) {
  2221.         theChr = event->message   & charCodeMask;
  2222.         theMod = event->modifiers & keyCodeMask;
  2223.         if ((theChr != 0x0D) && (theChr != 0x03))
  2224.             event->what = nullEvent;
  2225.         if (theMod & (cmdKey + optionKey + controlKey))
  2226.             event->what = nullEvent;
  2227.     }
  2228.     handled = KeyEquivFilter(dlg, event, item);
  2229.     event->what = what;
  2230.     return(handled);
  2231. }
  2232.  
  2233.  
  2234.  
  2235. /*****************************************************************************/
  2236.  
  2237.  
  2238.  
  2239. /* This code expects the key equivalents to be in item #2, which is a StatText
  2240. ** item that is located so the text is outside of the dialog.  This allows us
  2241. ** to put key equivalent information in the resource fork, so the key
  2242. ** equivalents are localizable.
  2243. **
  2244. ** An example save changes before closing or quitting res source with
  2245. ** keyEquiv info would look like:
  2246. **
  2247. ** resource 'DITL' (rYesNoCancel, purgeable) {
  2248. **     {
  2249. **         {71, 315, 91, 367}, Button     { enabled, "Save" },
  2250. **         {0, -1000, 20, 2},  StaticText { disabled,
  2251. **             "=S190001,=s190001,=D190003,=d190003,=.190104,1B190004" },
  2252. **         {71, 80, 91, 162},  Button { enabled, "Don’t Save" },
  2253. **         {71, 244, 91, 302}, Button { enabled, "Cancel" },
  2254. **         {11, 78, 61, 366},  StaticText { disabled,
  2255. **             "Save changes to the document “^0” before ^1?" },
  2256. **         {11, 23, 43, 55},        Icon { disabled, 2 }
  2257. **     }
  2258. ** };
  2259. **
  2260. ** The document name would be the string for param #0.
  2261. ** The text "closing" or "quitting" would be the string for param #1.
  2262. **
  2263. ** The keyEquiv entry is item #2, which has a rect that pushes it out of the
  2264. ** dialog.  The string info is interpreted as to what the key/modifier combo
  2265. ** is, and what dialog item it relates to.
  2266. **
  2267. ** A single key equiv entry is 8 characters.  Entries are separated by commas.
  2268. **
  2269. ** If the first character of an entry is an =, then the next character is the
  2270. ** key.  If the first character isn't an =, then the first two characters are
  2271. ** the hex value of the key.  (Ex:  =S or =s for save, 1B for ESC.)
  2272. **
  2273. ** If the key pressed is the same as the key value for any of the entries, then
  2274. ** the next two characters are the hex value for which modifiers to test.  This
  2275. ** modifier test value is anded with the modifier.  The result is then compared
  2276. ** to the value of the next two hex digits.  If they are equal, then the
  2277. ** modifiers are correct, as well as the key.  If this is so, we have a winner.
  2278. **
  2279. ** "=S190001,=s190001,=D190003,=d190003,=.190104,1B190004"
  2280. **
  2281. ** The above string breaks down as follows:
  2282. ** =S190001  =S  if event keypress is an S, check the modifier values
  2283. **           19  check controlKey/optionKey/cmdKey
  2284. **           00  all modifiers we are testing for should be false
  2285. **           01  if above is true, keypress maps to item # 1
  2286. ** =s190001  Same as =S, but lowercase
  2287. ** =D190001  Same as =S, but maps to item #3
  2288. ** =d190001  Same as =D, but lowercase
  2289. ** =.190104  =.  if event keypress is a period, check the modifier values
  2290. **           19  check controlKey/optionKey/cmdKey
  2291. **           01  controlKey/optionKey should be false, cmdKey should be true
  2292. **           04  if above is true, keypress maps to item # 4
  2293. ** 1B190004  1B  if event keypress is an ESC, check the modifier values
  2294. **           19  check controlKey/optionKey/cmdKey
  2295. **           00  all modifiers we are testing for should be false
  2296. **           04  if above is true, keypress maps to item # 4
  2297. */
  2298.  
  2299. #pragma segment Controls
  2300. pascal Boolean    KeyEquivFilter(DialogPtr dlg, EventRecord *event, short *item)
  2301. {
  2302.     short    itemType;
  2303.     Handle    itemHndl;
  2304.     Rect    itemRect;
  2305.     Str255    itemText;
  2306.     short    i, theChr, cc, theMod, equivChr, modMask, modVal, itemNum;
  2307.  
  2308.     if (event->what == updateEvt) {
  2309.         if (dlg == (DialogPtr)event->message)
  2310.             OutlineDialogItem(dlg, 1);
  2311.         return(false);
  2312.     }
  2313.  
  2314.     if (event->what != keyDown) return(false);
  2315.  
  2316.     itemNum = 0;
  2317.  
  2318.     theChr = event->message   & charCodeMask;
  2319.     theMod = event->modifiers & keyCodeMask;
  2320.  
  2321.     if ((theChr == 0x0D) || (theChr == 0x03)) {        /* If return or enter... */
  2322.         if (!(theMod & (cmdKey + optionKey + controlKey))) {
  2323.             *item = 1;
  2324.             return(true);
  2325.         }
  2326.     }
  2327.  
  2328.     GetDialogItem(dlg, 2, &itemType, &itemHndl, &itemRect);
  2329.     if (itemHndl) {
  2330.         GetDialogItemText(itemHndl, itemText);
  2331.         for (i = 1; i <= *itemText; i += 9) {
  2332.             cc = theChr;
  2333.             if (itemText[i] == (unsigned char)'≈')
  2334.                 if ((cc >= 'a') && (cc <= 'z')) cc -= 32;
  2335.             equivChr = GetHexByte((char *)(itemText + i));
  2336.             modMask  = GetHexByte((char *)(itemText + i + 2)) << 8;
  2337.             modVal   = GetHexByte((char *)(itemText + i + 4)) << 8;
  2338.             itemNum  = GetHexByte((char *)(itemText + i + 6));
  2339.             if (cc == equivChr)
  2340.                 if ((theMod & modMask) == modVal) break;
  2341.             itemNum = 0;
  2342.         }
  2343.     }
  2344.  
  2345.     if (itemNum) {
  2346.         GetDialogItem(dlg, itemNum, &itemType, &itemHndl, &itemRect);
  2347.         SelectButton((ControlHandle)itemHndl);
  2348.         *item = itemNum;
  2349.         return(true);
  2350.     }
  2351.  
  2352.     return(false);
  2353. }
  2354.  
  2355.  
  2356.  
  2357. /*****************************************************************************/
  2358. /*****************************************************************************/
  2359. /*****************************************************************************/
  2360.  
  2361.  
  2362.  
  2363. /* This function returns which kind of button the control is.  This does more
  2364. ** than GetCVariant in that it makes sure that the control is actually a
  2365. ** button.  It does this by comparing the defProc against the known defProc
  2366. ** for the various button types.  For 7.0, there is only one defProc for all
  2367. ** variants, but for pre-7.0, there is one defProc value for each variant.
  2368. ** The method below handles either case. */
  2369.  
  2370. #pragma segment Controls
  2371. short    GetButtonVariant(ControlHandle ctl)
  2372. {
  2373.     short            i;
  2374.     Boolean            stop;
  2375.     Rect            dummy;
  2376.     ControlHandle    dummyCtl;
  2377.  
  2378.     if (ctl) {
  2379.  
  2380.         if (gGetButtonVariant) {
  2381.             stop = false;
  2382.             i = (*gGetButtonVariant)(ctl, &stop);
  2383.             if (i >= 0) return(i);
  2384.             if (stop)   return(-1);
  2385.         }
  2386.  
  2387.         for (i = pushButProc; i <= radioButProc + useWFont; ++i) {
  2388.             if (i == radioButProc + 1)
  2389.                 i = pushButProc + useWFont;
  2390.             if (!gButtonProcs[i]) {
  2391.                 SetRect(&dummy, 0, 0, 0, 0);
  2392.                 dummyCtl = NewControl((*ctl)->contrlOwner, &dummy, (ConstStr255Param)"\p",
  2393.                                       false, 1, 0, 1, i, 0L);
  2394.                 if (dummyCtl) {
  2395.                     gButtonProcs[i] = (*dummyCtl)->contrlDefProc;
  2396.                     DisposeControl(dummyCtl);
  2397.                 }
  2398.             }
  2399.             if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gButtonProcs[i]))
  2400.                 return(GetControlVariant(ctl) & (0xFFFF - useWFont));
  2401.                     /* The handle may be locked, which means that the hi-bit
  2402.                     ** may be on, thus invalidating the compare.  Dereference the
  2403.                     ** handles to get rid of this possibility. */
  2404.         }
  2405.     }
  2406.  
  2407.     return(-1);
  2408. }
  2409.  
  2410.  
  2411.  
  2412. /*****************************************************************************/
  2413.  
  2414.  
  2415.  
  2416. #pragma segment Controls
  2417. Boolean GetCheckOrRadio(DialogPtr dlgPtr, short itemNo)
  2418. {
  2419.     short    iKind;
  2420.     Handle    iHandle;
  2421.     Rect    iRect;
  2422.  
  2423.     GetDialogItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  2424.     return(GetControlValue((ControlHandle)iHandle) != 0);
  2425. }
  2426.  
  2427.  
  2428.  
  2429. /*****************************************************************************/
  2430.  
  2431.  
  2432.  
  2433. #pragma segment Controls
  2434. Boolean    IsScrollBar(ControlHandle ctl)
  2435. {
  2436.     Rect            dummy;
  2437.     ControlHandle    dummyCtl;
  2438.  
  2439.     if (!ctl) return(false);
  2440.  
  2441.     if (!gScrollProc) {
  2442.         SetRect(&dummy, 0, 0, 16, 100);
  2443.         dummyCtl = NewControl((*ctl)->contrlOwner, &dummy, (ConstStr255Param)"\p",
  2444.                               false, 1, 0, 1, scrollBarProc, 0L);
  2445.         if (dummyCtl) {
  2446.             gScrollProc = (*dummyCtl)->contrlDefProc;
  2447.             DisposeControl(dummyCtl);
  2448.         }
  2449.     }
  2450.  
  2451.     return(StripAddress((*ctl)->contrlDefProc) == StripAddress(gScrollProc));
  2452.         /* The handle may be locked, which means that the hi-bit
  2453.         ** may be on, thus invalidating the compare.  Dereference the
  2454.         ** handles to get rid of this possibility. */
  2455. }
  2456.  
  2457.  
  2458.  
  2459. /*****************************************************************************/
  2460.  
  2461.  
  2462.  
  2463. #pragma segment Controls
  2464. void    MoveStyledControl(ControlHandle ctl, short xloc, short yloc)
  2465. {
  2466.     char    vv, hh;
  2467.  
  2468.     if (GetControlValue(ctl) == 1) {
  2469.         if (GetButtonVariant(ctl) == pushButProc) {
  2470.             hh = (*ctl)->contrlHilite;
  2471.             (*ctl)->contrlHilite = 1;        /* Force outline off. */
  2472.             OutlineControl(ctl);
  2473.             (*ctl)->contrlHilite = hh;
  2474.         }
  2475.     }
  2476.  
  2477.     vv = (*ctl)->contrlVis;
  2478.     HideStyledControl(ctl);
  2479.     MoveControl(ctl, xloc, yloc);
  2480.     (*ctl)->contrlVis = vv;
  2481.  
  2482.     DoDraw1Control(ctl, false);
  2483. }
  2484.  
  2485.  
  2486.  
  2487. /*****************************************************************************/
  2488.  
  2489.  
  2490.  
  2491. #pragma segment Controls
  2492. void    SizeStyledControl(ControlHandle ctl, short xsize, short ysize)
  2493. {
  2494.     char    vv, hh;
  2495.  
  2496.     if (GetControlValue(ctl) == 1) {
  2497.         if (GetButtonVariant(ctl) == pushButProc) {
  2498.             hh = (*ctl)->contrlHilite;
  2499.             (*ctl)->contrlHilite = 1;        /* Force outline off. */
  2500.             OutlineControl(ctl);
  2501.             (*ctl)->contrlHilite = hh;
  2502.         }
  2503.     }
  2504.  
  2505.     vv = (*ctl)->contrlVis;
  2506.     HideStyledControl(ctl);
  2507.     SizeControl(ctl, xsize, ysize);
  2508.     (*ctl)->contrlVis = vv;
  2509.  
  2510.     DoDraw1Control(ctl, false);
  2511. }
  2512.  
  2513.  
  2514.  
  2515. /*****************************************************************************/
  2516.  
  2517.  
  2518.  
  2519. #pragma segment Controls
  2520. void    SetStyledCtlValue(ControlHandle ctl, short value)
  2521. {
  2522.     char    hh;
  2523.  
  2524.     if (value < (*ctl)->contrlMin) value = (*ctl)->contrlMin;    /* Don't let it draw on its own. */
  2525.     if (value > (*ctl)->contrlMax) value = (*ctl)->contrlMax;
  2526.     if ((*ctl)->contrlValue != value) {
  2527.         (*ctl)->contrlValue  = value;
  2528.         DoDraw1Control(ctl, false);        /* This routine does the right thing for popups. */
  2529.     }
  2530.  
  2531.     if (GetButtonVariant(ctl) == pushButProc) {
  2532.         if (!value) {
  2533.             hh = (*ctl)->contrlHilite;
  2534.             (*ctl)->contrlHilite = 1;        /* Force outline off. */
  2535.             OutlineControl(ctl);
  2536.             (*ctl)->contrlHilite = hh;
  2537.         }
  2538.         else
  2539.             OutlineControl(ctl);
  2540.     }
  2541. }
  2542.  
  2543.  
  2544.  
  2545. /*****************************************************************************/
  2546.  
  2547.  
  2548.  
  2549. #pragma segment Controls
  2550. void    ShowStyledControl(ControlHandle ctl)
  2551. {
  2552.     Boolean        didPopup;
  2553.     WindowPtr    oldPort, window;
  2554.     RgnHandle    oldClip, newClip;
  2555.     Point        org;
  2556.     Rect        srct;
  2557.  
  2558.     if (!(*ctl)->contrlVis) {
  2559.  
  2560.         didPopup = false;
  2561.         if (gPopupProc) {        /* The popup control does not handle negative coords. */
  2562.             if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gPopupProc)) {
  2563.                 didPopup = true;
  2564.                 GetPort(&oldPort);
  2565.                 SetPort(window = (*ctl)->contrlOwner);
  2566.                 GetClip(oldClip = NewRgn());    /* We draw it once, so that internals   */
  2567.                 SetRect(&srct, 0, 0, 0, 0);        /* are fixed up.  We don't want to show */
  2568.                 ClipRect(&srct);                /* a flash though. */
  2569.  
  2570.                 RectRgn(newClip = NewRgn(), &(window->portRect));
  2571.                 org.h = window->portRect.left;
  2572.                 org.v = window->portRect.top;
  2573.                 SetOrigin(0, 0);
  2574.  
  2575.                 UseControlStyle(ctl);
  2576.                 OffsetRect(&((*ctl)->contrlRect), -org.h, -org.v);    /* Completely clipped out. */
  2577.                 ShowControl(ctl);                                    /* Just to fix internals.  */
  2578.                 Draw1Control(ctl);
  2579.  
  2580.                 SectRgn(newClip, oldClip, newClip);
  2581.                 OffsetRgn(newClip, -org.h, -org.v);
  2582.                 SetClip(newClip);
  2583.                 Draw1Control(ctl);                /* Now really show it. */
  2584.                 UseControlStyle(nil);
  2585.  
  2586.                 OffsetRect(&((*ctl)->contrlRect), org.h, org.v);
  2587.                 SetOrigin(org.h, org.v);
  2588.                 SetClip(oldClip);
  2589.                 DisposeRgn(newClip);
  2590.                 DisposeRgn(oldClip);
  2591.  
  2592.                 SetPort(oldPort);
  2593.             }
  2594.         }
  2595.  
  2596.         if (!didPopup) {
  2597.             (*ctl)->contrlVis = 255;
  2598.             DoDraw1Control(ctl, false);
  2599.         }
  2600.     }
  2601. }
  2602.  
  2603.  
  2604.  
  2605. /*****************************************************************************/
  2606.  
  2607.  
  2608.  
  2609. #pragma segment Controls
  2610. void    HideStyledControl(ControlHandle ctl)
  2611. {
  2612.     char        hh;
  2613.     Boolean        didPopup;
  2614.     WindowPtr    oldPort, window;
  2615.     RgnHandle    oldClip, newClip;
  2616.     Point        org;
  2617.     Rect        srct;
  2618.  
  2619.     if (!(*ctl)->contrlVis) return;
  2620.  
  2621.     if (GetButtonVariant(ctl) == pushButProc) {
  2622.         if (GetControlValue(ctl) == 1) {
  2623.             hh = (*ctl)->contrlHilite;
  2624.             (*ctl)->contrlHilite = 1;        /* Force outline off. */
  2625.             OutlineControl(ctl);
  2626.             (*ctl)->contrlHilite = hh;
  2627.             if ((*ctl)->contrlVis) {
  2628.                 GetPort(&oldPort);
  2629.                 SetPort(window = (*ctl)->contrlOwner);
  2630.                 srct = (*ctl)->contrlRect;
  2631.                 InsetRect(&srct, kButtonFrameInset, kButtonFrameInset);
  2632.                 InvalRect(&srct);
  2633.                 SetPort(oldPort);
  2634.             }
  2635.         }
  2636.     }
  2637.  
  2638.     didPopup = false;
  2639.     if (gPopupProc) {        /* The popup control does not handle negative coords. */
  2640.         if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gPopupProc)) {
  2641.             didPopup = true;
  2642.             GetPort(&oldPort);
  2643.             SetPort(window = (*ctl)->contrlOwner);
  2644.             GetClip(oldClip = NewRgn());    /* We draw it once, so that internals   */
  2645.             SetRect(&srct, 0, 0, 0, 0);        /* are fixed up.  We don't want to show */
  2646.             ClipRect(&srct);                /* a flash though. */
  2647.  
  2648.             RectRgn(newClip = NewRgn(), &(window->portRect));
  2649.             org.h = window->portRect.left;
  2650.             org.v = window->portRect.top;
  2651.             SetOrigin(0, 0);
  2652.  
  2653.             OffsetRect(&((*ctl)->contrlRect), -org.h, -org.v);    /* Completely clipped out. */
  2654.             Draw1Control(ctl);                                    /* Just to fix internals.  */
  2655.  
  2656.             SectRgn(newClip, oldClip, newClip);
  2657.             OffsetRgn(newClip, -org.h, -org.v);
  2658.             SetClip(newClip);
  2659.             HideControl(ctl);                /* Now really hide it. */
  2660.  
  2661.             OffsetRect(&((*ctl)->contrlRect), org.h, org.v);
  2662.             SetOrigin(org.h, org.v);
  2663.             SetClip(oldClip);
  2664.             DisposeRgn(newClip);
  2665.             DisposeRgn(oldClip);
  2666.  
  2667.             SetPort(oldPort);
  2668.         }
  2669.     }
  2670.  
  2671.     if (!didPopup) HideControl(ctl);
  2672. }
  2673.  
  2674.  
  2675.  
  2676. /*****************************************************************************/
  2677.  
  2678.  
  2679.  
  2680. #pragma segment Controls
  2681. void    OffsetControl(ControlHandle ctl, short dx, short dy)
  2682. {
  2683.     Rect    ctlRect;
  2684.  
  2685.     ctlRect = (*ctl)->contrlRect;
  2686.     MoveStyledControl(ctl, ctlRect.left + dx, ctlRect.top + dy);
  2687. }
  2688.  
  2689.  
  2690.  
  2691. /*****************************************************************************/
  2692.  
  2693.  
  2694.  
  2695. /* Given any control handle, this will draw an outline around it.  This is used
  2696. ** for the default button of a window.  The extra nice feature here is that
  2697. ** I’ll erase the outline for buttons that are inactive.  Seems like there
  2698. ** should be a Toolbox call for getting a control’s hilite state.  Since there
  2699. ** isn’t, I have to look into the control record myself.  This should be called
  2700. ** for update and activate events.
  2701. **
  2702. ** The method for determining the oval diameters for the roundrect is a little
  2703. ** different than that recommended by Inside Mac. IM I-407 suggests that you
  2704. ** use a hardcoded (16,16) for the diameters.  However, this only looks good
  2705. ** for small roundrects.  For larger ones, the outline doesn’t follow the inner
  2706. ** roundrect because the CDEF for simple buttons doesn’t use (16,16).  Instead,
  2707. ** it uses half the height of the button as the diameter.  By using this
  2708. ** formula, too, our outlines look better. */
  2709.  
  2710. #pragma segment Controls
  2711. void    OutlineControl(ControlHandle button)
  2712. {
  2713.     WindowPtr    oldPort;
  2714.     Rect        theRect;
  2715.     PenState    curPen;
  2716.     short        buttonOval;
  2717.     RgnHandle    oldClip, newClip;
  2718.     RGBColor    oldrgb;
  2719.  
  2720.     static RGBColor    whitergb = {0xFFFF, 0xFFFF, 0xFFFF};
  2721.     static RGBColor    grayrgb  = {0x8000, 0x8000, 0x8000};
  2722.     static RGBColor    blackrgb = {0x0000, 0x0000, 0x0000};
  2723.  
  2724.     if (button) {
  2725.         if ((*button)->contrlVis) {
  2726.             GetPort(&oldPort);
  2727.             SetPort((*button)->contrlOwner);
  2728.             GetPenState(&curPen);
  2729.             PenNormal();
  2730.             PenSize(kButtonFrameSize, kButtonFrameSize);
  2731.  
  2732.             theRect = (*button)->contrlRect;
  2733.             InsetRect(&theRect, kButtonFrameInset, kButtonFrameInset);
  2734.             buttonOval = (theRect.bottom - theRect.top) / 2 + 2;
  2735.  
  2736.             GetClip(oldClip = NewRgn());
  2737.             newClip = LocalScreenDepthRegion(4);
  2738.             SectRgn(oldClip, newClip, newClip);
  2739.             SetClip(newClip);
  2740.  
  2741.             if (!EmptyRgn(newClip)) {
  2742.                 GetForeColor(&oldrgb);
  2743.                 switch ((*button)->contrlHilite) {
  2744.                     case kCntlActivate:
  2745.                         RGBForeColor(&blackrgb);
  2746.                         break;
  2747.                     case kCntlDeactivate:
  2748.                         RGBForeColor(&grayrgb);
  2749.                         break;
  2750.                     default:
  2751.                         RGBForeColor(&whitergb);
  2752.                         break;
  2753.                 }
  2754.                 FrameRoundRect(&theRect, buttonOval, buttonOval);
  2755.                 RGBForeColor(&oldrgb);
  2756.             }
  2757.  
  2758.             DiffRgn(oldClip, newClip, newClip);
  2759.             SetClip(newClip);
  2760.             if (!EmptyRgn(newClip)) {
  2761.                 switch ((*button)->contrlHilite) {
  2762.                     case kCntlActivate:
  2763.                         PenPat((ConstPatternParam)&qd.black);
  2764.                         break;
  2765.                     case kCntlDeactivate:
  2766.                         PenPat((ConstPatternParam)&qd.gray);
  2767.                         break;
  2768.                     default:
  2769.                         PenPat((ConstPatternParam)&qd.white);
  2770.                         break;
  2771.                 }
  2772.                 FrameRoundRect(&theRect, buttonOval, buttonOval);
  2773.             }
  2774.  
  2775.             SetClip(oldClip);
  2776.             DisposeRgn(oldClip);
  2777.             DisposeRgn(newClip);
  2778.  
  2779.             SetPenState(&curPen);
  2780.             SetPort(oldPort);
  2781.         }
  2782.     }
  2783. }
  2784.  
  2785.  
  2786.  
  2787. /*****************************************************************************/
  2788.  
  2789.  
  2790.  
  2791. #pragma segment Controls
  2792. void    OutlineDialogItem(DialogPtr dlgPtr, short item)
  2793. {
  2794.     short    iKind;
  2795.     Handle    iHandle;
  2796.     Rect    iRect;
  2797.  
  2798.     GetDialogItem(dlgPtr, item, &iKind, &iHandle, &iRect);
  2799.     OutlineControl((ControlHandle) iHandle);
  2800. }
  2801.  
  2802.  
  2803.  
  2804. /*****************************************************************************/
  2805.  
  2806.  
  2807.  
  2808. /* Given the button control handle, this will cause the button to look as if it
  2809. ** has been clicked in.  This is nice to do for the user if they type return or
  2810. ** enter to select the default item. */
  2811.  
  2812. #pragma segment Controls
  2813. void    SelectButton(ControlHandle button)
  2814. {
  2815.     long    finalTicks;
  2816.  
  2817.     UseControlStyle(button);
  2818.     HiliteControl(button, kSelect);
  2819.     Delay(kDelayTime, &finalTicks);
  2820.     HiliteControl(button, kDeselect);
  2821.     UseControlStyle(nil);
  2822. }
  2823.  
  2824.  
  2825.  
  2826. /*****************************************************************************/
  2827.  
  2828.  
  2829.  
  2830. /* Handy function for setting the value of a radio button.  Given a dialog
  2831. ** pointer, and item number, and a state, this function will take care of the
  2832. ** rest. */
  2833.  
  2834. #pragma segment Controls
  2835. void    SetCheckOrRadioButton(DialogPtr dlgPtr, short itemNo, short state)
  2836. {
  2837.     short    iKind;
  2838.     Handle    iHandle;
  2839.     Rect    iRect;
  2840.  
  2841.     GetDialogItem(dlgPtr, itemNo, &iKind, &iHandle, &iRect);
  2842.     SetControlValue((ControlHandle)iHandle, state);
  2843. }
  2844.  
  2845.  
  2846.  
  2847. /*****************************************************************************/
  2848.  
  2849.  
  2850.  
  2851. #pragma segment Controls
  2852. void    ToggleCheck(DialogPtr dlgPtr, short chkItem)
  2853. {
  2854.     short    iKind;
  2855.     Handle    iHandle;
  2856.     Rect    iRect;
  2857.  
  2858.     GetDialogItem(dlgPtr, chkItem, &iKind, &iHandle, &iRect);
  2859.     SetControlValue((ControlHandle) iHandle, !GetControlValue((ControlHandle)iHandle));
  2860. }
  2861.  
  2862.  
  2863.  
  2864. /*****************************************************************************/
  2865.  
  2866.  
  2867.  
  2868. #pragma segment Controls
  2869. Boolean    WhichControl(Point mouseLoc, long when, WindowPtr window, ControlHandle *ctlHit)
  2870. {
  2871.     Boolean                    found;
  2872.     Rect                    rct;
  2873.     ControlHandle            ctl, lastCtl;
  2874.     static ControlHandle    lastWhenCtl;
  2875.  
  2876.     gWhichCtlTracking = false;
  2877.  
  2878.     found   = false;
  2879.     lastCtl = nil;
  2880.  
  2881.     if (ctlHit)
  2882.         *ctlHit = nil;
  2883.  
  2884.     if (window) {
  2885.         ctl = ((WindowPeek)window)->controlList;
  2886.         while (ctl) {
  2887.             if ((*ctl)->contrlVis) {
  2888.                 rct = (*ctl)->contrlRect;
  2889.                 if (PtInRect(mouseLoc, &rct)) {
  2890.                     found = true;            /* Return the last hit in the linked list, as */
  2891.                     lastCtl = ctl;            /* it is drawn last, and therefore on top.    */
  2892.                 }
  2893.             }
  2894.             ctl = (*ctl)->nextControl;
  2895.         }
  2896.     }
  2897.  
  2898.     if (ctlHit)
  2899.         *ctlHit = lastCtl;
  2900.  
  2901.     gWhichCtlDbl = false;
  2902.     if (when) {
  2903.         gWhichCtlHit = lastWhenCtl;
  2904.         lastWhenCtl  = lastCtl;
  2905.         if (gWhichCtlHit == lastCtl)
  2906.             if (when < gWhichCtlWhen + 30)
  2907.                 gWhichCtlDbl = true;
  2908.         gWhichCtlWhen = when;
  2909.     }
  2910.     gWhichCtlHit = lastCtl;
  2911.  
  2912.     return(found);
  2913. }
  2914.  
  2915.  
  2916.  
  2917. /*****************************************************************************/
  2918.  
  2919.  
  2920.  
  2921. #pragma segment Controls
  2922. void    DoDrawControls(WindowPtr window, Boolean scrollBarsOnly)
  2923. {
  2924.     ControlHandle    ctl;
  2925.  
  2926.     ctl = ((WindowPeek)window)->controlList;
  2927.     while (ctl) {
  2928.         DoDraw1Control(ctl, scrollBarsOnly);
  2929.         ctl = (*ctl)->nextControl;
  2930.     }
  2931. }
  2932.  
  2933.  
  2934.  
  2935. /*****************************************************************************/
  2936.  
  2937.  
  2938.  
  2939. #pragma segment Controls
  2940. void    DoDraw1Control(ControlHandle ctl, Boolean scrollBarsOnly)
  2941. {
  2942.     WindowPtr    window, oldPort;
  2943.     Rect        rct, srct;
  2944.     Point        org;
  2945.     RgnHandle    oldClip, newClip;
  2946.     Boolean        didPopup;
  2947.  
  2948.     window = (*ctl)->contrlOwner;
  2949.     rct  = (*(window->visRgn))->rgnBBox;
  2950.     srct = (*(window->clipRgn))->rgnBBox;
  2951.     SectRect(&rct, &srct, &srct);
  2952.  
  2953.     rct = (*ctl)->contrlRect;
  2954.     InsetRect(&rct, -4, -4);    /* Enclose possible control adornments. */
  2955.     SectRect(&rct, &srct, &srct);
  2956.     if (EmptyRect(&srct))
  2957.         if (!(window->picSave))
  2958.             return;
  2959.  
  2960.     if (IsScrollBar(ctl)) {
  2961.         if (((WindowPeek)window)->hilited)
  2962.             Draw1Control(ctl);
  2963.         else {
  2964.             if ((*ctl)->contrlVis) {
  2965.                 GetPort(&oldPort);
  2966.                 SetPort(window);
  2967.                 rct = (*ctl)->contrlRect;
  2968.                 FrameRect(&rct);
  2969.                 InsetRect(&rct, 1, 1);
  2970.                 EraseRect(&rct);
  2971.                 SetPort(oldPort);
  2972.             }
  2973.         }
  2974.     }
  2975.     else {
  2976.         if (!scrollBarsOnly) {
  2977.             UseControlStyle(ctl);
  2978.             didPopup = false;
  2979.             if (gPopupProc) {        /* The popup control does not handle negative coords. */
  2980.                 if (StripAddress((*ctl)->contrlDefProc) == StripAddress(gPopupProc)) {
  2981.                     didPopup = true;
  2982.                     GetPort(&oldPort);
  2983.                     SetPort(window);
  2984.                     GetClip(oldClip = NewRgn());    /* We draw it once, so that internals   */
  2985.                     SetRect(&srct, 0, 0, 0, 0);        /* are fixed up.  We don't want to show */
  2986.                     ClipRect(&srct);                /* a flash though. */
  2987.  
  2988.                     RectRgn(newClip = NewRgn(), &(window->portRect));
  2989.                     org.h = window->portRect.left;
  2990.                     org.v = window->portRect.top;
  2991.                     SetOrigin(0, 0);
  2992.  
  2993.                     OffsetRect(&((*ctl)->contrlRect), -org.h, -org.v);    /* Completely clipped out. */
  2994.                     Draw1Control(ctl);                                    /* Just to fix internals.  */
  2995.  
  2996.                     SectRgn(newClip, oldClip, newClip);
  2997.                     OffsetRgn(newClip, -org.h, -org.v);
  2998.                     SetClip(newClip);
  2999.                     Draw1Control(ctl);                /* Now really draw it. */
  3000.  
  3001.                     OffsetRect(&((*ctl)->contrlRect), org.h, org.v);
  3002.                     SetOrigin(org.h, org.v);
  3003.                     SetClip(oldClip);
  3004.                     DisposeRgn(newClip);
  3005.                     DisposeRgn(oldClip);
  3006.  
  3007.                     SetPort(oldPort);
  3008.                 }
  3009.             }
  3010.             if (!didPopup) {
  3011.                 if ((*ctl)->contrlVis) {
  3012.                     if (gDrawControl)
  3013.                         (*gDrawControl)(ctl);
  3014.                     else
  3015.                         Draw1Control(ctl);
  3016.                 }
  3017.             }
  3018.             UseControlStyle(nil);
  3019.             if (GetControlValue(ctl) == 1) {
  3020.                 if (GetButtonVariant(ctl) == pushButProc)
  3021.                     OutlineControl(ctl);
  3022.             }
  3023.         }
  3024.     }
  3025. }
  3026.  
  3027.  
  3028.  
  3029. /*****************************************************************************/
  3030.  
  3031.  
  3032.  
  3033. /* GetPopupCtlHandle takes a dialog and its item number and (assuming it is a
  3034. ** popup menu control) and returns the control handle for the popup. */
  3035.  
  3036. #pragma segment Controls
  3037. ControlHandle    GetPopupCtlHandle(DialogPtr theDialog, short itemNum)
  3038. {
  3039.     short        theType;
  3040.     Handle        theHndl;
  3041.     Rect        theBox;
  3042.  
  3043.     GetDialogItem(theDialog, itemNum, &theType, &theHndl, &theBox);
  3044.     return((ControlHandle)theHndl);
  3045. }
  3046.  
  3047.  
  3048.  
  3049. /*****************************************************************************/
  3050.  
  3051.  
  3052.  
  3053. /* GetPopupMenuHandle takes a popup control and returns the menu handle from
  3054. ** the control. */
  3055.  
  3056. #pragma segment Controls
  3057. MenuHandle    GetPopupMenuHandle(ControlHandle popupCtl)
  3058. {
  3059.     PopupCtlDataHandle    popupData;
  3060.  
  3061.     popupData = (PopupCtlDataHandle)(*popupCtl)->contrlData;
  3062.     if (popupData)
  3063.         return((*popupData)->mHandle);
  3064.  
  3065.     return(nil);
  3066. }
  3067.  
  3068.  
  3069.  
  3070. /*****************************************************************************/
  3071.  
  3072.  
  3073.  
  3074. /* GetPopupCtlValue returns value for the popup control. */
  3075.  
  3076. #pragma segment Controls
  3077. short    GetPopupCtlValue(DialogPtr theDialog, short popItem)
  3078. {
  3079.     ControlHandle    popupCtl;
  3080.  
  3081.     popupCtl = GetPopupCtlHandle(theDialog, popItem);
  3082.     if (popupCtl)
  3083.         return(GetControlValue(popupCtl));
  3084.  
  3085.     return(-1);
  3086. }
  3087.  
  3088.  
  3089.  
  3090. /*****************************************************************************/
  3091.  
  3092.  
  3093.  
  3094. /* SetPopupCtlValue makes value the new value for the popup control. */
  3095.  
  3096. #pragma segment Controls
  3097. void    SetPopupCtlValue(DialogPtr theDialog, short popItem, short value)
  3098. {
  3099.     ControlHandle    popupCtl;
  3100.  
  3101.     popupCtl = GetPopupCtlHandle(theDialog, popItem);
  3102.     if (popupCtl) {
  3103.         (*popupCtl)->contrlValue = value;
  3104.         DoDraw1Control(popupCtl, false);
  3105.     }
  3106. }
  3107.  
  3108.  
  3109.  
  3110. /*****************************************************************************/
  3111. /*****************************************************************************/
  3112. /*****************************************************************************/
  3113.  
  3114.  
  3115.  
  3116. #pragma segment Controls
  3117. OSErr    SetControlStyle(ControlHandle ctl, ControlStyleInfoPtr cinfo)
  3118. {
  3119.     short                len, tlen, ofst;
  3120.     OSErr                err;
  3121.     ControlStyleInfo    cin;
  3122.     Ptr                    ptr1, ptr2;
  3123.  
  3124.     tlen = (*ctl)->contrlTitle[0];
  3125.     ofst = offsetof(ControlRecord,contrlTitle) + tlen + 1;
  3126.     if (!cinfo) {
  3127.         SetHandleSize((Handle)ctl, ofst);
  3128.         return(noErr);
  3129.     }        /* If no info, then control is normalized. */
  3130.  
  3131.     cin   = *cinfo;
  3132.     ptr1  = (Ptr)&cin + offsetof(ControlStyleInfo,font);            /* Point at font. */
  3133.     ptr1 += ptr1[0] + 1;                                            /* Point at packed keyEquivs. */
  3134.     ptr2  = (Ptr)&cin + offsetof(ControlStyleInfo,keyEquivs);        /* Point at keyEquivs. */
  3135.     BlockMove(ptr2, ptr1, ptr2[0] + 1);
  3136.     ptr1 += ptr1[0] + 1;                                            /* Point at packed balloonHelp. */
  3137.     ptr2  = (Ptr)&cin + offsetof(ControlStyleInfo,balloonHelp);        /* Point at balloonHelp. */
  3138.     BlockMove(ptr2, ptr1, ptr2[0] + 1);
  3139.     ptr1 += ptr1[0] + 1;                                            /* Point past packed balloonHelp. */
  3140.  
  3141.     len = ptr1 - (Ptr)&cin;
  3142.     SetHandleSize((Handle)ctl, ofst + len);
  3143.     err = MemError();
  3144.     if (err) {
  3145.         SetHandleSize((Handle)ctl, ofst);
  3146.         return(err);
  3147.     }
  3148.  
  3149.     BlockMove((Ptr)&cin, ((Ptr)*ctl) + ofst, len);
  3150.     return(noErr);
  3151. }
  3152.  
  3153.  
  3154.  
  3155. /*****************************************************************************/
  3156.  
  3157.  
  3158.  
  3159. #pragma segment Controls
  3160. Boolean    GetControlStyle(ControlHandle ctl, ControlStyleInfoPtr cinfo)
  3161. {
  3162.     short    clen, tlen, ofst, ofst2, ofst3;
  3163.     Ptr        ptr;
  3164.  
  3165.     clen = GetHandleSize((Handle)ctl);
  3166.     tlen = (*ctl)->contrlTitle[0];
  3167.     ofst = offsetof(ControlRecord,contrlTitle) + tlen + 1;
  3168.     if (clen < ofst + sizeof(short)) return(false);
  3169.  
  3170.     if (cinfo) {
  3171.         ptr = (Ptr)*ctl;
  3172.         BlockMove(ptr + ofst, (Ptr)cinfo, clen - ofst);
  3173.         ptr   = (Ptr)cinfo;
  3174.         ofst  = offsetof(ControlStyleInfo,font);        /* font */
  3175.         ofst2 = ofst  + ptr[ofst]  + 1;                    /* keyEquivs */
  3176.         ofst3 = ofst2 + ptr[ofst2] + 1;                    /* balloonHelp */
  3177.         BlockMove(ptr + ofst3, ptr + offsetof(ControlStyleInfo,balloonHelp), ptr[ofst3] + 1);
  3178.         BlockMove(ptr + ofst2, ptr + offsetof(ControlStyleInfo,keyEquivs),   ptr[ofst2] + 1);
  3179.     }
  3180.  
  3181.     return(true);
  3182. }
  3183.  
  3184.  
  3185.  
  3186. /*****************************************************************************/
  3187.  
  3188.  
  3189.  
  3190. #pragma segment Controls
  3191. void    SetTrackControlProc(ControlHandle ctl, TrackControlProcPtr proc)
  3192. {
  3193.     ControlStyleInfo    cinfo;
  3194.  
  3195.     if (GetControlStyle(ctl, &cinfo)) {
  3196.         cinfo.trackProc = proc;
  3197.         SetControlStyle(ctl, &cinfo);
  3198.     }
  3199. }
  3200.  
  3201.  
  3202.  
  3203. /*****************************************************************************/
  3204.  
  3205.  
  3206.  
  3207. #pragma segment Controls
  3208. short    GetControlID(ControlHandle ctl)
  3209. {
  3210.     short    tlen, ofst, id;
  3211.  
  3212.     tlen = (*ctl)->contrlTitle[0];
  3213.     ofst = offsetof(ControlRecord,contrlTitle) + tlen + 1;
  3214.     if (GetHandleSize((Handle)ctl) < ofst + sizeof(short)) return(0);
  3215.  
  3216.     BlockMove(((Ptr)*ctl) + ofst, &id, sizeof(short));
  3217.     return(id);
  3218. }
  3219.  
  3220.  
  3221.  
  3222. /*****************************************************************************/
  3223.  
  3224.  
  3225.  
  3226. #pragma segment Controls
  3227. void    SetStyledCTitle(ControlHandle ctl, StringPtr title)
  3228. {
  3229.     ControlStyleInfo    cinfo;
  3230.     Boolean                hasStyle;
  3231.     char                vv;
  3232.  
  3233.     vv = (*ctl)->contrlVis;
  3234.     (*ctl)->contrlVis = 0;
  3235.  
  3236.     hasStyle = GetControlStyle(ctl, &cinfo);
  3237.     SetControlTitle(ctl, title);
  3238.     if (hasStyle)
  3239.         SetControlStyle(ctl, &cinfo);
  3240.  
  3241.     (*ctl)->contrlVis = vv;
  3242.     DoDraw1Control(ctl, false);
  3243. }
  3244.  
  3245.  
  3246.  
  3247. /*****************************************************************************/
  3248.  
  3249.  
  3250.  
  3251. #pragma segment Controls
  3252. void    UseControlStyle(ControlHandle ctl)
  3253. {
  3254.     WindowPtr            oldPort;
  3255.     short                fnum;
  3256.     ControlStyleInfo    cinfo;
  3257.     static short        txFont, txSize;
  3258.     static Style        txFace;
  3259.     static WindowPtr    ctlWindow;
  3260.  
  3261.     if (!ctl) {
  3262.         gDrawControl = nil;
  3263.         if (ctlWindow) {
  3264.             GetPort(&oldPort);
  3265.             SetPort(ctlWindow);
  3266.             TextFont(txFont);
  3267.             TextSize(txSize);
  3268.             TextFace(txFace);
  3269.             SetPort(oldPort);
  3270.         }
  3271.         return;
  3272.     }
  3273.  
  3274.     ctlWindow = nil;
  3275.     if (GetControlStyle(ctl, &cinfo)) {
  3276.         gDrawControl = cinfo.drawControl;
  3277.         if (GetControlVariant(ctl) & useWFont) {
  3278.             GetPort(&oldPort);
  3279.             SetPort(ctlWindow = (*ctl)->contrlOwner);
  3280.             txFont = ctlWindow->txFont;
  3281.             txSize = ctlWindow->txSize;
  3282.             txFace = ctlWindow->txFace;
  3283.             TextFace(cinfo.fontStyle);
  3284.             fnum = systemFont;
  3285.             if (cinfo.font[0])
  3286.                 GetFNum(cinfo.font, &fnum);
  3287.             TextFont(fnum);
  3288.             TextSize(cinfo.fontSize);
  3289.             SetPort(oldPort);
  3290.         }
  3291.     }
  3292. }
  3293.  
  3294.  
  3295.  
  3296. /*****************************************************************************/
  3297. /*****************************************************************************/
  3298. /*****************************************************************************/
  3299.  
  3300.  
  3301.  
  3302. #pragma segment Controls
  3303. Boolean    ControlKeyEquiv(WindowPtr window, EventRecord *event, ControlHandle *retCtl, StringPtr defaultEquivs)
  3304. {
  3305.     ControlHandle        ctl;
  3306.     ControlStyleInfo    cinfo;
  3307.     short                i, theChr, cc, theMod, equivChr, modMask, modVal, pass;
  3308.     Boolean                keyok;
  3309.  
  3310.     if (retCtl)
  3311.         *retCtl = nil;
  3312.  
  3313.     if ((event->what != keyDown) && (event->what != autoKey)) return(false);
  3314.  
  3315.     keyok  = (event->what != autoKey) ? true : false;
  3316.     theChr = event->message   & charCodeMask;
  3317.     theMod = event->modifiers & keyCodeMask;
  3318.  
  3319.     for (pass = 0; pass < 2; ++pass) {
  3320.         for (ctl = ((WindowPeek)window)->controlList; ctl; ctl = (*ctl)->nextControl) {
  3321.             if (!(*ctl)->contrlVis)   continue;        /* Control not visible, so next control. */
  3322.             if ((*ctl)->contrlHilite) continue;        /* Control not active, so next control. */
  3323.             cinfo.keyEquivs[0] = 0;
  3324.             switch (pass) {
  3325.                 case 0:
  3326.                     GetControlStyle(ctl, &cinfo);
  3327.                     break;
  3328.                 case 1:
  3329.                     if (GetButtonVariant(ctl) == pushButProc)                /* If simple button... */
  3330.                         if (GetControlValue(ctl) == 1)                        /* If is outlined button... */
  3331.                             if (defaultEquivs)                                /* If default equiv text passed in... */
  3332.                                 pcpy(cinfo.keyEquivs, defaultEquivs)    ;    /* Use it. */
  3333.                     break;
  3334.             }
  3335.             for (i = 1; i < cinfo.keyEquivs[0]; i += 7) {
  3336.                 if (cinfo.keyEquivs[i] == (unsigned char)':') break;
  3337.                 cc = theChr;
  3338.                 if (cinfo.keyEquivs[i] == (unsigned char)'≈')
  3339.                     if ((cc >= 'a') && (cc <= 'z')) cc -= 32;
  3340.                 equivChr = GetHexByte((char *)(cinfo.keyEquivs + i));
  3341.                 modMask  = GetHexByte((char *)(cinfo.keyEquivs + i + 2)) << 8;
  3342.                 modVal   = GetHexByte((char *)(cinfo.keyEquivs + i + 4)) << 8;
  3343.                 if (!keyok) {
  3344.                     if (equivChr == 0x0000)
  3345.                         if (modMask == 0x0000)
  3346.                             if (modVal == 0x0100)
  3347.                                 keyok = true;
  3348.                     continue;
  3349.                 }
  3350.                 if (cc == equivChr) {
  3351.                     if ((theMod & modMask) == modVal) {
  3352.                         if (retCtl)
  3353.                             *retCtl = ctl;
  3354.                         return(true);
  3355.                     }
  3356.                 }
  3357.             }
  3358.         }
  3359.     }
  3360.  
  3361.     return(false);
  3362. }
  3363.  
  3364.  
  3365.  
  3366.