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.
This commit is contained in:
buster%netscape.com 1999-02-22 15:53:31 +00:00
Родитель a5a9edc3d6
Коммит b259f714c6
20 изменённых файлов: 393 добавлений и 148 удалений

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

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

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

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