>If I perform a DisposeHandle on a pic handle, how come I am not able to
>load and display the picture a second time? DisposeHandle should just
>remove the handle, not the resouce, shouldn't it?
This is bad. Use KillPicture for all PICTs that aren't resources.
Use ReleaseResource for all other PICTs.
Greg
MPI Multimedia
>
> I've received one reply that stated all standard system calls will most
> likely crash when memory gets too low. Therefore, in my app, if the
> memory gets below 10k or 12k, I am going to inform the user that there is
> not enough, and that they should close a file.
>
>
Yes, this is important. Basically, your strategy needs to be that if the
amount of free memory gets to be too small (e.g. sufficently small that
operations WILL fail), you need to disable all of the commands that will
cause memory to be allocated. That is, if you don;t have enough memory for
the about box, disable the about box command. Similarly, if you are really
low on memory, don't allow the user to open another file, and perhaps ask
them to close one, or ask them to do something else that will free up
memory.
> If I perform a DisposeHandle on a pic handle, how come I am not able to
> load and display the picture a second time? DisposeHandle should just
> remove the handle, not the resouce, shouldn't it?
You definitely do not want to use DisposeHandle on a resource. The
Resource Manager keeps a table of which resources are loaded and where
they are in memory. The Memory Manager keeps a table(s) of which handles
are allocated and where they are in memory. If you tell the resource
manager to release the resource it cleans up its table and marks the
resource purgable. If you tell the memory manager to Dispose the handle,
it frees the handle, but the resource manager still thinks that the handle
exists... bad news. If you make the resource purgable (HPurge), then
GetPicture will return the resource handle, even if the handle has been
purged. This means that you will get an empty PicHandle (if the available
memory is small enough). An empty PicHandle is a non-null handle that
points to a NULL value. This will cause quickdraw problems.
>
> The other point I was trying to make was this: If I can get the image
> (and pic != nil), how come I am not able to display it? If GetPicture
> failed, it's supposed to return a 0, yet it doesn't, so what gives?
See above about empty PicHandles. Also, even if you do get the picture,
there may not be enough memory available for the DrawPicture command to
complete. If the picture is simply a bitmap there is not too much overhead
in DrawPicture, but if there are any regions polygons, etc, DrawPicture
can require a reasonable amount of memory. What program did you use to
create the picture? SuperPaint, for example, stuffs a lot of crap into its
pictures, including PostScript dictionaries. If you really want to be safe
for low mem conditions, convert your picture into a bitmap or a pixmap,
and use copybits to image it. Even with copybits, the fact that it is not
interrupt safe probably means that you cannot rely on it not to use
memory.
Basically, the toolbox is not terribly stable under really low memory
conditions. It was generally written to assume that memory allocation will
not fail. It is your responsibility to ensure that the Toolbox has enough
memory to satisfy any allocations that it wants to make. In your case, you
have found that about 10-12K is required. You must ensure that the amount
of memory avaiable to the system never drops below this amount. Disable
commands if you must and explain to the user why these commands are
disabled. It is better to not be able to do something than to have the
entire machine crash, especially if the function in question is simply
seeing the about box of the program.
If you want to get a little more sophisticated, read about growzone
functions in IM:Memory. This will allow you to set aside some 'emergency'
memory for those system calls that just cannot fail.
>
> Yes, I was a bit unclear. The second time I get the picture, GetPicture
> does not return a nil, yet I am unable to display the image. I have THINK
> Reference and it states that DrawPicture is a void, and it does not
> indicate any error codes from DrawPicture. I just looked up in my IM QD
> book the QDError function. I will use it for my app. Thanks for the tip.
>
>
See above statments about empty handles and DrawPicture.
> >> Do I need to do a lot of watch dogging and not let any operations be
> >> performed if the app goes beneath 10k of memory is free?
> > You have less than 10k of memory free and expect the
> > program to do something?
>
Yes. But you should allow operations that increase the amount of free memory.
> Yep. Verry standard. But the problem is this: My app will handle an
> unlimited number of files/windows (memory permitting). I do not wish to
> limit the user by only allowing them a max number of files open at a time
> (like 5 or 10). Each window/file at it's maximum will use ~ 55 handles
> (I'm displaing a max of 50 icons, each is contained within an IconSuite,
> which is a handle). If I plan on having 5 files open, I should probably
> call MoreMasters 4 times. If I plan on having 10 files open, I should
> probably call MoreMasters 9 times.
>
> Get my point?
>
> It's varriable depending on the user. Ideally it would be nice to Call a
> MoreMasters() call before I open a file, then do a DeleteMoreMasters call
> (if such a call had existed) after I calosed a file. These are all
> design issues I will have to iron out I guess.
>
>
There are a few things realed to this question. A master pointer block has
100 master pointers. The space for the pointers plus overhead is about 512
bytes (I think... don't remember exactly). You can get approx. 2 files per
master pointer block. If you initialize, say, 20 master pointer blocks,
that is only about 10k and it will allow approx. 40 windows before you
automagically get a new block. Probably OK (not many people can deal with
40 windows at once). Remeber, you need the master pointer blocks for other
types of handles also... not too much of a problem to have too many. Also,
will all of the icons in every window be different? 40 x 50 = 2000. I
would be really surprized if your app would actually have to show 2000
different icon suites (I could be wrong). You might look at sharing
handles for the common suites (This could be a big win).
If all of the above does not appeal, you can also look at generating new
heaps for each window (probably not a great solution).
But finally, fragmentation happens. You do everything you can to avoid it,
but there are parts of the toolbox that make it kind of difficult (if you
want to have no limits on your code). It is not the end of the world, just
something to be avoided. Especially if, as in your case, each window will
require approximately the same amount of space. If you have a memory map
like
X
P
X <-
X
X
X
P
P
P
P
where X = stuff for the window
and P = non-relocatable (e.g. Master pointer block)
if one window is closed (the one with the '<-', say) and another is
opened, then with what you have described, the new window ought to fit
into the memory occupied by the old window. In this case the fragmentation
does not affect you.
[stuff about memory management and MP blocks]
see above
> 1 Unconventional. I'm not taliking about event-driven programming
> conceps, but things like string types. Who the hell even USES Str63 or
> Str255?!?!??? After years of honning my pointer & string skills, I have
> to deal with this junk. If I write my own function, I use pointers, if I
> use a toolbox call, well... I use StrXXX. And linked lists... try doing
> a linked list on the Mac... I DARE YOU.
The Str63/Str255 is a legacy from pascal, and certain limits imposed from
the early design of the operating system (e.g. filename length limits).
They are generally not a problem (but I guess that I am used to them).
As far as linked lists goes.... use them all of the time. What is the problem?
> 3 Example code base is meeger. There are several areas of Mac programming
> which need some indepth examples. The app which I'm writing shouldn't
> have taken this long, but I got locked up on a couple topics.
>
Well, I guess that it is hard to make these claims if you don;t have
access to New Inside Macintosh. There are pretty good examples and
explanations of many of the issues you mention. Also, there is alot of
good source out on the net that essentially functions as sample code of
the type that you are looking for.
>
> > (new) Inside Macintosh: Memory - for references to
> > questions about: MoreMasters, NewHandle, CompactMem,
> > PurgeMem, FreeMem, etc.
>
> Don't have it, but I have THINK Reference.
>
Think reference is not really a substitute.
Good luck, and don't let it get you down. It gets easier. Really.
B.J.
> DoAnimation(theDialog, step);
> step++;
> if(step >= 4)
> step = 0;
> }
Just a minor thing - I'll leave the memory management thing for others -
but if your PICTs are sequentially numbered, why not use the resource ID
directly, and savve yourself the switch statement? If they aren't
guaranteed to be sequential, you could still store them in an array which
would be easier to update than adding another case in the switch.
> void DoAnimation(DialogPtr theDialog, short step)
> {
> PicHandle pic;
> Rect r;
>
>
> switch( step )
> {
> case 0:
> pic = GetPicture(128);
> break;
>
> case 1:
> pic = GetPicture(129);
> break;
etc.
--
Philip Machanick phi...@cs.wits.ac.za
Department of Computer Science, University of the Witwatersrand
2050 Wits, South Africa (at University of Cape Town 4 July-7 Nov)
phone 27(11)716-3309 fax 27(11)339-7965
Sorry, don't know for sure, but I wouldn't be too
surprised.
>
> 2) I am loading four separate pictures...
>
void DoAnimation(short step) {
PicHandle pic = GetPicture(128+step);
if (pic != nil) DrawPicture(pic, &(**pic).portRect);
}
>
> Looks good so far, no?
Well, no. I would guess this flashes like mad (but if you
haven't gotten it to work yet, you wouldn't know that ;^).
I would probably load the resources once, image them into
offscreen graphics worlds and then just CopyBits in
DoAnimation. Lots of sample code available to do this BTW.
> Well, the problem is that under a low memory condition (say ~7,000 -
> 8,000 bytes free), the first picture is loaded and displays fine, but
> when the second image is loaded, my app crashes...
How do you know how much memory you have free?
>
> I then went in and added a
> ReleaseResource( (Handle )pic);
> This time, each of the four pictures were loaded (and my app didn't crash)
This should be a clue... (what has changed? why did that
make a difference?... are your PICT resources marked
purgeable?)
> ...but when the counter turned back to 0, the first pic wasn't displayed.
>
> I dismissed the dialog box and brought it back up again. This time, none
> of the pictures were displayed! Well, this leads me to believe that when
> I call ReleaseResource(), it not only frees up the memory of the handle
> holding the picture, but it clears it from the current resource as well.
> I then tried to use the DisposeHandle() call in place of the
> ReleaseResource() call, and the same thing occurred (all four pictures
> were displayed once and only once).
>
> At this point, I added following:
>
if (pic != nil) {
...
} else {
> MoveTo(20, 20);
> DrawString("\pCan't open image");
> }
>
> the error message never came up!
>
> So what gives? I can't load and display the image, yet the pic isn't nil
> either!?!?!
>
There were three statements in that last line.
1) I can't load the image
2) I can't display the image
3) The handle to the image is not nil
These can not all be true. GetPicture returns nil if it
was unable to load the image. Since you say "the error
message never came up" I will assume that 3 is true. This
means that 1 must be false. This leaves only 2 as a
problem for your application. This is what you must
investigate.
BTW, have you investigated how QuickDraw reports errors.
Given that it appears that this "feature" is occurring in
the DrawPicture call, how would you know that it failed?
Apart from not being able to see the picture.
> Do I need to do a lot of watch dogging and not let any operations be
> performed if the app goes beneath 0k of memory is free?
>
You have less than 0k of memory free and expect the
program to do something?
BTW, just to be a total smart-***, the generally accepted
way to handle this type of situation is to:
1) Figure out how much memory you application needs.
2) Make sure that it gets at least that much.
;^) <--- note the smiley!
>
> 3) In Macintosh C Programming Primmer Vol 2, it states that when a
> program starts, it contains a block of master pointers. It is within
> this location that the location of the Handles are kept (64 of them). If
> the program requires more than 64, the MoreMasters() call needs to be
> made (which will create 64 more locations for handles). What happens if
> I have filled up all 64 locations with handles, then create another
> handle (for arguments' sake, let's say that there is enough memory to
> create the size of the handle, and we create a new handle without
> calling MoreMasters())? Will I run the risk of loosing the handle when
> memory is juggled around?
>
If you call NewHandle, and you have no more master
pointers available, NewHandle will call MoreMasters for
you. The point behind doing it youself is that master
pointer blocks are non-relocatable and tend to lead to
heap fragmentation.
If you let NewHandle make the call, the master pointer
block will be placed as low in the heap as possible.
Depending on what you have been doing, you may have
relocatable or purgeable structures in heap below that
block. If you want to reuse that memory, especially with
something that may be larger than the things that
previously occupied that space (as seems like you may) you
are unable to because you have a master pointer block
sitting where you need to put your new structure.
Go ahead and call MoreMasters two, three... maybe ten
times early in your program. Master pointer blocks are
pretty small compared to the space you could loose letting
NewHandle do it for you.
> 4) In my program, I manage multiple files at the same time (hence, my app
> manages several windows at the same time). In each file/window, there
> are LOTS of different handles (my app displays dozens of icon suites, and
> each icon suite is a handle). In fact, if I have a window that is maxed
> out (each window will hold a maximum amount of 50 icon suites), It would
> seem that I would almost have to call MoreMasters() each time I
> create/open a new window (when I create/open a new window, I perform a
> NewHandle( sizeof(data_in_my_window) ) type of call in my program).
>
that would be a BadThing(r), see above.
>
> Is
> there a call that REMOVES 64 master pointers? In other words, I was
> wondering if there is a way to call MoreMasters() before I create/open a
> window, and call RemoveMastersFunction() after I close a window? Yes, I
> could just add another MoreMasters() call at the begining of my program,
> but I intend to allow the user to have as many windows/files opened as
> they want.
>
no, again, see above
> 5) Is there a call that forces the system to compact the fragmented
> memory of an app? I
> remember reading that the system automatically compacts the memory at
> certain intervals, and I know that there are functions that will compact
> the memory, so there is a certain amount of memory free (e.g.
> CompactMem( x ), where x is the number of bytes needed), but is there a
> call that will force the system to compact as much as possible?
>
The memory manager has a number of calls in addition to
CompactMem (FreeMem and PurgeMem come to mind) but these
only help with relocatable and purgeable objects. If your
memory is fragmented, it will stay fragmented, these calls
only help you use the memory that you have left.
From your literary reference above (an excellent starting
point, I might add) I assume that you are (fairly) new to
Macintosh programming, although from the apparent
complexity of your application not to programming in
general. Rather than answer you questions with answers, I
will answer them with questions and refer you to further
reading, so that you can learn the material yourself and
not have to ask again next time.
(new) Inside Macintosh: Memory - for references to
questions about: MoreMasters, NewHandle, CompactMem,
PurgeMem, FreeMem, etc.
(new) Inside Macintosh: Imaging with QuickDraw - for
references to questions about: DrawPicture, GetPicture,
etc.
--
Hope this helps.
Mark H. Linton
____________________________________________________________________
mark \'märk\ n [ME, fr. OE mearc boundary, march, sign; akin to OHG
marha boundary, L margo] 1 a : a conspicuous object serving as a guide
for travelers 2 : A standard or criterion of quality 3 : An object or
point that serves as a guide --idiom. mark time. 1 : To make little or
no progress
<
<
< >> Do I need to do a lot of watch dogging and not let any operations be
< >> performed if the app goes beneath 0k of memory is free?
< > You have less than 0k of memory free and expect the
< > program to do something?
<
< That was a typo. It should have been 10k free.
<
< > BTW, just to be a total smart-***, the generally accepted
< > way to handle this type of situation is to:
<
< > 1) Figure out how much memory you application needs.
< > 2) Make sure that it gets at least that much.
<
< > ;^) <--- note the smiley!
<
< Yep. Verry standard. But the problem is this: My app will handle an
< unlimited number of files/windows (memory permitting). I do not wish to
< limit the user by only allowing them a max number of files open at a time
< (like 5 or 10). Each window/file at it's maximum will use ~ 55 handles
< (I'm displaing a max of 50 icons, each is contained within an IconSuite,
< which is a handle). If I plan on having 5 files open, I should probably
< call MoreMasters 4 times. If I plan on having 10 files open, I should
< probably call MoreMasters 9 times.
<
< Get my point?
<
< It's varriable depending on the user. Ideally it would be nice to Call a
< MoreMasters() call before I open a file, then do a DeleteMoreMasters call
< (if such a call had existed) after I calosed a file. These are all
< design issues I will have to iron out I guess.
<
<
Most of the sample code I've seen uses a size of about 40K as the time to
post a low memory warning. Since we're talking about 'Real World' apps
you should know that ALL real world apps have a growZone procedure and use
some mechanism for keeping a buffer of memory available. Usually this
done by a mechanism known as the rainy-day fund. Briefly, at app startup
you allocate a handle of, say, 40K. That's your rainy day fund. Each
time through your main event loop ( or perhaps only on null events) you
check the available memory. If it's too low you post a warning alert.
Under some circumstances you release the rainy day handle. Either from
your growZone Proc or possibly in response to an explicit call from
somewhere in your app.
Regarding the MoreMasters calls. Exercise your app thoroughly with a
number of windows/documents open that is on the high side of what you
would consider avaerage. See how many Master Pointer blocks were needed.
Maybe add 2 or 3 to this number and call MoreMasters this many times.
Eight or ten should be more than sufficient. Realize that any user that
sees the 'not enough memory' warning is going to up the partition size for
the app. Although this doesn't automatically increase the number of
Master Pointer blocks it does give the app more breathing room so that if
any are automatically allocated any problems caused by heap fragmentation
are minimized. The important thing is to warn when memory gets low.
< The biggest problems I have encountered w/the Mac are:
<
< 1 Unconventional. I'm not taliking about event-driven programming
< conceps, but things like string types. Who the hell even USES Str63 or
< Str255?!?!??? After years of honning my pointer & string skills, I have
< to deal with this junk. If I write my own function, I use pointers, if I
< use a toolbox call, well... I use StrXXX. And linked lists... try doing
< a linked list on the Mac... I DARE YOU.
Gee Jeff, we were just beginning to like you, and then you turn on us like
this:) Are you aware that your windowlist is a linked list? There are
numerous operating system queues that are linked lists. Doing linked
lists with memory allocated by NewPtr or by malloc is no different than on
any other architecture. You can do linked lists with handles. The only
difference is an extra * here or there when referring to the memory
blocks.
If you're not aware, the reason for the Str255 and friends string types
are due to the Mac's Pascal heritage. Don't complain about it, just
accept it. Every development environment has utility routines to
translate between C and P strings. Sorry you had to learn something new.
<
< 2 There are several good Mac programming books out there, but all only
< cover the basics. What I'd like to see is something that covers a full
< scale real world type app. One that covers such topics as Multiple
< files/windows opened at a time, localization, printing, error-proofing
< apps, etc... I've seen some books that start to deal with some of these
< topics, but don't go into very much depth on them.
<
< 3 Example code base is meeger. There are several areas of Mac programming
< which need some indepth examples. The app which I'm writing shouldn't
< have taken this long, but I got locked up on a couple topics.
Are you aware of the sample code at ftp.apple.com and at the
alt.sources.mac archive at ftp://ftpbio.bgsu.edu/?
<
<
<
< Have it.
<
< >--
<
< >Hope this helps.
<
<
< a little
<
<
< Jeff
Good luck,
--
Brian Stern :-{)}
Toolbox commando and Menu bard
Jae...@fquest.com
Get ZoneRanger and a color monitor. This is the *coolest* free program
for figuring out what the heck your app is doing in its memory
partition. It should be on any archive site and plenty of CDs.
Also, get ProcessWatcher, another free and useful tool.
>Most of the sample code I've seen uses a size of about 40K as the time to
>post a low memory warning. Since we're talking about 'Real World' apps
>you should know that ALL real world apps have a growZone procedure and use
>some mechanism for keeping a buffer of memory available. Usually this
>done by a mechanism known as the rainy-day fund. Briefly, at app startup
>you allocate a handle of, say, 40K. That's your rainy day fund. Each
>time through your main event loop ( or perhaps only on null events) you
>check the available memory. If it's too low you post a warning alert.
>Under some circumstances you release the rainy day handle. Either from
>your growZone Proc or possibly in response to an explicit call from
>somewhere in your app.
I've abstracted and elaborated this. Each level in an app gets a
reserve memory. Then there's a memory cushion in addition. The app
sets the allocation level. The Toolbox level is the lowest, since the
TB can crash if it doesn't get memory. When I need to allocate memory,
I bump up the level, then restore it afterwards. For critical things,
like quitting and saving a file, I bump up the memory to a "critical"
level. Each level allows access to different memory reserves. The size
of the memory reserves for each level is set in a configuration
resource. The grow zone function runs a loop in which it frees up
reserves (depending on the current level) until enough bytes have been
freed. Memory warnings are issued depending on how much of the
reserves are depleted and how little memory is left. At each warning
level, the application can take different actions, e.g., at first just
an alert, then disabling functions like undo, then automatically
asking the user to close files, then automatically closing unmodified
files and saving modified files to temporary locations, and, finally,
terminating the application if all of the reserves are depleted and
there is very little memory left (e.g., less than 10K). I also have
code to automatically unload inactive segments, but it's not very
portable (works only with THINK C, not with Metrowerks).
>...
>< 1 Unconventional. I'm not taliking about event-driven programming
>< conceps, but things like string types. Who the hell even USES Str63 or
>< Str255?!?!??? After years of honning my pointer & string skills, I have
>< to deal with this junk. If I write my own function, I use pointers, if I
>< use a toolbox call, well... I use StrXXX. And linked lists... try doing
>< a linked list on the Mac... I DARE YOU.
>...
>If you're not aware, the reason for the Str255 and friends string types
>are due to the Mac's Pascal heritage. Don't complain about it, just
>accept it. Every development environment has utility routines to
>translate between C and P strings. Sorry you had to learn something new.
I got tired of worrying about string types. At first, I just made a
rule that everything was a C string, and wrote wrappers around
offending toolbox routines. Then I decided it just didn't make sense
to worry about how long a string is, especially for variable length
things. So I wrote a string library that allocates everything
dynamically, and even replaces sprintf. This would have been easier
with C++, but hey, it works even with C. For string-intensive portions
of my code where many strings are used and where performance is
important, say parsing, I use direct pointers and allocate things from
a large chunk of memory or use a fixed string length. the string
library has functions for converting to and from regular C or Pascal
strings.
>< 3 Example code base is meeger. There are several areas of Mac programming
>< which need some indepth examples. The app which I'm writing shouldn't
>< have taken this long, but I got locked up on a couple topics.
>
>Are you aware of the sample code at ftp.apple.com and at the
>alt.sources.mac archive at ftp://ftpbio.bgsu.edu/?
Yup, I'd have to agree that there's tons of sample code. And there's
all the sample code that comes with your compiler (e.g., TC,
Metrowerks), and with Develop, etc.
--
"Ramsgate (n.) All institutional buildings must, by law, contain at
least twenty ramsgates. These are doors that open the opposite way to
the one you expect." -- D. Adams & J. Lloyd "The Meaning of Liff", p75.
This paragraph is inconsistent. Basically, the Toolbox level has the
highest priority. The normal priority is the Toolbox level, since
there are so many TB calls that can allocate memory it's just easier
to keep it as the default. At the TB level, both my reserves and the
TB reserves can be accessed. When I allocate memory, I lower the
priority so as not to deplete the TB reserves, but I can still deplete
my reserves. This scheme can be extended to any number of levels
(which, in my case, is a bit necessary, since I have the TB, low-level
libraries, then the real application, each of which should have their
own reserves, even though my libraries aren't supposed to crash if
they run out of memory).
>< conceps, but things like string types. Who the hell even USES Str63 or
>< Str255?!?!??? After years of honning my pointer & string skills, I have
>< to deal with this junk. If I write my own function, I use pointers, if I
>< use a toolbox call, well... I use StrXXX. And linked lists... try doing
>< a linked list on the Mac... I DARE YOU.
I use Str31, Str63 and Str255 where appropriate; mostly as
structure members and stack-based variables.
Anyone who knows enough C or C++ to program any computer for a
living (in those languages...) knows that when you have a
typedef:
typedef unsigned char Str31 [ 32 ] ;
what really gets passed to functions is a pointer to unsigned
char, so all functions should be declared as:
void
MyFunc (
const unsigned char * source ,
unsigned char * dest )
Similarly; you can pass an unsigned char pointer everywhere the
headers say "StrXXX"
Similarly for linked lists; use malloc() if you like it better,
or use NewPtr(). Or do a linked list with Handles; it's really
easy:
typedef struct elem {
struct elem * * next ;
long data ;
} elem , * elemPtr , * * elemHandle ;
elemHandle theList ;
void
insertelematend (
long data )
{
elemHandle theE = ( elemHandle ) NewHandle ( sizeof ( elem ) ) ;
elemHandle * theP = & theList ;
( * theE ) -> next = NULL ;
( * theE ) -> data = data ;
while ( * theP )
{
theP = & ( * theP ) -> next ;
}
* theP = theE ;
}
Cheers,
/ h+
--
Jon Wätte (h...@nada.kth.se), Hagagatan 1, 113 48 Stockholm, Sweden
This is the kind of totally-gross-out-sick stuff you can do with C++ that
makes the language kind of neat.
-- Keith Rollin
6 months is really not long enough to know the toolbox very well, but
certainly long enough to get a feel of what programming the Mac is like.
It's taken me 10 years to REALLY understand the guts of how the Macintosh
work -- and I was programming for 10 years prior to the Mac introduction
(mainframes, minis, micros).
In relation to your problem with the pictures, if the handle is NULL, the
resource didn't exist. If the first dereference of the handle is NULL,
there either wasn't enough memory to load the resource, or the resource
was purged. If the first dereference is NULL, call LoadResource to see
if you can load it. Code that I use for loading any handle looks like
this:
Handle h = GetResource('XXXX', id);
if (h) // resource exists?
{
if (!*h)
LoadResource(h);
if (*h)
{
// use the resource
}
ReleaseResource(h); // or HPurge(h) is even better!
}
>The biggest problems I have encountered w/the Mac are:
>
>1 Unconventional. I'm not taliking about event-driven programming
>conceps, but things like string types. Who the hell even USES Str63 or
>Str255?!?!??? After years of honning my pointer & string skills, I have
>to deal with this junk. If I write my own function, I use pointers, if I
>use a toolbox call, well... I use StrXXX. And linked lists... try doing
>a linked list on the Mac... I DARE YOU.
No problem. I use linked lists all the time. Pointer AND Handles.
>2 There are several good Mac programming books out there, but all only
>cover the basics. What I'd like to see is something that covers a full
>scale real world type app. One that covers such topics as Multiple
>files/windows opened at a time, localization, printing, error-proofing
>apps, etc... I've seen some books that start to deal with some of these
>topics, but don't go into very much depth on them.
I agree. I've been thinking about that one for a while. Especially
printing. Printing is *EASY* on the Mac. Try writing a simple printable
app for Windows -- what a NIGHTMARE! For example, under Windows, you
have to do your own scaling (Move and Line are
device-resolution-specific, but Ellipse and such are based upon the
current scaling factor set). I also found a major bug in printing
landscape (on an HP PCL printer) -- the same code which worked correctly
when printing portrait broke badly when printing landscape. Items were
moved, portions of graphic items were drawn in different places on the
page (for example, half of an ellipse was drawn in one spot, the other
half was drawn in another spot, and there was white space between the two
halves!). I ended up writing my own landscape code, and letting the
print drivers (plural -- each printer does its own print code) tell me
whether I should do my landscaping code. That bug alone took two months
to find, diagnose and fix, because, although you can rotate text, many of
the parts of Windows GDI break down when dealing with vertical rather
than horizontal text.
>3 Example code base is meeger. There are several areas of Mac
programming
>which need some indepth examples. The app which I'm writing shouldn't
>have taken this long, but I got locked up on a couple topics.
I definately agree on this one, especially some of the newer managers!
However, many of the newer managers (that are extensive, like AOCE or
QDGX) have many example programs to search through to find the answers to
many questions.
However, it has been my experience that Windows programming examples are
even scarcer -- I had to find PD applications which addressed some of the
same issues I had to deal with! Microsoft basically doesn't provide
anything easily accessable, and although Borland did provide some sample
code with their compiler, most of it had to do with the "bells &
whistles" of Windows, like OLE, MCI, and so forth, but very little on
standard "how to display a window contents and deal with scroll bars." I
basically had to experiment with that until I got it right -- another two
months down the drain.
The same basic program that I wrote under Windows which took 12 months to
write and debug took 1 weekend (that's less than 40 hrs, folks!) to write
using Symantec C++ and TCL. Much of the stuff I got for free on the
Macintosh. Much of the stuff I had to write under Windows...
//
// Glenn L. Austin
// Computer Wizard and Racing Car Driver
// Internet: gle...@efn.org
//
> Yes, this is important. Basically, your strategy needs to be that if the
> amount of free memory gets to be too small (e.g. sufficently small that
> operations WILL fail), you need to disable all of the commands that will
You also have to make sure that the amount of free memory doesn't get so
small that the user can't save documents, quit, etc.
--
Larry Rosenstein
Taligent, Inc.
> I've received one reply that stated all standard system calls will most
> likely crash when memory gets too low. Therefore, in my app, if the
> memory gets below 10k or 12k, I am going to inform the user that there is
> not enough, and that they should close a file.
Try 33K. Why? Because 32K is the largest several of the more complicated
data structures in the Toolbox can be. Add 1K for super-emergencies and
you should be better off than using only 12K.
> The other point I was trying to make was this: If I can get the image
> (and pic != nil), how come I am not able to display it? If GetPicture
> failed, it's supposed to return a 0, yet it doesn't, so what gives?
Because the data in a 'PICT' is compressed. It gets expanded somewhat
during DrawPicture.
Also, consider skipping calls like GetPicture and simply using GetResource
directly. It provides an opportunity to do better error checking at the
price of the following difference in typing:
PicHandle ph = GetPicture (128);
PicHandle ph = (PicHandle) GetResource ('PICT',128);
Now you can call 'ResError' and find out all the other things which might
have gone wrong other than 'resNotFound'.
>The biggest problems I have encountered w/the Mac are:
>
> 1 Unconventional. I'm not taliking about event-driven programming
> conceps, but things like string types. Who the hell even USES Str63 or
> Str255?!?!??? After years of honning my pointer & string skills, I have
> to deal with this junk. If I write my own function, I use pointers, if I
> use a toolbox call, well... I use StrXXX.
I actually prefer Pascal strings for most operations because I always have
the length available without worrying about caching the result of
'strlen'. The fact that there are a zillion 'Str...' shouldn't faze you;
they're just Pascal strings with different maximum sizes. I use 'Str15',
for example, all the time for quick calls to 'NumToString'.
> And linked lists... try doing
> a linked list on the Mac... I DARE YOU.
I have. Other posters have pointed out that handles on the Macintosh are
not the same as handles on Windows. There's no more difficulty in writing
linked list code on the Mac than there is in typing an extra '*'. (It's
when people start trying to optimize the double-dereferencing that they
get into trouble.)
> 3 Example code base is meeger. There are several areas of Mac programming
> which need some indepth examples. The app which I'm writing shouldn't
> have taken this long, but I got locked up on a couple topics.
This is an odd observation, given that you appear to have "real" internet
access. Perhaps you are unaware of the many 'ftp' archive sites. There is
also copious example code on the various CD ROMs produced by Apple.
> > (new) Inside Macintosh: Memory - for references to
> > questions about: MoreMasters, NewHandle, CompactMem,
> > PurgeMem, FreeMem, etc.
>
> Don't have it, but I have THINK Reference.
You absitively posolutely need to buy the relevant Inside Macintosh
volumes. They cost a lot of money. You need to buy them anyway.
--
Views expressed here do not necessarily reflect the views of Novell.