nsXULTemplateBuilder::SubstituteText(Match& aMatch, const nsString& aAttributeValue, nsString& aResult)
nsXULTemplateBuilder::SubstituteText(nsTemplateMatch& aMatch, const nsAReadableString& aAttributeValue, nsAString& aResult)
nsXULTemplateBuilder::SubstituteText(Match& aMatch,                                     const nsString& aAttributeValue,                                     nsString& aResult){    // See if it's the special value "..."    if (aAttributeValue.Length() == 3        && aAttributeValue[0] == PRUnichar('.')        && aAttributeValue[1] == PRUnichar('.')        && aAttributeValue[2] == PRUnichar('.')) {        Value memberval;        aMatch.GetAssignmentFor(mConflictSet, mMemberVar, &memberval);        nsIRDFResource* member = VALUE_TO_IRDFRESOURCE(memberval);        NS_ASSERTION(member != nsnull, "no member!");        if (! member)            return NS_ERROR_UNEXPECTED;        const char *uri = nsnull;        member->GetValueConst(&uri);        aResult.AssignWithConversion(uri);        return NS_OK;    }    // Reasonable guess at how big it should be    aResult.SetCapacity(aAttributeValue.Length());    // XXX wish we could use iterators, but we can't right now.    PRInt32 len = aAttributeValue.Length();    for (PRInt32 i = 0; i < len; ++i) {        PRInt32 backup = i;        // A variable is either prefixed with '?' (in the extended        // syntax) or "rdf:" (in the simple syntax).        PRBool isvar;        if (aAttributeValue[i] == PRUnichar('?')) {            isvar = PR_TRUE;        }        else if ((aAttributeValue[i] == PRUnichar('r') && ++i < len) &&                 (aAttributeValue[i] == PRUnichar('d') && ++i < len) &&                 (aAttributeValue[i] == PRUnichar('f') && ++i < len) &&                 (aAttributeValue[i] == PRUnichar(':'))) {            isvar = PR_TRUE;        }        else {            isvar = PR_FALSE;        }        if (! isvar || ++i >= len) {            // It's not a variable, or we ran off the end of the            // string after the initial variable prefix. Since we may            // have slurped down some characters before realizing that            // fact, back up to the point where we started.            i = backup;            aResult += aAttributeValue[i];            continue;        }        // Construct a substring that is the symbol we need to look up        // in the rule's symbol table. The symbol is terminated by a        // space character, or the end of the string, whichever comes        // first. (The space character is consumed.)        PRInt32 first = backup;        while (i < len && aAttributeValue[i] != PRUnichar(' '))            ++i;        PRInt32 last = i;        nsPromiseSubstring<PRUnichar> symbol(aAttributeValue, first, last);        // The symbol "rdf:*" is special, and means "this guy's URI"        PRInt32 var = 0;        if (symbol == NS_LITERAL_STRING("rdf:*"))            var = mMemberVar;        else            var = aMatch.mRule->LookupSymbol(symbol);        // No variable; treat as a variable with no        // substitution. (This shouldn't ever happen, really...)        if (! var)            continue;        // Got a variable; get the value it's assigned to        Value value;        PRBool hasAssignment =            aMatch.GetAssignmentFor(mConflictSet, var, &value);        // If there was no assignment for the variable, bail. This'll        // leave the result string with an empty substitution for the        // variable.        if (! hasAssignment)            continue;        // Got a value; substitute it.        switch (value.GetType()) {        case Value::eISupports:            {                nsISupports* isupports = NS_STATIC_CAST(nsISupports*, value);                nsCOMPtr<nsIRDFNode> node = do_QueryInterface(isupports);                if (node) {                    // XXX ideally we'd just point this right at the                    // substring which is the end of the string,                    // turning this into an in-place append.                    nsAutoString temp;                    gXULUtils->GetTextForNode(node, temp);                    aResult += temp;                }            }            break;        case Value::eString:            aResult += NS_STATIC_CAST(const PRUnichar*, value);            break;        default:            break;        }    }    return NS_OK;}