Jump to content
PB170

Macintosh Toolbox programming questions

Recommended Posts

Having worked as an intern at Apple in the late ‘90s where part of my job was writing example code (for OpenDoc, but never mind that), sadly, I would not necessarily have complete faith that Apple’s example code is sacrosanct. :) 

 

If you can provide your entire source code somewhere, I would be happy to browse it more carefully.

 

Good point, yes, since you’re writing a code resource, THINK C’s debugger won’t help.  You’d want to use Macsbug.  In Macsbug, once your control strip loads, I would hit the interrupt switch and enter “ATB _ControlStripDispatch”.  This should break any time a control strip call Iike SBTrackSlider() is called.  Then, mouse down on your slider, “S” to step into the SBTrackSlider code, and see what’s going on in there and exactly what got passed to it on the stack.   You’d need to learn a bit of 68k assembly to be able to follow along if you haven’t already.  Apple’s original Macsbug Reference and Debugging Guide is terrific and may tell you most of what you’d need to know.

Share this post


Link to post
Share on other sites

Wow, cool to hear that you worked at Apple in the 90's! Must have been fascinating.

 

Well… all I can do at this point is trust the examples provided :) although I try my best to fully understand how they work.

 

Thank you for the instructions on Macsbug. Very helpful, once I get started with it (have yet to install it :)). I'm a little bit familiar with assembly and the inner workings of CPU's in general (on a broad level – haven't done any actual coding), so that shouldn't be too difficult to learn I think.

 

I included the full project in my post earlier ;)

 

Thank you for helping out!

Edited by PB170

Share this post


Link to post
Share on other sites

Sorry had missed that - just looked at your code now.

 

I see that sliderSetting is indeed not initialized anywhere and that feels quite problematic to me, would suggest triple-checking that this problem indeed recurs once that's set properly, or even just set to 0 in the SBTrackSlider() call for test purposes.

 

One thing that makes me a bit uncomfortable is in main(), if you somehow get handed NIL in globs on an sdevMouseClick, you don't do any error checking -- you'll call HandleMouseClick with an uninitialized pointer in gb, then pass random stuff to SBTrackSlider().  I realize that feels unlikely and is probably not what's happening, but I would add an error check there and alert/fail gracefully somehow if that happens.

Share this post


Link to post
Share on other sites

Like I said, I just missed it when I went back to Apple's example for my post here – it's been initialized properly throughout all my tests :) It's initialized to 0 during the initialization call to the module after the global variables are allocated.

 

Regarding the globals, is this level of error checking necessary? Isn't it enough to check if the allocation was successful, like it's done in the program, as long as the values are initialized properly?

 

Would you mind having a look at what happens when SBTrackSlider() is called while the code is running? If so, I can upload a version with the proper initialization included. Otherwise, I guess this could be a good point for me to get familiar with Macsbug :) (Though I still lean towards this being a bug in the Control Strip software.)

 

By the way, I have had the initial value for the slider continuously set to 0 during all of my testing, since the slider won't appear when the value is less than 0.

Share this post


Link to post
Share on other sites

Yeah I can probably try to debug it this weekend.

 

Personally when writing a CODE resource that's handed a pointer when the system invokes it, I would always check to ensure it's not NIL before dereferencing it just in case something weird happened somewhere outside my code (or in case I allocated it in my Init... routine but then forgot to return it in some edge cases, or something!), just to prevent having to chase down weird cases where my variables hold random nonsense.  Again though I think it's unlikely this is happening.

Edited by Crutch

Share this post


Link to post
Share on other sites

Oh, it's buggy alright :) After having a first look at MacsBug, I played around a bit with a version of the control strip module that sets the initial value to "0" if the previously returned value is out of range (not using of MacsBug at this point) and discovered that if the module is just clicked on very quickly (without bringing up the slider (not possible every time) ), it returns the value "2". After that the slider works properly one time (positive values in the range specified). Bringing the slider up again a second time (now with a positive value passed as the initial value) makes the handle on the slider appear outside of the slider (makes sense, I guess…). Setting it to a new value makes it go back to negative values. However, if no new setting is made, the value returned appears to decrease by 2 and 3 alternately for each click, until it reaches "0". That is, unless the starting value is odd, in which case it appears to decrease by 4 the first time…

 

