CPreferences.cp

/*
    Implements a preference file and resource io therein. Also handy
    for resource io in any LFile.
 
    Created 29 Jan 1996 by EGH
    
    Copyright © 1996, Apple Computer, Inc. All rights reserved.
*/
 
#include <String_Utils.h>
 
#include "CPreferences.h"
 
CPreferences::CPreferences()
{
    mFile = nil;
    mOwnsFile = true;
}
 
CPreferences::CPreferences(
    LFile *inFile)
{
    mFile = inFile;
    mOwnsFile = false;
}
 
CPreferences::CPreferences(
    OSType inFileType,
    OSType inFileCreator,
    StringPtr inFileNameP)
{
    mFile = nil;
    mOwnsFile = true;
    FindOrCreatePreferencesFile(inFileType, inFileCreator, inFileNameP);
}
 
CPreferences::~CPreferences()
{
    if (mOwnsFile && mFile != nil)
        delete mFile;
}
 
void CPreferences::FindOrCreatePreferencesFile(
    OSType inFileType,
    OSType inFileCreator,
    StringPtr inFileNameP)
{
    OSErr err = noErr;
    FSSpec spec;
    
    err = FindFolder(
        kOnSystemDisk,
        kPreferencesFolderType,
        true,
        &spec.vRefNum,
        &spec.parID);
    
    if (err == noErr)
    {
        CopyPStr(inFileNameP, spec.name, sizeof(spec.name));
        
        mFile = new LFile(spec);
        
        SetDebugThrow_(debugAction_Nothing); // turn this off as below will probably be thrown
        
        Try_
        {
            mFile->CreateNewFile(inFileCreator, inFileType, nil);
        }
        Catch_(inErr)
        {
            if (inErr != dupFNErr)
            {
                delete mFile;
                mFile = nil;
            }
            
            // fall through
        }
        EndCatch_
        
        SetDebugThrow_(debugAction_Alert);
    }
}
 
Handle CPreferences::GetPreferenceResource(
    OSType inResType,
    ResIDT inResID)
{
    Handle resH = nil;
    
    if (mFile != nil)
    {
        Int16
            saveResRef,
            resRef;
        
        Try_
        {
            saveResRef = ::CurResFile();
            
            SetDebugThrow_(debugAction_Nothing); // don't bitch unecessarily
            resRef = mFile->OpenResourceFork(fsRdPerm);
            SetDebugThrow_(debugAction_Alert); // ok, start bitching again
            
            ::UseResFile(resRef); // to force this file to the head of the chainÉ
            
            resH = ::Get1Resource(inResType, inResID); // Éso that Get1 can be used
            
                // the resource fork will be closed, so detach it so we don't lose it
            if (resH != nil)
            {
                ::HNoPurge(resH);
                ::DetachResource(resH);
            }
            
            mFile->CloseResourceFork();
            ::UseResFile(saveResRef);
        }
        
        Catch_(inErr)
        {
            ::UseResFile(saveResRef);
            
            // fall through
        } EndCatch_
    }
    
    return resH;
}
 
void CPreferences::SavePreferenceResource(
    OSType inResType,
    ResIDT inResID,
    Handle inPrefH)
{
    if (mFile != nil)
    {
        Int16
            saveResRef,
            resRef;
        Handle resH;
        
        Try_
        {
            saveResRef = ::CurResFile();
            
            resRef = mFile->OpenResourceFork(fsRdWrPerm);
            ::UseResFile(resRef); // to force this file to the head of the chainÉ
            
            resH = ::Get1Resource(inResType, inResID); // Éso that Get1 can be used
            
                // if the resource already exists, update the old one
            if (resH != nil)
            {
                ::HNoPurge(resH);
                ::SetHandleSize(resH, GetHandleSize(inPrefH));
                ::BlockMove(*inPrefH, *resH, GetHandleSize(resH));
                if (::ResError() == noErr)
                {
                    ::ChangedResource(resH);
                    if (::ResError() == noErr)
                    {
                        ::WriteResource(resH);
                        if (::ResError() == noErr)
                            ::ReleaseResource(resH);
                    }
                }
            }
            else
            {
                ::AddResource(inPrefH, inResType, inResID, "\p");
                if (::ResError() == noErr)
                {
                    ::WriteResource(inPrefH);
                    ::DetachResource(inPrefH); // do not throw the handle
                }
            }
            
            mFile->CloseResourceFork();
            ::UseResFile(saveResRef);
        }
        
        Catch_(inErr)
        {
            ::UseResFile(saveResRef);
            
            // fall through
        } EndCatch_
    }
}