implemented simple cases of RemoveTextProperty. other cases are no-op'd now.

added aFirst out param to GetTextProperty, so the caller can know if the first character has the property in the case of aAny=true and aAll=false.
fixed a bunch of places where result was being used incorrectly as a return val from do_QueryInterface
some minor undo/redo fixes to split and join of interior nodes.
This commit is contained in:
buster%netscape.com 1999-04-04 18:01:35 +00:00
parent b249af5eeb
commit 16027c9454
24 changed files with 853 additions and 115 deletions

View File

@ -50,7 +50,7 @@ DeleteElementTxn::~DeleteElementTxn()
NS_IMETHODIMP DeleteElementTxn::Do(void)
{
if (gNoisy) { printf("Do Delete Element element = %p\n", mElement.get()); }
if (gNoisy) { printf("%p Do Delete Element element = %p\n", this, mElement.get()); }
if (!mElement)
return NS_ERROR_NULL_POINTER;
@ -65,12 +65,12 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
#ifdef NS_DEBUG
// begin debug output
nsCOMPtr<nsIDOMElement> element;
element = do_QueryInterface(mElement, &result);
element = do_QueryInterface(mElement);
nsAutoString elementTag="text node";
if (element)
element->GetTagName(elementTag);
nsCOMPtr<nsIDOMElement> parentElement;
parentElement = do_QueryInterface(mParent, &result);
parentElement = do_QueryInterface(mParent);
nsAutoString parentElementTag="text node";
if (parentElement)
parentElement->GetTagName(parentElementTag);
@ -80,7 +80,7 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
if (c&&p)
{
if (gNoisy)
printf("DeleteElementTxn: deleting child %s from parent %s\n", c, p);
printf(" DeleteElementTxn: deleting child %s from parent %s\n", c, p);
delete [] c;
delete [] p;
}
@ -97,10 +97,35 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
NS_IMETHODIMP DeleteElementTxn::Undo(void)
{
if (gNoisy) { printf("Do Delete Element element = %p, parent = %p\n", mElement.get(), mParent.get()); }
if (gNoisy) { printf("%p Undo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
#ifdef NS_DEBUG
// begin debug output
nsCOMPtr<nsIDOMElement> element;
element = do_QueryInterface(mElement);
nsAutoString elementTag="text node";
if (element)
element->GetTagName(elementTag);
nsCOMPtr<nsIDOMElement> parentElement;
parentElement = do_QueryInterface(mParent);
nsAutoString parentElementTag="text node";
if (parentElement)
parentElement->GetTagName(parentElementTag);
char *c, *p;
c = elementTag.ToNewCString();
p = parentElementTag.ToNewCString();
if (c&&p)
{
if (gNoisy)
printf(" DeleteElementTxn: inserting child %s back into parent %s\n", c, p);
delete [] c;
delete [] p;
}
// end debug output
#endif
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mElement, mRefNode, getter_AddRefs(resultNode));
return result;
@ -108,7 +133,7 @@ NS_IMETHODIMP DeleteElementTxn::Undo(void)
NS_IMETHODIMP DeleteElementTxn::Redo(void)
{
if (gNoisy) { printf("Redo Delete Element\n"); }
if (gNoisy) { printf("%p Redo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;

View File

@ -69,7 +69,7 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
{
PRUint32 count;
nsCOMPtr<nsIDOMCharacterData> textNode;
textNode = do_QueryInterface(mStartParent, &result);
textNode = do_QueryInterface(mStartParent);
if (textNode)
textNode->GetLength(&count);
else
@ -81,7 +81,7 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
}
NS_ASSERTION(mStartOffset<=(PRInt32)count, "bad start offset");
textNode = do_QueryInterface(mEndParent, &result);
textNode = do_QueryInterface(mEndParent);
if (textNode)
textNode->GetLength(&count);
else

View File

@ -36,9 +36,9 @@ DeleteTextTxn::~DeleteTextTxn()
}
NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
{
NS_ASSERTION(aEditor&&aElement, "bad arg");
mEditor = do_QueryInterface(aEditor);
@ -46,6 +46,10 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor,
mOffset = aOffset;
mNumCharsToDelete = aNumCharsToDelete;
NS_ASSERTION(0!=aNumCharsToDelete, "bad arg, numCharsToDelete");
PRUint32 count;
aElement->GetLength(&count);
NS_ASSERTION(count<aNumCharsToDelete, "bad arg, numCharsToDelete. Not enough characters in node");
NS_ASSERTION(count<aOffset+aNumCharsToDelete, "bad arg, numCharsToDelete. Not enough characters in node");
mDeletedText = "";
return NS_OK;
}

View File

@ -54,13 +54,14 @@ InsertElementTxn::~InsertElementTxn()
NS_IMETHODIMP InsertElementTxn::Do(void)
{
if (gNoisy) { printf("Do Insert Element\n"); }
if (gNoisy) { printf("%p Do Insert Element of %p into parent %p at offset %d\n",
this, mNode, mParent, mOffset); }
if (!mNode || !mParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
nsCOMPtr<nsIDOMNode>refNode;
if (0!=mOffset)
//if (0!=mOffset)
{ // get a ref node
PRInt32 i=0;
result = mParent->GetFirstChild(getter_AddRefs(refNode));
@ -94,7 +95,8 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
NS_IMETHODIMP InsertElementTxn::Undo(void)
{
if (gNoisy) { printf("Undo Insert Element\n"); }
if (gNoisy) { printf("%p Undo Insert Element of %p into parent %p at offset %d\n",
this, mNode, mParent, mOffset); }
if (!mNode || !mParent)
return NS_ERROR_NULL_POINTER;

View File

@ -135,7 +135,7 @@ NS_IMETHODIMP InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransacti
if (childTxn)
{
nsCOMPtr<InsertTextTxn> otherInsertTxn;
otherInsertTxn = do_QueryInterface(childTxn, &result);
otherInsertTxn = do_QueryInterface(childTxn);
if (otherInsertTxn)
{
if (PR_TRUE==IsSequentialInsert(otherInsertTxn))

View File

@ -23,7 +23,7 @@
#include "nsIEditorSupport.h"
#ifdef NS_DEBUG
static PRBool gNoisy = PR_TRUE;
static PRBool gNoisy = PR_FALSE;
#else
static const PRBool gNoisy = PR_FALSE;
#endif
@ -63,7 +63,7 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
if ((NS_SUCCEEDED(result)) && (mNewLeftNode))
{
if (gNoisy) { printf(" created left node = %p\n", this, mNewLeftNode.get()); }
if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); }
// get the parent node
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
// insert the new node
@ -103,21 +103,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
return NS_ERROR_NOT_INITIALIZED;
}
#ifdef NS_DEBUG
// sanity check
nsCOMPtr<nsIDOMNode>parent;
nsresult debugResult = mExistingRightNode->GetParentNode(getter_AddRefs(parent));
NS_ASSERTION((NS_SUCCEEDED(debugResult)), "bad GetParentNode result for right child");
NS_ASSERTION(parent, "bad GetParentNode for right child");
NS_ASSERTION(parent==mParent, "bad GetParentNode for right child, parents don't match");
debugResult = mNewLeftNode->GetParentNode(getter_AddRefs(parent));
NS_ASSERTION((NS_SUCCEEDED(debugResult)), "bad GetParentNode result for left child");
NS_ASSERTION(parent, "bad GetParentNode for left child");
NS_ASSERTION(parent==mParent, "bad GetParentNode for right child, left don't match");
#endif
// this assumes Do inserted the new node in front of the prior existing node
nsresult result;
nsCOMPtr<nsIEditorSupport> editor;
@ -125,6 +110,11 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
if (NS_SUCCEEDED(result) && editor)
{
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
if (gNoisy)
{
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
if (NS_SUCCEEDED(result))
{
if (gNoisy) { printf(" left node = %p removed\n", this, mNewLeftNode.get()); }
@ -154,6 +144,7 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (gNoisy) {
printf("%p Redo Split of existing node %p and new node %p offset %d\n",
this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset);
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
nsresult result;
nsCOMPtr<nsIDOMNode>resultNode;
@ -163,6 +154,11 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (rightNodeAsText)
{
result = rightNodeAsText->DeleteData(0, mOffset);
if (gNoisy)
{
printf("** after delete of text in right text node %p offset %d\n", rightNodeAsText.get(), mOffset);
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
}
else
{
@ -176,11 +172,25 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (!child) {return NS_ERROR_NULL_POINTER;}
child->GetNextSibling(getter_AddRefs(nextSibling));
result = mExistingRightNode->RemoveChild(child, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
result = mNewLeftNode->AppendChild(child, getter_AddRefs(resultNode));
if (gNoisy)
{
printf("** move child node %p from right node %p to left node %p\n", child.get(), mExistingRightNode.get(), mNewLeftNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
}
child = do_QueryInterface(nextSibling);
}
}
// second, re-insert the left node into the tree
result = mParent->InsertBefore(mNewLeftNode, mExistingRightNode, getter_AddRefs(resultNode));
if (gNoisy)
{
printf("** reinsert left child node %p before right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
return result;
}

View File

@ -1128,7 +1128,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
{
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection,&result);
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
@ -1144,8 +1144,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
result = range->GetStartParent(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && (node))
{
result = NS_ERROR_UNEXPECTED;
nodeAsText = do_QueryInterface(node,&result);
nodeAsText = do_QueryInterface(node);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
@ -1451,7 +1450,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection,&result);
enumerator = do_QueryInterface(selection);
if (enumerator)
{
for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
@ -1553,7 +1552,7 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
{ // there is a priorNode, so delete it's last child (if text content, delete the last char.)
// if it has no children, delete it
nsCOMPtr<nsIDOMCharacterData> priorNodeAsText;
priorNodeAsText = do_QueryInterface(priorNode, &result);
priorNodeAsText = do_QueryInterface(priorNode);
if (priorNodeAsText)
{
PRUint32 length=0;
@ -1590,7 +1589,7 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
{ // there is a priorNode, so delete it's last child (if text content, delete the last char.)
// if it has no children, delete it
nsCOMPtr<nsIDOMCharacterData> nextNodeAsText;
nextNodeAsText = do_QueryInterface(nextNode,&result);
nextNodeAsText = do_QueryInterface(nextNode);
if (nextNodeAsText)
{
PRUint32 length=0;
@ -1815,6 +1814,9 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
nsIDOMNode* aNewLeftNode,
nsIDOMNode* aParent)
{
printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset);
nsresult result;
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
(nsnull!=aNewLeftNode) &&
@ -1826,6 +1828,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
{
nsCOMPtr<nsIDOMNode> resultNode;
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
//printf(" after insert\n"); content->List(); // DEBUG
if (NS_SUCCEEDED(result))
{
// split the children between the 2 nodes
@ -1847,21 +1850,26 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
}
else
{ // otherwise it's an interior node, so shuffle around the children
// go through list backwards so deletes don't interfere with the iteration
nsCOMPtr<nsIDOMNodeList> childNodes;
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRInt32 i=0;
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
PRInt32 i=aOffset-1;
for ( ; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
if ((NS_SUCCEEDED(result)) && (childNode))
{
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
//printf(" after remove\n"); content->List(); // DEBUG
if (NS_SUCCEEDED(result))
{
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
nsCOMPtr<nsIDOMNode> firstChild;
aNewLeftNode->GetFirstChild(getter_AddRefs(firstChild));
result = aNewLeftNode->InsertBefore(childNode, firstChild, getter_AddRefs(resultNode));
//printf(" after append\n"); content->List(); // DEBUG
}
}
}
@ -1917,7 +1925,7 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRUint32 i;
PRInt32 i; // must be signed int!
PRUint32 childCount=0;
childNodes->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
@ -1927,7 +1935,9 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
}
nsCOMPtr<nsIDOMNode> resultNode;
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
// have to go through the list backwards to keep deletes from interfering with iteration
nsCOMPtr<nsIDOMNode> previousChild;
for (i=childCount-1; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
@ -1935,11 +1945,15 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
{
if (PR_TRUE==aNodeToKeepIsFirst)
{ // append children of aNodeToJoin
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
//was result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
result = aNodeToKeep->InsertBefore(childNode, previousChild, getter_AddRefs(resultNode));
previousChild = do_QueryInterface(childNode);
}
else
{ // prepend children of aNodeToJoin
//was result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
firstNode = do_QueryInterface(childNode);
}
}
}
@ -2047,6 +2061,28 @@ NS_IMETHODIMP nsEditor::GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayout
return result;
}
NS_IMETHODIMP
nsEditor::DebugDumpContent() const
{
nsCOMPtr<nsIContent>content;
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if (nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>bodyNode;
nodeList->Item(0, getter_AddRefs(bodyNode));
if (bodyNode) {
content = do_QueryInterface(bodyNode);
}
}
content->List();
return NS_OK;
}
//END nsEditor Private methods

View File

@ -60,13 +60,15 @@ private:
nsIPresShell *mPresShell;
nsIViewManager *mViewManager;
PRUint32 mUpdateCount;
nsCOMPtr<nsIDOMDocument> mDoc;
nsCOMPtr<nsITransactionManager> mTxnMgr;
friend PRBool NSCanUnload(nsISupports* serviceMgr);
static PRInt32 gInstanceCount;
protected:
nsCOMPtr<nsIDOMDocument> mDoc;
public:
/** The default constructor. This should suffice. the setting of the interfaces is done
* after the construction of the editor class.
@ -278,8 +280,6 @@ protected:
NS_IMETHOD GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
//Methods not exposed in nsIEditor
/** Create an aggregate transaction for deleting current selection
* Used by all methods that need to delete current selection,
* then insert something new to replace it
@ -290,6 +290,8 @@ protected:
*/
NS_IMETHOD CreateAggregateTxnForDeleteSelection(nsIAtom *aTxnName, EditAggregateTxn **aAggTxn);
NS_IMETHOD DebugDumpContent() const;
protected:
// XXXX: Horrible hack! We are doing this because
// of an error in Gecko which is not rendering the

View File

@ -310,7 +310,18 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::i);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::i, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::i);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::i);
}
}
}
@ -336,7 +347,18 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::b);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::b, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::b);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::b);
}
}
}
break;
@ -348,7 +370,19 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::u);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::u, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::u);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::u);
}
}
}
break;

View File

@ -113,9 +113,9 @@ NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty)
return nsTextEditor::SetTextProperty(aProperty);
}
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll)
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll)
{
return nsTextEditor::GetTextProperty(aProperty, aAny, aAll);
return nsTextEditor::GetTextProperty(aProperty, aFirst, aAny, aAll);
}
NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty)

