changed nsIEditor to enable undo separately from Init

work in progress API changes to nsIEditor and nsEditor
This commit is contained in:
buster%netscape.com 1999-01-28 06:02:53 +00:00
Родитель 8583c23d49
Коммит 1d6de2d02b
20 изменённых файлов: 561 добавлений и 223 удалений

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

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

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

@ -60,6 +60,7 @@ public:
protected:
//XXX: if this was an nsISupportsArray, it would handle refcounting for us
nsVoidArray *mChildren;
};

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

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

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

@ -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<nsIDOMNode> mParent;
nsCOMPtr<nsIEditor> mEditor;
friend class TransactionFactory;

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

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

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

@ -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<nsIDOMNode> mParent;
nsCOMPtr<nsIEditor> mEditor;
friend class TransactionFactory;

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

@ -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<nsIDOMEventReceiver> 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<nsIDOMEventReceiver> 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<nsIDocument> 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<nsIDOMElement> 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 <BR>
H1-H6 if at end, create a <P> 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<nsIEnumerator> 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(&currentItem);
if ((NS_SUCCEEDED(result)) && (currentItem))
{
nsCOMPtr<nsIDOMRange> 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<nsIDOMNode> 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(&currentItem);
@ -863,7 +941,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
nsCOMPtr<nsIDOMRange> 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,

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

@ -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<nsIDOMDocument> mDomInterfaceP;
nsCOMPtr<nsIDOMDocument> mDoc;
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
// nsCOMPtr<nsISelection> 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);

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

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

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

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

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

@ -60,6 +60,7 @@ public:
protected:
//XXX: if this was an nsISupportsArray, it would handle refcounting for us
nsVoidArray *mChildren;
};

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

@ -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 <BR>
H1-H6 if at end, create a <P> 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<nsIEnumerator> 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(&currentItem);
if ((NS_SUCCEEDED(result)) && (currentItem))
{
nsCOMPtr<nsIDOMRange> 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<nsIDOMNode> 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(&currentItem);
@ -863,7 +940,6 @@ nsresult nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
nsCOMPtr<nsIDOMRange> 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,

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

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

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

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

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

@ -60,6 +60,7 @@ public:
protected:
//XXX: if this was an nsISupportsArray, it would handle refcounting for us
nsVoidArray *mChildren;
};

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

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

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

@ -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<nsIDOMNode> mParent;
nsCOMPtr<nsIEditor> mEditor;
friend class TransactionFactory;

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

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

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

@ -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<nsIDOMNode> mParent;
nsCOMPtr<nsIEditor> mEditor;
friend class TransactionFactory;

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

@ -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.
*/