attr.Left(left, index); attr.Right(right, attr.Length()-index-1);
attrTok.Left(left, index); attrTok.Right(right, attrTok.Length()-index-1);
nsXBLBinding::ConstructAttributeTable(nsIContent* aElement){  // XXX This function still needs to deal with the  // ability to map one attribute to another.  nsAutoString inherits;  aElement->GetAttribute(kNameSpaceID_None, kInheritsAtom, inherits);  if (!inherits.IsEmpty()) {    if (!mAttributeTable) {      mAttributeTable = new nsSupportsHashtable(4);    }    // The user specified at least one attribute.    char* str = inherits.ToNewCString();    char* newStr;    // XXX We should use a strtok function that tokenizes PRUnichar's    // so that we don't have to convert from Unicode to ASCII and then back    char* token = nsCRT::strtok( str, ", ", &newStr );    while( token != NULL ) {      // Build an atom out of this attribute.      nsCOMPtr<nsIAtom> atom;      nsCOMPtr<nsIAtom> attribute;      // Figure out if this token contains a :.       nsAutoString attr; attr.AssignWithConversion(token);      PRInt32 index = attr.Find(":", PR_TRUE);      if (index != -1) {        // This attribute maps to something different.        nsAutoString left, right;        attr.Left(left, index);        attr.Right(right, attr.Length()-index-1);        atom = getter_AddRefs(NS_NewAtom(left.GetUnicode()));        attribute = getter_AddRefs(NS_NewAtom(right.GetUnicode()));      }      else {        nsAutoString tok; tok.AssignWithConversion(token);        atom = getter_AddRefs(NS_NewAtom(tok.GetUnicode()));        attribute = atom;      }            // Create an XBL attribute entry.      nsXBLAttributeEntry* xblAttr = new nsXBLAttributeEntry(attribute, aElement);      // Now we should see if some element within our anonymous      // content is already observing this attribute.      nsISupportsKey key(atom);      nsCOMPtr<nsISupports> supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*,                                                                      mAttributeTable->Get(&key)));        nsCOMPtr<nsIXBLAttributeEntry> entry = do_QueryInterface(supports);      if (!entry) {        // Put it in the table.        mAttributeTable->Put(&key, xblAttr);      } else {        nsCOMPtr<nsIXBLAttributeEntry> attr = entry;        nsCOMPtr<nsIXBLAttributeEntry> tmpAttr = entry;        do {          attr = tmpAttr;          attr->GetNext(getter_AddRefs(tmpAttr));        } while (tmpAttr);        attr->SetNext(xblAttr);      }      // Now make sure that this attribute is initially set.      // XXX How to deal with NAMESPACES!!!?      nsAutoString value;      nsresult result = mBoundElement->GetAttribute(kNameSpaceID_None, atom, value);      PRBool attrPresent = (result == NS_CONTENT_ATTR_NO_VALUE ||                            result == NS_CONTENT_ATTR_HAS_VALUE);      if (attrPresent) {        aElement->SetAttribute(kNameSpaceID_None, attribute, value, PR_FALSE);        nsCOMPtr<nsIAtom> tag;        aElement->GetTag(*getter_AddRefs(tag));        if ((tag.get() == kHTMLAtom) && (attribute.get() == kValueAtom) && !value.IsEmpty()) {          nsCOMPtr<nsIDOMText> textNode;          nsCOMPtr<nsIDocument> doc;          mBoundElement->GetDocument(*getter_AddRefs(doc));          nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(doc));          domDoc->CreateTextNode(value, getter_AddRefs(textNode));          nsCOMPtr<nsIDOMNode> dummy;          nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(aElement));          domElement->AppendChild(textNode, getter_AddRefs(dummy));        }      }      token = nsCRT::strtok( newStr, ", ", &newStr );    }    nsAllocator::Free(str);  }  // Recur into our children.  PRInt32 childCount;  aElement->ChildCount(childCount);  for (PRInt32 i = 0; i < childCount; i++) {    nsCOMPtr<nsIContent> child;    aElement->ChildAt(i, *getter_AddRefs(child));    ConstructAttributeTable(child);  }  return NS_OK;}