• Hello MLAers! We've re-enabled auto-approval for accounts. If you are still waiting on account approval, please check this thread for more information.

Macintosh Toolbox programming questions

(Part 2 of the post above)

A second issue that I encountered (and was able to work around) while developing the module is the following:

When I moved over to work the voltage module, a need to deal with floating point numbers emerged. My first idea was to use the standard C functions. However, it turns out that all C functions dealing with floating point numbers are unsupported when developing non-applications in Think C. Bummer.

Okay, surely then, there must be some useful toolbox function to do this (specifically, convert floating point numbers to text strings). When looking into Apple's documentation, I found the following:
 

If you are working with floating-point numbers, or if you want to accommodate the possible differences in output formats for numbers in different countries and regions of the world, you need to work with number format specification strings. […] To use number format specification strings and convert numbers, you need to follow these steps:

1. You first define the format of numbers with a number format specification string. An example of such a string is ###,###.##;-###,###.##;0. This string specifies three number formats: for positive number values, for negative number values, and for zero values. The section "Using Number Format Specification Strings," which begins on page 5-39, describes these definitions in detail.

2. You must also define the syntactic components of numeric string formats using a number parts table. This table is part of the tokens ('itl4') resource for each script system. It includes definitions of which characters are used in numeric strings for displaying the percent sign, the minus sign, the decimal separator, the less than or equal sign, and other symbols. The number parts table is described with the tokens resource in the appendix "International Resources" in this book.

3. You then use Text Utilities routines to convert the number format specification string into an internal representation that is stored in a NumFormatStringRec record. This is a private data type that is used by the number conversion routines. You convert a number format specification string into a NumFormatStringRec record with the StringToFormatRec function, and you perform the opposite conversion with the FormatRecToString function. Both of these functions are described in the section "Converting Number Format Specification Strings Into Internal Numeric Representations," which begins on page 5-43.

4. Once you have a NumFormatStringRec record that defines the format of numbers for a certain country or region, you can convert floating-point numbers into numeric strings and numeric strings into floating-point numbers. The StringToExtended and ExtendedToString functions perform these conversions; these are described in the section "Using Number Format Specification Strings," which begins on page 5-39.


Needless to say, I developed my own function for the conversion.

I can see the that this amount of flexibility could be useful when developing more advanced applications, but when just performing simple conversions, I would have imagined that the system functions would just use whatever numerical format was specified in the Numbers control panel.

Is this convoluted method really the only way Apple provided for converting simple floating point numbers to strings?

 
Hi @PB170, first of all I’m sorry I never noticed the above updates back in May, I remember recently wondering if this ever worked out for you.  It definitely feels like there is some weird bugginess in the Control Strip software.  (I was running tests on my PowerBook 550c running 7.5.5 and THINK C 6.)

I haven’t really done development with PowerBook-specific things much and don’t know much about the Power Manager.  Is it possible it lives in the PowerBook system extension?  Do you have that?

