mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-29 17:40:42 +00:00
deleting the last editable object in a document now causes a bogus placeholder <P> </P> to be added to the document. This node has the
attribute MOZ_EDITOR_BOGUS_NODE set to TRUE. this solves the problem of when you do a SelectAll then a DEL, you don't have a cursor or any way to set selection in the document. You do still have the problem that the nbsp is pretty narrow and the frame containing it is hard to hit with the mouse. We really need the "set selection to frame nearest the mouse down point" operation. the intent is for all inserts to look for this node, and if found delete it before the insert. likewise, all deletes will be no-ops if this node is found.
This commit is contained in:
parent
9450d290ae
commit
b615bb95b3
@ -752,7 +752,7 @@ NS_IMETHODIMP nsEditor::SelectAll()
|
||||
if (NS_SUCCEEDED(result) && selection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsString bodyTag = "body";
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
@ -846,9 +846,9 @@ nsString & nsIEditor::GetTextNodeTag()
|
||||
|
||||
|
||||
NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
|
||||
nsIDOMNode * aParent,
|
||||
PRInt32 aPosition,
|
||||
nsIDOMNode ** aNewNode)
|
||||
nsIDOMNode * aParent,
|
||||
PRInt32 aPosition,
|
||||
nsIDOMNode ** aNewNode)
|
||||
{
|
||||
CreateElementTxn *txn;
|
||||
nsresult result = CreateTxnForCreateElement(aTag, aParent, aPosition, &txn);
|
||||
@ -1075,7 +1075,7 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
||||
BeginTransaction();
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsString bodyTag = "body";
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
|
@ -17,16 +17,17 @@
|
||||
*/
|
||||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEnumerator.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsTextEditRules)
|
||||
NS_IMPL_RELEASE(nsTextEditRules)
|
||||
static char* kMOZEditorBogusNode="MOZ_EDITOR_BOGUS_NODE";
|
||||
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
@ -46,23 +47,25 @@ static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
|
||||
nsTextEditRules::nsTextEditRules()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mEditor = nsnull;
|
||||
}
|
||||
|
||||
nsTextEditRules::~nsTextEditRules()
|
||||
{
|
||||
// do NOT delete mEditor here. We do not hold a ref count to mEditor. mEditor owns our lifespan.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::Init(nsIEditor *aEditor, nsIEditRules *aNextRule)
|
||||
nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
{
|
||||
// null aNextRule is ok
|
||||
if (!aEditor) { return NS_ERROR_NULL_POINTER; }
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mNextRule = do_QueryInterface(aNextRule);
|
||||
mEditor = aEditor; // we hold a non-refcounted reference back to our editor
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
@ -78,7 +81,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result;
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
@ -183,25 +186,99 @@ nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
// any prep work would go here
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if the document is empty, insert a bogus text node with a
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we just return it
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
|
||||
// if the delete selection resulted in no content
|
||||
// insert a special bogus text node with a character in it.
|
||||
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
mEditor->GetDocument(getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
PRUint32 count;
|
||||
nodeList->GetLength(&count);
|
||||
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
|
||||
nsCOMPtr<nsIDOMNode>bodyNode;
|
||||
result = nodeList->Item(0, getter_AddRefs(bodyNode));
|
||||
if ((NS_SUCCEEDED(result)) && bodyNode)
|
||||
{ // now we've got the body tag.
|
||||
// iterate the body tag, looking for editable content
|
||||
// if no editable content is found, insert the bogus node
|
||||
PRBool needsBogusContent=PR_TRUE;
|
||||
nsCOMPtr<nsIDOMNode>bodyChild;
|
||||
result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
while ((NS_SUCCEEDED(result)) && bodyChild)
|
||||
{ //XXX: wrongly assumes that all content is editable
|
||||
//XXX: needs a "IsEditableNode(node) method
|
||||
needsBogusContent = PR_FALSE;
|
||||
break;
|
||||
/*
|
||||
nsCOMPtr<nsIDOMNode>temp;
|
||||
bodyChild=>GetNextSibling(getter_AddRefs(temp));
|
||||
bodyChild = do_QueryInterface(temp);
|
||||
*/
|
||||
}
|
||||
if (PR_TRUE==needsBogusContent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>newPNode;
|
||||
result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0,
|
||||
getter_AddRefs(newPNode));
|
||||
if ((NS_SUCCEEDED(result)) && newPNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>newTNode;
|
||||
result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newPNode, 0,
|
||||
getter_AddRefs(newTNode));
|
||||
if ((NS_SUCCEEDED(result)) && newTNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>newNodeAsText;
|
||||
newNodeAsText = do_QueryInterface(newTNode);
|
||||
if (newNodeAsText)
|
||||
{
|
||||
nsAutoString data;
|
||||
data += 160;
|
||||
newNodeAsText->SetData(data);
|
||||
aSelection->Collapse(newTNode, 0);
|
||||
}
|
||||
}
|
||||
// make sure we know the PNode is bogus
|
||||
nsCOMPtr<nsIDOMElement>newPElement;
|
||||
newPElement = do_QueryInterface(newPNode);
|
||||
if (newPElement)
|
||||
{
|
||||
newPElement->SetAttribute(kMOZEditorBogusNode, "TRUE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIID.Equals(nsISupports::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIEditRules::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIEditRules*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
*aInstancePtr = 0;
|
||||
return NS_NOINTERFACE;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -19,10 +19,11 @@
|
||||
#ifndef nsTextEditRules_h__
|
||||
#define nsTextEditRules_h__
|
||||
|
||||
#include "nsIEditRules.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsTextEditor;
|
||||
|
||||
|
||||
/** Object that encapsulates HTML text-specific editing rules.
|
||||
*
|
||||
@ -35,25 +36,25 @@
|
||||
* 2. Selection must not be explicitly set by the rule method.
|
||||
* Any manipulation of Selection must be done by the editor.
|
||||
*/
|
||||
class nsTextEditRules : public nsIEditRules
|
||||
class nsTextEditRules
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsTextEditRules();
|
||||
virtual ~nsTextEditRules();
|
||||
|
||||
NS_IMETHOD Init(nsIEditor *aEditor, nsIEditRules *aNextRule);
|
||||
NS_IMETHOD Init(nsTextEditor *aEditor);
|
||||
|
||||
NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
NS_IMETHOD GetInsertBreakTag(nsIAtom **aTag);
|
||||
|
||||
NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsCOMPtr<nsIEditRules> mNextRule;
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
|
||||
};
|
||||
|
||||
|
@ -64,12 +64,9 @@ class nsIFrame;
|
||||
#include <strstrea.h>
|
||||
#endif
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
|
||||
// until there is a rules factory...
|
||||
#include "nsTextEditRules.h"
|
||||
|
||||
|
||||
@ -91,6 +88,7 @@ nsTextEditor::nsTextEditor()
|
||||
{
|
||||
// Done in nsEditor
|
||||
// NS_INIT_REFCNT();
|
||||
mRules = nsnull;
|
||||
}
|
||||
|
||||
nsTextEditor::~nsTextEditor()
|
||||
@ -115,6 +113,9 @@ nsTextEditor::~nsTextEditor()
|
||||
else
|
||||
NS_NOTREACHED("~nsTextEditor");
|
||||
}
|
||||
if (mRules) {
|
||||
delete mRules;
|
||||
}
|
||||
}
|
||||
|
||||
// Adds appropriate AddRef, Release, and QueryInterface methods for derived class
|
||||
@ -180,11 +181,9 @@ NS_IMETHODIMP nsTextEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
//erP->AddEventListener(mMouseListenerP, kIDOMMouseListenerIID);
|
||||
|
||||
// instantiate the rules for this text editor
|
||||
// XXX: we should get the rules from a factory
|
||||
// XXX: we should be told which set of rules to instantiate
|
||||
nsIEditRules *rules = (nsIEditRules *) new nsTextEditRules();
|
||||
rules->Init((nsIEditor *)this, nsnull);
|
||||
mRules = do_QueryInterface(rules);
|
||||
mRules = new nsTextEditRules();
|
||||
mRules->Init(this);
|
||||
|
||||
result = NS_OK;
|
||||
|
||||
@ -380,7 +379,28 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::DeleteSelection(nsIEditor::Direction aDir)
|
||||
{
|
||||
return nsEditor::DeleteSelection(aDir);
|
||||
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
nsresult result = nsEditor::BeginTransaction();
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->WillDeleteSelection(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = nsEditor::DeleteSelection(aDir);
|
||||
// post-process
|
||||
result = mRules->DidDeleteSelection(selection, result);
|
||||
}
|
||||
|
||||
nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result!
|
||||
NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::InsertText(const nsString& aStringToInsert)
|
||||
@ -431,7 +451,7 @@ NS_IMETHODIMP nsTextEditor::InsertBreak()
|
||||
}
|
||||
}
|
||||
nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result!
|
||||
NS_ASSERTION ((NS_SUCCEEDED(result)), "bad end transaction result");
|
||||
NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result");
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -705,10 +725,10 @@ NS_IMETHODIMP nsTextEditor::OutputHTML(nsString& aOutputString)
|
||||
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset,
|
||||
nsIAtom *aPropName)
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset,
|
||||
nsIAtom *aPropName)
|
||||
{
|
||||
nsresult result=NS_OK;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIEditRules.h"
|
||||
#include "nsTextEditRules.h"
|
||||
|
||||
class nsIStyleContext;
|
||||
class nsIDOMRange;
|
||||
@ -121,7 +121,7 @@ protected:
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
nsCOMPtr<nsIEditRules> mRules;
|
||||
nsTextEditRules* mRules;
|
||||
nsCOMPtr<nsIDOMEventListener> mKeyListenerP;
|
||||
nsCOMPtr<nsIDOMEventListener> mMouseListenerP;
|
||||
|
||||
|
@ -752,7 +752,7 @@ NS_IMETHODIMP nsEditor::SelectAll()
|
||||
if (NS_SUCCEEDED(result) && selection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsString bodyTag = "body";
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
@ -846,9 +846,9 @@ nsString & nsIEditor::GetTextNodeTag()
|
||||
|
||||
|
||||
NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
|
||||
nsIDOMNode * aParent,
|
||||
PRInt32 aPosition,
|
||||
nsIDOMNode ** aNewNode)
|
||||
nsIDOMNode * aParent,
|
||||
PRInt32 aPosition,
|
||||
nsIDOMNode ** aNewNode)
|
||||
{
|
||||
CreateElementTxn *txn;
|
||||
nsresult result = CreateTxnForCreateElement(aTag, aParent, aPosition, &txn);
|
||||
@ -1075,7 +1075,7 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert)
|
||||
BeginTransaction();
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsString bodyTag = "body";
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = mDoc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
|
@ -17,16 +17,17 @@
|
||||
*/
|
||||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMRange.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEnumerator.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsTextEditRules)
|
||||
NS_IMPL_RELEASE(nsTextEditRules)
|
||||
static char* kMOZEditorBogusNode="MOZ_EDITOR_BOGUS_NODE";
|
||||
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
@ -46,23 +47,25 @@ static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
|
||||
nsTextEditRules::nsTextEditRules()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mEditor = nsnull;
|
||||
}
|
||||
|
||||
nsTextEditRules::~nsTextEditRules()
|
||||
{
|
||||
// do NOT delete mEditor here. We do not hold a ref count to mEditor. mEditor owns our lifespan.
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::Init(nsIEditor *aEditor, nsIEditRules *aNextRule)
|
||||
nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
{
|
||||
// null aNextRule is ok
|
||||
if (!aEditor) { return NS_ERROR_NULL_POINTER; }
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mNextRule = do_QueryInterface(aNextRule);
|
||||
mEditor = aEditor; // we hold a non-refcounted reference back to our editor
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
@ -78,7 +81,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result;
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
@ -183,25 +186,99 @@ nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
// any prep work would go here
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if the document is empty, insert a bogus text node with a
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we just return it
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
|
||||
// if the delete selection resulted in no content
|
||||
// insert a special bogus text node with a character in it.
|
||||
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
mEditor->GetDocument(getter_AddRefs(doc));
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
nsAutoString bodyTag = "body";
|
||||
nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList));
|
||||
if ((NS_SUCCEEDED(result)) && nodeList)
|
||||
{
|
||||
PRUint32 count;
|
||||
nodeList->GetLength(&count);
|
||||
NS_ASSERTION(1==count, "there is not exactly 1 body in the document!");
|
||||
nsCOMPtr<nsIDOMNode>bodyNode;
|
||||
result = nodeList->Item(0, getter_AddRefs(bodyNode));
|
||||
if ((NS_SUCCEEDED(result)) && bodyNode)
|
||||
{ // now we've got the body tag.
|
||||
// iterate the body tag, looking for editable content
|
||||
// if no editable content is found, insert the bogus node
|
||||
PRBool needsBogusContent=PR_TRUE;
|
||||
nsCOMPtr<nsIDOMNode>bodyChild;
|
||||
result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
while ((NS_SUCCEEDED(result)) && bodyChild)
|
||||
{ //XXX: wrongly assumes that all content is editable
|
||||
//XXX: needs a "IsEditableNode(node) method
|
||||
needsBogusContent = PR_FALSE;
|
||||
break;
|
||||
/*
|
||||
nsCOMPtr<nsIDOMNode>temp;
|
||||
bodyChild=>GetNextSibling(getter_AddRefs(temp));
|
||||
bodyChild = do_QueryInterface(temp);
|
||||
*/
|
||||
}
|
||||
if (PR_TRUE==needsBogusContent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>newPNode;
|
||||
result = mEditor->CreateNode(nsAutoString("P"), bodyNode, 0,
|
||||
getter_AddRefs(newPNode));
|
||||
if ((NS_SUCCEEDED(result)) && newPNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>newTNode;
|
||||
result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newPNode, 0,
|
||||
getter_AddRefs(newTNode));
|
||||
if ((NS_SUCCEEDED(result)) && newTNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>newNodeAsText;
|
||||
newNodeAsText = do_QueryInterface(newTNode);
|
||||
if (newNodeAsText)
|
||||
{
|
||||
nsAutoString data;
|
||||
data += 160;
|
||||
newNodeAsText->SetData(data);
|
||||
aSelection->Collapse(newTNode, 0);
|
||||
}
|
||||
}
|
||||
// make sure we know the PNode is bogus
|
||||
nsCOMPtr<nsIDOMElement>newPElement;
|
||||
newPElement = do_QueryInterface(newPNode);
|
||||
if (newPElement)
|
||||
{
|
||||
newPElement->SetAttribute(kMOZEditorBogusNode, "TRUE");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aIID.Equals(nsISupports::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsISupports*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(nsIEditRules::GetIID())) {
|
||||
*aInstancePtr = (void*)(nsIEditRules*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
*aInstancePtr = 0;
|
||||
return NS_NOINTERFACE;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -19,10 +19,11 @@
|
||||
#ifndef nsTextEditRules_h__
|
||||
#define nsTextEditRules_h__
|
||||
|
||||
#include "nsIEditRules.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsTextEditor;
|
||||
|
||||
|
||||
/** Object that encapsulates HTML text-specific editing rules.
|
||||
*
|
||||
@ -35,25 +36,25 @@
|
||||
* 2. Selection must not be explicitly set by the rule method.
|
||||
* Any manipulation of Selection must be done by the editor.
|
||||
*/
|
||||
class nsTextEditRules : public nsIEditRules
|
||||
class nsTextEditRules
|
||||
{
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsTextEditRules();
|
||||
virtual ~nsTextEditRules();
|
||||
|
||||
NS_IMETHOD Init(nsIEditor *aEditor, nsIEditRules *aNextRule);
|
||||
NS_IMETHOD Init(nsTextEditor *aEditor);
|
||||
|
||||
NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
NS_IMETHOD GetInsertBreakTag(nsIAtom **aTag);
|
||||
|
||||
NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
nsCOMPtr<nsIEditRules> mNextRule;
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user