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