Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!decwrl!pacbell.com!pacbell!well!gurgle@well.sf.ca.us From: gurgle@well.sf.ca.us (Pete Gontier) Newsgroups: comp.sys.mac.programmer Subject: Re: Tracking the mouse. Message-ID: <21455@well.sf.ca.us> Date: 2 Nov 90 06:57:11 GMT References: <1990Oct31.100603.1989@agate.berkeley.edu> Sender: gurgle@well.sf.ca.us Organization: cellular Lines: 83 In article <1990Oct31.100603.1989@agate.berkeley.edu> scott@xcf.berkeley.edu writes: >I have just written and debugged my very first Macintosh application! Alert the media! Another hacker conquers the learning cliff! :-) >Does anyone out there perhaps have an idea of what the problem is? Doesn't look like there is any *problem* with your routine. You've done it all by the book, which is good. > Does anyone have code that work as it smoothly tracks the mouse? Now the ugly answer. Sometimes you can't do everything by the book. :-) The following suggestions apply only to short stretches of code and only to situations in which you are fairly certain you won't be interrupted by any other code that does anything similar to what you are doing. (In this case, it sounds pretty safe.) The Trap Dispatcher is a pig. It saves registers, calculates offsets, all sorts of horrible things that take up time. Accordingly, you need to minimize your trap calls. 1) write your loops using the minimum amount of trap calls 2) think about what those traps actually do -- you might be able to do the same thing -- convenience traps like SetPt come to mind 3) cut the Trap Dispatcher out of the picture a) before entering your loop, find out the address of the code that will execute when you call your traps -- learn the use of CallPascal, which is a compiler trick, not a trap call b) make judgement calls about how to fake traps -- exercise what's called 'Toolbox Karma' Now, here's the code you wrote that I would change: > do { > LineTo(p.h, p.v); > GetMouse(&p); > } while (StillDown()); The problem here, really, is that you are calling traps which call other traps. StillDown calls Button, GetMouse calls GlobalToLocal. I might write something like this (and I emphasize the _might_ -- I know this compiles, but that's it): #define kLineToTrapWord 0xA891 #define kGlobalToLocalTrapWord 0xA871 extern Boolean CrsrBusy : 0x08CD; extern Point Mouse : 0x0830; extern Boolean MouseButtonState : 0x0172; Point mousePt; long LineToTrapAddr, GlobalToLocalTrapAddr; LineToTrapAddr = NGetTrapAddress ( kLineToTrapWord, ToolTrap ); GlobalToLocalTrapAddr = NGetTrapAddress ( kGlobalToLocalTrapWord, ToolTrap ); if ( StillDown ( ) ) while ( MouseButtonState ) { while ( CrsrBusy ) ; /* just wait */ mousePt = Mouse; CallPascal ( & mousePt, GlobalToLocalTrapAddr ); CallPascal ( Mouse.h, Mouse.v, LineToTrapAddr ); } Voila, no trap calls in the loop. If you really want it to honk, do it in assembly, and all kinds of overhead goes away. You can keep things lying around in registers and you don't have to let the compiler do fourteen things when it only needs to do one. Is this DTS-approved technique? Nope. Not a chance. Does it work? Yep. (The next question is "Does it break anybody else?" Nope. At least not until System 8.) BTW, note that the "if ( StillDown ( ) ) while" strategy needs to be employed whether you use my way or your way. You can't draw a line and then test for StillDown at the bottom of the loop, because then you might as well just call Button -- the user may already have made the mistake. Pete Gontier, gurgle@well.sf.ca.us Software Imagineer, Kiwi Software, Inc.