diff --git a/mozilla/editor/base/DeleteRangeTxn.cpp b/mozilla/editor/base/DeleteRangeTxn.cpp index 197b77fe730..0d2c24e769e 100644 --- a/mozilla/editor/base/DeleteRangeTxn.cpp +++ b/mozilla/editor/base/DeleteRangeTxn.cpp @@ -465,6 +465,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParen return result; } +// XXX: probably want to move this to editor as a standard support method nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList) { nsresult result=NS_OK; diff --git a/mozilla/editor/base/EditAggregateTxn.h b/mozilla/editor/base/EditAggregateTxn.h index 9830a1d0656..f60845aa7f7 100644 --- a/mozilla/editor/base/EditAggregateTxn.h +++ b/mozilla/editor/base/EditAggregateTxn.h @@ -60,6 +60,7 @@ public: protected: + //XXX: if this was an nsISupportsArray, it would handle refcounting for us nsVoidArray *mChildren; }; diff --git a/mozilla/editor/base/JoinElementTxn.cpp b/mozilla/editor/base/JoinElementTxn.cpp index e6331ffddf9..c075da6b2ab 100644 --- a/mozilla/editor/base/JoinElementTxn.cpp +++ b/mozilla/editor/base/JoinElementTxn.cpp @@ -18,7 +18,6 @@ #include "JoinElementTxn.h" #include "nsIDOMNodeList.h" -#include "editor.h" JoinElementTxn::JoinElementTxn() @@ -26,9 +25,11 @@ JoinElementTxn::JoinElementTxn() { } -nsresult JoinElementTxn::Init(nsIDOMNode *aLeftNode, +nsresult JoinElementTxn::Init(nsIEditor *aEditor, + nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode) { + mEditor = aEditor; mLeftNode = aLeftNode; mRightNode = aRightNode; mOffset=0; @@ -63,7 +64,7 @@ nsresult JoinElementTxn::Do(void) { childNodes->GetLength(&mOffset); } - result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); + result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); } } } @@ -74,13 +75,13 @@ nsresult JoinElementTxn::Do(void) nsresult JoinElementTxn::Undo(void) { - nsresult result = nsEditor::SplitNode(mRightNode, mOffset, mLeftNode, mParent); + nsresult result = mEditor->SplitNode(mRightNode, mOffset, mLeftNode, mParent); return result; } nsresult JoinElementTxn::Redo(void) { - nsresult result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); + nsresult result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); return result; } diff --git a/mozilla/editor/base/JoinElementTxn.h b/mozilla/editor/base/JoinElementTxn.h index d094efe5f09..4f30f8f9c02 100644 --- a/mozilla/editor/base/JoinElementTxn.h +++ b/mozilla/editor/base/JoinElementTxn.h @@ -22,6 +22,7 @@ #include "EditTxn.h" #include "nsIDOMNode.h" #include "nsCOMPtr.h" +#include "nsIEditor.h" #define JOIN_ELEMENT_TXN_IID \ {/* 9bc5f9f0-ac48-11d2-86d8-000064657374 */ \ @@ -37,7 +38,8 @@ class JoinElementTxn : public EditTxn { public: - virtual nsresult Init(nsIDOMNode *aLeftNode, + virtual nsresult Init(nsIEditor *aEditor, + nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode); protected: JoinElementTxn(); @@ -78,6 +80,7 @@ protected: /** the parent node containing mLeftNode and mRightNode */ nsCOMPtr mParent; + nsCOMPtr mEditor; friend class TransactionFactory; diff --git a/mozilla/editor/base/SplitElementTxn.cpp b/mozilla/editor/base/SplitElementTxn.cpp index 0568cc41d8b..d97fe6ceaa2 100644 --- a/mozilla/editor/base/SplitElementTxn.cpp +++ b/mozilla/editor/base/SplitElementTxn.cpp @@ -19,7 +19,6 @@ #include "SplitElementTxn.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" -#include "editor.h" // note that aEditor is not refcounted SplitElementTxn::SplitElementTxn() @@ -27,9 +26,11 @@ SplitElementTxn::SplitElementTxn() { } -nsresult SplitElementTxn::Init(nsIDOMNode *aNode, +nsresult SplitElementTxn::Init(nsIEditor *aEditor, + nsIDOMNode *aNode, PRInt32 aOffset) { + mEditor = aEditor; mExistingRightNode = aNode; mOffset = aOffset; return NS_OK; @@ -52,7 +53,7 @@ nsresult SplitElementTxn::Do(void) // insert the new node if ((NS_SUCCEEDED(result)) && (mParent)) { - result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); + result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); } } return result; @@ -61,13 +62,13 @@ nsresult SplitElementTxn::Do(void) nsresult SplitElementTxn::Undo(void) { // this assumes Do inserted the new node in front of the prior existing node - nsresult result = nsEditor::JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE); + nsresult result = mEditor->JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE); return result; } nsresult SplitElementTxn::Redo(void) { - nsresult result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); + nsresult result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); return result; } diff --git a/mozilla/editor/base/SplitElementTxn.h b/mozilla/editor/base/SplitElementTxn.h index 0a163ee1eb8..6dabbac63ad 100644 --- a/mozilla/editor/base/SplitElementTxn.h +++ b/mozilla/editor/base/SplitElementTxn.h @@ -22,6 +22,7 @@ #include "EditTxn.h" #include "nsIDOMNode.h" #include "nsCOMPtr.h" +#include "nsIEditor.h" #define SPLIT_ELEMENT_TXN_IID \ {/* 690c6290-ac48-11d2-86d8-000064657374 */ \ @@ -36,7 +37,8 @@ class SplitElementTxn : public EditTxn { public: - virtual nsresult Init (nsIDOMNode *aNode, + virtual nsresult Init (nsIEditor *aEditor, + nsIDOMNode *aNode, PRInt32 aOffset); protected: SplitElementTxn(); @@ -74,6 +76,7 @@ protected: /** the parent shared by mExistingRightNode and mNewLeftNode */ nsCOMPtr mParent; + nsCOMPtr mEditor; friend class TransactionFactory; diff --git a/mozilla/editor/base/editor.cpp b/mozilla/editor/base/editor.cpp index abc799a2e75..f62604078a3 100644 --- a/mozilla/editor/base/editor.cpp +++ b/mozilla/editor/base/editor.cpp @@ -38,6 +38,7 @@ #include "nsICollection.h" #include "nsIEnumerator.h" #include "nsIAtom.h" +#include "nsVoidArray.h" // transactions the editor knows how to build #include "TransactionFactory.h" @@ -58,7 +59,8 @@ static NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID); static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); -static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID); +static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID); +static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID); static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID); static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID); @@ -188,7 +190,7 @@ nsEditor::~nsEditor() //the autopointers will clear themselves up. //but we need to also remove the listeners or we have a leak nsCOMPtr erP; - nsresult t_result = mDomInterfaceP->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(erP)); + nsresult t_result = mDoc->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(erP)); if (NS_SUCCEEDED( t_result )) { erP->RemoveEventListener(mKeyListenerP, kIDOMKeyListenerIID); @@ -231,20 +233,25 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr) nsresult -nsEditor::GetDomInterface(nsIDOMDocument **aDomInterface) +nsEditor::GetDocument(nsIDOMDocument **aDoc) { - *aDomInterface = mDomInterfaceP; return NS_OK; + *aDoc = nsnull; // init out param + NS_PRECONDITION(mDoc, "bad state, null mDoc"); + if (!mDoc) + return NS_ERROR_NULL_POINTER; + return mDoc->QueryInterface(kIDOMDocumentIID, (void **)aDoc); } nsresult -nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell) +nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell) { - if ((nsnull==aDomInterface) || (nsnull==aPresShell)) + NS_PRECONDITION(nsnull!=aDoc && nsnull!=aPresShell, "bad arg"); + if ((nsnull==aDoc) || (nsnull==aPresShell)) return NS_ERROR_NULL_POINTER; - mDomInterfaceP = aDomInterface; + mDoc = aDoc; mPresShell = aPresShell; NS_ADDREF(mPresShell); mViewManager = mPresShell->GetViewManager(); @@ -264,7 +271,7 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell) return t_result; } nsCOMPtr erP; - t_result = mDomInterfaceP->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(erP)); + t_result = mDoc->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(erP)); if (NS_OK != t_result) { mKeyListenerP = 0; @@ -277,61 +284,74 @@ nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell) /* fire up the transaction manager */ - /* - now to handle selection - */ - /* - nsCOMPtr document; - if (NS_SUCCEEDED(t_result = mDomInterfaceP->QueryInterface(kIDocumentIID, getter_AddRefs(document)))) - { - if (!NS_SUCCEEDED(t_result = document->GetSelection(*getter_AddRefs(mSelectionP)))) - { - NS_NOTREACHED("query interface"); - return t_result; - } - } - else - { - NS_NOTREACHED("query interface"); - return t_result; - } -*/ - - nsISupports *isup = 0; - nsresult result; - - result = nsServiceManager::GetService(kCTransactionManagerFactoryCID, - kITransactionManagerIID, &isup); - - if (NS_FAILED(result) || !isup) { - printf("ERROR: Failed to get TransactionManager nsISupports interface.\n"); - return NS_ERROR_OUT_OF_MEMORY; - } - - result = isup->QueryInterface(kITransactionManagerIID, (void **)&mTxnMgr); - - if (NS_FAILED(result)) { - printf("ERROR: Failed to get TransactionManager interface. (%d)\n", result); - return result; - } - - if (!mTxnMgr) { - printf("ERROR: QueryInterface() returned NULL pointer.\n"); - return NS_ERROR_NULL_POINTER; - } + NS_POSTCONDITION(mDoc && mPresShell, "bad state"); return NS_OK; } - - nsresult -nsEditor::InsertString(nsString *aString) +nsEditor::EnableUndo(PRBool aEnable) { + nsISupports *isup = 0; + nsresult result=NS_OK; + + if (PR_TRUE==aEnable) + { + if (!mTxnMgr) + { + result = nsServiceManager::GetService(kCTransactionManagerFactoryCID, + kITransactionManagerIID, &isup); + if (NS_FAILED(result) || !isup) { + printf("ERROR: Failed to get TransactionManager nsISupports interface.\n"); + return NS_ERROR_NOT_AVAILABLE; + } + result = isup->QueryInterface(kITransactionManagerIID, (void **)&mTxnMgr); + if (NS_FAILED(result) || !mTxnMgr) { + printf("ERROR: Failed to get TransactionManager interface. (%d)\n", result); + return result; + } + } + } + else + { // disable the transaction manager if it is enabled + if (mTxnMgr) + { + mTxnMgr = nsnull; + } + } + + return result; +} + +nsresult nsEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo) +{ + aIsEnabled = ((PRBool)(mTxnMgr)); + if (aIsEnabled) + { + PRInt32 numTxns=0; + mTxnMgr->GetNumberOfUndoItems(&numTxns); + aCanUndo = ((PRBool)(0==numTxns)); + } + else { + aCanUndo = PR_FALSE; + } return NS_OK; } - +nsresult nsEditor::CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo) +{ + aIsEnabled = ((PRBool)(mTxnMgr)); + if (aIsEnabled) + { + PRInt32 numTxns=0; + mTxnMgr->GetNumberOfRedoItems(&numTxns); + aCanRedo = ((PRBool)(0==numTxns)); + } + else { + aCanRedo = PR_FALSE; + } + return NS_OK; +} nsresult nsEditor::SetProperties(Properties aProperties) @@ -447,26 +467,6 @@ nsEditor::Commit(PRBool aCtrlKey) //END nsIEditorInterfaces -//BEGIN nsEditor Calls from public -PRBool -nsEditor::KeyDown(int aKeycode) -{ - return PR_TRUE; -} - - - -PRBool -nsEditor::MouseClick(int aX,int aY) -{ - return PR_FALSE; -} - - - -//END nsEditor Calls from public - - //BEGIN nsEditor Private methods @@ -476,10 +476,12 @@ nsEditor::GetCurrentNode(nsIDOMNode ** aNode) { if (!aNode) return NS_ERROR_NULL_POINTER; + if (!mDoc) + return NS_ERROR_NULL_POINTER; /* If no node set, get first text node */ nsCOMPtr docNode; - if (NS_SUCCEEDED(mDomInterfaceP->GetDocumentElement(getter_AddRefs(docNode)))) + if (NS_SUCCEEDED(mDoc->GetDocumentElement(getter_AddRefs(docNode)))) { return docNode->QueryInterface(kIDOMNodeIID,(void **) aNode); } @@ -491,6 +493,8 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO { nsresult result=NS_OK; + if (!mDoc) + return NS_ERROR_NULL_POINTER; if (!aResult) return NS_ERROR_NULL_POINTER; @@ -500,7 +504,7 @@ nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDO if (nsnull==aStartNode) { - mDomInterfaceP->GetDocumentElement(getter_AddRefs(element)); + mDoc->GetDocumentElement(getter_AddRefs(element)); result = element->QueryInterface(kIDOMNodeIID,getter_AddRefs(node)); if (NS_FAILED(result)) return result; @@ -666,10 +670,6 @@ nsEditor::EndUpdate() return NS_OK; } -nsresult nsEditor::Delete(PRBool aForward, PRUint32 aCount) -{ - return NS_OK; -} nsresult nsEditor::CreateElement(const nsString& aTag, nsIDOMNode * aParent, @@ -694,7 +694,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag, result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn); if (nsnull != *aTxn) { - (*aTxn)->Init(mDomInterfaceP, aTag, aParent, aPosition); + result = (*aTxn)->Init(mDoc, aTag, aParent, aPosition); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -723,7 +723,7 @@ nsresult nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aParent, result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(aElement, aParent); + result = (*aTxn)->Init(aElement, aParent); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -777,7 +777,7 @@ nsresult nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert, result = TransactionFactory::GetNewTransaction(kInsertTextTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(nodeAsText, offset, aStringToInsert); + result = (*aTxn)->Init(nodeAsText, offset, aStringToInsert); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -817,7 +817,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement, result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(aElement, aOffset, aLength); + result = (*aTxn)->Init(aElement, aOffset, aLength); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -825,6 +825,84 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement, return result; } +// operates on selection +// deletes the selection (if not collapsed) and splits the current element +// or an ancestor of the current element +/* context-dependent behaviors + SELECTION ACTION + text node split text node (or a parent) + block element insert a
+ H1-H6 if at end, create a

