//Copyright Paul Reiche, Fred Ford. 1992-2002 /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "options.h" #include "port.h" #include "resintrn.h" #include "libs/memlib.h" #include "libs/log.h" #include "libs/uio/charhashtable.h" const char *_cur_resfile_name; // When a file is being loaded, _cur_resfile_name is set to its name. // At other times, it is NULL. ResourceDesc * lookupResourceDesc (RESOURCE_INDEX idx, RESOURCE res) { return (ResourceDesc *) CharHashTable_find (idx->map, res); } void loadResourceDesc (ResourceDesc *desc) { desc->vtable->loadFun (desc->fname, &desc->resdata); } void * LoadResourceFromPath (const char *path, ResourceLoadFileFun *loadFun) { uio_Stream *stream; unsigned long dataLen; void *resdata; stream = res_OpenResFile (contentDir, path, "rb"); if (stream == NULL) { log_add (log_Warning, "Warning: Can't open '%s'", path); return NULL; } dataLen = LengthResFile (stream); log_add (log_Info, "\t'%s' -- %lu bytes", path, dataLen); if (dataLen == 0) { log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path); goto err; } _cur_resfile_name = path; resdata = (*loadFun) (stream, dataLen); _cur_resfile_name = NULL; res_CloseResFile (stream); return resdata; err: res_CloseResFile (stream); return NULL; } const char * res_GetResourceType (RESOURCE res) { RESOURCE_INDEX resourceIndex; ResourceDesc *desc; if (res == NULL_RESOURCE) { log_add (log_Warning, "Trying to get type of null resource"); return NULL; } resourceIndex = _get_current_index_header (); desc = lookupResourceDesc (resourceIndex, res); if (desc == NULL) { log_add (log_Warning, "Trying to get type of undefined resource '%s'", res); return NULL; } return desc->vtable->resType; } // Get a resource by its resource ID. void * res_GetResource (RESOURCE res) { RESOURCE_INDEX resourceIndex; ResourceDesc *desc; if (res == NULL_RESOURCE) { log_add (log_Warning, "Trying to get null resource"); return NULL; } resourceIndex = _get_current_index_header (); desc = lookupResourceDesc (resourceIndex, res); if (desc == NULL) { log_add (log_Warning, "Trying to get undefined resource '%s'", res); return NULL; } if (desc->resdata.ptr == NULL) loadResourceDesc (desc); if (desc->resdata.ptr != NULL) ++desc->refcount; return desc->resdata.ptr; // May still be NULL, if the load failed. } DWORD res_GetIntResource (RESOURCE res) { RESOURCE_INDEX resourceIndex; ResourceDesc *desc; if (res == NULL_RESOURCE) { log_add (log_Warning, "Trying to get null resource"); return 0; } resourceIndex = _get_current_index_header (); desc = lookupResourceDesc (resourceIndex, res); if (desc == NULL) { log_add (log_Warning, "Trying to get undefined resource '%s'", res); return 0; } return desc->resdata.num; } BOOLEAN res_GetBooleanResource (RESOURCE res) { return (res_GetIntResource (res) != 0); } // NB: this function appears to be never called! void res_FreeResource (RESOURCE res) { ResourceDesc *desc; ResourceFreeFun *freeFun; desc = lookupResourceDesc (_get_current_index_header(), res); if (desc == NULL) { log_add (log_Debug, "Warning: trying to free an unrecognised " "resource."); return; } if (desc->refcount > 0) --desc->refcount; else log_add (log_Debug, "Warning: freeing an unreferenced resource."); if (desc->refcount > 0) return; // Still references left freeFun = desc->vtable->freeFun; if (freeFun == NULL) { log_add (log_Debug, "Warning: trying to free a non-heap resource."); return; } if (desc->resdata.ptr == NULL) { log_add (log_Debug, "Warning: trying to free not loaded " "resource."); return; } (*freeFun) (desc->resdata.ptr); desc->resdata.ptr = NULL; } // By calling this function the caller will be responsible of unloading // the resource. If res_GetResource() get called again for this // resource, a NEW copy will be loaded, regardless of whether a detached // copy still exists. void * res_DetachResource (RESOURCE res) { ResourceDesc *desc; ResourceFreeFun *freeFun; void *result; desc = lookupResourceDesc (_get_current_index_header(), res); if (desc == NULL) { log_add (log_Debug, "Warning: trying to detach from an unrecognised " "resource."); return NULL; } freeFun = desc->vtable->freeFun; if (freeFun == NULL) { log_add (log_Debug, "Warning: trying to detach from a non-heap resource."); return NULL; } if (desc->resdata.ptr == NULL) { log_add (log_Debug, "Warning: trying to detach from a not loaded " "resource."); return NULL; } if (desc->refcount > 1) { log_add (log_Debug, "Warning: trying to detach a resource referenced " "%u times", desc->refcount); return NULL; } result = desc->resdata.ptr; desc->resdata.ptr = NULL; desc->refcount = 0; return result; } BOOLEAN FreeResourceData (void *data) { HFree (data); return TRUE; }