tim@hoptoad.uucp (Tim Maroney) (05/02/90)
In article <21747@dartvax.Dartmouth.EDU> sean@eleazar.dartmouth.edu (Sean P. Nolan) writes: >Objective: to have a dialog pop up everytime an application is launched so > that the user can choose whether or not to install a small utility. >approach: patch _LoadSeg so that it watches for somebody loading code #1. > If they are, we know an application is being launched. We want to > wait until the app. has done it's initialization before popping > the dialog. So, we patch _GetNextEvent to (A) show the dialog > and (B) unpatch itself so that our dialog is only shown once per > application startup. Problem 1 -- application may never call GetNextEvent. Modern applications use WaitNextEvent if it's available. Problem 2 -- you are assuming the application will not itself patch GNE. If it does, your "unpatch" can't work. Problem 3 -- because of the strange way it works, LoadSeg is about the last trap you ever want to patch. Use an alternative, like InitDialogs. >To show the dialog, I do the following: at system startup, I GetResource the >itemlist, and detach and nopurge the handle. I then use NewDialog to bring >up the box. > >Problems: 1. The dialog never gets ahold of the itemlist. It puts up a box > with nothing in it at all. > 2. After dropping out of _ModalDialog, I call the normal _GNE > proc, which works for a second and then bombs. Which, to me, seems to imply you're not handling the item list correctly. Possible problems: You need not only to GetResource, detach, and unpurge the item list -- you also need to make sure it's in the system heap, or it will go away as soon as your INIT finishes running. Another: You can't just attach the item list to the DialogRecord; you also have to iterate over the items and initialize them, particularly controls. There's a tech note which has a detailed append routine you can use. (TN #95) Yet another: Don't attach the actual item list, or it will get freed when you close the dialog -- instead, build a copy in memory. Yet another: Don't *call* the old GetNextEvent -- that's a tail patch. Your routine should do something like returning to an outer shell of assembly language, popping the stack frame back to its state when you were called, and jumping to the old routine address. A popular way of doing this last part is to push the old address and then RTS, but I always put the old address into a scratch register and jump to it instead (if I can -- beware of register-based traps). Personally, if I were doing this, I'd go ahead and do a tail patch, but do it on InitDialog and forget the whole GNE/WNE charade: it's too complicated. How can I actually recommend a tail patch? Simple -- InitDialogs is called in one very well-defined place, from an application startup. The chance of it being called by any system software, and so the chance of acquiring a come-from check which would screw up a tail patch, is so slim as to be worth forgetting. So call the old InitDialogs first, forget about unpatching, and then go on and call your mysterious one-per-launch dialog before returning from your InitDialogs patch. >Any help? I'm about to kill myself. Thanks in advance... Don't jump off a bridge; it's not a reliable method. (That's a joke, son. I'll feel like a real cad if you really do it.) -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com FROM THE FOOL FILE: "In any religion or form of worship, followers should be allowed to think for themselves. In every religion that has a god other than Jesus Christ, adherents are not allowed to think for themselves." -- Lauren Stratford, "Satan's Underground"
tim@hoptoad.uucp (Tim Maroney) (05/02/90)
One more problem with this -- GetNextEvent or WaitNextEvent will be called from ModalDialog.... -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com It is not only fallacious to ignore points, or to answer them solely with preconceived and contrived arguments: it is also very, very rude. Someone who behaves in this way has only themselves to blame if things become heated.
jeremyr@cs.qmw.ac.uk (Jeremy Roussak) (05/09/90)
In article <11282@hoptoad.uucp> tim@hoptoad.UUCP (Tim Maroney) writes: > >Yet another: Don't *call* the old GetNextEvent -- that's a tail >patch. Your routine should do something like returning to an outer >shell of assembly language, popping the stack frame back to its state >when you were called, and jumping to the old routine address. A >popular way of doing this last part is to push the old address and then >RTS, but I always put the old address into a scratch register and jump >to it instead (if I can -- beware of register-based traps). > >Personally, if I were doing this, I'd go ahead and do a tail patch, >but do it on InitDialog and forget the whole GNE/WNE charade: it's >too complicated. How can I actually recommend a tail patch? Simple -- >InitDialogs is called in one very well-defined place, from an application >startup. The chance of it being called by any system software, and so >the chance of acquiring a come-from check which would screw up a tail >patch, is so slim as to be worth forgetting. So call the old InitDialogs >first, forget about unpatching, and then go on and call your mysterious >one-per-launch dialog before returning from your InitDialogs patch. Tim raises an interesting point here: is it *ever* OK to tail patch? The reason I'm interested is that I want to write (well, have written in fact) an INIT that intercepts a menu selection from a certain application and does something else when a particular item is chosen. Now, the easy way to do this is to tail patch MenuSelect, and this is what I've done. I know about all the no-nos, but it works (at the moment). The difficult way, it seems to me, is to write a jGNEFilter patch that detects mouseDown events, find out where they are and simulates MenuSelect. Seems tedious, boring and rather like re-inventing the wheel: if there's a perfectly good MenuSelect routine already in my Mac's ROM, why should I write another? All advice gratefully received, and comments welcome. No flames, please. Jeremy Roussak and no, it's not the sound-on-emptying-the-trash again (for anyone who remembers the last tail patching flame wars)