diff --git a/mozilla/editor/base/CreateElementTxn.cpp b/mozilla/editor/base/CreateElementTxn.cpp index 2c81569033e..3565e6d4992 100644 --- a/mozilla/editor/base/CreateElementTxn.cpp +++ b/mozilla/editor/base/CreateElementTxn.cpp @@ -183,3 +183,14 @@ nsresult CreateElementTxn::GetRedoString(nsString **aString) } return NS_OK; } + +nsresult CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode) +{ + if (!aNewNode) + return NS_ERROR_NULL_POINTER; + if (!mNewNode) + return NS_ERROR_NOT_INITIALIZED; + *aNewNode = mNewNode; + NS_ADDREF(*aNewNode); + return NS_OK; +} diff --git a/mozilla/editor/base/CreateElementTxn.h b/mozilla/editor/base/CreateElementTxn.h index 35f59ad4377..11ea100985a 100644 --- a/mozilla/editor/base/CreateElementTxn.h +++ b/mozilla/editor/base/CreateElementTxn.h @@ -72,6 +72,8 @@ public: virtual nsresult GetRedoString(nsString **aString); + virtual nsresult GetNewNode(nsIDOMNode **aNewNode); + protected: /** the document into which the new node will be inserted */ diff --git a/mozilla/editor/base/InsertElementTxn.cpp b/mozilla/editor/base/InsertElementTxn.cpp new file mode 100644 index 00000000000..d8b638834e8 --- /dev/null +++ b/mozilla/editor/base/InsertElementTxn.cpp @@ -0,0 +1,118 @@ +/* -*- 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 "InsertElementTxn.h" + +#ifdef NS_DEBUG +static PRBool gNoisy = PR_FALSE; +#else +static const PRBool gNoisy = PR_FALSE; +#endif + + +InsertElementTxn::InsertElementTxn() + : EditTxn() +{ +} + +nsresult InsertElementTxn::Init(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aOffset) +{ + if (!aNode || !aParent) + return NS_ERROR_NULL_POINTER; + + mNode = do_QueryInterface(aNode); + mParent = do_QueryInterface(aParent); + return NS_OK; +} + + +InsertElementTxn::~InsertElementTxn() +{ +} + +nsresult InsertElementTxn::Do(void) +{ + if (!mNode || !mParent) + return NS_ERROR_NULL_POINTER; + + nsresult result; + nsCOMPtrrefNode; + if (0!=mOffset) + { // get a ref node + PRInt32 i=0; + result = mParent->GetFirstChild(getter_AddRefs(refNode)); + for (; inextSib; + result = refNode->GetNextSibling(getter_AddRefs(nextSib)); + if (NS_FAILED(result)) { + break; // couldn't get a next sibling, so make aNode the first child + } + refNode = do_QueryInterface(nextSib); + if (!refNode) { + break; // couldn't get a next sibling, so make aNode the first child + } + } + } + + nsCOMPtr resultNode; + result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode)); + return result; +} + +nsresult InsertElementTxn::Undo(void) +{ + if (!mNode || !mParent) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr resultNode; + nsresult result = mParent->RemoveChild(mNode, getter_AddRefs(resultNode)); + return result; +} + +nsresult InsertElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction) +{ + if (nsnull!=aDidMerge) + *aDidMerge=PR_FALSE; + return NS_OK; +} + +nsresult InsertElementTxn::Write(nsIOutputStream *aOutputStream) +{ + return NS_OK; +} + +nsresult InsertElementTxn::GetUndoString(nsString **aString) +{ + if (nsnull!=aString) + { + **aString="Remove Element: "; + } + return NS_OK; +} + +nsresult InsertElementTxn::GetRedoString(nsString **aString) +{ + if (nsnull!=aString) + { + **aString="Insert Element: "; + } + return NS_OK; +} diff --git a/mozilla/editor/base/InsertElementTxn.h b/mozilla/editor/base/InsertElementTxn.h new file mode 100644 index 00000000000..7bd202bdf06 --- /dev/null +++ b/mozilla/editor/base/InsertElementTxn.h @@ -0,0 +1,81 @@ +/* -*- 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 InsertElementTxn_h__ +#define InsertElementTxn_h__ + +#include "EditTxn.h" +#include "nsIDOMNode.h" +#include "nsCOMPtr.h" + +#define INSERT_ELEMENT_TXN_IID \ +{/* b5762440-cbb0-11d2-86db-000064657374 */ \ +0xb5762440, 0xcbb0, 0x11d2, \ +{0x86, 0xdb, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} } + +/** + * A transaction that deletes a single element + */ +class InsertElementTxn : public EditTxn +{ +public: + + /** initialize the transaction. + * @param aNode the node to insert + * @param aParent the node to insert into + * @param aOffset the offset in aParent to insert aNode + */ + virtual nsresult Init(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aOffset); + +private: + InsertElementTxn(); + +public: + + virtual ~InsertElementTxn(); + + virtual nsresult Do(void); + + virtual nsresult Undo(void); + + virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction); + + virtual nsresult Write(nsIOutputStream *aOutputStream); + + virtual nsresult GetUndoString(nsString **aString); + + virtual nsresult GetRedoString(nsString **aString); + +protected: + + /** the element to delete */ + nsCOMPtr mNode; + + /** the node into which the new node will be inserted */ + nsCOMPtr mParent; + + /** the index in mParent for the new node */ + PRInt32 mOffset; + + friend class TransactionFactory; + +}; + +#endif diff --git a/mozilla/editor/base/Makefile.in b/mozilla/editor/base/Makefile.in index 292b5b0640f..e596848fe83 100644 --- a/mozilla/editor/base/Makefile.in +++ b/mozilla/editor/base/Makefile.in @@ -28,6 +28,7 @@ CPPSRCS = \ nsEditor.cpp \ nsTextEditor.cpp \ nsEditorEventListeners.cpp \ + nsEditProperty.cpp \ nsEditFactory.cpp \ nsTextEditFactory.cpp \ ChangeAttributeTxn.cpp \ @@ -36,6 +37,7 @@ CPPSRCS = \ InsertTextTxn.cpp \ DeleteTextTxn.cpp \ CreateElementTxn.cpp \ + InsertElementTxn.cpp \ DeleteElementTxn.cpp \ DeleteRangeTxn.cpp \ SplitElementTxn.cpp \ diff --git a/mozilla/editor/base/SplitElementTxn.cpp b/mozilla/editor/base/SplitElementTxn.cpp index 295c76daa69..037060c537b 100644 --- a/mozilla/editor/base/SplitElementTxn.cpp +++ b/mozilla/editor/base/SplitElementTxn.cpp @@ -127,3 +127,14 @@ nsresult SplitElementTxn::GetRedoString(nsString **aString) } return NS_OK; } + +nsresult SplitElementTxn::GetNewNode(nsIDOMNode **aNewNode) +{ + if (!aNewNode) + return NS_ERROR_NULL_POINTER; + if (!mNewLeftNode) + return NS_ERROR_NOT_INITIALIZED; + *aNewNode = mNewLeftNode; + NS_ADDREF(*aNewNode); + return NS_OK; +} diff --git a/mozilla/editor/base/SplitElementTxn.h b/mozilla/editor/base/SplitElementTxn.h index ec0081ab0a3..8a8af69da99 100644 --- a/mozilla/editor/base/SplitElementTxn.h +++ b/mozilla/editor/base/SplitElementTxn.h @@ -67,6 +67,8 @@ public: virtual nsresult GetRedoString(nsString **aString); + virtual nsresult GetNewNode(nsIDOMNode **aNewNode); + protected: /** the element to operate upon */ diff --git a/mozilla/editor/base/TransactionFactory.cpp b/mozilla/editor/base/TransactionFactory.cpp index c8fab50f90d..c443558549e 100644 --- a/mozilla/editor/base/TransactionFactory.cpp +++ b/mozilla/editor/base/TransactionFactory.cpp @@ -22,6 +22,7 @@ #include "InsertTextTxn.h" #include "DeleteTextTxn.h" #include "CreateElementTxn.h" +#include "InsertElementTxn.h" #include "DeleteElementTxn.h" #include "DeleteRangeTxn.h" #include "ChangeAttributeTxn.h" @@ -32,6 +33,7 @@ static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID); static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID); static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID); static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID); +static NS_DEFINE_IID(kInsertElementTxnIID, INSERT_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID); static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID); @@ -57,6 +59,8 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult) *aResult = new DeleteTextTxn(); else if (aTxnType.Equals(kCreateElementTxnIID)) *aResult = new CreateElementTxn(); + else if (aTxnType.Equals(kInsertElementTxnIID)) + *aResult = new InsertElementTxn(); else if (aTxnType.Equals(kDeleteElementTxnIID)) *aResult = new DeleteElementTxn(); else if (aTxnType.Equals(kDeleteRangeTxnIID)) diff --git a/mozilla/editor/base/makefile.win b/mozilla/editor/base/makefile.win index 90dbffd8f7e..4d0efc2b232 100644 --- a/mozilla/editor/base/makefile.win +++ b/mozilla/editor/base/makefile.win @@ -24,6 +24,7 @@ CPPSRCS = \ nsEditor.cpp \ nsTextEditor.cpp \ nsEditorEventListeners.cpp \ + nsEditProperty.cpp \ nsEditFactory.cpp \ nsTextEditFactory.cpp \ EditTxn.cpp \ @@ -32,6 +33,7 @@ CPPSRCS = \ InsertTextTxn.cpp \ DeleteTextTxn.cpp \ CreateElementTxn.cpp \ + InsertElementTxn.cpp \ DeleteElementTxn.cpp \ DeleteRangeTxn.cpp \ SplitElementTxn.cpp \ @@ -43,7 +45,8 @@ CPP_OBJS = \ .\$(OBJDIR)\nsEditor.obj \ .\$(OBJDIR)\nsTextEditor.obj \ .\$(OBJDIR)\nsEditorEventListeners.obj \ - .\$(OBJDIR)\nsEditFactory.obj \ + .\$(OBJDIR)\nsEditProperty.obj \ + .\$(OBJDIR)\nsEditFactory.obj \ .\$(OBJDIR)\nsTextEditFactory.obj \ .\$(OBJDIR)\EditTxn.obj \ .\$(OBJDIR)\EditAggregateTxn.obj \ @@ -51,6 +54,7 @@ CPP_OBJS = \ .\$(OBJDIR)\InsertTextTxn.obj \ .\$(OBJDIR)\DeleteTextTxn.obj \ .\$(OBJDIR)\CreateElementTxn.obj \ + .\$(OBJDIR)\InsertElementTxn.obj \ .\$(OBJDIR)\DeleteElementTxn.obj \ .\$(OBJDIR)\DeleteRangeTxn.obj \ .\$(OBJDIR)\SplitElementTxn.obj \ diff --git a/mozilla/editor/base/nsEditProperty.cpp b/mozilla/editor/base/nsEditProperty.cpp new file mode 100644 index 00000000000..b144d9f6c89 --- /dev/null +++ b/mozilla/editor/base/nsEditProperty.cpp @@ -0,0 +1,63 @@ +/* -*- 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 "nsEditProperty.h" + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); + + +NS_IMPL_ADDREF(nsEditProperty) + +NS_IMPL_RELEASE(nsEditProperty) + +nsIAtom * nsIEditProperty::bold = NS_NewAtom("BOLD"); +nsIAtom * nsIEditProperty::italic = NS_NewAtom("ITALIC"); + +nsresult +nsEditProperty::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(kIEditPropertyIID)) { + *aInstancePtr = (void*)(nsIEditProperty*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +nsresult NS_NewEditProperty(nsIEditProperty **aResult) +{ + if (aResult) + { + *aResult = new nsEditProperty(); + if (!*aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(*aResult); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} \ No newline at end of file diff --git a/mozilla/editor/base/nsEditProperty.h b/mozilla/editor/base/nsEditProperty.h new file mode 100644 index 00000000000..388cd49d4eb --- /dev/null +++ b/mozilla/editor/base/nsEditProperty.h @@ -0,0 +1,107 @@ +/* -*- 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://wwwt.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 __nsEditProperty_h__ +#define __nsEditProperty_h__ + +#include "nsIEditProperty.h" +#include "nsIAtom.h" +#include "nsCOMPtr.h" +#include "nsISupports.h" + +/** simple class for describing a single property as it relates to a range of content. + * not ref counted. + * + */ +class nsEditProperty : public nsIEditProperty +{ +public: + /*interfaces for addref and release and queryinterface*/ + NS_DECL_ISUPPORTS + +protected: + nsEditProperty (); + virtual ~nsEditProperty(); + +public: + virtual nsresult Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll); + virtual nsresult GetProperty(nsIAtom **aProperty) const; + virtual nsresult GetValue(nsIAtom **aValue) const; + virtual nsresult GetAppliesToAll(PRBool *aAppliesToAll) const; + +protected: + nsCOMPtrmProperty; + nsCOMPtrmValue; + PRBool mAppliesToAll; + + friend nsresult NS_NewEditProperty(nsIEditProperty **aResult); +}; + +inline nsEditProperty::nsEditProperty() +{ + NS_INIT_REFCNT(); +}; + +inline nsEditProperty::~nsEditProperty() {}; + +inline nsresult nsEditProperty::Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll) +{ + if (!aPropName) + return NS_ERROR_NULL_POINTER; + + mProperty = do_QueryInterface(aPropName); + mValue = do_QueryInterface(aValue); + mAppliesToAll = aAppliesToAll; + return NS_OK; +}; + +inline nsresult nsEditProperty::GetProperty(nsIAtom **aProperty) const +{ + if (!aProperty) { + return NS_ERROR_NULL_POINTER; + } + *aProperty = mProperty; + if (*aProperty) { + NS_ADDREF(*aProperty); + } + return NS_OK; +}; + +inline nsresult nsEditProperty::GetValue(nsIAtom **aValue) const +{ + if (!aValue) { + return NS_ERROR_NULL_POINTER; + } + *aValue = mValue; + if (*aValue) { + NS_ADDREF(*aValue); + } return NS_OK; +}; + +inline nsresult nsEditProperty::GetAppliesToAll(PRBool *aAppliesToAll) const +{ + if (!aAppliesToAll) { + return NS_ERROR_NULL_POINTER; + } + *aAppliesToAll = mAppliesToAll; + return NS_OK; +}; + + + +#endif diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index 582bdd3736d..76371c34f0c 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -48,6 +48,7 @@ #include "EditAggregateTxn.h" #include "ChangeAttributeTxn.h" #include "CreateElementTxn.h" +#include "InsertElementTxn.h" #include "DeleteElementTxn.h" #include "InsertTextTxn.h" #include "DeleteTextTxn.h" @@ -78,6 +79,7 @@ static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID); static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID); static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID); static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID); +static NS_DEFINE_IID(kInsertElementTxnIID, INSERT_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID); static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID); @@ -566,14 +568,12 @@ nsresult nsEditor::Do(nsITransaction *aTxn) { nsresult result = NS_OK; - if (nsnull!=aTxn) + if (aTxn) { - if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) - { + if (mTxnMgr) { result = mTxnMgr->Do(aTxn); } - else - { + else { result = aTxn->Do(); } } @@ -690,12 +690,19 @@ nsresult nsEditor::ScrollIntoView(PRBool aScrollToBegin) nsresult nsEditor::CreateNode(const nsString& aTag, nsIDOMNode * aParent, - PRInt32 aPosition) + PRInt32 aPosition, + nsIDOMNode ** aNewNode) { CreateElementTxn *txn; nsresult result = CreateTxnForCreateElement(aTag, aParent, aPosition, &txn); - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) + { result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = txn->GetNewNode(aNewNode); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetNewNode can't fail if txn::Do succeeded."); + } } return result; } @@ -720,16 +727,28 @@ nsresult nsEditor::InsertNode(nsIDOMNode * aNode, nsIDOMNode * aParent, PRInt32 aPosition) { - // GetLayoutObjectFor test - nsAutoString cellTag("TD"); - nsCOMPtr node; - if (NS_SUCCEEDED(GetFirstNodeOfType(nsnull, cellTag, getter_AddRefs(node)))) - { - PRInt32 cellIndex; - GetColIndexForCell(mPresShell, node, cellIndex); - printf("%d\n", cellIndex); + InsertElementTxn *txn; + nsresult result = CreateTxnForInsertElement(aNode, aParent, aPosition, &txn); + if (NS_SUCCEEDED(result)) { + result = Do(txn); } - return NS_ERROR_NOT_IMPLEMENTED; + return result; +} + +nsresult nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode, + nsIDOMNode * aParent, + PRInt32 aPosition, + InsertElementTxn ** aTxn) +{ + nsresult result = NS_ERROR_NULL_POINTER; + if (aNode && aParent && aTxn) + { + result = TransactionFactory::GetNewTransaction(kInsertElementTxnIID, (EditTxn **)aTxn); + if (NS_SUCCEEDED(result)) { + result = (*aTxn)->Init(aNode, aParent, aPosition); + } + } + return result; } nsresult nsEditor::DeleteNode(nsIDOMNode * aElement) @@ -753,7 +772,6 @@ nsresult nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aElement, result = (*aTxn)->Init(aElement); } } - return result; } @@ -1280,12 +1298,19 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode) nsresult nsEditor::SplitNode(nsIDOMNode * aNode, - PRInt32 aOffset) + PRInt32 aOffset, + nsIDOMNode **aNewLeftNode) { SplitElementTxn *txn; nsresult result = CreateTxnForSplitNode(aNode, aOffset, &txn); - if (NS_SUCCEEDED(result)) { - result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = txn->GetNewNode(aNewLeftNode); + NS_ASSERTION((NS_SUCCEEDED(result)), "result must succeeded for GetNewNode"); + } } return result; } diff --git a/mozilla/editor/base/nsEditor.h b/mozilla/editor/base/nsEditor.h index 4c1893cdb30..7eb0b7ca470 100644 --- a/mozilla/editor/base/nsEditor.h +++ b/mozilla/editor/base/nsEditor.h @@ -36,6 +36,7 @@ class nsIPresShell; class nsIViewManager; class ChangeAttributeTxn; class CreateElementTxn; +class InsertElementTxn; class DeleteElementTxn; class InsertTextTxn; class DeleteTextTxn; @@ -47,25 +48,6 @@ class nsVoidArray; //This is the monitor for the editor. PRMonitor *getEditorMonitor(); -/* -struct Properties -{ - Properties (nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll); - ~Properties(); - - nsIAtom *mPropName; - nsIAtom *mValue; - PRBool mAppliesToAll; -}; - -inline Property::Property(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll) -{ - mPropName = aPropName; - mPropValue = aPropValue; - mAppliesToAll = aAppliesToAll; -}; - -*/ /** implementation of an editor object. it will be the controler/focal point * for the main editor services. i.e. the GUIManager, publishing, transaction @@ -123,7 +105,8 @@ public: virtual nsresult CreateNode(const nsString& aTag, nsIDOMNode * aParent, - PRInt32 aPosition); + PRInt32 aPosition, + nsIDOMNode ** aNewNode); virtual nsresult InsertNode(nsIDOMNode * aNode, nsIDOMNode * aParent, @@ -135,7 +118,8 @@ public: virtual nsresult DeleteSelection(nsIEditor::Direction aDir); virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode, - PRInt32 aOffset); + PRInt32 aOffset, + nsIDOMNode ** aNewLeftNode); virtual nsresult JoinNodes(nsIDOMNode * aNodeToKeep, nsIDOMNode * aNodeToJoin, @@ -207,6 +191,11 @@ protected: PRInt32 aPosition, CreateElementTxn ** aTxn); + virtual nsresult CreateTxnForInsertElement(nsIDOMNode * aNode, + nsIDOMNode * aParent, + PRInt32 aOffset, + InsertElementTxn ** aTxn); + virtual nsresult CreateTxnForDeleteElement(nsIDOMNode * aElement, DeleteElementTxn ** aTxn); diff --git a/mozilla/editor/base/nsEditorEventListeners.cpp b/mozilla/editor/base/nsEditorEventListeners.cpp index d33f9e2569e..f18585ab36d 100644 --- a/mozilla/editor/base/nsEditorEventListeners.cpp +++ b/mozilla/editor/base/nsEditorEventListeners.cpp @@ -23,8 +23,8 @@ #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMCharacterData.h" - - +#include "nsIEditProperty.h" +#include "nsISupportsArray.h" #include "nsString.h" static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); @@ -225,36 +225,52 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr } break; - // hard-coded split node test: works on first

