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.