+ dest.InsertChild(copyOfNode, dest.GetChildren());
+ }
+ }
+ }
+
+ if ( dest.GetType() == wxXML_TEXT_NODE && overwriteWith.GetContent().length() )
+ dest.SetContent(overwriteWith.GetContent());
+}
+
+wxObject *
+wxXmlResource::DoCreateResFromNode(wxXmlNode& node,
+ wxObject *parent,
+ wxObject *instance,
+ wxXmlResourceHandler *handlerToUse)
+{
+ // handling of referenced resource
+ if ( node.GetName() == wxT("object_ref") )
+ {
+ wxString refName = node.GetAttribute(wxT("ref"), wxEmptyString);
+ wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
+
+ if ( !refNode )
+ {
+ ReportError
+ (
+ &node,
+ wxString::Format
+ (
+ "referenced object node with ref=\"%s\" not found",
+ refName
+ )
+ );
+ return NULL;
+ }
+
+ const bool hasOnlyRefAttr = node.GetAttributes() != NULL &&
+ node.GetAttributes()->GetNext() == NULL;
+
+ if ( hasOnlyRefAttr && !node.GetChildren() )
+ {
+ // In the typical, simple case, <object_ref> is used to link
+ // to another node and doesn't have any content of its own that
+ // would overwrite linked object's properties. In this case,
+ // we can simply create the resource from linked node.
+
+ return DoCreateResFromNode(*refNode, parent, instance);
+ }
+ else
+ {
+ // In the more complicated (but rare) case, <object_ref> has
+ // subnodes that partially overwrite content of the referenced
+ // object. In this case, we need to merge both XML trees and
+ // load the resource from result of the merge.
+
+ wxXmlNode copy(*refNode);
+ MergeNodesOver(copy, node, GetFileNameFromNode(&node, Data()));
+
+ // remember referenced object's file, see GetFileNameFromNode()
+ copy.AddAttribute(ATTR_INPUT_FILENAME,
+ GetFileNameFromNode(refNode, Data()));
+
+ return DoCreateResFromNode(copy, parent, instance);
+ }
+ }
+
+ if (handlerToUse)
+ {
+ if (handlerToUse->CanHandle(&node))
+ {
+ return handlerToUse->CreateResource(&node, parent, instance);
+ }
+ }
+ else if (node.GetName() == wxT("object"))
+ {
+ for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
+ h != m_handlers.end(); ++h )
+ {
+ wxXmlResourceHandler *handler = *h;
+ if (handler->CanHandle(&node))
+ return handler->CreateResource(&node, parent, instance);
+ }
+ }
+
+ ReportError
+ (
+ &node,
+ wxString::Format
+ (
+ "no handler found for XML node \"%s\" (class \"%s\")",
+ node.GetName(),
+ node.GetAttribute("class", wxEmptyString)
+ )
+ );
+ return NULL;
+}
+
+wxIdRange::wxIdRange(const wxXmlNode* node,
+ const wxString& rname,
+ const wxString& startno,
+ const wxString& rsize)
+ : m_name(rname),
+ m_start(0),
+ m_size(0),
+ m_item_end_found(0),
+ m_finalised(0)
+{
+ long l;
+ if ( startno.ToLong(&l) )
+ {
+ if ( l >= 0 )
+ {
+ m_start = l;
+ }
+ else
+ {
+ wxXmlResource::Get()->ReportError
+ (
+ node,
+ "a negative id-range start parameter was given"
+ );
+ }
+ }
+ else
+ {
+ wxXmlResource::Get()->ReportError
+ (
+ node,
+ "the id-range start parameter was malformed"
+ );
+ }
+
+ unsigned long ul;
+ if ( rsize.ToULong(&ul) )
+ {
+ m_size = ul;
+ }
+ else
+ {
+ wxXmlResource::Get()->ReportError
+ (
+ node,
+ "the id-range size parameter was malformed"
+ );
+ }
+}
+
+void wxIdRange::NoteItem(const wxXmlNode* node, const wxString& item)
+{
+ // Nothing gets added here, but the existence of each item is noted
+ // thus getting an accurate count. 'item' will be either an integer e.g.
+ // [0] [123]: will eventually create an XRCID as start+integer or [start]
+ // or [end] which are synonyms for [0] or [range_size-1] respectively.
+ wxString content(item.Mid(1, item.length()-2));
+
+ // Check that basename+item wasn't foo[]
+ if (content.empty())
+ {
+ wxXmlResource::Get()->ReportError(node, "an empty id-range item found");
+ return;
+ }
+
+ if (content=="start")
+ {
+ // "start" means [0], so store that in the set
+ if (m_indices.count(0) == 0)
+ {
+ m_indices.insert(0);
+ }
+ else
+ {
+ wxXmlResource::Get()->ReportError
+ (
+ node,
+ "duplicate id-range item found"
+ );
+ }
+ }
+ else if (content=="end")
+ {
+ // We can't yet be certain which XRCID this will be equivalent to, so
+ // just note that there's an item with this name, in case we need to
+ // inc the range size
+ m_item_end_found = true;
+ }
+ else
+ {
+ // Anything else will be an integer, or rubbish
+ unsigned long l;
+ if ( content.ToULong(&l) )
+ {
+ if (m_indices.count(l) == 0)
+ {
+ m_indices.insert(l);
+ // Check that this item wouldn't fall outside the current range
+ // extent
+ if (l >= m_size)
+ {
+ m_size = l + 1;
+ }