View File

@ -51,7 +51,7 @@ public:
// Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll);
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty);
NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert);

View File

@ -96,6 +96,11 @@ static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
static NS_DEFINE_IID(kIContentIteratorIID, NS_ICONTENTITERTOR_IID);
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
#ifdef NS_DEBUG
static PRBool gNoisy = PR_FALSE;
#else
static const PRBool gNoisy = PR_FALSE;
#endif
/* ---------- TypeInState implementation ---------- */
// most methods are defined inline in TypeInState.h
@ -317,8 +322,8 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
{
nsEditor::BeginTransaction();
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection, &result);
if ((NS_SUCCEEDED(result)) && enumerator)
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
nsISupports *currentItem;
@ -401,7 +406,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
return result;
}
NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll)
NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll)
{
if (!aProperty)
return NS_ERROR_NULL_POINTER;
@ -409,13 +414,15 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PR
nsresult result=NS_ERROR_NOT_INITIALIZED;
aAny=PR_FALSE;
aAll=PR_TRUE;
aFirst=PR_FALSE;
PRBool first=PR_TRUE;
nsCOMPtr<nsIDOMSelection>selection;
result = nsEditor::GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection, &result);
if ((NS_SUCCEEDED(result)) && enumerator)
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
nsISupports *currentItem;
@ -448,6 +455,11 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PR
{
PRBool isSet;
IsTextPropertySetByContent(node, aProperty, isSet);
if (PR_TRUE==first)
{
aFirst = isSet;
first = PR_FALSE;
}
if (PR_TRUE==isSet) {
aAny = PR_TRUE;
}
@ -523,7 +535,107 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
{
return NS_ERROR_NOT_IMPLEMENTED;
if (!aProperty)
return NS_ERROR_NULL_POINTER;
nsresult result=NS_ERROR_NOT_INITIALIZED;
nsCOMPtr<nsIDOMSelection>selection;
result = nsEditor::GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
PRBool isCollapsed;
selection->IsCollapsed(&isCollapsed);
if (PR_TRUE==isCollapsed)
{
// manipulating text attributes on a collapsed selection only sets state for the next text insertion
SetTypeInStateForProperty(mTypeInState, aProperty);
}
else
{
nsEditor::BeginTransaction();
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
nsISupports *currentItem;
result = enumerator->CurrentItem(&currentItem);
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
{
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
nsCOMPtr<nsIDOMNode>commonParent;
result = range->GetCommonParent(getter_AddRefs(commonParent));
if ((NS_SUCCEEDED(result)) && commonParent)
{
PRInt32 startOffset, endOffset;
range->GetStartOffset(&startOffset);
range->GetEndOffset(&endOffset);
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
range->GetStartParent(getter_AddRefs(startParent));
range->GetEndParent(getter_AddRefs(endParent));
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);
}
else
{
nsCOMPtr<nsIDOMNode> startGrandParent;
startParent->GetParentNode(getter_AddRefs(startGrandParent));
nsCOMPtr<nsIDOMNode> endGrandParent;
endParent->GetParentNode(getter_AddRefs(endGrandParent));
if (NS_SUCCEEDED(result))
{
PRBool canCollapseStyleNode = PR_FALSE;
if (endGrandParent.get()==startGrandParent.get())
{
result = IntermediateNodesAreInline(range, startParent, startOffset,
endParent, endOffset,
startGrandParent, canCollapseStyleNode);
}
if (NS_SUCCEEDED(result))
{
if (PR_TRUE==canCollapseStyleNode)
{ // the range is between 2 nodes that have a common (immediate) grandparent,
// and any intermediate nodes are just inline style nodes
result = RemoveTextPropertiesForNodesWithSameParent(startParent,startOffset,
endParent, endOffset,
commonParent,
aProperty);
}
else
{ // the range is between 2 nodes that have no simple relationship
result = RemoveTextPropertiesForNodeWithDifferentParents(range,
startParent,startOffset,
endParent, endOffset,
commonParent,
aProperty);
}
}
}
}
if (NS_SUCCEEDED(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.
}
}
}
}
nsEditor::EndTransaction();
}
if (NS_SUCCEEDED(result))
{ // set the selection
// XXX: can't do anything until I can create ranges
}
}
return result;
}
NS_IMETHODIMP nsTextEditor::DeleteSelection(nsIEditor::Direction aDir)
@ -1255,6 +1367,382 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
return result;
}
NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsIAtom *aPropName)
{
nsresult result=NS_OK;
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
nodeAsChar = do_QueryInterface(aNode);
if (!nodeAsChar)
return NS_ERROR_FAILURE;
PRBool textPropertySet;
IsTextPropertySetByContent(aNode, aPropName, textPropertySet);
if (PR_TRUE==textPropertySet)
{
PRUint32 count;
nodeAsChar->GetLength(&count);
// split the node, and all parent nodes up to the style node
// then promote the selected content to the parent of the style node
nsCOMPtr<nsIDOMNode>newLeftNode; // this will be the leftmost node,
// the node being split will be rightmost
if (0!=aStartOffset) {
printf("* splitting text node %p at %d\n", aNode, aStartOffset);
result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newLeftNode));
printf("* split created left node %p\n", newLeftNode.get());
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newMiddleNode; // this will be the middle node
if ((PRInt32)count!=aEndOffset) {
printf("* splitting text node (right node) %p at %d\n", aNode, aEndOffset-aStartOffset);
result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newMiddleNode));
printf("* split created middle node %p\n", newMiddleNode.get());
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
else {
printf("* no need to split text node\n");
newMiddleNode = do_QueryInterface(aNode);
}
NS_ASSERTION(newMiddleNode, "no middle node created");
// now that the text node is split, split parent nodes until we get to the style node
nsCOMPtr<nsIDOMNode>parent;
parent = do_QueryInterface(aParent); // we know this has to succeed, no need to check
if (NS_SUCCEEDED(result) && newMiddleNode)
{
// split every ancestor until we find the node that is giving us the style we want to remove
// then split the style node and promote the selected content to the style node's parent
while (NS_SUCCEEDED(result) && parent)
{
printf("* looking at parent %p\n", parent);
// get the tag from parent and see if we're done
nsCOMPtr<nsIDOMNode>temp;
nsCOMPtr<nsIDOMElement>element;
element = do_QueryInterface(parent);
if (element)
{
nsAutoString tag;
result = element->GetTagName(tag);
printf("* parent has tag %s\n", tag.ToNewCString()); // leak!
if (NS_SUCCEEDED(result))
{
if (PR_FALSE==tag.Equals(aPropName))
{
printf("* this is not the style node\n");
PRInt32 offsetInParent;
result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent);
if (NS_SUCCEEDED(result))
{
if (0!=offsetInParent) {
printf("* splitting parent %p at offset %d\n", parent, offsetInParent);
result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode));
printf("* split created left node %p sibling of parent\n", newLeftNode.get());
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNodeList>childNodes;
result = parent->GetChildNodes(getter_AddRefs(childNodes));
if (NS_SUCCEEDED(result) && childNodes)
{
childNodes->GetLength(&count);
NS_ASSERTION(count>0, "bad child count in newly split node");
if ((PRInt32)count!=1)
{
printf("* splitting parent %p at offset %d\n", parent, 1);
result = nsEditor::SplitNode(parent, 1, getter_AddRefs(newMiddleNode));
printf("* split created middle node %p sibling of parent\n", newMiddleNode.get());
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
else {
printf("* no need to split parent, newMiddleNode=parent\n");
newMiddleNode = do_QueryInterface(parent);
}
NS_ASSERTION(newMiddleNode, "no middle node created");
parent->GetParentNode(getter_AddRefs(temp));
parent = do_QueryInterface(temp);
}
}
}
}
// else we've found the style tag (referred to by "parent")
// nwMiddleNode is the node that is an ancestor to the selection
else
{
printf("* this is the style node\n");
PRInt32 offsetInParent;
result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNodeList>childNodes;
result = parent->GetChildNodes(getter_AddRefs(childNodes));
if (NS_SUCCEEDED(result) && childNodes)
{
childNodes->GetLength(&count);
if (0!=offsetInParent && ((PRInt32)count!=offsetInParent+1)) {
printf("* splitting parent %p at offset %d\n", parent, offsetInParent);
result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode));
printf("* split created left node %p sibling of parent\n", newLeftNode.get());
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
if (NS_SUCCEEDED(result))
{ // promote the selection to the grandparent
nsCOMPtr<nsIDOMNode>grandParent;
result = parent->GetParentNode(getter_AddRefs(grandParent));
if (NS_SUCCEEDED(result) && grandParent)
{
printf("* deleting middle node %p\n", newMiddleNode.get());
result = nsEditor::DeleteNode(newMiddleNode);
if (gNoisy) {DebugDumpContent(); } // DEBUG
if (NS_SUCCEEDED(result))
{
PRInt32 position;
result = nsIEditorSupport::GetChildOffset(parent, grandParent, position);
if (NS_SUCCEEDED(result))
{
printf("* inserting node %p in grandparent %p at offset %d\n",
newMiddleNode.get(), grandParent.get(), position);
result = nsEditor::InsertNode(newMiddleNode, grandParent, position);
if (gNoisy) {DebugDumpContent(); } // DEBUG
if (NS_SUCCEEDED(result))
{
PRBool hasChildren=PR_TRUE;
parent->HasChildNodes(&hasChildren);
if (PR_FALSE==hasChildren) {
printf("* deleting empty style node %p\n", parent.get());
result = nsEditor::DeleteNode(parent);
if (gNoisy) {DebugDumpContent(); } // DEBUG
}
}
}
}
}
}
}
}
break;
}
}
}
}
}
}
}
return result;
}
/* this should only get called if the only intervening nodes are inline style nodes */
NS_IMETHODIMP
nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
nsIAtom *aPropName)
{
printf("not yet implemented\n");
return NS_OK;
nsresult result=NS_OK;
PRBool textPropertySet;
IsTextPropertySetByContent(aStartNode, aPropName, textPropertySet);
if (PR_FALSE==textPropertySet)
{
nsCOMPtr<nsIDOMNode>newLeftTextNode; // this will be the middle text node
if (0!=aStartOffset) {
result = nsEditor::SplitNode(aStartNode, aStartOffset, getter_AddRefs(newLeftTextNode));
}
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMCharacterData>endNodeAsChar;
endNodeAsChar = do_QueryInterface(aEndNode);
if (!endNodeAsChar)
return NS_ERROR_FAILURE;
PRUint32 count;
endNodeAsChar->GetLength(&count);
nsCOMPtr<nsIDOMNode>newRightTextNode; // this will be the middle text node
if ((PRInt32)count!=aEndOffset) {
result = nsEditor::SplitNode(aEndNode, aEndOffset, getter_AddRefs(newRightTextNode));
}
else {
newRightTextNode = do_QueryInterface(aEndNode);
}
if (NS_SUCCEEDED(result))
{
PRInt32 offsetInParent;
if (newLeftTextNode) {
result = nsIEditorSupport::GetChildOffset(newLeftTextNode, aParent, offsetInParent);
}
else {
offsetInParent = -1; // relies on +1 below in call to CreateNode
}
if (NS_SUCCEEDED(result))
{
nsAutoString tag;
aPropName->ToString(tag);
// create the new style node, which will be the new parent for the selected nodes
nsCOMPtr<nsIDOMNode>newStyleNode;
result = nsEditor::CreateNode(tag, aParent, offsetInParent+1, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result))
{ // move the right half of the start node into the new style node
nsCOMPtr<nsIDOMNode>intermediateNode;
result = aStartNode->GetNextSibling(getter_AddRefs(intermediateNode));
if (NS_SUCCEEDED(result))
{
result = nsEditor::DeleteNode(aStartNode);
if (NS_SUCCEEDED(result))
{
PRInt32 childIndex=0;
result = nsEditor::InsertNode(aStartNode, newStyleNode, childIndex);
childIndex++;
if (NS_SUCCEEDED(result))
{ // move all the intermediate nodes into the new style node
nsCOMPtr<nsIDOMNode>nextSibling;
while (intermediateNode.get() != aEndNode)
{
if (!intermediateNode)
result = NS_ERROR_NULL_POINTER;
if (NS_FAILED(result)) {
break;
}
// get the next sibling before moving the current child!!!
intermediateNode->GetNextSibling(getter_AddRefs(nextSibling));
result = nsEditor::DeleteNode(intermediateNode);
if (NS_SUCCEEDED(result)) {
result = nsEditor::InsertNode(intermediateNode, newStyleNode, childIndex);
childIndex++;
}
intermediateNode = do_QueryInterface(nextSibling);
}
if (NS_SUCCEEDED(result))
{ // move the left half of the end node into the new style node
result = nsEditor::DeleteNode(newRightTextNode);
if (NS_SUCCEEDED(result))
{
result = nsEditor::InsertNode(newRightTextNode, newStyleNode, childIndex);
}
}
}
}
}
}
}
}
}
}
return result;
}
NS_IMETHODIMP
nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
nsIAtom *aPropName)
{
printf("not yet implemented\n");
return NS_OK;
nsresult result=NS_OK;
if (!aRange || !aStartNode || !aEndNode || !aParent || !aPropName)
return NS_ERROR_NULL_POINTER;
// create a style node for the text in the start parent
nsCOMPtr<nsIDOMNode>parent;
result = aStartNode->GetParentNode(getter_AddRefs(parent));
if (NS_FAILED(result)) {
return result;
}
// create style nodes for all the content between the start and end nodes
nsCOMPtr<nsIContentIterator>iter;
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
kIContentIteratorIID, getter_AddRefs(iter));
if ((NS_SUCCEEDED(result)) && iter)
{
nsCOMPtr<nsIContent>startContent;
startContent = do_QueryInterface(aStartNode);
nsCOMPtr<nsIContent>endContent;
endContent = do_QueryInterface(aEndNode);
if (startContent && endContent)
{
iter->Init(aRange);
nsCOMPtr<nsIContent> content;
iter->CurrentNode(getter_AddRefs(content));
nsAutoString tag;
aPropName->ToString(tag);
while (NS_COMFALSE == iter->IsDone())
{
if ((content.get() != startContent.get()) &&
(content.get() != endContent.get()))
{
nsCOMPtr<nsIDOMCharacterData>charNode;
charNode = do_QueryInterface(content);
if (charNode)
{
// only want to wrap the text node in a new style node if it doesn't already have that style
nsCOMPtr<nsIDOMNode>node;
node = do_QueryInterface(content);
PRBool textPropertySet;
IsTextPropertySetByContent(node, aPropName, textPropertySet);
if (PR_FALSE==textPropertySet)
{
nsCOMPtr<nsIDOMNode>parent;
charNode->GetParentNode(getter_AddRefs(parent));
if (!parent) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIContent>parentContent;
parentContent = do_QueryInterface(parent);
PRInt32 offsetInParent;
parentContent->IndexOf(content, offsetInParent);
nsCOMPtr<nsIDOMNode>newStyleNode;
result = nsEditor::CreateNode(tag, parent, offsetInParent, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result) && newStyleNode) {
nsCOMPtr<nsIDOMNode>contentNode;
contentNode = do_QueryInterface(content);
result = nsEditor::DeleteNode(contentNode);
if (NS_SUCCEEDED(result)) {
result = nsEditor::InsertNode(contentNode, newStyleNode, 0);
}
}
}
}
}
// note we don't check the result, we just rely on iter->IsDone
iter->Next();
result = iter->CurrentNode(getter_AddRefs(content));
}
}
}
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
nodeAsChar = do_QueryInterface(aStartNode);
if (!nodeAsChar)
return NS_ERROR_FAILURE;
PRUint32 count;
nodeAsChar->GetLength(&count);
result = SetTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName);
// create a style node for the text in the end parent
result = aEndNode->GetParentNode(getter_AddRefs(parent));
if (NS_FAILED(result)) {
return result;
}
nodeAsChar = do_QueryInterface(aEndNode);
if (!nodeAsChar)
return NS_ERROR_FAILURE;
nodeAsChar->GetLength(&count);
result = SetTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName);
return result;
}
NS_IMETHODIMP
nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPropName)
{
@ -1271,7 +1759,8 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro
{ // get the current style and set boldness to the opposite of the current state
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
GetTextProperty(aPropName, any, all); // operates on current selection
PRBool first = PR_FALSE;
GetTextProperty(aPropName, first, any, all); // operates on current selection
aTypeInState.SetBold(!any);
}
}
@ -1285,7 +1774,8 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro
{ // get the current style and set boldness to the opposite of the current state
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
GetTextProperty(aPropName, any, all); // operates on current selection
PRBool first = PR_FALSE;
GetTextProperty(aPropName, first, any, all); // operates on current selection
aTypeInState.SetItalic(!any);
}
}