in the document - case nsIDOMEvent::VK_S: - /* + // hard-coded ChangeTextAttributes test -- italics + case nsIDOMEvent::VK_I: if (PR_TRUE==ctrlKey) { - nsAutoString pTag("P"); - nsCOMPtr currentNode; - nsCOMPtr element; - if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode)))) - { - nsresult result; - SplitElementTxn *txn; - if (PR_FALSE==isShift) // split the element so there are 0 children in the first half - { - result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn); - if (txn) - 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(mEditor, currentNode, 1); - } - if (txn) - mEditor->Do(txn); - } aProcessed=PR_TRUE; + if ((nsITextEditor *)nsnull!=mEditor.get()) + { + nsCOMPtrprop; + nsresult result = NS_NewEditProperty(getter_AddRefs(prop)); + if ((NS_SUCCEEDED(result)) && prop) + { + prop->Init(nsIEditProperty::italic, nsnull, PR_TRUE); + nsCOMPtrpropList; + result = NS_NewISupportsArray(getter_AddRefs(propList)); + if ((NS_SUCCEEDED(result)) && propList) + { + propList->AppendElement(prop); + mEditor->SetTextProperties(propList); + } + } + } + } + break; + + // hard-coded ChangeTextAttributes test -- bold + case nsIDOMEvent::VK_B: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if ((nsITextEditor *)nsnull!=mEditor.get()) + { + nsCOMPtrprop; + nsresult result = NS_NewEditProperty(getter_AddRefs(prop)); + if ((NS_SUCCEEDED(result)) && prop) + { + prop->Init(nsIEditProperty::bold, nsnull, PR_TRUE); + nsCOMPtrpropList; + result = NS_NewISupportsArray(getter_AddRefs(propList)); + if ((NS_SUCCEEDED(result)) && propList) + { + propList->AppendElement(prop); + mEditor->SetTextProperties(propList); + } + } + } } - */ break; diff --git a/mozilla/editor/base/nsIEditProperty.h b/mozilla/editor/base/nsIEditProperty.h new file mode 100644 index 00000000000..de2c7abb698 --- /dev/null +++ b/mozilla/editor/base/nsIEditProperty.h @@ -0,0 +1,53 @@ +/* -*- 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://wwwt.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 __nsIEditProperty_h__ +#define __nsIEditProperty_h__ + +#include "nsISupports.h" + +class nsIAtom; + +#define NS_IEDITPROPERTY_IID \ +{/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ +0x9875cd40, 0xca81, 0x11d2, \ +{0x8f, 0x4d, 0x0, 0x60, 0x8, 0x15, 0x9b, 0x0c} } + +/** simple interface for describing a single property as it relates to a range of content. + * + */ + +class nsIEditProperty : public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IEDITPROPERTY_IID; return iid; } + + virtual nsresult Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll)=0; + virtual nsresult GetProperty(nsIAtom **aProperty) const =0; + virtual nsresult GetValue(nsIAtom **aValue) const =0; + virtual nsresult GetAppliesToAll(PRBool *aAppliesToAll) const =0; + +/* we're still trying to decide how edit atoms will work. Until then, use these */ +// XXX: fix ASAP! + static nsIAtom *bold; + static nsIAtom *italic; +}; + +extern nsresult NS_NewEditProperty(nsIEditProperty **aResult); + +#endif \ No newline at end of file diff --git a/mozilla/editor/base/nsTextEditor.cpp b/mozilla/editor/base/nsTextEditor.cpp index 571e567ab02..e4c4d34741b 100644 --- a/mozilla/editor/base/nsTextEditor.cpp +++ b/mozilla/editor/base/nsTextEditor.cpp @@ -19,13 +19,17 @@ #include "nsTextEditor.h" #include "nsIEditorSupport.h" #include "nsEditorEventListeners.h" +#include "nsIEditProperty.h" #include "nsIDOMDocument.h" #include "nsIDOMEventReceiver.h" #include "nsIDOMKeyListener.h" #include "nsIDOMMouseListener.h" #include "nsIDOMSelection.h" +#include "nsIDOMRange.h" #include "nsIDOMNodeList.h" #include "nsEditorCID.h" +#include "nsISupportsArray.h" +#include "nsIEnumerator.h" #include "CreateElementTxn.h" @@ -35,6 +39,7 @@ static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID); static NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID); +static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); static NS_DEFINE_CID(kEditorCID, NS_EDITOR_CID); static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID); @@ -122,7 +127,84 @@ nsresult nsTextEditor::InitTextEditor(nsIDOMDocument *aDoc, return result; } -nsresult nsTextEditor::SetTextProperties(nsVoidArray *aPropList) +// this is a total hack for now. We don't yet have a way of getting the style properties +// of the current selection, so we can't do anything useful here except show off a little. +nsresult nsTextEditor::SetTextProperties(nsISupportsArray *aPropList) +{ + if (!aPropList) + return NS_ERROR_NULL_POINTER; + + nsresult result=NS_ERROR_NOT_INITIALIZED; + if (mEditor) + { + nsCOMPtrselection; + result = mEditor->GetSelection(getter_AddRefs(selection)); + if ((NS_SUCCEEDED(result)) && selection) + { + mEditor->BeginTransaction(); + PRInt32 count = aPropList->Count(); + PRInt32 i=0; + for ( ; iElementAt(i); + if (propAsSupports) + { + nsCOMPtr prop; + result = propAsSupports->QueryInterface(kIEditPropertyIID, + getter_AddRefs(prop)); + if ((NS_SUCCEEDED(result)) && prop) + { + nsCOMPtrpropName; + result = prop->GetProperty(getter_AddRefs(propName)); + if ((NS_SUCCEEDED(result)) && prop) + { + nsCOMPtr enumerator; + enumerator = do_QueryInterface(selection, &result); + if ((NS_SUCCEEDED(result)) && enumerator) + { + enumerator->First(); + nsISupports *currentItem; + result = enumerator->CurrentItem(¤tItem); + if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem)) + { + nsCOMPtr range(currentItem); + nsCOMPtrcommonParent; + result = range->GetCommonParent(getter_AddRefs(commonParent)); + if ((NS_SUCCEEDED(result)) && commonParent) + { + PRInt32 startOffset, endOffset; + range->GetStartOffset(&startOffset); + range->GetEndOffset(&endOffset); + nsCOMPtr startParent; nsCOMPtr endParent; + range->GetStartParent(getter_AddRefs(startParent)); + range->GetEndParent(getter_AddRefs(endParent)); + if (startParent.get()==endParent.get()) { + result = SetTextPropertiesForNode(startParent, commonParent, + startOffset, endOffset, + propName); + if (NS_SUCCEEDED(result)) + { // set the selection + // don't want to actually do anything with selection, because + // I'm still iterating through it. Just want to create and remember + // an nsIDOMRange, and later add the range to the selection after clearing it. + } + } + } + } + } + } + } + NS_RELEASE(propAsSupports); + } + } + mEditor->EndTransaction(); + } + } + return result; +} + +nsresult nsTextEditor::GetTextProperties(nsISupportsArray *aPropList) { nsresult result=NS_ERROR_NOT_INITIALIZED; if (mEditor) @@ -132,17 +214,7 @@ nsresult nsTextEditor::SetTextProperties(nsVoidArray *aPropList) return result; } -nsresult nsTextEditor::GetTextProperties(nsVoidArray *aPropList) -{ - nsresult result=NS_ERROR_NOT_INITIALIZED; - if (mEditor) - { - result = NS_ERROR_NOT_IMPLEMENTED; - } - return result; -} - -nsresult nsTextEditor::RemoveTextProperties(nsVoidArray *aPropList) +nsresult nsTextEditor::RemoveTextProperties(nsISupportsArray *aPropList) { nsresult result=NS_ERROR_NOT_INITIALIZED; if (mEditor) @@ -201,14 +273,26 @@ nsresult nsTextEditor::InsertBreak(PRBool aCtrlKey) nsCOMPtr node; PRInt32 offset; result = selection->GetAnchorNodeAndOffset(getter_AddRefs(node), &offset); - nsCOMPtr parentNode; - result = node->GetParentNode(getter_AddRefs(parentNode)); - result = mEditor->SplitNode(node, offset); - // now get the node's offset in it's parent, and insert the new BR there - result = nsIEditorSupport::GetChildOffset(node, parentNode, offset); - nsAutoString tag("BR"); - result = mEditor->CreateNode(tag, parentNode, offset); - selection->Collapse(parentNode, offset); + if ((NS_SUCCEEDED(result)) && node) + { + nsCOMPtr parentNode; + nsCOMPtr newNode; + result = node->GetParentNode(getter_AddRefs(parentNode)); + if ((NS_SUCCEEDED(result)) && parentNode) + { + result = mEditor->SplitNode(node, offset, getter_AddRefs(newNode)); + if (NS_SUCCEEDED(result)) + { // now get the node's offset in it's parent, and insert the new BR there + result = nsIEditorSupport::GetChildOffset(node, parentNode, offset); + if (NS_SUCCEEDED(result)) + { + nsAutoString tag("BR"); + result = mEditor->CreateNode(tag, parentNode, offset, getter_AddRefs(newNode)); + selection->Collapse(parentNode, offset); + } + } + } + } } if (PR_TRUE==beganTransaction) { result = mEditor->EndTransaction(); @@ -431,3 +515,42 @@ nsTextEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr) } +nsresult nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aStartOffset, + PRInt32 aEndOffset, + nsIAtom *aPropName) +{ + nsresult result; + nsCOMPtrnewTextNode; // this will be the middle text node + result = mEditor->SplitNode(aNode, aStartOffset, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) + { + result = mEditor->SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) + { + nsAutoString tag; + if (nsIEditProperty::bold==aPropName) { + tag = "b"; + } + else if (nsIEditProperty::italic==aPropName) { + tag = "i"; + } + PRInt32 offsetInParent; + result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent); + if (NS_SUCCEEDED(result)) + { + nsCOMPtrnewStyleNode; + result = mEditor->CreateNode(tag, aParent, offsetInParent, getter_AddRefs(newStyleNode)); + if (NS_SUCCEEDED(result)) + { + result = mEditor->DeleteNode(newTextNode); + if (NS_SUCCEEDED(result)) { + result = mEditor->InsertNode(newTextNode, newStyleNode, 0); + } + } + } + } + } + return result; +} \ No newline at end of file diff --git a/mozilla/editor/base/nsTextEditor.h b/mozilla/editor/base/nsTextEditor.h index 9e7fb65980e..49d21126ae1 100644 --- a/mozilla/editor/base/nsTextEditor.h +++ b/mozilla/editor/base/nsTextEditor.h @@ -23,6 +23,8 @@ #include "nsCOMPtr.h" #include "nsIDOMEventListener.h" +class nsISupportsArray; + /** * The text editor implementation.
@@ -45,9 +47,9 @@ public: virtual ~nsTextEditor(); // Editing Operations - virtual nsresult SetTextProperties(nsVoidArray *aPropList); - virtual nsresult GetTextProperties(nsVoidArray *aPropList); - virtual nsresult RemoveTextProperties(nsVoidArray *aPropList); + virtual nsresult SetTextProperties(nsISupportsArray *aPropList); + virtual nsresult GetTextProperties(nsISupportsArray *aPropList); + virtual nsresult RemoveTextProperties(nsISupportsArray *aPropList); virtual nsresult DeleteSelection(nsIEditor::Direction aDir); virtual nsresult InsertText(const nsString& aStringToInsert); virtual nsresult InsertBreak(PRBool aCtrlKey); @@ -77,6 +79,15 @@ public: virtual nsresult OutputText(nsIOutputStream *aOutputStream); virtual nsresult OutputHTML(nsIOutputStream *aOutputStream); + +protected: +// Utility Methods + virtual nsresult SetTextPropertiesForNode(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aStartOffset, + PRInt32 aEndOffset, + nsIAtom *aPropName); + // Data members protected: nsCOMPtr mEditor; diff --git a/mozilla/editor/libeditor/base/CreateElementTxn.cpp b/mozilla/editor/libeditor/base/CreateElementTxn.cpp index 2c81569033e..3565e6d4992 100644 --- a/mozilla/editor/libeditor/base/CreateElementTxn.cpp +++ b/mozilla/editor/libeditor/base/CreateElementTxn.cpp @@ -183,3 +183,14 @@ nsresult CreateElementTxn::GetRedoString(nsString **aString) } return NS_OK; } + +nsresult CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode) +{ + if (!aNewNode) + return NS_ERROR_NULL_POINTER; + if (!mNewNode) + return NS_ERROR_NOT_INITIALIZED; + *aNewNode = mNewNode; + NS_ADDREF(*aNewNode); + return NS_OK; +} diff --git a/mozilla/editor/libeditor/base/CreateElementTxn.h b/mozilla/editor/libeditor/base/CreateElementTxn.h index 35f59ad4377..11ea100985a 100644 --- a/mozilla/editor/libeditor/base/CreateElementTxn.h +++ b/mozilla/editor/libeditor/base/CreateElementTxn.h @@ -72,6 +72,8 @@ public: virtual nsresult GetRedoString(nsString **aString); + virtual nsresult GetNewNode(nsIDOMNode **aNewNode); + protected: /** the document into which the new node will be inserted */ diff --git a/mozilla/editor/libeditor/base/InsertElementTxn.cpp b/mozilla/editor/libeditor/base/InsertElementTxn.cpp new file mode 100644 index 00000000000..d8b638834e8 --- /dev/null +++ b/mozilla/editor/libeditor/base/InsertElementTxn.cpp @@ -0,0 +1,118 @@ +/* -*- 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 "InsertElementTxn.h" + +#ifdef NS_DEBUG +static PRBool gNoisy = PR_FALSE; +#else +static const PRBool gNoisy = PR_FALSE; +#endif + + +InsertElementTxn::InsertElementTxn() + : EditTxn() +{ +} + +nsresult InsertElementTxn::Init(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aOffset) +{ + if (!aNode || !aParent) + return NS_ERROR_NULL_POINTER; + + mNode = do_QueryInterface(aNode); + mParent = do_QueryInterface(aParent); + return NS_OK; +} + + +InsertElementTxn::~InsertElementTxn() +{ +} + +nsresult InsertElementTxn::Do(void) +{ + if (!mNode || !mParent) + return NS_ERROR_NULL_POINTER; + + nsresult result; + nsCOMPtrrefNode; + if (0!=mOffset) + { // get a ref node + PRInt32 i=0; + result = mParent->GetFirstChild(getter_AddRefs(refNode)); + for (; inextSib; + result = refNode->GetNextSibling(getter_AddRefs(nextSib)); + if (NS_FAILED(result)) { + break; // couldn't get a next sibling, so make aNode the first child + } + refNode = do_QueryInterface(nextSib); + if (!refNode) { + break; // couldn't get a next sibling, so make aNode the first child + } + } + } + + nsCOMPtr resultNode; + result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode)); + return result; +} + +nsresult InsertElementTxn::Undo(void) +{ + if (!mNode || !mParent) + return NS_ERROR_NULL_POINTER; + + nsCOMPtr resultNode; + nsresult result = mParent->RemoveChild(mNode, getter_AddRefs(resultNode)); + return result; +} + +nsresult InsertElementTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction) +{ + if (nsnull!=aDidMerge) + *aDidMerge=PR_FALSE; + return NS_OK; +} + +nsresult InsertElementTxn::Write(nsIOutputStream *aOutputStream) +{ + return NS_OK; +} + +nsresult InsertElementTxn::GetUndoString(nsString **aString) +{ + if (nsnull!=aString) + { + **aString="Remove Element: "; + } + return NS_OK; +} + +nsresult InsertElementTxn::GetRedoString(nsString **aString) +{ + if (nsnull!=aString) + { + **aString="Insert Element: "; + } + return NS_OK; +} diff --git a/mozilla/editor/libeditor/base/InsertElementTxn.h b/mozilla/editor/libeditor/base/InsertElementTxn.h new file mode 100644 index 00000000000..7bd202bdf06 --- /dev/null +++ b/mozilla/editor/libeditor/base/InsertElementTxn.h @@ -0,0 +1,81 @@ +/* -*- 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 InsertElementTxn_h__ +#define InsertElementTxn_h__ + +#include "EditTxn.h" +#include "nsIDOMNode.h" +#include "nsCOMPtr.h" + +#define INSERT_ELEMENT_TXN_IID \ +{/* b5762440-cbb0-11d2-86db-000064657374 */ \ +0xb5762440, 0xcbb0, 0x11d2, \ +{0x86, 0xdb, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} } + +/** + * A transaction that deletes a single element + */ +class InsertElementTxn : public EditTxn +{ +public: + + /** initialize the transaction. + * @param aNode the node to insert + * @param aParent the node to insert into + * @param aOffset the offset in aParent to insert aNode + */ + virtual nsresult Init(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aOffset); + +private: + InsertElementTxn(); + +public: + + virtual ~InsertElementTxn(); + + virtual nsresult Do(void); + + virtual nsresult Undo(void); + + virtual nsresult Merge(PRBool *aDidMerge, nsITransaction *aTransaction); + + virtual nsresult Write(nsIOutputStream *aOutputStream); + + virtual nsresult GetUndoString(nsString **aString); + + virtual nsresult GetRedoString(nsString **aString); + +protected: + + /** the element to delete */ + nsCOMPtr mNode; + + /** the node into which the new node will be inserted */ + nsCOMPtr mParent; + + /** the index in mParent for the new node */ + PRInt32 mOffset; + + friend class TransactionFactory; + +}; + +#endif diff --git a/mozilla/editor/libeditor/base/SplitElementTxn.cpp b/mozilla/editor/libeditor/base/SplitElementTxn.cpp index 295c76daa69..037060c537b 100644 --- a/mozilla/editor/libeditor/base/SplitElementTxn.cpp +++ b/mozilla/editor/libeditor/base/SplitElementTxn.cpp @@ -127,3 +127,14 @@ nsresult SplitElementTxn::GetRedoString(nsString **aString) } return NS_OK; } + +nsresult SplitElementTxn::GetNewNode(nsIDOMNode **aNewNode) +{ + if (!aNewNode) + return NS_ERROR_NULL_POINTER; + if (!mNewLeftNode) + return NS_ERROR_NOT_INITIALIZED; + *aNewNode = mNewLeftNode; + NS_ADDREF(*aNewNode); + return NS_OK; +} diff --git a/mozilla/editor/libeditor/base/SplitElementTxn.h b/mozilla/editor/libeditor/base/SplitElementTxn.h index ec0081ab0a3..8a8af69da99 100644 --- a/mozilla/editor/libeditor/base/SplitElementTxn.h +++ b/mozilla/editor/libeditor/base/SplitElementTxn.h @@ -67,6 +67,8 @@ public: virtual nsresult GetRedoString(nsString **aString); + virtual nsresult GetNewNode(nsIDOMNode **aNewNode); + protected: /** the element to operate upon */ diff --git a/mozilla/editor/libeditor/base/TransactionFactory.cpp b/mozilla/editor/libeditor/base/TransactionFactory.cpp index c8fab50f90d..c443558549e 100644 --- a/mozilla/editor/libeditor/base/TransactionFactory.cpp +++ b/mozilla/editor/libeditor/base/TransactionFactory.cpp @@ -22,6 +22,7 @@ #include "InsertTextTxn.h" #include "DeleteTextTxn.h" #include "CreateElementTxn.h" +#include "InsertElementTxn.h" #include "DeleteElementTxn.h" #include "DeleteRangeTxn.h" #include "ChangeAttributeTxn.h" @@ -32,6 +33,7 @@ static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID); static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID); static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID); static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID); +static NS_DEFINE_IID(kInsertElementTxnIID, INSERT_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID); static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID); @@ -57,6 +59,8 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult) *aResult = new DeleteTextTxn(); else if (aTxnType.Equals(kCreateElementTxnIID)) *aResult = new CreateElementTxn(); + else if (aTxnType.Equals(kInsertElementTxnIID)) + *aResult = new InsertElementTxn(); else if (aTxnType.Equals(kDeleteElementTxnIID)) *aResult = new DeleteElementTxn(); else if (aTxnType.Equals(kDeleteRangeTxnIID)) diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 582bdd3736d..76371c34f0c 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -48,6 +48,7 @@ #include "EditAggregateTxn.h" #include "ChangeAttributeTxn.h" #include "CreateElementTxn.h" +#include "InsertElementTxn.h" #include "DeleteElementTxn.h" #include "InsertTextTxn.h" #include "DeleteTextTxn.h" @@ -78,6 +79,7 @@ static NS_DEFINE_IID(kEditAggregateTxnIID, EDIT_AGGREGATE_TXN_IID); static NS_DEFINE_IID(kInsertTextTxnIID, INSERT_TEXT_TXN_IID); static NS_DEFINE_IID(kDeleteTextTxnIID, DELETE_TEXT_TXN_IID); static NS_DEFINE_IID(kCreateElementTxnIID, CREATE_ELEMENT_TXN_IID); +static NS_DEFINE_IID(kInsertElementTxnIID, INSERT_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteElementTxnIID, DELETE_ELEMENT_TXN_IID); static NS_DEFINE_IID(kDeleteRangeTxnIID, DELETE_RANGE_TXN_IID); static NS_DEFINE_IID(kChangeAttributeTxnIID,CHANGE_ATTRIBUTE_TXN_IID); @@ -566,14 +568,12 @@ nsresult nsEditor::Do(nsITransaction *aTxn) { nsresult result = NS_OK; - if (nsnull!=aTxn) + if (aTxn) { - if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) - { + if (mTxnMgr) { result = mTxnMgr->Do(aTxn); } - else - { + else { result = aTxn->Do(); } } @@ -690,12 +690,19 @@ nsresult nsEditor::ScrollIntoView(PRBool aScrollToBegin) nsresult nsEditor::CreateNode(const nsString& aTag, nsIDOMNode * aParent, - PRInt32 aPosition) + PRInt32 aPosition, + nsIDOMNode ** aNewNode) { CreateElementTxn *txn; nsresult result = CreateTxnForCreateElement(aTag, aParent, aPosition, &txn); - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) + { result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = txn->GetNewNode(aNewNode); + NS_ASSERTION((NS_SUCCEEDED(result)), "GetNewNode can't fail if txn::Do succeeded."); + } } return result; } @@ -720,16 +727,28 @@ nsresult nsEditor::InsertNode(nsIDOMNode * aNode, nsIDOMNode * aParent, PRInt32 aPosition) { - // GetLayoutObjectFor test - nsAutoString cellTag("TD"); - nsCOMPtr node; - if (NS_SUCCEEDED(GetFirstNodeOfType(nsnull, cellTag, getter_AddRefs(node)))) - { - PRInt32 cellIndex; - GetColIndexForCell(mPresShell, node, cellIndex); - printf("%d\n", cellIndex); + InsertElementTxn *txn; + nsresult result = CreateTxnForInsertElement(aNode, aParent, aPosition, &txn); + if (NS_SUCCEEDED(result)) { + result = Do(txn); } - return NS_ERROR_NOT_IMPLEMENTED; + return result; +} + +nsresult nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode, + nsIDOMNode * aParent, + PRInt32 aPosition, + InsertElementTxn ** aTxn) +{ + nsresult result = NS_ERROR_NULL_POINTER; + if (aNode && aParent && aTxn) + { + result = TransactionFactory::GetNewTransaction(kInsertElementTxnIID, (EditTxn **)aTxn); + if (NS_SUCCEEDED(result)) { + result = (*aTxn)->Init(aNode, aParent, aPosition); + } + } + return result; } nsresult nsEditor::DeleteNode(nsIDOMNode * aElement) @@ -753,7 +772,6 @@ nsresult nsEditor::CreateTxnForDeleteElement(nsIDOMNode * aElement, result = (*aTxn)->Init(aElement); } } - return result; } @@ -1280,12 +1298,19 @@ nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode) nsresult nsEditor::SplitNode(nsIDOMNode * aNode, - PRInt32 aOffset) + PRInt32 aOffset, + nsIDOMNode **aNewLeftNode) { SplitElementTxn *txn; nsresult result = CreateTxnForSplitNode(aNode, aOffset, &txn); - if (NS_SUCCEEDED(result)) { - result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = Do(txn); + if (NS_SUCCEEDED(result)) + { + result = txn->GetNewNode(aNewLeftNode); + NS_ASSERTION((NS_SUCCEEDED(result)), "result must succeeded for GetNewNode"); + } } return result; } diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index 4c1893cdb30..7eb0b7ca470 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -36,6 +36,7 @@ class nsIPresShell; class nsIViewManager; class ChangeAttributeTxn; class CreateElementTxn; +class InsertElementTxn; class DeleteElementTxn; class InsertTextTxn; class DeleteTextTxn; @@ -47,25 +48,6 @@ class nsVoidArray; //This is the monitor for the editor. PRMonitor *getEditorMonitor(); -/* -struct Properties -{ - Properties (nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll); - ~Properties(); - - nsIAtom *mPropName; - nsIAtom *mValue; - PRBool mAppliesToAll; -}; - -inline Property::Property(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll) -{ - mPropName = aPropName; - mPropValue = aPropValue; - mAppliesToAll = aAppliesToAll; -}; - -*/ /** implementation of an editor object. it will be the controler/focal point * for the main editor services. i.e. the GUIManager, publishing, transaction @@ -123,7 +105,8 @@ public: virtual nsresult CreateNode(const nsString& aTag, nsIDOMNode * aParent, - PRInt32 aPosition); + PRInt32 aPosition, + nsIDOMNode ** aNewNode); virtual nsresult InsertNode(nsIDOMNode * aNode, nsIDOMNode * aParent, @@ -135,7 +118,8 @@ public: virtual nsresult DeleteSelection(nsIEditor::Direction aDir); virtual nsresult SplitNode(nsIDOMNode * aExistingRightNode, - PRInt32 aOffset); + PRInt32 aOffset, + nsIDOMNode ** aNewLeftNode); virtual nsresult JoinNodes(nsIDOMNode * aNodeToKeep, nsIDOMNode * aNodeToJoin, @@ -207,6 +191,11 @@ protected: PRInt32 aPosition, CreateElementTxn ** aTxn); + virtual nsresult CreateTxnForInsertElement(nsIDOMNode * aNode, + nsIDOMNode * aParent, + PRInt32 aOffset, + InsertElementTxn ** aTxn); + virtual nsresult CreateTxnForDeleteElement(nsIDOMNode * aElement, DeleteElementTxn ** aTxn); diff --git a/mozilla/editor/libeditor/base/nsIEditProperty.h b/mozilla/editor/libeditor/base/nsIEditProperty.h new file mode 100644 index 00000000000..de2c7abb698 --- /dev/null +++ b/mozilla/editor/libeditor/base/nsIEditProperty.h @@ -0,0 +1,53 @@ +/* -*- 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://wwwt.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 __nsIEditProperty_h__ +#define __nsIEditProperty_h__ + +#include "nsISupports.h" + +class nsIAtom; + +#define NS_IEDITPROPERTY_IID \ +{/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ +0x9875cd40, 0xca81, 0x11d2, \ +{0x8f, 0x4d, 0x0, 0x60, 0x8, 0x15, 0x9b, 0x0c} } + +/** simple interface for describing a single property as it relates to a range of content. + * + */ + +class nsIEditProperty : public nsISupports +{ +public: + static const nsIID& IID() { static nsIID iid = NS_IEDITPROPERTY_IID; return iid; } + + virtual nsresult Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll)=0; + virtual nsresult GetProperty(nsIAtom **aProperty) const =0; + virtual nsresult GetValue(nsIAtom **aValue) const =0; + virtual nsresult GetAppliesToAll(PRBool *aAppliesToAll) const =0; + +/* we're still trying to decide how edit atoms will work. Until then, use these */ +// XXX: fix ASAP! + static nsIAtom *bold; + static nsIAtom *italic; +}; + +extern nsresult NS_NewEditProperty(nsIEditProperty **aResult); + +#endif \ No newline at end of file diff --git a/mozilla/editor/libeditor/html/nsEditProperty.cpp b/mozilla/editor/libeditor/html/nsEditProperty.cpp new file mode 100644 index 00000000000..b144d9f6c89 --- /dev/null +++ b/mozilla/editor/libeditor/html/nsEditProperty.cpp @@ -0,0 +1,63 @@ +/* -*- 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 "nsEditProperty.h" + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); + + +NS_IMPL_ADDREF(nsEditProperty) + +NS_IMPL_RELEASE(nsEditProperty) + +nsIAtom * nsIEditProperty::bold = NS_NewAtom("BOLD"); +nsIAtom * nsIEditProperty::italic = NS_NewAtom("ITALIC"); + +nsresult +nsEditProperty::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(kIEditPropertyIID)) { + *aInstancePtr = (void*)(nsIEditProperty*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +nsresult NS_NewEditProperty(nsIEditProperty **aResult) +{ + if (aResult) + { + *aResult = new nsEditProperty(); + if (!*aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(*aResult); + return NS_OK; + } + return NS_ERROR_NULL_POINTER; +} \ No newline at end of file diff --git a/mozilla/editor/libeditor/html/nsEditProperty.h b/mozilla/editor/libeditor/html/nsEditProperty.h new file mode 100644 index 00000000000..388cd49d4eb --- /dev/null +++ b/mozilla/editor/libeditor/html/nsEditProperty.h @@ -0,0 +1,107 @@ +/* -*- 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://wwwt.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 __nsEditProperty_h__ +#define __nsEditProperty_h__ + +#include "nsIEditProperty.h" +#include "nsIAtom.h" +#include "nsCOMPtr.h" +#include "nsISupports.h" + +/** simple class for describing a single property as it relates to a range of content. + * not ref counted. + * + */ +class nsEditProperty : public nsIEditProperty +{ +public: + /*interfaces for addref and release and queryinterface*/ + NS_DECL_ISUPPORTS + +protected: + nsEditProperty (); + virtual ~nsEditProperty(); + +public: + virtual nsresult Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll); + virtual nsresult GetProperty(nsIAtom **aProperty) const; + virtual nsresult GetValue(nsIAtom **aValue) const; + virtual nsresult GetAppliesToAll(PRBool *aAppliesToAll) const; + +protected: + nsCOMPtrmProperty; + nsCOMPtrmValue; + PRBool mAppliesToAll; + + friend nsresult NS_NewEditProperty(nsIEditProperty **aResult); +}; + +inline nsEditProperty::nsEditProperty() +{ + NS_INIT_REFCNT(); +}; + +inline nsEditProperty::~nsEditProperty() {}; + +inline nsresult nsEditProperty::Init(nsIAtom *aPropName, nsIAtom *aValue, PRBool aAppliesToAll) +{ + if (!aPropName) + return NS_ERROR_NULL_POINTER; + + mProperty = do_QueryInterface(aPropName); + mValue = do_QueryInterface(aValue); + mAppliesToAll = aAppliesToAll; + return NS_OK; +}; + +inline nsresult nsEditProperty::GetProperty(nsIAtom **aProperty) const +{ + if (!aProperty) { + return NS_ERROR_NULL_POINTER; + } + *aProperty = mProperty; + if (*aProperty) { + NS_ADDREF(*aProperty); + } + return NS_OK; +}; + +inline nsresult nsEditProperty::GetValue(nsIAtom **aValue) const +{ + if (!aValue) { + return NS_ERROR_NULL_POINTER; + } + *aValue = mValue; + if (*aValue) { + NS_ADDREF(*aValue); + } return NS_OK; +}; + +inline nsresult nsEditProperty::GetAppliesToAll(PRBool *aAppliesToAll) const +{ + if (!aAppliesToAll) { + return NS_ERROR_NULL_POINTER; + } + *aAppliesToAll = mAppliesToAll; + return NS_OK; +}; + + + +#endif diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index d33f9e2569e..f18585ab36d 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -23,8 +23,8 @@ #include "nsIDOMDocument.h" #include "nsIDOMElement.h" #include "nsIDOMCharacterData.h" - - +#include "nsIEditProperty.h" +#include "nsISupportsArray.h" #include "nsString.h" static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); @@ -225,36 +225,52 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr } break; - // hard-coded split node test: works on first

