[comp.sys.mac] Quickergraf bugs...

lippin@ragu.berkeley.edu (The Apathist) (03/18/88)

Recently dplatt@coherent.com (Dave Platt) said:
>Apple has apparently changed the MDEF so that it can recover gracefully
>if it can't get a pixmap big enough to save the screen pixels;  it
>simply displays the menu without saving the pixels, and [when the user
>releases the mouse button or moves to a different menu] erases the menu
>rectangle to black and tells QuickDraw to invalidate the rectangle;
>the application(s) that have windows intersecting the invalidated
>rectangle are given window-update events, and can then redraw the
>erased data.

This causes a problem for me.  Since there are so many ways for
out-of-memory problems to screw up the toolbox, I've responded by
writing a growzone function which, when it can't scrounge memory, will
unload most segments, put up an alert, and then longjmp back into the
main event loop.  But this makes some menu choices fail even when
MenuSelect could get by without the memory.

What I want is a way to tell if a memory request is vital or not.  I
can write this into my side of the code, but I know of no way to test
this when it's a toolbox call that needs the memory.  Is there one?
Will there be one eventually?  (This is all grungy stuff that would be
better handled by the OS anyway, I say.)

					--Tom Lippincott
					..ucbvax!bosco!lippin

	"Those who understand will require no further explanation."
					--Saul Bellow,
					_Henderson the Rain King_

stew@endor.harvard.edu (Stew Rubenstein) (03/21/88)

In article <7786@agate.BERKELEY.EDU> lippin@ragu.UUCP (Tom Lippincott, ..ucbvax!bosco!lippin) writes:
>Recently dplatt@coherent.com (Dave Platt) said:
>>Apple has apparently changed the MDEF so that it can recover gracefully
>>if it can't get a pixmap big enough to save the screen pixels;
>
>This causes a problem for me.  Since there are so many ways for
>out-of-memory problems to screw up the toolbox, I've responded by
>writing a growzone function which, when it can't scrounge memory, will
>unload most segments, put up an alert, and then longjmp back into the
>main event loop.  But this makes some menu choices fail even when
>MenuSelect could get by without the memory.
>
>What I want is a way to tell if a memory request is vital or not.  I
>can write this into my side of the code, but I know of no way to test
>this when it's a toolbox call that needs the memory.  Is there one?
>Will there be one eventually?  (This is all grungy stuff that would be
>better handled by the OS anyway, I say.)

Low memory handling on the Mac is a bitch.  There isn't any way to
know when a memory request is critical, except to know what the
toolbox needs the memory for.  You have to assume that any request is
critical.  This is not far from the truth - memory allocation failures
are handled very poorly by the toolbox.  In my apps, I have routines
Critical() and NonCritical(), which clear and set a flag checked by
the growzone function.  Then I have:

INT32 MyMenuSelect(thePoint)
	Point thePoint;
{
	INT32 result;

	NonCritical();
	saveGhost = GhostWindow; /* MenuSelect will not update properly */
	GhostWindow = 0;	 /*   if you use GhostWindow.  */
	result = MenuSelect(thePoint);
	GhostWindow = saveGhost;
	Critical();
	return result;
}

I also have a NewHandleNC() which I use for noncritical memory
allocations in my own code.  Another useful trick is to allocate a
couple of buffers at the start of your program so that you have
something to release when the growzone proc is called.

Finally, it's important to preflight every memory request that you
can.  For example, before you call a routine in another segment, do a
GetResource on the right CODE segment and check to see it succeeds.  A
failure to load a CODE segment causes an immediate system error.  The
GetResource won't waste much time, but you have to identify all the
intersegment calls and have some way of telling what segment it's in.
In MPW it's easy because it names the resources.  For example:

	if (PreFlightCall(SEG_RotateFrob))
	  {
		RotateFrob();
		UnloadSeg(RotateFrobox);
	  }
	else
	  {
		Alert (ALRT_notEnoughMemToRotateFrob, (FilterProc) 0);
	  }

It's especially hard to preflight QuickDraw region operations.  I
assume that an upper bound on the size of a region is proportional to
the area of the bounding rectangle times an empirically derived fudge
factor related to the likely complexity of the region.  You can also
use MapRgn to do the operation on a scaled-down region first, as
suggested in Inside Macintosh, but I find this too time consuming for
most purposes.

Stew Rubenstein
Cambridge Scientific Computing, Inc.
UUCPnet:    seismo!harvard!rubenstein            CompuServe: 76525,421
Internet:   rubenstein@harvard.harvard.edu       MCIMail:    CSC

jv0l+@andrew.cmu.edu (Justin Chris Vallon) (03/31/88)

I don't know if this is an actual bug in QuickerGraf, but the Menu-Manager is
quite smart when drawing menus.  If the MenuManager cannot allocate enough
memory to save the image of the screen behind the menu being drawn, it
erases it, and posts an Update event.  The Update event tells the application
that some parts of some windows are not drawn (in layman's terms :-)

Making some crude calculations, the file/apple menu using Suitcase could be the
length of the entire screen, which could be 10 inches, and about 2 1/2 inches
wide, gives about:
  175 pixels across x 700 pixels x 1 byte/pixel (8-bit mode) = 122.5K (!)

Running under multi-finder, the Finder has a 160K partition, with about 40K
free (taken from my About Finder... window).  Needless to say, the MenuManager
cannot allocate enough memory to save the screen image under the menu.
So, it does the next best thing:  erase the background and post and update
event.  I have seen this happen before when testing my own programs under
low memory conditions, and on a Mac II.  The erased windows were always re-
drawn when I let go of the menu... are your windows being redrawn?

-Justin