added DeleteElementTxn and DeleteRangeTxn, and added merging of text insertions.

added some better error checking on all transactions.
This commit is contained in:
buster%netscape.com 1999-01-14 18:02:45 +00:00
Родитель 9af46bff3c
Коммит 92705ab193
40 изменённых файлов: 1616 добавлений и 92 удалений

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

@ -94,6 +94,8 @@ nsresult ChangeAttributeTxn::GetIsTransient(PRBool *aIsTransient)
nsresult ChangeAttributeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -110,6 +110,8 @@ nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult CreateElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteElementTxn.h"
#include "editor.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
// note that aEditor is not refcounted
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode * aElement,
nsIDOMNode * aParent)
: EditTxn(aEditor)
{
mDoc = aDoc;
NS_ADDREF(mDoc);
mElement = aElement;
NS_ADDREF(mElement);
mParent = aParent;
NS_ADDREF(mParent);
}
DeleteElementTxn::~DeleteElementTxn()
{
NS_IF_RELEASE(mDoc);
NS_IF_RELEASE(mParent);
NS_IF_RELEASE(mElement);
}
nsresult DeleteElementTxn::Do(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
#ifdef NS_DEBUG
nsresult testResult;
nsCOMPtr<nsIDOMNode> parentNode;
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
#endif
// remember which child mElement was (by remembering which child was next)
nsresult result = mElement->GetNextSibling(getter_AddRefs(mRefNode)); // can return null mRefNode
nsCOMPtr<nsIDOMNode> resultNode;
result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Undo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mElement, mRefNode, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Redo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteElementTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Element: ";
}
return NS_OK;
}
nsresult DeleteElementTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Element: ";
}
return NS_OK;
}

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

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteElementTxn_h__
#define DeleteElementTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMElement;
/**
* A transaction that deletes a single element
*/
class DeleteElementTxn : public EditTxn
{
public:
DeleteElementTxn(nsEditor *aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode *aElement,
nsIDOMNode *aParent);
virtual ~DeleteElementTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** the document into which the new node will be inserted */
nsIDOMDocument *mDoc;
/** the element to delete */
nsIDOMNode *mElement;
/** the node into which the new node will be inserted */
nsIDOMNode *mParent;
/** the index in mParent for the new node */
PRUint32 mOffsetInParent;
/** the node we will insert mNewNode before. We compute this ourselves. */
nsCOMPtr<nsIDOMNode> mRefNode;
};
#endif

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

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteRangeTxn.h"
#include "editor.h"
#include "nsIDOMRange.h"
// note that aEditor is not refcounted
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange)
: EditTxn(aEditor)
{
aRange->GetStartParent(getter_AddRefs(mStartParent));
aRange->GetEndParent(getter_AddRefs(mEndParent));
aRange->GetStartOffset(&mStartOffset);
aRange->GetEndOffset(&mEndOffset);
}
DeleteRangeTxn::~DeleteRangeTxn()
{
}
nsresult DeleteRangeTxn::Do(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Undo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Redo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteRangeTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Range: ";
}
return NS_OK;
}
nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Range: ";
}
return NS_OK;
}

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteRangeTxn_h__
#define DeleteRangeTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMRange;
/**
* A transaction that deletes an entire range in the content tree
*/
class DeleteRangeTxn : public EditTxn
{
public:
DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange);
virtual ~DeleteRangeTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** p1 in the range */
nsCOMPtr<nsIDOMNode> mStartParent;
/** p1 offset */
PRInt32 mStartOffset;
/** p2 in the range */
nsCOMPtr<nsIDOMNode> mEndParent;
/** p2 offset */
PRInt32 mEndOffset;
};
#endif

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

