caught up to new ScrollIntoView changes.

most transactions now properly set selection after modifying content, for Do, Undo, Redo.
lots of cleanup and minor bug fixes.


git-svn-id: svn://10.0.0.236/trunk@21466 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
buster%netscape.com
1999-02-22 15:53:31 +00:00
parent 294ccdc501
commit fb7ad5c58c
20 changed files with 393 additions and 148 deletions

View File

@@ -17,21 +17,25 @@
*/
#include "CreateElementTxn.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMSelection.h"
#include "nsIEditorSupport.h"
CreateElementTxn::CreateElementTxn()
: EditTxn()
{
}
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
nsresult CreateElementTxn::Init(nsIEditor *aEditor,
const nsString& aTag,
nsIDOMNode *aParent,
PRUint32 aOffsetInParent)
{
if ((nsnull!=aDoc) && (nsnull!=aParent))
NS_ASSERTION(aEditor&&aParent, "null args");
if (aEditor && aParent)
{
mDoc = do_QueryInterface(aDoc);
mEditor = do_QueryInterface(aEditor);
mTag = aTag;
mParent = do_QueryInterface(aParent);
mOffsetInParent = aOffsetInParent;
@@ -57,28 +61,50 @@ CreateElementTxn::~CreateElementTxn()
nsresult CreateElementTxn::Do(void)
{
// create a new node
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
if ((NS_SUCCEEDED(result)) && (mNewNode))
NS_ASSERTION(mEditor, "bad state -- null editor");
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor)
{
// insert the new node
nsCOMPtr<nsIDOMNode> resultNode;
if (CreateElementTxn::eAppend==mOffsetInParent)
// create a new node
nsCOMPtr<nsIDOMDocument>doc;
result = mEditor->GetDocument(getter_AddRefs(doc));
if ((NS_SUCCEEDED(result)) && (doc))
{
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
}
else
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
result = doc->CreateElement(mTag, getter_AddRefs(mNewNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
if ((NS_SUCCEEDED(result)) && (mNewNode))
{
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
if ((NS_SUCCEEDED(result)) && (mRefNode))
// insert the new node
nsCOMPtr<nsIDOMNode> resultNode;
if (CreateElementTxn::eAppend==mOffsetInParent)
{
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
}
else
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
if ((NS_SUCCEEDED(result)) && (mRefNode))
{
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
}
}
}
}
@@ -90,6 +116,19 @@ nsresult CreateElementTxn::Undo(void)
{
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;
}
@@ -97,6 +136,19 @@ nsresult CreateElementTxn::Redo(void)
{
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
nsresult selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;
}

View File

@@ -20,7 +20,7 @@
#define CreateElementTxn_h__
#include "EditTxn.h"
#include "nsIDOMDocument.h"
#include "nsIEditor.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsCOMPtr.h"
@@ -40,13 +40,13 @@ public:
enum { eAppend=-1 };
/** Initialize the transaction.
* @param aDoc the document containing aParent
* @param aEditor the provider of basic editing functionality
* @param aTag the tag (P, HR, TABLE, etc.) for the new element
* @param aParent the node into which the new element will be inserted
* @param aOffsetInParent the location in aParent to insert the new element
* if eAppend, the new element is appended as the last child
*/
virtual nsresult Init(nsIDOMDocument *aDoc,
virtual nsresult Init(nsIEditor *aEditor,
const nsString& aTag,
nsIDOMNode *aParent,
PRUint32 aOffsetInParent);
@@ -75,7 +75,7 @@ public:
protected:
/** the document into which the new node will be inserted */
nsCOMPtr<nsIDOMDocument> mDoc;
nsCOMPtr<nsIEditor> mEditor;
/** the tag (mapping to object type) for the new element */
nsString mTag;

View File

@@ -231,7 +231,12 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
if (nsnull!=txn)
{
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
PRInt32 numToDel;
if (aStartOffset==aEndOffset)
numToDel = 1;
else
numToDel = aEndOffset-aStartOffset;
txn->Init(mEditor, textNode, aStartOffset, numToDel);
AppendChild(txn);
}
}
@@ -293,7 +298,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
if (nsnull!=txn)
{
txn->Init(textNode, start, numToDelete);
txn->Init(mEditor, textNode, start, numToDelete);
AppendChild(txn);
}
else

View File

@@ -18,6 +18,7 @@
#include "DeleteTextTxn.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMSelection.h"
DeleteTextTxn::DeleteTextTxn()
@@ -25,10 +26,13 @@ DeleteTextTxn::DeleteTextTxn()
{
}
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
nsresult DeleteTextTxn::Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
{
NS_ASSERTION(aEditor&&aElement, "bad arg");
mEditor = do_QueryInterface(aEditor);
mElement = do_QueryInterface(aElement);
mOffset = aOffset;
mNumCharsToDelete = aNumCharsToDelete;
@@ -38,15 +42,49 @@ nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
nsresult DeleteTextTxn::Do(void)
{
// get the text that we're about to delete
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
return (mElement->DeleteData(mOffset, mNumCharsToDelete));
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor && mElement)
{
// get the text that we're about to delete
result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
selectionResult = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
return result;
}
//XXX: we may want to store the selection state and restore it properly
// was it an insertion point or an extended selection?
nsresult DeleteTextTxn::Undo(void)
{
return (mElement->InsertData(mOffset, mDeletedText));
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor && mElement)
{
result = mElement->InsertData(mOffset, mDeletedText);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
selectionResult = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
return result;
}
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)

View File

@@ -20,6 +20,7 @@
#define DeleteTextTxn_h__
#include "EditTxn.h"
#include "nsIEditor.h"
#include "nsIDOMCharacterData.h"
#include "nsCOMPtr.h"
@@ -36,11 +37,13 @@ class DeleteTextTxn : public EditTxn
public:
/** initialize the transaction.
* @param aEditor the provider of basic editing operations
* @param aElement the content node to remove text from
* @param aOffset the location in aElement to begin the deletion
* @param aNumCharsToDelete the number of characters to delete. Not the number of bytes!
*/
virtual nsresult Init(nsIDOMCharacterData *aElement,
virtual nsresult Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete);
@@ -62,7 +65,10 @@ public:
virtual nsresult GetRedoString(nsString **aString);
protected:
/** the provider of basic editing operations */
nsCOMPtr<nsIEditor> mEditor;
/** the text element to operate upon */
nsCOMPtr<nsIDOMCharacterData> mElement;

View File

@@ -113,8 +113,12 @@ nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction
if (nsnull!=mChildren)
{
PRInt32 count = mChildren->Count();
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
result = txn->Merge(aDidMerge, aTransaction);
NS_ASSERTION(count>0, "bad count");
if (0<count)
{
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
result = txn->Merge(aDidMerge, aTransaction);
}
}
return result;

View File

@@ -56,16 +56,18 @@ nsresult InsertTextTxn::Do(void)
{
// advance caret: This requires the presentation shell to get the selection.
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = mPresShell->GetSelection(getter_AddRefs(selection));
selection->StartBatchChanges();
res = mElement->InsertData(mOffset, mStringToInsert);
if (NS_SUCCEEDED(res)) {
res = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n");
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
result = mElement->InsertData(mOffset, mStringToInsert);
if (NS_SUCCEEDED(result)) {
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
}
selection->EndBatchChanges();
}
else
NS_ASSERTION(PR_FALSE,"Could not get selection in InsertTextTxn::Do\n");
selection->EndBatchChanges();
return res;
return result;
}
nsresult InsertTextTxn::Undo(void)
@@ -77,8 +79,11 @@ nsresult InsertTextTxn::Undo(void)
{ // set the selection to the insertion point where the string was removed
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result)) {
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
result = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;

View File

@@ -711,7 +711,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag,
{
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn);
if (NS_SUCCEEDED(result)) {
result = (*aTxn)->Init(mDoc, aTag, aParent, aPosition);
result = (*aTxn)->Init(this, aTag, aParent, aPosition);
}
}
return result;
@@ -866,7 +866,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
{
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn);
if (NS_SUCCEEDED(result)) {
result = (*aTxn)->Init(aElement, aOffset, aLength);
result = (*aTxn)->Init(this, aElement, aOffset, aLength);
}
}
return result;
@@ -1486,6 +1486,40 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
return result;
}
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
{
NS_ASSERTION((aChild && aParent), "bad args");
nsresult result = NS_ERROR_NULL_POINTER;
if (aChild && aParent)
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRInt32 i=0;
for ( ; NS_SUCCEEDED(result); i++)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
if ((NS_SUCCEEDED(result)) && (childNode))
{
if (childNode.get()==aChild)
{
aOffset = i;
break;
}
}
else if (!childNode)
result = NS_ERROR_NULL_POINTER;
}
}
else if (!childNodes)
result = NS_ERROR_NULL_POINTER;
}
return result;
}
//END nsEditor Private methods

