if (!aProperty) { return NS_ERROR_NULL_POINTER; } if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } ForceCompositionEnd();  nsAutoEditBatch batchIt(this); nsAutoRules beginRulesSniffing(this, kOpRemoveTextProperty, nsIEditor::eNext);  if (gNoisy) { nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); if (gNoisy) { printf("---------- start nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } nsCRT::free(propCString); }  nsresult result; nsCOMPtr<nsIDOMSelection>selection; result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) return result; if (!selection) return NS_ERROR_NULL_POINTER;  PRBool cancel, handled; nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty); result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); if (NS_FAILED(result)) return result; if (!cancel && !handled) { PRBool isCollapsed; selection->GetIsCollapsed(&isCollapsed); if (PR_TRUE==isCollapsed) {   if ( (aProperty == mBoldAtom.get()) || (aProperty == mItalicAtom.get()) || (aProperty == mUnderlineAtom.get()) ) { SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull); } else if (aProperty == mLinkAtom.get()) {    nsCOMPtr<nsIDOMNode> selNode, tmpNode, parent; PRInt32 selOffset, outOffset; result = GetStartNodeAndOffset(selection, &selNode, &selOffset); if (NS_FAILED(result)) return result; tmpNode = selNode; while (tmpNode) { if (nsHTMLEditUtils::IsBody(tmpNode)) break; if (IsLinkNode(tmpNode)) { result = SplitNodeDeep(tmpNode, selNode, selOffset, &outOffset); if (NS_FAILED(result)) return result; tmpNode->GetParentNode(getter_AddRefs(parent)); selection->Collapse(parent, outOffset); break; } tmpNode->GetParentNode(getter_AddRefs(parent)); tmpNode = parent; } } } else {    nsCOMPtr<nsIDOMNode> parentForSelection; PRInt32 rangeStartOffset, rangeEndOffset; GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection), rangeStartOffset, rangeEndOffset); nsCOMPtr<nsIDOMNode> startParent, endParent; PRInt32 startOffset, endOffset; nsCOMPtr<nsIEnumerator> enumerator; result = selection->GetEnumerator(getter_AddRefs(enumerator)); if (NS_FAILED(result)) return result; if (!enumerator) return NS_ERROR_NULL_POINTER;  enumerator->First(); nsCOMPtr<nsISupports>currentItem; result = enumerator->CurrentItem(getter_AddRefs(currentItem)); if (NS_FAILED(result)) return result;  if (currentItem) { nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) ); nsCOMPtr<nsIDOMNode>commonParent; result = range->GetCommonParent(getter_AddRefs(commonParent)); if (NS_FAILED(result)) return result; if (!commonParent) return NS_ERROR_NULL_POINTER;  range->GetStartOffset(&startOffset); range->GetEndOffset(&endOffset); result = range->GetStartParent(getter_AddRefs(startParent)); if (NS_FAILED(result)) return result; if (!startParent) return NS_ERROR_NULL_POINTER; result = range->GetEndParent(getter_AddRefs(endParent)); if (NS_FAILED(result)) return result; if (!endParent) return NS_ERROR_NULL_POINTER;  if (startParent.get()==endParent.get()) {  startParent->GetParentNode(getter_AddRefs(commonParent)); result = RemoveTextPropertiesForNode(startParent, commonParent, startOffset, endOffset, aProperty, nsnull); } else { result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset, endParent,  endOffset, commonParent, aProperty, nsnull); } if (NS_FAILED(result)) return result;  {      } } if (NS_SUCCEEDED(result)) { result = CollapseAdjacentTextNodes(selection); } if (NS_SUCCEEDED(result)) {  ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection); } } } if (!cancel) {  result = mRules->DidDoAction(selection, &ruleInfo, result); } if (gNoisy) { nsAutoString propString; aProperty->ToString(propString); char *propCString = propString.ToNewCString(); if (gNoisy) { printf("---------- end nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); } nsCRT::free(propCString); } return result;
return RemoveInlinePropertyImpl(aProperty, aAttribute);
NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsString *aAttribute){  if (!aProperty) { return NS_ERROR_NULL_POINTER; }  if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }  ForceCompositionEnd();  nsAutoEditBatch batchIt(this);  nsAutoRules beginRulesSniffing(this, kOpRemoveTextProperty, nsIEditor::eNext);    if (gNoisy)   {     nsAutoString propString;    aProperty->ToString(propString);    char *propCString = propString.ToNewCString();    if (gNoisy) { printf("---------- start nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); }    nsCRT::free(propCString);  }  nsresult result;  nsCOMPtr<nsIDOMSelection>selection;  result = GetSelection(getter_AddRefs(selection));  if (NS_FAILED(result)) return result;  if (!selection) return NS_ERROR_NULL_POINTER;  PRBool cancel, handled;  nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty);  result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);  if (NS_FAILED(result)) return result;  if (!cancel && !handled)  {    PRBool isCollapsed;    selection->GetIsCollapsed(&isCollapsed);    if (PR_TRUE==isCollapsed)    {      // manipulating text attributes on a collapsed selection only sets state for the next text insertion      // But only if it's a property for which we have TypeInState!      if ( (aProperty == mBoldAtom.get()) ||            (aProperty == mItalicAtom.get()) ||            (aProperty == mUnderlineAtom.get()) )      {        SetTypeInStateForProperty(*mTypeInState, aProperty, aAttribute, nsnull);      }      else if (aProperty == mLinkAtom.get())      {        // a hack for links.  The user is trying to kill the link "style" where        // they are typing.  We need to split up through any link elements above the        // collapsed insertion point.        nsCOMPtr<nsIDOMNode> selNode, tmpNode, parent;        PRInt32 selOffset, outOffset;        result = GetStartNodeAndOffset(selection, &selNode, &selOffset);        if (NS_FAILED(result)) return result;        tmpNode = selNode;        while (tmpNode)        {          if (nsHTMLEditUtils::IsBody(tmpNode)) break;          if (IsLinkNode(tmpNode))          {            result = SplitNodeDeep(tmpNode, selNode, selOffset, &outOffset);            if (NS_FAILED(result)) return result;            tmpNode->GetParentNode(getter_AddRefs(parent));            selection->Collapse(parent, outOffset);            break;          }          tmpNode->GetParentNode(getter_AddRefs(parent));          tmpNode = parent;        }      }    }    else    {      // removing text properties can really shuffle text nodes around      // so we need to keep some extra state to restore a reasonable selection      // after we're done      nsCOMPtr<nsIDOMNode> parentForSelection;  // selection's block parent      PRInt32 rangeStartOffset, rangeEndOffset;      GetTextSelectionOffsetsForRange(selection, getter_AddRefs(parentForSelection),                                       rangeStartOffset, rangeEndOffset);      nsCOMPtr<nsIDOMNode> startParent, endParent;      PRInt32 startOffset, endOffset;      nsCOMPtr<nsIEnumerator> enumerator;      result = selection->GetEnumerator(getter_AddRefs(enumerator));      if (NS_FAILED(result)) return result;      if (!enumerator) return NS_ERROR_NULL_POINTER;      enumerator->First();       nsCOMPtr<nsISupports>currentItem;      result = enumerator->CurrentItem(getter_AddRefs(currentItem));      if (NS_FAILED(result)) return result;      //XXX: should be a while loop to get all ranged in selection      if (currentItem)      {        nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );        nsCOMPtr<nsIDOMNode>commonParent;        result = range->GetCommonParent(getter_AddRefs(commonParent));        if (NS_FAILED(result)) return result;        if (!commonParent) return NS_ERROR_NULL_POINTER;        range->GetStartOffset(&startOffset);        range->GetEndOffset(&endOffset);        result = range->GetStartParent(getter_AddRefs(startParent));        if (NS_FAILED(result)) return result;        if (!startParent) return NS_ERROR_NULL_POINTER;        result = range->GetEndParent(getter_AddRefs(endParent));        if (NS_FAILED(result)) return result;        if (!endParent) return NS_ERROR_NULL_POINTER;        if (startParent.get()==endParent.get())         { // the range is entirely contained within a single text node          // commonParent==aStartParent, so get the "real" parent of the selection          startParent->GetParentNode(getter_AddRefs(commonParent));          result = RemoveTextPropertiesForNode(startParent, commonParent,                                                startOffset, endOffset,                                               aProperty, nsnull);        }        else        {          result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset,                                                                    endParent,  endOffset,                                                                   commonParent,                                                                   aProperty, nsnull);        }        if (NS_FAILED(result)) return result;        { // compute a range for the selection          // don't want to actually do anything with selection, because          // we are still iterating through it.  Just want to create and remember          // an nsIDOMRange, and later add the range to the selection after clearing it.          // XXX: I'm blocked here because nsIDOMSelection doesn't provide a mechanism          //      for setting a compound selection yet.        }      }      if (NS_SUCCEEDED(result))      {        result = CollapseAdjacentTextNodes(selection);  // we may have created wasteful consecutive text nodes.  collapse them.      }      if (NS_SUCCEEDED(result))      {         // XXX: ERROR_HANDLING should get a result and validate it        ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection);      }    }  }  if (!cancel)  {    // post-process     result = mRules->DidDoAction(selection, &ruleInfo, result);  }  if (gNoisy)   {     nsAutoString propString;    aProperty->ToString(propString);    char *propCString = propString.ToNewCString();    if (gNoisy) { printf("---------- end nsTextEditor::RemoveInlineProperty %s ----------\n", propCString); }    nsCRT::free(propCString);  }  return result;}