@ -55,6 +55,8 @@ nsresult DeleteTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -20,6 +20,8 @@
#include "editor.h"
#include "nsIDOMCharacterData.h"
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
// note that aEditor is not refcounted
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
nsIDOMCharacterData *aElement,
@ -52,6 +54,23 @@ nsresult InsertTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
// set out param default value
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
{
// if aTransaction isa InsertTextTxn, absorb it
nsCOMPtr<InsertTextTxn> otherTxn;
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
if (NS_SUCCEEDED(result) && (otherTxn))
{
nsString otherData;
otherTxn->GetData(otherData);
mStringToInsert += otherData;
}
*aDidMerge = PR_TRUE;
}
return NS_OK;
}
@ -79,3 +98,27 @@ nsresult InsertTextTxn::GetRedoString(nsString **aString)
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
nsresult
InsertTextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kInsertTextTxnIID)) {
*aInstancePtr = (void*)(InsertTextTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}
/* ============ protected methods ================== */
nsresult InsertTextTxn::GetData(nsString& aResult)
{
aResult = mStringToInsert;
return NS_OK;
}

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

@ -21,6 +21,11 @@
#include "EditTxn.h"
#define INSERTTEXTTXN_IID \
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
0x93276f00, 0xab2c, 0x11d2, \
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
class nsIDOMCharacterData;
/**
@ -50,6 +55,16 @@ public:
virtual nsresult GetRedoString(nsString **aString);
// nsISupports declarations
// override QueryInterface to handle InsertTextTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
virtual nsresult GetData(nsString& aResult);
protected:
/** the text element to operate upon */

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

@ -33,7 +33,9 @@ CPPSRCS = \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
SplitElementTxn.cpp \
DeleteElementTxn.cpp \
DeleteRangeTxn.cpp \
SplitElementTxn.cpp \
$(NULL)
MODULE = editor

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

@ -82,6 +82,8 @@ nsresult SplitElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult SplitElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -25,6 +25,7 @@
#include "nsIDOMAttr.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMRange.h"
#include "nsIDocument.h"
#include "nsRepository.h"
#include "nsIServiceManager.h"
@ -32,13 +33,17 @@
#include "nsEditorCID.h"
#include "nsTransactionManagerCID.h"
#include "nsITransactionManager.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsIAtom.h"
// transactions the editor knows how to build
#include "ChangeAttributeTxn.h"
#include "CreateElementTxn.h"
#include "DeleteElementTxn.h"
#include "InsertTextTxn.h"
#include "DeleteTextTxn.h"
#include "DeleteRangeTxn.h"
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
@ -47,6 +52,7 @@ 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(kIDocumentIID, NS_IDOCUMENT_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
@ -153,6 +159,9 @@ nsEditor::nsEditor()
nsEditor::~nsEditor()
{
NS_IF_RELEASE(mPresShell);
NS_IF_RELEASE(mTxnMgr);
//the autopointers will clear themselves up.
//but we need to also remove the listeners or we have a leak
nsCOMPtr<nsIDOMEventReceiver> erP;
@ -207,12 +216,14 @@ nsEditor::GetDomInterface(nsIDOMDocument **aDomInterface)
nsresult
nsEditor::Init(nsIDOMDocument *aDomInterface)
nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
{
if (!aDomInterface)
if ((nsnull==aDomInterface) || (nsnull==aPresShell))
return NS_ERROR_NULL_POINTER;
mDomInterfaceP = aDomInterface;
mPresShell = aPresShell;
NS_ADDREF(mPresShell);
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
if (NS_OK != t_result)
@ -596,8 +607,31 @@ nsresult nsEditor::CreateElement(const nsString& aTag,
{
CreateElementTxn *txn = new CreateElementTxn(this, mDomInterfaceP, aTag, aParent, aPosition);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
nsIDOMNode * aElement)
{
nsresult result;
if ((nsnull != aParent) && (nsnull != aElement))
{
DeleteElementTxn *txn = new DeleteElementTxn(this, mDomInterfaceP, aElement, aParent);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -610,8 +644,13 @@ nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
{
InsertTextTxn *txn = new InsertTextTxn(this, aElement, aOffset, aStringToInsert);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -619,13 +658,42 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aLength)
{
nsresult result;
nsresult result=NS_OK;
if (nsnull != aElement)
{
DeleteTextTxn *txn = new DeleteTextTxn(this, aElement, aOffset, aLength);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
nsresult nsEditor::DeleteSelection()
{
nsresult result;
nsISelection* selection;
result = mPresShell->GetSelection(&selection);
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
{
nsCOMPtr<nsIDOMRange> range;
result = selection->QueryInterface(kIDOMRangeIID, getter_AddRefs(range));
if ((NS_SUCCEEDED(result)) && (range))
{
DeleteRangeTxn *txn = new DeleteRangeTxn(this, range);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -673,8 +741,10 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
}
}
}
else result = NS_ERROR_NULL_POINTER;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -730,7 +800,8 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
}
}
else
result = NS_ERROR_NULL_POINTER;
result = NS_ERROR_INVALID_ARG;
return result;
}

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

@ -27,7 +27,7 @@
//#include "nsISelection.h"
class nsIDOMCharacterData;
class nsIPresShell;
//This is the monitor for the editor.
PRMonitor *getEditorMonitor();
@ -41,6 +41,7 @@ PRMonitor *getEditorMonitor();
class nsEditor : public nsIEditor
{
private:
nsIPresShell *mPresShell;
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
@ -64,7 +65,7 @@ public:
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
virtual nsresult Init(nsIDOMDocument *aDomInterface);
virtual nsresult Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell);
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
@ -171,6 +172,11 @@ public:
nsIDOMNode * aParent,
PRInt32 aPosition);
nsresult DeleteElement(nsIDOMNode * aParent,
nsIDOMNode * aElement);
nsresult DeleteSelection();
nsresult InsertText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
const nsString& aStringToInsert);

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

@ -138,33 +138,55 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
switch(keyCode) {
case nsIDOMEvent::VK_BACK:
{
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
if (PR_FALSE==ctrlKey)
{
// XXX: for now, just append the text
PRUint32 offset;
text->GetLength(&offset);
nsresult result = mEditor->DeleteText(text, offset-1, 1);
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
{
// XXX: for now, just append the text
PRUint32 offset;
text->GetLength(&offset);
nsresult result = mEditor->DeleteText(text, offset-1, 1);
}
}
else
{
mEditor->DeleteSelection();
}
}
break;
case nsIDOMEvent::VK_DELETE:
{
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
if (PR_FALSE==ctrlKey)
{
nsresult result = mEditor->DeleteText(text, 0, 1);
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
{
nsresult result = mEditor->DeleteText(text, 0, 1);
}
}
else
{ // XXX: delete the first P we find
nsString pTag("P");
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> parentNode;
nsCOMPtr<nsIDOMElement> element;
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
{
currentNode->GetParentNode(getter_AddRefs(parentNode));
nsresult result = mEditor->DeleteElement(parentNode, currentNode);
}
}
}
break;

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

@ -21,27 +21,31 @@ IGNORE_MANIFEST=1
LIBRARY_NAME=ender
CPPSRCS = \
editor.cpp \
editorInterfaces.cpp \
nsEditFactory.cpp \
EditTxn.cpp \
editor.cpp \
editorInterfaces.cpp \
nsEditFactory.cpp \
EditTxn.cpp \
ChangeAttributeTxn.cpp \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
SplitElementTxn.cpp \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
DeleteElementTxn.cpp \
DeleteRangeTxn.cpp \
SplitElementTxn.cpp \
$(NULL)
CPP_OBJS = \
.\$(OBJDIR)\editor.obj \
.\$(OBJDIR)\nsEditFactory.obj \
.\$(OBJDIR)\editor.obj \
.\$(OBJDIR)\nsEditFactory.obj \
.\$(OBJDIR)\editorInterfaces.obj \
.\$(OBJDIR)\EditTxn.obj \
.\$(OBJDIR)\ChangeAttributeTxn.obj \
.\$(OBJDIR)\InsertTextTxn.obj \
.\$(OBJDIR)\DeleteTextTxn.obj \
.\$(OBJDIR)\CreateElementTxn.obj \
.\$(OBJDIR)\SplitElementTxn.obj \
.\$(OBJDIR)\EditTxn.obj \
.\$(OBJDIR)\ChangeAttributeTxn.obj \
.\$(OBJDIR)\InsertTextTxn.obj \
.\$(OBJDIR)\DeleteTextTxn.obj \
.\$(OBJDIR)\CreateElementTxn.obj \
.\$(OBJDIR)\DeleteElementTxn.obj \
.\$(OBJDIR)\DeleteRangeTxn.obj \
.\$(OBJDIR)\SplitElementTxn.obj \
$(NULL)
MODULE=editor

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

@ -94,6 +94,8 @@ nsresult ChangeAttributeTxn::GetIsTransient(PRBool *aIsTransient)
nsresult ChangeAttributeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -110,6 +110,8 @@ nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult CreateElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteElementTxn.h"
#include "editor.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
// note that aEditor is not refcounted
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode * aElement,
nsIDOMNode * aParent)
: EditTxn(aEditor)
{
mDoc = aDoc;
NS_ADDREF(mDoc);
mElement = aElement;
NS_ADDREF(mElement);
mParent = aParent;
NS_ADDREF(mParent);
}
DeleteElementTxn::~DeleteElementTxn()
{
NS_IF_RELEASE(mDoc);
NS_IF_RELEASE(mParent);
NS_IF_RELEASE(mElement);
}
nsresult DeleteElementTxn::Do(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
#ifdef NS_DEBUG
nsresult testResult;
nsCOMPtr<nsIDOMNode> parentNode;
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
#endif
// remember which child mElement was (by remembering which child was next)
nsresult result = mElement->GetNextSibling(getter_AddRefs(mRefNode)); // can return null mRefNode
nsCOMPtr<nsIDOMNode> resultNode;
result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Undo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mElement, mRefNode, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Redo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteElementTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Element: ";
}
return NS_OK;
}
nsresult DeleteElementTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Element: ";
}
return NS_OK;
}

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

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteElementTxn_h__
#define DeleteElementTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMElement;
/**
* A transaction that deletes a single element
*/
class DeleteElementTxn : public EditTxn
{
public:
DeleteElementTxn(nsEditor *aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode *aElement,
nsIDOMNode *aParent);
virtual ~DeleteElementTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** the document into which the new node will be inserted */
nsIDOMDocument *mDoc;
/** the element to delete */
nsIDOMNode *mElement;
/** the node into which the new node will be inserted */
nsIDOMNode *mParent;
/** the index in mParent for the new node */
PRUint32 mOffsetInParent;
/** the node we will insert mNewNode before. We compute this ourselves. */
nsCOMPtr<nsIDOMNode> mRefNode;
};
#endif

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

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteRangeTxn.h"
#include "editor.h"
#include "nsIDOMRange.h"
// note that aEditor is not refcounted
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange)
: EditTxn(aEditor)
{
aRange->GetStartParent(getter_AddRefs(mStartParent));
aRange->GetEndParent(getter_AddRefs(mEndParent));
aRange->GetStartOffset(&mStartOffset);
aRange->GetEndOffset(&mEndOffset);
}
DeleteRangeTxn::~DeleteRangeTxn()
{
}
nsresult DeleteRangeTxn::Do(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Undo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Redo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteRangeTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Range: ";
}
return NS_OK;
}
nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Range: ";
}
return NS_OK;
}

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteRangeTxn_h__
#define DeleteRangeTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMRange;
/**
* A transaction that deletes an entire range in the content tree
*/
class DeleteRangeTxn : public EditTxn
{
public:
DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange);
virtual ~DeleteRangeTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** p1 in the range */
nsCOMPtr<nsIDOMNode> mStartParent;
/** p1 offset */
PRInt32 mStartOffset;
/** p2 in the range */
nsCOMPtr<nsIDOMNode> mEndParent;
/** p2 offset */
PRInt32 mEndOffset;
};
#endif

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