View File

@ -52,7 +52,7 @@ public:
// Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll);
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty);
NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert);
@ -137,6 +137,28 @@ protected:
nsIDOMNode *aParent,
nsIAtom *aPropName);
NS_IMETHOD RemoveTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsIAtom *aPropName);
NS_IMETHOD RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
nsIAtom *aPropName);
NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
nsIAtom *aPropName);
NS_IMETHOD SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPropName);

View File

@ -50,7 +50,7 @@ DeleteElementTxn::~DeleteElementTxn()
NS_IMETHODIMP DeleteElementTxn::Do(void)
{
if (gNoisy) { printf("Do Delete Element element = %p\n", mElement.get()); }
if (gNoisy) { printf("%p Do Delete Element element = %p\n", this, mElement.get()); }
if (!mElement)
return NS_ERROR_NULL_POINTER;
@ -65,12 +65,12 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
#ifdef NS_DEBUG
// begin debug output
nsCOMPtr<nsIDOMElement> element;
element = do_QueryInterface(mElement, &result);
element = do_QueryInterface(mElement);
nsAutoString elementTag="text node";
if (element)
element->GetTagName(elementTag);
nsCOMPtr<nsIDOMElement> parentElement;
parentElement = do_QueryInterface(mParent, &result);
parentElement = do_QueryInterface(mParent);
nsAutoString parentElementTag="text node";
if (parentElement)
parentElement->GetTagName(parentElementTag);
@ -80,7 +80,7 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
if (c&&p)
{
if (gNoisy)
printf("DeleteElementTxn: deleting child %s from parent %s\n", c, p);
printf(" DeleteElementTxn: deleting child %s from parent %s\n", c, p);
delete [] c;
delete [] p;
}
@ -97,10 +97,35 @@ NS_IMETHODIMP DeleteElementTxn::Do(void)
NS_IMETHODIMP DeleteElementTxn::Undo(void)
{
if (gNoisy) { printf("Do Delete Element element = %p, parent = %p\n", mElement.get(), mParent.get()); }
if (gNoisy) { printf("%p Undo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
#ifdef NS_DEBUG
// begin debug output
nsCOMPtr<nsIDOMElement> element;
element = do_QueryInterface(mElement);
nsAutoString elementTag="text node";
if (element)
element->GetTagName(elementTag);
nsCOMPtr<nsIDOMElement> parentElement;
parentElement = do_QueryInterface(mParent);
nsAutoString parentElementTag="text node";
if (parentElement)
parentElement->GetTagName(parentElementTag);
char *c, *p;
c = elementTag.ToNewCString();
p = parentElementTag.ToNewCString();
if (c&&p)
{
if (gNoisy)
printf(" DeleteElementTxn: inserting child %s back into parent %s\n", c, p);
delete [] c;
delete [] p;
}
// end debug output
#endif
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mElement, mRefNode, getter_AddRefs(resultNode));
return result;
@ -108,7 +133,7 @@ NS_IMETHODIMP DeleteElementTxn::Undo(void)
NS_IMETHODIMP DeleteElementTxn::Redo(void)
{
if (gNoisy) { printf("Redo Delete Element\n"); }
if (gNoisy) { printf("%p Redo Delete Element element = %p, parent = %p\n", this, mElement.get(), mParent.get()); }
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;

View File

@ -69,7 +69,7 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
{
PRUint32 count;
nsCOMPtr<nsIDOMCharacterData> textNode;
textNode = do_QueryInterface(mStartParent, &result);
textNode = do_QueryInterface(mStartParent);
if (textNode)
textNode->GetLength(&count);
else
@ -81,7 +81,7 @@ NS_IMETHODIMP DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
}
NS_ASSERTION(mStartOffset<=(PRInt32)count, "bad start offset");
textNode = do_QueryInterface(mEndParent, &result);
textNode = do_QueryInterface(mEndParent);
if (textNode)
textNode->GetLength(&count);
else

View File

@ -36,9 +36,9 @@ DeleteTextTxn::~DeleteTextTxn()
}
NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
{
NS_ASSERTION(aEditor&&aElement, "bad arg");
mEditor = do_QueryInterface(aEditor);
@ -46,6 +46,10 @@ NS_IMETHODIMP DeleteTextTxn::Init(nsIEditor *aEditor,
mOffset = aOffset;
mNumCharsToDelete = aNumCharsToDelete;
NS_ASSERTION(0!=aNumCharsToDelete, "bad arg, numCharsToDelete");
PRUint32 count;
aElement->GetLength(&count);
NS_ASSERTION(count<aNumCharsToDelete, "bad arg, numCharsToDelete. Not enough characters in node");
NS_ASSERTION(count<aOffset+aNumCharsToDelete, "bad arg, numCharsToDelete. Not enough characters in node");
mDeletedText = "";
return NS_OK;
}

View File

@ -54,13 +54,14 @@ InsertElementTxn::~InsertElementTxn()
NS_IMETHODIMP InsertElementTxn::Do(void)
{
if (gNoisy) { printf("Do Insert Element\n"); }
if (gNoisy) { printf("%p Do Insert Element of %p into parent %p at offset %d\n",
this, mNode, mParent, mOffset); }
if (!mNode || !mParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
nsCOMPtr<nsIDOMNode>refNode;
if (0!=mOffset)
//if (0!=mOffset)
{ // get a ref node
PRInt32 i=0;
result = mParent->GetFirstChild(getter_AddRefs(refNode));
@ -94,7 +95,8 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
NS_IMETHODIMP InsertElementTxn::Undo(void)
{
if (gNoisy) { printf("Undo Insert Element\n"); }
if (gNoisy) { printf("%p Undo Insert Element of %p into parent %p at offset %d\n",
this, mNode, mParent, mOffset); }
if (!mNode || !mParent)
return NS_ERROR_NULL_POINTER;

View File

@ -135,7 +135,7 @@ NS_IMETHODIMP InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransacti
if (childTxn)
{
nsCOMPtr<InsertTextTxn> otherInsertTxn;
otherInsertTxn = do_QueryInterface(childTxn, &result);
otherInsertTxn = do_QueryInterface(childTxn);
if (otherInsertTxn)
{
if (PR_TRUE==IsSequentialInsert(otherInsertTxn))

View File

@ -23,7 +23,7 @@
#include "nsIEditorSupport.h"
#ifdef NS_DEBUG
static PRBool gNoisy = PR_TRUE;
static PRBool gNoisy = PR_FALSE;
#else
static const PRBool gNoisy = PR_FALSE;
#endif
@ -63,7 +63,7 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
if ((NS_SUCCEEDED(result)) && (mNewLeftNode))
{
if (gNoisy) { printf(" created left node = %p\n", this, mNewLeftNode.get()); }
if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); }
// get the parent node
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
// insert the new node
@ -103,21 +103,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
return NS_ERROR_NOT_INITIALIZED;
}
#ifdef NS_DEBUG
// sanity check
nsCOMPtr<nsIDOMNode>parent;
nsresult debugResult = mExistingRightNode->GetParentNode(getter_AddRefs(parent));
NS_ASSERTION((NS_SUCCEEDED(debugResult)), "bad GetParentNode result for right child");
NS_ASSERTION(parent, "bad GetParentNode for right child");
NS_ASSERTION(parent==mParent, "bad GetParentNode for right child, parents don't match");
debugResult = mNewLeftNode->GetParentNode(getter_AddRefs(parent));
NS_ASSERTION((NS_SUCCEEDED(debugResult)), "bad GetParentNode result for left child");
NS_ASSERTION(parent, "bad GetParentNode for left child");
NS_ASSERTION(parent==mParent, "bad GetParentNode for right child, left don't match");
#endif
// this assumes Do inserted the new node in front of the prior existing node
nsresult result;
nsCOMPtr<nsIEditorSupport> editor;
@ -125,6 +110,11 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
if (NS_SUCCEEDED(result) && editor)
{
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
if (gNoisy)
{
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
if (NS_SUCCEEDED(result))
{
if (gNoisy) { printf(" left node = %p removed\n", this, mNewLeftNode.get()); }
@ -154,6 +144,7 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (gNoisy) {
printf("%p Redo Split of existing node %p and new node %p offset %d\n",
this, mExistingRightNode.get(), mNewLeftNode.get(), mOffset);
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
nsresult result;
nsCOMPtr<nsIDOMNode>resultNode;
@ -163,6 +154,11 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (rightNodeAsText)
{
result = rightNodeAsText->DeleteData(0, mOffset);
if (gNoisy)
{
printf("** after delete of text in right text node %p offset %d\n", rightNodeAsText.get(), mOffset);
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
}
else
{
@ -176,11 +172,25 @@ NS_IMETHODIMP SplitElementTxn::Redo(void)
if (!child) {return NS_ERROR_NULL_POINTER;}
child->GetNextSibling(getter_AddRefs(nextSibling));
result = mExistingRightNode->RemoveChild(child, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
result = mNewLeftNode->AppendChild(child, getter_AddRefs(resultNode));
if (gNoisy)
{
printf("** move child node %p from right node %p to left node %p\n", child.get(), mExistingRightNode.get(), mNewLeftNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
}
child = do_QueryInterface(nextSibling);
}
}
// second, re-insert the left node into the tree
result = mParent->InsertBefore(mNewLeftNode, mExistingRightNode, getter_AddRefs(resultNode));
if (gNoisy)
{
printf("** reinsert left child node %p before right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
if (gNoisy) {mEditor->DebugDumpContent(); } // DEBUG
}
return result;
}

View File

@ -1128,7 +1128,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
{
result = NS_ERROR_UNEXPECTED;
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection,&result);
enumerator = do_QueryInterface(selection);
if (enumerator)
{
enumerator->First();
@ -1144,8 +1144,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
result = range->GetStartParent(getter_AddRefs(node));
if ((NS_SUCCEEDED(result)) && (node))
{
result = NS_ERROR_UNEXPECTED;
nodeAsText = do_QueryInterface(node,&result);
nodeAsText = do_QueryInterface(node);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
@ -1451,7 +1450,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection,&result);
enumerator = do_QueryInterface(selection);
if (enumerator)
{
for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
@ -1553,7 +1552,7 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
{ // there is a priorNode, so delete it's last child (if text content, delete the last char.)
// if it has no children, delete it
nsCOMPtr<nsIDOMCharacterData> priorNodeAsText;
priorNodeAsText = do_QueryInterface(priorNode, &result);
priorNodeAsText = do_QueryInterface(priorNode);
if (priorNodeAsText)
{
PRUint32 length=0;
@ -1590,7 +1589,7 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
{ // there is a priorNode, so delete it's last child (if text content, delete the last char.)
// if it has no children, delete it
nsCOMPtr<nsIDOMCharacterData> nextNodeAsText;
nextNodeAsText = do_QueryInterface(nextNode,&result);
nextNodeAsText = do_QueryInterface(nextNode);
if (nextNodeAsText)
{
PRUint32 length=0;
@ -1815,6 +1814,9 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
nsIDOMNode* aNewLeftNode,
nsIDOMNode* aParent)
{
printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset);
nsresult result;
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
(nsnull!=aNewLeftNode) &&
@ -1826,6 +1828,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
{
nsCOMPtr<nsIDOMNode> resultNode;
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
//printf(" after insert\n"); content->List(); // DEBUG
if (NS_SUCCEEDED(result))
{
// split the children between the 2 nodes
@ -1847,21 +1850,26 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
}
else
{ // otherwise it's an interior node, so shuffle around the children
// go through list backwards so deletes don't interfere with the iteration
nsCOMPtr<nsIDOMNodeList> childNodes;
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRInt32 i=0;
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
PRInt32 i=aOffset-1;
for ( ; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
if ((NS_SUCCEEDED(result)) && (childNode))
{
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
//printf(" after remove\n"); content->List(); // DEBUG
if (NS_SUCCEEDED(result))
{
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
nsCOMPtr<nsIDOMNode> firstChild;
aNewLeftNode->GetFirstChild(getter_AddRefs(firstChild));
result = aNewLeftNode->InsertBefore(childNode, firstChild, getter_AddRefs(resultNode));
//printf(" after append\n"); content->List(); // DEBUG
}
}
}
@ -1917,7 +1925,7 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRUint32 i;
PRInt32 i; // must be signed int!
PRUint32 childCount=0;
childNodes->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
@ -1927,7 +1935,9 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
}
nsCOMPtr<nsIDOMNode> resultNode;
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
// have to go through the list backwards to keep deletes from interfering with iteration
nsCOMPtr<nsIDOMNode> previousChild;
for (i=childCount-1; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
@ -1935,11 +1945,15 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
{
if (PR_TRUE==aNodeToKeepIsFirst)
{ // append children of aNodeToJoin
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
//was result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
result = aNodeToKeep->InsertBefore(childNode, previousChild, getter_AddRefs(resultNode));
previousChild = do_QueryInterface(childNode);
}
else
{ // prepend children of aNodeToJoin
//was result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
firstNode = do_QueryInterface(childNode);
}
}
}
@ -2047,6 +2061,28 @@ NS_IMETHODIMP nsEditor::GetLayoutObject(nsIDOMNode *aNode, nsISupports **aLayout
return result;
}
NS_IMETHODIMP
nsEditor::DebugDumpContent() const
{
nsCOMPtr<nsIContent>content;
nsCOMPtr<nsIDOMNodeList>nodeList;
nsAutoString bodyTag = "body";
mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
if (nodeList)
{
PRUint32 count;
nodeList->GetLength(&count);
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
nsCOMPtr<nsIDOMNode>bodyNode;
nodeList->Item(0, getter_AddRefs(bodyNode));
if (bodyNode) {
content = do_QueryInterface(bodyNode);
}
}
content->List();
return NS_OK;
}
//END nsEditor Private methods

View File

@ -60,13 +60,15 @@ private:
nsIPresShell *mPresShell;
nsIViewManager *mViewManager;
PRUint32 mUpdateCount;
nsCOMPtr<nsIDOMDocument> mDoc;
nsCOMPtr<nsITransactionManager> mTxnMgr;
friend PRBool NSCanUnload(nsISupports* serviceMgr);
static PRInt32 gInstanceCount;
protected:
nsCOMPtr<nsIDOMDocument> mDoc;
public:
/** The default constructor. This should suffice. the setting of the interfaces is done
* after the construction of the editor class.
@ -278,8 +280,6 @@ protected:
NS_IMETHOD GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
//Methods not exposed in nsIEditor
/** Create an aggregate transaction for deleting current selection
* Used by all methods that need to delete current selection,
* then insert something new to replace it
@ -290,6 +290,8 @@ protected:
*/
NS_IMETHOD CreateAggregateTxnForDeleteSelection(nsIAtom *aTxnName, EditAggregateTxn **aAggTxn);
NS_IMETHOD DebugDumpContent() const;
protected:
// XXXX: Horrible hack! We are doing this because
// of an error in Gecko which is not rendering the

View File

@ -113,9 +113,9 @@ NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty)
return nsTextEditor::SetTextProperty(aProperty);
}
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll)
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll)
{
return nsTextEditor::GetTextProperty(aProperty, aAny, aAll);
return nsTextEditor::GetTextProperty(aProperty, aFirst, aAny, aAll);
}
NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty)

View File

@ -51,7 +51,7 @@ public:
// Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll);
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll);
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty);
NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert);

View File

@ -310,7 +310,18 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::i);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::i, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::i);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::i);
}
}
}
@ -336,7 +347,18 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::b);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::b, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::b);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::b);
}
}
}
break;
@ -348,7 +370,19 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
aProcessed=PR_TRUE;
if (mEditor)
{
mEditor->SetTextProperty(nsIEditProperty::u);
// XXX: move this logic down into texteditor rules delegate
// should just call mEditor->ChangeTextProperty(prop)
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
mEditor->GetTextProperty(nsIEditProperty::u, first, any, all);
if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::u);
}
else {
mEditor->RemoveTextProperty(nsIEditProperty::u);
}
}
}
break;