Carbon open/read/close resource example code?

kuroyume

Registered
I am still rather new to MacOS programming (almost 20 years other). I have a plugin for an application. Using CodeWarrior Pro 9 for MacOS and a Classic target to make a shared lib (the plugin) using C++. The plugin works quite well, but it needs to access the resource forks of other files to extract the PICT data within. These are not system or application resources, but resource forks attached to text files.

The Windows version of the plugin was easier since the resource fork files have been converted to .rsr files that can be processed using any standard or SDK file operations.

For MacOS, I need to use Carbon to find, open, extract the PICT data (this I can do or at least understand the resource structure), and close the resource fork of the referenced file, of course, using Resource methods. It's been days of searching and asking. Still have yet to find a direct answer. Been to developer.apple.com. I even have the MacTech Carbon C docs and examples. But they still don't show how to do just this. Preferences = no. Application resources = no. System resources = no.

So, can anyone show example source code? Does anyone have links to example source code?

Thank you,

Robert
 
wadesworld said:
Robert,

I don't have any code, but what you would do is:

1) Use the File Manager functions to locate the files.

Okay, I'm not using File Manager, but the SDK functions to get the base file name. How do I bridge between the SDK 'Filename' class (which contains the file specifier as a string - full path) and the File Manager functions?

Robert
 
brianleahy said:

You're talking like I know what any of that means. I am NEW to MacOS programming. No previous experience. Which part of that voluminous code is useful? What are all the Ref numbers? Why is a File Copy relevant to opening/reading/closing a fork?

Robert
 
Here's my Windows version of the code:

Code:
// Change RSR file into temp PCT file
BOOL iPDialog::ReadRSR(Filename fn)
{
	CHAR buf[8];
	UWORD i, type, index, num;
	LONG dataoff, mapoff, datasize;

	AutoAlloc<BaseFile> rsrFile;
	AutoAlloc<BaseFile> pctFile;
	if (!rsrFile || !pctFile) throw ErrorException(ERROR_MEMORY, "iPDialog.ReadRSR.rsrFile");
	if (!(rsrFile->Open(fn, GE_READ, FILE_NODIALOG))) throw ErrorException(ERROR_READFILE, fn.GetString());
	if (!(pctFile->Open(tmpthumbFN, GE_WRITE, FILE_NODIALOG))) throw ErrorException(ERROR_WRITEFILE, tmpthumbFN.GetString());

	// Get Header's Resource Data and Map Offsets
	if (!rsrFile->ReadLong(&dataoff)) return FALSE;
	if (!rsrFile->Seek(4, GE_START)) return FALSE;
	if (!rsrFile->ReadLong(&mapoff)) return FALSE;
	// Jump to Map's Type Count (num-1)
	if (!rsrFile->Seek(mapoff+28, GE_START)) return FALSE;
	if (!rsrFile->ReadUWord(&type)) return FALSE;
	type++;
	index = 0;
	// Find index of 'PICT' type
	for (i = 0; i < type; i++)
	{
		if (!rsrFile->ReadBytes(&buf[0], 8)) return FALSE;
		//if (!rsrFile->ReadUWord(&num)) return FALSE;
		num = (UWORD)(buf[4]<<8) + buf[5];
		buf[4] = 0;
		if (String(&buf[0]) == "PICT") break;
		index += (num+1);
	}
	if (i == type) return FALSE;
	type = i;

	// Find Data by index
	if (!rsrFile->Seek(dataoff, GE_START)) return FALSE;
	if (!rsrFile->ReadLong(&datasize)) return FALSE;
	for (i = 0; i < index; i++)
	{
		if (!rsrFile->Seek(datasize, GE_RELATIVE)) return FALSE;
		if (!rsrFile->ReadLong(&datasize)) return FALSE;
	}

	// Copy PICT data to temp file
	memset(&buffer, 0, 512);
	pctFile->WriteBytes(&buffer, 512);
	for (LONG size = 512; datasize; datasize -= size)
	{
		if (size > datasize) size = datasize;
		if (!(size = rsrFile->ReadBytes(&buffer, size, FALSE))) return FALSE;
		if (!pctFile->WriteBytes(&buffer, size)) return FALSE;
	}
	pctFile->Close();
	rsrFile->Close();
	return TRUE;
}

That simple. The PICT image file is then loaded using the SDK since the application can handle various types of 2D and 3D files automatically.

Robert
 
Did I mention that this plugin has to work on OS9 and OS10? So FSPathMakeRef() is useless (10.1 or above).

Robert
 
kuroyume said:
Okay, I'm not using File Manager, but the SDK functions to get the base file name. How do I bridge between the SDK 'Filename' class (which contains the file specifier as a string - full path) and the File Manager functions?

Robert

First, I would seriously consider dumping OS 9 support. If you're new to the Mac, dealing with the idiosyncracies of OS 9 and the fewer supported functions is going to do nothing but add to your frustration.

Since FSpOpenResFile takes a FSSpec, you'll need to convert from a full path to a FSSpec.

What you need to do is:

Code:
//assumes path is a null-terminated string with / as a path
//separator
int ConvertPathToFSSpec( FSSpec *spec, char *path )
{
    Str255  pPath;
    OSStatus err;
    int i;

    //convert from c path to "old style" pascal path
    CopyCStringToPascal( path, pPath );
    for ( i=1 ; i < pPath[0]  ; i++ )
         if ( pPath[i] == '/' )
               pPath[i] = ':';

    err = FSMakeFSSpec( 0, 0, pPath, spec );
}

Hope this helps,

Wade
 
It is all working now. Can't consider dumping OS 9 support since the host application for the plugin runs in both OS 9 and 10 and, believe it or not, there are still users running the app in OS 9 out there. At some point, there would be someone asking why they can't use my plugin in the app in OS 9.

Found the way to do Path to FSSpec. Even after going to FSMakeFSSpec() several times, I didn't catch on that setting the first two arguments to 0 would convert the ':'-separated filepath into an FSSpec without the need for those number references.

The only downside to this approach is the 255 character limit for full paths. You know that there is going to be a user who breaks that easily. ;)

Robert
 
Back
Top