@ -55,6 +55,8 @@ nsresult DeleteTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -20,6 +20,8 @@
#include "editor.h"
#include "nsIDOMCharacterData.h"
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
// note that aEditor is not refcounted
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
nsIDOMCharacterData *aElement,
@ -52,6 +54,23 @@ nsresult InsertTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
// set out param default value
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
{
// if aTransaction isa InsertTextTxn, absorb it
nsCOMPtr<InsertTextTxn> otherTxn;
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
if (NS_SUCCEEDED(result) && (otherTxn))
{
nsString otherData;
otherTxn->GetData(otherData);
mStringToInsert += otherData;
}
*aDidMerge = PR_TRUE;
}
return NS_OK;
}
@ -79,3 +98,27 @@ nsresult InsertTextTxn::GetRedoString(nsString **aString)
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
nsresult
InsertTextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kInsertTextTxnIID)) {
*aInstancePtr = (void*)(InsertTextTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}
/* ============ protected methods ================== */
nsresult InsertTextTxn::GetData(nsString& aResult)
{
aResult = mStringToInsert;
return NS_OK;
}

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

@ -21,6 +21,11 @@
#include "EditTxn.h"
#define INSERTTEXTTXN_IID \
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
0x93276f00, 0xab2c, 0x11d2, \
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
class nsIDOMCharacterData;
/**
@ -50,6 +55,16 @@ public:
virtual nsresult GetRedoString(nsString **aString);
// nsISupports declarations
// override QueryInterface to handle InsertTextTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
virtual nsresult GetData(nsString& aResult);
protected:
/** the text element to operate upon */

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

@ -33,7 +33,9 @@ CPPSRCS = \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
SplitElementTxn.cpp \
DeleteElementTxn.cpp \
DeleteRangeTxn.cpp \
SplitElementTxn.cpp \
$(NULL)
MODULE = editor

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

@ -82,6 +82,8 @@ nsresult SplitElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult SplitElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -25,6 +25,7 @@
#include "nsIDOMAttr.h"
#include "nsIDOMNode.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMRange.h"
#include "nsIDocument.h"
#include "nsRepository.h"
#include "nsIServiceManager.h"
@ -32,13 +33,17 @@
#include "nsEditorCID.h"
#include "nsTransactionManagerCID.h"
#include "nsITransactionManager.h"
#include "nsIPresShell.h"
#include "nsISelection.h"
#include "nsIAtom.h"
// transactions the editor knows how to build
#include "ChangeAttributeTxn.h"
#include "CreateElementTxn.h"
#include "DeleteElementTxn.h"
#include "InsertTextTxn.h"
#include "DeleteTextTxn.h"
#include "DeleteRangeTxn.h"
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
@ -47,6 +52,7 @@ 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(kIDocumentIID, NS_IDOCUMENT_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
@ -153,6 +159,9 @@ nsEditor::nsEditor()
nsEditor::~nsEditor()
{
NS_IF_RELEASE(mPresShell);
NS_IF_RELEASE(mTxnMgr);
//the autopointers will clear themselves up.
//but we need to also remove the listeners or we have a leak
nsCOMPtr<nsIDOMEventReceiver> erP;
@ -207,12 +216,14 @@ nsEditor::GetDomInterface(nsIDOMDocument **aDomInterface)
nsresult
nsEditor::Init(nsIDOMDocument *aDomInterface)
nsEditor::Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell)
{
if (!aDomInterface)
if ((nsnull==aDomInterface) || (nsnull==aPresShell))
return NS_ERROR_NULL_POINTER;
mDomInterfaceP = aDomInterface;
mPresShell = aPresShell;
NS_ADDREF(mPresShell);
nsresult t_result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
if (NS_OK != t_result)
@ -596,8 +607,31 @@ nsresult nsEditor::CreateElement(const nsString& aTag,
{
CreateElementTxn *txn = new CreateElementTxn(this, mDomInterfaceP, aTag, aParent, aPosition);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
nsresult nsEditor::DeleteElement(nsIDOMNode * aParent,
nsIDOMNode * aElement)
{
nsresult result;
if ((nsnull != aParent) && (nsnull != aElement))
{
DeleteElementTxn *txn = new DeleteElementTxn(this, mDomInterfaceP, aElement, aParent);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -610,8 +644,13 @@ nsresult nsEditor::InsertText(nsIDOMCharacterData *aElement,
{
InsertTextTxn *txn = new InsertTextTxn(this, aElement, aOffset, aStringToInsert);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -619,13 +658,42 @@ nsresult nsEditor::DeleteText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
PRUint32 aLength)
{
nsresult result;
nsresult result=NS_OK;
if (nsnull != aElement)
{
DeleteTextTxn *txn = new DeleteTextTxn(this, aElement, aOffset, aLength);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
nsresult nsEditor::DeleteSelection()
{
nsresult result;
nsISelection* selection;
result = mPresShell->GetSelection(&selection);
if ((NS_SUCCEEDED(result)) && (nsnull!=selection))
{
nsCOMPtr<nsIDOMRange> range;
result = selection->QueryInterface(kIDOMRangeIID, getter_AddRefs(range));
if ((NS_SUCCEEDED(result)) && (range))
{
DeleteRangeTxn *txn = new DeleteRangeTxn(this, range);
if (nsnull!=txn)
result = ExecuteTransaction(txn);
else
result = NS_ERROR_OUT_OF_MEMORY;
}
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -673,8 +741,10 @@ nsEditor::SplitNode(nsIDOMNode * aNode,
}
}
}
else result = NS_ERROR_NULL_POINTER;
}
else
result = NS_ERROR_INVALID_ARG;
return result;
}
@ -730,7 +800,8 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
}
}
else
result = NS_ERROR_NULL_POINTER;
result = NS_ERROR_INVALID_ARG;
return result;
}

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

@ -27,7 +27,7 @@
//#include "nsISelection.h"
class nsIDOMCharacterData;
class nsIPresShell;
//This is the monitor for the editor.
PRMonitor *getEditorMonitor();
@ -41,6 +41,7 @@ PRMonitor *getEditorMonitor();
class nsEditor : public nsIEditor
{
private:
nsIPresShell *mPresShell;
nsCOMPtr<nsIDOMDocument> mDomInterfaceP;
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
@ -64,7 +65,7 @@ public:
/*interfaces for addref and release and queryinterface*/
NS_DECL_ISUPPORTS
virtual nsresult Init(nsIDOMDocument *aDomInterface);
virtual nsresult Init(nsIDOMDocument *aDomInterface, nsIPresShell* aPresShell);
virtual nsresult GetDomInterface(nsIDOMDocument **aDomInterface);
@ -171,6 +172,11 @@ public:
nsIDOMNode * aParent,
PRInt32 aPosition);
nsresult DeleteElement(nsIDOMNode * aParent,
nsIDOMNode * aElement);
nsresult DeleteSelection();
nsresult InsertText(nsIDOMCharacterData *aElement,
PRUint32 aOffset,
const nsString& aStringToInsert);

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

@ -138,33 +138,55 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent)
switch(keyCode) {
case nsIDOMEvent::VK_BACK:
{
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
if (PR_FALSE==ctrlKey)
{
// XXX: for now, just append the text
PRUint32 offset;
text->GetLength(&offset);
nsresult result = mEditor->DeleteText(text, offset-1, 1);
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
{
// XXX: for now, just append the text
PRUint32 offset;
text->GetLength(&offset);
nsresult result = mEditor->DeleteText(text, offset-1, 1);
}
}
else
{
mEditor->DeleteSelection();
}
}
break;
case nsIDOMEvent::VK_DELETE:
{
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
if (PR_FALSE==ctrlKey)
{
nsresult result = mEditor->DeleteText(text, 0, 1);
// XXX: for now, just grab the first text node
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> textNode;
nsCOMPtr<nsIDOMCharacterData> text;
if (NS_SUCCEEDED(mEditor->GetCurrentNode(getter_AddRefs(currentNode))) &&
NS_SUCCEEDED(mEditor->GetFirstTextNode(currentNode,getter_AddRefs(textNode))) &&
NS_SUCCEEDED(textNode->QueryInterface(kIDOMCharacterDataIID, getter_AddRefs(text))))
{
nsresult result = mEditor->DeleteText(text, 0, 1);
}
}
else
{ // XXX: delete the first P we find
nsString pTag("P");
nsCOMPtr<nsIDOMNode> currentNode;
nsCOMPtr<nsIDOMNode> parentNode;
nsCOMPtr<nsIDOMElement> element;
if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode))))
{
currentNode->GetParentNode(getter_AddRefs(parentNode));
nsresult result = mEditor->DeleteElement(parentNode, currentNode);
}
}
}
break;

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

@ -21,27 +21,31 @@ IGNORE_MANIFEST=1
LIBRARY_NAME=ender
CPPSRCS = \
editor.cpp \
editorInterfaces.cpp \
nsEditFactory.cpp \
EditTxn.cpp \
editor.cpp \
editorInterfaces.cpp \
nsEditFactory.cpp \
EditTxn.cpp \
ChangeAttributeTxn.cpp \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
SplitElementTxn.cpp \
InsertTextTxn.cpp \
DeleteTextTxn.cpp \
CreateElementTxn.cpp \
DeleteElementTxn.cpp \
DeleteRangeTxn.cpp \
SplitElementTxn.cpp \
$(NULL)
CPP_OBJS = \
.\$(OBJDIR)\editor.obj \
.\$(OBJDIR)\nsEditFactory.obj \
.\$(OBJDIR)\editor.obj \
.\$(OBJDIR)\nsEditFactory.obj \
.\$(OBJDIR)\editorInterfaces.obj \
.\$(OBJDIR)\EditTxn.obj \
.\$(OBJDIR)\ChangeAttributeTxn.obj \
.\$(OBJDIR)\InsertTextTxn.obj \
.\$(OBJDIR)\DeleteTextTxn.obj \
.\$(OBJDIR)\CreateElementTxn.obj \
.\$(OBJDIR)\SplitElementTxn.obj \
.\$(OBJDIR)\EditTxn.obj \
.\$(OBJDIR)\ChangeAttributeTxn.obj \
.\$(OBJDIR)\InsertTextTxn.obj \
.\$(OBJDIR)\DeleteTextTxn.obj \
.\$(OBJDIR)\CreateElementTxn.obj \
.\$(OBJDIR)\DeleteElementTxn.obj \
.\$(OBJDIR)\DeleteRangeTxn.obj \
.\$(OBJDIR)\SplitElementTxn.obj \
$(NULL)
MODULE=editor

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

@ -94,6 +94,8 @@ nsresult ChangeAttributeTxn::GetIsTransient(PRBool *aIsTransient)
nsresult ChangeAttributeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -110,6 +110,8 @@ nsresult CreateElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult CreateElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteElementTxn.h"
#include "editor.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
// note that aEditor is not refcounted
DeleteElementTxn::DeleteElementTxn(nsEditor * aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode * aElement,
nsIDOMNode * aParent)
: EditTxn(aEditor)
{
mDoc = aDoc;
NS_ADDREF(mDoc);
mElement = aElement;
NS_ADDREF(mElement);
mParent = aParent;
NS_ADDREF(mParent);
}
DeleteElementTxn::~DeleteElementTxn()
{
NS_IF_RELEASE(mDoc);
NS_IF_RELEASE(mParent);
NS_IF_RELEASE(mElement);
}
nsresult DeleteElementTxn::Do(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
#ifdef NS_DEBUG
nsresult testResult;
nsCOMPtr<nsIDOMNode> parentNode;
testResult = mElement->GetParentNode(getter_AddRefs(parentNode));
NS_ASSERTION((NS_SUCCEEDED(testResult)), "bad mElement, couldn't get parent");
NS_ASSERTION((parentNode==mParent), "bad mParent, mParent!=mElement->GetParent() ");
#endif
// remember which child mElement was (by remembering which child was next)
nsresult result = mElement->GetNextSibling(getter_AddRefs(mRefNode)); // can return null mRefNode
nsCOMPtr<nsIDOMNode> resultNode;
result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Undo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->InsertBefore(mElement, mRefNode, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::Redo(void)
{
if (!mParent || !mElement)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> resultNode;
nsresult result = mParent->RemoveChild(mElement, getter_AddRefs(resultNode));
return result;
}
nsresult DeleteElementTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteElementTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteElementTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Element: ";
}
return NS_OK;
}
nsresult DeleteElementTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Element: ";
}
return NS_OK;
}

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

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteElementTxn_h__
#define DeleteElementTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMElement;
/**
* A transaction that deletes a single element
*/
class DeleteElementTxn : public EditTxn
{
public:
DeleteElementTxn(nsEditor *aEditor,
nsIDOMDocument *aDoc,
nsIDOMNode *aElement,
nsIDOMNode *aParent);
virtual ~DeleteElementTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** the document into which the new node will be inserted */
nsIDOMDocument *mDoc;
/** the element to delete */
nsIDOMNode *mElement;
/** the node into which the new node will be inserted */
nsIDOMNode *mParent;
/** the index in mParent for the new node */
PRUint32 mOffsetInParent;
/** the node we will insert mNewNode before. We compute this ourselves. */
nsCOMPtr<nsIDOMNode> mRefNode;
};
#endif

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

