зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
a5a9edc3d6
Коммит
b259f714c6
|
@ -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);
|
||||
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче