else if ((tag.get() == nsXULAtoms::textnode) && (nameSpaceID == kNameSpaceID_XUL)) {
else if (tag == nsXULAtoms::textnode && nameSpaceID == kNameSpaceID_XUL) {
nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,                                              nsIContent *aResourceNode,                                              nsIContent *aRealNode,                                              PRBool aIsUnique,                                              nsIRDFResource* aChild,                                              PRBool aNotify,                                              nsTemplateMatch* aMatch,                                              nsIContent** aContainer,                                              PRInt32* aNewIndexInContainer){    // This is the mother lode. Here is where we grovel through an    // element in the template, copying children from the template    // into the "real" content tree, performing substitution as we go    // by looking stuff up in the RDF graph.    //    //   |aTemplateNode| is the element in the "template tree", whose    //   children we will duplicate and move into the "real" content    //   tree.    //    //   |aResourceNode| is the element in the "real" content tree that    //   has the "id" attribute set to an RDF resource's URI. This is    //   not directly used here, but rather passed down to the XUL    //   sort service to perform container-level sort.    //    //   |aRealNode| is the element in the "real" content tree to which    //   the new elements will be copied.    //    //   |aIsUnique| is set to "true" so long as content has been    //   "unique" (or "above" the resource element) so far in the    //   template.    //    //   |aChild| is the RDF resource at the end of a property link for    //   which we are building content.    //    //   |aNotify| is set to "true" if content should be constructed    //   "noisily"; that is, whether the document observers should be    //   notified when new content is added to the content model.    //    //   |aContainer| is an out parameter that will be set to the first    //   container element in the "real" content tree to which content    //   was appended.    //    //   |aNewIndexInContainer| is an out parameter that will be set to    //   the index in aContainer at which new content is first    //   constructed.    //    // If |aNotify| is "false", then |aContainer| and    // |aNewIndexInContainer| are used to determine where in the    // content model new content is constructed. This allows a single    // notification to be propagated to document observers.    //    nsresult rv;#ifdef PR_LOGGING    // Dump out the template node's tag, the template ID, and the RDF    // resource that is being used as the index into the graph.    if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {        nsCOMPtr<nsIAtom> tag;        rv = aTemplateNode->GetTag(getter_AddRefs(tag));        if (NS_FAILED(rv)) return rv;        nsXPIDLCString resourceCStr;        rv = aChild->GetValue(getter_Copies(resourceCStr));        if (NS_FAILED(rv)) return rv;        nsAutoString tagstr;        tag->ToString(tagstr);        nsAutoString templatestr;        aTemplateNode->GetAttr(kNameSpaceID_None, nsXULAtoms::id, templatestr);        nsCAutoString templatestrC,tagstrC;        tagstrC.AssignWithConversion(tagstr);        templatestrC.AssignWithConversion(templatestr);        PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,               ("xultemplate[%p] build-content-from-template %s (template='%s') [%s]",                this,                tagstrC.get(),                templatestrC.get(),                resourceCStr.get()));    }#endif    // Iterate through all of the template children, constructing    // "real" content model nodes for each "template" child.    PRUint32 count = aTemplateNode->GetChildCount();    for (PRUint32 kid = 0; kid < count; kid++) {        nsIContent *tmplKid = aTemplateNode->GetChildAt(kid);        PRInt32 nameSpaceID;        tmplKid->GetNameSpaceID(&nameSpaceID);        // Check whether this element is the "resource" element. The        // "resource" element is the element that is cookie-cutter        // copied once for each different RDF resource specified by        // |aChild|.        //        // Nodes that appear -above- the resource element        // (that is, are ancestors of the resource element in the        // content model) are unique across all values of |aChild|,        // and are created only once.        //        // Nodes that appear -below- the resource element (that is,        // are descnendants of the resource element in the conte        // model), are cookie-cutter copied for each distinct value of        // |aChild|.        //        // For example, in a <tree> template:        //        //   <tree>        //     <template>        //       <treechildren> [1]        //         <treeitem uri="rdf:*"> [2]        //           <treerow> [3]        //             <treecell value="rdf:urn:foo" /> [4]        //             <treecell value="rdf:urn:bar" /> [5]        //           </treerow>        //         </treeitem>        //       </treechildren>        //     </template>        //   </tree>        //        // The <treeitem> element [2] is the "resource element". This        // element, and all of its descendants ([3], [4], and [5])        // will be duplicated for each different |aChild|        // resource. It's ancestor <treechildren> [1] is unique, and        // will only be created -once-, no matter how many <treeitem>s        // are created below it.        //        // Note that |isResourceElement| and |isUnique| are mutually        // exclusive.        PRBool isResourceElement = PR_FALSE;        PRBool isUnique = aIsUnique;        {            // We identify the resource element by presence of a            // "uri='rdf:*'" attribute. (We also support the older            // "uri='...'" syntax.)            nsAutoString uri;            tmplKid->GetAttr(kNameSpaceID_None, nsXULAtoms::uri, uri);            if ( !uri.IsEmpty() ) {              if (aMatch->mRule && uri[0] == PRUnichar('?')) {                  isResourceElement = PR_TRUE;                  isUnique = PR_FALSE;                  // XXXwaterson hack! refactor me please                  Value member;                  aMatch->mAssignments.GetAssignmentFor(aMatch->mRule->GetMemberVariable(), &member);                  aChild = VALUE_TO_IRDFRESOURCE(member);              }              else if (uri.Equals(NS_LITERAL_STRING("...")) || uri.Equals(NS_LITERAL_STRING("rdf:*"))) {                  // If we -are- the resource element, then we are no                  // matter unique.                  isResourceElement = PR_TRUE;                  isUnique = PR_FALSE;              }            }        }        nsCOMPtr<nsIAtom> tag;        rv = tmplKid->GetTag(getter_AddRefs(tag));        if (NS_FAILED(rv)) return rv;#ifdef PR_LOGGING        if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {            nsAutoString tagname;            tag->ToString(tagname);            nsCAutoString tagstrC;            tagstrC.AssignWithConversion(tagname);            PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,                   ("xultemplate[%p]     building %s %s %s",                    this, tagstrC.get(),                    (isResourceElement ? "[resource]" : ""),                    (isUnique ? "[unique]" : "")));        }#endif        // Set to PR_TRUE if the child we're trying to create now        // already existed in the content model.        PRBool realKidAlreadyExisted = PR_FALSE;        nsCOMPtr<nsIContent> realKid;        if (isUnique) {            // The content is "unique"; that is, we haven't descended            // far enough into the tempalte to hit the "resource"            // element yet. |EnsureElementHasGenericChild()| will            // conditionally create the element iff it isn't there            // already.            rv = EnsureElementHasGenericChild(aRealNode, nameSpaceID, tag, aNotify, getter_AddRefs(realKid));            if (NS_FAILED(rv)) return rv;            if (rv == NS_RDF_ELEMENT_WAS_THERE) {                realKidAlreadyExisted = PR_TRUE;            }            else {                // Mark the element's contents as being generated so                // that any re-entrant calls don't trigger an infinite                // recursion.                nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(realKid);                if (xulcontent) {                    rv = xulcontent->SetLazyState(nsIXULContent::eTemplateContentsBuilt);                    if (NS_FAILED(rv)) return rv;                }                // Potentially remember the index of this element as the first                // element that we've generated. Note that we remember                // this -before- we recurse!                if (aContainer && !*aContainer) {                    *aContainer = aRealNode;                    NS_ADDREF(*aContainer);                    PRUint32 indx = aRealNode->GetChildCount();                    // Since EnsureElementHasGenericChild() added us, make                    // sure to subtract one for our real index.                    *aNewIndexInContainer = indx - 1;                }            }            // Recurse until we get to the resource element. Since            // -we're- unique, assume that our child will be            // unique. The check for the "resource" element at the top            // of the function will trip this to |false| as soon as we            // encounter it.            rv = BuildContentFromTemplate(tmplKid, aResourceNode, realKid, PR_TRUE,                                          aChild, aNotify, aMatch,                                          aContainer, aNewIndexInContainer);            if (NS_FAILED(rv)) return rv;        }        else if (isResourceElement) {            // It's the "resource" element. Create a new element using            // the namespace ID and tag from the template element.            rv = CreateElement(nameSpaceID, tag, getter_AddRefs(realKid));            if (NS_FAILED(rv)) return rv;            // Add the resource element to the content support map so            // we can the match based on content node later.            mContentSupportMap.Put(realKid, aMatch);            // Assign the element an 'id' attribute using the URI of            // the |aChild| resource.            const char *uri;            rv = aChild->GetValueConst(&uri);            NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource URI");            if (NS_FAILED(rv)) return rv;            // XXX because gcc-2.7.2.3 is too dumb to keep a            // compiler-generated temporary around.            NS_ConvertUTF8toUCS2 x(uri);            const nsAString& id = x;            rv = realKid->SetAttr(kNameSpaceID_None, nsXULAtoms::id, id, PR_FALSE);            NS_ASSERTION(NS_SUCCEEDED(rv), "unable to set id attribute");            if (NS_FAILED(rv)) return rv;            if (! aNotify) {                // XUL document will watch us, and take care of making                // sure that we get added to or removed from the                // element map if aNotify is true. If not, we gotta do                // it ourselves. Yay.                nsCOMPtr<nsIXULDocument> xuldoc =                    do_QueryInterface(mRoot->GetDocument());                if (xuldoc)                    xuldoc->AddElementForID(id, realKid);            }            // Set up the element's 'container' and 'empty'            // attributes.            PRBool iscontainer, isempty;            rv = CheckContainer(aChild, &iscontainer, &isempty);            if (NS_FAILED(rv)) return rv;            if (iscontainer) {                realKid->SetAttr(kNameSpaceID_None, nsXULAtoms::container,                                 NS_LITERAL_STRING("true"), PR_FALSE);                if (! (mFlags & eDontTestEmpty)) {                    NS_NAMED_LITERAL_STRING(true_, "true");                    NS_NAMED_LITERAL_STRING(false_, "false");                    realKid->SetAttr(kNameSpaceID_None, nsXULAtoms::empty,                                     isempty ? true_ : false_,                                     PR_FALSE);                }            }        }        else if ((tag.get() == nsXULAtoms::textnode) && (nameSpaceID == kNameSpaceID_XUL)) {            // <xul:text value="..."> is replaced by text of the            // actual value of the 'rdf:resource' attribute for the            // given node.            PRUnichar attrbuf[128];            nsAutoString attrValue(CBufDescriptor(attrbuf, PR_TRUE, sizeof(attrbuf) / sizeof(PRUnichar), 0));            rv = tmplKid->GetAttr(kNameSpaceID_None, nsXULAtoms::value, attrValue);            if (NS_FAILED(rv)) return rv;            if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (!attrValue.IsEmpty())) {                nsAutoString value;                rv = SubstituteText(*aMatch, attrValue, value);                if (NS_FAILED(rv)) return rv;                nsCOMPtr<nsITextContent> content =                  do_CreateInstance(kTextNodeCID, &rv);                if (NS_FAILED(rv)) return rv;                rv = content->SetText(value.get(), value.Length(), PR_FALSE);                if (NS_FAILED(rv)) return rv;                rv = aRealNode->AppendChildTo(nsCOMPtr<nsIContent>( do_QueryInterface(content) ),                                              aNotify, PR_FALSE);                if (NS_FAILED(rv)) return rv;                // XXX Don't bother remembering text nodes as the                // first element we've generated?            }        }        else {            // It's just a generic element. Create it!            rv = CreateElement(nameSpaceID, tag, getter_AddRefs(realKid));            if (NS_FAILED(rv)) return rv;        }        if (realKid && !realKidAlreadyExisted) {            // Potentially remember the index of this element as the            // first element that we've generated.            if (aContainer && !*aContainer) {                *aContainer = aRealNode;                NS_ADDREF(*aContainer);                PRUint32 indx = aRealNode->GetChildCount();                // Since we haven't inserted any content yet, our new                // index in the container will be the current count of                // elements in the container.                *aNewIndexInContainer = indx;            }            // Remember the template kid from which we created the            // real kid. This allows us to sync back up with the            // template to incrementally build content.            mTemplateMap.Put(realKid, tmplKid);            // Copy all attributes from the template to the new            // element.            PRUint32 numAttribs = tmplKid->GetAttrCount();            for (PRUint32 attr = 0; attr < numAttribs; attr++) {                PRInt32 attribNameSpaceID;                nsCOMPtr<nsIAtom> attribName, prefix;                rv = tmplKid->GetAttrNameAt(attr, &attribNameSpaceID,                                            getter_AddRefs(attribName),                                            getter_AddRefs(prefix));                if (NS_FAILED(rv)) return rv;                if (! IsIgnoreableAttribute(attribNameSpaceID, attribName)) {                    // Create a buffer here, because there's a good                    // chance that an attribute in the template is                    // going to be an RDF URI, which is usually                    // longish.                    PRUnichar attrbuf[128];                    nsAutoString attribValue(CBufDescriptor(attrbuf, PR_TRUE, sizeof(attrbuf) / sizeof(PRUnichar), 0));                    rv = tmplKid->GetAttr(attribNameSpaceID, attribName, attribValue);                    if (NS_FAILED(rv)) return rv;                    if (rv == NS_CONTENT_ATTR_HAS_VALUE) {                        nsAutoString value;                        rv = SubstituteText(*aMatch, attribValue, value);                        if (NS_FAILED(rv)) return rv;                        rv = realKid->SetAttr(attribNameSpaceID, attribName, value, PR_FALSE);                        if (NS_FAILED(rv)) return rv;                    }                }            }            // Add any persistent attributes            if (isResourceElement) {                rv = AddPersistentAttributes(tmplKid, aChild, realKid);                if (NS_FAILED(rv)) return rv;            }                        nsCOMPtr<nsIXULContent> xulcontent = do_QueryInterface(realKid);            if (xulcontent) {                PRUint32 count2 = tmplKid->GetChildCount();                if (count2 == 0 && !isResourceElement) {                    // If we're at a leaf node, then we'll eagerly                    // mark the content as having its template &                    // container contents built. This avoids a useless                    // trip back to the template builder only to find                    // that we've got no work to do!                    xulcontent->SetLazyState(nsIXULContent::eTemplateContentsBuilt);                    xulcontent->SetLazyState(nsIXULContent::eContainerContentsBuilt);                }                else {                    // Just mark the XUL element as requiring more work to                    // be done. We'll get around to it when somebody asks                    // for it.                    xulcontent->SetLazyState(nsIXULContent::eChildrenMustBeRebuilt);                }            }            else {                // Otherwise, it doesn't support lazy instantiation,                // and we have to recurse "by hand". Note that we                // _don't_ need to notify: we'll add the entire                // subtree in a single whack.                //                // Note that we don't bother passing aContainer and                // aNewIndexInContainer down: since we're HTML, we                // -know- that we -must- have just been created.                rv = BuildContentFromTemplate(tmplKid, aResourceNode, realKid, isUnique,                                              aChild, PR_FALSE, aMatch,                                              nsnull /* don't care */,                                              nsnull /* don't care */);                if (NS_FAILED(rv)) return rv;                if (isResourceElement) {                    rv = CreateContainerContents(realKid, aChild, PR_FALSE,                                                 nsnull /* don't care */,                                                 nsnull /* don't care */);                    if (NS_FAILED(rv)) return rv;                }            }            // We'll _already_ have added the unique elements; but if            // it's -not- unique, then use the XUL sort service now to            // append the element to the content model.            if (! isUnique) {                rv = NS_ERROR_UNEXPECTED;                if (gXULSortService && isResourceElement) {                    rv = gXULSortService->InsertContainerNode(mDB, &sortState,                                                              mRoot, aResourceNode,                                                              aRealNode, realKid,                                                              aNotify);                }                if (NS_FAILED(rv)) {                    rv = aRealNode->AppendChildTo(realKid, aNotify, PR_FALSE);                    NS_ASSERTION(NS_SUCCEEDED(rv), "unable to insert element");                }            }        }    }    return NS_OK;}