@ -0,0 +1,100 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "DeleteRangeTxn.h"
#include "editor.h"
#include "nsIDOMRange.h"
// note that aEditor is not refcounted
DeleteRangeTxn::DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange)
: EditTxn(aEditor)
{
aRange->GetStartParent(getter_AddRefs(mStartParent));
aRange->GetEndParent(getter_AddRefs(mEndParent));
aRange->GetStartOffset(&mStartOffset);
aRange->GetEndOffset(&mEndOffset);
}
DeleteRangeTxn::~DeleteRangeTxn()
{
}
nsresult DeleteRangeTxn::Do(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Undo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::Redo(void)
{
if (!mStartParent || !mEndParent)
return NS_ERROR_NULL_POINTER;
nsresult result;
return result;
}
nsresult DeleteRangeTxn::GetIsTransient(PRBool *aIsTransient)
{
if (nsnull!=aIsTransient)
*aIsTransient = PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}
nsresult DeleteRangeTxn::Write(nsIOutputStream *aOutputStream)
{
return NS_OK;
}
nsresult DeleteRangeTxn::GetUndoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Insert Range: ";
}
return NS_OK;
}
nsresult DeleteRangeTxn::GetRedoString(nsString **aString)
{
if (nsnull!=aString)
{
**aString="Remove Range: ";
}
return NS_OK;
}

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

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#ifndef DeleteRangeTxn_h__
#define DeleteRangeTxn_h__
#include "EditTxn.h"
#include "nsIDOMNode.h"
#include "nsCOMPtr.h"
class nsIDOMDocument;
class nsIDOMRange;
/**
* A transaction that deletes an entire range in the content tree
*/
class DeleteRangeTxn : public EditTxn
{
public:
DeleteRangeTxn(nsEditor *aEditor,
nsIDOMRange *aRange);
virtual ~DeleteRangeTxn();
virtual nsresult Do(void);
virtual nsresult Undo(void);
virtual nsresult Redo(void);
virtual nsresult GetIsTransient(PRBool *aIsTransient);
virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction);
virtual nsresult Write(nsIOutputStream *aOutputStream);
virtual nsresult GetUndoString(nsString **aString);
virtual nsresult GetRedoString(nsString **aString);
protected:
/** p1 in the range */
nsCOMPtr<nsIDOMNode> mStartParent;
/** p1 offset */
PRInt32 mStartOffset;
/** p2 in the range */
nsCOMPtr<nsIDOMNode> mEndParent;
/** p2 offset */
PRInt32 mEndOffset;
};
#endif

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

