mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 01:49:19 +00:00
1248 lines
34 KiB
C
1248 lines
34 KiB
C
/*
|
||
File: DAHandler.c
|
||
|
||
Contains: The System Desk Accessory Handler application
|
||
|
||
Written by: Phil Goldman
|
||
|
||
Copyright: © 1986-1993 by Apple Computer, Inc., all rights reserved.
|
||
|
||
Change History (most recent first):
|
||
|
||
<SM18> 7/21/93 joe Back out <SM17>.
|
||
<16> 9/25/92 DRF Get rid of MyGestalt
|
||
<15> 4/10/92 JSM Undo revision 14, we fixed the problem someplace else.
|
||
<14> 4/4/92 DTY #1019369,<FM>: For each desk accessory, remember the current
|
||
keyboard state, and the keyboard state after the driver has been
|
||
opened. On a resume, set the keyboard to the state the driver
|
||
left it, and on a suspend, set it to the original state.
|
||
<13> 3/23/92 JSM OSEvents.h is obsolete, use Events.h.
|
||
<12> 1/9/92 DTY In CleanupAndExit, check to see if there are any more desk
|
||
accessories running. If there aren’t, unload the DAHandler
|
||
segment. ThereAreMoreDeskAccessories ripped off from scott’s 7
|
||
Up code. Also unload Init and %A5Init in main() after DAHandler
|
||
is done with them.
|
||
<11> 11/1/91 DTY TOPMAPHANDLE should be set to the top system override map in
|
||
SetupMenus so DA’s can enjoy overridden system resources too.
|
||
Also, use the generic desk accessory icon if the desk accessory
|
||
is in a system override map.
|
||
<10> 4/4/91 DFH VL, WS#DFH-910404a : Fixed CloseDACleanupAndExit to be more
|
||
careful about a non-existent driver table entry.
|
||
<9> 1/10/91 DFH (dba) Got rid of InForeground, since it was just left over from
|
||
the sleep time calculation that got removed.
|
||
<7> 1/8/91 DFH (dba) Removed stack shrinkage from StartupCode() since stack
|
||
requirement is greater now that modal dialogs can call menu
|
||
select.
|
||
<6> 1/3/91 fjs (DFH) handle edit function keys
|
||
<5> 1/3/91 DFH (fjs) OpenTheDeskAccessory() was setting the myDriverRefnum
|
||
global to the OpenDeskAcc result. This is bad in the case that
|
||
the result was not a real refnum, since our cleanup/exit code
|
||
relies on it being -1 or a refnum. This resulted in wiping out
|
||
random memory as we tried to MemClear() the DCE in
|
||
CloseDACleanupAndExit().
|
||
<4> 12/10/90 DFH Added custom icon support.
|
||
<3> 12/5/90 DFH Remove sleep time calculation. Scheduler will do that for us
|
||
now.
|
||
<2> 11/19/90 DFH Robustified ExitToShell patch. Was same as Quit command, which
|
||
is not good in crash cases. Now sets myUnitNumber and
|
||
myDriverRefNum as early as possible, so we can deal with
|
||
ExitToShell in OpenDeskAcc (need to close driver if it got
|
||
open).
|
||
<0> x/xx/86 PYG New Today.
|
||
|
||
*/
|
||
|
||
#include <types.h>
|
||
#include <memory.h>
|
||
#include <resources.h>
|
||
#include <quickdraw.h>
|
||
#include <fonts.h>
|
||
#include <events.h>
|
||
#include <windows.h>
|
||
#include <dialogs.h>
|
||
#include <controls.h>
|
||
#include <menus.h>
|
||
#include <textedit.h>
|
||
#include <devices.h>
|
||
#include <desk.h>
|
||
#include <toolutils.h>
|
||
#include <errors.h>
|
||
#include <osutils.h>
|
||
#include <segload.h>
|
||
#include <diskinit.h>
|
||
#include <sound.h>
|
||
#include <GestaltEqu.h>
|
||
#include <Palettes.h>
|
||
#include <Icons.h>
|
||
#include <IconUtilsPriv.h>
|
||
#include <traps.h>
|
||
#include <Processes.h>
|
||
#include <Layers.h>
|
||
#include <ResourceMgrPriv.h>
|
||
|
||
#include "Lomem.h"
|
||
#include "SysMisc.h"
|
||
#include "Glue.h"
|
||
|
||
#undef assert
|
||
#ifdef DEBUG
|
||
#define assert(exp) {if (!(exp)) SysError(dsCoreErr);}
|
||
#else
|
||
#define assert(exp)
|
||
#endif DEBUG
|
||
|
||
/*
|
||
* Menu ID constants. These are the positive counterparts of the resource IDs.
|
||
*/
|
||
#define appleID 16473
|
||
#define fileID 16472
|
||
#define editID 16471
|
||
|
||
/*
|
||
* Menu item constants.
|
||
*/
|
||
#define appleMenu 0
|
||
#define aboutMeCommand 1
|
||
#define fileMenu 1
|
||
#define closeCommand 1
|
||
#define quitCommand 2
|
||
#define editMenu 2
|
||
#define undoCommand 1
|
||
#define cutCommand 3
|
||
#define copyCommand 4
|
||
#define pasteCommand 5
|
||
#define clearCommand 6
|
||
|
||
#define menuCount 3
|
||
|
||
/*
|
||
* For the About… DLOG
|
||
*/
|
||
#define aboutMeDLOG (-16473)
|
||
#define okButton 1
|
||
#define daIcon 2
|
||
#define daNameItem 3
|
||
#define firstAboutString 4
|
||
#define secondAboutString 5
|
||
#define AlertID_OutOfMem (-16472)
|
||
#define DitlID_OutOfMem (-16472)
|
||
#define AlertID_NotFound (-16471)
|
||
#define DitlID_NotFound (-16471)
|
||
#define StrID_InSysFile (-16471)
|
||
|
||
/* Extra slop to get up alert: Window, icon, etc. */
|
||
#define ALERT_SLOP_SIZE 0x800
|
||
|
||
/* Masks and a macro to ensure alignment of counts and addresses. Word alignment is
|
||
* required by the 68000 for non-byte pointer refereneces. Note that the result of
|
||
* WORD_ALIGN is the same as the original if the original was already word-aligned.
|
||
* Long alignment is for 68020 (and up) efficiency in general, and is a requirement
|
||
* of blocks in a 32-bit mode heap.
|
||
*/
|
||
#define LONGALIGN_MASK 0xFFFFFFFC
|
||
#define WORDALIGN_MASK 0xFFFFFFFE
|
||
#define LONG_ALIGN(value) (value = ((value + sizeof(long) - 1) & LONGALIGN_MASK))
|
||
#define WORD_ALIGN(value) (value = ((value + sizeof(short) - 1) & WORDALIGN_MASK))
|
||
#define LONG_ALIGNED(value) (((value) & (sizeof(long) - 1)) == 0)
|
||
#define WORD_ALIGNED(value) (((value) & (sizeof(short) - 1)) == 0)
|
||
|
||
/* HIWORD and LOWORD macros, for readability. */
|
||
#define HIWORD(aLong) (((aLong) >> 16) & 0xFFFF)
|
||
#define LOWORD(aLong) ((short)(aLong))
|
||
|
||
/* Macro to look up a particular byte in a pascal string */
|
||
#define StringByte(pStr, byteIndex) (*((char *) pStr + byteIndex + 1))
|
||
|
||
/* Macros for Resource Mgr peeking */
|
||
#define isNotDARefNum(refNum) (((refNum) >= 0) || ((refNum) <= -UNITNTRYCNT))
|
||
#define MapRefNumOffset 20
|
||
#define TopResFile() (*((short *) (*TOPMAPHANDLE + MapRefNumOffset)))
|
||
#define IsSystemRefNum(refNum) ((refNum == SYSMAP) || (refNum == 0))
|
||
|
||
/* Bit assignments in the dCtlFlags of a driver control block */
|
||
#define DNeedLock (1<<(8+6)) /* Driver will be locked when opened? */
|
||
#define DNeedTime (1<<(8+5)) /* Does driver need periodic control calls? */
|
||
#define DNeedGoodbye (1<<(8+4)) /* Does driver need a goodbye kiss? */
|
||
#define DStatEnable (1<<(8+3)) /* Can driver respond to Status calls? */
|
||
#define DCtlEnable (1<<(8+2)) /* Can driver respond to Control calls? */
|
||
#define DWritEnable (1<<(8+1)) /* Can driver respond to Write calls? */
|
||
#define DReadEnable (1<<(8+0)) /* Can driver respond to Read calls? */
|
||
#define DActive (1<<7) /* Is driver currently executing? */
|
||
#define DRamBased (1<<6) /* Is driver RAM-based? */
|
||
#define DOpened (1<<5) /* Is driver already open? */
|
||
|
||
/* Symbols for values of the asych parameter of HFS calls */
|
||
#define AsyncHFS true
|
||
#define SyncHFS false
|
||
|
||
/* Function prototypes */
|
||
void main(void);
|
||
void StartupCode(void);
|
||
void SetupMenus(void);
|
||
void DoCommand(long);
|
||
void OpenTheDeskAccessory(void);
|
||
OSErr PreflightDA(void);
|
||
void HandleCloseDA(short);
|
||
void CloseDACleanupAndExit(Boolean);
|
||
void ExitToShellPatch(void);
|
||
void MemClear(Ptr, unsigned long);
|
||
void PutUpDeathAlert(OSErr);
|
||
Boolean IsDrvrOpen(void);
|
||
|
||
/* Functions imported from DAHandler.a */
|
||
void CloseFrontDeskWindow(void);
|
||
void ClosePatch(void);
|
||
void SystemEventPatch(void);
|
||
StringPtr GetSysHeapString(void);
|
||
Handle GetMapHdlFromRefNum(short, Handle);
|
||
void InitAboutMeDialog(void);
|
||
|
||
/* From %A5Init */
|
||
extern void _DataInit();
|
||
|
||
/*
|
||
* Global Data objects.
|
||
*/
|
||
MenuHandle MyMenus[menuCount]; /* The menu handles */
|
||
Ptr oldCloseAddress; /* Address of old _Close routine */
|
||
Ptr oldSystemEventAddress; /* Address of old _SystemEvent routine */
|
||
Ptr oldExitToShellAddress; /* Address of old _ExitToShell routine */
|
||
short doneFlag; /* Time to quit yet? */
|
||
Boolean Colorized; /* Whether this machine has color capability */
|
||
Boolean Has32BitQD; /* Whether this machine has 32-bit QuickDraw */
|
||
short myFileRefNum; /* Refnum of file holding the DRVR */
|
||
short myDriverRefNum; /* Refnum of driver resource */
|
||
short myUnitNumber; /* the UNITTABLE index of my DA */
|
||
short myDisplayIconID; /* Resource ID of icon and info strings */
|
||
short wdShrinkOfAboutMe, htOfAboutMeStrings, htOfFirstAboutString, htOfSecondAboutString;
|
||
StringHandle hFirstAboutMeString, hSecondAboutMeString;
|
||
#define SetPSN(X, dst) {(dst)->highLongOfPSN = 0; (dst)->lowLongOfPSN = (X);}
|
||
|
||
/* ThereAreMoreDeskAccessories. Returns true if there are other desk accessories running. */
|
||
Boolean
|
||
ThereAreMoreDeskAccessories()
|
||
{
|
||
int count = 0;
|
||
ProcessSerialNumber psn = { 0, kNoProcess };
|
||
ProcessInfoRec info;
|
||
|
||
info.processInfoLength = sizeof(ProcessInfoRec);
|
||
info.processName = nil;
|
||
info.processAppSpec = nil;
|
||
|
||
while (GetNextProcess(&psn) == noErr)
|
||
{
|
||
if (GetProcessInformation(&psn, &info) == noErr)
|
||
{
|
||
if (info.processMode & modeDeskAccessory)
|
||
{
|
||
++count;
|
||
if (1 < count)
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
return (1 < count);
|
||
}
|
||
|
||
/* CleanupAndExit. Remove any trace of our existence. */
|
||
void
|
||
CleanupAndExit(void)
|
||
{
|
||
/* Restore zone (prudent) and remove our patches */
|
||
THEZONE = APPLZONE;
|
||
NSetTrapAddress((long)oldCloseAddress, (short) _Close, OSTrap);
|
||
NSetTrapAddress((long)oldSystemEventAddress, (short) _SystemEvent, ToolTrap);
|
||
NSetTrapAddress((long)oldExitToShellAddress, (short) _ExitToShell, ToolTrap);
|
||
|
||
// <12> If there are no other desk accessories running, unload DAHandler.
|
||
|
||
if (!ThereAreMoreDeskAccessories())
|
||
UnloadSeg((Ptr) main);
|
||
|
||
/* Tell OS to destroy us altogether */
|
||
ExitToShell();
|
||
}
|
||
|
||
/* GiveGoodByeKiss. Give this driver a goodbye kiss if it wants one. */
|
||
GiveGoodByeKiss(DCtlPtr dCtlPtr)
|
||
{
|
||
CntrlParam goodByeParamBlock;
|
||
|
||
/* Give him a goodbye kiss, if necessary */
|
||
if ((dCtlPtr->dCtlFlags & DNeedGoodbye) != 0)
|
||
{
|
||
goodByeParamBlock.csCode = csCodeGoodBye;
|
||
goodByeParamBlock.ioCRefNum = dCtlPtr->dCtlRefNum;
|
||
PBControl(&goodByeParamBlock, SyncHFS);
|
||
}
|
||
}
|
||
|
||
/* MemClear. Two-bit routine to clear 'bytes' bytes starting at *'ptr' */
|
||
void
|
||
MemClear(register Ptr ptr, register unsigned long bytes)
|
||
{
|
||
do
|
||
{
|
||
*ptr++ = (char) 0x00;
|
||
}
|
||
while (--bytes != 0);
|
||
|
||
}
|
||
|
||
/* ExitToShellPatch. Our patch to ExitToShell. Give the driver a fighting chance at
|
||
* cleaning up
|
||
* NOTE: The etsDepth counter is to keep us from additional flailing if we are
|
||
* forced to ExitToShell even as we are closing the DA.
|
||
*/
|
||
void
|
||
ExitToShellPatch(void)
|
||
{
|
||
static short etsDepth = 0;
|
||
|
||
/* Try to do it nice. Then just do it. */
|
||
A5Restore(CURRENTA5);
|
||
if (etsDepth++ == 0)
|
||
CloseDACleanupAndExit(false);
|
||
else
|
||
CleanupAndExit();
|
||
}
|
||
|
||
/* CloseDACleanupAndExit. Patch for _ExitToShell. Gives the DA a chance to
|
||
* cancel (i.e. by leaving windows up).
|
||
*/
|
||
void
|
||
CloseDACleanupAndExit(Boolean beNice)
|
||
{
|
||
register DCtlPtr dCtlPtr;
|
||
register DCtlHandle dCtlHdl;
|
||
|
||
A5Restore(CURRENTA5);
|
||
if (myDriverRefNum != 0)
|
||
CloseDeskAcc(myDriverRefNum);
|
||
|
||
/* Quit if the DA did */
|
||
if ((beNice == false) || (FrontWindow() == nil))
|
||
{
|
||
if (myUnitNumber != 0)
|
||
{
|
||
dCtlHdl = ((DCtlHandle) UNITTABLE[myUnitNumber]);
|
||
if ((dCtlHdl != nil) && (dCtlPtr = *dCtlHdl) != nil)
|
||
{
|
||
if ((dCtlPtr->dCtlFlags & (DNeedGoodbye | DOpened)) == (DNeedGoodbye | DOpened))
|
||
GiveGoodByeKiss(dCtlPtr);
|
||
MemClear(dCtlPtr, sizeof(DCtlEntry));
|
||
dCtlPtr->dCtlRefNum = myDriverRefNum;
|
||
}
|
||
}
|
||
|
||
CleanupAndExit();
|
||
}
|
||
}
|
||
|
||
typedef struct MP
|
||
{
|
||
struct MP *pNextMP;
|
||
} MP;
|
||
|
||
/* Determine whether the current zone has at least the given number
|
||
* of free master pointers.
|
||
*/
|
||
Boolean
|
||
ThisManyMPs(unsigned short cMinAcceptableMPs)
|
||
{
|
||
MP *pCurMP;
|
||
|
||
for (pCurMP = (MP *)THEZONE->hFstFree; pCurMP != nil; pCurMP = pCurMP->pNextMP)
|
||
if (--cMinAcceptableMPs == 0)
|
||
return true;
|
||
|
||
return false;
|
||
}
|
||
|
||
#define MIN_ACCEPTABLE_MPS 32
|
||
|
||
#define kFunctionKey 0x10
|
||
#define kUndo 0x7A
|
||
#define kCut 0x78
|
||
#define kCopy 0x63
|
||
#define kPaste 0x76
|
||
|
||
void
|
||
main(void)
|
||
{
|
||
EventRecord myEvent;
|
||
WindowPtr whichWindow;
|
||
static Point bmPt = {100,100}; /* ULH pt of Disk Err dialog */
|
||
#define MAXSLEEPTIME (0xFFFFFFFF) /* largest value of WaitNextEvent sleep */
|
||
|
||
StartupCode();
|
||
|
||
/* Force all into system heap */
|
||
THEZONE = SYSZONE;
|
||
|
||
/* Because we are about to use this heap heavily */
|
||
if (ThisManyMPs(MIN_ACCEPTABLE_MPS) == false)
|
||
MoreMasters();
|
||
|
||
/* Get the sucker open */
|
||
OpenTheDeskAccessory();
|
||
|
||
// <12> Now that DAHandler is up and running, it’s Init and %A5Init segments can be
|
||
// unloaded.
|
||
|
||
UnloadSeg((Ptr) StartupCode); // <12> Unload Init
|
||
UnloadSeg((Ptr) _DataInit); // <12> Unload %A5Init
|
||
|
||
/* The event loop */
|
||
for (;;)
|
||
{
|
||
short thereIsAnEvent;
|
||
|
||
if (doneFlag)
|
||
CloseDACleanupAndExit(true);
|
||
|
||
/*
|
||
* Handle the next event.
|
||
*/
|
||
|
||
/* Anybody out there? */
|
||
thereIsAnEvent = WaitNextEvent(everyEvent, &myEvent, MAXSLEEPTIME, nil);
|
||
|
||
/* NOTE: This should be done after _WNE also, in case of DAs like Intermail
|
||
* that close themselves on the fly (in _SystemTask). We do the processing
|
||
* after waking up, which is now.
|
||
*/
|
||
if (doneFlag)
|
||
CloseDACleanupAndExit(true);
|
||
|
||
/* check for timeout */
|
||
if (!thereIsAnEvent || myEvent.what == nullEvent)
|
||
continue;
|
||
|
||
switch (myEvent.what)
|
||
{
|
||
case mouseDown:
|
||
switch (FindWindow(myEvent.where, &whichWindow))
|
||
{
|
||
case inSysWindow:
|
||
SystemClick(&myEvent, whichWindow);
|
||
break;
|
||
case inMenuBar:
|
||
DoCommand(MenuSelect(myEvent.where));
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case keyDown:
|
||
if (myEvent.modifiers & cmdKey)
|
||
DoCommand(MenuKey((char)myEvent.message));
|
||
else
|
||
{
|
||
unsigned char key;
|
||
unsigned char virtualKey;
|
||
|
||
key = (char) myEvent.message;
|
||
virtualKey = (myEvent.message & keyCodeMask) >> 8;
|
||
|
||
if (key == kFunctionKey)
|
||
{
|
||
switch (virtualKey)
|
||
{
|
||
case kUndo:
|
||
key = 'Z';
|
||
break;
|
||
|
||
case kCut:
|
||
key = 'X';
|
||
break;
|
||
|
||
case kCopy:
|
||
key = 'C';
|
||
break;
|
||
|
||
case kPaste:
|
||
key = 'V';
|
||
break;
|
||
|
||
default:
|
||
key = 0;
|
||
break;
|
||
}
|
||
|
||
if (key) // if we mapped it then menukey
|
||
DoCommand(MenuKey(key));
|
||
}
|
||
}
|
||
break;
|
||
|
||
case diskEvt:
|
||
if (*((short *)&myEvent.message) != noErr)
|
||
(void)DIBadMount(bmPt, myEvent.message);
|
||
break;
|
||
|
||
case app4Evt:
|
||
break;
|
||
|
||
/* default:
|
||
* break;
|
||
*/
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Initialization code: unload this segment when done with it.
|
||
*/
|
||
#pragma segment Init
|
||
|
||
/* InitConfig. Find out what sort of software/hardware setup we're dealing with.
|
||
* NOTE: This is the place to make any costly determinations about our environment
|
||
* for later time savings. None such, yet.
|
||
*/
|
||
void
|
||
InitConfig(void)
|
||
{
|
||
long qdInfo;
|
||
|
||
Colorized = false;
|
||
Has32BitQD = false;
|
||
|
||
if (Gestalt(gestaltQuickdrawVersion,&qdInfo) == noErr)
|
||
{
|
||
qdInfo &= 0xFFFF;
|
||
Colorized = (qdInfo >= gestalt8BitQD);
|
||
Has32BitQD = (qdInfo >= gestalt32BitQD);
|
||
}
|
||
}
|
||
|
||
/* SetupMenus. Set up the Apple, and Edit menus.
|
||
* NOTE: If the MENU resources are missing, we die.
|
||
*/
|
||
void
|
||
SetupMenus(void)
|
||
{
|
||
extern MenuHandle MyMenus[];
|
||
register MenuHandle *pMenu;
|
||
Handle prevTop;
|
||
short topFile;
|
||
|
||
/* Set up the desk accessories menu. The "About…" item, followed by a grey
|
||
* line, is presumed to be already in the resource. We then append the desk
|
||
* accessory names from the 'DRVR' resources. We copy the menu because
|
||
* each DA Handle needs its own version of the common menu resource. HandToHand
|
||
* into the application heap means that dispose is automatic, even on crash.
|
||
* NOTE: We have to sidestep the DA file itself, since it has DRVR resource(s) and
|
||
* AddResMenu always uses the whole chain.
|
||
*/
|
||
MyMenus[appleMenu] = GetMenu(-appleID);
|
||
HandToHand(&MyMenus[appleMenu]);
|
||
|
||
topFile = CURMAP;
|
||
prevTop = TOPMAPHANDLE;
|
||
CURMAP = SYSMAP;
|
||
TOPMAPHANDLE = GetOverrideMap(SYSMAPHANDLE);
|
||
AddResMenu(MyMenus[appleMenu], (ResType) 'DRVR');
|
||
TOPMAPHANDLE = prevTop;
|
||
CURMAP = topFile;
|
||
|
||
/*
|
||
* Now File, Edit menus.
|
||
*/
|
||
MyMenus[fileMenu] = GetMenu(-fileID);
|
||
MyMenus[editMenu] = GetMenu(-editID);
|
||
|
||
/*
|
||
* Now insert all of the application menus in the menu bar.
|
||
*/
|
||
for (pMenu = &MyMenus[0]; pMenu < &MyMenus[menuCount]; ++pMenu)
|
||
InsertMenu(*pMenu, 0);
|
||
|
||
DrawMenuBar();
|
||
|
||
return;
|
||
}
|
||
|
||
void
|
||
StartupCode(void)
|
||
{
|
||
/* Clear global flag that tells us when to quit */
|
||
doneFlag = 0;
|
||
|
||
/* Initialization traps, pretty much required */
|
||
MaxApplZone();
|
||
InitConfig();
|
||
InitGraf(&qd.thePort);
|
||
InitFonts();
|
||
InitWindows();
|
||
InitMenus();
|
||
TEInit();
|
||
InitDialogs(nil);
|
||
InitCursor();
|
||
FlushEvents(everyEvent, 0);
|
||
myDriverRefNum = 0;
|
||
myUnitNumber = 0;
|
||
|
||
SetupMenus();
|
||
|
||
/* Patch _Close to check for closing desk accessories */
|
||
oldCloseAddress = (Ptr)NGetTrapAddress((short) _Close, OSTrap);
|
||
NSetTrapAddress((long)ClosePatch, (short) _Close, OSTrap);
|
||
|
||
/* Patch _SystemEvent so we can handle cmd-Q and cmd-W */
|
||
oldSystemEventAddress = (Ptr)NGetTrapAddress((short) _SystemEvent, ToolTrap);
|
||
NSetTrapAddress((long)SystemEventPatch, (short) _SystemEvent, ToolTrap);
|
||
|
||
/* Patch _ExitToShell to check for closing desk accessories, so that
|
||
* we can handle ES from MacsBug.
|
||
*/
|
||
oldExitToShellAddress = (Ptr)NGetTrapAddress((short) _ExitToShell, ToolTrap);
|
||
NSetTrapAddress((long)ExitToShellPatch, (short) _ExitToShell, ToolTrap);
|
||
}
|
||
|
||
/* GetRsrcHdlMatchingFirstLongword. Find the first resource of specified type that
|
||
* has the given value in its first long word. Scope is current file.
|
||
*/
|
||
Handle
|
||
GetRsrcHdlMatchingFirstLongword(long resType, long firstLong)
|
||
{
|
||
Handle hdl;
|
||
short resIndex, resLast;
|
||
|
||
resLast = Count1Resources(resType);
|
||
for (resIndex = 1; resIndex <= resLast; resIndex++)
|
||
{
|
||
hdl = Get1IndResource(resType, resIndex);
|
||
if (hdl != nil)
|
||
{
|
||
if (**((long **) hdl) == firstLong)
|
||
return (hdl);
|
||
ReleaseResource(hdl);
|
||
}
|
||
}
|
||
|
||
return (nil);
|
||
}
|
||
|
||
/* GetIconIDFromBundle. Figure out the icon family resource ID for the given type and
|
||
* creator. Starts at the current resource map. Uses the same search path that Finder
|
||
* does (FREF -> BNDL -> icon resource).
|
||
*/
|
||
short
|
||
GetIconIDFromBundle(OSType theType, unsigned long theCreator)
|
||
{
|
||
Ptr pRsrc;
|
||
short typeIndex, icnIndex;
|
||
Handle rsrcHdl;
|
||
short localID, globalID;
|
||
|
||
/* Find the FREF of the type */
|
||
rsrcHdl = GetRsrcHdlMatchingFirstLongword('FREF', theType);
|
||
if (rsrcHdl == nil)
|
||
return(0);
|
||
|
||
pRsrc = *rsrcHdl + 4;
|
||
localID = *((short *) pRsrc);
|
||
ReleaseResource(rsrcHdl);
|
||
|
||
/* Get the BNDL */
|
||
rsrcHdl = GetRsrcHdlMatchingFirstLongword('BNDL', theCreator);
|
||
if (rsrcHdl == nil)
|
||
return(0);
|
||
|
||
pRsrc = *rsrcHdl + 6;
|
||
|
||
/* Major loop -- find global id of icon in bundle */
|
||
globalID = 0;
|
||
for (typeIndex = *((short *) pRsrc)++; typeIndex >= 0; typeIndex--)
|
||
{
|
||
/* Is this type ICN# ? */
|
||
if (*((long *) pRsrc)++ == 'ICN#')
|
||
{
|
||
/* Minor loop - find a match for our given local ID and get it */
|
||
for (icnIndex = *((short *) pRsrc)++; icnIndex >= 0; icnIndex--)
|
||
{
|
||
if (*((short *) pRsrc)++ == localID)
|
||
{
|
||
/* Found it! */
|
||
globalID = *((short *) pRsrc);
|
||
break;
|
||
}
|
||
|
||
pRsrc += 2;
|
||
}
|
||
|
||
/* Either we found it or we looked at all icons */
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
/* Skip over all of this type's resources, carefully because count
|
||
* is zero-based.
|
||
*/
|
||
((long *) pRsrc) += *((short *) pRsrc)++;
|
||
((long *) pRsrc)++;
|
||
}
|
||
}
|
||
|
||
/* Clean up and go */
|
||
ReleaseResource(rsrcHdl);
|
||
return(globalID);
|
||
}
|
||
|
||
/* GetDisplayIconID. Return the resource ID of the DA's icon family. */
|
||
short
|
||
GetDisplayIconID(void)
|
||
{
|
||
ProcessInfoRec procInfo;
|
||
short retval;
|
||
FInfo finderInfo;
|
||
FSSpec fileSpec;
|
||
|
||
/* Nothing special if in the system file or an override map */
|
||
if (IsThisASystemResourceMap(TOPMAPHANDLE))
|
||
return(genericDeskAccessoryIconResource);
|
||
|
||
/* Get process info for search */
|
||
procInfo.processInfoLength = sizeof(ProcessInfoRec);
|
||
procInfo.processName = nil;
|
||
procInfo.processAppSpec = &fileSpec;
|
||
SetPSN(kCurrentProcess, &(procInfo.processNumber));
|
||
if (GetProcessInformation(&procInfo.processNumber, &procInfo) != noErr)
|
||
return(genericDeskAccessoryIconResource);
|
||
|
||
/* Try for custom icon first. If not custom, use our type and signature in
|
||
* BNDL lookup.
|
||
*/
|
||
if ((FSpGetFInfo(&fileSpec, &finderInfo) == noErr) && ((finderInfo.fdFlags & FILE_FLAG_HAS_CUSTOM_ICON) != 0))
|
||
retval = kCustomIconID;
|
||
else if ((retval = GetIconIDFromBundle(procInfo.processType, procInfo.processSignature)) == 0)
|
||
retval = genericDeskAccessoryIconResource;
|
||
|
||
return(retval);
|
||
}
|
||
|
||
/* ID of owned resources for the "about me" dialog */
|
||
#define OWN_ABOUT_ME_ID (1)
|
||
#define OWN_DLOG_PROTO (OWNED_BY_DRVR | OWN_ABOUT_ME_ID)
|
||
|
||
#define STANDARD_DLOG_WIDTH (260)
|
||
|
||
/* InitAboutMeDialog. Figure out the strings and offsets we'll need to set up the
|
||
* "about me" dialog. The dialog has (among other things) two static text items
|
||
* positioned one atop the other. The texts are supplied by resources, and both
|
||
* are optional. If just one is missing, the other goes in the top position. Sets
|
||
* the hFirstAboutMeString, hSecondAboutMeString, wdShrinkOfAboutMe, htOfAboutMeStrings,
|
||
* htOfFirstAboutString, and htOfSecondAboutString.
|
||
*/
|
||
void
|
||
InitAboutMeDialog(void)
|
||
{
|
||
DialogRecord dialogRecord;
|
||
|
||
THEZONE = APPLZONE;
|
||
|
||
/* Set defaults in case we don't want or can't get everything */
|
||
wdShrinkOfAboutMe = 0;
|
||
htOfAboutMeStrings = 0;
|
||
htOfFirstAboutString = 0;
|
||
htOfSecondAboutString = 0;
|
||
hFirstAboutMeString = nil;
|
||
hSecondAboutMeString = nil;
|
||
|
||
/* Determine resource ID of display icon. Use it to locate the info strings. */
|
||
if ((myDisplayIconID = GetDisplayIconID()) != genericDeskAccessoryIconResource)
|
||
hFirstAboutMeString = Get1Resource('dast', myDisplayIconID);
|
||
|
||
/* If DA is from the system file, get the informative string */
|
||
if ((hSecondAboutMeString = (IsSystemRefNum(myFileRefNum)) ? GetResource('STR ', StrID_InSysFile) : nil) != nil)
|
||
{
|
||
DetachResource(hSecondAboutMeString);
|
||
HNoPurge(hSecondAboutMeString);
|
||
}
|
||
|
||
/* Determine the lineup */
|
||
if (hFirstAboutMeString == nil)
|
||
{
|
||
hFirstAboutMeString = hSecondAboutMeString;
|
||
hSecondAboutMeString = nil;
|
||
}
|
||
else
|
||
HandToHand(&hFirstAboutMeString);
|
||
|
||
if (GetNewDialog(aboutMeDLOG, &dialogRecord, (WindowPtr) -1) != nil)
|
||
{
|
||
if (hFirstAboutMeString != nil)
|
||
{
|
||
short itemType;
|
||
Handle itemHdl;
|
||
Rect itemRect1, itemRect2;
|
||
short lineHeight;
|
||
register StringHandle hStr;
|
||
GrafPtr savePort;
|
||
|
||
GetPort(&savePort);
|
||
SetPort(&dialogRecord);
|
||
GetDItem(&dialogRecord, secondAboutString, &itemType, &itemHdl, &itemRect2);
|
||
GetDItem(&dialogRecord, firstAboutString, &itemType, &itemHdl, &itemRect1);
|
||
itemRect1.bottom = itemRect1.top+100;
|
||
SetDItem(&dialogRecord, firstAboutString, editText, itemHdl, &itemRect1);
|
||
lineHeight = (*dialogRecord.textH)->lineHeight;
|
||
|
||
hStr = hFirstAboutMeString;
|
||
do
|
||
{
|
||
short numLines;
|
||
|
||
HLock(hStr);
|
||
SetIText(itemHdl, *hStr);
|
||
HUnlock(hStr);
|
||
numLines = (*dialogRecord.textH)->nLines;
|
||
if (hStr != hFirstAboutMeString)
|
||
{
|
||
htOfSecondAboutString = numLines * lineHeight;
|
||
htOfAboutMeStrings += (itemRect2.top - itemRect1.top) + htOfSecondAboutString;
|
||
break;
|
||
}
|
||
htOfAboutMeStrings = htOfFirstAboutString = numLines * lineHeight;
|
||
hStr = hSecondAboutMeString;
|
||
} while (hStr != nil);
|
||
|
||
SetPort(savePort);
|
||
}
|
||
wdShrinkOfAboutMe = (htOfAboutMeStrings != 0) ? 0 : dialogRecord.window.port.portRect.right - dialogRecord.window.port.portRect.left - STANDARD_DLOG_WIDTH;
|
||
CloseDialog(&dialogRecord);
|
||
}
|
||
else
|
||
{
|
||
hFirstAboutMeString = nil;
|
||
hSecondAboutMeString = nil;
|
||
}
|
||
|
||
THEZONE = SYSZONE;
|
||
}
|
||
|
||
/* PutUpDeathAlert. Put up an alert, if there's enough memory. Try to get the memory
|
||
* out of the DA Handler app heap, which should be unaffected by the ravages of what is
|
||
* now a very small sys heap.
|
||
*/
|
||
void
|
||
PutUpDeathAlert(OSErr err)
|
||
{
|
||
Handle slopHdl;
|
||
short alertID;
|
||
|
||
THEZONE = APPLZONE;
|
||
alertID = (err == memFullErr) ? AlertID_OutOfMem : AlertID_NotFound;
|
||
if (GetResource('ALRT', alertID) == nil
|
||
|| GetResource('DITL', alertID) == nil
|
||
|| (slopHdl = NewHandle(ALERT_SLOP_SIZE)) == nil)
|
||
{
|
||
SysBeep(20);
|
||
return;
|
||
}
|
||
|
||
DisposHandle(slopHdl);
|
||
ParamText(CURAPNAME, nil, nil, nil);
|
||
(void)StopAlert(alertID, nil);
|
||
THEZONE = SYSZONE;
|
||
}
|
||
|
||
typedef pascal unsigned long (*GzProcPtr)(unsigned long cbNeeded);
|
||
|
||
/* Without doing actual purging, guarantee there are cbNeeded free or purgeable bytes
|
||
* in THEZONE, including attempts to grow the heap.
|
||
*/
|
||
Boolean
|
||
CanGetThisMuchFreeOrPurgeSpace(long cbNeeded)
|
||
{
|
||
GzProcPtr gzProcPtr = SYSZONE->gzProc;
|
||
|
||
for (;;)
|
||
{
|
||
/* Quit now if enough contiguous space already exists */
|
||
if (SysContigPurgeSpace() >= cbNeeded)
|
||
return true;
|
||
|
||
/* See how much the growzone procedure buys us */
|
||
if (gzProcPtr == nil || (*gzProcPtr)(cbNeeded) == 0)
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/* IsDrvrOpen. Return boolean whether our driver is open. Assumes myUnitNumber. */
|
||
Boolean
|
||
IsDrvrOpen(void)
|
||
{
|
||
DCtlEntry **ppDCtlEntry;
|
||
|
||
ppDCtlEntry = ((DCtlEntry ***)UNITTABLE)[myUnitNumber];
|
||
return (ppDCtlEntry != nil && (((*ppDCtlEntry)->dCtlFlags & DOpened) != 0));
|
||
}
|
||
|
||
|
||
#define DA_SLOP_SIZE 0x2000 /* Min memory a DA need to operate in (a guess) */
|
||
#define TOOLBOX_SLOP_BASE 0x5000 /* Always require at least this much */
|
||
#define TOOLBOX_SLOP_32QD 0x4000 /* Add this much if toolbox has 32-bit QuickDraw */
|
||
#define TOOLBOX_SLOP_COLOR 0x5000 /* Add this much if toolbox has non-32-bit color */
|
||
|
||
/* EstimatedToolboxHeap. Because the DA will be calling toolbox routines using the
|
||
* system heap, if the toolbox takes too much memory, other DAs and/or applications
|
||
* will die. We therefore preflight the system heap. The required amount is hard to
|
||
* predict, but is strongly related to the toolbox capabalitities. This routine makes
|
||
* its estimate by starting at a value for the fundamental toolbox, then adding a weight
|
||
* representative of each capability we have found to be a memory hog.
|
||
* For now, it is felt that color quickdraw is the only thing that greatly
|
||
* contributes. As more hogs are born, check for them here and add an appropriate
|
||
* amount if they exist.
|
||
*/
|
||
long
|
||
EstimatedToolboxHeap(void)
|
||
{
|
||
long requirement;
|
||
|
||
requirement = TOOLBOX_SLOP_BASE;
|
||
|
||
/* Color always requires more, but 32-bit QuickDraw is lesser of two evils */
|
||
if (Has32BitQD)
|
||
requirement += TOOLBOX_SLOP_32QD;
|
||
else
|
||
{
|
||
if (Colorized)
|
||
requirement += TOOLBOX_SLOP_COLOR;
|
||
}
|
||
|
||
return requirement;
|
||
}
|
||
|
||
/* PreflightDA. Determine if there is enough room for a DA in the system heap. */
|
||
OSErr
|
||
PreflightDA(void)
|
||
{
|
||
Handle drvrHdl;
|
||
Handle slopHdl;
|
||
long flags;
|
||
Boolean gotSpace;
|
||
|
||
/* Find the resource. Return error if not found, or not enough room for it. */
|
||
if ((drvrHdl = GetNamedResource('DRVR',CURAPNAME)) == nil)
|
||
return RESERR;
|
||
|
||
/* Take a whack at one of our globals */
|
||
myFileRefNum = HomeResFile(drvrHdl);
|
||
|
||
/* Found the resource, so determine unit table index from resource ID.
|
||
* NOTE: Assumes the best even if we couldn't get resource info.
|
||
*/
|
||
ROMMAPINSERT = -1;
|
||
GetResInfo(drvrHdl, &myUnitNumber, nil, nil);
|
||
if (RESERR != noErr)
|
||
return noErr;
|
||
|
||
/* Base the preliminary settings of the unit number and refnum globals on the
|
||
* resource ID returned by GetResInfo. These will get reset after OpenDeskAcc. We
|
||
* need them now so that we can handle an ExitToShell from inside OpenDeskAcc. If
|
||
* the OpenDeskAcc got far enough, the driver will be open and need to be closed.
|
||
*/
|
||
myDriverRefNum = (-(myUnitNumber + 1));
|
||
|
||
/* No space problem if the driver is already open */
|
||
if (IsDrvrOpen())
|
||
return(noErr);
|
||
|
||
/* Error if there wasn't space for driver. */
|
||
if (*drvrHdl == nil)
|
||
return(memFullErr);
|
||
|
||
/* Make sure there's enough room for everything else, too. But don't let the
|
||
* driver get purged by the check.
|
||
*/
|
||
gotSpace = false;
|
||
flags = HGetState(drvrHdl);
|
||
HNoPurge(drvrHdl);
|
||
if ((slopHdl = NewHandle(DA_SLOP_SIZE)) != nil)
|
||
{
|
||
gotSpace = CanGetThisMuchFreeOrPurgeSpace(EstimatedToolboxHeap());
|
||
DisposHandle(slopHdl);
|
||
}
|
||
HSetState(drvrHdl, flags);
|
||
|
||
return (gotSpace ? noErr : memFullErr);
|
||
}
|
||
|
||
/* OpenTheDeskAccessory. Routine to call when we're ready to open the DA. */
|
||
void
|
||
OpenTheDeskAccessory(void)
|
||
{
|
||
GrafPtr savePort;
|
||
short odaResult;
|
||
MenuHandle appleMenuHdl;
|
||
StringHandle tempStrHdl;
|
||
unsigned char ParamZeroStr[3] = {2, '^','0'};
|
||
StringPtr ptr1, ptr2;
|
||
unsigned long len1, len2;
|
||
OSErr err;
|
||
Str255 strItemName;
|
||
|
||
/* Go to the top of the chain */
|
||
CURMAP = TopResFile();
|
||
|
||
/* Cancel operation if there is not enough memory to work with. */
|
||
if ((err = PreflightDA()) != noErr)
|
||
{
|
||
PutUpDeathAlert(err);
|
||
doneFlag = true;
|
||
return;
|
||
}
|
||
|
||
/* Put DA name in the place of honor */
|
||
appleMenuHdl = MyMenus[appleMenu];
|
||
GetItem(appleMenuHdl, aboutMeCommand, &strItemName);
|
||
if ((tempStrHdl = NewString(strItemName)) != nil)
|
||
{
|
||
ptr1 = (StringPtr) &ParamZeroStr;
|
||
len1 = (unsigned long) Length(ptr1);
|
||
ptr1 = &StringByte(ptr1, 0);
|
||
ptr2 = &StringByte(CURAPNAME, 1);
|
||
len2 = (unsigned long) Length(CURAPNAME) - 1;
|
||
(void) Munger(tempStrHdl, 0, ptr1, len1, ptr2, len2);
|
||
Length(*tempStrHdl) += len2 - len1;
|
||
if (MEMERROR == noErr)
|
||
{
|
||
HLock(tempStrHdl);
|
||
SetItem(appleMenuHdl, aboutMeCommand, *tempStrHdl);
|
||
HUnlock(tempStrHdl);
|
||
}
|
||
DisposHandle(tempStrHdl);
|
||
}
|
||
|
||
/* Do actual open */
|
||
GetPort(&savePort);
|
||
odaResult = OpenDeskAcc(CURAPNAME);
|
||
SetPort(savePort);
|
||
|
||
/* Check whether open failed. */
|
||
if (isNotDARefNum(odaResult))
|
||
{
|
||
doneFlag = true;
|
||
return;
|
||
}
|
||
|
||
/* Base the permanent settings of the unit number and refnum globals on the
|
||
* OpenDeskAcc function result.
|
||
*/
|
||
myDriverRefNum = odaResult;
|
||
myUnitNumber = (-(myDriverRefNum + 1));
|
||
|
||
/* Check whether DA completed already. */
|
||
if (IsDrvrOpen() == false)
|
||
{
|
||
doneFlag = true;
|
||
return;
|
||
}
|
||
|
||
/* Set up the about box dialog. */
|
||
InitAboutMeDialog();
|
||
}
|
||
|
||
#pragma segment Main
|
||
|
||
pascal void
|
||
MyItemProc(WindowPtr theWindow, short itemNum)
|
||
{
|
||
short typ;
|
||
Handle hdl;
|
||
Rect theRect;
|
||
GrafPtr savePort;
|
||
|
||
/* Frame the OK button */
|
||
GetDItem(theWindow, okButton, &typ, &hdl, &theRect);
|
||
PenSize(3, 3);
|
||
InsetRect(&theRect, -4, -4);
|
||
FrameRoundRect(&theRect, 16, 16);
|
||
|
||
/* Plot the icon */
|
||
GetPort(&savePort);
|
||
SetPort(theWindow);
|
||
GetDItem(theWindow, itemNum, &typ, &hdl, &theRect);
|
||
PlotIconID(&theRect, atAbsoluteCenter, ttNone, myDisplayIconID);
|
||
SetPort(savePort);
|
||
}
|
||
|
||
/* showAboutMeDialog. Display the DAHandler Application dialog. */
|
||
void
|
||
showAboutMeDialog(void)
|
||
{
|
||
GrafPtr savePort;
|
||
DialogRecord dialogRecord;
|
||
Handle hDLOG;
|
||
short itemType;
|
||
Handle itemHdl;
|
||
Rect itemRect;
|
||
short itemHit;
|
||
|
||
THEZONE = APPLZONE;
|
||
|
||
GetPort(&savePort);
|
||
|
||
/* Pre-adjust dialog size for optional parts */
|
||
{
|
||
Rect *pRect;
|
||
|
||
if ((hDLOG = GetResource('DLOG', aboutMeDLOG)) == nil)
|
||
return;
|
||
HNoPurge(hDLOG);
|
||
pRect = (Rect *) *hDLOG;
|
||
pRect->right -= wdShrinkOfAboutMe;
|
||
pRect->bottom += htOfAboutMeStrings;
|
||
}
|
||
|
||
/* Allocate a dialog record */
|
||
if (GetNewDialog(aboutMeDLOG, &dialogRecord, (WindowPtr) -1) == nil)
|
||
return;
|
||
|
||
/* Release the resource so that resizing change will not be remembered */
|
||
ReleaseResource(hDLOG);
|
||
|
||
/* Display dialog if there's still enough room */
|
||
if ((hDLOG = NewHandle(ALERT_SLOP_SIZE)) != nil)
|
||
{
|
||
short pixelsNeeded;
|
||
|
||
DisposHandle(hDLOG);
|
||
|
||
SetPort(&dialogRecord);
|
||
AutoPositionWindow((WindowPtr) &dialogRecord, lcMainScreen, hcCenter, vcAlertCenter);
|
||
|
||
/* Set the user item proc address into the icon item */
|
||
GetDItem(&dialogRecord, daIcon, &itemType, &itemHdl, &itemRect);
|
||
SetDItem(&dialogRecord, daIcon, itemType, (Handle) &MyItemProc, &itemRect);
|
||
|
||
/* Set the DA name */
|
||
GetDItem(&dialogRecord, daNameItem, &itemType, &itemHdl, &itemRect);
|
||
SetIText(itemHdl, (StringPtr)CURAPNAME);
|
||
|
||
/* Adjust the first text item length */
|
||
if ((pixelsNeeded = htOfAboutMeStrings) != 0)
|
||
{
|
||
GetDItem(&dialogRecord, firstAboutString, &itemType, &itemHdl, &itemRect);
|
||
itemRect.bottom = itemRect.top + htOfFirstAboutString;
|
||
SetDItem(&dialogRecord, firstAboutString, itemType, itemHdl, &itemRect);
|
||
HLock(hFirstAboutMeString);
|
||
SetIText(itemHdl, *hFirstAboutMeString);
|
||
HUnlock(hFirstAboutMeString);
|
||
|
||
/* Adjust the second text item vertical position and length */
|
||
if (hSecondAboutMeString != nil)
|
||
{
|
||
GetDItem(&dialogRecord, secondAboutString, &itemType, &itemHdl, &itemRect);
|
||
itemRect.top += htOfFirstAboutString;
|
||
itemRect.bottom = itemRect.top + htOfSecondAboutString;
|
||
SetDItem(&dialogRecord, secondAboutString, itemType, itemHdl, &itemRect);
|
||
HLock(hSecondAboutMeString);
|
||
SetIText(itemHdl, *hSecondAboutMeString);
|
||
HUnlock(hSecondAboutMeString);
|
||
}
|
||
}
|
||
|
||
/* Adjust the position of the OK button */
|
||
GetDItem(&dialogRecord, okButton, &itemType, &itemHdl, &itemRect);
|
||
itemRect.bottom += pixelsNeeded;
|
||
itemRect.left -= wdShrinkOfAboutMe;
|
||
itemRect.top += pixelsNeeded;
|
||
itemRect.right -= wdShrinkOfAboutMe;
|
||
MoveControl(itemHdl, itemRect.left, itemRect.top);
|
||
SetDItem(&dialogRecord, okButton, itemType, itemHdl, &itemRect);
|
||
|
||
/* Get this show on the road!
|
||
* NOTE: Must switch back to system heap since ModalDialog and/or WDEF may load
|
||
* resources or allocate memory.
|
||
*/
|
||
ShowWindow(&dialogRecord);
|
||
THEZONE = SYSZONE;
|
||
ModalDialog(nil, &itemHit);
|
||
THEZONE = APPLZONE;
|
||
|
||
SetPort(savePort);
|
||
}
|
||
|
||
CloseDialog(&dialogRecord);
|
||
if (dialogRecord.items != nil)
|
||
DisposHandle(dialogRecord.items);
|
||
|
||
/* Back to the DA zone */
|
||
THEZONE = SYSZONE;
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* Process mouse clicks in menu bar
|
||
*/
|
||
void
|
||
DoCommand(long mResult)
|
||
{
|
||
extern MenuHandle MyMenus[];
|
||
short theMenu, theItem;
|
||
Str255 daName;
|
||
|
||
theItem = LOWORD(mResult);
|
||
theMenu = HIWORD(mResult); /* This is the resource ID */
|
||
|
||
switch (theMenu)
|
||
{
|
||
case appleID:
|
||
if (theItem == aboutMeCommand)
|
||
showAboutMeDialog();
|
||
else
|
||
{
|
||
GrafPtr savePort;
|
||
|
||
GetItem(MyMenus[appleMenu], theItem, &daName);
|
||
GetPort(&savePort);
|
||
(void) OpenDeskAcc(&daName);
|
||
SetPort(savePort);
|
||
}
|
||
break;
|
||
|
||
case fileID:
|
||
switch (theItem)
|
||
{
|
||
case closeCommand:
|
||
CloseFrontDeskWindow();
|
||
break;
|
||
|
||
case quitCommand:
|
||
CloseDACleanupAndExit(true);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
case editID:
|
||
/*
|
||
* If this is for a 'standard' edit item,
|
||
* run it through SystemEdit first.
|
||
* SystemEdit will return FALSE if it's not a system window.
|
||
*/
|
||
SystemEdit(theItem-1);
|
||
}
|
||
|
||
HiliteMenu(0);
|
||
}
|
||
|
||
/* HandleCloseDA. Routine to be called from our Close patch. Shuts down the
|
||
* DA if the DA is asking to close its driver code.
|
||
*/
|
||
void
|
||
HandleCloseDA(short daRefNum)
|
||
{
|
||
ProcessSerialNumber myPSN;
|
||
|
||
if (daRefNum == myDriverRefNum)
|
||
{
|
||
SetPSN(kCurrentProcess, &myPSN);
|
||
(void) WakeUpProcess(&myPSN);
|
||
doneFlag = true;
|
||
}
|
||
}
|