зеркало из https://github.com/mozilla/pjs.git
Highlights:
updated to new nsCOMPtr usage nsTextEditor::InsertBreak() implemented splits the text node at the caret (deletes any extended selection to force a collapsed selection.) inserts a <BR> which I assume we'll convert to a CR when we write to a text stream. undo and redo work, except for the bug noted below More stuff: interface cleanup strategic debugging code added delete selection txn sets the collapses the selection...this is just a placeholder, but I needed it for undo/redo of InsertBreak. join and split now work for text nodes as well as interior nodes
This commit is contained in:
Родитель
f43db5b48f
Коммит
061b766061
|
@ -37,6 +37,13 @@ nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
|||
mOffsetInParent = aOffsetInParent;
|
||||
mNewNode = nsnull;
|
||||
mRefNode = nsnull;
|
||||
#ifdef NS_DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> testChildNodes;
|
||||
nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes));
|
||||
NS_ASSERTION(testChildNodes, "bad parent type, can't have children.");
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "DeleteTextTxn.h"
|
||||
#include "DeleteElementTxn.h"
|
||||
#include "TransactionFactory.h"
|
||||
|
@ -44,10 +45,11 @@ DeleteRangeTxn::DeleteRangeTxn()
|
|||
{
|
||||
}
|
||||
|
||||
nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
||||
nsresult DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
|
||||
{
|
||||
if (nsnull!=aRange)
|
||||
if (aEditor && aRange)
|
||||
{
|
||||
mEditor = aEditor;
|
||||
nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent));
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed.");
|
||||
result = aRange->GetEndParent(getter_AddRefs(mEndParent));
|
||||
|
@ -60,6 +62,7 @@ nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
|||
NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed.");
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
{
|
||||
PRUint32 count;
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||
textNode = do_QueryInterface(mStartParent, &result);
|
||||
|
@ -88,6 +91,7 @@ nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
|||
if (gNoisy)
|
||||
printf ("DeleteRange: %d of %p to %d of %p\n",
|
||||
mStartOffset, (void *)mStartParent, mEndOffset, (void *)mEndParent);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -129,8 +133,18 @@ nsresult DeleteRangeTxn::Do(void)
|
|||
}
|
||||
|
||||
// if we've successfully built this aggregate transaction, then do it.
|
||||
if (NS_SUCCEEDED(result))
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = EditAggregateTxn::Do();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -141,6 +155,16 @@ nsresult DeleteRangeTxn::Undo(void)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = EditAggregateTxn::Undo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -150,6 +174,16 @@ nsresult DeleteRangeTxn::Redo(void)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = EditAggregateTxn::Redo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,10 @@ class DeleteRangeTxn : public EditAggregateTxn
|
|||
public:
|
||||
|
||||
/** initialize the transaction.
|
||||
* @param aEditor the object providing basic editing operations
|
||||
* @param aRange the range to delete
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMRange *aRange);
|
||||
virtual nsresult Init(nsIEditor *aEditor, nsIDOMRange *aRange);
|
||||
|
||||
private:
|
||||
DeleteRangeTxn();
|
||||
|
@ -100,6 +101,9 @@ protected:
|
|||
/** p2 offset */
|
||||
PRInt32 mEndOffset;
|
||||
|
||||
/** the editor for this transaction */
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
#include "JoinElementTxn.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
|
||||
JoinElementTxn::JoinElementTxn()
|
||||
|
@ -64,6 +67,12 @@ nsresult JoinElementTxn::Do(void)
|
|||
{
|
||||
childNodes->GetLength(&mOffset);
|
||||
}
|
||||
//XXX: WRONG! needs commented code below
|
||||
/*
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||
*/
|
||||
result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +84,15 @@ nsresult JoinElementTxn::Do(void)
|
|||
|
||||
nsresult JoinElementTxn::Undo(void)
|
||||
{
|
||||
nsresult result = mEditor->SplitNode(mRightNode, mOffset, mLeftNode, mParent);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mRightNode, mOffset, mLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "SplitElementTxn.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
SplitElementTxn::SplitElementTxn()
|
||||
|
@ -53,7 +56,14 @@ nsresult SplitElementTxn::Do(void)
|
|||
// insert the new node
|
||||
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||
{
|
||||
result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -62,13 +72,29 @@ nsresult SplitElementTxn::Do(void)
|
|||
nsresult SplitElementTxn::Undo(void)
|
||||
{
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result = mEditor->JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult SplitElementTxn::Redo(void)
|
||||
{
|
||||
nsresult result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ nsEditFactory::CreateInstance(nsISupports *aOuter, REFNSIID aIID, void **aResult
|
|||
|
||||
|
||||
if (mCID.Equals(kEditorCID))
|
||||
obj = (nsISupports *)new nsEditor();
|
||||
obj = (nsISupports *)(nsIEditor*)new nsEditor();
|
||||
//more class ids to support. here
|
||||
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
|||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
|
||||
|
@ -211,7 +212,9 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
nsIEditor *tmp = this;
|
||||
nsISupports *tmp2 = tmp;
|
||||
*aInstancePtr = (void*)tmp2;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -220,6 +223,11 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIEditorSupportIID)) {
|
||||
*aInstancePtr = (void*)(nsIEditorSupport*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
@ -235,7 +243,15 @@ nsEditor::GetDocument(nsIDOMDocument **aDoc)
|
|||
return mDoc->QueryInterface(kIDOMDocumentIID, (void **)aDoc);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetSelection(nsIDOMSelection **aSelection)
|
||||
{
|
||||
if (!aSelection)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aSelection = nsnull;
|
||||
nsresult result = mPresShell->GetSelection(aSelection); // does an addref
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell)
|
||||
|
@ -383,9 +399,9 @@ nsEditor::GetAttributeValue(nsIDOMElement *aElement,
|
|||
nsresult result=NS_OK;
|
||||
if (nsnull!=aElement)
|
||||
{
|
||||
nsIDOMAttr* attNode=nsnull;
|
||||
result = aElement->GetAttributeNode(aAttribute, &attNode);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=attNode))
|
||||
nsCOMPtr<nsIDOMAttr> attNode;
|
||||
result = aElement->GetAttributeNode(aAttribute, getter_AddRefs(attNode));
|
||||
if ((NS_SUCCEEDED(result)) && attNode)
|
||||
{
|
||||
attNode->GetSpecified(&aResultIsSet);
|
||||
attNode->GetValue(aResultValue);
|
||||
|
@ -955,7 +971,7 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
|
|||
result = TransactionFactory::GetNewTransaction(kDeleteRangeTxnIID, (EditTxn **)&txn);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=txn))
|
||||
{
|
||||
txn->Init(range);
|
||||
txn->Init(this, range);
|
||||
(*aTxn)->AppendChild(txn);
|
||||
}
|
||||
else
|
||||
|
@ -1224,6 +1240,18 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||
PRInt32 aOffset)
|
||||
{
|
||||
SplitElementTxn *txn;
|
||||
nsresult result = CreateTxnForSplitNode(aNode, aOffset, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = Do(txn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
|
||||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn)
|
||||
|
@ -1239,6 +1267,20 @@ nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
JoinElementTxn *txn;
|
||||
nsresult result = CreateTxnForJoinNode(aNodeToKeep, aNodeToJoin, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = Do(txn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn)
|
||||
|
@ -1255,10 +1297,10 @@ nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
nsIDOMNode* aParent)
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
nsIDOMNode* aParent)
|
||||
{
|
||||
nsresult result;
|
||||
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
|
||||
|
@ -1278,25 +1320,40 @@ nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
|||
// move all the children whose index is < aOffset to aNewLeftNode
|
||||
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> rightNodeAsText(aExistingRightNode);
|
||||
nsCOMPtr<nsIDOMCharacterData> leftNodeAsText(aNewLeftNode);
|
||||
if (leftNodeAsText && rightNodeAsText)
|
||||
{
|
||||
PRInt32 i=0;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
|
||||
// fix right node
|
||||
nsString leftText;
|
||||
rightNodeAsText->SubstringData(0, aOffset, leftText);
|
||||
rightNodeAsText->DeleteData(0, aOffset);
|
||||
// fix left node
|
||||
leftNodeAsText->SetData(leftText);
|
||||
}
|
||||
else
|
||||
{ // otherwise it's an interior node, so shuffle around the children
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
PRInt32 i=0;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
|
||||
{
|
||||
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1307,10 +1364,10 @@ nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
nsresult result;
|
||||
NS_ASSERTION(((nsnull!=aNodeToKeep) &&
|
||||
|
@ -1321,41 +1378,68 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
|||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> keepNodeAsText(aNodeToKeep);
|
||||
nsCOMPtr<nsIDOMCharacterData> joinNodeAsText(aNodeToJoin);
|
||||
if (keepNodeAsText && joinNodeAsText)
|
||||
{
|
||||
PRUint32 i;
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
|
||||
nsString rightText;
|
||||
nsString leftText;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
keepNodeAsText->GetData(leftText);
|
||||
joinNodeAsText->GetData(rightText);
|
||||
}
|
||||
else
|
||||
{
|
||||
keepNodeAsText->GetData(rightText);
|
||||
joinNodeAsText->GetData(leftText);
|
||||
}
|
||||
leftText += rightText;
|
||||
keepNodeAsText->SetData(leftText);
|
||||
}
|
||||
else
|
||||
{ // otherwise it's an interior node, so shuffle around the children
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
PRUint32 i;
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{ // prepend children of aNodeToJoin
|
||||
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{ // prepend children of aNodeToJoin
|
||||
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // delete the extra node
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
else if (!childNodes) {
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // delete the extra node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
else
|
||||
result = NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "prmon.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsIContextLoader.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
@ -28,7 +29,6 @@
|
|||
#include "nsITransactionManager.h"
|
||||
#include "TransactionFactory.h"
|
||||
#include "nsRepository.h"
|
||||
//#include "nsISelection.h"
|
||||
|
||||
class nsIDOMCharacterData;
|
||||
class nsIDOMRange;
|
||||
|
@ -72,7 +72,7 @@ inline Property::Property(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesTo
|
|||
* manager, event interfaces. the idea for the event interfaces is to have them
|
||||
* delegate the actual commands to the editor independent of the XPFE implementation.
|
||||
*/
|
||||
class nsEditor : public nsIEditor
|
||||
class nsEditor : public nsIEditor, public nsIEditorSupport
|
||||
{
|
||||
private:
|
||||
nsIPresShell *mPresShell;
|
||||
|
@ -104,6 +104,8 @@ public:
|
|||
|
||||
virtual nsresult GetDocument(nsIDOMDocument **aDoc);
|
||||
|
||||
virtual nsresult GetSelection(nsIDOMSelection **aSelection);
|
||||
|
||||
virtual nsresult SetProperties(nsVoidArray *aPropList);
|
||||
|
||||
virtual nsresult GetProperties(nsVoidArray *aPropList);
|
||||
|
@ -133,9 +135,7 @@ public:
|
|||
virtual nsresult DeleteSelection(nsIEditor::Direction aDir);
|
||||
|
||||
virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
PRInt32 aOffset);
|
||||
|
||||
virtual nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
|
@ -232,10 +232,20 @@ protected:
|
|||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn);
|
||||
|
||||
virtual nsresult SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
|
||||
virtual nsresult CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn);
|
||||
|
||||
virtual nsresult JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
#if 0
|
||||
nsresult CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn);
|
||||
#endif
|
||||
|
|
|
@ -22,8 +22,12 @@
|
|||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsEditorCID.h"
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
|
||||
#include "nsRepository.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
|
@ -171,7 +175,42 @@ nsresult nsTextEditor::InsertBreak(PRBool aCtrlKey)
|
|||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
if (mEditor)
|
||||
{
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
PRBool beganTransaction = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if ((NS_SUCCEEDED(result)) && selection)
|
||||
{
|
||||
beganTransaction = PR_TRUE;
|
||||
result = mEditor->BeginTransaction();
|
||||
PRBool collapsed;
|
||||
result = selection->IsCollapsed(&collapsed);
|
||||
if (NS_SUCCEEDED(result) && !collapsed)
|
||||
{
|
||||
result = mEditor->DeleteSelection(nsIEditor::eLTR);
|
||||
// get the new selection
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
#ifdef NS_DEBUG
|
||||
PRBool testCollapsed;
|
||||
result = selection->IsCollapsed(&testCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==testCollapsed, "selection not reset after deletion");
|
||||
#endif
|
||||
}
|
||||
// split the text node
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 offset;
|
||||
result = selection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset);
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
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);
|
||||
nsAutoString tag("BR");
|
||||
result = mEditor->CreateNode(tag, parentNode, offset);
|
||||
selection->Collapse(parentNode, offset);
|
||||
}
|
||||
if (PR_TRUE==beganTransaction) {
|
||||
result = mEditor->EndTransaction();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -389,3 +428,39 @@ nsTextEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
||||
// 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==aChild)
|
||||
{
|
||||
aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!childNode)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
else if (!childNodes)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,11 @@ 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;
|
||||
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
||||
|
|
|
@ -37,6 +37,13 @@ nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
|||
mOffsetInParent = aOffsetInParent;
|
||||
mNewNode = nsnull;
|
||||
mRefNode = nsnull;
|
||||
#ifdef NS_DEBUG
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> testChildNodes;
|
||||
nsresult testResult = mParent->GetChildNodes(getter_AddRefs(testChildNodes));
|
||||
NS_ASSERTION(testChildNodes, "bad parent type, can't have children.");
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "DeleteTextTxn.h"
|
||||
#include "DeleteElementTxn.h"
|
||||
#include "TransactionFactory.h"
|
||||
|
@ -44,10 +45,11 @@ DeleteRangeTxn::DeleteRangeTxn()
|
|||
{
|
||||
}
|
||||
|
||||
nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
||||
nsresult DeleteRangeTxn::Init(nsIEditor *aEditor, nsIDOMRange *aRange)
|
||||
{
|
||||
if (nsnull!=aRange)
|
||||
if (aEditor && aRange)
|
||||
{
|
||||
mEditor = aEditor;
|
||||
nsresult result = aRange->GetStartParent(getter_AddRefs(mStartParent));
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "GetStartParent failed.");
|
||||
result = aRange->GetEndParent(getter_AddRefs(mEndParent));
|
||||
|
@ -60,6 +62,7 @@ nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
|||
NS_ASSERTION((NS_SUCCEEDED(result)), "GetCommonParent failed.");
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
{
|
||||
PRUint32 count;
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode;
|
||||
textNode = do_QueryInterface(mStartParent, &result);
|
||||
|
@ -88,6 +91,7 @@ nsresult DeleteRangeTxn::Init(nsIDOMRange *aRange)
|
|||
if (gNoisy)
|
||||
printf ("DeleteRange: %d of %p to %d of %p\n",
|
||||
mStartOffset, (void *)mStartParent, mEndOffset, (void *)mEndParent);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
@ -129,8 +133,18 @@ nsresult DeleteRangeTxn::Do(void)
|
|||
}
|
||||
|
||||
// if we've successfully built this aggregate transaction, then do it.
|
||||
if (NS_SUCCEEDED(result))
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = EditAggregateTxn::Do();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -141,6 +155,16 @@ nsresult DeleteRangeTxn::Undo(void)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = EditAggregateTxn::Undo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -150,6 +174,16 @@ nsresult DeleteRangeTxn::Redo(void)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult result = EditAggregateTxn::Redo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,10 @@ class DeleteRangeTxn : public EditAggregateTxn
|
|||
public:
|
||||
|
||||
/** initialize the transaction.
|
||||
* @param aEditor the object providing basic editing operations
|
||||
* @param aRange the range to delete
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMRange *aRange);
|
||||
virtual nsresult Init(nsIEditor *aEditor, nsIDOMRange *aRange);
|
||||
|
||||
private:
|
||||
DeleteRangeTxn();
|
||||
|
@ -100,6 +101,9 @@ protected:
|
|||
/** p2 offset */
|
||||
PRInt32 mEndOffset;
|
||||
|
||||
/** the editor for this transaction */
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
};
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
#include "JoinElementTxn.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
|
||||
JoinElementTxn::JoinElementTxn()
|
||||
|
@ -64,6 +67,12 @@ nsresult JoinElementTxn::Do(void)
|
|||
{
|
||||
childNodes->GetLength(&mOffset);
|
||||
}
|
||||
//XXX: WRONG! needs commented code below
|
||||
/*
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||
*/
|
||||
result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +84,15 @@ nsresult JoinElementTxn::Do(void)
|
|||
|
||||
nsresult JoinElementTxn::Undo(void)
|
||||
{
|
||||
nsresult result = mEditor->SplitNode(mRightNode, mOffset, mLeftNode, mParent);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mRightNode, mOffset, mLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include "SplitElementTxn.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
SplitElementTxn::SplitElementTxn()
|
||||
|
@ -53,7 +56,14 @@ nsresult SplitElementTxn::Do(void)
|
|||
// insert the new node
|
||||
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||
{
|
||||
result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -62,13 +72,29 @@ nsresult SplitElementTxn::Do(void)
|
|||
nsresult SplitElementTxn::Undo(void)
|
||||
{
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result = mEditor->JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult SplitElementTxn::Redo(void)
|
||||
{
|
||||
nsresult result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
|||
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
|
||||
|
@ -211,7 +212,9 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
nsIEditor *tmp = this;
|
||||
nsISupports *tmp2 = tmp;
|
||||
*aInstancePtr = (void*)tmp2;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -220,6 +223,11 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIEditorSupportIID)) {
|
||||
*aInstancePtr = (void*)(nsIEditorSupport*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
@ -235,7 +243,15 @@ nsEditor::GetDocument(nsIDOMDocument **aDoc)
|
|||
return mDoc->QueryInterface(kIDOMDocumentIID, (void **)aDoc);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetSelection(nsIDOMSelection **aSelection)
|
||||
{
|
||||
if (!aSelection)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
*aSelection = nsnull;
|
||||
nsresult result = mPresShell->GetSelection(aSelection); // does an addref
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell)
|
||||
|
@ -383,9 +399,9 @@ nsEditor::GetAttributeValue(nsIDOMElement *aElement,
|
|||
nsresult result=NS_OK;
|
||||
if (nsnull!=aElement)
|
||||
{
|
||||
nsIDOMAttr* attNode=nsnull;
|
||||
result = aElement->GetAttributeNode(aAttribute, &attNode);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=attNode))
|
||||
nsCOMPtr<nsIDOMAttr> attNode;
|
||||
result = aElement->GetAttributeNode(aAttribute, getter_AddRefs(attNode));
|
||||
if ((NS_SUCCEEDED(result)) && attNode)
|
||||
{
|
||||
attNode->GetSpecified(&aResultIsSet);
|
||||
attNode->GetValue(aResultValue);
|
||||
|
@ -955,7 +971,7 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
|
|||
result = TransactionFactory::GetNewTransaction(kDeleteRangeTxnIID, (EditTxn **)&txn);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=txn))
|
||||
{
|
||||
txn->Init(range);
|
||||
txn->Init(this, range);
|
||||
(*aTxn)->AppendChild(txn);
|
||||
}
|
||||
else
|
||||
|
@ -1224,6 +1240,18 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||
PRInt32 aOffset)
|
||||
{
|
||||
SplitElementTxn *txn;
|
||||
nsresult result = CreateTxnForSplitNode(aNode, aOffset, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = Do(txn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
|
||||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn)
|
||||
|
@ -1239,6 +1267,20 @@ nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
JoinElementTxn *txn;
|
||||
nsresult result = CreateTxnForJoinNode(aNodeToKeep, aNodeToJoin, &txn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = Do(txn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn)
|
||||
|
@ -1255,10 +1297,10 @@ nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
nsIDOMNode* aParent)
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
nsIDOMNode* aParent)
|
||||
{
|
||||
nsresult result;
|
||||
NS_ASSERTION(((nsnull!=aExistingRightNode) &&
|
||||
|
@ -1278,25 +1320,40 @@ nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
|||
// move all the children whose index is < aOffset to aNewLeftNode
|
||||
if (0<=aOffset) // don't bother unless we're going to move at least one child
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> rightNodeAsText(aExistingRightNode);
|
||||
nsCOMPtr<nsIDOMCharacterData> leftNodeAsText(aNewLeftNode);
|
||||
if (leftNodeAsText && rightNodeAsText)
|
||||
{
|
||||
PRInt32 i=0;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
|
||||
// fix right node
|
||||
nsString leftText;
|
||||
rightNodeAsText->SubstringData(0, aOffset, leftText);
|
||||
rightNodeAsText->DeleteData(0, aOffset);
|
||||
// fix left node
|
||||
leftNodeAsText->SetData(leftText);
|
||||
}
|
||||
else
|
||||
{ // otherwise it's an interior node, so shuffle around the children
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aExistingRightNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
PRInt32 i=0;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (i<aOffset)); i++)
|
||||
{
|
||||
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
result = aExistingRightNode->RemoveChild(childNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = aNewLeftNode->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1307,10 +1364,10 @@ nsEditor::SplitNode(nsIDOMNode * aExistingRightNode,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
nsresult result;
|
||||
NS_ASSERTION(((nsnull!=aNodeToKeep) &&
|
||||
|
@ -1321,41 +1378,68 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
|
|||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> keepNodeAsText(aNodeToKeep);
|
||||
nsCOMPtr<nsIDOMCharacterData> joinNodeAsText(aNodeToJoin);
|
||||
if (keepNodeAsText && joinNodeAsText)
|
||||
{
|
||||
PRUint32 i;
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
|
||||
nsString rightText;
|
||||
nsString leftText;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
keepNodeAsText->GetData(leftText);
|
||||
joinNodeAsText->GetData(rightText);
|
||||
}
|
||||
else
|
||||
{
|
||||
keepNodeAsText->GetData(rightText);
|
||||
joinNodeAsText->GetData(leftText);
|
||||
}
|
||||
leftText += rightText;
|
||||
keepNodeAsText->SetData(leftText);
|
||||
}
|
||||
else
|
||||
{ // otherwise it's an interior node, so shuffle around the children
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aNodeToJoin->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
PRUint32 i;
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
for (i=0; ((NS_SUCCEEDED(result)) && (i<childCount)); i++)
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{ // prepend children of aNodeToJoin
|
||||
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{ // prepend children of aNodeToJoin
|
||||
result = aNodeToKeep->InsertBefore(childNode, firstNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // delete the extra node
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
else if (!childNodes) {
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // delete the extra node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
}
|
||||
}
|
||||
else
|
||||
result = NS_ERROR_INVALID_ARG;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "prmon.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsIContextLoader.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
@ -28,7 +29,6 @@
|
|||
#include "nsITransactionManager.h"
|
||||
#include "TransactionFactory.h"
|
||||
#include "nsRepository.h"
|
||||
//#include "nsISelection.h"
|
||||
|
||||
class nsIDOMCharacterData;
|
||||
class nsIDOMRange;
|
||||
|
@ -72,7 +72,7 @@ inline Property::Property(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesTo
|
|||
* manager, event interfaces. the idea for the event interfaces is to have them
|
||||
* delegate the actual commands to the editor independent of the XPFE implementation.
|
||||
*/
|
||||
class nsEditor : public nsIEditor
|
||||
class nsEditor : public nsIEditor, public nsIEditorSupport
|
||||
{
|
||||
private:
|
||||
nsIPresShell *mPresShell;
|
||||
|
@ -104,6 +104,8 @@ public:
|
|||
|
||||
virtual nsresult GetDocument(nsIDOMDocument **aDoc);
|
||||
|
||||
virtual nsresult GetSelection(nsIDOMSelection **aSelection);
|
||||
|
||||
virtual nsresult SetProperties(nsVoidArray *aPropList);
|
||||
|
||||
virtual nsresult GetProperties(nsVoidArray *aPropList);
|
||||
|
@ -133,9 +135,7 @@ public:
|
|||
virtual nsresult DeleteSelection(nsIEditor::Direction aDir);
|
||||
|
||||
virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
PRInt32 aOffset);
|
||||
|
||||
virtual nsresult JoinNodes(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
|
@ -232,10 +232,20 @@ protected:
|
|||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn);
|
||||
|
||||
virtual nsresult SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
|
||||
virtual nsresult CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn);
|
||||
|
||||
virtual nsresult JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
#if 0
|
||||
nsresult CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn);
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@ Editor interface to outside world
|
|||
{ 0x8f, 0x4c, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc } }
|
||||
|
||||
class nsIDOMDocument;
|
||||
class nsIDOMSelection;
|
||||
class nsIPresShell;
|
||||
class nsString;
|
||||
|
||||
|
@ -79,6 +80,13 @@ public:
|
|||
*/
|
||||
virtual nsresult GetDocument(nsIDOMDocument **aDoc)=0;
|
||||
|
||||
/**
|
||||
* return the DOM Selection for the presentation shell that has focus
|
||||
* (or most recently had focus.)
|
||||
* @param aSelection [OUT] the dom interface for the selection
|
||||
*/
|
||||
virtual nsresult GetSelection(nsIDOMSelection **aSelection)=0;
|
||||
|
||||
/**
|
||||
* SetAttribute() sets the attribute of aElement.
|
||||
* No checking is done to see if aAttribute is a legal attribute of the node,
|
||||
|
@ -168,12 +176,9 @@ public:
|
|||
* @param aExistingRightNode the node to split. It will become the new node's next sibling.
|
||||
* @param aOffset the offset of aExistingRightNode's content|children to do the split at
|
||||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
* @param aParent the parent of aExistingRightNode
|
||||
*/
|
||||
virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent)=0;
|
||||
PRInt32 aOffset)=0;
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
|
|
Загрузка…
Ссылка в новой задаче