@ -55,6 +55,8 @@ nsresult DeleteTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}

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

@ -20,6 +20,8 @@
#include "editor.h"
#include "nsIDOMCharacterData.h"
static NS_DEFINE_IID(kInsertTextTxnIID, INSERTTEXTTXN_IID);
// note that aEditor is not refcounted
InsertTextTxn::InsertTextTxn(nsEditor *aEditor,
nsIDOMCharacterData *aElement,
@ -52,6 +54,23 @@ nsresult InsertTextTxn::GetIsTransient(PRBool *aIsTransient)
nsresult InsertTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
// set out param default value
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
if ((nsnull!=aDidMerge) && (nsnull!=aTransaction))
{
// if aTransaction isa InsertTextTxn, absorb it
nsCOMPtr<InsertTextTxn> otherTxn;
nsresult result = aTransaction->QueryInterface(kInsertTextTxnIID, getter_AddRefs(otherTxn));
if (NS_SUCCEEDED(result) && (otherTxn))
{
nsString otherData;
otherTxn->GetData(otherData);
mStringToInsert += otherData;
}
*aDidMerge = PR_TRUE;
}
return NS_OK;
}
@ -79,3 +98,27 @@ nsresult InsertTextTxn::GetRedoString(nsString **aString)
}
return NS_OK;
}
/* ============= nsISupports implementation ====================== */
nsresult
InsertTextTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kInsertTextTxnIID)) {
*aInstancePtr = (void*)(InsertTextTxn*)this;
NS_ADDREF_THIS();
return NS_OK;
}
return (EditTxn::QueryInterface(aIID, aInstancePtr));
}
/* ============ protected methods ================== */
nsresult InsertTextTxn::GetData(nsString& aResult)
{
aResult = mStringToInsert;
return NS_OK;
}

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

@ -21,6 +21,11 @@
#include "EditTxn.h"
#define INSERTTEXTTXN_IID \
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
0x93276f00, 0xab2c, 0x11d2, \
{0x8f, 0xb4, 0x0, 0x60, 0x8, 0x15, 0x9b, 0xc} }
class nsIDOMCharacterData;
/**
@ -50,6 +55,16 @@ public:
virtual nsresult GetRedoString(nsString **aString);
// nsISupports declarations
// override QueryInterface to handle InsertTextTxn request
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
static const nsIID& IID() { static nsIID iid = INSERTTEXTTXN_IID; return iid; }
virtual nsresult GetData(nsString& aResult);
protected:
/** the text element to operate upon */

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

@ -82,6 +82,8 @@ nsresult SplitElementTxn::GetIsTransient(PRBool *aIsTransient)
nsresult SplitElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
{
if (nsnull!=aDidMerge)
*aDidMerge=PR_FALSE;
return NS_OK;
}