Q & A Stack 4.0.5
Table of Contents
Devices & Hardware
Graphics, Imaging & Printing
Networking & Communications
Operating System
Platforms & Tools
Toolbox & IAC
Devices & Hardware: A/ROSE & MCP Card: NuBus’90 and MCP card timing
The Macintosh Coprocessor (MCP) card uses the NuBus 10 MHz clock for the system clock and the NuBus’90 clock is 20 MHz, so how can the cards continue to work? The 68000 isn’t rated for 20 MHz. Is there a new pinout for NuBus’90 that provides both clocks?
The NuBus’90 CLK signal (pin C32) is 10 MHz (didn’t change); the 20 MHz clock signal is the CLK2X signal, which is pin B24 (previously -5.2 Volts).
Devices & Hardware: A/ROSE & MCP Card: A/ROSE NetCopy process description
How does the NetCopy cVirtualToReal routine work in the oscglue.a file of the Portable A/ROSE code? I’m trying to emulate the NetCopy command in my A/ROSE code. II want the copy routine to work without requiring the user to use the LockRealArea command on the MacOS side, but this means that I have to worry about the addressing being passed in as being virtual. Is the A/ROSE kernal on the board providing the virtual-to-real mapping or does it just send a message back to A/ROSEprep to do it and then uses the results?
What cVirtualToReal() does is take as input, a transaction ID (TID), a virtual address and a size. It returns a NuBus address and a size. If the returned size is zero, cVirtualToReal() could not find a corresponding NuBus address for the virtual address. If the returned size is non-zero, this size is the size of the contiguous address range for the virtual address starting at the NuBus address.
This is how cVirtualToReal() works: cVirtualToReal() examines the TID to find out the slot (call it slot s) associated with the TID. cVirtualToReal() looks at the iccm communications area of slot s looking at MapCnt, MapPtr, and MapChk. (Please refer to iccmDefs.h or iccmDefs.a in the iccm commucations area record ca_Rec.)
If MapCnt is zero, the virtual address is assumed to be the same as the NuBus address. In this case, cVirtualToReal() sets the returned NuBus address value to be that of the virtual address and returns the size the same as the size on input.
If MapCnt is non-zero, the slot either has an address scheme where the virtual address that the TID on slot s uses cannot be the same as the NuBus address (say the processor was a 68020 with no PMMU and required that local card addresses have zero for the high address byte) or the slot has something like VM (which is what happens on the main-logic board). cVirtualToReal() will use the address map pointed to by MapPtr on slot s to try to resolve the virtual address to a NuBus address. MapPtr is a pointer to a linked list of struct AddrMap (defined in os.h or os.a). If cVirtualToReal() can resolve the virtual address by looking at the AddrMap entries, it will do so. If cVirtualToReal() cannot, it will return zero for the size. The MapChk and MapCnt variables in ca_Rec are used for concurrancy. cVirtualToReal() will fetch a pointer from the MapPtr structure and then check to see if MapChk has changed. cVirtualToReal() knows that the pointers in MapPtr and the AddrMap entry have not changed if MapChk has not changed. cVirtualToReal() starts its search over at the beginning of the MapPtr list should MapChk change. cVirtualToReal() knows that it can start searching the MapPtr list only when MapCnt equals MapChk.
What cLockRealArea() does is take as input a virtual address and size and returns on output the NuBus address/length pairs associated with that virtual address and size. cLockRealArea() also returns a success/failure status indicating if cLockRealArea() successfully “locked” the pages in memory associated with the virtual address and size.
Please note: there is a cLockRealArea() on the main logic board used to lock memory on the main logic board. There is also a cLockRealArea() in the A/ROSE kernel on the NuBus card which WOULD lock memory on the NuBus card. The cLockRealArea() on the NuBus card acts as a no-op at this moment and is present for compatibility reasons.
Here's a descritpion of how cLockRealArea() works: cLockRealArea() on a NuBus card acts as a no-op. cLockRealArea() on a NuBus card returns a NuBus address/length pair as one would expect but otherwise does nothing.
cLockRealArea() on the mainlogic board is much more interesting. cLockRealArea() on the main-logic board tries to lock down the pages associated with the virtual address/size (assuming a PMMU is present and the appropriate a_line traps are present) calling either _LockMemory or _LockMemoryContiguous . Next, if _LockMemory or _LockMemoryContiguous works, cLockRealArea() tries to create an AddrMap entry to store the NuBus addresses associated with the virtual address. cLockRealArea() needs to call _LockMemoryContiguous on this AddrMap entry to lock it down as well. Finally, if cLockRealArea() has made it this far, cLockRealArea() will try to insert the AddrMap entry into the linked list pointed to by MapPtr in the iccm communications area ca_Rec. cLockRealArea() will change MapChk, insert the AddrMap entry, and then change MapCnt to be the same value as MapChk.
What cNetCopy() does is take as input a source TID/source address, destination TID/destination address, and size. cNetCopy() calls cVirtualToReal() to convert the source TID/source address and the destination TID/destination address into NuBus addresses. If cVirtualToReal() can convert the addresses, cNetCopy() will perform a blockmove() operation moving the data itself. If cVirtualToReal() cannot convert the addresses, cNetCopy() will send an A/ROSE IPC message to the NuBus slot (please note that the main logic board is NuBus slot zero) asking the iccm (please note that iccm is built into the A/ROSE driver on the main logic board) to perform the copy. Iccm will perform the copy and send a reply back to cNetCopy() when the copy is complete.
At this moment, the only slot that can have virtual addresses that cVirtualToReal() cannot convert to NuBus addresses are main-logic board addresses. cVirtualToReal() can always resolve virtual addresses that exist on NuBus cards.
If the user on the MacOS side does not use LockRealArea() and PMMU is believed to be active, an A/ROSE IPC message is sent from the NuBus card to the iccm portion of the A/ROSE driver on the main logic board to perform the copy. The iccm portion of the A/ROSE driver will send back a reply when it has performed the copy.
One unasked question is could the card request that memory on the main-logic board be locked down from the card. The answer to this question is no. The LockRealArea() routine on the main-logic board which does the locking down of memory on the main logic board associates the memory that it is locking down with the TID of the main-logic board process that is calling LockRealArea().
Devices & Hardware: A/ROSE & MCP Card: gCommon addresses and downloading card-dependent routines
After upgrading to A/ROSE 1.1.2, when I download to my board, it doesn’t call my board-specific routines in the resource 'hlta' that I installed into A/ROSE prep.
Check the gCommon area on the card at locations gCardInit0, gCardInit1, and gCardInit2. These are the addresses where the Download subroutine would have placed the card-dependent routines when placing the routines on the card. You can find these addresses in the :A/ROSE:includes:arose.a header file.
If these addresses are zero, that means either the Download subroutine failed to find the card-dependent routines when doing the downloading, or the Download subroutine is the wrong version and doesn’t know about card-dependent routines, or the application doing the downloading was not linked with a recent enough version of Download-Lib.o and contains the old Download subroutine code. The actual code for doing downloading has been moved from the application to the A/ROSE Prep file and glue code is now in the Download-Lib.o file, which is what the application really calls. This glue code knows how to load the actual downloading code.
If these addresses are non-zero, A/ROSE, during its initialization, should call these routines. If A/ROSE is not calling them, check to see where the A/ROSE kernel is coming from. Was the A/ROSE kernel linked in with the code. In this case, you need to relink your code with a more recent version of the A/ROSE kernel.
Devices & Hardware: A/ROSE & MCP Card: A/ROSE & MCP card for real-time priority multitasking
Our application communicates via serial I/O with real-time devices in the field. Some functions of our application must run at a higher “priority” than anything else on the Macintosh®, even if a MultiFinder®-hostile application takes over the CPU to do animation or whatever. Our initial approach is to perform these critical functions at ioCompletion (interrupt) time, but this is a royal pain in the neck to implement. We’d rather not require A/UX® because it increases the price and complexity of our system. What’s the best way to make it all hang together?
The Macintosh, by itself, is not a valid platform for real time processes or priority multitasking. A/ROSE™ (Apple/Real-time Operating System Environment) which runs concurrent prioritized processes on compatible coprocessor NuBus cards should fit your needs nicely.
A/ROSE runs as a driver under the standard Macintosh operating system. It downloads, starts, stops, sets priorities, and communicates with real-time processes that run on any A/ROSE compatible NuBus card. The Apple (Macintosh Coprocessor Platform™ (MCP) card is available from APDA® (Macintosh Coprocessor Platform Developers Kit #M0793LL/A) and provides you with an MCP card, A/ROSE, A/ROSE documentation and development information on how to design your own (if you prefer) coprocessor card. There is also an excellent article in Issue 4 on developing with A/ROSE and MCP.
An alternative development environment for real-time programming would be to license and develop your application under A/UX on the Macintosh.
I would not suggest trying to ‘tough it out’ at interrupt level as this will put you at odds with the way the Macintosh operates; accRun time will never provide you with ‘priority’ runtime, only time that is otherwise available. Patching StillDown is just not a supportable option. Were I attempting this project I would head straight for A/ROSE and run it on either the Apple Serial NB card (A/ROSE compatible with on-board 10 MHz 68000 and 4 dedicated serial ports) or design my own serial hardware on the MCP card.
Devices & Hardware: A/ROSE & MCP Card: A/ROSE & MCP development questions
What restrictions (power, speed, and so on) does the Macintosh Coprocessor Platform™ (MCP) impose on the hardware added to the platform? Can we use A/ROSE™ on a board which we design ourselves from scratch? If so, we have the following questions concerning the hardware requirements for a board running A/ROSE: Must the CPU running A/ROSE be a 68000 or could it be a 68020 or 68030? Can A/ROSE handle master transfers under NuBus control between the card and main board memory? Is the source code for A/ROSE (and specifically the InterCard Communication Manager) available if we needed to tailor that code to our system?
To the knowledge of the A/ROSE engineer, A/ROSE requires modification in order to permit master transfers under NuBus control between the card and main board memory. The engineer succeeded in designing a routine to perform the write operation from A/ROSE; however, the read operation proved to be a challenge. A solution to your problem would be to release the source code. However, at this time this isn’t possible. There has been consideration on this subject but no final decision.
In response to your other questions, MCP doesn’t impose any restrictions on the hardware. There are some card dependencies imposed by A/ROSE, described in the document, “A/ROSE Card Dependency,” available on AppleLink.
I’m familiar with a couple of cards based on the MCP board. On one card in particular, the processor was swapped with a 68020 using A/ROSE.
Devices & Hardware: A/ROSE & MCP Card: Ordering a Macintosh Coprocessor Platform (MCP) card
How do I order a Macintosh Coprocessor Platform™ (MCP) card and software? What do I get when I order it?
You can order the MCP card and software through Apple Software Licensing. The card comes with the MCP platform and software which contains the appropriate libraries and header files. On the card is the 68000, ROM (256K), RAM (512K), and the NuBus Logic to drive the card in both master and slave modes. There is also blank space on the board, left there for your communications hardware. Basic documentation is also included.
Devices & Hardware: Apple Desktop Bus: ADBReinit clarification
ADBReinit doesn’t seem to work exactly as described in the Apple Desktop Bus (ADB) documentation. Please clarify.
A SendReset command byte is never sent across the bus, as Inside Macintosh and other documentation seems to imply. In fact, when the ADB Manager is asked to SendReset, it actually instructs the ADB transceiver to assert an Global Reset pulse.
The Talk R3 sequence after a reset is as follows: each of the 16 device addresses is polled once, and then the ADB Manager returns to the addresses that did not time out (addresses which contain at least one device) and retries those addresses (moving devices between default and temporary addresses) multiple times (50 in the current implementation) until it is satisfied that devices have separated properly.
This initialization task is patched out by System 6.0.5 and later, so every machine can use the new, improved ADB Manager which debuted with the Macintosh IIci ROM.
Devices & Hardware: Apple Desktop Bus: Minimizing ADB Manager address resolution collision potential
Minimizing ADB Manager address resolution collision potential
Apple offers two suggestions to minimize the potential for collisions during address resolution using the Apple Desktop Bus (ADB) Manager:
1. Use a somewhat random stop-to-start time in the range 140 µs ≤ Tlt ≤ 260 µs. Don’t be too generous here, however. Tlt is one of the more sensitive ADB timing parameters and it’s best to be near the middle of the window—try not to be too close to the endpoints or you may notice erratic behavior. Of course, there is a finite amount of time in the Tlt window and there are a finite number of random addresses a device may return, but in most cases devices should be able to resolve themselves properly. If they do not, it should be a rare coincidence which can be resolved by rebooting or simply using a utility program which executes the
_ADBReinit trap.
2. Return a random number in the R3 address field. In fact, you’re never required to respond with your actual address in response to a Talk R3. You only must keep track of what your current address is and readdress in accordance with Listen R3 commands from the host. By returning a random number in the address field, you minimize the possibility that two devices are transmitting exactly the same data on the bus at exactly the same time. This is the only instance where a well-designed algorithm would fail to detect a collision.
A well-designed algorithm detects collisions by sensing the ADB data line asserted when it is not expected to be. It must monitor for this condition before transmitting and any time the device is transmitting and expects the data line to be negated. One check per bit cell is typically not sufficient. Monitoring for collision should be a key, repetitive part of the transmission process.
Devices & Hardware: Apple Desktop Bus: Apple Desktop Bus (ADB) startup timing
I need exact Apple Desktop Bus (ADB) startup timing data for each Macintosh model. When does the ADB query to devices first go out and when does it receive confirmation of a device present? When does the File Manager start loading the control files? What type of signal is sent and received--a pulse of what parameters?
It’s not possible to tell you when ADB devices are initialized after power- up with any accuracy, because it depends on factors such as how much RAM is in the machine and what kind of screens are connected to it. When the system begins loading control files, it’s even more variable, depending on things like disk speeds and if the user is booting off a floppy. In general, timing issues are difficult with the Macintosh, as it doesn’t even approach being a real-time machine.
Regarding the characteristics of the ADB startup sequence, the best thing to do is get the ADB Specification from Apple’s Software Licensing; it contains all the information you need (along with Inside Macintosh and the Macintosh Hardware Reference) to build an ADB device.
Devices & Hardware: Apple Desktop Bus: Apple IIGS and ADB device differentiation
The Apple IIGS® does not seem to sort out equivalent devices on the Apple Desktop Bus™ (ADB) as the Macintosh® does and as outlined in the ADB specification. We want multiple keyboard support, but the Apple IIGS ADB micro just begins reading blindly from addresses 2 and 3, assuming one keyboard and one mouse are attached. Is this information correct?
The Apple IIGS does not do the same kind of dynamic device mapping and remapping that the Macintosh ADB Manager does. The “Apple Desktop Bus Tool Set” chapter of the Apple IIGS Toolbox Reference gives instructions on how to remap devices dynamically yourself. Essentially, you have two options:
• You can leave the second keyboard address as 2, allowing input from multiple keyboards, but the keyboards’ modifier key input will be mixed.
• You can dynamically remap the keyboards in your program or in an INIT (although some forms of remapping require the user to press a key on the device to be remapped) and then a second keyboard will not appear as the standard keyboard—requiring all who use it to do their own ADB requests to get at the information entered from a second keyboard.
If you don’t expect many developers to use a second keyboard, you might just choose to remap it inside any program that uses it. You could write an external library or functions that remap a second keyboard and read from it.
Devices & Hardware: Apple Desktop Bus: ADB power requirements on Macintosh LC
What is the maximum power draw on the Apple Desktop Bus™ (ADB) on the Macintosh® LC? The low-power mouse specifications state that the mouse shall consume no more than 10 mA. Why does Apple specify 80 mA for a mouse on the Macintosh LC? What does Apple recommend for maximum power consumption for a third-party ADB device?
The power budget for the Macintosh LC’s ADB port changed after the information was compiled for its product information sheets. The Macintosh LC can supply the standard 500 mA that all ADB hosts are supposed to supply.
The standard keyboard and mouse are specified to draw no more than 100 mA. Because any of these devices may be attached to a Macintosh LC, it is necessary to specify the machine for significantly more than the 10 mA actually drawn by “low-power” ADB peripherals.
Apple has always recommended that ADB devices requiring 100 mA or more be designed to provide their own 5 V power source. The ADB engineering specification (062-0267), which you get when you license our ADB technology, has both the host and the device power loading information on page 4.
Devices & Hardware: Apple Desktop Bus: Timing extremes & undefined transaction sizes cause ADB problems
Why do my ADB devices fail often after a restart on my Macintosh® IIfx, but work fine on other Macintosh models? Why do they simply not work on the Macintosh IIsi and Macintosh LC?
With each new system release and each new machine we hear a few more complaints about broken ADB devices. This is true of system software versions 6.0.4 and 6.0.5, and the Macintosh IIci, IIfx, IIsi, and LC.
A little historical perspective is in order. The Apple Desktop Bus™ specification is pretty sloppy with tolerances as high as ±30% on some signal timings. This has led to many marginal implementations for ADB devices, both within Apple and from third parties. Unfortunately, the first generation of machines supporting ADB could have been even more lenient than the specification, so that devices which were -35% might have worked just fine. In at least one instance, a minimum timing was not enforced at all! Our more recent products and system software, while remaining within specifications, are relatively stricter about allowable tolerances.
The most common manifestation of an ADB timing problem is during device initialization. Developers must adhere strictly to the minimum and maximum delay times for initialization transactions and they should aim for the middle of the tolerance window, not the edge. Of particular importance recently is the Tlt (stop to start time) parameter from the ADB Specification. Nominally it is 200 µs. The minimum delay is 140 µs. Many devices which do not initialize properly are found to respond more quickly than this minimum delay during the TalkR3 initialization sequence.
The problem with the Macintosh IIsi and LC is one of protocols. The ADB specification requires a transaction to consist of at least two bytes. Some device/driver combinations have been getting away with “single-byte” transactions. These will not necessarily slip by newer implementations.
Devices & Hardware: Apple Desktop Bus: ADB name mapping
Where is the translation of ADB (Apple Desktop Bus™) type from an unsigned integer (e.g., 1) to the “real” thing (e.g., “mouse”) documented? If so, what is it?
The only mappings of device IDs and addresses to names that you can rely on are the ones that appear in Inside Macintosh. Most devices appear like one of those devices. However, there isn’t any other ID to name mappings.
Devices & Hardware: Apple Desktop Bus: “How to ADB” Apple Desktop Bus references
I understand that doing Apple Desktop Bus™ (ADB) development for mice (or is it mouses) can be difficult. Are there many undocumented technical issues which I need to be aware of in order to effectively communicate with the ADB bus?
You should have the following bits o’ info:
• Inside Macintosh®, Volume V, Chapter 20, “Apple Desktop Bus”
• Macintosh Technical Note #206, “Space Aliens Ate My Mouse (ADB-The Untold Story)”
• Macintosh Technical Note #266, “Absolute Pointing Device Memory Structure”
• Macintosh Technical Note #160, “Key Mapping”
• Apple Desktop Bus specifications package. This is a package of official
Apple Specifications covering the ADB protocol, and Apple-manufactured ADB Devices. This is available from Apple’s software licensing department upon execution of an ADB License Agreement. Contact the licensing department at:
Apple Software Licensing
Apple Computer, Inc.,
20525 Mariani Avenue, M/S 38-I
Cupertino, CA, 95014
(408) 974-4667
AppleLink®: SW.LICENSE
Additional ADB references:
Inside Macintosh, Volume V, The Apple Desktop Bus
Macintosh Family Hardware Reference
Apple IIGS® Hardware Reference Manual
Apple IIGS Firmware Reference Manual
IMPORTANT NOTE: In the case of a discrepancy between the ADB specification and a reference manual, the specification supersedes.
Baum, Peter.
“Boarding the Bus,” MacUser, July 1987, p. 142.
“An Overview of Apple Desktop Bus,” Call A.P.P.L.E., June 1987, p. 24.
In addition to the written word, there are some code samples that will probably prove useful:
• MacDTS Sample Code #SC.017.TbltDrvr - An example pointing device driver for the Macintosh
• ADBLister - A simple program that uses the ADB manager to display information about devices connected to ADB. (On the Developer Series CD, in a folder called “Cameron’s Source”).
Finally, for any remaining questions, contact Macintosh Developer Technical Support via AppleLink at “MacDTS” or via the US Mail at:
Macintosh Developer Technical Support
Apple Computer, Inc.
20400 Stevens Creek Blvd. MS 75-3T
Cupertino, CA 95014
Devices & Hardware: Apple Desktop Bus: Using the LEDs on the Apple Extended Keyboard
How can I use the LEDs on the Apple® Extended Keyboard?
Using the LEDs on the extended keyboard involves the _ADBOp call. Once you determine that you have an extended keyboard (with _CountADBs and _GetIndADB), then register 2 of the extended keyboard has the LED toggles in the low 3 bits.
Therefore, you would do a Talk to register 2 to have the device send you the contents of register 2, manipulate the low 3 bits to set the LEDs, and then pass the modified register 2 back to the device with a Listen to register 2 command.
The Apple Extended Keyboard has an ID of 02 and a device handler ID of 02, while the Apple Standard Keyboard has an ID of 02 and a device handler ID of 01.
Note: At this point it is not clear what Apple has in mind for these LEDs, so you are using them at your own risk.
Devices & Hardware: Apple Desktop Bus: _ADBOp call service routines and data areas
I am confused about the service routines and data areas passed in the _ADBOp call. What does it all mean?
That’s a good question.
FUNCTION ADBOp (data:Ptr; compRout:ProcPtr; buffer:Ptr;
commandNum:INTEGER) : oserr;
data is a pointer to the “optional data area.”
This area is provided for the use
of the service routine (if needed).
compRout is a pointer to the completion or service
routine to be called when the _ADBOp command
has been completed. It has the same meaning
as the service routine passed to the
_SetADBInfo call.
buffer is a pointer to a Pascal string, which may
contain 0 to 8 bytes of information. These
are the 2 to 8 bytes that a particular
register of an ADB device is capable of
sending and receiving.
commandNum is an integer that describes the command to
be sent over the bus.
There is some confusion over the way that the completion routines are called from _ADBOp. This calling may be done in one of the following three ways:
(1) You do not wish to have a completion routine called, as in a Listen command. Pass a NIL pointer to _ADBOp.
(2) You wish to call the routine already in use by the system for that address (as installed by _SetADBInfo). Call _GetADBInfo before calling _ADBOp, and pass the routine pointer returned by _GetADBInfo to _ADBOp.
(3) You wish to provide your own completion routine and data area for the _ADBOp call. In this case, simply pass your own pointers to the _ADBOp call.
Remember, there rarely should be a reason to call _ADBOp. Most cases are handled by the system’s polling and service request mechanism. In the cases where it is necessary to call _ADBOp, it should not be done in a polling fashion, but as a mechanism of telling the device something (for example, change modes, or in the case of our extended keyboard, turn on or off an LED).
Devices & Hardware: Apple Desktop Bus: Using ADB to auto power up the Macintosh
How can I make my Macintosh® II or IIx power up automatically after a power outage?
The Macintosh II and IIx power can be turned on via the keyboard through the Apple Desktop Bus™ port (ADB) since the reset key is wired to pin 2 of the ADB connector. When you press this key, it pulls pin 2 to ground and initiates a power-on sequence. You can emulate this feature with a momentary switch connected to the ADB port. Note that the switch on the back panel of a Macintosh IIcx can be locked in the On position to automatically restart after a power outage.
An idea for a power-on circuit would be to have a momentary (one-shot) relay powered by the same outlet that powers the machine and have the contacts close pin 2 of the ADB connector. (Without having tried this, I am concerned that you may need a delay before the relay fires to give the AC time to stabilize, etc.)
Devices & Hardware: Apple Desktop Bus: Boot time ADB device address conflict resolution
I’m confused about the way Apple Desktop Bus™ (ADB) device address conflicts are resolved at boot time.
The method used by the host to separate and identify the devices at boot time is not well documented, so I’ll try to describe it with some clarity.
The host issues a Talk R3 command to an address. Let’s say there are two devices at that address. Both try to respond to the command, and when they try to put the random number (the address field of register 3) on the bus, one of them should detect a collision. The one that detects the collision backs off and marks itself (internally) as unmovable.
The device that did respond successfully is then told to move to a new address (the highest free address). By definition, moving to a new address means that it now responds only to commands addressed to this new address, and it ignores commands to the original address.
The host then issues another Talk R3 command to the original address. This time the second device responds without detecting a collision. When it successfully completes a Talk R3 response, it marks itself as movable. It then is told to move to a new address.
The host again issues a Talk R3 command to the original address. Since there are no more devices at that address, the bus times out, and the host moves the last device back to the original address. At this point, the host moves up to the next address that has a device and begins the process all over.
Generally, when you have trouble separating devices on the ADB, it is because the collision detection doesn’t work well. In fact, this problem is evident on Apple® keyboards. The bug is that the random number returned in R3 isn’t really a random number. Since the microcontrollers on the keyboards are clocked with a crystal, they tend to generate the same “random” number, so when the system attempts to separate them with a Talk R3 command, they never detect the collision.
One possible solution is to use a low-tolerance capacitor on the reset line of the microcontroller, thereby forcing the time from power on to the time reset is negated to be fairly random. In this way, the microcontroller can start a count until it receives the first Talk R3 command, and hopefully it is a different number from the number of another device at the same address on the bus.
If you find your device shows up at all addresses, it may be because it is responding to the move address command when it should be marked as unmovable.
Finally, if the device doesn’t show up at all, it may be because it is unable to respond to the Talk R3 command at boot time (that is, it is not able to initialize itself and start watching the bus in time).
Devices & Hardware: Apple Desktop Bus: Distinguishing between two keyboards on the Macintosh
I connected two keyboards to my Macintosh®, but I can’t distinguish between the two. How can I tell which keyboard a key press came from?
Because of a problem in the Apple Desktop Bus™ (ADB) code, keyboards do not always correctly resolve collisions (multiple devices of the same type on the bus). This problem is in the keyboard, not in the Macintosh. For some applications, simply trying different keyboards until you find two that are assigned different IDs may be a workable solution. An Apple® Keyboard and an Apple Extended Keyboard should not collide when connected on the same bus.
Devices & Hardware: Apple Desktop Bus: Use of Apple’s ADB Transceiver IC for complex signal timing
I want to design the next best-selling graphics pad for Macintosh®. I plan to use Apple Desktop Bus™ (ADB). Is there a chip set available to implement the complex signal timing of the ADB specification?
Sorry. Apple’s ADB Transceiver IC is proprietary and not currently for sale or licensing. This is the greatest hurdle in designing your own ADB device and requires that you implement your own logic via a dedicated processor or application-specific integrated circuit (ASIC).
Devices & Hardware: Apple Desktop Bus: Apple Desktop Bus (ADB) licensing information
Apple Desktop Bus (ADB) licensing information
To license the Apple Desktop Bus™ and ADB Device Specifications, contact:
Apple Software Licensing
Apple Computer, Inc.
20525 Mariani Ave., M/S 38-I
Cupertino, CA 95014
1-408-974-4667
AppleLink: SW.LICENSE
Devices & Hardware: Apple II: Macintosh LC Apple IIe Card technical reference
Does the Apple IIe Card for the Macintosh LC have a technical reference manual?
There’s no separate technical reference manual. Use the Apple IIe Technical Reference (Addison-Wesley), together with Apple IIe Technical Note #10, “The Apple IIe Card for the Macintosh LC.”
Devices & Hardware: Cache: Apple IIGS caching logic if GS/OS cachePriority word is zero
Matt, I found your Apple IIGS® caching article to be very informative, but I’m confused about the driver level of caching. You say that if the cachePriority word on GS/OS direct page is zero, the driver should not write the block to the cache. If the block was already in the cache, won’t this mean the disk has a different block than is in the cache, messing things up drastically?
Thanks, and yes. When a driver is supposed to ignore the cache on a write call (because the cachePriority field is zero), it still must deal with the possibility that the block may already be in the cache. When writing with cachePriority zero, drivers may not add new blocks to the cache but must update blocks that are already in the cache. This step is necessary because the next time someone reads with caching enabled, the block in the cache will be returned. Next time I forget something, I promise that it will be less important.
Devices & Hardware: CD-ROM: CD-ROM and File Sharing
How do I make a single CD-ROM drive visible to users over the network? When I connect the CD-ROM drive to a machine running System 7.0 with File Sharing turned on, the CD-ROM drive doesn’t show up in the volume list at startup.
Unless a CD is specifically mastered to be compatible with File Sharing, it won’t be sharable. It doesn’t work as it does for hard drives because not all CDs are in HFS format and have the appropriate directory information that File Sharing requires. The easiest way to determine whether the CD you have is sharable, go to your System 7 machine, try selecting the disc, and then select “Sharing…” from the File menu. It will tell you if the disc can’t be shared. This may be the most likely reason why you couldn’t see the CD from a remote workstation. However, if that’s not the reason, it may be one that follows.
Folders from a CD-ROM disc can be shared the same way as a folder on a local hard disk. However, to be shared, the CD-ROM must be inserted before File Sharing is turned on. To switch between CD-ROMs, File Sharing must first be turned off, the new CD-ROM inserted, and File sharing turned back on.
If you insert a CD-ROM while File Sharing is on, you can eject and insert the disc, but you can’t share it. If a CD-ROM is inserted before File Sharing is on, then you have to turn File Sharing off to eject it.
Devices & Hardware: CD-ROM: File Sharing and CD-ROM discs
When I tried to disconnect (unmount) a CD-ROM in System 7.0, I got the message, “Can’t put away. Disk is being shared.” However, File Sharing status shows no volumes/folders shared. Restarting the Macintosh fixes the problem.
When File Sharing starts up, it takes a snapshot of the volumes available on the current desktop. All volumes (excluding floppies, which cannot be shared) are implicitly shared. This occurs even if no one is connected to your system, and you have not explicitly shared any folders/volumes via the Sharing menu.
The reason for this is that when you start File Sharing, you are making all volumes on the machine available to the owner from anywhere on the network. Therefore, your CD-ROM, and any other removable media, such as removable hard drives and optical drives, are now being shared for the owner and can't be removed.
If you make a volume available to your system after File Sharing has been started, that volume won't be available to the owner unless you explicitly share it via the Sharing menu. Therefore, once you start File Sharing either by booting with it active, or through the Sharing Setup Control Panel, you can mount and unmount new volumes as often as you like until they are explicitly shared.
If you wish to remove a volume that has been implicitly shared from your desktop, turn File Sharing off, remove the volume, and then turn File Sharing back on without restarting your system.
Restarting your Macintosh works because your CD-ROM ejects at restart, File Sharing is reset, and then you re-insert the CD-ROM.
(This Q&A was stolen from AppleLink’s Tech Info Library for Dev Tech Answers because developers ask this question frequently.)
Devices & Hardware: CD-ROM: HyperCard 2.0 and High Sierra format
With HyperCard 2.0 when accessing files in High Sierra format, the same stack that works OK on our hard disk fails to work on a CD-ROM. Some text files aren’t opened with the “open fname” instruction. Is it the “HOME.;1” syndrome—that is, should scripts say “open fname.;1”?
The problem probably does lie in the fact that the standard ISO naming convention has the “;1” appended. The workaround is to see if “open fname;1” works, but there may be a problem with the Home stack. You can insist that the home stack be copied to a local disk, or you can edit the string in HyperCard that has the name of the Home stack. In HyperCard 2.1 it’s in STR# 128 (“Misc”), item 17. Or you could violate the ISO naming convention and select your own name without the suffix.
Devices & Hardware: CD-ROM: Using the Macintosh ISO 9960 FST with another drive
How can I write an extension to the CD-ROM driver, such as a 'ufob' like the ISO 9660 module, or how can I use the 9960 with some other kind of drive?
You can use the ISO 9960 File System Translator with any type of drive. The only requirement is that the drive contain a file system in the ISO format. The file system just doesn’t care. The file system on the Macintosh® looks something like this:
Application (could be the Finder™)
|
V
File Manager
/ \
HFS Volume / \ Some Other Format Volume
/ \
(HFS) External File System (FFA, AppleShare®)
| |
| ISO, High Sierra, Audio CD
| File System Translators
| |
| |
Block Oriented Device Driver
(CD-ROM, Hard Disk, Floppy Disk, etc.)
||
\/
Data on Disk
Basically, what’s going on is if HFS doesn’t recognize a volume it passes control on to the External File System hook, which tries to decode the volume format of the unrecognized disk. You can think of the ISO FST as a decoder for Foreign File Access that “knows” what ISO disks look like. It in turn makes calls to the low-level driver associated with the device in question. The net result is that you can use FFA with any block-oriented device. All that needs to be written is a driver.
That’s the good news. Writing a Foreign File System or even an FST is an incredibly difficult procedure. Because the documentation is so poor and the mechanisms so convolved, it’s so hairy that DTS is unable to support it. It probably would take between 25 and 35 man-months of *extremely* talented Macintosh programmers to pull it off.
Devices & Hardware: CD-ROM: CD Remote INIT must be in System 7’s System Folder root
How can I use the CD Remote DA under Macintosh® System 7.0? I installed from the new CD utilities, but I get the message “can’t find the INIT.”
CD Remote INIT versions prior to 3.1 must be in the System Folder, not in the Extensions Folder. CD Remote INIT version 3.1 installs itself in the proper place, and has other bug fixes as well. Because of the bug fixes, you should upgrade to the current version, included with System 7.0 packages and available on AppleLink®.
(Placing an INIT in System 7.0's System Folder generally helps if you encounter a similar incompatibility problem. Some third-party products need to be upgraded to know about the various folders available. If you’re using a product that needs upgrading, make sure its developer is aware of the problem.)
Devices & Hardware: CD-ROM: Mounting audio CDs under MultiFinder
Using Macintosh® System 6.0.5, and/or System 6.0.7, and Apple CD-ROM driver set version 3.0.1 and/or version 3.0.2, I cannot mount Audio CDs under MultiFinder® or Finder™. I get the message “Please unlock the disk ‘Audio CD 1’ and try again. The desktop file couldn’t be created.”
However, if I am using a single application (say, HyperCard® 2.0), with MultiFinder turned off, I am able to mount an Audio CD without trouble.
That’s an odd problem. So why don’t you just unlock the Audio CDs? Sorry, just kidding! You should be able to mount CD-ROM discs from MultiFinder without any problem at all. I have a few suggestions for you to try:
First, try starting up your computer on the CD Installation disk. This assures that there are no strange INITs or anything loaded other than the CD-ROM software. If this works fine, this indicates some strange INITs in your System Folder.
Also, make sure your RAM cache is set to a value other than 32K. System 7.0ß1 has a bug in that if the RAM cache is set to 32K, it won’t allow you to mount CDs.
Last, try different combinations of SCSI cables, computers, and CD-ROM discs if you have the spares.
Devices & Hardware: CD-ROM: No changes to AppleCD SC driver 3.0.2
What’s the difference between the Macintosh AppleCD SC® software 3.0.2 uploaded to “Apple SW Updates” on AppleLink® and the old 3.0.1 update? According to the ResEqual utility in MPW®, all files are the same. So what’s the story?
There really aren’t any “real” changes with the AppleCD SC driver between 3.0.1 and 3.0.2. Basically all that was changed was the Installer script to make it compatible with Macintosh® System 6.0.7.
Devices & Hardware: CD-ROM: Why does my CD-ROM take so long to mount?
Why does my CD-ROM take so long to mount?
Slow loading can happen in several ways. For example, slow loading happens if you (or the CD-ROM mastering company) forgot to dismount the hard disk volume before making a copy for mastering. Whenever an HFS disk is mounted, a bit is set in the volume’s header, and it’s cleared again when you dismount the disk or shut down the Macintosh® normally. (Ever wondered what “You may now shut off your Mac safely” means? Now you know!) The purpose of this bit is a “crash flag”—if the Mac dies abnormally, leaving the bit set, at the next boot the Mac will recheck the integrity of the file structure and Desktop of the disk, just in case something got smashed during the crash. So if you master from a hard disk that has the bit set because you didn’t dismount it, the Mac will think your CD-ROM is potentially crashed every time you load it, and will spend a lot of time rechecking EVERYTHING on the CD.
If you are pressing a CD-ROM in High Sierra or ISO 9660 format, and it has a lot of files, the 2.0.1 version of our High Sierra/ISO 9660 support takes a lot time to mount the CD. This will be fixed in a future release.
Devices & Hardware: CD-ROM: Avoiding invalid boot blocks on a CD-ROM
How do I make sure that my CD-ROM doesn’t contain invalid boot blocks?
The normal way of pressing a Macintosh® HFS CD-ROM is by making an image copy of a hard disk. Unfortunately, this means that the boot blocks are copied as well. The startup code for a hard disk isn’t the same as for a CD-ROM (for example, a CD-ROM starts up in 2048-byte block mode, whereas hard disks start up in 512-byte block mode.)
To invalidate the boot blocks, use a volume editor to zero out the first 2 bytes on the volume. (These bytes contain the characters “LK” if the boot blocks are present.) By zeroing out these bytes, the Macintosh will not try to use the invalid boot blocks that have been copied from the hard disk.
Devices & Hardware: CD-ROM: -120 (dirNFerr) on a Macintosh
Why do I get a -120 (dirNFErr) on a High Sierra CD-ROM, but not on a HFS CD?
Your program is probably saving directory IDs as a 16-bit quantity. Directory IDs are 32-bit values. On most HFS disks, this doesn’t matter; you must have many, many files on a disk to get a directory id that is a long value. Because of the implementation of our support for High Sierra and ISO 9660 CDs, the directory ID is always a long value.
Devices & Hardware: CD-ROM: Identifying a CD-ROM in the drive queue or volume queue
What is a reliable way to tell which element in the drive queue or volume queue is a CD-ROM? I am trying to write a routine that prompts a user to insert specific volumes by name and ejects any that may be in the drive.
For a CD in High Sierra, ISO 9660, or Audio only formats, you can use PBHGetVInfo to check for the ioVFSID (file system ID.
High Sierra disks always have a FSID of 0x4242.
ISO 9660 disks always have a FSID of 0x4147.
Audio CDs always have an FSID of 0x4A48.
You should also check for a hardware locked device by checking the ioVAtrb field. The bits for this are defined on page 167 of Inside Macintosh® Volume IV.
For the AppleCD SC® drive, you can call the driver with a PBstatus call of 97. csParam+1 contains bits corresponding to each of the 8 possible SCSI IDs. SCSI ID 0 is the right-most bit. A bit is set if an AppleCD SC drive exists at that SCSI ID. See the “AppleCD SC Developer’s Guide,” available from APDA®, for further details.
Devices & Hardware: CD-ROM: System 7.0b1 crashes when I insert a CD into my CD-ROM drive
Macintosh® System 7.0b1 crashes when I insert a CD into my CD-ROM drive.
System 7.0b1 wants the size of your Apple Disk Cache to be 128K or more. You can set it using System 7’s Memory ‘cdev’ in the control panel.
Devices & Hardware: CD-ROM: CD-ROM ignored by System 7.0b1 if 32-bit addressing is enabled
My CD-ROM drive is ignored by Macintosh® System 7.0b1 if 32-bit addressing is enabled.
Don’t use 32-bit addressing if you want to read from a CD using this beta system software.
Devices & Hardware: CD-ROM: Where Macintosh System 7 wants CD-ROM files placed
Is there a way to load the INITs for the CD-ROM drive in a fashion that System 7 accepts, so the drive appears on the Macintosh® desktop?
You’re encountering problems installing the CD-ROM drivers on System 7? Imagine that! Not to be too glib, but that’s a common problem.
Here’s the scoop: The “CD Remote” DA goes into the Apple Menu items folder; the “Foreign File Access” and “Apple CD ROM” files go into the Extensions folder; and “CD Remote INIT,” “CD Remote Programs (if you have this file),” “ISO 9660 File Access,” “High Sierra File Access,” and “Audio CD Access” all go into the top level of your System Folder.
The easiest way to accomplish this is to run the CD-ROM installer and then rearrange the files as necessary. Even if you have the files in the right place the first time, if it still doesn’t work, you should erase them and run the installer. For some reason it may take a second try.
Devices & Hardware: CD-ROM: CD-ROM technical references
CD-ROM technical references:
- AppleCD SC® Developer’s Guide
- Macintosh® Technical Note #209, “High Sierra & ISO
9660 CD ROM Formats”
Devices & Hardware: CD-ROM: Pressing a CD-ROM
How do I press my own CD-ROM?
We’ll assume that you’re looking at a moderate number of CDs (one hundred to several thousand) for your needs. It makes sense to press a CD if you have 10 megabytes or more of data and need 100 or more copies of it.
CDs behave just like a locked, very fast, very big floppy. If you can run your program or HyperCard® stack on a locked floppy, it will run on a CD.
To press a CD-ROM, you have two options; the easy way and the hard way. The easy way gives you a Macintosh® CD that’s a copy of a hard disk. The hard way gives you the Macintosh CD plus the ability to create audio CD quality sound tracks, or to create a CD that can be used across many operating systems in a format called High Sierra.
The easy way is to put your data onto a hard disk and send the hard disk to one of the companies listed below (call before sending). They will create an image copy of your hard disk (an exact duplicate) and put that image onto CDs. Easy, quick, and painless. To create such a CD, you’ll be charged a mastering charge (for creating the initial image) plus a duplication charge per CD. The mastering charge varies, but is usually under $1500. The duplication charge is around $1.85 per CD, including packaging. The average turnaround time is 5 to 10 days.
If you want faster turnaround time, you’ll pay more. Typical mastering charges for one day turnaround starts under $3000. If you want zillions and zillions of CDs, you’ll pay less money. Any of the production companies will be thrilled to hear from you.
The hard way of pressing a CD-ROM involves using a premastering system to create a tape that a pressing plant can use to create CDs. This provides much more flexibility, since you control what goes on the tape. You need much more technical knowledge, and you need access to a premastering facility. You can purchase a premastering system; you’ve got names in the Apple CD-ROM Development Resource Guide. There are companies that will rent you time on their premastering system and help you out with the details (for a fee).
If you want to press a CD that can be used on many different operating systems, you want to use a volume format called High Sierra (also known by the name of its international standard, ISO 9660). If you press a CD in this format, you can read the data on many different operating systems. You’ll need to plan your data carefully so that it can be used on many machines; for example, many spreadsheets can read a common format, and almost every word processor can read plain text. HyperCard uses a proprietary format that can only be used on the Macintosh, so it’s generally not a good choice for a High Sierra CD.
For a good overview of CD-ROM, read the AppleCD SC® Developer’s Guide, available from APDA®. There is a new magazine called CD-ROM EndUser, available from DDRI, 6609 Rosecroft Place, Falls Church, VA 22043.
Some companies to contact regarding CD-ROM production (in no particular order):
3M Optical Recording DADC
Building 223-5S-01 / 3M Ctr. 1800 N. Fruitridge Avenue
St. Paul, MN 55144 Terre Haute, IN 47804
612-736-3274 812-462-8100
Mark Arps/Dick Tendill Linda Watson/Kozo Arai
AppleLink: D2462 AppleLink: D2125
Discovery Systems Philips Dupont Optical
7001 Discovery Blvd 1409 Foulk Road, Suite 200
Dublin, Ohio 43017 Wilmington, DE 19803
614-761-4287 800-433-3475
Jack Ryan Jill Jones
AppleLink: D1191 AppleLink: D2173
Nimbus Information Systems Denon America
SR 629, Guildford Farm 222 New Road
Ruckersville, VA 22968 Parsippany, NJ 07054
800-782-0778 201-575-2532
Larry Boden Nob Tokutake/Ben Garcia
Disctronics
1120 Cosby Way
Anaheim, CA 92806
714-630-6700
Wan Seegmiller
Some technical hints:
• Don’t put 1000 files in one folder. The Finder is very slow at opening such folders.
• Make your disk contiguous for speed. Either back up, reformat the disk, and copy everything on again, or use a commercial disk organizer such as DiskExpress by AlSoft or SUM by Symantec.
• Waste disk instead of cycles. Precompute information that speeds up your program or stack; you’ve got 660 megabytes to waste. Use them.
• Take advantage of the static nature of CD-ROM. Put absolute file names in your HyperCard® stacks.
(The legal beagles want me to tell you: All company names and prices are here for your information, but Apple Computer, Inc., does not recommend or endorse any particular company listed. Apple, HyperCard and Macintosh are registered trademarks of Apple Computer, Inc. AppleCD SC and APDA are trademarks of Apple Computer, Inc. DiskExpress is a trademark of AlSoft, Inc. SUM is a trademark of Symantec, Inc.)
Devices & Hardware: Custom ICs: Why Macintosh IIci and IIsi don’t support direct video
What prevents the RBV (Ram Based Video) chip in the Macintosh® IIsi from displaying 16-bit color on the new 12" Macintosh RGB monitor similar to the Macintosh LC?
The RBV chip is not able to supply data directly to its D/A converters; thus it bypasses the color lookup step completely. The Macintosh IIci and IIsi hardware is not capable of supporting direct video.
Devices & Hardware: Custom ICs: Don’t access Macintosh RBV chip VIA emulation registers directly
Are the VIA emulation registers of the Macintosh® RBV chip documented? If not, what are the offsets to the VIA emulation registers on the RBV chip? Is there more than one way to access the RBV registers?
The VIA emulation registers of the RBV chip are not documented because Apple does not want developers to use them. We have not supported the use of the VIA registers and we do not plan on supporting the registers of the various new ASICs that Apple has developed. If you decide to use these registers anyway, you are on your own. We don’t know of another way to access the RBV registers.
Devices & Hardware: Custom ICs: Where to find out how to control the Apple IIc Plus accelerator
How can I control the speed of the Apple® IIc Plus?
Firmware routines exist to allow the programming of the accelerator in the Apple IIc Plus. These routines are documented in the Apple IIc Technical Reference, 2nd Edition, available from APDA®. Apple encourages all developers with products that run on the Apple IIc to replace previous IIc documentation with this book.
Devices & Hardware: Device Manager: Determining if a file is read from CD-ROM or hard disk
How can we tell whether a particular Macintosh file is being read from a CD- ROM or a hard disk?
You can call the Device Manager routine OpenDriver using the “.AppleCD” string to find a driver reference number of the AppleCD SC drive. If there is more than one AppleCD SC drive hooked up, then additional “.AppleCD” driver reference numbers can be obtained by using the PBControl call with a csCode = 97 (WhoIsThere). This command returns a mask of which SCSI devices are being serviced by the “.AppleCD” driver (that is, which other drives are AppleCD SCs).
The following code returns the driver reference number for an “.AppleCD” driver instance. The input parameter CDDrive specifies which logical AppleCD SC drive in the SCSI chain to open.
#define csWhoIsThere 97
typedef unsigned short Word;
typedef unsigned long Long;
typedef struct WhoIsThereRec {
ParamBlockHeader
short ioRefNum;
short csCode;
struct {
Byte fill;
Byte SCSIMask;
} csParam;
} WhoIsThereRec;
pascal OSErr OpenCD(Byte CDDrive, short *ioRefNum) {
auto OSErr osErr;
auto short ioRefNumTemp,
CDDriveCount,
SCSIID;
auto WhoIsThereRec *pb;
pb = (WhoIsThereRec *) NewPtrClear(sizeof (*pb));
osErr = MemError();
if (0 != pb && noErr == osErr) {
osErr = OpenDriver("\p.AppleCD", &ioRefNumTemp);
if (noErr == osErr) {
(*pb).ioRefNum = ioRefNumTemp;
(*pb).csCode = csWhoIsThere;
osErr = PBStatus((ParmBlkPtr)pb, false);
if (noErr == osErr) {
CDDriveCount = 0;
for (SCSIID = 0; SCSIID < 7; ++SCSIID) {
if (BitTst(&(*pb).csParam.SCSIMask, 7 - SCSIID)) {
++CDDriveCount;
if (CDDrive == CDDriveCount) {
*ioRefNum = -(32 + SCSIID) - 1;
DisposPtr((Ptr) pb);
return noErr;
}
}
}
osErr = paramErr;
}
}
DisposPtr((Ptr) pb);
}
return osErr;
}
You can modify OpenCD to do exactly what it is you need it to do. Or, you might use it to iterate over the logical CD drive numbers from 0 to 6 until OpenCD returns something other than noErr. If you modify the OpenCD routine, you’ll need the “AppleCD SC Developers Guide, Revised Edition” (APDA #A7G0023/A, $25.00) to be successful. Note also that all unused fields of a parameter block used with the “.AppleCD” driver must be set to zero before calling PBControl.
Iterating over the seven possibilities will result in a table of known “.AppleCD” drive entries—perhaps something like the following structure:
struct {
int count;
short cdDRefNum[7];
} knownCDDRefNum;
With this table in hand, you can match the driver reference number for the volume of any file. In most cases you know which volume the file was on when you opened it. Also, the routines PBGetFCBInfo and PBGetCatInfo both return the volume reference number for a file.
Once you determine the volume reference numbers, either traverse the VCB table or call PBGetVInfo to get the driver reference number. This driver reference number is the driver handling all requests made by the File System for your file!
If that driver reference number for the file is in our “knownCDDRefNum” table, then that file resides on an AppleCD SC drive. This technique works only for Apple or Apple-compatible drivers. An alternate approach to the problem is stepping through the driver table and locating all entries with the name “.AppleCD,” noting their driver reference numbers, and then following the procedure outlined above to determine if a file is on a volume owned by that driver.
The csCode method is far clearer than this one, and should be used whenever possible. The bottom line is that there is no guaranteed method of locating a CD-ROM drive due to the lack of a standardized driver model.
X-Ref:
Device Manager chapters of Inside Macintosh Volumes II, IV, and V “Finding a Slot for a Driver” note on latest Developer CD Series disc
Devices & Hardware: Device Manager: Accessing a Macintosh driver resource fork at accRun time
How do I get Macintosh® resources from a driver Init file at accRun time? I can’t think of a way other that getting the full path name, which is discouraged.
Basically, you need to call PBGetFCBInfo at INIT time to grab the filename, directory ID and volume reference number for the INIT’s resource fork. You can then store these in your INIT and pull them out at accRun time. At accRun, just call HOpenResFile to get to your resources. This method is _much_ better than using a full pathname, since this still works in the case where the user re-names the folder containing your INIT.
Here’s some sample code that does what you need:
OSErr GetCurResLocn(short *saveVRefNum,long *saveDirID,StringPtr saveFName)
{
FCBPBRec pb;
OSErr err;
short theFile;
Str255 fName;
theFile = CurResFile();
pb.ioFCBIndx = 0;
pb.ioVRefNum = 0;
pb.ioRefNum = theFile;
pb.ioNamePtr = saveFName;
err = PBGetFCBInfo (&pb,false);
*saveVRefNum = pb.ioFCBVRefNum;
*saveDirID = pb.ioFCBParID;
return err;
}
OSErr SetCurResLocn(short saveVRefNum,long saveDirID,StringPtr saveFName,
short *newResFile)
{
short resRef;
OSErr err;
HOpenResFile(saveVRefNum,saveDirID,saveFName,fsRdWrPerm);
err = ResError();
if (err!=noErr)
return err;
UseResFile(resRef); /* <-- needed in case the res. file was
prev. open */
*newResFile = resRef;
return ResError();
}
void main()
{
OSErr err;
short saveVRefNum;
long saveDirID;
Str255 saveFName;
short newResFile;
err = GetCurResLocn(&saveVRefNum,&saveDirID,saveFName);
if (err!=noErr)
return;
/* … pass control off to computer here (we're an app, so we
fake it) … */
err = SetCurResLocn(saveVRefNum,saveDirID,saveFName,&newResFile);
if (err!=noErr)
DebugStr("\pfailed");
}
As you can see, this is an application, so you’ll have to do some minor modifications (possibly convert to 680x0). It’s pretty straightforward, and the HOpenResFile call is included in MPW® glue for MPW 3.0 and is a built-in call for System 7.
Devices & Hardware: Device Manager: New info on Macintosh Device Manager calls
Are Macintosh® Device Manager status calls with csCode=1 calls filtered out? Also, are all high-level Device Manager routines always executed synchronously? If all the calls are synchronous, why is there a high level KillIO routine (to terminate current and pending processes)?
Yes, a Status call made with a csCode of 1 never calls your driver. Instead, it returns (in the csParam field) the handle to your driver’s Device Control Entry from the Unit Table.
High-level Device Manager calls are executed synchronously. Only the low-level calls can be specified to execute asynchronously. The high-level KillIO routine is useful for terminating I/O pending from a low-level call, which may have been initiated by someone else.
Devices & Hardware: Device Manager: JMP or JSR when calling IODone
After an I/O call to a Macintosh® slot device driver, shouldn’t the IODone routine be called by a JSR instead of a JMP instruction in order for a slot device to return to it with D0 set to an appropriate value depending on whether the interrupt was serviced?
You only call IODone when the queued up I/O request has been fully completed. If the interrupt handler is completing an asynchronous call, then you need to call IODone. IODone returns via an RTS, and preserves D0. Therefore, what you should do is have your interrupt service routine set D0 and then jump to IODone (via JIODone*). IODone will do its thing return via an RTS instruction. The sequence would be something like:
0. A program is running
1. The interrupt occurs
2. The Device Manager does a JSR to your Interrupt Service Routine (ISR)
3. The I/O request is complete, so your ISR sets D0 and jumps through JIODone
4. IODone does an RTS, which will be back to the Device Manager
5. The Device Manager does an RTE back to the program
6. The program continues
*The J (in JIODone) stands for Jump, so the ISR pushes JIODone onto the stack, which puts the address of what’s in JIODone ($8FC) on the stack. This is followed by an RTS instruction which executes it. So JIODone can be thought of as a vector to IODone.
If you are just handling a hardware interrupt or the I/O is not yet complete, don’t call IODone. Do an RTS like the example in Designing Cards and Drivers for the Macintosh Family (Chapter 9 source example, starting with the BeginIH label).
Devices & Hardware: Device Manager: Given a Macintosh gdRefNum, how can I find the associated slot?
Given a Macintosh® gdRefNum, how can I find the associated slot?
Get the slot number from the auxiliary DCE. The following code snippet indexes through the GDevices (it’s assumed the check showed the presence of Color QuickDraw™), and pulls the slot number from each GDevice record:
gGDHandle := GetDeviceList; {get the first GDevice list handle}
repeat
if gGDHandle <> nil then
begin
gAuxDCEHandle :=
AuxDCEHandle(GetDCtlEntry(gGDHandle^^.gdRefNum));
{ do whatever slot specific work is desired, now that
the slot }
{ number is known }
gGDHandle := GetNextDevice(gGDHandle);
{ pass in present GDHandle; the next one is returned }
end;
until gGDHandle = nil;
Devices & Hardware: Device Manager: Macintosh Device Manager handles queuing and asynchronous calls
How can the Macintosh® Device Manager help my driver handle things like asynchronous calls, queueing, and so on?
The Device Manager will handle all the queueing and asynchronous niceties for you with the jFetch, jStash, and jIODone calls. jIODone handles queueing and calling completion routines for asynchronous calls. jFetch, and jStash are for the interrupt handlers, and provide the mechanism for knowing how far along you are in a particular request.
When you call jIODone, the entry that was being handled will be removed from the queue, its completion routine is called, and then if there is another entry in the queue, your driver will be called to handle it.
If you return via an RTS rather than jIODone (you haven’t yet completed the operation requested—that is, waiting for more bytes), the queue entry will remain in the queue, and others behind it will not execute until the next jIODone is called. Queued entries are always executed in sequence. If your driver is not asynchronous, you still need to call jIODOne to clear the queue for the next entry (unless the IMMED bit is set in the ioTrap field).
jFetch and jStash are two calls provided to assist an interrupt driven asynchronous driver. From within your interrupt routine, you can call jFetch to get the next byte from the caller’s buffer, or jStash to place the next byte in the caller’s buffer. In addition to dealing with the caller’s buffer, these two calls also handle the ioActCount and let you know when you have completed the current request (see Inside Macintosh Volume II, pages 194-195).
A good example of this is the serial drivers. In the case of the output driver, if the calling application makes a pbWrite call to the serial output driver, and specifies a buffer of 200 characters, the Device Manager places the request in the queue for the Serial Driver and calls the prime routine. The prime routine gets the first character from the buffer by using the jFetch call, and places it in the transmit buffer of the SCC chip and simply does an RTS. The SCC chip has the ability to generate an interrupt when the transmit buffer is empty, so when that happens, the interrupt handler gets the next character from jFetch, and sticks it in the transmit buffer. When jFetch finally gets the last character, the interrupt routine places it in the transmit buffer, and calls jIODone, which then removes that request from the queue, calls the completion routine, if any, and executes the next queued request, if any.
If your driver is supporting non-interrupt driven hardware, you can just receive the prime call, and use jFetch (for example) to get the requested bytes from the buffer, send them to your hardware, and repeat until jFetch returns buffer empty, then return via jIODone. This is an example of synchronous operation that still uses the queueing mechanism, except that no new requests will ever have a chance to get queued until the previous request is completed.
Devices & Hardware: Device Manager: How do I support locked and ejectable SCSI devices?
How do I support locked and ejectable SCSI devices?
The only things you should have to support are the _DriveStatus call and modify the DrvQEl record. The rest will be handled by the Macintosh® system. The _DriveStatus call gives the information for srvStsCode. This is how the system will know what your disk can support. It is typically only used by floppy (or removable) disk drives. The sample SCSI driver from Apple doesn’t need to support it, because it doesn’t support any of the information in the _DriveStatus call.
The DrvSts record contains some information of no concern here. The diskInPlace, twoSideFmt, and needsFlush are probably ignored for your device. It’s best to zero them out. The DrvSts information is pretty much just the same information returned in the DrvQEl record.
Also, people sometimes get into trouble while developing a driver because current File Manager documentation about the drive queue element is vague. There are 4 bytes in front of a DrvQEl record. These determine the device’s abilities, but THESE BYTES ARE NOT ALLOCATED BY THE SYSTEM. When creating the DrvQEl record, you need to add these four bytes in front of the record yourself. The pointer to a DrvQEl will be the actual record, which is AFTER these 4 bytes. To read these bytes yourself, you’ll have to subtract 4 bytes from the DrvQEl pointer.
It is important to note that the Disk Switch error dialog is not an actual dialog, but the system error. It is handled by the same code as SysError which shows the system bomb alert. While this window is present, _SystemTask is not being called. This means the driver will not get an accRun call. To work around this, you will need a VBL task. When the VBL is called it checks the SCSI bus for being free and if so, tests for a new cartridge. Once found, posts a diskInsertEvt. This will be received by the driver.
While the media is inserted, the VBL should not be running until after the cartridge is ejected. Otherwise, the SCSI bus will continue to be accessed unnecessarily, which slows the bus. The VBL task could also slow the system while virtual memory is running.
Devices & Hardware: Device Manager: Macintosh journaling mechanism
How can I use the journaling mechanism described in Inside Macintosh®?
The old journaling mechanism isn’t supported any more. It is no longer necessary because of MacroMaker and similar products. MacroMaker now “owns” the older driver, and any future journaling will be done through MacroMaker. Currently there is no technical documentation available for MacroMaker. The current abilities of MacroMaker may not support what some developers will want to do with journaling. Future versions of MacroMaker may add more features.
Devices & Hardware: Disk Driver: Macintosh disk drivers and System 7 compatibility
Is there anything special that a Macintosh hard disk or a removable cartridge driver must do to be fully compatible with System 7?
One important thing you should be aware of regarding removable cartridges is that a cartridge can’t be removable if VM is to use it for a backing store. Some removables allow you to fix this with a SCSI command to prohibit ejection and, just as important, the drive must be marked nonejectable in the drive queue.
Here are a couple of suggestions: Read Macintosh Technical Note #285, “Coping with VM and Memory Mappings.” Also, take a look at the Memory Management chapter of Inside Macintosh Volume VI and the Virtual Memory paper (Goodies:VM Goodies:VM Paper) on the System 7 Golden Master CD.
Devices & Hardware: Disk Driver: System 7 disk driver reentrancy requirements
What are the reentrancy requirements for System 7 disk device drivers?
If and only if multiple DCEs point to the same shared code in memory, it is possible for a disk driver to be reentered by VM. This will only happen when the driver is busy with one drive and VM wants to access another one controlled by the same driver as a result of a page fault at interrupt time. To prevent reentrancy problems, a disk driver should maintain a separate independent set of variables for each drive it supports, and it should access those variables only through the DCtlPtr passed to the driver in A1 when it is called.
Many disk drivers don’t even need to worry about this because a separate copy loads for each entry in the unit table.
X-Ref:
Macintosh Technical Note #285, “Coping with VM and Memory Mappings”
Devices & Hardware: Disk Driver: Low-level Macintosh floppy disk access
I need to be able to modify the number of sectors per track and the interleave the disk drive looks for. There must be some way to do this through the driver. Do you have any example code of accessing the driver directly?
The only floppy access we support is through the driver, as documented in Technical Note #272. The driver only handles block-level access, except that if you’re using a Macintosh® IIfx, the Raw Track Dump call gives direct read access to the data on the track. This may be just what you need; unfortunately, we don’t have any example code that covers this call.
Devices & Hardware: Disk Driver: Macintosh RAM disk driver tricks
How are you able to keep the Macintosh® Portable’s RAM Disk from being destroyed after it has been dragged to the trash? Could we pull that trick with our RAM disk too? How does the RAM Disk’s memory stay protected during system startup? Also, the Finder’s “Get Info” window for the RAM disk shows “Where: Internal RAM disk” rather than “Where: AppleTalk.” How does the driver convey this information to the operating system?
At the time that your driver receives a disk eject, post a disk insertion event to the OS event queue. Your icon will disappear and reappear like magic.
The Macintosh Portable has a special version of the disk driver that looks for special header blocks for a RAM disk and multiple ROM disks in the ROM expansion address space. If it finds the correct header, it tells the system initialization (again specially coded for the Macintosh Portable) to not check the RAM mapped out by the RAM disk header.
The ‘Get Info’ dialog gets the “Where” information from the standard control call to the disk driver. Your driver should respond to a Status call with a csCode =21 as documented in Inside Macintosh Volume V, page 470.
Devices & Hardware: Disk Driver: System 7.0 and color volume icons
Now that Macintosh® Finder™ icons can be in color, is it possible to have color volume icons as well, and, if so, would you share the specifics?
Unfortunately, there’s no way for the driver to provide the default icon in color—that is, there are no calls newer than those described in Macintosh Technical Note #28, “Finders and Foreign Drives.”
The System 7.0 Finder can display a custom color icon for a volume, though. The user can paste a new color icon over the old one in the volume’s Get Info box. (Click the icon in the box to select it, then Paste.)
Devices & Hardware: Disk Driver: System 7 requires disk driver updates
I can’t get the 7.0 beta to run on either of my Macintosh® systems. The problem seems to be tied to my third-party hard disks. System 7 wouldn’t install on one third-party hard drive, and my other system crashed at startup attempting to access another third-party hard drive.
With System 7.0, we provided the Apple HD SC Setup utility with new HD drivers to update the drivers for our hard disks. Third parties will have to update the drivers for their equipment to be compatible with 7.0.
Devices & Hardware: Disk Driver: Macintosh Finder eject on Unmount
Why doesn’t dragging a mounted hard disk partition into the Trash Can generate an Eject call to the device driver?
Only ejectable media such as floppy disks generate an eject call. All others generate an Unmount call. If you were to set the ejectable bit (which is documented in Inside Macintosh® Volume II, page 127-8), you will get an eject call for a hard disk which will then result in a continuous “Please insert <your hard disk>” alert.
Devices & Hardware: Disk Driver: Logical-to-physical sector information for 800K disks
Does the translation between logical and physical sectors on an 800K disk work in the same manner as a 400K disk (as per Inside Macintosh®). If so, do track/sector numbers alternate between sides? Is this information available elsewhere, or should we be able to figure this out from data available from FEdit?
The translation between logical and physical sectors on an 800K disk follows in a manner similar to that for the 400K disk (Inside Macintosh, Volume II, page 211), except that sectors alternate between sides before moving on to the next track as you suggested.
First we’ll define side 0 and side 1. Similar to the 400K disk, there are 80 tracks on each side. Track 0 is outermost, track 79 is innermost. The sectors per track are grouped in a similar manner to the 400K disk.
The first 12 sectors for an 800K disk map to side 0, track 0, sectors 0-11, similar to the corresponding sectors on the 400K disk. The next 12 sectors for the 800K disk map to side 1 in a similar manner—side 1, track 0, sectors 0-11. Logical sectors 24-36 map to side 0, track 1, sectors 0-11, and so on. The following chart demonstrates this:
Side Track Sectors Physical Logical
Per Track Sectors Sectors
0 0 12 0-11 0-11
1 0 12 0-11 12-23
0 1 12 0-11 24-35
1 1 12 0-11 36-47
...
1 15 12 0-11 372-383
0 16 11 0-10 384-394
1 16 11 0-10 395-405
0 17 11 0-10 405-415
...
1 31 11 0-10 725-735
0 32 10 0-9 736-745
1 32 10 0-9 746-755
0 33 10 0-9 756-765
...
1 47 10 0-9 1046-1055
0 48 9 0-8 1056-1064
1 48 9 0-8 1065-1073
0 49 9 0-8 1074-1082
...
1 63 9 0-8 1335-1343
0 64 8 0-7 1344-1351
1 64 8 0-7 1352-1359
0 65 8 0-7 1360-1367
...
1 79 8 0-7 1592-1599
Devices & Hardware: Disk Driver: How to determine if a disk drive supports ejectable media
How can I determine if a disk drive supports ejectable media?
The disk driver in Macintosh® System 6.0.2 (and later) supports control calls with cscode = 23; this call returns information about the drive’s physical location, size, and other characteristics described as follows:
Return Drive Info (csCode = 23) csParam = long;
Most of the bits are not used at the moment and are being reserved for future expansion. The drive type field is in bits 0 through 3 and describes the type of drive that is connected. The supported types are as follows:
0 no such drive
1 unspecified drive
2 400K
3 800K
4 High Density drive FDHD
5 reserved
6 reserved
7 Hard Disk 20
8-15 reserved
The attributes field occupies bits 8 through 11 and describes the following:
bit 8 0 - Internal 1 - external
bit 9 0 - IWM 1 - SCSI
bit 10 0 - removable 1 - fixed media
bit 11 0 - primary 1 - secondary
So, bit 10 in csParm tells whether the drive in question supports ejectable media or not.
Drivers from other manufacturers may not support this control call, in which case it becomes necessary to traverse the queue in order to secure the information. The following little assembly language routine shows how to do it the old-fashioned way, as mentioned in Inside Macintosh Volume II (page 128) and Volume IV (page 181):
;--------------------------------------------------------------
; FUNCTION DoItTheOldWay(ioDrvNum: INTEGER): integer;
; returns: 0 = is ejectable
; -1 = is not ejectable
; 1 = error occurred (could not find specified drive)
;--------------------------------------------------------------
DoItTheOldWay PROC
MOVE.L (sp)+,A0 ; save the return address
MOVE (sp)+,D1 ; get target drive #
MOVE.L DrvQHdr+QHead, A1 ; Point to the drive queue
@0 CMP.W DQDrive(A1), D1 ; is it the right drive #?
BEQ.S @1 ; if so, skip out
MOVE.L QLink(A1), A1 ; Get the link to the next
vol
MOVE.L A1, D0 ; is it NIL?
BNE.S @0 ; if not, go back.
MOVE.W #1,(SP)
JMP (A0)
@1
CMP.B #8,-3(A1) ; ejectable value??
@5 SGE (SP) ; record if it isn't ok
JMP (A0)
ENDP
Devices & Hardware: Disk Driver: DTS’s copy protection position
How can I protect my software? I want to prevent my software from being illegally copied and distributed.
Apple Developer Technical Support’s official position is that software copy protection is a bad idea, so we don’t support development of protection schemes. Here is a summary of arguments against copy protection:
(1) You will have to put your valuable resources into engineering a scheme, which usually means disassembling the ROM to understand the disk drivers, HFS, MFS, and so on, as well as fully understanding how the hardware for each machine your software runs on works. This extra work adds time to your development schedule.
(2) You’ll have to maintain your software when it doesn’t work on future machines or system software releases. Virtually every copy protection scheme devised so far (that we know about) has required revision for new Apple® CPUs.
(3) You’ll have to test the software on all machines and products, including third-party hardware and file system software.
(4) You’ll have to support possibly angry users who have problems using the software because of the protection scheme, or have broken “key” disks, etc. Users may be frustrated by an inability to copy software to a hard disk, make backups, or immediately use the software with new hardware or software.
(5) Every copy protection scheme devised so far (that we know about) can be defeated by commercial products that remove or circumvent the protection.
(6) Protected software frequently receives poor reviews or mentions in the press because of the protection scheme.
We feel that copy protection is not a worthwhile use of development time. We cannot help you develop a protection scheme, or provide support when protected software breaks with future hardware or software.
Devices & Hardware: Disk Initialization Package: Apple HD SC Setup and third-party hard drives
The Apple HD Setup utility formats my third-party drive, but it reports an error mounting the drive before partitioning it.
The Apple HD SC Setup utility is written for Apple drives—or, more specifically, for the controller on Apple drives. Even if the hard drive you are trying to format with the utility is from an Apple supplier, it may have a different controller than an Apple drive. You should use the formatting utility that was included with your drive.
Devices & Hardware: Disk Initialization Package: GS/OS volumes and ProDOS 32 MB file system limit
Adv.Disk.Util on the Apple IIGS® System 5.0.4 System Tools disk lets me create a 60 MB partition, I can only format it for 32 MB, effectively loosing 28 MB in the partition. Is there any way to get around this?
GS/OS® volumes can be any size up to four gigabytes. However, GS/OS has no native file system and relies on file system translators (FSTs) to read any physical file layout on any disk.
Currently, the main FST used for the Apple IIGS is for the ProDOS® file system, and ProDOS volumes can't be larger than 32 MB because the file system structures don't allow access to more than 65,536 512-byte blocks.
You can make any volume size you want, but ProDOS can only use the first 32 MB of any volume. Other FSTs (like AppleShare®) do not have this limitation.
Devices & Hardware: Disk Initialization Package: System 7.0, Disk First Aid 7.0, and Hard Disk Setup 2.0.4
We were told that it would be highly advisable to do a file-by-file back-up of all hard drives, a fresh format, and a restore because of a bug in the B-Tree algorithms that’s been fixed in the System 7.0 Golden Master. Can we do this and then return to System 6.0.7 safely? Is Apple going to make any sort of general announcement about this problem? Also, can we expect that it is not a “contagious” problem in any way—that is, can we back things up and restore without worrying about it moving from disk to disk?
Apple is recommending that users run the final version of Disk First Aid (version 7.0) on all their hard drives to determine if there are any problems with the B-Trees. The reason for this is that a bug has existed in the Macintosh® (HFS) operating system from its inception such that the B-Tree structures for devices would become corrupted under certain EXTREMELY RARE circumstances. If and only if DFA reports a problem that it cannot fix (it will tell you if it can or can’t) should users perform a file-by-file back up of their data, then reformat all Apple hard drives using HD Setup before copying files back. Making a mirror backup of your data will only put the damaged B-Tree catalog back onto the drive when you restore, so be sure to make your backup file-by-file.
Apple does not intend to make any general published announcement about this because it is addressed in the System 7.0 documentation. As for the commonly asked question, “Why should we back up our data before upgrading to System 7.0? Are we in danger of losing our data?”: Backing up your data on a regular basis is always a good idea, and we are recommending it prior to installing System 7.0 only because there is always a chance of data loss when major changes are made to any system configuration. Since System 7.0 is very different in many ways from previous system software versions, some software packages are no longer compatible under this release and conflicts can potentially cause loss of data integrity.
There has been some confusion as to what, exactly, Disk First Aid version 7.0 can do. This version can detect problems with the B-Tree structures (whereas previous versions could not—the only clue it would offer is the “unable to verify status of disk” error). It cannot fix the damage, however. Another bug that DFA 7.0 can correct lies in the Directory Valance. This bug went generally unnoticed for years; it usually resulted in VERY INfrequent occurrences of some annoying behaviors such as not being able to throw away an empty folder (remember the old “Trash could not be emptied because a file was busy or locked” error?). Like the B-Tree structure corruption, this is a bug, not a virus, and is in no way contagious.
If you reformat the drive then reinstall System 6.0.x, you run the risk of damaging the B-Tree structures again because the bug is still present in the B-Tree Manager in ROM. Again, however, let me reiterate that it isn’t easy to take it that far. Suffice it to say, you will, in fact, be almost assuredly safe if you run DFA 7.0 occasionally to make sure your B-Tree structures are OK. If it says everything is fine, it is. If not, back up your data and reformat.
Another important step in your upgrade to System 7.0 is updating all SCSI device drivers by using the Hard Disk Setup (2.0.4 or later) utility for Apple hard drives that accompanies the System 7.0 software (for third-party devices, refer to the vendor to determine if updated drivers are necessary) BEFORE upgrading to System 7.0. The reason for this is that these newer drivers are incompatible with Virtual Memory. Failure to update these structures will prohibit using VM—it won’t even turn on—however, you’ll be able to use all other features of System 7.0 without any problems provided, of course, that your configuration meets the recommended memory requirements and all your software is fully compatible with this system software release.
Devices & Hardware: Disk Initialization Package: Macintosh System 6.0.4 and HD Setup 2.0.1
Is it OK to initialize a Macintosh® IIci with Apple HD Setup 2.0.1 (shipped with System 6.0.5) to get the interleave factor of 1 instead of 2, but then install and use System 6.0.4 instead of System 6.0.5?
Yes, it’s OK to initialize any Macintosh, including the Macintosh IIci, using HD Setup 2.0.1, which was shipped with System 6.0.5. It’s better, however, to use HD Setup 7.0, included on the System 7.0 CD, with Virtual Memory and File Share disk driver support.
System 6.0.4 is no longer recommended for use on either the Macintosh Portable or the Macintosh IIci.
Devices & Hardware: Disk Initialization Package: Multiple Macintosh disk partitions
I want to divide my 80 MB internal hard disk into two 40 MB Macintosh® partitions to keep Systems 6.0.x and 7.0 on the same disk and to speed up 40 MB tape backups, but “Apple HD SC Setup” doesn’t seem to support multiple Macintosh partitions.
While Apple’s own “HD SC Setup” utility does not allow multiple Macintosh partitions, several third-party products, such as SilverLining from La Cie, allow you to partition your drive with 2 or more Macintosh partitions.
You could also have two system folders on your one partition, one for System 6.x and one for 7.0, and switch between them.
Devices & Hardware: Display & Video Hardware: Adding video device to slotless Macintosh desktop
My video driver for Macintosh 68000 SE-type models installs itself as a driver, but since there’s no Graphics Device Manager in the ROM, it can’t add itself to the desktop by creating a GDevice using NewGDevice and putting itself into the DeviceList. Do I need to add my region to the region whose handle is in GrayRgn and patch the QuickDraw bottlenecks to divert drawing to my VRAM, or is there an easier way?
For the Macintosh Plus, SE, Classic, and Portable, your idea of how to add your video device to the system is right on: Add your region to the region whose handle is in GrayRgn and patch the QuickDraw bottlenecks to divert drawing to your VRAM. You didn’t ask for implementation details, so this is just a confirmation that your approach is good.
Devices & Hardware: Display & Video Hardware: QuickDraw 32-bit video RAM access and boundaries
Is there a way to let QuickDraw access video RAM in 32-bit mode, but on a word boundary ? Usually QuickDraw reads/writes on word boundaries, but sometimes it takes advantage of the 68020/30 and reads not a word boundary.
QuickDraw optimizes whenever it can to make efficient frame buffer accesses, but there isn’t a way for you to control how it makes accesses itself. That is, video hardware MUST be able to handle all flavors of accesses. This is because the user can position a window or other object on the screen that is not on a long/word boundry. However, some applications—HyperCard being a prime example—create their windows on aligned boundries and allow movement only to boundaries, so you’ll see a “snap”-to-grid kind of effect. Your application can do so as well, but that’s as far as you should go.
Devices & Hardware: Display & Video Hardware: Adding video device to slotless Macintosh desktop
My video driver for Macintosh 68000 SE-type models installs itself as a driver, but since there’s no Graphics Device Manager in the ROM, it can’t add itself to the desktop by creating a GDevice using NewGDevice and putting itself into the DeviceList. Do I need to add my region to the region whose handle is in GrayRgn and patch the QuickDraw bottlenecks to divert drawing to my VRam, or is there an easier way?
For the Macintosh Plus, SE, Classic, and Portable, your idea of how to add your video device to the system is right on: Add your region to the region whose handle is in GrayRgn and patch the QuickDraw bottlenecks to divert drawing to your VRam.
Devices & Hardware: Display & Video Hardware: Saving and restoring Apple IIGS SHR screen(s)
What’s the proper method of saving the Apple IIGS Super Hi-Res (SHR) screens? If my application both uses shadowing and is fast-port aware, the restored screen colors are garbaged. Can I simply use HandToPtr with ptr representing the screen addresses, or will this mess up the scan-line control byte (SCB) restoration since these are read-modify-write locations?
The shadowed screen’s SCBs may not be correct, so by saving and restoring them you’re causing random data to be restored into the standard SCBs. Your best bet, if shadowing is on, is to turn shadowing off, restore the bank $01 screen, including its SCBs and color tables, turn shadowing on, and restore the $E1 screen and contents. If you don’t want to double-restore the $E1 screen and $01 screen, you should turn shadowing off, restore the bank $01 color tables/SCBs, turn shadowing on, and restore the $01 screen. But, since these screens are never guaranteed to be the same when you save, you should always restore both screens separately.
QuickDraw never touches the shadowed screen SCBs, so if the fastPort flag is set you can ignore the restoring of the bank $01 SCBs/color tables, since the application promised not to interfere with them. But since this won’t save very much time, you probably shouldn’t worry about it.
Devices & Hardware: Display & Video Hardware: Determining if Graphics Devices Manager calls are supported
Is SysEnvirons’ hasColorQD a good way to determine if I can make Graphic Device calls?
SysEnvirons’ hasColorQD field is a good way to check whether the Graphics Device calls are available. Another good way is to see if Gestalt returns something ≥ gestalt8BitQD. You can tell if you have GWorlds (see the Graphics Devices chapter of Inside Macintosh VI) if Gestalt returns something (> gestaltOriginalQD and < gestalt8BitQD) or ≥ gestalt32BitQD.
Devices & Hardware: Display & Video Hardware: SetEntries and setting CLUT asynchronously
I want to call the device driver Control function on my screen device to set the CLUT asynchronously, so that it won’t wait until vertical retrace time like SetEntries does, causing an average delay of half the screen refresh rate, which is too much for my application. Does the firmware in the Apple video boards support asynchronous operation, or do I need to write a VBL task to handle the setting of the CLUT?
The control call (SetEntries) in the video card is designed to turn off interrupts in the machine until it can sync to the VBL and then change the CLUT. It does this because otherwise the update to the CLUT will look really bad. You can call PBControl to make the SetEntries call (basically what the Color Manager is doing). There is a flag for making the control call Async, but it will not take care of the problem with waiting for the VBL. This limit is due to the way the video cards are designed. There may be some video cards which don’t do this, but you probably don’t want to be hardware dependent. If you are interested in using the PBControl call, then you may want to take a look at the Cards and Drivers manual.
In general, DTS doesn’t recommend using SetEntries to animate the CLUT. It is not a very clean way to change the CLUT, and you don’t really gain anything by using it over the Palette Manager. For more information about the two ways,take a look at the “Palette Manager Animation” article in issue #5 of develop.
Devices & Hardware: Display & Video Hardware: Main versus application screens with multiple displays
On a multiple-display system, most commercial software comes up on the primary screen, even though it may need the color screen next door. Is there a utility for changing the default screen to a different one AFTER startup so I can switch to a color screen for certain applications without having to reboot?
A user can use Monitors to change the main screen (the one with the menu bar). If an application or utility were to change the main screen whenever it wants, then every time you run a new application, the menu bar would be moved on you. This would get reeeeeeally ugly. If commercial applications need (or run better on) one screen over another, they should do the right thing and look for the right screen instead of the main screen. The code to do this is very easy. This is not the job for a utility package.
You need to reboot the machine each time you change the main screen, because the Macintosh does a lot of caching of information and building internal structures early in the boot process, which need to be changed each time the screen information is changed. It might be possible to do this, but it would require a lot of patches to the system, as well as a deep knowledge of the internals of the ROM and OS. You’ll also run into a lot of compatibility problems.
Devices & Hardware: Display & Video Hardware: Where to place video board gamma table & custom option menu code
Can I put both my custom option menu and my custom gamma table in the firmware of my color video board, or must I have an 'INIT'?
The gamma table information can be stored in the ROM of the video card; in fact, in most cases that is where you will want it. The monitor extension, however will need to be in the system folder. You can find a fair amount of information about making a monitor extension, including sample code, in Chapter 10 of Inside Macintosh® Volume VI.
Devices & Hardware: Display & Video Hardware: Maximum Macintosh color monitor cable length
How long a cable can be used between a Macintosh® IIsi and a 13-inch color monitor?
Apple formally supports only the monitor cables and cable lengths available through Apple, but theoretically, using 75-ohm impedance value cable (usually RG-59U standard coaxial video cable), the signal will be very reliable up to 50 feet. The distance is limited by the loss of signal strength through attenuation within the cable:
Specifications: 75 ohm impedance cable
Signal strength: 13.33 milliamps @ 1 volt into 75 ohms load
Signal in MHz: 30.24
The DB loss per foot (or attenuation) using an RG-59U standard cable is approximately .0015. This gives a power loss of 4% of the original 1 volt signal at 100 feet.
The signal will drop to 50% at 2000 feet, with a 3 DB drop in power. Apple recommends staying within 95% percent of the signal, which would be under 150 feet. Increasing the monitor brightness control can correct for some of the signal loss.
(NOTE: Because of the TTL sync signal for the Apple High Resolution Monitors, it is unlikely the monitor will work correctly with sync signals under 4 volts, which would be a cable about 650 feet in length.)
Devices & Hardware: Display & Video Hardware: Apple monitors and gDevice pixel map hRes and vRes fields
It seems to me that the Apple® portrait monitor is an 80 dpi graphics device yet the hRes and vRes fields of the pixel map contained in the gDevice list state that it is a 72 dpi device.
Most monitors claim to be 72 dpi devices for compatibility with the original Macintosh®. Bitmap fonts expect 72 dpi resolution, for example. In reality each type of monitor is a little different, varying somewhere between 68 dpi and 80 dpi. Monochrome displays tend to have a slightly higher resolution than do color displays. These minor variations should be insignificant. The Macintosh goal is WYSIWYG, not necessarily WYMIWYG (What You Measure Is What You Get).
Devices & Hardware: Display & Video Hardware: Macintosh Display Cards 4*8 & 8*24 and third-party monitors
What do I need to determine if my third-party monitor is compatible with an Apple video display card?
The Macintosh® Display Cards 4•8 & 8•24 support any monitor that meets one of the following specifications:
- - - - - - MHz - - - - -
Sense pins Hor x Vert Dot Vert Horiz
10 7 4 Display Pixels Clock Refrsh Refrs
------- --------------------- ---------- ------ ----- ------
0 0 0 21-inch Color Monitor 1152 x 870 100 75 68.7
0 0 1 Apple Portrait Display 640 x 870 57.2832 75 68.9
0 1 1 Apple Two-Page Monitor 1152 x 870 100 75 68.7
1 1 0 12” Apple
Monochrome Monitor 640 x 480 30.24 66.7 35.0
1 1 0 13” AppleColor
RGB Monitor 640 x 480 30.24 66.7 35.0
0 - Grounded 1 - Not Connected
Note that sense pins 4, 7, and 10 are referred to as SENSE0, SENSE1, and SENSE2 in video connector pinout tables, such as the table in “Macintosh Display Cards 4•8 and 8•24 Developer Note.”
Here are the pinouts for the Macintosh Display Cards:
Pin Description
--- -----------
1 Red Video Ground
2 Red Video
3 Composite Sync
4 SENSE0
5 Green Video
6 Green Video Ground
7 SENSE1
8 Not Connected
9 Blue Video
10 SENSE2
11 Composite Sync and Vertical Sync Ground
12 Vertical Sync
13 Blue Video Ground
14 Horizontal Sync Ground
15 Horizontal Sync
Shell Chassis Ground
Devices & Hardware: Display & Video Hardware: 8*24 GC card memory management
How does the 8•24 GC card handle its memory management, such as caching, memory swapping, and out-of-memory handling?
The article, “Macintosh® Display Card 8•24 GC: The Naked Truth,” in issue #3 of develop has a good description of the card’s inner workings. You needn’t need to worry about what’s going on behind your back as far as memory management goes.
Devices & Hardware: Display & Video Hardware: Apple color video cards work on all Macintosh II models
Can I use a color video card from a Macintosh® IIfx to upgrade an old Mac II to color?
Yes, the RGB video cards for the Macintosh II series computers are interchangeable. If you are using Apple’s Hi-Res RGB monitor you have several video card choices (such as the “4•8” or the “8•24”).
Devices & Hardware: Display & Video Hardware: Recognizing a 32-bit address mode video card
How do I get the Macintosh® system to recognize that I have a video card installed that only supports 32-bit addressing?
Two bits need to be set in the sRsrcFlags field: fOpenAtStart (bit 1) and f32BitMode (bit 2). If you do not have these bits set, SecondaryInit will not get called and QuickDraw™ will not realize that your card is a 32-bit address only card. These bits are documented in the second edition of Designing Cards and Drivers for the Macintosh Family on page 123.
Devices & Hardware: Display & Video Hardware: 8•24 GC card pinouts and resolution
Can you provide me with the video pinouts for Apple’s 24-bit QuickDraw™ accelerator card so I can use another display instead of Apple’s RGB? Also, what is the maximum pixel height and width that the card can display?
The Apple 8•24 GC video card supports any large color monitor with the same resolution and timing as the Apple® Two-Page display. Currently, the only one I am aware of is sold by SuperMac. It is only 8 bits though, not 24. Pinouts for the 8•24 GC card are the same as for Apple’s other display cards (4•8 and 8•24).
For further information about this, please refer to the Tech Info Library on AppleLink® for a video card pinout listing and for monitor cable details.
Devices & Hardware: Display & Video Hardware: Eliminating 1-bit per pixel mode
How do I declare 8- and 24-bit modes without having 1 bit-per-pixel (bbp) mode in my sResources?
The trick is that your first video mode (which, in your code, would be 8 bpp) must start with ID 128. The modes have to be sequential so the next mode (24 bpp in your case) would be ID 129.
Besides Designing Cards and Drivers for the Macintosh® Family (2nd edition), there are some MacDraw® drawings of configuration ROMs, one of which shows an old Apple® video card (sometimes referred to as the “TFB” card). It is out of date, especially with regard to 32-Bit QuickDraw™ and multiple mode families, but it will give you an idea about how these things interact. A picture showing the exploded ROM and all these video sResource components may help when reading C&D. You can find these drawings on our developer CD and on AppleLink® under the MacDTS folder of Developer Services (look for the hardware hints/slots folder).
The only other gotcha I can think of is whether or not you can be the startup device if you don’t have 1 bit per pixel. And I think this was due to older MacsBugs not being able to handle more than 1 bpp, which of course is fixed now.
Devices & Hardware: Display & Video Hardware: Macintosh video connector pinouts J26 and J2
What are the pinout and signal descriptions of the tiny little connector marked J26, located on the main logic board near the external video connector. Also, what is the part number and manufacturer of the mating connector?
You seem to be asking about the external connector (J26), but my guess is that you really want to know about the internal connector (J2), so I will tell you about both. J26 is the external connector and is documented in the Developer Notes for the Macintosh® LC on page 13. The pin assignments are as follows:
1 Red video ground
2 Red video
3 Composite horizontal and video synch
4 Monitor ID bit 1
5 Green video
6 green video ground
7 monitor ID bit 2
8 not used
9 blue video
10 monitor ID bit 3
11 CSYNC ground
12 Vertical sync
13 blue video ground
14 not used
15 not user
16 shield ground
This connector is a standard DB-15 external connector.
Connector J2 is the internal connector that is documented in the Developer Notes on pages 37 and 38. The pinouts are as follows.:
1 ground
2 green video
3 ground
4 red video
5 ground
6 blue video
7 ground
8 composite blanking
9 ground
10 overlay signal
11 ground
12 composite horizontal and video sync signal
One source for the mating connector is Amp Incorporated, Harrisburg, PA 17105.
The part number of the connector is 4-174904-2.
Devices & Hardware: Display & Video Hardware: When to put Macintosh configuration ROM at top of 16-MB slot space
Is it OK to put the configuration ROM on my board at the top of the 16-MB slot space?
As long as the card is installed on all Macintosh® systems after the Rev A Macintosh II (the very first Macintosh II systems that were shipped), you will not have a problem with putting your configuration ROM at the top of the 16-MB space; in fact, we recommend this. To determine if the machine is a Rev A Macintosh II, you can use the tester application that is on the developer CD. Just run the application and if the machine is one of the old ones, a dialog box displays that tells the user to upgrade (for free) to a new motherboard.
Devices & Hardware: Display & Video Hardware: Macintosh 8•24 GC card 4-MB SIMM testing and pinouts
Does the current Macintosh® 8•24 GC card work with 4-MB SIMMs? What are the pinouts for the higher density SIMM?
We have made 4-MB SIMMs for the 8•24 GC card, tested them, and they work just fine. The 'cdev' sees them and they work. One way to test your SIMMs is to do a memory test over NuBus on addresses $sD000000 to $sD3FFFFF (Bank A) and $sD400000 to $sD7FFFFF (Bank B).
The pinouts for the DRAM SIMMs are as follows:
D0-2 d16-33 a0-10 CAS0-8
D1-3 d17-34 a1-28 CAS1-26
D2-5 d18-36 a2-6 CAS2-39
D3-4 d19-35 a3-15 CAS3-57
D4-14 d20-45 a4-16 Vcc-18,37,47,56
D5-13 d21-44 a5-50 GND-1,19,25,38,48,55,59,64
D6-11 d22-42 a6-9
d7-12 d23-43 a7-7
d8-20 d24-51 a8-40
d9-21 d25-52 a9-41
d10-23 d26-54 RAS-46
d11-22 d27-53 OE-27
d12-32 d28-63 WE0-58
d13-31 d29-62 WE1-49
d14-29 d30-60 WE2-24
d15-30 d31-61 WE3-17
Devices & Hardware: Display & Video Hardware: Video depth on Macintosh IIsi and LC Systems
Is there any way to get 24-bit color with a Macintosh® IIsi or LC? For the Macintosh LC, is it possible to substitute a 1-MB Video RAM SIMM for the 512K VRAM SIMM, which substitutes for the 256K stock VRAM?
Neither the Macintosh IIsi nor the Macintosh LC is designed to support 24-bit video.
The on-board video hardware and the video driver on the Macintosh IIsi are only designed to support 1, 2, 4, and 8-bit video. Putting more memory in the SIMMs or any hacks you might come up with will not get 24-bit video on the on- board video hardware.
The on-board video hardware on the Macintosh LC is capable of supporting 16- bit video on the 12" monitor, but it is still limited to 8-bit video on the 13" monitor. If you try to put 1-MB of VRAM into the video RAM SIMM, you probably will not be able to boot the machine. At best the machine will only see 512K of the VRAM. So, on the Macintosh LC the video hardware and the video driver only support 1,2,4,8 bits on Apple’s 13" monitor and 1,2,4,8,16 bits on Apple’s 12" monitor.
Devices & Hardware: Display & Video Hardware: All modes must have same starting address for a frame buffer
Does Macintosh® QuickDraw™ require that all modes have the same starting address for a frame buffer? In other words, I can’t have 1-bit mode start at offset 1024 and 8-bit mode start at offset 2048, right?
Yes, QuickDraw requires that all modes have the same starting address for a frame buffer.
Devices & Hardware: Display & Video Hardware: Upgrade old Macintosh II ROMs to use with 8•24 GC card
Why does our Macintosh® II with old ROMs not boot up with the 8•24 GC card, but it works fine on a Macintosh IIfx?
There is a problem with the really old Macintosh II ROMs that prevents them from working correctly with cards that have more than 1 MB of memory. The upgrade program is still available so take your machine to your friendly dealer and ask for a new board.
Devices & Hardware: Display & Video Hardware: Macintosh II video connector pinouts
What are the pinouts for the Macintosh® II video card and IIci built-in video connector?
Here are the pinouts for the Apple 13" RGB and 12" Monochrome monitors for
Macintosh II video cards and IIci built-in video:
12" B/W
Pin Signal Description 13" RBG 15" B & W
-- ----- ---------- ------ ---------
1 RED.GND Red Video Ground RED.GND n/c
2 RED.VID Red Video RED.VID n/c
3 CSYNC~ Composite Sync CSYNC~ n/c
4 MON.ID1 Monitor ID, Bit 1 ID1.GND n/c
5 GRN.VID Green Video GRN.VID n/c
6 GRN.GND Green Video Ground GND.GND n/c
7 MON.ID2 Monitor ID, Bit 2 n/c ID2.GND
8 n/c n/c n/c
9 BLU.VID Blue Video BLU.VID BLU.VID
10 MON.DI3 Monitor ID, Bit 3 n/c ID3.GND
11 C&VSYNC.GND CSYNC & VSYNC Ground CSYNC.GND VSYNC.GND
12 VSYNC~ Vertical Sync n/c VSYNC~
13 BLU.GND Blue Video Ground BLU.GND BLU.GND
14 HSYNC.GND HSYNC Ground n/c HSYNC.GND
15 HSYNC~ Horizontal Sync n/c HSYNC~
shell CHASSIS.GND Chassis Ground CHASSIS.GND CHASSIS.GND
Macintosh IIci video MON.ID information
‘0’ means that the line is grounded inside the monitor to provide information to the Macintosh IIci as to what kind of monitor is connected. If no monitor is connected to the IIci’s built-in video port, then the port is automatically disabled at startup.
ID3 ID2 ID1 Monitor Type
--------------------------------------------------------
0 0 0 Unsupported
0 0 1 15" B&W Portrait Monitor (640x870)
0 1 0 RESERVED for use be Apple
0 1 1 Unsupported
1 0 0 Unsupported
1 0 1 RESERVED for use by Apple
1 1 0 Mac II 12" B&W, 13" Hi-Res RGB (640x480)
1 1 1 No external monitor connected (automatic)
--------------------------------------------------------
Devices & Hardware: Electrical Issues: Power Manager BatteryStatus returns voltage & charger details
How can we check if a Macintosh Portable is charging?
The Power Manager chapter of Inside Macintosh Volume VI (pages 31-23 and 31- 24) describes the BatteryStatus call, which provides you with the following information:
• Whether the charger is connected (status bit 0)
• Whether the charger is in High or Normal charge
• If the battery voltage is below the warning threshold
• A power value from which you can calculate the battery’s current voltage
To calculate a battery’s current voltage, you’ll need to average the voltage over an extended time period (tens of seconds to several minutes for good accuracy). The power load within the Portable is a dynamic environment, so the current draw of the various subsystems on the battery will affect the voltage that you read.
Devices & Hardware: Electrical Issues: IEC 801-2 ESD testing standard
Where can I get specs for environmental and electrostatic discharge (ESD) testing?
Apple doesn’t disclose its testing specs; however, there is an international ESD testing standard specification called the IEC 801-2 Athough not every company adheres to it, as ESD testing becomes written into law, it is almost a sure thing to say that this specification will be the standard on which that law is written up. As it stands now, the manufacturers of the testing equipment are already setting their machines to test at the levels set forth in the specification.
For more information regarding this issue, contact your source for ESD testing equipment. Since that portion of the industry has already taken notice of and implemented the specification, they’d be the best source for the kind of information you’re looking for.
Devices & Hardware: Electrical Issues: Apple Serial NuBus Card metal plate supplier
What vendor supplies the metal plate on the Apple Serial NB Card that holds the D-62 connector and covers the hole in the RF shielding?
North American Tool and Die (NATD) makes Apple’s metal plates (shields). Their address is as follows:
North American Tool and Die
999 Beecher Street
San Leandro, CA 94577
(415) 352-5500
Before ordering the shield (part #805-5101), you must first obtain authorization through MacDTS.
Devices & Hardware: Electrical Issues: Auto-restarting a Macintosh II after a power failure
What does it take to make a Macintosh II auto-restart after a power failure?
To get the Macintosh II to auto-restart after a power failure, the “reserved” Apple Desktop Bus (ADB) pin #2 (PWRON) must be grounded for a couple of seconds when the power comes up.
Devices & Hardware: Electrical Issues: Macintosh IIsi external floppy drive port power specs
How much current is available at +5V and +12V at the Macintosh® IIsi external floppy drive port? Assume an internal hard drive is in use.
According to Inside Macintosh Volume III, page 33, this connector was designed for a Macintosh 3 1/2-inch disk drive, which represents a load of 500 milliamps at +12 volts, 500 milliamps at +5 volts, and 0 milliamps at –12 volts. If any other device uses this connector, it must not exceed these loads by more than 100 milliamps at +12 volts, 200 milliamps at +5 volts, and 10 milliamps at –12 volts, including loads from all other connectors combined.
Devices & Hardware: Electrical Issues: Macintosh Classic, LC, & IIsi internal hard disk power specs
What is the maximum current available on the +5V and +12V hard disk power lines on the Macintosh IIsi, LC, and Classic?
Here are Apple's internal hard disk drive power specifications for the Macintosh Classic, Macintosh LC and Macintosh IIsi computers:
+5V +12V Total Power
----- ------ -----------
Startup 700mA 1000mA (see explanation below)
Accessing 700mA 300mA ≤ 5.5 Watts (see explanation below)
Operating (Idle) 500mA 300mA ≤ 5.5 Watts (see explanation below)
• The initial power consumption during startup must be less than 10 Watts RMS as measured during the first 2 seconds. After 2 seconds, the accessing/operating requirements govern.
• These specifications include terminator power which must be supplied by the drive.
• These are the absolute maximum allowable numbers (not the mean of a distribution of drives). Any drive that operates above any one of these numbers may not work.
• There is a discrepancy in maximum total operating power in Watts (5.5W) and standard power calculations (500mA * 5V) + (300mA * 12V) = 6.1W). This means that drives cannot draw the maximum current from both the +5V and +12V supplies.
• On the Macintosh Classic, there must be a delay of at least 700 msec before hard disk spin-up to prevent the +12V startup peak from happening at the same time as the Macintosh Classic's floppy drive’s startup head recalibration.
Devices & Hardware: Electrical Issues: Where to find information on Coaxial card Twinax connector
Is there any documentation on how to gain access to the Twinax connector on the Macintosh® Coaxial card?
Andrew/KMW Systems has developed a device interface for the Twinax connector on the Macintosh Coaxial card for their product. For more information, you can contact them at the following address:
Andrew/KWM Systems
6034 West Courtyard Drive
Suite 100
Austin, TX
78730-5014
AppleLink: D0500
For additional documentation, you might want to contact National Semiconductor for a copy of their technical documentation on the Biphase Communications Processor - DP8344A. Also, some Twinax technical documentation might be available from IBM.
Devices & Hardware: Electrical Issues: Macintosh power supply limits
Table 6-24 on page 263 of the 2nd edition of the Macintosh® Family Hardware Guide gives a limit of 18 amps @ 5 volts on the Macintosh® power supply. Can we exceed the recommended 6 x 2 = 12 amp limit at +5V on our cards?
It would not be a very good idea to exceed this limit, unless you don’t plan to have the card work in machines with internal hard drives or single-slot Macintosh systems such as the Macintosh IIsi. The remainder of the 18 amps not used by NuBus™ are used by the motherboard and the hard drive. If you do go with machines that do not have internal hard drives, then you will be able to use a little more power, but you will still need to leave some power for the video card. This leaves you back at about a 12-amp limit. If you put your own power converter on your card, you could convert the 12-volt power to 5 volts, but this is not going to gain a lot. In general, third parties who use more power than they should have ended up adding an external power source to their cards. In some cases there have been cards that required replacing the entire Macintosh power supply. Adding power will also require a bigger fan—that is, these limits aren’t just electrical; they represent maximum thermal values as well. This is particularly important in the Macintosh IIsi.
Devices & Hardware: Electrical Issues: Macintosh Classic and Macintosh LC power information
We need a cable to use our external card with the Macintosh® Classic® and Macintosh LC. The only available powered port seems to be the Apple Desktop Bus™ (ADB). How much power does the ADB on the Classic and LC supply?
You can approach your problem a couple of ways. We suggest that developers do not steal power from any of the CPU’s ports but if you insist on doing otherwise, then consider the following:
Maximum ADB power available is low—only about 125 ma per device at +5. You would have to provide an in-and-out connector since our newest CPUs have only one ADB port on them. We suggest that only three devices be used on each ADB port, and your device would count as one of those devices. See Chapter 8, page 295, of the Guide To Macintosh Family Hardware, Second Edition.
Power is available on the floppy drive port (+12, +5) and the maximum current available is higher than ADB. Allowing for a floppy drive plugged into your adapter, you would still have 200 ma @ +5 with a 400K drive connected and 340 ma @ +5 with an 800K drive connected. You must also provide a way for a floppy to be plugged into your adapter using a DB19 connector back to back on the Classic and you would have to run a cable out the back from the second floppy port on the inside of the LC. See Chapter 9, page 335, of the Guide To Macintosh Family Hardware, Second Edition, for more information.
If you still decide to use the ADB, remember that your device must support the following: ADB pass through and only about 100-125 ma @+5 current draw. Also, remember to add documentation to your product user’s manual that your device counts as one of the three allowed devices per ADB connector.
Devices & Hardware: Electrical Issues: Where to get connectors for making Apple-compatible cables
Where can I get connectors for making Apple®-compatible cables?
Here are some suppliers of the mini-DIN connectors. This list is provided for information only—Apple does not endorse any of the vendors.
Hosiden America/Harmonix Sales
Mike Ferrera
10090 Pasadena Avenue, Suite A-2
Cupertino, CA 95014
408-725-2424
CompuCable
Bob Mickey
180 Vallecitos De Oro
San Marcos, CA 92069
619-744-2789
800-222-2332 (outside CA)
TRW
Illinois
Gene Kazmarek aka Kaz
408-720-8727
HB Associates
Hank Lorta
415-487-3933
Union City, CA
Harbor Electronics
Ron Marsilio
650 Danbury Road
Ridgefield, CT 06877
203-438-9625
Also try AMP; they may supply the 8-pin variety.
Devices & Hardware: Input Devices: Apple Extended Keyboard values recognized by Apple IIGS
How can I use the "extra" keys on the Apple Extended Keyboard on my Apple IIGS®? What values do they return?
The following chart shows what the "extra" keys and other extended keys of the Apple Extended Keyboard return on the Apple IIGS. All of the keys turn on bit 4 of the Modifier Key register at $C025 (see page 124 of the Apple IIGS Hardware Reference) to distinguish these keys from the "regular" keys.
Key ASCII char Key ASCII char Key ASCII char
--- ---------- --- ---------- --- ----------
F1 z F8 d F15 q
F2 x F9 e help r
F3 c F10 m home s
F4 v F11 g page up t
F5 ` ($E0) F12 o page down u
F6 a F13 i end w
F7 b F14 k del |X> y
Devices & Hardware: Input Devices: Macintosh and multiple keyboard input
Is it possible to connect more than one keyboard into an ADB chain on a Macintosh II family computer?
Connecting multiple keyboards in parallel should work; however, a bug in many existing keyboards prevents them from distinguishing themselves at boot time. The result is that an application has no way of telling which keyboard has sent input. Parallel input from multiple keyboards doesn’t present a problem, but differentiating input from multiple keyboards often won’t work. This situation has improved with the Extended Keyboard II.
If you need to differentiate multiple keyboard input, use the Extended Keyboard II exclusively or mix your keyboards. Alternatively, the Macintosh can always distinguish a standard ADB keyboard from nonalike keyboards such as the Apple IIGS keyboard.
You can’t go wrong by trying, so hook them up and see if your needs are adequately served. If you don’t notice any problems, then great!
Devices & Hardware: Input Devices: Apple IIGS keyboard buffering: disabling and enabling
We need to turn off Apple IIGS keyboard buffering temporarily. Setting BParam $2B (keyboard buffering) and calling ToBRAMSetup ($E1/0094) works, but it’s invasive; a user’s Reset, for example, leaves the Control Panel in a “tampered with” state. Is there a way to do it without involving the Control Panel, like setting speed with the $C036 softswitch?
Keyboard buffering on the Apple IIGS occurs in the ADB microcontroller chip. While there’s no softswitch to control it, there is a way to disable keyboard buffering without modifying any battery RAM or permanent user setup stuff. To disable and re-enable keyboard buffering, use the Clear Modes and Set Modes ADB microcontroller commands, documented on page 189 of the Apple IIGS Firmware Reference. To “contact” the keyboard micro and communicate with it, you’ll need to use the Apple Desktop Bus Tool Set function SendInfo (Apple IIGS Toolbox Reference Volume 1, page 3-19). The background information in both these chapters, together with the code snippet below, will help you get up and running without keyboard buffering. Keep in mind that buffering does not affect the event queue, so when the VBL occurs and you are running an event driven application, the keyboard will still be polled and any keys put in the event queue.
mcopy 2/aInclude/m16.adb
copy 2/aInclude/e16.adb
longa on
longi on
KeyBufferOn Start ;called with jsl in full 16-bit mode
lda #$0001 ;dataLength = 1
pha
lda #^data ;dataPtr = pointer to data
pha
lda #data
pha
lda #setModes ;adbCommand = Set Modes
pha ;this will set the buffer keyboard mode
_SendInfo ;make ADB SendInfo call
rtl ;and return to caller
KeyBufferOff Entry ;called with jsl in full 16-bit mode
lda #$0001 ;dataLength = 1
pha
lda #^data ;dataPtr = pointer to data
pha
lda #data
pha
lda #clearModes ;adbCommand = Clear Modes
pha ;this will set the buffer keyboard mode
_SendInfo ;make ADB SendInfo call
rtl ;and return to caller
data dc b'00010000' ;bit 4 = Buffer keyboard mode.
End
Devices & Hardware: Input Devices: Using GetKeys to check Macintosh key status
Is there a way to test whether a particular key is down independently of the event record? My application needs to check the option key status before entering the main event loop.
The call GetKeys(VAR k:KeyMap) returns a keyMap of the current state of all the keys on the keyboard. The call is documented in Inside Macintosh Volume I on page 259, with the definition of keyMap on page 260. The option key will appear as the 58th bit (counting from zero) in the map. In MacsBug you can see this with a DM KeyMap which returns:
0000 0000 0000 0004 0000 0000 0000 0000
It is important to understand that the keyMap is an array of packed bits. You need to test if the option key BIT is 1 or 0. The key code 58 = $3A is the 58th bit of the keyMap. This number can be determined from the keyboard figure on page 251 of Inside Macintosh. (If in counting the above bits you get 61 instead of 58, remember that the bits within each byte counts right to left.)
With the above information you should be able to determine the status of any key on the keyboard within your program without waiting for an event.
Devices & Hardware: Input Devices: Mapping “Standard” Apple IIGS Option-key input to char table
How can we determine which physical Apple IIGS® key is pressed, when a user types Option-Keystroke? For example, if the user types Option-A, we want to determine the “A” key was pressed. When the keyboard translation is set to “None” this is not a problem, but when it is set to “Standard” the keystroke is translated to a high ASCII character that’s not simply “Key+$80.”
There is no way to get the physical keystroke when keyboard translation is turned on. There is an imperfect, gnarly way that might work though, explained below. However, it’s better to simply equate the standard dead keys with the characters they belong with inside your application, so that whether you receive an option-A or an option-å you perform the macro associated with A. This is probably the simplest but not the most foolproof method.
If you are willing to write a lot code, there is a way to reverse engineer thekeystroke that you receive in most cases. To de-translate a standard keystroke, you will first have to obtain the current keytrans table. Then take the keystroke returned to you and search for its ASCII value in the proper 128 bytes of the translation table. If the Option key is not down in the modifiers message, search the first 128 bytes of the table. If the option key is down, search the second 128 bytes. The offset into either of these two tables tells you the probable ASCII code for the real keystroke—”probable” because there is no rule that says two different physical keystrokes cannot return the same translated ASCII value. Fortunately you won’t have to worry about this with the standard translation much, assuming that you stick to Option-letter keystrokes. Dead key sequences will be much tougher, but since they require multi-key input, your users will probably not have a problem with them.
See the Event Manager chapter of Apple IIGS Toolbox Reference, Volume 3, for a complete description of how the data structure looks and how to determine the resource number of the keytrans table.
Devices & Hardware: Input Devices: Macintosh interfaces for Apple Scanner
Is there a set of Macintosh® C interfaces for the Apple Scanner driver?
The Apple Scanner Reference (APDA #M7078) comes with a disk that has interface files for assembly language, Pascal, and C. The C headers are in a file called ScIntf.j. Just #include this file and Link with the file called ScIntf.a.o (on that same disk), and you should be able to control the scanner from C.
Devices & Hardware: Input Devices: Macintosh LC and IIsi sound input hardware documentation
Where can we get documentation on the Macintosh® LC and IIsi sound input hardware?
You can find sound input information in the Macintosh LC and IIsi Developer Notes, which you should have received by now as part of Apple’s developer mailing. Developer Notes are available from APDA® if you don’t already have them. Additionally, may I suggest that you refer to the Sound Manager chapter of Inside Macintosh Volume VI.
Devices & Hardware: Input Devices: How the Macintosh mouse/cursor mechanism works
I’m writing a tablet (mouse, pointer, etc.) driver, and I need to be able to position the cursor and post mouseUp mouseDown events. How do I do it?
Here is an explanation of the Macintosh® mouse/cursor mechanism, which should provide the information necessary for you to place the cursor:
The mouse is a “relative” device, which means it does not return actual coordinates; it returns a “count” or amount of movement since the last report.
When the mouse has new information, it interrupts the Macintosh. The interrupt handler adds the horizontal and vertical counts to MTemp (a low-memory location), and sets crsrNew to tell the system that the coordinates are new. Some time later (but before normal VBLs are executed) the cursor VBL task is executed, and it compares MTemp with RawMouse (which has the last value), and figures out the delta (that is, the horizontal and vertical distance moved), and does the scaling trick depending on what the user has selected in the control panel. It also updates MTemp to reflect the new value. Then it draws the cursor.
Here are the names and locations of the relevant low-memory locations:
RawMouse equ $82C ;point
MTemp equ $828 ;point
CrsrNew equ $8CE ;byte
CrsrCouple equ $8CF ;byte
(NOTE: These may change in future CPUs.)
If you wish to place the cursor in an absolute location on the screen, you must set RawMouse, and MTemp to the same value, and set CrsrNew to the same value as CrsrCouple.
Keep in mind that moving the cursor from an application may violate the Human Interface Guidelines, possibly confusing and frustrating the user. Also keep in mind that the low-memory locations named above are not documented, and as such, are considered unsupported and volatile.
Posting mouse down/up events is a simple matter of keeping track of the last state of your device button, and when you detect a change, you post the appropriate event. If you wish to support the ToolBox Event Manager call Button, you must also update the low-memory global MBState. The high bit of MBState reflects the current state of the mouse button: 1 = button up, 0 = button down.
Unfortunately, the system mouse driver will change this value if it notices that the state of MBState is different from the state of the real mouse button. This means if there is a mouse connected to the Macintosh while your device is connected, it will override whatever you put in MBState. On systems equipped with ADB, this will happen only when the mouse moves, or the button is pressed. On earlier systems this happens all the time, since the button checking routine was a VBL task, and is always executed. One possible workaround is to patch Button, and return the state of your button, rather than MBState. The obvious problem is that you disable the real mouse from working with Button.
Devices & Hardware: Interrupt Handling: Use Time Manager instead of VIA2 timer T1
The Apple Macintosh Family Hardware Reference, first edition, (page 17-28) says VIA2 timer T1 can generate interrupts up to every 1.2766 microsecond. Is there any documentation for programming the timer to generate the interrupt at high speeds and installing the interrupt service routine? By the way, the Time Manager documented in Inside Macintosh Volume IV (page IV- 299) is capable of generating interrupts at the accuracy of only one millisecond.
Apple discourages direct use of the VIA2 because it’s not present on all Macintosh CPUs. It’s absent on the popular Macintosh IIci and IIfx models, for example.
Contrary to the outdated Inside Macintosh Volume IV Time Manager documentation, the Time Manager in System 6.0.3 and later has accuracy on the order of 1 microsecond. See Inside Macintosh Volume VI for details on new Time Manager features.
Devices & Hardware: Interrupt Handling: Macintosh Read calls at interrupt time
Read calls at interrupt time often result in a “hang,” waiting for the paramblock to show “done.” This occurs if the interrupt occurred during another Read call. I have tried checking the LowMem global FSBusy, and that decreases the occurance of this problem, but does not eliminate it. When it is safe to make the Read call?
The problem you are experiencing is a common one known as DEADLOCK. The good news is that you can ALWAYS make Read calls at interrupt time! The only requirement is that you must make them ASYNCHRONOUSLY and provide a completion routine, rather than loop, waiting for the ioResult field to indicate the call has completed. This will require that you use the lower-level PBRead call, rather than the high-level FSRead.
The low-memory global FSBusy is NOT a reliable indicator of the state of the File Manager. The File Manager’s implementation has changed over time, and new entities patch it, and use the hooks it offers to do strange and wonderful things. FileShare really turns it on its ear. The result is that when FSBusy is set, you can be sure the File Manager is busy, but when it is clear you can’t be sure it is free. Therefore, it would be best if you ignore its existence.
If you need to have the Read calls execute in a particular order, then you will have to chain them through their completion routine. The basic concept is that the completion routine for the first Read, initiates the next Read, and so on until you’re done Reading.
By the way, never make Synchronous calls at interrupt time (and contrary to the popular misconception, Deferred Tasks are still considered to be run at interrupt time) or from ioCompletion routines, which may get called at interrupt time.
Devices & Hardware: Interrupt Handling: Macintosh interrupt routines and I/O
Are there any dangers in doing a synchronous read at interrupt time? In particular, if an asynchronous write is executing and is interrupted by a synchronous read, can the re-entrancy into the Macintosh ROM read/write code cause problems?
The Macintosh ROMs are not re-entrant. For this and for timing considerations, you should do as little as possible within an interrupt routine. In any case, you should not be doing I/O of any kind from within your interrupt routines. You should simply use the interrupt to do the minimum possible to respond to the signaled condition and set indicators to your larger application to handle the larger context, like initiating additional I/O.
Devices & Hardware: Interrupt Handling: Macintosh disk drivers and slot interrupts
Macintosh disk drivers and slot interrupts
In the present-day implementation, Macintosh slot interrupts are always disabled for floppy disk access. The floppy driver disables the interrupts using code like this:
OR.W #HiIntMask, SR
where
HiIntMask EQU $0300
For hard drives, interrupts are enabled with SCSI transfers. They are disabled for very short periods of time during SCSI reset and when things are being put into and removed from queues.
Note that some day Apple might implement SCSI chip interrupts, which might defer slot interrupts if a card wanted to interrupt while a SCSI interrupt wasbeing serviced. To ensure future compatibility, please design variances in interrupt latency into your product.
Devices & Hardware: Interrupt Handling: VBL tasks under System 7 with virtual memory running
I use a VBL task to animate the cursor when my disk driver installer performs tasks such as media verification and low-level formatting. When a command such as Format Unit is sent to the drive, the Macintosh® does not gain control until the drive completes the command, which ranges from a few minutes to close to an hour. Under System 7.0 with virtual memory (VM) running, the cursor is never even set, much less animated. I’ve tried HoldMemory, and I’ve tried allocating a system heap pointer and installing the VBL task there. Any help would be appreciated.
The reason your cursor is not animating when VM is running is fairly straightforward to explain.
VBL tasks are deferred until a time when paging is safe if the VBL interrupt occurs at a time when paging is not safe. Paging is not safe when the VM backing store drive’s driver is busy, when a page fault is already being serviced, or when the SCSI bus is busy.
When you issue your Format Unit command, you call SCSIGet(), which makes the SCSI bus busy. It probably takes several minutes before this command completes and you are able to call SCSIComplete, which makes the SCSI bus free. All during this SCSI bus tenure, VM paging is unsafe and no VBL tasks may execute. Holding memory will not help this situation.
It would be nice if the Macintosh® SCSI Manager supported SCSI Disconnect/Reconnect, but this is not an option either.
The beach ball in Apple HD SC Setup does continue to rotate during Apple HD SC Setup disk formatting, even under VM. Apple HD SC Setup uses the standard RotateCursor call in the MPW® CursorCtl.h interfaces rather than a VBL, and apparently never loses control to the SCSI Manager. What Apple HD SC Setup does after SCSICmd returns is loop on SCSIStat until the SCSI bus enters status phase and then call SCSIComplete. This allows the cursor to rotate and a watchdog counter to time out the Format in case the drive dies. You’re probably going to need to do something similar. VBLs aren’t going to do you much good during a long format.
Devices & Hardware: Interrupt Handling: VBL tasks shouldn’t call Macintosh Memory Manager
What’s wrong with having VBL (vertical blanking) tasks make calls to the Macintosh® Memory Manager, either directly or indirectly?
The problem is that the Memory Manager could be moving memory around when an interrupt occurs. If the VBL task also moves memory, the heap could be destroyed.
VBL tasks are intended to provide a method of time-syncing to the video beam of the display. (On slotted Macintosh models you’d use SlotVInstall.) They’re also used to get periodic time for short tasks, although the Time Manager is better for this. VBL tasks should minimize execution time. The best use of a VBL task is to do a short condition check and set a flag for the main process to indicate that it’s now a good time to do something.
Devices & Hardware: Interrupt Handling: Eliminating Macintosh VBL animated cursor ghosts
What do I have to do to prevent an animated cursor from leaving ghosts on the Macintosh® screen?
Make sure the low-memory global CrsrBusy is FALSE before you try to change the cursor. MacApp® does this.
Devices & Hardware: Interrupt Handling: OK to set Apple IIGS TaskCnt to zero to prevent task execution
Is it possible to store a zero into the TaskCnt field to keep the Apple IIGS® system from ever executing a heartbeat task in the Heartbeat Task Queue? We are using the heartbeat task as a time-out, during which the routine may complete and the same task will need to be reinitialized immediately for the next routine’s time-out.
Yes, if you know where the count word is. You can then set it to zero to prevent it from being called. The system does not keep this information in a separate buffer; it checks the value in the queue header each pass through the heartbeat queue. So if you are at 200 one pass, and then 0 the next, the system is not bothered by that; it does not remember the previous value. And because the task is not executed unless the system itself decrements the count to zero, this is a fine way to prevent a task from executing.
Devices & Hardware: Interrupt Handling: Macintosh VBL documentation
Comments in the Technical Note #180 examples mention that A0 points to the VBL record when a VBL task is called, but we can’t find this documented in Inside Macintosh®. Is this really true? Is it going to change in 7.0?
Although we would like our documentation to be perfect, I must admit that sometimes it isn’t. We are always striving to improve the documentation. One method of making corrections to published volumes already in the hands of developers is to issue technical notes. So, although we will strive to have Inside Macintosh document that A0 points to the VBL record entry on when called, until it is published in a new volume we provided Technical Note #180 as additional update documentation. You can depend on A0’s contents as it is documented in Technical Note #180. It will not be changing in System 7.0.
Devices & Hardware: Interrupt Handling: Reset and NMI on a Macintosh IIsi or LC
The Macintosh® IIsi and LC computers don't come with programmer’s switches. How do I get reset and NMI on these machines?
Both machines have an ADB (Apple DeskTop Bus™) I/O processor which incorporate the reset and NMI functions through the keyboard. The functions are accessed as follows:
Reset on these Macintoshes is always available by simultaneously pressing the command (cloverleaf), control, and power-on keys.
To enable the NMI on the Macintosh IIsi or LC, you need MacsBug 6.2 or later. It's needed because the IIsi and LC start up with NMI disabled (if they didn't, nontechnical users might get into trouble with it), and the ADB controller must be programmed to enable it.
Once MacsBug is installed, NMI is activated by simultaneously pressing the command (cloverleaf) and power-on keys (like the Programmer's Key).
Under some circumstances you may have to hold the reset and NMI key combinations down for a little while (but no more than a second) to make sure the ADB processor sees them.
MacsBug 6.2 final is available in several places. You can buy the software and the manual from APDA® for $35.00 (if you don't have the MacsBug reference manual, we recommend it). The software can be downloaded from AppleLink. The path is:
Developer Support
Developer Services
Developer Technical Support
Macintosh Tools
MacsBug
In addition, various Beta versions of MacsBug are on the System 7 beta CD, the latest developer CD and the E.T.O. CD.
Devices & Hardware: Interrupt Handling: Macintosh interrupt handling saves and restores startup MMU mode
How does the Macintosh® system handle swapping MMU mode from 32 bit to 24 bit?
The system interrupt handler takes responsibility for the MMU mode. The first thing a low-level interrupt vector does is push the system’s startup MMU mode on the stack. It then sets the Macintosh to the 24-bit MMU mode. After the mouse vector is executed, the interrupt walks through the VBL queue, processing any tasks that are pending. Before the interrupt leaves interrupt land, by executing an RTE, it restores the MMU mode that was saved on the stack upon entry.
Devices & Hardware: Interrupt Handling: How to make sure inactive application VBL tasks always get time
Why is my Macintosh® VBL task (installed via SlotVBInstall in VBL queue) getting dumped after a few successful operations if I use a GetNextEvent or EventAvail call within the routine, but runs OK if I don’t?
One of the lesser-known mysteries of running in the world of MultiFinder® is that on either major or minor context switches (which both GetNextEvent and EventAvail allow), VBL tasks installed in the application heap will be unhooked until that application is the current application again.
If you wish for your VBL task to always get time install the VBLRecord in the system heap. One way to do this would be to use NewPtrSys(sizeof(VBLRecord)) and then to cast the resulting pointer as needed.
Devices & Hardware: Interrupt Handling: Macintosh LC SIntInstall & SLOTIRQ Interrupt Handling
How can we get our Macintosh® driver to talk with hardware using the SLOTIRQ provided on the bus?
To get SLOTIRQ to work correctly you need to use SIntInstall to add a slot interrupt queue element for slot $E. The interrupt service routine pointed to by the slot interrupt queue element must clear the interrupt line before returning. The slot interrupt enable bit in the V8 chip referred to by the Macintosh LC developer note (page 26 in the /SLOTIRQ signal description) is enabled during the boot process, so you don’t need to worry about it.
SIntInstall is described in Inside Macintosh Volume V on pages V-426 through V-428 and in Designing Cards and Drivers for the Macintosh Family on pages 161 through 163. Designing Cards and Drivers for the Macintosh Family also includes an example of a driver on pages 178 through 202.
Devices & Hardware: Interrupt Handling: System 6 “Faceless Background Driver” bug and workaround
We want to improve performance by getting frequent and consistent run times, but our Macintosh® driver seems to get run time only about every 0.5 sec under MultiFinder®, even when set to be awakened every tic. This current behavior degrades our performance noticeably when Finder™ is the active application and no other applications are running. Is there a way around this problem?
I successfully reproduced the result you reported. With only the Finder running, my driver got called on once every $1E (30) ticks.
It seems that the reason for this is considered a MultiFinder bug (called the “Faceless Background Driver” bug). What happens is that MultiFinder doesn’t call SystemTask when all applications are asleep. When Finder is the the only application, for example, it gets awakened once every 30 ticks. Otherwise, it’s asleep. When it’s asleep, MultiFinder just spins its gears, and fails to call SystemTask. If you run another application that has a much smaller sleep time (like AppleLink®), you’ll find that your driver gets called more frequently.
I talked with one of the other support guys here who was once in a situation almost identical to yours when he did a tape backup driver for a third party. What he did was write a VBL that would make a special Control call to the driver. The code that responded to the Control call would do whatever processing he wanted to do, taking care not to move or allocate any memory. Then, the next time he got an accRun message, he’d take care of any memory munging that he couldn’t do at VBL time. He says that it wasn’t hard to do, and that it all worked out very well.
Otherwise, I don’t know if there is much you can do. I understand that System 7.0 is supposed to fix the problem, but I haven’t double-checked that yet. It also doesn’t help all your System 6.0.x customers, so you might want to investigate the VBL solution.
Devices & Hardware: Interrupt Handling: International VBL timing on the Macintosh
Do VBL tasks execute at 50 Hz in Europe?
Televisions use AC line frequency to determine the vertical retrace interval. The Macintosh® does not. All Macintosh systems have their own internal 60.15 Hz clock for timing VBL tasks, regardless of whether that clock is actually connected to video circuitry. Tasks installed by _VInstall are always timed by this 60.15 Hz clock. Slotted Macintosh systems may have additional frequencies determined by the installed video card. Tasks installed by _SlotVInstall are timed by these card-specific clocks. In any case, VBL task frequency is not determined by the location of your power source.
Devices & Hardware: Interrupt Handling: What can I do and not do from a Macintosh interrupt routine?
What can I do and not do from a Macintosh® interrupt routine?
The most popular examples of interrupt code are I/O completion routines, VBLs, Time Manager tasks, and deferred tasks. Contrary to popular belief, the Deferred Task Manager will run your task at interrupt level. All code that runs at interrupt level must follow very strict rules. The most significant rule is that the code cannot allocate, move, or purge memory, nor can it call a Toolbox routine that would. This eliminates nearly, if not all, QuickDraw™ operations. For a more complete list of these toolbox routines, refer to the Inside Macintosh X-Ref.
Additionally, interrupt code must avoid accessing a low-memory global or calling a trap that would access one. While MultiFinder® is running, application’s low-memory globals are being swapped in and out. Because of this, the interrupt code cannot rely on which application’s globals are currently available. Even if CurApName is correct, the interrupt routine may be called while MultiFinder is in the process of swapping the application’s globals. This restriction is difficult to deal with because it isn’t documented as to which low-memory globals are swapped by MultiFinder, nor which globals are accessed by traps.
A typical example of this problem is interrupt routines that attempt to restore A5 by examining CurrentA5. This low-memory global is only valid while the current application is running at non-interrupt time. Thus, the MPW® routine SetCurrentA5 (or the obsolete SetupA5) cannot be used at interrupt level. It is necessary to place the application’s A5 somewhere it can find while in interrupt routine. This is documented in DTS’s Macintosh Technical Notes #180 and #208. In fact, the exact code you need is in #180.
It is best to avoid interrupt code if at all possible. Also, there are limitations while System 7.0 is running under virtual memory. Move the functionality of the interrupt code into the application. For example, if you do require a VBL, limit the code to an absolute minimum. Set a global flag for the application to check in its event loop.
Devices & Hardware: Interrupt Handling: How to set the Macintosh cursor at interrupt time
How do I set the Macintosh® cursor at interrupt time, such as a VBL task?
Changing the cursor at interrupt time is permissible as long as the cursor handle is locked in memory and the cursor routines are not busy. A test needs to be performed before changing the cursor. If you want to call SetCursor (with a cursor handle locked in memory), you must check CrsrBusy, a low-memory global defined in MPW® SysEqu. If CrsrBusy is true, then you cannot call SetCursor. Changing the cursor while CrsrBusy is true causes it to leave mouse bits, or trails, on the screen.
CrsrBusy EQU $8CD ; Cursor locked out? [byte]
Devices & Hardware: Interrupt Handling: Consistent application scrolling speed for all Macintosh systems
How can I keep the speed of my application’s scrolling consistent on all Macintosh® systems, including faster ones such as the Mac® II?
One method is to use TickCount. If a certain number of ticks has passed since the last increment of the scroll bar, then go on. If not, then loop until the desired number of ticks has passed before scrolling. It’s easy to include this test, but you’ll have to play with itawhile to find the right number of ticks for the desired delay. Also, consider that some Macintosh systems are faster than a Mac II, such as the SE/30 and Macintosh systems with third-party accelerator boards. It might be nice to let users set their preference for the scrolling speed.
Devices & Hardware: IOPs: Information on the IOP Manager not available
After reading the preliminary release notes for the Macintosh® IIfx, I found myself craving more information on the IOP interface and the IOP Manager. Where can I get more information about this new manager?
Apple will not be releasing IOP Manager information to developers because we plan on expanding the use of the IOPs in the future.
As the release notes stated, the IOP Manager can handle up to eight IOPs, but only two are currently used. The other six cannot be used by developers, because they are reserved by Apple for this future expansion.
Devices & Hardware: NuBus: Macintosh NuBus card development tools
Does a card exist with built-in circuits interfacing to NuBus that I can use to design my own custom part for my own interface card? Is there a chip set available to handle the NuBus protocol?
There are two levels of prebuilt NuBus support available to you, depending upon the level of control you wish to exercise over the interface of the design and how expandable and compatible you desire your card to be.
The first is to use the Macintosh Coprocessor Platform (MCP) prototyping kit available from APDA: Macintosh Coprocessor Platform Developers Kit (#M0793LL/B). The Macintosh Coprocessor Platform, together with A/ROSE, is a generic hardware and software foundation to help developers create add-on cards and software applications for NuBus-compatible Macintosh computers. The card helps the developer quickly build a NuBus coprocessor prototype and ultimately helps speed time-to-market. This product contains the Macintosh Coprocessor Platform, A/ROSE (Apple Real-Time Operating System Environment) software, and the Macintosh Coprocessor Platform Developer’s Guide. Its intent is to inform and assist the developer in creating an interface to the Macintosh II product family bus (NuBus).
The Macintosh Coprocessor Platform card is a prototyping card with over 26 square inches of space available for the developer to use. It has no input/output interface, but is a generic master/slave I/O processor. Affiliated I/O devices that the developer adds, such as RS232 ports or Token-Ring connectors, give the card access to the outside world. The Macintosh Coprocessor Platform includes a Motorola 68000 processor operating at 10 megahertz and has 512K of RAM. The NuBus interface provides a bus master interface to NuBus on the Macintosh II main logic board. The Macintosh Coprocessor Platform card acts as a slot device to the Macintosh II operating system, freeing the processor on the Macintosh II to perform other functions.
A/ROSE is a real-time multitasking operating system for smart cards and provides an intelligent peripheral-controller interface to NuBus on Macintosh II computers. It provides the operating system and core software services required by Macintosh Coprocessor Platform card by providing software services to smart card application programs. The code includes a collection of traps, interrupt handlers, and tasks that provide support for task naming, timing services, and inter- and intra-card communications via messages. The manual provides information about the Macintosh Coprocessor Platform and A/ROSE software. The manual also provides a general overview of the product as well as detailed information on both the hardware and software components of the product. In addition, there are sample programs and instructions on how to create applications using the services of the hardware and software. If you plan to redistribute any portion of the A/ROSE software, either within their own company or outside, you must sign a license agreement with Apple Software Licensing.
Note: Because of the card’s design, access to the 6800 requires direct wiring to the 68000 socket.
For development with the Macintosh Coprocessor Platform you need a Macintosh II computer (with NuBus) running Macintosh System Software v. 6.0.2 or later, A/ROSE software and the Macintosh Coprocessor Platform, MPW v.2.0 or later, MPW C and/or MPW Assembler, and a Macintosh Coprocessor Platform NuBus card.
The second option is to use two NuBus™ interface chips designed by Texas Instruments specifically to aid in interfacing to the Macintosh NuBus. These chips are MCP NuBus Interface Controller SN74ACT2441 and MCP NuBus Address/Data Registered Transceiver SN74BCT2425. These chips are described and documented in the Texas Instruments NuBus Interface Products Data Book available from Texas Instruments
Devices & Hardware: NuBus: Should similar Macintosh LC and NuBus cards have same ID?
We’re considering a Macintosh LC card with the same functionality as our NuBus card. In creating the declaration ROM for this card, should we be requesting a new card ID from you or should we use the same ID as we do in the NuBus version?
Whether you request a new board ID is up to you. We argued about it here in DTS a bit:
Pro-New-ID: “You may someday need to tell the difference between the two boards; any design shortcuts that depend on ID equality are probably bad.”
Con-New-ID: “If they’re basically the same board, they oughta have the same ID.”
It really came down to: they’re not *exactly* the same board, and since board IDs are plentiful and free, you might as well request a unique ID for the new board.
Devices & Hardware: NuBus: Macintosh IIsi MMU table bug fixed for System 7
Macintosh IIsi MMU table bug fixed for System 7
A bug in the Macintosh IIsi MMU tables, which has been fixed for System 7, caused slot 9 to be shadowed in slot B. This shouldn’t affect applications or drivers using the Slot Manager to look for their cards IF they scan starting from slot 0 up to E, because a card in 9 will get seen in 9 and all will work OK. But if someone scans from E down to 0, the Slot Manager would think it found the card in B. That’s bad because the driver would install the SIntInstall interrupt routine for slot B, and the card would really interrupt on 9, causing a crash. Fortunately every example DTS has seen publishes indexes from 0 to E.
Devices & Hardware: NuBus: NuBus 90 documentation
Where can we get NuBus 90 information?
NuBus 90 is specified in the following two ocuments published by the Institute of Electrical and Electronics Engineers (IEEE):
• IEEE Standard for a Simple 32-bit Backplane Bus: NuBus
• IEEE Std. R1196-R1990
You can obtain these documents by contacting IEEE at the following address:
IEEE Service Center
445 Hoes Lane
Piscataway, NJ 08854
201-981-0060
Devices & Hardware: NuBus: How to request advance NuBus product information from Apple
We develop NuBus products. How can we get advance information if Apple makes any NuBus changes?
Pre-release product information is managed by Apple’s Evangelism Group. To request advance information on future NuBus technology from Apple, please provide the following information either by AppleLink or letter addressed to MacDTS (the Hotline staff will forward your information to the appropriate Evangelist.):
• A detailed description of the product you intend to or are developing.
• Key distinguishing features of your product
• Resources you have to conduct the development including:
- a description of your company’s technical expertise
- development experience and how it relates to the product
- development you propose (include programming experience,
products you’ve developed, etc.)
• How and where you intend to sell and distribute your product.
• Why you think this product warrants seeding.
• What does your product do uniquely with a new technology.
Your request for advance information or pre-release product seeding will be reviewed carefully by Evangelism. Because of the limited quantities of seed units, not all requests can be granted, nor can Apple seed for compatibility issues alone. Approximately three weeks after Apple receives your information, Evangelism will inform you of the decision regarding your request.
Devices & Hardware: NuBus: Use DirectSetEntries for remapping individual color components
Use DirectSetEntries for remapping individual color components
You can use DirectSetEntries to remap each individual color component of a DAC instead of mapping 16 million colors to 16 million colors mapping in 24-bit mode. This works for Apple’s 24-bit video cards and others that support the DirectSetEntries call described in "Designing Cards and Drivers for the Macintosh Family," second edition, page 171. It can be used to change brightness and contrast, as well as for doing color correction.
The sample program called DirectSetEntries in the Snippets folder on AppleLink and the latest Developer CD Series disc demonstrates how to call DirectSetEntries.
Devices & Hardware: NuBus: Macintosh bus or resource locking for NuBus access
Is there a way to do Macintosh®-to-NuBus™ access with bus or resource locking but without the CAS CPU operation which uses a Read-Modify-Write cycle? Does a CPU Read-Modify-Write cycle do resource locking when the CPU accesses NuBus?
Macintosh II CPUs perform an Attention-Resource Lock cycle as a prelude to Read-Modify-Write cycles to NuBus addresses. There is no other way to initiate bus or resource locking from the Macintosh CPU. Macintosh CPUs do not support locking NuBus for longer tenures.
The only Read-Modify-Write instructions are TAS, CAS, and CAS2.
Use of these instructions is problematic, as they may introduce timing problems for certain CPUs (see Macintosh Technical Note #271), and the operand address must always be previously cached in the MMU address translation cache or else a bus error results. They must be used with extreme care.
Devices & Hardware: NuBus: Byte lanes and 8-bit NuBus data transfers
Can we use the Macintosh® SReadFHeader function and specify the appropriate byte lanes to send 8-bit data over the NuBus™ through QuickDraw?™
I don’t think it’s a great idea to be 8 bits wide. But I think you are confusing byte lanes with the Macintosh actually talking to the board.
Byte lanes values serve _only_ to show where the declaration ROM is, not anything at all about how the rest of the card is laid out or accessed. Reading the header to figure out the byte lanes values is only used to figure out how to access the declaration ROM. The driver or application that locates the card (via the Slot Manager) is presumed to know how to talk to the card and so will do so in the most efficient manner.
Most card developers use a byte-wide declaration ROM and design the rest of the card for whatever makes the most sense. For example, video cards need some registers and frame buffering RAM. It makes the most sense to have the frame buffer be 32 bits wide for performance reasons. Because QuickDraw and the operating system don’t need to access the video card’s declaration ROM much at all (mostly during startup), it’s quite OK and cost efficient to have the declaration ROM be byte-wide (you can put it on any lane you like in this case, such as B/L 0). The registers are mapped typically to byte locations as well.
One thing to note is that QuickDraw (always) talks _directly_ to the frame buffer RAM on the card by doing long word accesses. This is done for speed reasons, because video buffers can get big and if you have a lot of video activity, QuickDraw has to push a lot of data around.
So, if you want to respond with an 8-bit RAM frame buffer port, when QuickDraw is accessing the video buffer on your card, your card is going to see the NuBus TM lines from the Macintosh showing long word accesses, and you will have to (slowly) fetch, and latch and hold each of the 4 bytes of the long word until you fill that long access (that is, all 32 bits) before ACKing. For this reason, no one to my knowledge has ever produced a video board that did not have a 32-bit wide frame buffer. Also, QuickDraw does Bit Field Extract instructions to the buffer, so that may slow things down some more.
Devices & Hardware: NuBus: NuBus board sResources needn’t start with ID=1
Does the first item in the Macintosh® NuBus™ sResource directory have to be a board sResource with an ID of 1? Is a declaration ROM in error if this is not the case?
There’s no restriction that sResources must begin with a board sResource with an ID of 1. All our examples do start this way, but it’s not necessary. The sResource IDs do need to be organized in ascending order. A special case restriction is that video board functional sResource IDs must begin at 128 (for the default mode) and continue sequentially, covering the remaining operating modes. Beyond this restriction, the board sResource can have any ID value.
Devices & Hardware: NuBus: Where to find NuBus declaration ROM sample source code
Where can I find a source code sample for NuBus™ declaration ROM creation?
You can find sample code for a NuBus declaration ROM in issue 1 of develop and in the develop folder on the latest developer CD.
Devices & Hardware: NuBus: NuBus RAM can be used as RAM disk driver but not system memory
Can the Macintosh® use my NuBus™ board RAM as additional system memory or as a RAM disk?
There is no way that the Macintosh operating system can recognize NuBus RAM and use it for applications. If you want to use it as a RAM disk, you’ll need to write a RAM disk driver. (Refer to Inside Macintosh for more information about this.)
Devices & Hardware: NuBus: Where to get Macintosh IIsi NuBus expansion card specs
What are the exact physical specifications for NuBus™ expansion cards for the Macintosh® IIsi? I have heard that there were some slight differences from the physical specs published in Designing Cards and Drivers for the Macintosh Family.
Macintosh IIsi dimension restrictions for NuBus cards are documented in Macintosh Technical Note #234. (This was written before the Macintosh IIsi was released, but with the IIsi in mind.)
Devices & Hardware: NuBus: Test and board exchange for early Macintosh II/NuBus problem
I seem to remember that the first few months’ worth of Macintosh® II systems shipped had some sort of NuBus problems, which Apple acknowledged and even had a free motherboard swap offer. These problems were subsequently fixed on later revisions. What was the real problem with those early Macintosh II systems? Is the free (or any other) board swap still available, and how does an end user take advantage of it? What were the serial numbers of the affected Macintosh units? What should we be telling our customers and dealers?
The Rev A Macintosh II mother boards had a problem with 32-bit addressing of NuBus™ space. If you have a card which has its ROM mapped into the top of the 16 MB space, then the card would not be seen. The other problem was with cards which had more than 1 MB of RAM.
The swap is still available as far was we know. The way to get the swap is to go into any dealer and ask for it. It may take a week for the dealer to get the parts, but they should be able to help any user.
We give out a tool that will determine if the board is an old version or not. The tool, “NuBusTester,” is on the developer CD and you can give it to all of your users. The tool checks the machine and if the machine is one of the problem machines, then it will bring up a dialog which tells the user to see their dealer. If the machine is fine then the app does nothing. The tester application will tell the customer what to do.
Devices & Hardware: NuBus: Macintosh board IDs and sResource equate info not available
Can I get a list of all Macintosh® NuBus™ board IDs?
No, that information is confidential. We register board ID and functional sResource equates so developers don’t use equates that are already in use, but we can’t distribute the list because the database contains information on unreleased products.
However, even if the list could be distributed, any program that depended on the information in it would be obsolete as soon as a new board came out.
We recommend that you use the Slot Manager’s ability to find certain cards or functions. That way, you only need to write your code once, and it will work with newer boards. That’s why QuickDraw™ can find video cards years after it was frozen in ROM. It does so by calling the Slot Manager and looking for boards that perform the QuickDraw-compatible video function.
Devices & Hardware: NuBus: How to register a Macintosh NuBus board
How do I register a Macintosh® NuBus™ board?
You need to have Developer Technical Support assign ID values for the sRsrc_Type fields (Category, cType, DrvrSW, and DrvrSW) for sResources other than the board sResource (the sRsrc_Type fields for the board sResource are ALWAYS $0001, $0000, $0000, and $0000 for the Category, cType, DrvrSW, and DrvrSW fields respectively), as well as board IDs for the board sResource. AppleLink® or mail the following information to MacDTS:
- Company name
- Company address
- Person to contact (name, mailstop, phone number, and electronic
mail address)
- The official product name (or at least a code name for
the board)
- What the board will do
- If the board will have a software driver
- If the board will have a software driver, if it will be
in ROM
- If the board will have a software driver, if it will be
compatible with one that has already been defined
(for example, Apple's defined video driver)
We need this information to maintain our database of NuBus boards. The information you provide is kept confidential, and the database is not available outside of DTS.
Devices & Hardware: NuBus: NuBus test for early 1-MB Macintosh systems
My NuBus™ card needs more than 1 MB of memory. How do I determine if my card has been installed in a Macintosh® that can see more than 1 MB of memory?
Some early Macintosh II systems can’t use more than 1 MB of memory. There is an upgrade available for those machines.
“NuBus Tester,” available on AppleLink and on the current developer CD, tells you which version of Macintosh you are running on.
There are object files that you can link with so that you can call CheckNuBus from your own application. You can also just send out the application called “NuBus Tester,” which checks the Macintosh and alerts you if you need to upgrade.
Do not try to make your own version of CheckNuBus—the dialog was set up by Apple’s legal department.
Devices & Hardware: NuBus: Macintosh II NuBus slot numbers and addresses
What are the numbers and addresses of the NuBus™ slots in the Macintosh® II class of machines?
If viewed from the front of the machines, from left to right:
Macintosh II 1,2,3,4,5,6 ($9, $A, $B, $C, $D, $E)
Macintosh IIx 1,2,3,4,5,6 ($9, $A, $B, $C, $D, $E)
Macintosh IIfx 1,2,3,4,5,6 ($9, $A, $B, $C, $D, $E)
Macintosh IIcx 1,2,3 ($9, $A, $B)
Macintosh IIci 4,5,6 ($C, $D, $E)
Macintosh IIsi 1 ($9)
Software should not assume anything about slot numbers. Programs should call the Slot Manager and index through the slots using the range 0 through E.
(NuBus is a trademark of Texas Instruments.)
Devices & Hardware: NuBus: How to upgrade earlier EtherTalk cards for Mac IIcx and IIci
Why am I having problems with EtherTalk® and my Macintosh® IIcx/IIci?
Revisions J and earlier of the Apple® EtherTalk card have a timing problem with Macintosh IIcx and IIci units. Symptoms of the problem are intermittent and include system hangs on boot, serious system errors, and exceedingly poor network performance. Revisions K and later of the EtherTalk card have been modified so that they will not exhibit this problem.
This problem occurs because the capacitance of a six-slot NuBus was factored into the timing mechanism of the EtherTalk card. Consequently, the capacitance level in a three-slot NuBus is lower, thereby affecting adversely the EtherTalk card’s timing.
As additional NuBus cards are installed into a system, the capacitance level is raised on the NuBus. As a result, the problem is less likely to present itself. The most likely IIcx and IIci candidates for having the symptoms mentioned above are units with a single EtherTalk card installed and no other NuBus cards in the remaining two slots. This is a configuration that would be commonly used for routers, file servers, mail servers, and so on.
If you need to exchange your EtherTalk card for a newer revision, please see your local authorized Apple dealer. To find a dealer near you, call toll-free 800-538-9696. You will be asked for your zip code, and you’ll be given names and phone numbers of all dealers in your area.
Devices & Hardware: Processor Direct Slot: SE/30 expansion card form doesn‘t require square holes
SE/30 expansion card form doesn‘t require square holes
The small square holes at the top of the SE/30 expansion card depicted in Figure 15-9 of “Designing Cards and Drivers for the Macintosh Family,” Second Edition, are not necessary. Their appearance in the diagram is probably a legacy of either an abandoned design approach or some fluke in the construction of the sample card used by engineering on which the diagrams were based.
Devices & Hardware: Processor Direct Slot: Processor Direct Slot (PDS) adaptor card documentation
Processor Direct Slot (PDS) adaptor card documentation
Processor Direct Slot (PDS) adaptor card specifications for the Macintosh IIsi are documented on pages 49-71 of the Macintosh IIsi Developer Note, available on AppleLink and on the latest Developer CD Series disc.
Devices & Hardware: Processor Direct Slot: Dynamic bus sizing on the Macintosh IIfx PDS
Referring to pages 312-3 of the second edition of Designing Cards and Drivers for the Macintosh Family, it seems the Macintosh IIfx handles PDS Pseudo NuBus differently between read and write cycles, and therefore does not support true 68030-style dynamic bus sizing. Could you please explain?
To clarify Designing Cards and Drivers…, the paragraph with the wording about “cycles incoming to the Macintosh IIfx memory” on page 313 really refers to MASTER cycles incoming to the Macintosh IIfx memory. The memory controller will respond to masters reading IIfx memory with STERM (and only STERM) as a 32-bit port.
PDS slaves can use either DSACK or STERM—it’s your choice. DSACK is passed directly to the processor in this case. So the right thing should happen because the Macintosh IIfx circuitry is not altering your DSACK signals.
While there are buffers on the Macintosh IIfx connected to the PDS, they are only bi-directional buffers that flip one way or the other, depending on whether a read or write is happening. There is no byte-swapping.
The only differences between an Macintosh SE/30 card and the Macintosh IIfx are that the IIfx uses slot E and the PDS is a 20 MHz rather than a 16 MHz slot.
The only way to get on D0-D15 would be if a 16-bit cycle was made on a 32-bit port. Again, the Macintosh IIfx PDS doesn’t do anything funny with regard to slave accesses.
Devices & Hardware: Processor Direct Slot: Don’t exceed Macintosh LC expansion card size specifications
The Macintosh® LC expansion card specifications are clear, but I’m wondering why a larger expansion card cannot be developed. It seems that a card with an “L” shape could be used to increase the size of the board. There don’t seem to be any restrictive components other than a large electrolytic capacitor which could be avoided. Are the restrictions due to heat or power considerations? What would Apple think about a card that was larger than the specifications if it was within the power budget?
Making a larger or oddly-shaped expansion board for the Macintosh LC is not a viable alternative. Besides physical size limitations, blocking ventilation and air flow patterns, increasing the heat dissipation, and exceeding the power budget all become more acute because the Macintosh LC is designed with even less tolerance for “bending the rules” than any model before. Also, in designing upgrades to any Macintosh model, our engineers know not to violate the documented expansion space reserved for you. Likewise, your staying out of areas not defined for your use will eliminate conflicts with Apple’s upgrades.
The guidelines were set up to protect you and your product from an expensive exercise in incompatibility. Apple very much wants to see your product to be asuccess in the market place.
Devices & Hardware: Processor Direct Slot: Macintosh SE expansion card must be parallel to motherboard
The documentation for a Macintosh® SE expansion card shows the board mounted parallel to the motherboard, but the chassis of the Macintosh SE which I have is the same as the one used on the Macintosh SE/30, whose expansion cards are mounted perpendicular to the motherboard. Is it possible to design an expansion card for the Macintosh SE following Macintosh SE/30 guidelines?
When hardware guidelines are set up, such as expansion board dimensions, power budgets, heat dissipation, Apple goes to great lengths to ensure that if you stay within these parameters your board will fit into every unit of that specification. This should remain true regardless of any manufacturing change to the unit and with all configurations of options.
The Macintosh SE internal chassis was changed in mid-production life to be interchangeable with the Macintosh SE/30 chassis. Although this appears to allow you to use the Macintosh SE/30 form factor on your expansion board, this is not the case. First, your board would not physically fit in all Macintosh SE systems because many have the original chassis. Second, there is no way for a user to tell which chassis s/he has, short of opening up the case. Third, even though the newer chassis does not block a vertical version of the board, other components used at various times in manufacture WILL block a vertical board in a Macintosh SE. The maximum allowable specifications for each model’s expansion boards are detailed in Designing Cards and Drivers for the Macintosh Family, 2nd edition. If you design beyond these specifications, even if it seems to work in a specific Macintosh you own, it will not fit in all or even most of the other units within the same model. Mounting the card perpendicular to the motherboard on a Macintosh SE is not a viable option.
Devices & Hardware: Processor Direct Slot: /CPUCLK signal
What are the termination and fanout specifications for the /CPUCLK signal on pin A38 of the DIN connector?
There are no known problems with the /CPUCLK signal termination. The buffering available on the motherboard is rated for 1 TTL input. If you need more than you must provide the buffer yourself.
Devices & Hardware: Processor Direct Slot: /NUBUS signal
What is the function of the /NUBUS signal on the Macintosh® expansion connector?
The /NUBUS signal can be used to start decoding the address lines, but in general it is of very little use.
Devices & Hardware: Processor Direct Slot: Processor Direct Slot RAM access references
Please send us timing diagrams and any other useful information about accessing the RAM on the motherboard from the Processor Direct Slot (PDS) on the Macintosh® IIsi and LC.
You will find the information you need in the Macintosh IIsi and LC Developer Notes, which are available through APDA® (Apple Programmers and Developers Association). APDA is a membership organization for professional, advanced amateur programmers and developers who work on Apple® equipment. Membership is open to anyone needing advanced tools and information for use in the development of Apple-compatible products. Dues are $20.00 annually. Contact APDA for product information at 1-800-282-2732 or write
APDA
Apple Computer, Inc.
20525 Mariani Avenue, Mail Stop 33-G
Cupertino, CA 95014.
AppleLink®: APDA
You may also want to consult the 68020 and 68030 user’s manuals, which are available from Motorola.
Devices & Hardware: Processors: Identifying a unique system and why Apple doesn’t serialize ROMs
Is there any way to uniquely identify a Macintosh®? For example, if we have twenty Macintosh IIfx systems, can we tell which is which? Is the ROM unique?
The ROMs are all identical. The best you can do with software is to look at some combination of things, like the user name, internal disk name, something like that. 'STR ' -16413 (the Macintosh name entered at the Sharing Setup Control Panel) in the system file might be one way to ID a system. Or you could create files in the system folder that had unique serial numbers. Of course, the user could change any of this.
The last Apple machine to have serialized ROMs (in the video PALs on the CPU board) was the Lisa. When the software was installed, it copied the serial number on to the master disks and would only work on that machine. The serialized ROMs caused lots of problems. Making and tracking the ROMs was expensive in manufacturing, and when the user took a machine in for service, if the CPU board got exchanged, the service people had to remember to pull out the old PAL and put it in the new board. If the PAL was the thing that went bad, it got even worse, since only the factory could program them.
Devices & Hardware: Processors: Macintosh LC and MC68030 load limits
Can you explain the apparent differences between the information contained in the Macintosh® LC Developer Notes concerning the MC68030 load limits for A0-31 and D0-31 and page 13-2 of the MC68030 User’s Manual?
The loads listed on page 24 of the Macintosh LC Developer Notes are the total loads allowed on the TTL lines. The table on page 27 listing the lines and their loads has different values because they are the values of each line after considering the loads that are already on these lines. In other words, some of the lines already have loads on them (such as pull-up resistors) and these loads have been subtracted out of the total load allowed and then listed. The load values to follow are those listed on page 27 of the Developer Notes.
Devices & Hardware: Processors: Where to find list of “sad Macintosh” error codes & descriptions
Where can I find a list of “sad Macintosh®” startup error codes and descriptions?
A list of the “sad Macintosh” error codes and descriptions is on AppleLink® and on the current Developer CD.
Devices & Hardware: Processors: 68030/Macintosh LC notes
What do I need to know to replace the 68020 with a 68030 in my Macintosh® LC? We know we need to generate the /AVEC but can we ignore the other signals that are not in the Macintosh LC’s 68020 direct slot bus, or are they even used in the 020 design? Also, is the LC compatible with the 68030 implementation as per the book with regard to the no-cache instruction fetches mentioned in the Motorola guide?
A few signals are not in the Macintosh LC’s 020 direct slot bus—namely, /1PEND, /AVEC, /ECS, /OCS, /CDIS, and /DBEN. Also, since there is only a 16- bit bus to the LC processor from the main memory, there is some question as to how Apple handled the no-cache instruction fetches.
Pull up all signals other than the /AVEC. The /AVEC signal should be grounded. As long as you don’t try to support bursting, you shouldn’t have a problem with None Cachable instruction fetches.
There is one other problem, however, which will affect you. There seems to be a problem with the early test code in the ROM, which does not like the 68030. When you try to run a Macintosh LC with a 68030, you will get the chimes. Apple is looking into the problem.
Something else which you need to be very careful about is the power budget on the Macintosh LC PDS. The LC power supply is very minimal and will not allow cards to take more than they are allocated. So keep your power budget in mind while you are developing your card.
Devices & Hardware: Processors: Macintosh CAS2 instruction needs bus error trap handler
When we use the CAS2 instruction with the Apple’s 8•24 GC card, we get a bus error. Why?
The reason you get a bus error has to do with the way the NuBus™ interface works on the Macintosh® II. If an incoming NuBus cycle to the motherboard happens exactly at the same time a Read-Modify-Write (RMW) instruction such as CAS2 tries to go out over NuBus (something a card with bus master capability might do), the processor gets a bus error due to the bus conflict. What your software must do is set a bus error trap handler before the CAS2 instruction and eliminate the trap handler after the instruction. The trap handler needs only to do an RTE instruction to cause the CPU to retry the CAS2 instruction.
Devices & Hardware: RAM: Macintosh RAM addressability under System 7.0
Macintosh RAM addressability under System 7.0
Maximum
Addressable Classic II, IIx IIci,
RAM in: Plus, SE SE/30 IIcx IIfx IIsi LC Portable
----------- -------- ----- -------- ---- ---- ---- --------
24-bit mode 4 8 8 8 8 8^ 9/8*
24-bit mode N/A 13** 13** 13** 12^^ N/A N/A with VM
32-bit mode N/A 128t 128t 128 65tt 10^ N/A
32-bit mode N/A 1GB~ 1GB~ 1GB~ 1GB~ N/A N/A with VM
* The maximum addressable RAM on the original Macintosh® Portable is 9 MB; because of its memory controller, the backlit Protable is limited to only 8 MB of RAM.
** The original 24-bit mode memory map allocated 8 MB for RAM, 1 MB for ROM, 1 MB for I/O and 6 MB for NuBus™ (1 for each of 6 slots; if the slots were not occupied this memory could be used for RAM) for a total of 16 MB. On the Macitosh SE/30 and IIci, built-in video takes up 1 MB that was previously allocated for an expansion slot. On the Macintosh II, IIx, IIcx and IIfx, a video card is needed which also takes away 1MB. That means there is 16MB -1MB (I/O) - 1MB (ROM) - 1MB (video on board or on NuBus) =13MB maximum RAM memory available. On the Macintosh II, the 68851 PMMU chip is needed for VM.
^ The Macintosh LC uses its own contiguous memory scheme that gives a total of 8 MB accessible RAM in 24-bit mode and 10 MB RAM in 32-bit mode.
^^ The 24-bit memory map on the Macintosh IIsi is the same as for all other Mac II systems. It allocates 8 MB for RAM, 1 MB for ROM, 1 MB for I/O and 6 MB for expansion slots. However, because of the slot table, the on-board video takes up 2 slots rather than 1, which results in 2 MB allocated for on-board video. That means there is 16MB -1MB (I/O) - 1MB (ROM) - 2MB (on-board video) =12 MB maximum RAM available.
t - With either a 32-bit software patch (Connectix Mode32) or A/UX®. Also, Macintosh II and IIx systems can be upgraded to Macintosh IIfx systems; likewise, Macintosh IIcx systems can be upgraded to Mac IIci systems.
tt - The Macintosh IIsi has 1 MB soldered on the main logic board (Bank A) and 4 SIMMs (Bank B). A maximum of 64MB is addressable in Bank B, which gives a total of 1+64=65MB RAM.
~ Under the 32-bit memory map, 1 GB is allocated to RAM, 256 MB to ROM, 256 MB to I/O, and 2.5 GB to NuBus. VM in 32-bit mode only accesses the 1 GB RAM. Again, for the Macintosh SE/30, II, IIx and IIcx, it is necessary to have either a 32-bit software patch (Connectix Mode 32) or A/UX. Or, a Macintosh II or IIx can be upgraded to a Macintosh IIfx; likewise, a Macintosh IIcx can be upgraded to a Macintosh IIci. On the Macintosh II it is also necessary to have the 68851 PMMU.
Devices & Hardware: RAM: Macintosh LC Developer Note VRAM correction
Macintosh LC Developer Note VRAM correction
The VRAM memory map information in Table 1-1 on page 10 of the “Macintosh LC Developer Note” is incorrect. The line that currently reads:
Function 24-bit mode 32-bit mode
VRAM $FC 0000-$FF FFFF $50FC 0000-$50FF FFFF
should be corrected as follows:
Function 24-bit mode 32-bit mode
VRAM $F4 0000-$FB FFFF $50F4 0000-$50FB FFFF
Devices & Hardware: RAM: Apple IIGS text page 2 and shadowing
How can I force text-page-two shadowing on the Apple IIGS?®
Most uses for text-page-two shadowing come from older, 8-bit applications that use text page two. On the Apple IIGS, a Monitor ROM routine at $F962 (TEXT2COPY) toggles shadowing of text page two, through hardware on ROM 3 and through software on older machines. (A heartbeat task copies the bank $00 screen to the bank $E1 screen for software shadowing.)
TEXT2COPY is only a toggle—it can't tell you the current state of shadowing. To see if shadowing is currently enabled (the user may have enabled it manually with the Alternate Display Mode desk accessory), try storing a character in the bank $00 text-page-two screen, waiting more than 1/60th of a second and seeing if the character has been copied to bank $E1.
Devices & Hardware: RAM: Macintosh IIci DRAM specifications
What are the required specifications of the Macintosh® IIci DRAM?
Here are the Macintosh IIci memory specifications:
256K (made from 1 MB Fast Page Mode parts), 1 MB, 4 MB,
or 16 MB SIMMs
RAS: 80 ns
CAS: 20 ns
Access Type: Fast Page Mode
Refresh Type: CAS before RAS
Refresh Period: 15.6 µs
The SIMMs can be composed of the following sizes in each bank:
4 256K SIMMs (composed of 1 MB of fast page parts only)
4 1 MB SIMMs
4 4 MB SIMMs
If on-board video is going to be used, RAM must be installed in Bank A, since the frame buffer is maintained beginning at physical address $0000 0000. If two different sizes of RAM will be installed—that is, 5 MB comprised of 4 256K and 4 1 MB SIMMs—then install the 256K SIMMs in Bank A for best video performance.
Devices & Hardware: RAM: Macintosh IIfx SIMM specifications
I would like to make SIMMs for the Macintosh® IIfx. Where do I get the specification for the new SIMMs?
The information about the new SIMMs is in the Guide to the Macintosh Family Hardware, 2nd Edition, pages 210-211. The physical and electrical specifications are the same for LaserWriter II-compatible SIMMs; however, the Macintosh IIfx requires 80 ns or faster RAM. You can obtain this specification by writing Developer Technical Support and requesting a copy of the “Macintosh IIfx SIMM Physical Specification.”
Devices & Hardware: RAM: Applications should not change Macintosh parameter RAM settings
How can I change the Macintosh® parameter RAM settings?
Changing parameter RAM is not supported. Inside Macintosh documents portions of PRAM and a couple of calls that will modify it. The layout of the standard PRAM was detailed, but since then PRAM has changed and extended. PRAM is reserved for the system, and is set by the user via the control panel. As you may have noticed, changing the settings of PRAM does not necessarily mean the system will start using those settings.
The system examines the contents of PRAM at startup time, and build its low- memory global information based on it. If you change PRAM during run-time, you would also have to change all of the affected low-memory globals. This is exactly how the Mouse and the rest of the control panel items work. Also, there is no trap to change the RAM cache setting because it is considered a user function. The RAM cache will only go into effect at the next application’s launch. The only supported documentation regarding the cache is in Macintosh Technical Note #81 and Inside Macintosh.
Parameter RAM is under the control of the user, not the application. We do not condone, and can’t support, applications that attempt to modify the PRAM.
Devices & Hardware: ROM: Macintosh II “32-bit clean” upgrade
I want to upgrade my Macintosh II with new ROMs so that I can be 32-bit clean and address more than 14 MB of RAM. Will the SuperDrive upgrade with new ROMs provide the solution I am looking for? If not, then is there any way to be able to address RAM using 32 bits in the future on a Macintosh II or do I have to upgrade to a Macintosh IIfx? I would prefer to stay with my Macintosh II and would like an upgrade path of this nature.
Currently the only way to obtain 32-bit clean ROMs for a Macintosh II is to purchase the Macintosh IIfx logic board upgrade. There are no plans at this time to provide 32-bit clean ROMs for CPUs prior to the Macintosh IIci that would allow the extended 32-bit addressing supported by System 7.0.
Devices & Hardware: ROM: No 32-bit clean Macintosh II ROM upgrade
I have heard that there is a ROM upgrade available for the Macintosh® II which is necessary for it to be fully 32-bit clean or to be compatible with System 7.0. Please respond and let us know whether a ROM upgrade is necessary, and if so how it may be obtained, and if there is any cost for the upgrade.
We don’t have a 32-bit clean ROM upgrade kit for any of our Macintosh systems. All our newer Macintosh systems have 32-bit clean ROMs, but all our computer models prior to the Macintosh IIci don’t. You might be thinking of the PMMU chip upgrade.
This won’t stop you from using System 7, however. It just keeps you from using 32-bit addressing. You can still use Virtual Memory if you put a PMMU in your Macintosh II. Even with a PMMU, however, you won’t be able to access more than 14 megabytes of RAM (minus 1 megabyte for each NuBus slot you’re using). If you did have 32-bit clean ROMs and used 32-bit addressing, you could address up to 128 megabytes of physical RAM, and address over a gigabyte of Virtual Memory! Most people would not need to use even a fraction of that. So even if you did have 32-bit clean ROMs, it’s likely you wouldn’t need 32-bit addressing.
Devices & Hardware: SCC: Macintosh maximum sustainable serial baud rate
When my hardware device sends data to a Macintosh at 57.6 kilobaud, characters can get lost if LocalTalk is on and a file server is mounted. Does Apple know about the problem? Is there a solution?
The specification for the top speed of the serial port on a Macintosh is an absolute maximum given that no other processing or use of the SCC are present. Although the speed of the Macintosh IIfx has now allowed this ceiling to be reached in the presence of other processing, it is just not attainable on other models of the Macintosh except when the machine is dedicated to this purpose. While AppleTalk remains active there is no guarantee on serial port data transmissions over 2400 baud. The same processor must handle the OS, the Serial driver and the AppleTalk driver (with no advantage of DMA), so the overhead is considerable. Because of the AppleTalk driver’s considerations for incoming serial data, users can usually work at up to 9600 bps without any problems. All models in the current product line, except the Macintosh IIfx, are unable to sustain throughput with baud rates beyond 19.2 kbaud except when exclusively dedicated to that task.
There is essentially no way to guarantee 100% serial data acquisition when using AppleTalk. This is due to the fact that while the Macintosh is receiving an AppleTalk packet, interrupts are disabled for the duration of packet transmission. What this means in a “worst case” situation is that a 603-byte packet (the largest possible AppleTalk packet) sent to the serial port would take approximately 26 milliseconds to receive. Compare this with asynchronous serial data transmitted at 9600 bps which would only take 1 millisecond to receive. A very realistic situation arises in which 26 bits could be lost during a concurrent AppleTalk/Serial Device transmission. The possibility is further strengthened when there are routers on the network, which send out large RTMPs (Routing Table Maintenance Packets).
To alleviate possible data loss, the AppleTalk driver interrogates the serial port at key times that won’t interfere with packet reception. However, the checks are not at regular intervals; they are encoded in the driver as stated above. This means that these random checks may not coincide with the demands of the serial driver, and an occasional character is lost.
This same loss of characters may also occur in conjunction with the Sony driver. If a disk is inserted and it requires special attention (like formatting) then the odds of losing characters is increased. The Sony driver has built-in considerations like the AppleTalk driver (although not as frequent). So you can still lose data at high transfer rates if a disk is inserted during the transfer.
The character dropout also occurs on systems which are not currently running AppleTalk but are receiving serial transmissions from high-speed devices (57.6 kbaud) and are performing CPU tasks which require a high amount of memory access (such as a CPU like the Macintosh IIsi or IIci running on-board video in 8-bit mode, or a CPU using VM).
There is, however, a way to ensure reception of high-speed serial data without character loss—through the use of a Serial NuBus™ card or other third-party NuBus cards with a dedicated processor necessary to provide higher speeds The cards in essence operate as dedicated port-handling circuitry. They are able to perform necessary buffering while the processor is servicing other interrupts. This is the reason that network cards such as EtherTalk and TokenTalk can accomplish lossless transactions; they do at least some of their own buffering until being serviced to avoid interference with other operations like receiving serial data.
Alternatively, you may want to develop a custom card yourself that exactly fits the needs of your product. In this case you should look into the Macintosh Coprocessing Platform (MCP) and Apple / Real-time Operating System Environment (A/ROSE) as a basis of this line of development. Development packages for both these products are available from APDA.
Devices & Hardware: SCC: NuBus cards that monitor multiple serial ports simultaneously
What NuBus cards are on the market to monitor multiple serial ports simultaneously? Do any of these come with source?
You should be able to use the Apple Serial NB Card, along with the Macintosh Communications Toolbox. The board ships with the Serial NB tool, which is the best way to access the card.
You can also check the Redgate Product Registry on AppleLink for the Creative Solutions serial card and other third-party products that might be other options for you.
Devices & Hardware: SCC: Separate transmit & receive baud rates for Macintosh serial port
Separate transmit & receive baud rates for Macintosh serial port
The Serial Driver does not support separate baud rates for transmit and receive. This is due to limitations imposed by the Z8530 SCC.
The SCC supports separate transmit and receive clocks; each is independently configurable to use a clock from the RTxC pin, the TRxC pin, the internal baud rate generator, or the output of the onboard DPLL. The first two options provide only a very limited, fixed set of baud rates. The last is used primarily for synchronous protocols. For maximum baud rate flexibility, the Serial Driver uses the internal baud rate generator for both transmit and receive. In some scenarios, separate transmit and receive rates would require two baud rate generators per channel, but there is only one.
Also, because the input and output drivers for a particular serial channel share code and data structures, commands like SerReset and SerHShake operate on both channels, regardless of the input or output designation corresponding to the refNum. In spite of the historical admonitions to make these calls separately for each driver, it’s not necessary to do so.
There are essentially only two options for running separate transmit/receive baud rates: operate in a half-duplex mode and SerReset between sending and receiving (gross and disgusting), or reprogram the SCC (risky) to use the RTxC clock or some other clocking option for either the transmitter or receiver, and live with one of the limited baud rate options that offers you. Baud rate options are limited because the standard input clock you have to depend on is 3.672 MHz. You could divide this down by factors of 1, 16, 32, or 64, giving you a minimum baud rate of 57.375 kbaud—not very helpful if you need something like 2400 or 9600 baud. You could run an external clock, but this adds expense and complexity.
Devices & Hardware: SCC: How to keep power on the Macintosh Portable SCC
How do I tell the SCC on the Macintosh® Portable to stay on (powered)?
The Macintosh Portable has a second CPU known as the Power Manager. The Power Manager controls power to each subsystem of the Portable in order to best conserve power on those parts that are not currently in use. The Power Manager is documented in Inside Macintosh Volume VI as is a trap (_SerialPower) that can be used by a driver to turn on (and off when done) the SCC.
Devices & Hardware: SCC: Where to get detailed Zilog Z8530 SCC documentation
I need to find documentation for the Zilog Z8530 SCC beyond Inside Macintosh®. Do you how I can contact Zilog or another vendor for this documentation?
You can get documentation on the SCC from the following source:
Advanced Micro Devices (AMD Z8530)
901 Thompson Place
P.O. Box 3453
Sunnyvale, CA 94088
Devices & Hardware: SCC: Macintosh IIfx Serial Switch 'cdev' for SCC direct access
My application requires direct access to the SCC and I do not find the Macintosh® IIfx Serial Switch 'cdev' to be good solution. Is there a way for me to get the support I need from the Serial Driver, or do I need to continue breaking the rules?
The Serial Switch 'cdev' is a compromise between not allowing developers any solution or Apple redesigning the serial driver and waiting for developers to implement it. For the moment, this Serial Switch 'cdev' is the best solution available; however, Apple is working on improving the Serial Driver to solve this problem. Unfortunately, it was not possible to produce this improved Serial Driver in time for the Macintosh IIfx introduction.
Devices & Hardware: SCC: Macintosh Device Manager and IOP Serial Driver access
On the Macintosh® IIfx, does the Device Manager still use the same offsets into the Unit Table to access the IOP Serial Driver? Does this serial driver maintain the low-memory SCCASts and SCCBSts globals?
Yes, the Device Manager uses the same offsets. If you use the Serial Switch 'cdev' for compatibility mode, then the Serial Driver does maintain both SCCASts and SCCBSts.
Devices & Hardware: SCC: SCC and AppleTalk timing
The AppleTalk® spec claims a data rate of 230.4 kbaud, which should require a 3.6864 MHz input to the SCC, but RTxCB on the Macintosh® carries a 3.672 MHz clock. How does the AppleTalk driver reconcile this and what frequency should I use?
The SCC contains a phase-locked loop which is able to lock on and synchronize with AppleTalk transmissions whose clock rates are not exactly to specifications, so everything is fine as long as both ends of the communication are using approximately the same clock frequency. If you are designing your own AppleTalk hardware from scratch, it is easiest to use a 3.6864 MHz oscillator and a Z8530. This has been tested and works just fine.
Devices & Hardware: SCSI: Macintosh Quadra and SCSI termination
Macintosh Quadra and SCSI termination
Proper SCSI termination is critical for correct operation of the Macintosh Quadra computers, just as with all Macintosh computers. The Macintosh Quadra computers require external SCSI termination at the end of the device chain, either supplied by the last device in the chain, or using a standard Apple SCSI Cable Terminator (M0332LL/A). Note that this is the standard SCSI terminator, NOT the black terminator required by the Macintosh IIfx (although the black IIfx terminator may be used as well).
Termination is generally supplied at the factory for use with internal SCSI devices. Some early floppy-only Macintosh Quadra 700 units may not have internal termination, so users who attach external SCSI devices (without having added an internal SCSI device) may need to double terminate their external SCSI chain. Properly terminated floppy-only Macintosh Quadra 700 units will have a terminator inserted into the motherboard internal SCSI cable connector. Users of internal SCSI devices must, of course, remove this terminator before connecting their internal SCSI device.
The Macintosh Quadra 900 is the first Macintosh computer to provide a separate, internal SCSI bus. This bus is physically isolated from the external SCSI bus and must also be properly terminated. The cable provided with the machine includes all the termination necessary, so ALL internal devices must have SCSI termination removed before connecting to the internal Macintosh Quadra 900 SCSI cable. If extra termination is supplied it may cause intermittent hardware failures as well as physical damage to the device.
Developers who ship terminated SCSI devices for possible internal use in the Macintosh Quadra 900 must provide users with instructions for removing the termination.
Devices & Hardware: SCSI: Documentation describing VM/SCSI driver requirements
Are there any new rules regarding SCSI driving with Virtual Memory? My System 6 driver doesn’t work with System 7.
You need the following new documentation:
• Inside Macintosh Volume VI contains new information specific to Virtual Memory as it relates to drivers and especially SCSI.
• Technical Note #285, “Coping with VM and Memory Mappings”
• “VM Paper” from the System 7.0 developer CD in the VM Goodies folder.
These documents provide a good overview of what you need to do to revise a SCSI driver for VM compatibility.
Devices & Hardware: SCSI: Use Macintosh SCSI Manager for SCSI chip compatibility
Our SCSI driver asserts the SCSI bus protocol directly, according to the SCSI bus specs, using the low-memory global SCSIBase as the SCSI base address. Our code works fine on systems using the NCR 5380, but hangs with the new SCSI NCR 53C96. Do I need to add a NOP somewhere because the new chip is faster?
Although SCSIBase is exactly where a SCSI device driver should look to find the base address of a SCSI chip in the Macintosh, the NCR 53C96 is a physically different chip then the NCR 5380. Besides having its registers in different locations of the address map and a slightly different register set, the chip takes on much more of the burden (and control) of accessing the SCSI bus. The major difference is that with the 5380, the chip controller (drvr) needs to actively respond to the phases of the SCSI bus as the target changes them and to be ready to correctly react to any unexpected changes in state. For continued compatibility with the Macintosh product lines, your driver must use the SCSI Manager rather than to write directly to the chip. With the new chip (5396) the chip controller needs to set up all information for the entire command sequence (Arbitration thru Message In) and then tell the chip to execute it. The “controller” is not in direct control of the SCSI bus. (With the earlier chip, it’s really the Target that’s always in control, not your driver, but the 5380’s interaction model gives the IMPRESSION that your driver is in control.)
Your best course of action is to make sure your SCSI driver uses the SCSI Manager so that you will automatically work on all Macintosh platforms in the event that Apple changes chips in the future. If there is something odd about your SCSI device that it just cannot be accommodated by the SCSI Manager (this is rare!) then you will need to get the documentation for the NCR 5396 (from NCR) and rewrite your driver to use this new “setup and go” interaction model.
Devices & Hardware: SCSI: Macintosh SCSI reselection
How should we handle target reselection with the Macintosh SCSI Manager?
The Macintosh SCSI Manager does not support disconnection and reselection. After arbitration and selection, the target device should perform a SCSIMsgOut to identify the logical unit number and especially to see if disconnection and reselection is allowed (bit 6 of the Identify message). The Macintosh currently always sets bit 6 of the Identify message to 0, meaning disconnection is not allowed.
A target device should always assume that disconnection is not allowed unless it is specifically told otherwise by the Identify message. In this way, the target will do the right thing even if it does not follow protocol and issue a Message Out before requesting the Command.
Devices & Hardware: SCSI: Apple SCSI cable information
Where can we get specs for Apple’s SCSI cables, similar to Apple’s paint and finish standard, which allows us to match our hardware exactly to the Macintosh family? SCSI details we are concerned with are: single versus double shielding, contact types (such as gold), wire gage, and color.
The information you’ve requested is unavailable for distribution. Apple simply doesn’t supply specifications for any of its hardware to outside parties. However, you might try looking at the following SCSI specifications for more information:
Specification: Available from:
_____________ ___________
SCSI-1: ANSI X3.131-1986 American National Standards Institute
ISO DP 9316 1430 Broadway
ECMA-111 New York, NY 10018
CCS: X359.2/85-52,1986 (Rev 4.B) American National Standards Institute
(Common Command Set) 1430 Broadway
New York, NY 10018
SCSI-2: ANSI X3.131-1990 Global Engineering Documents
(Revision 10c) 2805 McGaw
Irvine, CA 92714
Tel: (800) 854-7179 or (714) 261-1455
These specifications discuss SCSI interface and, although they don’t tell you exactly how to build a SCSI cable, they give you a good benchmark for engineering one. Both of the above specs are available from:
Another alternative is to go out and buy one of Apple’s cables and reverse engineer it. Your local dealer might be the best location for this.
Devices & Hardware: SCSI: Transferring data from SCSI device to Macintosh
How can an external SCSI device interrupt the Macintosh system CPU? What’s the procedure for transferring data from my external SCSI device’s buffer to system RAM?
Transferring data from a SCSI device to a Macintosh is not a simple task. The Macintosh SCSI implementation does not support arbitration, so only the Macintosh can start a SCSI transaction. If someone else were to begin transferring data on the bus, and the Macintosh wanted to begin a transfer, it would not know how to deal with the situation.
This rules out your SCSI device being able to decide to send data to the Macintosh. The only way to accomplish what you need to do is to write a VBL or Time Manager task that periodically checks your device to see if it needs to be serviced, and if so, initiates a SCSI transfer to get the data from it. While this approach requires somewhat more care, because of its granularity, it should prove adequate.
Devices & Hardware: SCSI: SCSI hardware specifications
SCSI hardware specifications
SCSI 1 and Common Command Set (CCS) hardware specifications are published by the American National Standards Institute. You can request specifications from this organization by contacting them at:
American National Standards Institute
1430 Broadway
New York, NY 10018
SCSI 2 and most other SCSI documents are available from:
Global Engineering Documents
2805 McGaw
Irvine, CA 92714
Tel: (800) 854-7179 or (714) 261-1455
Devices & Hardware: SCSI: SCSI/NuBus card development tools and resources
Are there any new tools or resources for developing a SCSI/NuBus card? None of the slot tools available on AppleLink have been updated since September 1989.
We recommend you look at the application named Slots, on the latest Developer CD Series disc. It allows you to look at declaration ROM sResources and make your own calls to the Slot Manager. It was written in 1990 by an engineer working on the Slot Manager.
Devices & Hardware: SCSI: SCSI drivers and virtual memory
How can we disable virtual memory (VM) from a SCSI driver, for dequeuing partitions? How can our driver determine which volume the virtual swap file resides upon?
The use of virtual memory requires that at boot time the PMMU be programmed with the appropriate memory mapping tables and enabled. The virtual memory is then laid out in the “VM Storage” file and available “real” RAM begins to be used to implement those portions of the virtual memory that need to be resident. It is not possible to turn this on and off while the machine is running. Specifically, it cannot be disabled / re-enabled from within your SCSI driver. With VM running, you can dismount and remount any disk or partition EXCEPT the unit that contains the VM Storage file. Whenever the system boots with VM on, the Finder makes sure there is only one file of that name mounted anywhere and deletes any “extra” files it encounters.
Currently there is no interface for locating the VM Storage file. Since the file name is guaranteed to be unique, it should be sufficient to search each volume for that file name.
Devices & Hardware: SCSI: Currently A/UX is only OS to use Macintosh IIfx SCSI DMA chip
Does System 6.0.7 or 7.0 make use of the DMA portion of the Macintosh® IIfx hardware?
System 7.0, or any version of the Macintosh operating system at this point, does not utilize the SCSI DMA chip in the Macintosh IIfx. A/UX® is the only operating system on the Macintosh that does use this chip.
Devices & Hardware: SCSI: Using Macintosh SCSI Manager for direct disk access
I would like to read and write sectors directly on a SCSI disk. Do I need to access the SCSI chip directly or can I use the SCSI Manager for this?
The normal way to access a SCSI disk is to use the Macintosh® file system, which calls the SCSI Manager to access the SCSI bus and command the hard disk to read or write data in various blocks. You should be able to directly command the hard disk yourself and directly send and receive the sector buffers by calling the SCSI Manager to perform the SCSI communication for you.
Pseudo code to perform this kind of transaction would be:
• Prepare a command block for read or write, etc.
• Prepare your data buffer and a transfer instruction block (tib) containing instructions for data transfer. For example, a tib for transferring six 512-byte blocks of data from or to address $67B50 contains the following:
SCINC $67B50 512
SCLOOP -10 6
SCSTOP
• Call SCSIGet() to gain control of the buss
• Call SCSISelect(TargetId) to select the target device (your hard drive) and allow the target to command the bus.
• Call SCSICmd(CommandBlock,Length) to give the SCSI Manager the command you want it to transfer when the target requests the command.
• Call SCSIRead(tib) (or SCSIWrite) to tell the SCSI Manager where to put the bytes (or where to get them from on a write) when the target requests them.
• Call SCSIComplete(Status, message) to finish the transaction and receive the (potential) error code.
If what you intended to ask was how to write your own SCSI hardware driver, be aware that this is not an area that DTS normally supports. If you are developing for a unique SCSI device that cannot be interfaced to using the provided SCSI Manager, please let DTS know the details about your device and the problems you are encountering that will not allow its control via the SCSI Manager. Also, please note that the specific SCSI chip used in a specific Macintosh model may change in some future Macintosh model and will break your custom driver, requiring you to rev your driver if you want to continue to be compatible. For this reason we strongly suggest that you use the provided SCSI Manager if at all possible.
Devices & Hardware: SCSI: Macintosh System 7.0 SCSI function #14
What does the new Macintosh® SCSI function #14 do in System 7.0?
The new selector is called SCSIBusy or, more accurately, SCSIMgrBusy, selector #14 or $0E. It is a parameterless SCSI call to determine whether the SCSI Manager is busy or idle. A non-zero return value indicates that SCSI Manager is busy, meaning it is currently processing a SCSI transaction. It is important to note that return value does NOT reflect the busy/idle state of the SCSI bus. It is possible to get a return value of zero--SCSIMgr is idle--while the SCSI bus is busy.
The selector is intended to be used by Apple only, specifically by the file
system.
Devices & Hardware: SCSI: SetDefaultStartup sdRefNum should be real SCSI ID, not -33
If I’m doing a SetDefaultStartup for a SCSI device can I simply set sdRefNum to -33 for the SCSI ID? Do I have to set any other fields of the DefStartPtr? Will these other fields be ignored?
Don’t count on the unit table always staying the same. It would be better to use the real SCSI ID.
Devices & Hardware: SCSI: Macintosh/SCSI compatibility
Is there any reason that a SCSI device (scanner) would work on a Macintosh® IIfx but not work on a IIci?
Without a bit more information it is difficult to speculate what might be causing the problem. If you access the scanner through the SCSI Manager, there should be no problem. Usually it is the other way around (works on the Macintosh IIci but not on the IIfx). If any part of your driver does access hardware directly on the Macintosh IIci, it would likely have problems on the IIfx because its SCSI hardware is very different. It may simply be related to termination on the SCSI bus and not driver code on the IIci. The IIci is prone to termination problems if there is no internal HD or if it is not properly terminated externally. Check for that possibility by changing the arrangement of SCSI devices. There are also some specific bugs/quirks in the SCSI Manager documented in Macintosh Technical Notes #96, 212, and 258.
Devices & Hardware: SCSI: If Macintosh doesn’t boot with multiple SCSI devices
What would cause the system to refuse to boot up when I connect a third-party SCSI drive after the Apple CD-ROM drive?
Your problems with the CD SC and a third-party disk are probably related to noise on the SCSI bus. We use CD SCs here with as many as 5 other external SCSI devices without problems. However, any SCSI device’s performance can be affected by noise and is exacerbated as more devices are added to the SCSI chain. The most common causes of noise are improper termination, damaged or poor quality cables, and incorrectly designed SCSI devices. Because DTS successfully uses the CD with multiple devices (both Apple and third party), I suspect the third party drive is the source of the noise. If it uses any kind of internal termination, the terminator MUST be removed. Apple recommends that all SCSI device manufacturers not use internal termination, relying instead on the external terminators provided by Apple which can easily be rearranged or upgraded (as with the Macintosh IIfx). Also, try a different SCSI peripheral cable in case yours is damaged or not up to par. You may also be having problems if there is no internal hard drive in your system. This leaves the internal end of the SCSI bus unterminated. This is particularly a problem for the fast CPUs such as the Macintosh IIci and Macintosh IIfx, because they are more sensitive to noise. If this is the case, try installing an internal hard drive, or you can obtain an internal SCSI terminator from MicroNet (see the Macintosh Buyer’s Guide for a #/address). For more information, see Macintosh Technical Note #273.
Devices & Hardware: SCSI: Connecting two Macintosh systems via SCSI
How can I connect two Macintosh® systems together using the SCSI port so they can run in parallel?
For many reasons, connecting any two systems via SCSI port to SCSI port should not be attempted. The most important reason is that you would then have two devices (the CPUs, and probably the internal drive) on the bus with the same SCSI ID. Further, a straight-through cable would connect outputs to outputs and inputs to inputs, which would bring communications to a halt.
However, a SCSI-to-SCSI connection, like the type mentioned below, is possible between the Macintosh Portable and a desktop Macintosh using LapLink Macintosh III from Traveling Software. It works only on the Macintosh Portable since the SCSI ID of the Macintosh Portable can be changed from 7 to 6, avoiding the ID conflicts. Traveling Software also provides a special SCSI-SCSI cable, which is required for this connection. (This setup cannot connect two desktop Macintosh systems unless the drive ID can be changed. This is not possible with Apple’s internal drives but you may be able to do it with other internals. In any case, this is unsupported, so if you attempt this you do so at your own risk. You probably will void your warranty.)
LapLink Macintosh III
Traveling Software, Inc.
18702 North Creek Parkway
Bothell, WA 98011
206-483-8088
Devices & Hardware: SCSI: SCSI terminator specs
Please provide us with specs on Apple® Part No. M0332LL/A, and also information on what type of SCSI terminator can be used for Macintosh® IIfx.
Specs for Apple SCSI terminators (the original gray terminator and the special black Macintosh IIfx terminator) can be found in Macintosh Technical Note #273. The Macintosh IIfx requires the black terminator for external termination and either a properly terminated internal hard disk or the internal termination block and filter for internal termination. All Macintosh IIfx computers shipped without an internal hard disk include this internal terminator and filter plugged into the SCSI connector on the logic board.
Devices & Hardware: SCSI: Where to get Macintosh SCSI Manager sample code
Can you provide some sample code on using the Macintosh® SCSI Manager to access a SCSI device?
A SCSI Development Package is available from APDA® for around $20. You can contact APDA at (800) 282-2732.
Devices & Hardware: SCSI: Cannot make SCSI inquiries of CPU
Is there a way to get the SCSI information for the CPU (ID 7) using a SCSI call?
No, sorry. The SCSI protocol says that there is a SCSI bus Master and a SCSI target, and that the two will not be the same. Since the Macintosh® is always the master, there is no way you can make inquiries of it.
Devices & Hardware: SCSI: No new System 7.0 SCSI Manager yet
Where are the C header files for the new Macintosh® System 7.0 SCSI Manager?
There currently is no new SCSI Manager in use in System 7.0. This was announced a while back, but then it was also announced that it would not be implemented after all. I don’t know what the plans are for implementing a new manager, but the references you saw were probably left in there by mistake. As far as we know, there is no new SCSI manager and there aren’t any plans to place it in a system in the near future. If Apple does replace it, however, we will contact our developers so you shouldn’t worry about being left in the dark to guess when/if it does become reality. You should be able to use the same files as before since there isn’t any problem with incompatibility at this time.
Devices & Hardware: SCSI: Macintosh IIci SCSI power connector changes
What changes are there to the Macintosh® IIci SCSI power connector?
The IIci SCSI power connector is supplied by Molex. It is plug housing part number 39-01-2040 with four crimp pins (part number 39-00-0039) per housing needed. You can contact Molex sales representatives Dave Rios in San Jose, CA (408-946-4700) or Randy Kempf in Lisle, IL (312-969-4550) for these parts.
Figure as seen looking down at the IIci logic board:
+----------+ 1 +12V
| 3 1 | 2 ground
| | 3 ground
| 4 2 | 4 +5V
+----------+
Devices & Hardware: SCSI: Macintosh IIfx SCSI compatibility
My SCSI product is having problems working on the Macintosh® IIfx. What are the differences between the IIfx SCSI and SCSI on all the other SCSI-equipped Macintosh systems?
The SCSI chip on the IIfx is different from any of Apple’s previous machines. The new SCSI chip is an Apple ASIC which adds functionality to the 5380. The pinouts are identical, the cables are identical, but the terminator is different.
Every IIfx is shipped with the new terminator, so unless you have internal termination on your external SCSI device, there is no known reason for your product not working. The new terminator is black in color (instead of gray or platinum) and completely replaces the old terminator.
If your SCSI device is directly accessing the SCSI low-memory globals, then this is likely to cause your incompatibility problems, since the globals have changed in the IIfx and could change again in the future.
As stated in Technical Note #273, if you can give DTS detailed information on your compatibility problems with the IIfx and your SCSI device, we should be able to provide you with more information about the possible causes.
Devices & Hardware: SCSI: Can I have a device powered off and connected to the SCSI bus?
Can I have a device powered off and connected to the SCSI bus?
The SCSI specification does not define how a device is to behave while powered off. The best advice and the official line from Apple is not to have devices on the bus and powered off. It’s been found that having devices powered off and on the bus causes degradation to performance and the signals. This is the issue: electrical problems of termination and termination power. Some devices are NOT following the description of how Apple’s devices work, and following the guidelines of the Apple cable guide does not apply with non-Apple devices. The termination problem can cause hardware damage. Therefore, the rule is this: Do NOT have devices connected to the bus with their power off. Also, do not power on a device connected to the bus after booting and never connect one while the system is on.
Devices & Hardware: Serial Driver: Conditions degrading 57.6 Kbaud transmission
We are experiencing intermittent character dropout at 57.6 Kbaud on a Macintosh® IIsi in 256-color mode, but if we drop down to 16-color mode, everything works hunky dory. MultiFinder® on or off makes no difference. What’s the connection between the number of colors and the serial port?
It turns out that various additions to the system cause performance to degrade, such that serial operation at 57.6 Kbaud cannot reliably be maintained.
There are various factors here, including the video mode (which requires more memory accesses and wait states to produce the same video rate, thus incurring a higher processor overhead). VM, if turned on, exacts an additional performance penalty. These problems are not limited to the Macintosh IIsi; we’ve had reports that they can also occur on the Macintosh IIci when running the on-board video in 256-color mode without a cache card.
Devices & Hardware: Serial Driver: Macintosh serial driver doesn’t support synchronous communication
What Macintosh® system call should I use to use the modem port for synchronous communication?
Unfortunately, the Macintosh serial driver does not support synchronous communication. The only way to perform synchronous communication is to manipulate the hardware directly, which is unsupported. This means that if you directly manipulate the hardware, your product won’t work on Macintosh systems that don’t allow direct access to the SCC, such as the Macintosh IIfx.
Devices & Hardware: Serial Driver: Where to get “Sample Serial NuBus Driver Code” disk
How can I get a copy of the Macintosh® “Sample Serial NuBus™ Driver Code” disk mentioned on page vii of the Apple Serial NuBus Card Programmer’s Guide (APDA # M0941LL/A)?
After doing some rather extensive checking I have been informed that the Driver Code is available through APDA. The product quoted is the Serial NB Tool, Product Number M0950LL/A. The tool is available for $40.00 and includes a disk and documentation.
Devices & Hardware: Serial Driver: Serial driver DCE dCtlFlags and serial port arbitration
How do I tell which serial ports are available? DTS’s Macintosh® Technical Note #249 says not to check SPConfig, PortAUse or PortBUse. If I do an OpenDriver on both ports to see which ones return no error, I may have two serial ports open, and I’m not supposed to close them. When I set the handshaking options on the output port, am I also setting them on the input port?
Serial port arbitration… such a lofty goal. The Communications Toolbox sort of does it, and you can do it in about the same way if you simply look at bit 5 of the low-order byte of the dCtlFlags field of the Serial Driver’s DCE (Inside Macintosh, Volume II, p. 190).
If the driver is already open, assume someone else is using it. When you use it, be sure to close it when you’re done.
I’m not sure what you mean by you’re “not supposed to close them” unless you’re referring to the ancient serial driver documentation in Inside Macintosh, Volume II. You can simply call CloseDriver these days as long as you’re using a reasonably new serial driver (everything later than the 128K Macintosh Plus ROM).
If you want to be precise, you can call Status on the serial output driver with a csCode of 1 to get a handle to the driver’s DCE. If the return value in csParam is a valid handle, you can dereference it and check the byte at offset dCtlQueue+1 (=7) to get the driver version number. If it’s not zero, it’s OK to close the driver.
That in itself should help you a lot.
It’s not entirely obvious to what refNum one should address the SerHShake command, so you’ll have to trust me. Just call it once on the output driver and everything will be OK. The serial driver doesn’t support separate baud rates and handshaking protocols for each half of the duplex. (Ironically, I do recommend that you call SerReset on both halves. Don’t ask me why.)
Devices & Hardware: Serial Driver: Macintosh serial hardware handshaking
What is the method of asserting and then negating DTR with csCode=17 and csCode=18 respectively, in LightSpeed C on the Macintosh®?
Open the serial output driver and get its refNum followed by:
ctrlErr = Control(refNum, csCode, &csParam);
The results depends on what csCode is used. For the csCodes 17 and 18, csParam is not used and could probably even be NULL.
As an example, it is necessary to use csCode=14 instead of SerHShake() if you want to do full hardware handshaking. The code to do so is:
setHskErr = Control(gOutRefNum, kSerHShakeDTR, &hskFlags);
assuming that kSerHShakeDTR = 14 and hskFlags is a SerShk record.
Devices & Hardware: Serial Driver: Opening the Serial Driver more than once and the PortInUse error
Shouldn’t I get a PortInUse error if I open the Macintosh® Serial Driver twice?
Arbitration is only done on DIFFERENT types of drivers. Say you try to open the Macintosh ROM asynchronous driver; it will fail ONLY if the port is in use by a driver that is something other than async. If the port is in use by another asynchronous driver, you won’t get an error.
For example, if you try to open the async ROM driver while AppleTalk® (which is a different type of driver) is using it, you WILL get an error.
This unfortunately means users can open AppleLink®, SmartCom, Red Ryder, and so on, under MultiFinder®, and, because they all use the Macintosh async driver, get no errors. Of course, all programs can then merrily change the SCC like crazy. That is why it has to be documented that users can’t run multiple applications that use the Serial Driver under MultiFinder.
Devices & Hardware: Serial Driver: Specifying a specific Macintosh serial baud rate
How can I program the Macintosh® Serial Driver to use a baud rate of 38,400?
Use a baud rate constant of 1 for 38,400 baud. Note that you can specify a given baud rate by making the Serial Driver control call with a control code (csCode) of 13. The driver will return the closest baud rate that the Serial Driver will generate. Some trivia:
The formula for figuring out the SerConfig baud rate constants is
114709
Baud Rate Constant = ----------- 2.0
Baud Rate
For example, the baud rate constant for 9600 baud is
114709
Baud Rate Constant = ------ 2.0 = 11.949 - 2.0 = 9.949 = 10
9600
The 114709 figure comes from the SCC clock (3.670702 MHz) which comes from the system clock (15.6672 MHz), but doesn’t divide down evenly because of the timing PALs (in fact, 3.670702 = 15667200 /4 * 15/16, where the 15/16 is due to PAL timing). For the Mac XL (Lisa), use 115200 instead of 114709.
Similarly, you can do a reverse calculation and find the baud rate, given a constant. Reversing the formula, you get
114709
Baud Rate = --------------------------
Baud Rate Constant + 2.0
So, using the constant 10 (for 9600 baud), the formula gives
114709
Baud Rate = -------------------------= 9559.083
10 + 2.0
This isn’t exactly 9600 baud. In fact, the error percentage is
9559.083
1.0 -------------= 1.0 - 0.996 = 0.426%
9600
If you try this with 38400, you get
114709
Baud Rate Constant = --------- 2.0 = 2.987 - 2.0 = 0.987 = 1,
38400
a baud rate of
114709
Baud Rate = -------------------------- = 38236.333,
Baud Rate Constant + 2.0
and an error percentage of
38236.333
1.0 -------------= 1.0 - 0.996 = 0.426%
38400
Devices & Hardware: Slot Manager: How to tell if Slot Manager is implemented
How do you tell whether the Slot Manager is implemented?
The best way is to just check for the existence of one of the Slot Manager traps. You should be able to check the implementation of Trap $A06E and if it is there, then the Slot Manager will be there. Below is a piece of code which does this check:
#define SlotManager 0xA06E
#define NoTrap 0xA89F
main()
{
if ((GetTrapAddress(SlotManager) != GetTrapAddress(NoTrap)))
SysBeep(5); // if the Slot Manager is avail then beep
}
Devices & Hardware: Slot Manager: SGetCString and memory (de)allocation
Inside Macintosh Volume V (page V-445) states that SGetCString automatically allocates memory for holding the requested string. Does this mean that repeated calls to SGetCString will eventually exhaust memory and, if so, what is the correct way to release the memory?
The documentation doesn’t say so, but...
SGetCString automatically allocates memory (via NewPtr) for holding the requested string. It copies the string into that pointer and returns the pointer in spResult. You need to call DisposPtr on spResult to deallocate the pointer.
Devices & Hardware: Slot Manager: NuBus card prototype and declaration ROM development
Is it possible to convince the Slot Manager *after the boot process* that a NuBus card is now in a previously (apparently) empty slot?. Is there some standard declaration ROM to burn in order to have a “more generic” look to the system? We want to slam cards in and out of a system, and make all kinds of weird prototype boards without changing or making new declaration ROMs.
You’d have to hack the slot resource and slot info tables, which are undocumented. It probably would be doable, but not all that easy; just restarting would be easier and faster.
To do as much as you can running code from an application, pretending all the code that goes to the declaration ROM “works” would be easier, as you say. Then, only at the last, when you have everything working, put the driver in the ROM. You might make a very simple ROM that just lets the Slot Manager know a card is installed, run as much code as you can from the application level until it’s debugged, and then fold it into the ROM.
If you need code to a “generic” sort of ROM, why not take the skeleton from “Debugging Declaration ROMs” in the first issue of develop, available on the latest Developer CD Series disc. It would take very minor tweaking to work in your system.
Devices & Hardware: Slot Manager: Installing a Macintosh VBL task for on-board video
Installing a VBL task doesn’t seem to work on Macintosh systems with on-board video. I get the slot number for a video card by extracting the second nibble of the base address of the screen’s PixMap; however, on-board video computers report that the video card is in slot $B but the video card doesn’t seem to exist in any slot. Is there a better way to determine video card slot number? Is there any way to attach a VBL task to on-board video? How can I determine if the main monitor is using on-board video?
You should be getting the slot number for the video, not from the base address of the PixMap, but from the AuxDCE entry (IM V-424). You’ll need to get the gdRefNum for the desired monitor from the device list (IM V, Chapter 5).
For example, to install a VBL for the main screen, do something like this:
GDevHand := GetMainDevice;
IF GDevHand = NIL THEN BEGIN WriteLn(’no main device!’); HALT; END;
mainGDRefNum := GDevHand^^.gdRefNum;
DCEHand := AuxDCEHandle(GetDctlEntry(mainGDRefNum));
IF DCEHand = NIL THEN BEGIN WriteLn(’GetDctlEntry failed’); HALT; END;
retCode := SlotVInstall(@myVBLTask, DCEHand^^.dCtlSlot);
IF retCode <> noErr THEN WriteLn('SlotVInstall failed');
This should work regardless of the kind of video used.
Devices & Hardware: Slot Manager: Macintosh LC “Sad Mac” error code 0000000F 00000033
What is a Macintosh® LC “Sad Mac” error 0000000F 00000033?
This Macintosh LC error code means “unserviceable slot interrupt”—that is, a slot interrupt occurred but the Slot Manager was unable to find an interrupt service routine that would handle the interrupt. This might occur if the primary initialization (PrimaryInit) code for a card fails to establish an interrupt handler for the card but enables interrupts for the slot containing that card anyway.
Devices & Hardware: Slot Manager: Detecting a NuBus or PDS card in the Macintosh IIsi slot
Why does a call to gestaltNuBusConnectors return zero slots when there actually is a NuBus™ card or a PDS (Processor Direct Slot) card in the Macintosh® IIsi slot?
A call to gestaltNuBusConnectors returns zero slots because there’s no way to determine if there’s a NuBus card or a PDS card in the Macintosh IIsi slot. Gestalt can’t assume that there’s always a NuBus or PDS slot, so it just says there’s no slot. However, Apple recommends that you always use the Slot Manager instead of Gestalt to search for cards, after first checking to see that the Slot Manager trap is implemented. The Slot Manager will safely do all the necessary work for you whether a card with a valid declaration ROM is installed or not, and you can search for the card using a variety of criteria. This technique will allow you to locate NuBus cards, but has the added benefit of being able to find PDS cards that contain declaration ROMs.
The Macintosh SE/30, IIfx, and LC have the Slot Manager and PDS slots. It’s safe to assume the Slot Manager will be resident in all future machines that have either NuBus or PDS slot capability.
Devices & Hardware: Slot Manager: NuBus board configuration ROMs and IDs
I am making a NuBus board and I don’t think that I need a configuration ROM. Do I need to build a configuration ROM? If so, how do I get the SResource board ID? Why should board manufacturers have configuration ROMs?
Technically, you don’t need one, but if you don’t have at least a minimal configuration ROM (also known as a declaration ROM), you can’t use the library of Macintosh® Slot Manager calls.
Developer Technical Support assigns the board IDs (and sRsrc_Type IDs). These exist in order for your card to tell the world what functions your board can perform. In order for DTS to assign these values, you need to provide certain information about your board and your company. There is a HyperCard® stack published by DTS that allows you to enter the required information (it also has a tutorial that explains the Slot Manager and configuration ROM concepts in more detail).
A configuration ROM is desirable for flexibility. The combination of the Slot Manager and configuration ROM exists to locate and identify your expansion card and allow the computer and higher-level applications and drivers to communicate with it.
To better understand this, let’s look at the Slot Manager in more detail, and see why it is desirable for you, the developer, to take advantage of it.
The Slot Manager/configuration ROM architecture has two main functions. The first is to provide a mechanism to allow the user to insert a card in a slot and have the card be operational without having to set any switches, worry about which slot to put the card in, or install any special software.
The second is to free an application from being dependent on a particular type of hardware. That is, the goal is to allow an application to be insulated from the hardware by being able to locate underlying, intermediate driver software that will “know” about and talk to the specific hardware. This frees the application to be able to deal with higher-level functions without being tied to a given set of hardware. It allows for different revisions of a given card, or even cards made by different vendors to work with applications, without requiring a revision of the application each time a card changes (or a new one is introduced).
Both these goals are accomplished via the Slot Manager software and the firmware data structures contained in the configuration ROMs of each card. If a valid configuration ROM is present, system software as well as applications and drivers can take advantage of the Slot Manager library of routines to perform the two functions stated above.
Let’s examine the architecture and concepts further.
The specific functions of the Slot Manager are as follows:
Locate and list the cards with configuration ROMs (also known as
declaration ROMs); Impose a uniform structure on the information
in the declaration ROM and provide a set of library routines to
access the information. One major advantage of this is that once
certain sets of data structures are defined and made public, host
applications may use information contained in the structures on
any card regardless of vendor;
Provide routines to allow host applications to transparently access
information in the ROMs without regard to NuBus or byte lanes;
Provide a mechanism for cards to have initialization code run on the
host CPU during the host’s startup sequence;
Allow cards to have drivers in their declaration ROMs loaded into
the host CPU;
Initialize and manipulate the parameter RAM on the host CPU for the
card in the slot during startup.
Without a configuration ROM, most of this will be impossible. Locating the card will be difficult. You can’t ask the customer where it is, without violating the user-friendly interface of the Macintosh, and you can’t find it with software without the possibility of stepping on other cards’ registers, memory, and so on, not to mention having to deal with bus errors for empty slots. Configuration ROMs are well defined in terms of location in the slot address space and structure. Getting at stored nonvolatile data on the board will probably be different for each card. Having code and or drivers loaded and executed at startup time will not be possible.
In summary, you should make a configuration ROM, and use the Slot Manager. It will provide services to applications (and drivers) accessing the card, and will mean less maintenance for applications and drivers.
Devices & Hardware: Slot Manager: Ghost image when scanning Macintosh IIfx slots with the Slot Mgr
When I scan the Macintosh® IIfx slots with the Slot Manager I find a ghost image of a card in slot 1. Am I doing something wrong, or is this a bug?
This is a bug in the Macintosh IIfx Fast Memory Controller (FMC), but it should not cause you any problems.
Devices & Hardware: Storage Devices: Disk First Aid checks native HFS structures, not file contents
What does Disk First Aid check in the Macintosh System, desktop, and other files to determine that they are invalid? Does it check the resources, the resource map, or something else?
Disk First Aid doesn’t check the system or desktop files at all; it treats all files the same without examining their contents. The only things it does check are the native HFS structures, such as the catalog and extents b- trees, and the volume bitmap.
Devices & Hardware: Storage Devices: Macintosh csCode 100.
What is csCode 100? A control call with csCode 100 seems to come in to my block device driver whenever the Macintosh system fails to recognize the file system on my media. Should my driver specify valid non-HFS formats such as ISO 9660?
The csCode 100 you’re seeing is a ReadTOC command bound for what the operating system thinks is a CD-ROM drive. What’s happening here is that after deciding your device doesn’t contain a HFS partition, Foreign File Access (FFA) is attempting to identify the file system residing on that device; looking at the Table of Contents on a CD is one of the ways that it attempts to go about that. You can find this csCode documented in the CD SC Developer’s Guide which is currently available through APDA.
If you remove the Audio CD FST from your system folder, you’ll find that csCode no longer gets issued. The reason for this is that the ReadTOC call returns information about Audio CDs. Your driver need not even support this call; if FFA sees a paramErr (which you should return upon seeing an unrecognized csCode) it knows it can’t be looking at an audio CD.
You need not worry about adding any support to your driver for ISO 9660 or High Sierra. FFA’s File System Translators will just request certain blocks from your driver which contain information that identify the disk in question as ISO or HFS.
Devices & Hardware: Storage Devices: Apple IIGS and third-party SCSI disk drives
Do third-party generic SCSI drives work with the Apple IIGS® and the Apple II High-Speed SCSI Card? What sort of formatting/partitioning software do I need?
You should be able to hook up almost any SCSI device to the Apple IIGS® using the Apple II High-Speed SCSI Card. As long as it’s a standard SCSI device, it should work fine. As for disk utilities, you should use the Advanced Disk Utilities that come with the latest version of the IIGS system software. Before purchasing a particular third-party hard disk for your Apple IIGS, ask your distributor about compatibility.
Devices & Hardware: Storage Devices: Low-power hard drive requirements for Macintosh Portable
We can’t get some internal hard drives to work in the Macintosh® Portable.
We think this is a power draw problem. The Macintosh Portable drive needs to be a low-power drive. According to the “Macintosh Portable Developer Notes,” power requirements are as follows:
Voltage: 12 Vdc and 5 Vdc with ±5% tolerance
Voltage ripple to be ≤100 mv
Current (Amps): Currents drawn must be less than or equal to the values shown below.
DC Current: 5 Vdc 12 Vdc
Peak Max(rms) Typ(rms) Peak Max(rms) Typ(rms)
Startup (<5 sec) 1.5 1.1 1.0 .8 .56 .53
Seeking (<100 ms) 1.5 1.1 1.0 .44 .31 .28
Read/write TBD TBD .45 .65 .46 .42
Standby (spindle on) TBD TBD .25 .15 .11 .10
Autoshutdown
(spindle off) TBD TBD .16 TBD TBD .06
Note also that the Portable must have the battery installed; the adapter alone can’t spin a drive. Also the drive must be at SCSI ID 0 and the time-out value has to be sufficient to allow the drive to come up (you can look at the values and set them with GetTimeOut and SetTimeOut which are documented in Inside Macintosh Volume V, page 356). If this doesn’t solve the problem, then it’s possible there may be a SCSI termination problem.
Graphics, Imaging & Printing: Color Manager: Color Manager search and complement procedures
The AddComp complement procedure description in Inside Macintosh Volume V, pages 145-147, is vague. The last paragraph on page V-146 states, “Complement procedures work the same as search procedures,” but SearchProc is a function, CompProc is a procedure, and each have a different number of parameters. What else does CompProc need as input and on exit?
CompProc should be declared as a FUNCTION that returns a Boolean. The code performs a CLR.B for the return value of CompProc, so treat it like SearchProc. CompProc only uses one parameter since its one parameter is a VAR, which means it will be replaced with the correct complementary color. SearchProc returns an index in its second parameter, which is why it needs a second parameter.
Graphics, Imaging & Printing: Fonts: Apple IIGS FixFontMenu and NDAs
When I call FixFontMenu from my Apple IIGS new desk accessory (NDA), everything works fine, but if the current application has a font menu it stops working. What’s wrong?
FixFontMenu keeps only one correspondence between menu item IDs and font family numbers—if you call FixFontMenu from an NDA, you blow away the already existing correspondence that the application was using, maintained within the Font Manager. ItemID2FamNum then works only on item IDs corresponding to your NDA’s font menu, and these usually are unrelated to the values the application passes from its font menu. Worse, FamNum2ItemID will subsequently return menu item IDs for font family numbers that have nothing to do with the application’s menus; depending on how the application operates on the resulting item ID, this could be disastrous.
Fortunately, doing this yourself is fairly easy with the Font Manager’s help. CountFamilies tells you how many font families there are, and FindFamily returns the name of each of them. You can manipulate this information into a font menu in a fairly straightforward way, using standard Menu Manager calls. While you’re at it, you can also use FindFontStats to figure out what point sizes and styles are available for each font family, so you can indicate this in your Size and Style menus. You could even use the information to build your own font-choosing dialog, much as HyperCard IIGS does. Remember that your NDA should run in either 320 or 640 mode, so don’t make the dialog box too wide.
Graphics, Imaging & Printing: Fonts: FScaleDisable and Macintosh screen rendering
What is the current interface guideline on font scaling? Should we set FScaleDisable to true or false for screen rendering? I believe the old guideline was to set it to true (thus disabling font scaling) so that if you have a 23 pt screen font you will see 12 pt glyphs with 23 pt widths. We want performance on Apple’s low-end machines, and we don’t want to make this a user preference.
Most applications now set FScaleDisable to false all the time. If you are worried about the speed degradation in your application when running on slower Macintosh systems, you could have your software identify which Mac it is running on using Gestalt, SysEnvirons, etc., and then set FScaleDisable to true only on the slow machines. From the purely interface point of view, “what-you-see-is-what-you-get” is best, if processor speed allows it.
With TrueType there is no issue, since FScaleDisable doesn’t have any effect on an outline font.
Graphics, Imaging & Printing: Fonts: Remapped keys for System 7
Remapped keys for System 7
The System 7 keyboard map has changed for the following 11 keys:
Shift-Option-` Shift-Option-M Shift-Option-V
Shift-Option-E Shift-Option-N Shift-Option-X
Shift-Option-G Shift-Option-R Shift-Option-Z
Shift-Option-I Shift-Option-T
The remapping is not a bug; it’s the result of conscious decisions, taken with the consideration of the advantages and disadvantages of changing the 'KCHR' key-mapping resource (this is where the change did in fact occur). The opt- shift-e and opt-shift-u characters, for example, were changed to create the lone representations of their dead key equivalents, opt-e and opt-u or ´ and ¨. Opt-shift-` now returns the character marked on the key, `, rather than the bunny rabbit symbol you used to get (with Geneva, at least). These were deemed more logical mappings.
Your application shouldn’t attempt to depend on key-to-character mappings, because they can change from version to version and they definitely change from country to country.
X-Ref:
Inside Macintosh, Volume VI, page 14-97
Graphics, Imaging & Printing: Fonts: System 7 reserved fonts
Which are the reserved fonts for System 7 and international versions?
All Macintosh system software—including System 7 and international versions— contains four basic fonts, all of them bitmapped: Chicago (12 point), Geneva (9, 12), and Monaco (9). In fact, these fonts cannot even be removed with Font/DA Mover. All systems normally contain other font families, and international versions with multiple script systems contain special font sets. For example, Hebrew system software uses Elath and Hermon.
As of September 1991, System 7 ships in the United States with nine standard font families: Chicago, Courier, Geneva, Helvetica, Monaco, New York, Palatino, Symbol, and Times. Eight of these include TrueType versions: Chicago (plain), Courier (plain, bold), Geneva (plain), Helvetica (plain, bold), Monaco (plain), New York (plain), Symbol (plain), and Times (plain, bold, italic, bold-Italic). Of course, there is no guarantee that users will keep all these fonts in their systems.
X-Ref:
“Guide for Software Localization” beta draft (APDA #M1528LL/A)
Graphics, Imaging & Printing: Fonts: Creating fixed fractional width fonts with ResEdit
How do we create a “fixed fractional width” font using ResEdit 2.1. I tried setting FontInfo fields such as ascent and widMax with fractional numbers, but ResEdit refused all noninteger numbers.
ResEdit doesn’t know how to take fixed-point numbers as input, so it assumes the number you enter for a value like WidMax is the integer representation of the fixed-point number. In other words, ResEdit displays a 16-bit fixed-point number as an integer with 256 times the value of the fixed number actually used by the Font Manager.
To enter the numbers with ResEdit, you’ll need to do the conversion yourself. Take a 8.8 fixed number and multiply by 256 to get the integer to type in, or take a 4.12 fixed number and multiply by 4096 to get the integer.
This rigamarole occurs because ResEdit wasn’t really designed to build fonts from scratch. You may find that certain third-party tools, such as Fontographer (from Altsys) or FontStudio (from Letraset), which are specifically designed to this task, may be easier for you. The time you save in building your width table may be worth the cost of the program.
Graphics, Imaging & Printing: Fonts: Five font style-mapping table styles
Why is “47” the bounds of the indexes’ array in the StyleTable?
The style-mapping tables, which are used for mapping of a font style to a particular font for printing, have only five possible styles, unlike the six screen styles (underline is omitted, since a laser printer just explicitly draws a line under the string—it doesn’t need a special font for that). You can have any combination of these five styles, EXCEPT that you can’t have “Condense” and “Extend” at the same time (Condensed Extended wouldn’t make a whole lot of sense). Thus you get (combinatorics come back to haunt us) 48 possible unique styles to map to.
X-Ref:
Chapter 2, “Working with Fonts,” LaserWriter Reference (Addison-Wesley; APDA #M7073, $19.95).
Graphics, Imaging & Printing: Fonts: 'FOND' resource features subject to change
Which 'FOND' features are subject to change, and what parts can I rely on?
'FOND' features not documented in Inside Macintosh, Macintosh Technical Notes, or develop are subject to change. That’s the official word.
Graphics, Imaging & Printing: Fonts: System 7 and modified fonts
We ship modified versions of the Chicago and Geneva fonts and their fonds in our application’s resource fork. With System 6, when we ask for font 0 or font 3, we get our modified fonts in windows, buttons, menus and dialogs, but not with System 7. Is there a new way to tell System 7 to use my version of Chicago 12 to display all system related stuff?
What’s happened is that the system software is being much more strict about whose “Chicago” it uses for menus and dialogs. The Menu and Control Managers now only look at the system file for the Chicago they use.
There are a couple of ways to get around this: First, you can try patching DrawString right before calling MenuSelect in your program. The patch would select your Chicago and then jump to the standard DrawString. After MenuSelect, remove the patch. The disadvantage of this method is that, if a future system software release doesn’t use DrawString for drawing menus, the patch would cease to have any effect.
A better solution is to write your own menu and control definition code—in other words, your own custom MDEF and CDEFs. The way you typically do this is to get a copy of the standard Macintosh system’s MDEF or CDEF, and alter it to your specifications. In your case, this would be merely selecting your font instead of the system font. Name your font something other than Chicago and just select that font by name in the menu or control’s draw routine. The Control and Menu Manager chapters in Inside Macintosh Volume I have more information on writing custom definitions. There is only one problem with this right now: While the System 6 MDEF and CDEF are available on AppleLink, the System 7 versions are not available yet, although they will be soon.
A note on the use of Chicago in your application: As the June 1991 edition of Macintosh Technical Note #245 mentions, fonts are copyrighted material. Apple owns the Chicago font and typeface, so be sure you check into licensing issues before releasing any version, altered or unaltered, with your application.
Graphics, Imaging & Printing: Graphics Devices Manager: Determining video RAM size
How can we determine how much video memory is available to us to use on any given Macintosh? We need to determine how much memory is on plug-in video cards and how much memory is allocated for built-in screen video at system startup.
Video memory is not for your use! <grin> What you are asking is how to find the total physical memory on the board or allocated. There is no method to deterministically find this out. Each video board manufacture provides a driver that knows how to interact with QuickDraw and has its own special knowledge of how much memory is on board or how to test for how much is installed. Without this special knowledge you will not be able to tell where the memory starts (some start on other than even megabyte boundaries) or if the RAM image wraps over and over throughout the address space. Some areas of the memory may be set aside for other controlling data and your attempt to use this space will disable the proper functioning of the board. The same applies to built-in video.
Graphics, Imaging & Printing: Palette Manager: SetPalette cUpdates, NSetPalette, and window update events
When I pass false in the cUpdates parameter to SetPalette, I still get update events to that window when I modify its palette. What’s going on?
SetPalette’s cUpdates parameter controls whether color-table changes cause that window to get update events only if that window is NOT frontmost. If that window is frontmost, then any changes to its palette causes it to get an update event regardless of what the cUpdates parameter is. When you call SetEntryColor and then ActivatePalette for your front-most window, it gets an update event because it’s the front-most window even though you passed false in the cUpdates parameter. Another important point is that windows that don’t have palettes also get update events even when another window’s palette is activated.
Fortunately, system software version 6.0.2 introduced the NSetPalette routine, which you can find documented in Macintosh Technical Note #211, “Palette Manager Changes in System 6.0.2,” and on page 20-20 in the revamped Palette Manager chapter of Inside Macintosh Volume VI. This variation of SetPalette gives you a lot more flexibility in controlling whether your window gets an update event than SetPalette does. If you pass pmAllUpdates in the nCUpdates parameter, then that window gets an update event when either it or another window’s palette is activated. If you pass pmFgUpdates, then it gets an update event when a palette is activated only if it’s the front-most window (in effect, it only gets an update event if its own palette is activated). If you pass pmBkUpdates, then it gets an update event when a palette is activated only if it’s not the front-most window (in effect, it only gets an update event if another window’s palette is activated). If you pass pmNoUpdates, then that window never gets an update event from any window’s palette being activated, including that window itself.
Graphics, Imaging & Printing: Palette Manager: Restoring Finder desktop colors after using Palette Manager
After using the Macintosh Palette Manager, how do I restore the Finder’s desktop colors?
The Finder desktop’s colors are restored automatically on quitting applications that use the Palette Manager. Colors aren’t restored automatically when switching from your application to another, but if that application needs a certain set of colors and uses the Palette Manager to get them, then it’ll have them the moment it comes to the front. If you’re concerned about applications that don’t use the Palette Manager, you can use RestoreDeviceClut(gd:GDHandle), passing the handle to the GDevice of the screen you want to reset, or nil if you want to reset all of your devices. Passing nil to RestoreDeviceClut is your best bet, as it is very straightforward, and resets all of your monitors. You may not wish to do this, however, because RestoreDeviceClut is only available on machines with 32-bit color QuickDraw.
To reset a screen’s GDevice for machines without 32-bit color QuickDraw, you will need to keep track of the color table.When your application starts up, get the GDevice’s color table and save it—you’ll need it later. This value can be found at (**(**GDHandle).gdPMap).pmTable, where gdPMap is a PixMapHandle, and pmTable is a CTabHandle which tells you the absolute colors for this image. These data structures are found in Inside Macintosh Volume V, pages 52 and 119.
Build your application’s “world” using the Palette Manager, and avoid low- level methods of changing colors. When your application is about to quit and you want to restore the environment to its original state, get the color table you saved in the beginning. Convert this to a palette using CTab2Palette. Then set your window to this palette with SetPalette. This will cause the environment to update to the original color table that you initially got from the GDevice. If the application that is behind your application is Palette Manager friendly, then it will restore the environment to its palette. You may also want to do this procedure at the suspend event, as shown in the DTS sample MacApp program, FracApp. One of the problems that you won’t be able to solve this way involves multiple monitors. You won’t know which one to update. Only the monitor that has the window that you’ve called ActivatePalette on will update.
If your application changes the color environment with the Palette Manager, then RestoreDeviceClut is called automatically when your application quits. This means that you shouldn’t have to worry about restoring the palette if you don’t want to. There is a catch, however (there always is). When you use the SADE version of MultiFinder (6.1b9), it prevents this from automatically happening. Other versions of MultiFinder don’t have this side effect.
Graphics, Imaging & Printing: Palette Manager: RestoreDeviceClut and color flash when application quits
When my application, which uses a color palette, quits, there is momentary but distracting flash of weird colors in the Finder windows and the desktop temporarily appears in a weird color. Is there any way to get around this?
When you quit, RestoreDeviceClut is called to restore the color table and an update event is called to redraw the screen. It’s the delay between the change in the color table and the update event that causes the flash of incorrect colors to be displayed. This, unfortunately, is unavoidable.
Graphics, Imaging & Printing: Picture Utility Package: Spooling PixMaps to disk
Do you have sample code for spooling PixMaps to disk in PICT format? Should I write the PICT opcodes to the file myself?
Apple recommends that you do not try to write the PICT opcodes yourself. Instead, replace the PutPicProc bottleneck proc, as shown in the Color QuickDraw chapter of Inside Macintosh Volume V on page V-89.
Two additional samples can be found in the sample code contained in the Developer CDs. Look for: “Tools & Apps (Moof!): Graphics and Imaging: PICT Stuff.” One is a program and the other is an FKEY; both dump the main screen to disk as a PICT. The FKEY is a more complete sample in the sense that it works in black and white as well as Macintosh color computers, but the other is a smaller and simpler sample.
Graphics, Imaging & Printing: Printer Drivers: Changing printer driver settings without using the dialog
Changing printer driver settings without using the dialog
To change default printer driver settings without using the dialog, keep a copy of the print record with the various settings you want, and when you want to choose your settings, just use your special print record. The current Macintosh print architecture doesn’t allow procedural access to the print record, so you must call the dialogs once for yourself, choose your settings, and then save a copy of the print record that is produced. Some settings are job-dependent, but values that are retrieved from the print record can be changed using this technique. You can only save the settings in the Style dialog. Call PrValidate when retrieving a print record from the resource fork to make sure it is “good.”
See develop, issue #1, pages 58-65, for a complete discussion of changing default printer driver settings and sample code.
Graphics, Imaging & Printing: Printer Drivers: Printing 2-byte bitmap fonts on PostScript LaserWriters
Macintosh Technical Note #91 refers to using QuickDraw picComments to print rotated text, but this doesn’t work for 2-byte Japanese text. Is there a recommended workaround for this problem?
Two-byte characters don’t print when using the TextBegin, TextCenter, and TextEnd PicComments because of the structure of the data that is being sent in the comments. The LaserWriter driver uses these PicComments to rotate text, and it is not expecting the data to be in the 2-byte format. The 2- byte format is converted to bitmap data by the driver, so the data is ignored and nothing is printed. The driver is expecting the comments to contain “normal” text.
Since the data is in bitmap format, you can use the RotateBegin and RotateEnd PicComments to perform the rotation, as follows:
RotateBegin
DrawString (...); << To rotate your 2 byte Japanese characters
RotateEnd
The tricky part of the solution is that you only need to use this approach when you’re printing 2-byte Japanese bitmap fonts. Therefore, you’ll need to check the type of data that is to be printed, and send the appropriate PicComments.
You can also use the following PicComments to hide the QuickDraw representation of the rotated text, as shown below:
PostScriptBegin
CopyBits (...); << For the QuickDraw printers
PostScriptEnd
The PostScriptBegin and PostScriptEnd PicComments are used to hide the CopyBits calls from the LaserWriter driver in a device-independent manner. When you use PostScriptBegin, the LaserWriter driver doesn’t interpret any QuickDraw calls until it finds the PostScriptEnd PicComment. Since QuickDraw printer drivers do *not* understand the PostScriptBegin and PostScriptEnd PicComments, they ignore the PicComments, and the CopyBits call is used to perform the rotation of your text.
There is one problem with the previously mentioned solution: If you record the previous PicComments into a picture and print it, everything will print exactly as expected, but if you display the picture into a window, you’ll see the *unrotated* version of the text. This is definitely a bug, which has been reported, but it won’t be fixed in the very near future. So, what do you do in the meantime? You have the following two options:
1) Do not export pictures that contain this type of rotated data.
2) Export the picture with this problem, and explain the problem to your users.
Neither solution is ideal. Quite a few applications out in the market today have decided to use idea #2.
Graphics, Imaging & Printing: Printer Drivers: Use LaserWriter Driver srcCopy instead of srcOr transfer mode
I’m creating PICTs that are comprised of many lines drawn in srcOr mode. When using the LaserWriter 6.x or 7.x driver with the Color/Grayscale radio button selected, some lines fail to print. Why is this happening?
The problem is a bug in the LaserWriter driver. Sometimes, when using a CGrafPort, the driver doesn’t reproduce lines drawn in srcOr mode. (A CGrafPort is used when the Color/Grayscale print option is selected; in Black & White print mode, a regular grafPort is used.) A workaround is to use srcCopy instead of srcOr when drawing QuickDraw objects within your PICTs.
Graphics, Imaging & Printing: Printer Drivers: LaserWriter ignores ForeColor while filling smoothed polygon
When doing the FillRgn for drawing the fill of a smoothed polygon (as described in Macintosh Tech Note #91) the foreColor isn’t used on the LaserWriter. Any way to make it work?
You’ve discovered a design limitation of the LaserWriter driver. Things that have patterns associated with them are rendered by using the LaserWriter screen operators. This results in an assumption of the foreground color being black and the background color being white, which is what’s causing the problem you noticed. In short, it makes the driver ignore your foreground and background colors.
You can work around the problem by working in an offscreen GWorld first and then CopyBitsing everything to the printer port using srcCopy. There are a couple of problems with this approach: First, don’t do it with text or your text will be turned into a bitmap and you’ll get the “jaggies.” Second, you’ll probably want to increase the printer port’s resolution from its default of 72 dpi for better results. A value of 288 dpi works nicely since it’s an even multiple of QuickDraw’s native 72-dpi resolution. Also, make sure that the GWorld you create has the same bounds as the printer port’s rPage rectangle to avoid unnecessary scaling and clipping. After you’ve done all that, draw into it and CopyBits the result to the printer port. The nice thing about doing everything offscreen first is that then you can use some of the non-printer- friendly transfer modes like blend or dithered. Also, you can use ForeColor/BackColor and get the right thing this way.
If you don’t want to use this method for all printers, (since it can be quite a memory hog), you can check for the LaserWriter driver and use this method in just that case. For other drivers, you should just print as normal.
So, what do you need to do all this? Well, to set the resolution of the printer port, use PrGeneral as described in Inside Macintosh Volume V and develop #3.
To determine whether you have the LaserWriter driver or not, check the high byte of the wDev field in your print handle. This is described in Tech Note #72. While this method might break some day, it’s currently the best way to determine which driver you’re using, and Apple will have to let developers know before we break it.
If the high byte of the wDev is 3, then you either have the LaserWriter driver or a third-party driver impersonating the LaserWriter. Some PostScript drivers do that because many apps assume a wDev of 3 means a PostScript printer, and anything else doesn’t. By acting like Apple’s LaserWriter driver, they get preferential treatment from apps that “special case” for PostScript. That’s not really a problem in this situation.
Graphics, Imaging & Printing: Printer Drivers: Asynchronous LaserWriter driver no longer supported
What is causing incorrect characters to be printed on the Asynchronous LaserWriter driver we licensed from Apple for use with a non-Apple PostScript- equipped printer?
The printing of incorrect characters is probably due to an incompatibility between the async driver and the version of PostScript being used in the printer.
The reason for the incompatibility is that the driver is no longer supported and hasn’t been revised for quite some time. The driver was originally developed outside of Apple, and Apple licensed the driver for its use. The company subsequently went out of business and the driver hasn’t been revved since.
PostScript and Apple’s AppleTalk LaserWriter drivers have been updated and changed quite a bit since then, which is why the characters print correctly when using AppleTalk, but not when printing asynchronously. The old Async driver just doesn’t know how to handle the new PostScript versions and therefore prints “garbage” characters.
The SL Laser II driver is no longer supported by Apple, and at this time Apple has no plans to update this driver or write a new one. Since things work correctly with AppleTalk, you should confine usage to AppleTalk when printing PostScript to the LaserWriter. If this is unacceptable, you might check around with different clearinghouses to see if a third-party developer has a compatible, up-to-date Asynchronous LaserWriter driver that you can use.
Graphics, Imaging & Printing: Printer Drivers: LaserPrep 7.0 file & AppleShare Print Server
LaserPrep 7.0 file & AppleShare Print Server
The LaserPrep 7.0 file is included on the System 7 “Printing” disk and the System 7 Group Update CD for upgrading the AppleShare Print Server to support the LaserWriter 7.0 driver. The AppleShare Print Server has its own LaserWriter driver built in and all it needs to print is a LaserPrep file. In fact, the AppleShare Print Server completely ignores any LaserWriter driver installed in the System Folder of the server.
Page 49 of the “System 7 Group Upgrade Guide” states the following procedure for upgrading an AppleShare Print Server to support the System 7 LaserWriter drivers:
1. Shut down the print server software.
2. Install the printer driver update…
3. Drag the LaserPrep icon from the Printer Update folder to the Server Folder of the print server Macintosh®.
4. Restart the print server Macintosh and the AppleShare Print Server software.
Actually, step #2 in the “System 7 Group Upgrade Guide” is unnecessary. Installing the printer driver update has no effect on the AppleShare Print Server software.
Graphics, Imaging & Printing: Printer Drivers: LaserWriter 7.0 driver and LaserPrep dictionary
In the old LaserWriter drivers it was possible to create a PostScript file with or without the LaserPrep dictionary (“f” or “k” key). Is it possible to generate a file without the dictionary with the LaserWriter 7.0 driver?
In 7.0 printing, a LaserPrep dictionary is always sent with a print job. This is done to prevent constant reinitialization of the LaserWriter by conflicting printer drivers. You cannot prevent it from being sent. Fortunately the 7.0 version of the LaserPrep dictionary is much smaller (≈40K total) than its 6.x predecessors.
Graphics, Imaging & Printing: Printing: ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
If an application uses PrGeneral to set draftBits mode on an ImageWriter II (using the 6.1 or 7.0 drivers) and then does a PrStlDialog, a fatal crash occurs. This happens with both the AppleTalk and non-AppleTalk drivers. This only happens on Macintosh systems with Color QuickDraw.
The problem is connected to the two 'dctb' resources which were added in the 6.1 driver. When the landscape icon is being grayed out (since it’s unsupported in draftBits mode), the driver is jamming the gray pen pattern directly into the GrafPort. While this brute-force method works fine with GrafPorts, the 'dctb' resources make the Dialog Manager use a CGrafPort now. Jamming the pattern into this CGrafPort as if it were a GrafPort makes a mess and causes a fatal crash, manifesting itself as a “division by zero” error, for example.
To work around the problem, check to see if you are printing to a 6.1 or 7.0 ImageWriter driver, and if so, do the style dialog before setting draftBits. The disadvantage of this is that setting draftBits before calling PrStlDialog causes the 50% reduction and landscape controls to be disabled, and this method doesn’t. Therefore, after the style dialog, you should check to see if the user selected landscape printing or 50% reduction by calling PrGeneral (getRotnOp) and checking bit 3 of the wDev field (See “Learning To Drive” on the Developer CDs for more about the wDev.) If the user selected either of those options, display a dialog warning them that those features will be ignored. Then, call PrGeneral to set draftBits and continue normally. PrGeneral will adjust the print record so that options not supported with draftBits are turned off. If a non 6.1/7.0 ImageWriter driver is used, the code should set draftBits as usual, before the PrStlDialog call.
This workaround is the better alternative to hacking the 'dctb's out of the driver or patching around the problem, although it doesn’t help 7.0 users running applications that already make use of the draftBits option. The following Pascal snippet demonstrates how to use the workaround:
(* Sample snippet that demonstrates how to work-around the
'dctb' bug in the ImageWriter II 6.1 and 7.0 drivers.
Bug causes a crash when doing a style dialog
after setting draftbits with PrGeneral.
*)
{
What's what in the code snippet that follows.
thePrRecHdl : THPrint;
rslData : TSetRslBlk;
draftData : TDftBitsBlk;
rotnData : TGetRotnBlk;
isBadImageWriter : Boolean;
isLandscape : Boolean;
isReduced : Boolean;
}
PrOpen;
IF (PrError = noErr) THEN
BEGIN
PrintDefault(thePrRecHdl);
IF (PrError = noErr) THEN
BEGIN
{See if we're using a version 6.1 or 7.0 ImageWriter driver.}
IF (thePrRecHdl^^.prStl.wDev DIV 256) = 1 THEN
isBadImageWriter := (PrDrvrVers = 61) OR (PrDrvrVers = 70)
ELSE
isBadImageWriter := FALSE;
IF NOT (isBadImageWriter) THEN
BEGIN
{Set draftBits mode now, if not our special case.}
draftData.iOpCode := draftBitsOp;
draftData.hPrint := thePrRecHdl;
PrGeneral(@draftData);
END;
{Do the style dialog.}
IF (PrStlDialog(thePrRecHdl)) THEN
IF (isBadImageWriter) THEN
BEGIN
{If so, see if they selected rotation or 50% reduction.}
rotnData.iOpCode := getRotnOp;
rotnData.hPrint := thePrRecHdl;
PrGeneral(@rotnData);
isLandscape := rotnData.fLandscape;
isReduced := BTst(thePrRecHdl^^.prStl.wDev, 3);
{If so, warn them that those things will be ignored.
Preferably use something other than DebugStr… }
IF (isLandscape) OR (isReduced) THEN
DebugStr('Bad ImageWriter; landscape and/or reduced.');
{Now, set draftBits mode, since we didn't before.}
draftData.iOpCode := draftBitsOp;
draftData.hPrint := thePrRecHdl;
PrGeneral(@draftData);
END;
IF (PrJobDialog(thePrRecHdl)) THEN
BEGIN
{Print}
END;
END;
END;
PrClose;
Graphics, Imaging & Printing: Printing: How to abort printing while PrPicFile is executing
Can I abort printing from within PrPicFile? My attempts haven’t been succesful.
The following Pascal procedure is *roughly* the same as the default idle procedure—the one the system supplies for you when you don’t supply one of your own:
procedure MyPIdleProcedure;
var
pIdleEventRecord: EventRecord;
begin
if GetNextEvent(keyDownMask, pIdleEventRecord) then
begin
if ((BitAnd(pIdleEventRecord.message, charCodeMask) =
longint('.')) and
(BitAnd(longint(pIdleEventRecord.modifiers), cmdKey) =
cmdKey)) then
PrSetError(iPrAbort);
end;
end;
(This is written in Think Pascal, but it should work fine under MPW Pascal if you change the “BitAnd” functions to “BAND”.)
As you can see, the system aborts when you press Command-period by using PrSetError to the constant iPrAbort, which is the same error returned when the user clicks “Cancel” in the style or job dialogs. If you set the error to iPrAbort, the system will take care of the rest. Your print loop will also gracefully cancel, provided you follow the guidelines in Macintosh Technical Note #161, “A Printing Loop That Cares.”
Graphics, Imaging & Printing: Printing: ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
ImageWriter II 6.1 & 7.0 driver PrGeneral/PrStlDialog bug
If an application uses PrGeneral to set draftBits mode on an ImageWriter II (using the 6.1 or 7.0 drivers) and then does a PrStlDialog, a fatal crash occurs. This happens with both the AppleTalk and non-AppleTalk drivers. This only happens on Macintosh systems with Color QuickDraw.
The problem is connected to the two 'dctb' resources which were added in the 6.1 driver. When the landscape icon is being grayed out (since it’s unsupported in draftBits mode), the driver is jamming the gray pen pattern directly into the GrafPort. While this brute-force method works fine with GrafPorts, the 'dctb' resources make the Dialog Manager use a CGrafPort now. Jamming the pattern into this CGrafPort as if it were a GrafPort makes a mess and causes a fatal crash, manifesting itself as a “division by zero” error, for example.
To work around the problem, check to see if you are printing to a 6.1 or 7.0 ImageWriter driver, and if so, do the style dialog before setting draftBits. The disadvantage of this is that setting draftBits before calling PrStlDialog causes the 50% reduction and landscape controls to be disabled, and this method doesn’t. Therefore, after the style dialog, you should check to see if the user selected landscape printing or 50% reduction by calling PrGeneral (getRotnOp) and checking bit 3 of the wDev field (See “Learning To Drive” on the Developer CDs for more about the wDev.) If the user selected either of those options, display a dialog warning them that those features will be ignored. Then, call PrGeneral to set draftBits and continue normally. PrGeneral will adjust the print record so that options not supported with draftBits are turned off. If a non 6.1/7.0 ImageWriter driver is used, the code should set draftBits as usual, before the PrStlDialog call.
This workaround is the better alternative to hacking the 'dctb's out of the driver or patching around the problem, although it doesn’t help 7.0 users running applications that already make use of the draftBits option. The following Pascal snippet demonstrates how to use the workaround:
(* Sample snippet that demonstrates how to work-around the
'dctb' bug in the ImageWriter II 6.1 and 7.0 drivers.
Bug causes a crash when doing a style dialog
after setting draftbits with PrGeneral.
*)
{
What's what in the code snippet that follows.
thePrRecHdl : THPrint;
rslData : TSetRslBlk;
draftData : TDftBitsBlk;
rotnData : TGetRotnBlk;
isBadImageWriter : Boolean;
isLandscape : Boolean;
isReduced : Boolean;
}
PrOpen;
IF (PrError = noErr) THEN
BEGIN
PrintDefault(thePrRecHdl);
IF (PrError = noErr) THEN
BEGIN
{See if we're using a version 6.1 or 7.0 ImageWriter driver.}
IF (thePrRecHdl^^.prStl.wDev DIV 256) = 1 THEN
isBadImageWriter := (PrDrvrVers = 61) OR (PrDrvrVers = 70)
ELSE
isBadImageWriter := FALSE;
IF NOT (isBadImageWriter) THEN
BEGIN
{Set draftBits mode now, if not our special case.}
draftData.iOpCode := draftBitsOp;
draftData.hPrint := thePrRecHdl;
PrGeneral(@draftData);
END;
{Do the style dialog.}
IF (PrStlDialog(thePrRecHdl)) THEN
IF (isBadImageWriter) THEN
BEGIN
{If so, see if they selected rotation or 50% reduction.}
rotnData.iOpCode := getRotnOp;
rotnData.hPrint := thePrRecHdl;
PrGeneral(@rotnData);
isLandscape := rotnData.fLandscape;
isReduced := BTst(thePrRecHdl^^.prStl.wDev, 3);
{If so, warn them that those things will be ignored.
Preferably use something other than DebugStr… }
IF (isLandscape) OR (isReduced) THEN
DebugStr('Bad ImageWriter; landscape
and/or reduced.');
{Now, set draftBits mode, since we didn't before.}
draftData.iOpCode := draftBitsOp;
draftData.hPrint := thePrRecHdl;
PrGeneral(@draftData);
END;
IF (PrJobDialog(thePrRecHdl)) THEN
BEGIN
{Print}
END;
END;
END;
PrClose;
Graphics, Imaging & Printing: Printing: Determining if printer supports color and/or grayscale printing
Is there any way to determine whether I’m printing to either a color printer or a printer simulating color, such as the LaserWriter set for Color/Grayscale?
Check the grafPort returned by your call to PrOpenDoc. If the rowBytes of the grafPort is less than 0, the Printing Manager has returned a color grafPort. You can then make Color QuickDraw calls into this grafPort. LaserWriter driver version 6.0 and later returns a color grafPort from the PrOpenDoc call, if the Color/Grayscale button has been set.
The following code fragment demonstrates this:
(* This function determines whether the port passed to it is a *)
(* color port. If so, it returns TRUE. *)
FUNCTION IsColorPort(portInQuestion: GrafPtr): BOOLEAN;
BEGIN
IF portInQuestion^.portBits.rowBytes < 0 THEN
IsColorPort := TRUE
ELSE
IsColorPort := FALSE;
END;
A third-party printer driver should return the type of grafPort that represents the abilities of its printer. Therefore, if the printer supports color and/or grayscale, and if Color QuickDraw is present, the application will receive a color grafPort after calling PrOpenDoc. Otherwise, if the Macintosh you’re running on does not support Color QuickDraw, you should return a black-and-white grafPort.
Graphics, Imaging & Printing: Printing: Apple IIGS ImageWriter driver page sizes
How do I specify custom page sizes to the Apple IIGS ImageWriter driver?
The Apple IIGS ImageWriter driver can’t handle paper sizes other than what’s built in, which is what shows up in the “Page size” pop-up menu. It means if the form isn’t listed, the ImageWriter Driver can’t print to it. (Please don’t confuse the Print Manager with the ImageWriter driver -- see the article in Develop #4 and Apple IIGS Technical Note #93 for more details, but the Print Manager isn’t doing *anything* other than making sure the ImageWriter driver is loaded and passing all the calls along to it.) Other drivers will behave differently, depending on how they were written. There’s no generic, works-on- all-drivers way to add new page sizes to a driver you want to print to. The 6.0 ImageWriter driver does not have this feature either.
Graphics, Imaging & Printing: Printing: GS/OS and text-only printing to a character device
What’s the best way to do text-only printing to a character device through GS/OS?
If you want to print text to GS/OS character device, here’s how you do it:
1. Look at all the devices online to find which are character devices. You can tell when a device is a character device by examining bit 7 of the “characteristics” word returned by DInfo--the bit is set for block devices and clear for character devices. You don’t have to hard-code a list of character device IDs.
2. Present the user with a list of device names followed by their location and generic type in parentheses. You can adjust the names of device types to reflect your use. For example, “.RPM (AppleTalk printer, port 1),” “.DEV2 (serial modem, port 2),” or “.DEV3 (generic character device, slot 5).” You can use bit 3 of the slot returned by DInfo to know whether to return “slot” or “port,” too.
3. When the user selects a device to print to, call Open on the device name (such as .RPM for an AppleTalk printer). Use Write to write the information, just like you would to a file, then call Close (you can call Flush if you like, but it shouldn’t be necessary). That’s all that’s necessary.
Remember not to embed ImageWriter or any other printer-specific codes in the output stream. With the exception of choosing a device and creating a file, this same code could be used to print to another device such as a disk, *any* text printer, or modem. You might give users a “text printing preferences” dialog where they can enter some codes if they like, and you might have built- in sets for ImageWriters and other common printers, but don’t make it too complicated. This is very generic and will work well on *any* setup, not just an ImageWriter II connected through the serial port.
Graphics, Imaging & Printing: Printing: Personal LaserWriter LS 1.1 driver is faster
My LaserWriter LS is very slow when printing from my Macintosh SE. Any suggestions?
Use the new LaserWriter LS driver version 1.1. It was released after System 7.0, and is available on AppleLink or from your dealer.
If you’re printing Word files, Microsoft’s TrueType INIT will help. It’s available from MicroSoft Technical Support or from commercial bulletin board services.
Graphics, Imaging & Printing: QuickDraw: System 7 QuickDraw DrawText performance
We’ve noticed that using DrawText is much slower in System 7, especially when drawing in color (anything other than black on white). What can be done to restore the drawing speed to System 6 levels?
A QuickDraw function like DrawString or DrawText will be slower under certain circumstances in System 7 than System 6. Specifically, if you are drawing in srcCopy mode and you colorize the text—that is, foreground color is not black and background color is not white (Inside Macintosh Volume VI, page 17-16)—then QuickDraw really slows down as you have noticed. SOMETIMES, the speed of drawing is 6 times as slow as System 6.
The cause of this slowness is a known System 7 bug. The bug has concerned the engineers greatly and will be responded to in an appropriate manner in the future.
There are a few workarounds: One, you can avoid using the srcCopy mode and use the default srcOr mode instead. However, this is not a real workaround, since you may have essential reasons to use srcCopy. The other option is to create an offscreen pixmap or GWorld and perform a DrawText with srcOr to this GWorld with colorization. Then, you can perform a CopyBits from the offscreen to the screen with srcCopy mode and no colorization. Using CopyBits will not cost you much time. Again, this is a workaround and is not ideal.
The srcOr is a bit slower than in System 6.0.x, but it does not have a bug; rather it is a side effect of system enhancements. The slow speed is a trade-off taken to receive the host of other benefits.
Graphics, Imaging & Printing: QuickDraw: No System 7 QuickDraw alpha channel support
How can I directly access the alpha channel (the unused 8 bits in a 32-bit direct pixel using QuickDraw) under System 7? Under System 6 it was easy, but under System 7’s CopyBits() the alpha channel works with srcXor but not with srcCopy.
With the System 7.0 QuickDraw rewrite, all “accidental” support for the unused byte was removed, because QuickDraw is not supposed to operate on the unused byte of each pixel. QuickDraw has never officially supported use of the extra byte for such purposes as an alpha channel. As stated in Inside Macintosh Volume VI, page 17-5, “8 bits in the pixel are not part of any component. These bits are unused: Color QuickDraw sets them to 0 in any image it creates. If presented with a 32-bit image—for example, in the Copybits procedure—it passes whatever bits are there.”
Therefore, you cannot rely on any QuickDraw procedure to preserve the contents of the unused byte, which in your case is the alpha channel. In fact, even CopyBits may alter the byte if stretching or dithering is involved in the copybits by setting them to zero. Therefore, the only possible workarounds for this problem are to not use the unused byte for alpha channel storage since the integrity of the data cannot be guaranteed; or, to not use QuickDraw drawing routines which can alter the unused byte.
Graphics, Imaging & Printing: QuickDraw: Macintosh PICT-to-PostScript conversion
How do I convert PICT format data to PostScript in my printer driver?
Converting PICT files to PostScript involves a detailed understanding of both bitmaps (or pixmaps) and the graphics state in PostScript, which is a data structure defining the context in which other graphic operators in PostScript execute. If you don’t know PostScript, the following manuals are a must:
• PostScript Language Tutorial and Cookbook (Addison-Wesley) is an introduction to PostScript.
• PostScript Language Reference Manual (Addison-Wesley).
• PostScript Language Program Design (Addison-Wesley) details designing efficient PostScript programs. It has a lot of useful sample programs on topics like writing a print spooler.
You need to convert all the QuickDraw operations in a PICT to corresponding PostScript operations. To get a feel for this conversion, you can analyze the PostScript dump from a LaserWriter to see how it converts a PICT to PostScript. Under System 6.x, a PostScript dump can be obtained by pressing Command-K while printing. Under System 7.0, you can get a dump by selecting the PostScript File option in the Print dialog.
Some areas of QuickDraw, such as transfer modes, do not have a correspondence in PostScript. The PostScript imaging model is designed so that all areas of a page affected by an image are marked as if with opaque paint. Using image masks can help. See the Graphics chapter in the PostScript reference manual.
PICT-to-PostScript conversion can be a long process, especially if one is unfamiliar with PostScript. Using the above books and the PostScript dump from the LaserWriter (but ONLY as a general guide) should help.
Graphics, Imaging & Printing: QuickDraw: OpenCPicture and PICTs other than 72 dpi
Can I use OpenCPicture to create PICTs with a higher resolution than 72 dots per inch (dpi)?
There’s good news and bad news: The good news is that you’re on top of the situation, which means the bad news is that there aren’t better ways to do what you want to do, mostly. Here’s the scoop:
You can use vRes and hRes in pictures opened with OpenCPicture to tell QuickDraw it’s not a 72-dpi picture, and as long as the application that receives the picture uses DrawPicture to image it, QuickDraw will Do The Right Thing—scaling it on the screen to 72 dpi instead of making it humongously large. Unfortunately, this way you lose hairlines; if you print such a picture to a 72 dpi grafPort (like the LaserWriter driver normally returns), you’ll get 1/72-inch lines instead of 1/300-inch lines as you probably want.
(This _can_ work correctly, but the receiving application has to notice your picture is bigger than 72 dpi and ask PrGeneral to increase the resolution of the printing grafPort accordingly, and this doesn’t always or often happen.)
Graphics, Imaging & Printing: QuickDraw: Highlighting ignored if foreground same as background color
Under System 7, but not System 6, HiliteColor is not used for InvertRect when the hilite bit is set and the background is exactly black (R=G=B=$0000). Also, HiliteColor doesn’t draw when a pen mode of XOR is used in a LineTo call.
The problem you encounter exists whenever the background and foreground color are the same when using highlight mode. If the foreground color is the same as the background color, highlighting is ignored. Therefore, when you set the foreground color to white, you should set the background color to something other than the default color of white.
Graphics, Imaging & Printing: QuickDraw: GetPixelsState is slow sometimes
Why do I sometimes see incredible slowdowns under System 7.0 when calling either GetPixelsState or LockPixels (I’m not sure which) for the PixMapHandle of a GWorld allocated in temporary memory?
GetPixelsState takes an arbitrary amount of time since it makes a call to RecoverHandle to get the handle pointing to the baseaddr. Therefore, the slowdown you see as actually due to the call to RecoverHandle, which is slow because it must traverse the heap to find the pointer to the baseaddr. LockPixels is not responsible for the slowdown because it does not make call to any traps which could take an extended amount of time.
Graphics, Imaging & Printing: QuickDraw: Using a Macintosh PICT file that‘s larger than available memory
How can I read a 2 MB PICT file into only 1 MB of memory?
You can’t read it in since you don’t have enough memory, but drawing the picture contained in the file using a technique called “spooling” increases your chances of using a 2 MB PICT file with 1 MB memory. Spooling is documented in the Color QuickDraw chapter of Inside Macintosh Volume V (pages 88-89).
Graphics, Imaging & Printing: QuickDraw: Getting a single scan line from a PICT file
Is there any way to obtain a particular scan line from a PICT file?
A PICT file may contain more than just pixmaps, so getting one scan line out of it is not possible. The file may also contain other elements that overlap, such as rects and arcs. The only way to obtain a single line is to draw it offscreen and then, once the whole image is in memory, you can go and study individual pixels.
Graphics, Imaging & Printing: QuickDraw: Determining pixel depth from PICT files
How do you find out the pixel size of a PICT file on the disk?
A picture is by nature independent of depth. For example, you can have a picture containing DrawRects and LineTos and therefore lacking of any info regarding depth.
On the other hand, if the picture you are looking at has pixmap opcodes in it, then each pixmap contains its own pixel size and in this case a picture can have a number of depths associated with it.
If you want to see the pixel size for each pixmap opcode in a picture, replace all the bottleneck routines and every time the bitsProc is called you can see the pixmap and get the info out. Since the picture is in a file, you can use the spooling technique described in the QuickDraw chapter in Inside Macintosh Volume V. Be ready to deal with multiple, possibly different, pixmaps as well as direct pixmaps if the picture was created under 32-bit QuickDraw.
”KnowsPICT,” on the Developer CD Series disc, extracts this kind of information. The System 7.0 Picture Utilities package gets this information too.
Graphics, Imaging & Printing: QuickDraw: Rendering color PICTs in a black-and-white environment
I want to be able to render a color PICT as a black-and-white image substituting patterns for colors. My images are pretty small and have under 16 colors. What do you suggest as the easiest way?
One easy way is to take advantage of 32-Bit QuickDraw and System 7.0’s ditherCopy transfer mode modifier or flag (documented in Inside Macintosh Volume VI, page 17-17). Call DrawPicture into an offscreen pixmap with the pixel depth of the original color PICT. Then call CopyBits to copy the pixmap to the screen, with srcCopy + ditherCopy as the transfer mode. This will result in a nicely dithered image on the black-and-white end.
Under System 6 without 32-Bit QuickDraw, the solution is not nearly so cut and dried. One way might be to take advantage of the fact that DrawPicture goes through the QuickDraw bottlenecks for drawing. For each grafproc in your PICT, you'd intercept StdBits during DrawPicture and call your own dithering routine to examine the foreground color and set the pen pattern or fill pattern so that it has about the same lightness as the original color.
Well, this came out as a great sales pitch for writing a System 7-savvy app!
Graphics, Imaging & Printing: TrueType: RealFont and TrueType
What is the story with RealFont and TrueType? I am finding that, of the standard System 7 fonts, only Symbol and Courier get a TRUE for 7 point.
You are absolutely correct with your observation of RealFont for size 7 and certain TrueType fonts. The explanation is hidden in “The TrueType Font Format Specification” (APDA M0825LL/A), page 227:
The “head” FontHeader table contains a field “lowestRecPPEM,” which indicates the “lowest recommended pixel number per Em,” or, in other words, the “smallest readable size in pixels.” As it turns out, the Font Manager in its wisdom uses this information for the value it returns from RealFont. Note that for higher resolution devices, a point size of 7 does *not* correspond to 7 pixels; but as the unit “point” is 1/72 inch, and the screen resolution is (approximately) 72 dpi, the result corresponds to reality in this case.
The value for lowestRecPPEM can be arbitrarily set by the Font designer. We all know that small point sizes on low-resolution devices never look “great,” and even less so for outline fonts. Courier and Symbol have lowestRecPPEM = 6, while the other outline fonts in the System have lowestRecPPEM = 9. This doesn’t really mean that Courier and Symbol in size 7 (TrueType) look better than Times or Helvetica under the same conditions. It means the font designer had higher standards (or was in a different mood) when he choose lowestRecPPEM = 9.
Graphics, Imaging & Printing: TrueType: RealFont and smaller-than-legible TrueType font sizes
RealFont and smaller-than-legible TrueType font sizes
RealFont returns a false on a TrueType font if the font’s point size is less than the minimum legible point size defined in the 'sfnt'. A scaled bitmap is created for smaller-than-legible point sizes. This is a small point (a lame font pun there), but you might want to know.
Graphics, Imaging & Printing: Color Manager: Macintosh Color Manager versus Palette Manager
When should the Macintosh® Color Manager be used and when should the Palette Manager be used?
The Palette Manager is by far the friendlier and more versatile of the two. It provides all the functionality you need to customize and animate the colors in your application. You shouldn’t ever need to use the Color Manager unless you require custom color search and complement functions. Unless you really understand the Color Manager in detail, you are likely to have problems getting the Color Manager to work in a clean fashion. When using the Palette Manager, applications following the rules will maintain their respective color environments safely as applications move back and forth from foreground to background, and from one screen to another. Accomplishing this with the Color Manager calls is not worth the effort. For additional information, see the Palette Manager article in this issue.
Graphics, Imaging & Printing: Fonts: Chicago Control-Q prints propeller or clover symbol
How do I get the character that represents the clover used for command-key equivalents in documents and in menus?
This key is documented in the Apple Style Guide, which is available on the latest Developer CD Series disc as well as from APDA. One little feature of Key Caps which is not widely known is the Control key (not the Command or Option keys). Pressing the Control key in Chicago shows that Control-Q in Chicago maps to the propeller symbol for which you search.
Graphics, Imaging & Printing: Fonts: Apple IIGS static text item font bug and workaround
When I ran my Apple IIGS® application on a single 3.5-inch drive, I found that some of my windows were displaying static text items in the Shaston font that were meant to be shown in Geneva. Because the program disk was in the drive when the window was displayed, the system defaulted to the system font instead of asking for the system disk to be inserted so it could load the font. It just defaulted to the system font. Is this a bug and is there a workaround?
The Apple IIGS Font Manager keeps its fonts in separate files that it opens only when the font is requested. Hence, when the system tries to load the font on a one-disk system, the Font Manager simply gets a file (or volume) not found message. In any case, since the file was not already open, the system does not call TLMountVolume, and the Font Manager doesn’t, so… The Font Manager simply reports that the font does not exist and you get the default system font. The solution? Not a very pretty one. You’ll have to call LoadFont or InstallFont yourself, and if you get a “volume not found” error, call TLMountVolume yourself.
Graphics, Imaging & Printing: Fonts: Macintosh double-byte character encoding
When will System 7 and TrueType™ be able to support a larger character encoding vector than the current 256 characters? Is this something I could do now?
System 7 does not have double-byte character encoding support now. In the future, Apple will use the two-byte UNICODE standard for its operating systems. However, such a change will be huge and therefore will not be available before the next major system revision.
Ever since 6.0.2, KanjiTalk™ has had double-byte encoding, so you can use the Japanese system at this time. The system which allows you to do this is called shift-JIS (Japanese Input System). The mappings are on the current Developer CD in the Kanji folder.
Graphics, Imaging & Printing: Fonts: Macintosh Font Manager FOND information
Can you help me figure out the setwidth tables in Macintosh® FOND resources?
Basically, each width table entry looks like this:
struct WidTableEntry {
word widStyle; /* Bit flags describing which style this
table measures. */
word widRec[numChars+2]; /* Width information for each
character. */
};
To get the width information for character number x in the width table, you just index by x into the widRec. The font widths are stored in 4.12 fixed- point format—four bits to the left of the decimal point, and twelve bits to the right. If you need to convert to floating point, probably the easiest way is to coerce the 4.12 16-bit fixed-point number to 16.16 32-bit fixed-point (this type, "Fixed,” is described in Inside Macintosh Volume I, page 79), and then use the Toolbox Utilities routine Fix2X (Inside Macintosh Volume IV, page 65) to convert to the 80-bit "Extended" floating-point format.
theFix16_16 = Fixed(longword(theFix4_12)<<4);
theExtended = Fix2X(theFix16_16);
If your application needs to do the calculations quickly, it might be useful to avoid floating-point altogether, keep the widths in Fixed format, and do all the calculations with the Toolbox Utilities fixed-point routines. Fixed- point math is much faster, and for your purposes a resolution of 2^-16 may be sufficient to avoid rounding error.
One last caveat: To maintain System 7.0 compatibility when digging into FONDs for bitmap fonts, it's really important to check that the FOND info you are checking/altering refers to 'FONT' or 'NFNT' resources, not to the new 'sfnt' resource used for outline fonts. The internal FOND structure is unsupported and subject to change.
Graphics, Imaging & Printing: Fonts: Determining PostScript font intrinsic styles
How can I determine the intrinsic styles that are supported by a particular PostScript® font?
To find the styles which are supported by a particular font, you need to access one of two tables. To find the screen fonts that are available, you can use the Font Association Table. This table is shown in Inside Macintosh® IV- 38. Each entry in the table contains the size and style of the font, as well as the resource ID. Each font in this table should be available for the screen.
When you print a font to a PostScript printer, the Font Manager uses the style mapping table in the family record to create a PostScript name for the font. The table has a list of strings, followed by an entry for each style supported by that particular font. A table for Helvetica® might look like this:
|__?ΩHelvetica
-
Bold
Italic
The first part ('|_____') is the prefix the LaserWriter® uses for fonts that it has coordinated. In the process of downloading a PostScript font, the LaserWriter driver has to change the encoding vector so that the special characters supported by the Macintosh will be usable on the printer. When the LaserWriter does this, it renames the font and prepends this prefix so it can distinguish it from the original version. The rest of the table is used to build the font name for a particular style. This is a little sick, so hang on. Let's look at the table again, and number each line:
1 |__?Ω2 Helvetica
3 -
4 Bold
5 Italic
6 1,2
7 1,2,3
8 1,2,4
9 1,2,3,4
So entry number 6 here, is the entry for plain Helvetica. It is built by using lines 1 and 2 creating the name '|_____Helvetica'. Entry number 9 is the entry for bolditalic. The name that gets built here is: '|_____Helvetica- BoldItalic'. The style-mapping table is not covered in the Font Manager chapter of Inside Macintosh since it is so specific to PostScript. Instead, this information is in the LaserWriter Reference (available from Addison- Wesley), pages 28-35. It's pretty hard to grasp without the preceding description.
Graphics, Imaging & Printing: Fonts: Don't put fonts into your Macintosh application
My Macintosh® application will not run. The problem seems to be my font that I keep in the application. The first time I call DrawString the machine hangs.
We don't recommend putting fonts into an application because the ID numbers may conflict with fonts in the System file.
Graphics, Imaging & Printing: Fonts: Preshifted FASTFONT increases Apple IIGS text drawing speed
What is "FASTFONT" on the Apple IIGS® and how can I use it?
FASTFONT is a new disk file for System Software 5.0. It contains a preshifted version of the ROM font, Shaston 8. QuickDraw™ will load FASTFONT from the Fonts directory at QDStartUp time (if present) and use it for greatly increased text drawing speed. Currently, the System does not support different or multiple FastFonts, and no special work is needed by the application to take advantage of the present capability.
Graphics, Imaging & Printing: Fonts: Fonts and Apple IIGS aspect ratio
Why do Apple IIGS® fonts look tall and skinny, as if they were made out of rubber and stretched too far in one direction. They look OK when I print using the "vertical condensed" option.
Nearly all the Apple IIGS fonts were originally designed for other systems, usually the Macintosh®. Font definitions for the Apple IIGS and other systems are nearly identical. Macintosh pixels are square; the width-to-height ratio of a pixel is 1:1. Apple IIGS pixels are much taller than they are wide. (The ratio for Apple IIGS 640 mode is about 5:12.) When a font designed for square pixels is displayed on a system with pixels of a different shape, the characters look stretched. This is what happens on the Apple IIGS.
Apple could have changed the font strike for a more pleasing look at Apple IIGS resolutions, but for legal reasons such a change would require renaming the fonts. Times wouldn't be Times anymore, Helvetica wouldn't be Helvetica, and so on. The fonts would look the same, but the names would have to be different. In the tradeoff between appearance and well-recognized font names, Apple chose to keep the familiar names and font strikes.
To compensate for the stretched fonts, all of Apple's printer drivers include a "vertically condensed" printer option. Selecting this option causes the printer drivers to print with double the screen's vertical resolution. Doubling the vertical resolution effectively makes the pixel aspect ratio about 10:12, or 5:6, which is close enough to square that the fonts look the way we expect them to.
Some fonts are designed for the Apple IIGS aspect ratio of 5:12. Such fonts are identified in their font family numbers by having the high bit set.
Graphics, Imaging & Printing: Fonts: Fonts shipped with Macintosh system software
What are the standard fonts shipped with Macintosh® system software?
Chicago 12
Courier 10,12
Geneva 9,10,12,14,18,20,24
Helvetica® 10,12
Monaco 9,12
New York 9,10,12,14,18,20,24
Times® 10,12
Venice 14
Graphics, Imaging & Printing: Fonts: Macintosh fractional font width problems
Why can’t I get Macintosh® fractional font widths (FFWs) to work correctly?
There are a number of problems with the current implementation of fractional font widths. Because of these problems, Apple discourages use of fractional font widths at this time. Here are some of the difficulties:
The most serious problem with the current implementation of fractional font widths involves the way QuickDraw™ uses them. When you draw a string on the screen with FFWs enabled, QuickDraw rounds the fractions into integers. Rather than adding this rounding error onto the end of the string, QuickDraw distributes it across certain characters in the string. Note that this error will only occur on the screen. If this string is printed on a high resolution device (like a LaserWriter®), it looks fine.
The distributed rounding error causes one more significant problem. If an application wants to redraw part of a string, the rounding error is distributed differently than if the entire string is drawn. One solution for this problem is not to redraw sections of a string, but that doesn’t solve the problem completely. For example, consider a word processing application that tries to determine where to place its insertion point. Unless it has drawn each character individually, there is no way for it to correctly calculate the position between characters. You can see this by using TextEdit with FFWs enabled.
Enabling FFWs disables the Font Substitution feature of the LaserWriter driver because there is no way to mix the widths of a screen font with those of a printer font. For example, if you are using Geneva with FFWs enabled and the LaserWriter substitutes Helvetica®, which widths should it use? If the driver uses Geneva widths with the Helvetica font, the What You See Is What You Get (WYSIWYG) correspondence between screen and printer is lost. To solve this problem, the driver disables Font Substitution and uses the Geneva widths with the Geneva font.
Another problem with FFWs concerns QuickDraw pictures. Unfortunately, the FractEnable flag is not recorded into pictures, so if you create a layout with text in a picture with FFWs enabled, then paste that picture into an application which has FFWs disabled, you lose your layout. This problem with pictures is especially bad for applications which generate forms, since the field names no longer fit correctly in the boxes which surround them. Applications which generate pictures should do so with FFWs disabled.
Graphics, Imaging & Printing: Graphics Devices Manager: Technique for Macintosh GC card GWorld access
How can a Macintosh® in 24-bit addressing mode read from disk into a GWorld? If the GC card is installed, sometimes the GWorld is a 32-bit one cached on the card. How do we ensure the GWorld will be in main memory?
When you create your GWorld, set the keepLocal flag in the flags field of the NewGWorld call. This ensures that the newly created GWorld will be in main memory where you can access it. Read your data into the GWorld and then clear the keepLocal flag with a call to SetPixelState. This will issue a “GWorld hasbeen updated” type of message, causing the GWorld to be cached off to the GC card, giving you the best performance. When you want to load another image, call SetPixelState again, setting the keepLocal flag to bring the GWorld back to main memory. Using this technique you’ll be able to load your GWorld and cache it too, and you won’t need to recreate the GWorld each time you want to load more data into it.
Graphics, Imaging & Printing: Graphics Devices Manager: Code snippet for getting Macintosh display information
In my Macintosh® system, I have two screens. The main screen in a 19" monochrome. The second screen, to the left of the main one, is color. How can my program know whether or not a color display is available, its depth, and its coordinates?
The following bit of code will show you basically how to walk the GDevice list and find the information you want from it. Most of this information can be found on pages 119 and 124 of Inside Macintosh Volume V.
count = 0;
GDevHand = GetDeviceList();
ScreenRect[count] = (*(*gDevHand)->gdPMap)->bounds;
ScreenDepth[count] = (*(*gDevHand)->gdPMap)->pixelSize;
ScreenColor[count] = TestDeviceAttribute (GDevHand, gdDevType);
While ((GDevHand = GetNextDevice(GDevHand)) != nil) {
++count;
ScreenRect[count] = (*(*gDevHand)->gdPMap)->bounds;
ScreenDepth[count] = (*(*gDevHand)->gdPMap)->pixelSize;
ScreenColor[count] = TestDeviceAttribute (GDevHand, gdDevType);
}
Graphics, Imaging & Printing: Palette Manager: Macintosh Palette Manager and off-screen graphics
Macintosh Palette Manager and off-screen graphics
The Macintosh Palette Manager does not work on off-screen graphics. It needs to have a Window record in order to work correctly.
You can work around this limitation. For example, use Index2Color and then RGBForeColor to get the color to be set for drawing, instead of using PMForeColor.
A remake of the GiMeDaPalette code sample, available on the latest Developer CD Series disc, does off-screen drawing in place of copying a PICT.
Graphics, Imaging & Printing: Palette Manager: Macintosh palette disposal
What is the method of disposing of palettes that are attached to a window?
Disposing of palettes takes some thought; it's not straightforward. If you call GetNewPalette or create a palette using NewPalette and SetPalette then you are responsible for disposing the palette when you dispose of the window. If you call GetPalette for a window then you are again responsible for disposing the palette when you're done with the window.
If there is an associated palette to a window (there was a pltt=0 or pltt=WIND ID resource available) and you don't touch the palette with GetPalette, or any of the other previously mentioned calls, then the palette is disposed of for you automatically.
One thing to remember, it's best to play it safe and dispose of the window first and the palette second. You'll need the handle for the palette so make sure you have it before disposing the window. Though it doesn't matter which one gets done first, it's always best to keep yourself covered and do the window first.
Graphics, Imaging & Printing: PostScript: LaserWriter Font Utility copies Postscript file to printer
Is there a utility that will send a PostScript file from disk to the LaserWriter?
The LaserWriter Font Utility handles this job and is part of the System 7 disk set. On the System 7 Golden Master CD, the path is System 7.0: System Software 7.0: Installer Version: Tidbits folder.
Graphics, Imaging & Printing: PostScript: Apple IIGS EmulatorFont
What is EmulatorFont in the the font catalog of my LaserWriter? There’s no sample text for it.
EmulatorFont is a PostScript font installed by the ImageWriter Emulator. It doesn’t have ASCII characters in the normal range—it only contains the MouseText special characters that IWEM can’t map to Courier or Times when printing text. If you want to get rid of the font, restart the printer and don’t re-download IWEM. If you want to see the font definition, just open IWEM off the current IIGS System Tools disk.
Graphics, Imaging & Printing: PostScript: PostScript setprintername doesn’t accept colons in string
Why can’t I use a colon with the PostScript command setprintername to change the Personal LaserWriter NT network name and type, but it works with the LaserWriter II?
The reason that the Personal LaserWriter NT is not accepting the PostScript you’re sending is not because of a bug, but rather a bug fix. Colons have never been acceptable in the string passed to setprintername. (See page 296 of Adobe’s “PostScript Language Reference Manual.”) The reason the call works in older LaserWriters but not the Personal LaserWriter NT is that the NT has a newer version of PostScript in it. Older versions of PostScript didn’t enforce Adobe’s printer naming conventions. The setprintername restrictions have been enforced in the new version, however. Therefore, colons are not allowed.
If you need to change the LaserWriter network type, it can be done with the AppleTalk-type parameter described on page 105 of Apple’s “LaserWriter Reference” manual. This method will work on the new printers as well as the old.
Graphics, Imaging & Printing: PostScript: Printing an Encapsulated PostScript (EPS) file
I want to be able to print any Encapsulated PostScript (EPS) file. How can I do this? Can I somehow tell the LaserWriter driver to grab the files and print them?
Unfortunately, the Laserwriter driver cannot handle this for you. There’s no easy way to do what you’re asking, because PostScript in the Macintosh world is different from standard PostScript. Even if a standard PostScript file were dumped to the printer using PostScriptHandle, the printer would not be able to resolve the differences in standard PostScript. The only way you could print such PostScript files through the LaserWriter driver would be to do preprocessing such as changing transformation matrices and changing pen transfer modes. To be completely compatible with these files, you’d need to parse completely through them and fix the problems as they appear. This is a major job, requiring in-depth knowledge of PostScript. As it stands, the LaserWriter driver cannot handle vanilla PostScript. A printer driver *could*be written to do this, but then every job would have to be parsed and every job would be slowed down because of it.
One of the problems is that Adobe’s document structuring conventions just went final a short while ago. There are many EPS files out there that don’t match the structuring conventions that Adobe has laid down, so the only way you can get the vitals of a PostScript file consistently is to parse it completely. Ideally, everyone would comment their EPSF correctly and printer drivers could decide what to do based on that. Unfortunately, we’re a long way away from that point today. The only way to do what you need to do is to get real deep into PostScript and devote a lot of time to the project. You have to weigh the time and resources required against the benefit of being compatible with non-Macintosh EPS files.
Graphics, Imaging & Printing: PostScript: PostScript documentation
PostScript documentation
Adobe Systems publishes three great manuals that can help you with PostScript commands: “PostScript Language Reference Manual,” “PostScript Language Tutorial,” and “PostScript Language Cookbook.” You can find these manuals at just about any bookstore, or you can order them through APDA by calling (800) 282-2732 or writing them at:
Apple Computer, Inc.
20525 Mariani Avenue, Mail Stop 33-G
Cupertino, CA 95014
Graphics, Imaging & Printing: PostScript: PostScript code for renaming LaserWriter
In checking a printer name to ensure an even number of characters, does the LaserWriter Namer append a space to the end if the total is odd?
In a nutshell, yes. The Namer does indeed append an extra space to odd-length printer names. The reasoning behind this is to be compatible with some of the old 68000 processors. The addressing scheme of these old processors requires that memory be accessed by even-numbered addresses. To get at a piece of memory located after an odd-length LaserWriter name, you would need to get an odd-numbered address (which is not directly possible). This obviously can be worked around, but the authors of the Namer felt it best to avoid this altogether by padding the name when necessary. It’s worth noting that the version 7.0 Namer does this too.
If you’d like to work around this, here’s an alternate method for renaming the printer:
The printer name is stored as a string in the persistent parameters of all LaserWriters. This string can be changed by the following PostScript program:
serverdict begin 0 exitserver
statusdict begin (NEWNAME) setprintername
Replace NEWNAME with the name you want for the printer. The name can be up to 31 characters and should consist entirely of printing characters--the “@” and “:” cannot be used. Note that parentheses are required.
This program can be downloaded to the LaserWriter in batch or interactive mode. In interactive mode you should type both command strings on the same line before pressing Enter, because exitserver disconnects you from the printer. When you reestablish your connection to the printer, the name will be changed.
Make sure you have selected the correct LaserWriter using the Chooser before downloading this program, so you don’t rename the wrong LaserWriter.
Graphics, Imaging & Printing: PostScript: SCSI drive format for LaserWriter II NTX with Rev. 3 ROMs
What could be causing intermittent PostScript® errors from a LaserWriter® II NTX with an SCSI hard disk mounted after installing the Rev 3 ROM upgrade?
The LaserWriter II NTX with Rev 3 ROMs does not work properly with a hard disk formatted with the LaserWriter Font Utility 1.x. You need to reformat the disk and copy the fonts back onto the hard disk using the LaserWriter Font Utility 2.0.2. Unfortunately, there is no way to make this procedure easier.
Graphics, Imaging & Printing: PostScript: Where to find Encapsulated PostScript file (EPSF) documentation
I am developing an application that creates pictures containing both QuickDraw™ and PostScript® (as picComments). How do I create an encapsulated PostScript file (EPSF)? Is the format explained anywhere, and is it possible to convert the QuickDraw into PostScript directly in the application?
Adobe’s EPSF format is documented in the new (2nd) edition of Adobe’s PostScript Language Reference Manual (Addison-Wesley) and in “Adobe Document Structuring Conventions,” available from Adobe Systems. Adobe’s references explain how to structure your comments in your PostScript file so that other applications know how to read it.
You probably don’t want to try to convert QuickDraw to PostScript directly in your application, although it is possible. Basically, it involves translating each QuickDraw command into PostScript, which is what the LaserWriter® Driver does. It’s a lot of work and makes you dependent on the QuickDraw features being used, which can be a problem when new features are added.
Graphics, Imaging & Printing: PostScript: How to inhibit LaserWriter test page
How do I inhibit the test page on a LaserWriter®?
Download the following PostScript commands:
serverdict begin 0 exitserver
statusdict begin
false setdostartpage
end
The above commands can be downloaded from your Macintosh® to the printer several ways:
1. You can use a PostScript utility like LaserTalk from
Emerald City Software.
2. The PostScript Language facility in Microsoft Word.
3. PSDump or PSsend
4. An Adobe downloader utility that they include with
their products.
5. Use the PostScript utilities in the Developer CD’s
PostScript Utilities folder.
6. Use the menu command in the LaserWriter Font Utility
that comes with System 7.0ßx.
When you issue the commands, your LaserWriter will probably crank and grind for a few seconds (it has to re-program the EPROM inside) then after the lights stop flashing, your LaserWriter will no longer spit out the start-up page.
For more information on the above subject I recommend the PostScript Language Reference Manual by Adobe Systems.
Graphics, Imaging & Printing: PostScript: Using PostScript to control LaserWriter serial I/O
Where can I find information on using PostScript to control a multi-tray sheet feeder by communicating through the LaserWriter® serial port?
You need to talk with Adobe on how they control the serial chip with PostScript. They use some undocumented PostScript calls to control the serial chip on the controller board of the LaserWriter. They can be reached at:
Adobe Systems, Inc.
1585 Charleston Road
Mountain View, CA 94039
- or -
AppleLink Address: ADOBE.SUPT (Tech Support)
Details about installing feeder resources for Macintosh® into the LaserWriter driver 7.0 dialogs are available on request from Apple’s Developer Technical Support group.
Graphics, Imaging & Printing: PostScript: How to send PostScript from the Macintosh to the LaserWriter
How do I send PostScript® from the Macintosh® to the LaserWriter®?
The best method for sending PostScript to the LaserWriter is to use the PostScriptHandle (kind = 192) PicComment documented in Tech Note #91. There are a few PicComments for sending PostScript to the LaserWriter, but the easiest to use and most problem free is the PostScriptHandle comment. One model is:
PrOpenPage(...)
{ Send some QuickDraw™ so that the Printing Manager gets a }
{ chance to define the clip region. }
MoveTo(-32000, -32000);
Line(0, 0);
PicComment(PostScriptBegin, 0, NIL);
{ QuickDraw representation of graphic. }
MoveTo(100, 100);
LineTo(200, 200);
{ PostScript representation of graphic. }
thePSHandle^^ := '100 100 moveto 200 200 lineto stroke';
PicComment(PostScriptHandle,GetHandleSize(thePSHandle),thePSHandle);
PicComment(PostScriptEnd, 0, NIL);
PrClosePage(...)
The described fragment prints a line on any type of printer, PostScript or not. The first MoveTo/Line combination is required to give the LaserWriter driver a chance to define a clipping region. The LaserWriter driver replaces the grafProcs record in the GrafPort returned from PrOpenDoc. In order for the LaserWriter driver to get execution time, you must execute a QuickDraw drawing routine that calls one of the grafProcs. In this case, the MoveTo/Line combination is sent firing the StdLine grafProc. When StdLine executes, it notices that the GrafPort has been reinitialized, and therefore initializes the clipping region for the port. Until the MoveTo/Line combination is executed, the clipping region for the port is set to (0,0,0,0). If PostScript code is sent via the PostScriptHandle PicComment before executing any QuickDraw routines, all PostScript operations will be clipped to (0,0,0,0). The next thing to do is send the PostScriptBegin PicComment. This comment is recognized only by PostScript printer drivers. When the driver receives this comment, it saves the current state of the PostScript device (by executing the PostScript gsave operator), then disables all QuickDraw drawing operations. This way, the QuickDraw representation of the Graphic will be ignored by PostScript devices. In the previous example, the MoveTo/LineTo combination is only executed on non-PostScript devices. The next comment is the PostScriptHandle PicComment. This tells the driver that the data in thePSHandle is to be sent to the device as PostScript code. The driver then passes this code unchanged to the PostScript device for execution. The PostScriptHandle PicComment is only recognized by PostScript printer drivers. The last PicComment, PostScriptEnd, tells the driver to restore the previous state of the device (via a PostScript grestore call), and to enable QuickDraw drawing operations. Since all PicComments are ignored by QuickDraw devices, only the QuickDraw representation is printed. Since PostScriptBegin tells PostScript drivers to ignore QuickDraw operations, only the PostScript representation is printed on PostScript devices. This is a truly device- independent method for providing both PostScript and QuickDraw representations of a document.
Graphics, Imaging & Printing: PostScript: PicComment TextIsPostScript versus PostScriptHandle
When using the Macintosh® TextIsPostScript picture comment, my PostScript code is also “printed” on the ImageWriter®. Why isn’t it ignored?
One of the comments, TextIsPostScript, allows the application to use the QuickDraw™ DrawString procedure to send the PostScript® code. This method is no longer recommended, as it is not device independent. If you use the TextIsPostScript comment when printing to a non-PostScript device, the PostScript code will be printed as text. On an ImageWriter, the entire PostScript program will be printed as one line on the page, because the TextIsPostScript PicComment is ignored by the ImageWriter drivers, and the DrawString calls are executed normally.
To avoid this problem, developers should use the PostScriptHandle comment. This comment accepts a handle as a parameter. The handle points to the PostScript code that you want to download. This comment is better for two reasons:
First, there is no QuickDraw/PostScript interaction. For example, early versions of the LaserWriter® driver sent the strings passed to DrawString as- is. The latest version of the driver appends carriage returns onto those strings. If your application is expecting the DrawString calls to work one way or another, you might get a surprise.
The other reason for using the PostScriptHandle comment involves device independence. When a non-PostScript driver sees the PostScriptHandle PicComment, it not only ignores the comment, but also ignores the PostScript data that was passed to the comment, so nothing prints if you use the PostScriptHandle comment on a non-PostScript driver.
Graphics, Imaging & Printing: PostScript: LaserWriter driver and PostScript showpage
When I print a PostScript® file, why do I get one blank page for every page printed?
Your PostScript file probably contains calls to the PostScript showpage operator. This operator is also called by the Macintosh® LaserWriter® driver when it receives the PrClosePage call. The solution to this problem is to strip showpage calls from the file before sending the file to the LaserWriter. If you send one QuickDraw™ graphic at the beginning of each page,
MoveTo(-32000, -32000);
Line(0, 0);
the LaserWriter driver will handle calling showpage for you. Versions of the LaserWriter driver before 5.2 do not send the showpage operator unless a QuickDraw drawing routine (that is, something other than PicComment) is sent. This is why you need to do the MoveTo/LineTo. Versions 5.2 and later will send the showpage operator whether any QuickDraw has been sent or not. Since you can’t be sure whether showpage will be sent for you or not, the best solution is to let the LaserWriter driver send it.
Graphics, Imaging & Printing: PostScript: Macintosh spooling should be device independent
How can I tell whether the chosen printer supports PostScript® or not?
There is no supported method for determining whether or not a device speaks PostScript. Apple engineering would like all Macintosh® applications to spool both PostScript and QuickDraw™ regardless of the chosen printer, so that the spool file is device-independent and can be redirected after spooling. Since engineering is strongly encouraging developers to spool both models, it is doubtful that Apple will be providing a query mechanism in the future. The best method is to assume PostScript is available, and format your document based on information returned by PrGeneral and the print record.
Graphics, Imaging & Printing: Printer Access Protocol (PAP): Monitoring PAP PostScript packets with AppleTalk Peek
Are there hardware or software tools for monitoring AppleTalk Printer Access Protocol (PAP) packets in some direct way?
A tool called “AppleTalk Peek” allows you to monitor packets that are being sent over AppleTalk. It is available on the AppleLink and on the latest Develope CD Series disc. You can find the tool via the following path: Storage and Communication Folder : Network Folder : AppleTalk Tools Folder. This tool might enable you to determine experimentally, PostScript handle sizes that work best for your application.
Graphics, Imaging & Printing: Printer Access Protocol (PAP): Using PAP & code for finding printer driver under System 7
Is there any documentation or sample code on the Printer Access Protocol (PAP), besides Inside AppleTalk® and MacTutor’s sample? Or is there a better way to shove 1 MB and larger files down the pipe to a PostScript® device?
The question that you ask has become a popular one these days; it seems that a lot of people are writing PAP programs. Unfortunately, there isn’t really a clean-cut answer. There are several options:
1) The code that appeared in MacTutor seems to work just fine. Of course, it is unsupported by Apple and it may very well break under a future system software release. It is definitely the quickest way to get a PAP-based program coded.
2) You could write your own PAP interfaces. This is a very time consuming operation, but it also most likely not to break under future systems. Other companies have done it, and it is fairly straightforward.
3) Through software licensing, you can license a library named papworkstation.o. It is a library only, with little or no documentation, and it is unsupported. It is, however, used by several third parties, and it works OK.
In case you do use the MacTutor code, the following example shows a method for finding the printer driver under System 7:
FUNCTION GetPAPDriver: BOOLEAN;
VAR
theResFile: INTEGER;
theWorld: SysEnvRec;
theError: OSErr;
DoinFolders: BOOLEAN;
myFeature: LONGINT;
sysVRefNum: INTEGER;
sysDirID: LONGINT;
gotDriver: BOOLEAN;
numStr: Str255;
BEGIN
gotDriver := TRUE;
DoinFolders := FALSE;
(*--------------------- The 7.0 Way! --------------------------*)
IF GestaltAvailable THEN BEGIN
theError := Gestalt(gestaltFindFolderAttr, myFeature);
IF theError = noErr THEN BEGIN
DoinFolders := BitTst(@myFeature,
31-gestaltFindFolderPresent);
IF DoinFolders THEN BEGIN
theError := FindFolder(kOnSystemDisk, kExtensionFolderType,
kDontCreateFolder, sysVRefNum, sysDirID);
IF theError <> noErr THEN BEGIN
DebugStr('FindFolder err');
gotDriver := FALSE;
END;
END;
END;
END;
(* If FindFolder was not available, use good ol' SysEnvirons (thanks Jim)*)
IF NOT DoinFolders THEN BEGIN
(* No FindFolder! Gotta do it the old way... *)
theError := SysEnvirons(1, theWorld);
IF theError = noErr THEN
sysVRefNum := theWorld.sysVRefNum
ELSE
gotDriver := FALSE;
END;
(*----------------------------------------------------------------*)
(* Okay, at this point we should have found the folder where the*)
(* drivers are. If we are running under System 7.0, this folder*)
(* will be the extensions folder in the System folder. If we are*)
(* pre-7.0,this will be the System folder. If FindFolder was *)
(* available, then we have to use HOpenResFile because *)
(* FindFolder uses dirIDs. If we just used SysEnvirons (ie. pre *)
(* 7.0), then we can use OpenRFPerm. *)
IF gotDriver THEN BEGIN
IF DoinFolders THEN
theResFile := HOpenResFile(sysVRefNum, sysDirID, driverName, fsRdPerm)
ELSE
theResFile := OpenRFPerm(driverName, sysVRefNum, fsRdPerm);
theError := ResError;
IF theError = noErr THEN BEGIN
driverCode := GetResource('PDEF', 10);
HNoPurge(driverCode);
DetachResource(driverCode);
IF ResError = noErr THEN BEGIN
LWName := StringHdl(GetResource('PAPA', -8192));
DetachResource(Handle(LWName));
CloseResFile(theResFile)
END ELSE
gotDriver := FALSE;
END ELSE BEGIN
NumToString(theError, numStr);
DebugStr(numStr);
gotDriver := FALSE;
END;
END ELSE
gotDriver := FALSE;
GetPAPDriver := gotDriver;
END; (* GetPAPDriver *)
Graphics, Imaging & Printing: Printer Drivers: Update Backgrounder if using LaserWriter 7.0 under System 6
When we use the LaserWriter® driver 7.0 with System 6.0, the Chooser’s Background Printing “On” button is always dimmed. Is there any way to enable background printing?
To get the LaserWriter 7.0 driver to work with System 6.0.x, update your Backgrounder file with the version on the Printing Tools Disk that’s used to install System 7.0.
In short, to use the 7.0 LaserWriter Driver, 7.0 PrintMonitor, and System 6.0.x, place these files from the System 7.0 Printing Tools installation disks into your System Folder. All three must be used together for printing to work correctly. After you’ve placed these files in the System Folder, you should find the Background Printing option enabled for your use.
There are no known incompatibilities with the 7.0 drivers and System 6.0.x, so everyone should use the latest drivers, even with a mixed environment. This will also get rid of “printer wars” that occur when users use more than one version of the LaserWriter driver to print to the same printer. (The printer must be reinitialized if the current user uses a different version of the driver than what was used by the previous user.)
Graphics, Imaging & Printing: Printer Drivers: LaserWriter 6.1 versus 7.0 (use new installer for both)
What is the difference between the LaserWriter® driver version 6.1 and 7.0?
The 6.1 driver is basically an early release of the 7.0 driver. A number of bugs were corrected in the final 7.0 release. In terms of functional differences, there aren’t any. Some features just function a little bit more like they’re supposed to in the 7.0 version.
Since the 7.0 driver can be used with 6.0.x systems, there’s really no reason to use the 6.1 driver anymore. If you decide to use the 7.0 driver with a 6.0.x system, be sure to install it with the 7.0 installer. Several system files must be removed or updated to work with the 7.0 driver and the installer correctly handles this.
Graphics, Imaging & Printing: Printer Drivers: Printing directly to a LaserWriter from an Apple II application
How can my 8-bit Apple® II application print bitmapped graphics directly to a LaserWriter®?
To print directly to a LaserWriter from an Apple II, you have a few choices. All of Apple’s system software support assumes you’re going to connect the LaserWriter through an AppleTalk network, so that’s how most of your help for doing this is structured.
When you choose a given LaserWriter (either through Chooser II from ProDOS® 8 or from the LaserWriter cdev under GS/OS®), you can make sure something called the “ImageWriter® Emulator” is installed. IwEm is a PostScript® program that works with the Remote Print Manager (AppleTalk® software in the Apple II) so that direct ImageWriter commands sent to the AppleTalk port (which looks like a serial port) work. This works even for bitmapped graphics, although only at ImageWriter resolutions. If you’re using networked LaserWriters, you might choose to tell your users to pretend the printer is an ImageWriter connected to the network slot. As long as they’ve properly chosen the printer and downloaded the ImageWriter emulator, this will work fine.
If you want to directly connect the LaserWriter, you have only a couple of choices. You can use the Diablo 630 emulation, or the HP LaserJet emulation on those printers that have it, but that requires physically flipping a dip switch in some cases. The only other option is to do what the Macintosh® and Apple IIGS® printer drivers do—drive the printer by sending it PostScript commands to image your page. This will produce the best output at the cost of being the most difficult to code.
Instructions for emulations and direct PostScript modes are in the LaserWriter Reference, available from Addison-Wesley. Instructions on PostScript are available from Addison-Wesley as well, in one of several Adobe technical books or non-Adobe PostScript books.
Graphics, Imaging & Printing: Printer Drivers: Save and restore long word if using $948 under System 7
Unless my Macintosh® application restores the contents of the long word at $948 after using that space for globals, the Finder™ draws icons incorrectly and my third-party LaserWriter® driver crashes. Is somebody now using $948 for other purposes?
This is a known System 7 icon drawing bug, and also a bug with the printer driver that you are using.
The icon drawing utilities are trying to determine if a print page is currently open, by looking at that variable ($948 is part of printvars). This turns out not to be such a good idea, and it will be fixed in the next release of the system software.
The printer driver bug that you are experiencing is that every printer driver must return the variable at $948 to -1 when they are done printing. Also, while printing, the driver should set it to <> -1.
Graphics, Imaging & Printing: Printer Drivers: Where to get documentation on writing a Macintosh printer driver
Where is documentation on how to write a Macintosh® printer driver equivalent to the ImageWriter® or LaserWriter® driver?. In particular, how are Print Manager and QuickDraw™ commands translated into calls to the print driver? I also need information on how to install the driver into the Slot Manager.
See the “Learning to Drive Information” document in MacDTS’s Interim Technical Documents folder in the Developer Service icon on Applelink. You should also take a look in Inside Macintosh and in the reference Designing Cards and Drivers for information on the Slot Manager.
Graphics, Imaging & Printing: Printer Drivers: Determining if a printer driver accepts Color QuickDraw calls
How do you find out if a printer driver accepts Macintosh® Color QuickDraw™ calls?
Check to see if the printer driver has returned a color GrafPort to your application after the call to PrOpenDoc (that is, the port that PrOpenDoc returns).
To determine if the GrafPort is color, you need to check to see if rowBytes from the GrafPort are less than 0. The following code fragment demonstrates this idea:
(* This function determines if the port passed to it
is a color port. If *)
(* so, it returns TRUE. *)
FUNCTION ColorPort(portInQuestion: GrafPtr): BOOLEAN;
BEGIN
IF portInQuestion^.portBits.rowBytes < 0 THEN
ColorPort := TRUE
ELSE
ColorPort := FALSE;
END;
Graphics, Imaging & Printing: Printer Drivers: Writing a Macintosh printer driver
I have a printer I would like to connect to the Macintosh®. Where can I find information on writing a printer driver?
A Macintosh printer driver is more than a standard device driver. A printer driver contains code to implement all of the standard Macintosh Printing Manager routines. The code includes routines like PrOpen/PrClose, and PrOpenDoc/PrCloseDoc. A Printing Resource File contains all of the resources (including code) to implement the Macintosh Printing Manager for a particular device. A driver works best with all Macintosh applications if it supports both the high and low-level Printing Manager interfaces, as well as the PrGeneral (IM V:410) routine and its associated opcodes.
Apple is not currently supporting the development of Chooser-selectable device drivers, at least not those that support printers. There are many reasons for this, and here are at least a few of them:
First, there are no documentation or examples available. Each of the Apple® printer drivers is unique. They are all written almost entirely in 68000 assembler, and consequently, are not very easy to read. Since each driver is different, the only real documentation for how the drivers work is the source code to the driver. There is some general interface information available, but important information, like how the driver manages its print record, is described only in the source code. This information could be extracted and distilled into some kind of document, but this brings up the next problem:
The Macintosh Printing Manager is currently being revised and enhanced. These revisions will require major changes to the architecture of the Printing Manager. It’s not clear what effect these changes will have on existing printer drivers, but it is very possible that the drivers that exist today will have to be revised significantly to run under the new Printing Manager.
Apple is designing and implementing the next generation Macintosh Printing Manager. Developers’ suggestions for features are being taken into account. One of the goals of the new architecture is to make writing drivers much simpler, and to allow the sharing of code between drivers. When this architecture becomes available, Apple will reconsider its position of driver development, and will probably end up with some kind of licensing agreement for developers that want to write drivers. Until then, the preceding reasons should be adequate justification for NOT attempting a Macintosh printer driver at this time.
If you still aren’t convinced, and want to write a driver despite the challenge, see the article in the December ‘88 issue of MacTutor magazine. There is an example printer driver written in C. It is just a skeleton driver, and does not handle any of the more difficult problems such as line layout, font substitution, graphics, or banding. But it is a start, and gives you a general idea of the structure of a driver. Since some developers began writing their drivers before Apple discontinued support, DTS is still answering questions concerning driver development. However, these questions are limited to those that can be answered by the DTS engineers. You should also be aware that some of the techniques used by Apple® printer drivers are considered proprietary. Information on methods used for line layout as well as certain aspects of font handling will not be disclosed.
Graphics, Imaging & Printing: Printer Drivers: Macintosh print record wDev field
What is the Macintosh® print record wDev value for the ImageWriter® LQ, LaserWriter® IISC, and AppleFax™ Modem?
Apple strongly discourages the use of the wDev field in the print record for several reasons. First, this field contains a unique ID for each printer driver on the Macintosh. Coding your application to use this ID makes it device dependent, and device dependence will cause many problems in the future as the Macintosh Printing Manager continues to evolve. Many applications currently check for wDev = 3 to determine whether or not to send PostScript®. Although the Apple® LaserWriter driver has a wDev of 3, third party printer drivers for PostScript devices do not, so if you’re application determines whether or not to send PostScript based on wDev alone, your application may incorrectly print with QuickDraw™ on third party PostScript devices. A second problem concerns spoolers and spool files. If a spooler is installed between an application and the printer driver that is going to do the printing, the application receives the wDev ID of the spooler instead of the target driver. If the application makes assumptions based on this ID, it probably gets unexpected results. In the future, it may also be possible to redirect spool files. This means that a file that was originally spooled for a PostScript printer may be redirected to a QuickDraw device. If the spool file contains only the PostScript representation of the document, it will be useless to the QuickDraw device. Despite these strong warnings, some developers are convinced they need the wDev values, and there may be some vertical applications where they’re needed. For those cases, here is the current list of wDev IDs for Apple printer drivers:
Device wDev (Hi Byte)
ImageWriter I/II: 1
LaserWriter,
LaserWriter Plus,
LaserWriter IINT,
LaserWriter IINTX: 3
LaserWriter IISC: 4
ImageWriter LQ: 5
AppleFax Modem: 10
DTS does not support the use of these constants. They are definitely subject to change.
Graphics, Imaging & Printing: Printer Drivers: FractEnable (TRUE) disables Font Substitution
Why does enabling Macintosh® fractional font widths (FFWs) with FractEnable(TRUE) disable Font Substitution?
When you call FractEnable(TRUE), you are telling the Printing Manager that you always want to use the fractional width information in the FOND resource of a font. This fractional information is specified for a 1 point font, and can be scaled for any desired size. When you tell the Printing Manager to use this width information, the normal font width information (stored in the ROM of the LaserWriter®) is ignored. Font Substitution provides the ability to substitute high quality PostScript® fonts for fonts that have no PostScript equivalent. For example, a document laid out in Geneva will be printed with Helvetica® if Font Substitution is enabled. When this substitution occurs, the Printing Manager makes adjustments to the intercharacter spacing of the line to make the printed Helvetica version match the width of the Geneva version displayed on the screen. When you enable fractional font widths for a document that uses Geneva, the Printing Manager is being told to print Helvetica characters on the printer using fractional widths from the Geneva screen font. If the Printing Manager placed the Helvetica characters using the fractional widths, formatting problems might occur. For example, some of the Helvetica characters may be wider than their Geneva equivalents, causing character collisions. To avoid this problem, the LaserWriter driver disables the Font Substitution option when fractional fonts are enabled, so that WYSIWYG is maintained. If you want to use fractional fonts, format your document using fonts that have PostScript versions available on the LaserWriter.
Graphics, Imaging & Printing: Printing: Getting Mac Page Setup dialog’s “Reduce or Enlarge” value
Is it safe to get the Macintosh Page Setup dialog’s “Reduce or Enlarge” value from the TPrint.prXInfo.iBandH record, or is there a better way to tell if it’s been changed?
You don’t want to rely on the value contained in TPrint.prXInfo.iBandH to determine if “Reduce or Enlarge” has been selected by the user if you want to avoid possible compatibility problems with other printer drivers. The best and cleanest approach to determining if “Reduce or Enlarge” has been selected is to check the value of rPage (Inside Macintosh Volume II, page II-150). rPage is the printable area for the currently selected printer.
For example, when the user does not change the value of “Reduce or Enlarge” (the field defaults to 100%), rPage is 0, 0, 730, 552. If 50% is selected, rPage changes to 0, 0, 1460, 1104, which is a factor of 2 greater than the 100% case, thereby printing your image at half its original size.
This method works without any difficulties until the user selects “landscape” printing. It still works, but you need to check for this condition. Let’s look at how the numbers change: If “landscape” is selected, and “Reduce or Enlarge” is 100%, rPage is set to 0, 0, 552, 730. Notice that the values for bottom and right have been swapped. Everything still works, but you need to make sure that you notice the change to use the correct values for calculating the “Reduce or Enlarge” factor.
You can check for this change to “landscape” printing by comparing the bottom and right values in rPage, or you can use PrGeneral’s GetRotn opcode to determine if “landscape” has been selected by the user. See the July issue of develop and Inside Macintosh Volume V, pages 410-415, for details about using PrGeneral and the GetRotn opcode.
Graphics, Imaging & Printing: Printing: Displaying document name in Print Monitor box
How do I include the name of the document in the Print Monitor window?
Macintosh Technical Note #149, “Document Names and the Printing Manager,” explains how to get the Print Manager to display the name of the document that you’re printing. Basically, this should already work, unless you don’t have a window open when printing or if the name of the window is something other than the name of the document you’re printing (like “Untitled”). The tech note also explains how to create the window with the appropriate title so that it appears invisible to the user in case you don’t want to show a window for some reason.
You also need to call PrValidate between PrClose and PrOpen for the next document if you want the name of the next document to correctly appear when it’s printed.
Graphics, Imaging & Printing: Printing: Troubleshooting 7.0bx/LaserWriter problems
My Macintosh® is bombing all over the place every time I try to print with the LaserWriter® (and the PrintMonitor isn't helping) with System 7.0bx. Please advise.
We are using 7.0bx in our department with no problems printing to a variety of LaserWriters from both 7.0 and 6.x systems. I suspect your problem is related to either an incompatibility with some specific product or that the system software is corrupted. Here are a couple of things to try: First, hold down the Shift key while booting to disable all system extensions (INITs), set addressing to 24 bit, turn off filesharing and VM. Try printing. If it works, then add things back in one at a time to find the incompatibility. If it still bombs, then trash the 7.0 system folder and reinstall from scratch. Try using only Apple hardware, no third-party devices or software drivers.
Graphics, Imaging & Printing: Printing: Choosing a printer from within an application
Is it possible to select a printer among several printers programmatically instead of having to go to the Macintosh® Chooser each time?
Unfortunately, the answer is no. It obviously violates lots of human interface guidelines, but beyond that it would almost require the writing of a single printer driver that could support all of those different printers (a tremendous undertaking).
A little background might help explain the problems. The type of the currently selected printer is stored in the System file in 'STR ' resource ID -8192. This will be the name of the driver selected, such as LaserWriter® or ImageWriter®. The name of the actual printer selected will be in the driver file (same name as the printer type chosen) in 'PAPA' resource ID -8192. Look at this resource with ResEdit™ to see what is in it.
In programs that support such a thing (for example, 4D), you could write an External procedure to modify the name of the actual printer. I guess you could also modify the name of the driver selected, but unless your system never changes, this would almost certainly cause you headaches (for example, better not try to select a driver that has changed its name).
In a nutshell: You can change the 'STR ' and 'PAPA' resources, but it may not work now or in the future. We do not recommend changing the system file or circumventing the Chooser. Further, any program that depends on these resources or tries to change the selected printer will almost certainly break with future releases of the system software.
The least objectionable solution I can think of is to set up a QuickKeys macro that automates changing between printers via the chooser.
Graphics, Imaging & Printing: Printing: Modifying PDEFs to have printer driver jump into dialog code
Could you please point me to the correct section in “Learning to Drive” (or send me an example) that we would need to modify the appropriate PDEF resource in order to have the driver jump to our dialog code?
Pages 15-18 discuss the contents of the various PDEFs. You will need patch the appropriate PDEF to get your required functionality. You should also realize that patching PDEFs is not an easy task, nor will it always survive “new” Macintosh® LaserWriter® driver releases. I want you to know that before you go too far down the PDEF patching road.
By the way, we do know of a couple of developers that have patched PDEFs successfully. The following paragraphs are a “high-level” look at patching a PDEF:
To patch a PDEF, you must write an installer application that lets users choose the printer driver they want to modify via Standard File. You can cause Standard File to display only printer drivers by telling it to display only files of type “PRER”. Once the user has selected a driver you need to scan the driver for the PDEF 0 and 1 resources. When you find one of these you read it in and modify it.
However, I'll give you a quick overview of what you need to do. PDEF 0 & 1 both start with jump tables (a table of JMP instructions followed by the PC relative address to jump to). The JMP to PrClosePage always begins at offset 12. So what your installer needs to do after it loads the resource is grab the eighth word in the resource. That is the offset to the actual start of the PrClosePage code. Then you have to resize the handle so that it is big enough to hold your patch and then BlockMove {IM II-44} your code into the end of the handle. The following illustration might help:
JMP $0486 << Note: some PDEF's have multiple
JMPs at the beginning of the
* - - - - - - - - - - - - - * code. The original offset to
* * PrClosePage was $0386.
* >> Original PDEF code << *
* *
$0386 --> PrClosePage << Note: most PDEF's have
* * multiple printing calls defined.
* *
* *
* - - - - - - - - - - - - - *
$0486 --> {{{ Your Code }}}
* * << You resize the resource
* * handle to this and blockmove
* * your code in here.
* *
* - - - - - - - - - - - - - *
JMP $0386 << At this point we jump into
the printer driver's original
code for PrClosePage.
Note: The previous illustration is not to scale nor completely accurate in regards to the addresses used. Please consult “Learning To drive” for the correct offsets for each PDEF.
Then replace the original offset to PrClosePage with the offset to your new code. Remember that this is PC relative so you would calculate it like this: If the original PrClosePage JMP was JMP 10(SP) and the size of the original PDEF was 50 bytes, then you need to replace the JMP 10(SP) with JMP 50-16(SP). In other words, you need to JMP to what was formerly the end of the PDEF resource but what is now the beginning of your code (subtract 16 because the offset table is 16 bytes long. Refer to “Learning to Drive” for more details). Then on the end of your code, add a JMP ((SizeOfJumpTable + originalOffset) – (sizeofOriginalPDEF + SizeOfYourCode))(SP). Your code will end with a JMP to a negative offset off the PC back to the original PrCloseRoutine.
If you are willing to support “Post 3.3” systems only (basically that means that you won’t be supporting Macintosh 512K and 512KE computers), you don’t have to deal with all the PDEF changing, and you can simply patch out the $A8FD trap and look for the proper selector on the stack. (Use SysEnvirons to be sure that you are on a Post 3.3 system.) This will work because the newer libraries (that is, any library that shipped since the Macintosh II shipped) first checks for the trap and jumps there if the trap exists so even if the application has linked in the printing library they still end up calling the trap on systems after Post 3.3.
Graphics, Imaging & Printing: Printing: Call Printing Mgr’s bottleneck to send StdText to printer driver
We need to use the Macintosh® toolbox call StdText instead of DrawChar, DrawString, and DrawText to accomplish horizontal scaling and fractional point sizes, but StdText does not work on the LaserWriter® IISC. Is there any workaround?
The problem is that you are calling the low-level bottleneck directly, and the Printing Manager has replaced the bottleneck completely with its own. So when you are actually printing, the print driver will not see your call to StdText. The work-around for this is to call the Print Manager’s bottleneck itself when you are printing. You can do this in the following way:
/* typedef the function */
typedef pascal void (*StdTextProcPtr)( short, Ptr, Point, Point );
void tstDrawStuff( pInfo, thePort, pageNum )
TPrint pInfo;
GrafPtr thePort;
unsigned short pageNum;
{
StdTextProcPtr Proc; /* declare a variable here */
/* do your clipping etc. */
/* TEST -- no good w/o PriMon */
/* do your moveto etc. */
/* Is there a replacement bottleneck ?*/
if ( thePort->grafProcs ) {
Proc = (StdTextProcPtr)thePort->grafProcs->textProc; /* yes, so
grab it */
(*Proc)( strlen("HELLO") , (Ptr) "HELLO", numer, denom );
}
/* else just call standard text */
}
This technique will work in both background and foreground printing. I have tested this solution on the Personal LaserWriter SC and the LaserWriter IINTX, and it prints fine.
Graphics, Imaging & Printing: Printing: System 6.0.x and Color Printer software compatibility
Which versions of Apple® Color Printer software work with which Macintosh® system software versions? Can Apple Color Printer software distributed with System 6.0.7 work with previous system software releases?
The software sent with System 6.0.7 will work with all other System 6.0.x systems. This should be the rule with most other LaserWriter® printer software, as well. There really isn’t any simple way (yet) to match up the version of the printer software with the version of the system software with which it is compatible. Starting with System 7.0, they are hoping to keep this type of system matching standard throughout. This is not a guarantee, just something that is being considered.
Graphics, Imaging & Printing: Printing: Apple IIGS Parallel.Card driver prints to first card found
How can I get the Apple IIGS® Print Manager to print to the parallel card I choose when more than one is in my system?
The port driver provided with the system (the file Parallel.Card) searches for a card with which it can communicate in the PrDevIsItSafe routine, as documented in Apple IIGS Technical Note #36. The search routine scans upward starting with slot one, stopping when it finds a suitable card. The driver will always print to the card in the lower-numbered slot; it has no facilities to let the user choose among all suitable interfaces.
Graphics, Imaging & Printing: Printing: Macintosh System 7 printing architecture is same as System 6
Is the Macintosh® printing architecture different for System 7?
No changes were made to the printing architecture for System 7. Printer drivers were revised for System 7 to support TrueType™, to be completely 32- bit clean, and to fix bugs, but the printing architecture remains the same for System 7.
Graphics, Imaging & Printing: Printing: Macintosh Printing Manager error -8133
What is Macintosh® Printing Manager error -8133?
Printing Manager error -8133 occurs when the PostScript® interpreter of the LaserWriter® (or any other PostScript printer) generates a PostScript error. A description of the PostScript command that caused the error is displayed in the status window. This error often occurs when an application sends PostScript directly to the printer, and that PostScript contains an error. To debug this problem, look at the PostScript generated by the driver. Hold down the Command-F key right after clicking okay in the Print dialog. A file named PostScript0 will be created in the current directory.
Graphics, Imaging & Printing: Printing: Customizing Macintosh printer page sizes
I am printing checks, labels, etc. and the page sizes provided by the Apple® Macintosh® printer driver are not sufficient. How can I customize these page sizes?
Most printer drivers (Apple as well as third-party) do not support customization of their page sizes by an application, because the page sizes provided are usually based on physical characteristics of the device. On some devices, printing outside of the imageable area of the page (specified by prInfo.rPage) can cause physical damage to the printer, so customization of page sizes is generally discouraged. However, there are some valid reasons for wanting to customize the page size of a driver, and there are applications available that provide this feature. Since this is one of the most requested features (by developers), expect to see some Printing Manager support for customizing page sizes in the future. Until then, there are two ways to go:
1. Pound the print record: Most applications that allow you to customize page sizes relay the custom page size information by storing into fields of the print record. When the print record is subsequently passed to PrValidate, the driver recalculates its internal buffers based on the information in the print record. There are a number of reasons, however, that DTS does not support this method. First, the print record is a device-dependent, private structure. Although most of the record is documented in Inside Macintosh, only a few fields are needed by the application at print time, such as rPage, iCopies, and bJDocLoop. There are only a few of these fields that applications need to modify: iCopies if application handles multiple copies, iFstPage/iLstPage if application handles page ranges, and others. Most of the fields in the record are global variables of the current printer driver. When an application starts writing to other fields in the print record, it has to make assumptions about the driver’s interpretation of these changes. Since the print record is “owned” by the printer driver, developers are free to change the format of the record as they require. Although important fields like rPage are likely to remain available for applications to read, writing to these fields may lead to undesirable/unpredictable results. Rather then taking this compatibility risk, DTS recommends that you either wait for a supported solution from engineering, or consider method 2 below.
2. Semi-supported solution: This solution is “semi-supported” because it only works on three of Apple’s devices; ImageWriter® I, II, and LQ. The default page sizes provided by the Apple printer drivers are stored in a resource of type 'PREC' with an ID of 3. The format of this resource is as follows:
PageSizeRecord = RECORD
numItems: INTEGER;
botRights: ARRAY [0..NumPageOptionsZB] OF Point;
titles: PACKED ARRAY [0..0] OF CHAR;
END;
numItems is the number of page sizes displayed in the dialog. The maximum number is six (since there is only room for six radio buttons in the Page Setup dialog). botRights is an array of points specifying the bottom right corner for each page. This corner is specified in 120ths of an inch, and it should define the physical size of the paper, not the imageable area. For example, U.S. Letter is specified as:
bottom = 1320(11"), right = 1020(8.5"). titles is a packed array of page size names. Each name begins with a length byte, followed by the number of characters specified by the length byte. The strings are packed, so
string1[LENGTH(string1)+1]
would reference the length byte of string2. To use this mechanism, your application should create a PREC resource with an ID = 4. You can do this very easily by copying PREC(3). Once you have a copy, you can modify the page sizes as you wish. When the printer driver is called to display the Page Setup dialog, it will first look for PREC(4). If found, it will use it to define the page sizes. If not found, the driver will use the standard sizes in PREC(3). This method is supported only by the Apple ImageWriter drivers. Other drivers (including the LaserWriter® and LaserWriter IISC) will ignore the resource. If you decide to implement this feature in your application, be sure to warn your users that custom page sizes may not be available on all devices. For a Pascal example of this method, send an AppleLink® message to DTS and ask for “PagePounder.”
Graphics, Imaging & Printing: Printing: Low-level Printing Manager interface changes
My Macintosh® application uses the low-level interface to print to the ImageWriter® just fine, but crashes when printing to the LaserWriter®. Why?
The original model documented in Volume II of Inside Macintosh (pages 163-164) for opening and closing the low-level Printing Manager interface looked like this:
PrDrvrOpen;
PrCtlCall(iPrDevCtl, lPrReset, 0, 0);
{ Image data sent here via other control calls... }
PrCtlCall(iPrDevCtl, lPrPageEnd, 0, 0);
PrDrvrClose;
This worked fine on all LaserWriter drivers up to version 5.0. Now in 5.0 and later versions of the driver, applications are required to follow this model (documented in Tech Note #192):
PrDrvrOpen;
PrCtlCall(iPrDevCtl, lPrDocOpen, 0, 0);
PrCtlCall(iPrDevCtl, lPrPageOpen, 0, 0);
{ Image data sent here via other control calls... }
PrCtlCall(iPrDevCtl, lPrPageClose, 0, 0);
PrCtlCall(iPrDevCtl, lPrDocClose, 0, 0);
PrDrvrClose;
This is because the newest LaserWriter driver is actually converting the low level calls into their high-level equivalents before executing them. This makes for a cleaner internal structure for the driver.
Graphics, Imaging & Printing: Printing: Macintosh color printing code sequence
I have an application running in Color on the Macintosh® II. What is the recommended method for printing in Color?
Your application should first call SysEnvirons to check for Color QuickDraw™. If Color QuickDraw is available, you should then check the portBits of the Printing Manager’s GrafPort (returned by PrOpenDoc).
IF printingPort.gPort.portBits.rowBytes < 0 THEN BEGIN
{ Printer driver supports color, use Color Quickdraw calls }
{ to image data. }
RGBForeColor(RGBred);
RGBBackColor(RGBgreen);
MoveTo(100, 100);
LineTo(200, 200);
END ELSE BEGIN
{ Printer driver does not support color, use }
{ Quickdraw color calls or PostScript®... }
PicComment(PostScriptBegin, 0, NIL);
{ Quickdraw representation for ImageWriter® and other }
{ non-PostScript printers. }
ForeColor(redColor);
BackColor(greenColor);
MoveTo(100, 100);
LineTo(200, 200);
{ PostScript representation for imaging with halftones. }
{ This should be used only when the driver for a device }
{ doesn’t support color. See the question, 'How do I }
{ use the PostScript image operator to print halftones?'}
thePSHandle^^ := '.75 setgray 100 100 moveto 200 200 lineto';
PicComment(PostScriptHandle,GetHandleSize(thePSHandle),thePSHandle);
PicComment(PostScriptEnd, 0, NIL);
END;
Graphics, Imaging & Printing: Printing: Update Macintosh color table if printing in color
I’m having trouble printing in color. When I copy a color image from a Macintosh® offscreen pixmap to the printer, I get a black piece of paper. If I draw directly it comes out fine. What am I doing wrong?
When you built your offscreen port and copied the color table from a GDevice, did you change the color table to reflect that the color table is now part of a pixmap? In a GDevice the color table’s value field is zero for all entries, but in a pixmap the value field represents the index value of each color in the table. If the color table has not been converted, printing won’t work properly.
Graphics, Imaging & Printing: Printing: Printing halftone images on the LaserWriter
How can I print halftone images on the LaserWriter®? How do I use the PostScript® “image” operator for printing halftones?
The PostScript “image” operator is similar to the Macintosh® QuickDraw™ CopyBits routine. It can be used by converting a QuickDraw bitmap/pixmap into an image call. This is only necessary if you are printing color information with a PostScript printer driver that doesn’t support Color QuickDraw. LaserWriter drivers up to 5.2 do NOT support Color QuickDraw. If you want to send color information to a LaserWriter with version 5.2 of the driver, you will have to convert your color images into image commands. Before doing this it is important to check the GrafPort returned by PrOpenDoc. If this port is a Color QuickDraw port (for example, portBits.rowBytes < 0) then you should use Color QuickDraw commands and let the driver handle the conversion to PostScript.
About image: The PostScript image operator is used to send bitmaps or pixmaps to the LaserWriter. The image operator can handle depths from one to eight bits per pixel. Our current LaserWriters can image only about 16 shades of gray, but the printed page will look like there’s more. Because the image operator is still a PostScript operator, it expects its data in the form of hexadecimal bytes. The bytes are represented by two ASCII characters(“0”-”9,” “A”-”F”) per byte. The image operator takes these parameters:
width height depth matrix image-data
The first three are the width, height, and depth of the image, and the matrix is the transformation matrix to be applied to the current matrix. See the PostScript Language Reference Manual for more information. The image data is where the actual hex data should go. Instead of inserting the data between the first parameters and the image operator itself, it is better to use a small PostScript procedure to read the data starting right after the image operator. For example:
640 480 8 [640 0 0 480 0 0] {currentfile picstr readhexstring pop} image FF 00 FF 00 FF 00 FF 00...
In the preceding example, the width of the image is 640, the height is 480, and the depth is 8. The matrix (enclosed in brackets) is set up to draw the image starting at QuickDraw’s 0,0(top left of page), and with no scaling. The PostScript code (enclosed in braces) is not executed. Instead, it is passed to the image operator, and the image operator calls it repeatedly until it has enough data to draw the image. In this case, it is expecting 640*480 bytes. When the image operator calls the procedure, it does the following:
1. Pushes the current file which in this case is the stream of data coming to the LaserWriter over AppleTalk®. This is the first parameter to the readhexstring operator.
2. Pushes picstr. picstr is a string variable defined to hold one row of hex data. The PostScript to create the picstr is:
/picstr 640 def
3. readhexstring is called to fill picstr with data from the current file. It begins reading bytes which are the characters following the image operator.
4. readhexstring leaves the string we want, and a boolean that we don’t want, on the stack, so we do one pop to kill off the boolean. Now the string is left behind for the image operator to use.
Using the above PostScript code you can easily print an image. Just fill in the width height and depth, and send the hex data immediately following the PostScript code.
Setting up for image: Most of the users of this technique are going to want to print a Color QuickDraw pixmap. Although the image command does a lot of the work for you, there are still a couple of tricks for performance:
Assume the maximum depth: Since the current version of the image operator has a maximum depth of eight bits/pixel, it is wise to convert the source image to the same depth before imaging. You can do this very simply by using an offscreen GrafPort that is set to eight bits/pixel, and then using CopyBits to do the depth conversion for you. This does a nice job of converting lower resolution images to 8 bits/pixel.
Build a color table: An eight bit deep image can use only 256 colors. Since the image that you are starting with is probably color, and the image you get will be grayscale, you need to convert the colors in the source color table into PostScript grayscale values. This is actually easy to do using the Color Manager. First create a table that can hold 512 bytes. This is two bytes for each color value from 0 to 255. Since PostScript wants the values in ASCII, you need two characters for each pixel. Now loop through the colors in the color table. Call Index2Color to get the real RGB color for that index, and then call RGB2HSL to convert the RGB color into a luminance value. This value is expressed as a SmallFract which can then be scaled into a value from 0 to 255. This value should then be converted to ASCII, and stored at the appropriate location in the table. When you are done, you should be able to use a pixel value as an index into your table of PostScript color values. For each pixel in the image, send two characters to the LaserWriter.
Sending the data: Once you have set up the color table, all that’s left to do is loop through all of the pixels, and send their PostScript representation to the LaserWriter. There are a couple of ways to do this. One is to use the low-level Print Manager interface and stream the PostScript using the stdBuf PrCtlCall. Although this seems like it would be the fastest way, the latest version of the LaserWriter driver (5.0) converts all low-level calls to their high level equivalent before executing them, so the low-level interface is no longer faster than the high level. Another way is to use the high-level Print Manager interface, and send the data via the PostScriptHandle PicComment. This enables you to buffer a large amount of data before actually sending it. Using this second technique, you should be able to image a Macintosh II screen in about 5 minutes on a LaserWriter Plus, and about 1.5 minutes on a LaserWriter II NTX.
Graphics, Imaging & Printing: Printing Resources: Animate! graphics file format
How can I access Brøderbund’s Animate! graphics files from my Apple® II application?
If you’re looking for documentation on the Animate! file format, you will haveto contact Brøderbund software. As the authors of that format, they would be able to give you more information about it.
Graphics, Imaging & Printing: Printing Resources: Identifying Macintosh’s currently selected printer
How can I find out which printer the user has selected with the Macintosh® Chooser? How can I change it without going through the Chooser?
The type of the currently selected printer is stored in the System file in 'STR ' resource ID -8192. This will be the name of the driver selected, such as LaserWriter® or ImageWriter®. The name of the actual printer selected will be in the driver file (same name as the printer type chosen) in 'PAPA' resource ID -8192. Look at this resource with ResEdit™ to see what is in it.
You can change the 'STR ' and 'PAPA' resources, but it may not work now or in the future. WE DO NOT RECOMMEND CHANGING THE SYSTEM FILE OR CIRCUMVENTING THE CHOOSER! The Chooser is a very complicated piece of software, and it has many dependencies. Implementing the chooser within your application would make your application dependent on a particular version of the system software. Like the Chooser, your application would then have to be revised each time a new system is released.
Graphics, Imaging & Printing: Printing Resources: How to save Macintosh Page Setup and Print dialog options
How do I save options set in the Macintosh® Page Setup and Print dialogs?
The only supported method to save the dialog options is to save the Print Record that was passed to the PrStlDialog/PrJobDialog calls. This print record contains the options chosen in the Page Setup and Print dialogs. Although these options are saved in the print record, they cannot be used as defaults for the Page Setup. For example, say the user chooses landscape printing in the page setup dialog, and sets the number of copies to 5 in the print dialog. If the print record is passed to PrStlDialog, the dialog shows that landscape printing was selected in the print record. However, if that print record is passed to PrJobDialog, number of copies is shown as 1, because options in the PrJobDialog are considered to be “job dependent,” as opposed to “document dependent.”
The best method for saving the print record is to save it as a resource in your document’s resource fork. Since the print record is already pointed to by a valid handle, creating a resource is easy. Here are the required steps:
1. Save the refNum returned by CurResFile;
2. Make sure the resource fork of the document file is opened using
OpenResFile (IM I:115).
3. Now that you have a place to put the resource, you must get the resource manager to create it for you. First, pick a type and ID for your resource. You can use the Unique ID function (IM I:121) to generate the ID. Next, call the AddResource procedure (IM I:124). This procedure takes four parameters:
Parameter Type What to Pass
--------------------------
theData Handle The handle to the currently valid print record.
theType ResType The four character resource type you have
chosen.
theID INTEGER The ID returned from the UniqueID function.
name Str255 The name for this resource or '' if none.
4. Call WriteResource (IM I:125), and UpdateResFile (IM I:125) to make sure the new resource gets saved into the file.
5. Reset the currently selected file back to whatever it was before you began the save using UseResFile (IM I:117).
The important things to keep in mind when doing this are:
1. Make your resource type something different than those used by the Print Manager. This prevents the Print Manager from getting confused and grabbing the wrong resource. Types to avoid include 'PREC', 'PDEF', and 'POST'.
2. Don’t make any assumptions about the size of the print record. If you really need to know the size, use GetHandleSize.so that if the record gets bigger in the future, your code will still work.
3. Be sure to pass the record that you get from your document to PrValidate before using it. This ensures that the record gets updated if any changes have been made to record structure or contents since the record was saved.
Graphics, Imaging & Printing: PrintMonitor: Workaround code if Print Monitor changes custom palette
When our application prints with Print Monitor active, Print Monitor changes our custom screen color lookup table (CLUT) created with the Palette Manager.
A solution to your problem, until this Print Monitor problem is fixed, is to save your custom palette and restore it if the Print Monitor changes it. The following code segment does the trick:
<<<< Initialize oldSeed >>>>
oldSeed = (*(*(*GetMainDevice ())-> gdPMap)->pmTable)-> ctSeed;
• • Additional code • •
case updateEvt:
if ((WindowPtr) myEvent.message == myWindow) {
if (oldSeed != (*(*(*GetMainDevice ())-> gdPMap)->pmTable)-> ctSeed)
{
oldSeed = (*(*(*GetMainDevice ())-> gdPMap)->pmTable)-> ctSeed;
ActivatePalette (myWindow);
}
BeginUpdate (myWindow)
• • Additional code • •
If you put this piece of code inside your event loop where you check for update events, it should work without any problems.
Graphics, Imaging & Printing: PrintMonitor: Location for spool files under System 7.0
Is there a recommended location for printer driver writers to put their own spool files?
Place it in the “PrintMonitor Documents” folder within a “personal spool” folder. PrintMonitor will ignore other folders and it will delete its spool file when it was done with it.
The biggest advantage with this approach is that all the spool files end up in the same location, which is probably the best solution for the native user.
There are a few cases when the folder might not be present (such as if the user has deleted it for some reason). Therefore, you should check to make sure that the folder is present before trying to add a file to it. If it is not present, be sure to create it with the exact name; otherwise, PrintMonitor will not be able to find it and will create a second folder with a different name, possibly confusing the native user. Folder management is relatively straightforward with the addition of the “Folder Manager” to System 7.0. The Finder™ chapter in Inside Macintosh Volume 6 contains the details about using it.
Graphics, Imaging & Printing: PrintMonitor: Background printing no longer affects color environment
Why does the color environment of our Macintosh® application get messed when I use background printing on the LaserWriter® II? We are using the Palette Manager. When I trace the code I notice that I am getting an update event for all the windows of the application when the printing completes. Calls to activate the palette (ActivatePalette) and set the windows palette (SetPalette) have no effect. As soon as a window is resized or moved the color environment is corrected.
The problems that you having been encountering with the Print Monitor affecting the color environment after the print job has been completed have been fixed in LaserWriter driver v7.0a12. The LaserWriter driver on the System 7.0 beta CD contains this fix.
This version of the driver will work on Systems 6 and 7, but it cannot be shipped with your application until System 7.0 is final.
Graphics, Imaging & Printing: PrintMonitor: Macintosh PicComments and background printing
My Macintosh® application prints fine when Background Printing is disabled, but doesn’t print or prints blank pages when Background Printing is enabled. Why?
The Printing Manager gets execution time by replacing the grafProcs of the
Printing Manager GrafPort (returned from the PrOpenDoc call). This GrafPort is created by the PrOpenDoc call, and is reinitialized by every call to PrOpenPage. On the LaserWriter® driver with Background Printing enabled, this reinitialization causes the clipping region of the port to be set to (0,0,0,0). On the next call to StdLine or StdText, for example, the Printing Manager notices the zeroed clipping region, and sets it to the rectangle specified by prInfo.rPage in the print record. If your application prints its documents with PostScript® using PicComments, the Printing Manager never gets a chance to define the clipping region. All of your PostScript code is sent to the LaserWriter and executed, but the results are clipped to (0,0,0,0). To work around this problem, you must call at least one Quickdraw™ drawing routine at the beginning of each page. The following is frequently used:
PrOpenPage(...);
MoveTo(-32000, -32000);
Line(0, 0);
{ PostScript code here }
PrClosePage(...);
The MoveTo is needed so that the line is drawn outside of the imageable area of the page, and thus is invisible. The Line call calls the Printing Manager’s version of the StdLine procedure, which defines the clipping region for the port. All subsequent PostScript code will be clipped correctly. Since PrOpenPage resets the clipping region, the MoveTo/Line combination must be done after each call to PrOpenPage.
Graphics, Imaging & Printing: PrintMonitor: SetOrigin and background printing
I have noticed PostScript® graphics printing in different locations depending on whether or not Background printing is enabled on the Macintosh®. What causes this?
In LaserWriter® 4.0 - 5.2, SetOrigin is handled differently when Background printing is enabled. The method used by these drivers is described below:
Background Printing DISABLED: The application calls SetOrigin, and QuickDraw™ responds to the call by adjusting the portRect of the Print Manager’s GrafPort. Since SetOrigin does not cause any grafProcs to run, the Printing Manager doesn’t see this change until the next QuickDraw drawing operation such as DrawString or LineTo. At that time, the Printing Manager notices the change in the portRect, and updates its internal origin. All QuickDraw graphics are now localized to the new origin. All PostScript graphics will also get the localization to the new origin.
Background Printing ENABLED: Because QuickDraw is playing back a picture that was spooled earlier, it handles calls to SetOrigin a little differently. When the SetOrigin call is encountered in a DrawPicture call, the portRect of the GrafPort is NOT updated. Instead, QuickDraw keeps the current origin cached, and offsets each graphic on the fly. Since the portRect was not modified, the Printing Manager does not see the SetOrigin call. Although all QuickDraw objects are still localized correctly (by QuickDraw), PostScript graphics do not move to the new origin. Instead, the application localizes the coordinates of its PostScript graphics. You could also use the technique documented in Technical Note #183.
The implementation of the SetOrigin (IM I:166) and ClipRect (IM I:167) calls has been revised in LaserWriter 6.0. This is a general description of those changes:
LaserWriter 6.0: Both QuickDraw and PostScript coordinates are offset with respect to the origin set by SetOrigin. The driver now inserts a picture comment into the spool file so that the Print Monitor knows that the origin was changed during spooling.
Since applications must support versions of the LaserWriter driver other than 6.0, they should still use the method described in Tech Note #183 to make sure their PostScript is position-independent.
Graphics, Imaging & Printing: PrintMonitor: Macintosh spool file formats aren’t available
What is file format of Macintosh® Printing Manager and LaserShare™ spool files?
Unfortunately, the formats for these files are not currently available, and it is doubtful that they will be made available in the future. Whenever new features are added to LaserShare, the Printing Manager, or other parts of the Macintosh toolbox, it’s not uncommon for these spool file formats to be affected. If the file format were published, and essentially frozen, it would be much harder for engineering to add features. On the bright side, many developers have asked for the format of these files. Rather then just publishing the current file format, engineering would be better off providing routines for reading these files regardless of the current format. This way, applications would have access to the information they need, without being dependent on the file format. If and when such routines become available, they will be documented via a technical note or system software release note.
Graphics, Imaging & Printing: QuickDraw: ditherCopy not supported on LaserWriter or ImageWriter
ditherCopy not supported on LaserWriter or ImageWriter
ditherCopy is not supported on LaserWriters or ImageWriters. On a LaserWriter, ditherCopy gets misinterpreted and inverts the image. On an ImageWriter it’s treated as a srcCopy. The ImageWriter driver doesn’t support color grafPorts, which is the only way to do the pixel image required for ditherCopy. Use srcCopy instead for both printers.
Graphics, Imaging & Printing: QuickDraw: Macintosh QuickDraw and pen characteristic routines
When generating pictures and then looking at the corresponding Macintosh PICT file, we notice that QuickDraw is optimizing PnMode, PnPat, and PnSize. Can you tell us how to stop QuickDraw from optimizing, and how to know when QuickDraw will optimize?
QuickDraw does not optimize away new pen characteristic routines, but it does insert them into pictures just before a drawing routine that uses the pen rather than place them where they are called. Therefore, you may not see your new pen characteristic routine until later in a picture when it is about to be used. Opcodes for pen characteristics are inserted into the picture when they are changed from the previous time they’re used.
Graphics, Imaging & Printing: QuickDraw: Macintosh animation samples
Do you have an example of flicker-free animation on the Macintosh?
We have some good stuff that’s written in MPW Pascal. It’s DTS Sample Code #16, OffSample, and this uses some routines defined in DTS Sample Code #15, OffScreen. Also, the System 7.0 CD sample code folder contains a smaller sample called “GMonde” that uses GWorlds.
Graphics, Imaging & Printing: QuickDraw: Save and restore document window grafPort at print time
DTS’s printing tech note should also probably recommend saving and restoring the document window grafport around printing, in case an error occurs during printing and the printing code leaves the current port set to some trashed value.
You’re right about saving and restoring the grafPort at print time. If you don’t, things could get ugly.
X-Ref:
Macintosh Technical Note #294, “Me and my PIdle Proc…”
Graphics, Imaging & Printing: QuickDraw: Install pIdle proc before calling PrOpenDoc
Macintosh Technical Note #294 says that “When installing your pIdle proc, it must be installed before the application calls PrOpenDoc.” Inside Macintosh Volume II, on the other hand, says, “If you designate a background procedure, you must set pIdleProc *after* presenting the dialogs, validating the print record, and initializing the printing grafPort: The routines that perform these operations reset pIdleProc to NIL,” (page 154), and “PrOpenDoc initializes a printing grafPort for using in printing a document...” (page 159). Who’s right?
The tech note is correct. If you do not install your pIdle proc before PrOpenDoc, you pIdle proc will NOT receive any time.
X-Ref:
Macintosh Technical Note #294, “Me and my PIdle Proc…”
Graphics, Imaging & Printing: QuickDraw: Version 2 PICTs on pre-Color QuickDraw models
Inside Macintosh Volume V says a System 4.1 (and later) patch ensures that version 2 PICTs are displayed correctly on earlier machines that don’t have Color QuickDraw, such as the Macintosh Plus and SE. However, my version 2 PICT, consisting primarily of a PixMap (opcode = $90 since rowbytes <8) displays correctly on a Macintosh IIfx but displays garbage on a Macintosh SE.
The PICT problem you reported is caused by a bug in 6.0.7 QuickDraw. The workaround for the time being is to:
• Use System 7.0, where it’s been fixed, or
• Don’t use opcode $90. Instead, use padding so that opcode $98 can be used. (Opcode $98 is the packed copybits version that works for rowbytes >= 8.) You can do this by creating the picture with a PixMap that’s wider than you actually need, and then use the clip region to clip out the part you don’t need.
Graphics, Imaging & Printing: QuickDraw: Detecting hidden application window or visRgn # portRect
We draw directly to the screen to gain the fastest possible animation speed, and when we need compatibility—such as when windows overlap or for multiple screens—we do use CopyBits. How do we tell whether the window is hidden or that the visible part is not rectangular?
If your window is hidden partially by another applications window or if your layer has been hidden by the process menu, the visRgn of your window’s grafport will not be the portRect anymore. (Keep in mind that if you scroll by modifying the portRect of the grafport, then you’ll have to do a more complex calculation...) Here is a small Pascal routine that returns this information:
Function UseCopyBits(thePort:grafptr):Boolean;
begin
UseCopyBits:= NOT( (thePort^.VisRgn^^.rgnSize=10) and
(thePort^.visRgn^^.RgnBBox=thePort^.PortRect) );
end;
Graphics, Imaging & Printing: QuickDraw: Using dithering and animation on the same Macintosh image
Using dithering and animation on the same Macintosh image
When setting up a dithered grayscale image for subsequent animation (to adjust brightness, for example), a conflict arises between the use of Palette animation and the ditherCopy CopyBits mode.This problem is demonstrated in the develop #5 GiMeDaPalette code sample: If you change srcCopy to ditherCopy in the CopyBits call, then run the program and selected Animate, the resulting image is pure black and white, with what appears to be an attempt to dither with just the black and white color table entries (that are not reserved for animation).
This happens because ditherCopy tries to use the inverse table to do color matching, but when the image is animated, the inverse table colors are limited to just black and white.
To work around the problem, you can jump into the bottlenecks and when you see the PICT hitting the opcode for CopyBits, change the PICT from a srcCopy to a ditherCopy. This way the dithering happens when you do the call to DrawPicture and not later on. This makes it possible to use dithering and animation on the same image.
Graphics, Imaging & Printing: QuickDraw: Gestalt 'qdrw' selector bug and workaround
Why does Gestalt tell me I have Color QuickDraw features on a non-Color QuickDraw machine?
The gestaltQuickdrawFeatures ('qdrw') selector, used for determining your system’s Color QuickDraw features, has a bug that causes it to tell you incorrectly that noncolor machines have color. The fix is quite simple: Gestalt has another selector, gestaltQuickdrawVersion ('qd '), which simply returns the QuickDraw version number. This version number is < gestalt8BitQD for classic QuickDraw and >= gestalt8BitQD for Color QuickDraw (see Inside Macintosh Volume VI, page 3-39, for more information). The trick is to ask Gestalt for the QuickDraw version first; once you’ve determined that you have Color QuickDraw, the 'qdrw' selector is OK to use to find out specifics.
Graphics, Imaging & Printing: QuickDraw: Sending PostScript via PostScriptHandle PicComment
If I use the PostScriptHandle PicComment to send PostScript code to the LaserWriter driver, do I need to open a picture and then draw the picture to the driver, or can I just use the PicComment with no picture open while drawing to the printer’s grafPort?
You don’t need to create a picture with your PicComment in it and draw the picture to the driver. The best method for sending PostScript code to the LaserWriter is to use the PostScriptHandle PicComment documented in Macintosh Technical Note #91, “Optimizing for the LaserWriter—Picture Comments,” as shown below.
PrOpenPage(...)
{ Send some QuickDraw so that the Printing Manager gets a }
{ chance to define the clipping region. }
PenSize(0,0);
MoveTo(0,0);
LineTo(0,0);
PenSize(1,1);
PicComment(PostScriptBegin, 0, NIL);
{ QuickDraw representation of graphic. }
MoveTo(100, 100);
LineTo(200, 200);
{ PostScript representation of graphic. }
thePSHandle^^ := '100 100 moveto 200 200 lineto stroke';
PicComment(PostScriptHandle, GetHandleSize(thePSHandle),
thePSHandl);
PicComment(PostScriptEnd, 0, NIL);
PrClosePage(...)
The above code prints a line on any type of printer, PostScript or not. The first MoveTo/LineTo combination is required to give the LaserWriter driver a chance to define a clipping region. The LaserWriter driver replaces the grafProcs record in the grafPort returned from PrOpenDoc. In order for the LaserWriter driver to get execution time, you must execute a QuickDraw drawing routine that calls one of the grafProcs. In this case, the MoveTo/LineTo combination calls the StdLine grafProc. When StdLine executes, it notices that the grafPort has been reinitialized, and therefore initializes the clipping region for the port. Until the MoveTo/LineTo combination is executed, the clipping region for the port is set to (0,0,0,0). If PostScript code is sent via the PostScriptHandle PicComment before executing any QuickDraw routines, all PostScript operations will be clipped to (0,0,0,0).
The next thing that’s done is to send the PostScriptBegin PicComment. This comment is recognized only by PostScript printer drivers. When the driver receives this comment, it saves the current state of the PostScript device (by executing the PostScript gsave operator), then disables all QuickDraw drawing operations. This way, the QuickDraw representation of the graphic will be ignored by PostScript devices. In the above example, the second MoveTo/LineTo combination is executed only on non-PostScript devices.
The next PicComment is PostScriptHandle, which tells the driver that the data in thePSHandle is to be sent to the device as PostScript code. The driver then passes this code unchanged to the PostScript device for execution. The PostScriptHandle comment is recognized only by PostScript printer drivers.
The last PicComment, PostScriptEnd, tells the driver to restore the previous state of the device (via a PostScript grestore call), and to enable QuickDraw drawing operations.
Since most PicComments are ignored by QuickDraw devices, only the QuickDraw representation is printed. Since PostScriptBegin tells PostScript drivers to ignore QuickDraw operations, only the PostScript representation is printed on PostScript devices. This is a truly device-independent method for providing both PostScript and QuickDraw representations of a document.
Graphics, Imaging & Printing: QuickDraw: Use srcOr instead of srcCopy for Macintosh text drawing
DrawText with srcCopy takes six times as long as with srcOr now that my Macintosh is running System 7. Why is this so slow? Is this a bug in System 7?
It’s true that srcCopy is slower than srcOr when handling text, especially in color mode. This loss in speed occurs because CopyBits is a lot smarter than it used to be. It can handle foreground and background colors a lot better, but that improvement came at the cost of speed. Our recommended method for drawing text is to erase before drawing, and use srcOr to draw, not srcCopy. Alternatively, you could draw colorized text in srcOr mode off screen and then use CopyBits to draw it on the screen in srcCopy mode without colorization.
Graphics, Imaging & Printing: QuickDraw: Dimming text in an Apple IIGS application
How can I “dim” text in my Apple IIGS application, similar to the way the Toolbox dims menu titles and menu options, and the way that HiliteControl dims a button name?
Dimming text is a piece of cake. Here’s how the Apple IIGS Menu Manager does it in both 640 and 320 mode. The same thing works great for both.
1. Calculate the bounding box of the text.
2. Fill it with the proper background color for the operation in question.
3. Draw the text.
4. Execute code that looks something like this:
pea dimmed>>16
pea dimmed
_SetPenMask ;Set the pen mask to "dimmed" mask
pea textRect>>16
pea textRect ;Push pointer to text boundary rect
lda backColor ;Get text's background color
and #$00FF ;Always solid
; Here you need to do something in your code to get the
; appropriate pattern for the text you're drawing. This will be
; one of the 16 patterns in the 512-byte table, starting with 16
; bytes of $00, 16 bytes of $11, and ending with 16 bytes of $FF.
; We leave the routine GetColorPtr for you to code, but our
; example assumes it returns the pointer we need in A (low word)
; and X (high word).
jsr GetColorPtr ;(see above)
phx ;high word
ph ;low word
_FillRect ;Fill will be dithered
pea nor_mask>>16 ;Reset drawing mask to normal solid
pea nor_mask
_SetPenMask
rts
textRect DC.B $00,00,00,00 ;Put your rectangle here
backColor DC.W $0000 ;Background color of text to dim
dimmed DC.B $55,$AA,$55,$AA,$55,$AA,$55,$AA
nor_mask DC.B $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
Yes, it’s really this easy!
Graphics, Imaging & Printing: QuickDraw: GetGWorldPixMap bug and workaround
Why does GetGWorldPixMap (when called on a Macintosh II, IIcx, or IIx running system software version 6.0.5 or 6.0.7 with 32-Bit QuickDraw 1.2) return a combination of the device field (two bytes) and the first two bytes of the portPixMap field? Is this a bug?
Your analysis of GetGWorldPixMap is exactly right: It doesn’t work correctly in system software version 6.0.5 and 6.0.7 with 32-Bit QuickDraw 1.2. It returns a value that’s two bytes before the value it’s supposed to return.
The solution is to use GWorldPtr->portPixMap instead of GetGWorldPixMap. It’s safe to do this, but you should use GetGWorldPixMap under System 7. Not only is the bug fixed there, but dereferencing the port is dangerous under System 7 because it may not be CGrafPort. Use Gestalt with the gestaltQuickdrawVersion selector to determine whether you can use GetGWorldPixMap. If Gestalt returns a value from gestalt8BitQD ($0100) through gestalt32BitQD12 ($0220), then GetGWorldPixMap either doesn’t exist or is the buggy version. If it returns gestalt32BitQD13 ($0230) or higher, then GetGWorldPixMap does exist and works correctly. Interestingly, GetGWorldPixMap can be called on a black-and-white QuickDraw machine under System 7. It returns a handle to a structure which should be treated as a BitMap structure, though there are some undocumented fields after the normal BitMap fields. To tell whether GetGWorldPixMap is available on a black-and-white QuickDraw machine, you must check the system software version by calling Gestalt with the gestaltSystemVersion selector. If it returns $0700 or higher, GetGWorldPixMap is available.
Graphics, Imaging & Printing: QuickDraw: Code for reversing Macintosh PICT images
Is there a simple way to put PICT images up in mirror image format, or is there sample code showing how to flip an offscreen bitmap?
There is no easy way to do this, nor do we have sample code showing how to flip an offscreen bitmap. Indeed, the best way to do what you want is to draw it to an offscreen pixel map and reverse it.
If you are using Color QuickDraw, always draw it to an 8-bit-per-pixel offscreen bitmap, and then the reverse is a very simple task. Here is some sample Pascal code that might roughly do what you want, with the following assumptions:
1. You are going to add error checking where appropriate.
2. Rowbytes correspond exactly to pixel width of the port.
3. The port is 8 bits deep.
4. You add the code to make this sketch work.
5. The origin of your offscreen port is (0,0).
Procedure FlipScanLine(theV:Integer; thePort:cGrafPtr);
{ Given any scan line number in the indicated port, this routine }
{ will flip that scan line horizontally. This routine assumes that } { you have made sure that scan line theV exists. }
type ScanLn=Packed Array [0..0] of Byte;
ScanPtr=^ScanLine;
var thePixMap:PixMapPtr;
Index,Size:Integer;
ThisScanLine:ScanPtr;
TempPixel:Byte;
Begin
thePixMap:=thePort^.PortPixMap^;
{ First create a pointer to the scan line we are currently }
{ reversing. }
ThisScanLine:=ScanPtr(thePixMap^.BaseAddr);
ThisScanLine:=ScanPtr(ord4(ThisScanLine)+(thePixMap^.RowBytes*theV));
{ Now simply reverse all the bytes. }
{ The scan line is simply an array [0..RowBytes] of Byte, and }
{ since this is 8 bits per pixel, each one is a single pixel.}
Size:=thePixMap^.RowBytes;
For Index:=0 to (Size div 2) do
begin
tempPixel:=ThisScanLine^[Index];
ThisScanLine^[Index]:=ThisScanLine[Size-Index-1];
ThisScanLine^[Index]:=tempPixel;
end;
end;
This same procedure can be used also to swap a 1-, 2- or 4-bit-per-pixel
pixmap if you add a function that accepts a byte and swaps the pixels in it.
Graphics, Imaging & Printing: QuickDraw: Macintosh picture (PICT) 90-degree rotation
Macintosh picture (PICT) 90-degree rotation
The trick for rotating a Macintosh QuickDraw picture 90 degrees is to intercept all bottlenecks and exchange the x and y coordinates. Then, call OpenPicture to receive the rotated picture, call DrawPicture(unrotatedPicture), and then call ClosePicture on the rotated picture. You’re done! QuickDraw spins out the DrawPicture call into its component parts, but runs each component through the bottlenecks first, so they get rotated (by YOUR bottleneck intercepts) and stuck into the new picture, already rotated.
Here‘s a bottleneck intercept for StdLine that rotates a PICT composed entirely of Line commands (which depend on the current pen position):
procedure MyLineProc(newPt: point);
var
tempV : integer;
begin
tempV := thePort^.pnLoc.v; { Swap current pen location
coordinates }
thePort^.pnLoc.v := thePort^.pnLoc.h;
thePort^.pnLoc.h := tempV;
tempV := newPt.v; { Swap destination pen location
coordinates }
newPt.v := newPt.h;
newPt.h := tempV;
StdLine(newPt);
tempV := thePort^.pnLoc.v; { Restore current pen location
coordinates }
thePort^.pnLoc.v := thePort^.pnLoc.h;
thePort^.pnLoc.h := tempV;
end;
Notice that the start coordinates as well as the destination coordinates must be swapped before calling StdLine. The resulting pen location is swapped back again after the operation, so the port looks like it should if unrotated drawing were performed. For things that don’t depend on the current pen location, things are simplified a little bit.
You’ll still need bitmap rotation code for the StdBits and StdText intercepts.You might do StdText by setting the port to an offscreen one you create earlier, calling QuickDraw’s StdText, and then calling your bitmap rotation code to copy it into the destination.
Graphics, Imaging & Printing: QuickDraw: System 7 TextMode problem and workaround
Our application uses the TextMode (blend + mask) as documented in Inside Macintosh® Volume V (blend is equal to the current ditherCopy constant) to make translucent text. Under System 7, this transfer mode causes garbage to appear when the text is drawn. Is there a way to work around the problem? Will there be a fix?
The problem you are seeing is due to the use of CopyDeepMask instead of the old-fashioned CopyBits to do the job. It is being studied now, and the hope is that it will work as advertised in a future release. One workaround is to render the text to an off-screen pixmap and then call CopyBits (using blendMode) to actually put it in the picture.
Graphics, Imaging & Printing: QuickDraw: CopyBits bug and workaround
Has anyone run across what I’m told is a bug in CopyBits? It works like this: In the deep, dark workings of CopyBits, some routine tries to read the two bytes preceding the baseAddress of the source PixMap. If the baseAddress is at the start of a card’s NuBus™ space and there isn’t a card filling the adjacentspace, this causes a bus error! Has anyone found a good workaround?
The short answer is: you’re right. QuickDraw™ inadvertently reads from memory below the base address of a pixmap. The workaround is to place the video base address 32 bytes into the RAM on the card; if the card you’re using doesn’t have this workaround, there’s nothing you can do other than making sure there’s a card in the next-lower slot.
Graphics, Imaging & Printing: QuickDraw: Construct a 'clut' instead of changing b/w palette entries
How can I change the first and last (white and black) entries in a Macintosh® palette?
The answer to your question about changing the black and white entries in a palette is a little strange. You can’t simply change the palette associated with an on-screen window, because too many portions of the Toolbox/OS assume that the first entry is white and the last entry is black.
However, what you _can_ do is create an off-screen GWorld and construct a 'clut' for it that does what you want. Creating the 'clut' is fairly straightforward:
/* Making a reversed gray-scale color table */
CTabHandle offColors;
offColors = (CTabHandle) NewHandleClear (sizeof (ColorTable) + 255 *
sizeof (ColorSpec));
(**offColors).ctSize = 255;
for (index = 0; index <= (**offColors).ctSize; index++)
{
(**offColors).ctTable [index].value = index;
(**offColors).ctTable [index].rgb.red = (index << 8) | index;
(**offColors).ctTable [index].rgb.green = (index << 8) | index;
(**offColors).ctTable [index].rgb.blue = (index << 8) | index;
}
(**offColors).ctFlags = 0;
(**offColors).ctSeed = GetCTSeed ();
Note that using this 'clut' with an off-screen GWorld will work fine _except_ if you attempt to draw text into the GWorld. Apparently drawing text off screen carries the same assumptions that all drawing does on screen.
Once you have done your off-screen drawing with the reversed 'clut' as described above, all that remains is to CopyBits from your off-screen GWorld to your on-screen window. Your on-screen window will need the appropriate palette. Fortunately, constructing that palette from the 'clut' is trivial:
/* Make a palette out of it */
aPalette = NewPalette (offColors, (**offColors).ctSize + 1, pmTolerant, 0);
Attaching this palette to the window will cause the correct remapping to occur when you CopyBits from the GWorld to the window, and everything should look just fine.
Graphics, Imaging & Printing: QuickDraw: Updating Macintosh cursor without mouse competition
How can I programmatically move the Macintosh® mouse without the real mouse interfering?
The real answer to your question is twofold: First, you can do exactly what you want to do with the sample included below. HOWEVER, this is not a good thing to do, it would be better if you took the solution used in Apple’s Guided Tour disks: Always hide the cursor and then decouple the cursor from the mouse. Then, instead of using the system’s cursor, simply draw your own “cursor” using QuickDraw and treat it as a little animated bitmap on the screen. This avoids all the problems that you have with the mouse competing. (Apple does update the mouse globals with the mouse position so that other things function correctly.)
Now, as promised, here is the way to do what you want using the real cursor. As you have discovered, setting the crsrCouple variable to false prohibits the mouse from affecting the cursor; unfortunately, it also prohibits the jcrsrTask routine from drawing the cursor. The solution to this is to set crsr couple to true, call the cursor drawing routine jCrsrTask yourself, and then set the crsrCouple variable to false, as shown below:
procedure callcrsr;
inline $2078 ,$08EE ,$4E90;
{ move.L jcrsrTask,A0
jsr (A0) }
Procedure FudgeMouse;
type PointPtr=^Point;
var RawMouse:PointPtr;
MTemp:PointPtr;
RandPt:Point;
CrsrNew:ptr;
CrsrCouple:ptr;
fred:Longint;
begin
RawMouse:=PointPtr($82C);
MTemp:=PointPtr($828);
CrsrNew:=ptr($8CE);
CrsrCouple:=ptr($8CF);
RandPt:=RawMouse^;
repeat
RandPt.h:=RandPt.h+1;
RandPt.V:=RandPt.v+1;
RawMouse^:=RandPt;
MTemp^:=RandPt;
CrsrNew^:=1;
CrsrCouple^:=1;
callCrsr;
crsrCouple^:=0;
repeat until fred<tickCount;
fred:=tickCount+3;
until Button;
crsrCouple^:=1;
end;
Graphics, Imaging & Printing: QuickDraw: Techniques for graying Macintosh text
How do I draw grayed-out text on the Macintosh®, like the text for disabled buttons or menu items?
There are currently two different kinds of grayed text: First, there’s “patterned” gray, where every other dot is missing. This really only looks good with Chicago or other heavy fonts and was always used for graying out menus and controls in system software through 6.0.x, and is still used in 7.0 when the screen is set to less than 4 bits deep. This is done by first drawing the text in a normal, srcCopy transfer mode. Then a gray rectangle is drawn over the text using the patBic mode. This “erases” half the bits in the text, and is rapid enough that there is very rarely any flicker.
The second kind of text is the actually gray text, which is used in System 7 on screens that are 4 bits deep or deeper for menus, controls, and other grayed text. To draw this text, just call GetGray (as documented on page 17-27 of Inside Macintosh, Volume VI) to get an appropriate gray. Then draw the text in that color.
Graphics, Imaging & Printing: QuickDraw: Use assembly to flip a 24-bit off-port color PixMap
What’s the best approach to horizontally flip a 24-bit off-port color PixMap?
Unfortunately, you won’t be able to use CopyBits for this kind of procedure; you’ll have to write your own routine to move each pixel. I’d suggest doing this in assembly language to squeeze the best possible performance out of your code.
Graphics, Imaging & Printing: QuickDraw: Drawing to off-screen bit maps allocated by 8*24 GC card
Can we use non-QuickDraw™ drawing routines in off-screen BitMaps allocated by the Macintosh® 8•24 GC accelerator card?
The 8•24 GC card is caching your GWorld onto the card so it can manipulate it as quickly as possible. As a result your GWorld could end up in 32-bit address space, and if you happen to be running in 24-bit mode you’ll be writing to the wrong address.
The solution is to get the address of the PixMap right before you write to it using GetPixMapAddr, swap over to 32-bit mode (call _SwapMMUMode), do your thing, and then swap back to the original mode so your machine doesn’t croak. The way to accomplish this is as follows:
baseAdd = GetPixBaseAddr(MyGWorld->portPixMap);
theMode = true326;
SwapMMUMode(&theMode); /* returns old mode and sets new */
…
Do_your_stuff();
…
SwapMMUMode(&theMode); /* leaves it the way it was */
Graphics, Imaging & Printing: QuickDraw: CopyBits maps source PixMap colors to GDevice inverse table
I’m trying to draw off screen so I made my own CGrafPort, PixMap, and color table, but when I draw into it, the colors come out all wrong. What’s going on here?
It’s a very common misconception that CopyBits maps the colors available in the source PixMap’s color table to the colors available in the destination PixMap’s color table.
What actually happens is that CopyBits maps the colors in the source PixMap to the colors available in the current GDevice’s inverse table. See Inside Macintosh, Volume V, pages 137 through 139 for a description of inverse tables. Inverse tables is a backwards color table. With a color table, you use a pixel value as an index into the table to return a color. With an inverse table, you use a color-like value as an index into the table to return a pixel value. When CopyBits maps colors from one pixel map to another, it takes a source pixel value, uses the source PixMap’s color table to get the corresponding color, and uses that color as an index into the current GDevice’s inverse table to get the pixel value of the closest color in the destination PixMap’s color table.
Generally speaking, every conceivable color table has exactly one conceivable inverse table. If you alter the contents of a color table, then the inverse table must likewise be altered. It’s just like numbers: for any number you give me, I can give you its negative. For any color table you give me, MakeITable can give you its inverse table. MakeITable is documented in Inside Macintosh, Volume V, page 142.
Think of the current GDevice as an implied parameter to CopyBits. If you don’t deal with GDevices at all, then the current GDevice is always the main screen’s GDevice as far as you’re concerned. Color QuickDraw often switches between different screens’ GDevices so that you can draw to multiple screens, but that’s all handled behind your back. If you create a PixMap, give it a color table, and CopyBits to it, then the main screen’s GDevice’s inverse table is used to map colors from the source PixMap. That’s OK as long as your destination PixMap’s color table is compatible with the main screen’s inverse table. If you change the depth and/or color table of the main screen, and then still CopyBits to this same PixMap with the same old depth and color table, then things won’t work correctly because the main screen’s GDevice’s inverse table changes, making it incompatible with your destination PixMap’s color table. This problem usually manifests itself as incorrect colors, but it can result in crashes.
To fix this, you’ll have to remove your reliance on the main screen’s GDevice. To do that you’ll have to make your own GDevice. There’s a routine called NewGDevice, but it always makes the GDevice in the system heap. Instead, you should just call NewHandle to allocate a GDevice record yourself. Here’s what the fields should hold:
gdRefNum - The GDevice has no driver, so set this to zero.
gdID - It doesn’t matter what this is set to — might as well set it to zero.
gdType - Set this to 2 if the off-screen uses direct colors (16 or 32 bits per pixel) or 0 if the off-screen uses a color table (1 through 8 bits per pixel).
gdITable - Allocate a small (maybe just a 2-byte) handle for this field. After you’re done setting up this GDevice and your off-screen PixMap, color table (if any) and CGrafPort, then set this GDevice as the current GDevice by calling SetGDevice. Then call MakeITable, passing it NIL for both the color table and inverse table parameters, and 0 for the preferred inverse table resolution.
gdResPref - I’d guess that more than 99.9% of all inverse tables out there have a resolution of 4. Unless you have some reason not to, I’d recommend the same here.
gdSearchProc - Set to NIL. Use AddSearch if you want to use a SearchProc.
gdCompProc - Set to NIL. Use AddComp if you want to use a CompProc.
gdFlags - Set to 0 initially, and then use SetDeviceAttribute after you’ve set up the rest of this GDevice.
gdPMap - Set this to be a handle to your off-screen PixMap.
gdRefCon - Set this to whatever you want.
gdNextGD - Set this to nil.
gdRect - Set this to be equal to your off-screen PixMap’s bounds.
gdMode - Set this to -1. This is intended for GDevices with drivers anyway.
gdCCBytes - Set to 0.
gdCCDepth - Set to 0.
gdCCXData - Set to 0.
gdCCXMask - Set to 0.
gdReserved - Set to 0.
For gdFlags, you should use SetDeviceAttribute to set the noDriver bit and the gDevType bit. You should set the gDevType bit to 1 even if you have a monochrome color table. The 0 setting was only used when monochrome mode was handled by the video driver, and 32-Bit QuickDraw eliminated that convention. Your GDevice doesn’t have a driver anyway.
Once this is done, the GDevice and the off-screen PixMap should be treated as inseparable. When you CopyBits or draws into the PixMap, first call SetGDevice to set its GDevice as the current GDevice. When that’s done, call SetGDevice to restore the previous GDevice. Doing this insulates you from changes in a screen’s GDevice.
If you alter your PixMap’s color table, you should make sure you update the ctSeed of that color table, either by assigning to it the result of GetCTSeed (documented on page 143 of Inside Macintosh, Volume V) or by passing a handle to the color table to CTabChanged. The next time that PixMap is drawn into, Color QuickDraw will update your GDevice’s inverse table automatically when it realizes that the ctSeed is different from the current GDevice (which had better be yours) inverse table’s iTabSeed.
GWorlds work this way on Color QuickDraw machines. Every GWorld comes with a PixMap and a GDevice. When you call SetGWorld, that sets both the GWorld and its GDevice as current.
Graphics, Imaging & Printing: QuickDraw: Why PlotCIcon requires GetCIcon instead of Get1Resource
Why do I have to use GetCIcon(resID) instead of Get1Resource('cicn',resID) for PlotCIcon to work correctly?
You apparently thought something that, at first, I thought also: that GetCIcon(resID) is just a utility routine that translates to Get1Resource('cicn',resID). However, this is not the case; GetCIcon not only gets the 'cicn' resource, but it also performs some minor surgery on the results, fills in some placeholder fields in the resource data, and the like. Basically, PlotCIcon can’t work without the things that GetCIcon does.
Graphics, Imaging & Printing: QuickDraw: Macintosh Color QuickDraw and packed PICTs
Does Macintosh® 32-Bit QuickDraw™ support packed PICTs? What’s the technique for saving packed PICT formats? What compression schemes are supported?
Color QuickDraw has always supported packed PICTs. See Inside Macintosh, Volume V, for details on how CLUT PixMaps are packed. Under 32-Bit QuickDraw, to pack direct RGB PixMaps in PICTs, call CopyBits with the packType field in the source PixMap set to one of the following constants that apply to direct RGB PixMaps:
0 - default packing (pixelSize 16 defaults to packType 3 and pixelSize 32 defaults to packType 4)
1 - no packing
2 - remove pad byte (32-bit pixels only)
3 - run-length encoding by pixel size chunks (16-bit pixels only)
4 - run-length encoding, all of one component at the time, one scan line at a time (24-bit pixels only)
Scheme 4 will store the alpha channel also if cmpCount is set to to four. PackSize is not used and should be set to zero for compatibility reasons. These are the only compression techniques supported at this time.
Graphics, Imaging & Printing: QuickDraw: Calling InitCursor instead of SetCursor
Is it legal to call InitCursor instead of SetCursor(arrow) when I want to set the cursor to an arrow (after my normal one-time program initialization code, in my UpdateCursor routine)? The only reason I'd want to do such a skanky thing is to save code. Calling a trap with no parameters is less code than one with parameters. What, exactly, if anything, does InitCursor do besides setting the cursor to an arrow and setting the cursor level to zero?
There's no problem at all with this, as long as you are aware that the hidden, busy, and obscured states are cleared when you call InitCursor, so if the cursor was hidden or obscured for good reason it'll suddenly reappear. It also gets the arrow from QuickDraw™, of course, but that's not a problem.
Graphics, Imaging & Printing: QuickDraw: PICT fontName opcode
Is there an up-to-date canonical source for PICT opcodes? In “Night of the Living Disc,” as far as I can see, the only list of PICT opcodes is in Macintosh® Tech Note #21, which does not mention opcode $2C. It appears that opcode $2C concerns font names. I recall seeing a patch for PictDetective named "fontnameop" or something like that. However I can't be sure that $2C is the only new opcode.
The fontName opcode is documented in Tech Note #275. Note also that since the introduction of 32-Bit QuickDraw™ there are two more bitmap opcodes for direct RGB PixMaps $009A (DirectBitsRect) and $009B (DirectBitsRgn). The QuickDraw section of Inside Macintosh Volume VI has all these opcodes listed in a single place, making it easier to get the necessary info. Here is the info on font names and pictures from Tech Note #275:
PICTs Contain Font Name Information
Every time you draw text inside of an _OpenPicture and _ClosePicture pair, QuickDraw stores the name of the current font and uses it when playing back the picture. The opcode used to save this information is $002C and its data is as follows:
PictFontInfo = Record
length : Integer; { length of data in bytes }
fontID : Integer; { ID in the source system }
fontName : Str255;
END;
QuickDraw saves this information only one time for each font used in a picture. When QuickDraw plays back a picture, it uses the fontID as a reference into the list of font names which are used to set the correct font on the target system.
For example, the following code:
GetFNum('Venice', theFontID); { Set a font before opening PICT}
TextFont(theFontID);
pHand2 := OpenPicture (pictRect);
MoveTo(20,20);
DrawString(' Better be Venice');
GetFNum('Geneva', theFontID);
TextFont(theFontID);
MoveTo(20,40);
DrawString('Geneva');
GetFNum('New York', theFontID);
TextFont(theFontID);
MoveTo(20,60);
DrawString('New York');
GetFNum('Geneva', theFontID);
TextFont(theFontID);
MoveTo(20,80);
DrawString('Geneva');
ClosePicture;
generates a picture containing font information like this:
OpCode 0x002C {9,
"0005 0656 656E 6963 65"} /* save current font */
TxFont 'venice'
DHDVText {20, 20, " Better be Venice"}
OpCode 0x002C {9, /* save next font name */
"0003 0647 656E 6576 61"}
TxFont 'geneva'
DVText {20, "Geneva"}
OpCode 0x002C {11, /* ditto */
"0002 084E 6577 2059 6F72 6B"}
TxFont 'newYork'
DVText {20, "New York"}
TxFont 'geneva' /* second Geneva does not
need another $002C guy */
DVText {20, "Geneva"}
This feature works regardless of the type of picture being saved, including old style PICTs in a black-and-white port. Using _OpenCPicture instead of _OpenPicture to start a recording session results in the same functionality.
Graphics, Imaging & Printing: QuickDraw: BitMapToRgn is available for nonColor QuickDraw Macintosh models
Is _BitmapToRegion available on any pre-System7 nonColor QuickDraw™ configurations such as the Macintosh® Classic, Plus, or SE? If not, is source or a library module available so that I don't have to take the time and compatibility risk of rolling my own?
BitMapToRegion works on pre-color Macintosh systems. You can license BitMapToRegion from
Software Licensing
Apple Computer, Inc.
20525 Mariani Ave. MS:38-I
Cupertino, CA 95014
AppleLink: SW.LICENSE
Phone:(408) 974-4667
Graphics, Imaging & Printing: QuickDraw: Macintosh OpenCPicture 72 dpi calculation bug
The 32-Bit QuickDraw™ _OpenCPicture call incorrectly calculates the 72 dpi frame width if the height of the native resolution srcRect exceeds 910 dots. To work around this problem, I calculate the 72 dpi frame independently, and store it in the PicHandle returned by _OpenCPicture.
It’s a known bug that under Macintosh® Systems 6.0.5 and 6.0.7 with 32-Bit QuickDraw 1.2, OpenCPicture doesn’t properly calculate the right coordinate of the 72 dpi picFrame if the height of the srcRect (native resolution rectangle) multiplied by 72 exceeds $0000FFFF. That works out to a maximum height of 910 pixels, just as you found. This bug is fixed in System 7.0, but gestaltQuickDrawVersion returns $0220 both under Systems 6.0.5 and 7.0, so you can’t tell whether the bug is fixed that way. Instead, you should use Gestalt with the gestaltSystemVersion selector. If the returned value is $0700 or greater, then let OpenCPicture handle the picFrame calculation; otherwise you should do the calculation yourself.
Graphics, Imaging & Printing: QuickDraw: Saving 32-bit Macintosh PICTs
I am using a packType=4 and have several questions about saving Macintosh® 32- bit images in a PICT format:
(1) What are the ramifications of using cmpCount=3 as opposed to cmpCount=4?
(2) How is the pixData actually stored? According to several references, each line is run-length encoded; that is, [byteCount][data]. If rowBytes>250 then byteCount is a word. After looking at several examples, I came to the conclusion that you are actually using packBits and that the term “run-length” encoded is a misnomer.
(1) The difference between using cmpCount=3 or cmpCount=4 is that in the first case only the R, G and B values are stored in the picture; in the second case QuickDraw stores in the picture the alpha channel plus R, G and B. cmpCount=4 can be used when it is important to also save the alpha channel (as when you have some flags stored there).
(2) Unless rowBytes is less than 8, the PixMap is compressed using PackBits, and the length is a word or a byte depending on rowBytes, but it always refers to the number of bytes comprising one scan line. My guess is that “run-length encoding” refers to the fact that pictures have data organized one row at a time.
To show how direct RGB PixMaps are stored inside a picture, I am including the decoding of a picture that I created to show how the different packing schemes change the resulting PixMap opcode data. First I created a direct RGB PixMap and drew three lines into it. The first line is 8 pixels long with a color of {0x1111,0xAAAA, 0x7777}, the third line is 8 pixels of {0xFFFF, 0x3333, 0xBBBB} and the line in between is two pixels of the first color then two pixels of the second color and so on until you make 8 pixels. Then I created a picture made of CopyBits calls copying the same lines but using different packing schemes. Finally I dumped the contents and the result is what you see here. I have put comments I think help make it clear how the packing scheme of choice changes the results.
I recommend that you have the Inside Macintosh Volume V QuickDraw™ chapter at hand to check the opcodes and data associated with them. If you had Inside Macintosh Volume VI then you wouldn't need to also check the 32-Bit QuickDraw docs for the direct RGB PixMap opcodes. Technical Note #171 gives details on how the packed data is arranged.
0256 0000 0000 0008 0008 /* size and rect */
0011 02FF 0C00 FFFF FFFF /* PICT2 Header */
0000 0000 0000 0000 0008
0000 0008 0000 0000 0000
001E /* Default hilite */
001A FFFF 3333 BBBB /* RGB Fore Color */
0001 000A 8001 8001 7FFF 7FFF /* ClipRgn */
009A /* direct pixels opcode; see IM VI QD
chapter for details */
0000 00FF 8020 0000 0000 0003 0008 0000 /* See IM V or VI
QuickDraw chapter */
0001 0000 0000 0048 0000 0048 0000 0010 /* packType 0001 = no
packing */
0020 0003 0008 0000 0000 006D A7DC 0000
0000 0000 0000 0003 0008 0000 0000 0003
0008 0000
0011 AA77 0011 AA77 0011 AA77 0011 AA77 /* line one xRGB after
xRGB */
0011 AA77 0011 AA77 0011 AA77 0011 AA77
0011 AA77 0011 AA77 00FF 33BB 00FF 33BB /* second line same */
0011 AA77 0011 AA77 00FF 33BB 00FF 33BB
00FF 33BB 00FF 33BB 00FF 33BB 00FF 33BB /* third line same */
00FF 33BB 00FF 33BB 00FF 33BB 00FF 33BB
009A /* same direct pixels
opcode */
0000 00FF 8020 0000 0000 0003 0008 0000
0002 0000 0000 0048 0000 0048 0000 0010 /* packType 2 = fourth
byte off*/
0020 0003 0008 0000 0000 006D A7DC 0000
0000 0000 0000 0003 0008 0003 0000 0006
0008 0000
11AA 7711 AA77 11AA 7711 AA77 /* one line of RGB
after RGB */
11AA 7711 AA77 11AA 7711 AA77 /* compare with
previous*/
11AA 7711 AA77 FF33 BBFF 33BB /* same here*/
11AA 7711 AA77 FF33 BBFF 33BB
FF33 BBFF 33BB FF33 BBFF 33BB /* and here */
FF33 BBFF 33BB FF33 BBFF 33BB
009A /* bits opcode */
0000 00FF 8020 0000 0000 0003 0008 0000
0004 0000 0000 0048 0000 0048 0000 0010 /* packType 4 =
pack */
0020 0003 0008 0000 0000 006D A7DC 0000 /* componentCount = 3 */
0000 0000 0000 0003 0008 0006 0000 0009 /* R,G and B separated */ 0008 0000
/* for details on packed data see
Tech Note #171 */
06 /* first line made of 6 bytes
including count */
F9 11F9 AAF9 77 /* -(-7)+1 of 11, -(-7)+1 of AA, and
-(-7)+1 of 77 -> 8 RGB triplets */
19 /* second row made of $19 bytes */
1711 11FF FF11 11FF FFAA AA33 33AA AA33 3377 77BB BB77 77BB BB
/* $17+1 unpacked values */
06 /* third line same as first */
F9FF F933 F9BB /* repeated R and B and G values */
009A /* bits opcode again */
0000 00FF 8020 0000 0000 0003 0008 0000
0004 0000 0000 0048 0000 0048 0000 0010 /* same packing = 4 but*/
0020 0004 0008 0000 0000 006D A7DC 0000 /* component count = 4*/
0000 0000 0000 0003 0008 0009 0000 000C /* alpha channel, R, G,
and B */
0008 0000
08 /* first line */
F9 00F9 11F9 AAF9 77
/* same as before but packing the high byte (00
value) also */
1B /* second line first has -(-7)+1 '00' and then
the same line as above */
F900 1711 11FF FF11 11FF FFAA AA33 33AA AA33 3377 77BB BB77 77BB BB
08 /* third line same as first */
F900 F9FF F933 F9BB
00FF /* end of PICT */
A section of the code that produces this picture follows:
RGBColor oneColor = {0x1111, 0xaaaa, 0x7777},
twoColor = {0xffff,0x3333,0xbbbb};
SetGWorld(GgwPtr, nil); /* set the offscreen GWorld */
if ( LockPixels(GgwPtr -> portPixMap) )
{
EraseRect(&(GgwPtr->portRect));
RGBForeColor(&oneColor);
MoveTo(0,0);
LineTo(7,0);
MoveTo(0,1);
LineTo(1,1);
RGBForeColor(&twoColor);
MoveTo(2,1);
LineTo(3,1);
RGBForeColor(&oneColor);
MoveTo(4,1);
LineTo(5,1);
RGBForeColor(&twoColor);
MoveTo(6,1);
LineTo(7,1);
MoveTo(0,2);
LineTo(7,2);
SetRect(&localR,0,0,8,3);
rr = localR;
p = OpenPicture(&(GgwPtr->portRect));
/* first no packing */
(*(GgwPtr -> portPixMap)) -> packType = 1;
CopyBits((*(GgwPtr -> portPixMap)),(*(GgwPtr -> portPixMap)),
&rr,&localR,srcCopy,nil);
/* second pack 2: remove alpha chanel */
OffsetRect(&localR,0,3);
(*(GgwPtr -> portPixMap)) -> packType = 2;
CopyBits((*(GgwPtr -> portPixMap)),(*(GgwPtr -> portPixMap)),
&rr,&localR,srcCopy,nil);
/* third pack 4: packing component by component */
OffsetRect(&localR,0,3);
(*(GgwPtr -> portPixMap)) -> packType = 4;
CopyBits((*(GgwPtr -> portPixMap)),(*(GgwPtr -> portPixMap)),
&rr,&localR,srcCopy,nil);
/* The last case is pack 4 but storing the alpha
channel also */
OffsetRect(&localR,0,3);
(*(GgwPtr -> portPixMap)) -> packType = 4;
(*(GgwPtr -> portPixMap)) -> cmpCount = 4;
CopyBits((*(GgwPtr -> portPixMap)),(*(GgwPtr -> portPixMap)),
&rr,&localR,srcCopy,nil);
ClosePicture();
UnlockPixels(GgwPtr -> portPixMap);
}
Graphics, Imaging & Printing: QuickDraw: Direct RGB PICT file compression
How are bits packed in direct RGB PICT files created by 32-Bit QuickDraw™? I looked at Macintosh® Technical Note #171, but this run-length encoded compression is clearly inefficient for cases where pixelSize is greater than 8 bits. I write software for machines other than Macintosh that decodes PICT files; therefore, I cannot issue any QuickDraw calls such as _unpackBits.
You’re quite right; compressing direct pixels using straight run-length encoding doesn’t work very well. Fortunately, direct pixel maps aren’t compressed this way. Compression schemes are discussed in Inside Macintosh Volume VI in the section titled “The New OpCodes: Expanded Format.”
In short, if the packType field holds the value 1, then no compression is done at all. The complete pixel image is saved in the PICT. If the packType field holds the value 2 and the pixel map is 32-bits per pixel, then all that’s done is that the alpha-channel byte is removed. So this:
00 FF FF FF 00 FF FF FF
is compressed to:
FF FF FF FF FF FF
If the packType field holds the value 3 and the pixel map is 16 bits per pixel, then run-length encoding is done, but not through PackBits. Instead, a run-length encoding algorithm private to QuickDraw is used. This algorithm is very similar to PackBits, but where PackBits compresses runs of bytes, this routine compresses runs of words. The format of the resulting data is exactly the same as described in Technical Note #171, but you’ll get words instead. To build on the example in Technical Note #171, lets say the 16-bit pixel image begins with these pixel values:
AAAA AAAA AAAA 8080 0000 2A2A AAAA AAAA AAAA AAAA 8080 0000
2A2A 2222 AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA
After being packed by QuickDraw’s internal compression routine, this becomes:
FE AAAA
02 8080 0000 2A2A
FD AAAA
03 8080 0000 2A2A 2222
F7 AAAA
or
FEAA AA02 8080 0000 2A2A FDAA AA03 8080 0000 2A2A 2222 F7AA AA
* * * * *
where the asterisks mark the flag-counter bytes. Notice that you can’t assume that the pixel values are word-aligned. PackBits packs data 127 bytes at a time, though it will do this for up to 32,767 total bytes. Similarly, the internal compression routine packs data 127 words at a time.
If the packType field holds the value 4 and the pixel map is 32-bits per pixel, then run-length encoding via PackBits is done, but only after some preprocessing is done. QuickDraw first rearranges the color components of the pixels so that each color component of every pixel is consecutive. So the following four pixels (the row below the pixel values indicates a = alpha channel, r = red, g = green, b = blue, and the pixel offset):
00 FF FF FF 00 FF C0 00 00 FF 80 00 00 C0 80 00
a0 r0 g0 b0 a1 r1 g1 b1 a2 r2 g2 b2 a3 r3 g3 b3
is rearranged to become:
FF FF FF C0 FF C0 80 80 FF 00 00 00
r0 r1 r2 r3 g0 g1 g2 g3 b0 b1 b2 b3
The first four bytes are the red components of the four pixels, the next four bytes indicate the green components of the four pixels, and so on. The alpha channel isn’t included unless the cmpCount field contains 4 rather than the normal 3. If cmpCount contains 4, then all the alpha channel bytes are placed before the red bytes. Once this is done, then PackBits is called to compress the rearranged data.
Those are the only four compression schemes (including no compression) that are supported for direct pixel maps in PICTs. As always, reading PICTs yourself puts you in danger of not being able to read PICTs generated by future versions of QuickDraw. For compatibility reasons, these compression algorithms as I’ve described them probably can’t change in the future. It’s possible that new values for packType could be implemented though.
Graphics, Imaging & Printing: QuickDraw: Color and nonColor QuickDraw trap dispatch differences
Why does a call to RGBForeColor cause a corruption of the stack without resulting in an unimplemented trap error on nonColor QuickDraw™ Macintosh® systems?
The trap dispatcher on Color QuickDraw and nonColor QuickDraw machines are different. If you look at page 89 of Inside Macintosh Volume I, you’ll see the toolbox trap word format as it was in the days before Color QuickDraw. Bit 9 was “reserved for future use” and was ignored by the trap dispatcher, and so it was normally set to 0. That means that valid toolbox traps could either look like $A8XX or $A9XX as long as the auto-pop bit was turned off. Color QuickDraw machines have a trap dispatcher that uses that reserved bit to allow for more trap words, and therefore it has a much larger trap dispatch table. Color QuickDraw traps have that reserved bit set, so those traps look like $AAXX or $ABXX.
When a nonColor QuickDraw machine tests to see if a trap is implemented or not, it just checks the trap dispatch table to see if a routine is implemented for that trap or not. Because the reserved bit is ignored, trap words that look like $AAXX are treated as equivalent to $A8XX and trap words that look like $ABXX are treated as equivalent to $A9XX. The trap word for RGBForeColor is $AA14. If you call RGBForeColor on a nonColor QuickDraw machine, $AA14 is treated as $A814, which is the trap word for SetFractEnable. SetFractEnable is implemented on 128K ROM machines or greater, so no unimplemented trap error occurs.
If you look at recent DTS sample programs, such as the Utilities sample (SC.025.Utilities, which you can find on AppleLink® in Developer Support and on the current developer CD), you’ll see a routine in Utilities.c called TrapExists. It takes into account the size of the trap dispatch table so that you can tell in one call whether a routine is implemented or not regardless of whether it’s a Color QuickDraw trap or not and regardless of what kind of Macintosh you’re running on.
Under system software version 7.0, the trap dispatcher is modified on nonColor QuickDraw machines so that many Color QuickDraw traps are implemented and work as well as they can in black and white.
Graphics, Imaging & Printing: QuickDraw: CLUT should be black for video card startup
On a system restart, our PrimaryInit routine clears our video card’s memory before displaying grayscreen, but garbage appears on the Macintosh® LC screen. What should we do to fix this problem?
The problem you are having with your video card on the Macintosh LC sounds like a CLUT problem. We recommend that you start by setting your entire CLUT to black then do what you are already doing. Basically the problem is caused by the CLUT DAC coming in early. If the CLUT is set then it should not cause you any problems.
Graphics, Imaging & Printing: QuickDraw: Macintosh QuickDraw pixel map stack requirements
What are the guidelines for determining how much image can be copied to a Macintosh® pixel map at one time, given a particular set of characteristics for the source map and the destination map and given how much stack space is available. For example, we could say that we have an 8-bit deep PixMap to be copied to a 32-bit deep PixMap using the pmDithered mode and expanded by a factor of 4, and we have 45K of stack space.
Banding the image does not reduce the stack space requirement, though it does reduce your overall memory needs. The real stack requirement driver for QuickDraw™ is the width of each scan line (rowBytes). The rule of thumb is that you need at least as much stack as the widest rowBytes in your image (which can be huge with 32-bit QuickDraw) with the following additional modifiers: add an additional rowBytes for dithering; add an additional rowBytes for any stretching (source/dest rect != ); add an additional rowBytes for any color map changing; add an additional rowBytes for any aliasing. So, the rough maximum stack space you’d need is five times the rowBytes of your image. In general, you’ll be better off with processing narrower scan lines. Reducing the vertical size will not affect stack requirements. Narrow, tall bands (if you can use them) will reduce the stack.
Graphics, Imaging & Printing: QuickDraw: Using PicComments to rotate text
I have a PostScript® routine (using TextBegin/TextEnd) to generate bitmapped rotated text on the screen (which can be later printed on QuickDraw™ printers). Why do I get duplicate text? I get both bitmapped rotated text and PostScript rotated text when I print on the LaserWriter® II, and both bitmapped rotated text and horizontal text on the ImageWriter®. When I make a machine dependent check (check type of printer) and call the proper printing procedure, it works fine. Because of the speed and memory considerations of generating the rotated bitmapped text (especially at 300 dpi), is there a way to ensure that the printer will use the PostScript BEFORE generating the bitmap?
We will use the following Macintosh® PicComments to hide your QuickDraw calls from the LaserWriter, but the ImageWriter will use them:
PostScriptBegin
>> Put your CopyBits and QuickDraw calls to image your rotated
>> bitmapped text here....
PostScriptEnd
By wrapping your QuickDraw code within the PostScriptBegin and PostScriptEnd PicComments, the code will be ignored by the LaserWriter, but the ImageWriter will use the QuickDraw calls. Basically, the PostScriptBegin and PostScriptEnd PicComments tell the LaserWriter driver to turn “off” QuickDraw. In the ImageWriter case, the ImageWriter does not understand the PicComments. Therefore, it will use the QuickDraw calls to create and image your bitmapped text.
Now, we need to use the rotation PicComments to rotate the text on the LaserWriter, but have the ImageWriter ignore the code:
Rect zeroRect;
SetRect (&zeroRect, 0, 0, 0, 0);
TextBegin
TextCenter
ClipRect (&zeroRect);
>> Draw your text to be rotated on the LaserWriter....
ClipRect (&rPageRect);
TextEnd
Wrapping your text drawing call(s) between the ClipRect calls will ensure that the text is drawn only on the LaserWriter. Setting the ClipRect to zero tells the ImageWriter to ignore all QuickDraw calls until the ClipRect is reset to something “real” (actually, a zero ClipRect prevents QuickDraw from drawing anything). After we have completed drawing the rotated text, we reset the ClipRect to the dimensions of rPage (that is, rPage is the image-able area of the currently selected printer—see Inside Macintosh, Volume II, page 150). This will allow all of your normal drawing to continue on the ImageWriter and LaserWriter. If you did not reset the ClipRect after the TextEnd call, nothing would be drawn on the ImageWriter or LaserWriter.
Graphics, Imaging & Printing: QuickDraw: Using dithered drawing mode with QuickDraw
When I draw a 32-bit Macintosh® PICT image from a file to an 8-bit port via an offscreen GWorld, I use dither mode in the CopyBits call and the results are quite impressive. If there is not enough memory to allocate the GWorld, I draw the image directly to the port. But since there does not seem to be any way to tell QuickDraw™ to use dithered drawing mode, the image looks horrible.
Do you have any suggestions? I have installed bottleneck procs to allow DrawPicture to get its data from the file instead of the handle in memory. Is there a way, while in the bottlenecks, to find the CopyBits call that comes from the picture and force it to use dithered mode instead of source mode? I don’t want to try and parse the PICT myself, but I thought that maybe a QuickDraw global could be modified in my StdBits proc to force dithered drawing for that operation only?
You can install a StdBits or bitsProc bottleneck procedure to get all the CopyBits calls when the picture is being played back. One of the parameters to the StdBits call is the mode. You can install a procedure that saves the current mode, and then passes ditherMode to the original StdBits proc. This is all you should need to do. It’s been done here so we know it works, only not in any form that can be sent to you as sample code at this time.
Graphics, Imaging & Printing: QuickDraw: Why grafPort’s clipRgn should be changed before OpenPicture
On page 189 of Inside Macintosh®, Volume I, in the QuickDraw™ chapter’s description of OpenPicture, is the following warning:
“A grafPort's clipRgn is initialized to an arbitrarily large region. You should always change the clipRgn to a smaller region before calling OpenPicture, or no drawing may occur when you call DrawPicture.”
The “arbitrarily large” clipping region rectangle is set to -32767, -32767,32767,32767 (top, left, bottom, right) for new ports. This is the largest rectangle possible. If this is not a "valid" clipping rectangle for pictures, what is? Is there some specific limit to the size of the clipping rectangle? Does it depend on either available memory or the size of the picture?
Inside Macintosh ’s warning is based on truth but it’s incomplete. It didn’t actually say that this rectangle is invalid as a clipping region, because this is in fact a perfectly valid clipping region. But, you could run into problems if you use this as a clipping region when creating a QuickDraw picture. It’s not a matter of available memory or size; it’s a simple matter of 16-bit signed integer overflow and underflow.
When you open a picture, the current clip region is recorded in the picture (this wasn’t necessarily true in some early versions of QuickDraw). When you draw the resulting picture using the picture’s picFrame as the destination rectangle, there won’t be any problems. But if you use a destination rectangle that’s larger than the picFrame, QuickDraw scales everything in the picture proportionately, including the clip region. If you allowed the default clip region to be recorded into the picture, then its rgnBBox, already as large as possible, will be made even larger. That means that the -32767 coordinates might wrap around to the positive number range, and the 32767 coordinates might wrap around to the negative number range. This leaves you with an empty clip region. Nothing at all gets drawn when the current port’s clip region is empty.
If the destination rectangle is smaller than the picture’s picFrame, you won’t have any problems because the default clip region will be made smaller, and that’s no problem.
This is why Inside Macintosh suggests that you make the clip region smaller than the default clip region before opening a picture. By doing this, you’re almost guaranteed that the clip region won’t get scaled to the point that it turns inside out. What size should you make it? Small enough so that the risk of the clip region’s coordinates being scaled out of QuickDraw coordinate space is minimal. I usually just set the clip region to the picFrame of the picture. It’s hard to go wrong this way.
Graphics, Imaging & Printing: QuickDraw: Use Mac 8•24 GC card as video buffer only for now with 7.0ßx
Can I use my Macintosh® 8•24 GC card with System 7.0ßx? I was told the GC INIT misbehaves with any and all nonlinear address mapping, such as System 7.0 and A/UX®. Is this true? Can this be fixed with CODE/INIT patch? Is it scheduled to be fixed in the near future?
The 8•24 GC card INIT version 1.0 is not intended to run in any environment involving virtual memory management. A VM-compatible version of the GC INIT will be made available when System 7.0 is final. Until then, the card can be used as a video buffer, and System 7 preliminary software might run with VM switched off.
Graphics, Imaging & Printing: QuickDraw: Using Mac System 7 OpenCPicture for higher resolution
We want to use OpenCPicture for higher resolution, not for color per se. Can OpenCPicture in System 7 be used with non-Color as well as Color QuickDraw™ Macintosh® computers?
Yes, with System 7, OpenCPicture can be used to create extended PICT2 files from all Macintosh computers. Under System 6.0.7 or later, you must test for 32-Bit QuickDraw before using OpenCPicture. You can do this by calling Gestalt with the gestaltQuickDrawVersion selector. If it returns gestalt32BitQD or greater, then 32-Bit QuickDraw is installed.
Graphics, Imaging & Printing: QuickDraw: Macintosh QDError function under System 6 and System 7
Under what System 7 and System 6 conditions is it legal to call the Macintosh® QDError function?
Under System 7, QDError can be called from all Macintosh computers. (System 7 supports RGBForeColor, RGBBackColor, GetForeColor, and GetBackColor for all Macintosh computers as well.) On a non-Color QuickDraw™ Macintosh, QDError always returns a “no error.” Under System 6, QDError cannot be used for non-Color QuickDraw Macintosh systems.
Graphics, Imaging & Printing: QuickDraw: Macintosh CopyBits transfer modes changed for System 7
Why do some Macintosh® CopyBits transfer modes produce different results for System 7 than for System 6?
Under System 6, the srcOr, srcXor, srcBic, notSrcCopy, notSrcOr, notSrcXor, and notSrcBic transfer modes do not produce the same effect for a 16- or 32- bit (direct) pixel map as for an 8-bit or shallower (indexed) pixel map. With Color QuickDraw these classic transfer modes on direct pixel maps aren’t color based; they’re pixel value based. Color QuickDraw performs logical operations corresponding to the transfer mode on the source and destination pixel values to get the resulting pixel value.
For example, say that a multicolored source is being copied onto a black and white destination using the srcOr transfer mode, and both the source and destination are 8 bits per pixel. Except in unusual cases, the pixel value for black on an indexed pixel map has all its bits set, so an 8-bit black pixel has a pixel value of $FF. Similarly, the pixel value for white has all its bits clear, so an 8-bit white pixel has a pixel value of $00. CopyBits takes each pixel value of the source and performs a logical OR with the corresponding pixel value of the destination. Using OR to combine any value with 0 results in the original value, so using OR to combine any pixel value with the pixel value for white results in the original pixel value. Using OR to combine any value with 1 results in 1, so using OR to combine any pixel value with the pixel value for black results in the pixel value for black. The resulting image shows the original image in all areas where the destination image was white and shows black in all areas where the destination image was black.
Take the same example, but this time make the source and destination 32 bits per pixel. The direct-color pixel value for black is $00000000 and the direct- color pixel value for white is $00FFFFFF. CopyBits still performs a logical OR on the source and destination pixel values, but notice what happens in this case. Using OR to combine any source pixel value with the pixel value for white results in white, and using OR to combine any source pixel value with the pixel value for black results in the original color. The resulting image shows the original image in all areas where the destination image was black and shows white in all areas where the destination image was white—roughly the opposite of what you see on an indexed pixel map.
The newer transfer modes addOver, addPin, subOver, subPin, adMax, and adMin work consistently at all pixel depths, and often, though not always, correspond to the theoretical effect of the old transfer modes. For example, the adMin mode works similarly to the srcOr mode on both direct and indexed pixel maps. Also, 1-bit deep source pixel maps work consistently and predictably regardless of the pixel depth of the destination even with the old transfer modes.
Under System Software 7.0, the old transfer modes now perform by calculating with colors rather than pixel values. You’ll find that transfer modes like srcOr and srcBic work much more consistently even on direct pixel maps.
Graphics, Imaging & Printing: QuickDraw: System 7.0ß1 BitMapToRgn limitation
BitMapToRegion does not work as described in Macintosh® Tech Note #275, for a PixMap with baseAddr = (NuBus™ address). Which calls support PixMap 32-bit base addressing with pmVersion = 4?
As of System 7.0ß1, BitMapToRgn cannot handle a bitmap whose base address is in the NuBus address space or any bitmap that requires 32-bit addressing. The problem will be fixed for System 7’s final release. BitMapToRgn seems to be the only call that doesn’t yet support 32-bit addressed bitmaps.
Graphics, Imaging & Printing: QuickDraw: Macintosh QuickDraw region quirks
I’m working with regions, and I’m having problems with Macintosh® QuickDraw™ trashing the heap and crashing, even though my regions are under 32K.
There are some quirks in the current version of QuickDraw. Here are some the commonly-encountered problems:
1. When doing operations which use more than one region, sduch as UnionRgn, DiffRgn, XorRgn, or SectRgn, the sum of the sizes of the source regions MUST BE LESS THAN 32K, regardless of the size of the resulting region.
2. FrameRgn will fail if it tries to frame a region bigger than 16K.
3. If CloseRgn fails, the internal region data is already corrupt; there is nothing you can do to recover. CloseRgn will also fail if there isn’t at least a 32K block of free space available.
Here are some workarounds:
1. Keep regions small and not too complex. Keep track of the sizes of all regions so you can check the SUM of the sizes before calling a routine that has a 32K limit.
2. Keep 32K free, or allocate a 32K block and release it just before calling CloseRgn.
Apple is working on these problems and expects to fix them in future versions of QuickDraw.
Graphics, Imaging & Printing: QuickDraw: How to get Macintosh QuickDraw arc endpoints
Is there a way to obtain the endpoints of an arc drawn by the Macintosh® QuickDraw™ arc routines, such as FrameArc and PaintArc?
Given a rectangle R which frames the arc you wish to draw, convert your angles to an absolute coordinate system, where three o’clock is 0 degrees and 12 o’clock is 90 degrees.
Now, let:
x = .5 (+ or -) (R.right - R.left)
y = .5 (+ or -) (R.bottom - R.top)
The endpoint of the curve will be defined by:
EndPoint.h = x (+ or -) cos(ang);
EndPoint.v = y (+ or -) sin(ang);
h & v are relative to center of rectangle R
This calculates only the upper endpoint of the arc, but you can easily calculate the other endpoint using the same formula by calculating the absolute angle for the start point and applying the same formula.
Here is a subroutine which illustrates the algorithm, in LightSpeed Pascal:
{ DrawCurve: draw an arc from 0 degrees until the point defined }
{ by 'angle'. At that point draw a 4 by 4 crosshair. }
procedure DrawCurve (frame : Rect; angle : integer);
var
x, y : integer;
xr, yr : extended;
rad : extended;
begin
{ Convert angle to radians }
rad := (90 - angle) / 180 * 3.14159;
{ Find end point }
xr := (frame.right - frame.left) * cos(rad) / 2;
yr := (frame.bottom - frame.top) * sin(rad) / 2;
x := (frame.right + frame.left) / 2 + Num2Integer(xr);
y := (frame.bottom + frame.top) / 2 + Num2Integer(yr);
{ Draw crosshair }
MoveTo(x - 4, y);
LineTo(x + 4, y);
MoveTo(x, y - 4);
LineTo(x, y + 4);
{ Draw arc }
FrameArc(frame, 0, angle);
end;
Graphics, Imaging & Printing: QuickDraw: Mac PixMap is clipped to visRgn defined by screenBits.bounds
I’m drawing into a large offscreen bitmap (PixMap), but anything drawn outside the 640 by 480 pixel Macintosh® screen area doesn’t get written to the PixMap. Why not?
When you create a new port with OpenPort or OpenCPort the visRgn is initialized to the rectangular region defined by screenBits.bounds (IM I:163). If your port has a large portRect, any drawing will be clipped to the visRgn and you will lose any drawing outside of the screenBits.bounds rectangle.
To correct this set the visRgn of the port to coincide with your port’s portRect after creating the port.
Also note that OpenPort initializes the clipRgn to a wide-open rectangular region (-32768, -32768, 32767, 32767). Some operations, like OpenPicture, can fail with this setup, so try setting clipRgn to a smaller rectangle.
Graphics, Imaging & Printing: QuickDraw: How to identify 32-Bit QuickDraw version
How can my program find out which version of Macintosh® 32-Bit QuickDraw™ is running?
The following code snippet demonstrates how to use the Gestalt Manager to determine which version of 32-Bit QuickDraw is installed. There is no way to determine the version of 32-Bit QuickDraw before Gestalt. For 32-Bit QuickDraw version 1.2, Gestalt returns 2.2. IM VI describes the Gestalt Manager in detail.
#defineTRUE0xFF
#defineFALSE0
#define Gestalttest0xA1AD
#define NoTrap0xA89F
main()
{
OSErrerr;
longfeature;
if ((GetTrapAddress(Gestalttest) != GetTrapAddress(NoTrap))) {
err = Gestalt(gestaltQuickdrawVersion, &feature);
if (!err) {
if ((feature & 0x0f00) == 0x0000)
printf ("We have Original QuickDraw version 0.%x\n", (feature & 0x00ff));
else if ((feature & 0x0f00) == 0x0100)
printf ("We have 8 Bit QuickDraw version 1.%x\n", (feature & 0x00ff));
else if ((feature & 0x0f00) == 0x0200)
printf ("We have 32 Bit QuickDraw version 2.%x\n", (feature & 0x00ff));
else
printf ("We don't have QD\n");
}
else
printf ("Gestalt err = %i\n",err);
}
else
printf ("No Gestalt\n");
}
Graphics, Imaging & Printing: QuickDraw: Macintosh Color QuickDraw CalcCMask and SeedCFill clarified
I’m having trouble using CalcCMask and SeedCFill. What am I doing wrong?
There is some confusion regarding the use of the Macintosh® Color QuickDraw™ routines CalcCMask and SeedCFill, which are analogous to the older CalcMask and SeedFill. Much of the confusion was caused by early documentation errors. Be sure you have the release version of Volume 5 of Inside Macintosh and version 2.0 or later of the MPW® interface files.
The correct interface for CalcCMask is:
PROCEDURE CalcCMask(srcBits, dstBits: BitMap;
srcRect, dstRect: Rect;
seedRGB: RGBColor;
matchProc: ProcPtr;
matchData: LongInt);
The correct interface for SeedCFill is:
PROCEDURE SeedCFill(srcBits, dstBits: BitMap;
srcRect, dstRect: Rect;
seedH, seedV: INTEGER;
matchProc: Ptr;
matchData: LongInt);
Each routine calculates a one-bit deep BitMap representing either the mask or the fill area depending upon the routine. In both cases, the source BitMap may be either a BitMap or a pixmap, but the destination must be a BitMap, because it must have a depth of one-bit.
It is difficult to pass a pixmap for the source parameter because of Pascal’s type checking. To get around this difficulty, you can declare a new type:
BitMapPtr = ^BitMap
then use it to coerce the pixmap as follows:
SeedCFill(BitMapPtr(@myPixMap)^, ...);
If you have a PixMapHandle, do the following:
SeedCFill(BitMapPtr(myPixMapHandle^)^, ...);
If you are using a GrafPort (or a window), you can pass myWindow^.portBits and not have to worry about whether the port uses a BitMap or a PixMap.
Most of the other parameters are explained in detail in Inside Macintosh. To use the matchProc and the matchData parameters, though, you need more information.
As stated in Inside Macintosh, the matchProc parameter is a pointer to a routine that you would like to use as a custom SearchProc. To better understand how this is used, it is helpful to know how SeedCFill and CalcCMask actually work.
Both routines start by creating a temporary BitMap which, by definition, is one bit deep. The source PixMap (or BitMap) is then copied to the temporary BitMap using CopyBits. This copy causes the image to be converted to a depth of one-bit. Now with a normal black-and-white image, the standard CalcMask or SeedFill routine is used to generate the destination BitMap.
Most of the real work is done in the original call to CopyBits, which maps the PixMap image to a monochrome BitMap equivalent. For each color in the source PixMap, CopyBits will map it to either black or white. Which colors map to black and which ones to white is determined by the SearchProc.
SeedCFill installs a default SearchProc that maps all colors to black except for the color of the pixel at (seedH,seedV). SeedFill then calculates as usual the fill mask for the white bits .
The default SearchProc for CalcCMask maps all colors to white except the color passed in the seedRGB parameter. The seedRGB parameter, then, would be the color of the item that you wanted to “lasso.”
But suppose you want to fill over all colors that were shades of green, not just the particular shade of green at (seedH,seedV). Or maybe you want to fill over all colors that are lighter than 50% brightness. Or maybe you want to use dark colors as edge colors for CalcCMask. To do such things, you need to pass a pointer to your own SearchProc in the matchProc parameter.
Because your matchProc is just a custom search procedure for the Color Manager, it should be declared as one, but Volumes I-V of Inside Macintosh have documented this routine incorrectly. The correct declaration for a custom SearchProc is as follows:
FUNCTION SearchProc(VAR RGB: RGBColor;
VAR result: LongInt) : Boolean;
Normally, as each SearchProc is installed, it is added to the head of the SearchProc chain, so that it is called before all of the other ones which were already installed. When a SearchProc is installed, it can do one of three things:
1. Completely ignore the call by returning FALSE and not modifying any of the input parameters; 2. Completely handle the call by setting the result parameter to be the index into the color table that matches (according to your rules) the RGB parameter. In that case, the SearchProc returns TRUE; 3. Partially handle the call by modifying the RGB parameter, then returning FALSE.
In cases 1 and 3, the Color Manager continues down the SearchProc chain until it finds one that returns TRUE. If none of the custom routines handle the call, then the built-in default routine is used. In case 3, you can change the RGB color that is being matched. For example, if you want all shades of green to map to pure green, modify the RGB color, then return FALSE, letting the Color Manager find the index of that green in the color table.
In case 2, you return TRUE to indicate that you handled the call, and you return the color table index in the result parameter. The Color Manager then uses that index. For example, if you want to substitute white for all colors that can’t be matched exactly in the color table, then each time you get called you either return the index into the color table of the exact color, or 0 (which is the index for white) for all other colors.
A custom SearchProc for SeedCFill and CalcCMask should always return TRUE because the default Color Manager SearchProc usually doesn’t make sense. Because SeedCFill and CalcCMask are using CopyBits to copy to a 1-bit BitMap, you need to set the result to be either 0 or 1 (the only possible values in a 1-bit BitMap). A result of 0 is white, and a result of 1 is black.
All colors for SeedCFill that should be “filled over” would generate a result of 0 (white), and all colors that stop the fill generate a 1 (black). SeedFill is then called to fill the white area. All colors for CalcCMask that you want to form boundaries should generate results of 1 (black).
When your SearchProc gets called, the gdRefCon field of the current GDevice (theGDevice^^.gdRefCon) contains a pointer to the following record:
matchRec = RECORD
red: Integer;
green: Integer;
blue: Integer;
matchData: LongInt;
END;
The red, green, and blue parameters for SeedCFill are the values of the color of the pixel at (seedH,seedV). For CalcCMask, they are the fields from the seedRGB parameter. Your SearchProc can use this information to decide which colors are “fill-over” colors and which colors are “boundary” colors. For example, if you always set (seedH,seedV) to be the mouse point, your SearchProc then bases its decisions using the color of the pixel under the cursor. For example, the user clicks on a shade of green, so all shades of green get filled over.
The matchData field contains the value that you passed into the SeedCFill or CalcCMask routines in the matchData parameter. The use of this field is completely user-defined. For example, since your SearchProc routine may be a separate module, you might want to use this field to pass a handle to your variables. This field can contain a handle, a pointer, a long integer, or whatever; or you can just ignore this field altogether.
Warning: There are some features of CalcCMask and SeedCFill you should be aware of. To understand them, you should be familiar with the use of CalcMask and SeedFill, which are described in the QuickDraw chapter of IM IV.
CalcCMask and SeedCFill both use a parameter set that is very similar to the one used by CopyBits. CalcMask and SeedFill, however, are a different story. Instead of passing bitmaps and rectangles to SeedFill and CalcMask, these routines use an unusual set of parameters that describe the memory to be operated upon in terms of pointers, height, width, and offsets to the next row (rowBytes). Although these parameters are fairly easy to calculate, there are some limitations.
The most restrictive limitation is that the width of the rectangle used must be an even multiple of 16 bits. This limitation exists because the width of the rectangle is passed to SeedFill and CalcMask as a number of words (2 bytes). When calculating this parameter, SeedCFill and CalcCMask round down to an even word boundary. This rounding means that the rectangles you pass to CalcCMask and SeedCFill should be an even multiple of 16 pixels in width. If they are not, then the rightmost portion of the mask will be garbage.
To figure out the color of the pixel at (seedH,seedV), SeedCFill calls GetCPixel. GetCPixel finds the color of the pixel at (h,v) in the current port. Therefore, if you pass a PixMap which is not the PixMap of the current port you will get bizarre results. In other words, seedH and seedV are expressed in the local coordinates of the current port, not the coordinate of the source PixMap.
You have two methods to make it work. First, always pass the PixMap of the current port as the source parameter. If you are using an off-screen PixMap, it is a good idea to have an associated port for it, and then call SetPort, passing it a pointer your off-screen port, before you call SeedCFill.
The second method involves letting SeedCFill get some wrong value for the color at (seedH,seedV) then using your own custom SearchProc to do the real work. The default SearchProc for SeedCFill relies on getting the correct color, but your SearchProc doesn’t have to.
SeedCFill also makes the assumption that the seedH and seedV parameters are in the local coordinate system of the destination BitMap. This assumption comes into play when SeedCFill calculates the seedH and seedV parameters for SeedFill.
All this means that SeedCFill only works correctly if the source PixMap, destination PixMap, and current port all use the same coordinate system. Because of the above problem, this is almost automatic since the current port’s portRect and the bounds of the source PixMap have to be the same anyway.
The easiest way to make all this work is to have your main port be an even multiple of 16 pixels wide. Then, make sure that your source and destination structures (PixMap or BitMap) are all the same size and all have origins of (0,0).
Graphics, Imaging & Printing: TrueType: SetPreserveGlyph and font glyph preservation
The TrueType SetPreserveGlyph call works as described for Times and Helvetica, but it doesn’t appear to affect New York, Geneva, Monaco, or Chicago. The glyph size remains constant regardless of preserveGlyph’s state. Is this supposed to happen?
TrueType’s SetPreserveGlyph call with preserveGlyph set to “true” works as you’d expect for Times and Helvetica, but it has no effect on New York, Geneva, Monaco, or Chicago.
Why does SetPreserveGlyph work this way? Glyph preservation is a function of the font. It turns out that Times and Helvetica have glyphs that extend above the ascent line, thereby enabling SetPreserveGlyph to have an effect on a particular glyph. New York, Geneva, Monaco, and Chicago’s characters all fit between the ascent and descent lines, and so do not need to be compressed to fit if preserveGlyph is true. A font must have glyphs extending above or below the ascent or descent lines for SetPreserveGlyph to have an effect.
To see the ascent or descent lines for a particular glyph, use one of the new TrueType font tools. These tools allow you to see the glyph with the ascent and descent lines drawn.
Graphics, Imaging & Printing: TrueType: Getting Macintosh character outline data
Can you describe a procedure for extracting TrueType™ character outline data directly from the Macintosh® system software?
Future releases of Macintosh system software probably will include calls for accessing TrueType character outline data. In the meantime, sample code showing how to parse the 'sfnt' outline font resource is available on Volume VIII of the Developer CD Series disc and on AppleLink in the Developer Support:Developer Services:Developer Technical Support:Developer Essentials:Sample Code folder.
Graphics, Imaging & Printing: TrueType: Macintosh 6.0.7 and TrueType
Where can I find information on manipulating TrueType® fonts under System 6.0.7?
The System 6.0.7 TrueType INIT includes all the outline calls in System 7.0, so everything you need is in Inside Macintosh Volume VI. See also the article “Scoring Points With TrueType” in this issue. Use Gestalt’s gestaltFontMgrAttr selector (described in the “Compatibility Guidelines” chapter of Volume VI, and available in System 6.0.4 and later) to determine whether TrueType is available on the machine in question, and then use outline calls freely and with abandon. The latest MPW release has the header files, called OutlineCalls. Use version 4.1 of Font/DA Mover to move outline fonts under System 6.0.7. Both the TrueType INIT and Font/DA Mover 4.1 are available on AppleLink® and on the Developer CD Series disc, and you can license Font/DA Mover to include it with your product release by contacting Apple’s Software Licensing group.
Networking & Communications: Alternate AppleTalk: EtherTalk DriverClose function
My EtherTalk DriverClose function is never called by the system, so my VBL and interrupt service routines remain active, even though another network device is active. Any ideas or tips on what might be going on?
Your findings are as per design. Just because the user decides not to use EtherTalk doesn’t mean that the user no longer wants Ethernet services. For example, the user might be using MacTCP. MacTCP accesses the .ENET driver directly, bypassing the LAP Manager. Should the NetWork cdev close the .ENET driver when the user switches to LocalTalk or TokenTalk while MacTCP is still using the driver, a system crash would likely result.
Networking & Communications: Alternate AppleTalk: Apple Ethernet Cable System power requirements
Sections 3.1.2 and 3.1.3 of the “Apple Ethernet Cable System Product Family Overview and Interface Descriptions” state that pin 1 provides either 12 V/2.1W or 5 V/1.9 W, and that 5 volts will be made available on pins 7 and 8, if the host can supply greater than or equal to 1.9W @ 5 V. Which models do not have 5 V available on pins 7 and 8, which models have 12 V on pin 1, and which have 5 V on pin 1?
All known hosts will provide 5 V at pins 7 and 8. It is absolutely NOT recommended that a Multiple Access Unit (MAU) designer use Voltage Agile (pins 1 and 14) powering to power a 5 V-only MAU. It is anticipated that all friendlynet-compliant hosts will supply +5 V to pins 7 and 8. Third parties desiring a 5 V-only MAU should use these pins.
MAUs using pins 1 and 14 MUST have a DC-DC converter.
Apple doesn’t presently have a product that uses +12 V on pins 1 and 14 but may in the future. As this is an “open standard,” at least one clone maker and several third-party Apple printer and card manufacturers use this interface, and others are expected.
Networking & Communications: Alternate AppleTalk: IEEE assigns Ethernet card addresses
We need a range of Ethernet card addresses to uniquely identify each Ethernet card we manufacture. We received board IDs and equates from Apple, but not the range of Ethernet addresses.
You weren’t sent a range of Ethernet addresses because Apple does not assign them. IEEE is the governing body that you have to contact to get a range of numbers; Apple had to do the same thing to get the numbers for its boards. IEEE will assign you a block of numbers that includes a unique manufacturer’s ID allowing network sniffers to recognize your products.
Networking & Communications: Alternate AppleTalk: “Undefined entry” link errors when opening Ethernet Driver
When I try to open the EtherNet driver as described in Inside Macintosh Volume VI on pages 32-80 and 32-81, I get the following undefined entry error messages:
### Link: Error: Undefined entry, name: (Error 28) "DisplaySInfo"
Referenced from: Init_Enet in file: Mac_Raid.c.o
### Link: Error: Undefined entry, name: (Error 28) "SaveSInfo"
Referenced from: Init_Enet in file: Mac_Raid.c.o
### Link: Error: Undefined entry, name: (Error 28) "SGetTypeSRsrc"
Referenced from: Init_Enet in file: Mac_Raid.c.o
Any clue as to where these are?
The “DisplaySInfo” and “SaveSInfo” are bogus procs that the sample writer didn’t take out or comment out.
However, SGetTypeSRsrc is a legal Slot Manager trap, IF you are using the new version of the Slot Manager. The definitions from the latest interfaces (slots.p, slots.h) are as follows:
FUNCTION SGetTypeSRsrc(spBlkPtr: SpBlockPtr): OSErr;
INLINE $205F,$700C,$A06E,$3E80;
#pragma parameter __D0 SGetTypeSRsrc(__A0)
pascal OSErr SGetTypeSRsrc(SpBlockPtr spBlkPtr)
= {0x700C,0xA06E};
The Slot Manager is dispatched via D0 selectors; there is no glue.
Networking & Communications: Alternate AppleTalk: Use EtherTalk 2.5 with Macintosh LC only
Which Macintosh® systems does EtherTalk® 2.5 support?
EtherTalk 2.5 was developed to provide EtherTalk services on the Macintosh LC system, including the resources for installing AppleTalk version 55 on the Macintosh LC. This was the only platform on which version 55 was tested and the only platform that should be used with this software.
Networking & Communications: Alternate AppleTalk: Selecting alternate AppleTalk driver at system startup
I need to know how to set the Macintosh® parameter RAM field that controls which alternate AppleTalk® driver is used at system startup (for example, EtherTalk®).
We discourage directly setting the parameter RAM. The Network 'cdev' and the 'adev' device work together to handle this. Each type of AppleTalk connection (other than LocalTalk®) must have its own 'adev' file. The construction of the 'adev' file is similar to that of a 'cdev' file. For each type of AppleTalk connection, such as EtherTalk, the 'adev' file must contain the following resources:
'ICN#'
'STR '
'BNDL'
'FREF'
owner resource
'adev' code resource
'atlk' code resource
The 'adev' and 'atlk' resources are pieces of stand-alone code that reside in the adev file. The 'adev' resource is responsible for handling all control panel interactions with the Network 'cdev'. The 'atlk' resource contains the actual implementation code for the supported AppleTalk connection. When the user selects an AppleTalk connection from the Network control panel, the Network 'cdev ' updates parameter RAM with a value that represents the AppleTalk connection that is currently selected. This value remains in parameter RAM after the user turns off the Macintosh.
More information about this can be obtained from EtherTalk and Alternate AppleTalk Connections Reference, available from APDA®.
Networking & Communications: AppleShare: System 7 and AppleTalk Internet Router
We’ve tried to run the Apple Internet Router with our System 7 File Sharing servers. There does not appear to be support for multiple networks. Is there some solution to this?
The AppleTalk Internet Router and System 7 are compatible, with two exceptions: virtual memory and 32-bit addressing. You need to drag-install it instead of using the Installer. The Installer script on the router disk will put the parts of the router in the wrong place. Here are the steps to drag-install the router:
1) Drag the files Router, LocalTalk (Built-in), and LocalTalk (Modem) from the System Folder on the “AppleTalk Internet Router” disk to the closed System Folder on the disk where you want to install. System 7 will automatically put the Router file in the System Folder, and put the LocalTalk (Built-in) and LocalTalk (Modem) files in the Extensions folder in the System folder.
2) Under System 7, open the System file on the “AppleTalk Internet Router” disk (double-click on the System file). A window will open showing the desk accessories, fonts, and sounds that are part of that System file. Drag the “Router” desk accessory from that window to the closed System Folder on the disk where you want to install. System 7 will automatically put the “Router” desk accessory in the Apple Menu Items folder in the System folder.
3) Reboot.
That’s all there is to it.
X-Ref:
“System 7: Installing Internet Router 2.0,” AppleLink Tech Info Library
Networking & Communications: AppleShare: AppleShare open file limit
AppleShare open file limit
On an AppleShare 2.0 File Server platform, the only application that can access files outside of the Server Folder (i.e., the System Folder) is the file server application. AppleShare Foreground applications (described in Macintosh Tech Note #167) are the only other applications that should be running on a server and they can only access files inside the Server Folder. All file forks (referred to as files from here on) opened by remote AppleShare workstations are opened by the File Server application.
The File Server application will open a file only one time. All access to that file from any number of workstations will use the single access path the File Server has opened. Only when all workstations have closed the file does the File Server really close the file on the server. So, that means only one FCB is used on the server per open file, even if 50 users have shared access to that file.
The File Server application handles all access control to an open file using the AppleTalk Filing Protocol (AFP) deny-mode permission model. The only reason a user won’t be able to open an access path to a file on a server is if another user has opened that file with a deny-mode that conflicts with the second user’s request, or the user does not have the access rights needed to open files in the file’s parent directory or directory ancestors. The AFP deny-mode permission model is described briefly in Inside Macintosh Volume V, File Manager Extensions In a Shared Environment, and in detail in the AppleTalk Filing Protocol chapter of Inside AppleTalk.
As noted in Macintosh Tech Note #216, the maximum number of open file forks on an AppleShare 2.0 server is either 80 on a 1-MB MC68000 server platform, or 160 on an server platform with more than 1MB and a MC68020 or greater processor. That figure includes the number of files kept open by the system and the file server application. If an AppleShare Foreground application is running on the server (for example, the AppleShare Print Server), then any files it may have open count against the maximum, too. The same can be said for open desk accessories. Tech Note #216 currently doesn’t say anything about those files counting towards the limit. If the 160 (or 80) file limit is a problem, you can use the “Up Your FCBs” INIT to bump the number of available up to the maximum (342) allowed by the File Manager. “Up Your FCBs” can be found on AppleLink in the Developer Support:Developer Technical Support:Hacks folder.
Networking & Communications: AppleShare: TMGetTermEnvirons envVersTooBig error
A call made to TMGetTermEnvirons returns -5502 or envVersTooBig. The call is made with a good terminal handle started from your TTY tool. What’s wrong? How do I fix it?
When you call TMGetTermEnvirons, the TermEnvironRec that you hand it a pointer to must have initialized the version field with curTermEnvRecVers. The following will work properly:
void getTEnvirons(TermHandle aTerm)
{ ...
TermEnvironRec tEnv;
TMErr err;
...
tEnv.version = curTermEnvRecVers;
err = TMGetTermEnvirons(aTerm,&tEnv);
/* check for errors, do whatever... */
...
}
This is consistent with most other Macintosh “get environment” calls such as SysEnvirons, and is documented (somewhat unclearly) at the top of page 113 in “Inside the Macintosh Communications Toolbox.”
Networking & Communications: AppleShare: Macintosh AppleShare versus FileShare capabilities
We are using the FileShare capabilities of Macintosh® systems with System 7.0 to make them mini file servers. Where can information that details the features of both AppleShare® and FileShare be found? We are considering using only FileShare in the office if it is capable of providing most of what AppleShare provides.
Information on file sharing can be found in the System 7 Personal Upgrade Kit and in Inside Macintosh, Volume VI, on your Developer CD Series disc. The maximum number of concurrent connections allowed on a Macintosh using file sharing is 10. The performance of an AppleShare® file server (the standard kind of server) is approximately 25% better than a similar configuration of Macintosh computers acting as a file sharing server.
Networking & Communications: AppleShare: AppleShare Apple II Setup current version is 2.1.3
Is there a new version of Apple II Setup for AppleShare® to go with the Apple IIGS® 5.0.4 system, or is 2.1.3 the latest?
Apple II Setup version 2.1.3 is the correct version to use with Apple IIGS System 5.0.4.
Networking & Communications: AppleShare: Macintosh EOF in an AppleShare environment
I ran into the following when updating the logical end of file (EOF) of a shared file: Application A and Application B have access to a file under AppleShare®. Each is using fsRdWrShPerm. When Application A changes the logical EOF, Application B doesn’t seem to notice that EOF has changed until Application B calls GetEOF. Is there a better way to make Application B aware of the change of logical EOF?
You’ve made a correct assumption that the correct way to keep track of EOF in an AppleShare environment is to ask for it. When you open a file, the AppleShare workstation code translates the Macintosh operating system Open call to the AFP (AppleTalk Filing Protocol) FPOpenFork call, and sets the bits in the bitmap parameter to current length of the fork opened (in the case of Open, the data fork). It then uses THAT as the EOF for future operations unless it gets an update from the server. Because the server does not constantly update everyone who has the file open, you have to ask to find if another user (or application) has made a change. Just remember that using GetEOF will only get you the EOF at that instant in time. Someone else sharing the file could change EOF right after you check it.
The PBLockRange function can be used by an AppleShare aware application to prevent another user from appending data to a shared file while you are appending data. For example:
paramBlock.ioRefNum := myFileRef;
err := PBGetEOF(@paramBlock, FALSE); {get the current EOF}
{check for errors in a real application}
oldEOF := paramBlock.ioMisc; {save the current EOF}
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := oldEOF; {start range lock at current EOF}
err := PCLockRange(@paramBlock, FALSE); {and lock the rest of
the fork}
{check for errors in a real application}
{now you can append data to the file}
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := oldEOF;
err := PCUnlockRange(@paramBlock, FALSE); {unlock the locked range}
{check for errors in a real application}
PBLockRange can also be used when you need to truncate a shared file. Locking the portion of the file you're about to truncate prevents another user from using that portion during the truncation process. For example:
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := theNewEOF; {start lock at truncation
point}
err := PCLockRange(@paramBlock, FALSE); {and lock the rest of the
fork}
{check for errors in a real application}
paramBlock.ioMisc:= theNewEOF;
err := PBSetEOF(@paramBlock, FALSE); {set the new EOF (truncate
the file)}
{check for errors in a real application}
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := theNewEOF;
err := PCUnlockRange(@paramBlock, FALSE); {unlock the locked range}
{check for errors in a real application}
The entire fork can be locked with:
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := 0; {lock from the beginning}
err := PCLockRange(@paramBlock, FALSE); {lock the whole fork}
{check for errors in a real application}
{do your thing}
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := 0; {unlock from the beginning}
err := PCUnlockRange(@paramBlock, FALSE); {unlock the whole fork}
{check for errors in a real application}
Networking & Communications: AppleShare: Macintosh file system active ranges
How many active ranges can a Macintosh® application have on a shared file? If the answer is more than one, is the limit per application or per machine? If two ranges overlap, are they joined into one range? Can an application nest ranges? For example, if an application’s user performs an action that forces a record to be locked and later the application locks the full range of the file, does the initial record lock disappear?
The only way to determine the limit is to hit the limit and get a NoMoreLocks error. The number of range locks supported is a limit of the server platform, and that limit is shared by all users of the server (at least it is with Apple’s AppleShare® server software). With Apple’s server-based version of AppleShare, approximately 40 locks per user are allowed (for example, if the server allows 25 users, there are 1000 locked ranges total; if the server allows 50 users, there are 2000 locked ranges total; and with File Sharing running under System 7.0, approximately 20 locks are allowed per user). Other vendors may allow more or fewer locked ranges on their implementations of an AppleTalk® Filing Protocol (AFP) server. Notice that the numbers given are per user, not per application. It’s assumed that a user probably won’t need more than a few locks at a time on a single file.
You cannot have range locks that overlap. You’ll get a RangeOverlap error from AFP. All the rules for range locking can be found in the AFP chapter of Inside AppleTalk (page 13-56). Additional information on AppleShare limits is available in the Dev Tech Answers library on AppleLink and on the Developer CD Series disc.
The February 1991 revision of Macintosh Technical Note #186 covers several important details about PBLockRange and PBUnlockRange that are not in Inside Macintosh.
Networking & Communications: AppleShare: Purpose of AppleShare SP file
What is the file “AppleShare® SP” and what does it do? The AppleShare File Server seems to run without it, and it reduces the alert sound to just a beep even when the server is not running on that computer. Is the file really needed?
You do need the AppleShare SP INIT on your file server. The AppleShare SP (Small Patch) INIT is designed to correct a minor incompatibility between AppleShare 2.0x and the Sound Manager. The INIT forces the Macintosh® to use the “Simple Beep” sound at all times. System 7.0 file sharing and future versions of AppleShare do not need the INIT.
Networking & Communications: AppleShare: Software-selecting an AppleShare volume
Is there any source code available for mounting/unmounting AppleShare® volumes?
There are actually a couple of ways to select an AppleShare volume. You could use the ‘Choose’ tool in MPW® that accomplishes this, or you can do it with aliases under System 7. Other than the MPW tool, there is no other supported way of doing this under pre-7.0 systems; there are no current ‘hooks’ to allow easy mounting of AppleShare volumes programmatically. It gets pretty nasty trying to figure out everything that is necessary to accomplish this, which is why people here pretty much stay away from this as well. Also, some low-level stuff may be proprietary, which is why the tool is supplied for developers. ‘Choose’ is described in the MPW docs. It should be pretty straightforward to use.
Networking & Communications: AppleShare: Apple II Aristotle “Access Privileges” recommendations
What is the reason that when I try to log into AppleWorks 3.0 network through Aristotle on an Apple IIGS® I get the message “System error in Server/ Server.Setup / CDevInit See your Network Administrator”?
It sounds like the access privileges for the System folder (the one containing the Apple IIGS System files) are set wrong. I recommend that the System folder and all of the folders within it, and the Icons folder (the folder that contains the Apple IIGS icon files) be set to Bulletin Board (if you use an Apple IIGS to set the privileges) or See Folders = Everyone, See Files = Everyone, Make Changes = Owner, where the Owner is the system administrator.
Networking & Communications: AppleShare: Detecting AppleTalk being closed down by user
How do I detect that a user has closed down my AppleTalk® connection (by turning AppleTalk off from the Chooser or by changing network connections from the Network control panel)?
The AppleTalk Transition Queue provides a means to determine when the AppleTalk drivers change status or when they might be closed in the very near future. The Transition Queue informs its clients (everyone who has asked to be added to the queue) each time the state of the .MPP driver changes state (opened or closed) or is about to change state.
The AppleTalk Transition Queue is documented in Inside Macintosh VI, Chapter 32 (The AppleTalk Manager) and is also documented in the Macintosh® AppleTalk Connections Programmer’s Guide, Chapter 3 (“Calls to the LAP Manager”), available from APDA.®
Networking & Communications: AppleShare: How to tell if application’s running on a server
What is the best way to determine if a Macintosh® application is running on a server?
For 2.0.1 you can test the longword at $B50. If it is 0 or -1, the server is not running. If it isn’t—i.e., it’s a real address—then the server is either starting up, or is running. There might be a hook available in future versions of AppleShare which your process can hook into.
Networking & Communications: AppleShare: Server Move & Rename folder
A folder is created in the Server Folder called “…Move & Rename.” What is this and what are its contents? Should it be backed up? Are there any other temporary folders and files that might need to be backed up?
It’s the “$01$02$03Move & Rename” folder that AppleShare 2.0.1 and future versions create for the two-step process of moving and renaming a file or a folder, a feature that is not provided via HFS. It should be backed up, but in general will not contain anything. (It has something in it only for a brief instant and only if the server has IBM PCs or some other computer that uses this call. Macintosh systems don’t.) It needs to be backed up for 2.0.1 so that the folder is there if the server is restored. (Otherwise, Admin will have to be run to create a new one, a somewhat disconcerting action to perform after completely restoring a file server.)
Networking & Communications: AppleShare: 2.0.1 PBHGetDirAccess and PutDirAccess restrictions
If a volume is connected to an AppleShare server, but is not an AppleShare volume, will the PBHGetDirAccess (and PutDirAccess) function work on it? Can an INIT on the server make these calls?
For AppleShare 2.0.1, the INIT cannot make these calls on non-file server volumes. In future versions, the PBHGetDirAccess and PutDirAccess calls can safely be made on all volumes connected.
Networking & Communications: AppleShare: AppleShare user limit
What is the maximum number of users that can be logged in to any one AppleShare® file server? What can we do to increase the limit? Will upgrading to AppleTalk® Phase II help? Is there an upgrade to the AppleShare 2.0.1 software?
AppleShare currently has a limit of 50 simultaneous users. This is a limitation in the software and is not related to AppleTalk. Changing from AppleTalk Phase I to Phase II will not change anything. The next version of AppleShare might raise this limitation. We do not have any projected dates for a release of the next version of AppleShare. You may want to periodically check with APDA® for any update or new release.
Networking & Communications: AppleShare: Maximum number of users supported by AppleShare for each CPU
What is the maximum number of users supported by AppleShare®? Does this number change based on the type of CPU being used for the server?
The following chart lists some current AppleShare limits (AppleShare 1.1, 2.0, and 2.01) which are based upon the chosen server platform and memory configuration. The limits which otherwise might be present on a workstation are still in effect, and are not affected by the workstation being logged into an AppleShare server. These limits will change in the future.
Server machine is Macintosh Plus, SE, or II with one MB:
Number of users: 25
Number of locked ranges: 1000
Number of open files: 80
Number of volumes: 16
Server machine is Macintosh II with more than one MB:
Number of users: 50
Number of locked ranges: 2000
Number of open files: 160
Number of volumes: 16
Networking & Communications: AppleShare: Accessing the Server Folder on the AppleShare file server
I am trying to access the Server Folder on AppleShare® file server from my program. I have tried AFP (AppleTalk Filing Protocol) calls OpenDir and EnumerateCatalog, but they cannot access the Server Folder. Is there another method to access a Server Folder?
No. Access to the Server Folder of an AppleShare server is not possible except during local maintenance of the AppleShare server. It is then only accessible through the Finder™ while the AppleShare server application is not running.
Networking & Communications: AppleShare PC: AppleShare PC 2.0 changes
What are the new changes to AppleShare® PC 2.0?
AppleShare PC 2.0 was designed to affect developers in a MINIMAL way, so there were some very MINOR changes to the way programmers interact with AppleShare PC 2.0.
• The Int60 mechanism no longer exists; now far calls to the code are made.
• DS:BX no longer contains the parameter block pointer; ES:BX does.
• Commands 4, 5, 6, and 7 are no longer supported.
• The Open Data-Link Interface (ODI) was used and adhered to in the design of AppleShare PC 2.0.
• Compat.com was created and included to make all previous applications useable and compatible with AppleShare PC 2.0.
If your application uses any of these older methods (as outlined in the “LocalTalk® PC Card and Driver Preliminary Notes”), compat.com “translates” the interface to one which AppleShare 2.0 is able to use (that is, put DS:BX into ES:BX, make a far call to the code, and call different commands which replace commands 4,5,6 and 7).
ODI, which was co-developed with Novell, makes it possible for many different cards with different drivers to be usable by different upper-layer protocols. If there are ODI drivers for a given TokenRing/Ethernet/LocalTalk card, AppleShare PC 2.0 will work over TokenTalk/EtherTalk/LocalTalk. Currently, there are several drivers provided with AppleShare PC 2.0: IBM TokenRing drivers (IBM TokenRing cards—short, long and MCA), two Ethernet drivers (EtherLink MC Adapter card, and EtherLink II card), and the LocalTalk PC card driver. For more information about ODI, and/or becoming an ODI developer, contact Scott Lemon at Novell.
To use the AppleTalk® protocol stack (included as part of AppleShare PC 2.0), you need to reference the “LocalTalk PC Card and Driver Preliminary Notes” (August 3, 1987). These notes detail the AppleTalk stack and the PC interfaces to the stack. The “LocalTalk PC Card and Driver Preliminary Notes” document is available through APDA® (Order #M7055).
Networking & Communications: AppleShare PC: AppleShare PC 2.0 supports EtherTalk and TokenTalk
Does AppleShare® PC support EtherTalk®? TokenTalk®?
AppleShare PC v2.0 supports both EtherTalk and TokenTalk. Cards that work
include:
• 3Com’s EtherLink and EtherLink/MC Ethernet cards
• IBM’s TokenRing cards (long, short and MCA)
• DayStar Digital’s LocalTalk® board
Networking & Communications: AppleTalk: How to get the User and Computer names used by AppleTalk
I’d like to use the same names that the system uses to identify itself on the AppleTalk network in my program. Where can I find those names?
The names used by the system for network services are stored in two 'STR ' resources in the System file. Your program can retrieve those names with the Resource Manager’s GetString function.
Only one of the names is available in systems before System 7; the name set by the Chooser desk accessory. That name is stored in 'STR ' resource ID - 16096. Under System 7, the Sharing Setup control panel lets the user assign two names for network services: the Owner name and the Computer name.
The Owner name is the name stored in 'STR ' resource ID -16096 and it identifies the user of the Macintosh. The Owner name is used by System 7 for two primary purposes: to identify the owner of the system when accessing the system remotely through System 7 File Sharing or the user identity dialog used by the PPC Toolbox (and Apple Event Manager), and as the default user name when logging on to other file servers with the Chooser.
The Computer name (also known as “Flagship name”) is the name stored in 'STR ' resource ID -16413 and used to identify the Macintosh. The Computer name is the name used by system network services to identify themselves on the AppleTalk network. For example, if your system’s Computer name were "PizzaBox", the PPC Toolbox registers the name “PizzaBox:PPCToolBox@*” when you start Program Linking and File Sharing registers the name “PizzaBox:AFPServer@*” when you start File Sharing.
Networking & Communications: AppleTalk: Which AppleTalk routines can & can’t be called at interrupt time
Can any AppleTalk routines be called at interrupt time? Inside Macintosh says that DDPWrite and DDPRead can’t be called from interrupts. If all higher-level AppleTalk protocols are based on DDP, it seems that they all would not work.
The AppleTalk routines you can’t call at interrupt time are the original AppleTalk Pascal Interfaces listed in Inside Macintosh Volume II; these are also known as the “Alternate Interface” AppleTalk routines, or ABPasIntf.
The Alternate Interface routines cannot be called at interrupt time because they allocate the memory structures needed to make the equivalent assembly language AppleTalk call. For example, when the NBPLookup routine is called, it’s passed a handle to an ABusRecord. NBPLookup then has to allocate an MPPParamBlock and move the parameters from the ABusRecord into the newly allocated MPPParamBlock. Then NBPLookup makes a LookupName call, passing it the MPPParamBlock. When LookupName completes, NBPLookup must move results into the ABusRecord and release the memory used by the MPPParamBlock. Since memory is allocated and released within the routine, it cannot be called at interrupt time.
With that out of the way, the calls you can make at interrupt time (with some restrictions listed below) are what Apple calls the “Preferred Interface” AppleTalk routines. Most of the Preferred Interface routines are listed on page 562 of Inside Macintosh Volume V. There are a few additional calls that were added after the publication of Inside Macintosh Volume V; they’re documented in the AppleTalk chapter of Inside Macintosh Volume VI.
The Preferred Interface AppleTalk routines can be made at interrupt time as long as:
• You make them asynchronously with a completion routine (that is, the asynch parameter must be TRUE and you must provide a pointer to the completion routine in the ioCompletion field of the call’s parameter block). Making a call asynchronously and polling ioResult immediately afterward within the same interrupt-time code (which is basically the same as making the call synchronously) is not the same as using a completion routine.
• They are not listed as routines that may move or purge memory. The Preferred Interface routines do not allocate or dispose of any memory, since they’re just high-level ways to make the assembly language AppleTalk calls and are not built upon the old Alternate Interface routines.
X-Ref:
Macintosh Technical Note #121, “Using the High-Level AppleTalk Routines”
Macintosh Technical Note #132, “AppleTalk Interface Update”
Macintosh Technical Note #142, “Avoid Use of Network Events”
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): PPC Toolbox and its use of AppleTalk protocol layers
Can I use the PPC Toolbox’s program linking dialog interface via the PPCBrowser function with AppleTalk protocols such as ADSP, ATP, and DDP? If not, can I access the ADSP data structures used by the PPC Toolbox?
The PPCBrowser function is for use by applications that use the PPC Toolbox, high-level events, or Apple events (high-level events and Apple events depend on the services of the PPC Toolbox). The PPCBrowser uses the functions GetZoneList, PLookupName, and IPCListPorts to fill the AppleTalk Zones, Macintoshes, and Programs lists in the program linking dialog. Since the IPCListPorts function returns a list of PPCPorts at a particular location, it isn’t useful for AppleTalk protocols and thus, makes the PPCBrowser function unsuitable for use with AppleTalk protocols which don’t have PPCPorts associated with them. It’s fairly easy for an application to create a browsing dialog for AppleTalk protocols that has two lists, one for zones found with GetZoneList and one for entity names found with PLookupName. See the “dmz” example on the Macintosh System Software 7 Golden Master CD for example code that builds two such lists.
Although the PPC Toolbox currently uses ADSP as the transport mechanism to communicate with other Macintosh systems, the ADSP structures used by the PPC Toolbox aren’t accessible for good reason: The transport mechanism used by the PPC Toolbox could change in the future to support other transport mechanisms besides ADSP. (On the local machine, PPC transfers the data directly, circumventing ADSP.) If you really need to use ADSP in a way that the PPC Toolbox does not, then you should skip the PPC Toolbox and use ADSP directly.
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): ADSP dspAttention and attention retransmit timer interval
I’m having problems with the AppleTalk Data Stream Protocol (ADSP) call dspAttention. Sometimes it takes several minutes for dspAttention to complete. I’ve tried using ADSP 1.5.1 with System 6.0.7 and ADSP 56, which ships as part of System 7.
ADSP 1.5.1 (and ADSP 56) no longer uses the attnInterval field in the DSPParamBlock for the attention retransmit timer interval. Instead, the attention retransmit timer interval is based on the round-trip time of ADSP data packets. When a connection end is established, the attention retransmit acknowledged, the attention retransmit timer interval is adjusted for the connection speed. This mechanism works well when a connection end is established, an ADSP connection is opened, the connection is used, the connection is closed, and then the connection is eliminated.
A problem in this mechanism can surface when a connection end is established and is reused over and over for several ADSP connections. When a connection is closed and then a new connection is opened using the same connection end, the attention retransmit timer interval is not reset to the default starting value (the problem). Instead, some garbage value in memory is used. If the first ADSP attention packet or the acknowledgment packet returned for that attention packet is lost on the network, ADSP will use the “garbage” value for the attention retransmit timer interval and it could take several minutes for ADSP to retry sending the attention packet.
This has been fixed for versions of ADSP greater than version 56 and will be available soon (maybe by the time you read this message). Until then, the only workaround is to use a new connection end for every new ADSP connection requiring ADSP’s attention mechanism.
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): ADSP closes connections on eClosed or eTearDown events
When I receive an eClosed or eTearDown ADSP connection event, do I have to close my end of the connection, or does ADSP close it automatically?
When you get a eClosed unsolicited event, it means the other (remote) side of the ADSP connection sent a Close Connection Advice control packet and ADSP has closed the connection. It is purely advisory and does not require you to take any action. The Close Connection Advice control packet allows ADSP to close connections faster than just waiting for the connection to time-out due to the open timer expiring.
When you get a eTearDown unsolicited event, it means the network connection with other side of the ADSP connection was lost (the open timer expired) and ADSP has closed the connection. Again, it is purely advisory and does not require you to take any action.
The ADSP chapter of Inside AppleTalk® (Chapter 12) might help other questions you have about ADSP in the future since it explains how ADSP works beneath the Macintosh® implementation documented in Inside Macintosh® Volume VI.
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): AppleTalk Data Stream Protocol references
Where are the AppleTalk® Data Stream Protocol (ADSP) calls documented?
APDA® has a product called “ADSP: AppleTalk Data Stream Protocol Development Kit” that gives you ADSP and the ADSP call descriptions. ADSP and ADSP interfaces can be found on the Developer CD and can be used for your development purposes. However, you’ll need to license ADSP through Apple Software Licensing (AppleLink®: SW.LICENSE) before you ship your product.
If you want to use ADSP, then you should read ALL of the documentation. There are various tips and explanations that may be vital to your implementation of ADSP in your product. It is useful for transferring data between machines and provides built-in error checking to ensure that you do receive the data at the other end. For these reasons, you should read Inside AppleTalk, Chapter 12, Apple Data Stream Protocol, to make sure you utilize it to its fullest.
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): Sending broadcast packets to transmit data to multiple clients
How do I broadcast information over AppleTalk® using the Communications Toolbox (CTB) and the AppleTalk Data Stream Protocol Development (ADSP) Tool or multiple access? I cannot find any significant information regarding broadcast or multiple access transmissions.
There is no supported method to send broadcast packets to transmit data to multiple clients. The reason is that this method does not ensure the data was received by every client. It is possible to lose a packet on a network before it reaches a client even though it may reach the others. If this is the case then the data is lost forever for this client unless you resend the packet. This is highly inefficient and unreliable.
If you want to have multiple clients, then you’ll need to write your own server software that can handle multiple clients logged on simultaneously. The server will then need to keep a record of every connection and its corresponding transaction ID even though you will be sending the same information to each client; this is to ensure that each client receives the data. Following the ADSP protocol should be enough for you to implement this server/client connection and ensure that the data is reliably transmitted to each node.
Networking & Communications: AppleTalk Data Stream Protocol (ADSP): Using ADSP with AppleTalk for Apple’s VMS
I am trying to create a simple program to try ADSP (AppleTalk® Data Stream Protocol) with AppleTalk for Apple’s VMS (version 2). I started the bridge process but got an access violation on the first call.
You need to make three calls before you can call any other functions with AppleTalk for VMS. These calls are:
ATK$INIT_ATALK
ATK$INIT_PORT
ATK$OPEN_PORT
Then you can use the other routines.
Networking & Communications: AppleTalk Filing Protocol (AFP): How an AFP volume’s allocation block size is calculated
The AppleTalk Filing Protocol (AFP) doesn’t appear provide a way to learn about the allocation block size of a server volume. So, how is the allocation block size determined on AFP server volumes? I noticed that the Macintosh® Finder™ seems to calculate “size on disk” erratically for files on some AFP server volumes. Is that a related problem?
All the workstation can get from an AFP server is the Bytes Total and Bytes Free (returned by FPGetVolParms and FPOpenVol), so the AFP workstation code estimates the value it uses in the allocation block size field (vcbAlBlkSiz) of the volume control block (VCB). The workstation code comes up with a value for vcbAlBlkSiz from the Bytes Total value returned to FPOpenVol when the volume is opened. The calculation used is:
vcbAlBlkSiz := round((BytesTotal / (512 * 65536)) + 0.5) * 512;
This is the same value a local HFS volume would use. If an AFP server is not running on a Macintosh (and then, probably not using HFS), then this value may not be what the server platform is actually using. And yes, the Finder uses the allocation block size in its calculations to decide how much space is used by a file, so the “size on disk” may not exactly reflect the amount of disk space actually used.
Networking & Communications: AppleTalk Filing Protocol (AFP): AFP 2.0 FPRead NewLine Mask change
I’m confused about the changes to FPRead in AFP (AppleTalk® Filing Protocol) version 2.0. How do I use the NewLine Mask?
The difference between AFP 1.1 and AFP 2.0 as far as the NewLine Mask is concerned is that, in AFP 1.1, the only legal values of NewLine Mask are $00 and $FF, whereas in AFP 2.0, all values of NewLine Mask are allowed. The NewLine Mask is logically ANDed with a copy of each byte read. If the result matches the NewLine character, the read terminates. The NewLine character is returned as the last byte of data that was read from the fork.
Networking & Communications: AppleTalk Session Protocol (ASP): ASPOpenSession error -17 bug fixed for next System 7 beta
Why does an attempt to open a remote database file that is hosted under both Macintosh® System 6.0.x and 7.0ß1 cause the AppleTalk® ASPOpenSession routine to always returns the error code -17 (I/O control error)?
This is a known bug with System Software 7.0ß1 and has been fixed, so the next release of 7.0 that you get should work again. I checked to see if there was a work-around that you might be able to patch into your application for 7.0ß1 but there isn’t.
Networking & Communications: AppleTalk Session Protocol (ASP): Server side of AppleTalk Session Protocol
I have the client side of the AppleTalk® Session Protocol (ASP), but not the server side. How do I get the server side of the protocol?
Apple only provides the interfaces and the driver for the workstation side of the ASP. We do not provide interfaces or the driver for the server side.
Depending upon your project, you can either use Apple’s implementation of an ASP/AFP server (AppleShare®) or write your own ASP server side of the protocol.
Networking & Communications: AppleTalk Tools: AppleTalk Peek and Poke tools
Is there an update for the Apple tool called Poke?
The following versions of Peek and Poke are current:
AppleTalk Peek 3.1
AppleTalk Peek 3.2d5
AppleTalk Poke 3.1
You’ll find them on Lord of the Files, the latest Developer CD Series disc, in Tools & Apps:Networking & Communications:AppleTalk Tools.
Networking & Communications: AppleTalk Transaction Protocol (ATP): Responder protocol documentation not available
Can you please point us to the note that describes the Responder protocol? I recall seeing it documented somewhere.
If you have seen any Responder documentation around, it must be bootleg documentation. After talking with the AppleTalk® engineers, I was assured that this documentation is not available. Some people wanted it available; others didn’t. Guess who won.
Anyway, the Responder uses ATP (AppleTalk Transaction Protocol) as well as AEP (AppleTalk Echo Protocol) to send/receive data from one machine to another. If you have a copy of Peek and Inter•Poll you can check this out on the network to better understand it. It’s a pretty straightforward implementation. AEP and ATP are documented in Inside AppleTalk. These, coupled with Gestalt or SysEnvirons, to get any machine-specific information you may wish to send, should be all you need to understand how the Responder works.
Networking & Communications: Connection Manager (CTB): Systems 6 & 7 Macintosh Comm Toolbox (CTB) installation
How do users install the Macintosh Communications Toolbox (CTB)?
The Communications Toolbox consists of two parts: the CTB managers and the CTB tools. The installation procedure for CTB tools is different between System 6 and System 7. Under System 6 the CTB tools are dragged from the Basic Connectivity Set disk to the Communications Folder in the System Folder on the hard disk. Under System 7 the CTB tools are dragged from the Basic Connectivity Set disk to the Extensions folder in the System Folder on the hard disk. Of course, because of the way System 7 works, CTB tools can simply be dragged to the System Folder and the Finder will automatically move them to the Extensions folder where they belong.
No installation of the CTB managers is required under System 7, since System 7 includes the Communications Toolbox as part of the system. Users running System 6.0.5 should use the Installer and Install script on the Communications 1 disk to install the CTB managers and other resources onto their hard disks. Users running System 6.0.7 should use the Installer and Install script on the Network Products Installer disk, which is part of the System 6.0.7 set users receive with their Macintosh systems. The Network Products Installer disk does not contain the CTB managers and other resources, but it prompts the user to insert the Communications 1 disk during the installation procedure.
The Basic Connectivity Set and Communications 1 disks should be shipped with your CTB-aware product. Contact Apple’s Software Licensing group (AppleLink SW.LICENSE) for a licensing agreement to ship the disks.
Networking & Communications: Connection Manager (CTB): Macintosh CTB CRMSerialRecord documentation correction
Macintosh CTB CRMSerialRecord documentation correction
On page 183 of Inside the Macintosh Communications Toolbox, the CRMSerialRecord data structure contains two fields, inputDriverName and outputDriverName, declared as type StringHandle. These two fields are erroneously described as “pointer to Pascal string” in the documentation further down the page. The correct declaration is type StringHandle.
Networking & Communications: Connection Manager (CTB): Macintosh Communications Toolbox resource ID conflicts
Macintosh Communications Toolbox resource ID conflicts
MPW’s Simple I/O Window (SIOW) package is incompatible with certain Macintosh Communications Toolbox (CTB) Tools because of difficulties with CMGetConfig and CMChoose. The CTB and Tools do a somewhat imperfect job of looking in the correct resource map for string components used in CMGetConfig; the application-defined 'STR ' IDs override the correct Tool defined IDs. CMChoose has a similar problem with 'CNTL' resource conflicts.
This problem is not confined to SIOW; it can happen for any application. In the case of SIOW, it is particularly frustrating since SIOW is a precompiled library and you can’t simply change resource IDs to ones that don’t conflict. Also, you cannot be certain that you won’t ever conflict in this manner for any arbitrary Tool and application.
There is a workaround to this situation which should be used for all applications, not just SIOW-based apps. The CTB makes sure that resource maps for Tools are searched after the system resource map—that is, instead of the resource chain looking like this:
ROM (resource lookup progresses from the bottom up)
System
Application
Document
Tool
it looks like this:
ROM
Tool
System
Application
Document.
The workaround is to save the current resource file reference, set the current resource file to the System file, and return to the proper resource file after completing CMGetConfig or CMChoose. Here is a C code fragment illustrating this technique:
{ ...
short saveResFile;
Point displayPt;
Ptr cfgString;
...
// save the current resource file
saveResFile = CurResFile();
// set resource file to the System file
UseResFile(0);
// call CMChoose to configure the Tool
err = CMChoose(&connectionHdl,displayPt,NULL);
// call CMGetConfig to get the configuration string
cfgString = CMGetConfig(connectionHdl);
// restore proper resource file
UseResFile(saveResFile);
...
}
and again in Pascal:
VAR
...
saveResFile : INTEGER;
displayPt : Point;
cfgString : Ptr;
BEGIN
...
{save the current resource file}
saveResFile := CurResFile;
{set resource file to the System file}
UseResFile(0);
{call CMChoose to configure the Tool}
err := CMChoose(connectionHdl,displayPt,NIL);
{call CMGetConfig to get the configuration string}
cfgString := CMGetConfig(connectionHdl);
{restore proper resource file}
UseResFile(saveResFile);
...
END;
Networking & Communications: Connection Manager (CTB): Mac Communications Toolbox (CTB) theEnvirons initialization
Mac Communications Toolbox (CTB) theEnvirons initialization
The Macintosh Communications Toolbox (CTB) Connection Manager and Terminal Manager each support a “get environment” function in order that the application can obtain the current environment of the connection or terminal record. They are declared as follows in the Pascal interface files:
FUNCTION CMGetConnEnvirons(hConn: ConnHandle;
VAR theEnvirons: ConnEnvironRec): CMErr;
FUNCTION TMGetTermEnvirons(hTerm: TermHandle;
VAR theEnvirons: TermEnvironRec): TMErr;
and in the C header files:
pascal CMErr CMGetConnEnvirons(ConnHandle hConn,
ConnEnvironRec *theEnvirons);
pascal TMErr TMGetTermEnvirons(TermHandle hTerm,
TermEnvironRec *theEnvirons);.
“Inside the Macintosh Communications Toolbox” does not make it clear that the respective theEnvirons parameter blocks used for these two functions require initialization for the functions to operate correctly. For CMGetConnEnvirons, theEnvirons.version should be initialized with the constant curConnEnvRecVers; similarly, TMGetTermEnvirons needs theEnvirons.version initialized with the constant curTermEnvRecVers. These constants are defined in Connections.p and Terminals.p (Connections.h and Terminals.h for C).
Initializing theEnvirons properly will prevent error result codes envBadVers or envVersTooBig. On return with cmNoErr or tmNoErr results, CMGetConnEnvirons and TMGetTermEnvirons will have filled in theEnvirons correctly for the version you specified and will update theEnvirons.version with the current revision level of the environment function call.
Networking & Communications: Connection Manager (CTB): Macintosh Communications ToolBox (CTB) initialization
Is there a way to tell if Macintosh Communications ToolBox (CTB) is already initialized? The CTB documentation says to make initialization calls once and only once.
The CTB documentation isn’t really true in that regard. It was originally thought that you couldn’t re-initialize the CTB, but that was changed, and it is safe to do so.
Networking & Communications: Connection Manager (CTB): Installer 3.2 and Macintosh Communications Toolbox
How do we make the Macintosh Communications Toolbox (CTB) installation script work with Installer 3.2 for users running System 6.x?
The current installer script for the CTB is not compatible with Installer 3.2, nor will it be in the near future. Installer 3.2 was designed to be compatible with System 7.0. Because the CTB is included with System 7.0, and Systems 6.0.5 and 6.0.7 come with the installation disk necessary to install the CTB, there’s no need to update the script. There isn’t really any Apple-approved way to make the script Installer 3.2-compatible.
Your users who are still using System 6.0.7 (or earlier) need to install the CTB separately from your product. They should have the installation disks necessary to install the CTB on their system. For System 6.0.5, they’ll need to use the Installer and Install script on the Communications 1 disk to install the CTB managers and other resources onto their hard disks. Users running System 6.0.7 should use the Installer and Install script on the Network Products Installer disk, which is part of the System 6.0.7 set users receive with their Macintosh systems. The Network Products Installer disk does not contain the CTB managers and other resources, but it prompts the user to insert the Communications 1 disk during the installation procedure.
The Basic Connectivity Set and Communications 1 disks should be shipped with your CTB-aware product. Contact Apple’s Software Licensing group (SW.LICENSE on AppleLink) for a licensing agreement to ship the disks. This will also help ensure that the users are using the version of the tool(s) that is most compatible with your product.
Remember to use Gestalt to make sure that you have the Communications ToolBox available, and check to make sure that the tools you need are available as well. For specific information on using Gestalt, please refer to Inside Macintosh Volume VI and Macintosh Technical Note #129, “_Gestalt and _SysEnvirons-A Never Ending Story.”
Networking & Communications: Connection Manager (CTB): Macintosh Communications ToolBox documentation
Can you point me to documentation on the Macintosh Communications Toolbox?
Inside the Macintosh Communications Toolbox (Addison-Wesley, APDA #M1215LL/A, $24.95) is a nice, comprehensive manual, detailing how to write programs that use the Communications Toolbox. In addition, the documents for the newly updated Macintosh Communications Toolbox 1.1 APDA packages are useful supplements to the Addison-Wesley reference.
Networking & Communications: Connection Manager (CTB): Customizing a modem’s initialization string
How do you customize the intialization string of a modem?
If the user holds down the option key while clicking on the Modem Type Popup menu in the lower left corner of the “Apple Modem Tool” dialog box, then an additional menu item appears. This item is called “custom,” and when selected, it brings up another dialog that contains the initialization string of whichever modem type (such as Hayes or Apple Personal) was LAST selected. You can then customize the intialization string to whatever you want it to be. In other words, select the modem, use the option-select method to get to custom, and then edit the init string.
Networking & Communications: Connection Manager (CTB): Connection Manager and connection records
When my application quits after using the Connection Manager to create a connection record but before the record is disposed, I can no longer create a connection record. Even if I exit the application and re-launch, it still does not work unless I re-boot. Is this a bug?
The behavior you describe is normal for Communications ToolBox 1.0. This has to do with how the CTB manages mapping shareable resources, heap zones, Resource Manager interactions, and all that. If you have a ConnectionHandle in a heap zone which is opened and you then dispose of the heap zone without closing it, the Connection Manager will be confused about life in general until you restart the Macintosh.
Networking & Communications: Connection Manager (CTB): Macintosh Communications Toolbox manual init correction
Macintosh Communications Toolbox manual init correction
The latest Macintosh Communications Toolbox manual says InitCTBUtilities should be called after InitCRM (page 192), but it should be the other way around. Call InitCTBUtilities before InitCRM, as do SurferPlus and Sessions.
System 7 initializes all appropriate CTB utilities itself, so it shouldn’t matter which order you call these routines if you’re using System 7, but it does matter for earlier versions of the operating system.
Networking & Communications: Connection Manager (CTB): Use Gestalt to check for Macintosh Connection Manager support
My driver uses the Macintosh® Communications Toolbox. How can I check to make sure the system software version supports CTB?
The solution to this sort of problem is to use the Gestalt mechanism to find out precisely what services/features are available. Full information on using Gestalt is available in Inside Macintosh Volume VI, on your System 7.0 CD. Gestalt can be called at interrupt time so drivers can use it, although there is a caveat included in the documentation. Also, using MPW 3.2 or later, you can call glue code that will let you use Gestalt even if it is not in ROM or in the System file, which is handy. This should provide exactly what you need for your driver.
Networking & Communications: Connection Manager (CTB): Trapping the “connect” message returned to CTB AMT by a network
When I use the Macintosh® Communications Toolbox (CTB) Apple Modem Tool (AMT) to dial and connect to Telenet or CompuServe, I never see the “connect” message returned by the network. Does the tool remove the “connect” message? If so, how can I trap on the “connect” message?
The Communications ToolBox (CTB) Apple Modem Tool traps the keywords, such as “Connect,” and does not pass this information on to the application. You’ll need to set a search stream using CMAddSearch.
Networking & Communications: Connection Manager (CTB): Macintosh Communications Toolbox Reference changes
Is the new Addison-Wesley Macintosh® Communications Toolbox Reference significantly different from the MacintoshCommunications Toolbox 1.0 reference manual that’s been available from APDA® for a while?
The Addison-Wesley manual has more information regarding extensions to the File Transfer Manager. It also has a description of the scripting interface to the tools and the Basic Connectivity Set, as well as having some of the text reworked. If you’re unsure about buying it, try taking a look at it first at a computer bookstore.
Networking & Communications: Connection Manager (CTB): How to obtain Macintosh Communication Toolbox
Does System 7.0 ship with the Macintosh® Communications Toolbox?
Though the Communications Toolbox is a part of System 7.0, the Communications Tools are not. They are, however, available from APDA® as the following products:
• Macintosh Communications Tools Basic Connectivity Set, Version 1.0 (part # M0379LL/B)
• LAT: Local Access Transport Connection Tool, Version 1.0 (M0800LL/A)
• Serial NuBus™ Tool, Version 1.0F11 (M0950LL/A)
• VT320 Terminal Emulation Tool, Version 1.0 (M0801LL/A)
You can license the above tools through Software Licensing. If you need the Communications Tools (or any other connection tool) to run a third-party product, the software probably is provided as part of the third-party product. The specific tools you need depend on the third-party product.
Networking & Communications: Connection Manager (CTB): Macintosh CTB initialization calls from nonapplications
What are the effects of InitCM, InitCRM, InitCRMUtilities, and similar calls to the Macintosh® Communications Tools by nonapplications such as INITs or background processes? What effect do multiple INIT calls have on Communications Tools operations and any existing connections? What do these calls do, and when (and how many times) is it safe to call them?
All these initialization calls deal with the process of loading the 'cmtb' resource into the system heap, putting entries into the Communications Toolbox (CTB) dispatch table with references to the current heap zone, and setting up various things having to do with resource management for the operation of the CTB. You can call them over and over again without damaging existing information.
With the perspective provided by that information, you can see that a synergy exists between operations of the CTB and the Resource Manager. The CTB needs to be in the appropriate heap zone when a ConnHandle is generated or referenced for it to operate as desired. If you’re writing a background process that maintains its own persistent heap zone, you shouldn’t have any difficulties using the CTB.
If you’re writing an INIT, matters are more complex. You must SetZone(SystemZone) while performing all CTB operations (including initialization, CMGetProcID, and CMNew) to be sure the heap zone will persist after the INIT has completed. Possibly the reason for doing this at INIT time is to create ConnHandles that will persist for CTB access at a later time. It seems reasonable that ConnHandles thus created require a SetZone(SystemZone) by any routine that needs to access them for Read/Write/Status/Delete operations.
Networking & Communications: Connection Manager (CTB): How to “de-install” Communications Toolbox under System 6.0.x
I have installed the Macintosh® Communications Toolbox (CTB) under System 6.0.7. What do I need to do to “de-install” it?
As you launch the Comm Toolbox Installer, hold down the option key. When the installer window comes up, you can toggle back and forth between the install and remove options using the option key.
Networking & Communications: Connection Manager (CTB): OK to use Communications Toolbox in DRVRs, cdevs, and INITs
Can the Macintosh® Communication Toolbox (CTB) be used in a DA? InitCM has to be called and the manual says to only call it one time (implies a crash if it is called twice). Is there any way to know if CM has already been INITed?
Yes, it is all right to call CTB Initialization routines from CODE Resources. This includes DRVR, cdev, and INIT. The CTB Reference Manual was not clear about this.
Networking & Communications: Datagram Delivery Protocol (DDP): AppleTalk and 'INIT's
Does AppleTalk work the same with an 'INIT' as with an application? I’m using only Name Binding Protocol (NBP) and Datagram Delivery Protocol (DDP) stuff.
Yes! Responder is an example of an 'INIT' that utilizes the NBP to register a Macintosh on the network. NBP requires DDP, so it is also present. AppleTalk is loaded before any 'INIT's, which makes it available to them.
Networking & Communications: Datagram Delivery Protocol (DDP): Datagram Delivery Protocol (DDP) header checksum field
Does the Macintosh® client pay attention to and validate Datagram Delivery Protocol (DDP) checksums within long DDP packets received?
DDP is a client of the AppleTalk Transaction Protocol (ATP), which is a client of the AppleTalk Session Protocol (ASP) and AppleTalk Filing Protocol (AFP). DDP is told by the entity for whom it is a client whether it should use checksumming. For performance reasons, our version of ATP does not specify that DDP use the checksum. Both AppleShare® and the AppleShare client are out of the loop; neither can specify whether or not to use the DDP checksum.
The LAP layer performs checksumming, ensuring no on-the-wire corruption. The only benefit of DDP checksumming is end-to-end corruption detection when the packet has travelled over a malicious router that has validly received a DDP packet on one net, changed the packet, re-computed the LAP checksum, and sent it out on another cable. Because of the performance hit of DDP checksumming and the rarity of such a malicious router, it was decided not to request DDP checksumming.
Networking & Communications: Datagram Delivery Protocol (DDP): Communication between players in a game on an AppleTalk network
How can I use the broadcast mode in an AppleTalk® DataGram Delivery Protocol (DDP) layer to communicate with the other players of a game that is on a network and not interfere with other network users?
The broadcast mode may seem like a solution, but Apple doesn’t recommend using broadcast mode. Applications like games generally end up sending LOTS of update packets to other players of the games. If your program broadcasts those packets, then all nodes on your network will be interrupted for every packet sent and that can cause performance problems on every machine on a network. In Apple supplied software, broadcast mode is only used when packets need to be sent to every node on a network. For example, Name Binding Protocol (NBP) Lookup packets are broadcast because the network address is unknown.
The following suggestions should help implement communications between players.
The DDP protocol layer does not guarantee delivery of packets (the disadvantage), but has very little overhead (the advantage). If you require delivery of all packets and can take a small additional performance hit, you should use the AppleTalk Transaction Protocol (ATP) layer.
The DDP type you use must be in the range of $10-$FF. The DDP type you choose to use (in that range) probably won’t make a lot of difference unless you define multiple clients to DDP within your socket listener. Packets addressed to your socket will get sent to your socket listener. How you use the type is up to you (as long as you stay out of the reserved range).
You should open a dynamic socket (i.e., use 0 for the socket number and use the socket number in the range $80-$FE that is returned) with the OpenSocket call and then register a name on the network for that socket with the RegisterName call. If all copies of the game register with the same NBP type, then you can use the LookupName call to find other players on the network. Once you’ve found other players and decided who you’re going to play against, you just address each DDP packet to the internet address(es) of the other player(s) socket(s). Several multi-player network games I’ve seen on the Macintosh do just that. (Hint: If you limit games to players on a single network, DDP will use short header packets which are slightly faster to send (8 bytes less per packet).)
If you build a table (array) of network addresses from those playing a game, you can use this algorithm to send a packet to each player.
BEGIN
{ put data into buffer for DDP and set the common parameter
block fields: }
{ Async Flag, Command, Checksum Flag, Source Socket, DDP Type,
BDS Pointer }
{ and Destination Network (if limiting play to a single
network). }
buildPacket;
FOR Player := 1 to NumberOfPlayers DO
BEGIN
{ Set the Destination Node and Destination Socket fields
of the }
{ parameter block to the network address of a player.
That address }
{ would be in an array of network addresses (one for each
player). }
setAddress(Player);
{ Send the datagram to a player using SendDatagram call. }
doSendDatagram;
END;
END;
Networking & Communications: Link Access Protocol (LAP): AppleTalk AOpen and AClose codes 7 & 8
What are AppleTalk messages 7 and 8? They’re documented in lapequ.a as:
AOpen EQU 7 ; Open an ATlk
AClose EQU 8 ; Close an ATlk
but what should the adev do with them and what parameters are passed?
The AOpen and AClose messages are sent when the .MPP driver is opened and closed, respectively. When the AppleTalk driver is closed, a shutdown message is not sent. Instead, the LAP Manager determines whether an adev is version 3 or greater and, if true, assumes that the adev can respond to the AClose message and sends the message. Conversely, when the .MPP driver is re-opened while the adev is active, the AOpen message is sent to the adev (assuming that the adev is version 3 or greater).
An important note on this matter is that if you modify your adev to version 3, additional selectors must be supported. These new selectors will be documented in a forthcoming Tech Note.
Networking & Communications: Link Access Protocol (LAP): Use transition queue to make sure AppleTalk isn’t turned off
How do I check if the user has turned off AppleTalk after I have already started using it?
The best way to determine this information is to submit an AppleTalk transition queue element so that whenever changes to the active state of AppleTalk occur, your program is notified. Check out Inside Macintosh Volume VI, page 32-17, Macintosh Technical Note #250, which discuss this topic. A simple description of the process is as follows.
First, define a transition handler function, which has the following form:
/*
* AppleTalk Transition Queue Sample
*
* Macintosh Developer Technical Support
* ©1990 Apple Computer, Inc.
*
* 10/31/90 pvh
*/
#include <AppleTalk.h>
/*
* Transition queue routines are designed with C calling
* conventions in mind. They are passed parameters with a C style
* stack and return values are expected to be in register D0.
*/
/* defined in IM VI, pgs 32-21&22, and MPW AppleTalk.h and
* AppleTalk.a Includes
*/
#define ATOpenEvent 0 /* MPP just opened */
#define ATCloseEvent 2 /* MPP is closing */
#define ATClosePrepEvent 3 /* OK for .MPP to close? */
#define ATCancelCloseEvent 4 /* MPP close was cancelled */
long main(long selector, ATQEntry *q, void *p)
{
long returnVal = 0;
/*
* This is the dispatch part of the routine. We’ll check
* the selector passed into the task; its location is 4 bytes
* off the stack (selector).
*/
switch(selector) {
case ATOpenEvent:
/*
* Someone has opened the .MPP driver. This is where
* one would reset the application to its usual network
* state (i.e., you could register your NBP name here).
* Always return 0.
*/
break;
case ATCloseEvent:
/*
* When this routine is called .MPP is going to shut
* down no matter what we do. Handle that type of
* situation here (i.e., one could remove an NBP name
* and close down all sessions) p will be nil.
* Return 0 to indicate no error.
*/
break;
case ATClosePrepEvent: {
/*
* This event gives us the chance to deny the closing
* of AppleTalk if we want. Returning a value of
* 0 means it’s OK to close, non-zero indicates we’d
* rather not close at this time. With this event,
* the parameter "p" actually means something.
* p in this event is a pointer to an address which
* can hold a pointer to a string of our choosing.
* This string indicates to the user which task would
* rather not close. If you don’t want
* AppleTalk to close, but you don’t have a name to
* stick in there, you MUST place a nil value in there
* instead. (We’re doing this all locally to this case
* because it’s C and we can, so there.)
*/
char **t;
/*
* Get a new reference to the address we were passed
* (in a form we can use)
*/
t = (char **) p;
/*
* Place the address of our string into the address
* we were passed
*/
*t = "\pBanana Mail"; /* this will either be an
* Ax reference or PC relative,
* depending on compiler
* and options
*/
/*
* Return a nonzero value so AppleTalk knows we’d
* rather not close.
*/
returnVal = 1;
break;
}
case ATCancelCloseEvent:
/*
* Just kidding, we didn’t really want to cancel
* that AppleTalk closing after all. Reset all you
* network activites that you have disabled here
* (if any). In our case, we'll just fall through.
* p will be nil.
*/
break;
default:
/*
* For future transition queue events (and yes,
* Virginia, there will be more)
*/
break;
} /* end of switch */
/*
* return value in register D0
*/
return returnVal;
}
OK, the next thing to do is to use the LAPAddATQ function, passing along the address of the handler, for insertion of the handler into the transition queue. See Inside Macintosh Volume VI, page 32-18, and Tech Note #250 for details. After that, your handler will be called every time some transition event takes place, even if it’s one which you initiated—“like closing down AppleTalk,” for example.
When the application is finished, remember to call LAPRmvATQ to remove the ATQ element; otherwise, AppleTalk will continue to send trans queue messages to a code resource which has since gone away. Oops.
X-Ref:
Macintosh Technical Note #250, “AppleTalk Phase 2 on the Macintosh”
Inside Macintosh Volume VI, Chapter 32, “AppleTalk Manager”
Networking & Communications: MacTCP: MacTCP and SLIP
Does MacTCP actually support SLIP? If not, does Apple plan to provide SLIP support in the future. Does anyone know of any company that does a SLIP for the Macintosh?
SLIP is an asynchronous, serial line protocol developed for running TCP/IP over serial communications lines in a point-to-point configuration. SLIP was developed to transmit IP packets over low-speed, sometimes noisy, asynchronous communications lines where error recovery and an efficient line protocol are needed. The SLIP protocol is now being replaced with a new serial line protocol named “PPP,” which uses a more efficient means of establishing a point-to-point IP connection.
MacTCP includes hooks that let you write different link-layer modules. This makes possible the development of interfaces to SLIP, PPP, and to any other link layer that someone may need, like broadband, X.25, and FDDI. Apple does not currently provide support in MacTCP for SLIP or any other serial line protocol.
Networking & Communications: MacTCP: Terminating a MacTCP asynchronous read operation
After having set up an ASYNC read operation (with a long or infinite timeout), is there any way to cause it to terminate sooner than the timeout, or to abort the read without aborting the connection? Would it work to change the timeout value in the parameter block to a small value?
Unfortunately, PBKillIO isn’t implemented in the MacTCP driver, so you can’t kill the pending operation by the standard Device Manager method.
Changing the value of the timeout or ioResult field is not really a good idea, since the result of doing so isn’t really defined for the Device Manager. Even if this works now, there’s really no way to guarantee that it would work in the future.
The best solution for the least hassle.is to make your timeout smaller, possibly setting it to the value that you would wait before aborting the call in your method. If you want to try the receive again, you can simply re-issue the call from your completion routine without a problem.
If you want to abort a MacTCP call while releasing the stream the call is being performed on, you can issue a TCPRelease. This will kill any outstanding calls on the stream, close the connection (if present), and release the stream. Of course, you said you don’t want to close the connection, so I would still recommend the re-issuing from completion described above.
Networking & Communications: MacTCP: Using MacTCP to communicate different processes on the same Mac
Is it possible to have both the source and the destination application on the same machine if they are using MacTCP sockets to communicate? If so, what should I do to make sure both applications share the processor so this works properly?
It is possible to use MacTCP to communicate to different processes on the same Macintosh computer. Unlike PPC, MacTCP does not bypass the network for same-machine connections, so there is still some “network traffic” involved.
As far as “sharing” the processor goes, this is VERY important in what you are doing. Here’s a brief outline of what you need to do:
• Make asynchronous MacTCP driver calls;
• Completion routines aren’t really necessary; instead, poll until ioResult < 1;
• Call WaitNextEvent or EventAvail while waiting for driver calls to complete (this gives time to the other MacTCP applications);
• Or, instead of calling WaitNextEvent in an “idle” procedure, make your application multi-threaded and yield time while waiting for driver calls to complete.
For a good reference on using “idle procs” to give time to background applications when using MacTCP, refer to the article, “MacTCP Cookbook” in develop magazine, Issue 6 and get the “NewsWatcher” source code from the Developer CD Series. For a reference on using threads to achieve better process time management, you can read the article, “Threads on the Macintosh,” also in develop magazine, Issue 6.
Networking & Communications: MacTCP: MacTCP name server resolver
I am trying to create a TCP/IP server socket and I get the error message from dnr.o “Failed to load name server resolver code -23004.” What is a name server resolver and where should its code be located?
The name server resolver is the piece of code residing in the 'dnrp' resource in MacTCP, which is called to translate a machine name (like apple.com) into an IP address or vice versa. For compatibility with pre-MacTPC 1.1 applications, MacTCP creates a file called MacTCP DNR that the glue code looks for and then executes; you don’t have to worry about creating it.
Networking & Communications: MacTCP: MacTCP hardware requirements
To use MacTCP, do I need just the software or do I need to have any extra hardware on the Macintosh, like an Ethernet card? Can I use MacTCP to set up a socket connection fromLocalTalk to LocalTalk or I need to have some sort of an IP gateway between two Macintosh systems?
You have three choices: First, you can run MacTCP with an Ethernet card and directly connect to any other machine running TCP (including other Macintosh systems). Another choice is to use your LocalTalk port. This requires an additional piece of hardware to do DDP-to-UDP encapsulation (also called KIP encapsulation). One example of this is the Cayman Gatorbox. You can’t do LocalTalk to LocalTalk without the hardware. Your third choice is to use EtherTalk in combination with a KIP gateway such as Fastpath or Gatorbox.
Networking & Communications: MacTCP: MacTCP 1.1 header file incompatibilities and fixes
MacTCP 1.1 header file incompatibilities and fixes
MacTCP 1.1, Apple’s System 7-compatible version of MacTCP, fixes several problems in earlier releases, but doesn’t address several header file incompatibilities. This short note outlines the MacTCP 1.1 header file problems, but it does not include the fixes. Patches in the form of MPW “compare” output are available on Apple’s latest Developer CD Series disc. The new headers are available as part of the “MacTCP Developers’ Kit,” available from APDA (part #M0704/C).
Each header problem is described below, organized by file(s) containing the problem and classified as a general bug or shortcoming, a Think C incompatibility, or a C++ incompatibility. NOTE: The changes have not been thoroughly tested, so use them cautiously.
Problems affecting all header files:
• General problem: Each header file is missing the
#ifdef __cplusplus
extern "C" {
#endif
and
#ifdef __cplusplus
extern "C" {
#endif
which are necessary for C++ unmangling.
• General problem: There are no #ifdefs to prevent including a file multiple times, as in other Apple headers. This was fixed by adding the following to each of the header files:
#ifndef __MACTCPCOMMONTYPES__
#define __MACTCPCOMMONTYPES__
...
#endif
where “MACTCPCOMMONTYPES” is replaced by the name of the header file.
• Think C problem: Think C before 5.0 does not support pascal typedefs, which MacTCP makes use of, so #ifdef THINK_C was added in several instances to declare these pascal typedef functions as type ProcPtr. This fixes the problem.
GetMyIPAddr.h problem:
• General problem: ParamBlockHeader is used as a #define here, conflicting with its use in <Files.h>. The solution is to change the name of the #define to IPParamBlockHeader.
MiscIPPB.h problems:
• General problem: ParamBlockHeader is used as a #define here, conflicting with its use in <Files.h>. The solution is to change the name of the #define to GetIPParamBlockHeader.
• General problem: The structure IPParamBlock is defined in this file with a different definition from the one in GetMyIPAddr.h. The solution is to change the name of the struct.
• General problem: AppleTalk.h is required for successful compilation. Code was added to include this if it has not already been included.
• General problem: icmpEchoTimeoutErr is defined in MacTCPCommonTypes in addition to being defined in MiscIPPB.h. Solution is to remove its definition here.
AddressXLation.h problems:
Think C incompatibility: The “int” type is used within the “hostInfo” structure definition. The default size of an int is different from Think to MPW. In all cases, int in the MacTCP headers should be changed to long.
• Think C incompatibility: The returnRec struct uses an int. Fix is to change to a long as above.
• Think C incompatibility: The CloseResolver() prototype is defined with an empty parameter list, not with a void parameter list. Think C requires the void to consider the definition a prototype. The fix is to add the void keyword as the function parameter list.
• C++ incompatibility: The cacheEntryRecord struct uses a variable named “class”. This causes major problems with C++ compilers, since the class keyword takes on a different meaning in this instance. The fix is to change this to “cacheClass.”
dnr.c problems:
• General/Think C problem: The typedef for OSErrProcPtr was incomplete, causing ambiguity for argument casting. This was changed to "typedef OSErr (*OSErrProcPtr)(long,...);" to make sure the first parameter to the name resolver calls is passed as a long.
• Think C incompatibility: Defines in Think default to short, not long, so all name resolver calls are made incorrectly. This is fixed by the typedef in above, but Think 4.0.5 does not recognize partial prototypes correctly. The fix is to add a “L” to the end of each of the name resolver command #defines.
• Think C incompatibility: The MXInfo() procedure has an extra semicolon after the trailing brace “};” which causes a syntax error with the Think C compiler. The semicolon was removed to fix the problem.
Networking & Communications: MacTCP: AdminTCP “obtain address” options
Under AdminTCP, what is the significance of the “obtain address” options, with respect to (1) manually, (2) server, and (3) dynamically?
According to the MacTCP 1.0 Documentation Kit (APDA #M0217LL/A), “obtain address” means the following:
• Manually: You will need to fill in some or all of the fields in the IP Address box;
• Server: The Internet Protocol (IP) address for the user Macintosh is automatically obtained from a server every time the user Macintosh boots up. This option requires - a Reverse Address Resolution Protocol (RARP) or Bootstrap Protocol (BootP) server on an Ethernet, or - a Datagram Delivery Protocol–to–Internet Protocol (DDP-IP) gateway on an AppleTalk network that’s compatible with the Kinetics Internet Protocol (KIP) developed at Stanford (also called “IPTalk”), such as the Shiva Fastpath or Cayman Gatorbox
• Dynamically: The node portion of the IP address for the user Macintosh is set dynamically every time the user Macintosh boots up. With this option you still need to set some of the fields in the IP Address Box. All these processes are described in further detail in the MacTCP documentation.
Networking & Communications: MacTCP: MacTCP resolver code is in domain name resolver
Is the MacTCP resolver code contained in the domain name resolver (DNR)?
According to the MacTCP 1.0 Documentation Kit (APDA #M0217LL/A), the resolver code is contained in the MacTCP DNR. The DNR code is stored as a resource file in the System folder and is read into memory as necessary in order to convert host names into addresses. It is used in conjunction with a domain name server or with the local hosts file.
Networking & Communications: MacTCP: MacTCP Hosts file location and function
Where should the MacTCP Hosts file be located, and who looks for that file?
According to the MacTCP 1.0 Documentation Kit (APDA #M0217LL/A), the Hosts file should be located in the user’s System Folder. The file maps machine names to internet addresses, providing the same service as the domain name server. The Hosts file can be used if you have no domain server on your network. It is also suggested that this file be used for frequently used name- to-address mappings. Instructions on setting up the file are included in the MacTCP documentation.
Networking & Communications: MacTCP: How to tell how many of StrToAddr’s network addresses are valid
How to tell how many of StrToAddr’s network addresses are valid
Using StrToAddr, you can receive up to four IP network addresses returned by the service for the host requested, but the MacTCP Programmer’s Guide does not say how to tell how many of the addresses are valid. According to the name resolver code, MacTCP zeros out 4 long words before the StrToAddr lookup and then fills in the addresses it finds. This means that the array contains *at most* 4 addresses, and is terminated by a zero address (0.0.0.0) if fewer than four addresses are returned.
Networking & Communications: MacTCP: System 7 and MacTCP
Is there a special version of MacTCP® for System 7.0?. If not, how can I get the current MacTCP (v 1.0.1) to work under System 7.0?
Currently there is no MacTCP version for System 7.0. To get version 1.0.1 to work with System 7.0, (1) make sure virtual memory is turned off, and (2) install MacTCP at the root level of your System Folder and not in the Control Panels folder.
Networking & Communications: MacTCP: Current MacTCP doesn’t run on TokenRing network
Does MacTCP® run on top of a TokenRing environment?
MacTCP does not run on a Macintosh TokenRing environment presently. This is being investigated by Apple N&C Engineering, however.
Networking & Communications: MacTCP: MacTCP gateway address and subnet mask fields
What are the MacTCP® Gateway Address and Subnet Mask fields used for?
In the TCP/IP protocol, there are a couple of provisions for simplifying the addressing scheme for smaller local networks. One of these is the subnet mask. It allows the sender to identify the destination machine by a shorter address,which is long enough to distinguish all the machines on the local network. This mask is made up of four octets, and is used as a bitwise mask to show how many bits are being used to specify the network number, subnet number, and node. The gateway address field specifies the IP address of the local network’s router. Packets destined for another network are sent to this router, which then transmits the packets to other networks.
Networking & Communications: MacTCP: Use AppleTalk to print from Macintosh A/UX to a LaserWriter
To print from a Macintosh® running A/UX to a LaserWriter®, would I use AppleTalk® or TCP/IP?
To print from an A/UX machine to a LaserWriter, you need to use AppleTalk. If you use your LocalTalk® port as your AppleTalk connection, you will require no further hardware (other than your LocalTalk network). If you use your Ethernet as your AppleTalk connection, you will need some kind of router to translate these packets from Ethernet to LocalTalk, as LaserWriters are available only with LocalTalk connections.
Networking & Communications: MacTCP: Porting a TCP/IP application to the Macintosh
We need the following to port our mainframe front-end application to the Macintosh®:
• a C++ compiler compatible with AT&T 2.0 (and ANSI C)
• a TCP/IP library with an Application Programming Interface (API) similar to sockets
• an Ethernet card
MPW® C++ is based on AT&T CFront 2.0. For information about CFront 2.0, please refer to the UNIX System V AT&T C++ Language System Release 2.0 Product Reference Manual.
Sockets is the general UNIX (Berkeley) API for TCP/IP programming. Apple currently offers some libraries that allow you to work with MacTCP but not APIs similar to sockets. Third-party socket libraries for MacTCP are available, however. Also, universities such as the University of Toronto provide public domain socket wrappers for MacTCP.
Ethernet cards are available from a number of sources, including some new Ethernet cards Apple introduced last month.
Networking & Communications: MacTCP: How to cancel transactions under MacTCP
How do I cancel transactions (specifically connect requests) under MacTCP? I know that I can specify a timeout; however, I would like the user to be able to hit ‘Command-.’ if the transaction’s tired of waiting. I tried KillIO but that seems to crash.
You should use Abort and Release. Abort terminates the pumping of data, and Release releases the driver. If there’s no release, the driver still believes there’s a process that it is working with, and it hangs when it tries to read data from a memory location that does not have anything.
Networking & Communications: MacTCP: A/UX® 2.0 doesn’t support IP encapsulation inside DDP packets
Can I get A/UX 2.0 to talk TCP/IP over the LocalTalk® network? MacTCP seems to support this but I can’t pummel A/UX into doing it.
IP encapsulation inside LocalTalk DDP packets is not supported under the current A/UX 2.0.
Networking & Communications: MacWorkStation: Using TextEdit for MacWorkstation “WYSIWYG” Exec
I am developing a MacWorkstation EXEC that will support a WYSIWYG display of a mainframe word processing document. Can I use TextEdit for display and editing?
You can use TextEdit, but you should know about some of its limitations. The latest TextEdit supports styles like bold, italic, and underlining, but does not support strike-thru (which can be done with QuickDraw™).
The TextEdit package may give the impression that there is a full featured word processing system built in the ROM, but unfortunately, TextEdit is not up to the job of being a word processor, for several reasons. First, TextEdit is limited to 32,767 characters per record (the TELength is defined as an integer). A second more subtle limit is the drawing limit of the rectangles surrounding the text. The destRect and viewRect both surround the complete TextEdit record. Using some rather rough approximations, there is an upper limit of about 40 pages of text that can be supported in the QuickDraw rectangle. This is quite a lot for some applications, but not very many considering the job typically required of a word processor.
Another programmatic limitation is performance. TextEdit will become quite sluggish with large blocks of data. After 2,000-4,000 characters are stored in a TextEdit record, performance slows to an unacceptable level. It is notable that the lineStarts array is a linear array of offsets into the edit record. If the data towards the end of the data record (high in the record) changes, the offsets must be changed. This can involve updating thousands of integer offsets for every character typed. If the different font, size and style information is tacked on top of all that, the performance can be expected to suffer with large blocks of text. This is especially true in a MacWorkStation Exec. TextEdit was not designed to handle large documents. It was designed as a simple field editor for the Dialog Manager, and extended from there. It was never intended to handle the large jobs expected of a word processor.
In order to perform the operations required of a word processor it is necessary to use QuickDraw extensively. The expected Macintosh selection approach with autoscrolling, typing over selected text, cut/copy/paste, and so on are best implemented using QuickDraw directly. How the text is stored internally is the primary determining factor on how the word processor will perform.
Networking & Communications: MacWorkStation: Customizing MacWorkstation documents
Where should I put resources—in the MacWorkstation document or the MacWorkstation application file?
To maintain the generic nature of MacWorkstation, it is important that you do all customization is on MWS documents and not on the MWS application. Any resource added to an MWS application may produce incompatibility with other applications that use MWS. Also, future versions of MWS may support multiple sessions. Here are some of the things that go into MWS documents:
• Communication module code resources
• Host application’s menu and dialog resources
• Any other host-specific resources such as icons, pictures, and data-strings
• Exec modules are stored in MWS documents as resources of type 'MWSX', along with a resource ID number for each module. The host program can load the module using either its resource ID number or its name.
Networking & Communications: MacWorkStation: How to make CCL “Debug” & “Matchstr” commands work correctly
The “Debug” and “Matchstr” commands in the Communication Command Language (CCL) don’t work as documented.
MacWorkstation does not attempt to read from the communications module at any time other than during the “Wait” command, so if a script does not have the “Wait” command, neither the “Debug” nor the “Matchstr” command will work. Add the “Wait” command and it all works.
Networking & Communications: MacWorkStation: Restricting access permissions for the Macintosh host
Is there some way to restrict the access permissions for the host?
Currently there is no easy way to restrict access permissions for the host. The host can access any file on the Macintosh® and create resources in the MacWorkstation documents. It would be possible, however, to write an EXEC which would prohibit certain commands from working under MWS, such as all file transfer commands.
Networking & Communications: MacWorkStation: Filtering out non-printing characters on the MacWorkstation end
How can I filter out non-printing characters on the Macintosh® end of the connection?
No checking is done on the MacWorkStation (MWS) side to filter out non- printing characters. If you want to filter them out, you must write your own communication module. This could also be a function of the host application.
Networking & Communications: MPP Driver: RAM-based AppleTalk driver fixes Mac Plus PNSendRequest error
I get an odd address error when using PNSendRequest on the Macintosh® Plus. The Mac® Plus has version 19 of the .MPP driver. Is there is an INIT or something that patches the older Macintosh models with the newer drivers?
Inside Macintosh suggests checking the .MPP driver version to see if the new driver is available (version >= 48).
You need the RAM-based AppleTalk drivers on the older Macintosh models to use the calls documented in Inside Macintosh Volume V. The RAM-based AppleTalk driver is available as an AppleTalk System file, and you need to place it in the System Folder of your Mac Plus.
Networking & Communications: Name Binding Protocol (NBP): AppleTalk 56 NBP reply packet entity field checks
AppleTalk 56 NBP reply packet entity field checks
As stated in Inside AppleTalk, each entity field in an NBP reply packet can be a maximum of 32 characters. In previous versions of AppleTalk, no range checking was done on entity field lengths, and often names that were too long were used, which eventually caused a crash somewhere else in the protocol stack.
Likewise, a null character in the object field of an entity has never been OK; it just happened to work because no range checking was done. (The only place that a null can legally be used in an NBP tuple is in the zone name field of an NBP LkUp, FwdReq, or BrRq packet; see page 7-17 of Inside Appletalk for more information.)
Now, under Appletalk 56, a range check is done on each entity field to ensure that the length is legal (1<=length<=32). When it finds a packet that contains a “corrupt” entity name, that packet is discarded.
Networking & Communications: Name Binding Protocol (NBP): Name Binding Protocol (NBP) interval and count fields
Is there a limit on the values set in the Name Binding Protocol (NBP) interval and count fields when used with PLookUpName and PConfirmName calls? How does the interval and count work? If a device is not on the network and I send a PLookUpName with intervals = 20 and count = 20, will I wait 400 seconds before PLookUpName return?
Since the interval and count parameters for NBP calls are both 1-byte, the values used are limited to the range of 0-255 ($00-$ff). Here’s what the values do:
interval = retransmit interval in 8-tick units. This value is used to set up
a VBL task. A value of 0 should not be used because that would
mean the VBL task would never be executed and would be removed
from the VBL queue.
count = total number of transmit attempts. Each time the interval timer
expires, this value is decremented by one. When it reaches 0, the
NBP call completes. So, if a value of 0 is used, the packet will
be retransmitted 255 times (or transmitted 256 times).
Three things can happen to make the LookupName, RegisterName or ConfirmName calls complete:
1) PKillBNP can be called to abort one of the calls (see Inside Macintosh, Volume V, page 519).
2) maxToGet matches are returned or the return buffer is filled. Here’s how this works: Each time a NBP lookup reply packet (LkUp-Reply) is received, an attempt is made to add all the NBP tuples found in that LkUp-Reply packet to the return buffer. If all of the tuples cannot be added to the buffer because there isn’t enough room, then the call completes with as many tuples as could fit and the numGotten field will contain the number of matches in the buffer. If all of the tuples from the LkUp-Reply packet are added to the buffer, then numGotten (the number of matches in the buffer) is compared to the value passed in the maxToGet field. If numGotten is greater than or equal to maxToGet, then the call completes and the numGotten field will contain the number of matches in the buffer. Since the buffer can fill before maxToGet matches are received and since LkUp-Reply packets can return multiple tuples, you may get more or less matches than you asked for with maxToGet.
3) The count is decremented to 0. You can use this equation to determine how long the call would take to complete this way:
IF count = 0
then count := 256;
TimeToCompleteInTicks := count * interval * 8;
The RegisterName and ConfirmName calls always complete after they receive the first LkUp-Reply packet packet to their request, so you could look at them as always having a maxToGet of 1 (maxToGet is NOT one of the parameters for those two calls).
Networking & Communications: Name Binding Protocol (NBP): Where to find AppleTalk Name Binding Protocol code sample
Do you have AppleTalk® sample code that uses NBP (Name Binding Protocol) to check for a name and type on the network and, if not found, register the name and type on the network?
The sample you’ve requested is available on the Macintosh® System 7.0 beta CD.
Networking & Communications: Name Binding Protocol (NBP): Version tests before using AppleTalk NBP’s RemoveName under A/UX
When I was running my program under A/UX® 2.0, the AppleTalk® NBP (Name Binding Protocol” routine RemoveName seems to do nothing. Beta manuals hint that LaserWriter® printing works but other parts of AppleTalk are absent or iffy. Am I right in assuming that RegisterName works but RemoveName doesn’t? Is it safe to check for AppleTalk version 0 for this purpose? When will RemoveName work under A/UX?
We recommend checking the A/UX version instead of the AppleTalk version. Good recommendations about how to do that are found in Macintosh Technical Note #283. If you use Gestalt you could also check if the release level is 2.0. Now that this problem is fixed in 2.0.1, you can check for release level and enable your functionality.
Networking & Communications: Name Binding Protocol (NBP): Macintosh NBPLookup badUnitErr conditions
Why am I getting a badUnitErr as a result code from NBPLookup? This error is not listed as a result code for NBPLookup, nor anywhere in the AppleTalk® Manager.
You’re probably getting the badUnitErr result because you don’t have the AppleTalk drivers open. Since AppleTalk calls are made to a device driver (the AppleTalk driver), you can get back general operating system errors from the driver.
See Macintosh® Technical Note #224 “Opening AppleTalk” for a description of how to open the AppleTalk drivers.
Networking & Communications: Name Binding Protocol (NBP): Don’t access the MPW NBP EntityName field directly
When I fill in the fields of MPW®’s Name Binding Protocol (NBP) EntityName structure, AppleTalk® doesn’t recognize the entity, even though I know it’s out there. What’s going on?
The real definition of EntityName is 3 PACKED strings of any length (32 is an example). No offsets for Asm are specified since each string address must be calculated by adding the length byte to the last string pointer. In Pascal, String(32) will be 34 bytes long since fields never start on an odd byte unless they are only one byte long, so this will generate correct-looking interfaces for Pascal and C, but the interfaces will not be the same. This is OK since they are not used.
The point is that you should never try to access the fields of the EntityName field directly. The only reason the type is defined at all is so that you can allocate EntityName variables that will hold the largest possible EntityName. To fill in an EntityName record, you call the NBPSetEntity routine.
Networking & Communications: Routing Table Maintenance Protocol (RTMP): Receiving RTMP packets from a generic router
I’m trying to receive the periodic Routing Table Maintenance Protocol (RTMP) packets sent out from a generic router. The only solution so far is to close down the Link Access Protocol (LAP) handlers and install my own. However, when I’m finished, I must restart AppleTalk® when my program exits. Is there an alternative solution?
You’ve hit upon a side effect of the AppleTalk architecture. It’s understandable that being only a listener, that you would simply want to attach yourself into the LAP chain without shutting down AppleTalk. Your findings are correct though—you would need to shut down the LAP handler and install one of your own. This would require restarting AppleTalk when your program exits.
You’d find that EtherPeek, a commercially available software sniffer works similarly. This has the ramifications of complicating the process by restarting AppleTalk with the desired connection method. It also limits compatibility with Apple cards and those from other vendors you select to support.
Networking & Communications: Token Ring: TokenTalk LLCBadList and LLCTruncated
When a list-directed receive is queued to TokenTalk’s implementation of Logical Link Control (LLC) with a total data size less than the active frame size, LLCBadList is returned when the receive completes. If a nonlist-directed receive is used, and the buffer size is less than a frame size, LLCTruncated is returned. Why aren’t the same error codes (LLCTruncated) returned as the condition is the same?
The LLCBadList error results because of an undocumented limitation imposed on the number of lists allowed in a list-directed receive. It’s likely that you’ve specified a list array with greater than eight elements. When the list is passed to LLCReceive, a check is made on the list array if one is used. If more than eight elements are in the list, the LLCBadList error is returned immediately with no processing of the incoming data.
On the other hand, if a nonlist-directed receive is used, the LLCReceive call is queued into the task list. The present TokenTalk LLC implementation doesn’t support partial reads of large data frames, so if it turns out that the buffer size is smaller than the frame size, only the information that fits into the buffer is returned. The remaining information is discarded. The error condition LLCTruncated is returned to indicate that this event occurred.
Networking & Communications: X.25 & X.400: How to increase Macintosh X.25 user list size
How do we go beyond the Macintosh® X.25 user list entry limit of 256?
The size of the X.25 user list can be modified by modifying the 'Maxu' resource in the X.25 Admin program using ResEdit™. If you’re using the latest revision of ResEdit v2.1, a template for the 'Maxu' resource exists to assist with this modification. The other recommended change is to increase the program partition size of X.25 Admin by 32 bytes for each additional user to ensure that there is enough memory to hold all of the names. Note that this change does not increase the number of simultaneous connections.
Networking & Communications: X.25 & X.400: Feasibility of MacX25 AppleTalk internet routers
What’s the feasibility of developing internet routers for AppleTalk® networks over MacX25?
This has been done at Apple, and tested between Cupertino and Paris. The problem is ITMP packets are a burden on the X.25 network. Too much bandwidth is used by AppleTalk® router protocol. The throughput goes way down, and the monetary cost of these undesirable packets is high. Efforts are underway to improve throughput. In other words, it is feasible but not practical to do this until modifications are rolled into the AppleTalk and router protocols.
Networking & Communications: X.25 & X.400: Providing general “listeners” on MacX25 servers
Is it feasible to develop general “listeners” on the MacX25 servers? This would allow users to connect to MacX25 servers and request specific services to be provided. Other non-Macintosh systems could also communicate with such “listeners.”
MacX25 does indeed provide a listener agent. Please refer to the MacX25 product documentation. If, however, you want to develop your own listener, one could be provided via access to A/ROSE®.
Networking & Communications: X.25 & X.400: Where to find X.400 & X.500 references
Where can I find documentation on the X.400 and X.500 electronic mail standard?
There are a few interesting articles about X.400 in the Technical Information Library on AppleLink®. One of them mentions that Apple has a forthcoming X.400 solution which is an X.400-compliant MTA (Message Transfer Agent) that runs on any modular Macintosh under System 7. It includes the seven layers of the OSI model. It works either over X.25 (on top of the MacX25 product) or over 802.3. (This is the most used link in the U.S.) It lets Macintosh users gain access to public X.400 networks or to connect to their private X.400 backbone.
For standards and specifications on X.400 and X.500, I would check with your local library for an IEEE periodical index. IEEE documents this type of stuff fairly regularly.
Networking & Communications: X.25 & X.400: Translating 8-bit Macintosh text to 7-bit ASCII
Is there an Apple-recommended method for converting 8-bit Apple text characters to that which can be sent over 7-bit mediums while observing X.400 rules, and only submit 7-bit text into the x.400 IA5Text body parts?
There is no Apple-recommended method to translate 8-bit characters to 7-bit characters. You’ll need to check around and see if someone has implemented this already. This would save you some time trying to figure out a formula for this. Unfortunately, there are some differences between the IBM-based environment and the Macintosh® environment that are extremely hard to overcome and this is one of them.
The following are some possible methods:
1. Strip the 8th bit off and send the character in 7-bit mode. Doing this will cause you to lose half of the normal 8-bit ASCII code, but there is still enough for people to work with. Most of the missing characters are special ones which usually require the option key to obtain them.
This limitation should not be restrictive for most users, except for those writing in foreign languages that may require such characters. This is another area that requires some thought. How do you handle foreign languages? If they are using 8-bit ASCII to get their special characters then they are out of luck. If they use the Script Manager they may be able to get what they need in the first 128 characters. You would have to check in the Script Manager of Inside Macintosh to know for sure if this is the case.
2. Just transfer 7 bits at a time. Break after every 7th character and then put the characters back together again at the other end. This might require a Macintosh-to-Macintosh connection, but it will provide you with the method of retaining the entire 8 bit ASCII character set and still get the file transferred.
Finally, You might want to check with user groups and bulletin boards to see if someone has done anything that is suitable to your needs.
Operating System: Alias Manager: Special Macintosh alias file types
Why does the alias of a font suitcase created in System 7.0 have a type of 'drop' instead of 'FFIL'? Should applications that open 'FFIL' files also try to open 'drop' files?
While it is true that an alias file generally has the same type and creator asthe file it points to, certain special Finder™ objects are given their own type, such as aliases to server volumes. An alias file of type 'drop' is an alias to a container object—that is, one that can contain other files like fonts. The complete list of special alias types is in the Finder Interface chapter of Inside Macintosh Volume VI and is defined in Finder.h.
You asked why the Finder needs to create this special type. The user is allowed to drag objects around the desktop, and if an object is dragged over something it can be dropped on or into, such as a folder, that object is immediately highlighted so the user knows this is a cool thing to do. Since the actual object an alias file points to may not even be currently accessible—for example, if it’s on a server volume—the Finder can’t resolve itimmediately to know if it’s cool to highlight the object, so alias files of type 'drop' are a catchall type that tells the Finder dropping is cool.
You should not assume an alias file of this type always points to a font file.It can also point to a desk accessory, for example. If you want to handle thistype properly in a standard file dialog, you need to filter on type 'drop', then have a filter proc which attempts to resolve the alias file. DTS recommends you use MatchAlias with kARMnoUI set in the rulesMask to see quickly if the alias file can be resolved with no user intervention required.
Alternatively, you can allow the user to select the file for opening and then if it doesn’t resolve to the correct type, inform the user via a dialog that the file isn’t of the appropriate type.
Operating System: Backgrounder: Valid resource handles for Notification Manager nmIcon field
Why can’t I pass a handle to an 'ICN#' as the Notification Manager nmIcon under System 7?
The Notification Manager chapter of Inside Macintosh Volume VI describes the nmIcon field as follows:
nmIcon: Contains a handle to a small icon that is to appear periodically in the menu bar...
The nmIcon field holds a handle to the icon that flashes in the process menu. Since 'ICN#' are not small (16x16), they will not work for this purpose. You need to pass a 'SICN' handle in the parameter block. Changing the icon that appears in the notification alert dialog box is not supported.
Operating System: DAs: System 7.0 DAs and 'vers' resources
Why does System 7.0 get rid of my 'vers' resources in my desk accessories when dropped into the System Folder icon?
The System 7 DA mover takes over some of the job of the old Font/DA Mover program. The Font/DA Mover took great pains to keep all resources owned by the DA together with the driver resource. This is mentioned in Macintosh Technical Note #6, “Shortcut for Owned Resources.”
Under System 7, the 'vers' resource used for Finder information is not owned by the desk accessory, so when the Finder copies the desk accessory it skips the resources extraneous to the DA—including the 'vers' resource.
The simplest thing to do is to provide a System 7-ready version of your desk accessory. The Finder will not strip off resources if the file type is already 'dfil' when the DA is dragged to the System folder. You can also provide a version of the DA in a suitcase for System 6, or you can instruct System 6 users to hold down Option while clicking Open in Font/DA Mover if they want to install your DA.
Operating System: DAs: Macintosh DA with custom 'WDEF'
Is it acceptable to write an installation program for a DA that uses a custom 'WDEF'? The Font/DA Mover won’t install a 'WDEF' because the 'WDEF' cannot be an owned resource.
Although the owned resource mechanism and the 'WDEF' ID with variation code are directly incompatible with each other, it is a simple matter to work around this problem with just a little code.
First, number your 'WDEF' resource as an owned resource, following the instructions on page 109 of Inside Macintosh Volume I. This will allow your users to simply use the DA/Font Mover to install/deinstall your DA and eliminate the need for you to do a custom installer with all the problems that involves.
Next, when you open a window that needs your custom 'WDEF', open it “invisible” and with a standard built-in 'WDEF' procedure ID; GetResource the 'WDEF' resource handle yourself and store the handle into the windowDefProc field of the window record. Its “owned” resource ID is calculated from the DA’s installed driver unit number, dCtlRefNum. Note: a refNum of -4 is a unit number of 3. See Inside Macintosh Volume II, page 191, for details.
Finally, show your window and it should be drawn using the custom 'WDEF'.
Operating System: DAs: DAs cannot call UnmountVol trap under System 7.0
DAs cannot call UnmountVol trap under System 7.0
Under System 7.0 a DA can no longer call the UnmountVol trap to unmount a volume, as it can under earlier systems.
The only known workaround is to build your product as an application and not a DA. Since System 7.0 will place any application into the Apple Menu, you don’t really need to make it a DA to have it easily accessible to the user.
Operating System: DAs: How to build a System 6 suitcase allowing for System 7 'ICN#'
Is there a way to build a file that is recognized by Font/DA Mover as a suitcase for System 6 that also allows the DA to have an 'ICN#' for System 7?
Yes, this is possible. You need to add a 'BNDL' resource to the DA, and mark it (in ResEdit’s “Info on <filename>“ window) as having a bundle. Make sure all the 'BNLD' components, such as 'BNDL', 'FREF', and 'ICN#', are owned resources of the DA.
All you need to do is add a 'BNDL' to your DA suitcase with your creator and a filetype for the icon of 'dfil'. Then, when the user drags the DA out of the suitcase (or drops it into the System file) in System 7 the Mover should associate that icon with that “naked” DA.
This works reasonably well; however, occasionally the Finder™ will “forget” the custom icon and default to the left-hand DA icon. Rebuilding the desktop usually fixes this.
So, it does work, but you (and your users) make occasionally experience a loss of the icon, but rebuilding the desktop will fix them.
Operating System: DAs: Increasing heap space for Macintosh DAs
I am writing a Macintosh desk accessory (DA) that opens large PICT files and makes offscreen pixel maps for them. Is there a way for a DA to ask for more space when it opens up, or should we be modern about this and make it an application instead of a DA?
A DA, like any application, can ask for available MultiFinder® temporary memory, as documented in “Programmer’s Guide to MultiFinder” (APDA #M7044) for running under System 6.0.x and in Inside Macintosh Volume VI for running under 7.0. You can also set the current heap to the system heap so that memory allocation will take place there until you set it back to the current heap. If you do this, you open up the can of worms of “how much space is left in the system heap?” Under Finder™ there’s a fixed amount of space, set by the boot blocks. Under MultiFinder (and System 7.0) the system heap adjusts itself to keep about 16K free, but if you allocate all 16K you will not know when it will resize larger or when the system might crash because all of its heap space has been used up.
DAs, however, were never intended to use large amounts of memory. For all but the most trivial (and small) functionality, it is better to implement as an application than as a DA, especially under System 7.0 where an application has all the advantages of a DA with none of the restrictions.
Operating System: DAs: DAs in background under under System 7.0 lack UnitTable entries
Under System 6 my driver, which runs all the time, can send a control call to my open DA (because it too is a driver). Under System 7.0 I get badUnitErr errors (-21) because evidently my DA resides in a different process that is inaccessible to my system-resident driver. How can I get around this?
DAs in System 7.0 do not actually have UnitEntries unless they are currently running, so your driver cannot call your DA unless the DA is frontmost. What you might consider instead is having the DA perodically issue a call to the driver, asking if there is anything for it at the moment. If you have an entity that hands data to your resident driver, and the DA then requests the data from the resident driver from time to time, you should have a very robustmechanism, albeit a slightly slower one with greater latency.
Operating System: DAs: How an Apple IIGS New Desk Accessory obtains its ID
How does an Apple IIGS® New Desk Accessory (NDA) obtain its ID?
Each Apple IIGS NDA has two IDs: a Memory Manager ID and a Menu ID. If you want the Memory Manager ID, simply call MMStartup from your DA. The NDA ID for the OpenNDA call can easily be obtained from your menu string. The Desk Manager replaces the ** of your \H** at the end of your menu string with your Menu ID, which is also your NDA number. A note of caution: Please be sure you’re running in the 16-bit environment before using the NDA ID to call OpenNDA. If you try this while ProDOS 8 is running, nothing good comes of it!
Operating System: DAs: Using 'dast' resource to display “About…” DA under System 7.0
I’m upgrading my desk accessory to be more compatible with Macintosh® System 7.0, but I’m unable to get anything to display in “About…” using the Alarm Clock’s 'dast' resource. What do I need to change?
The 'dast' resource will be used only if the system thinks your DA is System 7.0-friendly. The way to convince it of this is to add a BNDL and FREF resource into your DA file, along with the appropriate signature string (just like an application would have done). You then make sure that all of these resources are owned by the DRVR. This can be done in the GetInfo window of ResEdit™. The only resource that should be special is the signature resource which should still have a resource ID of 1. Once all of this is done, set the Bundle flag, and clear the INITed flag (also using ResEdit) to get the Finder™ to notice the changes. At this point, your DA should have the correct icons, and should also display the dast string in your about box. To make it easy, just copy all of the resources including the ICN# and icXX resources out of the Alarm Clock file, and then make them owned by your driver. If your DRVR resource has the same ID as the Alarm Clock, all you have to do is copy them over. Once the system starts using them, you can simply use ResEdit to edit the icons. This way you will have the appropriate icon in the Apple Menu as well as the About box.
Operating System: DAs: Zero non-input fields before calling Apple IIGS TaskMasterDA
How do I use the Apple IIGS® TaskMasterDA call?
TaskMasterDA is a call provided in Apple IIGS System Software 5.0 and later so that new desk accessory authors may use the features of TaskMaster even when the current application doesn’t use TaskMaster. The Desk Manager will pass an event record to the NDA, which should then copy it into an extended task record. TaskMasterDA will return values in the extended task record and will use values passed in that record, so be sure that the non-input fields are zeroed before your first call to TaskMasterDA. The parameters to the call are listed in Volume 3 of the Apple IIGS Toolbox Reference.
Operating System: DAs: Apple IIGS DAs can have resource forks
Can my Apple IIGS® DA have a resource fork?
A new desk accessory may use the Resource Manager if it requires System Software 5.0 or later, as the Resource Manager will always be present. However, New Desk Accessory (NDA) authors must be aware that any application doing a Close with reference number zero will close the NDA’s resource fork. The IIGS Finder™ can do this under some circumstances. Changing the file level will not solve this problem, as the level belongs to the current application and should not be permanently changed by desk accessories.
This means that your NDA can’t open its resource fork at DAInit time and expect it to always be open. You can use resources in an NDA by opening the resource fork when your DA is opened and closing it when your DA is closed. Although an application could still close your resource fork while your DA window is open but not active, this is not likely.
Classic Desk Accessories may also have resource forks. The same warnings apply, and the author must also be aware that the Resource Manager is not available to the CDA when the current operating system is ProDOS® 8.
For important details, refer to the Apple IIGS Technical Notes, especially Tech Note #71.
Operating System: Disk Cache: Tail-patching the Macintosh Write trap
How do I make Macintosh® Control Panel RAM cache a “write-through” cache?
The Write trap is not being patched by Apple. This makes sense, as Write isn’t called much from within the system software itself, and even when it is, it’s not a likely candidate for a come-from patch. The upshot of this is that you can probably safely tail-patch it. Here’s a suggested implementation:
TST.W ioFRefNum(A0) ;Is this _Write for a file?
BMI.S JumpToROM ;Go if not
BSET #5,ioPosMode(A0) ;One-shot disable for caching
PEA FollowUp ;Put new return address on stack
JumpToROM JMP <OldWrite> ;Jump to ROM address
FollowUp MOVE.W D0,-(SP) ;Save OSErr
BCLR #5,ioPosMode(A0) ;Restore ioPosMode
MOVE.W (SP)+,D0 ;Restore OSErr; also sets conditions!
The above takes care of a few not-necessarily-obvious things:
1) By testing ioFRefNum(A0), it determines whether it even needs to worry about the cache; that is, it determines whether this is a File Manager _Write or a Device Manager _Write.
2) The tail portion of my example clears bit 5 of ioPosMode while taking great care to ensure that the condition flags aren’t screwed up in the process.
Operating System: File System: PBGetUGEntry documentation fix
When I call the PBGetUGEntry function (documented in Macintosh Technical Note #305, “PBShare, PBUnshare, and PBGetUGEntry,” October 1991), it always returns a fnfErr error. I know there are users and groups on the system. Does the PBGetUGEntry function really work?
Get out your pencil and make this change on page 7 of Technical Note #305 (October 1991 version only):
ioObjType Word input value: Determines the type of object to be
returned, as follows:
$0000 return next user
$FFFF return next group
There is no value of ioObjType that will return both the next user and the next group.
Operating System: File System: Unlocking a Macintosh volume
PBSetVInfo failed to reset a software lock bit that had been set using PBSetVInfo, because the volume was, of course, locked. How do you allow a volume to be unlocked?
DTS discourages developers from locking and unlocking volumes through software because it’s not readily apparent to users. Many users are aware only of the physical reasons that they would be prevented from modifying a disk. For example, it’s easy to identify CD-ROMs and locked floppies as unchangeable.
Additionally, the Finder caches the contents of its windows, so a change in the locked status of a volume may not be reflected immediately. An unlocked volume may still show a lock icon in its window, misleading users into thinking that the particular volume is still protected. For these reasons, we recommend that volumes not be locked by software.
If you need to software lock a volume, be sure it’s done only after explicitly warning the user that the disk will be locked and providing an opportunity to cancel the operation.
Locking a volume is done by calling PBSetVInfo with bit 15 of the ioVAtrb field set. However, this creates a Catch-22 in that you can’t make the call to unlock the disk. To override the locked status for the volume and unlock it, you must walk the volume-control-block queue in memory and clear the lock bit for the drive, as shown in the following code:
USES Files, Errors;
FUNCTION SoftwareVolumeUnlock(targetVRefNum: INTEGER): OSErr;
TYPE VCBPtr = ^VCB;
VAR
theVCBQHdrPtr: QHdrPtr;
myVCBPtr: VCBPtr;
BEGIN
theVCBQHdrPtr := GetVCBQHdr;
myVCBPtr := VCBPtr(theVCBQHdrPtr^.qHead);
WHILE (myVCBPtr <> NIL) AND
(myVCBPtr^.vcbVRefNum <> targetVRefNum) DO
myVCBPtr := VCBPtr(myVCBPtr^.qLink);
IF myVCBPtr^.vcbVRefNum = targetVRefNum THEN
BEGIN
{ clear locked bit }
myVCBPtr^.vcbAtrb := BAND(myVCBPtr^.vcbAtrb, $7FFF);
{ write change to disk }
SoftwareVolumeUnlock := FlushVol(NIL, targetVRefNum)
END
ELSE SoftwareVolumeUnlock := nsvErr { volume not found }
END;
The VCB queue and volume attributes are discussed under “Volume Control Blocks” in the File Manager chapter of Inside Macintosh Volume IV.
Operating System: File System: Simulating PBExchangeFiles for System 6
Simulating PBExchangeFiles for System 6
Here’s how to do the equivalent of PBExchangeFiles (new in System 7) for System 6:
Create a new file. Copy the old files to the new one, do a PBHGetFileInfo on the old and and new, and copy the Finder and creation date from the old to the new. Then do a PBHSetFileInfo, renaming the new and deleting the old. The File Manager implements PBExchangeFiles as shown below:
Catmove file 1 to file 2’s directory
Catmove file 2 to file 1’s directory
rename file 2 to 1
rename file 1 to 2
Renaming and deleting require the file names instead of refnums. The file name may have been changed by the user since the file was opened because the Fnder doesn’t disallow changing names and moving files that are open. To get around this problem, use GetFCBInfo to recover the filename, DirID and VRefNum of an open file. In the case of files, the FCB’s ioFCBParID field is the ioDirID of the file, and ioFCBVRefNum is the ioVRefNum.
You may need to do an intermediate rename if there is file already exists with the name of the moved file in the destination directory. The File Manager is able to pull this procedure off a little more gracefully because it manipulates the B-Tree entries instead of going through the APIs.
Operating System: File System: Booting a write-protected disk under System 7
How do I boot a write-protected disk under System 7? It seems that the Macintosh operating system tries to write/modify the desktop file and I get an error message telling me to write-enable the disk.
Every Macintosh has been equipped with the ability for users to boot from both write-protected as well as writeable disks, all the way back to the first machine introduced in 1984. This didn’t change with System 7; in fact, the operating system has only an indirect impact on this capability. The only thing you can’t do from a write-protected boot disk is use the Chooser because the O/S needs to be able to write back the preferences for whatever you do in the Chooser.
You might be encountering the error you described because of desktop changes: Since the desktop file was obsoleted in System 7, which now uses the Desktop Manager instead, diskettes that are mastered on a System 7 machine then inserted into another machine running 6.0.x must have a desktop file created. (This does not apply to diskettes that you’re trying to boot from; rather, when you insert the disk into a machine already running 6.0.x.) When this situation is encountered, the user is presented with the now familiar dialog to the effect that the disk needs minor repairs (in fact, it needs a desktop file). If you say OK to this dialog, the desktop file will be created and all will be well. All this leads up to how (not) to treat diskettes mastered under System 7: If you drag a series of files to a floppy disk (from a System 7 machine), immediately eject and lock it, then try to boot from it, the machine will try to update the directory information on the diskette as the machine is booting up. The way around this is to either A) eject the floppy after copying your files then reinsert it (or simply open and close the main window) to allow the directory information to be updated or B) use the installer to place files on the floppy as the installer automatically updates the directory information.
Another possible explanation for the anomolous behavior you’re seeing is that you’ve got an INIT or application of some sort (such as a virus checker perhaps) on the floppy that wants to update itself after the system has finished starting up.
Operating System: File System: Code for detecting PBCatSearch support
Our code for volume searching using PBCatSearch doesn’t work for AppleShare volumes. Do know how we can make it work?
PBCatSearch only works on volumes that support it. If you attempt to use PBCatSearch on a volume that doesn’t support it, you’ll get a wrgVolTypErr (-123). (This isn’t documented in Inside Macintosh Volume VI.)
AppleShare 2.0 volumes (AppleShare 2.0 is an AFP 2.0 server) and volumes supported by some other external file systems do not support PBCatSearch, so you’ll have to resort to recursively searching the catalog using a routine similar to the one shown in Macintosh Technical Note #68 on those volumes. PBCatSearch is supported by AppleShare volumes on System 7 File Sharing servers because File Sharing supports AFP version 2.1 which includes CatSearch as a supported command.
You can use the File Manager call PBHGetVolParms to check a volume for most volume-specific features, including support for PBCatSearch. Here’s a short function that shows how to do that:
FUNCTION CatSearchable (vRefNum: Integer): Boolean;
{See if PBCatSearch is supported on the volume specified by vRefNum}
VAR
pb: HParamBlockRec;
infoBuffer: GetVolParmsInfoBuffer;
err: OSErr;
BEGIN
WITH pb DO
BEGIN
ioNamePtr := NIL;
ioVRefNum := vRefNum;
ioBuffer := @infoBuffer;
ioReqCount := SizeOf(infoBuffer);
END;
err := PBHGetVolParms(@pb, FALSE);
IF err = noErr THEN
IF BTst(infoBuffer.vMAttrib, bHasCatSearch) THEN
CatSearchable := TRUE
ELSE
CatSearchable := FALSE
ELSE
CatSearchable := FALSE;
END;
Operating System: File System: Changing a file’s fork without changing last-modified date
Inside Macintosh Volume VI, page 2-22, recommends updating the window positions in a file without changing the last modification date and time on the file. How do I alter a file without automatically changing the timestamp?
To modify the contents of a file’s data or resource fork without changing the last modified date, get the modified date before performing any save operations on the file and restore it when you’re done. You can use the PBHGetFInfo and PBHSetFInfo calls to do this. A short Pascal snippet that modifies the contents of a known file’s resource fork without modifying its modification date is included in the Snippets folder on this issue’s Developer CD Series disc. The code shows how the parameter block is filled in with the file’s information at the start of the routine with a PBHGetFInfo call, and the same data is then used without modification to set the file information at the end of the routine with a PBHSetFInfo. Inside Macintosh Volume IV, page 150, tells you which fields can be changed with PBHSetFInfo.
Procedure DummyResource;
var a:stringHandle;
b:Integer;
fred:str255;
theBlock:HParamBlockRec;
anErr:OSErr;
begin
{Set up the parameter block}
fred:='anIcon';
theBlock.ioCompletion:=nil;
theBlock.ioNamePtr:=@Fred;
theBlock.ioVRefNum:=0;
theBlock.ioFDirIndex:=0;
theBlock.ioDirID:=0;
{Recover the files info to save the mod date}
anErr:=PBHGetFInfo(@theBlock,false);
{modify the resource fork}
b:=OpenResFile('anIcon');
a:=StringHandle(GetResource('STR ',128));
a^^[1]:=char(ord(a^^[1])+1);
ChangedResource(Handle(a));
UpdateResFile(b);
CloseResFile(b);
{Now restore the original last mod date in the files
directory entry.}
theBlock.ioCompletion:=nil;
theBlock.ioNamePtr:=@Fred;
theBlock.ioVRefNum:=0;
theBlock.ioFDirIndex:=0;
theBlock.ioDirID:=0;
anErr:=PBHSetFInfo(@theBlock,false);
end;
Operating System: File System: System 7 Finder and file duplication time
Duplicating a large file under the System 7 Finder took four times as long as under System 6. How can I make System 7 copy more blocks and larger sizes, to reduce duplication time?
Duplicating a file in the Finder is slower in System 7.0 than in previous systems because the new system allows you to switch out of the Finder to another application for those really big file duplications. This is a feature that was installed into the Finder. The Finder is constantly checking to see if it should be switched out and this takes time. Since you can’t get something for nothing, even in the Macintosh world, there is a speed loss when copying files in the Finder.
This speed change will not happen from within an application. In fact, you may notice a small increase in the speed at which applications can duplicate files. Try using the “duplicate” command in MPW and you’ll see that it’s considerably faster than the Finder.
Operating System: File System: Copying a file or folder dragged to Macintosh application
What do I need to do to have my Macintosh application copy any folder or file that is dragged to it?
One method is to create an application and have it reside on the desktop. The user can then just drag files to that application, which will in turn receive an open event on the file and duplicate the file. This is possible because when a document’s icon is dragged on top of an application’s icon, the Finder will tell the application to open the file if the application knows about the file.. The only catch is that you’ll need to use the special 'FREF' type that will enable the Finder to send you an 'odoc' for ANY file. The key 'FREF's you’ll need are:
**** -- any file,
fold -- any folder,
disk -- any disk.
The characters should be all lowercase letters. This should allow your application to receive an open for anything that’s dragged to it. It will be up to your application to handle possible error conditions such as not enough disk space.
Operating System: File System: FSSpec and SFReply information blocks
How can I make FSSpec file information comply with what was a SFReply information block? Is there a way to convert FSSpec information—as passed, for example, via an Open Documents Apple event—to a vRefNum as understood by an SFReply record? We want to keep our tried-and-true non-System 7 file management logic and convert from FSSpec to SFReply-type format.
Not wanting to obsolete a good bit of file system code is understandable; however you would be better off investing in a redesign of all code that is dependent upon SFReply data structures. While it’s unlikely that Apple will dispense with support for old SFGet/PutFile functions in the near future, the use of SFReply-style data structures in internal calls has no development future.
The vRefNum field of the SFReply record was originally (Inside Macintosh Volume II days) a volume reference number; later, with the creation of HFS in 1986, it became a working directory reference number for purposes of backward compatibility. In HFS, a file or directory entity on a volume is specified with a volume reference number, a directory ID and a name. An FSSpec contains this latter information.
To convert from FSSpec to SFReply requires that your application manage the manipulation of working directory entities, which has disadvantages from the point of view of the system and compatibility.
There are several difficulties with working directory references:
• There is a system-wide limit on their number;
• If you have a working directory reference to which no file buffers are open and some other application closes that working directory without your knowledge of it, the internally stored reference number in your application is invalid and you have no way of knowing about it;
• The documentation about where/when/how to close a working directory is ambiguous and confusing…
• An FSSpec can refer to either a file or a directory while an SFReply can only refer to a file.
DTS urges you to take the time to remove dependencies upon SFReply data structures as soon as is feasible.
Operating System: File System: ioVAtrb bit 7 and bit 15 locked volume bits
I want to determine if a disk is locked before trying to open it. Examining bit 15 of ioVAtrb using PBGetVInfo, as suggested on page 104 of Inside Macintosh Volume II, bit 15 is clear for a locked volume such as a CD-ROM, but bit 7 is set. Why is this happening?
The reason for your observed discrepancy is that bit 15 is set for a software lock and bit 7 is set for a hardware lock. In the case of the CD-ROM there is no software lock but only a hardware lock, so bit 7 is set and bit 15 is clear. Volumes II and IV of Inside Macintosh both say that “only bit 15 can be changed” and should be set if the volume is locked. The fact that you can set it with PBSetVol means that it is a software lock. What the documentation fails to mention is that using PBGetVInfo you can also check bit 7 of ioVAtrb to see if there is a hardware lock. The recommended procedure is to first check the hardware lock (bit 7 of ioVAtrb) and then check the software lock (bit 15 of IOVAtrb).
Operating System: File System: How to search only nonserver mounted volumes
If I don’t want to search any AppleShare or File Sharing volumes, how can I tell which mounted volume to search?
You should be able to use the field vMServerAdr in the GetVolParmsInfo attributes buffer of PBHGetVolParms to determine whether to search a volume. Since the vMServerAdr field specifies the internet address of the server that manages an AppleTalk server volume, checking for a zero internet address before searching the volume would seem the way to go for you.
X-Ref:
Inside Macintosh Volume VI, pages 25-37 to 25-40
Operating System: File System: Apple IIGS Integer Math Frac numbers
The Apple IIGS Integer Math tool set has a square root function for Frac numbers. I’m not familiar with these Fracs; the Apple IIGS Toolbox Reference defines them as 32-bit signed with 30 bits of fraction. It would seem to me that this leaves 1 bit for the whole number. How can I use this call to extract the square root of 32-bit signed numbers with 6 bits of fraction (as found in TrueType point values)? Or is there a better alternative?
Fracs are 32-bit signed with 30 bits of fraction; this leaves 2 bits for the whole number portion, not 1. (Fracs represent numbers from -2 to 2 $80000000=- 2 and $7FFFFFFF=2.) The source of this information? Inside Macintosh Volume IV! Well, at least we did write it down…
You cannot, as you guessed, easily use this to get the square root of 32-bit
signed 6 bit decimal number, unless you consider the following information:
sqrt(x)=sqrt(x/100)*10
or
sqrt(x)=sqrt(x/10000)*100
or
procedure FixSqrt(theFix:Fixed):Fixed;
{ Take the square root of a fixed point number which has }
{ 16 bits of whole number and 16 bits of fraction. }
{ NOTE: This routine assumes the FixInput if between }
{ 20000 and -20000 }
var theFrac:Frac;
tempFix,anotherFixed:Fixed;
aLong:Longint;
begin
aLong:=10000;
tempFix:=Long2Fix(aLong);
tempFix:=FixDiv(theFix,tempFix);
theFrac:=Fix2Frac(tempFix);
theFrac:=FracSqrt(theFrac);
tempFix:=Frac2Fix(theFrac);
aLong:=100;
anotherFixed:=Long2Fix(aLong);
FixSqrt:=FixMul(tempFix,AnotherFixed);
end;
Of course, this could be simplified even further by hard-coding the constants for fix(100) and fix(10000), then recoding in assembly language to allow faster and looser type coercions.
Operating System: File System: Where to get Macintosh third-party file formats
How can I get the file format details on the likes of MacWrite, MacWrite II, and Microsoft Word?
Macintosh file formats are not published like Apple II file formats. You must contact the developers of the Macintosh software in order to obtain their file formats.
Operating System: File System: Macintosh open file maximums & how to alter
Macintosh open file maximums & how to alter
There’s a limit on the maximum number of files that you can have open on the Macintosh at one time. This varies between System 7 and earlier versions of the Macintosh operating system.
System 7 is basically limited in this area only by the amount of RAM that you have available. It dynamically allocates more memory for the file control blocks, depending on the number of files that you desire to open. So this typically is not a problem under System 7.
System 6, however, defaults to 10 open files at once. This is most easily altered by the use of an init called “Up Your FCBs,” available on the current Developer CD Series disc. Please note that you shouldn’t try to use this init with System 7; it isn’t necessary and most likely will cause you problems. Alternatively, you can change this value yourself by modifying your SystemStartup boot block information. This is fairly easy to do, but it should be noted that Apple doesn’t support modifications to your boot blocks.
The SystemStartup information (for a Macintosh system or a file server), is stored in logical blocks 0 and 1 of an HFS startup disk. It contains the maximum number of files that can be open simultaneously, with a default of 10. The location for this parameter is $7A of logical block 0 on an HFS disk. The number at $7A (default is $000A or decimal 10) serves as the parameter for files open at one time.
The number $000A (or decimal 10), for instance, is proper for 128K and 512K systems. If the Macintosh is equipped with 1 MB or more of memory, the system multiplies the number at $7A by four (that is, it becomes decimal 40) and uses the new number as the new file limiter.
You can use a disk editor, like FEdit, to change this number. The file control block buffer and system heap size will be calculated with the changed files open parameter upon restarting. If you must raise this number, do it in small increments. Raising the number in location $7A, as some users have done, can force the system to set aside too much memory. This causes a system error, which, because it is unexpected, the system cannot handle. The result is a system lockup.
The MPW linker tends to stretch the open file maximum. If you’re running into problems trying to link too many files at once, you might consider using the lib utility to combine some of these files, thus requiring fewer file control blocks to be open at once during the link process.
Operating System: File System: Code for reading from a nonMacintosh-formatted floppy disk
My Macintosh® application needs to recognize, list the files of, and read files from a DOS disk in a Macintosh application, while running under either System 6 or 7. Something akin to the way Apple File Exchange works would be fine—starting the application and then having the application recognize the DOS disk and listing its contents.
Assuming you want to start from scratch and write your own, instead of using a third-party software package such as DosMounter, you’ll probably need to check out technical references on DOS floppy formats. Here’s some code for the hard part—reading an arbitrary floppy in non-Macintosh format:
/* pass driver name, e.g. ".Sony" */
/* returns driver Reference Number */
OSErr
Open(fn, RefNum)
StringPtr fn;
short *RefNum;
{
OSErr result;
ParamBlockRec pb;
pb.ioParam.ioNamePtr = fn;
pb.ioParam.ioCompletion = 0;
pb.ioParam.ioPermssn = fsRdPerm;
result = PBOpen(&pb, false);
*RefNum = pb.ioParam.ioRefNum;
return result;
}
/* pass refNum gotten from Open */
/* pointer to destination */
/* bytes to read */
/* offset from byte 0 of disk */
OSErr
Read(refNum, dest, count, offset)
short refNum;
Ptr dest;
long count;
long offset;
{
OSErr result;
ParamBlockRec io;
io.ioParam.ioCompletion = NULL;
io.ioParam.ioVRefNum = 1;
io.ioParam.ioRefNum = refNum;
io.ioParam.ioBuffer = dest;
io.ioParam.ioReqCount = count;
io.ioParam.ioPosMode = fsFromStart;
io.ioParam.ioPosOffset = offset;
result = PBRead(&io, false);
if (result != noErr)
printf("PBRead failed. ioActCount = %d\n", io.ioParam.ioActCount);
return result;
}
Operating System: File System: Technique for maintaining up-to-date list of Macintosh volumes
How can my Macintosh® application maintain an up-to-date list of active volumes? Is there a way to detect if a volume is ejected?
No event is posted, and no other notification is available for when a volume is ejected. The best way of keeping your list of volumes up to date is to index periodically through all mounted volumes with PBHGetVInfo or PBGetVInfo and cross-check them against your program’s most up-to-date list of volumes.
It’s probably best to do this check also on every resume event, in case the user ejects a disk while in the Finder. The periodic check is still necessary, however, in case a Desk Accessory in your own heap ejects a disk or the user hits command-shift-1 or 2. Since you probably don’t want to check every call through WaitNextEvent, just keep track of the last time you updated the volume list and compare it to TickCount.
Operating System: File System: Changing the volume control block modification date
How can I change the modification date of my Macintosh® external file system driver’s volume control block? I’ve tried different values in both the vcbLsMod field of the volume control block and the ioVLsMod field of the HParamBlock without success.
Some of the volume information is getting magically cached somewhere, and that in order to update it, you must first put the volume offline! I know, it sounds weird, but I’ve seen the source code to disk copy utilities that do this in order to change that kind of information. So try putting the volume offline before writing the volume info out to it, and then call FlushVol on the volume.
Operating System: File System: Copying a file from application folder to System folder
My installer application should automatically copy known files from either a floppy or a folder in the same directory or folder as the application. How can I determine a reference number for the source file in the directory without using the Standard File Package SFGetFile?
Regarding your question as to how best to go about copying some files from the same folder as your application to the System folder, here are a few thoughts:
For any File Manager call that expects only a vRefNum—that is, it isn’t one of the HFS-specific calls—passing a vRefNum of zero (0) will refer to the same folder as the application. So, for example, you could pass zero to PBOpen to read the data fork of the file, and you could pass zero to read the resource fork. Note that in both cases, you should pass the name of the file as well, and specify read permission only, since your intent is to copy the file, not to write to it.
You should use the PB calls because they allow you to specify access privileges to the files, which is a particularly good idea in a shared environment, such as MultiFinder or a file server. If you do use the PB calls to open the file forks, you should also use them for reading and writing, as mixing and matching high- and low-level File Manager calls tends to give the Operating System indigestion, to say nothing of what it would do to the programmer.
Don’t forget to get the File Info from the source file and set the File Info of the copy! But in the process, don’t forget not to copy the INITed bit.
So, in summary: use a vRefNum of zero to refer to the same folder as the
application, refer to the files by name, and watch out for the above points,
and everything should go smoothly.
Operating System: File System: How to get the directory ID of a folder based on the path name
Is there any Macintosh® routine that gets the directory ID of a folder based on the path name?
You can call PBGetCatInfo with ioFDirIndex set to zero to get the directory ID of a folder based on the path name.
Operating System: File System: Code for identifying vRefNum and DirID of MAC System Folder
I need to identify the startup volume as I index through all volumes with PBHGetVInfo, but GetVol and SysEnvirons are returning WDIDs. How can I get the true vRefNum from these calls?
The code below is general purpose code to identify the vRefNum and DirID of the System Folder. It is System 7.0 friendly in that it will use FindFolder ifpresent; otherwise, it falls back to SysEnvirons and converts the wdRefNum into a vRefNum and DirID.
#define BTstQ(arg, bitnbr) (arg & (1 << bitnbr))
/* FindSysFolder returns the (real) vRefNum, and the DirID of
the current system folder. It uses the Folder Manager if
present, otherwise it falls back to SysEnvirons. It returns
zero on success, otherwise a standard system error. */
OSErr FindSysFolder(short *foundVRefNum, long *foundDirID)
{
long gesResponse;
SysEnvRec envRec;
WDPBRec myWDPB;
unsigned char volName[34];
OSErr err;
*foundVRefNum = 0;
*foundDirID = 0;
if (!Gestalt (gestaltFindFolderAttr, &gesResponse) &&
BTstQ (gesResponse, gestaltFindFolderPresent)) {
/* Does Folder Manager exist? */
err = FindFolder (kOnSystemDisk, kSystemFolderType,
kDontCreateFolder,
foundVRefNum, foundDirID);
} else {
/* Gestalt can't give us the answer, so we resort to
SysEnvirons */
if (!(err = SysEnvirons (curSysEnvVers, &envRec))) {
myWDPB.ioVRefNum = envRec.sysVRefNum;
volName[0] = '\000'; /* Zero volume
name */
myWDPB.ioNamePtr = volName;
myWDPB.ioWDIndex = 0;
myWDPB.ioWDProcID = 0;
if (!(err = PBGetWDInfo (&myWDPB, 0))) {
*foundVRefNum = myWDPB.ioWDVRefNum;
*foundDirID = myWDPB.ioWDDirID;
}
}
}
return (err);
}
Operating System: File System: System 7 UnmountVol and Eject calls return positive drive number
Why is my Macintosh® driver receiving a positive drive number under System 7.0 upon notification of an _Eject call?
When the “driver wants a call on eject” bit is set in the flag bytes preceding a drive queue element, _Eject will issue a _Control call with a csCode of 7 to the driver. This _Control call is supposed to inform the driver which disk the OS is attempting to eject, by passing the drive number in the ioVRefNum field of the parameter block.
However, there’s a bug in the ROM that only mainfests itself when _Eject is given a volume reference number for a disk that has both the “nonejectable” and “driver wants a call on eject” bits set in the drive flag bytes. This bug causes the driver to receive the negative of the drive number, rather than the positive drive number.
The System 7.0 Finder™ has reversed the order of its calls to _UnmountVol and _Eject, causing it to pass the drive number to _Eject, which then passes it on to the driver correctly. Unfortunately, under previous systems, the Finder passed the volume reference number to _Eject, forcing developers to work around the bug by accepting negative drive numbers; however, a problem could occur now under System 7.0 if positive drive numbers weren’t accepted as well.
A number of driver writers have notified us of this problem, but few (so far) have been adversely affected. As it has always been possible for utilities or applications to make _Eject calls with either a volume reference number or a drive number, the proper workaround is to handle both positive and negative drive numbers.
Operating System: File System: Apple II ProDOS file system cache
How can I turn off the GS/OS® file system cache, or keep it from writing to a disk while my file system optimizer is running?
Altering volumes at the block level will confuse GS/OS, because the ProDOS® File System Translator (FST) keeps copies of file system structures that aren’t in the cache. You need to use DWrite, although using DWrite instead of WRITE_BLOCK risks destroying the integrity of any open files on disk, such as the system resource file. If you use WRITE_BLOCK, you must close any open files, including the system resource file if you optimize the boot disk.
Once you start optimizing, don’t make any calls that could directly or indirectly result in operating system calls—no DA access, no Font Manager calls, no loading tools, nothing. When you’re done, GS/OS’s internal volume control records (VCRs) will be completely invalid and you’ll have to call OSShutDown.
Operating System: File System: Macintosh filename cannot start with a period (.)
Why do I get a bomb when I create a Macintosh® filename starting with a period (.)?
Macintosh filenames are not allowed to begin with a period, to avoid possible confusion with driver names, which must begin with a period. (This restriction does not apply to folder names.) Ideally, the Finder® should catch this possible error and require the file to be renamed, but it doesn’t. Future versions of the Finder should catch this potential problem, but until then users must remember not to begin a filename with a period. See Macintosh Technical Note #102, HFS Elucidations, for details.
Operating System: File System: Macintosh file reference number (refNum) range
Can the refNum returned by FSOpen ever be 1? What is the range or format of legal refNums?
Macintosh® file reference numbers (refNums) are currently positive and that means any positive number, including 1. This doesn’t mean that they won’t change in the future, however. To maintain system compatibility, use refNums only as they’re intended to be used.
Operating System: File System: PBHCopyFile and Macintosh file copying
I was just about to write a Macintosh® file copying function when I decided to look up a definition in HFS.h (THINK C 4.0.2) and stumbled across the following definition:
typedef struct {
STANDARD_PBHEADER
int ioDstVRefNum;
int filler8;
Ptr ioNewName;
Ptr ioCopyName;
longioNewDirID;
longfiller14;
longfiller15;
longioDirID;
} CopyParam;
Isn’t this a PB for a file copying function?
The ParamBlock structure that you found is indeed for the PBHCopyFile call. PBHCopyFile is documented in Inside Macintosh, Volume V, the File Manager chapter. The hitch is that it is an optional call for AppleShare® file servers, and it works only intra-server (but can work across volumes that are on the same server). You can determine whether a particular volume supports PBHCopyFile by calling PBHGetVolParms on that volume and checking the bHasCopyFile flag (bit 14) of the VMAttrib field. Also, you can determine whether two volumes are on the same server by calling PBHGetVolParms on them and comparing their internet addresses. If they are the same, then they are on the same server.
Unfortunately, if what you are looking for is a single call to copy a file on the Macintosh, there isn’t one (oddly enough). To handle the general case of copying a file on the Macintosh, you still have to copy the file’s data fork, resource fork, and Finder Info flags, except for the INITed bit.
Operating System: File System: Space & pointer needed for ioNamePtr name string to be returned
I am trying to convert from a Macintosh® working directory reference number, as returned by SFGetFile, to a directory ID (DirID) and volume reference number (vRefNum). I also require the volume name (ioNamePtr). My code successfully returns the former two items but repeatedly returns ioNamePtr as a NIL.
The File Manager calls that return a string always require you, the caller, to allocate space for that string and to pass the pointer to that memory in ioNamePtr. If the File Manager sees that ioNamePtr is NIL, it won’t bother returning the name string.
Operating System: File System: Determining the amount of free space on a Macintosh disk
How can I determine the amount of free space on my Macintosh® disk?
This is determined from information obtained from a pbHGetVInfo call. Determine the free space by multiplying the number of free blocks on the disk by the size of each of these blocks. Here’s an example in MPW® Pascal:
TwoIntsMakesALong = RECORD
{ Necessary trick to take into account that ioVFrBlk is unsigned }
CASE Integer OF
1: (long: LongInt);
2: (ints: ARRAY [0..1] OF Integer);
END; {TwoIntsMakesALong}
VAR
myHPB : HParamBlockRec;
convert : TwoIntsMakesALong;
BEGIN
WITH myHPB DO BEGIN { set up the block for the
PBHGetVInfo call}
ioNamePtr := NIL; { we don’t care about the name}
ioVRefNum := yourVRefNum;
ioVolIndex := 0; { use ioVRefNum only}
END; {with}
err := PBHGetVInfo(@myHPB,FALSE);
convert.ints[0] := 0;
convert.ints[1] := myHPB.ioVFrBlk;
FreeSpace := convert.long * myHPB.ioVAlBlkSiz;
END;
In MPW C, it looks something like this:
HParamBlockRec myHPB;
longint FreeSpace
myHPB.volumeParam.ioNamePtr = nil; /* don't care about
the name */
myHPB.volumeParam.ioVRefNum = yourVRefNum;
myHPB.volumeParam.ioVolIndex = 0; /* use ioVRefNum only */
err = PBHGetVInfo(&myHPB,false);
FreeSpace = (long)myHPB.volumeParam.ioVFrBlk * myHPB.volumeParam.ioVAlBlkSiz;
Operating System: File System: Opening and reading Macintosh files during I/O completion time
I have created a Macintosh® INIT that will communicate over the net asynchronously using ADSP (AppleTalk® Data Stream Protocol). I would like to be able to open and read files during IO completion time. File Manager calls like FSOpen would not work if an application were accessing the disk when the ioCompletion occurred. I am considering using ASYNC device driver calls, but PBOpen has the possibility of moving memory. Is there a way around this?
Hmmmmmm… in real life, PBOpen won’t move memory as long as you use the preallocated volume buffer that the system provides by default.
The File Manager isn’t reentrant, either, but there are a couple of things to try that might do the job for you:
1) Use the asynchronous versions of the calls. The problem here is that the SCSI Manager actually doesn’t support asynchronous SCSI I/O, but the effect that you’re really looking for—postponing the file operation until it’s safe— might be the end result anyway.
2) You might wish to block on the value of the low-RAM global FSBusy. If it’s TRUE, then a file operation is already in progress and you’ll have to wait.
A caveat: The FCB queue in System 7.0 is dynamically resized, which means that System 7.0 will no longer suffer from the “how many files can I have open at once” problem, but it also means that opening files will no longer be safe at times when it isn’t safe to call the Memory Manager (such as at interrupt/ioCompletion time).
Operating System: File System: How a new Macintosh directory ID is determined
Our Macintosh® application moves files between directories on a file system; the directories determine certain actions and are seldom changed; thus, the application keeps a persistent reference to the directories. The current form of this reference is <volume name, path from root>. According to a System 7 lecture, the preferred form for a persistent file reference is <volume name, directory ID, filename>, which reduces to <volume name, directory ID>, the preferred form for a persistent directory reference. The process of throwing folders away and creating new ones could result in a directory ID being reused on an HFS volume. Is this truly a threat, or has the directory allocation scheme been designed to require many transactions before reusing an ID?
You are correct in your assumption that many transactions need to take place before a directory ID gets reused. The system does not start with dir ID = 0 and search the hard disk until it finds an ID that’s not used. Instead, the ID of the last created folder in a “last created ID” field on the disk. When the system creates a new folder, it searches with that “last value” + 1. Since these are 32-bit values, you’d have to create over 4 billion folders before you wrap around again to zero.
Operating System: File System: No file limit within Macintosh HFS directory
Is there a limit to the number of Macintosh® files that can be put into a single directory under HFS?
There really isn’t a limit to the number of files that can be placed in a single directory under HFS. The only limit is disk space. The Finder™ may have some performance problems (for example, it may take a long time for the window to update), but there shouldn’t be any major problems.
Operating System: File System: _CatMove vs _HReName
When using the Macintosh® _CatMove trap, can I pass the ioNewName field and leave the ioNewDirID field nil? When tracing through a few calls to this trap, it seems that _CatMove works just fine when the reverse is true (ioNewName is nil).
It sounds like you are trying to get _CatMove to behave like _HRename. Leaving the ioNewName field nil is reasonable if you are just changing the position of the file in the directory structure without effecting its name. In the case of filling in ioNewName and leaving ioNewDirID blank (if it were allowed), this would be like saying “change the name and leave the directory unchanged.” This is definitely a job for _HRename.
Operating System: File System: Distinguishing between Macintosh vRefNums and WDRefNums
How do I find the real Macintosh® vRefNum and real dirID? If I pass a working directory to PBHGetFInfo, will the ioDirID field return a real dirID? Will the ioVRefNum field contain the working directory I passed in or the real vRefNum? Also, if I pass a real vRefNum to GetWDInfo, will it do nothing and yet return no error?
Here’s the way to tell the difference between vRefNums and WDRefNums (copied from Macintosh Technical Note #77):
A vRefNum is a small negative word (e.g. $FFFE).
A WDRefNum is a large negative word (e.g. $8033).
A dirID is a long word (for example, 38). The root directory
of an HFS volume always has a dirID of 2.
When you pass a real vRefNum into GetWDInfo, it will look at the ioWDIndex field in the WDPBPtr and return information about the corresponding working directory on that volume (Inside Macintosh, Volume IV, page 159). You can also specify an ioWDProcID and GetWDInfo will only index through Working Directories on the specified volume with the specified proc ID.
PBHGetFInfo will not return a valid dirID and vRefNum if you pass it a working directory; if you want that information you should pass the WDRefNum to PBGetWDInfo in ioVRefNum (making sure you set ioWDIndex to zero).
Remember that working directories are provided simply to facilitate compatibility between HFS and programs that were written under MFS. You should be converting working directories to their corresponding VRefNum and dirID pairs before using them with your PBH variant calls.
Operating System: File System: Working directories and WDRefNum
How do I get the directory ID when using HCreateResFile (as described in Macintosh® Technical Note #214). Also, what exactly are working directories, and do I need to be concerned with them, or are they a thing of the past?
The directory ID comes indirectly from the Standard File dialogue that the user uses to select an output or input file. Standard File returns a working directory reference number in the ioVRefNum. Use the PBGetWDInfo call to break that up into an ioVRefNum and ioDirID pair.
Working directories are a compatibility item to allow programs written for MFS to run under HFS. Since MFS didn’t support directories in any true sense, HFS needed to be able to encode both volume and directory information in the same place. The vRefNum was the most logical spot to do that, and hence the WDRefNum was born. The first and last thing you should do with a WDRefNum is convert it to a vRefNum and DirID pair. For more information on the PBGetWDInfo call, please refer to Inside Macintosh, Volume IV, page 159.
Operating System: File System: PBHDelete insights and code snippet
Using a synchronous call to delete an empty Macintosh® directory using PBHDelete returns a fBsyErr.
I don’t know exactly what is causing the fBsyErr on your machine, but here’s my best guess: The reason you are experiencing this problem is that something has set a working directory to the one you’re trying to delete. I was able to get this to happen by setting the current directory in MPW to “foo:temp:” and then trying to delete it. The bad news is that you can’t close another process’s working directory. There will be cases where your application won’t be able to delete the directory until the user resets the default directory in the offending application. Such are the perils of working in a multi-tasking environment....
Also, I would suggest using a routine like the one included below. It ensures that the specified file is in fact a directory, and supplies a vRefNum and DirID to PBHDelete, which I feel is safer than just giving a full pathname.
/*
**
** DirDelete.c
**
** An MPW tool to delete a directory.
** Gets the target file from the command line.
**
** Neil Day
** MacDTS
** Apple Computer, Inc.
** 11/29/90
**
*/
#include <Stdio.h> /* compiler interfaces */
#include <Files.h>
#include <Memory.h>
#include <Strings.h>
#define DIR_BIT 4
OSErr DirDelete (char *dirName); /* function prototypes */
main (argc,argv)
int argc;
char **argv;
{
int argCounter;
OSErr err;
if (argc < 2) {
printf ("Format : DirDelete <file1> [<file2> ... <fileN>]\n");
return;
}
for (argCounter = 1; argCounter < argc; argCounter++) {
printf ("%s\n",argv[argCounter]);
err = DirDelete (argv[argCounter]);
if (err)
printf ("DirDelete : got error %d while trying to remove %s\n",
err,argv[argCounter]);
}
}
/*
** DirDelete
** Deletes a directory given the full pathname to the directory.
**
** Uses PBGetCatInfo to retrieve the vRefNum and DirID
** of the directory and its status flags. Checks to see that
** the specified file is in a directory, and deletes
** it if it is...
**
*/
OSErr DirDelete (dirName)
char *dirName;
{
OSErr err;
CInfoPBPtr Info;
HParmBlkPtr delete_me;
err = noErr;
Info = (CInfoPBPtr) NewPtrClear (sizeof(CInfoPBRec));
Info->hFileInfo.ioNamePtr = c2pstr(dirName);
delete_me = (HParmBlkPtr) NewPtrClear (sizeof (HParamBlockRec));
err = PBGetCatInfo (Info,false);
if ((!err) && ((Info->hFileInfo.ioFlAttrib>>DIR_BIT) & 0x01)) {
delete_me->fileParam.ioVRefNum = Info->hFileInfo.ioVRefNum;
delete_me->fileParam.ioDirID = Info->hFileInfo.ioDirID;
err = PBHDelete (delete_me,false);
}
DisposPtr ((Ptr)Info);
DisposPtr ((Ptr)delete_me);
return err;
Operating System: File System: How to get the correct size of a Macintosh file
How do I determine the size of a Macintosh® file? I want to get exactly what the Finder™ reports when you do Get Info on a selected file. How do I use the FileParam fields, ioFlLgLen, ioFlPyLen, ioFlRLgLen and ioFlRPyLen to find out the size of a disk file after a call to PBGetFInfo?
To get the correct size of a Macintosh file one needs to sum the physical sizes of the resource and data forks. So, you’ll need to add the fields ioFlPyLen and ioFlRPylen returned in the parameter block.
Operating System: File System: Macintosh verified read error produces dataVerErr (-68)
If I call _Read with “44-ioPosMode” ORed with $40 for a Macintosh® verify, what error code is returned if the verify is not successful?
An error in a verified read should produce an dataVerErr (-68).
Operating System: File System: ioNamePtr needs value for PBGetWDInfo
Why does a call to PBGetWDInfo (without using the ioNamePtr) cause a bus error in the trap _HFSDispatch that is called from the XFCN glue?
DTS Macintosh Tech Note #179 says that you should always set ioNamePtr to some value (NIL if you don’t want a name returned to you).
Operating System: File System: Steps for duplicating a Macintosh file
Is there a routine in the Macintosh® operating system to duplicate a file? (Something that is similar to doing “File - Duplicate” or dragging a file from one disk to another.) We tried PBHCopyFile but, as Inside Macintosh V implied, it did not work.
Unfortunately there isn’t a routine in the Macintosh OS to duplicate a file. The only way to duplicate a file is by doing the following:
1) Create a new file,
2) Open the old file,
3) Open the new file,
4) Check to see how long the old file is,
5) Read the old file,
6) Write everything you read to the new file, then
7) Close both files.
Operating System: File System: Getting HFS directories from full pathnames
How can I determine Macintosh® HFS directories from the full pathnames without going through SFGetFile or opening files?
Apple recommends not using full pathnames. They’re unwieldy, they take up lots of space, the File Manager doesn’t deal with names longer than 255 characters, and they’re unnecessary.
However, if you are working with a piece of software other than your own, it may be unavoidable. If so, there are two methods depending on the size of the full pathname:
1. If the full pathname is less than 255 characters, simply get the dirID of the directory by calling PBGetCatInfo.
VAR
pbc: CInfoPBRec;
BEGIN
name := 'Chinese Junk:Test:VMCalls:';
WITH pbc DO BEGIN
ioCompletion := NIL;
ioNamePtr := @name;
ioVRefNum := 0;
ioFDirIndex := 0;
ioDrDirID := 0;
END;
err := PBGetCatInfo(@pbc, FALSE);
This will return to you the dirID of the folder in ioDrDirID.
2. If the full pathname is longer than 255 characters, you will have to break up the name into smaller parts and get information incrementally. This is shown below. Note that this example is not quite realistic since I store the original full pathname in a Pascal string, which will always be smaller than 255 characters.
VAR
pbc: CInfoPBRec;
pbh: HParamBlockRec;
name: Str255;
tempname: Str255;
vRefNum: Integer;
dirID: LONGINT;
done: Boolean;
lastPos: Integer;
curPos: Integer;
BEGIN
name := 'Chinese Junk:Test:VMCalls:';
tempname := name; {PBHGetVInfo modified ioNamePtr
string, so copy it}
WITH pbh DO BEGIN
ioCompletion := NIL;
ioNamePtr := @tempname;
ioVRefNum := 0;
ioVolIndex := 0;
END;
err := PBHGetVInfo(@pbh, FALSE);
vRefNum := pbh.ioVRefNum; {get vRefNum for PBGetCatInfo
calls}
dirID := 0; {init dirID to zero}
done := FALSE;
lastPos := 1;
REPEAT
curPos := lastPos; {look for the next chunk
surrounded by colons}
REPEAT
curPos := curPos + 1;
done := curPos >= LENGTH(name);
UNTIL (name[curPos] = ':') | (done);
tempname := Copy(name, lastPos, curPos - lastPos + 1);
lastPos := curPos;
WITH pbc DO BEGIN
ioCompletion := NIL;
ioNamePtr := @tempname;
ioVRefNum := vRefNum;
ioFDirIndex := 0;
ioDirID := dirID;
END;
err := PBGetCatInfo(@pbc, FALSE);
dirID := pbc.ioDrDirID; {get this dirID to use a
parent for next chunk}
Writeln('err = ', err);
Writeln('tempName = ', tempname);
Writeln('ioVRefNum = ', pbc.ioVRefNum);
Writeln('ioDrDirID = ', pbc.ioDrDirID);
Writeln('ioDrParID = ', pbc.ioDrParID);
UNTIL done;
END.
This will give you the following output:
err = 0
tempName = Chinese Junk:
ioVRefNum = -2
ioDrDirID = 2
ioDrParID = 2
err = 0
tempName = :Test:
ioVRefNum = -2
ioDrDirID = 271
ioDrParID = 2
err = 0
tempName = :VMCalls:
ioVRefNum = -2 <--- this is the vRefNum you want
ioDrDirID = 26399 <--- this is the dirID you want
ioDrParID = 271
Operating System: File System: How to display mounted volumes in a dialog box
In a MacApp® Pascal program, how can I display all mounted volumes in a dialog box including each volume’s icon and name (similar to the way the Finder™ displays volumes)? I cannot get the resource ID of the icons.
Inside Macintosh® IV-223 and V-469 describe how to read a volume’s ICON. “The Disc Driver” discusses csCode=21, which you can use to make special control calls that will work for all drives to get icon and other information. Tech Note #272, “What Your Sony Drives for You,” describes how to make floppy calls if necessary. The csCode control call should work for you. For an AppleShare® volume, Inside AppleTalk®’’s AppleTalk Filing Protocol (AFP) chapter, pages 13-91 to 13-94, describes a couple of helpful icon-related calls as well.
Operating System: File System: Where to find DirCreate documentation
How do I use DirCreate to create directories?
DirCreate (PBDirCreate) is documented in Inside Macintosh®, Volume IV, page 146. This should give you all the information you need to correctly create a directory with this call. You should also be able to find it listed in the index at the end of that volume for future reference.
Operating System: File System: Apple IIGS System 5 supports File Type Descriptor strings
I noticed the Apple IIGS® Finder™ is now using application-specific strings for the “kind” of a file. How can I use this capability?
The Finder on System Software 5.0 uses a new data structure known as a File Type Descriptor to allow a string to be matched with a particular file type and auxiliary type. Like icon files, multiple File Type Descriptor files may be used, so strings may be “added” to the Finder’s vocabulary. Details on the data structure and the Finder’s implementation are in Apple II File Type Note for File Type $42.
Operating System: File System: Where can I find more information about HFS structures?
Where can I find more information about HFS structures other than in Inside Macintosh®?
Another source of information besides Inside Macintosh® is the MPW® FSPrivate.a file, which contains some private equates used when building the system. None of the information found or used in this file, however, is supported. Don’t ask MacDTS questions regarding any of this information. Using the information is very risky, and will certainly lead to compatibility problems. Proceed at your own risk!
Operating System: File System: How to determine if a Mac file or resource file is already open
How can I tell if a Macintosh® file or a resource file is already open?
Use the File Manager routines PBGetFInfo (IM IV: 148), PBHGetFInfo (IM IV: 149), and PBGetCatInfo (IM IV: 155) to determine if a file is open, and which forks (resource and data) of the file are open. All these routines return ioFlAttrib in the parameter block, which has bits set or cleared to indicate if the file is locked, open, or a directory, and which forks are open (IM IV: 125).
OpenResFile will then call the File Manager to open the resource fork of a file. The refNum returned by OpenResFile is a File Manager reference number. To find out if a resource file is already open (so you don’t accidently close it, for example), just check if the resource fork of the file is open (before you call OpenResFile). If it is, call OpenResFile to get the refNum, but don’t call CloseResFile.
Here’s a fragment in C:
/* uses a full pathname rather than vRefNum/dirId */
HFileInfo fParams;
...
fParams.ioCompletion = NIL;
fParams.ioVRefNum = 0;
fParams.ioFDirIndex = 0;
fParams.ioDirID = 0L;
fParams.ioNamePtr := "\pVolume:Folder:Filename"; /* Pascal string */
err = PBGetCatInfo(fParams, FALSE);
if (fParams.ioFlAttrib & 0x10)
/* pathname is a directory */
else if (fParams.ioFlAttrib & 0x04)
/* resource fork is open */
else ...
Operating System: File System: How can I set the Protect bit of a Macintosh file?
How can I set the Protect bit of a Macintosh® file?
The Protect bit is neither documented nor supported. PBSetCatInfo and PBSetFInfo cannot set this bit. In fact, there is no system call that will modify this bit. Additionally, attempting to change the Lock bit also fails with either of these calls. SetFLock trap must be used to set the Lock bit of the file’s attribute. The Protect bit was an early method of copy protection. If the Finder sees this bit set, it will not allow the user to copy, move, delete or rename the file. It is important to note that ONLY the Finder is paying any attention to this Protect bit, so it would be possible to use any file utility to copy the file even if it is “protected.”
Operating System: File System: How to determine if a Macintosh file is on a locked disk
How do I determine whether a Macintosh® file is on a locked disk?
Call the function PBGetVInfo and check ioVAtrb, which it passes back in the parameter block. If the volume has a software lock, then bit 15 of ioVatrb will be set. If there is a hardware lock (such as the CD-ROM), bit 7 is set.
Operating System: File System: How do I tell if a Macintosh volume is MFS or HFS?
How do I tell if a Macintsoh® volume is MFS or HFS?
To determine whether a volume is HFS or MFS, call PBHGetVInfo. In the field ioVSigWord, the two values you want are $42$44 (HFS) or $D2$D7 (MFS).
Remember, there may be other types of volumes besides these two, such as High Sierra, ISO 9660, or MS-DOS. Don’t assume just two values.
Operating System: File System: How do I find the size of a Macintosh volume?
How do I find the size of a Macintosh® volume?
To find the size of a volume, call PBHGetVInfo. The size is the product of the number of allocation blocks and the allocation block size. (ioVNmAlBlks * ioVAlBlkSiz) It is important to remember—especially in Pascal—that ioVNmAlBlks is an UNSIGNED quantity. If you don’t take that into account, you may get negative results. See pages 123-4 and 130 of Inside Macintosh Volume IV for more details.
Operating System: File System: How do I tell if a volume is a floppy or hard disk, or removable
How do I tell if a Macintosh® volume is a floppy or hard disk?
What you probably want to know is whether a device in the drive queue is removable. Do this by examining the four bytes of flags proceeding the drive queue entry for the device. See pages 181-2 of Inside Macintosh Volume IV for details. C source is:
/* we assume that you get the drive number from some appropriate
place, such as doing a PBHGetVInfo for the volume or looking
directly in the vcb (ackk!)
*/
Boolean
IsEjectable(driveNumber)
short driveNumber
{
DrvQElPtr d;
QHdrPtr queueHeader;
Ptr p;
queueHeader = GetDrvQHdr();
d = (DrvQElPtr)queueHeader->qHead;
while (d != nil) /* find the appropriate drive # */
{
if (d->dQDrive == driveNumber) /* is this the drive
we want? */
{
p = (Ptr)d;
p -= 3; /* to get to the byte with eject info */
if (*p == 8)
return false; /* non ejectable disk
in drive */
else
return true;
}
d = (DrvQElPtr)d->qLink;
}
return false; /* you specified an invalid drive number */
}
If you actually want to know if a volume is a floppy or not, use PBHGetVInfo, and multiply the ioVNmAlBlks (remember, it’s unsigned!) times ioVAlBlkSiz. Currently valid sizes include 400K, 800K, 720K, 1440K.
How will you handle other sizes in the future? Nasty. That’s why I hope you are really asking to detect removable media.
Operating System: File System: How can I tell which directory my Macintosh application is in?
How can I tell which directory my Macintosh® application is in?
When an application is started, the default volume is set to the directory that contains the application. GetVol returns the default volume. If the application calls GetVol before changing the default volume, it will have the directory for the folder containing the application.
Operating System: File System: Forcing the Macintosh system to switch-launch
How can I get my Macintosh® application to force the system to switch to the application’s disk when the user launches it, like Installer does?
This is called switch-launching. You can do what Installer does, setting a Finder™ flag which tells Finder to switch-launch to the new volume. Set this flag with ResEdit™ by selecting the application, selecting “Get Info” from the File menu, then setting the appropriate check box. You can also set this with the MPW® command:
SetFile -a A foo
Note that forcing a switch-launch in this way NEVER works if any of the following conditions are true:
• The new volume is not bootable—that is, has no system
or Finder or is a volume like an AppleShare® volume;
• MultiFinder® is running;
• Either the system or Finder on the new volume is an
older version than the one currently in use.
If any of these conditions are true and you try to force a switch-launch, the user will get a dialog stating why switch-launching is not possible, and asking if the user wants to proceed with the launch (without the switch) or cancel it.
Because of these limitations, if you plan for your application to be used by others and you depend on this capability, you need to think carefully about the consequences of forcing switch-launching. For example, a user may (and probably will) choose to run MultiFinder. There is no way for you to know if MultiFinder is running, and if you are depending on the switch, strange things may happen. Switch-launching may be even more restricted in the future.
Operating System: Finder: Macintosh Finder’s 'fmnu' menu resource TMPL
A variety of homebrew TMPLs for the Finder’s 'fmnu' menu resources have been “thrown over the transom” on AppleLink and other bulletin boards, but I don’t recall anything official. Has Apple publicly documented this Finder resource?
Apple doesn’t have an official TMPL for the Finder’s 'fmnu' menu resources. It hasn’t been publicly documented, because (to some extent) it’s private to the Finder.
The Finder team agreed that there’d be no harm in releasing the Rez template they use, because users might want to mess with command keys, menu titles, etc, for their own use. However, they declined to release the definitions of the flag bits (marked below with three asterii); these should be left alone (they have to do with how the Finder decides to enable items and certain actions to be generically performed when an item is chosen). So, here’s the template, with the caveat that it could change anytime:
type 'fmnu'
{
integer; /* flags *** */
integer = $$CountOf(ItemArray); /* number of items */
array ItemArray
{
longint; /* command id */
integer; /* item flags *** */
string[1]; /* key equivalent */
align word;
pstring; /* menu title */
align word;
};
};
Operating System: Finder: Creating a Finder alias
How can I get my program to create a Finder alias?
Finder aliases are one aspect of the Macintosh human interface considered “reserved for users.” The format is intentionally undefined because it is subject to change, and because alias files should be neither created nor altered by applications. The Finder is the user’s domain, and aliases are a user convenience. If you are inclined to create an alias file, rethink your application design. Would clear instructions to users on how to make the aliases be adequate? Are the files your application needs too scattered?
If some demon still drives you to make alias files, the safest way to do it is by issuing Apple events to the Finder. The particular Finder event for making an alias is 'FNDR' 'sali'; it is documented in the Apple Event registry. Since this Finder event does not return either the name of or an alias to the new alias file, nor is there a Finder event for identifying the currently selected icons, moving the alias file elsewhere will be problematic.
The unsafe way to make an alias file is to create the file yourself. The format of alias files is undocumented; there is no guarantee that any alias files created by your application will always work. At present, you can construct an alias to a document by getting a handle to an alias with a NewAlias call, creating a resource file with the same creator and file type as the original file, adding the alias as a resource of type 'alis' and ID 0, and setting bit 15 of the file’s Finder flags. Aliases to applications have the file type 'adrp'; folder, volume, and system file aliases use other special file types. Finally, alias files should have the same custom icons as their targets.
Once again, DTS urges that you not create alias files from within an application.
Operating System: Finder: Macintosh Finder extensions aren’t supported
Please tell me how to write a Macintosh® Finder™ extension.
Sorry, but Finder extensions are not supported. They are not documented, and facilities for them have not been adequately tested. It is doubtful that there is enough free space in the Finder to reliably add any extensions which are not a standard part of the system.
This situation may change in the future, but for now, DTS has nothing to offer to help you in trying to write your own Finder Extension except assistance in finding an appropriate alternative.
Operating System: Finder: Updating Macintosh window to show new application icon
When I create an application from within my Macintosh® application and put it into an open folder, the new application’s icon does not show up. How come?
Have you made sure not to set the file’s “inited” bit? If this bit is not set,the Finder™ will eventually go check out the file and update the desktop with the bundle accordingly (then it sets the inited bit). This typically can take up to ten seconds to happen, but it should happen.
Unfortunately, there is no direct way to tell the Finder to update the desktop. The Finder will synchronize the desktop file’s appearance after it detects that a change has been made for a volume. This is triggered when the volume’s modification date changes. This occurs when you create or delete a file, for example, or move it to another folder. When a change occurs, HFS will change the modification date of the volume and that folder. When the Finder notices that the volume’s modification date has changed, it begins scanning for changes in all of the open folders. This scanning process takes place about once every 10 seconds, as mentioned above.
Changing the file’s FndrInfo or renaming the file does not change the modification date. As a suggestion for you, you might initially create a temporary file, and then, once all the files are moved around, delete the temporary file. Deleting the temporary file as a last step will cause the Finder’s window to be updated. This is pretty bogus, but it should work.
Keep in mind that the Finder may cache a windows directory and may not know about icon changes unless the folder’s modification date is updated. The update is not controlled by an interrupt, so an application that is not calling WaitNextEvent often enough will vary the period of updates.
Operating System: Finder: Macintosh Finder desktop updates
How does the Macintosh® Finder™ update its windows?
The Finder synchronizes the desktop file’s appearance after it detects that a change has been made for a volume. This is triggered when the volume’s modification date changes. This occurs when you create or delete a file, for example, or move it to another folder. When a change occurs, HFS changes the modification date of the volume and that folder. When the Finder notices that the volume’s modification date has changed, it begins scanning for changes in all of the open folders. This scanning process takes place about once every 10 seconds.
Changing the file’s FndrInfo or renaming the file does not change the modification date.
Keep in mind that the Finder may cache a window’s directory and may not know about icon changes unless the folder’s modification date is updated. The update is not controlled by an interrupt, so an application that is not calling WaitNextEvent often enough will vary the period of updates.
I’ve heard of other developers who changed the affected volume’s VCB lsMod time to the current time. This apparently forces the Finder to update, but it also apparently doesn’t work with floppy disks.
When the Finder is running without MultiFinder®, it is the only program running so it usually does not have to contend with its file system being manipulated under its nose. The major exception to this is when a driver or Desk Accessory adds, changes, or deletes a file. In this case the Finder is using a copy of the folder’s directory and does not know the contents have changed unless the modification date of the folder has changed.
Under MultiFinder the Finder is aware that other applications can be changing the file system under its nose and approximately every 5 seconds, as allowed by the foreground application calling WaitNextEvent, updates any windows that it knows have changed. The Finder still caches the windows directory and may not know about icon changes unless the folder’s modification date is updated. The update is not controlled by an interrupt; an application that is not calling WaitNextEvent often enough will vary the period of updates.
Operating System: Finder: Determining if Macintosh Desktop Manager is present
How does one determine if the Macintosh® Desktop Manager is available? I know under System 7.0 it’s always available, but how about under 6.0?
The best method for determining whether the Desktop Manager is available or not is to use PBGetVolParms on your boot volume and check one of the flags that’s returned, which indicates whether that volume has the new desktop.
Operating System: Finder: Saving as stationery for both Systems 6.0.x and 7.0
How should my application implement saving as stationery to be compatible with System 6.0.x as well as System 7.0?
When the user saves a document as stationery, your application should write it out with the appropriate stationery file type so both System 6.0.x and System 7.0 Finder vesions will display the file’s icon correctly. Also, set the file’s isStationery bit, which you’ll use to identify the file when the user opens it, under either system version. Of course, along with the regular document’s file type, you’ll need to register the stationery file type with DTS.
Operating System: Finder: Reason for Finder “trash can’t be emptied” alert in MultiFinder®
Why does the Macintosh® Finder™ sometimes display the alert “The trash could not be emptied (a file was busy or a folder was not empty)” when the trash contains only an emptied folder?
This is the behavior that you get from the Finder when another application is running (presumably the one that owns the documents that were trashed) that has the folder open as a working directory. Unfortunately, some applications that open working directories aren’t as careful as they should be about closing them, and the result is that the working directory doesn’t go away until the application has quit. Once it does go away, however, the folder can be trashed with impunity.
Operating System: Finder: Types of unsupported Macintosh Finder window manipulation
How can we access the Macintosh® Finder™’s desktop data structure to accomplish the following:
• Place a file or folder from any mounted volume on the desktop at (x,y)
• Determine what files and folders are on the desktop and where and what disks, directory they belong to.
• Open or close a finder window for a volume or folder
• Put away a file or folder that is on the desktop
under both System 6 and System 7?
Apple doesn’t support Finder window manipulation such as what you’ve described. There is a lot involved in this type of manipulation, and it requires knowledge in areas that also are not supported by Apple. If you really want to pursue this you can try to hack it out on your own, but we can’t guarantee that the techniques you come up with will continue to be compatible with future Finder versions.
Operating System: Finder: 7.0 Finder intercepts Control Panel command key menu events
Under System 7, Macintosh® command key menu events no longer are passed to a Control Panel’s main window and instead intercepted as Finder™ command key menu equivalents. Can I get around this?
Under System 7, all command-key equivalents refer to the menu bar. The problem lies in the fact that, if the Control Panel handles a command-keystroke, there is no way for the Finder to realize it. Although it’s not really recommended, you could conceivably patch KeyTrans and, upon finding that your Control Panel is up and that a command-keystroke is being pressed, queue those in your own private queue that the Control Panel could then search in addition to the normal event queue. This is probably much more trouble than it is worth.
Operating System: Finder: Applications shouldn’t position Macintosh Finder icons
In our installation program, how do we set the Macintosh® Finder™ location of folders that we create during the installation process? The method we’ve tried seems to work in positioning the folder in its parent, but causes the view state of the folder to be inconsistent in System 6—files in the folder appear by name, but the view icon has “by Small Icon” checked. Changing the view state from the View menu seems to work and has no further side effects.
The “right” to position icons in the Finder and to set the default view for new folders is reserved for the user. You create the files and folders, and let the Finder position them. In addition to being closer to what the user expects, you won’t have to worry about positioning conflicts with existing items in the folder (although if you’re creating the parent folder, this doesn’t matter as much). Even more significantly, you won’t have to worry about subtle changes between the 6.x and 7.0 Finders’ positioning and view algorithms.
Operating System: Finder: Macintosh desktop refresh rate
I have observed the Macintosh® desktop is refreshed every 10/20/30 ticks. What is the actual refresh period? Is it a constant or depends on an interrupt? Also is there a way that I can force a refresh? Is it the same under both Finder™ and MultiFinder®?
When the Finder is running without MultiFinder, it the only application running so it usually does not have to contend with its file system being manipulated under its nose. The major exception to this is when a driver or Desk Accessory adds/changes/deletes a file. In this case the Finder is using a copy of the folder’s directory and does not know the contents have changed unless the modification date of the folder has changed.
Under MultiFinder the Finder is aware that other applications can be changing the file system under its nose and approximately every 5 seconds, as allowed by the foreground application calling WaitNextEvent, updates any windows that it knows have changed. The Finder still caches the windows directory and may not know about icon changes unless the folder’s modification date is updated. The update is not controlled by an interrupt; an application that is not calling WaitNextEvent often enough will vary the period of updates.
Operating System: Finder: Controlling which application version is launched by Finder
We have several versions of a Macintosh® application (standard, demonstration, student, and so on) and they all share the same type ('APPL') and creator bytes. When we have all of the versions on a hard disk, double-clicking on a document launches the demonstration version rather than the full version. Is the system’s application choice based on its date of creation, name, or other attribute? How can a user specify which of several versions s/he wishes to launch when double-clicking on a document? Alternatively, what can we as developers do to designate the standard version as the one to be launched if there are other versions on the disk?
The Desktop file maintains a list called the Application List that is all the files of type APPL in order of their entry into the Desktop database. In deciding which one of several versions of the same application to launch, the Finder™ searches this list and launches the first app in the list with the matching creator ID. Applications in the list are ordered based on any event that would update their entry in the Desktop database. The last one copied to the volume is thus at the top of the list. To change the order, you must delete the one you want to be launched, rebuild the desktop and then copy the app back onto the disk. This puts it at the top of the list, and double- clicking any related document will now launch this version of the app.
Operating System: Finder: Apple IIGS 5.0.3 Finder bugs
In using Apple IIGS® System 5.0.3 and a 44 MB third-party removable hard drive, I have the following problems with the system disk: (1) In a disk-to- disk copy from a 32 MB partition to a removable cartridge, the progress bar does not reflect the actual time it takes to copy the partition (it moves too quickly) -- the actual copy DOES work. (2) If a cartridge is not in the drive at startup, a dialog appears stating that the disk is unreadable and asks if it is OK to reformat it.
What you’re seeing are Finder™ bugs. The Finder was not changed for System 5.0.3, but these bugs should be fixed in a future system software release.
Operating System: Finder: Macintosh System 6.0.x Finder rules for emptying trash
When does the Macintosh® 6.0.x Finder™ empty the trash?
According to the Finder source code, here are the conditions under which the trash will be emptied:
• Whenever a copy is done, both the source and destination
disk’s trash will be emptied
• Whenever a disk goes off line
• Whenever a disk is ejected
• Whenever a disk is formatted, the trash will be emptied
before the formatting begins.
• Whenever the user selects empty trash from the “Special” menu
• Whenever an application is launched
• Whenever the system is shut down.
(I determined this by searching the source for all occurrences of the trap _Delete. Then I looked at each of the routines to see if they pertained to trash management. If they did, I searched the source for all occurrences of those routines, looked at each of those and figured out what the enclosing routine did. Since all this was done by examination, it is possible that I missed something.)
Operating System: Finder: Where to find System 7 color icon documentation
How do you get color icons for your applications to show up on the desktop on Macintosh® II computers with color monitors?
Color icons are actually a System 7 feature and therefore unsupported in Systems 6.0.x or earlier. If you would like additional information on this, refer to Inside Macintosh, Volume VI, Chapter 9, “The Finder™ Interface.” This should give you all the information that you’ll need to get this to work under System 7.
Operating System: Finder: Apple IIGS Finder data file format is not available
What is the format of the Apple IIGS® Finder™ data files? There is no File Type Note describing the format.
The format of Finder data files is internal to the Finder. It is version- dependent and the information in the files can’t be reliably used at this point, so the file format is not available.
Operating System: Finder: Forcing the Macintosh Finder to update the desktop
How do I force the Macintosh® Finder™ to update its windows after my application has changed a file’s FndrInfo?
There is no direct way to tell the Finder to update the desktop. The Finder will synchronize the desktop file’s appearance after it detects that a change has been made for a volume. This is triggered when the volume’s modification date changes, which occurs when you create or delete a file, for example, or move it to another folder. When a change occurs, HFS will change the modification date of the volume and that folder. When the Finder notices that the volume’s modification date has changed, it begins scanning for changes in all of the open folders. This scanning process takes place about once every 10 seconds.
Changing the file’s FndrInfo or renaming the file does not change the modification date. As a suggestion for an installer program, you could initially create a temporary file, and then, once all the files are installed, delete the temporary file. Deleting the temporary file as a last step will cause the Finder’s window to be updated.
Operating System: Finder: What do all the bits in the Mac Finder’s 'LAYO' resource mean?
What do all the bits in the Macintosh® Finder’s 'LAYO' resource mean?
The following is probably the only documentation to be found on the 'LAYO' resource. It describes only the settings, not their values. You can use ResEdit to look at and change the values, but you do so at your own risk.
Font ID and size:
These change the font and size of most text displayed by the Finder™, including the icon titles, the window top margin text, all the text in the text views, and the printed text generated by “Print Catalog.” If, after changing font ID or size, you later change the System fonts or use the Finder with a different System file, the font you specified may be missing. In that case the default font will be used. If the size you specify is not available, a scaled size will be used.
Window rect:
This is the rectangle that controls the position and size of new windows created by the Finder. Windows of new folders are given the same view as the “parent” window, has regardless of the window rect.
Tab stops 1-7 and column justification:
You can adjust the column spacing used to display in the text views. The Finder truncates any text that is too wide for the column, so make sure the size, date, time and other columns are wide enough. You cannot change the ordering of the columns or eliminate any of them. Each column can be left or right justified.
Icon spacing options:
You can adjust the grid spacing by dragging the light gray icon, and the grid offset by dragging the dark gray icon. The grid offset vertically staggers the icons, allowing you to space the icons a bit closer together but still read the document titles. The grid you specify will be used when you do a “clean up” or grid drag, or when a new icon is created in a “by icon” format window.
Text view date:
The format of the date can be set to short (12/25/87), medium (Thu Dec 25, 1987) or long (Thursday, December 25, 1987).
Use zoom rects:
This is normally set TRUE, which means that the usual zooming effect takes place when the Finder opens a window or an application. If you set this to FALSE, the Finder does not use the zooming effect.
Skip trash warnings:
DISABLING THIS OPTION IS POTENTIALLY DANGEROUS. If you set this TRUE, the Finder will skip the usual warning that is given whenever you throw an application or system file into the trash.
Always grid drags:
This option is normally not set, which means you can position icons freely on the desktop. If you set this TRUE, whenever you drag an icon, the icon will snap into position on the grid automatically without having to do a “clean up.”
Sort style:
This option adjusts the style of the column heading by which the view is sorted. See the previous section on “text views” for more information. The column in which entries in the text view are sorted (“name in view” by name, “kind in view” by kind) is displayed according to the setting of the sort style.
Watch thresh:
This allows you to adjust length of time before the Finder will display a wristwatch cursor with animated hands during such lengthy operations as file copying. Older Finders don’t use the watch thresh option, so it is disabled and cannot be selected. The time is expressed in 60ths of a second. If you set length of time too short, the cursor will jitter and change shape too often.
Use phys icon:
This forces the system to display the floppy disk icon instead of an icon with an arrow pointing to a disk drive.
Title click:
This option is normally set FALSE. If it is set TRUE, a feature in the Finder is enabled, allowing you to double-click the title bar of a window so that window’s “parent window” opens or comes to the front if already open. The “parent window” is the one that contains the folder the original window represents.
Copy inherit and new folder inherit:
These options are for AppleShare folder privileges. They only affect folders created on an AppleShare server.
Color style:
Normally, folders and file icons are displayed with a color outline. Color style causes these icons to be filled in with color.
Max # of windows:
This allows you to set the maximum number of windows the Finder can open at one time. Increasing the number of windows causes the Finder to need more memory. Under MultiFinder, you may have to increase the memory allocation for the Finder.
Operating System: Finder: How often the Macintosh Finder updates its internal information
The Macintosh® Finder™ doesn’t always show changes my program makes to file sizes and attributes until I close and reopen the window.
The Finder updates its internal information every 10 seconds, and/or whenever a folder is opened. It may not notice some changes unless the folder’s modification date is changed.
Operating System: Folder Manager: Identifying a Macintosh folder correctly with FindFolder information
When I use the name and vRefNum returned from FindFolder, I always get a fnfErr from OpenRFPerm. Why?
FindFolder returns both a vRefNum and a DirID, and they both must be used to identify the folder. Instead of using OpenRFPerm (which only takes a vRefNum), try HOpenResFile. Avoid using PBHSetVol! (See Macintosh® Tech Note #140 for more information.)
Operating System: GS/OS: GS/OS GetFileInfo error conditions
Why does GetFileInfo return errors on some Apple IIGS device names but not others?
GetFileInfo is supposed to return an error because a device name is not a file. GetFileInfo returns information on the volume directory for online block devices, error $2F (device offline) for offline block devices, and error $45 (volume not found) for character devices. This makes sense when you realize that GS/OS is internally expanding all pathnames before trying to decide what to do with them. Device names in pathnames (to files) get converted to volume names before anything else is done with them.
Operating System: GS/OS: GS/OS newline mode and caching with ReadGS
I’m using GS/OS’s newline mode to let ReadGS only grab a record at a time from my file of variable-sized records, each separated by a null byte. Should I use caching in the Read call? If not, does GS/OS re-read the block for the next call to ReadGS?
Although “GS/OS caching” is only done at the driver level, other things can be cached as well. Most FSTs keep a copy of the block around the current mark in the file control record (FCR), just like they keep some key volume blocks in the volume control record (VCR), so usually caching isn’t necessary. However, the worst it can hurt you is the cost of the cache memory and the performance penalty of caching the entire file (which you will eventually do as you read in all the records), kicking out more useful blocks in the cache.
So, realistically, it probably won’t help. Try compiling with and without the cachePriority set to one and timing your code’s execution; you probablywon’t see see a speed increase.
Operating System: GS/OS: GS/OS Loaders “file number” parameter not used
What is the “file number” parameter used by calls to the GS/OS® Loaders such as LGetPathname2?
The file number parameter was intended for a multiple-file Object Module Format (OMF) facility that never quite made it, one way or the other. Unless future documentation says otherwise, always pass $0001 for the file number.
Operating System: GS/OS: GS/OS system service calls
When is it legal to make Apple IIGS® system service calls? I’d like to make calls such as MOVE_INFO from a driver that’s executing asynchronously.
It’s legal to make system service calls in response to a GS/OS® request, for example. Most of them require the OS environment, such as GS/OS’s direct page, but MOVE_INFO, SET_SYS_SPEED, DYN_SLOT_ARBITER, and SIGNAL do not.
When you’re not in the GS/OS environment, make sure the proper language card bank of bank 1 is swapped in. Just JSLing there will put you into something that’s not a system service call. You can either use the bank $E1 equivalents of MOVE_INFO, SET_SYS_SPEED, and DYN_SLOT_ARBITER, or you can make sure that the right $01 language card bank is enabled:
short
lda >$E0C068
pha
lda >$E0C08B
lda >$E0C08B
longmx
; Set up the registers and make your
; JSL My_Favorite_SysSrv_Call
short
lda >$E0C083
lda >$E0C083
pla
sta >$E0C068
longmx
Operating System: GS/OS: Recognizing SCSI partitions from GS/OS
Where can I find documentation on how to recognize SCSI partitions, such as MS DOS partitions, from GS/OS®?
The documents you’ll need are the GS/OS Reference (Addison-Wesley) and the GS/OS Device Driver Reference (APDA®). You can recognize SCSI hard disk partitions programmatically by looking for a SCSI Hard Drive device type ($0005) and a forwardLink or headLink that’s nonzero. This will give you all SCSI hard disk partitions, but it won’t give you non-SCSI partitions, which have a different device type.
Bit 13 of the Device Characteristics word is for “Linked devices” like partitions, but the GS/OS Device Driver Reference says that bit applies to removable media, so not all third-party GS/OS drivers may set that bit for partitions (even though Apple’s SCSI hard disk driver does).
Remember that GS/OS requires each partition to appear as a separate device, so there’s no support for multiple partitions on one logical device.
Operating System: GS/OS: Using notification procedure to patch GS/OS
In some of my recent work, I’ve found it necessary to patch the Apple IIGS® GS/OS® vectors in order to monitor OS calls. My patch works without interfering, but it disappears when the user switches to ProDOS® 8 and back to GS/OS. I tried unsuccessfully to fix this by using the notification queue, asking GS/OS to notify me when the user was coming back from ProDOS 8. How can I safely and reliably patch GS/OS on a permanent basis?
You should be able to patch GS/OS with System 5.0.4. Two observations may help:
• If you ask for all notification events, you’ll get at least one disk-insert event before you get any restart events, since the device driver for the startup disk will “fake” a disk insert to get the appropriate disk-switched statuses set before doing any real work.
• Your procedure may not be the first notification procedure called at restart time. For example, the Resource Manager inserts a procedure so that it can reopen the system resource file on return from ProDOS 8. If this mechanism was broken as you say, the Resource Manager’s notification procedure wouldn’t work either.
Operating System: GS/OS: Apple IIGS System 5.0.4 hard disk installation
How do I install the System 5.0.4 software on my Apple IIGS® SCSI hard disk? Does the Installer update the system?
1) Make backup copies of System.Disk and System.Tools, making sure they keep the same names.
2) Launch the Installer from System.Tools (backup) and install SCSI Driver on the backup of System.Disk. The Installer script knows to delete a couple of fonts as well as the Tutorial folder to make room for the SCSI stuff on a 3.5" disk.
3) Boot the backup of System.Disk and install 5.0.4 onto your hard drive. If you want Shaston 16 and Times 12, install “Additional Fonts” last.
The Installer knows how to make the stuff fit on a floppy. (It are smart <grin>.) It also knows how to update your system without requiring you to trash your existing system folder.
Operating System: GS/OS: Apple IIGS OSVolume error messages
Under GS/OS® 5.0.3, the OSVolume call for GS/OS returns a $27 error code when you use the call on a floppy disk that has never been initialized. It also returns $27 when you make the call to a disk that has been initialized previously as a Macintosh® disk.
We can’t reproduce the problem. Under 5.0.3, a disk which has never been initialized returns error $27 (I/O error) but a disk formatted under HFS correctly returns error $52 (unsupported volume type). $52 is what the FSTs internally report back to SCM if they don’t claim the disk, and if the last FST bounces it the error filters back to the application.
Operating System: GS/OS: Apple IIGS CloseView INIT works with System 5.0.3 or later
When the Apple IIGS® CloseView INIT is copied to my system disk as instructed in the documentation, every move of the mouse erases that portion of the screen until eventually all menus are pulled down and visible. When a newer system disk is used, the problem does not occur.
CloseView is compatible only with Apple IIGS System 5.0.3 and later, because of a change in the way QuickDraw™ II redraws the cursor while hardware shadowing is enabled.
Operating System: Memory Management: Get heap size using PurgeSpace instead of HeapEnd and ApplZone
Our application looks at the low-memory globals HeapEnd and ApplZone to calculate the size of the heap that it’s running in. Is this safe for future compatability or is there a better way?
A better method is to call PurgeSpace and find out how much available memory there really is. This tells you how much memory is available for your application (which is the real point) and it avoids low memory.
Operating System: Memory Management: Heap objects are guaranteed to be at least word aligned
Is the value returned by NewHandle guaranteed to be even? I know Inside Macintosh says the master pointer is guaranteed to be even, but it doesn’t say that the address of the master pointer is even as well.
Yes, the address of a master pointer will be even and all objects pointed to by a master pointer will be even (at minimum, word aligned), but you shouldn’t assume anything more than that. The Memory Manager aligns objects in a way best suited for the underlying hardware. You should not assume you know what that alignment will be, nor should you attempt to force a particular alignment, as that could defeat any performance improvements gained by such alignment and at worst, that could cause compatibility problems on future platforms. The Memory Manager currently aligns objects as follows:
68000 Machines Word aligned
68020 Machines Longword aligned
68030 Machines Longword aligned
68040 Machines Quadword (16 byte) aligned
Again, you must not make any programming assumptions based on this information.
Operating System: Memory Management: Macintosh private stack space
Occasionally, when we operate in our driver at accRun time or when we operate in some of our operating system patches, stack space gets dangerously and sometimes fatally low. Since our driver and patch code runs under the auspices of other applications, we cannot guarantee stack space for other apps, and they certainly have not accounted for us. Is there any way we can use a private stack to ensure we have enough space and always know how much there is?
DTS can’t recommend using a private stack; attempting this generally causes you more trouble than it’s worth. Rather, we recommend you carefully monitor your stack usage. It’s very easy to carelessly eat a lot of space in local stack frames, such as by allocating Str255s locally. Replace such wasteful usages with smaller strings (for example, don’t use a Str255 for a filename, as they’re limited to 31 characters), or use dynamic allocation. (For example, if you need an array of 200 integers, you may find it more convenient to allocate a handle and place the array there, rather than allocating it statically on the stack.) By applying these concepts, you probably can get your stack usage down to a reasonable level without resorting to such practices as a private stack.
If you do feel you need to use a private stack, you will have to disable the stack sniffer while you’re doing so. This can be done my setting the long word at address $110 (StkLowPt) to 0; this will disable the checking done to determine whether the stack has collided with the heap. When you’re done with your private stack, first restore A7, then set StkLowPt to the current A7. This will reenable the checking and start the sniffer off with a reasonable value. Of course, many toolbox routines will not work properly while the stack is in this state; QuickDraw and the Process Manager are two of the first to come to mind. Also, DTS really can’t support applications that attempt to call toolbox routines while using a private stack because it’s not part of the toolbox’s design.
Operating System: Memory Management: Macintosh trap patches from within an application
If you patch a trap from a Macintosh application, is the patch effective for all applications, or just the application that patched the trap?
Patches made from within an application apply only to calls made from the application. This is documented in Inside Macintosh, Volume VI, page 29-7. Global patches must be made at INIT time.
Patches apply only while the application is active because the Process Manager swaps the entire trap table during a major or minor switch. It also swaps selected low-memory globals and deactivates application heap VBL tasks. VBL tasks installed in the system heap are not deactivated on switching. For more information on application contexts, see the Process Management chapter of Inside Macintosh, Volume VI.
Operating System: Memory Management: Checking for GetHandleSize error conditions
Inside Macintosh Volume II, page 33 states that _GetHandleSize returns D0.L >= 0 if the trap is successful or D0.W < 0 if the trap is unsuccessful. What happens if the handle size is 0xFFFF, for instance? A TST.W will indicate an error when in fact there is none. How should I check for this condition?
Inside Macintosh is correct (although confusing…) regarding the determination of an error condition. The way to do it is first test the long to see if it is valid (D0 >= 0). If the long is valid, you can continue with confidence that no error occurred. If, however, the contents of the long in D0 is negative, then the lower word contains the error (and currently the upper word contains $FFFF, the sign extension). The reason to have the manual highlight the fact that only the low word contains the error is to allow you to save the error in standard fashion since all other errors are word sized, and also to caution you against using the processor status on exit from GetHandleSize since it will be based on the low word only. In other words, if the long word is negative, simply ignore the high word. Here is some assembly that will work:
move.L theHandle(a6),A0
_GetHandleSize
tst.L D0
bpl.s @valueOK
move.W D0,theError(A5)
moveQ #0,D0
@ValueOK
Operating System: Memory Management: How Macintosh memory location 0 gets changed
Why does the longword at location $0 get changed to 0x40810000 at every trap?
In System 7, the Process Manager slams a benign value into location $0 to help protect against bus errors when an application inadvertently dereferences a NIL pointer. (There’s no bus-error checking on writes to ROM, so the “benign value” is usually ROMBase+$10000.)
If you’re debugging, you want the opposite effect: you want these inadvertent accesses to “cause” bus errors. If you put a different value in location $0 before the Process Manager starts up (that is, from MacsBug or TMON initialization, or from an INIT like EvenBetterBusError), it will force that value instead. For more information, see the “Macintosh Debugging” article in this issue.
Operating System: Memory Management: Macintosh ID 28 error
Why am I getting an ID 28 error?
Let’s see, where‘s that form letter response for “Beats Me!”... Ah, here it is...
I’m not sure what’s causing your ID 28 error (Stack Meets Heap), but here are a few things you might try, to isolate the problem:
ID 28 is nearly always caused by a code path you didn’t expect, such that a procedure inadvertently calls itself. This doesn’t have to be simple (that is, one of your subroutines may be calling another, which then calls the first again, and so on). Each of these recursive calls adds to the stack (at the very least, four bytes [a return address] each time); if this cycle continues, the stack eventually meets the heap.
Though QuickDraw now checks its stack usage before its heavy-stack-usage operations (like CopyBits), stack collisions are possible if you have a really hungry interrupt handler or QuickDraw bottleneck procedure override.
If it is your intent for your procedures to recurse, it’s possible that the recursion isn’t limited, or that each level of recursion is adding too much data to the stack. For the former, you’ll have to figure out a way to make sure the procedures don’t call each other forever; for the latter, you should minimize the local variables used by the inner procedures (perhaps by declaring them in the outer scope)—this will reduce the amount of data placed on the stack each time.
One specific kind of recursion occurs when you call your main event loop from another procedure as a subroutine. In general, this design should be avoided because of just this problem; this technique can also cause problems if update events get nested.
Operating System: Memory Management: Sharing data between Macintosh applications
What are the preferred methods for sharing data between applications? I want to use the Program-to-Program Communications (PPC) stuff or Apple Events to dynamically link libraries, but the size of the data blocks to be passed between the applications makes copying them around unacceptable. The best method would be to somehow share the data and remain compatible with future systems (presumably with memory protection). How is the system heap on handling large chunks of memory?
As you point out, there could be some memory protection someday, but at this time there’s no indication of how shared memory will be allowed under these tighter rules.In the time being, if you are willing to pay the consequences later, then the following might help:
The four bytes of an address for a location in memory could be passed as data in a PPC data transfer, or Apple events could carry the information. Secondly, the Gestalt mechanism could be used to pass an address between processes or tasks. For your problem this probably is better then the other forms of IPC.
The best thing to do is allocate a shared handle in the system heap. HLock the block only when necessary. Remember, the system heap grows dynamically under System 7.0.
Operating System: Memory Management: Allocating contiguous Macintosh memory
How do you allocate and lock contiguous memory on the Macintosh® under System 6?
There is no method for doing this under System 6.0. In general, the only time you are expected to really need this is for a Macintosh IIci or IIsi under VM.GetPhysical may be used to determine if a block of memory is contiguous. If not, and this is unacceptable, allocate another block (without disposing the first). There is only one discontinuity, so the second block certainly will be contiguous.
Operating System: Memory Management: Using GetPhysical to map logical to physical memory address
How do you translate a Macintosh® logical address to a physical address in System 6?
Under System 6.0.x, an arbitrary memory range may contain at most one physical discontinuity, and then only on the Macintosh IIci or Macintosh IIsi. If a contiguous physical buffer is required, allocate a buffer (with NewHandle, for instance) and use GetPhysical to determine if it is indeed physically contiguous. If it is not, then allocate another buffer immediately. The second buffer should be contiguous since the only discontinuity is contained in the first buffer.
Under 6.0.x, memory is always “locked,” except that caching is enabled for all RAM by default. Calling LockMemory, which works if _MemoryDispatch is implemented, causes the buffer to be noncachable, which is of some value when performing DMA.
Operating System: Memory Management: How to increase Macintosh system heap at startup time
How can I set aside heap space for my device driver at system startup time? I have tried third-party “heap sizers” but they do not seem to help.
Unless you otherwise use the 'sysz' resource in an INIT, the system will only make sure that there is about 16K free for you at init time.
The correct way to increase the size of the system heap at initialization time (for drivers, for example) is to use the 'sysz' resource as documented on page 352 of Inside Macintosh Volume V. This expansion temporarily increases the system heap size by the size specified in the 'sysz' resource. You should be able to sysz as large a space as you may need and then only allocate the amount you actually need at INIT time.
A driver’s INIT should keep system heap space requests to a reasonable limit. Memory requests of 30K, 60K—even 100K with good reason—may be accommodated, but if you find that you are needing very large 'sysz' resources, perhaps your code would be better suited as something other than an INIT.
Operating System: Memory Management: Macintosh system heap size
How do I change the Macintosh® system heap size?
When running System 7.0, the system heap is sized dynamically while running. That is not to say that you cannot run out of system heap space while there is still free RAM available, but the system attempts to resize itself whenever its free space falls below about 16K. In this case there is no way for you to set, increase or decrease the (fixed) amount of system heap as it is dynamic and not fixed.
Under earlier systems, the system boot blocks specify how big the system heap is to be, and this is documented in Macintosh Technical Note #113, “Boot Blocks.”
The 'sysz' resource in an INIT file allows the INIT to specify the amount of free space it needs in the system heap when the INIT is loaded. (This space is reclaimed after the INIT has run if not used by the allocation of memory blocks by the INIT.)
Operating System: Memory Management: Macintosh Memory Manager ROM bug and MMInit
Where can we get our hands on a fix to the ROM bug in the Macintosh® IIci and Macintosh IIfx Memory Manager? Word has it that Apple wrote an INIT (MMInit) to fix this problem. Because we’re using our application on both the Macintosh IIci and the IIfx, and the application uses many handles, this fix would be appreciated.
Under System 6.0.x, Apple had identified a minor problem with the Memory Manager in the Macintosh IIfx, IIci, IIsi, and LC. This problem resulted in a performance degradation in an extremely small number of applications and did not cause system crashes. We believe this was an insignificant problem that affected few applications and very few customers. The problem was not new and was not caused by the introduction of System Software 6.0.5 or 6.0.7.
Based on developer feedback, customer feedback, and extensive in-house testing, Apple has identified very few affected applications. Because the problem affects only an extremely small number of developers, Apple is working with those developers to fix their applications. The best solution, however, is to upgrade to System 7.0, as it includes an enhancement to the Memory Manager to address this issue.
During extensive testing and research, Apple investigated a variety of solutions to enhance the Memory Manager performance. One area researched was a software solution called the Memory Manager INIT (a software “patch”), or MMInit as it’s most often called. Through testing we discovered that this patch did not enhance Memory Manager performance and introduced risks such as decreased performance in some mainstream applications.
An unofficial version of the Memory Manager INIT has surfaced. This INIT should not be used, because it has been modified from Apple’s experimental version and could cause data corruption, data loss, and crashes. Apple strongly urges that you discard the INIT if you have obtained a copy, and not use it. If any version of this INIT is used under System 7.0, it defeats the enhanced Memory Manager and reintroduces the bugs that were present in the System 6.0.x Memory Manager.
You may still wonder if you have been affected by this problem and how to avoid it under 6.0.x. The problem is most severe when allocating pointers in a heap with a rather large number of handles (on the order of tens of thousands). It’s helpful to allocate enough master pointers (via MoreMasters) during initialization. If the Memory Manager has to call MoreMasters later on, not only could it fragment memory, but it could take an exceedingly long time. It’s also helpful not to allocate thousands of handles. Besides requiring lots of master pointers, it takes the Memory Manager a long time to crunch through them during heap compaction.
Operating System: Memory Management: When to use SetCurrentA5
During a Macintosh® application’s life, does the value of A5 change? Why does SetCurrentA5 have to set A5 to CurrentA5? Aren’t A5 and CurrentA5 the same while an application is executing non–interrupt-time code?
A5 is not necessarily always equal to CurrentA5. Because the Macintosh operating system and Toolbox don’t need to access your application’s jump table or global variables (which A5 points to), they often use A5 for other purposes, except for the parts of the Toolbox that need to perform graphics operations and use the QuickDraw globals defined by your application.
Because the operating system or Toolbox can change A5, you must make sure it’s set correctly if the operating system or Toolbox ever calls your code in the form of a callback. For example, if you make an asynchronous File Manager call, your I/O completion routine must call SetCurrentA5 for your I/O completion routine. Other places where you may want to call SetCurrentA5 are in trap patches, your GrowZoneProc, custom MDEFs, WDEFs, or CDEFs, or control action procedures.
Please note that even SetCurrentA5 is not sufficient when writing code that’s executed at interrupt time, such as VBL and Time Manager tasks. When an interrupt occurs that your application wants to handle, there is no guarantee that the low-memory global CurrentA5 belongs to your application. The interrupt could occur while some other application is running under MultiFinder®. In this case, you should use other approaches to setting A5. Please see Technical Note #180, MultiFinder Miscellanea, for further information.
Operating System: Memory Management: Macintosh heap debugging tools
Do you know of any debugging tools for Macintosh® II heap problems besides TMON, which can scramble and check the heap every now and then, and the “Mr. Bus Error” INIT?
For figuring out problems with the stray writes/reads outside your application heap, you should check out Jasik’s debugger. I’m not as familiar with it as I would like, but I’ve heard that it allows you to keep an eye on those types of memory accesses. For deallocation and no heap space, try DTS’s “Leaks” dcmd, available on AppleLink®.
Operating System: Memory Management: Why Macintosh IIsi uses more system heap than Macintosh Plus
Why does the Macintosh® IIsi use so much more system heap than the Macintosh Plus? Is there any way to reduce system heap usage on the IIsi?
No, the reason the Macintosh IIsi has more system heap than the Macintosh Plus is that the IIsi is a color machine and the Plus is not. Color includes a lot of patches and a considerable increased requirement of memory, hence the need for the larger heap size in the IIsi.
Operating System: Memory Management: No maximum size that the Macintosh stack can be grown
Is there a maximum size that the Macintosh® stack can be grown?
No.
Operating System: Memory Management: How can I change the size of my Macintosh application’s stack?
How can I change the size of my Macintosh® application’s stack?
A default stack size is created by the system for each application. If you want to use the default stack size, just call MaxApplZone very early in the application’s startup process. The default size for the stack on a Macintosh Plus and SE is 8K, but it’s 24K for systems supporting Color QuickDraw™. The default may change again with future systems, so it’s best not to make any assumptions. Add to the current stack size and don’t assume a fixed size.
If you are interested in finding the top of the stack, there is a low memory global CurStackBase. It is advisable not to read low memory, but this is one of the safer globals. The following code is from MacApp which increases the stack size. Follow this with MaxApplZone:
PROCEDURE SetStackSpace(numBytes: LONGINT);
VAR
newLimit: LONGINT;
BEGIN
newLimit := Ord(GetCurStackBase) - numBytes;
IF Ord(GetApplLimit) > newLimit THEN
SetApplLimit(Ptr(newLimit));
END;
Alternatively, simply use the following line of code. Shrinking the application’s heap size allows the stack to increase by that same amount. Follow this with MaxApplZone.
SetApplLimit(Ptr(Ord4(GetApplLimit) - kAdditionalStackRequirements));
MaxApplZone; {this code is here to provide context}
InitGraf(@thePort);
Operating System: Memory Management: Increasing Macintosh stack size if system error 28 occurs
Why does my application crash with a system error 28 (“stack into heap”) on a Macintosh® SE or Plus but not on any Mac® II?
The default stack size on 68020/68030-based Macintosh models is 32K to accommodate Color QuickDraw™, while the default stack size in 68000-based Macintosh models is 8K. If you are experiencing stack overflows, increase the size of your stack. It is best to add a fixed amount to the stack without aiming for a specific size or checking the machine type so that, if Apple needs to expand the stack size in the future, you will be less likely to break again.
Operating System: Memory Management: How can I prevent Macintosh low memory conditions?
How can I prevent Macintosh® low memory conditions?
Once memory is low, it’s too late, so before calling NewPtr, NewHandle or other Toolbox routines that allocate memory, check for the available amount of memory. In other words, preflight for the dangerous situation. Use PurgeSpace to help determine if you’re running low on memory. If the heap ever runs below 40K, consider it dangerous. Write a small function such as the following that does such a test for a given amount and returns a Boolean:
FUNCTION IsMemoryAvailable(request): BOOLEAN;
CONST
kMinSpace = 40 * 1024; {40K is a safe amount}
VAR
total, contig: LONGINT;
BEGIN
PurgeSpace(total, contig);
IsMemoryAvailable:= (request < contig)
AND ((request + kMinSpace) < total)
END;
Then, before allocating memory, follow this example of creating a new dialog:
IF IsMemoryAvailable(SizeOf(dialogRecord)) THEN BEGIN
dialog:= NewPtr(SizeOf(dialogRecord));
IF dialog <> NIL THEN
GetNewDialog(id, dialog, behind)
ELSE
{out of memory, call MemError for more info};
END ELSE
{out of memory, report low memory condition to user};
Preflighting low memory is dependent on the situation at the time. In the previous example of creating a new dialog, you might include the Dialog Manager CouldDialog before calling IsMemoryAvailable. This will load the 'DLOG' and 'DITL' into memory and then test if there is enough additional memory to create the dialog. This could still fail if the dialog is using a non-system font or other custom feature. Also, consider that the above test doesn’t include the new regions that are necessary for the window. That’s why there’s a safety margin of 40K. Another useful part of memory management is a GrowZone procedure that can release a reserved block. Once the GrowZone is called, consider it an emergency and do whatever you can to regain the reserve block. The IsMemoryAvailable routine should include a test for this if you include a GrowZone reserve block.
Operating System: OS Utilities: Macintosh GetTrapAddress and StripAddress
What was the earliest Macintosh operating system that had _StripAddress? Do I still have to call GetTrapAddress to find out if a trap exists by comparing its address with the Unimplemented trap for a general utility trap like StripAddress?
StripAddress is available in System 4.1 and later for Macintosh Plus or later models. You should not have any problem on machines running 4.1 or later. StripAddress is always implemented in these machines, even if all that needs to be done is mask the high byte of the address.
You should still call Gestalt once on any machine at the beginning of your application to determine if any/all assumptions your program makes about the hardware it is running on is valid. This is to protect YOU from NOT working on a future machine that has a different mix of features than currently available.
Example case #1: Several programs broke on the Macintosh Portable because they assumed that any machine later than the Macintosh II would have Color QuickDraw. A simple HasCQD with a “You can’t run without Color” alert.would have eliminated user crashes and product revisions.
Example case #2: A spreadsheet program would not use the FPU on a new machine it did not previously know of, even though the FPU was present and WOULD have worked.
Operating System: OS Utilities: Textual Macintosh system error messages
It would be nice if Apple provided a Macintosh system resource with text for all defined error codes. Are there any plans to provide this?
A toolbox call or utility providing up-to-date error messages would be nice, but such a beast does not exist currently. The closest thing available is the MPW ErrMgr (Error File Manager Routines Interface File), which can be used to display errors for Tools written under MPW. This, of course, uses utilities included in the MPW application, so it isn’t of any use to standalone applications.
This feature hasn’t been provided because the error numbers and associated text are meant for a technical audience. Even if they were worded nicely, most of the errors (like Bus Error) wouldn’t mean anything to end users, and might be intimidating or confusing. Since each application has a different audience,it is better left to you to tailor error messages to make sense to your application’s audience.
We realize that it’s inconvenient to create 'STR#' resources from the Errors.h file (DTS does the same thing), but this is probably your best bet. By the way, Appendix A of Inside Macintosh Volume VI explains the error messages in more detail than the Errors.h file.
Operating System: OS Utilities: Disk First Aid error message explained
What does the Macintosh® Disk First Aid message “Unable to verify status of disk” mean?
Disk First Aid does a variety of diagnostics on your disk’s internal HFS structures, repairing problems for which it has complete information—primarily internal consistancy problems, where one set of information has gotten out of step with another, redundant set. When it has found a problem that it cannot repair, it tells you so. For a long time the relatively uninformative message “Unable to verify status of disk” was used. In the most recent version, released with System 7.0, the message “The disk is damaged. Disk First Aid is unable to repair this disk” is displayed. When you see this message, it means something is fairly wrong with the directory structures on your disk. You may not yet have seen any problems with the disk, but it’s likely that you will see them before long. Now would be a good time to back up all your files, reformat your drive, and restore your data from the backup.
Operating System: OS Utilities: Disk First Aid if unable to empty trash
We are unable to empty trash of a Macintosh® folder that appears to be empty. The message “The item could not be deleted because it contains items that are in use” is displayed.
Disk First Aid should solve your problem.
Hierarchical File System (HFS) keeps a count of the number of items in a directory, and probably your folder’s count didn’t get updated when your machine crashed at some point. Therefore, though the Finder can’t see anything in the folder (because it used indexed calls, and like a good application, doesn’t meander through HFS’s private structures), HFS still thinks there’s something there.
If you’ve run System 7 with that volume, be sure to use the latest Disk First Aid that came with System 7, because it knows about the changes in HFS’s data structures that were made for System 7.
Operating System: Process Management: Macintosh background DA alerts
How can I use the Notification Manager to alert the user to bring my DA to the front and then display an alert?
Basically, if your DA is in the foreground and you finish your task, you can just use Alert() to notify the user. If your DA is in the background when it finishes, post a notification with NMInstall that notifies the user by sound, icon, and mark in the process menu (but not an alert) that something is up in your desk accessory. When they switch to your DA, you then display your alert.
The following code is for a DA written in Think C that notifies the user as described above. Portions of the code are borrowed from the Think C example “Hex Dump DA.” Basically, this code keeps track of whether the DA is in the foreground or background by setting the global variable gInBackground at every activate and deactivate event. If there is a notification pending and an activate event is received, the routine MyResponse is called to remove the notification and display the appropriate alert.
Note that for MPW you’ll have to store your globals elsewhere, as MPW doesn’t provide the Think C A4 feature. You’ll have to modify the code to work with your function to get the proper resource IDs.
void PostNotify(StringPtr theStr)
{
extern Boolean gInBackground; /* true=in background */
extern NMRec *gNotify; /* global var pointing to notif.
rec 0=none */
Handle notIcon;
Ptr txtPtr;
/* blast away any other pending notification */
if (gNotify) {
DisposPtr((Ptr) gNotify->nmRefCon);
NMRemove(gNotify);
gNotify = nil;
}
/* see if we should notify or use alert */
if (gInBackground) {
/* allocate memory for notification */
txtPtr = NewPtr(sizeof(Str255));
if (MemError()!=noErr)
return;
gNotify = (NMRec *)NewPtr(sizeof(NMRec));
if (MemError()!=noErr)
return;
/* copy notif. string to dynamically allocated block */
BlockMove(theStr,txtPtr,256);
/* fill out notif. record */
notIcon = GetResource('SICN',OwnedResourceID(NOTIF_ICON));
gNotify->nmStr = nil;
gNotify->qType = nmType;
gNotify->nmMark = 1;
gNotify->nmIcon = notIcon;
gNotify->nmSound = (Handle)-1;
gNotify->nmResp = nil;
gNotify->nmRefCon = (long)txtPtr;
NMInstall(gNotify);
}
else {
ParamText(theStr,"\p","\p","\p");
StopAlert(OwnedResourceID(ALERT_DIALOG),nil);
}
}
/* response procedure-- called on activateEvt */
pascal void MyResponse(QElemPtr nmReqPtr)
{
StringPtr errTxt;
errTxt = (StringPtr) ((NMRec *)nmReqPtr)->nmRefCon;
NMRemove((NMRec *)nmReqPtr);
ParamText(errTxt,"\p","\p","\p");
StopAlert(OwnedResourceID(ALERT_DIALOG),nil);
DisposPtr(errTxt);
}
/*---------------------------------------------------------*/
here's the piece of the code that handles activate events
/*---------------------------------------------------------*/
doActivate(activate)
Boolean activate;
{
extern Boolean gInBackground;
extern NMRec *gNotify;
Rect r;
GrafPtr savePort;
GetPort(&savePort);
SetPort(wp);
r = wp->portRect;
r.top = r.bottom - 16;
r.left = r.left - 16;
InvalRect(&r);
gInBackground = !activate;
if ( activate ) {
if (gNotify) {
MyResponse((QElemPtr)gNotify);
gNotify = nil;
}
}
SetPort(savePort);
}
Operating System: Process Management: Launching a Macintosh application
Under MultiFinder® or Macintosh® System 7, is there a way to set a flag to terminate the current application before launching a different application? Under standard Finder™, the launcher quits before the launchee starts.However, under MultiFinder or System 7, they both must stay in memory for a brief time until control returns to the launcher and it hits the ExitToShell. Because most of our programs are set to use 1 MB, we need 2 MB of memory available for a short time.
Two distinct cases are involved here: the System 7.0 case and the pre-System 7.0 case.
In System 7.0 there is a new way to launch applications. The function is called (appropriately enough) LaunchApplication. The function and its new extended parameter block are documented in the Process Management chapter of Inside Macintosh Volume VI.
You can determine whether your system software has the new Launch Control capabilities by using Gestalt:
OSErr myOSErr;
long response;
myOSErr = Gestalt(gestaltOSAttr, &response);
if (noErr != myOSErr) /* If an OSErr occurs we must be pre-System 7.0 */
/* Handle pre-System 7.0 case */
if BTst(response, gestaltLaunchFullFileSpec)
/* Handle System 7.0 case */
else
/* Handle pre-System 7.0 case */
The above code assumes that you are developing with interfaces and libraries based on MPW® 3.2, as those interfaces and libraries support Gestalt even on system software versions that don’t implement the Gestalt trap.
The portion of the Process Management chapter of Inside Macintosh Volume VI that will interest you is the description of the launchControlFlags field of the parameter block. Here’s what the Process Management chapter has to say:
“When you use the LaunchApplication function, you specify the launch options in the launchControlFlags field of the launch parameter block. These are the constants you can specify in the launchControlFlags field.
CONST
launchContinue = $4000;
launchNoFileFlags = $0800;
launchUseMinimum = $0400;
launchDontSwitch = $0200;
launchAllow24Bit = $0100;
launchInhibitDaemon = $0080;
Set the launchContinue flag if you want your application to continue after the specified application is launched. If you do not set this flag, LaunchApplication terminates your application after launching the specified application, even if the launch fails.”
In other words, you have to request that your launching application continue if you use LaunchApplication—the default is to do precisely what you want. Note that clearing the launchContinue flag is effectively the same as following the LaunchApplication call with an ExitToShell call. Because applications should not terminate within an Apple event handler, they must set the launchContinue flag when calling LaunchApplication from within an Apple event handler.
This leaves the pre-System 7.0 case. System 4.1 and later allows for the use of an extended Launch parameter block also, but it is somewhat different from that of System 7.0. The complete details can be found in Macintosh Technical Note #126, “Sub(Launching) From a High-Level Language.” You’ll need to use the extended version of the parameter block and specify a launch rather than a sublaunch.
Unfortunately, the launching application does in fact _not_ quit until the launchee has come up. It sounds like you will have to launch a tiny utility application that then turns around and launches your real target.
This doesn’t really change what I’ve told you above, but it does potentially color the design of your utility if you intend to open documents in the target. For the pre-System 7.0 case, the utility can simply leave the AppParmHandle alone and launch the real target, which will then deal with the AppParmHandle. In the System 7.0 case, your utility will need an 'odoc' Apple® event handler. In that handler, you will have to coerce the event to one of type appparms and pass that along to the real target when you launch it.
A good example of how all of this works in the System 7.0 case can be found in the ProcDoggie 1.0a6 sample code, which is in the Sample Code folder on the System 7.0 February 1991 beta CD-ROM. Among other things, it demonstrates how to launch, and how to handle or send the required AppleEvents ('oapp' or 'odoc').
Operating System: Process Management: System 7 and MultiFinder’s “puppet strings”
When my application is running, it relies on the MultiFinder’s “puppet strings” (which choose Open from the application’s File menu and suppress the SFGetFile dialog) to open a document that was double-clicked in the Finder. Why doesn’t this work under System 7? The high-level event-aware bit in my 'SIZE' resource is clear.
System 7 will not pull puppet strings for an applications that makes use of the System 7 Standard File routines, such as StandardGetFile and CustomGetFile, nor will it pull them if the application’s high-level event- aware bit is set.
If you update an older application to take advantage of any System 7 features, be sure to also add support for the 'odoc' and other required Apple events. Sample code showing how to support the required Apple events is available on the System 7 Golden Master CD.
Operating System: Process Management: Notification Manager and color flashing icons
How can I get a color icon to flash in my application menu? The Notification Manager documentation says I can use an 'SICN' to flash an icon, but I can get only a black-and-white flashing icon.
At this time, you can’t have the Notification Manager flash a color icon. The best you can do is to have a black-and-white version of your small color icon flash. Sorry about this. That’s all it can do right now.
Operating System: Process Management: System 6 versus System 7 Desktop Manager
If the Desktop Manager (the version that comes with AppleShare) is installed under System 6.0.x, does it have equivalent functionality to that of System 7.0?
The Desktop Manager in System 7 is completely-backward compatible with that of System 6.0.x. The System 7 version has been highly optimized, and is more robust than the original.
Operating System: Process Management: Notification Manager’s nmIcon field & icon resources
Notification Manager’s nmIcon field & icon resources
Inside Macintosh Volume VI, page 24-7 states that a notification record’s nmIcon field should contain “a handle to a small icon or to an icon family,” but for the initial release of System 7, the Notification Manager recognizes only the 'SICN'.
The format for icon family resources has not yet been documented; it is not the same as that of existing resources such as 'ICN#' or 'ics#'. The only way currently to post a notification with an icon is to use the black & white 'SICN'.
Operating System: Process Management: Icon family documentation not available yet
According to page 24-7 of Inside Macintosh® Volume VI, the nmIcon field “contains a handle to a small icon or to an icon family containing a small color icon…” I give up, what is a handle to an icon “family”?
An icon family is just what its name implies: It’s a data structure containing icons of different sizes and colors. As you might have noticed, parts of the system software take advantage of this feature to draw color notification icons, such as the Alarm Clock, in the menu bar.
Unfortunately, Apple does not yet provide documentation on the format of these “icon families,” or how to get or use them, and the interfaces for accessing the calls are as of yet incomplete. Until the documentation is released, it is not possible for developers to take advantage of these routines to use color icons with the Notification Manager.
Operating System: Process Management: Code for placing a Macintosh file in proper place on the desktop
If I move a Macintosh® file from one folder to another and clear the “inited” bit, will the Finder™ then place that file in the proper place? Is that the best way to handle files that I move?
Here’s a little program that does just that. It takes a file (from SFGetFile) and moves it to the desktop by PBCatMove and then clears the inited bit (PBHGet/SetFInfo).
void InitStuff()
{
InitGraf(&thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
FlushEvents(everyEvent,0);
InitCursor();
}
OSErr MakeFile(HFileParam *pBlock)
{
SFReply reply;
Point where = {100,100};
OSErr err;
StringPtr fName;
WDPBRec wdRec;
Str255 tmpName;
SFGetFile ( where, "\p", nil, -1, (OSType *)"????", nil, &reply );
if (!reply.good)
return -1;
wdRec.ioNamePtr = tmpName;
wdRec.ioWDIndex = 0;
wdRec.ioVRefNum = reply.vRefNum;
wdRec.ioWDProcID = nil;
wdRec.ioWDVRefNum = 0;
err = PBGetWDInfo(&wdRec,false);
if (err!=noErr)
return err;
fName = (StringPtr)NewPtr(256);
BlockMove(reply.fName,fName,256);
pBlock->ioNamePtr = fName;
pBlock->ioVRefNum = wdRec.ioWDVRefNum;
pBlock->ioDirID = wdRec.ioWDDirID;
pBlock->ioFVersNum = 0;
/* err = PBHCreate(pBlock,false);
if (err!=noErr)*/
return err;
}
OSErr MoveFile(HFileParam *pBlock)
{
CMovePBRec pMove;
OSErr err;
Str255 newStr;
BlockMove("\pDesktop Folder",(Ptr)newStr,15);
pMove.ioNamePtr = pBlock->ioNamePtr;
pMove.ioVRefNum = pBlock->ioVRefNum;
pMove.ioNewName = newStr;
pMove.ioNewDirID = fsRtDirID;
pMove.ioDirID = pBlock->ioDirID;
err = PBCatMove(&pMove,false);
return err;
}
OSErr ClearInit(HFileParam *pBlock)
{
OSErr err;
long dirID;
dirID = pBlock->ioDirID;
pBlock->ioFDirIndex = 0;
err = PBHGetFInfo(pBlock,false);
if (err!=noErr)
return -1;
pBlock->ioDirID = dirID;
pBlock->ioFlFndrInfo.fdFlags &= ~(0x0100); /* mask off inited
bit */
err = PBHSetFInfo(pBlock,false);
return err;
}
void main()
{
HFileParam pBlock;
OSErr err;
InitStuff();
err = MakeFile(&pBlock);
if (err==noErr)
err = ClearInit(&pBlock);
if (err==noErr)
err = MoveFile(&pBlock);
if (err!=noErr)
SysBeep(1);
}
Operating System: Process Management: Use Mac® Finder for application file & folder icon placement
When my Macintosh® program creates a file in the Desktop folder, how can I get it to appear where the Finder™ would place it on the desktop?
Don’t set the “INITed” bit when you create your file or folder, and the Finder will take care of icon placement for you.
You should not attempt to place the icon behind the Finder’s back, although the icons’ positions within the folder relate to where they appear on the desktop. You will have a hard (or impossible) time with icon placement, since you don't have access to the private Finder data structure where the positions of the volume icons are stored. You are better off letting the Finder handle placement. Making assumptions about the way the Finder works internally is a bad idea.
Operating System: Process Management: Background applications and alerts
My application, running in the background, detects an error condition and puts up an alert; but only part of the alert is visible (other windows cover most of it). When I switch back to my application, the full alert becomes visible but the “OK” is not highlighted and often the icon is not shown either. Is there something I can do to prevent this?
Applications running in the background should not be putting up alerts. In addition to the problems and complications you have already noted, under System 7.0 the user has the ability to hide a background application’s window set and your alert would not be seen at the time you expect it to.
There is, however, a mechanism in place that your background application can and should use: the Notification Manager. Documented in Inside Macintosh Volume VI, this manager allows a background process to notify the user that there is a alert, message, or situation pending in the background that needs to be taken care of. The user can then bring your application forward and you can present your alert as the foreground application.
Operating System: Process Management: Macintosh Notification Manager and moving memory
Is a Macintosh® Notification Manager’s response procedure actually a completion routine that can be called at interrupt time? Can a Notification Manager response procedure move memory without danger?
So-called “response procedures” aren’t called at interrupt time, so they can, in fact, move memory. Here are some additional notes regarding the Notification Manager:
1) Response procedures can move memory.
2) The notification is triggered from the SystemTask procedure, so if the application does not give time for systemtasks (a tight loop for instance), then the notification is never triggered.
3) The NMRec does have its own drawing A5 world, so applications could draw from the response procedure. However, an application should have its own A5 world for any possible graphics use.
Many of these issues are not documented because Apple doesn’t want developers to, for example, write dialog boxes that suddenly appear on the screen. Inside Macintosh ,Volume VI, pages 24-29, describes the response procedures—that they should be used mainly for deleting notification requests for freeing memory. Note, however, that it’s the Notification Manager that will free the memory if you pass the nmResp a value of -1, but you could free some of your own memory blocks with the response procedure.
Operating System: ProDOS 8: ProDOS 8 KVERSION field doesn’t map to version number
The KVERSION (kernel version) variable in ProDOS® 8 version 1.8 is $08. If we eventually see ProDOS 8 2.0, will the version number be stored as $0A, $20 or what?
The KVERSION field has nothing whatsoever to do with the user-visible version number of ProDOS, as this chart indicates:
Screen KVERSION
------ --------
1.0 $00
1.0.1 $00
1.0.2 $00
1.1 $01
1.1.1 $01
1.2 $02
1.3 $03
1.4 $04
1.5 $05
1.6 $06
1.7 $07
1.8 $08
1.9 $08
Unfortunately, ProDOS 8 contains no way to get the user-displayed version number. The KVERSION field is only for your reference in knowing what MLI calls and features you can expect.
Operating System: ProDOS 8: Apple II BASIC.SYSTEM extended file I/O error message
Why do I get a “FILE TYPE MISMATCH” error message from BASIC.SYSTEM when I try to BLOAD certain files created by GS/OS®?
GS/OS can create extended (forked) files, which cannot be read by ProDOS® 8. If you try to read an extended file with ProDOS 8, you’ll get a Bad Storage Type ($4B) error. BASIC.SYSTEM maps the Bad Storage Type error it gets from ProDOS 8 to “FILE TYPE MISMATCH.”
Operating System: Standard File Toolbox: Tabbing between SFPPutFile custom dialog text fields
How can I get the tab key to tab between text fields in my SFPPutFile custom dialog instead of switching drives?
Here is an event filter that beeps whenever the tab key is pressed (under System 6):
pascal Boolean MyDlgFilter(DialogPtr theDialog,EventRecord *theEvent,short
*itemHit)
{
WindowPtr updateWindow;
char theChar;
switch (theEvent->what) {
case keyDown:
case autoKey:
theChar = theEvent->message & charCodeMask;
switch (theChar) {
case 0x0d: /* CR */
case 0x03: /* enter */
*itemHit = OK;
return true;
case 0x1b: /* ESC */
*itemHit = Cancel;
return true;
case '\t':
SysBeep(1); // <----- do your "tabbing"
here
*itemHit = 0; // <----- this is what you
need to add
return true;
}
break;
}
return false;
}
Within dialog event filters, when the filter decides to process the event, the filter not only must return true, but must also return the item number acted on by the filter. Under System 7, tab is handled by the system automatically and is not controllable from dialog event filters.
Operating System: Standard File Toolbox: File handling within SFPGetFile & SFPPutFile DlgHook functions
How can I obtain the volume reference information in my DlgHook function for a file selected by the user before SFPPutFile or SFPGetFile has completed the reply record?
On exit, SFPGetFile and SFPPutFile generate a working directory reference number in the vRefNum field of the reply record. This is not available to you from within the operation of a DlgHook function. WDRefNums are provided to allow compatibility with older, pre-HFS functions that took vRefNum values of integer size with the older flat file system.
We suggest that, unless you plan to support the flat file system of 64K ROM Macintosh systems, you move your file system interfaces to the HFS interfaces documented in the File Manager sections of Inside Macintosh Volumes IV and V (or to the equivalent high-level calls as documented in Macintosh Technical Note #218, “New High-Level File Manager Calls”). If you’re using the HFS calls, low-memory globals SFSaveDisk and CurDirStore contain, respectively, the negative of the “real” volume reference number for the current volume and the HFS ID of the directory that Standard File is displaying. You then have all the information you need to create, open, rename, or delete files from within the SFPGetFile and SFPPutFile DlgHook functions. If a user is accessing an MFS volume on an HFS system, these calls are designed tohandle file access transparently.
Moving your file system interfaces to the HFS-level conventions has a side benefit of being closer to the System 7 file system specifications. If you look at the new high-level file system calls in Inside Macintosh Volume VI, you’ll recognize much of the HFS information embedded in the new data structures.
If your file system interfaces depend on MFS-style vRefNums, or WDRefNums in the HFS nomenclature, you can use the HFS functions PBOpenWD, PBCloseWD, and PBGetWDInfo to open, close, and obtain volume reference numbers and directory IDs. This is particularly important if, for instance, you’re using the THINK C ANSI file I/O functions, which rely on SetVol to operate correctly.
Complete information on the HFS-level calls that will be most useful in Standard File customization is contained in the File Manager chapters of Inside Macintosh Volumes IV and V, and in Macintosh Technical Notes #66, 77, 102, 140, 179, 190, and 218. For C users, Macintosh Technical Note #246 summarizes a list of the difficulties with mixing C file I/O with Macintosh file I/O. Macintosh Technical Notes #47 and 80 discuss a few points of Standard File customization from the point of view of HFS.
Operating System: Standard File Toolbox: Filtering out invisible folders from a Standard File dialog list
I want to display only visible files and folders in a Standard File dialog, but I can’t find a way to filter out invisible folders—specifically the 000Move&Rename folder. The FileFilter routine filters only files, not folders. If I put in a nonzero TypeList, invisible folders seem to be removed, but I want to open all types of files, just not invisible files or folders. Any suggestions?
This is, in fact, impossible under System 6 using general methods. The problem is that passing -1 as numTypes means not only to display all items, but to display invisible items. A file filter can be used to remove the invisible files but cannot affect invisible folders. The only current way to do this is to use CustomGetFile under System 7, as described in the Standard File Package chapter of Inside Macintosh Volume VI. This provides a filter that allows you to filter both files and folders. This will give you the right functionality, but will work only under System 7. We recommend that you use this method under System 7, and a more standard SFGetFile when running under earlier systems.
Operating System: Standard File Toolbox: Custom Standard File dialog edit fields under System 7
How do I change the active edit field inside a custom Standard File dialog under System 7? In a related problem I am finding that the selection range for all edit fields in the dialog equals the number of characters in the file name field when tabbing around.
The Standard File Package (SFP) routines don’t behave exactly the same as they did under System 6. Therefore, doing something like trying to change the active item number doesn’t work under System 7’s version of the SFP routines. The problem is that System 7 Standard File has a whole set of interfaces dedicated to the active item list and which item is currently active, whereas System 6 SF routines just use the dialog data to store this information. The solution to the problem, then, is to use CustomGetFile to accomplish the same thing if you are running under System 7. I’ve included a sample program which uses the new routine to change the focus and check the bounds of several editText items.
Your second problem is brought on by a bug in Standard File. The workaround is to install an activate procedure for Standard File (it’s a parameter to the CustomGetFile call) which calls SelIText on the appropriate field to select the entire range. The included sample also does this.
/* CustomGetFile example
Steve Falkenburg -- MacDTS
This sample uses CustomGetFile to add two edit text fields
to the standard get file box, and checks the values the user
enters into those fields. If the values are incorrect, the
user is alerted to change them, and the focus of the dialog
is changed to the proper field.
The standard file bug causing selection ranges to be calculated
improperly is also fixed in this sample by calling SelIText in
the activate procedure for edit text items.
*/
/* prototypes */
void InitStuff(void);
void CustomGet(void);
pascal void MyActProc(DialogPtr theDlg,short item,
Boolean activating, Ptr data);
pascal short DlgHook(short item,DialogPtr theDlg,Ptr userData);
Boolean CheckField(DialogPtr theDlg,short item);
/* constants */
#define kTextField1 10
#define kTextField2 11
#define kSFDlg 128
#define kAlertDlg 129
void main(void)
{
InitStuff();
CustomGet();
}
/* initialize managers */
void InitStuff(void)
{
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
FlushEvents(everyEvent,0);
InitCursor();
}
/* do getfile */
void CustomGet(void)
{
Point where = {-1,-1};
SFReply reply;
DialogPtr theDialog;
short item;
StandardFileReply sfReply;
short activeList[5];
/* set-up active items list */
activeList[0] = 3;
activeList[1] = 7;
activeList[2] = 10;
activeList[3] = 11;
CustomGetFile(nil,-1,nil,&sfReply,kSFDlg,where,DlgHook,
nil,activeList,MyActProc,nil);
}
/* activate procedure- this procedure handles the activate/deactivate of
textedit items and corrects the selection bug in standard file which
normally causes the selStart and selEnd fields of the texthandle to be
incorrect
*/
pascal void MyActProc(DialogPtr theDlg,short item,Boolean activating,Ptr data)
{
short iType;
Handle iHndl;
Rect iRect;
TEHandle textH;
GetDItem(theDlg,item,&iType,&iHndl,&iRect);
if (iType != editText)
return;
if (activating) {
SelIText(theDlg,item,0,32000);
return;
}
}
/* this dialog hook checks the contents of the additional edit fields
when the user selects a file. The focus of the dialog is changed if one
of the fields is out of range.
*/
pascal short DlgHook(short item,DialogPtr theDlg,Ptr userData)
{
if (item==ok) {
if (!CheckField(theDlg,kTextField1))
item = kTextField1 + sfHookSetActiveOffset;
else if (!CheckField(theDlg,kTextField2))
item = kTextField2 + sfHookSetActiveOffset;
}
return item;
}
/* this procedure checks the range of a given edittext item to make sure it
contains a number from 0 to 256. If not, it alerts the user that the
field must be re-entered.
*/
Boolean CheckField(DialogPtr theDlg,short item)
{
short iType;
Handle iHndl;
Rect iRect;
Str255 iText;
long num;
GetDItem(theDlg,item,&iType,&iHndl,&iRect);
GetIText(iHndl,iText);
StringToNum(iText,&num);
if (num<0 || num>256 || iText[0]==0) {
StopAlert(kAlertDlg,nil);
return false;
}
else
return true;
}
The resource file follows:
/*
Dialog and Alert templates for use with CustomGetFile example.
Steve Falkenburg -- MacDTS
*/
#include "types.r"
/* CustomGetFile dialog */
resource 'DLOG' (128, purgeable) {
{0, 0, 206, 344},
dBoxProc,
invisible,
noGoAway,
0x0,
128,
""
};
resource 'DITL' (128, purgeable) {
{ /* array DITLarray: 11 elements */
/* [1] */
{135, 252, 155, 332}, Button { enabled, "Open" },
/* [2] */
{104, 252, 124, 332}, Button { enabled, "Cancel" },
/* [3] */
{0, 0, 0, 0}, HelpItem { disabled,
HMScanhdlg {
-6042
}
},
/* [4] */
{8, 235, 24, 337}, UserItem { enabled },
/* [5] */
{32, 252, 52, 332}, Button { enabled, "Eject" },
/* [6] */
{60, 252, 80, 332}, Button { enabled, "Desktop" },
/* [7] */
{29, 12, 159, 230}, UserItem { enabled },
/* [8] */
{6, 12, 25, 230}, UserItem { enabled },
/* [9] */
{91, 251, 92, 333}, Picture { disabled, 11 },
/* [10] */
{175, 16, 191, 91}, EditText { enabled, "" },
/* [11] */
{175, 106, 191, 181}, EditText { enabled, "" }
}
};
/* input check value alert */
resource 'ALRT' (129) {
{110, 130, 208, 414},
129,
{ /* array: 4 elements */
/* [1] */
OK, visible, sound1,
/* [2] */
OK, visible, sound1,
/* [3] */
OK, visible, sound1,
/* [4] */
OK, visible, sound1
}
};
resource 'DITL' (129) {
{ /* array DITLarray: 2 elements */
/* [1] */
{68, 218, 88, 276},Button {enabled,"OK"},
/* [2] */
{10, 61, 62, 278},
StaticText { disabled,
"Your field entry is out of range. Pleas"
"e enter a number between 0 and 256."
}
}
};
Operating System: Standard File Toolbox: Displaying invisible files under Systems 6 & 7 without typeList
Under System 7 my filter proc for displaying invisible data files no longer works. How can I use Standard File to display the names of invisible files of a specific type under System 7?
System 7.0 can show invisible files in the standard getfile dialog box; however, not all System 6.0x Standard File package calls are handled the same in 7.0.
When using invisible files under 7.0, type filtering should be performed within a filter proc and not with the typeList field of the SFGetFile() call. System 7.0 no longer allows a typeList for detecting invisible files. The actual check for invisible files of a particular type(s) should be done within the file filter procedure.
The SFGetFile() call below displays only folders and invisible 'TEXT' files in the standard getfile dialog box. With the numTypes parameter set to -1, all types of files will be passed to the filter proc.
SFGetFile( where, "", myFilterProc, -1, typeList, nil, &reply );
In this example, the filter proc’s return value depends on the file’s type and Finder flags.
pascal Boolean myFilterProc( fp )
FileParam *fp;
{
if ((fp->ioFlFndrInfo.fdFlags & fInvisible) &&
(fp->ioFlFndrInfo.fdType == 'TEXT'))
return FALSE;
else
return TRUE;
}
Operating System: Standard File Toolbox: Standard File and nontrashable Macintosh folders
When we use Standard File to get a Macintosh file in a folder, it becomes impossible to throw that folder away and empty the trash without quitting first. Is this because the working directory is still open? It is my understanding that applications shouldn’t close working directories that were opened by Standard File. Is there something I should be doing, or is this just a limitation in the system?
Pre-System 7 Standard File calls (SFGetFile/SFPutFile/etc...) call PBOpenWD to open a working directory to the folder where the selected file resides.
This working directory, along with all others created within any application, are closed by MultiFinder (or the Process Manager under System 7) when the application is quit. Before the application quits, you will not be able to throw away the folder. After quitting, however, the directory is closed and the folder can be trashed.
As described in Macintosh Technical Note #190, this is accomplished in the following way: When Standard File calls PBOpenWD(), the ioWDProcID field is ignored, and MultiFinder replaces its contents with a unique process identifier. When your application quits, MultiFinder indexes through all open working directories with your unique process ID and closes them.
Your understanding is correct that you don’t have to close these Standard File working directories yourself. If, however, you want the user to be able to delete the directory *while* your application is still running, you will have to issue a PBCloseWD() call yourself, as in the following example:
WDPBRec theWD;
Point where = {100,100};
SFGetFile ( where, nil, nil, -1, nil, nil, &reply );
<do file stuff here>
theWD.ioVRefNum = reply.vRefNum;
err = PBCloseWD(&theWD,false);
If you’re running under System 7, you are much better off using the new StandardGetFile() and StandardPutFile() routines. They do not use working directories at all, and instead return FSSpecs to refer to files.
If none of the above helps, your problem may be that you have left a file open in the directory the user is trying to delete. This would cause the same error as the one you described.
Operating System: Standard File Toolbox: How to override System 7.0 Standard File dialog centering
Any way to override the new default screen location (upper-middle) for Standard File calls under System 7.0? My Standard File dialog needs to be somewhere else on the screen.
You can use the CustomGetFile (Inside Macintosh Volume VI, page 26-22) and CustomPutFile (Inside Macintosh VI, page 26-20) to place the related Standard File dialogs in the location you specify as a parameter. This should override the centering feature that System 7.0 uses on the StandardGetFile (Inside Macintosh VI, 26-22) and StandardPutFile (Inside Macintosh VI, 26-20) calls.
Operating System: Standard File Toolbox: Retained Macintosh file reference requirements
How do I retain a persistent reference to a file? What can I store in a configuration file so I can find a specific file again at a later launch?
The Macintosh® has two native file systems: the original (64K ROM) Macintosh File System (MFS) and the Hierarchical File System (HFS) (Macintosh Plus and newer). In an attempt to simplify this discussion, I’ll assume you know the differences between them and base my explanation upon the HFS system as it is the current one.
To retain a reference to a file location that will persist across application launch and restarts, store its file name, volume name and directory ID. With this information, you will be able to obtain the volume reference number (a dynamic value based on mount order, subject to change because the addition of another drive can change the mount order) and then use either the new high-level File Manager calls or the parameter block based calls to operate on these files. If you happen to encounter an MFS volume, the HFS File Manager will do the appropriate thing given that you use the calls correctly.
Only if you are supporting MFS for an old system will you need to call the MFSfunctions for obtaining the correct reference values; MFS was a flat file system.
Standard File’s reply.vRefNum value when used with HFS is actually a working directory reference number, not a fixed reference; therefore it will usually change between launches of the application or across restarts.
Documentation for the File Manager is extensive and spread out because it was updated when the Macintosh Plus was released and has been added to subsequently by Technical Notes. Inside Macintosh, Volume II deals with the MFS File Manager, Inside Macintosh, Volumes IV and V deal with the HFS File Manager through System 6.0.x, and Inside Macintosh, Volume VI (on your System 7.0 CD-ROM) lists the new File Manager services available under System 7.0. The following Technical Notes should prove useful to you:
File Manager:
024 - Available Volumes
066 - Determining Which File System is Active
077 - HFS Ruminations
102 - HFS Elucidations
140 - Why PBHSetVol is Dangerous
157 - Problem with GetVInfo
179 - Setting ioNamePtr in File Manager Calls
190 - Working Directories and MultiFinder
204 - HFS Tidbits
218 - New High-Level File Manager Calls
246 - Mixing HFS and C File I/O
Standard File:
047 - Customizing Standard File
080 - Standard File Tips
Operating System: Start & Shutdown Managers: SetTimeout refers to device specified by SetDefaultStartup
SetTimeout lets you specify the number of seconds the system will wait for theinternal hard disk to respond (Inside Macintosh, oluVolume V, page 356). Is this only for a SCSI device at ID=0 or is this the device specified by the SetDefaultStartup call? Can I assume that SetTimeout and SetDefaultStartup are supported if the machine type returned by SysEnvirons is greater than a Macintosh Plus? Is there a better way to determine if these calls are supported?
SetTimeOut is for the internal device, whose ID must be zero.
Operating System: System Configuration: Checking for specific Macintosh type
Page 3-44 of Inside Macintosh Volume VI warns against inferring the existence of certain hardware based on the gestaltMachineType selector, but there is no selector for the information we need. Our product works only on Macintosh Portable-type machines and there is no absolute way to determine whether our INIT is on a Portable. Should we ignore the warning?
There is no selector for determining the type of machine you are on, so in your case, you’ll have to ignore the warning and just test for specific machines. In the future if Apple comes out with a machine which your product does not know about, then you’ll need to update your INIT to look for the new machine as well.
Operating System: System Configuration: Checking for FPUs during installation
We plan to ship a Floating Processor Unit (FPU) version and a non-FPU version of our product (together), and we’re writing an Apple Installer script to install the correct application. How do we handle future CPUs which may have FPUs without knowing about their future Gestalt selectors?
Instead of testing for the existence of an FPU by checking all gestaltFPUTypes greater than 0, turn the logic around and check that there isn’t an FPU. If a value other than 0 is returned, then install the FPU version of your product.
Operating System: System Configuration: Zapping PRAM in System 7 and other fun System 7 stuff
Zapping PRAM in System 7 and other fun System 7 stuff
Silly and useful stuff in System 7.0:
System 7.0 power keys:
• Option Click on the DeskTop.
Start up an application. Hold down option key and click anywhere
in the desktop. The application will hide itself.
• Hold down Option key, select another application from the application menu using the mouse.
The application will hide itself.
• Command Option esc.
Launch an application. Hold down command option esc keys. A dialog appears.
Of course, the function ExitToShell is called to quit these applications.
ExitToShell is very robust and if there is no other application to drop
into, it will launch the application which is stored in the global
FinderName. The Finder will be stored in the FinderName global.
• Zap PRAM
Hold down Command Shift P R while starting up your machine.
Power up power keys.
• Command Option.
Restart the system. Hold down both command and option keys.
You will be prompted with a dialog box to rebuild the desktop file.
• Shift.
Restart the system. Hold down the shift key.
The extensions will not be loaded.
Map control panel application
• Option - “Click Find Button.”
Open Map Control panel. Hold down option button. Click in the Find button.
The cities will be alphabetically searched.
• Option - “Double Click Map icon”
Hold down option key. Launch Map icon from Control Panels folder.
Fun note: Try to open Fat Bits without closing the Control Panels folder
on the DeskTop.
• Type in “Middle of Nowhere” on English systems
• Open the scrapbook. Copy the Color Map. Open Map control panel.
Paste in the Color Map.
Monitors Control Panel
• Click on 7.0 in upper right hand corner of the window.
• Click on 7.0 and hit option key about 12 times in a row.
About the Macintosh...
• Hold down the option button and choose about the Finder from the Apple menu.
Miscellanea:
• You can also have a nifty little Keyboards menu to switch between keyboard
layouts if you use more than one. You just set the “Always show icon” bit on
in the 'itlc' resource in the System on. I use this to put that little
American flag on my Menu bar. Changing a system resource is risky, so be
careful while setting the bit!
• Hold down option and switch application from the application menu item.
The front most window will hide.
• Cmd-Y in the Finder unmounts the disk.
• Labels. Blank out all label names and reboot to see the authors’ names as
labels in the menu.
• Color. Click on the “sample text” item to see authors’ names
Operating System: System Configuration: Checking for sRsrcInfo
Is there a way from Pascal to check availability of traps like SRsrcInfo (which is not really a trap but a selector). On a Macintosh Plus, the trap SlotManager (A06E) is available but the debugger says the call sRsrcInfo was stopped is not available.
Use NGetTrapAddress, as in the following example:
{verify SlotManager is implemented}
IF (NGetTrapAddress(SlotManagerTrap,OSTrap) <>
NGetTrapAddress(UnImplementedTrap,OSTrap)) THEN
BEGIN
{SM implemented}
END
Code in the Compatibility Guidelines chapter of Inside Macintosh Volume VI shows this in more detail, and is more robust.
Operating System: System Configuration: Gestalt trap available starting with System 6.0.4
What’s the earliest Macintosh system software that has the Gestalt trap implemented?
Gestalt is in System 6.0.4 or later.
Operating System: System Configuration: gestaltSoundIOMgrPresent and gestaltSoundInputPresent
What’s the difference between the gestaltSoundAttr selector responses gestaltSoundIOMgrPresent (bit 3) and gestaltSoundInputPresent (bit 4)?
gestaltSoundIOMgrPresent means the new Sound Manager (which can do sound in and sound output) software is present, whereas gestaltSoundInputPresent tells you if built-in sound input HARDWARE is present.
Operating System: System Configuration: Version number digits explained
What does each digit of an Apple software release version number mean? For example, in System release 6.0.7 what do the “0” and the “7” mean? the 6 is pretty obvious but what does the .0 and the .7 mean? What types of changes to the system cause these numbers to change? We want our software release numbering to be consistent with Apple’s.
Basically, the first digit is the major release number, the second digit is for small functionality enhancements, and the third digit is for bug fixes or compatibility enhancements (with new hardware products). Realistically, however, you probably won’t need to use three digits (as Apple does). Most developers use two digits, the first being for a major release, followed by a bug fix or enhancement digit. If you need to release an interim version of your product, you can always append a third digit or letter. For more details, read Macintosh Technical Note #189, “Version Territory.”
For more information about setting version numbers, take a look at the 'vers' resource documented on page 9-23 of Inside Macintosh Volume VI. This is where the Finder gets the version number to display in the Get Info window for your application. (If the 'vers' resource is not present, the finder displays the string from your signature resource as the version information in the Get Info window.)
Operating System: System Configuration: Gestalt selector for ReadPartialResource is not implemented
When can I expect to see ReadPartialResource working? I noticed the trap was finally defined in the MPW® headers but Gestalt still says it is unavailable.
The new partial resouce calls are implemented in System 7.0. However, the Gestalt selector for the new calls is not implemented.
Operating System: System Configuration: Determining if a Macintosh video card is processor-based
Is there a SysEnvirons variant for determining if the video card installed is an 8•24GC or more generally, if it’s a processor-based video card?
Macintosh® Technical Note #288, “NuBus Block Transfer Mode sResource Entries,”covers most of this information, but probably not all. However, it’s the best there is at this point!
Operating System: System Configuration: System 7.0 doesn’t recognize gestaltResourceMgrAttr selector
Why does Gestalt appear to not recognize the selector “gestaltResourceMgrAttr” and return the error code “gestaltUndefSelectorErr” (-5551)?
It turns out that gestaltResourceMgrAttr selector support was not implemented in time for Macintosh® System 7.0. Because the only information the selector provides is whether partial resources are supported, you can check instead forthe presence of the _ResourceDispatch trap (0xA822), which will give you the same information.
Operating System: System Configuration: Macintosh System 6 and System 7 on the same hard disk
Can I set up a Macintosh® disk partition containing System 6.0.x and another containing System 7.0?
No, the Macintosh operating system does not support multiple partitions, but there is another way to accomplish the same basic principle, the details for which follow:
NOTE #1: You MUST use the Hard Disk Setup utility that accompanies the System 7.0 software to update ALL of your hard disk drivers (that is, for every device hooked up to your Macintosh) before installing System 7.0. The reason for this is that the Boot Block structures have all been restructured in this latest System software release. Failure to update these structures will result in abnormal behavior (such as crashing, freezing, and disk errors), which may difficult to trace for users.
NOTE #2: Equally as important as updating all SCSI device drivers (mentioned in Note #1 above) is using the final version of Disk First Aid (version 7.0) AFTER installing the final version of System 7.0. The reason for this is that a bug has existed in the Macintosh operating system from its inception such that the B-Tree structures for devices were created with minor inherent corruption. This did not effect applications directly nor users significantly, but it usually resulted in very infrequent occurrences of some annoying behaviors such as not being able to throw away an empty folder (remember the old “Trash could not be emptied because a file was busy or locked” error?). This bug has been fixed (hurray!) in the final version of System 7.0. Running Disk First Aid will correct the problems left behind by the older Systems.
And now on to the business at hand. Following are the recommended steps (in order) necessary for creating two System folders on a single device. <<NOTE #3: In general, keep in mind that having multiple System folders on a single device is not a good idea, but for the configuration described below please be aware that there should exist NO more than two (2).>>
• Use Apple’s HD Setup utility to update your drivers on all the drives you’ll be using with your System 7.0 machine
• Boot from the System Tools disk
• Move the Finder out of the System folder (preferably into another folder) on your hard drive and rename the System folder (“Sys folder” works fine). This renaming is a MUST (see explanation in Note #4 below)!
• Install whichever version of the system software you want
• Now, all you have to do is keep in another folder whichever version of the Finder you DON’T want to run.
NOTE #4: The only way to legally install two System folders on your hard drive is to move the Finder OUT of one of them and rename the folder because the installer looks for a folder called “System folder,” then for the Finder inside it. If both searches fail, it will create a new one.
As an example of how to run with this configuration, whenever I want to use System 7.0 on my Macintosh II, I drag the 6.0.7 Finder (from the System folder I’ve renamed to “Sys 6.0.7 folder”) into another folder on my desktop, put the 7.0 Finder back into my 7.0 System folder (called “Sys 7.0 folder”), then restart. It works great!
One final note: Of course, you can boot of another drive with the other system version on it rather than trying to maintain two on the same drive. To change system versions in this method, simply use the Startup Device cdev to tell the system which drive you want to boot from, then restart. This is actually cleaner and by far the nicest way (for the system) to alternate between two system versions, but as Apple realizes that the hardware required may not be feasible for all developers, DTS is providing the above alternative.
Operating System: System Configuration: Installing Apple IIGS system software
What is the correct procedure for installing system software on an Apple IIGS®?
Always use the Installer application. The Installer scripts provided by Apple on the Apple IIGS system disks will put everything you need on the startup disk. If you attempt to install system software without using the Installer, there’s a good chance you’ll forget to copy a needed file or delete an obsolete file.
Because SCSI hard disk drivers are not included on System.Disk, you’ll need to do the following to install System 5.0.4 on a hard disk:
1. Make backup copies of System.Disk and System.Tools, making sure they keep the same names.
2. Launch the Installer from System.Tools (backup) and install SCSI Driver on the backup of System.Disk. The Installer script will delete a couple of fonts as well as the tutorial folder to make room for the SCSI information on a 3.5- inch disk.
3. Boot the backup of System.Disk and install System 5.0.4 onto your hard drive. If you want Shaston 16 and Times 12 fonts, install “Additional Fonts” last.
The Installer knows how to make the software fit on a floppy disk. It can also update your system without requiring you to trash your existing System Folder.
Apple IIGS Technical Note #64, “Apple IIGS Installer and Installer Scripts,” describes how the Apple IIGS Installer executes Installer script files and how to write Installer script files.
Operating System: System Configuration: When to use Macintosh TrapAvailable function
The TrapAvailable function listed in the “Compatibility Guidelines” chapter of Inside Macintosh® Volume VI contains code that checks the size of the trap table. Do I have to do this if my application doesn’t support the old 64K ROMs?
Yes, you do. With the introduction of the Macintosh Plus and 128K ROMs, the trap table was divided into the OS trap table and Toolbox trap table. The number of trap table entries was increased and the format of those entries was expanded. For additional information on this expansion see the “Using Assembly Language” chapter of Inside Macintosh Volume IV. However, the 64K to 128K ROM trap table expansion is not what the code in the TrapAvailable function is checking for. The Toolbox trap table was expanded yet again when the Macintosh II was introduced. The Macintosh Plus and SE use the smaller Toolbox trap table on pre-7.0 systems. To be sure your application is compatible with these machines on pre-7.0 systems, check the size of the Toolbox trap table.
Operating System: System Extensions: Third-party menu items in Apple menu
How do you get the text of menu items such as CEToolbox, Super Boomerang, or QuickKeys in the Apple menu? These seem to install themselves in a way that you can’t even call them from HyperCard using doMenu. AddResMenu(menuHdl_,'DRVR') gets me some but not all menu items.
Menu items such as the ones you mentioned aren’t installed into menus until the very last moment. The application patches MenuSelect and MenuKey; when either routine is called, the application inserts its menu items and lets the call continue. Once the routine is finished, the application removes the items that it installed. This way, your application can continue to treat menus normally without worrying about items getting renumbered.
HyperCard’s DoMenu doesn’t see the menu items because they don’t exist in the menu bar when doMenu is called. You’ll probably never be able to “see” these menu items from your application, since any patch you add would be before and after the CE init (or whatever) adds and removes its item. This is also the method used to dispatch the menu item once it’s selected; your application gets back an indication that no menu item was selected and the menu item is handled by the patch.
To verify that this is, in fact, what an application is doing, you can follow the procedure below for looking at the menu list in memory at any arbitrary time:
1. Break into MacsBug (if you use TMon or Jasik you will have to modify these instructions)
2. Display the menu data for the Apple menu with Dp ((MenuList^^)+6)^^
3. Notice that in the ASCII display you can see the data for all the Apple menu items except the ones you’re looking for. This is because they do not exist yet.
4. Now simply break on MenuSelect and step into MenuSelect and watch items get added dynamically.
Now that you know how the menu items are fudged, you might be able to work around this somehow (although I can’t think of a way, but you might see something I don’t).
Operating System: System Extensions: Macintosh INITs and allocating system heap space
How do I use the space the 'sysz' resource allocates for my INIT?
INITs usually run in their own heap, separate from and just above the system heap. You could probably set the INIT's resource attributes to run in the system heap, but DTS does not recommend that. Rather, let your INIT run in its own heap, allocate memory with NewPtr, SYS and BlockMove your permanent code and data structures into that space. Alternatively, you can load a locked code or data resource into the system heap.
Whenever your INIT needs more than 16K of system heap space for the memory allocations the INIT will make or the resources it will load, you should include a 'sysz' resource specifying the space needed. The 'sysz' should not include the space necessary to hold the INIT code, as that will be in its own heap.
The 'sysz' specification is constant, so variable-size system heap space cannot be reserved by an INIT.
Operating System: System Extensions: Macintosh INIT and memory use
How can I adjust the Macintosh system heap to accommodate my 1.3 MB INIT so it doesn’t crash on systems that don’t have enough memory?
The current INIT31 doesn’t recover from oversized 'sysz' resources correctly. However, the INIT mechanism is really for patching, not for major application development involving large amounts of memory. Valid INITs are drivers that need 1-2K for buffer space or SMALL patches.
Operating System: System Extensions: Apple IIGS CloseView Init
Apple IIGS CloseView Init
The Apple IIGS CloseView init is part of a package called “Universal Access.” It’s on the latest Developer CD Series disc, as an 800K disk image and as discrete files. The documentation with it contains information such as system software requirements.
Operating System: System Extensions: Macintosh 'sysz' does not allow dynamic memory allocation
There appears to be a bug in the 'sysz' mechanism at startup time. If we create an INIT that has sysz == MemTop/2 and code consisting of a debugger trap such as trap $F and an RTS, the system crashes when it reboots. Basically, INIT 31 grows the system heap past the top of the stack before our code is even loaded. This is not a large memory allocation problem, as any INIT that requests more memory than is available will crash the machine.
This is the behavior of the 'sysz' mechanism. It has always been this way. The 'sysz' mechanism does not allow a dynamic memory allocation, nor does it perform any error checking. You must know by exactly how much you want to grow the system heap before loading your INIT, and you must not ask for more space than there is. If you ask for too much, the system heap will indeed grow right through your stack, boot blocks, and everything for that matter. The usual result is a horrendous crash at boot time.
System 7.0 fixes the problem by growing the system heap as much as possible but not more than allowable, given the restrictions imposed by the boot time stack.
Many developers have encountered this problem before and have tried various workarounds. There are no really attractive options. You might try running a pair of INITs that work together. Some find that it’s easier to do a static allocation by lowering BufPtr, but this too may have drawbacks in terms of VM compatibility (you might have to go to some extra effort) and there is an inconsistency in the post-Macintosh IIcx ROMs which invalidates the MemTop/2+1024 formula (this too is fixed in System 7.0).
In order to use the 'sysz' mechanism reliably for very large allocations under System 6.0.x, you’ll have to find some way of preflighting the 'sysz' by running an INIT to change the value of the 'sysz' resource on the fly and then have INIT 31 execute the real code with the preflighted 'sysz'.
Operating System: System Loader (AII): Apple IIGS System Loader and multiple user IDs
We want to load $BC files from a folder when our program is launched. How do we ask the Apple IIGS® System Loader to discard these loaded files at application shutdown time? We tried using the main program’s master ID from the Memory Manager, but the files are still not unloaded.
The Loader is not designed to support more than one program with one user ID. It assumes that InitialLoad or InitialLoad2 will be called with distinct user IDs for each “program” to be controlled individually.
You need to get new user IDs (probably $1000 type) for each module you load, so that you can call UserShutDown on each of them individually when you need to. Don’t dispose of the memory at the end; call UserShutDown on each of the IDs and the Loader will take care of the rest. If you’re not quitting, you might want to shut them down in zombie state so that they don’t have to be reloaded from disk if the memory is available. You can just pass $1000 as the user ID to InitialLoad and it will get a new ID for you and return it on the stack.
Remember that $BC auxiliary types are reserved and must be assigned by Apple Developer Technical Support.
Operating System: System Loader (AII): Apple IIGS ExpressLoad error handling
While linking my Apple IIGS® application, LinkIIGS does a system death: “ExpressLoad error 1301.” What am I doing wrong?
Believe it or not, LinkIIGS has dynamic segments. ExpressLoad has the annoying habit of taking error codes it’s not expecting, adding $1100 to them, and calling SysFailMgr. Why is this habit annoying? Well, it works just fine for what the author had in mind, which was GS/OS® errors (all of the form $00xx), but it causes problems with Toolbox errors.
You’ve probably figured out the rest by now: $1301 - $1100 = $0201 = Memory Manager “unable to allocate handle” error. ExpressLoad ran out of memory trying to load a dynamic segment in LinkIIGS.
The best solution is to get more memory. If you can’t make enough memory to link it, you might consider having some of your code in code resources instead of in dynamic segments in the data fork, to create separate links for those segments and make the big link even smaller.
Operating System: System Loader (AII): Error handling for Apple IIGS dynamic segment loading
Why does a dialog box without a Cancel button come up from an Apple IIGS® Loader call when the volume is not on line?
The loaders always set the preferences to “dialog, no Cancel button” when trying to load a dynamic segment indirectly (because you passed control to it). The loaders must do this because they have no way to report errors. For example, if your code does a JMP DynSegLabel, the Loader must load the dynamic segment. Should it get an error, it has no way to report an error and no place to pass control back to if your program does a JMP and the Loader has no place to return to. In earlier systems, inability to load a dynamic segment was a fatal system error. Today, the Loader will not give up until you insert the disk because it has no other choice. However, if you call LoadSegName yourself, the Loader should not change the preferences; because that’s a call, the Loader can return from it gracefully. Indirect dynamic segment loading doesn’t have that luxury. The current Loader documentation is in the Addison- Wesley version of GS/OS® Reference.
Operating System: Virtual Memory: Macintosh Virtual Memory and protecting large buffers
I’m filling a large buffer with one SCSIRead call. What happens if the Macintosh runs under System 7 with virtual memory (VM) and parts of my buffer are swapped out?
Parts of your buffer must not be swapped out. Before calling SCSIGet, you must ensure that all code and buffers accessed while the SCSI bus is busy are held in physical memory. If there isn’t enough real memory to allocate a full buffer, the application must request smaller blocks (if possible) from the SCSI device, because it’s not possible to swap in and out any buffer space during a single I/O operation. Page faults are not serviced while SCSI I/O is in progress. If SCSI I/O is performed at device driver-level Read or Write calls, VM holds your buffer for you. Otherwise, you are responsible for doing this yourself. If there is insufficient physical memory for VM to hold your buffers for you, the Read or Write call fails with an error result.
In general, I/O buffer space used by drivers must be held in real memory for the duration of the I/O operation. This is especially true for SCSI I/O because VM uses SCSI to swap virtual memory in and out, and encountering another page fault would cause a bus error. Device Manager-level I/O handles this automatically, by holding down the appropriate memory when the driver is entered through a Read or Write call. The Device Manager does not take care of this for you when the driver is entered through a Control or Status call, however. If the SCSIRead call is made from within a device driver as a result of a PBRead, no special action is necessary. Any other type of code must be very careful not to cause page faults between SCSIGet and SCSIComplete. This requires holding or placing in the system heap any code or data structures referenced during this time.
Platforms & Tools: A/UX: Setting file types and creators with A/UX’s setfile utility
Using A/UX language tools such as cc, ld, and make, how do I set a file’s type and/or creator? (I can use ResEdit, but I want to include the command to set type/creator in the A/UX makefile, as I do using Link under the Macintosh operating system.).
You can use the setfile utility under A/UX to set Macintosh types and creators. The syntax is the same as the MPW Tool of the same name, as follows::
SetFile [option…] file/folder…
-a attributes # attributes (lowercase = 0, uppercase = 1)*
-c creator # file creator
-d date # creation date (mm/dd/yy [hh:mm[:ss]
[AM | PM]])*
-l h,v # ICON location (horizontal,vertical)*
-m date # modification date (mm/dd/yy [hh:mm[:ss]
[AM | PM]])*
-t type # file type
Note: Period (.) represents the current date and time.
Note: The following attributes may be used with the -a option:
L Locked
V Invisible*
B Bundle
S System
I Inited*
D Desktop*
M Shared (can run multiple times)
A Always switch launch (if possible)
Note: Options/attributes marked with asterisk (*) are allowed with folders
Platforms & Tools: A/UX: MacX client and reading Macintosh Command key
I need some help with MacX under A/UX: Is there any way to read the Command key from a MacX client? Pressing the Command key doesn’t produce a keypress event.
The Command key is not activating a keypress because the Command key is used in the Macintosh side of the X world for the menu shortcuts and other things, and in order to avoid confusion, the design team made a deliberate decision not to trigger any key events on the X Windows side concerning theCommand key.
If you have an important reason why this should be otherwise, please let DTS know.
Platforms & Tools: A/UX: SGetcString in A/UX archives should be SGetCString
SGetcString in A/UX archives should be SGetCString
The Slot Manager function SGetCString is called SGetcString, with a lower-case “c,” in both libmac.a and libmac_s.a archives under A/UX 2.0 and 2.0.1. It should be SGetCString according to the rules of MPW and Inside Macintosh. This is another case where the case-sensitivity of UNIX bites.
If you have any similar problems with other calls to the Macintosh toolbox, try a script such as this:
strings use | lib | libmac.a | grep SGet
Also, check libmac_s.a if you are using shared libraries. The A/UX Toolbox: Macintosh ROM Interface manual.has a list of supported Slot Manager calls.
Platforms & Tools: A/UX: Use A/UX libraries to emulate Macintosh Toolbox functions
How can I use the Macintosh Toolbox functions from the A/UX kernel? When I link my module into the kernel, ld can’t resolve the references to toolbox functions.
MacOS ROM Toolbox emulation under A/UX is done with the help of a device driver, /dev/uinter0, which handles the A-line trap interrupt emulation. This will not work in the kernel side, because you can’t signal A-line traps suddenly to another device driver (without a lot of pain; anything is possible in software). For this reason, you should use the A/UX libraries that support most of the toolbox side concerning hardware. Slot Manager support, for example, is done with the slot libraries (-lslot).
Let DTS know if you need additional device driver support in the current hardware-related libraries. Otherwise, in the A/UX (or UNIX) device driver world, you should follow the rules and libraries of A/UX (most of the OS-related traps are mapped to UNIX-equivalent calls anyway).
Platforms & Tools: A/UX: A/UX and the Macintosh Deferred Task Manager (DTM)
A/UX and the Macintosh Deferred Task Manager (DTM)
The Deferred Task Manager (DTM) under A/UX is not supported at this time. A call to the DTInstall routine generates an unimplemented trap message.
The reason for this is that DTM should only be used for low-level driver functions, and for A/UX this is handled by device drivers talking with the NuBus cards.
To implement something with a similar functionality as the DTM provides, you’ll need to write a separate UNIX device driver, because Macintosh OS NuBus device drivers as they are don’t work with A/UX. For driver details, check the “A/UX Device Driver Kit,” available from APDA.
Platforms & Tools: A/UX: Accessing Macintosh operating system from A/UX program
Is there a way that you may access a Macintosh operating system file system from an A/UX program without going thru the toolbox?
Currently there is no way to access the Macintosh file system from an A/UX program without going through the toolbox. It may not be exactly what you want, but it is possible to write a faceless Toolbox application that works like most UNIX tools. Its only requirement is that, although the application can run from any terminal, someone must be logged in from the console for this faceless application to work correctly because the Toolbox must be active for it to work.
Platforms & Tools: A/UX: Converting parameter sizes for MPW and A/UX C
Is it possible to tell the MPW® C compiler to generate 68881 instructions without having the compiler represent extended numbers in 96 bits?
I know of no way to induce either MPW or A/UX® C to change the size of the parameters it passes, but there are SANE routines to convert back and forth. MPW Sane.h conditionally (depending on whether you are using mc68881 or not) defines the types extended80 and extended96 as well as routines to convert between them:
#ifdef mc68881
struct extended80 {
short w[5];
};
void x96tox80(const extended *x,extended80 *x80); /* x is src,
x80 is dest */
void x80tox96(const extended80 *x80,extended *x); /* x80 is src,
x is dest */
typedef struct extended80 extended80;
#else
typedef struct {short w[6];} extended96;
void x96tox80(const extended96 *x96,extended *x); /* x96 is src,
x is dest */
void x80tox96(const extended *x,extended96 *x96); /* x is src,
x96 is dest */
#endif
Build these routines into your MPW code, then call them from your A/UX code to do the conversion as necessary.
If you want to build these routines in assembler under A/UX, here is a dump of the code from MPW:
Module: Flags=$08=(Extern Code) Module="x96tox80"(313)
Segment="CSANELib"(259)
Content: Flags $08
Contents offset $0000 size $0018
00000000: 206F 0004 ' o..' MOVEA.L $0004(A7),A0
00000004: 226F 0008 '"o..' MOVEA.L $0008(A7),A1
00000008: 3290 '2.' MOVE.W (A0),(A1)
0000000A: 2368 0004 0002 '#h....' MOVE.L $0004(A0),$0002(A1)
00000010: 2368 0008 0006 '#h....' MOVE.L $0008(A0),$0006(A1)
00000016: 4E75 'Nu' RTS
Size: Flags $00 ModuleSize 24
Module: Flags=$08=(Extern Code) Module="x80tox96"(314)
Segment="CSANELib"(259)
Content: Flags $08
Contents offset $0000 size $0018
00000000: 206F 0004 ' o..' MOVEA.L $0004(A7),A0
00000004: 226F 0008 '"o..' MOVEA.L $0008(A7),A1
00000008: 2368 0006 0008 '#h....' MOVE.L $0006(A0),$0008(A1)
0000000E: 2368 0002 0004 '#h....' MOVE.L $0002(A0),$0004(A1)
00000014: 3290 '2.' MOVE.W (A0),(A1)
00000016: 4E75 'Nu' RTS
Size: Flags $00 ModuleSize 24
Platforms & Tools: A/UX: MacTCP “server” option address specification
What is the MacTCP® “server” option for obtaining an IP address?
The “server” option for address specification in MacTCP tells the Macintosh to broadcast AppleTalk® packets asking to have an IP address assigned when it boots up. Depending on whether MacTCP is configured for Ethernet or AppleTalk encapsulation, MacTCP will broadcast BootP protocol packets or AppleTalk packets respectively to get its IP address.
Platforms & Tools: A/UX: A/UX and A/ROSE Macintosh Coprocessor Platform (MCP) protocol
Are there any catches in developing MCP-based (Macintosh Coprocessor Platform™) cards to be used under A/UX®? Can they be developed under the Macintosh operating system as usual and then used under A/UX?
A/UX does not currently understand the A/ROSE™ MCP protocols, so cards that are using A/ROSE will not work under A/UX. The only way to get the cards working is to write a specific A/UX device driver that talks with the card from A/UX.
Platforms & Tools: A/UX: A/UX 2.0.1 and third-party partitioned hard disk drives
I’ve partitioned into two equal-sized Macintosh® volumes on my third-party hard drive, and A/UX® 2.0.1 refuses to recognize the second partition at all. Can you tell me how to get this second volume to mount on the desktop?
The A/UX file system emulation doesn’t recognize multiple Macintosh partitions on the same hard drive. The A/UX engineering team is working on this known restriction.
Platforms & Tools: A/UX: A/UX 2.0.1 fixes console login terminal control bugs
We are running A/UX® 2.0 on both a Macintosh® IIcx and a Macintosh IIci. When a console login session uses “set -o emacs” (emacs editing keys as opposed to vi) in the korn shell (ksh), the session hangs, whether the set command is in .kshrc or typed in. A remote connection as root can log in and kill the console process and return the system to the login program. Is this a A/UX ksh bug?
Bugs found in the A/UX 2.0 console login terminal control code have been fixed in A/UX 2.0.1. The set command “set -o emacs” in vi works OK in A/UX 2.0.1.
Platforms & Tools: A/UX: Macintosh drivers under A/UX sometimes not locked in heap
Under A/UX® MultiFinder®, RAM-based device drivers (loaded from a resource) are sometimes installed by the system as ROM-based drivers. The undesirable side effect of this is that the driver does not get locked in the heap when opened, even if the dNeedLock bit is set in the driver’s header flags.
Here’s why it happens: As part of installing a Macintosh® OS device driver, the ROM code compares the pointer to the driver to the value in the low-mem var ROMBase. If the driver pointer is greater than ROMBase, the driver is assumed to be in ROM. Its pointer, rather than Handle, is put in the DCE and a dCtlFlag bit is cleared to indicate a ROM based driver. Since a driver in ROM can’t move, the Device Manager ignores its dNeedLock bit and does not call HLock when opening the driver. Before making the comparison, the Device Manager calls _StripAddress on the driver pointer. Then, rather than call _StripAddress on the ROMBase, the code clears the high byte to zeros! (This happens at ROM address 40806A3C on my Macintosh IIx). This means that a driver loaded into the heap at any address higher than 0x800000 is installed as a ROM based driver.
Under A/UX MultiFinder, it is possible to have heaps located above 0x800000. In fact, on my Macintosh IIx with 20 MB of RAM, virtually all my application heaps are above that address. When an application (actually, a printer driver called by an application) opens our spooling device driver, the driver does not get locked in the heap.
To work around the problem, we set the locked bit for the 'DRVR' resource, ensuring the driver is locked when read into the heap, regardless of what the Device Manager does. In our case, this driver is stored as a resource in a Print Driver file. Once the Print Driver is closed, so is its file, and our driver is therefore removed from the heap. Otherwise, the driver would forever be locked in the heap, even when not open.
An alternative solution would be to have the driver lock itself. This is difficult because it would have to be done in the driver header code which is automatically prepended to the driver by the C compiler we use. (This header code loads a data resource, so the lock would have to precede that action). We could do our own header, but obviously that costs time and $$$.
Please let me know if you can think of any problem with the first solution. I’m assuming that you will also follow up on having this 32-bit unfriendliness corrected in future System Software.
Your analysis of the situation with Macintosh drivers under A/UX is excellent. I checked the ROM listings and it is doing exactly what you said. The good news on the Macintosh OS side is that the same code on the Macintosh IIci and IIfx has already been fixed in the ROM. Because these are the only machines in 32-bit mode under 7.0, it shouldn’t be a problem.
On the A/UX side, I have filed a bug report. I’m not sure when it will be fixed, but your workaround should be OK.
Platforms & Tools: A/UX: Checking network address for software protection
We need to have security for our software so that it will run on only one machine. With Macintosh® systems we are forced to use an Ethernet address because that is the only unique hardware number we are able to access. We need to know if there is some type of OS software running on A/UX® 2.0 that we can use or if there is a hardware code unique to a machine that we as developers can get to?
You could use the Ethernet address under A/UX, as long as you test that the system has an Ethernet card installed. There’s no rock-solid serial number available on the Macintosh hardware platform. One of the considerations is that if the motherboard or the ROMs are repaired and switched, the serial number might change and cause problems with applications.
The pros and cons considering software protection are many, and I don’t want to take any stands. Instead I will give you some other clues how to protect software, and I will also include at the bottom of this letter the official Apple DTS statement concerning software protection.
Anyway, one way (as you maybe know) is to use various dungles. We’ve had bad experience with ADB-based dungles and A/UX, so we suggest you use serial line- based (if you want to use the dungle method).
Another method of registering software is to register a unique name on the network (AppleTalk® or TCP/IP), and have the software check if there’s already someone else using this label. It assumes that the machine is connected to a network. Concerning AppleTalk solutions you might use a simple PRegister (Using the NBP Protocol), or in the case of a TCP/IP solution maybe a background task that checks a port and reacts if someone with similar identity calls.
There are also many other half-good solutions for registering a label and checking for this on the system. Unfortunately crackers are able to break these copy protection schemes; the nice thing is that the number of crackers among Macintosh users is very small.
So unfortunately I can’t give you a definite answer of how to protect your application from illegal copying. I hope this resolution explains the current situation. If you want to comment or if you have any other questions, please let us know.
---DTS Official position concerning software copy protection-----
DTS’s official position is that software copy protection is a bad idea, so we
don’t support development of protection schemes. Here is a summary of arguments against copy protection:
1. You will have to put your valuable resources into engineering a scheme, which usually means disassembling the ROM to understand the disk drivers, HFS, MFS, etc., as well as fully understanding how the hardware for each machine your software runs on works. This extra work adds time to your development schedule.
2. You’ll have to maintain your software when it doesn’t work on future machines or system software releases. Virtually every copy protection scheme devised so far (that we know about) has required revision for new Apple CPUs.
3. You’ll have to test the software on all machines and products, including third-party hardware and file system software.
4. You’ll have to support possibly angry users who have problems using the software because of the protection scheme, or have broken “key” disks, etc. Users may be frustrated by an inability to copy software to a hard disk, make backups, or immediately use the software with new hardware or software.
5. Every copy protection scheme devised so far (that we know about) can be defeated by commercial products that remove or circumvent the protection.
6. Protected software frequently receives poor reviews or mentions in the press because of the protection scheme.
We feel that copy protection is not a worthwhile use of development time. We cannot help you develop a protection scheme, or provide support when protected software breaks with future hardware or software.
Platforms & Tools: A/UX: Use kill -9 to kill MacOS but not an individual application
Can I use the “kill” command to kill a Macintosh® program running under A/UX? Is it even possible to kill a MacOS-based program from the Command shell window?
The kill -9 command should be able to kill the MacOS. It obviously won’t be able to kill an individual Macintosh program, however, since all Macintosh programs run under the framework of the one MacOS process.
Platforms & Tools: A/UX: Use ps -efa to see MacOS processes
Can I use the ps -efa command to tell if a Macintosh® program is running?
You should be able to see the MacOS processes with the ps -efa command (as you tried). It will be listed as Mac24 or Mac32, depending on whether you’re running in 24- or 32-bit mode. You can even launch (start) these processes from the command shell.
Platforms & Tools: A/UX: A/UX technical information sources
Is there a special AppleLink® group address to send A/UX®-related questions to rather than the general MACDTS address?
There’s a folder under Developer Services for A/UX-related (developers ask each other) questions. You’ll find a lot of good information also from USENET, comp.unix.aux. With the introduction of AppleLink 6.0, the browsing capabilities are far improved (threading of entries, browsing in general).
Platforms & Tools: A/UX: A/UX symbolic debugger
Is there a symbolic debugger for “hybrid” applications under A/UX®? MacsBug is not a solution for looking at data structures 1K in size.
Unfortunately I’m not familiar with any A/UX debuggers. I have heard of one, but I can’t say that I’ve ever used it. It’s called UDB - OASYS Universal Remote Debugger. It’s a multi-targeted, window-oriented, source level debugger for single and multiple embedded microprocessor systems. If you’d like to contact OASYS and talk about it, they can be reached at (617) 890-7889.
As for further information, you might have better luck calling the A/UX Hotline. Their number is (408) 974-5091.
Platforms & Tools: A/UX: A/UX 2.0 video ioctls not available with Finder
In A/UX® 1.1.1 there were video ioctls to get screen information (VIDEO_PIXSIZE, VIDEO_ADDR, and VIDEO_DATA), and one to map the physical screen into user address space (VIDEO_MAP). We used these to do documentation on our system in the form of screen dumps. (The normal screen dump function cannot be used with a menu held down with the mouse.) Under A/UX 2.0 these ioctls are unavailable when the Finder™ is running, WHY? They work fine if the finder is not running (using the console emulator only). Can you tell me how I can get the same information, specifically base address, bytes per line, screen rows, and map the screen in with the finder running, BUT not be a toolbox application?
The video ioctls documented in System Admin Reference won’t work with the Finder because Finder remaps video memory to other locations. In this case the documentation does not mention it, so we will try to make this point clear in the next documentation release (use only during console mode).
The suggested way is to play according to Macintosh® rules when Finder is running, so many of the public domain screen dump utilities should work, even with menus. Beware of utilities that use FKEYs; they won’t work with A/UX 2.0. If you want to write your own, check out the DTS Sample code FKEY, and trap the MenuHook for handling menus.
Platforms & Tools: A/UX: GetGamma and SetGamma support after A/UX 2.0.1ß2
Are GetGamma (csCode 4) and SetGamma supported in A/UX® 2.0.1?
GetGamma (csCode 4) is not supported. SetGamma will be supported, starting
with A/UX 2.0.1.
Platforms & Tools: A/UX: Code for determining if Mac application is running under A/UX
How does our app know whether it is running under A/UX®?
Below you will find a piece of sample code which will enable you to know whether or not your application is running under A/UX:
A/UX Sample Code:
#define BTstQ(arg, bitnbr) (arg & (1 << bitnbr))
/*
* GetGestaltResult returns the result value from Gestalt
for the specified
* selector. If Gestalt returned an error GetGestaltResult
returns 0. Use
* of this function is cool only if we don't care whether
Gestalt returned
* an error. In many cases you may need to know the exact
Gestalt error
* code so then this routine would be inappropriate. See
GetAUXVersion, for example.
*/
long GetGestaltResult (OSType gestaltSelector)
{
long gestaltResult;
if (Gestalt (gestaltSelector, &gestaltResult) == noErr)
return (gestaltResult);
else
return (0);
}
#define HWCfgFlags 0xB22 /* Low memory global used to check
if A/UX is running */
/*
* getAUXVersion -- Checks for the presence of A/UX by
* whatever means is appropriate. Returns the major version
* number of A/UX (i.e. 0 if A/UX is not present, 1 for
* any 1.x.x version 2 for any 2.x version, etc.)
* This code should work for all past, present, and future
* A/UX systems.
*/
short GetAUXVersion ( void )
{
long auxVersion;
short err;
short *flagPtr;
/*
* This code assumes the Gestalt glue checks for the
* presence of the Gestalt trap and does something
* intelligent if the trap is unavailable,
* i.e., return unknown selector.
*/
auxVersion = 0;
err = Gestalt (gestaltAUXVersion, &auxVersion);
/*
* If gestaltUnknownErr or gestaltUndefSelectorErr
* was returned, then either we weren't running on
* A/UX, or the Gestalt trap is unavailable so use
* HWCfgFlags instead. All other errors are ignored
* (implies A/UX not present).
*/
if (err == gestaltUnknownErr || err == gestaltUndefSelectorErr) {
/* Use HWCfgFlags */
flagPtr = (short *) HWCfgFlags;
if (BTstQ(*flagPtr, 9))
auxVersion = 0x100; /* Do Have A/UX, so assume
version 1.x.x */
}
/*
* Now right shift auxVersion by 8 bits to get major
* version number
*/
auxVersion >>= 8;
return ((short) auxVersion);
}
Platforms & Tools: A/UX: Use a device driver to speak with ADB device from A/UX
Does A/UX® do a Global Reset on the Apple Desktop Bus™ (ADB) when it initializes? That is, if an ADB device’s handler where changed by an INIT during the Macintosh® OS stage of A/UX startup, would that change persist in A/UX?
A/UX unfortunately does a reset on the ADB side when it boots. This means that any ADP opcodes that are sent to the devices are not recognized after the boot to the A/UX side. The only way for the moment to speak with the ADB device is by writing a device driver from the A/UX side.
Platforms & Tools: A/UX: Cloning A/UX
What is the easiest way to make a complete copy of A/UX® from one SCSI hard disk to another?
The dd command is the simplest way to copy A/UX. The following script documents the dd command usage and gives a sample dd command. If you use dd to copy slice 31, as in the example, the entire drive is duplicated, including the Macintosh® operating system partition.
# To clone an entire SCSI disk drive, issue the following command:
#
# dd bs=32b if=/dev/rdsk/cXd0s31 of=/dev/rdsk/cYd0s31
#
# where X is the SCSI id of the input device and
# Y is the SCSI id of the output device.
#
# if you have lots of memory, bs can be larger than 32b to allow
# faster copying. bs=512k works well on machines with 4MB or
# more.
#
# For example, to clone SCSI drive 4 onto SCSI drive 5 do:
#
# dd bs=32b if=/dev/rdsk/c4d0s31 of=/dev/rdsk/c5d0s31
#
# The 31 at the end of the device name is a partition number
# (31) refering to the entire drive. Substitute an appropriate
# partition number to copy just a single partition.
#
# This is set up to clone 4 onto 5.
#
dd bs=32b if=/dev/rdsk/c4d0s31 of=/dev/rdsk/c5d0s31
Platforms & Tools: A/UX: A/UX debugging tools
What debugging tools are available for A/UX®?
The debugging tools available depend on the task.
Very low-level kernel debugging: A kernel-level debugger ships with every system, although it is not included in the configuration. Documentation on the kernel debugger is in the release notes for the A/UX 2.0 Device Driver Kit.
Assembly debugging: The standard Unix assembly debugger, adb, is provided.
Source level debugging: The standard Unix source debugger, sdb, is provided. Additionally, an alternative source level debugger, cdb, is available through APDA.®
Macintosh® application debugging: Macintosh binaries can be debugged using MacsBug. MacsBug version 6.2b1 is compatible with A/UX. Place MacsBug and the “Debugger Prefs” file into the currently active A/UX System Folder, log out and then log back in. Once it is installed, you can drop into the debugger using the key combination “Control-Command-I” (using the hardware programmers switch doesn’t work). Contact APDA for the latest information on MacsBug.
A/UX Toolbox application debugging: This is currently a problem area. An A/UX Toolbox application is a standard Unix (COFF) executable which shares the A/UX Toolbox environment. The previously mentioned debuggers (sdb and cdb), while they understand the COFF file format and symbol information, use breakpoint or signalling mechanisms which are incompatible with the A/UX toolbox. MacsBug understands the Macintosh environment, but does not recognize COFF files. Apple is aware of these difficulties and is working on solutions; in the meantime, MacsBug is your best bet.
Platforms & Tools: A/UX: AppleSingle/AppleDouble file format
How can I find out more about the AppleSingle/AppleDouble file format specification?
The AppleSingle/AppleDouble file format specification was originally designed to facilitate storage of Macintosh® files on A/UX®. It has been generalized to allow storage across a variety of platforms. More information on this file format is contained in Chapter 6 of the A/UX 2.0 manual A/UX Toolbox: Macintosh ROM Interface. It is also available as a separate document titled “AppleSingle/AppleDouble Formats for Foreign Files Developer’s Note.” This document is available in printed form from APDA®, and in electronic form on the Developer CD series and on AppleLink® under in the Developer Support folder.
Platforms & Tools: A/UX: A/UX 2.0 and text file CR-to-LF conversion
When and why are carriage return characters translated to linefeed characters by A/UX® 2.0?
To understand the significance of this question you must realize that Macintosh® applications expect lines in text files to be terminated by a carriage return character (CR, 0x0D) while A/UX applications expect the lines to end with a linefeed character (LF, 0x0A). To allow the same files to be read and written by both kinds of applications, the A/UX Toolbox performs some magic translations when Macintosh applications read and write these files. While every attempt has been made to make this translation completely transparent to both the user and the application, some situations can arise where unexpected results ensue.
First, translation NEVER occurs except for files of type 'TEXT', and then only when the file is written to the “/” Unix partition. Translation does not occur if the file resides on a Macintosh file system, and binary files are not affected. But, if you have a file of type 'TEXT' and move that file to the Unix partition, THEN change the file type to something other than 'TEXT', translation will have already taken place and the file will have bad data.
When does this translation occur? Translation takes place on _Write and _Read calls. At that point, the A/UX toolbox looks at the file type and the destination/source file system and determines if translation is appropriate. This means, for example, if you create a file of type 'TEXT' and write some data to it, then change the file type, translation will have already occurred, so you should always set the correct file type before writing any data.
Finally, how does the toolbox deal with “ordinary” Unix files transferred to an HFS volume? For a more detailed discussion of the exchange of files see the question: “What assumptions are made when the A/UX Toolbox moves a file between an HFS partition and an A/UX partition?” With respect to CR/LF translation when transferring ordinary Unix files, the toolbox tries to determine if the file is a text file in the Unix sense. It does this in the same way the “file” utility does it (man (1) file). For more information on how it does this, see the question: “How does A/UX 2.0 associate file and creator information with ordinary Unix files?” If the file looks like an ordinary text file, like a shell script or source code, translation occurs; otherwise it does not. As long as the A/UX toolbox can identify the Unix file type and the toolbox can handle transfer both to and from the HFS partition, the process is completely reversible and no ambiguity occurs. But beware of transferring data only in one direction with the Toolbox. Suppose, for example, you transfer a file from A/UX to a Macintosh using a serial communication program, but then use the A/UX Finder to copy it back to the A/UX partition. You may not end up with an identical file because translation has taken place in one direction, but not the other.
Platforms & Tools: A/UX: A/UX Toolbox and HFS-to-A/UX file conversion
What assumptions are made when the A/UX® Toolbox moves a file between an HFS partition and an A/UX partition?
Implicit carriage return/line feed translation occurs for text files. See the question: “When and why are carriage return characters translated to linefeed characters by A/UX 2.0?”
There are some other assumptions made regarding text files. Macintosh® files, in addition to having the data in the data fork, often have additional information stored in the resource fork. Unix has nothing corresponding to a resource fork, nor does Unix have information such as the Finder™ maintains for files like type and creator information; so this information is not lost when the file is transferred to an A/UX partition. A/UX defines some special Unix file types.
The simplest form is the AppleSingle format. This includes a header indicating the size and location of data within the file; various entries for file Finder information; and resource and/or data fork (if appropriate). This is fine for binary Macintosh files such as applications or word processor and graphics files, but in the case of plain text files, this presents a problem for Unix utilities that expect only to see the text (data) in a file, so A/UX defines a second format referred to as AppleDouble.
AppleDouble format stores the Macintosh file in a pair of separate Unix files. The data fork resides in a Unix file all by itself, and all the other parts of the file go into a separate file under the same name but with a “%” character prepended. For example, if you have a Macintosh text file named “Foo,” which also has a resource fork, and you copy that file to a Unix partition, it still appears as a single file to the A/UX Finder and other Macintosh applications, but to Unix process there are two separate files named “Foo” (the text) and “%Foo” (the resource and other data).
Creation of an AppleSingle/AppleDouble file is NOT performed for files of type 'TEXT' which have no resource. Only a plain Unix text file is created and all Finder information is lost. This simplifies working with text files between Macintosh and Unix applications, avoids having the excess baggage of “%filename” files floating around and getting separated and allows Unix text files to be transferred to HFS partitions and back without change. Explicit conversion between AppleSingle, AppleDouble and plain Unix files is possible using the fcnvt utility.
Platforms & Tools: A/UX: How A/UX 2.0 handles file and creator information
How does A/UX® 2.0 associate file and creator information with ordinary Unix files?
File and creator information has no counterpart in the A/UX file system. All files under Unix are just streams of bytes, and some conventions have developed over the years to help applications determine the kind of files they are dealing with. Many of these conventions are exploited by the A/UX “file” utility to identify files.
The first few bytes of a file are often used to store a special number or string referred to as a “magic number.” Various magic numbers for files are contained in the file /etc/magic. For example, a file beginning with the string “#!/bin/sh” is a Bourne shell script. This is just a text file and the default for plain text files is to be owned by the TextEditor application. Plain text files will show up in the A/UX Finder with the TextEditor document icon. If you double-click the icon, TextEditor is launched to edit the file, but if you take that same file and make it executable (in the Unix sense) using chmod, it suddenly becomes executable by the CommandShell and has a CommandShell document icon associated with it. If you double-click the icon, the CommandShell is made the foreground application and commando is launched for the script.
The apparent type and creator is a fiction maintained entirely by the A/UX Toolbox; it is returned to Macintosh® applications just like real type/creator information, using the GetFInfo call, but it does not exist in the A/UX file system. If you want explicit type/creator information to be associated with a file, it must be an AppleSingle/AppleDouble format file.
Platforms & Tools: A/UX: Altering MultiFinder memory under A/UX 2.0
How can I get A/UX® 2.0 to increase the amount of virtual memory available to MultiFinder®?
Because A/UX is a virtual memory environment, A/UX can allow MultiFinder to run in a memory partition larger than physical RAM. There currently are some limitations based on the MultiFinder environment you are using, and there are of course tradeoffs when creating a virtual memory partition much larger than physical RAM, but here is the scoop:
In the 24-bit environment, A/UX limits MultiFinder to 8 MB. In the 32-bit environment, the limit is 16 MB. You can alter the default size by modifying the scripts /mac/bin/mac24 or /mac/bin/mac32 and adding the -m option to the startmac24 or startmac command lines. For example,
/mac/bin/startmac -m 10M
would create a 10 MB partition. Alternatively, you can alter the default size on a user-by-user basis by setting the environment variable TBMEMORY in the user’s .login script. For example,
setenv TBMEMORY 10m
will accomplish the same thing.
Platforms & Tools: A/UX: A/UX 2.0 recognizes AppleTalk Phase 2 (but not Phase 1) routers
Why does A/UX® 2.0 seem not to find all the AppleTalk® zones in my network?
The A/UX 2.0 AppleTalk implementation is AppleTalk Phase 2 and Phase 2 nodes do not recognize Phase 1 nodes and routers. You need to upgrade your routers to Phase 2. Alternatively, you can connect your A/UX machine to LocalTalk® which does not have this limitation.
Platforms & Tools: A/UX: Root has more free space than ordinary users
Why does root have more apparent free space than ordinary users?
When using Berkeley file systems, the system reserves a portion of the partition (called the “free-space reserve”) and makes it unavailable to user processes. For example, if you log in as Guest and issue the following commands, here is what you will see:
Guest 1 % df -t / /dev/dsk/c5d0s0 8640 blocks 18880 i-nodes
total 102204 blocks 23040 i-nodes
Guest 2 % su Password:
Guest 1 # df -t / /dev/dsk/c5d0s0 13752 blocks 18880 i-nodes
total 102204 blocks 23040 i-nodes
Although the total number of blocks are the same, the number of free blocks differ: 8640 for Guest, but 13752 for root. About 5% of the total number of blocks are reserved and unavailable to user processes. If an ordinary process were to write out more than 8640 blocks, it would get a file system full error, so df is accurately reporting the situation.
In the event that an ordinary process fills up the file system, root can still get in and take appropriate action because root still has access to the remaining free space. The free space reserve also helps reduce disk fragmentation because there are always free blocks (really) available, so the system does not have to scatter blocks all over the disk when creating or extending files. Disk fragmentation can have a drastic impact on performance; according to the main entry for tunefs, the free-space reserve “value can be set to 0 for the file system, although up to a factor of three in throughput is lost over the performance obtained at a 10% threshold.”
As the previous discussion implies, free-space reserve is a tuneable file system parameter which initially can be set using the newfs command, or later controlled using tunefs. (tunefs can only be performed on an unmounted file system; this means you can’t tune the “/” partition currently in use. You must be able to boot A/UX® separately so you can tune such a partition, so it is best to plan ahead and set such parameters when creating the partition.)
System V file systems do not have this feature, so df will report the same totals for both root and ordinary users.
Platforms & Tools: A/UX: How to recover if A/UX 2.0 Toolbox “hangs”
Why does A/UX® 2.0 appear to “hang” frequently?
A/UX 2.0 running Macintosh® applications is subject to the same problems caused by those applications under the Mac® OS. If an application is not “well behaved” according to the MultiFinder® guidelines, it can cause random behavior such as hanging the toolbox. But this is usually not as fatal as under the Mac OS. Usually when A/UX appears to “hang,” it is the A/UX Toolbox, not A/UX itself, which is “hung.” It is usually possible to kill off the A/UX Toolbox without having to resort to the drastic step of punching the reset button (which is very Unix-unfriendly and means you should check the file system with fsck when you reboot).
So, what is the best way to kill off a runaway toolbox? Well, if you have installed MacsBug for A/UX, you may be able to drop into the debugger using the key combination “Control-Command-I” (using the hardware programmers switch doesn’t work). Once in MacsBug, you may be able to kill off the errant application with the “es” command, or reboot with the “rb” command. As a more drastic measure, you can try the key combination “Control-Command-E” which should kill off the toolbox completely, log out the console and restart the login process on the console (in the absence of MacsBug, “Control-Command-I” is the same as “Control-Command-E”). Doing this is, of course, every bit as drastic as rebooting the Mac O/S; any work not saved by toolbox applications will be lost, but A/UX is still safe. If you have access to A/UX via a serial or network terminal, you can log in as root and kill off the startmac process (essentially equivalent to “Control-Command-E”).
You should always try these methods before resorting to doing a hardware reset.
Platforms & Tools: Apple File Exchange: Apple File Exchange (AFE) Apple II 'pdos' creator type
Could you give me a description (or where to find it) of the 'pdos' resource created by Apple File Exchange when bringing over files from an Apple ][?
Apple File Exchange (AFE) makes a 'pdos' creator type for Apple II files it creates on the Macintosh. The format of the file depends upon the type of file it was on the Apple II, but the creator is always 'pdos', with the file type differentiating between different Apple II file types.
The way files are supposed to be translated is found on page 141 of “The AppleShare Programmer’s Guide for the Apple II,” available through APDA. In the case of AppleShare, it must perform the translations on the fly, and AFE follows the same basic rules. In case you don’t currently have this manual, I’ll include the relevant parts of it below for your reference.
Equivalence of Macintosh and GS/OS file types
Apple II files are distinguished by a Macintosh creator of 'pdos'. The Apple II filetype SYS (=$FF) has a Macintosh filetype of 'PSYS'. The Apple II filetype S16 (=$B3) has a Macintosh filetype of 'PS16'. The Apple II unknown filetype (=$00) has Macintosh filetype 'BINA'. Apple II text files (TXT = $04) with auxtype of $0000 (i.e., normal ASCII text, no records) has Macintosh filetype 'TEXT'. These special cases allow Macintosh to display unique icons for these filetypes.
Macintosh files with creator 'pdos' and a filetype of the form 'XY ' (two hex digits followed by two spaces) will get Apple II filetype $XY and auxtype $0000. Macintosh files with creator 'pdos' and a filetype of the form $70uvwxyz ($70 is the lower-case “p”) have ProDOS filetype $uv and auxtype $wxyz (note the order of the bytes: on the Macintosh, they are stored high-low instead of low-high).
APW source files (ProDOS filetype $B0) are given Macintosh filetype 'TEXT' so that they can be edited more easily.
The conversion rules are summarized in the following tables. If more than one rule applies, the one closest to the top of the table is used.
ProDOS -> Macintosh conversion
ProDOS Macintosh
Filetype Auxtype Creator Filetype
$00 $0000 'pdos' 'BINA'
$B0 (SRC) (any) 'pdos' 'TEXT'
$04 (TXT) $0000 'pdos' 'TEXT'
$FF (SYS) (any) 'pdos' 'PSYS'
$B3 (S16) (any) 'pdos' 'PS16'
$uv $wxyz 'pdos' 'p' $uv $wx $yz
Macintosh -> ProDOS conversion
Macintosh ProDOS
Creator Filetype Filetype Auxtype
(any) 'BINA' $00 $0000
(any) 'TEXT' $04 (TXT) $0000
'pdos' 'PSYS' $FF (SYS) $0000
'pdos' 'PS16' $B3 (S16) $0000
'pdos' 'XY∆∆'* $XY $0000
'pdos' 'p' $uv $wx $yz $uv $wxyz
(any) (any) $00 $0000
* Where X, Y are hex digits (i.e., “0”-“9” or “A” - “F”), and ∆ is a space.
Platforms & Tools: Apple File Exchange: Apple File Exchange (AFE) translator documentation
Apple File Exchange (AFE) translator documentation
Information on how to write an Apple File Exchange (AFE) translator is available through APDA as “Apple File Exchange Technical Reference Package v.1.1.” The package includes an 800K disk and 184 pages of documentation.
Platforms & Tools: Apple File Exchange: CCITT Group 4 file conversion utilities
I want to save scanned photographs as CCITT Group 4 format files, but Apple’s scanner software supports only MacDraw, TIFF and PICT file formats. Do you have a Group 4 format conversion utility or know where I can get one?
We do not have such a utility; however, a couple of third-party developers who supply CCITT-related products that might be able to help you:
TMS Inc.
110 W. 3rd St.
P.O. Box 1358
Stillwater, OK 74076
405-377-0880
Fax: 405-372-9288
Creative Solutions, Inc.
4701 Randolph Rd., Suite 12
Rockville, MD 20852
301-984-0262
800-367-8465
Platforms & Tools: Apple File Exchange: Translating Macintosh extended ASCII set to 7-bit ASCII
What is the best way to convert text created using the standard Macintosh® character set to 7-bit ASCII for display on a terminal? Is there a standard call or table that will give me what I want?
The Macintosh uses an extended ASCII character set. The first 128 (0-127) characters are standard ASCII, but the next 128 (128-255) are unique to the Macintosh.
There are problems when converting from a large set to a smaller set. I am including two samples (there is no ONE correct way) of how to do the conversion from Macintosh to ASCII.
One way is to simplify the character to the closest ASCII character. This unfortunately loses information that distinguished the original character, but still maintains the same data size (it actually shrinks from 8 bits to 7 bits). Another way is to approximate the original character with multiple ASCII characters. This retains more information, but increases the size of the data.
You will have to choose the best approach for your situation.
We created the files by converting a Text file with the complete set of Char values with the Apple File Exchange utility (included with each set of System disks). We chose the Mac-ProDOS option (Text Translation...) and generated both single and multiple character conversions. I then combined the results with Excel.
You can get the Apple File Exchange Technical Reference package from APDA (M7051) and possibly use some of the routines from there. (I am not sure if the results are useful only with AFE or if you can link them into your own application.)
If the AFE tools are inappropriate for your situation, then it would be easy to take the following data and just do a table conversion. You will need to use a font like Courier to see the complete Macintosh character set.
ASCII Mac Single Multiple
128 Ä A A"
129 Å A AA
130 Ç C C,
131 É E E'
132 Ñ N N~
133 Ö O O"
134 Ü U U"
135 á a a'
136 à a a`
137 â a a^
138 ä a a"
139 ã a a~
140 å a aa
141 ç c c,
142 é e e'
143 è e e`
144 ê e e^
145 ë e e"
146 í i i'
147 ì i i`
148 î i i^
149 ï i i"
150 ñ n n~
151 ó o o'
152 ò o o`
153 ô o o^
154 ö o o"
155 õ o o~
156 ú u u'
157 ù u u`
158 û u u^
159 ü u u"
160 † t t
161 ° o <degrees>
162 ¢ c <cents>
163 £ L <pound>
164 § $ $
165 • o *
166 ¶ P P|
167 ß B B
168 ® r ®
169 © c (c)
170 ™ t tm
171 ´ ' '
172 ¨ . ..
173 ≠ = =/
174 Æ A AE
175 Ø O O/
176 ∞ % <infinity>
177 ± +-
178 ≤ < <=
179 ≥ > >=
180 ¥ Y Y=
181 µ u u
182 ∂ d d
183 ∑ S <SIGMA>
184 ∏ P PI
185 π p pi
186 ∫ S <integral>
187 ª a a_
188 º o o_
189 Ω O <omega>
190 æ a ae
191 ø o o/
192 ¿ ? ?
193 ¡ ! !
194 ¬ -
195 √ v <radical>
196 ƒ f f
197 ≈ = ~=
198 ∆ d <DELTA>
199 « < <<
200 » > >>
201 … . ...
202
203 À A A'
204 Ã A A~
205 Õ O O~
206 Œ O OE
207 œ o oe
208 – -
209 — -
210 “ " "
211 ” " "
212 ‘ ' '
213 ’ ' '
214 ÷ / <divided by>
215 ◊ o <>
216 ÿ y ye
217 Ÿ Y YE
218 ⁄ / /
219 € o o
220 ‹ < <
221 › > >
222 fi
223 fl f fl
224 ‡ | |=
225 · * .
226 ‚ , ,
227 „ , ,,
228 ‰ % %
229 Â A A^
230 Ê E E^
231 Á A A'
232 Ë E E"
233 È E E`
234 Í I I'
235 Î I I^
236 Ï I I"
237 Ì I I`
238 Ó O O'
239 Ô O O^
240 a <Apple>
241 Ò O O`
242 Ú U U'
243 Û U U^
244 Ù U U`
245 ı i i
246 ˆ ^ ^
247 ˜ ~ ~
248 ¯ -
249 ˘ , ,
250 ˙ * *
251 ˚ * *
252 ¸ , ,
253 ˝ " "
254 ˛ , ,
255 ˇ ˇ ˇ
Platforms & Tools: Apple II Tools: Applesoft floating-point routine and numeric accuracy
Apple II Applesoft’s floating-point routine results are sometimes accurate to only two places. For example, the answer returned for PRINT 55555.099- 5555.09 is 9.01031494 E-03. How can we get more accurate results?
The accuracy loss you’re experiencing with the Applesoft floating-point routines is normal. If you convert a number such as 555.099 to a base 2 floating-point number, you won’t get an exact representation using Applesoft’s floating-point routines or even 96-bit precision IEEE numerics. Because 9.01031494 E-03 is 0.0090103, you can see that you have accuracy out to 3 1/2 decimal places. The solution is to determine the accuracy that you desire and massage the result to give you that accuracy. Here is a sample program that shows common Applesoft rounding techniques:
1 REM Round to 3 decimal places of accuracy example
10 Input a
20 Input b
30 If a-b>1000 then 100: REM no 3-digit rounding of numbers >1000
40 Print "Standard Applesoft Non-accurate result:";a-b
50 Print "Truncated result:";INT((a-b)*1000)/1000
60 Print "Rounded result:";INT(((a-b)+.0001)*1000)/1000
70 Goto 10
100 Print "Result has 3 decimal accuracy already:";a-b
110 goto 10
This is the only way that you can get Applesoft to clip the numbers, apart from using a separate floating-point engine. Alternatively, you can do your own conversion from Applesoft internal numeric format to a string in assembly language and have it simulate the above operation when converting the number.
If you’re running on the Apple IIGS, you can use the SANE engine built into the firmware. This runs in native mode and you’d probably have to write a separate version of your calculation engine to work with it, but it would give you greater precision, with a slight loss of speed for the user. You can also license 6502 SANE from Apple for non-Apple IIGS machines, but this requires some memory. See the Apple Numerics Manual, Second Edition, for details.
Platforms & Tools: Apple II Tools: Teach files: saving print record as a resource also
How reasonable would it be to expand the definition of a Teach file, to save the print record as a resource also? This way, applications could handle different print records for each document more easily. It shouldn’t hurt existing applications at all, since they wouldn’t know about it.
The issue of saving print information was raised when Teach was written, but printing support wasn’t added because it isn’t important to Teach‘s function of Teach. Teach is designed to be an all-purpose text browsing program that allows users to read about files that come with various applications. The file format is for simple TextEdit data only. Feel free to add anything you like to the Teach data file’s resource fork for your own uses. You can add as many new resources to the file as you like and Teach will simply ignore them. However, since Teach won’t recognize the added print data, it should not get added to the file format.
Also, keep in mind that no print record resource format standard has been published. Once one has been published, you’ll most likely have only one per file, and most applications programs that want to use a print record resource could simply use countResources to determine if one existed and getIndResource to load the first one for use or modification. This method can be used with any current file format that does not include a one-only resource type that you think is important (“one-only” refers to resources where it is unlikely that you would have to have more than 1 per file…).
Platforms & Tools: Apple II Tools: “R” to”resume” program from Init GSBug
How can I get back to my program from the Init version of GSBug™?
The init version of GSBug installs the debugger to be present in the background, invokable with the keystrokes control-command-option-Escape. The command to quit the application version of GSBug (“Q”) does not work from the Init version; the correct command is “R” (for “resume”). If you break on a tool call, be sure to take tool breaks out before doing any tracing if you hope to not die a different horrible death than the one your application would normally have given you.
Platforms & Tools: Apple II Tools: Avoid toolbox calls in 8-bit mode with GSBug active
Some of the toolbox calls I make crash when executed with GSBug™ active, but behave normally when GSBug isn’t present. How come?
GSBug is intolerant of toolbox calls made in 8-bit mode. Although the Apple IIGS® Toolbox Reference (pages 1-2) clearly states that all toolbox calls must be made in full native mode, the current tool dispatcher protects you by beginning with a REP #$30 instruction, GSBug does not. Be sure to make all toolbox calls in full native mode.
Platforms & Tools: APW: Apple IIGS APW Tools & Interfaces changes
Do I need to purchase APW™ Tools & Interfaces if I already bought Programming Tools & Interfaces for APW?
Yes! The original Programming Tools & Interfaces utilities did not correctly support ORCA/Pascal and ORCA/C. Also, every tool in the package has been updated and enhanced. A new C library, used to build some of the tools, had bugs fixed in it (and will be available separately later). The new package also includes completely revised Apple IIGS® interfaces for APW C and the APW/ORCA assembler. The new APW Tools & Interfaces package is a class 1 product that may be ordered from Developer Tools Express; the previous class 2 product is no longer supported.
Platforms & Tools: HyperCard: Users often change “HyperCard” application name
Will the HyperCard application always be named “HyperCard,” or might Apple ship it with a different name, such as “HyperCard 1.2.2”, or perhaps another spelling appropriate to a foreign language?
Even if the application always is shipped as “HyperCard” (not guaranteed), users often change an application’s name, adding characters to make it sort up in a text view of the directory and adding the revision number for their reference.
It would be a bad bet to depend upon users NOT changing the name of any file. This is a freedom in the user interface that is not likely to be suppressed. You can probably depend on the name not changing often, usually only when a new version is installed. If you can’t find the file, you’ll need to re-ask the user where (what the name of) it is.
Platforms & Tools: HyperCard: Determining within HyperTalk whether balloon help is enabled
Determining within HyperTalk whether balloon help is enabled
There’s no easy way to tell whether Balloon Help is enabled from within HyperTalk, but an XFCN could be written to call HMGetBalloons, which would return a boolean indicating whether Balloon Help is enabled.
Platforms & Tools: HyperCard: Help balloons can’t be attached to HyperCard palettes
Help balloons can’t be attached to HyperCard palettes
Help balloons cannot be attached to HyperCard palettes? The problem is that palettes are structures that are built on the fly and handled by an XCMD called “Palette.”. Short of writing your own Palette XCMD, there’s no known way to attach help balloons to HyperCard palettes or to their contents.
Platforms & Tools: HyperCard: HyperMover and HyperCard IIGS
Why is there no Apple IIGS®-only version of HyperMover™?
HyperMover is actually implemented as a pair of HyperCard® stacks: HyperMover.mac, which runs under Macintosh® HyperCard and disassembles Macintosh stacks; and HyperMover.GS, which runs under HyperCard IIGS and reassembles the stacks into HyperCard IIGS stacks. Although there are a few XCMDs to handle tricky stuff like sounds and paint files, the majority of the work is done by simple HyperTalk scripts. It may seem like a disadvantage to require two computers to do the translation, but in fact there are a number of tremendous advantages:
• HyperMover doesn’t need to know anything about the internal binary format of stacks. This makes it somewhat immune to stack format changes. For example, you can convert a Macintosh HyperCard 1.2.5 stack to HyperCard 2.0 format, but HyperMover will still translate it because the HyperCard program takes care of reading data from the stack.
• The interchange format is simple—a file containing a complete textual description of the stack. After disassembly, you can open and even edit this file using any text editor (such as MPW® or APW™), before reassembling the file on the Apple IIGS side. This provides an easy way to browse scripts, looking for potential machine dependencies, and you can actually perform global modifications on your stack using the find-and-replace capabilities of your text editor.
• When small-font painted text is used to label objects, it often shrinks to unreadability when converted to the Apple IIGS screen resolution. You’ll need a Macintosh to view all the graphics and decide what they’re supposed to look like, before you can redraw them in 16-color Apple IIGS graphics.
• You’ll also need a Macintosh to perform side-by-side comparisons and testing of your new stack.
Having a Macintosh available is important at all phases of the stack translation process. You’ll find it makes the entire process much smoother.
Platforms & Tools: HyperCard: HyperMover, HyperCard, and HyperCard IIGS compatibility
Which versions of Macintosh® HyperCard® are compatible with HyperMover™?
The HyperMover stack will execute in the 1.2.5 and 2.0 Macintosh HyperCard environments. However, stacks that are translated should be either 1.2.5 stacks, or 1.2.5 stacks converted to 2.0 but not modified. There are two reasons for this:
• The graphics converters are designed to start from a Macintosh HyperCard 1.2.5–sized card only, because stacks with other card sizes may have objects and graphics improperly aligned.
• HyperCard IIGS® uses a version of the HyperTalk® scripting language derived from Macintosh HyperCard 1.2.5, so if a stack uses language elements that were not present in Macintosh HyperCard 1.2.5, it may translate correctly but report script errors when the script is executed.
Platforms & Tools: HyperCard: Error trapping in a HyperCard IIGS script
How can I perform error trapping in a HyperCard® IIGS® script?
Normally, most errors interrupt script execution and immediately present a dialog to the user. Advanced scripters may want to intercept these errors and deal with them more “aggressively.” Two new HyperCard properties, lockErrors and lastError, have been provided to control error handling:
• lockErrors is a Boolean property that has a simple effect: it prevents the display of errors. The errors, however, are still there, and stop execution of the current handler.
• lastError is a string property that always contains the text of the most recent error dialog, whether displayed or not. Because errors cause handlers to terminate, you’ll probably wind up checking lastError from an idle handler.
How do you use lockErrors and lastError? To activate an “error catcher” you can use the following scripts:
on CatchErrors errorSource -- Begin handling errors.
global gErrorSource
set the lastError to empty
set lockErrors to true
put errorSource into gErrorSource
end CatchErrors
on ClearErrors -- Handle errors normally.
global gErrorSource
set the lastError to empty
set lockErrors to false
put empty into gErrorSource
end ClearErrors
on idle -- Check for error occurrence.
global gErrorSource
if gErrorSource is not empty then
-- Error-handling code goes here.
-- gErrorSource = where in your code the error happened.
-- The lastError = what the error was.
end if
pass idle
end idle
If you have a button that does something dangerous, you can surround the dangerous portions of the handler with
on mouseUp
-- normal error handling out here
CatchErrors “dangerous operation #1”
-- Do things that might not work.
ClearErrors
-- Now we’re back to normal error handling.
end mouseUp
For more information, be sure to see the HyperCard IIGS Script Language Guide, published by Addison-Wesley.
Platforms & Tools: HyperCard: Converting Finder icons in a HyperCard IIGS stack
How can I install Finder™ icons into a HyperCard® IIGS® stack?
HyperCard IIGS icons are stored as individual resources in a stack or in the HyperCard IIGS program file. Finder icons were invented before there were resource forks for the Apple IIGS, so they’re stored in a special Finder- format icons file. There are several ways to convert them:
• Redraw by hand
• Use a third-party conversion tool
• Use a screen shot utility to take a “snapshot” of a screen containing the desired icon. Then import the picture, as paint, into the icon editor stack, and create an icon using the tools in the stack.
Platforms & Tools: HyperCard: Where to get HyperKRS information
How can I obtain information on the HyperKRS search engine that is used in the SpInside Macintosh stack?
HyperKRS is not an Apple product/technology. We actually licensed it from KnowledgeSet. You should get in touch with them for any additional information.
Platforms & Tools: HyperCard: Using HyperCard 2.0’s NewXWindow for XCMDs with windows
Is there anything special I have to do to let HyperCard® 2.0 know that I have created a window or does this happen in some magical way? Furthermore, is there any official Apple® technical documentation about these “hidden” features of HyperCard 2.0?
Yes Yes Yes!!! You should use the new callbacks to create and dispose of the window. In particular, you will probably want to use NewXWindow() to create the window. If you don’t use the callbacks, not only will HyperCard not know about the window, but Bad Things Will Happen™!
We don’t yet have sample code to demonstrate the creation of XCMDs with windows, but it’s really not that hard.
Platforms & Tools: HyperCard: HyperCard XCMD handle disposal
It is not clear from the “HyperCard® 2.0: The Extended XCMD Interface,” 4 Oct ‘90 documentation WHEN (or IF) an external is required to dispose of handles sent to it as a result of a callback or an event message. For example, when extracting parameters from an XWEventInfo record in response to a xSetPropEvt event, should the arguments in the eventParams array be disposed of by the external, or will HyperCard handle this when the event processing is completed by the external? What about “params” and “outArgs” in the XCmdBlock? Also, is it a safe assumption that HyperCard will dispose of all handles passed to it as arguments to callbacks, the result, or eventResult?
I think that in all cases where the programmer is responsible for disposing of the handles, the document states this. All of the cases you mentioned (params, outArgs, etc.) are cases where you DON’T have to dispose of anything. In general, the only things you have to dispose of are handles created by a callback which you AREN’T going to pass back to HyperCard. For example, if you use PasToZero() to create a handle, and you are returning this handle as your result, then you should not dispose of it. If, on the other hand, you’re using it only within your XCMD and not giving it back to HyperCard, then you should dispose of it when you are done.
Platforms & Tools: HyperCard: Get TERec to calculate text height for adaptive text fields
I’m inserting blocks of text of variable length into HyperCard® 2.0 card fields. I want these fields to act like buttons (so I don’t want them to be scrolling type). However, to make sure that long text chunks will fit, I must make the fields relatively large by default. This is fine for larger text chunks, but it looks pretty silly when I put small text chunks in. I need text fields that adaptively change their size to fit the text that they contain. I can think of some inelegant ways of doing it, like coming up with some sort of equation that relates number of characters to screen size (for example, 100 characters of Geneva 12 bold is about 400 pixels), but given that most fonts are nonproportional this equation may not hold up too well. Any ideas?
There is a solution for you, but it involves some XCMD programming. Keep in mind that there are many rectangles that could fit a given chunk of text: for example, text which fits in a rectangle 5 inches by 10 inches will probably also fit in a rectangle of 10 inches by 5 inches.
You could write an XCMD which uses the callback GetFieldTE to get access to the field’s TERec. This can be used to figure out how tall the field would have to be to fit all of the text. This approach will work as long as you only want to adjust the height of the field. You could still adjust the width but it just gets a bit more complicated.
Platforms & Tools: HyperCard: HyperCard trashed heap symptoms and solutions
Macintosh® HyperCard® 2.0 loads and executes several of my XCMD and XFCNs. Then, eventually, instead of running one of the XCMDs it simply SysBeeps. I noticed this happens when I set HyperCard’s MultiFinder® partition very high.
When HyperCard behaves that way, it’s usually because its heap has been trashed. Make sure your XCMDs and XFCNs are cleaning up after themselves properly. The easiest way to do this is by setting breakpoints at each of their entry points and getting a heap total on entry and on return. Checking the heap for inconsistencies is also a good idea.
Platforms & Tools: HyperCard: Sending an unexpected message to HyperCard
Is there a safe way to send a message to HyperCard® from an XCMD asynchronously, without requiring the XCMD to be polled from the HyperCard script’s idle loop?
When HyperCard isn’t (potentially) expecting a message, there is unfortunately no easy way to send it one. Is your XCMD an XWindoid? If so, and if you set it up to receive idle time, you can set a flag from your completion routine and actually send the message when your XWindoid gets called for idle.
Platforms & Tools: HyperCard: Where to find HyperCard limits
What are HyperCard’s limits, such as the size of fields or number of cards?
All of HyperCard’s limits are documented in Appendix G of the HyperCard® Script Language Guide (Addison-Wesley).
Platforms & Tools: HyperCard: HyperCard internal errors
What do HyperCard’s “unexpected error” numbers mean?
There is no published list of HyperCard’s internal errors. These errors indicate an internal HyperCard® error, not a problem with a script. Three possible causes are:
1. HyperCard doesn’t have enough memory.
2. An XCMD or XFCN has corrupted HyperCard’s environment.
3. The stack is corrupted.
If you repeatedly get HyperCard errors and you are sure none of the above conditions are causing them, report the problem to MacDTS.
Platforms & Tools: HyperCard: HyperCard internal structures are proprietary
What is the internal format of HyperCard® stacks?
HyperCard’s data structures and inner workings are proprietary; no programmer documentation is available for reading or writing stacks directly, or accessing any of HyperCard’s internal structures.
Platforms & Tools: HyperCard: Distributing HyperCard with your stack
Can I distribute HyperCard® with my stack?
Yes, but you must obtain a license from Apple Software Licensing. Contact them at (408) 996-1010, or AppleLink® SW.LICENSE. Be sure to carefully read the “Technical Guidelines” for distributing HyperCard included in the licensing package.
Platforms & Tools: HyperCard: International HyperCard
Is there an international version of HyperCard®?
Yes, but as of this writing the international versions of HyperCard 2.0 are not yet available. Watch this space for more information. APDA® will also distribute the international versions when they become available, so watch APDA too.
Platforms & Tools: HyperCard: HyperCard multi-user stack access
Is HyperCard® multi-user? Can stacks be shared on a network?
HyperCard is not multi-user. If a stack is made read-only, it can be viewed by simultaneous users, but stacks that are not read-only can only be accessed by a single user.
Platforms & Tools: HyperCard: HyperCard memory requirements
How much memory does HyperCard® need?
HyperCard version 2.0 will work in 700K, but just barely. Apple recommends that you not reduce its partition to less than 1000K. You will need more memory if your stack uses the paint tools, if you use any large sound resources, if you want to have lots of windows open all at once, or if you want to do anything else which uses lots of memory. Some XCMDs allocate memory, so you need to consider the size of the XCMDs as well as any memory they allocate.
Earlier versions of HyperCard don’t work well in less than 750K.
Platforms & Tools: HyperCard: How a HyperCard stack can get corrupted
How do HyperCard® stacks get corrupted?
While HyperCard is running, it has many objects in memory. These objects include cards, buttons, fields, scripts, and internal HyperCard data structures. If for any reason an object is corrupted in memory, or if it isn’t written to the stack on disk, the stack may be corrupted.
If the system crashes or loses power while HyperCard is running, the stack may be corrupted. HyperCard may run out of memory, or an XCMD may crash or corrupt HyperCard’s memory. XCMDs that allocate & dispose of memory, intercept events, access HyperCard’s data structures, or change resources in memory are most likely to corrupt HyperCard’s environment.
The best safeguard is to have current backups of your stacks. Before making a backup, make sure the stack isn’t corrupted. To check a stack for corruption, first compact the stack, then go to each card in the stack, using “show all cards” or something similar.
Platforms & Tools: HyperCard: How to recover a corrupted HyperCard stack
How can I fix a corrupted HyperCard® stack?
Broadly speaking, there are two classes of corrupted stacks: those that won’t open at all, and those that can’t get to one or more cards or backgrounds. There is currently no easy way to fix stacks that won’t open, but there is a way to get the good cards out of a broken stack that will open.
The basic technique is to identify the bad cards, then copy all of the good cards to another stack, skipping over the bad cards. Finding the bad cards is tedious, because HyperCard will quit when it encounters one. There are several stacks that automate the recovery procedure, including one from DTS called “Recover.”
In the future, Apple is planning to distribute a tool which will be able to fix some of the previously fatal kinds of stack corruption.
Platforms & Tools: HyperCard: HyperCard and background applications
Will HyperCard® run in the background under MultiFinder®?
Under versions of HyperCard previous to 2.0, scripts wouldn’t execute in the background, and HyperCard wouldn’t let itself be switched into the background. With version 2.0 and beyond, neither of these is true. Furthermore, HyperCard is now a slightly more polite foreground application--it gives time to background applications in between every executed line of HyperTalk®.
Platforms & Tools: HyperCard: HyperCard 2.0 visual effects work on all monitors
Why don’t visual effects work on some machines?
If visual effects don’t work on your monitor, you are probably using a version of HyperCard® previous to 2.0. Under HyperCard 2.0, visual effects should work on every kind of monitor.
Platforms & Tools: HyperCard: Painting over HyperCard buttons or fields
How can I paint over HyperCard® buttons or fields?
Paint in the card layer will overlay background buttons and fields. Background buttons and fields are always in front of background paint, and card buttons and fields are in front of card paint.
Keep in mind that fields with paint over them won’t print in the correct font. If any paint or buttons overlay any part of a field, the field will be printed as a bit map, not with the selected font. This only applies to printing cards, not printing reports.
Platforms & Tools: HyperCard: Painted HyperCard fields are printed as bit-mapped fonts
When I print HyperCard® cards on a LaserWriter®, fields are printed with bit-mapped fonts instead of the Postscript® fonts.
Fields with paint over them won’t print in the correct font. If any paint or buttons overlay any part of a field, the field will be printed as a bit map, not with the selected font. This only applies to printing cards, not printing reports.
Platforms & Tools: HyperCard: When “Recent” display has a blank slot
Why is there sometimes a blank slot in the “Recent” display?
When a HyperCard® card is deleted, or the stack it is in is deleted, that card’s image is removed from the “Recent” display.
Platforms & Tools: HyperCard: HyperCard 2.0 “find” works with card fields
Does the “find” work with HyperCard® card fields?
Now it does. (It didn’t used to.)
Platforms & Tools: HyperCard: HyperCard sorting
Is HyperCard®’s sort stable? How can I do multi-level sorts on several fields?
HyperCard’s sort is stable, meaning that it preserves the relative order of records with identical keys. If you sort a stack using a field as the sort key (sort by field xyz), and the sort field is empty in several cards, those cards will all sort to the front of the stack. Their order, relative to one another, is preserved after the sort.
You can use a stable sort to do multi-level sorts by sorting multiple times, starting with the lowest-order key and proceeding to the highest-order key. For example, to sort a stack by last name by first name, do:
sort by field "first name" -- first put in order by first name
sort by field "last name" -- now order by last name
Because the relative order of first names is preserved by the last name sort, the cards will be in order by last name, and by first name for all cards with the same last name.
Platforms & Tools: HyperCard: How to determine if a container contains a number
How can my script determine if a container contains a number?
HyperTalk® now has an expression for determining if a container represents a number. The syntax is:
myContainer is a number
This expression has a Boolean value: ”true“ if the expression is numeric, and ”false“ if it is not. You may also use expressions of the form:
myContainer is not a number
Note that the following is not legal syntax:
if I am not a number then I am a free man
Platforms & Tools: HyperCard: HyperCard global variable disposal
Is there any way to get rid of global variables I’ve defined in my HyperTalk® scripts?
There is no way to completely dispose of a global variable, but you can recover the space it occupies. Simply
put empty into theVar
to recover the space used by “theVar.”
Platforms & Tools: HyperCard: No HyperTalk error trapping
Is there some way to trap errors in HyperTalk®?
No. Some early versions of HyperCard® had a “cantUnderstand” message that was sent to the card when a HyperTalk error occurred, but the release versions don’t have any provision for error trapping. Under HyperCard 2.0, scripts are compiled before they are executed, so some errors are caught before the script actually starts running.
Platforms & Tools: HyperCard: Detecting command key with HyperTalk
Is there some way to detect when the command key is pressed?
Yes, with the “commandKey” function. Refer to page 245 of the HyperCard® Script Language Guide. The option and shift keys can also be detected with the “optionKey” and “shiftKey” functions. All of these functions return the state of the key—up or down.
Platforms & Tools: HyperCard: HyperCard single background “finding”
How can I constrain the “find” command to a single HyperCard® background?
Change your HyperTalk® “find” script to check the background and/or field names when it finds whatever you are looking for.
Platforms & Tools: HyperCard: What is the “dynamic path?”
What is the “dynamic path?”
Whenever a HyperTalk® message is sent, several objects get a chance to act on the message. For example, if a button receives a mouseDown message, first the button itself gets a chance at the message, then the card the button lives on, then the background the card lives on, and so on. However, when a script executes a “go” or “send” command to an object which isn’t in the hierarchy, and HyperTalk continues executing, something called the “dynamic path” comes into play. This mechanism allows both the “normal” inheritance chain and the inheritance chain of the “gone-to” card (or object) to affect the interpretation of the message. The easiest way to think of the dynamic path is to imagine that the object a message is “sent” to is put into the message hierarchy in front of the current object. For example:
on openCard
...
send openCard to card 1
end openCard
When the “send” command executes, card 1 is inserted into the message hierarchy in front of whatever object the executing handler is in. If card 1 has a different background than the original card, that background will also have a pass at the message.
Not understanding the dynamic path is a common source of strange recursion errors and other problems. For example, if card 1 from the example above had this handler:
on openCard
...
pass openCard
end openCard
the “openCard” message would be sent from the original card to card 1, then passed along (by the pass command) up the message hierarchy. The next object up the hierarchy is the original card, which would receive the openCard message and execute its openCard handler, which is already executing, thereby causing a recursion error.
The best way to understand the dynamic path is to write some scripts to experiment. It also helps to use “put” or “answer” commands in your scripts to follow the execution when you are getting recursion errors. For more information, see the new “HyperCard Script Language Guide” for HyperCard 2.0, pp. 55-58.
Platforms & Tools: HyperCard: HyperCard startup message order has changed
What is the order of messages sent when HyperCard® starts up?
These messages are sent to the first card when a stack is opened, in this order:
startup
openStack
openBackground
openCard
Note that this has changed from HyperCard 1.x. The old order didn’t make much
sense (thanks, Bill!), and Apple received feedback from developers that indicated this order was vastly preferred.
Platforms & Tools: HyperCard: “open with ” under MultiFinder
Why doesn’t “open <document> with <application>” always work under MultiFinder®? The application starts up, but the document isn’t opened.
The name of any document(s) to open at startup is passed to an application when it is launched. The application checks this information and opens or prints the specified documents (Inside Macintosh® Volume II, pages 55-56).
With MultiFinder, if application “A” (HyperCard®, for example) launches application “B” (which is what happens when HyperTalk® executes the “open…” command), and application “B” is already running, application “B” is switched in. Applications normally only check the list of documents to open or print when they start up, not when they are switched.
Platforms & Tools: HyperCard: How to license Apple-owned XCMDs, XFCNs, or stacks
How can I license XCMDs and XFCNs owned by Apple for use in my HyperCard® stacks?
If you plan to distribute Apple-owned XCMDs, XFCNs, or stacks in your product, you may need to obtain a license from Apple. Contact Software Licensing at (408) 996-1010, or AppleLink® SW.LICENSE.
Platforms & Tools: HyperCard: TNPict XCMD in Technical Notes stack can be licensed
Can I use the TNPict XCMD that’s in the Technical Notes stack?
You can arrange licensing for TNPict and other Apple-owned HyperCard® XCMDs by contacting Apple Software Licensing:
Apple Software Licensing
Apple Computer, Inc.,
20525 Mariani Avenue, M/S 38-I
Cupertino, CA, 95014
(408) 974-4667
AppleLink®: Sw.License
Internet: Sw.License
Platforms & Tools: HyperCard: Saving variable values between XCMD/XFCN calls
When my XCMD/XFCN returns to HyperCard®, all of its variables are lost. How can my XCMD/XFCN remember values of variables across calls?
Either put it into a HyperCard global variable, or allocate a relocatable/nonpurgeable block and store your information there, saving the handle to the block in HyperCard. Remember that HyperCard expects all values to be zero-terminate strings, so you must convert everything to that form.
{ save the value of 'myVar' in HC global }
temp := NumToStr(myVar); { convert to string }
hTemp := PasToZero(temp); { convert to C string }
SetGlobal('myGlobal', hTemp); { save in HC global }
DisposHandle(hTemp);
(Alternately, you could simply return the value in “the result.”)
To retrieve the value when your XCMD is invoked later:
{ retrieve 'myVar' from HC global }
hTemp := GetGlobal('myGlobal');
ZeroToPas(hTemp^, temp); { convert to Pascal string }
DisposHandle(htemp);
myVar := StrToNum(temp); { convert to number }
Instead of storing each variable you want to save in a HC global, you can create a block (with NewHandle), then just save & recover the handle using the technique above:
temp := LongToStr( Ord(myHandle) ); { convert handle to string }
...
myHandle := Handle( StrToLong(tempStr) ); {string to handle }
Make sure you dispose of the handles you create when you are done with them. Don’t lock blocks you create unless you have to, or you risk fragmenting HyperCard’s heap.
There is a sample XCMD avaliable from MACDTS which demonstrates this technique.
Platforms & Tools: HyperCard: How to use globals or string constants in an XCMD/XFCN
How can I use global variables or string literals in an XCMD/XFCN?
Think C™ from Symantec supports globals variables in 'CODE' resources—see the user manual, pp. 82-88.
If you are using MPW® or another development system besides Think C, see Tech Note #256 for information about creating your own A5 world for XCMDs which need global variables.
Note that if you are programming in MPW C 3.0 or later, you can use the “-b” option to make sure that string constants aren’t treated like global variables.
Platforms & Tools: HyperCard: Code for drawing into HyperCard’s port
How can an XCMD draw into HyperCard’s port and make HyperCard® “know about” the drawing?
The XCMD should do this:
...
hPic := OpenPicture(theRect);
ShowPen; { so you can see while drawing }
{ draw your picture here... }
HidePen;
ClosePicture;
HLock(hPic); { lock for de-reference }
{ put the picture on the clipboard }
err := ZeroScrap;
err := PutScrap( GetHandleSize(hPic), 'PICT', hPic^);
HUnlock(hPic);
DisposHandle(hPic);
...
From HyperTalk®, call your drawing XCMD (above), then paste the picture onto the card or background:
myDrawingXCMD -- leaves picture on the clipboard
lock screen -- to avoid flash from "paste"
doMenu "Paste Picture"
choose browse tool
unlock screen
Platforms & Tools: HyperCard: MPW HyperCard callback interface changes
The callback interfaces documented in the HyperCard® Script Language Guide don’t work in MPW® 3.0.
The callback routines were implemented as “glue” in MPW 2.0, but are implemented as a library in MPW 3.0; the Pascal callbacks were changed as well. If you are using MPW Pascal 3.0, look at
Interfaces:PInterfaces:HyperXCMD.p
for the correct interfaces. If you are using C, look at
Interfaces:CIncludes:HyperXCMD.h
Platforms & Tools: HyperCard: Macintosh HyperCard 2.0 XCMD WindowPtr documentation fix
Your document “HyperCard® 2.0: The Extended XCMD Interface” contains a minor error.
Within the body of the document, the header line for some procedure sections omits the WindowPtr argument. It appears just fine in the interface description at the end of the document.
Thanks for notifying us of this problem. We’ll correct the documentation as soon as we can.
Platforms & Tools: Installer: Network installation setup considerations
What are some of the considerations when configuring a network installation setup?
Under Installer 3.1 or 3.2, network software installations are made possible by setting up an installation folder on the server volume. This folder will contain the Installer application, the Script file, and a folder(s) matching the names of the required disk(s). Within the disk folder(s) are the corresponding contents of the disk(s).
One of the engineering problems which needed to be dealt with, can occur when a workstation is used to create the server installation folder. The problem occurs when the system date and time differ significantly between the workstation and the server. Under such a condition, files copied from the workstation to the server may have their creation and modification date time stamps altered. If a modification is made, the "delta" is constant for both the creation and modification date/time stamp and for all files copied at that time.
The Installer preflights a file by comparing its creation date/time stamp with the value stored in the corresponding 'infs' resource in the script file. To compensate for the fact that a server may alter a file’s creation date/time stamp, the Installer implements the 'incd' resource. After the user selects the Install button, the Installer reads the 'incd' resource and compares it with the script file’s creation date/time stamp. The difference is stored as the delta. On a normal disk installation, the delta is always zero. As the Installer finds each required source file, the file’s creation date/time stamp is converted to a long word and adjusted by the delta. The modified date/time stamp is then compared with that stored in the script file. If the values match, the file is considered found and the installation proceeeds. On network installations, the delta may be nonzero. If so, it indicates that the file’s creation date/time stamps were modified when copied to the server. Thus the 'incd' resource gives the Installer a way to maintain file verification even though the date/time stamp may be altered.
A specific problem can occur when an installation is set up on some systems running older versions of Novell Server software. Under specific conditions, files copied to some Novell servers have their creation time stamp altered to 12:00 AM regardless of the original time stamp. This includes the creation time stamp of the script file. This condition wreaks havoc with the Installer’s preflight mechanism. The delta determined between the 'incd' resource and the Script file’s creation date/time stamp may not be consistent with the creation date/time stamp stored in the 'infs' resource and the corresponding files time stamp now at 12:00 AM.
A workaround solution for this problem is to set the Creation time stamp for all files on the installation disk to 12:00 AM, BEFORE running the ScriptCheck tool. Use the MPW tool SetFile to perform this function. Here’s a sample MPW script for performing this function:
SetFile -d "1/1/91 12:00AM" `files -r -s -f ≈`
This script assumes that the current directory is set to the root of the Installation disk. For multiple disks, run this script on each disk.
Platforms & Tools: Installer: Macintosh Installer preflight checks
What checks are made by the Installer when preflighting an installation? Occasionally the alert “Could not find a required file…” occurs and the installation is aborted.
The Installer compiles a list of the source file specifications from each of the resource 'inra' and file 'infa' atoms specified among the package 'inpk' atoms included for installation. Each source file specification includes a complete path name. As each source file is accessed, a check is made of the files creation date/time stamp with the date/time stamp recorded in the corresponding 'infs' resource. If the date/time stamps do not match, the alert results and the installation is aborted.
Platforms & Tools: Installer: Macintosh 'incd' resource
What is the 'incd' resource about?
When the MPW ScriptCheck tool is used, it reads the script's file creation date/time stamp converting it into a long word with the Date2Secs procedure. ScriptCheck stores this long word in the 'incd' resource for use with verifying files when a network installation is performed.
Platforms & Tools: Installer: Including current Mac volume name with reportVolError alert
How can I include the current volume name in a reportVolError alert like many of the installation scripts from Apple do?
The volume name can be included by inserting “^0” as part of the Pascal string passed to the reportVolError error reporting clause.
Platforms & Tools: Installer: Why multiple 'DRVR' resources for DA installation
My Macintosh Installer script installs a Desk Accessory. Under System 6, each time I run the script, a new copy of the DA appears as a 'DRVR' resource in the System file. Why?
This happens when the dontDeleteWhenInstalling flag is used in conjunction with the updateExisting flag. The Installer 3.1 & 3.2 Scripting Guide indicates that resources marked with the dontDeleteWhenInstalling flag can be replaced with a new resource. The guide also indicates that the Installer will overwrite a preexisting resource in the target file if the updateExisting flag is set. Given these two flag settings, and the use of the replace byName (noByID) flag, the Installer does not delete the DA. Instead a new 'DRVR' resource is created with the same name but a new resource ID.
The correct Installer action is accomplished by setting the deleteWhenInstalling flag in conjunction with the updateExisting flag. On the other hand, use the dontDeleteWhenInstalling flag with the keepExisting flag.
Platforms & Tools: Installer: checkFileVersion clause and 'inrl' resource
How can I check for the existence of a minimum Macintosh file version?
Use the checkFileVersion clause as part of the 'inrl' Rules Framework resource. The format of the minimal-version parameter is shown in the InstallerTypes.r file as “#define Version.” The most common difficulties are in remembering that BCD values are required, and how to deal with two-digit version numbers. Some samples follow.
Assuming that the 'infs' target-filespec resource for the System file is 1000, then use the following clause to check for System 6.0.5:
checkFileVersion{1000, 6, 5, release, 0};
Assuming that the 'infs' target-filespec resource for the Finder file is 1001, then use the following clause to check for Finder 6.1.5:
checkFileVersion{1001, 6, 0x15, release, 0};
Assuming that the 'infs' target-filespec resource for the AppleTalk resource file is 1002, then use the following clause to check for AppleTalk version 53:
checkFileVersion{1002, 0x53, 0, release, 0};
Platforms & Tools: Installer: How Macintosh Installer locates source files
I notice that if I change the name of the installation disk, the Installer is still able to find the source files. How does this work? I’m writing an action atom code resource and I want to duplicate the source file-finding scheme implemented by the Installer, as described on page 30 of the “Installer 3.1/3.2 Scripting Guide.’
The Installer takes the source file spec and parses off the volume name leaving the filepath from the root of the current volume. It then searches for the filespec using this parsed file name from the root of the current volume. If the file is not found, then the search order continues with guidelines 1–4. In this manner, the Installer is able to install from disk copies of Installer disks when the diskette name has been changed.
Platforms & Tools: Installer: Installer 3.2 and preserving a file’s “locked” bit
When using the Apple Installer 3.2, source files which are locked become unlocked when the installer copies them to their destination. The installer preserves some of the other file attribute bits but not the locked bit. How can I preserve the locked bit? Will I have to write an action atom?
It appears that this is not a supported feature of the Installer. The problem here is that the locked bit is a Finder information setting. Were you to have your own Finder comments on a file source, you would find that these comments would no longer be part of the “installed” file.
In contrast, the Finder is designed to preserve this information during a copy. Apparently, the only method for preserving the locked bit is to do so through a post-installation action atom. You might use the target file 'infs' resource ID as the selector to the code resource, so that you can load the resource to determine the target file path.
Platforms & Tools: Installer: Macintosh Installer 3.1 makes backup copies of active files
If I start up from an 800K floppy disk with only the Macintosh® System and Finder™ files living on it (leaving some 350K of space free), and then try to use Installer 3.2 to move a 130K cdev and an 8K 'adbs' resource, I get a message that not enough disk space is available on the startup floppy disk. Installer says I need some 505K of space available, yet I am copying less than 150K. Why is this happening?
This results from the “live install” feature of the Installer. Because the floppy disk System file will be written to in this scenario, the Installer first attempts to make a backup copy of the system. This means that there needs to be additional disk space on the startup disk for a copy of all active files—in this case, the System file on the floppy drive. For the floppy there is insufficient room. If the system is started up from a different disk, the Installer installs the new resources into the inactive System file on a floppy disk without creating a backup.
Platforms & Tools: Installer: System 7.0 InstallInit.r sample script Types.h correction
When I Rez the InstallInit.r sample script which comes with the Installer package on the Macintosh® System 7.0 Golden Master CD, I encounter errors referencing the Types.h file. What’s going on?
This sample script was released without being edited to remove the reference to include the GestaltEqu.h file. In an early stage of System 7.0, the GestaltEqu.h consisted solely of #define statements which were useful in the CheckGestalt clause. With System 7.0b1, the GestaltEqu.h file was modified to include prototypes for the Gestalt, NewGestalt, and ReplaceGestalt functions. These prototypes required the inclusion of the Types.h file, including typedef statements that Rez does not understand. To correct this problem, simply delete the “include GestaltEqu.h” statement. Recent samples have been modified to correct this error.
Platforms & Tools: Installer: Current Macintosh Installer script references
I’m having problems creating an Installer script using the information in Macintosh® Technical Note #75. Why can’t I get Rez or SARez to work with the sample script in that Note?
I think the problem may be that you’re using the old installer information. The installer and its interface files have been completely revised. If your version of Technical Note #75 doesn’t say “Revised October 1990,” you’re referencing old information.
The new information is available on AppleLink™ and on the current Developer CD Series disc and the System 7.0 CD (Development Tools:Installer folder). On the CDs you’ll find a complete toolkit for writing installer scripts, including:
• The ScriptWriter’s Guide
• Interface files
• Script Checker application
• Sample scripts
Platforms & Tools: MacApp: Saving window state in pre-3.0 MacApp
How do I save new window size and location in a TWindows resource so it can be reused next time this window is opened or created?
To save your window state in an MacApp application, your implementation needs to do the following:
1. Create a record which holds the window state
2. Track whether the document is being opened or reopened
3. Read the window state information in your DoRead method
4. Restore or initialize the window state in your DoMakeViews method
5. Add in the number of bytes required for the window state when you compute the disk space required for the document file.
6. Write the window state when you save the document
You could store the window state record in the resource fork of the document file. Here’s a simple example:
TYPE
DocState = RECORD
theLocation : VPoint;
theSize : VPoint;
END;
HDocState = ^PDocState; {Handle to DocState information}
PDocState = ^DocState; {Pointer to DocState information}
In the document class, add some fields for keeping track of the state, as in the following code:
fDocState : DocState; {the record with the window state information}
fReopening: Boolean;
The fReopening flag is used to test whether the window state needs to be restored. If this is true, DoMakeViews should then know that it needs to restore the window state from the fDocState record. You need to set this boolean false in the Initialization phase of the Document object.
In the DoRead, check if the resource fork is open, and read in the record to the document field, and set the boolean to true.
Inside DoMakeViews, call another special method called RestoreWindow (or something similar) which takes the information in fDocState, and acts upon the window. For example, for window location, call the window Locate method and provide Locate with the values from the fDocState record. Then force the window on the screen. Same with the scroll location, call the ScrollTo, and provide any possible VCoordinates from the fDocState. Same also with the window size, use TWindow.Resize and resize the window according to the saved values.
Finally, you need to save the TView.fLocation, TView.fSize and other values in the fDocRec record, calculate how much space you need in DoNeedDiskSpace:
...
rsrcForkbytes = rsrcForkBytes + kRsrcTypeOverhead
+ kRsrcOverhead + sizeof(DocState);
And in DoWrite you add the resource to the resource fork, and before that catch the latest values in the various fields:
...
docStateHandle := HDocState(NewPermHandle(sizeof(DocState)) );
with docStateHandle^^ DO
BEGIN
theLocation := aWindow.flocation;
...
END;
AddResource(Handle(docStateHandle), kDocRsrcKind,
kDocStateID, 'Doc State');
FailOSErr(ResError);
...
END;
All this is slightly different in MacApp 3.0, because locations are in VPoints, and windows are keeping track of the location and size directly (fields in TWindow), so you need to modify the source code for this. MacApp 3.0 DrawShapes will also show how to save the window state information.
The LACS example in develop also has code that shows how to store and restore the window location information.
X-Ref:
“Asynchronous Background Networking on the Macintosh,” develop #2:1, Winter 91
Platforms & Tools: MacApp: %_BP and %_EP routines
When I attempt to link my program, the linker complains about %_BP and %_EP being undefined. What are these routines? Why are they needed? Why are they not being found?
The functions %_BP and %_EP are special routines that are conditionally called at the beginning and end of each procedure or function. This is designed for use by the MacApp® debugger, which uses these calls to follow the execution of the code being debugged. You can also put them to any purpose you wish, such as profiling.
Whether the calls to these routines are inserted is controlled through compiler directives: in MPW C, you can use the #pragma trace on|off directive to specify whether you wish these calls to be inserted. This can also be done with the compiler option -trace on|off|always|never, which makes the default state either on or off (the always and never options also override the #prgama trace directives). In MPW Pascal, you can control this feature with the {$D++} (which turns the calls on) and {$D--} (which turns them off) directives.
Generally, the routines themselves are supplied by a library you link with, such as the MacApp debugger or a profiling tool, so you won't need to write your own. If however, you decide to use this feature for your own devious purposes, here's how.
The procedures called are passed no arguments, and so should be defined as follows:
in MPW C,
pascal void BP()
or in MPW Pascal,
PROCDEDURE BP;
The only difficulty is that neither C nor Pascal allows you to create a function that begins with a % sign. Thus, you need to explicitly tell the linker to treat your functions, BP and EP, as %_BP and %_EP. To do this, add the options -ma BP=%_BP -ma EP=%_EP to your link statement, and all will be well.
Platforms & Tools: MacApp: Extracting text from MacApp TEditText views in dialogs
Where/when is the best place to extract text from my fill-in-the-blank Macintosh® dialog with several TEditText views? Does a method get called when another field is selected or another view (like a button) is chosen? I can think of several ways to accomplish what I want to do, but I’d rather use the MacApp® view architecture the way it is DESIGNED to be used.
You can get one answer to this by looking in the DemoDialogs example (C++ or OP). TView has a method called DoChoice, which should be activated, for instance, when a button, check box, or even with TrackMouse operating over a particular view or groups of view, has triggered something, and the application wants something to be done. Using MacBrowse, do a “Find References” (or Command-R) to find all references wherefrom DoChoice is called, such as TrackMouse or DoKeyCommand. Fields are Views, so they will inherit DoChoice, and in the case of TEditText you could, for instance, call DoChoice from HandleMouseDown (when clicking in a particular field).
HandleMouseDown is also a TView method, so most views have this one implemented. Special sub-Views have additional indicators that something was triggered inside the view.
Platforms & Tools: MacApp: Macintosh tear-off menus
Where can I find documentation describing the official way to implement tear-off menus in my Macintosh® application?
If you want to implement tear-off menus, you can use MacApp® 3.0 (when it’s released), or follow the article in MacTutor entitled “Tear-off Menus & Floating Palettes” in the ‘Best of’ MacTutor volume 4, page 112. The best approach is to use MacApp 3.0, but you won’t be able to implement tear-off menus using this wonderful application until it’s released.
The second method, described in MacTutor, is not supported by Apple. Many applications implement tear-off menus, so it is possible, but everyone that’s done it has done so on their own. We regret this, but there just aren’t any supported methods for implementing tear-off menus at this time. Because there currently isn’t a supported method, there isn’t any documentation, either.
Platforms & Tools: MacApp: MacApp and floating window support
Is there a way to add floating windows to a MacApp® application?
MacApp 2.0.1 contains experimental-and-unsupported code, and the floating window package is part of this code. Please check the source code (MacApp), and use the flag qExperimentalAndUnsupported for the build of the floating window code.
Official support for floating windows will be available from MacApp 3.0 forward. Meanwhile the Essential•Tools•Objects (E.T.O.) #3 CD contains an unsupported version of how to implement floating windows in MacApp 2.0.1.
Preliminary MacApp 3.0 is available on the E.T.O. CD starting with #4. Check the DrawShapes MacApp 3.0 sample for code showing how to program floating windows.
Platforms & Tools: MacApp: MacApp segmentation
What is the recommended method of segmentation for MacApp® applications? If I pull out my object modules and test them by themselves they function correctly. My application has now grown beyond my previous segmentation scheme and I’m back to the drawing board.
Yes, it makes sense to plan for segmentation with MacApp, mostly because the code segments tend to become very crowded, and also because Macintosh operating system does not have virtual-page memory paging, so it is the responsibility of the programmer to define where certain functions are in various segments. And MacApp will load those segments it needs—so the developer is in a way defining dynamically loaded libraries (and it makes sense to push certain methods which are seldom called into segments that reside most of the time on the hard disk instead of in the memory).
So try to separate all the methods in more segments, and to group methods that are related to the same segments. If possible create small segments, which load faster from disk to memory.
Here’s a suggestion list of where to place various methods in what segments (taken from the Dave Wilson MacApp training manual):
Segment name - routines
ARes - routines that get called often
DoSetupMenus
DoSetCursor
DoIdle
Draw
DoKeyCommands, if typing
ADebug - debugging code
AFields - your Fields methods
AInit - used only once (during the lifetime of the
application)
IYourApplication
ATerminate - used only when you quit
ASelCommand - for selecting commands
DoMenuCommand
DoMouseCommand
DoKeyCommand
TYourPasteCommand
IYourCommand
ADoCommand - for performing commands
TReColorCmd::DoIt
TSketcher::TrackMouse
TTypingCmd::Commit
AClipboard - for clipboard non-commands
MakeViewForAlienClipboard
GivePasteData
WriteToDeskScrap
AOpen - opening stuff
DoMakeViews
DoMakeWindows
IYourDocument
DoMakeDocument
IYourView
AClose - closing stuff
AReadFile - reading from disk
DoRead
DoInitialState
AWriteFile - saving files
DoNeedDiskSpace
DoWrite
AFile - rarely used
ANonRes - for routines you rarely call
ASomething - define your own segments and place related
methods here
Hint: If you are unsure where a method goes, put it in same code segment as the method that calls it.
The Mouser browser has a nice feature that shows the segment in which each method is placed—I use it myself a lot.
Another issue is that place segments that you don’t want to be unloaded automatically from memory in the 'res!' resource (good for methods that are time critical, and should not be unloaded to disk), and use the 'mem!' resource for defining how much to add to the basic temporary memory reserve memory size, permanent memory reserve, and stack space.
Platforms & Tools: MacApp: DAs shouldn’t be written in MacApp
Where can I find information about writing a desk accessory (DA) in MacApp®?
First, take a look at Macintosh® Technical Note # 239, “Inside Object Pascal,”which explains why, as an application framework, MacApp should be used to write only applications and MPW tools. Apple’s online MacApp forum and the MacApp Developers’ Association (MADA) are good points of contact for exchanging information about MacApp development. Contact MacApp.Admin on AppleLink® for details about the MacApp forum. MADA can be reached at 206-252-6946 or AppleLink address MADA.
Platforms & Tools: MacApp: Avoiding odd-address errors on 68000-based systems
My application crashes on Macintosh® SE but not Macintosh II systems while attempting to read a block of code into memory and parse it. The routine passes a pointer created by NewPermPtr to various objects and so that they can extract information and increment the pointer. The MacApp® debugger gives me the following message:
Exception #3 Address error: Word or long-word reference
made to an odd address
Bad address was: INVALID! ($0005372D)
You can get odd-address errors with 68000-based machines. Starting with 68020 the CPU is able to fetch data from odd addresses. Anyway, it’s a common problem to get into trouble with data fetched from odd addresses with 68000- based platforms. It could happen that the data you are saving and later retrieving has odd length, and so the next fetch will start on an odd address.
To guarantee that the data will always start on even boundaries, use the MacApp OffsetPtr global routine. Here’s the new MacApp 3.0 C++ version of this routine:
pascal void OffsetPtr(Ptr& p, long offset)
{
p += offset;
if (((long) p) & 1)
++p;
}
The function tests if the pointer is pointing at an odd address, and if so it increases the pointer one byte. You could do something similar in your member function, such as:
short* sptr = (short*)buf;
fValue = *sptr;
OffsetPtr(buf,sizeof(short)); // instead of buf+= sizeof(short);
Platforms & Tools: MacApp: MacApp developer technical support options
Is there a special address for MacApp® technical support or is MacDTS the correct target?
MacDTS is an option, though there are also other avenues of tech support for MacApp programmers as well. The first is the group address MacApp.Tech$. This is a group of MacApp developers on AppleLink that ask and answer questions of each other. You can simply send your questions to that address and request replies back to your personal account, or you can join the group and receive copies of all the mail sent to it by sending a request to MacApp.Admin.
Another avenue of support is from the MacApp Developer’s Association. This is a non-profit organization set up by MacApp lovers. It’s got about 1500 members across the nation, and even has a European counterpart. It has an annual MADA conference and a bimonthly magazine. If you are interested, call them at (206) 252-6946, or write to them at AppleLink address MADA. Annual fee is $75.
Platforms & Tools: MacApp: Debugging options for C++
What is the C++ equivalent for the {$D±} Object Pascal compiler directive? I’d like the same debugging options for C++ that exist for Object Pascal.
The MacApp® debugger is supported with C++ Object Pascal object information. In other words, you can’t trace other objects than those derived from PascalObjects.
This works OK if you include a “-trace on” or “-trace always” with CFront when you compile your MacApp source code. We assume that you are using the latest MPW® C++ (3.1 final and MPW 3.1ß C tools). Use either the startup file and include this as one of you basic parameters, or send it from MABuild.
We did some testing, and it seemed to work OK. In general the S (stack info) command with the MacApp debugger has a lower signal/noise ratio than the R (recent PC) command concerning useful information, but both work OK.
Platforms & Tools: Macintosh Common Lisp (MCL): Highlighting Macintosh Common LISP table dialog strings
I have defined a table dialog with “sequence dialog items” in the form of a list like
(("string1" . (function1)) ("string2" . (function2)) … )
How can I highlight the strings so that they are highlighted when the table dialog appears on the screen?
Create the window with (... :WINDOW-SHOW NIL ...), highlight cells with CELL-SELECT, and then ask the window to (WINDOW-SHOW).
Platforms & Tools: MacsBug: Byte-wide accesses for db, dw, and dl commands
Macsbug uses byte accesses when I issue the dw command in slot space to display a word.
MacsBug always makes byte-wide accesses to fetch data for the db, dw, or dl commands. This is to avoid errors that might be caused if you supplied an odd address on a 68000-based Macintosh.
To accomplish what you need to do, write a tiny 'dcmd' which explicity fetches and displays a word. This should only need to be a couple of lines long. How to write a 'dcmd' is documented in the files accompanying MacsBug on the Developer CD Series discs.
Platforms & Tools: MacsBug: MacsBug Heap Zone “!” flag
What does the “!” mean when I use the MacsBug Heap Zone (HZ) command? It appears in front of one of the zone names listed, or just after the address if the zone doesn’t have a name.
MacsBug’s HZ command does a quick-and-dirty heap check, and if it thinks something is wrong with a heap, it puts the exclamation point after the address range of the heap. If you select the heap flagged with a “!” with the Heap Exchange (HX) command and then use the regular Heap Check (HC) command, MacsBug tells you what it thinks is wrong with that heap.
Platforms & Tools: MacsBug: Macintosh 'dcmd' resource format
What is the format of a 'dcmd' resource?
The following information is taken from the MacsBug Reference manual, available from APDA:
A 'dcmd' resource begins with a 4-byte segment header, followed immediately by the program code. Since a 'dcmd' is limited to single segment, the segment header is used to specify a 'dcmd' version number and the amount of global variable space MacsBug needs to allocate for the 'dcmd' (that is, the size of its “A5 world”)—word of version followed by word of size.
Platforms & Tools: MacsBug: Trick for accessing MacsBug TargetZone variable
How can I get the target heap for my MacsBug dcmd? My command currently operates on whichever heap is in TheZone. It seems better to be operating on the target heap as that is what other currently available heap commands do.
In recent versions of MacsBug, there’s a predefined variable that contains the target heap zone; as you might guess, it’s “TargetZone.” Currently there’s no call-back to allow your dcmd to access this variable, but here’s a workaround: Write your dcmd as though the first parameter is always TargetZone, and the second parameter is an optional override for the first. Then, always call your dcmd through a macro; name the dcmd “htx,” and create a macro “ht” that expands to “htx TargetZone.” This will give your dcmd access to the TargetZone variable.
MacsBug User’s Guide and Reference—for MacsBug 6.2, Addison-Wesley
Platforms & Tools: MacsBug: Using Discipline with MacsBug
At the 1991 WWDC debugging session, mention was made of using Discipline with MacsBug. How this is done? Copies of Discipline on AppleLink and on the Developer CD Series discs never include documentation. When I install Discipline and reboot, I get the “MacsBug Installed” line in the original dialog, but then I always get a “No debugger installed” dialog from Discipline.
Discipline’s “No debugger installed” dialog is not a common message, but it can happen if you use try to use old versions of Discipline or MacsBug, or a third-party debugger that isn’t compatible with Discipline. Discipline also displays this message if you have Macintosh IIci ROMs in your IIx, and thus it can’t tell whether you have a 24-bit or 32-bit machine.
If you’re running System 7, you should use MacsBug 6.2.1 or later and Discipline 2.0.1 or later. You might even want to upgrade to Discipline 2.1d1, available on the Essentials•Tools•Objects (ETO) #5 CD.
To use Discipline with MacsBug, put the Discipline system extension into the Extensions folder (in your System Folder), and put the strict or lenient Discipline Startup document into your System Folder. For help on the Discipline commands, simply break into MacsBug and type DSC ? <return>. Pressing return additional times scrolls through the various pages of help.
Our lack of documentation on this tool does make it a little difficult to use. Hopefully we will be addressing that in the near future.
Platforms & Tools: MacsBug: Debugger Prefs HFSDispatch macros fixed on MacsBug 6.2.2
Why don’t the “HFSDispatch” macros that are included in the MacsBug 6.2 Debugger Prefs file work? When we try any of those macros, we get the error message “unrecognized symbol ‘HFSDispatch’” from MacsBug.
You must be using MacsBug 6.2.1. During the build of that version of MacsBug, one file was left out of the build script by mistake and it had some predefined constants that are needed by some macros. This has been fixed with MacsBug 6.2.2, available on the latest Developer CD Series disc.
Platforms & Tools: MacsBug: Macintosh IIfx MacsBug requirements
What version of MacsBug is required for a Macintosh IIfx?
Macintosh Technical Note #271, “IIfx: The Inside Story,” gives you Macintosh IIfx hardware and software details, including what version of MacsBug you need to use. You must have MacsBug 6.2 or later, as earlier versions are incompatible with the new hardware. You can get the latest MacsBug from APDA, the current Developer CD Series disc, and on AppleLink (in the Tools folder of Macintosh DTS). You can download Macintosh Technical Note #271 from AppleLink if you don’t have a copy.
Platforms & Tools: MacsBug: MacsBug and DebugStr documentation
Where can I find documentation on the Debugger and DebugStr calls? Also, I'm fairly certain I've seen a MacsBug® manual somewhere, but I've checked the latest Developer CD and find only a beta copy, and delta documentation. I've checked the Tech Notes stack, but there doesn't seem to be anything there on it.
Yes, there actually is a MacsBug manual, and on pages 107-109 are brief examples of how to use DebugStr in C, Pascal, and Assembly. MacsBug 6.2 hasn't really changed any of this since 6.1 (to my knowledge), but the MacsBug 6.2 manual should be a little more informative. MacsBug 6.2 is final, so the manual shouldn't be too far behind. You can purchase it from APDA. They can be reached at 800-282-2732.
As for other documentation on this, Macintosh Technical Note #280, “Bugs in MacApp? Yes, But I Love It!” has a little piece of sample code using DebugStr, and Inside Macintosh Volume VI on the System 7.0 CD describes how to properly exit debuggers.
Platforms & Tools: MacsBug: MacsBug heap check/scramble/purge dcmd
Is there a way to get MacsBug to do a heap purge in the same way that TMON does? I would like to be able to run my programs with a heap check/scramble/purge performed automatically after each trap. Would it help to write a dcmd?
Both the Product Manager and Engineer on the product said MacsBug can’t do a heap purge, so I tried the alternative you suggested, writing a dcmd.
This solution seems to work out well. I patch NewPtr, NewHandle, SetPtrSize, SetHandleSize, ReallocHandle, and MoveHHi. Whenever one of these is called, and the user has turned on heap purge (with “hp” in MacsBug), all purgeable handles are dumped by calling EmptyHandle.
I’ve included the MPW C source code below for you to play around with. I’ve also suggested to the Product Manager that heap purge be something we put into MacsBug in the future.
-----------
File: HP.c
-----------
/* HP.c
This is the Heap Purge dcmd.
The following MPW commands will build the dcmd and copy it to the
"Debugger Prefs" file in the System folder. The dcmd's name in
MacsBug will be the name of the file built by the Linker.
You must first copy dcmd.h, dcmdGlue.a.o and DRunTime.o from the
C Samples folder into this folder.
Asm hp.a
C -r -b hp.c #-sym on,novars,notypes -mbg off # for UltraSlimFast
Link dcmdGlue.a.o hp.c.o hp.a.o put.c.o DRuntime.o "{Libraries}"Interface.o
-o hp
BuildDcmd hp 1235
#Echo 'include "hp";' | Rez -a -o "{SystemFolder}TMON Folder:DCMD Holder"
Echo 'include "hp";' | Rez -a -o "{SystemFolder}Debugger Prefs"
DumpObj hp.c.o > hp.dumpObj
UltraSlimFast hp.dumpObj >hp.UltraSlimFast
*/
#include <Types.h>
#include <Memory.h>
#include <OSUtils.h>
#include <Files.h>
#include <Menus.h>
#include <Traps.h>
#include "dcmd.h"
#include "put.h"
extern pascal void NewNewPtr();
extern pascal void NewNewHandle();
extern pascal void NewReallocHandle();
extern pascal void NewSetPtrSize();
extern pascal void NewSetHandleSize();
extern pascal void NewMoveHHi();
extern pascal void SaveOldTrapAddress (long address, short addressKind);
extern pascal void SaveMyA5();
extern pascal long GetMyA5();
#define kOldNewPtr 0
#define kOldNewHandle 1
#define kOldReallocHandle 2
#define kOldSetPtrSize 3
#define kOldSetHandleSize 4
#define kOldMoveHHi 5
#define sysZoneMask 0x0400
Str255 pDumpString;
char ch;
Boolean purgingOn;
pascal void PurgeIt(long blockAddress, long blockLength, long addrOfMasterPtr, short blockType, Boolean locked, Boolean
purgeable, Boolean resource)
{
#pragma unused (blockAddress, blockLength, addrOfMasterPtr, resource)
if ((blockType == relocatableBlock) && (!locked) && (purgeable)) {
EmptyHandle((Handle)addrOfMasterPtr);
}
}
Boolean IsSysZone(unsigned short TrapWord)
{
return( (TrapWord & sysZoneMask) != 0);
}
pascal void PurgeAllBlocks(unsigned short TrapWord)
{
THz oldZone;
long oldA5;
oldA5 = SetA5(GetMyA5());
if (purgingOn) {
if (IsSysZone(TrapWord)) {
dcmdSwapWorlds();
oldZone = GetZone();
SetZone(SystemZone());
dcmdSwapWorlds();
}
dcmdForAllHeapBlocks(PurgeIt);
if (IsSysZone(TrapWord)) {
dcmdSwapWorlds();
SetZone(oldZone);
dcmdSwapWorlds();
}
}
(void) SetA5(oldA5);
}
TrapType GetTrapType(short theTrap)
{
// OS traps start with A0, Tool with A8 or AA.
return((theTrap & 0x0800) ? ToolTrap : OSTrap);
}
void PatchTrap(short trapNumber, short saveOffset, long newAddress)
{
// Use NGetTrapAddress since it is always safer on
// current machines. Take the result it gives me, and
// save it off in asm land, for future reference. Then,
// move in the new address of the routine, my asm glue.
SaveOldTrapAddress(NGetTrapAddress(trapNumber, GetTrapType(trapNumber)),
saveOffset);
NSetTrapAddress(newAddress, trapNumber, OSTrap);
}
void InstallPatches()
{
// Patch the traps… These are being patched in the world,
// not in the debugger world. Switch over to the real
// world, in case the debugger does world swaps. TMon Pro.
dcmdSwapWorlds();
PatchTrap(_NewPtr, kOldNewPtr, (long) NewNewPtr);
PatchTrap(_NewHandle, kOldNewHandle, (long) NewNewHandle);
PatchTrap(_ReallocHandle, kOldReallocHandle, (long)
NewReallocHandle);
PatchTrap(_SetPtrSize, kOldSetPtrSize, (long) NewSetPtrSize);
PatchTrap(_SetHandleSize, kOldSetHandleSize, (long)
NewSetHandleSize);
PatchTrap(_MoveHHi, kOldMoveHHi, (long) NewMoveHHi);
// Switch back to debugger world.
dcmdSwapWorlds();
}
pascal void CommandEntry(dcmdBlock* paramPtr)
{
switch (paramPtr->request)
{
case dcmdInit:
SaveMyA5();
purgingOn = false;
InstallPatches();
break;
case dcmdHelp:
dcmdDrawLine("\php");
dcmdDrawLine("\p Toggle Heap Purge on and off.
When on, heap purge purges
purgable blocks");
dcmdDrawLine("\p on NewPtr, NewHandle, ReallocHandle,
SetPtrSize, SetHandleSize, and
MoveHHi");
dcmdDrawLine("\p calls.");
break;
case dcmdDoIt:
dcmdDrawLine("\pHeap purge is ");
if (purgingOn)
dcmdDrawString("\poff.");
else
dcmdDrawString("\pon.");
purgingOn = !purgingOn;
break;
default:
PutPStr("\pUnknown request ");
PutUDec(paramPtr->request);
PutLine();
break;
}
} // CommandEntry
-----------
File: HP.a
-----------
include 'SysErr.a'
include 'SysEqu.a'
include 'Traps.a'
allRegs REG D0-D7/A0-A5
proc
import PurgeAllBlocks
; ———————————————————————————————————————————————————————————————
;
export SaveMyA5, GetMyA5
pMyA5 dc.l 0
SaveMyA5
lea pMyA5,A0
move.l A5,(A0)
rts
GetMyA5
move.l pMyA5,4(SP)
rts
; ——————————————————————————————————————————————————————————
;
; Storage for the old patch addresses, used to call through
; once the patch code executes. These are essentially globals,
; used by the asm code. They are specifically not exported,
; so that the Pascal code cannot access them directly. There
; are a number of interface routines I set up so that Pascal
; can get and set them, but has to go through this file.
; You know, sort of object like.
;
pFirstSavedTrap equ *
pOldNewPtr dc.l 0
pOldNewHandle dc.l 0
pOldReallocHandle dc.l 0
pOldSetPtrSize dc.l 0
pOldSetHandleSize dc.l 0
pOldMoveHHi dc.l 0
; ————————————————————————————————————————————————————————————
; When I'm am setting up the world, I call NGetTrapAddress
; to get the old version of the traps. I need to save that
; dude off so I can get back there when needed. This routine
; is a handy interface to the high-level world, isolating this
; asm junk from the code. All these routines are the same,
; just a different variable being affected. This hunk uses
; the PC-Relative addressing mode in order to get the address
; of the variable being set. This allows the code to function
; without any explicit global space, since the code acts like
; globals here.
;
; The interface is:
;
; PROCEDURE SaveOldTrapAddress (address: LongInt; addressKind: Integer);
;
export SaveOldTrapAddress
SaveOldTrapAddress
MOVE.L (SP)+,A0 ; get the return address
move.w (SP)+,D0
asl.w #2,D0
LEA pFirstSavedTrap,A1 ; the variable
to be setting
MOVE.L (SP)+,(A1,D0.w) ; save it, pulling
parameter too
JMP (A0) ; it's saved, return
to high-level
export NewNewPtr, NewNewHandle, NewReallocHandle
export NewSetPtrSize, NewSetHandleSize,
NewMoveHHi
NewNewPtr
move.l pOldNewPtr,-(SP)
bra.s Common
NewNewHandle
move.l pOldNewHandle,-(SP)
bra.s Common
NewReallocHandle
move.l pOldReallocHandle,-(SP)
bra.s Common
NewSetPtrSize
move.l pOldSetPtrSize,-(SP)
bra.s Common
NewSetHandleSize
move.l pOldSetHandleSize,-(SP)
bra.s Common
NewMoveHHi
move.l pOldMoveHHi,-(SP)
; bra.s Common
Common
movem.l allRegs,-(SP)
move.w D1,-(SP)
bsr PurgeAllBlocks
movem.l (SP)+,allRegs
rts
ENDP
END
Platforms & Tools: MPW: Window-splitting resource format for MPW 3.2
Window-splitting resource format for MPW 3.2
The Macintosh window-splitting resource 'MPSR' (ID =1008) for MPW 3.2 contains a 20-byte header, followed by an array of 10-byte elements that describe how to make the panes. Its fields are defined as follows, subject to revision in future MPW releases:
The Header:
rect (8 bytes) Open Rectangle (zoomed out size)
rect (8 bytes) Close Rectangle (zoomed in size)
long (4 bytes) First position (offset into file of upper left
corner for the lower right pane)
Each Element:
enum (1 byte) Orientation - (none = 0, row = 1, column = 2)
pad (1 byte)
short (2 bytes) PaneSpec - an ID number, the pane to split
short (2 bytes) Size - offset from top or left for the split
long (4 bytes) First Position - first character position
in the pane
The last element in the array is a null element with Orientation = none.
The PaneSpec is used to locate the pane to split. A Pane spec consists of 5 3-bit fields. [0 eee ddd ccc bbb aaa]. Panes can be nested up to 5 levels deep. A pane can be split up to 7 times (3 bits).
Platforms & Tools: MPW: Use File Manager SetEOF calls to do “lseek” file sizing
Using standard C I/O calls, I would create a new file of a specific size with the following code:
int n;
n = creat( "filename" );
lseek( n, the_size_I_want, 2);
However, under MPW 3.1 the lseek call always returns -1 with errno set to 6 (ENXIO). The only workaround I have found is to actually write the number of dummy bytes into the file before I have to seek around in it. Is there a call resembling the UNIX call ftruncate, or must I use stdio calls rather than fctnl calls?
MPW C lseek is not capable of increasing file sizes, as in the UNIX lseek code. The best way to achieve file sizing is to use the File Manager SetEOF calls, which can grow a file to whatever size (using Create, Open and SetEOF). Many of the low-level C I/O routines don’t work exactly like they work under other platforms, and this is a known worry when moving source code between PC, Macintosh and UNIX platforms. If possible, use the ANSI C file I/O routines.
Platforms & Tools: MPW: SIOW libraries run in 32-bit mode
Comments in the SIOW.r file indicate that the Standard I/O Window (SIOW) software is not 32-bit clean. Are there any known bugs that crop up if the current software is run in 32-bit mode anyway?
The “not32BitCompatible” setting in the SIZE resource is ignored, more or less. Originally, it was going to trigger an alert like “Be careful - this application may crash!” if the system was running in 32-bit mode; thankfully, this alert was removed before System 7.0 was shipped (though A/UX® still has it).
As far as the SIOW libraries are concerned, there isn’t anything about them that restricts their use to 24-bit environments. Other than the problems discussed in the release notes that come with MPW® 3.2 (which includes SIOW), Apple doesn’t know of any bugs with SIOW.
Platforms & Tools: MPW: Intro to OOP tutorial Lab 1 interface file update
When I try to compile Lab 1 of the Intro to OOP CD-ROM tutorial, I get a stack smashed into the heap error! Any ideas?
Try increasing memory partition for the MPW® Shell using Get Info. Also, the MPW interface file TYPES.h has been modified since MPW® 3.1. You will need to edit one line of the file, UTILS.h. UTILS.h can be found in the folder: “IntroToOOPLabs :C++:CourseLibrary:” Here is the segment of code as it appears in the shipping version of intro to OOP:
inline void Copystr255(const Str255 from, Str255 to)
{
BlockMove((Ptr) from, (Ptr) to, Length(from) +1;
}
Replace the above code with:
inline void Copystr255(const Str255 from, Str255 to)
{
BlockMove((Ptr) from, (Ptr) to, Length((StringPtr) from) +1);
Platforms & Tools: MPW: System 7 & MPW 3.x?
Will MPW® 3.1 work with System 7.0?
MPW 3.1 won’t work with System 7.0. The MPW 3.2 Shell is on the final System 7.0 CD, along with MPW 3.2 Choose, release notes, help files, and Include files. The other MPW 3.2 Tools are not included on the System 7.0 CD, but are available from APDA® as a standalone product and as part of the Essentials•Tools•Objects (ETO) #4 CD.
Platforms & Tools: MPW: MPW Backup command problem report
When I use the MPW® Backup command to generate a list of Duplicate commands, everything works properly with the form:
Set FileList 'Tweety 640:All Files'
Export FileList
Set newerFiles "Tweety 640:Newer Files"
Export newerFiles
Backup ∂
-from 'Tweety 640:Empty Folder:' ∂
-to 'Tweety 640:Taz:SCSI 90:' ∂
-r -check newer -a ∂
> "{newerFiles}"
But when I use the form:
Backup ∂
-from 'Tweety 640:Empty Folder:' ∂
-to 'Tweety 640:Taz:SCSI 90:' ∂
-a -r -since '01/01/04' ∂
> "{FileList}"
The “to” or destination folders are not correctly generated in the output file. An example is shown below:
Duplicate 'Tweety 640:Empty Folder:AppleLink:MachApp.Tech$' 'Tweety
640:Taz:SCSI 90:MachApp.Tech$' ### New File ###
Duplicate 'Tweety 640:Empty Folder:AppleLink:More on Daystar' 'Tweety
640:Taz:SCSI 90:More on Daystar' ### New File ###
Note that the Duplicate commands being generated are copying everything into the “to” folder instead of recursively generating sub-folder names as it does in the first form of “Backup” (without a -since option). What am I doing wrong?
I tried to duplicate everything that you’ve done, and I came up with exactly the opposite results: Using the MPW 3.2 Backup command with the -check newer parameter, subdirectories are NOT generated recursively, but with the -since '01/01/04' parameter, the Backup command does generate subdirectories recursively! As I understand it, this is exactly the opposite of what happened for you! In either case, it looks like you’ve found a bug with the Backup tool.
Platforms & Tools: MPW: MPW 3.1 doesn’t work with System 7
Will MPW® 3.1 work with Macintosh® System 7?
MPW 3.1 will not work with System 7.0. You should be using the latest version of MPW 3.2 that’s on the 7.0 CD or on the latest ETO (Essentials•Tools•Objects) CD. You can copy the entire MPW 3.2 folder off of one of the CDs.
Platforms & Tools: MPW: Directory can’t be prerequisiteFile in an MPW dependency rule
We are working on a project with MPW®. Is there a way to set up our makefile for the main project so that it is dependent on the source files from the library (already constructed), not the object file produced by running lib? Is there a way to refer to a directory (rather than a file) as a prerequisiteFile in a dependency rule?
That’s a great suggestion, but unfortunately it isn’t possible (at this time) to have a directory as a dependency. I will definitely forward the suggestion along to the appropriate people.
Platforms & Tools: MPW: Macintosh System 7.0ß1 Get Info window problem
The Macintosh® System 7.0 memory current size box seems to allow the the user to enter only four digits. How can I address a greater amount of memory?
The problem which you are seeing with 7.0 is known. The only problem is that the text field is too small. The information is still getting through. If you open the Get Info window and type into the Application Heap size field, you can get the size you want. At first it will not look like you got what you wanted, but if you close the window and bring it back, then it will look correct. An example of what I do and what it looks like is as follows:
-I select MPW
-say Get Info
-The current size says that I have a heap partition of 8000, but I want it to be 14,000
-So I select the 8000 and type “14000”
-The current size says that it is 14000 with part of the 1 cut off.
-I close the window and reopen it
-The current size says that it is 14000 with part of the last 0 cut off
-I launch the application
-From Finder™ I look at About This Macintosh and the partition for MPW is
14,000K
Seems to me that an earlier version of 7.0 (I am currently using a version ß3) did not show the 14000 at first but only a 1 or a zero. Either way, it still allowed you to set the partition to the size you wanted. There is still a limit and the limit is 100,000K.
Platforms & Tools: MPW: Which development system should I use for Macintosh development?
Should I use C or Pascal for Macintosh® development? Which language is better? Which development system should I use?
Asking MacDTS which language is better is like asking the Rolling Stones what their favorite song is: the answer depends on whom you ask and the mood they are in.
Use the language that you are most comfortable with. MacDTS engineers use both C and Pascal. Both languages have advantages and disadvantages. Many people complain that C is terse and unreadable. Others say that Pascal is too verbose, and that its lack of knowledge about the machine can make programming awkward.
There are many good development systems. MPW® is powerful and extensible, but it requires a lot of hardware to run efficiently. Both Think™ languages (from Symantec) are fast and easy to use, but they aren’t extensible at all. There are also good languages from other vendors, including Semper Software™ Modula- 2, Language Systems™Fortran, MicroSoft™ and Zedcor™ BASIC, and Allegro Common Lisp from Apple (formerly from Coral Software).
Officially, Apple doesn’t recommend any particular language or development system.
Platforms & Tools: MPW: Installing MPW 3.0
The MPW® installer is reporting that it can’t find the “DoIt” script. What is wrong and how can I properly install MPW?
The problems installing MPW 3.0 could be due to a limitation of the installation script—that is, using the Installer we provide will not work if there are single or double quotes, or other special characters, in the full pathname of the destination folder. This is noted in the MPW manual under “Getting Started.” The solution is to either install MPW by hand (not hard unless you’ve never done it before and don’t know where everything goes), or to rename your hard disk with a simpler name. Since most of MPW complaints occur when your hard disk’s name has an apostrophe in it, I would suggest the latter method.
Another possible problem is caused by a bug in some third-party 'INIT's that cause the MPW installer to fail. This bug is caused by those 'INIT's using PBHSetVol and changing the default volume behind MPW’s back. This problem is frequently reported by users with TOPS (from TOPS, a Sun Microsystems company).
Some 'INIT's use PBHGetVol to get and save the working directory, then attempt to restore it using PBHSetVol, but end up setting the working directory to the root instead. Macintosh Technical Note #140, “Why PBHSetVol is Dangerous,” warns against using PBHSetVol.
Not only do these 'INIT's interfere with the installer they can also interfere with other MPW operations, most commonly when MPW tries to access a script in your current directory or a tool tries to open a script in the current directory.
To work around the installer problem, you can:
1. Manually install MPW;
2. Disable any 'INIT's (remove them from the System Folder and reboot), then run the installer. (Note: you can prevent TOPS from loading by holding down the command key while you reboot);
3. Use a text editor to edit the file “Startup” in the Installation Folder. Search for the line starting with “DoIt” and insert the line “directory” immediately before it. This will force the MPW shell to reset the working directory. Save the Startup file and perform the installation procedure as documented.
Any 'INIT' that uses PBHSetVol will interfere with the setting of the working directory whenever a disk is inserted while MPW is running. You will have to issue a “directory” command to make the MPW shell reset the working directory.
Platforms & Tools: MPW: Calling/linking external routines
I’m trying to call external routines, written in assembler or some high-level language, from my C program, but the linker complains that my procedure is not defined anywhere. How can I make it accessible from C?
C is case sensitive, while some other languages, notably Pascal, are not. Pascal generates an all uppercase symbol names for any of your procedures. (For example, MyProc causes the Pascal compiler to create an entry point symbol named MYPROC.)
In C, if you are declaring a C routine, the name is case sensitive, For example,
extern MyProc();
requires an entry point named MyProc, but
Pascal MyProc();
requires an entry point named MYPROC, consistent with the Pascal compiler.
The assembler can be either case sensitive or case insensitive. Use the
CASE ON ; For C
directive to make the assembler case sensitive like C. Make sure your assembler routines match their expected usage.
If all else fails, you can use the linker -ma option to remap entry point names to satisfy unresolved references.
Platforms & Tools: MPW: MPW 3.0 max global data size is >32K, max local data still 32K
Is the maximum size for global and local data still 32K?
Starting with MPW® 3.0, the maximum size for global data in MPW became larger than 32K, using compiler and linker options -m and -srt. Local data is tougher, because local data is allocated by using the LINK instruction—for example, LINK A6,#$-380. With this relative addressing mode, you’re constrained to the negative side of a 16-bit value for local space, which translates to 32K. In other words, this limit is basically due to the Motorola processor architecture.
If you are allocating more than 32K either globally or locally, you might want to rearchitect your system to use dynamic (and theoretically unbounded, especially on virtual architectures) storage space.
Platforms & Tools: MPW Assembler: MPW Assembler and “~” character
When I try to turn on Macintosh interrupts after simple diagnostics, the MPW Assembler reports an error, as follows:
# 303: ANDI.W #~$0700,SR ### Error 54 ### Illegal/missing operands or opcode not allowed for target machine
Is there a way to get this to work?
Using the tilde character on a one’s complement operation in MPW Assembler can give confusing results. The assembler, in its infinite wisdom, treats all constants as signed 32-bit values. Therefore, $0700 is really treated as $00000700. The one’s complement of this is $FFFFF8FF, which is too large a value for an ANDI.W instruction. The syntax that will work is:
ANDI.W #~$FFFF0700,SR
Platforms & Tools: MPW Assembler: MPW 3.2 ASM generic instruction conversions
Where are the MPW 3.2 Assembler “generic instruction conversions”? After upgrading from MPW Assembler 3.1 to 3.2, I noticed while debugging some of my code that an Adda instruction was converted to Lea for me. While I appreciate this (it saves cycles) I didn’t expect it nor can I find where it’s documented. The cover letter that came with 3.2 says that Asm has “new optimizations” but doesn’t elaborate. I have found Appendix A in the 3.0 documentation that describes some obvious optimizations. Where is the corresponding list of optimizations for 3.2?
You correctly noted that the 3.2 Assembler supports optimization of instructions which were previously not optimized. The following additional optimizations are available:
ADD #<Data>,An [-8 <= data <= -1] =====> SUBQ #-<Data>,An
ADDA #<Data>,An [-8 <= data <= -1] =====> SUBQ #-<Data>,An
ADDI #<Data>,An [-8 <= data <= -1] =====> SUBQ #-<Data>,An
SUB #<Data>,An [-8 <= data <= -1] =====> ADDQ #-<Data>,An
SUBA #<Data>,An [-8 <= data <= -1] =====> ADDQ #-<Data>,An
SUBI #<Data>,An [-8 <= data <= -1] =====> ADDQ #-<Data>,An
These optimizations only occur when the Assembler understands the operand to be a negative number. Since the Assembler operates on 32-bit arithmetic, the operand value must be written as a negative number to activate the optimization, regardless of the size (B, W, L) of the instruction. Thus, in a byte operation, the operand must specify “-1” instead of “$FF,” even though, unoptimized, they would both compile to the same instruction.
ADDI #<Data>,<EA3> [+1 <= data <= +8] =====> ADDQ #<Data>,<EA3>
SUBI #<Data>,<EA3> [+1 <= data <= +8] =====> SUBQ #<Data>,<EA3>
ADD.I #<data>,An [-32767 <= data <= +32767] =====> LEA <Data>(An),An
Platforms & Tools: MPW Assembler: Using “far” addressing model with MPW Assembler
Now that MPW® includes the “far” addressing model, how does one use the assembler with the far model? For example, how does one generate a “jsr.l symbol” that the linker will recognize as a “far” reference?
The MPW Assembler does support the new “far” runtime model; it’s documented in the “MPW 3.2 Run-Time Architecture” release note, included with recent versions of MPW that support the new model. (The path to this note on E.T.O. #4 is E.T.O. #4:Tools - Objects:Macintosh Programmer’s Workshop:MPW QR4:QR4 Notes:MPW QR4 Run-Time Architecture.)
The specific example to your parenthetical question is “JSR (symbol).L”, but you should see the release note for background information and important caveats.
Platforms & Tools: MPW C: MPW 3.2 C objfilegen bug requires simpler statements
I’m using MPW C++ streams, and sometimes the compiler seems to generate bad code when I build a large statement, with lots << of << leftshift << operators. Why, and what can I do about it?
This is a known bug in the MPW 3.2 C compiler, but we don’t know when it will be fixed. It turns out that CFront translates your complex statement into a nested series of procedure calls. Eventually, this series becomes too complicated for the C compiler to deal with. Unfortunately, the C compiler doesn’t detect this condition itself. The only workaround is to make simpler statements (try to keep it to a dozen <<’s or less).
Platforms & Tools: MPW C: Avoiding mangled names received by C++ methods from C code
Avoiding mangled names received by C++ methods from C code
To avoid mangled names when using C++ methods which call into a body of C code, which in turn call functions written in MPW assembler, declare your C routines as extern "C", as shown below:
extern "C" {
void foo1 (void);
void foo2 (void);
//...
}
The MPW C headers have some examples of how to do this so that it works in both C and C++.
Platforms & Tools: MPW C: MPW C lseek call and creating a specific-size file
MPW C’s lseek call always returns -1 with errno set to 6 (ENXIO) when I attempt to create a new file of a specific size using the following code:
int n;
n = creat( "whatever" );
lseek( n, the_size_I_want, 2);
Why doesn’t this work?
The MPW C lseek call doesn’t work exactly like the UNIX version; your file creation technique isn’t supported in MPW’s lseek. You can write the number of dummy bytes into the file first, or for compatibility across platforms you can use the ANSI C stdIO calls to move code streams (low-level fcntl calls aren’t defined in ANSI C).
Platforms & Tools: MPW C: Use type “long” & “short” instead of “int” for Mac toolbox calls
Use type “long” & “short” instead of “int” for Mac toolbox calls
Using the “int” type isn’t a good idea for Macintosh toolbox calls, because the size of the int type is compiler dependent. MPW has 4-byte ints and Think C has 2-byte ints, for example. The code will compile slightly differently depending on the availability of prototypes and the compiler used. It’s better to use types “long” and “short” because they are 4 bytes and 2 bytes, respectively, for all Macintosh C compilers.
Platforms & Tools: MPW C: Maximum buffer size for MPW C setvbuf is 65536
Maximum buffer size for MPW C setvbuf is 65536
MPW C’s setvbuf size parameter is treated internally as an unsigned short. This means that the largest value acceptable to setvbuf for its size parameter is 65536. Larger values will be treated modulo this number. In practice, the optimal settings for this value using MPW C is somewhere in the range of 8K– 12K, so DTS recommends that you use a value of 10K. Alternatively you can experiment to see if other values provide better results for you. But any value you try should be within 64K. Your mileage using setvbuf may differ for other development environments.
Platforms & Tools: MPW C: MPW C or C++ and inline assembly
Is the “asm” keyword supported in MPW C or C++? I can’t seem to find anything in the manual about it.
Think C supports inline assembly using the asm keyword. MPW C does not support inline assembly. For very simple assembly functions, you might consider inline hex, which is supported. Most trap calls that use selectors rely on this method. The following example shows how to use inline hex to call a few Desktop Manager traps:
pascal OSErr MyHFSDispatch(DTPBRec *DTPB, long selector )
= { 0x201F, 0x205F,0xA260, 0x2E80 };
Which translates to:
move.l (A7)+,D0 ;move selector to D0
Move.l (A7)+,A0 ;move pointer into A0
DC.W $A260 ;HFSDispatch
MOVE.L D0,(a7) ;result back onto the stack
or
_HFSDispatch,IMMED
As you can see, this is applicable for very short assembly needs. If you’re dealing with anything much longer than this, you’ll just have to deal with the calling conventions. Using the Pascal keyword as in the above example makes calling conventions a little easier to deal with since the Pascal calling order is described with a nice picture on page I-97 of Inside Macintosh.
Platforms & Tools: MPW C: MPW C error 426 and workarounds
What does the following MPW C error mean?
# C - Fatal Error : 426
#-----------------------------------------------------------------------
File "HD80:MPW:Gui:Guie:source:debug.c"; Line 2383
#-----------------------------------------------------------------------
# C - Aborted !
“File "HD80:MPW:Gui:Guie:source:debug.c"; Line 2383” is a valid MPW compound command. If you triple click on it and press enter, the line is executed and it will take you to the exact line of your source code that produced the error 426.
The error 426 is an internal compiler error that occurs for several reasons, but all are related to symbol table space for local variables overflowing memory. Possible workarounds are:
• Use a bigger memory partition for MPW.
• Use less or shorter local variable names.
• Restructure your compile and linking so that less total local symbols are used in each compile.
Platforms & Tools: MPW C: Disable MPW dead-code stripping with #pragma directive
In my runtime MPW® C object messaging mechanism, when I resolve references to routines at runtime through a little piece of code, the linker never sees any references to my routines and thinks that they are all dead code, dutifully eliminating all them during the linking process. Is there a way to force a routine to be loaded into a code resource without adding either an unnecessary reference in the jump table or its code segment?
MPW C 3.2 has a #pragma directive to disable dead-code stripping. It is used
as follows:
#pragma force_active on // don't strip the below code
void not_accessed()
{
}
#pragma force_active off // go back to stripping as usual
The default for force_active is off, and so dead code will normally be stripped.
The #pragma directive didn’t exist before MPW 3.2, but it is still possible to avoid code stripping with a technique similar to the one used by MacApp®. Simply insert a conditional that is never true into a section of your program that _is_ called and make a function call from this conditional to the nonreferenced code, as shown below:
short i=0;
if (i==1)
DeadFuncCall()
You can easily check to make sure your code did not get stripped by adding the MPW linker option “-uf <file>.” This option will write the names of all unreferenced modules to the specified file.
Platforms & Tools: MPW C: MPW C compiler “-m” option
If I use the “-m” option in the MPW® C compiler to build my application, will my application be able to run in the 68000 machines?
The -m option doesn’t pertain to the processor that you want your application to run on. Rather, it generates less efficient code and allows you to address over 32K of global data. Because you can use over 32K of data, your code has to calculate the address of your data all of the time, hence the linker and your code will run slower. If you type “Help C” in MPW, it should say that the -m option generates 32 bit reference for data.
By default, the C compiler produces code that is compatible with 68000 machines. For additional information, see Macintosh Technical Note #256.
Platforms & Tools: MPW C: MPW C 3.1 symbolic table limit
When we compile a file with the MPW® C 3.1 “-sym on” option, it seems that the global and local variables (references) cannot exceed 12000. Is that the limit? Are there ways to increase the size?
There is no official way to change limit values with symbolic table generation. However, the internal values usually are increased with new tool releases. You might check the latest MPW C 3.2 beta compiler on the current E.T.O. (Essentials-Tools-Objects) CD for limit changes. In general, try to test each module in your code separately. The SADE debugger will work far better if you have .SYM information generated for a few modules you want to test.
Platforms & Tools: MPW C: MPW C compiler optimization
Is there a code optimizer for MPW® C?
Well, the C compiler tries its best to optimize; it optimizes by default. Compared with the UNIX world (where the cc has a special -O option), in the MPW world we have a lot of special optimizing flags that the developer can freely test separately. However, we would like to point out that it is usually recommended to only test a few things/flags at at time. With the new MPW 3.2 compiler the developer is also able to switch off optimization. Try to use the performance tools in order to find out the code bottlenecks where optimization would help (asm modules).
Platforms & Tools: MPW C: Preventing MPW C string constants from being compiled as globals
Using MPW® C, a local immediate text string such as printf("%s\n","This is a test") is compiled as a global variable. This is causing the global data over 32K problem. To get around this we used the “-m” option to compile some of the files that are not speed critical when running. We then link the entire program with the “-srt” option. Will this cause a degradation of performance?
The following options for the C compiler will move string constants into 'CODE' resources:
C [option…] [file] < file > preprocessor ≥ progress
-b # put string constants into code & generate
# PC-relative references
-b2 # implies '-b' above, and allows string constants
# to be overlaid
-b3 # overlaid string constants in code (but not
# PC-relative refs.)
Another idea is maybe to start using 'STR ' and 'STR#' resources and load strings into memory with the Resource Manager.
Platforms & Tools: MPW C: MPW C compiler parameter-handling difference
In our example below, when you pass the parameter in the test procedure, the i value we expect is the same for the x and y array. With MPW® C, the i for array x is incremented and the i for array y is not. With a different compiler, i is incremented after the parameter passing.
#include <StdIO.h>
main()
{
double x[8], y[8];
short i, j;
i = j = 0;
while (1) {
if (i >= 8) break;
j = i;
test(&(x[i]), &(y[i++]), j); /* problem here */
printf("i=%d x=%f y=%f\n", i, x[i - 1], y[i - 1]);
}
}
test(x, y, i)
double *x, *y;
short i;
{
*x = (double)i;
*y = (double)i;
}
Increment/decrement of values inside function calls is not defined concerning ordering. See K&R’s new edition, page 53. In general one should try to increase/decrease values before passing them as parameters. The sore point in your case is the , statement, which means that the compiler does not have an obligation to pass the first or second statement, or to increase the value in a certain order. So please increment the value before passing it as a function value. Concerning optimization, there’s no worry incrementing values before passing them.
Platforms & Tools: MPW C: MPW C 3.1 compiler -mc68020 option bug fixed for 3.2
In our example below, the bit field of record array “field1” is assigned a number 1, and then it is assigned into “field2” record array using “field1” value. When we print out the array we can consistently obtain a zero in the “field2[0].visible.” We should be getting all ones when we print the array.
/*
* Here is the bug we found on MPW® C compiler:
* We compiled using -mc68020 option, and the result didn't
* turn out to be what we expected.
*/
#include <Memory.h>
typedef struct _fldInfo {
unsigned short visible:1, unused:15;
} ReadoutField;
/*
* The result of this piece of code is:
* i=0 field1=1 field2=0 */
main()
{
ReadoutField field1[1], field2[1];
short i;
for (i = 0; i < 1; i++) {
field1[i].visible = 1;
field2[i].visible = (field1[i].visible); /* assignment of
same type */
printf("i=%d field1=%d field2=%d\n", i, field1[i].visible,
field2[i].visible);
}
}
This was a bug with the MPW 3.1 C compiler. The latest MPW C 3.2 beta compiler on the current E.T.O. (Essentials-Tools-Objects) CD fixes this problem. Then again bitfields are a little bit nasty, especially concerning porting issues— one has to consider issues like separate padding and data structure sizing. Bit fields are supported by the language, but they tend to cause problems.
Platforms & Tools: MPW C: MPW C doesn’t support the Asm function
Is there any way to imbed assembly code inside an MPW® C function?
Unfortunately MPW C doesn’t support the Asm function. Basically, the historical reason for having Asm was because C compilers generate assembly source which was fed to an assembler. Our C compiler doesn’t do that though, so we would have to put an assembler within the C compiler to be able to deal with this. I believe, however, that Think C does support this.
Platforms & Tools: MPW C: Building resources with MPW C
When building a 'CODE' resource with MPW® C the main entry point needs to be specified with the -m option of Link. So why does one need also to make sure that the routine is the first one in the file and that the file is the first one linked? Why can’t “-m” be enough to tell the linker where the entry point will be?
From your question, it sounds like you are asking about resources _other_ than 'CODE' resources containing object code (i.e., 'XMCD's, 'INIT's, 'cdev's, 'CDEF's, 'LDEF's, etc.). When you create 'CODE' resources, you are building a full-fledged application and don’t need to specify the -m option or make sure that the main entry point is the first one in the link list. With applications, that is done for you.
You need to specify the -m option and make sure that the main entry point is the first one in the link list only when you build stand-alone code resources. There are separate reasons for each of these requirements.
You specify the -m option to tell the linker what the root module or routine is. It uses this module as the start of a tree search for unreferenced modules. These unreachable modules are not included in the link, making your code smaller.
The reason for making sure that the main entry point is the first one in the link list is so that clients know where the starting point of the code is. With standalone code, you don’t get a jump table, which is normally the mechanism used to find the main entry point (the main entry point is in the first jump table entry). Without a jump table, you don’t have an indication of “the main entry point is $xxxx bytes into the resource,” so by convention, it’s the first byte. I think that the exception to this are 'DRVR's, which have a 5 entry table at the start of the resource that points to 5 routines in the 'DRVR'.
For more information on this, you might want to take a look at DTS Macintosh Tech Note #256.
Platforms & Tools: MPW C: MPW C function prototyping restrictions
When is a C function prototype NOT a C function prototype?
Many developers want to take advantage of function prototyping provided by the ANSI MPW® C 3.0 compiler. But the MPW C implementation is somewhat restrictive and you may be getting less than you bargained for.
Consider the following code:
// Declare functions, with prototypes
int foo (int a, int *b);
int bar ();
int foobar ();
// Now define foo()
int foo (a, b)
int a;
int *b;
{
*b = a;
return (a);
}
int bar ()
{
int i;
foo (1, &i);
return (i);
}
int foobar ()
{
return (foo (1, 2)); // The second parameter is not
pointer to int
}
If you simply compile this code without any options, it compiles without errors, even though the call to foo() in foobar() is clearly incorrect. If you compile with the -w2 option, the compiler issues the following warnings:
#
#foo (1, &i);
# ?
### Warning 270 This function has no prototype
#----------------------------------------------------------
File "foo.c"; Line 28
#----------------------------------------------------------
#{
#return (foo (1, 2)); // The second parameter is not
pointer to int
# ?
### Warning 270 This function has no prototype
#----------------------------------------------------------
File "foo.c"; Line 34
#----------------------------------------------------------
This may seem strange because the functions were clearly declared with prototypes.
The problem here is that in addition to using the new style function declarations, you MUST use new style function definitions. So the correct way to define foo() is:
int foo (int a, int *b)
{
*b = a;
return (a);
}
Now, when you compile, you correctly get the error message:
#{
#return (foo (1, 2)); // The second parameter is not pointer to int
# ?
### Error 229 mismatch between formal and actual parameter types
#---------------------------------------------------------------
File "foo.c"; Line 35
#---------------------------------------------------------------
The bottom line is that if you want full advantage of function prototypes, you MUST use new style function definitions. This seemingly arbitrary limitation was a design decision by the MPW C compiler writers. Their reasoning is now documented in the MPW C 3.1 release notes:
“There already existed a large body of code written in MPW C which used both K&R function declarations and the fact that there was no parameter checking to allow variable numbers of parameters to be passed. If we enforced strict parameter checking, that code would have failed to compile. Denizens of the C world even objected to making these warnings! We therefore do parameter checking only on declarations of the form:
int foo (int parm1, int parm2);
and not on:
int foo (parm1, parm2)
int parm1;
int parm2;
Perhaps in the future the -w2 option will at least generate warnings in such cases.”
Platforms & Tools: MPW C++: Undefined Pascal class constructor and Unmangle tool
When a constructor is declared in a Pascal object base class (used, for instance, in MacApp) and not defined, the error message contains a garbled name (strange characters at the beginning and end). The Unmangle tool is in my Tools folder. Do you know what the problem is?
The Unmangle tool doesn’t get invoked automagically; you’ll have to use it to unmangle the symbol that’s given in the error message yourself.
Platforms & Tools: MPW C++: MPW C++ moves pragmas outside function bodies
MPW C++ moves pragmas outside function bodies
Here’s something good to know: MPW C++ moves all pragma statements inside function bodies *outside*, which makes pragmas such as pragma unused and all the new MPW C pragmas for code optimization on/off unusable. It’s not clear whether this will change in the future, but it’s important to be aware of this when using current MPW C++.
Platforms & Tools: MPW C++: Script for filtering out C++ dump/load warning
Is there a way to turn off the warning message given by C++ when using the - load option? The message, “warning: -d or -u option(s) will not affect code saved in dump file,” makes it hard to spot real errors in our build log.
The warning about -d and -u options will be bounced to the -w1 flag in a future C++ release. Meanwhile, here’s a script for filtering unneeded warnings, based on streamedit (MPW 3.2). Note that because of the way pipes are implemented in MPW (files), the streamedit script that prints out the filtered information is not triggered until the compiler/linker and so on is finished at the left side of the pipe. This can be used for filtering any kinds of warnings that the developer would consist not to be important (even if all compiler and linker messages should be considered important information).
MABuild -nodebug -sym DemoText ∑ Dev:stdout | ∂
streamedit -e "/'warning: -d or -u'/ Delete; Print"
Platforms & Tools: MPW C++: Workaround for Revert failure with multiple forks open
Our application, written using C++ and MacApp, works under System 6, but, the Revert mechanism fails under System 7.0. We use both forks of our document’s file and keep both open. The failure occurs way down in MAOpenFile with a -49 error. It appears that the problem is related to the fact that ReadFromFile calls OpenAFile, even if both forks of the file being reverted are already open. I’ve overridden this behavior and things seem to work. Am I going to get into any additional trouble by doing this?
Some access permission strategies have changed between 6.0.x and 7.0. Until these changes are incorporated into MacApp, the only solution, as you found out, is to tweak the ReadFromFile-OpenAFile-MAOpenFile sequence so it doesn’t try to reopen an already opened fork. Seems like the old Revert code broke with the new System 7 behavior...
Test your fix also with an AppleShare-based file, checking for -54 permission errors and errors inside PBHOpenDeny.
Platforms & Tools: MPW C++: “MPW C++ 3.1 Compatibility Note” CLibraries error
“MPW C++ 3.1 Compatibility Note” CLibraries error
The 5/9/91 “MPW C++ 3.1 / MPW 3.2 Compatibility Note” has the following documentation error:
On the bottom of page 1, the instruction to delete the line:
"{Libraries}"Interface.o
is incorrect. The line to be deleted should be:
"{CLibraries}"CInterface.o
Some of the changes that occurred in the later stages of the development of MPW 3.2 included rolling the CInterface.o and CRuntime.o libraries (which used to live in the CLibraries folder) into the Interface.o and Runtime.o libraries (which live in the Libraries folder). So, you of course don’t want your makefiles to try to use either "{CLibraries}"CInterface.o or "{CLibraries}"CRuntime.o, because they are now subsets of "{Libraries}"Interface.o and "{Libraries}"Runtime.o, respectively.
To clarify, you should be able to get everything to work under MPW 3.2 by changing any makefiles you have as follows:
Change "{Clibraries}"CRuntime.o to "{libraries}"Runtime.o
Change "{Clibraries}"CInterface.o to "{libraries}"Interface.o
You might find it useful when dealing with library / link problems to make a text file that you can search from MPW which contains all of the module names contained in a particular library. For instance, you can do this with
dumpobj -mods "{libraries}"Runtime.o
If you have a folder with a file for each of the libraries, anytime something weird pops out of the link, you can search and find the library that it lives in.
Platforms & Tools: MPW C++: MPW C++ 3.1 and volatile variables
MPW C++ 3.1 and volatile variables
The “volatile” keyword isn't supported by CFront 2.0 (upon which MPW C++ is based). Until it is, you can keep a variable from being assigned to a register by taking its address (using the “&” operator).
To keep your code readable (and to make it easier to make the appropriate fixes when “volatile” works), you might use the following macro (MacApp 3.0 and the System 7 Finder both do this!):
#define VOLATILE(x) &x
Whenever you define a variable to be used in handling a failure, invoke this macro after you define it as follows:
unsigned long someImportantVariable; VOLATILE(someImportantVariable);
This workaround isn't free: it has the side effect of adding a harmless (but useless) LEA instruction to the resulting object code.
Platforms & Tools: MPW C++: MPW C++ “free store exhausted” error
I can’t compile any of the MacApp® C++ example programs without getting a CFront “free store exhausted” error from CFront. I cannot find any reference to this diagnostic in my MPW documentation. The example C programs compile OK.
Because the MPW® C++ compiler is a port of the AT&T CFront, which was designed with the assumption that all computers in the world have virtual memory paging(spell UNIX®), it makes notorious use of memory. It doesn’t care about the free memory because it assumes that unused memory will be paged out temporarily and new free pages will be available for the compiler. Enter PC and Macintosh systems, with no virtual memory paging. This is the reason the MPW C++ needs a lot of temporary memory.
Fortunately the peak “need memory” points are infrequent, mostly during the parsing phase. A switch called “-mf” can be used with all the MPW compiler, lib and link tools. It uses the MultiFinder® temporary memory, which is not in use normally and is sort of a pool of unused memory.
If you include the -mf switch with the set of Cfront options, either at the MPW Shell level, in the Makefile, with MAMake using the -Cfront -mf, or even defining it in the Startup file inside the MacApp folder as one of the defaultCfront parameters, then you should have a far easier time compiling MacApp/C++code.
If this does not help, increase the MPW Shell application heap size as well (Get Info on the MPW Shell icon in the Finder™). The shell size should be at least 2.5 MB, or up to 3 or 4 MB if possible. If you have even more memory and you use MPW most of the time, increase the size to near the top of the memory range.
UNIX® is a registered trademark of UNIX System Laboratories
Platforms & Tools: MPW C++: Put MPW C++ inlines in class definition header file
According to the AT&T Reference Manual, it’s possible to declare a constructor as “inline,” but in MPW C++ it only works if the definition of the constructor is in the declaration. For example, declaring the constructor of TEDocument (TESample) as inline results in a link error because the symbol table of the linker is wrong. Is there a solution?
Inline member functions must be in the same header file (xxx.h) as the class definition. If you do this with the inline constructor, the linker will not complain. Also, CFront tries to automatically inline most of the constructors by default.
Platforms & Tools: MPW C++: Creating C++ objects from resources
Can you give me an example of how to create C++ objects from resources in the way NewTemplateWindow creates Object Pascal objects from view templates?
The scheme for creating C++ objects from resources is the same using PascalObjects as the C++ base class as it is with Object Pascal. Check the method “NewObjectByName” in MacApp 2.0, and it should be fairly easy to transpose that method to C++, if you really want to do this.
Concerning non-MacApp base class objects, unfortunately you are on your own. There are many ways to obtain persistent objects in one form or another. For instance, "C++ programming with MacApp" by Wilson,Rosenstein and Shafer has anexample called TStream. MacApp 3.0 will include TStream as well.
Another article about meta-class handling is in the MADA Newsletter, Volume 3,No 5, "Meta-information in MacApp 2.0," by Larry Rosenstein.
Platforms & Tools: MPW C++: Where to find documentation on virtual table generation
Using the MPW® C++ -l option when linking some of our source files, we noticed the virtual table sizes in the output file are different for different objects. This we expected, but we couldn’t discern any pattern. What comprises the vtable?
The topic concerning generation of vtables is very big. As you know our MPW 3.1 C++ compiler originates from AT&T Cfront 2.0, so we generate vtables in the same manner as the original C++ compiler.
You can find information about virtual tables and how the tables are generated/accessed from the following sources:
“MPW C++ 3.1 Release Notes”
Macintosh Technical Note #281, “Multiple Inheritance and
Handle Objects”
“Multiple Inheritance for C++,” included with MPW C++
Chapter 10 of Annotated C++ Reference Guide, new book
by Ellis and Stroustrup
Platforms & Tools: MPW C++: Bottom up C++ construction, base classes through derived classes
When calling overridden functions from the constructor of a superclass, the functions in the superclass are called. Using the MPW® C++ TE example, when a function such as StackNeeded is called by the superclass constructor of an application object, the superclass function by that name is called when one would expect an overriding function returning the derived class’s needed value would be called instead.
To work around the problem, I created a function in the superclass called by the subclass’s constructor that is not a constructor (called it ReluctantInit). I would rather use the constructor, however, instead of the derived class having to “know” to call an init function in the superclass. (You might want to fix TECPlusSample, which makes this very same mistake.)
According to the AT&T docs, the superclass’s constructor should be called before the derived class’s. The syntax SubClass::SubClass:SuperClass (used in the derived class constructor) therefore does not make sense to me, as it suggests that the derived class constructor is called first.
I have bad news: You’ve uncovered a weirdness (sort of) in how MPW C++ constructs things. Apparently C++ constructs things “from the bottom up,” meaning from base classes through derived classes. Therefore, in a base-class constructor, calling a member function will call the base-class member function rather than the derived-class member function, because the derived class hasn’t been constructed yet!
Your workaround, although I agree that it’s philosophically displeasing, is the only one that I can think of offhand.
Platforms & Tools: MPW C++: Workaround for MPW® C++ -w2 option limitation
If I compile with the -w2 option, CFront generates an error message for the anachronism “overload” instead of a warning message. Why is it generating an error for this instead of a warning?
It seems that the -w2 option is a little bit too rough with good old “overload” keywords. ARM (page 405) also defines that overload could still be used in function declaration (even if this is not needed, and in the long run it’s gone, maybe ANSI C++ will not include this at all).
Anyway the -w1 option did not scream. Also if you have a lot of old C++ code with billions of overload declarations, do a “#define overload ” so those will not be used with -w2 testing. Meanwhile I will send a small bug report to the C++ dudes.
Platforms & Tools: MPW C++: Function pointer won’t return type pointer in union or struct
Why is it that I cannot define a Macintosh® function point that returns a pointer to a type (such as a long) in either a union or a struct, though I can outside of one. In fact, I can do this in C, but not in C++. The error
File "test.c"; line 5 # error: pascal member foo
occurs when compiled by C++. When compiled only in C, it compiles with no errors.
---------------------(test.c)------------------------
pascal long* (*biz) ();
union waka
{ long* (*baz) (); pascal long* (*foo) (); pascal short (*bar) (); };
---------------------(test.c)------------------------
Is this a bug in Apple’s MPW® C++ implementation?
It seems like this is a real bug (that is, any Pascal declared function pointer inside a union/struct that tries to return a pointer to a val won’t compile). I also tried to typecast this, but it naturally failed (because the typecast maps back to the original declaration).
I have to report this as a bug to C++ engineering. Meanwhile, the only workaround is either to use a nonPascal function for the work, or to return nonpointers. Note that there’s a known bug with Pascal functions and MPW C++: The Pascal keyword is broken in the specific situation where one attempts to call a C function that returns a pointer to a Pascal-style function. The C compiler currently misinterprets the C function as a Pascal-style function and the function result is lost. OK, this is in the C compiler side!
Platforms & Tools: MPW C++: MPW C++ compiler external link bug and workaround
Is there a bug in the dump/load functions of the Macintosh® MPW® C++ compiler (CFront) on declarations of external routines with C linkage—for example, the GraphAccel.h file?
You are absolutely right, it won’t work. As a workaround you might try something like:
// This one works…
//extern "C" { void SwapHandleBytes(Handle theBuffer);
// }
// This one won't…
extern "C" void SwapHandleBytes(Handle theBuffer)
In other words, put braces around the external link statement, and it works OK with the dump make rules. This is the reason most of the header files in CInclude files work without problems with dumping.
Platforms & Tools: MPW C++: How to use C++ dump/load capabilities
It seems like this dump facility is one of the features that everyone takes for granted, like me, and in real life it’s more tricky than the examples given in the manual.
I will try to write down what I learned experimenting with C++ dump/load and especially MacApp®.
A) To start with, the best thing to check if you have the right C compiler for dump/load is to do a simple test under Macintosh Programmer’s Workshop (MPW®). You need to have the C compiler included with the MPW C++ 1.0 final, and that one is MPW C 3.2ß1 (3.2ß1 or higher). If you have a C compiler from the MPW 3.1 release you won’t get dump/load to work at all.
OK, do a
CPlus "{CIncludes}"stdio.h -dump stdio.dump
or something similar. If the C compiler complains about “unexpected tokens” you have the wrong C compiler. This is especially true if you have one of the first APDA® ones, the MPW 3.1ß1 release.
B) If this worked, the next step is to get it working with a generic C++ program. The example given in the C++ release notes (C++ 1.0 final) is a good one that should work. Use the rules at page 6-7 to build a single uniform header file that will be used to include the other header files.
C) Let’s now try with MacApp. Here we got some really interesting issues. To start with, MacApp 2.0 has a new flag for MABuild with takes care of the whole dump/load management concerning the MacApp C++ header files. If you include a -CPlusLoad to MABuild it will happen automagically. The dumped file is stored into a folder under the MPW folder called “Load Files.” In the MacApp folder there’s a file called Startup where you can modify where the dump file is stored, as well as if the -CplusLoad is done every time without the flag to MABuild.
So in this case the dump/load management is handled for you. The drawback is that you could not include your own header files. Which leads to:
D.1) How to include your own header files. Here I actually found two different ways to do it. The first one is to hack a file under the MacApp:Tools folder called ‘Build Rules and Dependencies.’ If you search this one you will find a place where the dump/load is defined. Comment out the line that says, “Include you own files here.” I tested this and it worked OK.
D.2) Now let us assume that you want to build your own MAMake file. This is also OK. The trick in this case is to carefully specify where the dump, source and object files reside by using the prefix {ObjApp} and {SrcApp} for each file. The other trick is to have a dummy object file as one of the dependency rules that builds the dump file in the first place. It is important that the OtherLinkFiles variable has this dummy file in its definition!
The dump/load is about 2-3 times faster during the C compilation phase due to the fast load of static information. An example of an MAMake file for MacApp (“DemoText with C++ load/dump”) is on AppleLink.
Platforms & Tools: MPW C++: PascalObject destructors bug
Why can’t the linker find destructors for second generation classes derived from PascalObject—i.e. classes derived from classes derived from PascalObject?
I actually found the same bug this Sunday, when I defined most of my destructors in my TObject (PascalObject subclass) to be virtual.
I talked with the MPW C++ engineers, and they should fix this bug for the next release (1.1 or whatever they will call it). Meanwhile I will try to find a workaround...
In general there are a lot of problems with classes inherited from PascalObjects. For instance pointers to members, abstract classes and static functions won’t work as well. One reason was that the engineers were primary worried that everything that Object Pascal supported should be handled by C++, so the linking of MacApp® code would work.
Now a lot of C++ programmers want to make use of the other neat features of C++ with MacApp and PascalObjects, and this is the area that we have to fix.
Currently, the work-around is to be careful with the ordering of destructors and leave them non-virtual in the case of PascalObjects.
Platforms & Tools: MPW Interfaces: MPW C sound.h header file fix
I’m having trouble compiling & linking with the sound routines and MPW® C 2.0.2.
The “sound.h” header file shipped with MPW C 2.0.2 was incorrect. The correct header file is available on AppleLink® in the Developer Services Bulletin Board, and is also shipped with MPW 3.0.
Platforms & Tools: MPW Interfaces: How to create an 'ictb' resource
I am trying to implement colored controls in a dialog but I can not find the template for 'ictb' resources in any of the interface files in MPW®. Can you help?
Unfortunately, MPW rez can not handle the complicated task of compiling an 'ictb', so you have to create it by hand. The following is a sample 'ictb' resource with its accompanying 'DLOG' and 'DITL' (plus a free 'dctb'):
resource 'DLOG' (333) {
{100, 100, 300, 400},
dBoxProc,
invisible,
noGoAway,
0x0,
333,
""
};
resource 'DITL' (333) {
{ /* array DITLarray: 3 elements */
/* [1] */
{82, 93, 102,168},
Button {
enabled,
"OK"
};
/* [2] */
{119,46,137,240},
editText {
enabled, "this dialog has color palette!"
};
/* [3] */
{32,74,52,220},
editText {
enabled, "New Stuff"
}
}
};
resource 'dctb' (333,"CDlog Stuff") {
0x0, 0x0,
{
wContentColor,0xFFFF,0xffff,0xFFFF,
wFrameColor,0x0000,0x0000,0x0000,
wTextColor,0x0000,0x0000,0x0000,
}
};
DATA 'ictb' (333,"CDlog ictb") {
$"0000 0000" /* first item OK normal */
$"A00F 000C" /* edit 1: change family,face, size, fore, back,offset */
$"200D 0020" /* edit 2: change family,size,fore,back */
/* Text style record for second item, edit text 1 */
$"0034 0100 000C" /* font name at offset $34, bold, size 12 */
$"7F7F 0000 0000"/* fore color */
$"0000 7F7F 0000 0001"/* back color + mode */
/* Text style record for third item, edit text 2 */
$"01F9 0000 0012"/* font number,normal,size 18 */
$"6666 0000 3333"/* fore color */
$"FFFF 8E24 182F 0000"/* back color + mode */
$"0647 656E 6576 61"/* Geneva, for item */
};
/* this is the way you see the ictb when using resedit
00000000 0000 0000 A00F 000C ........
00000008 200D 0020 0034 0100 .. .4..
00000010 000C 7F7F 0000 0000 ........
00000018 0000 7F7F 0000 0001 ........
00000020 01F9 0000 0012 6666 ......ff
00000028 0000 3333 FFFF 8E24 ..33...$
00000030 182F 0000 0647 656E ./...Gen
00000038 6576 61 eva
*/
Platforms & Tools: MPW Libraries: Getting MPW to recognize a file created using “open”
I’m using the C standard library routines to read and write text files. But when I create a file using open(), MPW® doesn’t recognize it as a TEXT file. What’s going on?
When open() creates a file, it leaves the fdType and fdCreator blank, since it doesn’t know the format of the file you are going to write (it’s possible to write binary data using the standard C library).
To change the file type and creator of a file created by open(), use SetFInfo, as shown in the example below:
#include <stdio.h>
#include <fcntl.h>
#include <Files.h>
int main(void)
{
int fd;
short vol, err;
FInfo fInfo;
fd = open("junk.out",O_CREAT | O_RDWR | O_TRUNC);
if (fd < 0) {
printf("Error creating file\n");
return(1);
}
(void) close(fd);
err = GetVol((StringPtr) NULL,&vol);
if (err != 0) {
printf("Error %d getting current volume\n",err);
return(1);
}
err = GetFInfo((StringPtr) "\pjunk.out", vol, &fInfo);
if (err != 0) {
printf("Error %d getting file info\n",err);
return(1);
}
fInfo.fdType = 'TEXT';
fInfo.fdCreator = 'MPS ';
err = SetFInfo((StringPtr) "\pjunk.out", vol, &fInfo);
if (err != 0) {
printf("Error %d setting file info\n",err);
return(1);
}
return(0);
}
By the way, you are generally much better off if you use the File Manager’s routines to manipulate your files. The performance will be much better.
Platforms & Tools: MPW Pascal: Macintosh toolbox & Pascal procedure parameters
Macintosh toolbox & Pascal procedure parameters
The Macintosh toolbox does not support nested procedure pointers as parameters, although Pascal can support them in “native Pascal” usage. Consequently, Pascal requires that functions like the SFPGetFile filter and hook be global functions; they cannot be local to the method calling SFPGetFile nor can they be separate methods of an object calling SFPGetFile. Likewise, variables used by the filter and hook must be global. For further reading, Macintosh Technical Note #265, “Pascal To C: PROCEDURE Parameters,” provides technicalities of this issue.
Platforms & Tools: MPW Pascal: MPW 3.2 Paslib.o library and standalone code
MPW 3.2 Paslib.o library and standalone code
Linking a standalone code resource with the MPW 3.2 Paslib.o library generates the following link error message:
Link Error: Output must go to exactly one segment when using “-rt.”
The same link works fine if the MPW 3.1 Paslib.o is used. Linking with the new MPW 3.2 Paslib.o causes Pascal modules such as %_MUL4, %_DIV4, %_MOD$, and %_CAT to be stored in a new segment called Paslib 1. However, standalone code resource should just have the one segment.
To link a standalone code resource with the MPW 3.2 Paslib.o library, use the -sn option (like -sn PASLIB=Main) to pull all of the Pascal modules into your Main segment. If your main segment is called something other than Main, you can substitute that name in the -sn option instead of Main.
For more information on segmentation, check out the “Segmentation” section of Chapter 10 of the MPW Reference Manual.
Platforms & Tools: MPW Pascal: Why Pascal objects in HyperCard XCMDs is a challenge
Is possible to declare MPW® Pascal objects in a HyperCard® XCMD?
It’s possible but very difficult to use Pascal objects in an XCMD because Object Pascal uses the jump table in its method dispatch mechanism. XCMDs and other standalone code resources don’t have a jump table. See Macintosh Technical Note #256, “Stand-Alone Code, ad nauseam,” for more information about this.
Platforms & Tools: MPW Pascal: MPW 3.2 has new syntax for forward references to objects
My application, which has several units and objects, compiles under MPW® 3.1 but not under MPW 3.2. Do forward references to objects work differently with MPW 3.2?
MPW 3.2 has a new syntax for forward references to objects. Objects must be
declared as externals, as follows:
TYPE
TObjB = OBJECT; external; { MPW 3.2 requires this }
TObjA = OBJECT(TObject)
fFwdRef: TObjB;
{methods}
END;
Note that by default the Pascal compiler includes information such as USES in its symbol table resources, so simply using the correct USES and external declarations may not be sufficient; you may find it necessary to invoke the Pascal compiler with the -rebuild option to force it to reconstruct its symbol table resources from scratch.
Platforms & Tools: MPW Pascal: MPW Pascal converts SINGLE numbers to extended
Why does MPW® Pascal convert SINGLE numbers to extended, create a temporary area for them, and then pass a pointer to those extended numbers on the stack?
The conversion of single-precision values to extended is being done to maintain accuracy--it’s entirely possible while doing the intermediate math with single-precision values to generate values of extended precision, and the MPW compilers do this conversion to preserve accuracy.
If your application doesn’t need the accuracy, you can declare the parameters to be of type LONGINT, and typecast them as necessary within your procedure or function. There is no way to tell the MPW compilers not to do the conversion if the parameters are declared as SINGLE.
Platforms & Tools: MPW Pascal: Booleans and short circuits don’t mix
I can’t get expressions containing Booleans and short circuit in my MPW® Pascal program to evaluate correctly. I have to use all of the same type. Is this a bug?
Your workaround is correct. Presently this isn’t a bug. The MPW documentation states that mixing of short circuits and regular Booleans in the same expression IS NOT supported.
It is in Chapter 6, page 100 of the Pascal 3.0 manual.
Platforms & Tools: MPW Pascal: Pascal Dispose function bugs
I am having a hard time getting the Pascal function “Dispose” to work. It doesn’t seem to be freeing up memory.
Surprisingly, Dispose doesn’t work and has NEVER worked! As far as we know, there have been two bugs in the Dispose routine that have been in there from day 1.
The first bug has to do with the interaction between the code that the Pascal compiler creates, and the library routine (%_DISPOSE) it calls to do the actual dirty work. When the Dispose procedure gets compiled, the pointer to the memory block you want to free up and the amount of memory you want to free up are pushed onto the stack. Then a call to %_DISPOSE is made. However, this routine—written in Pascal—is declared to accept the memory pointer as a VAR parameter. This means that it is expecting a pointer to the parameter, and not the parameter itself.
The second bug occurs when trying to free a block of memory that doesn’t have any free memory in front of it within its sub-heap. When this occurs, the first block in the heap gets slightly corrupted; your data is still intact, but the header that identifies it gets smashed. The result of this is that the heap routines do not properly detect when the heap is empty and should be disposed of.
These problems are fixed in MPW® 3.1. In the meantime, there are a couple of things you might be able to do. The first is use the Memory Manager routines, and not the Pascal heap routines. Second, Mark and Release are bug free (and so is New), so you may try using them. Release will dispose of any additional allocated heap blocks. NOTE: Mark and Release only work if “forDispose” is FALSE.
Platforms & Tools: MPW Tools: MPW linker problem with PC-relative function address production
When I use “-model far” in MPW 3.2, all my intra-segment function addresses are calculated from the actual code address, rather than as a jump table address. What can I do to work around this?
Thanks for your report of a problem with the MPW linker regarding production of PC-relative function addresses. This is a verified bug. Until it’s fixed, you can either (1) place your functions in segments other than the segments where the address is taken, to force A5-relative addressing, or (2) place all functions whose addresses might be taken into a segment which is never unloaded, so that an absolute address is acceptable.
Platforms & Tools: MPW Tools: “-model far” affects jump table & code segment, not code module
I can’t define a procedure larger than 32K, even if I use -model far.
-Model farcode relaxes the 32K limit on jump table size, and eliminates the 32K limit on code segment size. It does *not* affect the limit on the size of an individual module: that remains at 32K. This is why you had trouble with your strings. [We don’t expect the module-size limitation to be relaxed anytime soon].
Platforms & Tools: MPW Tools: “-model far” and “PC-relative edit” link error
When using -model far, I get the following error from the linker:
### While reading file "HD:MPW:Libraries:Libraries:Runtime.o"
### Link: Error: PC-relative edit, offset out of range. (Error 48) %__MAIN
(260) Reference to: main in file: xxx.c.o
What does it mean?
In your Link command, you should put Runtime.o and the object file containing your main program close together, and as early in the list as possible. This is because %__MAIN (the part of Runtime.o that actually receives control when your application is launched) uses a PC-relative BSR instruction to transfer control to your “real” main (OK, so it’s “32-bit- almost-everything”!).
Platforms & Tools: MPW Tools: Balloon Help with MPW Tools
Is it possible to add Balloon Help to MPW 3.2 Tools?
After extensive head scratching, the answer is yes/no/no. There are basically three scenarios that might require Balloon Help: The first is if your tool takes it upon itself to have its own human interface with dialogs and windows of its own. This is not supported under MPW, but several people have succeeded in getting it to work with much work and programming. If you have gotten this to work, then Balloon Help is easy. It works just like an application; simply add the 'hdlg' resources to your resource fork (assuming you are using a dialog). This was verified by adding a proper 'hdlg' resource to the Choose tool; worked like a champ.
As for MPW supplied dialogs and alerts that may come up while your tool is running, there is no way to override the resources being loaded in many cases, since the dialogs are not created from a DLOG. In the case of MPW-supplied dialogs, Balloon Help is non-modifiable for you.
As for the only other dialog associated with your tool, the Commando dialog, you cannot add balloons to this either, but that is no real problem since Commando has its own built-in help system that allows you to associate help with any item in the commando dialog.
Platforms & Tools: MPW Tools: MPW glue for trackbox & other lowercase toolbox calls is broken
Is trackbox() in the MPW® C library broken? It always returns 0 (false).
You are correct, the glue for trackbox is broken. In fact, the glue for much of the lowercase toolbox calls is broken. Trying to get rid of these items in the library files and interfaces is a never-ending problem. We are reporting this as a bug (to go with the bugs we have reported on many of the rest of the all lower case glue). It probably will never be fixed; instead, expect to see all lowercase glue routines removed from future versions of MPW. What does this mean to you? Only use the proper mixed-case interfaces (the ones spelled just like in Inside Macintosh®) at all times. This also will serve to make your code smaller and faster, since the mixed-case interfaces cause direct tool calls to be made instead of glue routines in many of the cases.
P.S. In case you’re wondering, trackbox does not work because the glue is clearing a long for the result instead of a word, and pulling off a long, so the result is in the wrong byte of the register on return.
Platforms & Tools: MPW Tools: New calls available as MPW 3.2 glue for System 6
How do I find out what calls in Inside Macintosh® Volume VI are accessible from System 6?
As it turns out, there isn’t a comprehensive list of calls that are available as MPW glue. I used the search command in MPW 3.2 to search for “#ifdef SystemSevenOrLater” to locate the full list:
System 7 Calls Glue
-------------------
FindFolder()
Gestalt()
HOpenResFile() [this has been available for some time] TN#214
HCreateResFile() [this has been available for some time] TN#214
And also, if you have a sense of history,
System 6 Calls Glue
-------------------
StripAddress()
SysEnvirons()
In other words, FindFolder() works back to when HFS was introduced, Gestalt works back to when SysEnvirons was introduced, and if SysEnvirons is not present Environs is called.
Platforms & Tools: MPW Tools: MPW 3.2 'HEXA' resources
What are the four 'HEXA' resources in the MPW® 3.2 shell, and will changing any of them give me more room for linking?
Each 'HEXA' resource ID with a corresponding description follows. Twenty-three words of caution, however, are that these resources may change in the future, so use this information at your own risk.
128 : initial stack size
129 : initial number of master pointers
130 : inital pointer zone size (MPW allocates a block for random pointers)
131 : pointer zone delta (when the zone fills, MPW allocates this much more
room).
So, if you want to make more memory available to your MPW tools (like the linker and compiler), you can try modifying some of these values, starting with the 'HEXA' resource #128. This process is described further in the MPW C++ release notes.
Platforms & Tools: MPW Tools: InitGraf is only managers’ init routine called by MPW Tools
I have compiled and linked a multi-segmented MPW tool using the following switches in a Build/MAKE file:
C -sym full -s Main -r -t XXXXXX.C …(etc.)
(first segment named "Main"; others are arbitrarily named)
Link -c 'MPS ' -t MPST -map -rn -srt -sym full -x XXXXxref … (etc.)
(removed segment names)
I believe the above set of compile and link switches will, among other things, allow me to generate multi-segmented code without having to resort to #pragma segment directives in the source. Please correct me if I am wrong.
I have no difficulty building a multi-segmented product using THINK C™ 4.0. Although the MPW tool seems to build properly, when I run the tool, I get a bus error deep down in ROM after a call in my source to SFGetFile. I have used SADE, MacsBug, THINK C Debugger, and MacNosy/The Debugger and I just about give up! The information I’ve supplied, generated using Jasik’s Debugger (V2), will help to give you some clues.
The call to SFGetFile:
ADEA Pack3 AutoPop; (selector:INTEGER)
selector: 2
SFGetFile(where:Point; prompt:Str255; fileFilter:ProcPtr;
numTypes:INTEGER;
typeList:SFTypeList; dlgHook:ProcPtr; VAR reply:SFReply)
where : 0 0
prompt : ""
fileFilter : NIL
numTypes : 1
typeList :Array[1:4] of ASCII
[ 0] = 'AHED' <-- This is the only one that matters
[ 1] = $00 $14 $00 $00 <-- Elements 1,2,3: Junk?
[ 2] = $00 $0A $00 '4'
[ 3] = $C8 'ûfl
There certainly doesn’t appear to be anything wrong with your segmentation approach; it’s very unlikely that it’s the source of your problem.
What is more likely is that you’re initializing more than you need to in your tool. MPW Tools must call InitGraf in order to provide a valid global environment for themselves, but they cannot call any of the other Managers’ initialization functions. In particular, calling InitWindows will result in the behavior you are encountering when you call SFGetFile.
Platforms & Tools: MPW Tools: Decompressing compressed System 7 file resources
I tried to DeRez some of the resources in my Macintosh®System 7.0ßx system file, but for some of them all I got was garbage. Why?
Some of the resources shipped by Apple with System 7.0 are compressed. DeRez doesn’t use the Resource Manager (mostly for historical reasons), so it doesn’t benefit from the Resource Manager’s automatic decompression of these resources.
If you wish to examine the contents of one of these compressed resources, use ResEdit™ version 2.1. It will warn you that the resource you’re about to examine is compressed and that the resource must be decompressed to edit it (after which you can use DeRez to examine it in all its textual glory).
Platforms & Tools: MPW Tools: Use “Duplicate” to split file into data & resource fork files
Is there any simple way under MPW® to split a Macintosh file into two new files—one containing the data fork and the other containing the resource fork?
The “Duplicate” tool will do this quite easily. Either use the Commando dialog, or this from the command line:
duplicate A B -d # copies A's data fork ONLY to B
duplicate A C -r # copies A's resource fork ONLY to C
Platforms & Tools: MPW Tools: MPW Linker “Data initialization code not called” error
The MPW® linker is reporting a “Data initialization code not called” error. What is wrong?
This usually happens when trying to link an INIT or XCMD/XFCN code resource. Code resources are not allowed to use global variables or variables that are initialized at declaration time. First, make sure that you aren’t using any global or static variables. In Pascal and C, a global variable is one that is declared outside of any function or procedure. Also note that in MPW C, string constants (e.g. “hello, world”) are actually compiled as global variables (MPW C 3.0 has the -b option to override this). If you are using MPW C, check for string constants in your code.
To work around the string constant problem, read the string from a resource file:
char *myStr;
...
myStr = "Hello world";
becomes:
str255 myStr;
...
GetIndString(&myStr, 256, 1);
c2pstr(myStr);
Variables that are initialized at declaration time in the source code are actually initialized when the program starts up. The compiler generates the initialization code and puts it in a segment called %A5INIT. Because XCMDs, for example, must be a single segment, you can’t link the %A5INIT segment as well. You need to change the initialization to an explicit assignment at the beginning of the code:
short myCounter = 1;
becomes:
short myCounter;
...
myCounter = 1;
Platforms & Tools: MPW Tools: MPW 3.0 Linker and Vaccine
The MPW® 3.0 Linker hangs or prints odd error messages when I try to link my program. What’s wrong?
This is usually a problem associated with Vaccine, the anti-virus 'INIT'. You will either get the following error messages, or the Linker will apparently hang:
### Link: Resource not found (OS error -192)
### Link: Error: Resource I/O error, # (Error 6) setting resource attributes.
### Link: Errors prevented normal completion.
In the former case, either remove Vaccine, or select the option that allows MPW to work (in the current version of Vaccine). In the latter case, the MPW option has already been set, and Vaccine is merely waiting for you to press “y” to signify that the link process should continue.
Platforms & Tools: MPW Tools: MacsBug and TMON now support longer compiler symbol names
Why don’t the MPW® compilers generate debugger symbols which can be recognized by TMON or MacsBug?
The “-mbg ch8” option to the MPW 3.0 compilers cause the compilers to generate old style 8-character symbol names used by older versions of MacsBug and TMON. The default longer symbol names are necessary for use with object-oriented languages such as Object Pascal and C++, which generate very long symbol names. These names are supported by newer versions of MacsBug and TMON.
Platforms & Tools: MPW Tools: MPW “unable to swap in Shell segment” error
What causes an MPW® tool to abort with the message, “Unable to swap in Shell segment”?
This message almost always means memory allocation problems. It is most often encountered when compiling and linking large programs, especially with the - sym option. It often goes away in subsequent executions of the tool or when you exit and re-launch the shell. Another symptom that MPW is on the edge is the dreaded “bulldozer” cursor. You may think MPW is hung in this case, but thrashing itself to death is a better description.
Try increasing the MultiFinder® memory partition of the Shell and see if the problem persists. A better option under MPW 3.0 is to use the -mf option to enable the use of MultiFinder® temporary memory, if the tool supports it.
Platforms & Tools: MPW Tools: MPW “unable to swap in tool segment” error
When linking my application I get the error “unable to swap in tool segment.” What has gone wrong?
The MPW® linker has run out of memory. The first thing you can try is to turn off the RAM cache (with the Control Panel). If that doesn’t work, then take out your debugger. You will also want to remove any memory-hungry cdevs and 'INIT's. Another way to solve your problem is to segment your program using the Segment Loader (that is, make your big app into many little apps). If you still have problems, you need to get more memory.
Platforms & Tools: Other Tools: AnimCursors frame field color cursor bit
DTS’s AnimCursors sample code checked the high bit of the second word in an 'acur' resource to see if it should check a series of 'crsr's rather than 'CURS's. To quote from AnimCursor.c, “If the high bit of the frame field is set, AnimCurs is a list of color cursors.” The bit’s not represented in MPW 3.2 resources, however. Was the frame field “feature” forgotten in MPW Rez, or has it gone away?
It looks like the folks who put together the Rez template didn’t know about the bit. To get around this, copy the 'acur' template from Types.r into your own include file, and change the first “fill word;” line to
unsigned integer useCURS = 0, usecrsr = 0x8000; /* use 'CURS' or 'crsr'?
*/
This should get you on your way (albeit with one more compilation warning). The alternative is to define the resource as raw data, the way the sample does (of course, it has the excuse that it existed before types.r knew about it).
Platforms & Tools: Other Tools: AnimCursors frame field color cursor bit
DTS’s AnimCursors sample code checked the high bit of the second word in an 'acur' resource to see if it should check a series of 'crsr's rather than 'CURS's. To quote from AnimCursor.c, “If the high bit of the frame field is set, AnimCurs is a list of color cursors.” The bit’s not represented in MPW 3.2 resources, however. Was the frame field “feature” forgotten in MPW Rez, or has it gone away?
It looks like the folks who put together the Rez template didn’t know about the bit. To get around this, copy the 'acur' template from Types.r into your own include file, and change the first “fill word;” line to
unsigned integer useCURS = 0, usecrsr = 0x8000; /* use 'CURS' or 'crsr'?
*/
This should get you on your way (albeit with one more compilation warning). The alternative is to define the resource as raw data, the way the sample does (of course, it has the excuse that it existed before types.r knew about it).
Platforms & Tools: Other Tools: RAMDump and ReAnimator modem & printer nub extensions
On the “Desperately Seeking Seven” Developer CD, I found RamDump/ReAnimator, with a thing called ModemNub. The release notes claim documentation is included with it, but there isn’t any. Could you possibly round up some documentation?
You can obtain documentation on these utilities from APDA when you purchase RAMDump & ReAnimator v.1.0 (#M7045, $20.00). The trick, however, is that these utilities haven’t been updated since October, 1988, so RAMDump 1.0 won’t work on the Macintosh IIci or IIfx (RAMDump isn’t aware of the floppy controller, thus it can’t write to the disk). The revised version of RAMDump that you found on the Desperately Seeking Seven CD should address this problem.
To debug a running program using ReAnimator via two Macintosh systems, you need to have the following setup: Have a host Macintosh running ReAnimator, and the target Mac running the Nub init (modem nub or printer nub, depending on the port you use). This allows the host Mac to stop the target Mac, start it, and read its memory over the serial line. You run the program to be debugged on the target machine. Since ReAnimator is not running on the machine that is being debugged, ReAnimator can use windows and menus without interfering in the debugging process. When debugging a live Macintosh over a serial link, ReAnimator can step, trace, and perform other flow control instructions.
Platforms & Tools: Other Tools: Where to get third-party XTND translators
Where can I find XTND translators for third-party products?
The only XTND translators available from Apple ship with the XTND 1.3 package. You get MacWrite II, MacWrite 5.0, MacPaint, and PICT. To obtain more translators, you can purchase them from one of the companies that sell XTND translators (DataViz is one such company). You can also write your own translators. You might want to write translators for your own products and make them available to other third parties.
The translators that Claris ships with their products were written by Claris and are not currently available for distribution with your products. (However, any of your users who have these Claris translators will be able to use any XTND-aware product you have created with their translators.)
Platforms & Tools: Other Tools: Where to find Discipline module (DSC command)
Where can I get the trap Discipline module (DSC command) mentioned in the MacsBug documentation?
Discipline is included with the Essentials•Tools•Objects (E.T.O.) CD starting with #3, and is available on AppleLink®.
Platforms & Tools: Other Tools: Third-party database engines
I’m looking for a database engine that I can use in my own Macintosh® application. Currently, development is in Pascal, so a Pascal program must be able to call the database engine.
SyBase has a database library that you can link into with MPW®. I think the libraries are in C, but you can always call them from Pascal. Oracle also allows embedded SQL using SQLNet. This might be worth checking into as well. Finally, you might try calling Informix, Ingress, or DEC (Dec has a product called RDB). You will want to contact the individual companies for more information about their libraries.
Platforms & Tools: Other Tools: Status of new development tools mentioned at ‘88 WWDC
Some development tools from Apple were mentioned at the 1988 Developer’s Conference, and again in a short article in MacWorld. How and when can I get these tools?
Some of the tools mentioned are RamDump/ReAnimator, Player Piano, Spot and Extended Discipline. The only one of these that is currently available is RamDump/ReAnimator. RamDump produces a memory dump, and ReAnimator reads it. These are available from APDA®.
The other tools have not been completed. If and when they are completed and released, they will also be available from APDA. Note: It is possible that some of these tools will never be released.
Platforms & Tools: Projector: Don’t mix MPW versions sharing Projector files
Can both MPW® 3.1 and MPW 3.2 users share the same Macintosh® Projector® file, or has the file format changed?
It isn’t a good idea to mix different versions of MPW on the same Projector file—not because of differences in Projector, but rather because of MPW differences. Bug fixes and general changes in MPW 3.2 make it a better environment for development.
You should upgrade all your development systems so everyone can use the latest MPW version. If you’re hesitant to upgrade because you’ve customized MPW, you can copy your UserStartup file over to add your customized settings.
So, yes, you can use MPW 3.1 and 3.2 on the same Projector files, but we highly recommend that everyone upgrade to MPW 3.2.
Platforms & Tools: Projector: MPW 3.2 Projector revision authors can’t be changed
Using MPW® 3.2 Projector, is it possible to change the author of a revision?
No, it’s not possible to change the author of a revision. The Projector designers didn’t see this as an important feature, but your message has been forwarded to them to them as an enhancement suggestion.
Platforms & Tools: Projector: MPW 3.2 Projector and recursively checking out a named revision
Using MPW® 3.2 Projector, is there a way to automate or write a script for recursively checking out project revisions by name?
You can recursively check out a named revision from a hierarchy of projects as long as the name is defined in each project in the hierarchy. When this was tried with the System 7.0 Finder™ sources (it’s one project, containing a bunch of files and six more projects, which contain a total of...) there was no problem.
Here’s what happened:
The Finder project was mounted in its normal place (the sources were kept on an AppleShare® server; the local copy was kept in a directory called, strangely enough, “Finder”):
directory Biggie:Finder: #change to my local Finder directory
MountProject FinderServer:FinderSources: #mount the project from the server
CheckOutDir -r : #tell Projector about the hierarchy of folders in :Finder:
To try out the CheckOut command, another directory was created elsewhere on the hard disk, and the second named revision of Finder sources to it was checked out:
newfolder Biggie:OtherFinder: #make a new directory
directory Biggie:OtherFinder: #change to it
CheckOutDir -r : #tell projector to create the hierarchy beneath it
checkout -p -r 'a1' # checkout the old rev, and print progress
This worked as expected, recursively checking files out into the correct subfolders. That particular old revision was selected because it referenced files that had been deleted from the project. When CheckOut got to those files, it printed a warning and continued:
Warning, one of the files that the name “a1” expanded to does not exist anymore.
You can use a revision name instead of a specific file name with the checkout command. You’ll find this information on the CheckOut manual page of the MPW Reference Manual,Volume 2.
Platforms & Tools: Projector: Reducing Projector database size
When I use “DeleteRevision” to remove old revisions from my Projector® database, the actual size of the ProjectorDB file doesn’t decrease much. How can I make the file smaller?
Projector does not currently compact files. Instead, it marks the areas of the database that are now free and puts them into a free page list. This effectively puts holes into your database which subsequently get filled up when you add more revisions.
Your database will get smaller only if the free pages are at the end of the file; then Projector will shrink the file. However, there is very little you can do about controlling this situation. If you absolutely must have a smaller database, then all you can do is check everything out, orphan them, and create a new database. The disadvantage of this method is that you lose ALL your revisions and revision comments.
The Projector team is aware of the need to compact the database. They are currently studying the feasibility of implementing such a function.
Platforms & Tools: ResEdit: ResEdit can display Kanji and English at the same time
How do I get ResEdit™ to display English and Kanji at the same time, to make a Japanese version of our software? Can ResEdit even display Kanji?
The simple answer is yes, ResEdit can display Kanji and English at the same time. The first thing you’ll need to do is install KanjiTalk on your system. (Note: Installing _on top_ of a U.S. version of the system software won’t work; everything gets scrambled.) All you need to do (after ensuring that you have the latest releases of both KanjiTalk system software and ResEdit; check your latest Developer CD, the Developer Services folder on AppleLink®, or APDA®) is open up your old and your new resources at the same time and voila! you’ll be able to translate and see both at the same time because KanjiTalk will use the Japanese font but will display ASCII characters in Roman fonts as you would expect.
(FYI: This is how Apple translates system software.)
Platforms & Tools: ResEdit: ResEditFixer no longer required
ResEditFixer makes all the disk-switch alerts use the name of the startup disk (inserting the needed disk works, if you can figure out which it is). Is ResEditFixer still required with ResEdit™ 2.1?
ResEditFixer is not necessary with 2.1 and in fact can cause problems.
Platforms & Tools: ResEdit: Macintosh ResEdit 'RMAP' resource documentation
The ResEdit™ 2.0 resource 'RMAP' allows me to map a type of resource to another 'TMPL', but it is not clear what the Exceptions mean and what the Editor field means.
I forwarded your question to a friend who writes the ResEdit manuals. He gave me his blurb on 'RMAP' out of his next version of the manual. Note that this is written in specific for the 'ICN#' resource, but it is actually more general, as you are already aware. Here ‘tis:
“If you have Color QuickDraw™, but you want to be able to open the 'ICN#' editor by double-clicking a resource of type 'ICN#' (rather than opening the Finder™ icon family editor), you can make a resource of type 'RMAP' in the ResEdit Preferences file. (This resource should look like the one shown in Figure 6-1 in the book, which should be out around the beginning of March, we hope.) Notice that the name of the 'RMAP' resource is the name of the resource you will be opening, and the MapTo field contains the name of the editor you want to invoke. Set the name of the 'RMAP' resource as usual, with the Get Resource Info command from the Resource menu. If you set Editor Only? to 1, the 'RMAP' is used for the editor but not for the template, if one exists.”
Note that this answers your question about the “editor” field. I think you must be using an older version (like 2.0ß2, maybe), because the names of the fields have changed. I don’t actually remember what the ‘exception count’ field is for. It looks like you are thinking of the 'RMAP' as a way to map a resource over to a different 'TMPL'. That’s interesting—I was thinking of it as a way to map the resource to a different editor. Thanks, though, for mentioning it in that particular way.
Platforms & Tools: SADE: FPU instructions and SADE 1.3 or SourceBug on Quadra
Are there any known problems using SADE or SourceBug on a Quadra? My SourceBug crashes, and I get an “Unimplemented F-Line instruction” alert when stepping over a trap call..
The problem occurs when you execute an FPU instruction that is not implemented on the 68040, but is emulated instead in ROM. Normally, the 68040 generates an F-Line exception, which is intercepted by the numerics code and emulated. However, when the Process Manager launches SourceBug or SADE, this exception vector is patched, and F-Line exceptions are passed to the debugger instead. Therefore, when SourceBug or SADE is running, none of these transcendental FPU instructions can be emulated.
The problem will be fixed for SADE 1.3.1 and SourceBug 1.0b6.
Platforms & Tools: SADE: SADE “Invalid A6…” error message
What’s the cause of the SADE® error message, “Invalid A6, A6 must be greater than or equal to SP, and within valid stack range”?
The “Invalid A6, A6 must be greater than or equal to SP, and within valid stack range” error message that you are receiving stems from a feature that was placed into SADE 1.3a5. There is a simple fix. You just need to change the WantStackWindow variable located in the SadeStartup file from 1 to 0. (The WantStackWindow variable is about 30 lines down from the top of the SadeStartup file.)
When a user targets an application, SADE launches the application and runs until it hits an internally placed break point. At this point in time, the program is given a name and A6 is basically junk. The WantStackWindow basically tells SADE to check to see if A6 is valid or not as the program is running. When SADE hits the break point, A6 is junk, so the user will receive this error message. As the user continues to run the application, A6 becomes valid and the “error” no longer exists.
To sum it up, when WantStackWindow is set to 1, and your program is not running you will receive this error. When WantStackWindow is set to 1, and your program is running, you will not receive this error. By setting WantStackWindow to 0, it doesn’t check to see if A6 is valid; therefore, you will not receive the error message.
Platforms & Tools: SADE: Debugging MPW Tools with SADE
How do I debug MPW® Tools written in Pascal using SADE® 1.0?
Keep in mind the following:
• SADE 1.0, 1.1, and 1.2 are not compatible with Macintosh® System 7.
• If you’re using System 7, you’ll need to use MPW 3.2 and SADE 1.3.
• You must be using MultiFinder® 6.1b9 to use SADE with System 6.0.x.
• You need to compile and link your tool with the symbolic debugging flags on.
• SADE 1.0 has been upgraded to SADE 1.1 (so you should probably upgrade).
To start working with SADE on an MPW tool (in Pascal), compile and link the ResEqual tool in the Pascal examples folder using MPW. Here are the commands I used from MPW to do this:
<First, set the MPW directory to the PExamples folder>
set SymOptions "-sym on"
rez ResEqual.r -o ResEqual -append
Pascal ResEqual.p -o ResEqual.p.o {SymOptions}
Asm FStubs.a -o FStubs.a.o
Link -w -c 'MPS ' -t MPST ResEqual.p.o FStubs.a.o ∂
-sn STDIO=Main ∂
-sn INTENV=Main ∂
-sn %A5Init=Init ∂
"{Libraries}"Interface.o ∂
"{Libraries}"Runtime.o ∂
"{Libraries}"ToolLibs.o ∂
"{PLibraries}"Paslib.o ∂
-o ResEqual {SymOptions}
Once the ResEqual tool is compiled, get into SADE and type in the target command with the appropriate information. Mine looked like this:
target "HD:MPW 3.2:MPW Shell 3.2b12" using "HD:MPW 3.2:Examples:PExamples: ResEqual.SYM"
You shouldn’t have to use the SourcePath add command because all of the source code should be in the same folder as the ResEqual.SYM file.
Next, execute the MPW Shell by double clicking it from the Finder™ or by launching it from SADE (the launch command). The target command may launch it, depending on the version of SADE that you are using. Once you’re in MPW, execute the tool (type in ResEqual xyz xyz). When the tool is executing, you can press the command-option-period (the period must be the one on the numeric key pad) and it will break out of the tool back into SADE. Alternatively, you can set breakpoints in SADE before you run the tool from MPW. This will pop you into SADE without requiring you to press the break key (command-option- period).
Platforms & Tools: SADE: SADE “Cannot determine break address…” error
What does the SADE® error “Cannot determine break address: Could not determine address from available source information” mean and how do I fix it?
Two common problems are indicated by with SADE’s “Cannot determine break address: Could not determine address from available source information” error message are:
1. not all the source modules have been compiled with -sym on
2. one of the tools that produces .SYM file information does not conform to the latest format definition
For the first problem, put breakpoints everywhere except for where the error occurs, and make sure all source code is compiled with the “-sym on” option.
If you can’t set breakpoints, check for the second problem. The MPW 3.2 tools (compilers) generate the symbolic information that the Linker puts together for one single file, so eventually when you use an old tool it will not produce good symbolic information for the final .SYM file.
Check the latest Essentials•Tools•Objects (ETO) CD for the current SADE and MPW tools.
Platforms & Tools: SADE: SADE needs locked code resources
I am having difficulty in using SADE® on an Omnis 5 external. I have previously succeeded in using SADE on stand-alone code resources called from a standard C application, and with MPW® tools.
I place the external code resource in the Omnis 5 application resource fork, when the external executes, SADE yields:
Internal fatal error! Please kill the target process! at µEXTERNAL+$0010 in
"Omnis 5"
EXTERNAL
+0010 001164C8 4E45 •*TRAP #$5
Note that the TRAP is at the breakpoint address, which makes sense. Somehow SADE is getting confused and failing to recognize the TRAP as the breakpoint. What’s happening here?
It seems like that TRAP statement you got was something from outer space because the trap-dispatching with Macintosh® traps is handled by A-line traps whose opcodes start with hex A. The TRAP opcode is never used as with other operating systems, such as A/UX®.
The most likely reason for this behavior is that your code resources were moved around, and SADE picked up whatever it found in that memory location— after that the CODE had moved to another place. In order for SADE to get access to the real CODE resources you need to lock them.
Platforms & Tools: SADE: Debugging an external CODE resource with SADE
How do I debug an external 'CODE' resource with SADE? I can’t get it to work.
Lets say that the application which calls your code resource is in HD:AppDir:, and that the source code for your code resource is in HD:SrcDir:. To debug the code resource, enter the following commands in SADE:
Directory 'HD:AppDir:'
SourcePath 'HD:SrcDir:'
Target 'AppName' Using 'HD:SrcDir:ResourceName.SYM'
Break ResourceEntryPtName.(1)
Launch 'AppName'
That should do it. This is basically the same technique that is used to debug MPW® tools.
There are a couple of restrictions on this technique:
1. Your code resource must be in the applications resource fork;
2. HyperCard® XCMDs and XFCNs cannot be debugged in SADE.
Platforms & Tools: SADE: How MPW and SADE 1.0 work together
Why is using SADE 1.0 to step through an MPW® Tool so slow?
When MPW launches a Tool, it acts much like Finder™ launching an application. The MPW shell now becomes the operating system for the Tool. But unlike Finder, MPW has no hooks for a debugger like SADE. Because of this, SADE requires a huge amount of overhead for each step operation it performs. For each step operation, SADE must:
1. Save its low memory space so that MPW’s and the Tool’s may be swapped in;
2. Restore MPW’s as well as the Tool’s low memory;
3. Perform the necessary debugging operation (step);
4. (Block)Move the newly updated low memory to an area accessible by SADE (so that SADE’s low memory may be restored). Once SADE is restored, it will want to report on the new low memory state. This is why low memory had to be copied to an area accessible by SADE;
5. Swap SADE’s low memory space back in so that SADE can operate.
Platforms & Tools: SADE: Why using SADE 1.0 to look at low memory is so slow
Why is using SADE 1.0 to look at low memory so slow?
Since SADE needs to use low memory just like any other application, there is some overhead involved when using SADE to view low memory. Here is what SADE has to do to view the target application’s low memory:
1. Save its low memory space so that target application’s may be swapped in;
2. Restore the target’s low memory;
3. (Block)Move the newly updated low memory to an area accessible by SADE (so that SADE’s low memory may be restored). Once SADE is restored, it can report on the new low memory state. This is why low memory had to be copied to an area accessible by SADE;
4. Swap SADE’s low-memory space back in so that SADE can now analyze the low memory it copied in step #3 above.
Platforms & Tools: SADE: Can I use SADE to debug my XCMD/XFCN?
Can I use SADE to debug my XCMD/XFCN?
No. SADE currently doesn’t support debugging HyperCard® external commands.
Platforms & Tools: Virtual User: Virtual User and Macintosh Plus keyboard
Can I use a Macintosh Plus with an international keyboard as a Virtural User (VU) host?
Unfortunately, VU currently does not fully support the Macintosh Plus international keyboard. The VU General Reference manual (page 60) states, “key events for keys on this keyboard which have key codes that differ from those of the U.S. version of the keyboard will not be generated properly. The ASCII value portion of the key event will be correct but the key code will not be correct. This should only affect applications which use the key code portion of key events.”
Platforms & Tools: Virtual User: AppleLink’s Virtual User forum is a good resource
AppleLink’s Virtual User forum is a good resource
When you have Virtual User (VU) questions, you can usually obtain fast answers via AppleLink’s Virtual User forum from other developers as well as the VU authors monitoring the forum. The path to access this discussion is: Developer Support:Developer Talk:Macintosh Development Tool Discussions:Virtual User Discussion.
Platforms & Tools: Virtual User: Virtual User workaround for setting an individual list element
How do you set an individual element of a list using the Macintosh® Virtual User tool? When using the following code, the second line results in a syntax error.
x:={1,2,3,4,5}; #define a list
x[2]:=5; #change the 2nd element of list x
printlt x[2]; # print to log file the value of the 2nd element of list x
You’re right! I’m amazed, but I just tried it myself and got a syntax error. To work around this, I would suggest that you try to concatenate the left and right portions of the list to the new middle value. For example, if you want to change the second element of the list, concatenate the first element with your new value, and concatenate that result with the remaining elements in the list.
To make up for this deficiency, we have provided some system tasks in the language which help manipulate lists, such as
insert (element, index, list)
replace (element, index, list) and
remove (index, list)
These system tasks are described in Appendix F of the Virtual User Language Reference. (With future releases, you probably will be able to assign a value directly to a list element.)
Platforms & Tools: Virtual User: Path to AppleLink’s Virtual User forum
What is the path to the Virtual User (VU) forum on AppleLink®, mentioned in the Virtual User 1.0ß5 Release Notes?
The path for this discussion is “Developer Support:Developer Talk:Macintosh Developer Tools Discussions:Virtual User Discussion.”
Platforms & Tools: Virtual User: Macintosh Virtual User C++ headers
Do the MacApp® Units for Virtual User (VU) work with C++ and MacApp?
The MacApp Units for VU should work fine with C++. In the VU discussion folder on AppleLink® you’ll find a file called C++ Header Assist (or something like that). These are the C++ headers for VU, from Apple Europe. A VU engineer here says to his knowledge, the headers work fine, though he hasn’t tested them thoroughly. "Official" C++ headers should be available in the next month or so.
Platforms & Tools: Virtual User: Macintosh Virtual User testing system is compatible with A/UX
Does Virtual User 1.0ß5 run on an A/UX® system? If so, are there any special versions needed to be running this?
You should have no problem running VU on A/UX. If you do run into any problems, you might want to try upgrading to A/UX 2.0.1 (as opposed to 2.0), because VU was revised for compatibility with 2.0.1 and it may not be totally backwards compatible. But as far as I know, it should work fine with either version with no special enhancements needed.
Toolbox & IAC: Apple Events: Apple Event handler: Installation code
I’m writing a small application that uses Apple events, which neither opens documents nor prints. Inside Macintosh Volume VI says that all Apple event- aware applications should support the odoc and pdoc Apple events, but these are not appropriate in my case. What should I do?
You don’t necessarily need to install a handler for each event, but it makes your code cleaner. If you don’t have a handler, the Apple Event Manager will automatically return errAEEventNotHandled from your AEProcessAppleEvent call, since it can’t find a handler for the event in the handler tables. But we recommend installing handlers for the required Apple events anyway; it makes your code cleaner and easier to understand, as well as easily allowing you a place to put a routine when you need to implement it. And it doesn’t take up much memory. Just install a handler like this (in MPW C):
pascal OSErr AEPrintHandler(AppleEvent *messagein,
AppleEvent *reply, long refConIn)
{
/* Tell the compiler I'm not using these parameters */
#pragma unused (reply,refIn,messagein)
return(errAEEventNotHandled); /* and return my error */
}
Toolbox & IAC: Apple Events: Finding Apple event sender target ID of process serial number
How can I identify the sender of an Apple event?
If your application is just sending a reply, it should not be creating an Apple event or calling AESend. Instead, it should stuff the response information into the reply event in the Apple event handler, as shown on page 6-50 of Inside Macintosh Volume VI. The Apple Event Manager takes care of addressing and sending the event.
To find the target ID or process serial number of the sender of an Apple Event, use AEGetAttributePtr to extract the address attribute, as follows:
retCode := AEGetAttributePtr(myAppleEvent, keyAddressAttr,
typeWildCard, senderType, @senderBuffer, sizeof(senderBuffer),
senderSize)
The senderBuffer can later be used with AECreateDesc to create an address to be passed to AESend. The buffer should be at least as large as data type TargetID. See Inside Macintosh Volume VI, page 5-22, for a description of
TargetID.
Toolbox & IAC: Apple Events: Checking for registered sections
Inside Macintosh states. “…your application must keep its own list of registered sections for each open document that contains sections.” Which NewSection() and RegisterSection() results codes indicate the section was not registered successfully? Is there a field in the section record which can be examined to determine if the section is registered?
Checking the error codes is always a good idea, but the IsRegisteredSection routine should be used to determine if a section is registered—for example, after calling NewSection and RegisterSection. The fields of the section record should not be used to determine this.
Toolbox & IAC: Apple Events: Apple event application error handling
What do we return to the Apple event handler if we get an application error while processing a standard event, Edition Manager event, or custom Apple event for commands and queries? Probably not errAENotHandled, since that means we didn’t handle the event, which is different from trying to handle it and failing. Would it be errAEFail? What if we want to return more specific error information? Do we define our own errors, or try to use Apple’s errors such as memFullErr or parmErr?
You pass back errAENotHandled, because it’s true, and because some simple applications will not be able to handle anything more than that. What you can also do, and what most commercial applications will do (particularly applications that want to be scripting savvy), is add errn and errs parameters to the reply record for that event (as shown on page 6-49 of Inside Macintosh Volume VI). You can be as descriptive as you like in the text—the more the better, in fact, since this text will be seen at the user level usually. The errn value you pass back can be the system error number; then the sending program may be able to recover and try again.
Toolbox & IAC: Apple Events: Apple 'cncl' section cancel event
When will the “section cancel” Apple event be implemented in the future so the system can send it? I’ve implemented it, but because it’s hard to telt it, I’m tempted to take it out, unless you can give me a good reason to leave it in.
There’s no indication when this event will be implemented by the system. The 'cncl' event is primarily in there for applications to facilitate scripting compatibility, not for system use. Since Apple is encouraging all applications to send Apple events to themselves in response to user actions, the 'cncl' event is provided for completeness and user understanding. When scripting systems become more prevalent, then the 'cncl' (and other events) will make a lot more sense, since a scripter can then record (or a user scripting tool generate) a section cancel event and keep it in an Apple event script.
Toolbox & IAC: Apple Events: Apple events to yourself bypass WaitNextEvent processing
If I send Apple events to myself and specify kAEQueueReply to AESend, the event does not get put in the queue like I asked for. It shows up immediately in the reply parameter. According to Inside Macintosh, if I specify kAEQueueReply I should treat the reply event as undefined. Please help; my app falls apart because it never receives the event it is supposed to. If this is a bug, will the behavior be changed in the future?
This is not a bug, it’s an undocumented “feature” of the Apple Event Manager. If you send an Apple event to yourself, the Apple Event Manager *directly dispatches* to the handler you have installed for that event. So Apple events you send to yourself do not come in through WaitNextEvent.
This means that if you reply to an Apple event you sent yourself, then your 'ansr' handler will get called directly.
This was not an arbitrary decision, though it can have some confusing ramification for an application. Two factors influenced the decision, the first minor, the second major:
1) Speed. The Apple Event Manager has all the handlers for your application in a hashed table, and can dispatch VERY quickly to them, so for performance reasons direct dispatching was implemented.
2) Event priorities and sequencing. Apple events have a lower priority than user-generated events (keys, clicks), Apple events come in right before Update events. This created a potentially serious problem for applications that sent Apple events to themselves.
If all Apple events came through the event loop, the following scenario could very easily be created:
• User selects menu item, application sends an Apple event to itself in response, and this Apple event requires a reply or will cause other Apple events to be sent.
• User clicks with the mouse in an application window.
The mouse click would have a higher priority than the reply or any Apple events that are sent in response to the first Apple event, and would get posted ahead of the Apple event in the event queue. Which would mean that the mouse click would happen and conceivably change the current context of the application (perhaps switching windows, for example); then when the Apple events sent by the menu item handler were processed through the queue, the application state would *not* be the same as it was when the menu selection was made, and the menu selection may be totally inappropriate for the current configuration.
So, to prevent a loss of sequencing, the Apple Event Manager (AEM) directly dispatches. Any non-Apple events that happen while you’re sending and processing an Apple event to yourself will be queued and not interrupt the Apple event process you’ve initiated.
What this means in the case you’re describing is that queued replies do not happen when you are sending to yourself. The AEM will directly dispatch to your 'ansr' handler, to prevent any other events from breaking the chain of Apple events you may be processing.
So WaitNextEvent processing of Apple events is bypassed when you are sending events to yourself. This isn’t a major problem, but it is something you need to be aware of if you are expecting some other events to be processed before you get a reply or other Apple event.
Toolbox & IAC: Apple Events: AESend -600 error
When I send an 'odoc' Apple event to an already-running application, I get an -600 error at the AESend call. The process serial number is correct at entry. What is this error, and is it documented anywhere?
The error -600 means that the process serial number that you sent is either invalid or is the serial number of a process that does not accept Apple events—that is, the high-level event bit of the destination process’s size resource isn’t set.
Toolbox & IAC: Apple Events: Construction of Apple events
What is the construction of Apple events that is passed to an application at
launch time?
You can coerce the 'odoc' Apple event to a data type that doesn’t need to be pre-addressed.
A sample called ProcDoggie on the System 7.0 CD demonstrates this . If you look in the UProcessUtils.inc1.p file, you’ll find this comment:
“To create the kAEOpenDocuments or kAEPrintDocuments Apple event, a target address descriptor is needed. Because we’re converting the Apple event into a typeAppParameters descriptor rather than sending it somewhere, it doesn’t matter what target address we use. I just used the process serial number (PSN) of this application as a dummy value. Because this is an application and not something like a driver, I can just use the “kCurrentProcess” constant to represent this application’s PSN. A descriptor is made of this PSN, then this PSN is used when creating the new kAEOpenDocuments AppleEvent. Once this Apple event is created, the PSN descriptor is no longer needed and is disposed of.”
In other words, you just dummy up an address and coerce the descriptor to be of type typeAppParameters, and the address will be corrected for you by the AppleEvents Manager. Please refer to the ProcDoggie sample source code for the complete picture of how this is done.
Toolbox & IAC: Apple Events: Apple’s Apple Event Registry
How can I get a list of all Finder™ Apple events and a list of all Apple events in general from Apple?
The current list of known Apple events is in the Apple Event Registry. The latest version is on the System 7 Golden Master CD.
The registry will be the source point for finding out about current and new events, both those accepted as standard events by Apple and developers, and also for custom events that are application specific. The registry will be updated periodically, and the updates will appear on the Developer’s CD and will also be posted on AppleLink®.
The registry on the GM CD contains all the currently registered standard Apple events and all of the Finder events.
Toolbox & IAC: Apple Events: Macintosh Finder 'odoc' and 'pdoc' handling problems fixed
According to Inside Macintosh® Volume VI, after receiving a kAEPrintDocuments Apple event, eventually my application should then receive a kAEQuitApplication event, but does not. What’s wrong?
To mutilate Shakespeare: “The problem is not in the apps, but in our system…” The beta versions of the Finder™ did two things wrong:
1) Did not bring the application to the front on an 'odoc' or 'pdoc'
2) Did not send a 'quit' after a 'pdoc'.
Both these problems have been fixed in the final version of 7.0, so you should have no problems now.
These problems existed in the Finder because the Finder is not fully Apple event capable. The design and implementation of the Finder was completed _before_ the final decision to include the AppleEvent Manager (AEM) in the System was made. So, the Finder doesn’t use the AEM, it uses PostHighLevelEvent to send its events. Therefore, it does not use interaction flags, or some of the other features of the AEM. So, some of the behavior of Finder events was not in sync with the AEM for beta releases. Again, it’s beenfixed; you should experience no problems with the final version.
Toolbox & IAC: Apple Events: Apple Event Registry documentation fixes
The information in the Apple® Event Registry doesn’t appear to be complete, and some of the constants are wrong. Where can I go to get the latest, correct information?
The Apple Event Registry is a dynamic document, and will continue to change and be corrected as errors are found and developers define new suites of events. The best way for you to keep up with the Apple events world is to check AppleLink® periodically (path Developer Support:System 7 Talk:AppleEvents Discussion) for the latest and greatest information. New registry releases, errata messages, AppleEvent tools, and other information from Apple are posted there. Also, many third-party developers post their own tools and observations, and may save you hours of development time.
Toolbox & IAC: Apple Events: Opening documents from another application
How can I open Macintosh® documents that belong to an application that’s already running?
If you find that you have the Apple Event Manager present, then build 'odoc' Apple events to your heart’s content, and send them to whomever you wish. The Process Manager will hop in there if the target isn’t Apple event-aware and coerce the required Apple event to the appropriate Puppet String for you. No further hacks on your part are required. You literally don’t care (at least for the purposes of the required Apple events) whether your target is aware or not.
Toolbox & IAC: Apple Events: Core Apple events testing
Do you have any available tools or test programs for testing how well our Macintosh® application responds to core Apple events? We need a test application that will, for example, send events to open a document and print it within our application.
One of the best tools to test Apple events like 'odoc' and 'pdoc' is the Finder®. The System 7.0 CD version of the Finder provides excellent 'odoc' and 'pdoc' testing capabilities. That’s what most of DTS uses to test sample applications.
There are no tools designed specifically to send Apple events to an application as a test. Try using some of the DTS sample applications on the Developer Essentials disc to test your application. One of the easiest to use and adapt is the TrafficLight 3.0 sample. It already will send its own MoveWindow Apple event to any application, allowing you to see how your application is handling “foreign” events.
Also, you can adapt the CreateAndSendAppleEvent function in AppleEvents.c to send any type of event you’d like, which allows you to test events that may be specific to your application.
Toolbox & IAC: Control Manager: Changing a Macintosh control’s variant
What is the proper method to set a control’s variant field, if there’s no SetCVariant trap?
There is no way to set the Variant field of a control from the toolbox. Standard controls do not support the dynamic modification of the variant field; they are not tested for this and an undefined error could result. As for custom controls, if you need to change a variant midway through the control’s use, it’s better not to use the variant field at all, but instead to store your own data structure in the ctrlData field to track what type of control you are drawing. The reason for this is that the variant field is not always in the same place. The only time it is in a well-defined place is when you are operating in 24-bit mode (then it is stored in the high byte of the controls defproc handle, as documented in Inside Macintosh Volume I). When you are in 32-bit mode, it is stored in the AuxCtlRec in a private location.(high byte of the Reserved field right now, but that can change in an instant...)
Toolbox & IAC: Control Manager: Debugging a Macintosh 'CDEF' resource
Can you recommend documentation describing techniques for debugging 'CDEF's?
You debug 'CDEF's in almost the same way that you debug anything else. You should familiarize yourself with the order that messages are received when certain actions take place. One way to do this is to install some breakpoints in the main routine of DTS’s sample 'CDEF', watch the messages go by, and examine the parameters that are passed. This way you should be able to predict exactly what messages you should receive. (By the way, be sure to read Macintosh® Technical Note #212 on 32-bit cleanliness for information on the new 'CDEF' messages.)
Just as an aside, when tracing through a 'CDEF', use the following to break conditionally at certain points only if the Shift key is held down:
Function TestShift:Boolean;
InLine $1EB8,$017B;
Then, whenever you want to break, insert
If TestShift then DebugStr('Stopped because you held down
the shift key!');
Toolbox & IAC: Control Manager: Color with Macintosh radio button and check box controls
I can control the color of a Macintosh® radio button and its accompanying text using a control color table, but I am not able to exercise much control over the color of the background rectangle. Let’s say, for example, that I create a window whose content area is gray (using SetWinColor). Within the window, I draw a black box, and within the black box, I draw a pair of radiobuttons whose text color is white. I would like the background rectangles of the radiobuttons to be black so that they will match the color of the box. Unfortunately, using Draw1Control, the Control Manager seems to draw the background rectangle using the content color of the window (in this case, gray). Is there any easy way to get around this? (Calls to RGBForeColor and RGBBackColor seem to have no effect during Draw1Control.)
The explanation for the problems you are having is very simple. Standard check boxes and radio buttons use the window content color for their background. This is by design since the text of the button is not bounded by anything. Here are two resolutions to your problem: You can simply set your window background to the background you want the button to have, or you can write your own 'CDEF' to handle buttons and have it use the control’s background color instead of the window’s content color. You’ll find sample code that does this in the Snippets folder on AppleLink® and the latest Developer CDs.
Toolbox & IAC: Control Manager: Use calcCntlRgn and calcThumbRgn instead of calcCRgn high bit
We tried using our Macintosh® System 6.0 scroll bar 'CDEF's under System 7.0 Golden Master and find that they no longer update properly (although they worked fine in older versions of System 7). What's changed?
Nothing much has changed as far as custom 'CDEF's go between System 6 and System 7, except for the way the system gets the indicator (thumb region) for a control. As you may know, the high bit of the parameter passed to calcCRgn used to be set to indicate that only the thumb region was needed. Because this is not 32-bit clean, Apple has defined two new messages that work just like the old calcCRgn: calcCntlRgn (message #10) wants you to fill param with the entire control’s region structure, and calcThumbRgn (message #11) simply wants the indicator region. It is also important to note that you must return a non-zero result if you actually return this data. You probably are not yet processing these messages, or you are not setting your result to 1 to indicate that you have created the regions. You might also want to take
You might find DTS’s current sample 'CDEF', in the Snippets folder on AppleLink and the latest Developer CDs, helpful. Even though it is not a scroll bar, you can see the “standard” way to use the color table information.
Toolbox & IAC: Control Manager: Mouse clicks within Apple IIGS static text or picture control
I’m having trouble detecting clicks on picture and static text controls, even though I’m doing exactly what the Apple IIGS® Toolbox Reference, Volume 3 says to do.
There is an error in the Toolbox Reference regarding static text and picture controls. The definition procedures for these control types do not include code to test for clicks within the control rectangle; therefore, routines like TestControl will always return FALSE. If you want to test for mouse clicks within a static text or picture control, retrieve the control rectangle from the control record and use a routine like PtInRect.
Toolbox & IAC: Control Manager: Apple IIGS control color table resource ID & Types.Rez
What is the resource ID for an Apple IIGS® control color table, and why is it so hard to find in the Types.Rez interface file?
The resource ID for control color tables is $800D, and is referenced in Types.Rez as resource name r_BBBB. It is listed under its regular name (rCtlColorTable) in Appendix E of the Apple lIGS Toolbox Reference, Volume 3. The obscure name in Types.Rez. and the lack of a resource structure either in Types.Rez or Appendix E is caused by the structure being variable, depending on the control type associated with the color table.
Toolbox & IAC: Control Panels: System 7 Finder filters Command-key messages from cdevs
Our cdevs no longer receive key-down messages with the Command key held down in System 7. Why is this?
This is true under System 7.0. Under System 6.0.x, when a cdev is brought up with the Control Panel active, the cdev is the only possible recipient of key-down or auto-key events. Under System 7.0, the Finder has become the event-switching center and now handles the passing of events to the cdev(s). You’ll note that you can now have multiple cdevs open simultaneously. This design raised the potential problem that, with the Finder and other cdevs active at once, which one would be the target of the any command-key sequence.
If you use Command-F while a cdev is open, the Find dialog box appears under System 7.0. If a cdev is designed to respond to Command-F, should the Finder handle the command sequence as a command to Find, or send the sequence to the cdev?
To maintain the Finder user interface, engineering decided to translate all Command-key events to their respective cdev equivalents for those sequences which were published in Inside Macintosh Volume V. This means that instead of having to process Command-Z, V, C, or X, the cdev receives the appropriate undoDev, pasteDev, copyDev, or cutDev message. The Finder knows to send these messages to the cdev with the currently active window. Otherwise, the Finder filters Command-key messages from the cdev(s).
You can still determine whether the command key is held down by using the GetKeys function at the cdev’s entry point, as shown in the following code sample:
pascal Handle
CDEVEntry(short message, short item, short numItems, short CPanelID,
EventRecord *theEvent, Handle cdevValue, DialogPtr CPDialog)
{
#pragma unused (CPanelID) /* unused formal parameters */
KeyMap myKeys;
CDEVHdl cdevStorage;
...
cdevStorage = (CDEVHdl) cdevValue;
if (message == macDev) {
return( (Handle) 1); /* run on all systems */
}
else if (cdevStorage != nil) {
GetKeys(myKeys);
if (myKeys[1] & 0x00008000)
{
/* Command key presently down */
}
…
}
After determining whether the command key is held down, you need to determine the complete command key sequence by checking for other keys currently pressed in the KeyMap variable.
This solution doesn’t resolve problems such as responding to Command-F or Command-G. Also, it's not clear what new keys might be grabbed by the Finder team for use in future system versions.
Toolbox & IAC: Control Panels: Apple IIGS QuickDraw Auxiliary and CDEVs
Can an Apple IIGS CDEV assume that QuickDraw Auxiliary is started while its window is open? The Control Panel requires it for drawing the icons, so I am assuming it is left up.
Yes, CDEVs can count on QD Aux. The Control Panel does use it, and it will be started when you are called.
Toolbox & IAC: Control Panels: Apple IIGS CDEV windows with Control Panel RunCDEV call
It is possible with the Apple IIGS Control Panel NDA to issue the RunCDEV call before the CDEV’s window is actually drawn? Shouldn’t Control Panel make sure the CDEV is displayed before calling RunCDEV?
There are cases where you get a run before the window is drawn. To draw at run time, simply wait for an update event, set a flag saying draing is OK, and then draw away.
Toolbox & IAC: Control Panels: 'fwst' is window-position resource for cdevs
What’s the 'fwst' resource found in several System 7 cdevs as well as on the System 7 Golden Master CD? We want to make sure it’s not a virus.
The ‘fwst’ resource is the window position resource for cdevs. Under System 7.0, each cdev now appears in its own window. This is unlike previous systems where they appeared in the Control Panel window. Well, since each cdev now has its own window, it is expected that the user will want to place the window in a location that is suited to the user and the cdev. To keep this information for the next time the cdev is called up, the Finder now keeps an ‘fwst’ resource in the cdev, whether or not you placed one in there yourself.
Toolbox & IAC: Control Panels: cdevs and foreign language balloons
My cdev contains a 'STR#' resource for each foreign language we support. Prior to Balloon Help, text was taken from the resource file by doing a GetResource('STR#', BASE_ID + countryCode). Now, with Balloon Help, I have to have fixed resource IDs in the 'hdfr' and 'hdlg' resources. It would be nice to be able to tell the Help Manager to use the BASE_ID + countryCode selector, though as a workaround, the INIT associated with the cdev renames resources so that the correct text is selected.
You can set the dialog resource number explicitly from the code. Use the HMSetDialogResID (dialog number + country code), and have a different 'hdlg' for each country.
Toolbox & IAC: Control Panels: Control Panel cdev Balloon Help
How do I completely mimic the help in Apple’s Control Panel cdevs? Apple’s cdevs have two forms of help: (1) point to the icon and you get the descriptive text of what the cdev does, and (2) point to the name and you get both the descriptive text and help on how to change the name. I can only get (1) from the (hfdr, -5696) resource. Also, when I open my control panel, THEN point to the icon, I get the default help message, as if my balloon help were not present. If the control panel isn’t open, then the help is correct. Apple’s cdevs don’t do this; the correct help is displayed regardless of whether or not the cdev is open. What’s up?
The truth is that you cannot mimic the help given for Apple’s cdevs. The Finder is special-cased for the items that Apple includes on its disk, and in the Finder help file you’ll find all the help messages that go along with the cdevs and DAs and such. You’ll also find some 'fmap' resources. These basically point the Finder to the proper help message for each filetype/creator combination that Apple has. This is how the Finder knows to treat the icon specially. You aren’t supposed to modify these resources, so there is no way to mimic the Apple’s cdev help.
Toolbox & IAC: Control Panels: Control Panel devices on the Macintosh SE
I’m rewriting a Macintosh® II cdev for the Macintosh SE. I have changed the 'mach' (-4064) resource from $3FFF $0000 to $FFFF $0000 so the device will appear on all machine types, but it still doesn’t show up on the Macintosh SE.What else should I check for?
Try rebuilding your Control Panel cache, by holding down the option and command keys while opening the Control Panel. This will rebuild the list of things that the Control Panel is able to open. Because there’s no Control Panel DA under System 7, this technique works only for operating systems prior to System 7.
Toolbox & IAC: Dialog Manager: Code for displaying a Mac modal dialog in 10-pt plain Geneva
Code for displaying a Mac modal dialog in 10-pt plain Geneva
Here’s how to force a Macintosh modal dialog to display 10-point Geneva in static text and edit text items, and to make it stay that way:
CONST
kDlogID = 128; {Resource ID of our DLOG resource}
kEditTextItem = 3; {Item number of first editText item in theDialog}
VAR
theDialog: DialogPtr; {Pointer to our dialog box}
fontNum: Integer; {Font number of Geneva}
itemText: TEHandle; {Handle to theDialog's editText}
currFont: FontInfo; {Current font information}
(* Get our dialog box and make it the current port *)
theDialog := GetNewDialog (kDlogID, NIL, WindowPtr(-1));
SetPort (theDialog);
(* Set the text characteristics of the port *)
GetFNum ('Geneva', fontNum);
TextFont (fontNum);
TextSize (10);
(* Get a handle to the dialog's editText item *)
SelIText (theDialog, kTextItemNum, 0, 0);
itemText := DialogPeek(theDialog)^.textH;
(* Set the text characteristics of the editText item *)
itemText^^.txFont := fontNum;
itemText^^.txSize := 10;
(* IMPORTANT! Set the lineHeight and fontAscent fields of itemText *)
GetfontInfo (currFont);
itemText^^.lineHeight := currFont.ascent + currFont.descent +
currFont.leading;
itemText^^.fontAscent := currFont.ascent;
(* Now, enter the ModalDialog loop *)
Toolbox & IAC: Dialog Manager: Macintosh password dialog filter code
Macintosh password dialog filter code
The following code allows you to create a “password” dialog box. The code was adapted from the USENET Macintosh Programmers Guide, available on the System 7 beta (not Golden Master) CDs and on the USENET network. The code (admittedly a little twisted) stores each keypress event character before changing it into a “•” and it handles cases where the user selects and replaces a range of characters in the edit text item. In addition to handling bullet characters, it also handles cut/copy/paste/clear commands under System 6.
char gPwStr[256]; /* global to store the password */
short gScrambleItem; /* item # to password blank */
/* PasswordFilter is the dialog filter used to switch all
keys pressed into bullets (•) to hide the user’s password
from view.
*/
pascal Boolean PasswordFilter(DialogPtr theDialog,
EventRecord *theEvent,short *itemHit)
{
DialogPeek dPeek;
char theChar;
short selStart,selEnd;
dPeek = (DialogPeek) theDialog;
if (!dPeek)
return false;
if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
theChar = theEvent->message & charCodeMask;
if ((theEvent->modifiers & cmdKey) != 0
&& (dPeek->editField != gScrambleItem-1)) {
switch (theChar) {
case 'x':
DlgCut(theDialog);
*itemHit = 0;
return true;
case 'c':
DlgCopy(theDialog);
*itemHit = 0;
return true;
case 'v':
DlgPaste(theDialog);
*itemHit = 0;
return true;
case '.':
*itemHit = Cancel;
return true;
default:
return false;
break;
}
}
else if (dPeek->editField == gScrambleItem-1) {
theChar = theEvent->message & charCodeMask;
selStart = (**(dPeek->textH)).selStart;
selEnd = (**(dPeek->textH)).selEnd;
switch (theChar) {
case 0x08: /* backspace */
if (selStart == selEnd) {
if (selStart > 0)
BlockMove((Ptr)gPwStr + selStart,
(Ptr)gPwStr+selStart-1,
strlen(gPwStr)-selStart+1);
}
else
BlockMove((Ptr)gPwStr + selEnd,
(Ptr)gPwStr + selStart,
strlen(gPwStr)-selEnd+1);
break;
case CR: /* CR */
case 0x03: /* enter */
*itemHit = OK;
return true;
break;
case 0x09: /* tab */
case 0x1c: /* left */
case 0x1d: /* right */
case 0x1e: /* up */
case 0x1f: /* down */
return false;
break;
default:
BlockMove((Ptr)gPwStr+selEnd,
(Ptr)gPwStr+selEnd+1,
strlen(gPwStr)-selEnd+1);
*(gPwStr+selStart) = theChar;
theEvent->message = 0xffffff00 + '•';
return false;
break;
}
}
else if ((theChar == CR) || (theChar == 0x03)) {
if (gScrambleItem==4) {
theEvent->message = 0xffffff00 + '\t';
return false;
}
else {
*itemHit = OK;
return true;
}
}
else if (theChar==0x1b) {
*itemHit = Cancel;
return true;
}
}
return false;
}
-------- CODE TO CALL ABOVE -----
...
gPwStr[0] = '\0';
gScrambleItem = 4;
TEFromScrap();
do
ModalDialog((ProcPtr)PasswordFilter,&item);
while (item != OK && item != Cancel);
TEToScrap();
Toolbox & IAC: Dialog Manager: Movable modal dialog WDEF 0 procID
We’re using movable modal dialogs under both Systems 6 and 7. The standard System 7 WDEF 0 uses a procID of 5. The Apple WDEF ID 128 designed for System 6 usage requires a procID of 2503 (ID 128 * 16 + 5). Can Gestalt be used to detect at runtime whether WDEF 0 supports a procID of 5, so we can change the in-memory 'DLOG' resource’s procID to 2503 if necessary?
Also, are we free to use the WDEF (from latest Developer CD Series disc) in our commercial applications, or do some restrictions apply?
Please, use the WDEF that DTS provides on the CD with a clear conscience. You are free to use it all you like.
Unfortunatly the MovableModal WDEF is one of the many features that you cannot use gestalt to explicitly test for. However, what you should do in this case is simply test for system 7.0 or later, and if you have that then the new WDEF is available (I know we told you guys not to test the system version but in this instance its ok.) BTW the presence of the new DITL manipulation calls does not signify the movable modal WDEF so the gestalt test you were doing is not valid.
Toolbox & IAC: Dialog Manager: DialogDispatch and ShortenDITL routine
Can you give me the selector to DialogDispatch for the ShortenDITL routine. The routine is mentioned in Chapter 3, “Compatibility Guidelines,” of Inside Macintosh Volume VI, but there is no interface in any of the latest header files.
DialogDispatch does not have this routine. All routines for manipulating the dialog item list are part of the Macintosh Communications ToolBox dispatcher and are located in the ctbUtilities interface files. These are available on the System 7.0 Golden Master CD, as well as the latest Developer CD Series disc.
Toolbox & IAC: Dialog Manager: Where to find WDEF for movable modal dialog boxes
Where to find WDEF for movable modal dialog boxes
The WDEF for movable modal dialog boxes is available on the latest Developer CD Series disc as follows:
Developer Essentials:Technical Docs:Human Interface:
Human Interface Goodies:Movable-Modal WDEF 1.0.1
and on AppleLink:
Developer Support:Developer Services:
Developer Technical Support:Developer Essentials:…
Toolbox & IAC: Dialog Manager: Sample resources for setting font & size of Macintosh text items
How can I get a Geneva 9-pt default for static text and text edit items in my dialog?
The Dialog manager provides a mechanism for changing the font/size of static and edit text items via the 'ictb' (item color table) This structure is documented in inside Macintosh Volume V, pages V-279 to V-281. Basically you create an 'ictb' that has entries for each item that you want to modify. The only unfortunate aspect of this whole process is that we do not have rez templates for 'ictb's . So, I am including the source code to some sample resources that might help you get started.
----------------------- rez source code follows -----------------------
/* dlog stuff */
resource 'DLOG' (128) {
{80, 74, 290, 464},
dBoxProc,
visible,
goAway,
0x0,
128,
""
};
resource 'DITL' (128) {
{ /* array DITLarray: 8 elements */
/* [1] */
{185, 305, 205, 363},
Button {
enabled,
”Done”
},
/* [2] */
{46, 290, 64, 369},
CheckBox {
enabled,
”Memory”
},
/* [3] */
{97, 290, 115, 369},
CheckBox {
enabled,
”Memory”
},
/* [4] */
{148, 290, 166, 369},
CheckBox {
enabled,
”Memory”
},
/* [5] */
{41, 12, 70, 275},
EditText {
enabled,
""
},
/* [6] */
{92, 12, 121, 275},
EditText {
enabled,
""
},
/* [7] */
{143, 12, 172, 275},
EditText {
enabled,
""
},
/* [8] */
{5, 6, 21, 269},
StaticText {
disabled,
”Type into them to see whats up”
}
}
};
resource 'dctb' (128) {
{ /* array ColorSpec: 5 elements */
/* [1] */
wContentColor, 65535, 65535, 52428,
/* [2] */
wFrameColor, 0, 0, 0,
/* [3] */
wTextColor, 0, 0, 0,
/* [4] */
wHiliteColor, 0, 0, 0,
/* [5] */
wTitleBarColor, 65535, 65535, 65535
}
};
data 'ictb' (128) {
$"0020 0020” /*$00 the button item */
$"0000 0000” /*$04 Check box 1 */
$"0000 0000” /*$08 Check box 2 */
$"0000 0000” /*$0C Check box 3 */
$"0000 0000” /*$10 Edit Text 1 */
$"000D 0040” /*$14 Edit Text 2 just change the */
/*family, size, and text color */
$"0000 0000” /*$18 Edit Text 3 change family and */
/*size, using font name */
$"8005 0054” /*$1C Stat Text 1 */
/* Start of the ictb items here */
/* Color table for the done button */
$"0000 0000” /*$20 ccSeed */
$"0000 0002” /* Reserved / size of color table */
$"0000 0000 0000 FFFF” /* cFrameColor, 65535,65535,52428 */
$"0001 FFFF FFFF CCCC” /* cBodyColor, 0, 0, 0 */
$"0002 0000 0000 FFFF” /* cTextColor, 0, 0, 65535 */
/* Edit Text 2 item text/color info... */
$"0001” /*$40 diFont application font */
$"0000” /*$42 diStyle plain */
$"000A” /*$44 diSize whatever... */
$"FFFF 8000 0000” /*$46 forecolor */
$"FFFF FFFF CCCC” /*$4C backColor */
$"0000” /*$52 diMode */
/* Edit Text 3 item text/color info... */
$"0068” /*$54 diFont application font */
$"0000” /*$56 diStyle plain */
$"000C” /*$58 diSize whatever... */
$"0000 0000 0000” /*$5A forecolor */
$"FFFF FFFF CCCC” /*$60 backColor */
$"0000” /*$66 diMode */
/* Start of the font name table here */
$"0743 6F75 7269 6572” /*$68 font name Courier */
};
Toolbox & IAC: Dialog Manager: Where to find System 6 WDEF for movable modal dialogs
Where can I find the Macintosh® WDEF for supporting movable modal dialogs in System 6?
For the WDEF information you are looking for, try AppleLink with the following path: Developer Support:Developer Services:Developer Technical Support:Developer Essentials:Technical Documentation:Human Interface:Human Interface Goodies:Movable-Modal WDEF 1.01.sit. It is also on the current Developer CD in the Developer Essentials folder. To locate it quickly on the Developer CD, use Pathfinder to search for Movable-Modal.
Toolbox & IAC: Dialog Manager: Alert ParamText problem and workaround
What causes the Macintosh® call to an Alert to hang if one of an Alert’s ParamText items contains “^1”?
You’ve noticed a ParamText problem that’s existed for quite a while. Unfortunately, we don’t know of an easy workaround, other than prefiltering the strings you’re passing to ParamText to remove all the “^”s.
A more complicated workaround would be to use a normal modal dialog instead of Alert. You could build the whole message yourself and completely replace the appropriate dialog item with it using SetIText. Of course, you’d have to simulate the default button yourself.
Toolbox & IAC: Dialog Manager: Alert dialog not updating
My Alert dialog doesn’t completely update if the application was in the background or if a screen dimmer was activated.
“When an alert is removed, if it was overlapping the default button of a previous alert, that button’s bold outline won’t be redrawn.” (Inside Macintosh® Volume I, page 419)
Alerts are intended to call the user’s attention to something that requires immediate action. It would be confusing for a window to be drawing over an alert. MultiFinder® and screen dimmers are not entirely consistent with the alert interface: a screen dimmer will draw over the alert, and an application in the background may need to display an alert.
If an application in the background wants to show an alert, it should use the Notification Manager. Otherwise, when the application gets switched into the foreground the Dialog Manager will not update the alert as it does when it was first drawn. An application can work around this by using a modal dialog. Have a user item installed, as the “Dialog Manager” chapter describes. When the dialog gets an update event, it will call the user item to redraw.
If you find that alerts don’t do what you want, consider either using a filter proc or not using the Dialog Manager at all, and simply create and manage the alert window and contents in your application.
Toolbox & IAC: Dialog Manager: Macintosh code snippet for default button with standard border
How do I draw a standard border around the default button in a Macintosh® dialog?
Here’s a code snippet that does what you want:
/* This draws the standard border around the default button */
/* in a dialog. To use it, just install a userItem as a */
/* button. I personally always use item #3 as my border */
/* userItem, so my code always looks the same. So, before */
/* you call ShowWindow, install the item… */
GetDItem(dialogwindow,kMyUserItem,&itemtype,&itemhandle,&rect);
SetDItem(dialogwindow,kMyUserItem,userItem,(Handle)CircDraw,&rect);
pascal void CircDraw(WindowPtr dwind,short dinum)
{short itemtype;
Handle itemhandle;
Rect lrrect;
GetDItem(dwind,ok,&itemtype,&itemhandle,&lrrect);
/* ok is defined as 1 in the interfaces. If you'd like another item */
/* outlined, change this number, of course. */
InsetRect(&lrrect,-4,-4);
PenSize(3,3);
FrameRoundRect(&lrrect,16,16);
PenSize(1,1);
}
Toolbox & IAC: Dialog Manager: Macintosh code snippet for using Esc key to terminate a dialog
I want to terminate a Macintosh® dialog if the Esc key is pressed. Do you have code for doing this?
Here’s the code snippet you want:
/* This is my standard Esc key filter. Many folks want */
/* to use the Esc key to terminate a dialog; this does it */
/* for them. It also shows how you can make any event */
/* activate any dialog item, in general. It also momentarily */
/* highlights the button it's faking for, so the user */
/* gets visual feedback about the action they just took */ /* Use it like so.... */
ModalDialog((ModalFilterProcPtr)StdEscFilter,&hititem);
pascal Boolean StdEscFilter(DialogPtr thewind, EventRecord *theevent, short
*theitem)
{char thekey;
short itemtype;
long tilticks;
Handle itemhandle;
Rect rectat;
WindowPtr temp;
if((theevent->what==keyDown)||(theevent->what==autoKey)){
thekey=theevent->message & charCodeMask;
/* This filters for Return or Enter as item 1, and */
/* Esc as item 2 */
if((thekey==0x0d)||(thekey==0x03)){*theitem=1;
GetDItem(thewind,1,&itemtype,&itemhandle,&rectat);
GetPort(&temp);
SetPort(thewind);
InvertRoundRect(&rectat,4,4);
Delay(10,&tilticks);
InvertRoundRect(&rectat,4,4);
SetPort(temp);
return(true);}
if(thekey==0x1B){*theitem=2;
GetDItem(thewind,2,&itemtype,&itemhandle,&rectat);
GetPort(&temp);
SetPort(thewind);
InvertRoundRect(&rectat,4,4);
Delay(10,&tilticks);
InvertRoundRect(&rectat,4,4);
SetPort(temp);
return(true);}
}
return(false);
}
Toolbox & IAC: Dialog Manager: Color dialog boxes on Macintosh 68000 systems
Why does a color dialog box with multiple fonts using both the ictb and dctb resources show up as a single font on 68000 machines?
Color QuickDraw™ is not loaded (implemented) on 68000 machines, therefore, 'ictb's are ignored. However, you may still be able to use multiple fonts on your dialogs if you use a userItem and draw them yourself. When you create a userItem, you can set all the necessary attributes, draw the graphics, and just about anything else you want to do with a dialog without trying to compete with the dialog manager. Whenever you try to force attributes into a dialog, such as fonts, you don’t always get the update messages. This can lead to sloppy looking dialogs. The dialog manager will let you do what you want with your userItem, then all you need to do is to set the font attributes back to what they were before.
Below is a sample of how to do a userItem. It is not necessarily complete, but it is good for reference to get you started.
/* create a userItem that covers the whole text area */
/* you want to draw (it can overlap other dialog items, */
/* like buttons and so on) and install your procedure */
/* to it like so */
GetDItem(tdial,itemNumber,&isitem,&theHandle,&rect);
SetDItem(tdial,itemNumber,userItem,(Handle)doMyDrawing,&rect);
/* theHandle and rect are not necessary for you to keep */
/* track of, they're just needed to fill out the call. */
Pascal void doMyDrawing(DialgoPtr dialWindow, short theItem)
{short theSize;
short theFont;
SetPort(dialWindow);
theSize=dialWindow->txSize; /* save the current size */
/* and font */
theFont=dialWindow->txFont;
DrawMeasureText(); /* do your drawing */
TextFont(theFont); /* restore stuff */
TextSize(theSize);
}
Toolbox & IAC: Dialog Manager: Using Geneva 9 in Macintosh dialog text fields
In a Geneva 9 Macintosh® dialog edit text item, the last visible token that extends beyond the end of the item’s rectangle is not drawn when first displayed. Typing a character into the invisible part of the string results in the character before and all characters after the typed character being drawn. The problem always appears in the same edit text items but not in every edit text item. The only difference seems to be the width of item rectangles. What’s wrong?
Here is some sample code that should show how to set up your dialog to better support Geneva 9 for your dialog’s text fields. I have used it in my own code and everything seems to work OK.
myDialog := DialogPtr(NewPtr(SIZEOF(DialogRecord)));
if myDialog = nil then
ExitToShell;
for i := 1 to 3 do
begin
if EventAvail(everyEvent, evt) then
end;
myDialog := GetNewDialog(rDialog, Ptr(myDialog), DialogPtr(-1));
SetPort(myDialog);
dp := DialogPeek(myDialog);
TextFont(geneva);
TextSize(9);
dp^.textH^^.txFont := geneva;
dp^.textH^^.txSize := 9;
SetWTitle(myDialog, 'ADSP Thing');
{do other dialog setup stuff here, like putting your text in your dItems.}
ShowWindow(myDialog);
Toolbox & IAC: Dialog Manager: 9-point Geneva with a userItem proc requires TextFont & TextSize
Is there any way to stop the Macintosh® Dialog Manager from playing with the txSize and txFace fields of a dialog’s grafPort so that I can draw Geneva 9- point text from within a userItem proc?
Unfortunately, because the Dialog Manager forgets about your previous calls to TextFont and TextSize when you put up your dialog again, you will need to call TextFont and TextSize every time your userItem proc is called.
Toolbox & IAC: Dialog Manager: Drawing a bold outline around default Macintosh dialog button
How do I draw a bold outline around the default button in a dialog?
The sample code you need is on pages 406-7 of Inside Macintosh® Volume I, in the section titled “Item Numbers.”
Toolbox & IAC: Dialog Manager: How to gray out & restore static text item of 'DITL' in a 'DLOG'
How can I “gray out” and restore a static text item of a 'DITL' in a 'DLOG'?
To change the text from black to gray:
SetPort(...); { grafPtr of the dialog's port }
GetDItem(...) { the static text item }
PenPat(gray);
PenMode(patBic);
PaintRect(...); { the item's rect }
PenNormal;
To restore the text to black:
SetPort(...); { grafPtr of the dialog's port }
GetIText(...); { the text to restore }
SetIText(...); { restore the text }
Toolbox & IAC: Dialog Manager: Extended controls in Apple IIGS dialogs
How can I put extended controls in an Apple IIGS® dialog?
The Dialog Manager does not support the new extended controls, and probably will not be revised to do so. Inserting extended controls as user items generally won’t work because the Dialog Manager will insert an invisible custom control over your extended control, preventing FindControl from finding it.
If you want a pop-up menu in a dialog, you can create a user item with code that contains a non-control pop-up menu. When you get a hit on the item, call PopUpMenuSelect to handle the selection of a menu item. You must handle the drawing of the menu title, selected item and drop-shadowed rectangle yourself.
Toolbox & IAC: Dialog Manager: DlgCut, Copy and Paste are OK for modeless dialog boxes
A modeless dialog box is the only window that ever comes up in my Macintosh® application. A keydown event along with the cmd cut, copy, or paste modifier key calls the DlgCut, DlgCopy, or DlgPaste routines, passing the dialog box handle returned from a GetNewDialog call. When this dialog box contains an enabled edit text item, the cut works, but the application pastes garbage or sometimes bombs.
DlgCut, DlgCopy, and DlgPaste are fine for what you are doing, and the procedure you describe for your implementation sounds like it should work fine.
You do not need to set the port (as long as you’re checking that the front window is a dialog, which doesn’t affect you since you only have one window); the routines take their action based on the item list attached to the dialog pointer you pass. In fact, DlgCut, DlgCopy, and DlgPaste work on the dialog you passed even if the dialog is not frontmost, which is why you need to check.
I just tried a few things to get these routines to crash, and the only thing I could do to cause a crash or garbage was to pass a nil pointer to DlgCut or copy or paste. This is on a Macintosh SE, IIcx and IIfx. The only recommendation I can make is that you check the dialog pointer parameter again, and make certain that you are not passing nil, or an invalid dialog pointer.
Toolbox & IAC: Edition Manager: SetEditionFormatMark’s setMarkTo parameter
How is SetEditionFormatMark’s third parameter (setMarkTo) to be determined? Is it always zero for the start of each format? Does it mean that any chunk of the edition can be obtained, using the starting mark and byte count, exactly like reading a file?
The setMarkTo parameter is set only for the specific format you’re concerned with. So yes, it is always initially zero for any specific format in an edition container file. And you can set it to whatever you like for that particular format. You can get the length of the format you’re concerned with by calling
EditionHasFormat(refNum,formatDesired,&returnedSize);
and returnedSize will contain the size of that format. So in SetEditionFOrmatMark your range is 0-returnedSize.
The answer to your third question is “kinda.” You can almost think of the separate editions in a edition container file as accessible the same way a normal data fork is, but you have to remember that you must work with the Edition Manager calls to make sure this works.
The edition container format mark for a format does NOT relate at all to the actual mark the File Manager is using in the data fork. The Edition Manager does its own translation from Edition Manager mark to logical file mark when you make a ReadEdition call. So, you are never informed of where the actual data resides in the ECF.
This is necessary to allow the Edition Manager room to expand. By having the Edition Manager make the conversions, you achieve two things:
1) The header in the ECF can be modified, extended or shortened anytime, and no applications are dependent on the “real” file mark.
2) You as an application don’t have to worry about another format being added to the ECF while you are reading another one. Say the EDF currently has two formats, a 1K PICT at the beginning of the file, and a 2K TEXT after it. You are reading the TEXT 50 bytes at a time (for some reason or other). While you are doing that, the publisher updates the 'PICT'. The TEXT is held in a buffer, because the EM knows that someone is reading it. But the PICT can be written now, even if its size changes, and the Edition Manager just changes its offset to the mark for the TEXT. You as the application still continue to use the same mark; the size of the file changed but you did not have to be aware of it.
So you can manage reading formats yourself, you can “batch” in a large format (or write it out in chunks) but you have to use Edition Manager read and write calls to do it, not File Manager calls.
Toolbox & IAC: Edition Manager: Ordering of 'fmts' in an edition container
Is there any ordering to the 'fmts' edition format, like best to worst? For applications that support subscribing to a large number of formats, defaultingto “best” is nontrivial.
There is no implicit ordering of the formats in an edition container. They are written and read and returned in the 'fmts' resource in the order in which they were written into the container. This is not an arbitrary model, it’s based on information that the Edition Manager, as system software, _can’t_ know. The decision would be _very_ implementation dependent. Your users may prefer your own custom edition type over all others, so the way you would want the 'fmts' resource to be returned would be a great deal different than a simple word processor, who would be preferring TEXT.
So the system can’t make that decision. It doesn’t know who is calling the edition manager and can’t know what format your specific application prefers. Any ordering it may make would be wrong for a large set of developers. So, it relies on just giving back the formats in the order that they were written. Of course, if you are customizing your Subscriber dialog with your own popup, Apple recommends that you order the popup (or list, or whatever) to suit the needs of your application best, defaulting to your “best” format; however, there is no way to enforce this. The enhanced subscriber dialogs design is/are up to individual developers.
Toolbox & IAC: Event Manager: Events and switching between Macintosh applications
After selecting an application in the System 7 Application or Apple menu, sometimes control doesn’t switch from our application to the selected application.
The symptoms you’re described—the process menu not switching layers—is exactly what happens if you have an activate or update event pending that you are not acting upon. Here are ways that pending activate or update events have been handled incorrectly:
• dueling event loops
• your application isn’t asking for all events
• the word in your code that contains the everyEvent constant is trashed (unlikely)
• you are not calling BeginUpdate and EndUpdate (most likely problem)
Toolbox & IAC: Event Manager: Use Apple IIGS GetFuncPtr to save tickCount overhead
When using an Apple IIGS run queue item, can I use the second reserved field to find out when the item was last executed? I assume this value is the tickCount. Currently, I just get the current tickCount and subtract the last tickCount. Using this field could save me one tool call, and when doing animation via a RunQ, every extra tick counts.
No, you should not use undocumented fields in the run queue header because they could change with future software releases. However, there is a fast way to get the current tick count. Pass refNum $0005 to the GetAddr function in the Miscellaneous Tools once each time your program runs, and it tells you the location of the tick counter. Since the tick count changes during heartbeat interrupts, be sure to disable interrupts around your direct accesses to the tick counter (PHP, SEI, access tick count, PLP).
If your application makes certain tool calls frequently, it may be worthwhile to short-circuit the tool dispatcher and transfer control to the Toolbox function directly (if the tool takes a long time to execute anyway, it isn’t worth it). You can get a function’s address and work area pointer by calling GetFuncPtr and GetWAP in the Tool Locator. When the function gets control, the Y and A registers must contain the tool set’s work area pointer, the X register must contain the function number, and there must be two RTL addresses on the stack.
Toolbox & IAC: Event Manager: Macintosh Finder and DoubleTime global
How does the Macintosh Finder interpret the DoubleTime global? It seems the Finder doesn’t use DoubleTime the way it’s documented in Inside Macintosh.
The ratio of ticks to value of DoubleTime is 1:1—that is, the number in the DoubleTime variable (Inside Macintosh Volume I, page 260) is, in fact, the number of ticks between a mouse up and a mouse down. Of course, this is not how the Finder works. The Finder multiplies the DoubleTime variable by 2 to determine double click time. It does this to account for user problems that occur while the user is arranging icons. Thus, the hard-and-fast answer is the Finder uses DoubleTime*2, and the rest of the system just uses DoubleTime.
By the way, the Finder does not limit the double-time variable to 64 ticks. It treats it like a byte in most places, although in some places it is treated like a longword. However, clipping it at 64 ticks would be the best method since that would provide a 1 second double click (two second in the Finder), which is long enough for anyone.
Applications should use DoubleTime as documented in the manual, not as it’s used by the Finder.
Toolbox & IAC: Event Manager: 'SIZE' resource bit and resume events in window title bar
We set our 'SIZE' resource to say we don’t want mouse events for the click that generates a resume event, but when the user clicks in the title bar of our (inactive) window we get the event anyway.
You are quite right, you do get the mousedown if it occurs in the windows title bar. This choice was made so that when you click in the drag region of a window in the background you don’t have to click twice to get the window to drag. This somewhat negates the effect that some developers are trying to get by setting the bit in the 'SIZE' resource, but it really could not be avoided. Your best bet is to simply ignore the first mousedown after a resume if it is in the drag region of the window. This way, you will not loose any events in the unlikely event that the user can get a keystroke or something in the queue before you get your resume.
Toolbox & IAC: Event Manager: Help balloonw and OSEventAvail between BeginUpdate and EndUpdate
Random garbage is occasionally displayed on the screen if a Macintosh help balloon goes away due to an OSEventAvail call when a screen refresh is taking place. Is it possible that the Help Manager code isn’t entirely cool if it hides a balloon between a BeginUpdate and EndUpdate?
Yes, this is particularly nasty. Here’s the deal:
OSEventAvail does do balloon maintenance. This is a problem, because OSEventAvail is documented as to NOT move memory, but when balloons are active, it does sometimes. Beyond this, which is really a bad thing, it is still a problem for updates that allow interrupting, such as yours.
Your problem isn’t that it moves memory. What it does do is recalculate visRgns, due to the balloon moving. The balloons are actually windows, and the Help Manager has its own WDEF that does the funny balloon shapes. When a balloon/window is moved, the visRgns have to be recalculated to reflect what has been covered or exposed. This is normally fine, but it is a really bad thing between BeginUpdate and EndUpdate.
BeginUpdate first caches the visRgn. It then localizes the updateRgn. It then intersects the visRgn and updateRgn and places the result in the visRgn. It then clears the updateRgn. You are now ready to update just the portion of the window that needs updating.
The problem is that you are making a call to OSEventAvail between BeginUpdate and EndUpdate with balloons active, and somebody moves the mouse. The balloon therefore moves, the visRgns are recalculated, and the window being updated now has a new visRgn.
This would not be bad, except that the visRgn that was cached when BeginUpdate was called reflects the balloon’s old position. When EndUpdate is called, the visRgn for the window just updated will be restored to what it was before the balloon moved.
This now means that there is possibly an area on the screen that is shared between the updated window and the balloon window, plus a possible area that should be in a window, and is no longer. Obviously, this is really bad.
The only thing that I can think of to do is the following:
1) Call BeginUpdate, as usual.
2) Copy the resultant visRgn into the clipRgn.
3) Call EndUpdate
4) Draw to the window as you would for a normal update. (Your normal update also calls OSEventAvail every so often to see if it should interrupt.)
What this accomplishes is that the clipping for the area that doesn’t need updating is no longer done with the visRgn. It is done with the clipRgn instead. This will not be affected by any balloons moving. Also, after the EndUpdate, there is no longer a cached copy of the window’s visRgn, and therefore the balloon window can move and not mess up visRgns.
The above general technique should take care of the problem for you. At this point, there isn’t a resolution to this problem -- only a workaround. It is bad that OSEventAvail can move memory, as it was documented not to. The problem is that the Help Manager needs to do stuff at this time, and this may involve moving the balloon window.
DTS recommends making your code safe from this problem with the above workaround, and to also see if you can be hurt by memory moving when OSEventAvail is called in general.
Toolbox & IAC: Event Manager: System 7 applications need to be background-capable
System 7 applications need to be background-capable
System 7-savvy applications should have the 'SIZE' resource’s background processing bit set. (It’s not documented anywhere explicitly that you need to have this bit set.)
All System 7 Apple event-aware applications need to be background-capable, since there are many instances where Apple events will come in to you while you’re in the background, and there will be many times (as new applications are developed) where you will _not_ come to the front to process a series of events; you’ll work in the background as a client for another application.
You don’t want to hog a lot of system time when you have nothing to do in the background, but with the Edition Manager you do need to be able to receive events while you’re in the background. However, you can still be system-friendly when you do this. Here’s one way to do is this: When you’re switched into the background, set your sleep time to MAXLONG and make sure you have a nul mouse region. This way, you will be getting nul events _very_ rarely, and you will not be taking much time at all away from other applications, but you can still react to events sent to you by other parts of the system. Then when you come forward, you can reset your sleep time to your normal, low, frontmost sleep.
Toolbox & IAC: Event Manager: WaitNextEvent mouseRgn parameter & mouseMoved event handling
WaitNextEvent mouseRgn parameter & mouseMoved event handling
Passing nil as the mouseRgn in WaitNextEvent is entirely acceptable if a Macintosh application doesn’t need to respond to changes in the location of the mouse pointer. MouseMoved events are generated only as a convenience to the programmer.
From Inside Macintosh Volume VI, if nil is passed as the mouseRgn, mouseMoved events will _not_ be generated. Otherwise, a mouseMoved event will be generated when the user moves the mouse outside the specified region.
Inside Macintosh Volume VI, page 5-10, has a small snippet containing a main event loop which you may find useful. It describes Apple’s recommended way of calling WaitNextEvent with a non-nil mouseRgn parameter. Volume VI, page 5-29,has a long description of WaitNextEvent.
Toolbox & IAC: Event Manager: Code snippet that uses StillDown and WaitMouseUp for dragging
Code snippet that uses StillDown and WaitMouseUp for dragging
The code below gives a simple example of how to use StillDown and WaitMouseUp to do simple dragging.
Point oldPoint,newPt; /* contains the old and new mouse
positions */
EventRecord theEvent; /* contains the mouseDown event */
Rect r; /* this has already been set by now */
... called with mouseDown event in theEvent ...
oldPoint = theEvent.where;
GlobalToLocal(&oldPoint);
if (StillDown()) {
while (WaitMouseUp()) {
GetMouse(&newPoint);
if (DeltaPoint(oldPoint,newPoint)) {
EraseRect(&r);
OffsetRect(&r,newPoint.h-oldPoint.h,newPoint.v-oltPt.v);
FrameRect(&r);
oldPoint = newPoint;
}
}
}
...
Toolbox & IAC: Event Manager: 'SIZE' resource is32BitCompatible flag
Does setting the is32BitCompatible bit in the Macintosh® 'SIZE' resource have any effect in System 7.0?
The alert box that was to be shown for applications with the 'SIZE' resource’sis32BitCompatible flag disabled was found to be too confusing for an end user,so the is32BitCompatible flag is not used and the alert box is not displayed in the final System 7.0. (It is, however, displayed in A/UX® 2.0 and 2.0.1.) This could change in the future.
Toolbox & IAC: Help Manager: Balloon help for application windows
If I program the balloon help myself for my windows, does this mean I must program for the menus also, or can I use the resource method?
Each different type of balloon help—dialog, menu, and application—is independent of the others. Before the Menu Manager puts up any balloons it will remove the current balloon. You should do the same (see information and warning on page 11-71 of Inside Macintosh Volume VI). Bottom line, you can use the resource method for menu and dialog help (dialogs that use the Dialog Manager), and still manually provide help for your application windows.
Toolbox & IAC: Help Manager: Menu help balloons with application extensions
How can my Macintosh application extension change the help balloons for menus it has modified in the application?
You can head patch (DON’T tail patch) HMShowMenuBalloon to call the Help Manager’s HMSetMenuResID routine, which maps in an alternate menu help resource ('hmnu'). You create a copy of the application’s 'hmnu' resource, modify the copy and map it in using HMSetMenuResID—something like this:
HMSetMenuResID(mEdit, 256);
When you remove your changes to the menu, unmap your 'hmnu' help menu resource with another call to HMSetMenuResID, as follows:
HMSetMenuResID(mEdit, -1);
Toolbox & IAC: Help Manager: Help for nested dialogs
We define our helps through 'hdlg' and the call HMSetDialogResID Does this call support nested dialogs?
The HMSetDialogResID is a global function. It acts on all dialogs that are currently up in addition to dialogs that are to come up (contrary to what the manual implies). So, to handle help for nested dialogs you should do the following:
Always associate an 'hdlg' with a dialog via the 'DITL' help item whenever possible, thus eliminating the need to use HMSetDialogResID.
Before bringing up any dialog that you must use HMSetDialogResID with, you should first call hmGetDialogResID to preserve the current state. When the dialog in question goes away or is de-activated (in the case of a modeless dialog), you should reset the ID to what it was before the dialog was put up. Also, if you are using this with modeless dialogs, be sure to again call hmSetDialogResID at activation.
Toolbox & IAC: Help Manager: Help menus with two menu bars
I’m appending items to the system help menu but my program uses two menu bars and when I call SetMenuBar the items that were added to the help menu are lost. What can I do to keep from having to rebuild the help menu each time I do a SetMenuBar? I don’t fully understand the ownership of the help menu (each application gets its own?).
Well, if you must use two menu bars, then you will always have to re-add your help menu items after a call to setMenuBar. Of course, the reason for this is that the help menu, process menu, and keyboard menu are not considered part of your menu list. The system thinks it is doing you a favor by isolating these menus from you (which in the case of the process menu makes quite a good bit of sense). Unfortunatly, you have found the one big flaw in the whole plan. The solution for you is to write a routine that calls setMenuBar and re-adds the help menu items all at the same time.
Toolbox & IAC: Help Manager: HMSetBalloonContents controls runaway balloons
Help! I’ve just added Balloon Help to my application, but I’m having some problems. Whenever a balloon appears, it immediately begins floating away off the top of the screen. What can I do to stop this madness?
It appears you failed to heed our warning when it comes to routines that can move balloons. Consult Appendix D of Inside Macintosh X-Ref, “Routines That May Pop Balloons or Cause Barometric Disturbances,” for a complete listing of these help balloon meteorological nightmares. In addition, be sure to call the new trap HMSetBalloonContents:
OSErr HMSetBalloonContents (balloonContents: INTEGER);
CONST { types of balloon contents }
helium = 0;
air = 1;
water = 2;
whippedCream = 3;
with balloonContents set to something greater than helium.
Toolbox & IAC: Help Manager: Balloon help for menus with submenus
We defined balloon help for our menus and submenus, but if we click on the main menu item, the balloon for this item only appears in a flash and then disappears. The help for the hierarchical items work, but if we drag on the main item again, no help appears.
When submenus are present, the help item for the parent menu item is not supposed to show for three reasons: First, the menu item is the title of the submenu and you do not see the help for a menu title when the menu is pulled down. (This is what actually causes the help balloon not to show. The system is treating the menu item as a menu title, with the side effect that you can never position the cursor over the item without popping down the submenu, so the item’s associated help will never show.) Second, Apple’s human interface group felt that there would be little need for menu help once the submenu has appeared (envisioning a balloon that says something like “The submenu attached to this menu contains items that...” which would be redundant). The final reason is that if the balloon came up it would obscure the submenu that just popped up, forcing users to move the cursor to the submenu before they could see what choices are available. This looks bad and works bad.
Toolbox & IAC: Help Manager: Balloon Help and modeless dialogs
I have a problem with Balloon Help for modeless dialogs. The balloons don’t show up most of the time unless the user clicks the mouse over the dialog item of interest.
The problem you are having is that you are not calling isDialogEvent with nul events. The most likely cause for this is that you are not getting nul events, or you have your sleep time way too high in wait next event. If you are not getting nul events, it is probably due to unserviced update events in the event queue. If you can not ensure that you will get null events back from waitNextEvent, you must fudge them instead. This way the text edit insertion point will blink properly as well.
Toolbox & IAC: Help Manager: No pre-System 7 Help Manager
No pre-System 7 Help Manager
Contrary to rumors you might have heard, the Help Manager (including balloon help package) will not be available for pre-7.0 systems.
Toolbox & IAC: Help Manager: BalloonWriter 1.0f3 rez input file bug & workaround
BalloonWriter 1.0f3 rez input file bug & workaround
A rez input file generated by BalloonWriter 1.0f3 is not the same as the MPW 3.2 definitions in BalloonTypes.r. Until this is fixed, the only solution is to go in by hand and fix the resources yourself.
Toolbox & IAC: Help Manager: Help Manager menu command-key bug and workaround
I cannot get command-key equivalents to work on the System 7 Help menu. Under System 6 the first item’s command-? equivalent in my Help menu works, but under System 7 the MenuKey seems to return 0.
What you are experiencing is a bug in System 7. The bug only effects menu keys and the Help menu, so the workaround to it is really quite simple. Before you call menu key, test the key to see if it is a question mark (in other words, perform the menu key function yourself in this instance). Some Pascal code that might do this (modified from the MPW sample.p application) follows. Inside your case statement in your event loop, the keystroke event case would look something like this:
keyDown, autoKey: BEGIN {check for menukey equivalents}
key := CHR(BAnd(event.message, charCodeMask));
IF BAnd(event.modifiers, cmdKey) <> 0 THEN {Command key
down}
IF event.what = keyDown THEN BEGIN
AdjustMenus; {enable/disable/check menu items
properly}
If key<>'?' then { test for our special help menu
keystroke }
DoMenuCommand(MenuKey(key)) {if not,
just handle
normally}
Else begin
HiLiteMenu(kHMHelpMenuID);
DoMenuCommand(($10000*kHMHelpMenuID)+myHMItemNumber);
end;
END;
The workaround will not cause any problems if the bug’s fixed in the future, so it is safe to include in your software.
Toolbox & IAC: Help Manager: Changing the default help balloon for your Macintosh application
In the Macintosh® Finder™, when you point to the TeachText icon with Balloon Help turned on, a little description about the application appears. How can I create a similar description for my application?
TeachText is a special utility application included with Macintosh system software. Consequently, some TeachText-specific information is stored in system files. Specifically, the Finder Help file contains special strings which are used for the TeachText help balloons. Normal applications do not have this privilege.
You can create an 'hfdr' resource in your file, which lets you specify your own help balloon text. You can use the Rez tool in MPW® SARez, or BalloonWriter to make an 'hfdr'. Refer to “Overriding Help Balloons for Application Icons” in the Help Manager chapter of Inside Macintosh Volume VI for more details.
Toolbox & IAC: Help Manager: Macintosh Help Manager and resource files
Is there some kind of bug with the Macintosh® Balloon Help feature in System 7.0? It goes into the application and uses the text from the 'STR#' resource ID 4001 instead of the 'STR#' resource ID 4001 of Finder Help.
The System 7.0 Help Manager stores its balloon strings in the Finder™ Help resource file. Under certain circumstances, the Help Manager will access the string resources in your application before it accesses the resources of the Finder Help file. Consequently, problems will occur if your application contains certain 'STR#' and 'STR ' resources.
There are only two circumstances in which your application may be affected. First, if your application uses a 'STR#' resource with ID 4001, the Help Manager will use the first string resource of the list instead of the corresponding resource in Finder Help. When the pointer is placed over your application icon’s text on the desktop, the default text, “Change the icon’s name by clicking on the name and typing,” will be changed to the text stored in 'STR#' 4001 of your application.
Second, if your application has a 'STR ' resource with ID 17251, the Help Manager will use that string resource instead of the corresponding string resource in Finder Help. The default text, “This is an application—a program with which you…” will be changed to the text stored in 'STR ' 17251 of your application.
To avoid these problems, you have a few options. You can create your own 'hfdr' resource to override 'STR ' 17251, or you can avoid using 'STR ' 17251 and 'STR#' 4001. If you must use 'STR#' 4001, paste the text “Change the icon’s name by clicking on the name and typing” into the first string and use the rest of the strings for your application’s use.
Toolbox & IAC: Help Manager: HMSetMenuResID & kHMCompareItem with 'hmnu' resource
My DA uses a lot of hierarchical menus for which I have help strings in a 'STR#' resource. How do I get around potential renumbering problems? Is it safe to assume that I never get renumbered under System 7? Also, if a menu item has a hierarchical menu, how do I get help for the item?
According to the Help Manager chapter of the current Inside Macintosh, Volume VI draft,
“You can use the HMSetMenuResID function to set the 'hmnu' resource for a menu that did not previously have one or to supplement the existing 'hmnu' resource for a menu.
FUNCTION HMSetMenuResID (menuID,resID: Integer) : OSErr;
The menuID parameter specifies the menu to associate with the 'hmnu' resource. The resID parameter specifies the resource ID of the 'hmnu' resource to use for the menu specified by the menuID parameter. The menu identified by the menuID parameter should correspond to an existing menu in your menu list. The Help Manager maintains a list of the menus whose 'hmnu' resources you map (set or override) using the HMSetMenuResID function.
Specify –1 in the resID parameter to unmap the pairing of a particular menu and 'hmnu' resource that you previously mapped using the HMSetMenuResID function. You should unmap any resource IDs before your application quits.
Result codes
noErr 0 No error
memFullErr –108 Not enough room in the heap zone”
Regarding help items for hierarchical menus, you can use kHMCompareItem in your 'hmnu' resource to match against the menu item in question, and display the appropriate help message at that time. See the “Providing Help Balloons for Menus” section for details on the HMCompareItem identifier.
Toolbox & IAC: Human Interface: Human interface for wildcards and boolean operators
Is there a universally recognized wildcard character for the Macintosh (like the * in the MS-DOS world)? Furthermore, for boolean logic, should my application accept Pascal syntax (such as .NOT., .AND., .OR.), C syntax (such as !, &&, ||), or still another convention? My users are not programming gurus.
First, see if there’s a friendlier way to implement the wildcard’s function. Take a look at System 7 Finder’s “Find…” menu item, for example. If you find wildcard use is necessary, “*” is universally common, though for file searching any character other than “:” can be used in an HFS filename.
As for boolean operators, nonprogrammers prefer a syntax that matches English as closely as possible, so AND, OR, and NOT are better than their C counterparts. However, user testing indicates that the most intuitive, user- friendly way to put boolean search criteria on a command line is to bring up a dialog with pop-up menus used to form an English sentence describing the search (like System 7’s “Find…”). If you can make something like this work for your application, your nontechnical users will love you.
Toolbox & IAC: Human Interface: Alert user instead of sending 'quit' Apple event to free RAM
Is it acceptable to force other Macintosh® applications to quit to free up memory?
While it’s possible to free up memory by sending a 'quit' Apple event, a much better alternative from a human interface standpoint is to pose an alert to the user indicating that you couldn’t open the documents they requested due to a lack of memory, and asking the user to please try quitting some other applications and try again. It’s better to leave the user in control of the process.
Toolbox & IAC: International Utilities: System 7 and 'itl1' resources
System 7 doesn’t recognize some of my 'itl1' resource changes, such as date abbreviation length, that are recognized by System 6.
The field that you refer to is not doing what you want because System 7 introduced an expanded 'itl1' resource, with several new fields, including arrays that contain the proper abbreviations of all the months and days. If you look in Inside Macintosh Volume VI on pages 14-87 thru 14-89 you’ll find a description of this new resource as well as the rez definition of it. Note the two new arrays, abbrevDays and abbrevMonths. If you were to modify these additional fields, you’d see the date in the finder windows change. (In fact, the abbrev length field does not seem to be used if these new fields are present.)
Toolbox & IAC: International Utilities: Why 1904 is Macintosh Time base
The global variable Time contains the number of seconds since midnight, Jan. 1, 1904. Why was the year 1904 chosen ?
The ability to go back in time is one consideration. You would not want to start the clock from, say, 1984. You also want to go ahead in time a good amount, of course. So, the clock start date needs to put our current date somewhere in the middle of the clock’s range.
So what is the clock’s range? Since the clock chip has a four byte counter which is incremented each second, they had 4,294,967,295 seconds to work with, or 60*60*24*365.25 = 31,557,600 secs/yr, giving them 4,294,967,295/31,557,600 = 136 years (plus about a month?). This would make the Macintosh clock run out in 1904+136 = 2040. The maximum value, $FFFFFFFF, corresponds to 6:28:15 a.m., February 6, 2040.
Given the possible range of years/leap years/nonleap years (every fourth year, but not if at the end of a century, except at the end of every fourth century, which is a leap year) and the date when the clock will run out (2040) - the “leap year code” in the Macintosh only has to deal with the rule “every fourth year is a leap year” because none of the possible Macintosh dates violate that rule! Remember, 2000 is evenly divisible by 400, so it IS a leap year. 1900 is not. If they started at 1900, they would have to use a different algorithm that accounts for “non-leap year” leap years. Some other clocks start on 1901.
Why did they start on 12:00:00, January 1, 1904? Well, it probably has to do with 1904 being the first leap year after a “non-leap year” leap year (1900). So, the year was chosen for mechanical (4 byte limit on number of seconds) and pragmatic (you only want to use one algorithm to figure out the date et al) considerations.
So, back to the future...
X-Ref:
Chapter 4, “Worldwide Guide to System Software”
Toolbox & IAC: International Utilities: International documents reference list
International documents reference list
Human Interface Guidelines
Inside Macintosh:
“International Utilities,” Inside Macintosh, Volume I
“Script Manager” and “International Utilities,” Volume V
“Worldwide Software Overview,” Volume VI
Technical Notes:
Macintosh Technical Note #25, “Don’t Depend of Register A5”
Macintosh Technical Note #26, “Accuracy of Charwidth and StringWidth”
Macintosh Technical Note #138, “Using KanjiTalk”
Macintosh Technical Note #153, “New International Utilities”
Macintosh Technical Note #160, “Key Mapping”
Macintosh Technical Note #174, “The Print Action Routine”
Macintosh Technical Note #178, “Modifying String Comparison”
Macintosh Technical Note #182, “Constructing Word-Break Tables”
Macintosh Technical Note #237, “TextEdit Record Size Limitations”
Macintosh Technical Note #241, “Script Manager’s _Pixel2Char”
Macintosh Technical Note #242, “Fonts and the Script Manager”
Macintosh Technical Note #243, “Script Manager Variables”
Macintosh Technical Note #263, “International Cancelling”
Macintosh Technical Note #264, “Script Manager 2.0 Date & Time Problems”
Software Development for International Markets (#A27G0016)
Worldwide Development: Guide to System Software (#M7047/A)
Script System Software and associated User Notes
Japanese Interface System (KanjiTalk)
Arabic Interface System
Hebrew Interface System
Chinese Interface System (HanziTalk)
Korean Interface System (HanguTalk)
HyperCard Stack Design Guidelines
You may also want to check out:
TextEdit tech notes
Toolbox & IAC: International Utilities: 12 Golden Rules of worldwide design
I want my product to be usable around the world. Do you have a quick reference list of what I need to do so my Macintosh product can be localized easily?
Here’s a summary list from Apple’s International Software Support group:
(1) All text (including characters like ‘…’) seen by the user must be in resources so they can be translated easily into other languages.
(2) Remember, characters can be 1 or 2 bytes. Be careful of assuming character lengths.
(3) Word order should be easy to change. Watch out for those strCat calls! Use ParamText.
(4) All graphics should be culturally neutral; obtain country feedback.
(5) All sorting and date, time, number formatting information should be coming from the international resources.
(6) All keyboard information should be coming from the system file via the keyboard resources.
(7) If you create a custom resource that contains text, you must provide a ResEdit TMPL or editor to ensure localizability.
(8) All text handling should be accomplished using TextEdit and/or the Script Manager.
(9) Make no assumptions about the character set. Use the International Utilities and Script Manager routines to find out information about a character.
(10) Keep in mind the different standards used around the world, such as for character sets, paper sizes, and ergonomics.
(11) HyperCard stack developers: The convention for indicating text in scripts which needs to be localized is to add a comment “--∆” and an explanation. (∆=option j)
(12) Flexibility! Design in flexibility so your product can be localized in many different ways. For example, go ahead and set a default if you must (for example, a default keyboard layout), but allow the user to select other options if they are available.
Toolbox & IAC: International Utilities: RelString & EqualString vs International Utilities
What is the difference between RelString and the EqualString? What does DTS suggest its Macintosh® developers use when sorting? Or do you suggest having an option for the international sort?
RelString and EqualString are mainly intended for the File Manager. The File Manager uses them for quick-and-dirty string comparison so that it knows how to return files ordered alphabetically when you use an indexed File Manager routines and so that it can detect file name collisions. Beyond that, RelString and EqualString aren’t localizable and they’re not extensible.
The International Utilities string comparison routines are localizable and extensible. They use information in the active 'itl2' resource to determine how the characters are sorted. Most localized systems come with their own 'itl2' resource, and so string comparisons are done correctly for the region that the system is localized for. RelString and EqualString stay the same for all these regions, and so you’ll probably find some cases in which strings are compared incorrectly by these routines.
One important place where RelString and EqualString don’t work very well is with the new characters in the extended Macintosh character set. When the LaserWriter® was introduced, the LaserWriter fonts used the extended Macintosh character set which added many new characters, including several new upper-case characters with diacriticals. In system software version 6.0.4, the International Utilities were updated to take advantage of these new characters. For example, the upper case “E” with a grave accent first appeared in the extended Macintosh character set. With 6.0.4, the lower and upper case “E” with a grave accent were considered to be equal in primary ordering, and unequal in secondary ordering, which is correct. But RelString and EqualString, even today, still think in the old Macintosh character set, so they think that lower and upper case “E” with a grave accent have nothing to do with each other, and that’s not right.
Because the RelString and EqualString algorithms are more crude than the string comparison routines in the International Utilities, RelString and EqualString should win races with the International Utilities string comparison routines hands down. The File Manager uses them partly for this reason, and partly because RelString and EqualString don’t need access to the 'itl2' resource, which is usually pretty big. Normally, File Manager sorting isn’t critical anyway because it’s either irrelevant, or it can easily be cleaned up by using the International Utilities string comparison routines. The Standard File package, for example, uses the International Utilities string comparison routines to order file and folder names in its list so that the list is ordered correctly regardless of the system it’s running on.
Toolbox & IAC: International Utilities: Determining the language being used to enter text
Is there a way to tell what language is being used on the Macintosh®? I know how to find the script and other international items, but the language being spoken would be a very useful thing to know.
It depends on what you mean by “language.” It’s impossible to determine what language the user is typing in without doing a high-level analysis of what is being typed, as you probably know.
One way that’s been suggested in the past is to check on the current KCHR by calling GetScript with an smScriptKeys verb. This returns the resource ID of the currently active KCHR. All international systems come with a U.S. KCHR and possibly others, such as the Romaji and Kana KCHRs in the Japanese systems and the alternative Roman KCHRs in the various German and French systems. The thought was that the user will most likely choose the U.S. KCHR to type in English, and choose the French KCHR to type in French. One problem with this is that it isn’t necessarily true. You can type English with the French KCHR and you can type French with the U.S. KCHR, and many people do. A much larger problem is that the KCHR IDs aren’t standardized within a script system range. Because Apple defines a range of resource IDs for each script system for the international resources, you can tell what script system a KCHR is for, and you can even match up the KCHR ID with the standard KCHR IDs that Apple defines, but there’s nothing wrong with someone creating their own KCHR and giving it any ID they want, as long as it’s in the proper range for the script system they’ve written it for. If that’s the currently active KCHR, its resource ID tells you what script system it’s for, but it won’t tell you anything about what language it was intended for. For this reason, this method is frowned upon now.
In fact, there really is no reliable way of knowing the language that’s being used. The best you can do currently is to find out what the system is localized for. This is done by grabbing the vers resource ID 1 from the System file. In this resource is what was called the country code (the term “country code” is obsolete, in favor of “region code”) which indicates what region the system is localized for. These region codes are defined in Packages.p in MPW®, and have names like verUS and verFrance and the like.
There’s another way that you might want to consider. One of the GetScript verbs is smScriptLang. This returns the language code of the specified script system for the current system. If you pass smRoman as the script code to GetScript, it’ll return langFrench on a French system, langGerman on a German system, langEnglish on a U.S. or U.K. or Australian system, and so forth. If you pass smJapanese as the script code to GetScript, it’ll return langJapanese. Interestingly, if you pass smRoman as the script code to GetScript when a Japanese script system is running, it’ll return langEnglish. All non-Roman script systems return langEnglish if you pass smRoman as the script code to GetScript. The language constants are in Language.p in MPW. You’ll probably what to combine this GetScript call with a call to GetEnvirons to find out what the currently active script is. It might look something like this:
(* Get the currently-active keyboard script *)
keyboardScript := GetEnvirons (smKeyScript);
(* Now get the language that the keyboard script corresponds to *)
languageCode := GetScript (keyboardScript, smScriptLang);
In summary, there’s no system support for retrieving the language that the user is typing, nor is there any reliable support for retrieving the language related to any KCHR. But, you can find the region code of the active system, and you can find the language associated with the active script. Hopefully, that’s enough information to be useful to you.
Toolbox & IAC: International Utilities: 24-hour trailer in Macintosh 'itl0' and 'INTL' resources
How do I interpret the 24-hour trailer in the 'itl0' and 'INTL' resources?
The 24-hour trailer is eight characters long. It is divided into two four- character parts, the upper four for a.m, and the lower four, p.m. Some countries such as France do not use any trailers with their time, so the 24- hour trailer is blank. The German system uses the trailer Uhr (hour) for both a.m. and p.m., hence both parts of the trailer are identical.
Toolbox & IAC: International Utilities: Macintosh PRAM’s MachineLocation dlsDelta field
How is the dlsDelta field in PRAM’s time zone MachineLocation record used and set?
The dlsDelta field is currently not being used by Macintosh® system software, nor is its meaning defined currently. There are plans to use it in the future, so it’s important that you preserve its current value if you ever use WriteLocation to set the value of gmtDelta. See the description of the WriteLocation routine in “WorldWide Development: Guide to System Software,” available on the latest developer CD and from APDA (#M7047/A), for details on getting and setting gmtDelta while leaving dlsDelta intact. In short, the code looks like this:
VAR
myLocation: Location;
myGMTDelta: LongInt;
tempSignedByte: SignedByte;
:
tempSignedByte := myLocation.dlsDelta;
myLocation.gmtDelta := myGMTDelta;
myLocation.dlsDelta := tempSignedByte;
Toolbox & IAC: Line Edit (AII): Apple IIGS LETextBox2 and longStatText2 items
What are longStatText2 items, mentioned in the “Dialog Manager” chapter of the Apple IIGS® Toolbox Reference?
A longStatText2 item is similar to a longStatText item except that the text is drawn with LETextBox2. A longStatText2 item allows you to embed formatting codes so that you can change fonts, font styles, sizes, colors, and justification. The longStatText2 capability is built into the Dialog Manager to support formatting flexibility in standard dialogs. To use longStatText2 items, the Apple IIGS QuickDraw Auxiliary and Font Manager tools must be started.
Toolbox & IAC: List Manager: Avoid Macintosh List Manager for manipulating large matrices
Avoid Macintosh List Manager for manipulating large matrices
Avoid using the Macintosh List Manager for manipulating large matrices like spreadsheet cells.
The Macintosh List Manager becomes ungainly when handling more than about 500 cells. With several thousand cells, such as a 100x100 matrix, it becomes downright klunky.
Using standard techniques, the List Manager can store only 32K of data in a list. For 10,000 cells, this gives you only about 3.2 characters in a cell. It’s possible to switch to a system where each cell contains a pointer to text to be drawn, but with only 3.2 characters, it’s not possible to store a full pointer (4 bytes). After about 500 cells, the time needed to actually set the data in the cells becomes noticeable, on the order of 10 to 15 seconds.
Finally, the List Manager has some pretty fundamental restrictions. You cannot, for instance, create variable-width rows or columns, or hide a single row or column from a list.
For manipulating large matrices, you’re much better off bypassing the List Manager entirely and writing your own spreadsheet-type mechanism. Consider caching the cells to a temporary file, depending on your memory requirements. You’ll need to use the Control Manager to set up and process scroll bars, and you should use QuickDraw to draw the contents of the cells.
Basically, writing a spreadsheet shares many of the same necessary functions and problems as writing a text editor (replacing TextEdit). Neither one is simple, but both are possible.
Toolbox & IAC: List Manager: Apple IIGS extended list control and list draw routines
Does the custom draw routine for Apple IIGS® extended list controls have different inputs or other constraints from the list draw routine documented in Apple IIGS Technical Note #74?
The only difference between extended list controls and other lists is how you gain access to the same information—by a list record or a control handle. The draw procedures defined on page 11-5 of the Apple IIGS Toolbox Reference do not change for extended list controls.
Toolbox & IAC: List Manager: Creating Macintosh columns with various widths
How can I create a Macintosh® List Manager list with different size cells for some columns and different size cells for other columns?
I hate to say it, but the List Manager doesn’t allow variable-sized cells. One cell size fits all, or NOT! The List Manager was designed for simple lists (such the standard get file dialog), but not for spreadsheets. The source of the limitation is found in the ListRec as documented in Inside Macintosh Volume IV. The cellSize is a single variable (a Point). If multiple column widths were allowed, some sort of array would be required to store the width for each column, and you can see from looking at the ListRec data structure that no provision was made for this.
You can write your own List definition procedure, which can display alternative data types (PICTS, ICONS, or perhaps some data type of your own devising), but these are still limited to one cell size for the entire list. If you wish to have columns with various widths, you will need to treat each column as a separate list, or handle the lists entirely yourself as spreadsheet and database applications do.
Toolbox & IAC: List Manager: SetPort to your Apple IIGS window before calling SelectMember2
I did a SelectMember2 on an extended list control and the list was drawn at a funny place in my Apple IIGS® window. What gives?
The current port was not set to the window that the list control was in. Most List Manager calls, and many other toolbox calls, require that the current grafPort be explicitly set. Before you call SelectMember2, set the current port to your window with a SetPort call. Remember the note in the Apple IIGS Toolbox Reference , Volume 2 under the NewWindow call—”Important: NewWindow does not set the current port, but many routines require that a current port exist. Use the QuickDraw™ II routine SetPort to set the current port.” Using SetPort can prevent toolbox confusion and reduce your debugging time.
Toolbox & IAC: Menu Manager: Moving a menu bar from one screen to another
Under certain conditions, I want to have the menu bar moved from the main Macintosh screen to the second screen if there is one. Is this possible? Would you please give me some thoughts?
We don’t have a way to move the menu bar from one screen to another under application control.
It’s rather contrary to our human interface guidelines; the user expects the menu bar to stay in one place. The user can control the placement of the menu bar using the Monitors control panel.
Even if the user changes the screen on which the menu bar appears, the change isn’t effective until restart. There are several data structures that are affected by the menu bar placement, and they can’t really be changed “on the fly” because the system doesn’t even know where all of them are. These include the visible regions of other applications’ windows that may underlay the menu bar. System extensions like AppleShare (which displays an activity indicator in the menu bar, to the left of the apple menu title) may also assume that the menu bar is immobile.
Also, users assume that most new windows and alerts will appear on the main screen (ie, the one with the menu bar). While some applications may want color windows to show up on the “deepest” monitor, even this should be controllable as a preference item.
For your application, it might be more flexible, understandable, and useful to have a tool palette within your document’s window or in a floating window that the user can move at will.
Toolbox & IAC: Menu Manager: No way to include a color icon with a Macintosh menu title
How do we include color icons in menu titles, similar to balloon help and MultiFinder? Do we create an MDEF, use balloon help’s technique, or is there another method?
There’s no good solution for including color icons in menu titles. To begin with, an MDEF draws the contents of the menu but not the title itself. Furthermore, System 7 eliminated all support for accomplishing what you want. (How to write an MBDF, which is what is needed, hasn’t been documented.) Currently it isn’t possible to have an icon with the title of a menu, unless you are the system.
Toolbox & IAC: Menu Manager: Using Shift and Option keys with menu Command keys
How can I use Shift and Option keys with my menu Command keys?
There is no standard way of having shifted or optioned Command keys in menus.
First, using the Option key is a problem because holding down the Option key changes the meaning of the key pressed (for example, Option+8 = •, and Option+u is a dead key that prepares for an umlaut to be added to the following character). These dead keys and “optional” characters differ between international versions and even move around the keyboard on various international keyboards. Under System 7.0 it is now possible to instal several international scripts on the same Macintosh, so the Option key mappings could change frequently within the same document.
Second, although Apple recommends standard mnemonic Command-key equivalents for the major menu items, it is very difficult for command+œ to be mnemonic for most users, especially when it is just one of many such combinations. This would, of course, be considered a severe interface violation by users :). Likewise, the distinction between Command-F and Command-f is lost on most users, as an “F” is still an “f.”
The only way to do this kind of extended Command-key mapping is to write your own MDEF code and write a custom version of MenuKey. DTS strongly recommends against this. It is quite likely that if your users need this many menu keys that some elements of your interface could be better moved off the menu bar and into some other interface method.
Toolbox & IAC: Menu Manager: OK to call GetMenu repeatedly except for 128K or 512K Macintosh
Why does Inside Macintosh Volume I, page 352, warn about calling GetMenu only once for a particular menu?
Inside Macintosh warns about using GetMenu more than once because in the original (64K) ROMs GetMenu would load the 'MENU' resource when first called and then it would use the 'MDEF' ID to load the proper 'MDEF', and then store the handle to the 'MDEF' inside the 'MENU' record. The problem was that the second time you called GetMenu it would not check to see if the menu had been previously loaded, and would assume that the high byte of the 'MENU' record held the ID of the 'MDEF' to load; when it actually held the high byte of the handle to the 'MDEF'.
This problem was fixed in the 128K Macintosh Plus ROMs and all subsequent systems. Unless your application runs on a 128K or 512K Macintosh, you are safe to call GetMenu repeatedly.
Toolbox & IAC: Menu Manager: Help, Keyboard, and Application menu IDs don’t change
The System 7.0 Help, Keyboard, and Application menus at the right of the Macintosh® menu bar don’t have text titles that can be included in a command string like “File” or “Edit” can be. Do these menus always have the same menu ID? Do you have any scripts we can test with the new Script Manager?
The menu ID numbers of the Help, Keyboard, and Application menus are always the same, so the menus can always be identified by their IDs:
kHMHelpMenuID = -16490;
kPMKeyBdMenuID = -16491;
kPMProcessMenuID = -16489;
While we do not have any scripts available for the Script Manager menu, you can set the Always Show Icon bit of the 'itlc' resource in the system.
Toolbox & IAC: Menu Manager: TheMenu global and determining when a menu is pulled down
According to Inside Macintosh, the global variable TheMenu at address 0xA26 contains the menu ID of the currently highlighted menu, but TheMenu is always zero when MenuSelect is highlighting a menu. My test routine inserts its address in the global variable MenuHook to give me the value of the currently highlighted menu by looking at the global variable TheMenu. What am I missing?
Documentation on the global variable TheMenu is unclear. The variable is supposed to contain the menu whose title is currently highlighted after a call to MenuSelect. The standard 'MBDF' does not update this variable while it is selecting from a menu, only after a selection is made. The bottom line is that TheMenu is not valid at MenuHook time.
If there is some reason that you need to know when a specific menu is pulled down you might be able to use a custom MDEF (see the latest Developer CD Series disc for sample code) and then you would know which menu was pulled down, or you could use the mBarHook, which is called only when a menu is about to be drawn. You might then be able to use the rectangle that is passed to it to help you discover which menu is pulled down, by running through the current menu bar until you found the menu with the matching rectangle.
Toolbox & IAC: Menu Manager: Code for drawing to a Macintosh window while menu is open
How do I draw to a Macintosh window if it’s partially obscured by a menu that’s pulled down?
The Menu Manager is, by design, graphically the most modal component of the system. The reason for this harkens back to the days of the Macintosh Plus (or the modern time Macintosh Classic) These 68000-based machines do not have the horsepower to modify the visRgns of all visible windows during the menu draw. (It can slow the machine down something fierce if you have too many windows open.) Since the user tends to move back and forth on the menu bar, this could cause a great lag time for menu drawing. The down side, the menu’s being almost completely modal, is considered to be a small price to pay.
Fortunately, it is not hard to work around this little gottcha, and I think that with the code snippet below, you’ll be able to have the most non-modal menus in existence. Also, the code can lend a pretty cool animated real-time look to you application.
What you have to do is patch the mBarHook as well as the MenuHook. The MBarHook is called right before any menu is drawn, and it is passed the rectangle that the menu is going to go into (minus the drop shadow). All you need to do is to manage the cliprgn of the window that you want to draw into at mBarHook time and then all your drawing during menuHook time will be properly clipped to the menu’s interior, allowing the illusion of drawing “behind” the menu. Since this is called only before a menu is drawn, you do have to assume that the cliprgn of the window going into mBarHook is not right; simply call ClipRect(window^.portRect) to ensure that you are starting with a clean clipRgn. Also remember to reset the clipRgn after the call to menu select so that you don’t have persistent unsightly “menu holes” in your window when you redraw it.
; Here is a sample mBarHook & MenuHook that allows you to
; safely draw to a window while a menu is pulled down Install
; the hooks right before you call MenuSelect remove them right
; after just because its the tidy thing to do like this...
lea MyMBarHook,A0 ; get our hook routine
Move.L A0,MBarHook
lea MyMenuHook,A0
Move.L A0,MenuHook
CLR.L -(SP) ; space for MenuSelect
MOVE.L Where(A6),-(SP) ; Mouse coordinates
_MenuSelect ; pass MenuSelect's result
Move.L #0,D0
Move.L D0,MBarHook
Move.L D0,MenuHook
;
; Here is the code for the mBarHook. This routine is called
; once before any menu is pulled down. Its Pascal interface
; looks something like this:
; Procedure MBarHook(menuRect:Rect);
; You return a result code in D0, either 0 (continue with menu
; select)
; or 1 (Abort MenuSelect)
; Since this is called only before a menu is drawn, and not
; after a menu is released, we must always assume that we have
; been called before when fudging the window cliprgn
;
MyMBarHook Proc
Move.L 4(sp),D0 ; get the rectangle ptr off the stack
MoveM.L A0-A5/D1-D2,-(sp) ; save some registers
Move.L CurrentA5,A5 ; make sure A5 is correct
Move.L G.theWindow,A4 ; get the pointer to our window from globals
Move.L D0,A1 ; move the rectPtr into a proper
reg
lea MyRect,A2 ; now copy the rectangle into a
local rect
Move.L (A1)+,(A2)+ ;
Move.L (A1)+,(A2)+ ;
clr.L -(sp) ; preserve the menuMgrPort
Move.L sp,-(sp) ; on the stack for later
_GetPort ;
Move.L A4,-(sp) ; and use our window
_SetPort
pea MyRect ; convert the passed menu rect to
local coord's
_GlobalToLocal
pea MyRect+4
_GlobalToLocal
lea MyRect,A3 ; insetRect(myRect,-1,-1);
subQ #1,(A3)
subQ #1,2(A3)
AddQ #2,4(A3) ; adjust for drop shadow of menu
as well
AddQ #2,6(A3)
pea portRect(A4) ; reset the ports cliprect to the
whole window
_ClipRect
clr.L -(sp) ; and turn the adjusted menu rect
into a region
_NewRgn
Move.L (sp),A3
pea MyRect
_RectRgn
Move.L ClipRgn(A4),-(sp) ; Sutract menu rect from window
clip region
Move.L A3,-(sp)
Move.L ClipRgn(A4),-(sp)
_DiffRgn ; leaving the result in the
clip region
pea portRect(A4) ; erase the window for our demo
_EraseRect
Move.L a3,-(sp) ; get rid of the temporary
storage region
_DisposeRgn
_SetPort ; and put the saved menuMgrPort
back
MoveM.L (sp)+,A0-A5/D1-D2 ; restore the save registers
Move.L (sp)+,D0 ; get the return address
Move.L D0,(sp) ;discard the rect and restore the
return address
moveQ #00,D0 ; signal that we want to continue
RTS ; and back to the menu manager
MyRect ds.W 4 ; temporary storage
EndP
;
; And here is the menu hook routine that is called all the
; time while a menu is pulled down you can setport to the
; window and draw whatever you like.
; (I am just inverting for effect
;
MyMenuHook PROC
MoveM.L A0-A5/D0-D2,-(sp)
Move.L CurrentA5,A5
Move.L G.theWindow,A4
clr.L -(sp)
Move.L sp,-(sp)
_GetPort ; get the current grafport
Move.L A4,-(sp)
_SetPort
pea portRect(A4)
_InverRect ; draw in the window behind
the menu
_SetPort
MoveM.L (sp)+,A0-A5/D0-D2 ; restore the save registers
RTS
EndP
Toolbox & IAC: Menu Manager: Apple IIGS desktop tools don’t support mixed screen modes
Apple IIGS® HideMenuBar and ShowMenuBar use SetAllSCBs to fix up the screen control blocks (SCBs) for the rows containing the Apple Menu, which wipes out our 320-mode lines at the bottom of our 640-mode screen.
It’s true that HideMenuBar and ShowMenuBar could avoid using SetAllSCBs to do the work, but the fact still remains that the desktop tools absolutely positively do not support mixing 320 mode and 640 mode on the same screen. Even if Apple changed these Menu Manager calls, other calls in the system might have the same effect, and DAs could become confused or disfunctional.
Toolbox & IAC: Menu Manager: Associating Macintosh color icons with menu items
Is there a way to display Macintosh® 'ics8' icons in menus, like the Finder™ does?
You can have color icons associated with menu items, and it’s even quite simple. To associate a color icon with a menu item, simply make a 'cicn' resource with the proper item number for your icon and the system will use it instead of the 1-bit icon. You cannot associate 'ics8's with menu items yet, however, since this mechanism does not work properly yet.
Toolbox & IAC: Menu Manager: Dimming Macintosh menu items from a custom MDEF
What is the correct method for a custom MDEF to dim menu items when running under System 7? What is the preferred method for determining whether to draw in a gray color or paint the items with a gray pattern?
The proper method for dimming text in menu items is to use the GrayishTextOr transfer mode when drawing text. This is documented on page 17-17 of Inside Macintosh Volume VI. This is what Apple uses. this mode takes into account both color and black and white screens. A simple method for dimming non-text items is to set the OpColor to gray and then to draw the non-text item in Blend mode.
Toolbox & IAC: Menu Manager: Technique for changing a Macintosh menu title
How do I change the title of a menubar menu after it has been installed?
Although the format of menu resources is defined in Inside Macintosh® I-364, there are no Toolbox calls to change the menu title.
The format used to store menu titles and item names is a packed C string list, where the first byte is the length of the title, followed by the characters in the title and immediately followed by the length of the first item. It would be difficult and _extremely_ unsupported to try to grow this data structure (for example, if the programmer didn’t allocate it), but there is an easier way to solve your problem.
All you have to do is have a separate menu for each title. You can make the menus up on the fly, or just get them all from your resource file at the start of your program. You can then call InsertMenu and DeleteMenu followed by DrawMenuBar to add and remove them from your application’s menubar.
Toolbox & IAC: Menu Manager: Use dialog scrolling list instead of long menu list
Can the standard Macintosh® MDEF handle menus with more than 255 items? If not, do you have a simple fix to the standard MDEF source to increase this maximum?
The standard MDEF has a hard limit of 255 items (and a limit that only the first 31 can be enabled and disabled). To handle more than this number you will have to write your own MDEF.
Apple advises against writing an MDEF that handles more than 255 items because the speed of menu drawing, scrolling, and highlighting will tend toward unacceptably slow. Also, selecting from a >50-item menu is a very unpleasant experience for the user.
A better method of selecting among large numbers of items such as fonts is to allow the user to select from a scrolling list of fonts presented in a dialog.Key presses in the dialog scroll the list to match (á la the file list in Standard File) Finally, allow the users to customize their font menus, preferably both for the application’s default and additionally by document. Examples of most of the above methods are seen in MacDraw II and Microsoft Word.
This does not rule out other methods that you may have thought of to relieve the user of waiting through the scroll of hundreds of items. If you would like to flesh out your ideas, Link: MacInterface and we will be happy to help you develop your ideas.
Toolbox & IAC: Menu Manager: How to add icons to System 7.0 menus
How do I add icons to System 7.0 menus?
You can still add icons to menus in System 7.0 using ResEdit™ 2.1. To do this,simply open up the menu resource that you want to play with, open up the particular menu ID that you want to edit, and notice that there is a “Choose Icon...” option in the MENU menu.
Toolbox & IAC: Menu Manager: Lining up Macintosh submenus and 'SICN' resources
What would cause one of the hierarchical menus in a set of Macintosh® menus including both small icons ('SICN's) and hierarchical menus to pop up in the wrong place?
The problem you have noticed in submenus not lining up when you mix them with 'SICN's is true and is fixed under System 7.0. To work around this for the current release of System 6, you need to minimize the mixing of 'SICN's with hierarchicals. If you need to mix 'SICN's and submenus you may have to write your own MDEF, which does not have this problem. Although I do not recommend writing your own MDEF, sample source to a standard MDEF is available on developer CDs and on AppleLink®.
Toolbox & IAC: Menu Manager: Detecting if a menu belongs to a Macintosh Desk Accessory
How do I detect that a menu that is up belongs to a Desk Accessory (DA)?
The following code is one method (note that the menu will be the last one in the list):
FUNCTION daMenu: BOOLEAN;
CONST
MenuListLoc = $A1C;
TYPE
MenuRec = RECORD
menuoH: MenuHandle;
menuLeft: INTEGER; { Left edge of Menu. }
END; { MenuRec }
MenuList = RECORD
lastMenu: INTEGER; { Offset to last MenuHandle. }
lastRight: INTEGER; { Right edge of last Menu's
title. }
notUsed: INTEGER;
mArray: ARRAY[0..0] OF MenuRec;
END; { MenuList }
MenuListPtr = ^MenuList;
MenuListHdl = ^MenuListPtr;
VAR
MLHdl: MenuListHdl;
nbrMenusX6, numMenus: INTEGER;
daMenuHdl: MenuHandle;
BEGIN
MLHdl := MenuListHdl(MenuListLoc);
nbrMenusX6 := ORD(MLHdl^^.lastMenu);
numMenus := nbrMenusX6 DIV 6;
daMenuHdl := MLHdl^^.mArray[numMenus - 1].menuoH;
daMenu := (daMenuHdl^^.menuID < 0);
END; { daMenu }
Toolbox & IAC: Menu Manager: Forcing a pop-up menu to be drawn with extra space on right side
How can I force a Macintosh® pop-up menu to be drawn with extra space on the right side, as figure 3 of Human Interface Note #9 shows?
You need to get the latest version of the PopupMenu Sample code. You can obtain this from the Developer’s CD, or from the Developer Services files on AppleLink®. You will also need the Utilities file in the same folder as the sample code. These should get you going in the right direction.
Toolbox & IAC: Menu Manager: Changing fonts & font sizes displayed in Macintosh pop-up menus
How can I change fonts and font sizes displayed in Macintosh® pop-up menus?
One way to get pop-up menus in any font and style is to use the Communications Toolbox & IAC. There’s a pop-up menu 'CDEF' included with it that has a resource ID of 63. You can tell it to use the font and size of the current port’s font. You can get documentation on this in the Macintosh Communications Toolbox v.1.0 from APDA® (part #M0232LL/D). The Comm Toolbox is an integral part of System 7, so you know that this 'CDEF' is always around if you’re running 7.0 or later. Your users would need to install the Comm Toolbox to use your product under System 6.
You can also trick the standard 'MDEF'. Just before calling PopUpMenuSelect, patch the TextFont trap so that it points to a routine of yours that replaces the specified font number (which will be on the stack) with the font number for the font you want, then it calls the normal TextFont routine. When MenuSelect returns, patch TextFont back to what it was before you patched it. The patch routine looks something like the following if, for example, you want the menu to use the Geneva font:
MyTextFont PROC
MOVE.W #$0003,4(SP) ;Replace system font spec
;with Geneva spec
MOVE.L NormTrap,-(SP) ;Put addr of normal TextFont
;onto the stack
RTS ;Call normal TextFont
ENDPROC
The routine to install this patch will look something like this:
VAR
NormTrap : LongInt; {Address of normal TextFont routine}
WMPort : GrafPtr; {Pointer to Window Manager port}
CurrPort : GrafPtr; {Pointer to current GrafPort}
CurrFont : Integer; {Font number of normal font for Window Manager Port}
CurrSize : Integer; {Size of normal font for Window Manager port}
{Save current GrafPort for restoring later}
GetPort (CurrPort);
{Set the current port to the Window Manager port and set its font size}
GetWMgrPort (WMPort);
{Save the normal font and size and set the new size}
CurrFont := WMPort^.txFont;
CurrSize := WMPort^.txSize;
SetPort (WMPort);
TextSize (9);
{Patch TextFont so that our MyTextFont routine will be called.}
{NormTrap is global so that MyTextFont can see and use it.}
NormTrap := NGetTrapAddress ($A887, ToolTrap); {$A887 is trap for TextFont}
NSetTrapAddress (MyTextFont, $A887, ToolTrap);
{Now call PopUpMenuSelect}
SetPort (CurrPort);
MenuChoice := PopUpMenuSelect (MyMenuHandle, MyMenuLoc.v, MyMenuLoc.h, 1);
{Reset the TextFont trap to what it was before we changed it}
NSetTrapAddress (NormTrap, $A887, ToolTrap);
{Set the current font back to Chicago 12}
SetPort (WMPort);
TextSize (CurrSize);
TextFont (CurrFont);
{Set the current port back to what it was}
SetPort (CurrPort);
This routine assumes that the standard 'MDEF' will ALWAYS call TextFont, although this is a rather dubious assumption. The routine works on both Color QuickDraw™ and non-Color QuickDraw machines because the standard 'MDEF' copies the WMgrPort text characteristics to the CWMgrPort.
There’s yet another way to trick the standard 'MDEF'. You can change the QuickDraw bottleneck for drawing text so that it also changes the font. It works similarly to patching TextFont, but because the standard 'MDEF' does NOT copy the bottlenecks to the CWMgrPort on a Color QuickDraw machine, you must check for Color QuickDraw yourself and then use the appropriate port and type of QDProcs record (either QDProcs or CQDProcs). In the following example, assume there’s no Color QuickDraw:
VAR
WMPort : GrafPtr; {Pointer to Window Manager port}
MyProcs : QDProcs; {My bottlenecks}
CurrProcs : QDProcsPtr; {Pointer to normal bottlenecks}
CurrPort : GrafPtr; {Pointer to current GrafPort}
CurrFont : Integer; {Font number of normal font for Window Manager Port}
CurrSize : Integer; {Size of normal font for Window Manager port}
{Save current GrafPort for restoring later}
GetPort (CurrPort);
{Set the current port to the Window Manager port and set its font size}
GetWMgrPort (WMPort);
{Save the normal font, size, and procs and set the new size}
CurrFont := WMPort^.txFont;
CurrSize := WMPort^.txSize;
CurrProcs := WMPort^.grafProcs;
SetPort (WMPort);
TextSize (9);
{Set our bottleneck text proc to point to our text proc}
SetStdProcs (&MyProcs);
MyProcs.textProc := @MyTextProc;
WMPort^.grafProcs := @MyProcs;
{Now call PopUpMenuSelect}
SetPort (CurrPort);
MenuChoice := PopUpMenuSelect (MyMenuHandle, MyMenuLoc.v, MyMenuLoc.h, 1);
{Set the bottleneck back to normal}
WMPort^.grafProcs := CurrProcs;
{Set the current font back to Chicago 12}
SetPort (WMPort);
TextSize (CurrSize);
TextFont (CurrFont);
{Set the current port back to what it was}
SetPort (CurrPort);
PROCEDURE MyTextProc (byteCount : INTEGER; textBuf : Ptr;
numer, denom: Point);
VAR
currPort : GrafPtr;
currFont : Integer;
currSize : Integer;
BEGIN
GetPort (currPort);
currFont := currPort^.txFont;
currSize := currPort^.txSize;
TextFont (1);
StdText (byteCount, textBuf, numer, denom);
TextFont (currFont);
TextSize (currSize);
END;
Both these methods of “tricking” the standard 'MDEF' need global variables. Macintosh Tech Note #256 covers global use with stand-alone code.
The last way to do what you’re trying to do (and what the Comm Toolbox does) is set the SysFontFam ($0BA6) global to the font number of the font you want, set the SysFontSize ($0BA8) global to the font size you want, and then set the long word at LastSpExtra ($0B4C) to -1. The Font Manager caches the system font and only occasionally goes to the SysFontSize and SysFontFam globals when it needs to draw the system font. When LastSpExtra is set to -1, it acts as a flag to the Font Manager to flush the font cache and load the system font defined by the SysFontFam and SysFontSize globals.
So which method would I use? If my program had to run under all systems, I’d use this last method. If my program had to run under System 7 only, I’d use the Comm Toolbox’s 'CDEF'.
Toolbox & IAC: MIDI: MIDI tools support serial I/O
Is there an explanation for our Macintosh® IIx serial port’s failure when the MIDI Manager software is installed?
Your question centers on the SCC chip power-on configuration and the fact that MIDI developers have had to bypass the Toolbox to write directly to the SCC chip. With MIDI Management Tools, Apple now provides software for communicating to the serial ports without directly addressing the SCC chip. Because the MIDI Management Tools are a recent development, most existing MIDI programs still talk to the hardware directly.
Prior to Macintosh computers using the 68030, the contents of a particular register of the SCC chip had a power-on default of zero. (NOTE: This one register will be the only one discussed, but there are other registers in the SCC.)
Starting with the Macintosh IIx, the register’s power-on state may be set to something other than zero. This appears to be a random event. There is a utility from a company called Opcode (provided as an INIT) that assures that the setting of the Macintosh SCC register is set to zero. You can get in touch with Opcode at this address:
Opcode Systems
3641 Haven Dr., Suite A
Menlo Park, CA 94025
415-369-8131
415-369-1676 Technical support
Fax: 415-369-1747
AppleLink address: OPCODE
Known event sequences that reset the SCC register are:
- The Opcode INIT correctly sets the register’s value during startup process; printing takes place via a serial port; printing resets SCC register to something other than zero; SCC chip sends random data stream out the serial port; MIDI attempts to interpret the data stream as MIDI packets; everything connected to MIDI becomes confused (for example, locks up or crashes). Alternatively, nothing is sent out the serial port.
- AppleTalk, when it is turned on, changes the setting of the SCC register and sends AppleTalk packets; MIDI attempts to use those packets; this confuses all devices listening to the packets (for example, locks up or crashes). It is reported that Font/DA Juggler and Master Juggler are known to occasionally turn on AppleTalk.
To be sure that all works correctly, the following items need to be watched. These items assume that the Opcode INIT is in the System Folder of the startup disk.
- If any printing takes place after powering on and before a MIDI application is used, the SCC register may be set incorrectly for MIDI. Not printing prior to launching a MIDI program assures that the SCC’s register configuration is proper.
- If AppleTalk is turned on before MIDI is used, the SCC registers are likely to change and thus may cause lockups to occur in MIDI devices. This includes AppleTalk off at startup, turned on, then turned off; or AppleTalk on at startup, then turned off. Restarting with AppleTalk inactive and not activating AppleTalk prior to MIDI usage should allow the MIDI session to run smoothly.
- (This is not verified but has some logical merit, so it may provide a workaround.) Launching MacTerminal and quitting has been reported to clear the lockups experienced on MIDI devices. This apparently sets the SCC’s register to zero, which is the setting MIDI wants. One user with Southworth Music System’s Jambox, a MIDI interface, uses the Jambox DA to clear the lockups. Both of these solutions seem to work because of their interaction with the SCC’s register.
- It is also possible that a faulty SCC chip is on the logic board of the computer. However, with the situation appearing on two separate Macintosh IIx computers, it is unlikely that you are experiencing faulty hardware.
Toolbox & IAC: MIDI: Documentation about using MIDI tools on the Macintosh Portable
Do you have any information as to how to make MIDI software work on the Macintosh® Portable?
MIDI Manager 1.2 works on the Portable. The “Power Manager” chapter of Inside Macintosh Volume VI and “The Macintosh Portable Developer Notes” (available from APDA®) are crucial for those who want to make sure their software works on the Portable. There are features on the Portable such as “Sleeping” that developers need to be aware of when they make their software and hardware Portable compatible. The main things for you to be concerned about are sleep modes, how to program the SCC on a machine that sleeps, and the Portable environment in general. You might also want to obtain the latest MIDI Manager and other pertinent code from APDA as well.
Toolbox & IAC: Miscellaneous Tools (AII): Where to find Apple IIGS UnPackBytes bug/workaround info
Why is it that when I use the Apple IIGS® Miscellaneous Tool UnPackBytes call to unpack a minimum size buffer of 256 bytes it unpacks past the end of the buffer?
UnPackBytes has a couple of known problems, both of which involve having buffers on or near a bank crossing. Apple IIGS Technical Note #94, “Packing It In (and Out),” describes the problems in detail (4 pages) and how to work around them.
Toolbox & IAC: PPC Toolbox: Apple events and user authentication
I’d like to be able to start an Apple event-based session between two machines that are networked together without the user identity dialog box that always comes up, even if I only want to use Guest access. Is there any way I can use the PPC Toolbox’s PPCStart function to create a Guest session and use it for Apple Events?
Sessions set up by the Apple Event Manager with other Macintosh computers are always authenticated. That’s why you always get to see the user identity dialog box, even if you want to use Guest access. You’re always automatically authenticated with other processes on the local system and that’s the only time you won’t see the user identity dialog box.
You cannot use the PPC Toolbox to start a session and then pass that session off to the Apple Event Manager, even though the PPC Toolbox is the underlying transport mechanism used to send Apple events to other systems. By isolating the Apple Event Manager from the transport layer it uses to send Apple events as much as possible, Apple can change which transport layers are used in the future without breaking your applications.
If you really need to have connections made with no user intervention, you’ll have to use the PPC Toolbox or go directly to one of the AppleTalk protocol layers. If you choose the PPC Toolbox, you’ll have to make sure Guest access is allowed on the system you’re trying to connect to or you’ll still have to authenticate the session. (The authRequired field in the PortInfoRec returned by the PPCBrowser or IPCListPorts functions will be FALSE if Guest program linking is allowed). Since Guest access is global on a particular system and since some people may be nervous about allowing guests to Link with all high-level event aware applications on their systems, you might want to consider ADSP instead since it doesn’t require any user authentication.
Toolbox & IAC: PPC Toolbox: Call PPCEnd before PPCClose
Before closing a PPC port with PPCClose, is it necessary to call PPCEnd for my open sessions?
It isn’t always necessary to call PPCEnd before closing a PPC port. Calling PPCClose by itself will invalidate any active sessions for the given port and force the completion routines of all outstanding asynchronous calls to be called. This should be sufficient to close the port.
However, there are a few instances where you will want to call PPCEnd. If an error is returned in the completion routine of an asynchronous PPCRead or PPCWrite call you should then call PPCEnd asynchronously. This will allow PPC Toolbox resources to be released so they may be reused. If PPCEnd is not called in this manner, it will prevent the PPC Toolbox from cleaning up resources that it used for the active session.
Toolbox & IAC: QuickTime: MCSetClip and clipping with the movie controller
I use SetMovieDisplayClipRgn to set my movie clip, but the movie doesn’t obey my clipping. Does the movie controller component ignore this clipping?
You probably are directly modifying a movie that is attached to a controller without notifying the controller of the changes. The controller uses the display clip for its own purposes, such as for badges.
If you want to do clipping with the movie controller you must use MCSetClip. MCSetClip takes two regions. The first clips both the movie and the controller. The second clips just the movie, and is equivalent to the movie display clip. If both clips are set, the controller does the right thing and merges them as appropriate. If you don’t want one or the other of the clips, set them to zero.
In general, if you are going to do something to a movie that is attached to a controller you must either do it through the controller, using the action calls, or you must call MCMovieChanged. Otherwise, the controller would need to constantly poll the movie to see if its state changed. Clearly this would be Evil and Slow.
Toolbox & IAC: QuickTime: QuickTime interfaces for Think Pascal
Has Apple created QuickTime headers/interfaces for Think Pascal? The MPW Pascal headers don’t seem to be compatible.
There are no Think Pascal interfaces, but your Pascal Package comes with a program called Pascal Source Converter, which converts MPW Pascal sources to Think. This should be all you need to be able to use the provided interfaces with your favorite development package.
Toolbox & IAC: QuickTime: Status of rotating matrix support
What is the status of RotateMatrix and its use with SetMovieMatrix and SetTrackMatrix?
RotateMatrix works fine. But rotating matrixes are not supported for movies or images. So, although RotateMatrix will give you the correct mathematical result, unless you are using the matrix to transform something else (as with TransformFixedPoints) it has little use.
Rotation is a very important future direction that will get more attention in the future.
Toolbox & IAC: QuickTime: How to get the first video frame
Stepping through QuickTime movie video frames in the order they appear in the movie.is simple using GetMovieNextInterestingTime, except for getting the first frame. If I set the time to zero and rate to 1, then I get the second frame, not the first. In addition, the video may start later than at 0. How do you suggest finding this first frame of video?
To get the first frame in the conditions you describe you have to pass the flag nextTimeEdgeOK = $2000 to GetMovieInterestingTime. What this flag does is to make the call return the current interesting time instead of the next, if the current time is an interesting time. You need to do this since there is no way to go negative and then ask for the next interesting time.
Toolbox & IAC: QuickTime: Current QuickTime supports only video and sound media
Can I add a media to a QuickTime movie that is not video or audio? If so is there anything special I need to do to add text notes that can potentially accompany each frame in my “movie,” which can follow the video frames if a user edits the movie in any way.
The current release of QuickTime only allows for video and sound media. There is no way to install your own type, even in a case so obvious as the one you mention. Adding other media types is a high QuickTime priority and is likely to make it in a future release, but at the present there is no mechanism to do it.
Toolbox & IAC: QuickTime: QuickTime fills in image descriptor when data is compressed
When I send compressed images over Ethernet, CompressSequenceBegin doesn’t fill in the ImageDescription, which is needed at the other end of the conference link to DecompressSequenceBegin. Is this a bug?
CompressSequenceBegin doesn’t actually modify the handle that you pass. Instead, QuickTime makes a note of the handle that’s passed and doesn’t actually modify the contents until the first call that actually compresses data, such as CompressSequenceFrame. At that point, the handle will be changed.
If you can postpone dealing with the image descriptor until after the first call that compresses data, whatever you are writing should work just fine.
Toolbox & IAC: QuickTime: QuickTime Movie Toolbox “globals” are stored in system heap
According to the QuickTime Movie Toolbox documentation, “The Movie Toolbox maintains a set of global variables for every application using it.” How much global memory is required? Our application is shy on global data space.
The information maintained is not kept with the application’s global variables. The handle created by the EnterMovies call is stored in the system heap, not in the application heap. You don’t have to worry about how much space to allocate in your application. This initialization does not affect your A5 world either.
EnterMovies initializes everything, including setting up the necessary data space and creating a handle to it. When you’re done, be sure to make a call to ExitMovies to clean up the QuickTime data.
If an application makes multiple calls to EnterMovies, a different set of “globals,” or data area, is set up for each call. A call to ExitMovies should be made before exiting the area that made the call to EnterMovies. For example, an application that uses QuickTime will call EnterMovies and set up the QuickTime world. Then an external may be called upon that wants to use QuickTime. This external would have to make a call to EnterMovies to set up another QuickTime world for its use. Before leaving, the external should call ExitMovies to clean up after itself. The application can then continue to use QuickTime with the original world it set up.
Toolbox & IAC: QuickTime: QuickTime file audio retrieval
How can I retrieve audio from QuickTime files in 1-second chunks? I need a sound equivalent of GetMoviePict.
You will have to write your own audio extraction routine. The Movie Toolbox does not provide a simple call to, say, GetMovieSound(movie, time, duration). To get around this limitation, use GetMediaSample and collect the sound data by hand. The format for the final result is up to you; in the case of a 'snd ' resource you’d create the handle fill in the other fields and put the sample data in it.
You can use the QuickTime SoundDescription data structure (1) to find frequency, format, and other details, (2) to help you figure out how many samples you need for a second, and (3) to fill in the resource data fields.
Of course, this scheme gets more complicated in the case when there are more than a single sound track. The best source of information on sound resources and such is the Sound Manager chapter in Inside Macintosh Volume VI.
Toolbox & IAC: Resources: Apple IIGS UniqueResourceID system-range ID bug
I am using an Apple IIGS utility to generate resources for my application, and I noticed that some of the resource IDs generated are in the range $07FF0000 to $07FFFFFF, which is reserved for the system software’s use. What’s happening?
Your utility is calling UniqueResourceID with an IDRange of $FFFF, to request any unused resource ID. A bug in system software version 5.0.x allows UniqueResourceID to accidentally return a system-range resource ID if any system-range resources of that type are already present. This will be fixed in System 6. In the meantime, utilities can use UniqueResourceID with IDRange values other than $FFFF, and you should watch your resource IDs carefully to avoid using system-range resource IDs.
Toolbox & IAC: Resources: Macintosh resource ID numbering
Does the warning about using Macintosh resource IDs 0 through 127 apply to resource types of my own design?
When numbering resources, you can use any number you like on resource types of your own creation (that is, not of a type reserved by Apple.) In numbering resources you create of a type reserved by Apple, stick to the following guidelines:
• Negative numbers are reserved for various owned and otherwise “encoded” resources.
• The numbers 0–127 are reserved for Apple’s use.
• Positive numbers >127 are available for your use.
• DTS no longer registers 'FOND' IDs. 'FOND's should be referenced by name and not by number because the numbers change. Choose any 'FOND' ID within your font’s script range. For details, see Macintosh Technical Note #245, “Font Family Numbers.”
Toolbox & IAC: Resources: Partial resources and compressed resource format
Partial resources and compressed resource format
The partial resource calls ReadPartialResource and WritePartialResource do not decompress Apple’s compressed resource format. In fact, these two calls are the only way possible to read resources without decompressing them. It is not really possible to decompress part of a resource, since the decompression method requires the entire resource to be in memory for the conversion to occur.
Details of Apple’s compression scheme are not documented and Apple doesn’t currently license the algorithm to developers, but Macintosh compressed resources are contained only in the System file and other Apple-specific files. Because third-party products don’t use Apple’s compressed resources and all Apple’s compressed resources fit in memory without the partial calls, you needn’t worry about supporting partial resource calls with compressed resources. Just use the standard GetResource call to load these Apple- compressed resources.
You can determine if a resource is compressed by examining bit 0 of the resource’s attributes. If this bit is set, the resource is compressed, and partial resource calls will return the compressed data.
Toolbox & IAC: Resources: Changing a Macintosh resource
What is the recommended way to update a Macintosh resource?
As you may have guessed, there is no standard way to update a resource in a resource file. The general rule of thumb is, if the resource exists, simply load it in, modify it, mark it changed, and then cause it to be written out. It is also best at this point to write the resource if you know you are done changing it (ChangedResource simply schedules the resource to be written the next time the resource file is updated). (Read the caveat about changing purgeable resource on page I-123 of Inside Macintosh Volume I.)
You should, as a general rule, never remove and replace the resource. This causes undue accounting problems for yourself and the Resource Manager, and causes quite a bit more writing to the file than is absolutely needed.
If the write of a resource has failed for any reason and you would like to have the memory version of the resource contain what the disk version does, simply detach the current handle from the resource using detach, dispose of the handle if you don’t want the data anymore, and reload the resource as normal.
Toolbox & IAC: Resources: ResEdit doesn’t show Mac® Portable 'KCAP' resources
I am trying to use the 'KCAP' resource to draw the Macintosh® Portable keyboard layout in our application. I used the ResEdit® to check 'KCAP' in both System 7 and the Key Layout file, but the Portable keyboard type is not there.
The resource numbers 6 and 7 of 'KCAP' are contained in the ROM of the Portable. Being there, the resources are not directly viewable with ResEdit. They do, however, exist in your resource chain, so a GetResource for 'KCAP' #6 should load and return a pointer to this resource.
Toolbox & IAC: Resources: System 7.0 Resource Manager resource decompression
Is the resource compression technique used in System 7.0 documented anywhere?
Documentation describing the compression algorithm used on resources is not available. The System 7.0 Resource Manager automatically decompresses for you.You can force a resource to be permantly decompressed by modifying it with ResEdit™. Under System 6.0.7 or earlier systems, there’s no easy method to access compressed resources.
Toolbox & IAC: Resources: Modifying an Apple IIGS’s resource content
Do I have to write extra program code for my Apple IIGS® program to grow a resource?
No, it’s pretty straightforward. All you have to do to modify the content of any resource (including growing it) is to load the resource in, make any changes you want to the handle (such as change the data inside or call SetHandleSize to make it bigger), and then call MarkResourceChange. The Resource Manager updates the contents of your file when you call UpdateResourceFile. The Resource Manager recognizes the change in the size of the handle automatically.
Toolbox & IAC: Resources: Removing Macintosh resources during shutdown
What do I have to do to ensure that a resource installed in the Macintosh® System file will be removed at Shutdown or Restart?
First, your shutdown procedure must be installed before the System file is closed. It helps to understand the that Shutdown takes place after a couple of other steps in the process. The order of events is:
1) Close all drivers, issuing goodbye kisses to drivers that need them.
2) Eject and Unmount all volumes. (System file goes away!)
3) Restart or Shutdown, whichever was chosen.
Your shutdown procedure needs to be called before step 2. In other words, you should call ShutDwnInstall with sdOnUnmount and everything will be cool.
Toolbox & IAC: Resources: Troubleshooting a crash after setting a Mac window title
When a user chooses New from my Macintosh® application’s File menu, the application drifts off into bit-bucket land. The application fails in the SetWindowTitle method in the MacApp library while SADEing the application with the -sym option used. If I build the application with -debug and -sym on, I can cause the New command to work if I open another window besides the initial document window before choosing New from the file menu. I get worse results if I change the current segmentation approach, implying I may have dangling pointer(s), but I do not dereference anything except in calls to strcmp and PLstrcpy. Do those routines move memory?
If we follow the idea of something’s crashing when you set the window title, then this could happen if you have the window title stored in a STR resource. You open the thing, dereference it, and meanwhile the memory is shuffled, so when the method should set the title it points at garbage. Or maybe the window title is in a handle, and you dereference it during a PLstrcpy without locking it, and the memory shuffles the handle to another position.
The solution in this case would be to HLock and HUnlock the string- dereferenced possible handles, especially if you use handles or references to handles of some sort inside the PLstrcpy or strcmp calls. If you have some critical segments that should never be unloaded, put them into the 'seg!' resource definition in the MAMake file and see if that helps.
Toolbox & IAC: Resources: HOpenResFile versus OpenResFile
Why would using OpenResFile(fileName) cause a crash when I try to open a Macintosh® font file that’s already open?
The problem stems from the fact that OpenResFile doesn’t deal effectively with cases where the resource file is already open. Luckily, there are some relatively new Resource Manager calls that you can and should use instead. They’re all documented in the Resource Manager chapter of Inside Macintosh Volume VI and in Macintosh Technical Note #214, “New Resource Manager Calls.”
The call of interest in your case is HOpenResFile. To use it, break down the vRefNum (actually WDRefNum) returned by Standard File into a real vRefNum and dirID by calling PBGetWDInfo, and pass those to HOpenResFile along with the file name. The important part, however, is the permissions byte. If you expect to modify the file, pass fsRdWrPerm in that field. If there’s an error of any kind, expect HOpenResFile to return -1, which should serve as a signal that you need to call ResError to find out what went wrong.
Toolbox & IAC: Resources: 'SIZE' resource 32BitCompatible bit
Does setting the 32BitCompatible bit in the 'SIZE' resource have any effect in System 7.0b4? According to my Inside Macintosh® Volume VI draft, if the system is in 32-bit mode and the bit is OFF, a dialog reports that the application is not 32-bit clean. We see no such dialog.
The dialog box that was to be shown for applications with the 'SIZE' resource’s is32bitclean flag disabled was found to be too complex for an end user, so this dialog box is not shown in the System 7 final (while it’s still there in A/UX® 2.0.1). This could be subject to change in the future.
Toolbox & IAC: Resources: HOpenResFile with fsRdPerm permission returns unique access path
According to Macintosh® Technical Note #185, “OpenRFPerm will create multiple, unique, read-only access paths to a resource file.” Is this same behavior present in HOpenResFile? A cdev I have written must look within certain types of files for specific resources. If the file is already open, will a call to HOpenResFile with fsRdPerm permission return a unique path? Using OpenRFPerm seems to have no problems, but the overhead of creating working directories seems rather untidy.
I’ve investigated your question and discovered that HOpenResFile is simply a friendly face on top of OpenRFPerm, so the unique access paths that are created by OpenRFPerm will indeed percolate upward through HOpenResFile.
Toolbox & IAC: Resources: Apple IIGS Reference 0 “Close” call closes app’s resource fork
Why can’t I access my Apple IIGS® application’s resources after opening a file and then immediately closing it?
You are most likely issuing the “close” call with a reference number of zero without realizing it. This will close all open files, including your own resource fork. (It closes it out from under the Resource Manager, which is dangerous.) Try using the version of GSBug™ on the Developer CD to set an OSBreak on your close call and see what the reference number actually is.
Toolbox & IAC: Resources: Apple IIGS resource converter cannot call LoadResource
Can an Apple IIGS® resource converter load another resource?
No, the Resource Manager is not guaranteed to be so reentrant that a converter can call LoadResource.
Toolbox & IAC: Resources: How to determine if a Macintosh window is an rdocProc type
How do I determine if a Macintosh window is an rdocProc type?
The following code will provide that:
FUNCTION GetWindowType (window: WindowPtr): INTEGER;
{ Here, window type = Window Definition ID }
VAR
theType: ResType
theName: Str255.
windowVar, WDEFID, wType: INTEGER;
wDefProc: LONGINT;
wDefHdl: Handle;
BEGIN
windowVar := GetWVariant(window);
wDefProc := ORD4(WindowPeek(window)^.windowDefProc);
wDefHdl := Handle(BAND(wDefProc, $0FFF));
GetResInfo(wDefHdl, WDEFID, theType, theName); { this is the call }
{ that does it }
wType := 16 * WDEFID + windowVar;
IF (wType = documentProc) | (wType = zoomDocProc) THEN
hasGrowIcon := TRUE
ELSE
hasGrowIcon := FALSE;
GetWindowType := wType;
END; { GetWindowType }
This will provide the WDEFID value, along with the resource type and name info, which you can ignore.
Note that you should check ResError after the GetResInfo to see if anything bad happened.
Toolbox & IAC: Resources: Locate Macintosh folder first with FindFolder before OpenRFPerm
OpenRFPerm gets result code -43 (file not found) when opening a file that was put in the Macintosh® System 7 Control Panel folder, but when the file is moved outside the Control Panel folder and within the System Folder, OpenRFPerm works fine.
It sounds like you are calling OpenRFPerm and it is accessing the System Folder rather than the Control Panel Folder. System 7.0 doesn’t automatically search all of the subfolders in the System Folder; therefore, it is necessary to use the toolbox call FindFolder to locate the Control Panel folder before you call OpenRFPerm.
The FindFolder call is documented in Inside Macintosh VI, Chapter 8: “You can call the FindFolder function to get the path information so that you can access special folders. You pass FindFolder a target volume and a constant that tells it which special folder you are interested in. FindFolder returns a volume reference number and a directory ID. If the specified folder does not exist, FindFolder can create it and return the new directory ID. (See table 8-2 for the folder types [in System 7.0], resource types and constants.)”
Toolbox & IAC: Resources: Maximum Macintosh resource size is “maxlongint” bytes
Is the maximum size of a Macintosh® resource still 32K?
No. There used to be a bug in the 64K ROMs that didn’t allow you to write even multiples of 32K, such as 32K-64K or 128K-192K. This bug was fixed in 128K ROMs. As of 128K ROMs, the resource size is limited to “maxlongint” bytes.
Toolbox & IAC: Resources: Maximum number of items in a Macintosh resource file is 2727
Is there a maximum number of items for Macintosh® resources?
In a file, yes. It is 2727.
Toolbox & IAC: SANE: Converting between 96-bit and 64-bit number formats in SANE
Page 193 of the Apple Numerics Manual, Second Edition, refers to two SANE routines that convert between extended 96-bit floating point format, and 64- bit Comp integers. Where do these routines, Comp2X and X2Comp, live?
Page 193’s reference to the routines Comp2X and X2Comp is in error. Instead, the assembly macros FC2X and FX2C can be used as documented on page 156 and 157. For the 96-bit format, these are defined in SANEMacs881.a. Using the MPW C and MPW Pascal compilers, assigning an extended value to a comp variable, or vice versa, automatically converts to the target format.
Toolbox & IAC: SANE: SANE and NaNs
When I use the Str2Num procedure I want to be able to check if the string is an invalid numeric representation, but the following MPW Pascal code never catches a bad number-string:
t_ext : Extended ;
str_num : Str255 ;
t_ext := Str2Num (str_num) ;
IF (t_ext = NAN(017)) OR (t_ext = NAN(255)) THEN { error checking }
If I print the value of text to a text file then it will list NAN(017), but I cannot decipher NaN codes within the program. How can I decipher the NaNs to check for bad numbers?
Your code doesn’t catch bad number-strings because by definition two NaNs are never equal (they are unordered) so the condition in your IF statement cannot occur. When the concern is only to test for NaNs (regardless of the type), then the previous provides a nice, fast way to test whether the input string results in a valid number. The following semi-code shows how to do it:
VAR
x1,x2: Extended;
BEGIN
x1 := Str2Num(s);
x2 := x1;
IF x1 = x2 THEN
ProcessOKInput { String represents a valid number }
ELSE
ProcessBADInput; { String converts into a NaN }
END;
Note that in the case when x1 is INF (or -INF), the comparison x1 = x2 is TRUE. (Apple Numerics Manual, Second Edition, “Comparisons with NaNs and Infinities,” page 48)
When the objective is to find the NaN code, then you have to scan the result (Apple Numerics Manual, “Sane Data Types,” page 18). The basic clue is that the exponent is 32767 and the fractional part is not zero. For this example, let Nan(017) = $7FFF 4011 0000 0000 0000:
Field value
s (sign bit) 0 0
e (exponent) 32767 $7FFF
i (integer) don’t care
f (fraction) NOT 0 (it is zero in the case of infinities)
From the fraction we have $4011 = 100 0000 00010001(bin). The high bit means that this is a quiet (non-signaling) exception and 00010001 = 17 form the NaN code (17).
Hope this helps™
The Dogcow.
Toolbox & IAC: SANE: Apple II SANE is available from Software Licensing
I’ve heard about a version of SANE® for eight-bit Apple® II computers but I can’t find it anywhere. Is it still sold?
SANE is considered part of the System Software and is distributed by Apple’s Software Licensing group. You may contact them at (408) 974-4667 or through AppleLink® address SW.LICENSE. Although older versions of SANE were sold as part of Apple’s old “WorkBench” series, the current version should be obtained from Software Licensing. Even if you own an older copy of SANE you wish to use in your program, it still must be licensed from Software Licensing before distributing it. SANE is built in to all Apple IIGS® and Macintosh® computers.
Toolbox & IAC: Scrap Manager: Clipboard window should be hidden in MultiFinder
I think my application is completely MultiFinder®-aware and conforms to all the MultiFinder guidelines. What might I have missed?
Many developers forget one important MultiFinder feature—there is a note on page 3-3 of the “Programmer’s Guide to MultiFinder” which many programmers seem to miss: “Applications should hide their Clipboard window when not running in the foreground. The contents of the Clipboard are not valid unless the application is frontmost.” This means you must do more than just deactivate the Clipboard. Make it invisible—otherwise there can be multiple incarnations of the Clipboard window displayed on the screen at the same time, only one of which is necessarily current.
Toolbox & IAC: Script Manager: FormatX2Str strings
Using the Script Manager to convert numbers to strings and vice versa, in any language, what’s the best way to create the string to pass to FormatX2Str? Will strings using the characters: “#” or “0” or “.” or “,” work no matter what script is currently running, and if not, what can I do?
The number format string and canonical number format string mechanisms that you use with FormatX2Str and its kin is a strange design, for exactly the reason that you asked about. The number format string (the one with the characters such as “#” and “0”) does not necessarily work right regardless of the current script. In fact, it doesn’t even necessarily work right between localized versions within one script system. The canonical number format string does work between localized systems and between script systems. The strange thing is there’s an easy way to store number format strings (usually in a 'STR ' resource), but no obvious way to store canonical number format strings. Here’s what you can do when converting between numbers and strings:
When you convert a number format string to a canonical number format string with Str2Format on a U.S. system, it converts it from something like “###.###” to a canonical number format string that looks something like, “three digits, a decimal point, and three digits.” On a German system, that same number format string would be converted to “three digits, a thousands separator, and three digits.”
What you can do to get around this is to save the canonical number format string in a resource instead of the number format string. The canonical string stores things in a language- and script-independent way. Create this resource by writing a trivial utility program that takes a number format string and calls Str2Format to convert it into a canonical number format string, and then copy this into a handle and save it as a resource of a custom type, like 'NUMF'. In your real program, load the 'NUMF' resource, lock it, and then pass the dereferenced handle to FormatX2Str and FormatStr2X.
You can see this done in the ProcDoggie Process Manager sample from the 7.0 Golden Master CD. Take a look at the SetUpProcessInfoItems procedure in UProcessGuts.inc1.p file. You’ll see that the 'NUMF' resource is loaded, locked, and then passed to FormatX2Str. The result is displayed in the Process Information window.
If your program is localized by nonprogrammers, then you might want to provide the utility that converts a number format string to a canonical number format string resource just in case they have to change the entire format of the string. Then they can install the new 'NUMF' (or whatever you choose) resource as part of the localization process.
Toolbox & IAC: Script Manager: String2Date and Date2Secs conversion surprises
String2Date and Date2Secs treat all dates with the year 04 to 10 as 2004 to 2010 instead of 1904 to 1910.
This is correct; the Script Manager treats two-digit years less than or equal to 10 as 20xx dates if the current year is between 1990 and 1999, inclusive. Basically, it just assumes that you’re talking about 1-20 years in the future, rather than 80-100 years in the past. The same is true of two-digit 9x dates, when the current year is less than or equal to xx10. Thus, in 2003, the date returned when 3/7/94 is converted will be 1994, not 2094. This is all documented in “Worldwide Development: Guide to System Software,” available from APDA.
Toolbox & IAC: Script Manager: Using FormatXToStr and FormatStrToX with Pascal switches
Why do the FormatXToStr and FormatStrToX Script Manager routines stop working when I use the Pascal -MC68881 switch?
Regular SANE® extended numbers are 10 bytes long while MC68881 extended numbers are 12 bytes long, and the extra two bytes are right in the middle of every 68881 extended number. Appendix G “The SANE Library” in the Macintosh Programmer’s Workshop (MPW®) Object Pascal version 3.1 manual goes into detail about this. The FormatX2Str and FormatStr2X parse the extended number you pass them directly, and they can only parse 10-byte extended numbers. Fortunately, you can still use the -mc68881 option with these routines as long as you convert any extended numbers to 80-bit extended numbers before passing them to FormatX2Str and FormatStr2X. The SANE.p unit has routines to do this called X96toX80 and X80toX96 (incorrectly documented as X96to80 and X80to96 in the MPW Object Pascal manual). Because the extended80 and extended96 types aren’t equivalent to the extended type as far as Object Pascal is concerned, you have to redeclare FormatX2Str and FormatStr2X to take these types. You can do this as follows:
FUNCTION FormatX2Str80 (x: extended80;
myCanonical: NumFormatString;
partsTable: NumberParts;
VAR outString: Str255): FormatStatus;
INLINE $2F3C,$8210,$FFE8,$A8B5;
FUNCTION FormatStr2X80 (source: Str255;
myCanonical: NumFormatString;
partsTable: NumberParts;
VAR x: extended80): FormatStatus;
INLINE $2F3C,$8210,$FFE6,$A8B5;
Call these routines instead of the originals. To call FormatX2Str80, all you have to do is this:
VAR
x: extended80; {96-bit extended number}
myCanonical: NumFormatString;
partsTable: NumberParts;
outString: Str255
result := FormatX2Str80 (X96toX80 (x), myCanonical, partsTable, outString);
Calling FormatStr2X80 is just slightly more complicated because the extended number is passed by reference:
VAR
x: extended; {96-bit extended number}
x80: extended80; {80-bit extended number}
source: Str255;
myCanonical: NumFormatString;
partsTable: NumberParts;
x80 := X96toX80 (x);
result := FormatStr2X80 (theString, realCanon, PartsTable, x80);
x := X80toX96 (x80);
You should find that these calls now work properly with the -mc68881 option set. This of course means that you’ll need two versions of the source code; one with the calls to convert between 96-bit and 80-bit extended numbers for use with the -mc68881 option and another one which just uses plain old 80-bit extended numbers for use when the -mc68881 option is turned off.
Toolbox & IAC: Script Manager: Character type and subtype values within the Kanji system
What are the values of character type and subtype with the Macintosh® Kanji system?
For Roman, these are the values of character type:
Punctuation 0
ASCII 1
European 7
For KanjiTalk, the values are the same as Roman, with the addition of:
Katakana 2
Hiragana 3
Kanji 4
Greek 5
Russian (Cyrillic) 6
In Roman, the subtype field is interpreted as:
Normal punctuation 0
Numeric 1
Symbols 2
Blanks 3
The KanjiTalk subtype values are the same as Roman except if the character type is Kanji, in which case the subtype field takes these values:
JIS Level 1 0
JIS Level 2 1
JIS User Character 2
Finally, for KanjiTalk, the character direction field is replaced by the In-ROM field. It is 1 if the character is in the ROM card and 0 otherwise.
Toolbox & IAC: Sound Manager: Playing 16-bit sound data from a Macintosh disk
What’s the preferred method for playing sound from disk: with a doubleback routine and SndPlayDoubleBack or though the queue with our own routines? Does our 16-bit audio program have to convert the audio to 8-bit before playing through the Macintosh speaker or does the DoubleBackPlay or StartSoundFilePlay file playing routines do this for us?
The Sound Manager is not designed to handle 16-bit sound data at this time. You will need to convert the 16-bit data before giving it to the Sound Manager. The best method for playing from disk will be to make a doubleback routine and use SndPlayDoubleBack. You shouldn’t need to completely roll your own, but you’ll need to take care of getting the data from disk, converting it to 8-bit data and passing the data to the Sound Manager to be played.
Toolbox & IAC: Sound Manager: Which Macintosh systems support internal speaker stereo mixing
Why do I get only the left channel of a stereo sound out of my Macintosh IIcx?
The only Macintosh models that combine the two stereo channels into one for playback out of the internal speaker are the Macintosh SE/30 and the IIsi. All others use just the left channel. If you would like to check for the machine’s ability to do mixing, you can use Gestalt. This is documented in Inside Macintosh Volume VI, page 22-70. Bit 1 of the Gestalt selector for sound will tell you whether the machine has stereo mixing on the internal speaker.
Toolbox & IAC: Sound Manager: SndStartFilePlay 20,000-byte minimum buffer size
What’s the minimum buffer size for SndStartFilePlay?
SndStartFilePlay needs a buffer of at least 20,000 bytes (approximately 19.5K) to output sound without problems on the slowest Macintosh models.
Toolbox & IAC: Sound Manager: SndDoImmediate versus SndDoCommands
We want to allow the user to change the sound volume while a lengthy (many seconds to minutes) sound is playing.
If the sound that is playing belongs to your application, then you should be doing a sndDoImmediate with an ampCmd to change the amplitude of the current sound. (See Inside Macintosh Volume VI, pages 22-50 thru 22-52, for information.) You should not set the system wide volume to accomplish this.
Toolbox & IAC: Sound Manager: Macintosh sndRecord filter proc structure
What is the structure of a filter proc for SndRecord?
The filter procs used by SndRecord are identical to those used by the standard modal dialog. You can find information on writing filter procs in Inside Macintosh Volume I, page I-415. For sample code, take a look at Macintosh Technical Notes #47 and #80, and Sample Code #18 called StdFile.c
Toolbox & IAC: Sound Manager: SndPlayDoubleBuffer doesn’t work on Macintosh Plus or Classic
SndPlayDoubleBuffer doesn’t work on Macintosh Plus or Classic
The call SndPlayDoubleBuffer doesn’t produce sound on the Macintosh Plus or Classic because neither model is equipped with an Apple Sound Chip (ASC). The following is a short blurb taken from Inside Macintosh Volume VI, page 22-3 (second paragraph): “..the continuous play-from-disk routines and the ability to produce concurrent multiple channels of sampled sound are currently available only on machines equipped with the ASC.”
You can fake your own double-buffering routine, replaceing SndPlayDoubleBuffer, by issuing a string of buffering commands followed immediately by a callback routine. While this task takes a bit ‘o coding time, the method will work on all Macintosh models.
Alternatively, you can use the Gestalt function to test for the Apple Sound Chip (ASC), and then use SndPlayDoubleBuffer only with Macintosh systems that have the ASC.
Toolbox & IAC: Sound Manager: Determining Macintosh Sound Manager version
Determining Macintosh Sound Manager version
The call sndSoundManagerVersion returns 2018000 for the System 7.0 Sound Manager and 2006000 for the System 6.0.7 Sound Manager, but it crashes if earlier Sound Manager versions are in use. If you need to check for pre-6.0.7 Sound Manager versions before using the new Sound Manager calls, including sndSoundManagerVersion, use Gestalt’s gestaltSystemVersion.
Toolbox & IAC: Sound Manager: Sound Manager doesn’t tell Gestalt about sound input devices
When I register a Macintosh® sound input device with the Sound Manager, will the Sound Manager inform Gestalt that a sound input device is available, so a gestaltHasSoundInputDevice query returns true?
The Sound Manager doesn’t register devices for you, so your driver should install code to set the gestaltHasSoundInputDevice bit itself, using the function ReplaceGestalt (Inside Macintosh Volume VI, page 3-50) to make the change to gestaltHasSoundInputDevice.
Toolbox & IAC: Sound Manager: Macintosh Sound Manager SndAppDead bug
Is there any way to turn off a Macintosh® sound channel whose parent application has died?
You spotted a recently discovered Sound Manager bug. _SndAppDead is a call that supposedly shuts off all sound IO and de-allocates all sound channels from an application. Unfortunately, it didn’t work. If things worked right, it should have been called from _ExitToShell on all expected or unexpected quits from within the application or debugger. Instead of doing its thing correctly, it usually kills your Macintosh or makes the Sound Manager unusable until you restart. The bad news is there’s no known workaround. The good news is that it has been fixed, and will be available in the next beta release of System 7.
Toolbox & IAC: Sound Manager: Correct value of Macintosh initNoInterp
Is there an error in Inside Macintosh Volume VI where it claims that both initNoInterp and initChan0 have the same value of $0004?
You’re right, they’re the same. According to the guy who is doing time attempting to straighten out the Sound Manager, “initChan0 is ONLY used by the waveTableSynth, initNoInterp is ONLY used by the sampledSynth.” I’m always grateful for meaningful constant names, aren't you?!?!?
Toolbox & IAC: Sound Manager: Macintosh IIsi sound input documentation and samples
Where can we learn how to access the recording capabilities of the Macintosh® IIsi? We need to be able to acquire and process the samples in real time under program control (that is, no “push to record” button).
Inside Macintosh, Volume VI contains the comprehensive documentation on using sound with the Macintosh. It supersedes the information in the Sound Manager chapter of Inside Macintosh, Volume V. “Recording Sounds Directly From Sound Input Devices” is a section pertinent to your concerns. Also, check the SC.024.SoundApp folder in the DTS Sample Code folder and sound Q&As on AppleLink and on the latest developer CDs.
Toolbox & IAC: Sound Manager: Macintosh code and instructions for generating dial tones
My program lets a user dial the phone if a modem is connected to the user’s Macintosh®. How can I add the option of dialing without using the modem, just like HyperCard® does? Is generating dial tones a standard function of the Sound Manager?
So, ya wanna do dial tones just like HyperCard? Well, that’s not so hard (as long as you are patient enough to read through all the Sound Manager documents and beat your head against the wall for half an hour, like I did). The technique is simple: lift the 'snd ' resources from HyperCard and use them to generate dial tones! (Yes, that’s OK, dtmf tones are generic sounds; just don’t lift any of the other sounds!)
Start by using ResEdit™ to copy 'snd ' resources #130-145 from the HyperCard program file (I got them out of 2.0). Next use the Sound Manager to play them and to use them as an instrument definition for the samplesynth. Since this can be tricky, and since you may or may not want dive deep into the Sound Manager, I am including a generic subroutine that I wrote that will “dial” for you. All I ask is that if you use it “as is” in your application, please remember me in your prayers.
How to use the dial procedure:
To call the dial procedure simply pass it a string and it will do the rest. All digits A thru D, # and * play the proper tone for the touch tone key; any other characters generate a 1/2 second delay. Each tone is sounded for about 1/4 second. The interface to it is simply: Procedure Dial(theNum:Str255). Please note that in order to keep this short, very little error checking has been added, please add any/all that you need.
And now for the fabulous source code:
PROCEDURE Dial(theNum:str255);
var i:Integer;
theSound:Handle;
OldResFile,DialResFile:Integer;
theResNum:integer;
dummy:LongInt;
MyErr:OSErr;
MySndChannel:SndChannelPtr;
MyPlayCommand:SndCommand;
begin
if length(theNum)<1 then Exit(Dial);
OldResFile:=CurResFile;
{ I have not moved the resources yet, but if you move them into your
application you will not have to do any of the fooling with this stuff }
DialResFile:=OpenResFile('Hypercard');
If DialResFile=-1 then Exit(Dial);
for i:=1 to length(theNum) do
begin
case theNum[i] of
'0'..'9':theResNum:=ord(theNum[i])-ord('0')+130;
'A'..'D':theResNum:=ord(theNum[i])-ord('A')+140;
'*':TheResNum:=144;
'#':TheResNum:=145;
otherwise TheResNum:=0;
End; {Case}
If TheResNum<>0 then
begin
{ Load the proper sound resource from disk }
theSound:=GetResource('snd ',TheResNum);
hLock(TheSound);
{ allocate a channel to play this sound with... }
MySndChannel:=NIL;
{ 5=SampleSynth, $A0=mono/22kHz }
MyErr:=SndNewChannel(MySndChannel,5,$A0,NIL);
{Now send command 80, soundCmd, to install the instrument
we loaded }
MyPlayCommand.cmd:=80;
MyPlayCommand.Param1:=0000;
{ See sound manager docs for resource format of type 2 sounds
for more info }
MyPLayCommand.Param2:=ord4(TheSound^)+14;
MyErr:=SndDoImmediate(MySndChannel,@MyPLayCommand);
{ Now send the playnote command (40) to play a middle C (that's
how the instrument is defined... }
MyPlayCommand.cmd:=40; { Note command }
MyPlayCommand.Param1:=500; {1/4 second in
duration}
MyPlayCommand.Param2:=$FF000000+60; { Loud +
Middle c }
MyErr:=SndDoImmediate(MySndChannel,@MyPlayCommand);
{ and clean up after this note }
MyErr:=SndDisposeChannel(MySndChannel,false);
hUnLock(TheSound);
end
Else
{ all nonDTMF characters produce a delay… }
Delay(30,Dummy);
End; { For }
{ Now put the resource file back to normal }
CloseResFile(DialResFile);
UseResFile(OldResFile);
End;
Toolbox & IAC: Sound Manager: Where to get missing pages of IM VI Sound Manager chapter
Did you know that the image file version of Inside Macintosh®, Volume VI, on the System 7 Beta CD is missing about 20 pages of the Sound Manager chapter?
The missing pages of the Sound Manager chapter are available on AppleLink® in the following set of folders:
Developer Services
Macintosh Developer Technical Support
System Software 7.0
Inside Macintosh, Volume VI.
Toolbox & IAC: Sound Manager: Sound Manager versus Sound Driver
We generate sounds using the Four-Tone Synthesizer (StartSound, StopSound). Our application must run on all Macintosh® computers and all system software versions starting with System 6.0. According to an early version of Inside Macintosh, Volume VI, the Sound Manager’s Four-Tone Synthesizer does not perform as expected on some Macintosh systems. When should we use the Sound Manager and when should we use the Sound Driver?
The Sound Driver is no longer supported, as of System 6.0.7. The Four-Tone Synthesizer in the Sound Manager released with 6.0.7 does not work correctly for non-Apple® Sound Chip (ASC) machines (Macintosh Plus, Macintosh SE, Macintosh Classic®, and Macintosh LC), but we expect to fix this in System 7. If you need to use the Four-Tone Synthesizer for non-ASC machines running 6.0.7, you could try the Sound Driver with 6.0.7 on the chance it’ll work for your purpose. Use the Sound Driver for non-ASC machines running System 6.0.5 and earlier.
Toolbox & IAC: Sound Manager: Specifying a Macintosh Sound Manager frequency
Why don’t the Macintosh® System 6.0.5 Sound Manager’s noteCmd and freqCmd allow you to specify the frequency by specifying a three-byte frequency value, with the least significant byte representing the fractional part of the frequency? According to Inside Macintosh, Volume V, page 483, you should be able to specify frequency in this way, as well as by the selection of a musical note enumeration from an even-tempered scale (values 1 through 127). The Sound Manager chapter in Volume VI of Inside Macintosh does not discuss frequency specification at all. Is support for this very valuable feature forthcoming?
We are currently unsure if the second method for specifying a frequency will ever be supported. The problem is that there is no clean way to do the byte sharing which was suggested in Inside Macintosh. If we come up with some way to support this and still have a reasonable range of frequencies which can be played, then we will do it.
Toolbox & IAC: Sound Manager: How to play Macintosh sounds in a continuous sequence
When I open a Macintosh® sound channel under System 6.0.5, I can use SndPlay to play sampled sounds, one at a time. When I’m done, I close the channel. Under System 6.0.7, after the first sound is played, no other sounds will play. If I close and reopen the channel, I can play another sound, but only one (until I close and reopen the channel again). Why do sound routines that functioned normally in System 6.0.5 seem to operate incorrectly in System 6.0.7?
In System 6.0.5, the Sound Manager just barely allowed you to play a sampled synth when the channel was preopened with a synth. The problem is documented in the Sound Manager chapter of Inside Macintosh, Volume VI. If you have a 'snd ' resource that has a synth defined in it, then you cannot open your own channel with a synth and then call SndPlay. Because your code is playing the sound once, what is happening is that you have the channel set up correctly but you are trying to use it twice. The only way you can play a 'snd ' with a synth is to create and dispose of the channel each time, as in the following code (the resource used is just a SoundEdit resource):
#include <Sound.h>
#define TRUE 0xFF
#define FALSE 0
main()
{
Handle Sound;
SndChannelPtr chan;
int i;
OSErr err;
Sound = GetResource ('snd ', 100);
if (ResError() != noErr || Sound == nil)
Debugger();
for (i = 0; i < 3; ++i) {
chan = nil;
err = SndNewChannel (&chan, 0, 0, nil);
if (err != noErr)
Debugger();
err = SndPlay (chan, Sound, FALSE);
if (err != noErr)
Debugger();
err = SndDisposeChannel (chan,FALSE);
if (err != noErr)
Debugger();
}
}
If you want to play multiple sounds one after another, you may be able to do it by using SndPlayDoubleBuffer. You can just keep pumping sounds to it and it will continue to play them. Other than this you may want to change your 'snd ' files so that there are no synths in the 'snd '. Make sure all the 'snd ' resources have been changed and then define the synth when you create the channel. The way to tell if your 'snd ' has a synth is to check the third word in the 'snd ' file. If the value is a 5 then you have the synth set to sampledSynth.In the case of SoundEdit resources, you do get a synth. If you take this route, you will need to make sure that all the 'snd ' resources have been changed and you will want to define the synth when you create the channel.
You can avoid having to dispose of the channel after each play if you make sure that each 'snd ' does not have a synth (byte three = 0) and then create the channel with a synth and play the 'snd 's. The one problem with this is that you do not know when the sound is finished playing. If you play the sounds synchronously it would work, but this feature is not yet supported in System 7.0.
Toolbox & IAC: Sound Manager: System 6.0.7 Sound Manager SndPlay aSynch bug workaround
SndNewChannel (NIL passed in) followed by a SndPlay used to play sound from my Macintosh® application’s 'snd ' resource loaded via GetResource, but my code no longer works with System 6.0.7’s 7.0 Sound Manager. I don’t know if a 'snd ' resource created using SoundEdit has a synth device associated with it. How can I tell if a synth is associated with a 'snd ', and how can I change my code to work with the new Sound Manager?
The way to tell if your 'snd ' has a synth is to check the third word in the 'snd ' resource file. If the value is a 5 then the snth is set to sampled sound. In the case of SoundEdit resources, you do get a synth. The code below will take care of the problem you described:
void start()
{
OSErr err;
Handle Sound;
SndChannelPtr chan;
SndCommand theCmd;
Sound = GetResource ('snd', 100);
if (ResError() != noErr || Sound == nil)
Debugger();
/*
The resource above contains snth information. Check this
with ResEdit™.If you use this snd with SndPlay and a
channel, then the channe must be created with snth=0.
This is documented as an issue in Jim Reekes’ interim
Sound Manager documentation (10/2/88). SndPlay should
have been returning an error when this happens.
*/
chan = nil;
err = SndNewChannel (&chan, 0, 0, nil);
if (err != noErr)
Debugger();
/*
This just pointed out a bug to me. The aSynch flag
is being ignored by SndPlay, which should have waited
until the sound was completed before returning to the
caller. Instead, it returned immediately and then you
sent the quietCmd. This is why you didn't hear anything.
*/
err = SndPlay (chan, Sound, FALSE);
if (err != noErr)
Debugger();
/*
SndDisposeChannel will wait until the sound is done
before disposing the channel if quietNow is FALSE
*/
err = SndDisposeChannel (chan,FALSE);
if (err != noErr)
Debugger();
}
Toolbox & IAC: Sound Manager: Macintosh Sound Manager changes
What changes have been made to the Macintosh® Sound Manager?
System 6.0.3 Sound Manager changes: none
System 6.0.4 Sound Manager changes:
• The current Sound Manager is in the ROM of the Portable and IIci.
• Sound Manager will not crash if the application calls ExitToShell without disposing its channels.
• Sound Manager and Sound Driver conflicts have been resolved. While the Sound Driver is in use, the Sound Manager will not be available.
• SysBeep will flash the menu bar when a sound is active (SoundActive = TRUE). This sometimes crashed on the Macintosh Plus and SE.
• SndNewChannel will return an error if an attempt is made to allocate a second sampled sound channel. Previously, it would return a non-functioning channel and noErr.
• Sound is no longer available in HyperCard® XCMDs due to changes made in System 6.0.4 and HyperCard 1.2.5. HyperCard users have only the Play command. This was always unsupported by XCMD, but Sound Driver calls often worked. It was a risk and often crashed, but these conflicts were resolved in the Sound Manager. Now HyperCard will have to be revised to support an XCMD using sound.
• A new bug was created in 6.0.4. SndPlay will install a callBackCmd into the channel when a sampled sound 'snd ' resource is being used. This causes the user’s call-back routine, if present, to be called unexpectedly. The call-back routine can witness this additional callBackCmd by looking at its user parameters. Here’s what the bogus callBackCmd being received by the call back procedure looks like:
cmd = callBackCmd
param1 = snd handle state bits, result of GetHState(sndHandle)
param2 = handle to 'snd '
This happens when you supply a sound channel to SndPlay with a format 2 'snd ' and specify aSynch. It looks like this:
SndNewChannel(newChan, 0, 0, myCallBackProc);
SndPlay(newChan, format2Snd, aSynch);
The callBackCmd has two parameters that are for the programmer’s use. The call-back routine is called at interrupt time, and the routine needs to set a global flag. As a solution, store a unique value in param1 before issuing the callBackCmd. While in the callBack procedure, test for this value to determine if it is the correct callBackCmd.
Toolbox & IAC: Sound Manager: How to minimize clicking sound when using Mac Sound Manager
When I use the Sound Manager with MultiFinder®, I hear clicks before and after my sound plays. How can I stop the clicks?
The clicking is a hardware problem. The speaker clicks whenever the sound is turned on or off. There’s nothing you can do about this. Macintosh® Tech Note #19 explains a technique that minimizes the clicking.
Because the sound hardware can’t be shared among processes, if your program is using the Sound Driver and another process attempts to use the Sound Manager, it’s likely to crash the Mac®. This includes SysBeep (in System 6.0 and later, SysBeep calls the Sound Manager). For this reason, your application should close its sound channel when it receives a “suspend” event and when it terminates.
In systems without an Apple Sound Chip (the Macintosh Plus and SE), the Sound Manager will either skip or repeat bytes, based on the sample and playback rates. If you use a buffer size that is a multiple of 370 bytes and the bufferCmd, the clicking will be minimized, because the Sound Manager keeps an internal 370-byte buffer. This is all documented in the new Sound Manager documentation. You don’t need to use a VBL task (as Tech Note #19 suggests) when using the Sound Manager—simply call the bufferCmd for every chunk of data. The Sound Manager maintains a queue of all the commands. If 128 commands aren’t enough, you can use the callBackCmd to find out when your last command was processed, or you can create your own sound channel and increase the number of commands held in its queue.
Toolbox & IAC: Sound Manager: Specifying different frequencies for the Macintosh Note Synth
How do I specify different frequencies for the Macintosh® Note Synth?
The Note Synth sample code on page 484 of Inside Macintosh Volume V is incorrect. You should follow the 'snd ' method described on page 492. The pitch value should be specified in decimal notation as explained on page 483. Also note that the interface files shipped with pre-3.0 releases of MPW® may be incorrect. The following code produces a note:
{ Warning -- no error checking done here }
{ The NoteSynth = 1 }
Procedure DoSound;
VAR
myErr : osErr;
amp, pitch : LONGINT;
myChannel : sndChannelPtr;
myCmd : sndCommand;
BEGIN
amp := $FF000000;
pitch := 60;
myChannel := NIL;
WITH myCmd DO BEGIN
cmd := noteCmd;
param1 := 1000;
param2 := amp + pitch;
END;
myErr := SndNewChannel(myChannel, 1, 0, NIL);
myErr := SndDoImmediate(myChannel, myCmd);
myErr := SndDisposeChannel(myChannel, TRUE);
END;
Toolbox & IAC: Sound Manager: Changing the pitch of a sample in Macintosh Sound Manager
How do I specify different pitches for the sampled sound synthesizer of the Macintosh® Sound Manager?
If you want to change the pitch of a sample, change the sample rate. (The baseNote field is only used internally by the Sound Manager.) You can change the sample rate in the sample 'snd ' and play it back at any rate.
Toolbox & IAC: Sound Manager: How can I play more than one Macintosh sample at a time?
How can I play more than one Macintosh® sample at a time?
Unfortunately, the Sound Manager can play only one sample at a time. A basic limitation of the Sound Manager is that it only allows a single channel open with the sampled sound 'snth' and the note 'snth.' The wave table 'snth' allows up to four channels at a time, but doesn’t provide the same capabilities as the sampled sound 'snth.'
You can build chords yourself and play them through a single channel, which is essentially what the Apple IIGS® does.
Toolbox & IAC: Sound Manager: Why Macintosh system crashes when StartSound is launched twice
My Macintosh® application calls StartSound when it starts. The second time it is launched the system hangs. Why?
A bug in the InitApplZone trap is the cause of the bomb at the second launch. To avoid the problem, simply call StopSound before exiting the program. It is also a good idea to call StopSound before calling StartSound, in case another program called StartSound but never called StopSound. The “glue” in MPW® 2.0.2 and later versions fixes this problem.
Toolbox & IAC: Sound Utilities: Sound Input Manager sample code using SPBRecordToFile
Do you have any sample code showing how to use the System 7 Sound Input Manager to record asynchronously to disk?
The sample code below shows how to use the low-level sound input calls to record asynchronously to a disk file. The sample uses SPBRecordToFile to fill in an already-created sound file with new data.
*****************
#include <Quickdraw.h>
#include <Windows.h>
#include <dialogs.h>
#include <Files.h>
#include <Packages.h>
#include <OSEvents.h>
#include <Memory.h>
#include <Sound.h>
#include <SoundInput.h>
#include <OSUtils.h>
#define TRUE 0xFF
#define FALSE 0
typedef struct {
short OnOff;
short Level;
} Level;
pascal void MyRecComp (SPBPtr inParamPtr);
main()
{
Point where = {20,20};
SFReply reply;
short SomeRefNum;
char* string;
Level myLevel;
OSErr err;
SPBPtr RecordRec;
long SoundRefNum;
long totalMilRecord;
ParmBlkPtr paramBlock;
InitGraf(&qd.thePort);
FlushEvents(everyEvent, 0);
InitWindows();
InitDialogs(nil);
InitCursor();
string = (char*) "\pPick an SND File";
SFGetFile (where, (Str255) string, nil, -1, (SFTypeList) nil,
nil, &reply);
err = FSOpen(reply.fName, reply.vRefNum, &SomeRefNum);
if (err != noErr)
Debugger();
err = SetupAIFFHeader (SomeRefNum, 1, 0x56EE8BA3, 8, 'NONE',
0, 0);
if (err != noErr)
Debugger();
err = SPBOpenDevice ('', siWritePermission, &SoundRefNum);
if (err != noErr)
Debugger();
myLevel.OnOff = 1;
myLevel.Level = 0;
err = SPBSetDeviceInfo (SoundRefNum,siTwosComplementOnOff, (Ptr)
&myLevel);
if (err != noErr)
Debugger();
RecordRec = (SPBPtr) NewPtr(sizeof (SPB));
if (MemError() != noErr || RecordRec == nil)
Debugger();
RecordRec->inRefNum = SoundRefNum;
RecordRec->count = 0;
RecordRec->milliseconds = 15000;
RecordRec->bufferLength = 0;
RecordRec->bufferPtr = nil;
RecordRec->completionRoutine = (ProcPtr) MyRecComp;
RecordRec->interruptRoutine = nil;
RecordRec->userLong = 0;
RecordRec->error = 0;
RecordRec->unused1 = 0;
err = SPBRecordToFile (SomeRefNum, RecordRec, TRUE);
if (err != noErr)
Debugger();
do {
} while (RecordRec->userLong == 0);
totalMilRecord = 15000;
err = SPBMillisecondsToBytes(SoundRefNum, &totalMilRecord);
if (err != noErr)
Debugger();
paramBlock = (ParmBlkPtr) NewPtr(sizeof (IOParam));
if (MemError() != noErr || paramBlock == nil)
Debugger();
paramBlock->ioParam.ioRefNum = SomeRefNum;
paramBlock->ioParam.ioPosMode = 1;
paramBlock->ioParam.ioPosOffset = 0;
err = PBSetFPos(paramBlock, FALSE);
if (err != noErr)
Debugger();
err = SetupAIFFHeader (SomeRefNum, 1, 0x56EE8BA3, 8, 'NONE',
totalMilRecord, 0);
if (err != noErr)
Debugger();
SPBCloseDevice (SoundRefNum);
DisposePtr ((Ptr) RecordRec);
err = SndStartFilePlay (nil, SomeRefNum, 0, 74000, nil, nil,
nil, FALSE);
if (err != noErr)
Debugger();
FSClose (SomeRefNum);
}
/**********************************/
pascal void MyRecComp (SPBPtr inParamPtr)
{
inParamPtr->userLong = 1;
return;
}
/**********************************/
Toolbox & IAC: Sound Utilities: Macintosh System 6.0.5/MACE problem fixed for 6.0.7
After playing a MACE-compressed sound several times under System 6.0.5, my Macintosh® SE eventually hangs. The same code works fine under System 6.0.4 and System 6.0.7. Do you have any clues as to what is causing this?
MACE was shipped originally as a strange hack to System 6.0.4. It was not revised for System 6.0.5 and as a result, it has never worked under 6.0.5. In System 6.0.7, MACE became part of the Sound Manager, so it should work fine on all systems from 6.0.7 on. Unfortunately, it is not going to ever work under 6.0.5.
Toolbox & IAC: Sound Utilities: How to get MACE algorithms
What are the Macintosh® Audio Compression & Expansion (MACE) algorithms that will allow me to translate the compressed digitized audio from my device into compressed 'snd ' resource format?
The MACE algorithms are proprietary, but they are licensable. Contact Apple’s Software Licensing department for more information. You can reach them at (408) 996-1010 or at AppleLink® SW.LICENSE.
Toolbox & IAC: Sound Utilities: Tools to compress and expand Macintosh sound
Are there any tools for compressing Macintosh® sounds? Does MACE offer any way of decompressing a sound resource to a RAM buffer so a program can mess with the raw sound data before playing the resource?
Code samples in the MACE documentation, available from APDA®, show how to write a routine to compress and expand sampled sounds.
Toolbox & IAC: Sound Utilities: “Begin” calls needed for Apple IIGS ACE compression & expansion
Apple IIGS® ACE compression and expansion don’t work consistently for me. I can compress (or expand) one sound correctly, but the next time I try it the results are all wrong. What gives?
You forgot to call ACECompBegin or ACEExpBegin between different compressions or expansions. ACE maintains information on the current operation in its direct page space to allow you to do multipart expansions or compressions. When you start working with a new sound sample, you have to call either ACECompBegin or ACEExpBegin to inform ACE that you’re starting a new operation, and all the internal data should be reset. More information can be found in the ACE chapter of the Apple IIGS Toolbox Reference, Volume 3.
Toolbox & IAC: TextEdit: Resizing a Macintosh edit field for TEPaste
I have a small edit field and when I call TEPaste, the edit field contents scroll up. How can I calculate what the height of the edit field would be after the paste, resize the edit field to be that size, and then do the paste?
There are a couple of ways to implement this:
Method #1:
1. Set the clip region to something other than the viewRect of the edit field. 2. Call TEPaste or TEStylPaste to insert the clipboard text.
3. Call TEGetHeight to get the new height of the text.
4. Set the viewRect of the TERec to the new height. Call TECalText for good measure (and good lineStarts).
5. Finally, set the clip region back to normal and call TEUpdate.
Method#2:
1. Call TENew or TEStylNew to allocate a brand spankin’ new temporary TERec, and give it a viewRect and destRect that’s off the screen but that has the same width as the original TERec.
2. Next, copy the hText handle of the window’s TERec into the hText field of the temporary TERec (Good job for BlockMove [IM II-44]).
3. Call TECalText and TEActivate on it; then paste the clipboard text into the temporary TERec. Since the view and dest Rects are off the screen, none of this will be seen by the user.
4. Call TEGetHeight to get the new height, then copy the text back into the original TERec.
5. Finally, call TECalText, then TEUpdate and TEActivate on the original TERec.
Method #1 has less overhead and is a little easier to implement. However, if you have any custom hooks installed in your TERec, then you probably want to let TextEdit do as much of the work as possible. In this case, method #2 is a better way.
Toolbox & IAC: TextEdit: Dimming and disabling a specific TEditText object
How can I dim and disable a specific TEditText object in my TDialogView so the field is not editable?
The trick is to use the TView methods Dimstate and ViewEnable to disable and dim the TEditText Views, and then do a TEditText.StopEdit (which disables editing in the TEditText box), and in the other case enable dimming and the view itself and use the TEditText.StartEdit (which enables editing in the TEditText box), as shown in the C++ example below:
anEditText2->DimState(TRUE,kDontRedraw); // disable
anEditText2->ViewEnable(FALSE,kRedraw);
anEditText2->StopEdit();
anEditText1->DimState(FALSE,kDontRedraw); // enable
anEditText1->ViewEnable(TRUE,kRedraw);
anEditText1->StartEdit(TRUE,fTEView);
MacApp sample code using this technique is included with DTS’s Snippets files.
Toolbox & IAC: TextEdit: Macintosh SetClikLoop procedure and TERec clikLoop field
I have had some problems with the SetClikLoop procedure which don’t appear when I set the clikLoop field directly (in C). Why does TextEdit’s SetClikLoop procedure create a special procedure to call my clikLoop routine, rather that just installing the clikLoop directly? Inside Macintosh says you can set the clikLoop field directly in assembly. Why not in C?
The short answer is that the special procedure is a glue routine for shuttling a result between the stack and the register D0. The larger question is why does installing clikLoop directly work? C, I think, is the culprit.
But, before I get ahead of myself, let me explain the SetClikLoop procedure. As you know, the click loop routine has no parameters but it does return a Boolean result (IM I-380).
FUNCTION MyClikLoop : Boolean; { Pascal declaration }
pascal Boolean MyClikLoop(); { C declaration }
Now, MyClikLoop is called by the TextEdit Manager from inside the TEClick routine. The way the code was written, TEClick expects to get the Boolean result from D0. For assembly programmers, this is no problem. In Pascal, the return value is placed on the stack. So, D0 does not contain your routines’ Boolean and what TEClick grabs will be “who knows what” and your program should crash. SetClikLoop will install a glue routine which calls MyClikLoop. The glue routine will move the result from the stack to D0. By the way, this information is documented on pages 237-238 of Volume Two of Macintosh® Revealed, Second Edition, by Stephen Chernicoff.
Now why is your program causing problems when you use SetClikLoop? You might have declared your MyClikLoop as a C function. Since MyClikLoop takes no parameters, nothing is put on the stack. But C, unlike Pascal, places its return value in D0. So, for C, the glue routine is not needed. On the other hand, if you use the SetClikLoop routine with a C routine, you will take the top two bytes off the stack and clobber D0 with the wrong answer. Thus, you might get problems.
Though the C routine may work by setting it directly to the clikLoop field, doing it that way is not the supported method. You should declare your MyClikLoop function as a Pascal function and use SetClikLoop.
Toolbox & IAC: TextEdit: Special handling for Control-P keyboard input in a Mac dialog
Under System 6, when Control-P is pressed, a DLE character (hex 10) appears in a Macintosh® dialog’s editText field. Under System 7, pressing Control-P produces no change in the editText box. The character is fed in via a normal (unaltered) keyDown event fed to DialogSelect. Does Control-P have some special meaning to DialogSelect or TextEdit now?
Believe it or not, and it took several of us scratching our heads to figure this out; yes, it does, and this is by design! What you are running into is the Dialog Manager and TextEdit working together to make Cut, Copy, and Paste function keys work on an extended keyboard. The function keys on the top of an extended keyboard return $10 as their ASCII keycode. Thus, when TEKey detects that it is being called from dialog select, and the key you pass is a $10, it then looks for the event record on the stack and gets the raw keycode to determine which edit operation to perform. The bottom line is that it will not then enter the $10 in the edit field.
There is a simple workaround, and that is to install a filter proc in your dialog that detects keystrokes (actually it could always just look for this certain keystroke) and passes them to TEKey itself, thus skirting the whole issue.
Toolbox & IAC: TextEdit: How to handle typed password in Macintosh dialog box
In my Macintosh® dialog box, I have an editable text box where the password is typed in. What I need to do is encode the outgoing text characters so that the text string will contain the correct letters, but the display on the screen will show a bunch of zeroes or something.
A good way to handle the typing of passwords is to have two editable text fields: one that the user sees (and that you fill with “*”s in response to typed characters) and one that is outside the dialogs window that actually is being typed into. You will need to watch each tab and mouse click that is returned to you from modal dialog to make sure you reset the current text pointer to the hidden field. On a backspace character, delete one * from the dummy field. On allowed characters add one *. Even if it wasn’t a problem for this method, it is a bad idea to allow selection editing of blind (****) text as the user has no idea if there are any typos to begin with. You might even want to throw out the entire password on a backspace, like AppleLink® does.
Toolbox & IAC: TextEdit: IIGS TextEdit key filter proc opReplaceText’s theInputHandle
In using an Apple IIGS® TextEdit key filter procedure’s opReplaceText command, should I modify theInputHandle’s contents or should I allocate a new handle?
TextEdit expects you to change the contents of theInputHandle—don't dispose of it or create a new one.
Toolbox & IAC: TextEdit: Apple IIGS TextEdit TESetText redraws controls and records
Our Apple IIGS® TextEdit field created with NewControl2 appears to be redrawn within the TESetText call, but Apple IIGS Toolbox Reference Volume 3 says controls won’t be redrawn until the next update event. Is this a mistake in the documentation or in our logic?
Internally, TextEdit uses control records for all TextEdit records. The main difference between control and noncontrol records is that the control defproc handles many of the standard TextEdit functions without requiring your application to do so. In the case of TESetText, though, TextEdit will always redraw the entire viewRect. This is a mistake in the manual.
Toolbox & IAC: TextEdit: filterProc address with Apple IIGS TextEdit control template
When I write an Apple IIGS® TextEdit keyFilter procedure and put its address in my TextEdit control template, I get funny little pieces of garbage drawn on the screen in my TextEdit record, and sometimes TextEdit crashes. Doesn’t the keyFilter mechanism work?
The keyFilter mechanism in TextEdit works, but there’s no space for a keyFilter address in a TextEdit control template. The only filter procedure in the control template is the generic filter procedure, which does not take the same parameters as the keyFilter procedure. If you include a filterProc address in a TextEdit control template, it must be to a generic filter procedure. Generic filter procedures are defined on pages 49-16 through 49-18 of Apple IIGS Toolbox Reference Volume 3.
If you want to use TextEdit’s keystroke filter, word wrap hook, or word break hook, you must modify the TERecord directly to put your procedure’s address in the appropriate place.
Toolbox & IAC: TextEdit: Saving and restoring styled Macintosh TextEdit records
How do I save and restore Macintosh® records created with TextEdit that contain styles? Where can I find additional information or sample code?
There’s no standard for saving text with styles created by TextEdit, so all we can offer is a recommendation that’s modeled after the way that TECopy works on styled text. In styled TextEdit, the style information is stored separately from the text rather than embedded within it. TECopy maintains this separation when styled text is copied, so our recommendation maintains this separation, too.
To save the text part, you could make a file of type TEXT and save the text in the data fork of the file, like TeachText does. You could also save it in a resource of type TEXT.
The best way to save the style information is to use the StScrpRec record. Other records used by styled TextEdit contain references to other structures or they contain only a part of the style information, and that makes saving them awkward. The StScrpRec doesn’t contain references to any other structures, and it contains enough information to rebuild the entire tree of TextEdit structures. When you call TECopy on styled text, both a 'TEXT' and 'styl' scrap type is placed into the desk scrap. The 'TEXT' type just contains the text. The 'styl' type contains a StScrpRec containing all of the style information for the copied text. TextEdit doesn’t maintain a StScrpRec for the entire text buffer, so you have to tell TextEdit to do this for you when you’re ready to save the style information.
Fortunately, one call does it all. Inside Macintosh, Volume V, page 268, documents the GetStylScrap routine. It creates a new StScrpRec record, places all the style information of the selected text into it, and returns a handle to this StScrpRec. First, select the text you want to save either by calling TESetSelect or by setting the selStart and selEnd fields of the TextEdit record if you don’t want the selection to be visible to the user. (If you do this, remember to restore the old values of selStart and selEnd after you get the StScrpHandle.) Next, call GetStylScrap to construct the StScrpRec. You can now save the resulting StScrpRec, perhaps in a resource of type 'styl' or in whatever way you see fit.
Reading the text and styles back into a TextEdit record isn’t much more complicated. First, read the text back into a buffer and read the 'styl' resource (or however you saved it) into a StScrpRec. Create a styled TextEdit record (or use an old one), then call TEStylInsert, passing it a pointer to the text buffer and a handle to the StScrpRec. Your TextEdit record should then contain and display your original styled text. That’s all!
Toolbox & IAC: TextEdit: How to tell if an Apple IIGS TextEdit record has been changed
Can I tell if an Apple IIGS® TextEdit record has changed?
TextEdit maintains a “dirty flag” in bit six ($40) of the flags field (not the moreFlags or the textFlags fields). This bit is cleared when a TextEdit record is created and is set when the TextEdit record is changed. The flags field is byte $0010 in the TextEdit record (or the control record if using TextEdit controls).
Toolbox & IAC: Tool Locator (AII): Patching Apple IIGS tools
After patching the Apple IIGS® Control Manager’s TrackControl call, using GetTSPtr, SetTSPtr, and SetDefaultTPT, some Control Manager calls don’t work on ROM 03 systems. We know Apple doesn’t recommend patching tools, but our utility needs to know if TrackControl has been called, so the patch is absolutely necessary.
You that should never patch any Apple-provided toolset. This is always considered a bad idea. Also, if you do patch a system provided tool, you must only patch it while your application is running and at no other time. And, if you do permanently patch a system toolset, you should take special care to inform the user in your documentation ahead of time so that they will be able to decide if they want to install and run your software.
Having said all that, here is the proper way to patch a tool set on the Apple IIGS. Call GetTSPtr, and create a new fixed handle of a proper size to contain the table. Set the size of the table and zero out the rest. Now add new function pointers for the routines you want to patch. Lastly, always patch the bootinit function of the tool to a nop routine. This way the tool’s bootinit will not be called again. Call SetTSPtr. NEVER call SetDefaultTPT! The reason that you should not do this is that you do not know if the tool you are patching is in ROM or RAM. If you call SetDefaultTPT you will cause the Tool Pointer Table (TPT) to have pointers to your functions when the next application is launched.
To summarize, keep these handy hints in mind:
• Before patching any toolset, determine its version and be sure that it is a version you recognize. Future versions may not work exactly the same way, and your application should not patch any version it doesn’t recognize.
• Never call SetDefaultTPT on a RAM-based toolset, only on ROM-based toolset. If you must alter the behavior of a RAM-based toolset you will have to load the tool at init time, make your changes and then call SetDefaultTPT.
• NEVER “tail patch” a ROM-based tool call. This means modifying the return address or the stack contents before calling Apple’s routine to perform the desired function. Also…
• ALWAYS call the Real toolset function whenever you patch a tool call (ROM or RAM based), because…
• The above two rules must always be followed with no exceptions because Apple applies patches to several ROM routines by patching tool calls that these ROM routines might call. For this reason, the return address on the stack must be preserved because this is how the system software identifies that the patch must be applied. Also, since some patches require the modification of data much higher on the stack, or the examination of a return address higher on the stack, you must never change the stack level when passing control to system routines. If you break these rules you may disable patches installed by apple to fix bugs in the ROM and cause the system to crash.
• Thus, with all the above rules in mind, really, never patch a system-provided toolset and try to find an alternative.
Toolbox & IAC: Tool Locator (AII): Apple IIGS Message Center and global variables
Can we use the Apple IIGS® Message Center for global variables in our application? If so, would exporting variables affect Message Center performance?
The Message Center is implemented (as you can easily guess) as a linked list of handles. Therefore search time is linear, so a 100-message center takes twice as long to search (fully) as a 50-message center. This will slow down the performance of the Message Center considerably. Future system software makes more extensive use of the Message Center as well, so this could bog down the entire system.
The Message Center is designed for communication between applications, not to be a globals segment equivalent. You should find some other way to communicate your variables with your components, such as one message with a handle to a globals segment, where each variable has its name and then its value.
Toolbox & IAC: Tool Locator (AII): Use Apple IIGS MessageByName for function callback
How can we implement an Apple IIGS® function callback through the ProDOS® $e100a8 vector, much as APW™ does with its $1xx-series commands?
Apple does not recommend patching system vectors because you can now produce the same result using MessageByName to publish your own address. Simply create a message with your application’s name and other necessary information at launch time and put the address of your callback code into that address, so that you can publish it without having to patch anything.
Toolbox & IAC: Tool Locator (AII): Apple IIGS MessageCenter type assignments
Where do I find a current list of the Apple IIGS® MessageCenter message types that have been registered with DTS?
Message types that are assigned to individual developers are treated confidentially. We have very few of these, as most developers now use MessageByName to get an assignment dynamically.
Toolbox & IAC: Tool Locator (AII): Where to find information on Apple IIGS public message types
Where do I find technical documentation on the messages written by the Finder™ to tell an Apple IIGS® application which files to open as it starts up?
The only truly public message types are #1 (the files message from the Finder or other program launchers) and #2 (the desktop pattern message).
Message type #1 is documented in Apple IIGS Toolbox Reference Volume 2, with the description of the MessageCenter tool call. The documentation implies that there are both filenames and full pathnames (such as Standard File returns) in the message, but, in fact, each Pascal string indicates a totally separate file. Message type #2 is documented in Apple IIGS Toolbox Reference Volume 3, in the “Window Manager Update” chapter (page 52-4).
Toolbox & IAC: Window Manager: How the system WDEF determines color
We’re using wctb 0 and cctb 0 of the system so our WDEF and CDEF will be 7.0 friendly. Macintosh Technical Note #298 specifies the use of all the wctb table components, but in cases such as the title bar background and scroll bars, it states that colors are generated algorithmically without specifying the algorithm.What is the algorithm? Is it safe to assume that it’s 50% of the light and dark components of the resource?
A newer version of the Tech Note describes the way the system WDEF determines color. The trick is to use GetGray to determine the color from the two extremes available in the color table for the monitor on which the window is going to appear. GetGray is described in the Color QuickDraw section of Inside Macintosh Volume VI. The latest Developer CD Series disc has the system WDEF, which could help you in your work. The path to the file is Dev CD VIII: Tools & Apps (Moof!):OS/Toolbox: System 7 WDEF.
Toolbox & IAC: Window Manager: Implementing Macintosh floating windows or palettes
We’re having a lot of trouble with our floating palette which uses the global variable GhostWindow documented in Inside Macintosh® Volume I. What’s the best way to implement a floating palette?
There is no easy, built in, and supported way to do floating windows/palettes on the Macintosh. None of the solutions available are particularly elegant, but they do work.
Using the GhostWindow low-memory global to do floating windows is not a good idea, mostly because it’s a low-memory global, but also because it only allows one “floating” window in an application.
A solution that should work well for you, but it is not incredibly elegant, is to write “wrapper” functions for the Window Manager functions. Basically, your application doesn’t call many of the Window Manager functions (BringToFront/FrontWindow/MoveWindow) but instead calls routines that keep track of where the floating windows are, and how to keep them in front.
MacTutor has had a couple of good articles on this topic:
• “Tear-off Menus & Floating Palettes,” by Don Melton and Mike Ritter (MacTutor 4:4), describes how to do tear-off menus and turn them into floating palettes.
• “Tool Window Manager,” by Thomas Fruin (MacTutor 4:12), gives source (in C) to a new “window manager” which handles floaters the correct way through wrapper functions.
Toolbox & IAC: Window Manager: How to determine Mac window title bar height for localization
How can my application determine a window title bar’s height in pixels? Is there a method similar to reading the global MBarHeight ($BAA) for the menu bar height?
While the menu bar height can be easily found, determining the title bar height requires some effort. You are right to be concerned about the matter, as international versions of the system software may have various sizes of title bars.
In a nutshell, you need to find the difference between the top of the rectangle of the window’s content area, which is below the title bar, and the top of its structure region. Be aware that the window has to be visible for its structure rect to be valid. Given those, you can make your decision on where to place the window.
To get a better idea on how to implement these, take a look at the procedures pasted below. They are taken from DTS.Utilities in the Sample Code folder on the System 7 Golden Master CD (which includes a wide variety of other basic, useful routines as well). Or more directly, here’s an excerpt based on the DoWZoom routine in Macintosh® Technical Note #79, which includes the title bar height in its calculations:
GetPort(savePort);
SetPort(window);
windRect :=window^.portrect;
LocalToGlobal(windRect.topLeft);
LocalToGlobal(windRect.botRight);
titleHeight := windRect.top - WindowPeek(window)^.strucRgn^^.rgnBBox.top;
SetPort(savePort);
{ excerpted from DTS.Utilities:Utilities.inc1.p }
FUNCTION CenterWindow(window:WindowPtr; relatedWindow:WindowPtr): Rect;
{ Center a window within a particular device. The device to
center the window within is determined by passing a related
window. This allows related windows to be kept on the same
device. This is useful if an alert related to a specific
window, for example. }
VAR
whichDevice: WindowPtr;
deviceRect, oldWindowRect, newWindowRect, contentRect: Rect;
BEGIN
whichDevice := relatedWindow;
if whichDevice = NIL THEN
whichDevice := window;
{ If we have a window to center against, use the device for
that window, else use the device for the window that is
getting centered. }
deviceRect := GetWindowDeviceRectNMB(whichDevice);
{ We now have the rectangle of the device we want to
center within. }
newWindowRect := GetWindowStructureRect(window);
oldWindowRect := newWindowRect;
PositionRectInRect(deviceRect, newWindowRect, FixRatio (1, 2),
FixRatio (1, 3));
{ Figure out the new window strucRect so we can compare
it against the old strucRect. This will tell us how
much to move the window }
contentRect := GetWindowContentRect(window);
{ Get where the window is now. }
OffsetRect(contentRect, newWindowRect.left - oldWindowRect.left,
newWindowRect.top - oldWindowRect.top);
{ Calculate the new content rect. }
MoveWindow(window, contentRect.left, contentRect.top, false);
{ Move the window to the new location. }
CenterWindow := contentRect;
END;
FUNCTION GetWindowContentRect(window:WindowPtr):Rect;
{ Given a window pointer, return the global rectangle that encloses the
content area of the window. }
VAR
oldPort: WindowPtr;
contentRect: Rect;
BEGIN
GetPort(oldPort);
SetPort(window);
contentRect := window^.portRect;
LocalToGlobalRect(contentRect);
SetPort(oldPort);
GetWindowContentRect := contentRect;
END;
FUNCTION GetWindowStructureRect(window:WindowPtr):Rect;
{ This procedure is used to get the rectangle that surrounds
the entire structure of a window. This is true whether or
not the window is visible. If the window is visible, then
it is a simple matter of using the bounding rectangle of the
structure region. If the window is invisible, then the
strucRgn is not correct. To make it correct, then window has
to be moved way off the screen and then made visible. This
generates a valid strucRgn, although it is valid for the
position that is way off the screen. It still needs to be offset
back into the original position. Once the bounding rectangle
for the strucRgn is obtained, the window can then be hidden
again and moved back to its correct location. Note that
ShowHide is used, instead of ShowWindow and HideWindow.
HideWindow can change the plane of the window. Also, ShowHide
does not affect the hiliting of windows. }
VAR
oldPort: GrafPtr;
structureRect: Rect;
windowLoc: Point;
BEGIN
if WindowPeek(window)^.visible = true THEN
structureRect := WindowPeek(window)^.strucRgn^^.rgnBBox
ELSE BEGIN
GetPort(oldPort);
SetPort(window);
windowLoc := GetGlobalTopLeft(window);
MoveWindow(window, windowLoc.h, kOffscreenLoc, false);
ShowHide(window, true);
structureRect := WindowPeek(window)^.strucRgn^^.rgnBBox;
ShowHide(window, false);
MoveWindow(window, windowLoc.h, windowLoc.v, false);
SetPort(oldPort);
OffsetRect(structureRect, 0, windowLoc.v - kOffscreenLoc);
END;
GetWindowStructureRect := structureRect;
END;
Toolbox & IAC: Window Manager: Code for implementing a Macintosh grow box but not scroll bars
How do I draw a Macintosh® grow box without the scroll bars? In the past I avoided having the scroll bars by calling PenSize(-1, -1), which effectively turns off the drawing of the scroll bar lines, and then calling PenNormal, but this trick doesn’t work in System 7.
There is a very simple way to do this: Change the clipping region of the window before you call DrawGrowIcon. Make sure you save the old clipping region or all heck will break loose. Here’s a little routine that you can replace calls to DrawGrowIcon with:
#define kGrowBoxWidth 15
void MyDrawGrowIcon(WindowPtr window)
{
GrafPtr savePort;
RgnHandle saveRgn;
Rect growRect;
GetPort(&savePort);
SetPort(window);
growRect = window->portRect;
growRect.top = growRect.bottom - kGrowBoxWidth;
growRect.left = growRect.right - kGrowBoxWidth;
saveRgn = NewRgn();
GetClip(saveRgn);
ClipRect(&growRect);
DrawGrowIcon(window);
SetClip(saveRgn);
DisposeRgn(saveRgn);
SetPort(savePort);
DrawGrowIcon(window);
}
Just paste this code into your code and replace all calls to DrawGrowIcon with MyDrawGrowIcon.
Toolbox & IAC: Window Manager: Macintosh tool palette windoid reference
Do you have any sample code or WDEFs for Macintosh® tool palette windoids?
Floating windows or windoids are not supported by Apple’s system software. The best example has been published in the MacTutor article of April and May in 1988. (It’s reprinted in The Definitive MacTutor, Volume 4, entitled “Tool Window Manager.”) Its limitation is that it will only support a single window. There are also problem when using color QuickDraw regarding the Palette Manager, and we have not seen a good solution.
Unfortunately, no standard WDEF has been issued by Apple, nor have standards been set for appearance and characteristics of floating windows. Those may be available in the future, but we presently have no guidelines.
Toolbox & IAC: Window Manager: Apple IIGS TaskMaster and MultiClick information
How does Apple IIGS® TaskMaster return MultiClick information?
MultiClick information is passed back to the application in the wmClickCount field of the task record, at offset 0x1C. The field contains 0, 1, 2 or 3, depending on the click count, but it’s actually not as sophisticated as you may think. TaskMaster merely increments this field on a mouse click (if the last action was a click). You must clear the field after using it. For example, if you’re concerned about double clicks, keep checking that field. When it reads 2, you know a double click has happened, and you can process it.
Set the field to 0 during the processing. This is necessary because the field will not be cleared if the next event is an update, key, or any nonmouse-type event, and your event loop could get confused.
Read the wmClickCount field and clear it after something relevant happens and you process it. Of course, you also must set bit 19 (tmMultiClick) of the taskMask to tell TaskMaster to update the field.