Re: [MacPerl-Toolbox] Listing resources from the resource fork
[email protected] (Alan Fry) Fri, 22 Jun 2001 17:54:39 +0100
| Newsgroups | perl.macperl.toolbox |
|---|---|
| Message-ID | <p05100300b75928c749fc@[158.152.146.73]> |
At 6:29 pm +0200 21/06/01, Bart Lateur wrote:
>I am attempting to come to grips with reading resource fork in MacPerl.
>What I'm really trying to do, is to convert FOND resources from a font
>suitcase to an AFM file. But don't let me bother you with that.
>
>So here's my basic testing script. Save as a droplet, drop a file with a
>resource fork (for example a font suitcase) on it, and it will list all
>resource types, the count of resources for each, and then list them one
>by one, with a hex dump of the first 32 bytes.
>
>It kinda works.
>
> #! perl -w
> use Mac::Resources;
> use Mac::Memory;
> while(@ARGV) {
> my $file = shift;
> if (defined(my $RFD = OpenResFile($file))) {
> my $types = Count1Types;
> print "$file: $types types\n";
> for my $i (1 .. Count1Types) {
> my $restype = Get1IndType($i);
> print " Resource type: $restype\n";
> my $rescount = Count1Resources($restype);
> print " $rescount resources\n";
> for my $j (1 .. $rescount) {
> my $reshandle = Get1IndResource($restype, $j);
> my @resinfo = GetResInfo $reshandle;
> print " -> @resinfo\n";
> my $resdata = $reshandle->get(0,32);
> print " @{[map { sprintf '%02X', $_ } unpack 'C*',
> $resdata]}\n";
> # $reshandle->dispose; ????
> }
> }
> CloseResFile $RFD;
> } else {
> print "Cannot open resource fork for file $file: $^E\n";
> }
> }
>
>According to ResEdit, I have two resource types: "FOND", with 4 named
>resources (1 for each font), the resource name is the font name, Id's
>8798 to 8801; and "NFNT", which contains 20 resources, 20 bitmap fonts,
>with no name, and ID's between 17663 and 17686 (yes, there are a few
>missing).
>
>When run as above, I get the proper ID from GetResInfo for "NFNT", but
>without the string "NFNT", which I would expect in analogy to its
>behaviour under "FOND". I just get the ID.
Using "Acrobat Reader" (which happened to be handy) I get:
$rescount = 2
@resinfo = 32562 FOND .Espiago
@resinfo = 32700 FOND .MDEF Font
$rescount = 4
@resinfo = 32563 NFNT .Espiago Bold 9
@resinfo = 32562 NFNT .Espiago 9
@resinfo = 32716 NFNT .MDEF Font
@resinfo = 32728
It seems that if the resource is not named then the resource
'type-string' is not returned either? Maybe that's how it is. IM is
silent about this.
>But, with dispose, I get a repetition of the info for the last "FOND"
>resource, which got listed above, 20 times.
>
>So, something surely is wrong, either way.
So it does. That's weird!
> * is dispose the proper method? I've seen that Mac::Resources lists
>ReleaseResource and DetachResource as well, but their purpose is far
>from clear to me.
I doubt it is. After all MacPerl handles are only scalar references
(blessed with the name 'Handle') to real 'C' handles. In the MacOS
Toolbox such handles are created by the appropriate 'manager' and
usually moved high and locked in memory to be out of reach of the
claws of the 'memory manager'. In all cases the Toolbox provides a
specific procedure to unlock the handle and reverse the process of
creation.
It is not altogether surprising that the 'memory manager's' routine
for disposing of its own handles should fail if applied to some other
toolbox handle such as (in this instance) a handle to a resource.
> * Shouldn't Mac::Memory dispose of the memory all by itself, when the
>variable containing the handle gets DESTROY-ed?
No, the handle is usually hidden away to _stop_ the 'memory manager'
tinkering with it. It is always necessary to call the specific
Toolbox routines to dispose of handles and reclaim the memory space.
(MPW's 'ZoneRanger' is a useful tool to see whether or not the right
things have happened.)
After disposal of the handle itself the MacPerl reference to it will
still be in existence. That could cause an error if it were used to
reference a handle which had previously gone away.
>My problem is with disposing of the handle. I found that
>"RunTimeBuilder.dp" uses $sourceCodeRes->dispose, so that's what I tried
>first. My problem is that when I do that, I get errors in my dump. I
>probably get errors without it, too...
According to IM there are three methods of zapping resource handles:
ReleaseResource() sets master pointer to NIL
removes data from memory
DetatchResource() sets master pointer to NIL
keeps data in memory
RemoveResource() removes entry in resource map
removes data from memory
removes data from resource fork (on update)
I think ReleaseResource() must be the right thing to do. The script
above works fine with it but I haven't explored the result with
'ZoneRanger' however.
HTH,
Alan Fry