[comp.sys.apple2] Argh! That blasted StartUpTools

JWANKERL@UTCVM.BITNET ("Josef W. Wankerl") (05/29/90)

Okay, here we go again...
   I am working on a NDA which needs to start up some tools.  So
   I take the easy way out, I use the Tool Locator's StartUpTools ()
   function.  Apparently this doesn't like to work all the time.
   Since I'm inside a NDA I can't always be sure which tools I'll
   need so I have to check and build my Start/Stop record on the fly.
   I really don't want to break down and start allocating direct page
   memory and calling the individual StartUp calls myself, but alas,
   it looks like that's what I'm going to end up doing unless someone
   can shed some light on this problem.  So here goes:

Upon entering this function (oh yeah, I'm using ORCA/C 1.1 B11 -- thanx
 a bunch Mike and Patty! :-) I have all the nonchanging (flags, etc.)
 fields of my global structure, myTools, pre-initialized so all I
 should have to do is go through and add the tools I want to my
 start/stop array (which is properly declared, don't worry).  This
 function returns a true (1) value if the tools were started up
 correctly and a false (0) value if they weren't because
 StartUpTools () returned an error.  Unfortunately, this is not
 happening!!!  More details about this after the source code.  A
 global variable, toolsloaded, is also set so I can tell if I had to
 start any tools myself and so my Close function will call
 ShutDownTools ().

So without any further delay, I present my source code for inspection:

int StartTools (void)
{
   int errornumber;
   int loadokay = 1;

   toolsloaded = 0;
   myTools.numTools = 0;

   if (!IMStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x000B;

   if (!QDAuxStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x0012;

   if (!SFStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x0017;

   if (!FMStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x001B;

   if (!ListStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x001C;

   if (!TEStatus ())
      myTools.whichTools[myTools.numTools++].toolNumber = 0x0022;

   if (myTools.numTools)
   {
      programID = GetNewID (0x5100);
      toolref = StartUpTools (programID, 0, (Long) &myTools);
      if (!(loadokay = (!(errornumber = toolerror ()))))
         ErrorWindow (0, NULL, errornumber);

      toolsloaded = 1;
      InitCursor ();
   }

   return loadokay;
}

Got it?

Okay, so here's what's happening.  In the Finder, three of the six
tools are not active so I need to start them up.  Those three are the
Font Manager, Standard File, and TextEdit.  So I build my start/stop
structure appropriately, and then call StartUpTools (), which gives a
0 return value!  BAD, BAD STARTUPTOOLS!  It leaves the Font Manager
inactive!!!  The only reason I can think of why this might happen is
because I'm not asking for the Integer Math tools to be started as
well, but StartUpTools () should not care.  This code works
beautifully in some situations, but fails miserably in others.  It
took me many moons to figure out StartUpTools () is lying to me.
Somebody proove me wrong, please.  I want to live a simple life...

--
===> Josef W. Wankerl, college student | "I am a Viking"  -Y. Malmsteen
 ProLine:  jwankerl@pro-gsplus         | BITNET:  JWANKERL@UTCVM
InterNet:  jwankerl@pro-gsplus.cts.com | UUCP:  ...crash!pro-gsplus!jwankerl
ARPA/DDN:  ...crash!pro-gsplus!jwankerl@nosc.mil | I'm employed by EGO, GS+!

dlyons@Apple.COM (David A. Lyons) (06/27/90)

This reply is a little late, but Oh Well....

In article <9005291535.AA26340@apple.com> JWANKERL@UTCVM.BITNET ("Josef W. Wankerl") writes:
>   I am working on a NDA which needs to start up some tools.  So
>   I take the easy way out, I use the Tool Locator's StartUpTools ()
>   function.

This is a scary thing.  StartUpTools is really intended to be used by
applications.  For one thing, it's going to do an OpenResourceFile
on a pathname that is currently built from prefix 1 and the result
of the GS/OS call GET_NAME, which gives the current application name.
This means StartUpTools is probably going to open the current app's
resource fork a second time, adding it to the resource search path
for your NDA's user ID.  This won't usually cause any harm, but it
will at least prevent the application from closing and reopening its
own resource fork for read/write access, which some applications need
to do.

> [...]
> global variable, toolsloaded, is also set so I can tell if I had to
> start any tools myself and so my Close function will call
> ShutDownTools ().

Shutting down tools in your Close function is probably a bad idea.
Consider what would happen if I installed TWO copies of your NDA,
opened the first, opened the second, and then closed the FIRST.  The
second copy would still be open, but some of the tools it expects
would already be shut down.  I usually recommend shutting down tools
at DeskShutDown time (your DA's Init routine gets called then, with
a flag saying whether it's for StartUp or ShutDown).

>[...]
>   if (!QDAuxStatus ())
>      myTools.whichTools[myTools.numTools++].toolNumber = 0x0012;

I have *not* looked at the code that gets generated for this in ORCA/C,
but I suspect the results of xxxStatus are undefined in the case that
the toolset is not loaded.  The Status functions are inside the toolsets,
so if they aren't there the tool dispatcher returns error 1 or 2, but the
function result on the stack is unchanged--you get back whatever the
compiler pushed as room-for-result, which is probably garbage (whatever
was in A, for example).

The following may work, but I'd have to check the resulting code to make sure:

    if(!QDAuxStatus() || _toolErr) ...

>      programID = GetNewID (0x5100);
>      toolref = StartUpTools (programID, 0, (Long) &myTools);

It would be better to use your REAL user ID, as returned by MMStartUp.
Why?  For one thing, it's simpler.  For another, by feeding it to
StartUpTools you're feeding it to ResourceStartUp, and you're losing
the benefit of having the system automatically call SetCurResourceApp
for you whenever it calls your NDA's Action & other routines.
-- 
David A. Lyons, Apple Computer, Inc.      |   DAL Systems
Apple II Developer Technical Support      |   P.O. Box 875
America Online: Dave Lyons                |   Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
   
My opinions are my own, not Apple's.

jason@madnix.UUCP (Jason Blochowiak) (07/04/90)

In article <42396@apple.Apple.COM> dlyons@Apple.COM (David A. Lyons) writes:
 [Deleted most of the original article]
>It would be better to use your REAL user ID, as returned by MMStartUp.
>Why?  For one thing, it's simpler.  For another, by feeding it to
>StartUpTools you're feeding it to ResourceStartUp, and you're losing
>the benefit of having the system automatically call SetCurResourceApp
>for you whenever it calls your NDA's Action & other routines.

	Has this been guaranteed? I thought that this was something that was
true, but may not be at some point in the future. I may be behind on the
tech notes - last ones I have are those on _A Disc Called Wanda_...

	Has engineering given much/any thought to adding something to the
Desk Mgr to coordinate the way that NDA's use tools? It seems that NDA & tool
interaction is a source of a major amount of confusion, and, as such, a cause
of problems.

>David A. Lyons, Apple Computer, Inc.      |   DAL Systems
>Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons


-- 
                      Jason Blochowiak - jason@madnix.UUCP
or, try:         astroatc!nicmad!madnix!jason@spool.cs.wisc.edu
       "Education, like neurosis, begins at home." - Milton R. Saperstein

dlyons@Apple.COM (David A. Lyons) (07/05/90)

In article <1417@madnix.UUCP> jason@madnix.UUCP (Jason Blochowiak) writes:
>In article <42396@apple.Apple.COM> dlyons@Apple.COM (David A. Lyons) writes:
>[...]
>>It would be better to use your REAL user ID, as returned by MMStartUp.
>>Why?  For one thing, it's simpler.  For another, by feeding it to
>>StartUpTools you're feeding it to ResourceStartUp, and you're losing
>>the benefit of having the system automatically call SetCurResourceApp
>>for you whenever it calls your NDA's Action & other routines.
>
>Has this been guaranteed? I thought that this was something that was
>true, but may not be at some point in the future.

Is which part guaranteed?  Technical notes guarantee that it's okay to
call MMStartUp whenever you feel like it, to get the ID of the memory
block you're in.  A technical note coming out in the July batch by yours
truly talks about the Desk Manager calling SetCurResourceApp for you
when it calls your NDA routines.

>Has engineering given much/any thought to adding something to the
>Desk Mgr to coordinate the way that NDA's use tools? It seems that NDA & tool
>interaction is a source of a major amount of confusion, and, as such, a cause
>of problems.

I believe this is an area where your input would be helpful.  I am
interested in making it easier to use tools from NDAs, but I don't have
all the answers.
-- 
David A. Lyons, Apple Computer, Inc.      |   DAL Systems
Apple II Developer Technical Support      |   P.O. Box 875
America Online: Dave Lyons                |   Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
   
My opinions are my own, not Apple's.

JWANKERL%UTCVM@PUCC.PRINCETON.EDU ("Josef W. Wankerl") (07/06/90)

prefix, 4 Jul 90 22:46:31 GMT David A. Lyons said:
>(Stuff Killed)  Technical notes guarantee that it's okay to
>call MMStartUp whenever you feel like it, to get the ID of the memory
>block you're in.  A technical note coming out in the July batch by yours
>truly talks about the Desk Manager calling SetCurResourceApp for you
>when it calls your NDA routines.

Okay, so now I'll call MMStartUp to get an ID for my NDA, and then
MMShutDown when I no longer need my ID, right?

>
>>Has engineering given much/any thought to adding something to the
>>Desk Mgr to coordinate the way that NDA's use tools? It seems that NDA & tool
>>interaction is a source of a major amount of confusion, and, as such, a cause
>>of problems.
>
>I believe this is an area where your input would be helpful.  I am
>interested in making it easier to use tools from NDAs, but I don't have
>all the answers.

Okay, here's my thought that I brought up to Matt D. at the last
AppleFest, but he didn't like it too much.  Maybe someone else will.
Add another set of calls to the Desk Manager named NowNeedsTool() and
NoLongerNeedsTool().  NowNeedsTool will take a list of tools that a NDA
requires to operate and start them up if they aren't already.  It will
then return an ID to the program that NoLongerNeedsTool will take.
By calling one central routine to start and stop tools, this will ensure
that the tools are always there for the DA that needs them.
NoLongerNeedsTool will take the ID returned by NowNeedsTool and check
to see if another ID needs that tool.  If so, it is left alone.  If not,
the tool is shut down.  Simple and elegant, I think.

Old NDA's that start and stop tools all by themselves should continue
to work with this method, too.  If they follow the rules, they won't
start things already started or shut things down that they didn't start.

So whatcha think?

>--
>David A. Lyons, Apple Computer, Inc.      |   DAL Systems
>Apple II Developer Technical Support      |   P.O. Box 875
>America Online: Dave Lyons                |   Cupertino, CA 95015-0875
>GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
>Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
>
>My opinions are my own, not Apple's.

--
===> Josef W. Wankerl, college student | "I am a Viking"  -Y. Malmsteen
 ProLine:  jwankerl@pro-gsplus         | BITNET:  JWANKERL@UTCVM
InterNet:  jwankerl@pro-gsplus.cts.com | UUCP:  ...crash!pro-gsplus!jwankerl
ARPA/DDN:  ...crash!pro-gsplus!jwankerl@nosc.mil | I'm employed by EGO, GS+!

toddpw@tybalt.caltech.edu (Todd P. Whitesel) (07/07/90)

dlyons@Apple.COM (David A. Lyons) writes:

[ in reply to ]
>>Has engineering given much/any thought to adding something to the
>>Desk Mgr to coordinate the way that NDA's use tools? It seems that NDA & tool
>>interaction is a source of a major amount of confusion, and, as such, a cause
>>of problems.

>I believe this is an area where your input would be helpful.  I am
>interested in making it easier to use tools from NDAs, but I don't have
>all the answers.

I came up with a simple solution to this problem because I am working on a set
of graphics tools and I want them to be able to run in the desktop environment
without any of these silly problems. The Tool interface in the GS does not
exploit the power of the UserID system enough, and the UserID system allows
us to solve this resource arbitration problem by rewriting certain tools. There
are kludge ways to do what I am about to propose, but the tools for which it
will hurt badly need replacement anyway... In my view, system software
integrity and robustness is more important than backwards compatibility,
especially now when the only serious developers left are dedicated enough to
happily revise their software in order to make everyone's life easier.

I know that Apple has always been a stickler for backwards compaitibility, but
their are times when you have to make a choice between two worthy goals, and
the future of the machine is ALWAYS more important than its past. (The recent
extensions to ProDOS -- lowercase filenames and dual-forked files -- were
implemented in a manner which insults the original designers of ProDOS. ProDOS
directories allow you to specify the length of a directory entry and a version
number which would have allowed for an orderly addition of case and resource
fork information. I would love to hear why this was not done.)

Multi-Client tool usage procedure:
	Call tool Status. If it is inactive, you load it or restore it from a
purged state (If possible. Does the standard tool startup procedure do this for
you already?)
	Start up the tool and hand it a derived UserID. Any blocks allocated by
the tool set for your program will carry this ID. You may start it up again
with a new ID if you wish (one ID per open document, perhaps); so may an NDA or
CDA. The Tool will keep track of every ID it has been started up with, but will
not accept a MasterID as a startup argument. If you use the ID for other data,
be careful (see shutdown, below).
	Use the tool for whatever evil purposes. Mine initially will be GIF
decoding, palette crunching, and fill mode animation experiments.
	When you are finished using the tool, Shut it down with the ID you gave
it in the startup call. If you hand it a MasterID then the tool will treat it
intelligently, i.e. all derivatives of that ID which have been used to start
the tools will be shut down. Shutdown MAY call DisposeAll so don't allocate
anything else with an ID passed to the tools unless you are ready to accept the
consequences.
	Check the tool's status. If it is no longer active then you should
unload the tool or mark it purgeable or something. If the Tool Locator doesn't
already do this then I would like to mark the tool purgeable and leave
a Message telling where to find it if it hasn't been purged, but I don't know
of any way to get a Message Type (other than calling DTS).

Can anybody blow holes in this? All programs must follow the same algorithm
for it to work, and now that I think about it the Tool Locator probably does
the load/unload stuff for you, and the only change I am suggesting to the
normal tool procedure is in the Tool itself -- the Tool does not actually shut
down until all its users have shut down.

Matt/Dave: what's the official word on Tool management? Can an application
explicitly dispose of a Tool or force it to be reloaded from disk even if it
is active or restartable? I sincerely hope not, because it endangers this
scheme and puts serious dampers on any hope for a multitasking yet robust GS.

Todd Whitesel
toddpw @ tybalt.caltech.edu

dlyons@Apple.COM (David A. Lyons) (07/08/90)

In article <9007071530.AA09375@apple.com> JWANKERL%UTCVM@PUCC.PRINCETON.EDU ("Josef W. Wankerl") writes:
>Okay, so now I'll call MMStartUp to get an ID for my NDA, and then
>MMShutDown when I no longer need my ID, right?

MMStartUp doesn't _allocate_ an ID for you--it only tells you the ID that
you already have (that is, it returns the ID owning the memory block that
you're calling from).  Your NDA already "has" an ID, which the system
previously allocated using GetNewID.

Don't call MMShutDown, because you're *not* through with your ID...your
DA's code is still in memory with that ID (see description of MMShutDown
in TB Ref 1).

If you want to do a DisposeAll, don't do it with the ID MMStartUp returns--
instead, you can fiddle with the auxID field ($0x00), allocate blocks with
that modified ID, and DisposeAll only on a modified ID (see GS Technical
Note #17, "Application Memory Management and the MMStartUp ID"--some of the
wisdom in there applies to non-applications).

>[...]
>Add another set of calls to the Desk Manager named NowNeedsTool() and
>NoLongerNeedsTool().  NowNeedsTool will take a list of tools that a NDA
>requires to operate and start them up if they aren't already.  It will
>then return an ID to the program that NoLongerNeedsTool will take.
>By calling one central routine to start and stop tools, this will ensure
>that the tools are always there for the DA that needs them.
>NoLongerNeedsTool will take the ID returned by NowNeedsTool and check
>to see if another ID needs that tool.  If so, it is left alone.  If not,
>the tool is shut down.  Simple and elegant, I think.

I'm noture about -simple-, but it sounds like a reasonable start.  It
wouldn't even have to be new functions--StartUpTools and ShutDownTools
(which are currently *not* recommended for NDA use under 5.0.x!) have
plenty of extra bits in the startStopRefDesc if needed.

Maybe StartUpTools/ShutDownTools could keep a list of all the "active"
startStopToolsRecs (I don't think they currently do) and be intelligent
about when to actually shut things down.

This still leaves big questions about LoadOneTool, UnloadOneTool,
LoadTools, StartUpTools, ShutDownTools, and *all* xxxStartUp and
xxxShutDown functions, which applications and DAs are allowed to
call directly (after all, they were around before SUT/SDT were).

For example, there would have to be a mechanism preventing an
application from shutting down a tool that it originally started
but that is not being used by a DA.  I think the system would have
to intercept all startup and shutdown functions and be selective
about letting them execute.  UnloadOneTool would have to be handled
similarly.

Food for thought.
-- 
David A. Lyons, Apple Computer, Inc.      |   DAL Systems
Apple II Developer Technical Support      |   P.O. Box 875
America Online: Dave Lyons                |   Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
   
My opinions are my own, not Apple's.

dlyons@Apple.COM (David A. Lyons) (07/08/90)

In article <1990Jul7.044559.4967@laguna.ccsf.caltech.edu> toddpw@tybalt.caltech.edu (Todd P. Whitesel) writes:
[I (Dave L) said: ]
>>I believe this is an area where your input would be helpful.  I am
>>interested in making it easier to use tools from NDAs, but I don't have
>>all the answers.

>I came up with a simple solution to this problem because I am working on a set
>of graphics tools and I want them to be able to run in the desktop environment
>without any of these silly problems.

Please elaborate on the context here--your tools *are* going to be used as
User Toolsets, called through the $E10008/$E1000C dispatch vectors, right?
(Stealing System Toolset numbers is obviously bad, so I'll assume for now
you're not doing that.)

If you want your user toolsets to be usable by NDAs as well as applications,
I thinka large amount of caution is in order here, since all user toolset
numbers are owned by the current *application*, and there is no guarantee
that a DA will be able to call them.  (For example, what if there was a
"Switcher" environment some day?  User Toolsets would have to be swapped in
and out depending on what application had control, so they might or might
not be there when a NDA got control.)

It doesn't seem to me that that the tool dispatcher can currently provide
a safe way for third-party toolsets to be shared by applications and DAs.

On the other hand, the Message Center does (see MessageCenter in the Tool
Locator chapter of TB Ref 2 and MessageByName in the Tool Locator chapter
of TB Ref 3).  You can define the procedure for using your routines something
like this:  (1) Check the Message Center for a named message giving you the
4-byte entry point of your routines.  If the message was there, great--you
can call it.  (2) If the message wasn't there, use InitialLoad to get the
routines off disk, and call the code so it can initialize itself and publish
its entry point in the Message Center.  (The routines can have startup and
shutdown calls that count the number of users--when it gets shut down to 0
it can remove the MessageCenter message and return "Okay, you can call
UserShutDown on this ID now).


>[...] In my view, system software
>integrity and robustness is more important than backwards compatibility,
>especially now when the only serious developers left are dedicated enough to
>happily revise their software in order to make everyone's life easier.
>
>I know that Apple has always been a stickler for backwards compaitibility, but
>their are times when you have to make a choice between two worthy goals, and
>the future of the machine is ALWAYS more important than its past.

Your reasoning works both ways--a diminished "serious developer base" means
it's especially important to stay compatible with products that are out there
that are *not* going to be revised.

I'm perfectly willing to invent New and Preferred Ways of Doing Things, as
long as they don't make things *worse* for software that was written to
work as was recommended at the time.

I *don't* think we have to decide between one or the other of backwards
compatibility and improving the system.  I think it's practical to consider
both at the same time.


>[...] (The recent
>extensions to ProDOS -- lowercase filenames and dual-forked files -- were
>implemented in a manner which insults the original designers of ProDOS. ProDOS
>directories allow you to specify the length of a directory entry and a version
>number which would have allowed for an orderly addition of case and resource
>fork information. I would love to hear why this was not done.)

Life isn't that simple.  Here are two practical reasons *not* to change the
length of a ProDOS directory entry and have new features depend on it:

1. Directories created under "new" system software would have larger
   directory entries, while the old directories would have the old-
   sized entries.  So you grab a floppy and you don't know whether you
   will be able to put a lower-case name on there or not, and you don't
   know whether you will be able to create an extended file or not.

   (I don't think it would be good to have the system automatically
   extend the entry length of *existing* directories.)
   
   In other words, which do you prefer?
     (1) What we have now, or
     (2) Users being confused by alerts like:
             Can't create resource fork ($7x).
         or
             Sorry, could not create an extended file on
             :FLOPPY.  Please create a new folder or format
             a new disk, and save your file there instead.

   This, I think, would qualify as Icky and Really Weird.

2. A fair amount of popular software would stop working.  (Try it
   yourself--make a ProDOS disk with a larger entry length and smaller
   entPerBlock.)


>Multi-Client tool usage procedure:
>Call tool Status. If it is inactive, you load it or restore it from a
>purged state (If possible. Does the standard tool startup procedure do this
>for you already?)

(Ack!  You're proposing major changes to tool set management without
detailed knowledge of how things work presently.  I don't know how you
did it, but most of your ideas came out reasonable anyway.)

YES, LoadOneTool (and LoadTools and StartUpTools) automatically take
care of trying to Restart (a Loader function) a tool set that has been
put into a dormant purgable state.  UnloadOneTool (and ShutDownTools and
TLShutDown) automatically take care of putting tool sets into dormant
state by calling UserShutDown (another Loader function) with the right
flags.

>Start up the tool and hand it a derived UserID. Any blocks allocated by
>the tool set for your program will carry this ID. You may start it up again
>with a new ID if you wish (one ID per open document, perhaps); so may an NDA or
>CDA. The Tool will keep track of every ID it has been started up with, but will
>not accept a MasterID as a startup argument. If you use the ID for other data,
>be careful (see shutdown, below).

By "derived UserID" do you mean one with a nonzero auxiliary ID ($1002 =
master ID, $1102,$1202,...,$1f02 = derived IDs)?  If so, this doesn't
seem practical--there are only 15 derived IDs per master ID, and an app
could easily use more than 15 tool sets.

>[...]
>When you are finished using the tool, Shut it down with the ID you gave
>it in the startup call.
>[...]
>Check the tool's status. If it is no longer active then you should
>unload the tool or mark it purgeable or something.

This is a probably a reasonable approach for *your* tool set, since you're
inventing it and get to define how it's used.

To address the general problem of several *existing* applications using
the same tool set, the system would have to field UnloadOneTool calls
and screen some of them out--applications are justified in calling
UnloadOneTool on a tool set that they just shut down.

>If the Tool Locator doesn't
>already do this then I would like to mark the tool purgeable and leave
>a Message telling where to find it if it hasn't been purged, but I don't know
>of any way to get a Message Type (other than calling DTS).

Tool set code in RAM gets marked purgable when UnloadOneTool or TLShutDown
is called (these call UserShutDown in the Loader).  The loader Restart
function tells you where the code is when you want it back, so there is no
need for the Message Center here.

(By the way, if you *do* ever want to use the Message Center, there is no
need to get assigned a message type.  You can use MessageByName instead--
see GS Toolbox Reference Volume 3, Tool Locator chapter.)

>Can anybody blow holes in this? All programs must follow the same algorithm
>for it to work, [...] the only change I am suggesting to the
>normal tool procedure is in the Tool itself -- the Tool does not actually shut
>down until all its users have shut down.

The principle is good, but the details get Weird when you need to stay
compatible with existing rules.  (For what it's worth, note that the
system could, if it wanted to, check the memory manager ID of the caller,
by doing a FindHandle on the return address.  That means the parameters
to xxxStartUp and xxxShutDown functions would *not* have to be changed
to implement a count-the-startups scheme.)

>Matt/Dave: what's the official word on Tool management? Can an application
>explicitly dispose of a Tool or force it to be reloaded from disk even if it
>is active or restartable? I sincerely hope not, because it endangers this
>scheme and puts serious dampers on any hope for a multitasking yet robust GS.

Applications can do a lot of things, but the amount of "force" behind those
things is debatable.  For example, applications can call UnloadOneTool when
they're done using a tool, but that doesn't mean UnloadOneTool actually has
to unload it!  There are a lot of possibilities.

>Todd Whitesel
>toddpw @ tybalt.caltech.edu
-- 
David A. Lyons, Apple Computer, Inc.      |   DAL Systems
Apple II Developer Technical Support      |   P.O. Box 875
America Online: Dave Lyons                |   Cupertino, CA 95015-0875
GEnie: D.LYONS2 or DAVE.LYONS         CompuServe: 72177,3233
Internet/BITNET:  dlyons@apple.com    UUCP:  ...!ames!apple!dlyons
   
My opinions are my own, not Apple's.