in the document - case nsIDOMEvent::VK_S: - /* + // hard-coded ChangeTextAttributes test -- italics + case nsIDOMEvent::VK_I: if (PR_TRUE==ctrlKey) { - nsAutoString pTag("P"); - nsCOMPtr currentNode; - nsCOMPtr element; - if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, pTag, getter_AddRefs(currentNode)))) - { - nsresult result; - SplitElementTxn *txn; - if (PR_FALSE==isShift) // split the element so there are 0 children in the first half - { - result = TransactionFactory::GetNewTransaction(kSplitElementTxnIID, (EditTxn **)&txn); - if (txn) - 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(mEditor, currentNode, 1); - } - if (txn) - mEditor->Do(txn); - } aProcessed=PR_TRUE; + if ((nsITextEditor *)nsnull!=mEditor.get()) + { + nsCOMPtrprop; + nsresult result = NS_NewEditProperty(getter_AddRefs(prop)); + if ((NS_SUCCEEDED(result)) && prop) + { + prop->Init(nsIEditProperty::italic, nsnull, PR_TRUE); + nsCOMPtrpropList; + result = NS_NewISupportsArray(getter_AddRefs(propList)); + if ((NS_SUCCEEDED(result)) && propList) + { + propList->AppendElement(prop); + mEditor->SetTextProperties(propList); + } + } + } + } + break; + + // hard-coded ChangeTextAttributes test -- bold + case nsIDOMEvent::VK_B: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if ((nsITextEditor *)nsnull!=mEditor.get()) + { + nsCOMPtrprop; + nsresult result = NS_NewEditProperty(getter_AddRefs(prop)); + if ((NS_SUCCEEDED(result)) && prop) + { + prop->Init(nsIEditProperty::bold, nsnull, PR_TRUE); + nsCOMPtrpropList; + result = NS_NewISupportsArray(getter_AddRefs(propList)); + if ((NS_SUCCEEDED(result)) && propList) + { + propList->AppendElement(prop); + mEditor->SetTextProperties(propList); + } + } + } } - */ break;