following the header +*/ +#if 0 // THIS CODE WILL BE REMOVED. WE ARE GOING TO IMPLEMENT + // A GENERIC HANDLER SYSTEM. +nsresult nsEditor::CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn) +{ + // allocate the out-param transaction + nsresult result = TransactionFactory::GetNewTransaction(kEditAggregateTxnIID, (EditTxn **)aTxn); + if (NS_FAILED(result)) + { + return result; + } + nsISelection* selection; + result = mPresShell->GetSelection(&selection); + if ((NS_SUCCEEDED(result)) && (nsnull!=selection)) + { + nsCOMPtr enumerator; + enumerator = selection; + if (enumerator) + { + // XXX: need to handle mutliple ranges here, probably by + // disallowing the operation + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsISupports *currentItem=nsnull; + result = enumerator->CurrentItem(¤tItem); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + nsCOMPtr range(currentItem); + PRBool isCollapsed; + range->GetIsCollapsed(&isCollapsed); + if(PR_FALSE==isCollapsed) + { + EditAggregateTxn *delSelTxn; + result = CreateTxnForDeleteSelection(nsIEditor::eLTR, &delSelTxn); + if ((NS_SUCCEEDED(result)) && (delSelTtxn)) { + (*aTxn)->AppendChild(delSelTtxn); + } + } + // at this point, we have a collapsed selection + if (NS_SUCCEEDED(result)) + { + nsCOMPtr node; + result = range->GetStartParent(getter_AddRefs(node)); + if (NS_SUCCEEDED(result)) + { + nsVoidArray parentFrameList; + result = GetParentFrameList(node, &parentFrameList); + if (NS_SUCCEEDED(result)) + { + EditAggregateTxn *enterKeyTxn; + result = CreateTxnForEnterKeyAtInsertionPoint(range, &enterKeyTxn)); + if ((NS_SUCCEEDED(result)) && (enterKeyTxn)) { + (*aTxn)->AppendChild(enterKeyTxn); + } + } + } + } + } + } + } + } + + // if anything along the way failed, delete the out-param transaction + if (NS_FAILED(result)) { + NS_IF_RELEASE(*aTxn); + } + return result; +} +#endif + nsresult nsEditor::DeleteSelection(nsIEditor::Direction aDir) { @@ -854,7 +932,7 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, enumerator = selection; if (enumerator) { - for (enumerator->First();NS_OK != enumerator->IsDone() ; enumerator->Next()) + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) { nsISupports *currentItem=nsnull; result = enumerator->CurrentItem(¤tItem); @@ -863,7 +941,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, nsCOMPtr range(currentItem); PRBool isCollapsed; range->GetIsCollapsed(&isCollapsed); - printf("GetIsCollapsed returned %d\n", isCollapsed); if (PR_FALSE==isCollapsed) { DeleteRangeTxn *txn; @@ -888,12 +965,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, result = NS_ERROR_NULL_POINTER; // if we didn't build the transaction correctly, destroy the out-param transaction so we don't leak it. - if (NS_FAILED(result)) - { - printf ("new result = %d, NS_FAILED=%d, macro expanded out=%d\n", - result, NS_FAILED(result), ((result) & 0x80000000)); - } - if (NS_FAILED(result)) { NS_IF_RELEASE(*aTxn); @@ -1149,6 +1220,41 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode) return result; } +nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode, + PRUint32 aOffset, + SplitElementTxn **aTxn) +{ + nsresult result=NS_ERROR_NULL_POINTER; + if (nsnull != aNode) + { + result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)aTxn); + if (nsnull!=*aTxn) + { + result = (*aTxn)->Init(this, aNode, aOffset); + } + else + result = NS_ERROR_OUT_OF_MEMORY; + } + return result; +} + +nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode, + nsIDOMNode *aRightNode, + JoinElementTxn **aTxn) +{ + nsresult result=NS_ERROR_NULL_POINTER; + if ((nsnull != aLeftNode) && (nsnull != aRightNode)) + { + result = TransactionFactory::GetNewTransaction(kJoinElementTxnIID, (EditTxn **)aTxn); + if (nsnull!=*aTxn) + { + result = (*aTxn)->Init(this, aLeftNode, aRightNode); + } + else + result = NS_ERROR_OUT_OF_MEMORY; + } + return result; +} nsresult nsEditor::SplitNode(nsIDOMNode * aExistingRightNode, diff --git a/mozilla/editor/base/editor.h b/mozilla/editor/base/editor.h index 6550c10d6a5..c5fcd8b3640 100644 --- a/mozilla/editor/base/editor.h +++ b/mozilla/editor/base/editor.h @@ -40,6 +40,8 @@ class CreateElementTxn; class DeleteElementTxn; class InsertTextTxn; class DeleteTextTxn; +class SplitElementTxn; +class JoinElementTxn; class EditAggregateTxn; //This is the monitor for the editor. @@ -57,7 +59,7 @@ private: nsIPresShell *mPresShell; nsIViewManager *mViewManager; PRUint32 mUpdateCount; - nsCOMPtr mDomInterfaceP; + nsCOMPtr mDoc; nsCOMPtr mKeyListenerP; nsCOMPtr mMouseListenerP; // nsCOMPtr mSelectionP; @@ -82,9 +84,9 @@ public: /*interfaces for addref and release and queryinterface*/ NS_DECL_ISUPPORTS - virtual nsresult Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell); + virtual nsresult Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell); - virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface); + virtual nsresult GetDocument(nsIDOMDocument **aDoc); virtual nsresult SetProperties(Properties aProperties); @@ -101,35 +103,47 @@ public: virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute); + virtual nsresult CreateElement(const nsString& aTag, + nsIDOMNode * aParent, + PRInt32 aPosition); + + virtual nsresult DeleteElement(nsIDOMNode * aParent, + nsIDOMNode * aChild); + + virtual nsresult DeleteSelection(nsIEditor::Direction aDir); + + virtual nsresult InsertText(const nsString& aStringToInsert); + + virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode, + PRInt32 aOffset, + nsIDOMNode * aNewLeftNode, + nsIDOMNode * aParent); + + virtual nsresult JoinNodes(nsIDOMNode * aNodeToKeep, + nsIDOMNode * aNodeToJoin, + nsIDOMNode * aParent, + PRBool aNodeToKeepIsFirst); + + virtual nsresult Commit(PRBool aCtrlKey); + + virtual nsresult EnableUndo(PRBool aEnable); + virtual nsresult Do(nsITransaction *aTxn); virtual nsresult Undo(PRUint32 aCount); + virtual nsresult CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo); + virtual nsresult Redo(PRUint32 aCount); + virtual nsresult CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo); + virtual nsresult BeginUpdate(); virtual nsresult EndUpdate(); /*END nsIEditor interfaces*/ -/*BEGIN nsEditor interfaces*/ - - -/*KeyListener Methods*/ - /** KeyDown is called from the key event lister "probably" - * @param int aKeycode the keycode or ascii - * value of the key that was hit for now - * @return False if ignored - */ - PRBool KeyDown(int aKeycode); - -/*MouseListener Methods*/ - /** MouseClick - * @param int x the xposition of the click - * @param int y the yposition of the click - */ - PRBool MouseClick(int aX,int aY); //it should also tell us the dom element that was selected. /*BEGIN private methods used by the implementations of the above functions*/ @@ -156,73 +170,60 @@ public: */ nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult); - nsresult CreateElement(const nsString& aTag, - nsIDOMNode * aParent, - PRInt32 aPosition); - - nsresult DeleteElement(nsIDOMNode * aParent, - nsIDOMNode * aElement); - - nsresult DeleteSelection(nsIEditor::Direction aDir); - - nsresult InsertText(const nsString& aStringToInsert); - - nsresult DeleteText(nsIDOMCharacterData *aElement, - PRUint32 aOffset, - PRUint32 aLength); - - static nsresult SplitNode(nsIDOMNode * aExistingRightNode, - PRInt32 aOffset, - nsIDOMNode * aNewLeftNode, - nsIDOMNode * aParent); - - static nsresult JoinNodes(nsIDOMNode * aNodeToKeep, - nsIDOMNode * aNodeToJoin, - nsIDOMNode * aParent, - PRBool aNodeToKeepIsFirst); - - nsresult Delete(PRBool aForward, PRUint32 aCount); - - virtual nsresult InsertString(nsString *aString); - - virtual nsresult Commit(PRBool aCtrlKey); /*END private methods of nsEditor*/ protected: - nsresult CreateTxnForSetAttribute(nsIDOMElement *aElement, - const nsString& aAttribute, - const nsString& aValue, - ChangeAttributeTxn ** aTxn); + virtual nsresult CreateTxnForSetAttribute(nsIDOMElement *aElement, + const nsString& aAttribute, + const nsString& aValue, + ChangeAttributeTxn ** aTxn); - nsresult CreateTxnForRemoveAttribute(nsIDOMElement *aElement, - const nsString& aAttribute, - ChangeAttributeTxn ** aTxn); + virtual nsresult CreateTxnForRemoveAttribute(nsIDOMElement *aElement, + const nsString& aAttribute, + ChangeAttributeTxn ** aTxn); - nsresult CreateTxnForCreateElement(const nsString& aTag, - nsIDOMNode *aParent, - PRInt32 aPosition, - CreateElementTxn ** aTxn); + virtual nsresult CreateTxnForCreateElement(const nsString& aTag, + nsIDOMNode *aParent, + PRInt32 aPosition, + CreateElementTxn ** aTxn); - nsresult CreateTxnForDeleteElement(nsIDOMNode * aParent, - nsIDOMNode * aElement, - DeleteElementTxn ** aTxn); + virtual nsresult CreateTxnForDeleteElement(nsIDOMNode * aParent, + nsIDOMNode * aElement, + DeleteElementTxn ** aTxn); - nsresult CreateTxnForInsertText(const nsString & aStringToInsert, - InsertTextTxn ** aTxn); + virtual nsresult CreateTxnForInsertText(const nsString & aStringToInsert, + InsertTextTxn ** aTxn); - nsresult CreateTxnForDeleteText(nsIDOMCharacterData *aElement, - PRUint32 aOffset, - PRUint32 aLength, - DeleteTextTxn **aTxn); - nsresult CreateTxnForDeleteSelection(nsIEditor::Direction aDir, - EditAggregateTxn ** aTxn); + virtual nsresult DeleteText(nsIDOMCharacterData *aElement, + PRUint32 aOffset, + PRUint32 aLength); - nsresult CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, + virtual nsresult CreateTxnForDeleteText(nsIDOMCharacterData *aElement, + PRUint32 aOffset, + PRUint32 aLength, + DeleteTextTxn **aTxn); + + virtual nsresult CreateTxnForDeleteSelection(nsIEditor::Direction aDir, + EditAggregateTxn ** aTxn); + + virtual nsresult CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange, nsIEditor::Direction aDir, EditAggregateTxn *aTxn); + virtual nsresult CreateTxnForSplitNode(nsIDOMNode *aNode, + PRUint32 aOffset, + SplitElementTxn **aTxn); + + virtual nsresult CreateTxnForJoinNode(nsIDOMNode *aLeftNode, + nsIDOMNode *aRightNode, + JoinElementTxn **aTxn); + +#if 0 + nsresult CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn); +#endif + nsresult GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode); nsresult GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode); diff --git a/mozilla/editor/base/editorInterfaces.cpp b/mozilla/editor/base/editorInterfaces.cpp index 1cc2662ec19..051b3c76063 100644 --- a/mozilla/editor/base/editorInterfaces.cpp +++ b/mozilla/editor/base/editorInterfaces.cpp @@ -238,13 +238,13 @@ nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProces { result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn); if (txn) - txn->Init(currentNode, -1); + txn->Init(mEditor, currentNode, -1); } else // split the element so there are 2 children in the first half { result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn); if (txn) - txn->Init(currentNode, 1); + txn->Init(mEditor, currentNode, 1); } if (txn) mEditor->Do(txn); @@ -409,7 +409,6 @@ nsEditorMouseListener::MouseUp(nsIDOMEvent* aMouseEvent) nsresult nsEditorMouseListener::MouseClick(nsIDOMEvent* aMouseEvent) { - mEditor->MouseClick(0,0); return NS_OK; } diff --git a/mozilla/editor/core/DeleteRangeTxn.cpp b/mozilla/editor/core/DeleteRangeTxn.cpp index 197b77fe730..0d2c24e769e 100644 --- a/mozilla/editor/core/DeleteRangeTxn.cpp +++ b/mozilla/editor/core/DeleteRangeTxn.cpp @@ -465,6 +465,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParen return result; } +// XXX: probably want to move this to editor as a standard support method nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList) { nsresult result=NS_OK; diff --git a/mozilla/editor/core/EditAggregateTxn.h b/mozilla/editor/core/EditAggregateTxn.h index 9830a1d0656..f60845aa7f7 100644 --- a/mozilla/editor/core/EditAggregateTxn.h +++ b/mozilla/editor/core/EditAggregateTxn.h @@ -60,6 +60,7 @@ public: protected: + //XXX: if this was an nsISupportsArray, it would handle refcounting for us nsVoidArray *mChildren; }; diff --git a/mozilla/editor/core/editor.cpp b/mozilla/editor/core/editor.cpp index abc799a2e75..460d082dadf 100644 --- a/mozilla/editor/core/editor.cpp +++ b/mozilla/editor/core/editor.cpp @@ -38,6 +38,7 @@ #include "nsICollection.h" #include "nsIEnumerator.h" #include "nsIAtom.h" +#include "nsVoidArray.h" // transactions the editor knows how to build #include "TransactionFactory.h" @@ -694,7 +695,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag, result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn); if (nsnull != *aTxn) { - (*aTxn)->Init(mDomInterfaceP, aTag, aParent, aPosition); + result = (*aTxn)->Init(mDomInterfaceP, aTag, aParent, aPosition); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -723,7 +724,7 @@ nsresult nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aParent, result = TransactionFactory::GetNewTransaction(kDeleteElementTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(aElement, aParent); + result = (*aTxn)->Init(aElement, aParent); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -777,7 +778,7 @@ nsresult nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert, result = TransactionFactory::GetNewTransaction(kInsertTextTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(nodeAsText, offset, aStringToInsert); + result = (*aTxn)->Init(nodeAsText, offset, aStringToInsert); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -817,7 +818,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement, result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn); if (nsnull!=*aTxn) { - (*aTxn)->Init(aElement, aOffset, aLength); + result = (*aTxn)->Init(aElement, aOffset, aLength); } else result = NS_ERROR_OUT_OF_MEMORY; @@ -825,6 +826,82 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement, return result; } +// operates on selection +// deletes the selection (if not collapsed) and splits the current element +// or an ancestor of the current element +/* context-dependent behaviors + SELECTION ACTION + text node split text node (or a parent) + block element insert a
+ H1-H6 if at end, create a

