VError VMacResFile::_GetResource(const VString& inType, const VString& inName, Handle* outHandle) const { OSErr macError = noErr; Str255 spName; *outHandle = NULL; if (!testAssert(fRefNum != -1)) return VE_STREAM_NOT_OPENED; ResType type = inType.GetOsType(); if (type == 0) return VE_INVALID_PARAMETER; inName.MAC_ToMacPString(spName, 255); sWORD curres = ::CurResFile(); if (curres != fRefNum) ::UseResFile(fRefNum); *outHandle = fUseResourceChain ? ::GetNamedResource(type, spName) : ::Get1NamedResource(type, spName); macError = ::ResError(); if (curres != fRefNum) ::UseResFile(curres); VError error = VErrorBase::NativeErrorToVError((VNativeError)macError); return error; }
VError VMacResFile::AddResource(const VString& inType, const void* inData, sLONG inDataLen, const VString* inName, sLONG* outID) { VError error = VE_OK; *outID = 0; if (!testAssert(fRefNum != -1)) return VE_STREAM_NOT_OPENED; ResType type = inType.GetOsType(); if (type == 0) return VE_INVALID_PARAMETER; // test if the res file is not read-only if (!testAssert(!fReadOnly)) return VE_ACCESS_DENIED; sWORD curres = ::CurResFile(); ::UseResFile(fRefNum); sWORD id = ::Unique1ID(type); OSErr macError = ::ResError(); if (testAssert(macError == noErr)) { error = WriteResource(inType, (sLONG) id, inData, inDataLen, inName); if (error == VE_OK) *outID = (sLONG) id; } else error = VErrorBase::NativeErrorToVError((VNativeError)macError); ::UseResFile(curres); return error; }
VError VMacResFile::GetResourceListNames(const VString& inType, VArrayString& outNames) const { OSErr macError = noErr; outNames.SetCount(0); if (!testAssert(fRefNum != -1)) return VE_STREAM_NOT_OPENED; ResType type = inType.GetOsType(); if (type == 0) return VE_INVALID_PARAMETER; sWORD oldref = ::CurResFile(); sWORD ref = fRefNum; while(ref != -1 && ref != 0) { ::UseResFile(ref); sWORD count = ::Count1Resources(type); ::UseResFile(oldref); for(sWORD i = 1 ; i <= count ; ++i) { ::UseResFile(ref); ::SetResLoad(false); Handle data = ::Get1IndResource(type, i); macError = ::ResError(); ::SetResLoad(true); ::UseResFile(oldref); // one must restore proper context before calling VArrayValue::AppendWord if (data != NULL) { ResType type2; sWORD id; Str255 spName; ::GetResInfo(data, &id, &type2, spName); macError = ::ResError(); if (macError == noErr && spName[0] > 0) { VString name; name.MAC_FromMacPString(spName); if (outNames.Find(name) == -1) outNames.AppendString(name); } } } if (!fUseResourceChain) break; else { macError = ::GetNextResourceFile(ref, &ref); // returns ref = 0 and noerror at the end if (!testAssert(macError == noErr)) break; } } return VE_OK; }
VError VMacResFile::_GetResource(const VString& inType, sLONG inID, Handle* outHandle) const { OSErr macError = noErr; *outHandle = NULL; if (!testAssert(fRefNum != -1)) return VE_STREAM_NOT_OPENED; if (!testAssert(inID >= -32768 && inID <= 32767)) return VE_RES_INDEX_OUT_OF_RANGE; ResType type = inType.GetOsType(); if (type == 0) return VE_INVALID_PARAMETER; sWORD id = (short) inID; if (!fUseResourceChain) macError = ::InsertResourceFile( fRefNum, kRsrcChainAboveApplicationMap); sWORD curres = ::CurResFile(); if (curres != fRefNum) ::UseResFile(fRefNum); *outHandle = fUseResourceChain ? ::GetResource(type, id) : ::Get1Resource(type, id); macError = ::ResError(); if (curres != fRefNum) ::UseResFile(curres); if (!fUseResourceChain) macError = ::DetachResourceFile( fRefNum); VError error = VErrorBase::NativeErrorToVError((VNativeError)macError); return error; }
VError VMacResFile::WriteResource(const VString& inType, sLONG inID, const void* inData, sLONG inDataLen, const VString* inName) { if (!testAssert(fRefNum != -1)) return VE_STREAM_NOT_OPENED; // test if the res file is not read-only if (!testAssert(!fReadOnly)) return VE_ACCESS_DENIED; if (!testAssert(inID >= -32768 && inID <= 32767)) return VE_INVALID_PARAMETER; Handle data = NULL; VError error = _GetResource(inType, inID, &data); if (error == VE_OK || error == VE_RES_NOT_FOUND) { error = VE_OK; OSErr macError = noErr; Str255 spName; sWORD id = (short) inID; spName[0] = 0; if (inName != NULL) inName->MAC_ToMacPString(spName, 255); if ((data != NULL) && (*data != NULL)) { ::HNoPurge(data); ::EmptyHandle(data); // discard old data } if (data != NULL) { // Change existing resource if (inName != NULL) ::SetResInfo(data, id, spName); // if data size is small, we delay the writing to disk to improve flush speed // else we write it immediately and we don't keep it in memory if (inDataLen > 4096L) { ::SetResourceSize(data, inDataLen); macError = ::ResError(); if (testAssert(macError == noErr)) { ::WritePartialResource(data, 0, inData, inDataLen); macError = ::ResError(); assert(macError == noErr); } } else { ::ReallocateHandle(data, inDataLen); macError = MemError(); if (testAssert(macError == noErr)) { ::BlockMoveData(inData, *data, inDataLen); ::ChangedResource(data); ::WriteResource(data); ::ReleaseResource(data); data = NULL; macError = ::ResError(); assert(macError == noErr); } } if (data != NULL) { ::ReleaseResource(data); data = NULL; } } else { // Add a new resource sWORD curres = ::CurResFile(); if (curres != fRefNum) ::UseResFile(fRefNum); if (inDataLen > 4096L) { data = ::NewHandle(0); // AddResource needs a non-empty handle ::AddResource(data, inType.GetOsType(), id, spName); macError = ::ResError(); if (testAssert(macError == noErr)) { ::EmptyHandle(data); ::SetResourceSize(data, inDataLen); macError = ::ResError(); if (testAssert(macError == noErr)) { ::WritePartialResource(data, 0, inData, inDataLen); macError = ::ResError(); assert(macError == noErr); } ::ReleaseResource(data); data = NULL; } } else { data = ::NewHandle(inDataLen); macError = ::MemError(); if (testAssert(macError == noErr)) { ::BlockMoveData(inData, *data, inDataLen); ::AddResource(data, inType.GetOsType(), id, spName); macError = ::ResError(); if (testAssert(macError == noErr)) { ::WriteResource(data); macError = ::ResError(); assert(macError == noErr); ::ReleaseResource(data); } else { ::DisposeHandle(data); } data = NULL; } } if (data != NULL) { ::DisposeHandle(data); data = NULL; } if (curres != fRefNum) ::UseResFile(curres); } error = VErrorBase::NativeErrorToVError((VNativeError)macError); } return error; }