seperating out html edit rules from text edit rules
git-svn-id: svn://10.0.0.236/trunk@25439 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
bfe4edbf65
commit
46bf828d41
@ -18,11 +18,13 @@
|
||||
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsHTMLEditor.h"
|
||||
#include "nsHTMLEditRules.h"
|
||||
#include "nsEditorEventListeners.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsEditorCID.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
@ -96,6 +98,14 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsHTMLEditor::InitRules()
|
||||
{
|
||||
// instantiate the rules for this text editor
|
||||
// XXX: we should be told which set of rules to instantiate
|
||||
mRules = new nsHTMLEditRules();
|
||||
mRules->Init(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty)
|
||||
{
|
||||
return nsTextEditor::SetTextProperty(aProperty);
|
||||
@ -123,7 +133,80 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
||||
{
|
||||
return nsTextEditor::InsertBreak();
|
||||
nsresult result;
|
||||
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
result = nsEditor::BeginTransaction();
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->WillInsertBreak(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
// create the new BR node
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
nsAutoString tag("BR");
|
||||
result = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
||||
if (NS_SUCCEEDED(result) && newNode)
|
||||
{
|
||||
// set the selection to the new node
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
result = newNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not
|
||||
nsCOMPtr<nsIDOMNode>nextNode;
|
||||
newNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if (nextNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nextTextNode;
|
||||
nextTextNode = do_QueryInterface(nextNode);
|
||||
if (!nextTextNode) {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
else {
|
||||
offsetInParent=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
result = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (-1==offsetInParent)
|
||||
{
|
||||
nextNode->GetParentNode(getter_AddRefs(parent));
|
||||
result = nsIEditorSupport::GetChildOffset(nextNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selection->Collapse(nextNode, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
|
||||
result = mRules->DidInsertBreak(selection, result);
|
||||
}
|
||||
nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result!
|
||||
NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result");
|
||||
|
||||
// XXXX: Horrible hack! We are doing this because
|
||||
// of an error in Gecko which is not rendering the
|
||||
// document after a change via the DOM - gpk 2/13/99
|
||||
// BEGIN HACK!!!
|
||||
HACKForceRedraw();
|
||||
// END HACK
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Methods shared with the base editor.
|
||||
|
||||
@ -110,8 +110,14 @@ public:
|
||||
NS_IMETHOD JoinTableCells(PRBool aCellToRight);
|
||||
|
||||
// Data members
|
||||
|
||||
protected:
|
||||
|
||||
// rules initialization
|
||||
|
||||
virtual void InitRules();
|
||||
|
||||
|
||||
// EVENT LISTENERS AND COMMAND ROUTING NEEDS WORK
|
||||
// For now, the listners are tied to the nsTextEditor class
|
||||
//
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsEditor.h"
|
||||
#include "PlaceholderTxn.h"
|
||||
#include "InsertTextTxn.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -35,7 +35,11 @@ const static char* kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
|
||||
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
/*-------------------------------------------------------------------*
|
||||
* Helper Functions
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
PRBool nsTextEditRules::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
@ -51,7 +55,7 @@ static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool IsEditable(nsIDOMNode *aNode)
|
||||
PRBool nsTextEditRules::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
@ -91,6 +95,11 @@ PRBool IsEditable(nsIDOMNode *aNode)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*
|
||||
* Constructor/Destructor
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
|
||||
nsTextEditRules::nsTextEditRules()
|
||||
{
|
||||
mEditor = nsnull;
|
||||
@ -101,8 +110,15 @@ nsTextEditRules::~nsTextEditRules()
|
||||
// do NOT delete mEditor here. We do not hold a ref count to mEditor. mEditor owns our lifespan.
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*
|
||||
* Public methods
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
nsTextEditRules::Init(nsEditor *aEditor)
|
||||
{
|
||||
// null aNextRule is ok
|
||||
if (!aEditor) { return NS_ERROR_NULL_POINTER; }
|
||||
@ -110,6 +126,17 @@ nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
@ -168,126 +195,6 @@ nsTextEditRules::DidInsertText(nsIDOMSelection *aSelection,
|
||||
return DidInsert(aSelection, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return WillInsert(aSelection, aCancel);
|
||||
}
|
||||
|
||||
// XXX: this code is all experimental, and has no effect on the content model yet
|
||||
// the point here is to collapse adjacent BR's into P's
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after insert break.");
|
||||
// if the insert break resulted in consecutive BR tags,
|
||||
// collapse the two BR tags into a single P
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(aSelection,&result);
|
||||
if (enumerator)
|
||||
{
|
||||
enumerator->First();
|
||||
nsISupports *currentItem;
|
||||
result = enumerator->CurrentItem(¤tItem);
|
||||
if ((NS_SUCCEEDED(result)) && currentItem)
|
||||
{
|
||||
result = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
if (range)
|
||||
{
|
||||
nsIAtom *brTag = NS_NewAtom("BR");
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
result = range->GetStartParent(getter_AddRefs(startNode));
|
||||
if ((NS_SUCCEEDED(result)) && startNode)
|
||||
{
|
||||
PRInt32 offset;
|
||||
range->GetStartOffset(&offset);
|
||||
nsCOMPtr<nsIDOMNodeList>startNodeChildren;
|
||||
result = startNode->GetChildNodes(getter_AddRefs(startNodeChildren));
|
||||
if ((NS_SUCCEEDED(result)) && startNodeChildren)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
result = startNodeChildren->Item(offset, getter_AddRefs(selectedNode));
|
||||
if ((NS_SUCCEEDED(result)) && selectedNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> prevNode;
|
||||
result = selectedNode->GetPreviousSibling(getter_AddRefs(prevNode));
|
||||
if ((NS_SUCCEEDED(result)) && prevNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(prevNode, brTag))
|
||||
{ // the previous node is a BR, check it's siblings
|
||||
nsCOMPtr<nsIDOMNode> leftNode;
|
||||
result = prevNode->GetPreviousSibling(getter_AddRefs(leftNode));
|
||||
if ((NS_SUCCEEDED(result)) && leftNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(leftNode, brTag))
|
||||
{ // left sibling is also a BR, collapse
|
||||
printf("1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(selectedNode, brTag))
|
||||
{ // right sibling is also a BR, collapse
|
||||
printf("2\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// now check the next node from selectedNode
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
result = selectedNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if ((NS_SUCCEEDED(result)) && nextNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(nextNode, brTag))
|
||||
{ // the previous node is a BR, check it's siblings
|
||||
nsCOMPtr<nsIDOMNode> rightNode;
|
||||
result = nextNode->GetNextSibling(getter_AddRefs(rightNode));
|
||||
if ((NS_SUCCEEDED(result)) && rightNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(rightNode, brTag))
|
||||
{ // right sibling is also a BR, collapse
|
||||
printf("3\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(selectedNode, brTag))
|
||||
{ // left sibling is also a BR, collapse
|
||||
printf("4\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(brTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag)
|
||||
{
|
||||
if (!aTag) { return NS_ERROR_NULL_POINTER; }
|
||||
*aTag = NS_NewAtom("BR");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
|
||||
class nsTextEditor;
|
||||
class nsEditor;
|
||||
class PlaceholderTxn;
|
||||
|
||||
/** Object that encapsulates HTML text-specific editing rules.
|
||||
@ -44,11 +44,10 @@ public:
|
||||
nsTextEditRules();
|
||||
virtual ~nsTextEditRules();
|
||||
|
||||
NS_IMETHOD Init(nsTextEditor *aEditor);
|
||||
NS_IMETHOD Init(nsEditor *aEditor);
|
||||
|
||||
NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
NS_IMETHOD GetInsertBreakTag(nsIAtom **aTag);
|
||||
|
||||
NS_IMETHOD WillInsertText(nsIDOMSelection *aSelection,
|
||||
const nsString& aInputString,
|
||||
@ -71,7 +70,11 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
// helper functions
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
nsEditor *mEditor; // note that we do not refcount the editor
|
||||
nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc
|
||||
};
|
||||
|
||||
|
||||
@ -175,6 +175,9 @@ NS_IMETHODIMP nsTextEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
if (NS_OK != result)
|
||||
return result;
|
||||
|
||||
// Init the rules system
|
||||
InitRules();
|
||||
|
||||
result = NS_NewEditorKeyListener(getter_AddRefs(mKeyListenerP), this);
|
||||
if (NS_OK != result) {
|
||||
return result;
|
||||
@ -217,15 +220,10 @@ NS_IMETHODIMP nsTextEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
}
|
||||
//cmanske: Shouldn't we check result from this?
|
||||
erP->AddEventListenerByIID(mKeyListenerP, kIDOMKeyListenerIID);
|
||||
//erP->AddEventListenerByIID(mDragListenerP, kIDOMDragListenerIID);
|
||||
//erP->AddEventListenerByIID(mMouseListenerP, kIDOMMouseListenerIID);
|
||||
//erP->AddEventListener(mDragListenerP, kIDOMDragListenerIID);
|
||||
//erP->AddEventListener(mMouseListenerP, kIDOMMouseListenerIID);
|
||||
|
||||
erP->AddEventListenerByIID(mTextListenerP,kIDOMTextListenerIID);
|
||||
|
||||
// instantiate the rules for this text editor
|
||||
// XXX: we should be told which set of rules to instantiate
|
||||
mRules = new nsTextEditRules();
|
||||
mRules->Init(this);
|
||||
erP->AddEventListenerByIID(mTextListenerP,kIDOMTextListenerIID);
|
||||
|
||||
result = NS_OK;
|
||||
|
||||
@ -234,6 +232,16 @@ NS_IMETHODIMP nsTextEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void nsTextEditor::InitRules()
|
||||
{
|
||||
// instantiate the rules for this text editor
|
||||
// XXX: we should be told which set of rules to instantiate
|
||||
mRules = new nsTextEditRules();
|
||||
mRules->Init(this);
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
|
||||
@ -485,80 +493,11 @@ NS_IMETHODIMP nsTextEditor::InsertText(const nsString& aStringToInsert)
|
||||
|
||||
NS_IMETHODIMP nsTextEditor::InsertBreak()
|
||||
{
|
||||
nsresult result;
|
||||
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
// For plainttext just pass newlines through
|
||||
nsAutoString key;
|
||||
key += '\n';
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
result = nsEditor::BeginTransaction();
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->WillInsertBreak(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
// create the new BR node
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
nsAutoString tag("BR");
|
||||
result = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
||||
if (NS_SUCCEEDED(result) && newNode)
|
||||
{
|
||||
// set the selection to the new node
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
result = newNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not
|
||||
nsCOMPtr<nsIDOMNode>nextNode;
|
||||
newNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if (nextNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nextTextNode;
|
||||
nextTextNode = do_QueryInterface(nextNode);
|
||||
if (!nextTextNode) {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
else {
|
||||
offsetInParent=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
result = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (-1==offsetInParent)
|
||||
{
|
||||
nextNode->GetParentNode(getter_AddRefs(parent));
|
||||
result = nsIEditorSupport::GetChildOffset(nextNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selection->Collapse(nextNode, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
|
||||
result = mRules->DidInsertBreak(selection, result);
|
||||
}
|
||||
nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result!
|
||||
NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result");
|
||||
|
||||
// XXXX: Horrible hack! We are doing this because
|
||||
// of an error in Gecko which is not rendering the
|
||||
// document after a change via the DOM - gpk 2/13/99
|
||||
// BEGIN HACK!!!
|
||||
HACKForceRedraw();
|
||||
// END HACK
|
||||
|
||||
return result;
|
||||
return InsertText(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -89,6 +89,11 @@ public:
|
||||
NS_IMETHOD OutputHTML(nsString& aOutputString);
|
||||
|
||||
protected:
|
||||
|
||||
// rules initialization
|
||||
|
||||
virtual void InitRules();
|
||||
|
||||
// Utility Methods
|
||||
|
||||
virtual void IsTextStyleSet(nsIStyleContext *aSC,
|
||||
|
||||
@ -18,11 +18,13 @@
|
||||
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsHTMLEditor.h"
|
||||
#include "nsHTMLEditRules.h"
|
||||
#include "nsEditorEventListeners.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMKeyListener.h"
|
||||
#include "nsIDOMMouseListener.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsEditorCID.h"
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
@ -96,6 +98,14 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell)
|
||||
return result;
|
||||
}
|
||||
|
||||
void nsHTMLEditor::InitRules()
|
||||
{
|
||||
// instantiate the rules for this text editor
|
||||
// XXX: we should be told which set of rules to instantiate
|
||||
mRules = new nsHTMLEditRules();
|
||||
mRules->Init(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty)
|
||||
{
|
||||
return nsTextEditor::SetTextProperty(aProperty);
|
||||
@ -123,7 +133,80 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
||||
{
|
||||
return nsTextEditor::InsertBreak();
|
||||
nsresult result;
|
||||
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
PRBool cancel= PR_FALSE;
|
||||
|
||||
result = nsEditor::BeginTransaction();
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// pre-process
|
||||
nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
result = mRules->WillInsertBreak(selection, &cancel);
|
||||
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
// create the new BR node
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
nsAutoString tag("BR");
|
||||
result = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
||||
if (NS_SUCCEEDED(result) && newNode)
|
||||
{
|
||||
// set the selection to the new node
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
result = newNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not
|
||||
nsCOMPtr<nsIDOMNode>nextNode;
|
||||
newNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if (nextNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nextTextNode;
|
||||
nextTextNode = do_QueryInterface(nextNode);
|
||||
if (!nextTextNode) {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
else {
|
||||
offsetInParent=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nextNode = do_QueryInterface(newNode);
|
||||
}
|
||||
result = nsEditor::GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (-1==offsetInParent)
|
||||
{
|
||||
nextNode->GetParentNode(getter_AddRefs(parent));
|
||||
result = nsIEditorSupport::GetChildOffset(nextNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
selection->Collapse(nextNode, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
|
||||
result = mRules->DidInsertBreak(selection, result);
|
||||
}
|
||||
nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result!
|
||||
NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result");
|
||||
|
||||
// XXXX: Horrible hack! We are doing this because
|
||||
// of an error in Gecko which is not rendering the
|
||||
// document after a change via the DOM - gpk 2/13/99
|
||||
// BEGIN HACK!!!
|
||||
HACKForceRedraw();
|
||||
// END HACK
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Methods shared with the base editor.
|
||||
|
||||
@ -110,8 +110,14 @@ public:
|
||||
NS_IMETHOD JoinTableCells(PRBool aCellToRight);
|
||||
|
||||
// Data members
|
||||
|
||||
protected:
|
||||
|
||||
// rules initialization
|
||||
|
||||
virtual void InitRules();
|
||||
|
||||
|
||||
// EVENT LISTENERS AND COMMAND ROUTING NEEDS WORK
|
||||
// For now, the listners are tied to the nsTextEditor class
|
||||
//
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsEditor.h"
|
||||
#include "PlaceholderTxn.h"
|
||||
#include "InsertTextTxn.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -35,7 +35,11 @@ const static char* kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
|
||||
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
/*-------------------------------------------------------------------*
|
||||
* Helper Functions
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
PRBool nsTextEditRules::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
@ -51,7 +55,7 @@ static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool IsEditable(nsIDOMNode *aNode)
|
||||
PRBool nsTextEditRules::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
@ -91,6 +95,11 @@ PRBool IsEditable(nsIDOMNode *aNode)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*
|
||||
* Constructor/Destructor
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
|
||||
nsTextEditRules::nsTextEditRules()
|
||||
{
|
||||
mEditor = nsnull;
|
||||
@ -101,8 +110,15 @@ nsTextEditRules::~nsTextEditRules()
|
||||
// do NOT delete mEditor here. We do not hold a ref count to mEditor. mEditor owns our lifespan.
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------*
|
||||
* Public methods
|
||||
*-------------------------------------------------------------------*/
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
nsTextEditRules::Init(nsEditor *aEditor)
|
||||
{
|
||||
// null aNextRule is ok
|
||||
if (!aEditor) { return NS_ERROR_NULL_POINTER; }
|
||||
@ -110,6 +126,17 @@ nsTextEditRules::Init(nsTextEditor *aEditor)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
@ -168,126 +195,6 @@ nsTextEditRules::DidInsertText(nsIDOMSelection *aSelection,
|
||||
return DidInsert(aSelection, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
return WillInsert(aSelection, aCancel);
|
||||
}
|
||||
|
||||
// XXX: this code is all experimental, and has no effect on the content model yet
|
||||
// the point here is to collapse adjacent BR's into P's
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
nsresult result = aResult; // if aResult is an error, we return it.
|
||||
if (!aSelection) { return NS_ERROR_NULL_POINTER; }
|
||||
PRBool isCollapsed;
|
||||
aSelection->IsCollapsed(&isCollapsed);
|
||||
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after insert break.");
|
||||
// if the insert break resulted in consecutive BR tags,
|
||||
// collapse the two BR tags into a single P
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
enumerator = do_QueryInterface(aSelection,&result);
|
||||
if (enumerator)
|
||||
{
|
||||
enumerator->First();
|
||||
nsISupports *currentItem;
|
||||
result = enumerator->CurrentItem(¤tItem);
|
||||
if ((NS_SUCCEEDED(result)) && currentItem)
|
||||
{
|
||||
result = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
if (range)
|
||||
{
|
||||
nsIAtom *brTag = NS_NewAtom("BR");
|
||||
nsCOMPtr<nsIDOMNode> startNode;
|
||||
result = range->GetStartParent(getter_AddRefs(startNode));
|
||||
if ((NS_SUCCEEDED(result)) && startNode)
|
||||
{
|
||||
PRInt32 offset;
|
||||
range->GetStartOffset(&offset);
|
||||
nsCOMPtr<nsIDOMNodeList>startNodeChildren;
|
||||
result = startNode->GetChildNodes(getter_AddRefs(startNodeChildren));
|
||||
if ((NS_SUCCEEDED(result)) && startNodeChildren)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
result = startNodeChildren->Item(offset, getter_AddRefs(selectedNode));
|
||||
if ((NS_SUCCEEDED(result)) && selectedNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> prevNode;
|
||||
result = selectedNode->GetPreviousSibling(getter_AddRefs(prevNode));
|
||||
if ((NS_SUCCEEDED(result)) && prevNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(prevNode, brTag))
|
||||
{ // the previous node is a BR, check it's siblings
|
||||
nsCOMPtr<nsIDOMNode> leftNode;
|
||||
result = prevNode->GetPreviousSibling(getter_AddRefs(leftNode));
|
||||
if ((NS_SUCCEEDED(result)) && leftNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(leftNode, brTag))
|
||||
{ // left sibling is also a BR, collapse
|
||||
printf("1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(selectedNode, brTag))
|
||||
{ // right sibling is also a BR, collapse
|
||||
printf("2\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// now check the next node from selectedNode
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
result = selectedNode->GetNextSibling(getter_AddRefs(nextNode));
|
||||
if ((NS_SUCCEEDED(result)) && nextNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(nextNode, brTag))
|
||||
{ // the previous node is a BR, check it's siblings
|
||||
nsCOMPtr<nsIDOMNode> rightNode;
|
||||
result = nextNode->GetNextSibling(getter_AddRefs(rightNode));
|
||||
if ((NS_SUCCEEDED(result)) && rightNode)
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(rightNode, brTag))
|
||||
{ // right sibling is also a BR, collapse
|
||||
printf("3\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PR_TRUE==NodeIsType(selectedNode, brTag))
|
||||
{ // left sibling is also a BR, collapse
|
||||
printf("4\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(brTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag)
|
||||
{
|
||||
if (!aTag) { return NS_ERROR_NULL_POINTER; }
|
||||
*aTag = NS_NewAtom("BR");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
|
||||
class nsTextEditor;
|
||||
class nsEditor;
|
||||
class PlaceholderTxn;
|
||||
|
||||
/** Object that encapsulates HTML text-specific editing rules.
|
||||
@ -44,11 +44,10 @@ public:
|
||||
nsTextEditRules();
|
||||
virtual ~nsTextEditRules();
|
||||
|
||||
NS_IMETHOD Init(nsTextEditor *aEditor);
|
||||
NS_IMETHOD Init(nsEditor *aEditor);
|
||||
|
||||
NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
NS_IMETHOD GetInsertBreakTag(nsIAtom **aTag);
|
||||
|
||||
NS_IMETHOD WillInsertText(nsIDOMSelection *aSelection,
|
||||
const nsString& aInputString,
|
||||
@ -71,7 +70,11 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
nsTextEditor *mEditor; // note that we do not refcount the editor
|
||||
// helper functions
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
nsEditor *mEditor; // note that we do not refcount the editor
|
||||
nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user