following the header +*/ +nsresult nsEditor::CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn) +{ + // allocate the out-param transaction + nsresult result = TransactionFactory::GetNewTransaction(kEditAggregateTxnIID, (EditTxn **)aTxn); + if (NS_FAILED(result)) + { + return result; + } + nsISelection* selection; + result = mPresShell->GetSelection(&selection); + if ((NS_SUCCEEDED(result)) && (nsnull!=selection)) + { + nsCOMPtr enumerator; + enumerator = selection; + if (enumerator) + { + // XXX: need to handle mutliple ranges here, probably by + // disallowing the operation + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsISupports *currentItem=nsnull; + result = enumerator->CurrentItem(¤tItem); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + nsCOMPtr range(currentItem); + PRBool isCollapsed; + range->GetIsCollapsed(&isCollapsed); + if(PR_FALSE==isCollapsed) + { + EditAggregateTxn *delSelTxn; + result = CreateTxnForDeleteSelection(nsIEditor::eLTR, &delSelTtxn); + if ((NS_SUCCEEDED(result)) && (delSelTtxn)) { + (*aTxn)->AppendChild(delSelTtxn); + } + } + // at this point, we have a collapsed selection + if (NS_SUCCEEDED(result)) + { + nsCOMPtr node; + result = range->GetStartParent(getter_AddRefs(node)); + if (NS_SUCCEEDED(result)) + { + nsVoidArray parentFrameList; + result = GetParentFrameList(node, &parentFrameList); + if (NS_SUCCEEDED(result)) + { + EditAggregateTxn *enterKeyTxn; + result = CreateTxnForEnterKeyAtInsertionPoint(range, &enterKeyTxn)); + if ((NS_SUCCEEDED(result)) && (enterKeyTxn)) { + (*aTxn)->AppendChild(enterKeyTxn); + } + } + } + } + } + } + } + } + + // if anything along the way failed, delete the out-param transaction + if (NS_FAILED(result)) { + NS_IF_RELEASE(*aTxn); + } + return result; +} + + nsresult nsEditor::DeleteSelection(nsIEditor::Direction aDir) { @@ -854,7 +931,7 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, enumerator = selection; if (enumerator) { - for (enumerator->First();NS_OK != enumerator->IsDone() ; enumerator->Next()) + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) { nsISupports *currentItem=nsnull; result = enumerator->CurrentItem(¤tItem); @@ -863,7 +940,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, nsCOMPtr range(currentItem); PRBool isCollapsed; range->GetIsCollapsed(&isCollapsed); - printf("GetIsCollapsed returned %d\n", isCollapsed); if (PR_FALSE==isCollapsed) { DeleteRangeTxn *txn; @@ -888,12 +964,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir, result = NS_ERROR_NULL_POINTER; // if we didn't build the transaction correctly, destroy the out-param transaction so we don't leak it. - if (NS_FAILED(result)) - { - printf ("new result = %d, NS_FAILED=%d, macro expanded out=%d\n", - result, NS_FAILED(result), ((result) & 0x80000000)); - } - if (NS_FAILED(result)) { NS_IF_RELEASE(*aTxn); @@ -1149,6 +1219,41 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode) return result; } +nsresult nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode, + PRUint32 aOffset, + SplitElementTxn **aTxn) +{ + nsresult result=NS_ERROR_NULL_POINTER; + if (nsnull != aNode) + { + result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)aTxn); + if (nsnull!=*aTxn) + { + result = (*aTxn)->Init(aNode, aOffset); + } + else + result = NS_ERROR_OUT_OF_MEMORY; + } + return result; +} + +nsresult nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode, + nsIDOMNode *aRightNode, + JoinElementTxn **aTxn) +{ + nsresult result=NS_ERROR_NULL_POINTER; + if ((nsnull != aLeftNode) && (nsnull != aRightNode)) + { + result = TransactionFactory::GetNewTransaction(kJoinElementTxnIID, (EditTxn **)aTxn); + if (nsnull!=*aTxn) + { + result = (*aTxn)->Init(aLeftNode, aRightNode); + } + else + result = NS_ERROR_OUT_OF_MEMORY; + } + return result; +} nsresult nsEditor::SplitNode(nsIDOMNode * aExistingRightNode, diff --git a/mozilla/editor/core/editor.h b/mozilla/editor/core/editor.h index 6550c10d6a5..efc831b9867 100644 --- a/mozilla/editor/core/editor.h +++ b/mozilla/editor/core/editor.h @@ -40,6 +40,8 @@ class CreateElementTxn; class DeleteElementTxn; class InsertTextTxn; class DeleteTextTxn; +class SplitElementTxn; +class JoinElementTxn; class EditAggregateTxn; //This is the monitor for the editor. @@ -223,6 +225,16 @@ protected: nsIEditor::Direction aDir, EditAggregateTxn *aTxn); + nsresult CreateTxnForSplitNode(nsIDOMNode *aNode, + PRUint32 aOffset, + SplitElementTxn **aTxn); + + nsresult CreateTxnForJoinNode(nsIDOMNode *aLeftNode, + nsIDOMNode *aRightNode, + JoinElementTxn **aTxn); + + nsresult CreateTxnToHandleEnterKey(EditAggregateTxn **aTxn); + nsresult GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode); nsresult GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode); diff --git a/mozilla/editor/libeditor/base/DeleteRangeTxn.cpp b/mozilla/editor/libeditor/base/DeleteRangeTxn.cpp index 197b77fe730..0d2c24e769e 100644 --- a/mozilla/editor/libeditor/base/DeleteRangeTxn.cpp +++ b/mozilla/editor/libeditor/base/DeleteRangeTxn.cpp @@ -465,6 +465,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteNodesBetween(nsIDOMNode *aCommonParen return result; } +// XXX: probably want to move this to editor as a standard support method nsresult DeleteRangeTxn::BuildAncestorList(nsIDOMNode *aNode, nsISupportsArray *aList) { nsresult result=NS_OK; diff --git a/mozilla/editor/libeditor/base/EditAggregateTxn.h b/mozilla/editor/libeditor/base/EditAggregateTxn.h index 9830a1d0656..f60845aa7f7 100644 --- a/mozilla/editor/libeditor/base/EditAggregateTxn.h +++ b/mozilla/editor/libeditor/base/EditAggregateTxn.h @@ -60,6 +60,7 @@ public: protected: + //XXX: if this was an nsISupportsArray, it would handle refcounting for us nsVoidArray *mChildren; }; diff --git a/mozilla/editor/libeditor/base/JoinElementTxn.cpp b/mozilla/editor/libeditor/base/JoinElementTxn.cpp index e6331ffddf9..c075da6b2ab 100644 --- a/mozilla/editor/libeditor/base/JoinElementTxn.cpp +++ b/mozilla/editor/libeditor/base/JoinElementTxn.cpp @@ -18,7 +18,6 @@ #include "JoinElementTxn.h" #include "nsIDOMNodeList.h" -#include "editor.h" JoinElementTxn::JoinElementTxn() @@ -26,9 +25,11 @@ JoinElementTxn::JoinElementTxn() { } -nsresult JoinElementTxn::Init(nsIDOMNode *aLeftNode, +nsresult JoinElementTxn::Init(nsIEditor *aEditor, + nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode) { + mEditor = aEditor; mLeftNode = aLeftNode; mRightNode = aRightNode; mOffset=0; @@ -63,7 +64,7 @@ nsresult JoinElementTxn::Do(void) { childNodes->GetLength(&mOffset); } - result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); + result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); } } } @@ -74,13 +75,13 @@ nsresult JoinElementTxn::Do(void) nsresult JoinElementTxn::Undo(void) { - nsresult result = nsEditor::SplitNode(mRightNode, mOffset, mLeftNode, mParent); + nsresult result = mEditor->SplitNode(mRightNode, mOffset, mLeftNode, mParent); return result; } nsresult JoinElementTxn::Redo(void) { - nsresult result = nsEditor::JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); + nsresult result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE); return result; } diff --git a/mozilla/editor/libeditor/base/JoinElementTxn.h b/mozilla/editor/libeditor/base/JoinElementTxn.h index d094efe5f09..4f30f8f9c02 100644 --- a/mozilla/editor/libeditor/base/JoinElementTxn.h +++ b/mozilla/editor/libeditor/base/JoinElementTxn.h @@ -22,6 +22,7 @@ #include "EditTxn.h" #include "nsIDOMNode.h" #include "nsCOMPtr.h" +#include "nsIEditor.h" #define JOIN_ELEMENT_TXN_IID \ {/* 9bc5f9f0-ac48-11d2-86d8-000064657374 */ \ @@ -37,7 +38,8 @@ class JoinElementTxn : public EditTxn { public: - virtual nsresult Init(nsIDOMNode *aLeftNode, + virtual nsresult Init(nsIEditor *aEditor, + nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode); protected: JoinElementTxn(); @@ -78,6 +80,7 @@ protected: /** the parent node containing mLeftNode and mRightNode */ nsCOMPtr mParent; + nsCOMPtr mEditor; friend class TransactionFactory; diff --git a/mozilla/editor/libeditor/base/SplitElementTxn.cpp b/mozilla/editor/libeditor/base/SplitElementTxn.cpp index 0568cc41d8b..d97fe6ceaa2 100644 --- a/mozilla/editor/libeditor/base/SplitElementTxn.cpp +++ b/mozilla/editor/libeditor/base/SplitElementTxn.cpp @@ -19,7 +19,6 @@ #include "SplitElementTxn.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" -#include "editor.h" // note that aEditor is not refcounted SplitElementTxn::SplitElementTxn() @@ -27,9 +26,11 @@ SplitElementTxn::SplitElementTxn() { } -nsresult SplitElementTxn::Init(nsIDOMNode *aNode, +nsresult SplitElementTxn::Init(nsIEditor *aEditor, + nsIDOMNode *aNode, PRInt32 aOffset) { + mEditor = aEditor; mExistingRightNode = aNode; mOffset = aOffset; return NS_OK; @@ -52,7 +53,7 @@ nsresult SplitElementTxn::Do(void) // insert the new node if ((NS_SUCCEEDED(result)) && (mParent)) { - result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); + result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); } } return result; @@ -61,13 +62,13 @@ nsresult SplitElementTxn::Do(void) nsresult SplitElementTxn::Undo(void) { // this assumes Do inserted the new node in front of the prior existing node - nsresult result = nsEditor::JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE); + nsresult result = mEditor->JoinNodes(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE); return result; } nsresult SplitElementTxn::Redo(void) { - nsresult result = nsEditor::SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); + nsresult result = mEditor->SplitNode(mExistingRightNode, mOffset, mNewLeftNode, mParent); return result; } diff --git a/mozilla/editor/libeditor/base/SplitElementTxn.h b/mozilla/editor/libeditor/base/SplitElementTxn.h index 0a163ee1eb8..6dabbac63ad 100644 --- a/mozilla/editor/libeditor/base/SplitElementTxn.h +++ b/mozilla/editor/libeditor/base/SplitElementTxn.h @@ -22,6 +22,7 @@ #include "EditTxn.h" #include "nsIDOMNode.h" #include "nsCOMPtr.h" +#include "nsIEditor.h" #define SPLIT_ELEMENT_TXN_IID \ {/* 690c6290-ac48-11d2-86d8-000064657374 */ \ @@ -36,7 +37,8 @@ class SplitElementTxn : public EditTxn { public: - virtual nsresult Init (nsIDOMNode *aNode, + virtual nsresult Init (nsIEditor *aEditor, + nsIDOMNode *aNode, PRInt32 aOffset); protected: SplitElementTxn(); @@ -74,6 +76,7 @@ protected: /** the parent shared by mExistingRightNode and mNewLeftNode */ nsCOMPtr mParent; + nsCOMPtr mEditor; friend class TransactionFactory; diff --git a/mozilla/editor/public/nsIEditor.h b/mozilla/editor/public/nsIEditor.h index 2e48347f2b8..dff4bf9be77 100644 --- a/mozilla/editor/public/nsIEditor.h +++ b/mozilla/editor/public/nsIEditor.h @@ -21,6 +21,7 @@ #include "nsISupports.h" class nsIDOMElement; +class nsIDOMNode; class nsITransaction; /* @@ -60,29 +61,42 @@ public: /** * Init tells is to tell the implementation of nsIEditor to begin its services - * @param aDomInterface The dom interface being observed + * @param aDomInterface The dom interface being observed + * @param aPresShell TEMP: The presentation shell displaying the document + * once events can tell us from what pres shell they originated, + * this will no longer be necessary and the editor will no longer be + * linked to a single pres shell. */ virtual nsresult Init(nsIDOMDocument *aDomInterface, nsIPresShell *aPresShell) = 0; /** - * GetDomInterface() WILL NOT RETURN AN ADDREFFED POINTER + * return the DOM Document this editor is associated with * - * @param aDomInterface The dom interface being observed + * @param aDoc [OUT] the dom interface being observed, refcounted */ - virtual nsresult GetDomInterface(nsIDOMDocument **)=0; + virtual nsresult GetDocument(nsIDOMDocument **aDoc)=0; /** - * SetProperties() sets the properties of the current selection + * SetProperties() sets the aggregate properties on the current selection * * @param aProperty An enum that lists the various properties that can be applied, bold, ect. + * @see Properties + * NOTE: this is an experimental interface. Since it's really just a shortcut for + * the caller setting a set of attributes on a set of nodes, this method may be removed. + * If it's more than just a convenience method (ie, it has logic about what objects in a selection get + * which attributes) that's a whole other story. */ virtual nsresult SetProperties(Properties aProperties)=0; /** - * SetProperties() sets the properties of the current selection + * GetProperties() gets the aggregate properties of the current selection. + * All object in the current selection are scanned and their attributes are + * represented in a list of Property object. * * @param aProperty An enum that will recieve the various properties that can be applied from the current selection. + * @see nsIEditor::Properties + * NOTE: this method is experimental, expect it to change. */ virtual nsresult GetProperties(Properties **aProperties)=0; @@ -122,12 +136,69 @@ public: virtual nsresult RemoveAttribute(nsIDOMElement * aElement, const nsString& aAttribute)=0; - /** - * InsertString() Inserts a string at the current location - * - * @param aString An nsString that is the string to be inserted + /** + * CreateElement instantiates a new element of type aTag and inserts it into aParent at aPosition. + * @param aTag The type of object to create + * @param aParent The node to insert the new object into + * @param aPosition The place in aParent to insert the new node */ - virtual nsresult InsertString(nsString *aString)=0; + virtual nsresult CreateElement(const nsString& aTag, + nsIDOMNode * aParent, + PRInt32 aPosition)=0; + + /** + * DeleteElement removes aChild from aParent. + * If aChild is not a child of aParent, nothing is done and an error is returned. + * @param aChild The node to delete + * @param aParent The parent of aChild + */ + virtual nsresult DeleteElement(nsIDOMNode * aParent, + nsIDOMNode * aChild)=0; + + /** + * DeleteSelection removes all nodes in the current selection. + * @param aDir if eLTR, delete to the right (for example, the DEL key) + * if eRTL, delete to the left (for example, the BACKSPACE key) + */ + virtual nsresult DeleteSelection(nsIEditor::Direction aDir)=0; + + /** + * SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes + * @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; + + /** + * JoinNodes() takes 2 nodes and merge their content|children. + * @param aNodeToKeep The node that will remain after the join. + * @param aNodeToJoin The node that will be joined with aNodeToKeep. + * There is no requirement that the two nodes be of the same type. + * @param aParent The parent of aExistingRightNode + * @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the + * contents|children of aNodeToJoin, otherwise their positions are switched. + */ + virtual nsresult JoinNodes(nsIDOMNode *aNodeToKeep, + nsIDOMNode *aNodeToJoin, + nsIDOMNode *aParent, + PRBool aNodeToKeepIsFirst)=0; + + + /** + * InsertText() Inserts a string at the current location, given by the selection. + * If the selection is not collapsed, the selection is deleted and the insertion + * takes place at the resulting collapsed selection. + * + * NOTE: what happens if the string contains a CR? + * + * @param aString the string to be inserted + */ + virtual nsresult InsertText(const nsString& aStringToInsert)=0; /** * Commit(PRBool aCtrlKey) is a catch all method. It may be depricated later. @@ -137,8 +208,15 @@ public: */ virtual nsresult Commit(PRBool aCtrlKey)=0; - /** Do fires a transaction. It is provided here so clients can create their own transactions. - * Clients need no knowledge of whether the editor has a transaction manager or not. + /** turn the undo system on or off + * @param aEnable if PR_TRUE, the undo system is turned on if it is available + * if PR_FALSE the undo system is turned off if it was previously on + * @return if aEnable is PR_TRUE, returns NS_OK if the undo system could be initialized properly + * if aEnable is PR_FALSE, returns NS_OK. + */ + virtual nsresult EnableUndo(PRBool aEnable)=0; + + /** Do() fires a transaction. It is provided here so clients can create their own transactions. * If a transaction manager is present, it is used. * Otherwise, the transaction is just executed directly. * @@ -146,32 +224,47 @@ public: */ virtual nsresult Do(nsITransaction *aTxn)=0; - /** Undo reverses the effects of the last ExecuteTransaction operation + /** Undo reverses the effects of the last Do operation, if Undo is enabled in the editor. * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. * If a transaction manager is present, it is told to undo and the result of * that undo is returned. - * Otherwise, the Undo request is ignored. + * Otherwise, the Undo request is ignored and an error NS_ERROR_NOT_AVAILABLE is returned. * */ virtual nsresult Undo(PRUint32 aCount)=0; + /** returns state information about the undo system. + * @param aIsEnabled [OUT] PR_TRUE if undo is enabled + * @param aCanUndo [OUT] PR_TRUE if at least one transaction is currently ready to be undone. + */ + virtual nsresult CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)=0; + /** Redo reverses the effects of the last Undo operation * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. - * If a transaction manager is present, it is told to redo and the result of - * that redo is returned. - * Otherwise, the Redo request is ignored. + * If a transaction manager is present, it is told to redo and the result of the previously undone + * transaction is reapplied to the document. + * If no transaction is available for Redo, or if the document has no transaction manager, + * the Redo request is ignored and an error NS_ERROR_NOT_AVAILABLE is returned. * */ virtual nsresult Redo(PRUint32 aCount)=0; + /** returns state information about the redo system. + * @param aIsEnabled [OUT] PR_TRUE if redo is enabled + * @param aCanRedo [OUT] PR_TRUE if at least one transaction is currently ready to be redone. + */ + virtual nsresult CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo)=0; + /** BeginUpdate is a signal from the caller to the editor that the caller will execute multiple updates * to the content tree that should be treated in the most efficient way possible. + * All transactions executed between a call to BeginUpdate and EndUpdate will be undoable as + * an atomic action. * EndUpdate must be called after BeginUpdate. * Calls to BeginUpdate can be nested, as long as EndUpdate is called once per BeginUpdate. */ virtual nsresult BeginUpdate()=0; - /** EndUpdate is a signal from the caller to the editor that the caller is finished updating the content model. + /** EndUpdate is a signal to the editor that the caller is finished updating the content model. * BeginUpdate must be called before EndUpdate is called. * Calls to BeginUpdate can be nested, as long as EndUpdate is called once per BeginUpdate. */