View File

@@ -65,6 +65,8 @@ public:
nsIDOMNode *aNodeToJoin,
nsIDOMNode *aParent,
PRBool aNodeToKeepIsFirst)=0;
static nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);

View File

@@ -17,6 +17,7 @@
*/
#include "nsTextEditor.h"
#include "nsIEditorSupport.h"
#include "nsEditorEventListeners.h"
#include "nsIDOMDocument.h"
#include "nsIDOMEventReceiver.h"
@@ -167,9 +168,6 @@ nsresult nsTextEditor::InsertText(const nsString& aStringToInsert)
if (mEditor)
{
result = mEditor->InsertText(aStringToInsert);
if (NS_SUCCEEDED(result)) {
mEditor->ScrollIntoView(PR_TRUE);
}
}
return result;
}
@@ -207,7 +205,7 @@ nsresult nsTextEditor::InsertBreak(PRBool aCtrlKey)
result = node->GetParentNode(getter_AddRefs(parentNode));
result = mEditor->SplitNode(node, offset);
// now get the node's offset in it's parent, and insert the new BR there
result = GetChildOffset(node, parentNode, offset);
result = nsIEditorSupport::GetChildOffset(node, parentNode, offset);
nsAutoString tag("BR");
result = mEditor->CreateNode(tag, parentNode, offset);
selection->Collapse(parentNode, offset);
@@ -232,12 +230,8 @@ nsresult nsTextEditor::EnableUndo(PRBool aEnable)
nsresult nsTextEditor::Undo(PRUint32 aCount)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
if (mEditor) {
result = mEditor->Undo(aCount);
if (NS_SUCCEEDED(result)) {
mEditor->ScrollIntoView(PR_TRUE);
}
}
return result;
}
@@ -258,9 +252,6 @@ nsresult nsTextEditor::Redo(PRUint32 aCount)
if (mEditor)
{
result = mEditor->Redo(aCount);
if (NS_SUCCEEDED(result)) {
mEditor->ScrollIntoView(PR_TRUE);
}
}
return result;
}
@@ -440,37 +431,3 @@ nsTextEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
}
// utility methods
nsresult nsTextEditor::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
{
NS_ASSERTION((aChild && aParent), "bad args");
nsresult result = NS_ERROR_NULL_POINTER;
if (aChild && aParent)
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRInt32 i=0;
for ( ; NS_SUCCEEDED(result); i++)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
if ((NS_SUCCEEDED(result)) && (childNode))
{
if (childNode.get()==aChild)
{
aOffset = i;
break;
}
}
else if (!childNode)
result = NS_ERROR_NULL_POINTER;
}
}
else if (!childNodes)
result = NS_ERROR_NULL_POINTER;
}
return result;
}

