December 92 - MACINTOSH Q & A
MACINTOSH Q & A
MACINTOSH DEVLOPER TECHNICAL SUPPORT
Q Here's a tidbit I stumbled across in Inside Macintosh Volume VI, page 3-10: the four
Dialog Manager procedures CouldDialog, CouldAlert, FreeDialog, and FreeAlert are no
longer supported. I use CouldDialog, and I happened to notice that it didn't work right
when I tested it under System 7, but I reported it as a bug. Now you tell us that it's not
guaranteed to work in System 7. I can't recall a trap ever becoming suddenly
unsupported like this. What's the story?
A The system software engineers felt that CouldDialog, CouldAlert, FreeDialog, and
FreeAlert didn't do much good under System 6, since the Could calls never completely
guaranteed that all dialog items were loaded in. These calls also caused problems in the
beta versions of System 7. Relatively little software uses those traps anymore; like
many things in Inside Macintosh Volume I, they're relics of the days when Macintosh
programmers had to deal with desk accessory and floppy disk support issues. So these
calls were simply patched out. In the final System 7, the traps return without doing
anything.
Q I can't get the black-and-white version of my lasso-type tool to work correctly with
CalcMask and CopyMask. With CalcCMask it seems to work fine. What could I be doing
wrong?
A CalcMask and CalcCMask are similar in that they both generate a one-bit mask
given a source bitmap. With CalcCMask, though, a pixMap can be used in place of the
source bitmap; the seedRGB determines which color sets the bits in the mask image. An
easy mistake to make is to forget that CalcCMask expects a pointer to a BitMap data
structure while CalcMask expects a pointer to the actual bit image. And unlike
CalcCMask, which uses bounding rectangles for the image's dimensions, CalcMask uses
the bitmap's rowBytes and pixel image offsets to determine the bounding Rects for the
image. A typical call to these routines is as follows:
BitMap source, mask;
CalcMask (source.baseAddr, mask.baseAddr, source.rowBytes,
mask.rowBytes, source.bounds.bottom-source.bounds.top,
source.rowBytes>>1);
CalcCMask (&source, &mask, &(*source).bounds, &(*mask).bounds,
&seedRGB, nil, 0);
One last thing to note when using CalcMask is that the width of the image is in words
and not bytes. To learn more about these routines, see page 24 of Inside Macintosh
Volume IV and page 72 of Inside Macintosh Volume V. Also, the Developer CD Series
disc contains a sample, CalcCMask&CalcMask, that shows how to use these routines.
Q How do I update the color table of my off-screen graphics world without destroying
the picture?
A The recommended approach for changing the color table of an existing GWorld
involves calling UpdateGWorld, passing either clipPix or stretchPix for gWorldFlags.
When passed either of these constants, QuickDraw knows to update the pixels of the
pixMap image. Even though the actual image isn't changed, the flags are still needed to
remap the pixels to their new colors.
Q Are there any C++ or C compilation flags that will optimize performance of the
Macintosh Quadra computers? Even when I use the "-NeedsMC68030" flag in MacApp,
an investigation of the MABuild source files reveals that it sets compiler flags only for
the 68020 optimization. If Quadra-specific compilation flags don't exist, do you have
any Quadra performance optimization suggestions?
A The current MPW compilers don't have a 68040 performance optimization flag,
though Apple's future compilers will optimize code for the best possible '040
performance. In the meantime, here are some tips on '040 performance tuning:
• Cache management for the '040 can give you the biggest performance
boost. Keep program loops inside the cache space, and flush the cache as seldom
as possible. In most cases you'll have small loops inside the 4K instruction
cache.
• You might get better performance by not calling BlockMove, because the
system flushes the cache when you call it in case you're moving code. If you're
moving data, the cache doesn't need to be flushed, but the system can't tell
from the BlockMove call whether you're moving code or data. Testing will help
you determine whether you should call BlockMove or write your own transfer
routine. The new MOVE16 opcode is used by the BlockMove trap when the
system is running on an '040 processor, but because of problems with this
opcode in early '040 processors, it requires special handling. For details, see
the Macintosh Technical Note "Cache As Cache Can" (formerly #261).
• Transcendental functions aren't implemented in the 68040 hardware as
they are in the 68881 chip used with the 68020 and 68030. Consequently,
the functions are emulated in software, resulting in slower performance. If
you suspect that your floating point performance is less than optimal,
consider modifying your code to use functions supported by the internal '040
FPU. See the Macintosh Technical Note "FPU Operations on Macintosh Quadra
Computers" (formerly #317) for more information about this performance
factor. Future MPW compiler and library releases will support faster
transcendental operations and floating point-to-integer conversions.
Q In the past we had heard of a problem using calloc and NewPtr in the same program.
Is this true?
A There are a few difficulties, which you can deal with if you need to. The primary
problem is that calloc and all the other malloc routines weren't designed for the
Macintosh platform. Macintosh memory management is designed around trying to
squeeze as much as possible out of a limited memory area, which is why handles are
the primary storage scheme in a Macintosh; they can move, and so greatly reduce
memory fragmentation. Because the malloc tools return a pointer, they have to be
located in a locked block, so they tend to lead to fragmentation if used with any other
memory allocation calls (such as NewPtr). For this reason, any use of the malloc suite
of allocation calls isn't recommended for Macintosh programs. The only good reason to
use them is if you're porting a large body of code from other platforms; in this case, it
may be a reasonable tradeoff to keep the old allocation code.
You should also be aware that most of the Macintosh malloc routines never free up
memory. When you malloc some space, the routine must first allocate it from the
Memory Manager. It allocates a large block of space using NewPtr and divides it
internally for distribution in response to malloc calls. If, however, you eventually
free all the blocks you allocated from this NewPtr block, the block won't be released to
the Memory Manager with the DisposPtr call. This means that once you allocate some
memory with malloc, you won't be able to free it and then use that memory from a
Macintosh allocation call. Thus, if you had two phases to your program, one of which
used the malloc calls extensively and the second which used Toolbox calls, the second
phase wouldn't be able to use memory freed by the first phase. That memory is still
available in the malloc pool, of course; it simply can't be used by NewPtr or
NewHandle. The malloc routines supplied by THINK C work similarly, as described in
their Standard Libraries Reference . Thus, mixing the C and Macintosh allocation
routines requires special care.
Q Why do I get error -903 (a PPC Toolbox noPortErr) when I send an Apple event to a
running application with AESend?
A The isHighLevelEventAware bit of the sending application's SIZE -1 resource (and
SIZE 0 resource, if any) must be set.
Q Sometimes the Alias Manager mistakes one volume for another. In particular, we're
experiencing problems getting aliases to volumes to work correctly with our
AppleTalk Filing Protocol (AFP) server volumes. Here's how I can duplicate the
problem:
1. I mount two server volumes from my AFP server: VolA and VolB.
2. I use the Finder to create an alias file for each volume.
3. I unmount VolA.
4. I open the alias file for VolA. However, when I do this, VolB (which is still
mounted) is opened.
Is this a bug in the Alias Manager or did we implement something the wrong way in
our server?
A As noted in the Alias Manager chapter of Inside Macintosh Volume VI, the Alias
Manager uses three criteria to identify a volume: the volume's name, the volume's
creation date, and the volume's type. If the Alias Manager can't find a mounted volume
that matches all three criteria, it tries again with just the volume's creation date and
the volume's type. This second attempt finds volumes that have been renamed. If that
attempt fails, the Alias Manager tries one last time on mounted volumes with the
volume's name and the volume's type. If it can't find a mounted volume with those three
attempts and the alias is to an AFP volume (a file server), the Alias Manager assumes
the volume is unmounted and attempts to mount it.
The problem you're having is probably happening because both volumes have the same
creation date and type. That will cause the Alias Manager to mistake VolA for VolB and
VolB for VolA when it attempts to match by volume creation date and volume type. You
can prevent the Alias Manager from making this mistake by making sure your server
volumes all have unique volume creation dates.
This same behavior can be observed when partitioned hard disks use the same volume
creation date for all partitions. If one partition isn't mounted, the Alias Manager can
mistake one disk partition for another.
Q I'm looking for a Macintosh Toolbox routine that will allow me to turn down the
backlight on a Macintosh PowerBook from within a screen saver to prevent screen
burn and save battery life. Is there such a thing?
A Turning down the backlight won't prevent screen burn. Screen burn can be
prevented only by either shutting the system off or letting the PowerBook enter its
native sleep mode.
In an RGB monitor the phosphor that illuminates each pixel is what causes screen
burn. By setting the pixels to black (the phosphor isn't active) or rapidly changing the
colors of an RGB screen (as with a screen saver), you can prevent screen burn. While
effective on an RGB display, setting the pixels to black may actually cause screen
burn on a PowerBook. The reason is that all the PowerBooks have a liquid crystal
display (LCD), which can be burned by white pixels, black pixels, or repeating
patterns on the screen over a period of time. For this type of display the only good way
to save the screen is to power it off.
Only the Power Manager has access to the chip that shuts the screen off. After a
certain amount of time, the Power Manager makes the function calls to put the system
to sleep. (These calls are documented in Chapter 31 of Inside Macintosh Volume VI.) At
this time the Power Manager signals the chip to turn the screen off. There's no direct
interface between the user and the chip to achieve this. It's best to let the PowerBook's
native screen-saving mechanism (sleep mode, which shuts off the screen) work as is.
This also has the benefit of saving the precious battery power that would be used by the
screen saver.
By the way, if your PowerBook screen has ghost images because you've left it on too
long without going into sleep mode, letting the screen sleep or shutting down your
computer for at least 24 hours will probably make the ghost images go away. Although
there's no hard and fast rule, usually ghost images caused by your system being on for
less than 24 hours won't be permanent if the screen is rested for an equal amount of
time. Any ghost images caused by the system being on for greater than 24 hours may
be permanent.
Q How can I call Connect in AppleTalk Remote Access without an existing ARA
connection file created by the Remote Access application?
A This isn't directly possible, because without the ARA connection file your program
becomes tied to the underlying link tool. The file was implemented so that in the
future, when there are different link tools for the different link types, the program
will know the link type and tool, plus associated link-specific data to use. To connect
without the ARA connection file requires knowledge of the link tool data structures
used by each individual link tool. Because these may change, your code may break.
However, there's a roundabout way of calling Connect. It requires that you first
establish a connection using a document created by the ARA application. Next, make the
IsRemote call, setting the optionFlags to ctlir_getConnectInfo (see page 11 of the
AppleTalk Remote Access Application Programming Interface Guide). This will cause
the information necessary to create the remote connection (connectInfoPtr) to be
returned. You would then save this connectInfo data in your application, and when you
want to connect sometime later, you would pass this data to the Connect call (in the
connectInfo field).
Q When we allocate space for a new file using AllocContig with an argument in
multiples of clump size, we should be grabbing whole clumps at a time so that file
length (and physical EOF) will be a multiple of clump size. What happens if we
truncate a file by moving the logical EOF somewhere inside a clump? Inside Macintosh
says disk sectors are freed at the allocation block level, so we could have a file whose
physical EOF isn't a multiple of clump size, right? Does AllocContig guarantee that the
new bytes added are contiguous with the end of the existing file, or only that the newly
added bytes are contiguous among themselves? If the logical and physical EOFs aren't
the same, does AllocContig subtract the difference before grabbing the new bytes, or do
we get the extra bytes (between EOFs) as a bonus?
A You can create a file whose physical size isn't a multiple of the clump size, if you
try. When the file shrinks, the blocks are freed at the allocation level, without regard
for the clump size. Therefore, if you set the logical EOF to a smaller value, you can
create a file of any physical length.
There's no guarantee that the allocated bytes will be contiguous with the current end
of the file. The decisions that file allocation makes are as follows:
• It always attempts to allocate contiguously, regardless of whether you're
explicitly doing a contiguous allocation. (If it can't, it fails rather than
proceeding if doing an AllocContig.)
• It always attempts to keep the added space contiguous with the existing
space, but it will forgo this before it will fragment the current allocation
request (regardless of whether you're calling Allocate or AllocContig).
So these are the actions that file allocation will take:
1. Allocate contiguous space immediately after the current physical end of
file.
2. Allocate contiguous space separated from the current physical EOF.
3. Fail here if allocating contiguously.
4. Allocate fragmented space, where the first fragment follows the physical
EOF.
5. Allocate fragmented space somewhere on the volume.
You don't get "extra" space with AllocContig. It just does a basic allocation but makes
sure any added blocks are contiguous. PBAllocContig does not guarantee that the space
requested will be allocated contiguously. Instead, it first grabs all the room remaining
in the current extent, and then guarantees that the remaining space will be contiguous.
For example, if you have a 1-byte file with a chunk size of 10K and you try to allocate
20K, 10K-1 bytes will be added to the current file; the remaining 10K+1 bytes are
guaranteed to be contiguous.
Q Inside Macintosh says that ROM drivers opened with OpenDriver shouldn't be closed.
However, it seems that any driver opened with OpenDriver should be closed when the
application is done. Should our application close the serial port after using it?
A As a general rule, applications that open the serial driver with OpenDriver should
do so only when they're actually going to use it, and they should close it when they're
done. (Note that it's important to do a KillIO on all I/O before closing the serial port!)
There are a couple of reasons for closing the port when you're finished using it. First,
it conserves power on the Macintosh portable models; while the serial port is open the
SCC drains the battery. Second, closing the serial port avoids conflicts with other
applications that use it. Inside Macintosh is incorrect in stating that you shouldn't
close the port after issuing an OpenDriver call.
Most network drivers shouldn't be closed when an application quits, on the other hand,
since other applications may still be accessing the driver.
Q We've tried to put old CDs to productive use. We use them for coasters, but you can
only drink so many Mountain Dews at once. We've even resorted to using them for
skeet-shooting practice. Can you suggest other good uses for my old CDs?
A It's not well known that stunning special effects in some films, such as Terminator
2, were produced with the aid of compact disc technology. For example, the "liquid
metal" effect used for the evil terminator was nothing more than 5000 remaindered
Madonna CDs, carefully sculpted into the shape of an attacking android. And did you
know that dropping a CD into a microwave oven for five seconds or so produces an
incredible "lightning storm" effect? (Kids, don't try this at home; we're trained
professionals.) For ideas of what you can do with old CDs, see the letter on page 5.
Q I need to launch an application remotely. How do I do this? The Process Manager
doesn't seem to be able to launch an application on another machine and the Finder
Suite doesn't have a Launch Apple event.
A What you need to do is use the OpenSelection Finder event. Send an OpenSelection to
the Finder that's running on the machine you want to launch the other application on,
and the Finder will resolve the OpenSelection into a launch of the application.
As you can see if you glance at the OpenSelection event in the Apple Event Registry,
there's one difficulty with using it for remote launching: You have to pass an alias to
the application you want to launch. If the machine you want to launch the application on
is already mounted as a file server, this isn't important, since you can create an alias