home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-01-17 | 65.6 KB | 2,502 lines | [TEXT/CWIE] |
- /*
- * TransSkel - Transportable Macintosh application skeleton
- *
- * Release 3.23
- *
- * Please report problems to Paul DuBois.
- *
- *
- * TransSkel is in the public domain and was originally written by:
- *
- * Paul DuBois
- * Wisconsin Regional Primate Research Center
- * 1220 Capitol Court
- * Madison, WI 53715-1299 USA
- *
- * Internet: dubois@primate.wisc.edu
- *
- * Additional changes were made by:
- *
- * Owen Hartnett
- * OHM Software Company
- * 163 Richard Drive
- * Tiverton, RI 02878 USA
- *
- * Internet: omh@cs.brown.edu
- * UUCP: uunet!brunix!omh
- *
- * Owen is also responsible for the port to THINK Pascal.
- *
- * Bob Schumaker joined the cast between versions 2.0 and 3.0.
- *
- * Bob Schumaker
- * The AMIX Corporation
- * 1881 Landings Drive
- * Mountain View, CA 94043-0848
- *
- * Internet: bob@markets.amix.com
- * UUCP: {sun, uunet, netcom}!markets!bob
- * CIS: 72227,2103
- * AOL: BSchumaker
- *
- * This version of TransSkel compiles under THINK C 7 or 8 or Metrowerks C 5
- * or 6. (Possibly under THINK C 6 or Metrowerks 4.5 with some minor tweaks.)
- *
- * Reference key:
- * IM Inside Macintosh
- * TN Macintosh Technical Notes
- * MHIG Macintosh Human Interface Guidelines
- * HIN Human Interface Notes
- * PGMF Programmer's Guide to MultiFinder (APDA)
- * TPN TransSkel Programmer's Notes
- *
- * Recent history is given below. Earlier change history is in TSHistory.
- * If you've been writing applications with an earlier release, READ THAT FILE!
- *
- * 15 May 94 Release 3.17
- * - Changed references to QuickDraw globals so they're written in terms of the
- * qd struct. E.g., thePort -> qd.thePort, gray -> qd.gray.
- * - Redid some pattern references so they'll compile whether or not
- * dangerousPattern is defined, and if universal headers are used.
- * 25 May 94
- * - Try to cast the argument to InitDialogs() properly depending on whether or
- * not the universal headers are used.
- *
- * 10 Aug 94 Release 3.18
- * - Began adding full support for Universal Headers so TransSkel can be
- * compiled in native PowerPC mode. I'm doing this under Metrowerks C, so
- * for the moment this also involves porting to Metrowerks. (For compiling
- * M680x0 code under Metrowerks, no changes were necessary from release 3.17,
- * which was a pleasant surprise.)
- * - skelUnivHeaders invented. If value is 1, the Universal Headers are
- * available in the header files(and thus UPP definitions are also available),
- * otherwise workarounds are necessary for UPP types.
- * - skelPPC invented. If value is 1, PPC code is being compiled. Simpler
- * check than checking for powerc and __powerc.
- * 05 Sep 94
- * - Fixed bug in SkelDialog() with not checking whether the window property
- * type was already attached to the handler. That could happen when replacing
- * the handler for an existing window, and trying to add the property when one
- * is already there returns an error.
- * 30 Oct 94
- * - Release 3.17 went to the qd form of QuickDraw global access, but that
- * broke THINK Pascal support since THINK Pascal doesn't define the qd struct.
- * References to the QuickDraw globals are now made using SkelQD(global), which
- * can be defined to use the qd or non-qd access forms. The qd form is still
- * the default, but the THINK Pascal version of the TransSkel library can be
- * compiled easily by supplying a non-qd definition of SkelQD().
- *
- * 22 Dec 94 Release 3.19
- * - Cleaned up the source code a little (e.g., removed some unused variables).
- * 20 Mar 95
- * - Updated to compile under universal headers release 2, which differ
- * somewhat from release 1. These headers are supplied with Metrowerks 5.0
- * and 5.5.
- * - Converted old routine names (e.g., GetIText()) to new names (e.g.,
- * GetDialogItemText(). This may make TransSkel not compile under THINK C 6.
- * 25 May 95 Release 3.20
- * - Updated for Metrowerks 6.
- * - Updated for Symantec 8.0 C++ (PPC) and THINK C 8.0 (68K).
- * 30 Jun 95 Release 3.22
- * - Modified SkelInit() to properly set inForeground when the application is
- * launched directly into the background. Code is based on that supplied by
- * Hans van der Meer.
- * - Added SkelGestaltCheck() function.
- * 15 Jul 95
- * - Modified SkelInit() to test for presence of Thread Manager and to set the
- * hasThreads variable. The value of this variable can be obtained by passing
- * the new selector skelQHasThreads to SkelQuery(). Modified main event loop
- * to call Thread Manager, and added new functions SkelSetThreadTimes() and
- * SkelGetThreadTimes() for setting and getting the amound of time spent in
- * the Thread Manager. Code is based on that supplied by Hans van der Meer.
- */
-
- /*
- * This should be "#define useThreads 0" to turn off Thread Manager support,
- * e.g., if you can't get TransSkel.c to compile. Also, make sure there is
- * no "#define useThreads 1" in your compiler prefix.
- */
-
- # ifndef useThreads
- # define useThreads 0
- # endif
-
- /*
- * TransSkel.h contains defines, typedefs, and public function prototypes
- */
-
- # include "TransSkel.h"
-
-
- # include <Traps.h>
-
- # if skelUnivHeaders > 1
- # include <Gestalt.h>
- # else
- # include <GestaltEqu.h>
- # endif
-
- # include <EPPC.h>
-
- # if useThreads
- # include <Threads.h>
- # if skelUnivHeaders > 1
- # include <CodeFragments.h>
- # else
- # include <FragLoad.h>
- # endif
-
- /*
- * You may need to define some of these if they're not in your headers.
- */
- /*# define gestaltThreadMgrAttr 'thds'*/
- /*# define gestaltThreadMgrPresent 0*/
- /*# define gestaltThreadsLibraryPresent 2*/
-
- # endif /* useThreads */
-
-
- /*
- * New(TypeName) returns handle to new object, for any TypeName.
- * If there is insufficient memory, the result is nil.
- */
-
- # define New(type) (type **) NewHandle ((Size) sizeof (type))
-
-
- /* -------------- */
- /* Internal types */
- /* -------------- */
-
-
- /*
- * Private data types for window and menu handlers
- */
-
- typedef struct WHandler WHandler, *WHPtr, **WHHandle;
-
- struct WHandler
- {
- WindowPtr whWind; /* window/dialog to handle */
- SkelWindMouseProcPtr whMouse; /* mouse-click handler */
- SkelWindKeyProcPtr whKey; /* key-click handler */
- SkelWindUpdateProcPtr whUpdate; /* update handler */
- SkelWindActivateProcPtr whActivate; /* activate event handler */
- SkelWindCloseProcPtr whClose; /* close "event" handler */
- SkelWindClobberProcPtr whClobber; /* window disposal proc */
- SkelWindIdleProcPtr whIdle; /* main loop idle proc */
- SkelWindZoomProcPtr whZoom; /* zoom proc */
- SkelWindSelectProcPtr whSelect; /* item selection proc (dialog) */
- ModalFilterProcPtr whFilter; /* event filter proc (dialog) */
- Rect whGrow; /* limits on window sizing */
- Boolean whSized; /* true = window was resized */
- Boolean whFrontOnly; /* idle only when window active */
- short whFlags; /* various flags */
- SkelWindPropHandle whProperties; /* property list */
- WHHandle whNext; /* next window handler */
- };
-
- typedef struct MHandler MHandler, *MHPtr, **MHHandle;
-
- struct MHandler
- {
- short mhID; /* menu id */
- SkelMenuSelectProcPtr mhSelect; /* item selection handler */
- SkelMenuClobberProcPtr mhClobber; /* menu disposal proc */
- Boolean mhSubMenu; /* whether submenu */
- MHHandle mhNext; /* next menu handler */
- };
-
-
- /* ------------------------------------------- */
- /* Prototypes for internal (private) functions */
- /* ------------------------------------------- */
-
- static WHHandle GetWHandler (WindowPtr w);
- static void DetachWHandler (WHHandle wh);
-
- static void RouteEvent (EventRecord *evt);
-
- static void DoMenuCommand (long command);
- static void DoMenuHook (void);
-
- static void DoMouse (WHHandle h, EventRecord *evt);
- static void DoKey (WHHandle h, char ch, unsigned char code, short mods);
- static void DoUpdate (EventRecord *evt);
- static void DoActivate (EventRecord *evt);
- static void DoClose (WHHandle h);
- static void DoClobber (WHHandle h);
- static void DoDlogEvt (DialogPtr dlog, EventRecord *evt);
- static Boolean DoDlogFilter (DialogPtr dlog, EventRecord *evt);
-
- static void DoGrow (WHHandle h, Point startPt);
- static void DoZoom (WHHandle h, short partCode);
-
-
- /* ------------------ */
- /* Internal variables */
- /* ------------------ */
-
-
- /*
- * Window and menu handler variables.
- *
- * whList and mhList are the lists of window and menu handlers.
- * mhClobOnRmve is true if the menu handler disposal proc
- * is to be called when a handler is removed. It is temporarily set
- * false when handlers are installed for menus that already
- * have handlers - the old handler is removed WITHOUT calling the
- * disposal proc. The effect is to replace the handler for the menu
- * without destroying the menu itself.
- *
- * dragRect determines the limits on window dragging. It is set in
- * SkelInit() to the bounding box of the desktop region inset by 4 pixels.
- *
- * growRect contains the default limits on window sizing. It is set in
- * SkelInit(). The lower limits on window sizing of 80 pixels both directions
- * is sufficient to allow text windows room to draw a grow box and scroll
- * bars without having the thumb and arrows overlap. The upper limits are
- * determined from the screen size. (Probably incorrectly for the case of > 1
- * screen.)
- * These default values may be changed if with SkelGrowBounds if they are
- * not appropriate.
- *
- * zoomProc is the default zoom procedure to use if the window does not have
- * one of its own. zoomProc may be nil, in which case the default is to zoom
- * to just about full window size.
- *
- * mhDrawBarOnRmve determines whether the menu bar is redrawn by
- * SkelRmveMenu() after taking a menu out of the menu bar. Normally
- * it's true, but SkelClobber() sets it false temporarily to avoid
- * flicker as each menu is removed.
- */
-
-
- static WHHandle whList = (WHHandle) nil;
- static Rect dragRect;
- static Rect growRect;
- static SkelWindZoomProcPtr zoomProc = (SkelWindZoomProcPtr) nil;
-
- static WindowPtr oldWindow = (WindowPtr) nil;
- static WHHandle oldWHandler = (WHHandle) nil;
-
-
- static MHHandle mhList = (MHHandle) nil;
- static Boolean mhClobOnRmve = true;
- static Boolean mhDrawBarOnRmve = true;
-
-
- /*
- * Miscellaneous
- *
- * - skelEnv contains SysEnvirons() information.
- * - sysVersion contains the system software version.
- * - hasGestalt is true if Gestalt() is supported.
- * - has64KROM is true if the current machine has the 64K ROM.
- * - hasGetWVariant is true if GetWVariant() is supported.
- * - mBarHeight is menu bar height. Window sizing, zooming and dragging
- * code takes this into account. Initialized in SkelInit(), which see
- * for teeth-gnashing over such a simple thing.
- * - doneFlag determines when SkelEventLoop() returns. It is set by calling
- * SkelStopEventLoop(), which is how the host requests a halt.
- * - pIdle points to a background procedure, to be run during event
- * processing. Set it with SkelSetIdle(). If nil, there's no
- * procedure.
- * - pEvent points to an event-inspecting hook, to be run whenever an
- * event occurs. Set it with SkelSetEventHook(). If nil, there's no
- * procedure.
- * - eventMask controls the event types requested by GetNextEvent() or
- * WaitNextEvent() in SkelEventLoop().
- * - pMenuHook points to a procedure called whenever a menu selection is about
- * to be executed. nil if no hook.
- * - diskInitPt is the location at which the disk initialization dialog
- * appears, if an uninitialized disk is inserted.
- * - eventModifiers is the value of the modifiers field of the current event.
- * - eventPtr points to the current event (nil if none seen yet).
- * - defInitParams contains the default SkelInit() parameters if caller passes
- * nil.
- */
-
- static SysEnvRec skelEnv;
- static long sysVersion = 0;
- static Boolean hasGestalt;
- static Boolean has64KROM;
- static Boolean hasGetWVariant;
- static short mBarHeight;
- static short doneFlag;
- static short eventMask = everyEvent ^ keyUpMask;
- static short eventModifiers = 0;
- static EventRecord *eventPtr = (EventRecord *) nil;
- static Point diskInitPt = { /* v = */ 120, /* h = */ 100 };
-
- static SkelIdleProcPtr pIdle = (SkelIdleProcPtr) nil;
- static SkelEventHookProcPtr pEvent = (SkelEventHookProcPtr) nil;
- static SkelMenuHookProcPtr pMenuHook = (SkelMenuHookProcPtr) nil;
-
- static SkelInitParams defInitParams =
- {
- 6, /* no. of times to call MoreMasters() */
- (GrowZoneUPP) nil, /* GrowZone proc */
- (SkelResumeProcPtr) nil, /* resume proc */
- 0L /* stack adjustment */
- };
-
- /*
- * Multitasking support stuff
- *
- * - hasWNE is true if WaitNextEvent() is available.
- * - inForeground is true if application is running in foreground (not
- * suspended). Initially true unless application is launched directly
- * into the background.
- * - fgWaitTime and bgWaitTime are WaitNextEvent() times for foreground and
- * background states.
- * - getFrontClicks indicates whether the application wants to receive
- * content-area clicks that bring it to the foreground.
- * - pSuspendResume is the application function to call when suspend and
- * resume events occur.
- * - pClipCvt is the function to call for clipboard conversion.
- * - hasThreads is true if the Thread Manager is available.
- * - fgThreadTime and bgThreadTime indicate the number of ticks to spend
- * in the Thread Manager each passs through the main event loop, for
- * foreground and background states. These are initially zero, on the
- * assumption that the application is not multithreaded. The application
- * may set them non-zero to give more time to the Thread Manager. (Note
- * that the event loop is coded such that the Thread Manager is not locked
- * out even if the times are zero; it will simply be called only once each
- * time through the loop.)
- */
-
- static Boolean hasWNE;
- static Boolean inForeground = true;
- static long fgWaitTime = 6L; /* 0.1 seconds */
- static long bgWaitTime = 300L; /* 5.0 seconds */
- static Boolean getFrontClicks = false;
- static SkelSuspendResumeProcPtr pSuspendResume = (SkelSuspendResumeProcPtr) nil;
- static SkelClipCvtProcPtr pClipCvt = (SkelClipCvtProcPtr) nil;
-
- static Boolean hasThreads = false;
- static long fgThreadTime = 0L;
- static long bgThreadTime = 0L;
-
- /*
- * Apple Event support
- *
- * - hasAppleEvents is true if Apple Events are available.
- * - pAEHandler is the function to call when an Apple Event occurs.
- */
-
- static Boolean hasAppleEvents = false;
- static SkelAEHandlerProcPtr pAEHandler = (SkelAEHandlerProcPtr) nil;
-
-
- /* --------------------------- */
- /* Initialization and shutdown */
- /* --------------------------- */
-
- /*
- * Initialize the various Macintosh Managers and lots of other stuff.
- *
- * FlushEvents does NOT toss disk insert events; this is so disks
- * inserted while the application is starting up don't result
- * in dead drives.
- *
- * initParams contains initialization parameters:
- * - the number of times to call MoreMasters
- * - the address of a grow zone procedure to call if memory allocation
- * problems occur (nil if none to be used)
- * - the address of a resume procedure to pass to InitDialogs()
- * (nil if none is to be used)
- * - amount to adjust the application stack size by (default 0; no adjustment)
- *
- * if initParams is nil, defaults are used.
- */
-
- pascal void
- SkelInit (SkelInitParamsPtr initParams)
- {
- ProcessSerialNumber psn1, psn2;
- Boolean answer;
- EventRecord dummyEvent;
- Handle h;
- short i;
- # if useThreads
- long result;
- # endif
-
- if (initParams == (SkelInitParams *) nil)
- initParams = &defInitParams;
-
- if (initParams->skelGzProc != (GrowZoneUPP) nil)
- SetGrowZone (initParams->skelGzProc);
-
- SetApplLimit (GetApplLimit () - initParams->skelStackAdjust);
-
- MaxApplZone ();
-
- for (i = 0; i < initParams->skelMoreMasters; i++)
- MoreMasters ();
-
- FlushEvents (everyEvent - diskMask, 0 );
- InitGraf (&SkelQD (thePort));
- InitFonts ();
- InitWindows ();
- InitMenus ();
- TEInit ();
-
- /*
- * If universal headers are used, InitDialogs() no longer takes
- * a meaningful argument. Pass zero.
- */
-
- # if skelUnivHeaders
- InitDialogs (0);
- # else
- InitDialogs (initParams->skelResumeProc);
- # endif
- InitCursor ();
-
- (void) SysEnvirons (1, &skelEnv);
-
- sysVersion = (long) skelEnv.systemVersion;
-
- has64KROM = (skelEnv.machineType == envMac || skelEnv.machineType == envXL);
-
- /*
- * If 64K ROM machine, use hard-coded value of 20. Otherwise use
- * Script Manager routine GetMBarHeight(). (This assumes, just to be
- * safe, that GetMBarHeight() glue doesn't return 20 on 64K ROM systems,
- * which it very well may. The low memory variable MBarHeight (0x0BAA)
- * isn't used because it doesn't exist on 64K ROM machines (TN OV 4, p.7).
- */
-
- mBarHeight = (has64KROM ? 20 : GetMBarHeight ());
-
- /*
- * Determine whether WaitNextEvent() is implemented (TN's OV 16 and TN TB 14)
- */
-
- if (has64KROM)
- hasWNE = false;
- else
- hasWNE = SkelTrapAvailable (_WaitNextEvent);
-
- hasGestalt = SkelTrapAvailable (_Gestalt);
- /*
- hasAppleEvents = hasGestalt
- && Gestalt (gestaltAppleEventsAttr, &result) == noErr
- && (result & (1 << gestaltAppleEventsPresent));
- */
- hasAppleEvents = SkelGestaltCheck (gestaltAppleEventsAttr,
- gestaltAppleEventsPresent);
-
- # if useThreads
- # if skelPPC
- hasThreads = hasGestalt
- && Gestalt (gestaltThreadMgrAttr, &result) == noErr
- && (result & (1 << gestaltThreadsLibraryPresent))
- /*
- * If your compiler won't compile next line, change
- * kUnresolvedSymbolAddress to 0
- */
- && ((Ptr) NewThread != (Ptr) kUnresolvedSymbolAddress)
- && (result & (1 << gestaltThreadMgrPresent));
- # else
- hasThreads = hasGestalt
- && Gestalt (gestaltThreadMgrAttr, &result) == noErr
- && (result & (1 << gestaltThreadMgrPresent));
- # endif /* skelPPC */
- # endif /* useThreads */
-
- /*
- * Determine whether GetWVariant() exists for checking whether a dialog is
- * a movable modal or not. The variant code can be gotten other ways, but
- * the existence of trap precedes the existence of movalable modal windows,
- * so if the trap doesn't exist, movable modals aren't likely to, either.
- */
-
- hasGetWVariant = SkelTrapAvailable (_GetWVariant);
-
- /*
- * Check whether application wants to get "bring to front" clicks.
- */
-
- if ((h = GetResource ('SIZE', -1)) != (Handle) nil)
- {
- getFrontClicks = (((**(short **) h) & 0x200) != 0);
- ReleaseResource (h);
- }
-
- /*
- * Window dragging limits are determined from bounding box of desktop.
- * Upper limits of window sizing are related to that. Both can involve
- * multiple monitors, and should allow for menu bar. dragRect is inset
- * so as to leave at least 4 pixels of window title bar visible in both
- * directions (IM I-289).
- *
- * GetGrayRgn() bounding box gives desktop extents. On 64K ROM
- * machines, GetGrayRgn() might not be present; could use GrayRgn
- * bounding box, but use screenBits.bounds - menu bar, to avoid
- * low memory access. The two should be equivalent.
- */
-
- if (has64KROM)
- {
- dragRect = SkelQD (screenBits.bounds);
- dragRect.top += mBarHeight;
- }
- else
- {
- /* GetGrayRgn () already takes menu bar into account */
- dragRect = (**GetGrayRgn ()).rgnBBox;
- }
-
- SetRect (&growRect, 80, 80,
- dragRect.right - dragRect.left,
- dragRect.bottom - dragRect.top);
-
- InsetRect (&dragRect, 4, 4);
-
- /*
- * If Process Manager is present, query it as to initial foreground/background
- * status, overriding default setting of inForeground = true.
- */
- if (SkelGestaltCheck (gestaltOSAttr, gestaltLaunchControl)
- && GetCurrentProcess (&psn1) == noErr
- && GetFrontProcess(&psn2) == noErr
- && SameProcess (&psn1, &psn2, &answer) == noErr )
- inForeground = answer;
-
- /*
- * Let application come to front in multitasking environment, TN TB 35, p.8.
- * (Assuming it wants to, that is.)
- */
-
- (void) EventAvail (everyEvent, &dummyEvent);
- (void) EventAvail (everyEvent, &dummyEvent);
- (void) EventAvail (everyEvent, &dummyEvent);
- (void) EventAvail (everyEvent, &dummyEvent);
- }
-
-
- /*
- * Copy the default initialization parameters into the structure
- * pointed to by initParams.
- */
-
- pascal void
- SkelGetInitParams (SkelInitParamsPtr initParams)
- {
- *initParams = defInitParams;
- }
-
-
- /*
- * Clobber all the menu, window and dialog handlers. Tell SkelRmveMenu()
- * not to redraw menu bar so it doesn't flicker as menus are removed,
- * then redraw it manually.
- *
- * Before removing window handlers, hide all the windows. Do this from
- * back to front (more esthetic and speedier). If a window belongs to a DA,
- * close the DA. (For early systems (e.g., 4.1), if you leave a DA open,
- * the system crashes the next time you try to open that DA.)
- */
-
- pascal void
- SkelCleanup (void)
- {
- Boolean oldFlag;
- short theKind;
- WindowPeek w;
- WindowPtr lastVis;
-
- for (;;)
- {
- lastVis = (WindowPtr) nil;
- for (w = (WindowPeek) FrontWindow (); w != (WindowPeek) nil; w = w->nextWindow)
- {
- if (w->visible)
- lastVis = (WindowPtr) w;
- }
- if (lastVis == (WindowPtr) nil) /* no more visible windows */
- break;
- if (lastVis != (WindowPtr) nil)
- {
- theKind = ((WindowPeek) lastVis)->windowKind;
- if (theKind < 0) /* DA, close it */
- CloseDeskAcc (theKind);
- else
- HideWindow (lastVis);
- }
- }
-
- while (whList != (WHHandle) nil)
- SkelRmveWind ((**whList).whWind);
-
- oldFlag = mhDrawBarOnRmve;
- mhDrawBarOnRmve = false;
- while (mhList != (MHHandle) nil)
- SkelRmveMenu (GetMenuHandle((**mhList).mhID));
- mhDrawBarOnRmve = oldFlag;
- DrawMenuBar ();
- }
-
-
- /* ----------------------------------- */
- /* Execution environment interrogation */
- /* ----------------------------------- */
-
-
-
- #define trapMask 0x0800
-
- static short
- NumToolboxTraps (void)
- {
- if (NGetTrapAddress (_InitGraf, ToolTrap)
- == NGetTrapAddress (0xaa6e, ToolTrap))
- return (0x200);
- return (0x400);
- }
-
-
- static TrapType
- GetTrapType (short theTrap)
- {
- return ((theTrap & trapMask) ? ToolTrap : OSTrap);
- }
-
-
- pascal Boolean
- SkelTrapAvailable (short theTrap)
- {
- TrapType tType;
-
- if ((tType = GetTrapType (theTrap)) == ToolTrap)
- {
- theTrap &= 0x07ff;
- if (theTrap >= NumToolboxTraps ())
- theTrap = _Unimplemented;
- }
- return (NGetTrapAddress (theTrap, tType)
- != NGetTrapAddress (_Unimplemented, ToolTrap));
- }
-
-
- /*
- * This function returns true if the specific selector is present and
- * the bit denoted by the featureCode is set. Note that featureCode can
- * be -1 if you just want to check for the presence of the selector,
- * without any interest in its value.
- */
-
- pascal Boolean
- SkelGestaltCheck (OSType selector, short featureCode)
- {
- long result;
-
- if (!hasGestalt || Gestalt (selector, &result) != noErr)
- return (false);
-
- return ( featureCode < 0 ) ? true :
- ( (result & (1 << featureCode)) ? true : false );
- }
-
-
- /*
- * Query the TransSkel execution environment. Shouldn't be called until
- * after SkelInit() has been called. Result is undefined if selector isn't
- * legal.
- */
-
- pascal long
- SkelQuery (short selector)
- {
- long result;
- Rect r;
- RgnHandle rgn;
-
- switch (selector)
- {
- case skelQVersion:
- result = ((long) skelMajorRelease << 16) | skelMinorRelease;
- break;
- case skelQSysVersion:
- result = sysVersion;
- break;
- case skelQHasWNE:
- result = hasWNE ? 1 : 0;
- break;
- case skelQHas64KROM:
- result = has64KROM ? 1 : 0;
- break;
- case skelQMBarHeight:
- result = mBarHeight;
- break;
- case skelQHasColorQD:
- result = skelEnv.hasColorQD ? 1 : 0;
- break;
- case skelQQDVersion:
- /* get QuickDraw version number */
- if (!hasGestalt
- || Gestalt (gestaltQuickdrawVersion, &result) != noErr)
- result = 0; /* assume original QuickDraw */
- break;
- case skelQInForeground:
- result = inForeground ? 1 : 0;
- break;
- case skelQHasGestalt:
- result = hasGestalt ? 1 : 0;
- break;
- case skelQHasAppleEvents:
- result = hasAppleEvents ? 1 : 0;
- break;
- case skelQGrayRgn:
- rgn = NewRgn ();
- if (rgn != (RgnHandle) nil)
- {
- if (has64KROM)
- {
- r = SkelQD (screenBits.bounds);
- r.top += mBarHeight;
- RectRgn (rgn, &r);
- }
- else
- {
- /* GetGrayRgn () already takes menu bar into account */
- CopyRgn (GetGrayRgn (), rgn);
- }
- }
- result = (long) rgn;
- break;
- case skelQHasThreads:
- result = hasThreads ? 1 : 0;
- break;
- default:
- /* result is undefined! */
- break;
- }
- return (result);
- }
-
- /* ------------------------------------- */
- /* Event loop initiation and termination */
- /* ------------------------------------- */
-
-
- /*
- * Main event loop.
- *
- * - Take care of DA's with SystemTask() if necessary.
- * - Get an event.
- * - Pass event to event router.
- * - Call the Thread Manager, if present.
- *
- * doneFlag is restored to its previous value upon exit. This allows
- * SkelEventLoop() to be called recursively.
- */
-
- pascal void
- SkelEventLoop (void)
- {
- EventRecord evt;
- Boolean oldDoneFlag;
- long waitTime;
- long nextEventCheckTime = 0L;
-
- oldDoneFlag = doneFlag; /* save in case this is a recursive call */
- doneFlag = false; /* set for this call */
- while (!doneFlag)
- {
- if (TickCount () >= nextEventCheckTime)
- {
- if (hasWNE)
- {
- waitTime = (inForeground ? fgWaitTime : bgWaitTime);
- (void) WaitNextEvent (eventMask, &evt, waitTime, nil);
- }
- else
- {
- /*
- * On some early versions of the system software, it cannot
- * be assumed that the event contains a null event if the
- * GetNextEvent() return value is false. GetNextEvent() calls
- * SystemEvent() to handle some DA events, and returns false
- * if the event was handled. However, in such cases the event
- * record may still have the event that occurred, *not* a null
- * event. To avoid problems later with misinterpreting the
- * event as non-null, force it to look like a null event.
- */
- SystemTask ();
- if (!GetNextEvent (eventMask, &evt))
- evt.what = nullEvent;
- }
-
- SkelRouteEvent (&evt);
-
- nextEventCheckTime = TickCount ()
- + (inForeground ? fgThreadTime : bgThreadTime);
- }
-
- # if useThreads
- if (hasThreads)
- YieldToAnyThread ();
- # endif
- }
- doneFlag = oldDoneFlag; /* restore in case this was a recursive call */
- }
-
-
- /*
- * Tell current instance of SkelEventLoop() to drop dead
- */
-
- pascal void
- SkelStopEventLoop (void)
- {
- doneFlag = true;
- }
-
-
- /* ----------------- */
- /* Event dispatching */
- /* ----------------- */
-
-
- /*
- * Route a single event and run window idle procedures.
- *
- * If the event is a null-event, call the "no-event" handler for the front
- * window and for any other windows with idle procedures that are always
- * supposed to run. This is done in such a way that it is safe for idle
- * procs to remove the window handler for their own window if they want
- * (unlikely, but...).
- */
-
- pascal void
- SkelRouteEvent (EventRecord *evt)
- {
- WHHandle wh, wh2;
- GrafPtr tmpPort;
- WindowPtr w;
- SkelWindIdleProcPtr p;
-
- RouteEvent (evt);
-
- /*
- * Run applicable window idle procs. Make sure to save and restore
- * the port, since idle procs for the non-active window may be run.
- */
-
- if (evt->what == nullEvent)
- {
- GetPort (&tmpPort);
- for (wh = whList; wh != (WHHandle) nil; wh = wh2)
- {
- wh2 = (**wh).whNext;
- w = (**wh).whWind;
- if (w == FrontWindow () || !(**wh).whFrontOnly)
- {
- if ((p = (**wh).whIdle) != (SkelWindIdleProcPtr) nil)
- {
- if (!hasWNE)
- SystemTask ();
- SetPort (w);
- (*p) ();
- }
- }
- }
- SetPort (tmpPort);
- }
- }
-
-
- /*
- * General event dispatch routine.
- *
- * If there is an event-handling hook and it handles the event, the
- * event is not further processed here. Otherwise, run the application's idle
- * time procedure if the event is a null event, then process the event.
- *
- * Null events are sent through DialogSelect() if a dialog is active. This
- * is necessary to make sure the caret blinks if a dialog has any editText
- * items.
- *
- * Network events are not supported as per the deprecation in TN NW 07.
- * Application-defined events 1, 2 and 3 are not handled, either.
- */
-
- static void
- RouteEvent (EventRecord *evt)
- {
- Point evtPt;
- GrafPtr evtPort;
- short evtPart;
- short evtMods;
- char evtChar;
- long evtMsge;
- unsigned char evtCode;
- WHHandle wh;
- WindowPtr frontWind;
- Boolean frontIsDlog;
- short osMsge;
- Boolean osResume;
- Boolean osClipCvt;
- Rect r1, r2;
- WStateData **wdh;
- SignedByte state;
-
- /* save values for SkelGetCurrentEvent() and SkelGetModifiers() */
-
- eventPtr = evt;
- eventModifiers = evt->modifiers;
-
- /* don't bother handling event below if event hook does so here */
-
- if (pEvent != (SkelEventHookProcPtr) nil && (*pEvent) (evt))
- return;
-
- frontWind = FrontWindow ();
- frontIsDlog = SkelIsDlog (frontWind);
-
- evtPt = evt->where;
- evtMods = evt->modifiers;
- evtMsge = evt->message;
-
- switch (evt->what)
- {
- case nullEvent:
- /*
- * Run the application idle-time function. If the front window is
- * a dialog window, pass the event to the dialog event handler; this
- * is necessary to make the caret blink if it has an edit text item.
- * Don't use frontWind after calling the idle-time function, since
- * the function might change the front window!
- */
- if (pIdle != (SkelIdleProcPtr) nil)
- (*pIdle) ();
- if (SkelIsDlog (FrontWindow ()))
- DoDlogEvt (FrontWindow (), evt);
- break;
-
- /*
- * Mouse click. Get the window in which the click occurred, and
- * the part of the window.
- */
- case mouseDown:
- evtPart = FindWindow (evtPt, &evtPort);
- wh = GetWHandler (evtPort);
-
- /*
- * Beep if a click occurs outside of a movable modal dialog box.
- * Exceptions: allow clicks in menu bar, and command-clicks in
- * drag region of underlying windows.
- */
-
- if (SkelIsMMDlog (frontWind)
- && !PtInRgn (evtPt, ((WindowPeek) frontWind)->strucRgn))
- {
- if (evtPart != inMenuBar
- && !(evtPart == inDrag && evtPort != frontWind && (evtMods & cmdKey)))
- {
- SysBeep (1);
- break;
- }
- }
-
- switch (evtPart)
- {
-
- /*
- * Click in desk accessory window. Pass back to the system.
- */
- case inSysWindow:
- SystemClick (evt, evtPort);
- break;
-
- /*
- * Click in menu bar. Track the mouse and execute
- * selected command, if any.
- */
- case inMenuBar:
- DoMenuHook ();
- DoMenuCommand (MenuSelect (evtPt));
- break;
-
- /*
- * Click in grow box. Resize window.
- */
- case inGrow:
- DoGrow (wh, evtPt);
- break;
-
- /*
- * Click in title bar. Drag the window around.
- * Problem fix: DragWindow() seems to call StillDown()
- * first, so that clicks in drag regions while machine is
- * busy don't otherwise bring window to front if the mouse
- * is already up by the time DragWindow() is called. So the
- * window is selected first to make sure it's at least
- * activated (unless the command key is down, IM I-289).
- *
- * Also offset the window's userState by the amount of the drag
- * (it'd be simpler to set it to the final content rect but the
- * window might be in zoomed state rather than user state).
- */
- case inDrag:
- if (evtPort != frontWind && (evtMods & cmdKey) == 0)
- SelectWindow (evtPort);
- SkelGetWindContentRect (evtPort, &r1); /* post-drag position */
- DragWindow (evtPort, evtPt, &dragRect);
- SkelGetWindContentRect (evtPort, &r2); /* post-drag position */
- wdh = (WStateData **)(((WindowPeek) evtPort)->dataHandle);
- state = HGetState ((Handle) wdh);
- HLock ((Handle) wdh);
- OffsetRect (&(**wdh).userState, r2.left - r1.left, r2.top - r1.top);
- HSetState ((Handle) wdh, state);
- break;
-
- /*
- * Click in close box. Call the close proc if the window
- * has one.
- */
- case inGoAway:
- if (TrackGoAway (evtPort, evtPt))
- DoClose (wh);
- break;
-
- /*
- * Click in zoom box. Track the click and then zoom the
- * window if necessary.
- */
- case inZoomIn:
- case inZoomOut:
- if (TrackBox (evtPort, evtPt, evtPart))
- DoZoom (wh, evtPart);
- break;
-
- /*
- * Click in content region. If the window wasn't frontmost
- * (active), just select it, otherwise pass the click to the
- * window's mouse click handler. Exception: if the application
- * wants to receive content clicks event in non-frontmost windows,
- * select the window and "repeat" the click.
- */
- case inContent:
- if (evtPort != frontWind)
- {
- SelectWindow (evtPort);
- if (!getFrontClicks) /* don't pass click to handler */
- break;
- SetPort (evtPort);
- }
- if (frontIsDlog)
- DoDlogEvt (evtPort, evt);
- else
- DoMouse (wh, evt);
- break;
-
- }
- break; /* mouseDown */
-
- /*
- * Key down event. If the command key was down, process as menu
- * item selection, otherwise pass the character and the modifiers
- * flags to the active window's key handler.
- *
- * Command-period is not supposed to be used as a menu-item equivalent.
- * Consequently, that's noticed as a special case and not passed to
- * the menu routines.
- */
- case keyDown:
- case autoKey:
- evtChar = evtMsge & charCodeMask;
- evtCode = (evtMsge & keyCodeMask) >> 8; /* hope bit 7 isn't set! */
-
- if ((evtMods & cmdKey) && !SkelCmdPeriod (evt)) /* try menu equivalent */
- {
- DoMenuHook ();
- DoMenuCommand (MenuKey (evtChar));
- break;
- }
-
- if (frontIsDlog)
- DoDlogEvt (frontWind, evt);
- else
- DoKey (GetWHandler (frontWind), evtChar, evtCode, evtMods);
- break;
-
- /*
- * Key up event. Key-ups are signified by setting the high bit
- * of the key code. This never executes unless the application
- * changes the system event mask *and* the TransSkel event mask.
- */
- case keyUp:
- evtChar = evtMsge & charCodeMask; /* probably 0? */
- evtCode = ((evtMsge & keyCodeMask) >> 8) | 0x80;
-
- if (frontIsDlog)
- DoDlogEvt (frontWind, evt);
- else
- DoKey (GetWHandler (frontWind), evtChar, evtCode, evtMods);
- break;
-
- /*
- * Update a window.
- */
- case updateEvt:
- DoUpdate (evt);
- break;
-
- /*
- * Activate or deactivate a window.
- */
- case activateEvt:
- DoActivate (evt);
- break;
-
- /*
- * handle inserts of uninitialized disks. Deactivate the frontmost
- * window since the disk-init dialog doesn't do anything with
- * activate events for other windows.
- */
- case diskEvt:
- if (HiWord (evtMsge) != noErr)
- {
- SkelActivate (FrontWindow (), false);
- DILoad ();
- (void) DIBadMount (diskInitPt, evtMsge);
- DIUnload ();
- }
- break;
-
- case osEvt: /* aka app4Evt aka MultiFinder event */
- /* rip the message field into constituent parts */
- osMsge = ((evtMsge >> 24) & 0xff); /* high byte */
- osResume = (Boolean) ((evtMsge & resumeFlag) != 0);
- osClipCvt = (Boolean) ((evtMsge & convertClipboardFlag) != 0);
-
- switch (osMsge)
- {
- case suspendResumeMessage:
- /*
- * Tell application it's being suspended or resumed
- * Tell application to convert scrap if necessary
- */
-
- inForeground = osResume;
- if (pSuspendResume != (SkelSuspendResumeProcPtr) nil)
- (*pSuspendResume) (inForeground);
- if (!osResume) /* always convert on suspend */
- osClipCvt = true;
- if (osClipCvt && pClipCvt != (SkelClipCvtProcPtr) nil)
- (*pClipCvt) (inForeground);
- break;
-
- case mouseMovedMessage:
- /* recompute mouse region -- not implemented */
- break;
-
- /*
- * 0xfd is a child-died event -- not implemented here since it's
- * only had limited use, e.g., by certain debuggers. The child pid
- * is byte 2 ((evtMsge >> 16) & 0xff)
- case 0xfd:
- break;
- */
-
- default: /* other OS event */
- /* pass event to catch-all handler -- not implemented */
- break;
- }
- break;
-
- case kHighLevelEvent:
- if (pAEHandler != (SkelAEHandlerProcPtr) nil)
- (*pAEHandler) (evt);
- break;
- }
- }
-
-
- /*
- * Activate or deactivate a window by synthesizing a fake
- * activate event and sending it through the event router.
- * Useful for activating a window when you don't know its
- * activate function.
- */
-
- pascal void
- SkelActivate (WindowPtr w, Boolean active)
- {
- EventRecord evt;
-
- if (w != (WindowPtr) nil)
- {
- evt.what = activateEvt;
- evt.modifiers = active ? activeFlag : 0;
- evt.when = TickCount ();
- SetPt (&evt.where, 0, 0);
- evt.message = (long) w;
- SkelRouteEvent (&evt);
- }
- }
-
-
- /*
- * Call a window's close procedure. Useful for closing a window when you
- * don't know its close function.
- *
- * This function knows how to close Desk Accessories.
- */
-
- pascal void
- SkelClose (WindowPtr w)
- {
- if (w != (WindowPtr) nil)
- {
- if (((WindowPeek) w)->windowKind < 0) /* DA window */
- CloseDeskAcc (((WindowPeek) w)->windowKind);
- else
- DoClose (GetWHandler (w));
- }
- }
-
-
- /*
- * Set the TransSkel event mask. Does not have anything to do with the
- * system event mask. See TPN 3.
- */
-
- pascal void
- SkelSetEventMask (short mask)
- {
- eventMask = mask;
- }
-
-
- /*
- * Return the event mask.
- */
-
- pascal short
- SkelGetEventMask (void)
- {
- return (eventMask);
- }
-
-
- /*
- * Install an idle-time task. If p is nil, the current task is
- * disabled.
- */
-
- pascal void
- SkelSetIdle (SkelIdleProcPtr p)
- {
- pIdle = p;
- }
-
-
- /*
- * Return the current idle-time task. Return nil if none.
- */
-
- pascal SkelIdleProcPtr
- SkelGetIdle (void)
- {
- return (pIdle);
- }
-
-
- /*
- * Install an event-inspecting hook. If p is nil, the hook is
- * disabled.
- */
-
- pascal void
- SkelSetEventHook (SkelEventHookProcPtr p)
- {
- pEvent = p;
- }
-
-
- /*
- * Return the current event-inspecting hook. Return nil if none.
- */
-
- pascal SkelEventHookProcPtr
- SkelGetEventHook (void)
- {
- return (pEvent);
- }
-
-
- pascal void
- SkelSetSuspendResume (SkelSuspendResumeProcPtr p)
- {
- pSuspendResume = p;
- }
-
-
- pascal SkelSuspendResumeProcPtr
- SkelGetSuspendResume (void)
- {
- return (pSuspendResume);
- }
-
-
- pascal void
- SkelSetClipCvt (SkelClipCvtProcPtr p)
- {
- pClipCvt = p;
- }
-
-
- pascal SkelClipCvtProcPtr
- SkelGetClipCvt (void)
- {
- return (pClipCvt);
- }
-
-
- pascal void
- SkelSetWaitTimes (long fgTime, long bgTime)
- {
- fgWaitTime = fgTime;
- bgWaitTime = bgTime;
- }
-
-
- pascal void
- SkelGetWaitTimes (long *pFgTime, long *pBgTime)
- {
- if (pFgTime != (long) nil)
- *pFgTime = fgWaitTime;
- if (pBgTime != (long) nil)
- *pBgTime = bgWaitTime;
- }
-
-
- pascal void
- SkelSetThreadTimes (long fgTime, long bgTime)
- {
- fgThreadTime = fgTime;
- bgThreadTime = bgTime;
- }
-
-
- pascal void
- SkelGetThreadTimes (long *pFgTime, long *pBgTime)
- {
- if (pFgTime != (long) nil)
- *pFgTime = fgThreadTime;
- if (pBgTime != (long) nil)
- *pBgTime = bgThreadTime;
- }
-
-
- pascal EventRecord *
- SkelGetCurrentEvent (void)
- {
- return (eventPtr);
- }
-
-
- pascal short
- SkelGetModifiers (void)
- {
- return (eventModifiers);
- }
-
-
- pascal void
- SkelSetAEHandler (SkelAEHandlerProcPtr p)
- {
- pAEHandler = p;
- }
-
-
- pascal SkelAEHandlerProcPtr
- SkelGetAEHandler (void)
- {
- return (pAEHandler);
- }
-
-
- /* -------------------------------------------------------------------- */
- /* Window-handler event routing routines */
- /* */
- /* See manual for discussion of port-setting behavior: the current */
- /* port is set to a window when it becomes active in DoActivate(). */
- /* -------------------------------------------------------------------- */
-
-
- /*
- * Process dialog event. dlog is the dialog to which the event applies.
- * Give the filter a chance at the event first. If the filter doesn't
- * handle it, pass the event to DialogSelect(). If DialogSelect() selects
- * an item, pass the item to the window's item selection function, if
- * there is one. This is used to dispose of dialog events that aren't
- * handled in some other more direct fashion.
- */
-
-
- static void
- DoDlogEvt (DialogPtr dlog, EventRecord *evt)
- {
- short item;
- WHHandle wh;
- SkelWindSelectProcPtr select;
-
- if (DoDlogFilter (dlog, evt))
- return;
-
- if (DialogSelect (evt, &dlog, &item)
- && (wh = GetWHandler (dlog)) != (WHHandle) nil
- && (select = (**wh).whSelect) != (SkelWindSelectProcPtr) nil)
- {
- (*select) (dlog, item);
- }
- }
-
- /*
- * Run a dialog's filter function to give the filter first chance
- * at the event.
- *
- * The filter function returns false if it doesn't handle the event.
- * It returns true if it handled the event, in which case it should
- * set the item parameter. The item will be passed to the dialog's
- * item selection function.
- *
- * If the filter function returns true, look up the handler again
- * just in case the filter function also called SkelRmveDlog().
- * If it did, the handler will have become invalid. Looking it
- * up again avoids disaster.
- */
-
- static Boolean
- DoDlogFilter (DialogPtr dlog, EventRecord *evt)
- {
- short item;
- WHHandle wh;
- SkelWindSelectProcPtr select;
- ModalFilterProcPtr filter;
- Boolean result = false;
-
- if ((wh = GetWHandler (dlog)) != (WHHandle) nil
- && (filter = (**wh).whFilter) != (ModalFilterProcPtr) nil)
- {
- if ((*(ModalFilterProcPtr) filter) (dlog, evt, &item))
- {
- if ((wh = GetWHandler (dlog)) != (WHHandle) nil
- && (select = (**wh).whSelect) != (SkelWindSelectProcPtr) nil)
- {
- (*select) (dlog, item);
- }
- result = true;
- }
- }
- return (result);
- }
-
-
- /*
- * Pass local mouse coordinates, click time, and the modifiers flag
- * word to the handler. Should not be necessary to set the port, as
- * the click is passed to the active window's handler.
- */
-
- static void
- DoMouse (WHHandle h, EventRecord *evt)
- {
- Point thePt;
-
- if (h != (WHHandle) nil && (**h).whMouse != (SkelWindMouseProcPtr) nil)
- {
- thePt = evt->where; /* make local copy */
- GlobalToLocal (&thePt);
- (*(**h).whMouse) (thePt, evt->when, evt->modifiers);
- }
- }
-
-
- /*
- * Pass the character code, key code and the modifiers flag word to
- * the handler. Should not be necessary to set the port, as the click
- * is passed to the active window's handler.
- */
-
- static void
- DoKey (WHHandle h, char c, unsigned char code, short mods)
- {
- if (h != (WHHandle) nil && (**h).whKey != (SkelWindKeyProcPtr) nil)
- (*(**h).whKey) ((short) c, (short) code, mods);
- }
-
-
- /*
- * Call the window updating procedure, passing to it an indicator whether
- * the window has been resized or not. Then clear the flag, assuming
- * the update proc took whatever action was necessary to respond to
- * resizing.
- *
- * The Begin/EndUpdate stuff is done to clear the update region even if
- * the handler doesn't have any update proc. Otherwise the Window
- * Manager will keep generating update events for the window, stalling
- * updates of other windows.
- *
- * For dialog windows, UpdtDialog() does the normal item updating. The
- * filter procedure can take care of non-item drawing, such as a bold
- * outline around a default button.
- *
- * Saves, sets, and restore the port, since it's not always the
- * active window that is updated.
- */
-
- static void
- DoUpdate (EventRecord *evt)
- {
- WHHandle h;
- GrafPtr port;
- GrafPtr tmpPort;
-
- port = (WindowPtr) evt->message;
-
- GetPort (&tmpPort);
- SetPort (port);
- BeginUpdate (port);
- if (SkelIsDlog (port))
- {
- if (!DoDlogFilter (port, evt))
- UpdateDialog (port, port->visRgn); /* let Dialog Manager finish update */
- }
- else
- {
- h = GetWHandler (port);
- if (h != (WHHandle) nil)
- {
- if ((**h).whUpdate != (SkelWindUpdateProcPtr) nil)
- (*(**h).whUpdate) ((**h).whSized);
- (**h).whSized = false;
- }
- }
- EndUpdate (port);
- SetPort (tmpPort);
- }
-
-
- /*
- * Pass activate/deactivate notification to handler. On activate,
- * set the port to the window coming active. Normally this is done by
- * the user clicking in a window.
- *
- * *** BUT ***
- * Under certain conditions, a deactivate may be generated for a window
- * that has never had the port set to it by a preceding activate. For
- * instance, if an application puts up window A, then window B in front
- * of A, then starts processing events, the first events will be a
- * deactivate for A and an activate for B. Therefore, since it can't be
- * assumed that an activate ever set the port to A, the port needs to be
- * set for deactivates as well so drawing occurs in the correct port.
- *
- * This matters not a whit for the more usual cases that occur. If a
- * deactivate for one window is followed by an activate for another, the
- * port will still be switched properly to the newly active window. If
- * no activate follows the deactivate, the deactivated window is the last
- * one, and it doesn't matter what the port ends up set to, anyway.
- *
- * On deactivate, port is saved and restored in case deactivate is due to
- * a modal dialog having been brought in front and port changed to it
- * explicitly by the application. The deactivate shouldn't leave the port
- * changed away from the dialog!
- *
- * For dialogs, DoDlogEvt() is called, allowing DialogSelect() to do
- * whatever it does for dialog activates. The handler's activate procedure
- * is called in addition to this (e.g., to hilite controls or text selections,
- * adjust menus).
- */
-
- static void
- DoActivate (EventRecord *evt)
- {
- WHHandle h;
- GrafPtr port;
- GrafPtr tmpPort;
- Boolean active;
-
- active = (evt->modifiers & activeFlag);
- port = (WindowPtr) evt->message;
-
-
- GetPort (&tmpPort); /* save so can restore if deactivate */
- SetPort (port);
- if (SkelIsDlog (port))
- DoDlogEvt (port, evt);
- else
- {
- h = GetWHandler (port);
- if (h != (WHHandle) nil)
- {
- if ((**h).whActivate != (SkelWindActivateProcPtr) nil)
- (*(**h).whActivate) (active);
- }
- }
- if (!active)
- SetPort (tmpPort);
- }
-
-
- /*
- * Execute a window handler's close box proc. The close proc for
- * handlers for temp windows that want to remove themselves when the
- * window is closed can call SkelRmveWind to dispose of the window
- * and remove the handler from the window handler list. Thus, windows
- * may be dynamically created and destroyed without filling up the
- * handler list with a bunch of invalid handlers.
- *
- * If the handler doesn't have a close proc, just hide the window.
- * The host should provide some way of reopening the window (perhaps
- * a menu selection). Otherwise the window will be lost from user
- * control if it is hidden, since it won't receive user-initiated
- * events.
- *
- * This is called both for regular and dialog windows.
- *
- * Normally this is invoked because the close box of the active window
- * is clicked, in which case the port will be set to the window. However,
- * SkelClose() allows the application to close an aritrary window, not just
- * the frontmost one -- so the port is saved and restored.
- */
-
- static void
- DoClose (WHHandle h)
- {
- GrafPtr tmpPort;
-
- if (h != (WHHandle) nil)
- {
- GetPort (&tmpPort);
- SetPort ((**h).whWind);
- if ((**h).whClose != (SkelWindCloseProcPtr) nil)
- (*(**h).whClose) ();
- else
- HideWindow ((**h).whWind);
- SetPort (tmpPort);
- }
- }
-
-
- /*
- * Execute a window handler's clobber proc. This is called both
- * for regular and dialog windows.
- *
- * Saves sets, and restores the port, since any window (not just active
- * one) may be clobbered at any time.
- *
- * Don't need to check whether handler is nil, as in other handler
- * procedures, since this is only called by SkelRmveWind with a
- * known-valid handler.
- */
-
- static void
- DoClobber (WHHandle h)
- {
- GrafPtr tmpPort;
-
- GetPort (&tmpPort);
- SetPort ((**h).whWind);
- if ((**h).whClobber != (SkelWindClobberProcPtr) nil)
- (*(**h).whClobber) ();
- SetPort (tmpPort);
- }
-
-
- /*
- * Handlers for window events not requiring application handler routines
- * to be called.
- */
-
-
- /*
- * Have either zoomed a window or sized it manually. Invalidate
- * it to force an update and set the 'resized' flag in the window
- * handler true. The port is assumed to be set to the port that changed
- * size. Handler is assumed non-nil.
- */
-
- static void
- TriggerUpdate (WHHandle h)
- {
- GrafPtr port = (**h).whWind;
-
- InvalRect (&port->portRect);
- (**h).whSized = true;
- }
-
-
- /*
- * Size a window, using the grow limits in the handler record.
- *
- * The portRect is invalidated to force an update event. The window's
- * update handler procedure should check the parameter passed to it to
- * check whether the window has changed size, if it needs to adjust
- * itself to the new size. THIS IS A CONVENTION. Update procs must
- * notice grow "events", there is no procedure specifically for that.
- *
- * The clipping rectangle is not reset. If the host application
- * keeps the clipping set equal to the portRect or something similar,
- * then it will have to arrange to treat window growing with more
- * care.
- *
- * Since the grow region of only the active window may be clicked,
- * it should not be necessary to set the port.
- */
-
- static void
- DoGrow (WHHandle h, Point startPt)
- {
- GrafPtr growPort;
- Rect growRect;
- long growRes;
-
- if (h != (WHHandle) nil)
- {
- growPort = (**h).whWind;
- growRect = (**h).whGrow;
-
- /* growRes will be zero if the size was not actually changed */
-
- if ((growRes = GrowWindow (growPort, startPt, &growRect)) != 0)
- {
- SizeWindow (growPort, LoWord (growRes), HiWord (growRes), false);
- TriggerUpdate (h);
- }
- }
- }
-
-
- /*
- * Zoom the current window. Very similar to DoGrow, but window
- * is erased before zooming for nicer visual effect (per IM IV-50,
- * TN TB 30, p.4).
- *
- * Normally, since only the active window has a visible zoom box and
- * TransSkel sets the port to active window, this routine is triggered
- * by user-initiated clicks in zoom box and the port will be set to
- * the zoomed window.
- *
- * However, it is possible for zooms to be software initiated by the
- * application itself on any window; for such cases the port needs
- * to be saved and set before the zoom and restored afterward.
- */
-
- static void
- DoZoom (WHHandle h, short zoomDir)
- {
- GrafPtr w;
- GrafPtr tmpPort;
- Rect r, growRect;
-
- if (h != (WHHandle) nil)
- {
- w = (**h).whWind;
- GetPort (&tmpPort); /* save port and set to */
- SetPort (w); /* zoomed window */
- if ((**h).whZoom != (SkelWindZoomProcPtr) nil)
- ((**h).whZoom) (w, zoomDir); /* custom zoom proc */
- else if (zoomProc != (SkelWindZoomProcPtr) nil)
- (*zoomProc) (w, zoomDir); /* custom default zoom proc */
- else /* default zooming */
- {
- EraseRect (&w->portRect);
- if (zoomDir == inZoomOut) /* zooming to default state */
- {
- /*
- * Get the usable area of the device containing most of the
- * window. (Can ignore the result because the rect is always
- * correct. Pass nil for device parameter because it's
- * irrelevant.) Then adjust rect for title bar height, and
- * inset it slightly.
- */
- (void) SkelGetWindowDevice (w, (GDHandle *) nil, &r);
- r.top += SkelGetWindTitleHeight (w) - 1;
- /* leave 3-pixel border */
- InsetRect (&r, 3, 3);
- /* clip to grow limits */
- growRect = (**h).whGrow;
- growRect.left = growRect.top = 0;
- OffsetRect (&growRect, r.left, r.top);
- SectRect (&r, &growRect, &r);
- (**(WStateData **)(((WindowPeek)w)->dataHandle)).stdState = r;
- }
- ZoomWindow (w, zoomDir, false);
- }
- SetPort (tmpPort); /* restore original port */
- TriggerUpdate (h);
- }
- }
-
-
- /* --------------------------------------------------------- */
- /* Window handler installation/removal/modification routines */
- /* --------------------------------------------------------- */
-
-
- /*
- * Install handler for a window and set current port to it. Remove
- * any previous handler for it. Pass the following parameters:
- *
- * w
- * Pointer to the window to be handled. Must be created by host.
- * doMouse
- * Proc to handle mouse clicks in window. The proc will be
- * passed the point (in local coordinates), the time of the
- * click, and the modifier flags word.
- * doKey
- * Proc to handle key clicks in window. The proc will be passed
- * the character and the modifier flags word.
- * doUpdate
- * Proc for updating window. TransSkel brackets calls to update
- * procs with calls to BeginUpdate and EndUpdate, so the visRgn
- * is set up correctly. A flag is passed indicating whether the
- * window was resized or not. BY CONVENTION, the entire portRect
- * is invalidated when the window is resized or zoomed. That way,
- * the handler's update proc can redraw the entire content region
- * without interference from BeginUpdate/EndUpdate. The flag
- * is set to false after the update proc is called; the
- * assumption is made that the proc will notice the resizing and
- * respond appropriately.
- * doActivate
- * Proc to execute when window is activated or deactivated.
- * A boolean is passed to it which is true if the window is
- * coming active, false if it's going inactive.
- * doClose
- * Proc to execute when mouse clicked in close box. Useful
- * mainly to temp window handlers that want to know when to
- * self-destruct (with SkelRmveWind).
- * doClobber
- * Proc for disposal of handler's data structures
- * doWIdle
- * Proc to execute when no events are pending.
- * idleFrontOnly
- * True if doWIdle should execute on no events only when
- * w is frontmost, false if executes all the time. Note
- * that if it always goes, everything else may be slowed down!
- *
- * If a particular procedure is not needed (e.g., key events are
- * not processed by a handler), pass nil in place of the appropriate
- * procedure address.
- *
- * Return true if successful, false if no handler could be allocated.
- * If false is returned, the port will not have been changed.
- */
-
- pascal Boolean
- SkelWindow (WindowPtr w,
- SkelWindMouseProcPtr doMouse,
- SkelWindKeyProcPtr doKey,
- SkelWindUpdateProcPtr doUpdate,
- SkelWindActivateProcPtr doActivate,
- SkelWindCloseProcPtr doClose,
- SkelWindClobberProcPtr doClobber,
- SkelWindIdleProcPtr doWIdle,
- Boolean idleFrontOnly)
- {
- WHHandle whNew, whCur;
- SkelWindPropHandle wph = (SkelWindPropHandle) nil;
-
- /* Get new handler immediately, fail if can't allocate */
-
- if ((whNew = New (WHandler)) == (WHHandle) nil)
- return (false);
-
- /*
- * If there's a current handler for the window, remove it, but first
- * grab the property list from it so it can be transferred to the new
- * handler.
- */
-
- if ((whCur = GetWHandler (w)) != (WHHandle) nil)
- {
- wph = (**whCur).whProperties;
- (**whCur).whProperties = (SkelWindPropHandle) nil;
- DetachWHandler (whCur);
- }
-
- /*
- * Attach new handler to list of handlers. It is attached to the
- * beginning of the list, which is simpler; the order is presumably
- * irrelevant to the host, anyway.
- *
- * Then fill in handler fields (including properties attached to any
- * previous handler).
- */
-
- (**whNew).whNext = whList;
- whList = whNew;
-
- (**whNew).whWind = w;
- (**whNew).whMouse = doMouse;
- (**whNew).whKey = doKey;
- (**whNew).whUpdate = doUpdate;
- (**whNew).whActivate = doActivate;
- (**whNew).whClose = doClose;
- (**whNew).whClobber = doClobber;
- (**whNew).whZoom = (SkelWindZoomProcPtr) nil;
- (**whNew).whIdle = doWIdle;
- (**whNew).whGrow = growRect;
- (**whNew).whSized = false;
- (**whNew).whFrontOnly = idleFrontOnly;
- (**whNew).whFlags = 0;
- (**whNew).whProperties = wph;
- (**whNew).whSelect = (SkelWindSelectProcPtr) nil;
- (**whNew).whFilter = (ModalFilterProcPtr) nil;
- SetPort (w);
-
- return (true);
- }
-
-
- /*
- * Remove a window handler. This calls the handler's window disposal
- * routine and then takes the handler out of the handler list and
- * disposes of it (including its property list).
- *
- * SkelRmveWind is also called by SkelRmveDlog.
- */
-
- pascal void
- SkelRmveWind (WindowPtr w)
- {
- WHHandle h;
-
- if ((h = GetWHandler (w)) == (WHHandle) nil)
- return;
-
- DoClobber (h); /* call disposal routine */
- SkelRmveWindProp (w, skelWPropAll); /* toss properties */
-
- DetachWHandler (h); /* remove handler for window from list */
- }
-
-
- /*
- * Install a handler for a modeless or movable modal dialog window and set
- * the port to it. Remove any previous handler for it. SkelDialog calls
- * SkelWindow as a subsidiary to install a window handler, then sets
- * the event procedure on return. A property is also added to the window
- * to indicate that it's a modeless or movable modal dialog.
- *
- * Pass the following parameters:
- *
- * dlog
- * Pointer to the dialog to be handled. Must be created by host.
- * doFilter
- * Filter procedure to look at events before they are otherwise
- * processed.
- * doSelect
- * Procedure to execute when an item is "selected" (e.g., a mouse
- * click occurs in it).
- * doClose
- * Procedure to execute when mouse clicked in close box. Useful
- * mainly to dialog handlers that want to know when to
- * self-destruct (with SkelRmveDlog).
- * doClobber
- * Procedure for disposal of handler's data structures
- *
- * If a particular procedure is not needed, pass nil in place of
- * the appropriate procedure address.
- *
- * Return true if successful, false if no handler could be allocated.
- * If false is returned, the port will not have been changed.
- */
-
- pascal Boolean
- SkelDialog (DialogPtr dlog,
- ModalFilterProcPtr doFilter,
- SkelWindSelectProcPtr doSelect,
- SkelWindCloseProcPtr doClose,
- SkelWindClobberProcPtr doClobber)
- {
- WHHandle wh;
- short propType;
-
- if (!SkelWindow (dlog, nil, nil, nil, nil, doClose, doClobber, nil, true))
- return (false);
-
- /*
- * Determine dialog property type to add to window and add the property,
- * unless it already has one. (The property might already exist if
- * the handler for an existing window is being replaced.)
- */
- propType = (SkelIsMMDlog (dlog) ? skelWPropMovableModal : skelWPropModeless);
- if (SkelGetWindProp (dlog, propType) == (SkelWindPropHandle) nil
- && !SkelAddWindProp (dlog, propType, (long) 0))
- {
- SkelRmveDlog (dlog);
- return (false);
- }
-
- wh = GetWHandler (dlog);
- (**wh).whSelect = doSelect;
- (**wh).whFilter = doFilter;
- return (true);
- }
-
-
- /*
- * Remove a dialog and its handler
- */
-
- pascal void
- SkelRmveDlog (DialogPtr dlog)
- {
- SkelRmveWind (dlog);
- }
-
-
- /*
- * Override the default sizing limits for a window, or, if w
- * is nil, reset the default limits used by SkelWindow.
- */
-
- pascal void
- SkelSetGrowBounds (WindowPtr w, short hLo, short vLo, short hHi, short vHi)
- {
- WHHandle wh;
- Rect r;
-
- if (w == (WindowPtr) nil)
- SetRect (&growRect, hLo, vLo, hHi, vHi);
- else if ((wh = GetWHandler (w)) != (WHHandle) nil)
- {
- SetRect (&r, hLo, vLo, hHi, vHi);
- (**wh).whGrow = r;
- }
- }
-
-
- pascal void
- SkelSetZoom (WindowPtr w, SkelWindZoomProcPtr pZoom)
- {
- WHHandle h;
-
- if (w == (WindowPtr) nil)
- zoomProc = pZoom;
- else if ((h = GetWHandler (w)) != (WHHandle) nil)
- (**h).whZoom = pZoom;
- }
-
-
- /*
- * Return zoom proc associated with window, nil if there isn't one.
- * Return default zoom proc if window is nil.
- */
-
- pascal SkelWindZoomProcPtr
- SkelGetZoom (WindowPtr w)
- {
- WHHandle h;
-
- if (w == (WindowPtr) nil)
- return (zoomProc);
- if ((h = GetWHandler (w)) != (WHHandle) nil)
- return ((**h).whZoom);
- return ((SkelWindZoomProcPtr) nil);
- }
-
-
- pascal Boolean
- SkelWindowRegistered (WindowPtr w)
- {
- return ((Boolean) (GetWHandler (w) != (WHHandle) nil));
- }
-
-
- /*
- * Routines to determine whether a given window is a dialog, or a movable
- * modal dialog. Safe to pass nil.
- */
-
- pascal Boolean
- SkelIsDlog (WindowPtr w)
- {
- return (w != (WindowPtr) nil && ((WindowPeek)w)->windowKind == dialogKind);
- }
-
-
- pascal Boolean
- SkelIsMMDlog (WindowPtr w)
- {
- return (SkelIsDlog (w) && hasGetWVariant && GetWVariant (w) == movableDBoxProc);
- }
-
-
- /* ------------------------ */
- /* Handler finders/removers */
- /* ------------------------ */
-
- /*
- * Get handler associated with a window.
- *
- * Return nil if window doesn't belong to any known handler.
- *
- * This routine is absolutely fundamental to TransSkel.
- */
-
-
- static WHHandle
- GetWHandler (WindowPtr w)
- {
- WHHandle h;
-
- if (w == (WindowPtr) nil)
- return ((WHHandle) nil);
-
- if (w == oldWindow)
- return (oldWHandler); /* return handler of cached window */
-
- for (h = whList; h != (WHHandle) nil; h = (**h).whNext)
- {
- if ((**h).whWind == w)
- {
- oldWindow = w; /* set cached window and handler */
- oldWHandler = h;
- return (h);
- }
- }
- return ((WHHandle) nil);
- }
-
-
- /*
- * Detach a handler from the handler list and destroy it.
- *
- * Clear window cache variable, just in case it points to the window
- * whose hander is being destroyed (and thus has become invalid).
- */
-
- static void
- DetachWHandler (WHHandle wh)
- {
- WHHandle h, h2;
-
- if (whList != (WHHandle) nil) /* if list empty, ignore */
- {
- if (whList == wh) /* is it the first element? */
- {
- h2 = whList;
- whList = (**whList).whNext;
- }
- else for (h = whList; h != (WHHandle) nil; h = h2)
- {
- h2 = (**h).whNext;
- if (h2 == (WHHandle) nil)
- return; /* handler not in list! (huh?) */
- if (h2 == wh) /* found it */
- {
- (**h).whNext = (**h2).whNext;
- break;
- }
- }
- DisposeHandle ((Handle) h2); /* get rid of handler record */
- }
-
- oldWindow = (WindowPtr) nil; /* clear window cache variables */
- oldWHandler = (WHHandle) nil;
- }
-
-
- /* ------------------------------------------------------- */
- /* Menu handler installation/removal/modification routines */
- /* ------------------------------------------------------- */
-
-
- /*
- * Install handler for a menu. Remove any previous handler for it.
- * Pass the following parameters:
- *
- * theMenu
- * Handle to the menu to be handled. Must be created by host.
- * doSelect
- * Proc that handles selection of items from menu. If this is
- * nil, the menu is installed, but nothing happens when items
- * are selected from it.
- * doClobber
- * Proc for disposal of handler's data structures. Usually
- * nil for menus that remain in menu bar until program
- * termination.
- * subMenu
- * True if the menu is a submenu (not installed in menu bar).
- * drawBar
- * True if menu bar is to be drawn after menu is installed.
- * (Ignored if the menu is a submenu.)
- *
- * Return true if successful, false if no handler could be allocated.
- */
-
- pascal Boolean
- SkelMenu (MenuHandle m,
- SkelMenuSelectProcPtr doSelect,
- SkelMenuClobberProcPtr doClobber,
- Boolean subMenu,
- Boolean drawBar)
- {
- MHHandle mh;
- Boolean oldFlag;
-
- oldFlag = mhClobOnRmve; /* remove any previous handler for */
- mhClobOnRmve = false; /* menu, without redrawing menu bar */
- SkelRmveMenu (m);
- mhClobOnRmve = oldFlag;
-
- if ((mh = New (MHandler)) != (MHHandle) nil)
- {
- (**mh).mhNext = mhList;
- mhList = mh;
- (**mh).mhID = (**m).menuID; /* get menu id number */
- (**mh).mhSelect = doSelect; /* install selection handler */
- (**mh).mhClobber = doClobber; /* install disposal handler */
- (**mh).mhSubMenu = subMenu; /* set submenu flag */
- /* install menu in menu bar if not a submenu */
- InsertMenu (m, subMenu ? -1 : 0);
- }
- if (drawBar && !subMenu)
- DrawMenuBar ();
- return ((Boolean) (mh != (MHHandle) nil));
- }
-
-
- /*
- * Remove a menu handler. This calls the handler's menu disposal
- * routine and then takes the handler out of the handler list and
- * disposes of it. The menu bar is redrawn if the menu was not a
- * submenu and the global redraw flag hasn't been cleared.
- *
- * The menu MUST be deleted from the menu bar before calling the
- * clobber proc. Otherwise the menu bar will end up filled with
- * garbage if the menu was allocated with NewMenu (IM I-352).
- */
-
- pascal void
- SkelRmveMenu (MenuHandle m)
- {
- short mID;
- MHHandle h, h2;
- SkelMenuClobberProcPtr p;
-
- mID = (**m).menuID;
- if (mhList != (MHHandle) nil) /* if list empty, ignore */
- {
- if ((**mhList).mhID == mID) /* is it the first element? */
- {
- h2 = mhList;
- mhList = (**mhList).mhNext;
- }
- else
- {
- for (h = mhList; h != (MHHandle) nil; h = h2)
- {
- h2 = (**h).mhNext;
- if (h2 == (MHHandle) nil)
- return; /* menu not in list! */
- if ((**h2).mhID == mID) /* found it */
- {
- (**h).mhNext = (**h2).mhNext;
- break;
- }
- }
- }
- DeleteMenu (mID);
- if (mhDrawBarOnRmve && !(**h2).mhSubMenu)
- DrawMenuBar ();
- if (mhClobOnRmve
- && (p = (**h2).mhClobber) != (SkelMenuClobberProcPtr) nil)
- (*p) (m); /* call disposal routine */
- DisposeHandle ((Handle) h2); /* get rid of handler record */
- }
- }
-
-
- /*
- * General menu-selection handler. Just passes selection to the handler's
- * select routine. If the select routine is nil, selecting items from
- * the menu is a nop.
- */
-
- static void
- DoMenuCommand (long command)
- {
- short menu;
- short item;
- MHHandle mh;
-
- menu = HiWord (command);
- item = LoWord (command);
- for (mh = mhList; mh != (MHHandle) nil; mh = (**mh).mhNext)
- {
- if (menu == (**mh).mhID && (**mh).mhSelect != (SkelMenuSelectProcPtr) nil)
- {
- (*(**mh).mhSelect) (item);
- break;
- }
- }
- HiliteMenu (0); /* command done, turn off menu hiliting */
- }
-
-
- /*
- * Menu is about to be pulled down or command-key executed. Call menu
- * hook if there is one so application can set menus/items appropriately.
- */
-
- static void
- DoMenuHook (void)
- {
- if (pMenuHook != (SkelMenuHookProcPtr) nil)
- (*pMenuHook) ();
- }
-
-
- pascal void
- SkelSetMenuHook (SkelMenuHookProcPtr p)
- {
- pMenuHook = p;
- }
-
-
- pascal SkelMenuHookProcPtr
- SkelGetMenuHook (void)
- {
- return (pMenuHook);
- }
-
-
- /* ------------------------ */
- /* Window property routines */
- /* ------------------------ */
-
-
- /*
- * Add a property to a window. Fail if the window is unregistered
- * or can't allocate memory for a new property structure. If the
- * window already has such a property, fail.
- *
- * Returns a handle to the new property for success, nil for failure.
- */
-
- pascal Boolean
- SkelAddWindProp (WindowPtr w, short propType, long propData)
- {
- WHHandle wh;
- SkelWindPropHandle ph;
-
- if (propType == skelWPropAll)
- return (false);
- if ((ph = SkelGetWindProp (w, propType)) != (SkelWindPropHandle) nil)
- return (false);
- /* if window is unregistered, or can't allocate structure, fail */
- if ((wh = GetWHandler (w)) == (WHHandle) nil
- || (ph = New (SkelWindProperty)) == (SkelWindPropHandle) nil)
- return (false);
- (**ph).skelWPropType = propType;
- (**ph).skelWPropData = propData;
- (**ph).skelWPropNext = (**wh).whProperties;
- (**wh).whProperties = ph;
- return (true);
- }
-
-
- /*
- * Remove a window property. Does nothing if the window isn't
- * registered or if the window doesn't have the given property.
- *
- * If propType is skelWPropAll, SkelRmveWindProp() calls itself
- * recursively to remove all the properties on a window. This
- * means that if you put skelWPropAll into the skelWPropType field
- * of a property, you'll get an infinite loop here.
- */
-
- pascal void
- SkelRmveWindProp (WindowPtr w, short propType)
- {
- WHHandle wh;
- SkelWindPropHandle ph, ph2, pNext;
-
- if ((wh = GetWHandler (w)) == (WHHandle) nil
- || (ph = SkelGetWindProp (w, propType)) == (SkelWindPropHandle) nil)
- return;
-
- if (propType == skelWPropAll) /* remove all properties */
- {
- while ((ph = (**wh).whProperties) != (SkelWindPropHandle) nil)
- SkelRmveWindProp (w, (**ph).skelWPropType);
- return;
- }
-
- /* remove particular property */
- if ((ph2 = (**wh).whProperties) == ph) /* remove first in list */
- (**wh).whProperties = (**ph).skelWPropNext;
- else
- {
- while ((pNext = (**ph2).skelWPropNext) != (SkelWindPropHandle) nil)
- {
- if (pNext == ph)
- {
- (**ph2).skelWPropNext = (**ph).skelWPropNext;
- break;
- }
- ph2 = pNext;
- }
- }
- DisposeHandle ((Handle) ph);
- }
-
-
- /*
- * Find the given property for the window. Fail if window is
- * unregistered or has no such property.
- */
-
- pascal SkelWindPropHandle
- SkelGetWindProp (WindowPtr w, short propType)
- {
- WHHandle wh;
- SkelWindPropHandle ph = (SkelWindPropHandle) nil;
-
- if ((wh = GetWHandler (w)) != (WHHandle) nil)
- {
- if (propType == skelWPropAll) /* return head of list */
- ph = (**wh).whProperties;
- else for (ph = (**wh).whProperties; ph != (SkelWindPropHandle) nil; ph = (**ph).skelWPropNext)
- {
- if ((**ph).skelWPropType == propType)
- break;
- }
- }
- return (ph);
- }
-
-
- /*
- * Find the data value for a given property for the window. Return 0 if window
- * is unregistered or has no such property.
- *
- * If you need to be able to distinquish an error return from a valid zero-value
- * data value, you should call SkelGetWindProp() instead, check for an error,
- * and extract the data value if there was no error.
- *
- * skelWPropAll is not a valid properly type for this call.
- */
-
- pascal long
- SkelGetWindPropData (WindowPtr w, short propType)
- {
- SkelWindPropHandle ph;
-
- ph = SkelGetWindProp (w, propType);
- if (ph != (SkelWindPropHandle) nil)
- return ((**ph).skelWPropData);
- return (0);
- }
-