I would have normally used the SANE function num2str() to convert a float to a string (#include <SANE.h>).  Is that also not available from a non-application?

Based on this description http://mirror.informatimago.com/next/developer.apple.com/documentation/mac/Devices/Devices-291.html here’s how you could call PowerMgrDispatch from C (I haven’t tried running this, typos possible).  As you point out, this solves the problem of THINK C not having the relevant headers/glue, but you still need the routine to exist:

long voltage;

asm {
    move.l 0x0000001b, d0     // hi word is battery number (here, 0), low word is routine selector 0x1b
    dc.w 0xA09E                // _PowerMgrDispatch
    move.l d0, voltage
}




You should first check if A09E is a valid trap like this:

Code:
#include <Traps.h>
...
Boolean trapExists = (NGetTrapAddress(0xA09E, OSTrap) != NGetTrapAddress(_Unimplemented, ToolTrap));
 
Last edited by a moderator:
No problem! We all help each other voluntarily here so I'm thankful for any response I get. I'm constantly surprised by all the great feedback. When I doubt that I will get any response at all, I get great replies like this. (There is however another open question that I would be happy to get a response to, but I'll get back to that later :) )

Checking for the existence of the trap with the code you shared returns a negative result. (I assume this basically accomplishes the same thing as the Gestalt() method I included in my post above?)

I do have all the relevant extensions installed. I also tried installing a version of System 7.1.1 specifically for the PowerBook 520/540 under emulation, but that didn't change anything.

While the available documentation indicates that the dispatch routines are a part of the system software, I suspect that they're actually tied to, or a part of the power manager hardware itself. I found the following piece of information online which seems to support that. I don't own any other PowerBooks so that makes further development difficult :(

(excerpt from: http://www.rgaros.nl/gestalt/chapters/ch-09.html)

powr (System [6.0.4])
     gestaltPowerMgrAttr
     Returns information about the Power Manager, if present.

     enum {
     #define gestaltPowerMgrAttr 'powr' /* Power Mgr attributes */
     gestaltPMgrExists         = 0,  /* Power Mgr is present */
     gestaltPMgrCPUIdle        = 1,  /* CPU can idle */
     gestaltPMgrSCC            = 2,  /* can stop SCC clock */
     gestaltPMgrSound          = 3,  /* can shut off sound circuits */
     gestaltPMgrDispatchExists = 4,  /* dispatch routines are present */
     gestaltPMgrSupportsAVPowerStateAtSleepWake = 5}; /* &AS28 */

     NOTE:
     Bit 4 seen set on Power Macs (starting with System 7.5.2?)
     This is because some desktop machines support the Power Manager for
     things like Energy Star compliance.
(Two anonymous contributors)

     See also the 'pwrv' selector.




By the way, I discovered that the PowerBook 520/540 developer note includes a listing of a sample header file for the dispatch routines at the end. In it, the following glue code is listed for the GetBatteryVoltage() function:

Fixed GetBatteryVoltage(short whichBattery)
= {0x4840, 0x303C, 0x001B, 0xA09E};




This was the type of code I had I mind when I mentioned directly referencing the dispatch routines. However, while I have a broad understanding of assembly language, I don't understand how the syntax works here. How is it used, and what information is required within the curly braces?

I wasn't aware of the existence of the SANE library (though I have a feeling I've come across the acronym somewhere). I haven't seen it mentioned anywhere in Inside Macintosh or in the literature I've been reading. Thanks for introducing me to it. What's the syntax for the num2str() function?

Ps. Curiously, in newer versions of the Traps.h header file (including the one that comes with Think C 7), under the "Power Manager" section, there is a routine called _PowerDispatch located at 0xA09F. Very close to 0xA09E, but probably a completely different thing. Also, in even newer versions, where _PowerMgrDispatch is included, it (_PowerMgrDispatch) is listed together with _ControlStripDispatch, separate from the rest of the Power Manager traps.

 
Just a quick side question here :) (main post above)

As a side project, I just started making some modifications to the MacCalendar calendar module that comes with the Control Strip development kit, to make it more visually pleasing (have been using it for many years but don't really like how it looks).

One change I'd like to make is to replace the custom window design (a plainDBox with an extra frame drawn inside it) with the standard popup menu design. I thought an altDBoxProc (plain box with shadow) would fix this, but it draws a large two pixel shadow instead of the one pixel shadow that all standard menus and windows have.

So, how do I make a window with a one pixel shadow? Or is this some sort of custom design despite being applied all over the system? (I see that the offset for the shadows vary between windows — document windows have a one pixel offset, drop down menus three pixels, and the popup menus in the control strip seem to have an offset of either one or three pixels).

 
Lots of great stuff up there.  I will respond to what I can offhand!

Yeah SANE (the Standard Apple Numerics Environment) was always a weird beast that was only a pseudo-official member of the Mac standard libraries in terms of documentation. I’m not sure why. It’s documented in the Apple Numerics Handbook, not IM.  Try here:  https://vintageapple.org/inside_o/pdf/Apple_Numerics_Manual_Second_Edition_1988.pdf

In THINK C 6, you can find it in SANE.h in the “THINK #includes” directory.

Menus, including popup menus, aren’t actually windows at all in classic Mac OS.  The Menu Manager draws them itself.  If you want a popup-menu-like thing that vanishes when you release the mouse, I would draw it directly to the screen probably.  Save what’s under it first by copying it to an offscreen PixMap with _CopyBits, and restore it later (this is what _MenuSelect and _PopUpMenuSelect do).

Yes, if you want to just specifically check for one particular trap, the code I wrote is the easiest way.  If you want to check for a whole collection of features, like the Power Manager, you are better off using Gestalt (but then you have to check for Gestalt if you want to run on older systems - but you probably don’t need to bother in a Control Strip module).

The syntax used in your GetBatteryVoltage() example is literally just telling the compiler to use that exact 8-byte chunk of machine code whenever you call GetBatteryVoltage().  If you want to know what assembly instructions that corresponds to, I would write a little application that calls that routine, put a call to _Debugger at the start of it to drop into Macsbug, then type “IL” (instruction list) to see how Macsbug disassembles the following few instructions.  It’s going to look very similar to the asm{...} block I wrote above, you can see it does a couple things than calls 0xA09E.

 
Thanks for the reply! Sorry for the late response on my part.

I didn't assume that menus are windows. However, the popup menu in the calendar module is implemented as a window, and I just thought it would make sense if the altDBoxProc (plain box with shadow) had the same type of shadow as all standard windows and menus. What would be the best way to create a plainDBox type window with a standard 1 pixel shadow? Just getting the window's coordinates and manually draw the lines? Or is there a more appropriate way of doing it?

On a related note, I'm also interested in creating a slider (such as the volume slider in the sound control panel (or the vertical one in the control strip)) as well as a palette window (such as the ones used in ClarisWorks, Photoshop etc.). However, I haven't been able to find any information about how to create any of them in any of Apple's documentation. Are they not part of the system/Toolbox? Is not, is there some sample code for creating them available elsewhere?

 
If you literally want a window that looks like that, I think you will need to create a custom Window Definition Function (WDEF).  That would certainly be the “correct” way.

If you are only going to use it as a popup menu, though, I wouldn’t bother.  I would use CopyBits() to grab whatever’s on the screen there, then draw a nicely drop-shadowed rectangle straight to the screen with QuickDraw.  Then track the mouse until it’s released.  When done, just use CopyBits() again to put back whatever was supposed to be there originally.  (Again, this is what the Menu Manager itself does in _MenuSelect.)

I am not aware that sliders were ever added to the Toolbox, I think those were always done with custom CDEFs.  Same with pallete windows, as far as I know.  (Maybe they were added much later?  Certainly they weren’t part of the Toolbox in the earlier generations of System 7 or before, anyway.  I stopped paying as close attention circa 1994.)  However there is a terrific & comprehensive treatment of pallete windows (including the tricky part, making them “float” over other active windows) and extending them into HyperCard-style tear-off menus in MacTutor volume 4, number 4:  “Tear-Off Menus & Floating Palettes” by Don Melton and Mike Ritter of Impulse Technologies (maker of the famed Impulse Audio Digitizer, by the way, one of which I had in the ‘80s).  A quick Google failed to turn off the full text of that article online (but it probably exists somewhere on MacTech’s website—I have a hard copy), but I did find that follow on that might explain how to do it:  http://preserve.mactech.com/articles/mactech/Vol.04/04.12/ToolWindow/index.html

Warning—implementing using the Melton-Ritter approach is a fairly major project!

It looks like Apple blessed their approach later in a Technical Note:  https://www.fenestrated.net/mac/mirrors/Apple Technotes (As of 2002)/tb/tb_575.html

While Googling around on this topic, I stumbled on this which suggests Symantec added some support for these in TCL, but I never used this:  http://preserve.mactech.com/articles/mactech/Vol.09/09.02/TearOffTCL/index.html

 
Many thanks for the links! The tool window article look very thorough. Seems like I've got some more reading to do :) I'll see if I can find some information about implementing sliders on Mactech or elsewhere as well.

Regarding the calendar module, the thing is that in this particular case I just thought I'd make some minor visual adjustments to it, and the code is built around having the content drawn inside a window. If I would change it so that it draws directly to the screen, I would probably have to go through and rewrite much of the code. I already feel kind of exhausted by all the obstacles I've encountered with rest of the the control strip stuff so I'd rather not dive into that now :) Your explanations and tips are still very useful though, and help me a lot in understanding how things are done. Thanks!

One final question before I retreat into the programming cave, if you don't mind :) Does the toolbox (or other resources) support creating buttons with custom shapes? Basically, I would like to create a simple rectangle and make it behave like a button (highlight when clicked and assigned an action).

 
If you want to change the drop shadow of the window without eliminating the whole window, I would use the plain-rectangle window type with no shadow.  Then, I would CopyBits(the window’s rect plus a little extra for the shadow) to an offscreen buffer, and draw the shadow myself outside the window (using the WMgrPort).  Then when I close the window, I would use CopyBits() from the offscreen port to restore whatever was there under the shadow.

There is no built-in support for arbitrary shaped buttons.  You would need to write your own CDEF (control definition function) for a rectangular button.  I’ve done this before long ago, it’s easy, you just need to read up on the CDEF basics in Inside Macintosh Volume I.  You don’t actually need to put your CDEF in a resource, you can write a procedure then get a handle to it, which makes it much easier to debug since it can just live in your main chunk of code.  (That same article I referenced above explains how to do this with an MDEF by creating a little JumpInstruction struct and stuffing it into a handle returned by NewHandle(), same concept applies with a CDEF.) Of course you can always do it the “official” way too by building a code resource.

 
After a couple of hours of searching and skimming through various resources online, I’ve come to realize that writing a custom WDEF probably would be just as difficult, if not more, than going through and rewriting the code. Programming on classic Mac OS sure requires a ton of patience...!

Just modifying the standard window routine to remove the title bar would have been enough, but I haven't been able to find any C code for it.

 
Ah, I didn't see your reply until after my post above. That sounds like a good solution for now. I'll see if I can figure out how to code it.

Thanks for the information about the buttons. I'll put CDEFs on my growing list of things to read up on! :)

 
Small update regarding tool windows! After making a search for “WDEF” on Apple’s Developer Connection CD’s, I discovered a folder named “Floating Windows”, containing code for making windows float, as well as the third party software “Infinity Windoid WDEF” for implementing tool/palette windows. The documentation for the latter also mentions that OS support for tool windows was introduced with System 7.5 in conjunction with Apple Guide and its custom windows. I assume it wasn’t used much though, since I don't think I've seen any other software using the same style for its tool windows. Perhaps Infinity Windoid did a better job with the implementation.

 
Another small update! Sliders are apparently not called sliders, but dials in Apple's documentation. Inside Macintosh mentions them in the following passages (of which the second seems to contradict the first…) (my highlighting):
 

Another important category of controls is dials. These display the value, magnitude, or position of something, typically in some pseudo-analog form such as the position of a sliding switch, the reading on a thermometer scale, or the angle of a needle on a gauge; the setting may be displayed digitally as well. The control’s moving part that displays the current setting is called the indicator. The user may be able to change a dial’s setting by dragging its indicator with the mouse, or the dial may simply display a value not under the user’s direct control (such as the amount of free space remaining on a disk).

One type of dial is predefined for you: The standard Macintosh scroll bars. Figure 2 shows the five parts of a scroll bar and the terms used by the Control Manager (and this chapter) to refer to them. Notice that the part of the scroll bar that Macintosh users know as the “scroll box” is called the “thumb” here. Also, for simplicity, the terms “up” and “down” are used even when referring to horizontal scroll bars (in which case “up” really means “left” and “down” means “right”).

[…]

Dials
Dials display the value, magnitude, or position of something in the tool or system, and optionally allow the user to alter that value. Dials are predominantly analog devices, displaying their values graphically and allowing the user to change the value by dragging an indicator; dials may also have a digital display.

The best example of a dial is the shaft of a scroll bar. The indicator of the scroll bar is the thumb; it represents the position of the window over the length of the document. The user can drag the thumb to change that position.

Just as with buttons, there are a few standard dials defined in the ROM, but a programmer can implement a custom dial and link it in with the control mechanism.

 
Last edited by a moderator:
Yeah very early on Apple referred to sliders as “dials” but it never really stuck. Where did you see that last paragraph you quoted? I don’t see it in my copy of Inside Macintosh. Anyway it’s wrong - the only “dial” defined in ROM is the standard-issue scroll bar, I promise. 

 
Last edited by a moderator:
I trust you  :-) Thanks for clearing that up.

I found it while searching online. Apparently it's in an earlier version of Inside Macintosh, dated 1982–1984. Now that I check it, it's not in the 1985 version that I have saved on my computer. So probably a good idea that got scrapped :)

 
Back
Top