Also, if it's clicked on again after "2" is returned, it returns "−1" and then does so for all of the following clicks.

 

All of this seem to occur only when the initial value is positive.

 

Getting around this would involve patching the Control Strip software, I imagine. So odd that this bug isn't mentioned anywhere in the developer documentation… Surely, I can't be the first one to try out the slider function…?

 

Here's a version of the module that displays the value of the sliderSetting variable in place of the icon in Apple's example, and works as described above.

Module2.sit

Edited by PB170

Share this post


Link to post
Share on other sites
16 hours ago, PB170 said:

Oh, it's buggy alright :) After having a first look at MacsBug, I played around a bit with a version of the control strip module that sets the initial value to "0" if the previously returned value is out of range (not using of MacsBug at this point) and discovered that if the module is just clicked on very quickly (without bringing up the slider (not possible every time) ), it returns the value "2". After that the slider works properly one time (positive values in the range specified). Bringing the slider up again a second time (now with a positive value passed as the initial value) makes the handle on the slider appear outside of the slider (makes sense, I guess…). Setting it to a new value makes it go back to negative values. However, if no new setting is made, the value returned appears to decrease by 2 and 3 alternately for each click, until it reaches "0". That is, unless the starting value is odd, in which case it appears to decrease by 4 the first time…

 

Also, if it's clicked on again after "2" is returned, it returns "−1" and then does so for all of the following clicks.

 

All of this seem to occur only when the initial value is positive.

 

Getting around this would involve patching the Control Strip software, I imagine. So odd that this bug isn't mentioned anywhere in the developer documentation… Surely, I can't be the first one to try out the slider function…?

 

Here's a version of the module that displays the value of the sliderSetting variable in place of the icon in Apple's example, and works as described above.

Module2.sit

Would be fun to raise a ticket at Apples support site and report this as a software bug :lol:

Interesting to see if there is anyone left with a sense of humour at Apple or if all those guys are retired by now..

 

Anyway, keep reporting! It's a very interesting and fun read 8-)

Share this post


Link to post
Share on other sites
17 hours ago, John_A said:

Would be fun to raise a ticket at Apples support site and report this as a software bug :lol:

Interesting to see if there is anyone left with a sense of humour at Apple or if all those guys are retired by now..

 

Anyway, keep reporting! It's a very interesting and fun read 8-)

Haha :lol: Well, while I like the thought of it, the company that brags about having having 90-ish percent of their users on their latest OS and do all they can get away with to improve that number, would probably ditch bug reports about anything older than the second latest version unless it's critical. And you know, if it's humor, it's got to be market oriented. :wink: Anyone with any thoughts about the the past in their head are probably not retired, but fired :) But maybe I'm being too pessimistic.

 

Anyway, glad to hear you enjoy the thread! I had a feeling maybe it was getting a bit too specific to be of general interest :)

Share this post


Link to post
Share on other sites

It looks like my suspicion was correct and your statusRect is somehow getting nuked. SBTrackControl has no idea what to do with the nonsense Rect so pukes back a negative value. Here’s the statusRect Macsbug shows you passing in. I got this by noticing that you are putting the Rect at an offset of $000C to A6 on the stack for SBTrackControl, and doing “DM A6+C Rect” in Macsbug. I’ll look at your code again later and try to figure out what’s causing this. 
 

62D25396-DF2B-49FF-BDE4-AAEA24BFEA0E.jpeg

Share this post


Link to post
Share on other sites

OK I'm pretty sure the problem is in this weird implementation of DrawCurrentIcon.  Is this really Apple sample code?

 

This writes over the statusRect that was passed in by MacOS.  That seems weird.  I think this code should allocate a new Rect on the stack, set its coordinates, and call PlotIconSuite/DrawPicture with that.  What happens if you try your control strip module with all the lines after "arrowHeight = ..." commented out?  I think you should avoid every modifying the statusRect that gets passed in by the system and if you need to draw things elsewhere, set up a separate Rect on the stack or that.

 

