[comp.sys.mac.programmer] Dialog from a Trap

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)