View File

@@ -77,10 +77,6 @@ public:
virtual nsresult OutputText(nsIOutputStream *aOutputStream);
virtual nsresult OutputHTML(nsIOutputStream *aOutputStream);
// Utility methods
protected:
virtual nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);
// Data members
protected:
nsCOMPtr<nsIEditor> mEditor;

View File

@@ -17,21 +17,25 @@
*/
#include "CreateElementTxn.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMSelection.h"
#include "nsIEditorSupport.h"
CreateElementTxn::CreateElementTxn()
: EditTxn()
{
}
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
nsresult CreateElementTxn::Init(nsIEditor *aEditor,
const nsString& aTag,
nsIDOMNode *aParent,
PRUint32 aOffsetInParent)
{
if ((nsnull!=aDoc) && (nsnull!=aParent))
NS_ASSERTION(aEditor&&aParent, "null args");
if (aEditor && aParent)
{
mDoc = do_QueryInterface(aDoc);
mEditor = do_QueryInterface(aEditor);
mTag = aTag;
mParent = do_QueryInterface(aParent);
mOffsetInParent = aOffsetInParent;
@@ -57,28 +61,50 @@ CreateElementTxn::~CreateElementTxn()
nsresult CreateElementTxn::Do(void)
{
// create a new node
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
if ((NS_SUCCEEDED(result)) && (mNewNode))
NS_ASSERTION(mEditor, "bad state -- null editor");
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor)
{
// insert the new node
nsCOMPtr<nsIDOMNode> resultNode;
if (CreateElementTxn::eAppend==mOffsetInParent)
// create a new node
nsCOMPtr<nsIDOMDocument>doc;
result = mEditor->GetDocument(getter_AddRefs(doc));
if ((NS_SUCCEEDED(result)) && (doc))
{
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
}
else
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
result = doc->CreateElement(mTag, getter_AddRefs(mNewNode));
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
if ((NS_SUCCEEDED(result)) && (mNewNode))
{
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
if ((NS_SUCCEEDED(result)) && (mRefNode))
// insert the new node
nsCOMPtr<nsIDOMNode> resultNode;
if (CreateElementTxn::eAppend==mOffsetInParent)
{
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
}
else
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
if ((NS_SUCCEEDED(result)) && (mRefNode))
{
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
}
}
}
}
@@ -90,6 +116,19 @@ nsresult CreateElementTxn::Undo(void)
{
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;
}
@@ -97,6 +136,19 @@ nsresult CreateElementTxn::Redo(void)
{
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
PRInt32 offset=0;
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
nsresult selectionResult = selection->Collapse(mParent, offset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;
}

View File

@@ -20,7 +20,7 @@
#define CreateElementTxn_h__
#include "EditTxn.h"
#include "nsIDOMDocument.h"
#include "nsIEditor.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
#include "nsCOMPtr.h"
@@ -40,13 +40,13 @@ public:
enum { eAppend=-1 };
/** Initialize the transaction.
* @param aDoc the document containing aParent
* @param aEditor the provider of basic editing functionality
* @param aTag the tag (P, HR, TABLE, etc.) for the new element
* @param aParent the node into which the new element will be inserted
* @param aOffsetInParent the location in aParent to insert the new element
* if eAppend, the new element is appended as the last child
*/
virtual nsresult Init(nsIDOMDocument *aDoc,
virtual nsresult Init(nsIEditor *aEditor,
const nsString& aTag,
nsIDOMNode *aParent,
PRUint32 aOffsetInParent);
@@ -75,7 +75,7 @@ public:
protected:
/** the document into which the new node will be inserted */
nsCOMPtr<nsIDOMDocument> mDoc;
nsCOMPtr<nsIEditor> mEditor;
/** the tag (mapping to object type) for the new element */
nsString mTag;

View File

@@ -231,7 +231,12 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
if (nsnull!=txn)
{
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
PRInt32 numToDel;
if (aStartOffset==aEndOffset)
numToDel = 1;
else
numToDel = aEndOffset-aStartOffset;
txn->Init(mEditor, textNode, aStartOffset, numToDel);
AppendChild(txn);
}
}
@@ -293,7 +298,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
if (nsnull!=txn)
{
txn->Init(textNode, start, numToDelete);
txn->Init(mEditor, textNode, start, numToDelete);
AppendChild(txn);
}
else

View File

@@ -18,6 +18,7 @@
#include "DeleteTextTxn.h"
#include "nsIDOMCharacterData.h"
#include "nsIDOMSelection.h"
DeleteTextTxn::DeleteTextTxn()
@@ -25,10 +26,13 @@ DeleteTextTxn::DeleteTextTxn()
{
}
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
nsresult DeleteTextTxn::Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete)
{
NS_ASSERTION(aEditor&&aElement, "bad arg");
mEditor = do_QueryInterface(aEditor);
mElement = do_QueryInterface(aElement);
mOffset = aOffset;
mNumCharsToDelete = aNumCharsToDelete;
@@ -38,15 +42,49 @@ nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
nsresult DeleteTextTxn::Do(void)
{
// get the text that we're about to delete
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
return (mElement->DeleteData(mOffset, mNumCharsToDelete));
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor && mElement)
{
// get the text that we're about to delete
result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
selectionResult = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
return result;
}
//XXX: we may want to store the selection state and restore it properly
// was it an insertion point or an extended selection?
nsresult DeleteTextTxn::Undo(void)
{
return (mElement->InsertData(mOffset, mDeletedText));
nsresult result = NS_ERROR_NULL_POINTER;
if (mEditor && mElement)
{
result = mElement->InsertData(mOffset, mDeletedText);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMSelection> selection;
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(selectionResult) && selection) {
selection->StartBatchChanges();
selectionResult = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
}
return result;
}
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)

View File

@@ -20,6 +20,7 @@
#define DeleteTextTxn_h__
#include "EditTxn.h"
#include "nsIEditor.h"
#include "nsIDOMCharacterData.h"
#include "nsCOMPtr.h"
@@ -36,11 +37,13 @@ class DeleteTextTxn : public EditTxn
public:
/** initialize the transaction.
* @param aEditor the provider of basic editing operations
* @param aElement the content node to remove text from
* @param aOffset the location in aElement to begin the deletion
* @param aNumCharsToDelete the number of characters to delete. Not the number of bytes!
*/
virtual nsresult Init(nsIDOMCharacterData *aElement,
virtual nsresult Init(nsIEditor *aEditor,
nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aNumCharsToDelete);
@@ -62,7 +65,10 @@ public:
virtual nsresult GetRedoString(nsString **aString);
protected:
/** the provider of basic editing operations */
nsCOMPtr<nsIEditor> mEditor;
/** the text element to operate upon */
nsCOMPtr<nsIDOMCharacterData> mElement;

View File

@@ -113,8 +113,12 @@ nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction
if (nsnull!=mChildren)
{
PRInt32 count = mChildren->Count();
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
result = txn->Merge(aDidMerge, aTransaction);
NS_ASSERTION(count>0, "bad count");
if (0<count)
{
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
result = txn->Merge(aDidMerge, aTransaction);
}
}
return result;

View File

@@ -56,16 +56,18 @@ nsresult InsertTextTxn::Do(void)
{
// advance caret: This requires the presentation shell to get the selection.
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = mPresShell->GetSelection(getter_AddRefs(selection));
selection->StartBatchChanges();
res = mElement->InsertData(mOffset, mStringToInsert);
if (NS_SUCCEEDED(res)) {
res = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n");
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
result = mElement->InsertData(mOffset, mStringToInsert);
if (NS_SUCCEEDED(result)) {
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
}
selection->EndBatchChanges();
}
else
NS_ASSERTION(PR_FALSE,"Could not get selection in InsertTextTxn::Do\n");
selection->EndBatchChanges();
return res;
return result;
}
nsresult InsertTextTxn::Undo(void)
@@ -77,8 +79,11 @@ nsresult InsertTextTxn::Undo(void)
{ // set the selection to the insertion point where the string was removed
nsCOMPtr<nsIDOMSelection> selection;
result = mPresShell->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result)) {
if (NS_SUCCEEDED(result) && selection) {
selection->StartBatchChanges();
result = selection->Collapse(mElement, mOffset);
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
selection->EndBatchChanges();
}
}
return result;

View File

@@ -711,7 +711,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag,
{
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn);
if (NS_SUCCEEDED(result)) {
result = (*aTxn)->Init(mDoc, aTag, aParent, aPosition);
result = (*aTxn)->Init(this, aTag, aParent, aPosition);
}
}
return result;
@@ -866,7 +866,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
{
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn);
if (NS_SUCCEEDED(result)) {
result = (*aTxn)->Init(aElement, aOffset, aLength);
result = (*aTxn)->Init(this, aElement, aOffset, aLength);
}
}
return result;
@@ -1486,6 +1486,40 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
return result;
}
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
{
NS_ASSERTION((aChild && aParent), "bad args");
nsresult result = NS_ERROR_NULL_POINTER;
if (aChild && aParent)
{
nsCOMPtr<nsIDOMNodeList> childNodes;
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
PRInt32 i=0;
for ( ; NS_SUCCEEDED(result); i++)
{
nsCOMPtr<nsIDOMNode> childNode;
result = childNodes->Item(i, getter_AddRefs(childNode));
if ((NS_SUCCEEDED(result)) && (childNode))
{
if (childNode.get()==aChild)
{
aOffset = i;
break;
}
}
else if (!childNode)
result = NS_ERROR_NULL_POINTER;
}
}
else if (!childNodes)
result = NS_ERROR_NULL_POINTER;
}
return result;
}
//END nsEditor Private methods

View File

@@ -65,6 +65,8 @@ public:
nsIDOMNode *aNodeToJoin,
nsIDOMNode *aParent,
PRBool aNodeToKeepIsFirst)=0;
static nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);