From the Macsbug screen above, it looks like statusRect->top is good, and everything else is nonsense.  When I run this multiple times, statusRect->left and bottom are random nonsense values; statusRect->right is always -256.

Quote

 

void DrawCurrentIcon(Globals *gb, Rect *statusRect) {
    short            arrowHeight;

//    draw the current icon

    statusRect->right = statusRect->left + IconWidth;
    (void) PlotIconSuite(statusRect, atNone, ttNone, gb->lastIcon);

//    draw an ‘up arrow’ to show that the module has a popup menu

    arrowHeight = (**gb->popupArrowPicture).picFrame.bottom - (**gb->popupArrowPicture).picFrame.top;
    statusRect->left = statusRect->right;
    statusRect->right += (**gb->popupArrowPicture).picFrame.right - (**gb->popupArrowPicture).picFrame.left;
    statusRect->top = (statusRect->top + statusRect->bottom - arrowHeight) >> 1;
    statusRect->bottom = statusRect->top + arrowHeight;
    DrawPicture(gb->popupArrowPicture, statusRect);
}

 

 

Share this post


Link to post
Share on other sites

Typo in the Macsbug command above, should have been "DM (A6+C)^ Rect" with the caret.

 

Anyway, pretty sure that was the issue.  I rebuilt your sdev with the attached code that just manipulated a new Rect on the stack instead of messing with the one pointed to by statusRect.  Seems to work in my tests?

 

Hope this helps!

ControlStripSample.c

Share this post


Link to post
Share on other sites

Huge thanks for your effort and for looking into it!

 

Interesting to read about the results of your test. At first it felt like great news if the error was indeed in the code and easily fixed. However… when trying it out on my machine, the updated code doesn't change anything :( Very confusing this …

 

The code is indeed Apple's sample code. Moreover, it seems to work just fine on my setup. It appears that the statusRect gets restored with each new call to the module, so changing it in the meantime doesn't seem to do any harm (well, at least not on my machine …).

 

This far I've basically been debugging my code by simply printing any problematic variables out on the screen. Below is a video of a modified version of the module that displays 1) the result from the SBTrackSlider() function as stored in the sliderSetting variable, 2) the values of four members of the statusRect, 3) the ticks value passed to the function 4) another instance of the result from the function, stored in a local variable inside the HandleMouseClick() function (where SBTrackSlider() is called), and 5) a counter that's increased before and after the function, just to keep track of things.

 

The display is updated both before and after the SBTrackSlider() function is called, as well as during update calls to the module (in the DrawCurrentIcon() function). I've added two 1 second delays after the SBTrackSlider() function ends, just to be able to see the update after the function. After the first update/delay, I set all members of the rect variable to 0. As you can see, they revert to the correct values with the next call to the module.

 

Here's a brief description of what you see in the video:
First click: Making a setting on the slider returns a negative value (–131). After the SBTrackSlider() function ends, the statusRect values are all set to 0 in the code, and then immediately restored during the next call to the module.
Second click: Making a new setting returns another negative value. (Since the value of the sliderSetting is out of range after the first call, I reset it to 0 in the code before calling the function to have the menu appear.)
Third click: A quick click (mouse down/up) makes the SBTrackSlider() return the value '2'.
Fourth click: Now, when making a setting on the slider, the value returned is correct.
Fifth click: The value returned from the function is negative again.

 

 

I also activated Macsbug and typed in the commands you used (without understanding exactly what they do or if they are applicable with my setup, at this point), and the result looks all right:

 

Macsbug.jpg.dc6a0b7eb7ddb72f0148eb6fd5aa2807.jpg

 

Any further ideas about what to make of all this…?

 

To me is still seems like the bug is in the Control Strip software, since the module works properly under Mac OS 9, and the few changes I made to the code seem to be okay. But I really have know idea… Very odd that we are getting different results when testing it.

 

I really wish I could get this to work properly.

 

By the way, what setup are you doing your test on?

Edited by PB170

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×