/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiSource Program Utilities * * Copyright (C) 2002 Francis James Franklin * Copyright (C) 2002 AbiSource, Inc. * * 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 #include #include "ut_assert.h" #include "ut_debugmsg.h" #include "ut_string_class.h" #include "xap_Resource.h" #include "xap_ResourceManager.h" XAP_ResourceManager::XAP_ResourceManager () : m_current(0), m_resource(0), m_resource_count(0), m_resource_max(0), m_id_number(0) { // } XAP_ResourceManager::~XAP_ResourceManager () { for (UT_uint32 i = 0; i < m_resource_count; i++) delete m_resource[i]; if (m_resource) g_free (m_resource); } const UT_UTF8String XAP_ResourceManager::new_id (bool bInternal) { static const char utf8_hex[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' }; char buf[11]; /* external references (hyperlinks) are remapped from, say, http://this.com/that * to, say, /re_abc123 */ if (!bInternal) { buf[0] = '/'; buf[1] = 'r'; buf[2] = 'e'; } else { buf[0] = '#'; buf[1] = 'r'; buf[2] = 'i'; } buf[3] = '_'; if ((m_id_number & 0xffffff) != m_id_number) { UT_DEBUGMSG(("argh!! too many resources! who do you think I am?!\n")); UT_ASSERT((m_id_number & 0xffffff) == m_id_number); buf[4] = 0; } else { UT_uint32 number = m_id_number++; buf[9] = utf8_hex[number & 0x0f]; number >>= 4; buf[8] = utf8_hex[number & 0x0f]; number >>= 4; buf[7] = utf8_hex[number & 0x0f]; number >>= 4; buf[6] = utf8_hex[number & 0x0f]; number >>= 4; buf[5] = utf8_hex[number & 0x0f]; number >>= 4; buf[4] = utf8_hex[number & 0x0f]; buf[10] = 0; } return UT_UTF8String(buf); } /* returns resource corresponding to href * returns 0 if none is found */ XAP_Resource * XAP_ResourceManager::resource (const char * href, bool bInternal, UT_uint32 * index) { m_current = 0; if ( href == 0) return 0; if (*href == 0) return 0; if (bInternal) { if (*href == '/') return 0; if (*href == '#') href++; } else { if (*href == '#') return 0; if (*href == '/') href++; } if (*href != 'r') return 0; for (UT_uint32 i = 0; i < m_resource_count; i++) if (m_resource[i]->bInternal == bInternal) if (strcmp (href, m_resource[i]->name().utf8_str()) == 0) { m_current = m_resource[i]; if (index) *index = i; break; } return m_current; } /* resource objects are created/destroyed via ref/unref * ref() returns false if href is not, and cannot be, created */ bool XAP_ResourceManager::ref (const char * href) { if ( href == 0) return false; if (*href == 0) return false; bool bInternal = false; if (*href == '#') bInternal = true; else if (*href != '/') return false; XAP_Resource * match = resource (href, bInternal); if (match) { match->ref (); return true; } if (!grow ()) return false; XAP_Resource * r = 0; try { if (bInternal) r = new XAP_InternalResource (href); else r = new XAP_ExternalResource (href); } catch (...) { r = 0; } if (r == 0) return false; m_resource[m_resource_count++] = r; return true; } /* resource objects are created/destroyed via ref/unref * ref() returns false if href is not and cannot be created */ void XAP_ResourceManager::unref (const char * href) { if ( href == 0) return; if (*href == 0) return; bool bInternal = false; if (*href == '#') bInternal = true; else if (*href != '/') return; UT_uint32 index; XAP_Resource * match = resource (href, bInternal, &index); if (match == 0) return; if (match->unref () > 0) return; delete m_resource[index]; m_resource_count--; if (index < m_resource_count) m_resource[index] = m_resource[m_resource_count]; } /* call's writer's write_xml() & write_base64() callbacks */ UT_Error XAP_ResourceManager::write_xml (void * context, Writer & writer) { UT_Error err = UT_OK; static const char * psz_id = "id"; static const char * psz_content_type = "type"; static const char * psz_description = "desc"; const char * atts[8]; atts[4] = NULL; atts[5] = NULL; for (UT_uint32 i = 0; i < m_resource_count; i++) if (m_resource[i]->bInternal) { XAP_InternalResource * ri = dynamic_cast(m_resource[i]); UT_uint32 n = 0; atts[n++] = psz_id; atts[n++] = ri->name().utf8_str (); if (!(ri->type().empty ())) { atts[n++] = psz_content_type; atts[n++] = ri->type().utf8_str (); } if (!(ri->Description.empty ())) { atts[n++] = psz_description; atts[n++] = ri->Description.utf8_str (); } atts[n++] = NULL; atts[n++] = NULL; err = writer.write_xml (context, "resource", atts); if (err != UT_OK) break; err = ri->write_base64 (context, writer); if (err != UT_OK) break; err = writer.write_xml (context, "resource"); if (err != UT_OK) break; } return err; } bool XAP_ResourceManager::grow () { if (m_resource_count < m_resource_max) return true; if (m_resource == 0) { m_resource = static_cast(g_try_malloc (8 * sizeof (XAP_Resource *))); if (m_resource == 0) return false; m_resource_max = 8; return true; } XAP_Resource ** more = static_cast(g_try_realloc (m_resource, (m_resource_max + 8) * sizeof (XAP_Resource *))); if (more == 0) return false; m_resource = more; m_resource_max += 8; return true; }