зеркало из https://github.com/mozilla/gecko-dev.git
1. block transformation infrastructure is now in place. We can go ahead and implement interesting
features like set paragraph style, set list type, indent, etc. I'm sure there's holes in my implementation that these high level features will make obvious. 2. I've factored a lot of utility methods from several modules into nsEditor as public static methods. This makes them easily accessable to all, and will help Joe and I remove redundant methods. 3. I changed the HTML tags to lower case, and made all string compares case-insensitive. No, this isn't quite the right thing to do, but we don't have atoms from layout yet. The Right Thing is for us to reuse those atoms.
This commit is contained in:
Родитель
150cb9c442
Коммит
99a96a39ec
|
@ -17,12 +17,12 @@
|
|||
*/
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -125,7 +125,7 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ NS_IMETHODIMP CreateElementTxn::Undo(void)
|
|||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
PRInt32 offset=0;
|
||||
if (mRefNode) {
|
||||
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mRefNode, mParent, offset);
|
||||
}
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
|
@ -183,7 +183,7 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsresult selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
*/
|
||||
|
||||
#include "JoinElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -28,9 +28,6 @@ static PRBool gNoisy = PR_FALSE;
|
|||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
|
||||
JoinElementTxn::JoinElementTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
|
@ -84,10 +81,7 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
leftNodeAsText->GetLength(&mOffset);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); }
|
||||
|
@ -99,7 +93,6 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent");
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
*/
|
||||
|
||||
#include "SplitElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -28,7 +28,6 @@ static PRBool gNoisy = PR_FALSE;
|
|||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
SplitElementTxn::SplitElementTxn()
|
||||
|
@ -69,11 +68,7 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
// insert the new node
|
||||
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||
{
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor)
|
||||
{
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
if (NS_SUCCEEDED(result) && mNewLeftNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
|
@ -83,7 +78,6 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
selection->Collapse(mNewLeftNode, mOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -105,11 +99,7 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor)
|
||||
{
|
||||
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
result = nsEditor::JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
||||
|
@ -125,7 +115,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
selection->Collapse(mExistingRightNode, mOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ nsIAtom * nsIEditProperty::tt;
|
|||
nsIAtom * nsIEditProperty::u;
|
||||
// block tags
|
||||
nsIAtom * nsIEditProperty::blockquote;
|
||||
nsIAtom * nsIEditProperty::br;
|
||||
nsIAtom * nsIEditProperty::h1;
|
||||
nsIAtom * nsIEditProperty::h2;
|
||||
// properties
|
||||
|
@ -56,28 +57,29 @@ void
|
|||
nsEditProperty::InstanceInit()
|
||||
{
|
||||
// tags
|
||||
nsIEditProperty::a = NS_NewAtom("A");
|
||||
nsIEditProperty::b = NS_NewAtom("B");
|
||||
nsIEditProperty::big = NS_NewAtom("BIG");
|
||||
nsIEditProperty::font = NS_NewAtom("FONT");
|
||||
nsIEditProperty::i = NS_NewAtom("I");
|
||||
nsIEditProperty::span = NS_NewAtom("SPAN");
|
||||
nsIEditProperty::small =NS_NewAtom("SMALL");
|
||||
nsIEditProperty::strike=NS_NewAtom("STRIKE");
|
||||
nsIEditProperty::sub = NS_NewAtom("SUB");
|
||||
nsIEditProperty::sup = NS_NewAtom("SUP");
|
||||
nsIEditProperty::tt = NS_NewAtom("TT");
|
||||
nsIEditProperty::u = NS_NewAtom("U");
|
||||
nsIEditProperty::a = NS_NewAtom("a");
|
||||
nsIEditProperty::b = NS_NewAtom("b");
|
||||
nsIEditProperty::big = NS_NewAtom("big");
|
||||
nsIEditProperty::font = NS_NewAtom("font");
|
||||
nsIEditProperty::i = NS_NewAtom("i");
|
||||
nsIEditProperty::span = NS_NewAtom("span");
|
||||
nsIEditProperty::small =NS_NewAtom("small");
|
||||
nsIEditProperty::strike=NS_NewAtom("strike");
|
||||
nsIEditProperty::sub = NS_NewAtom("sub");
|
||||
nsIEditProperty::sup = NS_NewAtom("sup");
|
||||
nsIEditProperty::tt = NS_NewAtom("tt");
|
||||
nsIEditProperty::u = NS_NewAtom("u");
|
||||
// tags
|
||||
nsIEditProperty::blockquote = NS_NewAtom("BLOCKQUOTE");
|
||||
nsIEditProperty::h1 = NS_NewAtom("H1");
|
||||
nsIEditProperty::h2 = NS_NewAtom("H2");
|
||||
nsIEditProperty::blockquote = NS_NewAtom("blockquote");
|
||||
nsIEditProperty::br = NS_NewAtom("br");
|
||||
nsIEditProperty::h1 = NS_NewAtom("h1");
|
||||
nsIEditProperty::h2 = NS_NewAtom("h2");
|
||||
// properties
|
||||
nsIEditProperty::color= NS_NewAtom("COLOR");
|
||||
nsIEditProperty::face = NS_NewAtom("FACE");
|
||||
nsIEditProperty::size = NS_NewAtom("SIZE");
|
||||
nsIEditProperty::color= NS_NewAtom("color");
|
||||
nsIEditProperty::face = NS_NewAtom("face");
|
||||
nsIEditProperty::size = NS_NewAtom("size");
|
||||
// special
|
||||
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
|
||||
nsIEditProperty::allProperties = new nsString("moz_allproperties");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -98,6 +100,7 @@ nsEditProperty::InstanceShutdown()
|
|||
NS_IF_RELEASE(nsIEditProperty::u);
|
||||
// tags
|
||||
NS_IF_RELEASE(nsIEditProperty::blockquote);
|
||||
NS_IF_RELEASE(nsIEditProperty::br);
|
||||
NS_IF_RELEASE(nsIEditProperty::h1);
|
||||
NS_IF_RELEASE(nsIEditProperty::h2);
|
||||
// properties
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIEditProperty.h" // to be removed XXX
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMAttr.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "nsIEnumerator.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsICaret.h"
|
||||
|
||||
#include "nsIEditActionListener.h"
|
||||
|
@ -98,6 +100,7 @@ static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
|
|||
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
||||
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
|
||||
static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID);
|
||||
|
@ -106,7 +109,6 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
|||
static NS_DEFINE_IID(kITextEditFactoryIID, NS_ITEXTEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIHTMLEditFactoryIID, NS_IHTMLEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
|
||||
|
@ -144,8 +146,11 @@ static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID);
|
|||
#define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
|
||||
#define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
|
||||
|
||||
const char* nsEditor::kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
|
||||
const char* nsEditor::kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
#ifdef NS_DEBUG_EDITOR
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
@ -324,7 +329,7 @@ nsEditor::~nsEditor()
|
|||
|
||||
|
||||
|
||||
//BEGIN nsIEditor interface implementations
|
||||
// BEGIN nsEditor core implementation
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(nsEditor)
|
||||
|
@ -351,11 +356,6 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIEditorSupportIID)) {
|
||||
*aInstancePtr = (void*)(nsIEditorSupport*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
@ -665,109 +665,6 @@ nsEditor::InsertBreak()
|
|||
|
||||
//BEGIN nsEditor Private methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult)
|
||||
{
|
||||
nsresult result=NS_OK;
|
||||
|
||||
if (!mDoc)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
/* If no node set, get root node */
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
|
||||
if (nsnull==aStartNode)
|
||||
{
|
||||
mDoc->GetDocumentElement(getter_AddRefs(element));
|
||||
result = element->QueryInterface(kIDOMNodeIID,getter_AddRefs(node));
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
if (!node)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
else
|
||||
node = do_QueryInterface(aStartNode);
|
||||
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = node->GetFirstChild(getter_AddRefs(childNode));
|
||||
while (childNode)
|
||||
{
|
||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||
nsAutoString tag;
|
||||
if (NS_SUCCEEDED(result) && (element))
|
||||
{
|
||||
element->GetTagName(tag);
|
||||
if (PR_TRUE==aTag.Equals(tag))
|
||||
{
|
||||
return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref
|
||||
}
|
||||
else
|
||||
{
|
||||
nsresult result = GetFirstNodeOfType(childNode, aTag, aResult);
|
||||
if (nsnull!=*aResult)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||
{
|
||||
if (!aNode || !aRetNode)
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRUint16 mType;
|
||||
PRBool mCNodes;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> answer;
|
||||
|
||||
aNode->GetNodeType(&mType);
|
||||
|
||||
if (nsIDOMNode::ELEMENT_NODE == mType) {
|
||||
if (NS_SUCCEEDED(aNode->HasChildNodes(&mCNodes)) && PR_TRUE == mCNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node1;
|
||||
nsCOMPtr<nsIDOMNode> node2;
|
||||
|
||||
if (!NS_SUCCEEDED(aNode->GetFirstChild(getter_AddRefs(node1))))
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
}
|
||||
while(!answer && node1)
|
||||
{
|
||||
GetFirstTextNode(node1, getter_AddRefs(answer));
|
||||
node1->GetNextSibling(getter_AddRefs(node2));
|
||||
node1 = node2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsIDOMNode::TEXT_NODE == mType) {
|
||||
answer = do_QueryInterface(aNode);
|
||||
}
|
||||
|
||||
// OK, now return the answer, if any
|
||||
*aRetNode = answer;
|
||||
if (*aRetNode)
|
||||
NS_IF_ADDREF(*aRetNode);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::Do(nsITransaction *aTxn)
|
||||
|
@ -1510,7 +1407,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
selectedNode = do_QueryInterface(parentSelectedNode);
|
||||
selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode));
|
||||
selectedParentNodeAsText->GetLength(&selectedNodeContentCount);
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent);
|
||||
|
||||
if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount))
|
||||
{
|
||||
|
@ -1518,7 +1415,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode));
|
||||
// now get the node's offset in it's parent, and insert the new tag there
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1527,7 +1424,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent
|
||||
}
|
||||
else { // insert new node as last child
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node
|
||||
}
|
||||
}
|
||||
|
@ -1560,7 +1457,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode));
|
||||
// now get the node's offset in it's parent, and insert the new tag there
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1569,7 +1466,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
offsetOfNewNode = 0; // insert new node as first child
|
||||
}
|
||||
else { // insert new node as last child
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node
|
||||
}
|
||||
}
|
||||
|
@ -1821,108 +1718,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetPreviousSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetRightmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetPreviousSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
|
||||
return GetRightmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetNextSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetLeftmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetNextSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
return GetLeftmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetLastChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetFirstChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||
|
@ -2037,7 +1832,12 @@ NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
||||
// END nsEditor core implementation
|
||||
|
||||
// BEGIN nsEditor public static helper methods
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
|
@ -2113,7 +1913,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
|
@ -2203,7 +2003,8 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
nsresult
|
||||
nsEditor::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
{
|
||||
NS_ASSERTION((aChild && aParent), "bad args");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
|
@ -2236,8 +2037,478 @@ nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParen
|
|||
return result;
|
||||
}
|
||||
|
||||
// returns the number of things inside aNode.
|
||||
// If aNode is text, returns number of characters. If not, returns number of children nodes.
|
||||
nsresult
|
||||
nsEditor::GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount)
|
||||
{
|
||||
aCount = 0;
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result=NS_OK;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
|
||||
nodeAsChar = do_QueryInterface(aNode);
|
||||
if (nodeAsChar) {
|
||||
nodeAsChar->GetLength(&aCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool hasChildNodes;
|
||||
aNode->HasChildNodes(&hasChildNodes);
|
||||
if (PR_TRUE==hasChildNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
result = aNode->GetChildNodes(getter_AddRefs(nodeList));
|
||||
if (NS_SUCCEEDED(result) && nodeList) {
|
||||
nodeList->GetLength(&aCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// content-based inline vs. block query
|
||||
nsresult
|
||||
nsEditor::IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline)
|
||||
{
|
||||
// this is a content-based implementation
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsresult result;
|
||||
aIsInline = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
result = element->GetTagName(tag);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIAtom *tagAtom = NS_NewAtom(tag);
|
||||
if (!tagAtom) { return NS_ERROR_NULL_POINTER; }
|
||||
if (tagAtom==nsIEditProperty::a ||
|
||||
tagAtom==nsIEditProperty::b ||
|
||||
tagAtom==nsIEditProperty::big ||
|
||||
tagAtom==nsIEditProperty::font ||
|
||||
tagAtom==nsIEditProperty::i ||
|
||||
tagAtom==nsIEditProperty::span ||
|
||||
tagAtom==nsIEditProperty::small ||
|
||||
tagAtom==nsIEditProperty::strike ||
|
||||
tagAtom==nsIEditProperty::sub ||
|
||||
tagAtom==nsIEditProperty::sup ||
|
||||
tagAtom==nsIEditProperty::tt ||
|
||||
tagAtom==nsIEditProperty::u )
|
||||
{
|
||||
aIsInline = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockParent(nsIDOMNode *aNode, nsIDOMElement **aBlockParent)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aBlockParent) {return NS_ERROR_NULL_POINTER;}
|
||||
*aBlockParent = nsnull;
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
nsCOMPtr<nsIDOMNode>temp;
|
||||
result = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
while (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRBool isInline;
|
||||
result = IsNodeInline(parent, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
parent->QueryInterface(nsIDOMElement::GetIID(), (void**)aBlockParent);
|
||||
break;
|
||||
}
|
||||
result = parent->GetParentNode(getter_AddRefs(temp));
|
||||
parent = do_QueryInterface(temp);
|
||||
}
|
||||
if (gNoisy) { printf("GetBlockParent for %p returning parent %p\n", aNode, *aBlockParent); }
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockSection(nsIDOMNode *aChild,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aChild || !aLeftNode || !aRightNode) {return NS_ERROR_NULL_POINTER;}
|
||||
*aLeftNode = aChild;
|
||||
*aRightNode = aChild;
|
||||
|
||||
nsCOMPtr<nsIDOMNode>sibling;
|
||||
result = aChild->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
// XXX: needs some logic to work for other leaf nodes besides text!
|
||||
}
|
||||
*aLeftNode = sibling;
|
||||
result = (*aLeftNode)->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aLeftNode));
|
||||
// now do the right side
|
||||
result = aChild->GetNextSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*aRightNode = sibling;
|
||||
result = (*aRightNode)->GetNextSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aRightNode));
|
||||
if (gNoisy) { printf("GetBlockSection returning %p %p\n",
|
||||
(*aLeftNode), (*aRightNode)); }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockSectionsForRange(nsIDOMRange *aRange, nsISupportsArray *aSections)
|
||||
{
|
||||
if (!aRange || !aSections) {return NS_ERROR_NULL_POINTER;}
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> lastRange;
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> currentContent;
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode = do_QueryInterface(currentContent);
|
||||
if (currentNode)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> currentContentTag;
|
||||
currentContent->GetTag(*getter_AddRefs(currentContentTag));
|
||||
// <BR> divides block content ranges. We can achieve this by nulling out lastRange
|
||||
if (nsIEditProperty::br==currentContentTag)
|
||||
{
|
||||
lastRange = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool isInlineOrText;
|
||||
result = IsNodeInline(currentNode, isInlineOrText);
|
||||
if (PR_FALSE==isInlineOrText)
|
||||
{
|
||||
PRUint16 nodeType;
|
||||
currentNode->GetNodeType(&nodeType);
|
||||
if (nsIDOMNode::TEXT_NODE == nodeType) {
|
||||
isInlineOrText = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==isInlineOrText)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>leftNode;
|
||||
nsCOMPtr<nsIDOMNode>rightNode;
|
||||
result = GetBlockSection(currentNode,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if (gNoisy) {printf("currentNode %p has block content (%p,%p)\n", currentNode.get(), leftNode.get(), rightNode.get());}
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode)
|
||||
{
|
||||
// add range to the list if it doesn't overlap with the previous range
|
||||
PRBool addRange=PR_TRUE;
|
||||
if (lastRange)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> lastStartNode;
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLastStartNode;
|
||||
lastRange->GetStartParent(getter_AddRefs(lastStartNode));
|
||||
result = GetBlockParent(lastStartNode, getter_AddRefs(blockParentOfLastStartNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLastStartNode)
|
||||
{
|
||||
if (gNoisy) {printf("lastStartNode %p has block parent %p\n", lastStartNode.get(), blockParentOfLastStartNode.get());}
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLeftNode;
|
||||
result = GetBlockParent(leftNode, getter_AddRefs(blockParentOfLeftNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLeftNode)
|
||||
{
|
||||
if (gNoisy) {printf("leftNode %p has block parent %p\n", leftNode.get(), blockParentOfLeftNode.get());}
|
||||
if (blockParentOfLastStartNode==blockParentOfLeftNode) {
|
||||
addRange = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==addRange)
|
||||
{
|
||||
if (gNoisy) {printf("adding range, setting lastRange with start node %p\n", leftNode.get());}
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
result = nsComponentManager::CreateInstance(kCRangeCID, nsnull,
|
||||
kIDOMRangeIID, getter_AddRefs(range));
|
||||
if ((NS_SUCCEEDED(result)) && range)
|
||||
{ // initialize the range
|
||||
range->SetStart(leftNode, 0);
|
||||
range->SetEnd(rightNode, 0);
|
||||
aSections->AppendElement(range);
|
||||
lastRange = do_QueryInterface(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult)
|
||||
{
|
||||
aResult = PR_TRUE; // init out param. we assume the condition is true unless we find a node that violates it
|
||||
if (!aStartNode || !aEndNode || !aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
nsresult result;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
//XXX: maybe CreateInstance is expensive, and I should keep around a static iter?
|
||||
// as long as this method can't be called recursively or re-entrantly!
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIContent>startContent;
|
||||
startContent = do_QueryInterface(aStartNode);
|
||||
nsCOMPtr<nsIContent>endContent;
|
||||
endContent = do_QueryInterface(aEndNode);
|
||||
if (startContent && endContent)
|
||||
{
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> content;
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
if ((content.get() != startContent.get()) &&
|
||||
(content.get() != endContent.get()))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode;
|
||||
currentNode = do_QueryInterface(content);
|
||||
PRBool isInline=PR_FALSE;
|
||||
IsNodeInline(currentNode, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(currentNode);
|
||||
if (!nodeAsText) // text nodes don't count in this check, so ignore them
|
||||
{
|
||||
aResult = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetPreviousSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetRightmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetPreviousSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
|
||||
return GetRightmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetNextSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetLeftmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetNextSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
return GetLeftmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetLastChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetFirstChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
element->GetTagName(tag);
|
||||
if (tag.Equals(aTag->GetUnicode()))
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>text;
|
||||
text = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
PRUint32 length = data.Length();
|
||||
if (0==length) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// if the node contains only newlines, it's not editable
|
||||
PRUint32 i;
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
if ('\n'!=data.CharAt(0)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//END nsEditor static utility methods
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
void nsEditor::HACKForceRedraw()
|
||||
{
|
||||
|
@ -2398,42 +2669,96 @@ nsEditor::DebugDumpContent() const
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
/* ----- TEST METHODS ----- */
|
||||
// Methods defined here are TEMPORARY
|
||||
|
||||
/* ORIGINAL version by Steve - KEEP FOR REFERENCE
|
||||
NS_IMETHODIMP GetColIndexForCell(nsIPresShell *aPresShell, nsIDOMNode *aCellNode, PRInt32 &aCellIndex)
|
||||
nsresult
|
||||
nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode,
|
||||
const nsString &aTag,
|
||||
nsIDOMNode **aResult)
|
||||
{
|
||||
aCellIndex=0; // initialize out param
|
||||
nsresult result = NS_ERROR_FAILURE; // we return an error unless we get the index
|
||||
if ((nsnull!=aCellNode) && (nsnull!=aPresShell))
|
||||
{ // get the content interface
|
||||
nsCOMPtr<nsIContent> nodeAsContent(aCellNode);
|
||||
if (nodeAsContent)
|
||||
{ // get the frame from the content interface
|
||||
nsISupports *layoutObject=nsnull; // frames are not ref counted, so don't use an nsCOMPtr
|
||||
result = aPresShell->GetLayoutObjectFor(nodeAsContent, &layoutObject);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=layoutObject))
|
||||
{ // get the table cell interface from the frame
|
||||
nsITableCellLayout *cellLayoutObject=nsnull; // again, frames are not ref-counted
|
||||
result = layoutObject->QueryInterface(nsITableCellLayout::GetIID(), (void**)(&cellLayoutObject));
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=cellLayoutObject))
|
||||
{ // get the index
|
||||
result = cellLayoutObject->GetColIndex(aCellIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
nsresult result=NS_OK;
|
||||
|
||||
/* ----- END TEST METHODS ----- */
|
||||
if (!aStartNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = aStartNode->GetFirstChild(getter_AddRefs(childNode));
|
||||
while (childNode)
|
||||
{
|
||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||
nsAutoString tag;
|
||||
if (NS_SUCCEEDED(result) && (element))
|
||||
{
|
||||
element->GetTagName(tag);
|
||||
if (PR_TRUE==aTag.Equals(tag))
|
||||
{
|
||||
return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref
|
||||
}
|
||||
else
|
||||
{
|
||||
nsresult result = GetFirstNodeOfType(childNode, aTag, aResult);
|
||||
if (nsnull!=*aResult)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||
{
|
||||
if (!aNode || !aRetNode)
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRUint16 mType;
|
||||
PRBool mCNodes;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> answer;
|
||||
|
||||
aNode->GetNodeType(&mType);
|
||||
|
||||
if (nsIDOMNode::ELEMENT_NODE == mType) {
|
||||
if (NS_SUCCEEDED(aNode->HasChildNodes(&mCNodes)) && PR_TRUE == mCNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node1;
|
||||
nsCOMPtr<nsIDOMNode> node2;
|
||||
|
||||
if (!NS_SUCCEEDED(aNode->GetFirstChild(getter_AddRefs(node1))))
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
}
|
||||
while(!answer && node1)
|
||||
{
|
||||
GetFirstTextNode(node1, getter_AddRefs(answer));
|
||||
node1->GetNextSibling(getter_AddRefs(node2));
|
||||
node1 = node2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsIDOMNode::TEXT_NODE == mType) {
|
||||
answer = do_QueryInterface(aNode);
|
||||
}
|
||||
|
||||
// OK, now return the answer, if any
|
||||
*aRetNode = answer;
|
||||
if (*aRetNode)
|
||||
NS_IF_ADDREF(*aRetNode);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
NS_IMETHODIMP nsEditor::DoInitialPreeeditInsert(const nsString& aStringToInsert)
|
||||
{
|
||||
|
@ -2601,3 +2926,4 @@ nsEditor::SetPreeditText(const nsString& aStringToInsert)
|
|||
EndTransaction();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "prmon.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsIContextLoader.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
@ -46,6 +45,7 @@ class SplitElementTxn;
|
|||
class JoinElementTxn;
|
||||
class EditAggregateTxn;
|
||||
class nsVoidArray;
|
||||
class nsISupportsArray;
|
||||
|
||||
//This is the monitor for the editor.
|
||||
PRMonitor *getEditorMonitor();
|
||||
|
@ -56,7 +56,7 @@ PRMonitor *getEditorMonitor();
|
|||
* manager, event interfaces. the idea for the event interfaces is to have them
|
||||
* delegate the actual commands to the editor independent of the XPFE implementation.
|
||||
*/
|
||||
class nsEditor : public nsIEditor, public nsIEditorSupport
|
||||
class nsEditor : public nsIEditor
|
||||
{
|
||||
private:
|
||||
nsIPresShell *mPresShell;
|
||||
|
@ -75,6 +75,10 @@ protected:
|
|||
nsIDOMDocument * mDoc;
|
||||
|
||||
public:
|
||||
|
||||
const static char* nsEditor::kMOZEditorBogusNodeAttr;
|
||||
const static char* nsEditor::kMOZEditorBogusNodeValue;
|
||||
|
||||
/** The default constructor. This should suffice. the setting of the interfaces is done
|
||||
* after the construction of the editor class.
|
||||
*/
|
||||
|
@ -186,32 +190,6 @@ public:
|
|||
/*END nsIEditor interfaces*/
|
||||
|
||||
|
||||
/*BEGIN public methods unique to nsEditor. These will get moved to an interface
|
||||
if they survive.
|
||||
*/
|
||||
|
||||
/** GetFirstTextNode ADDREFFS and will get the next available text node from the passed
|
||||
* in node parameter it can also return NS_ERROR_FAILURE if no text nodes are available
|
||||
* now it simply returns the first node in the dom
|
||||
* @param nsIDOMNode *aNode is the node to start looking from
|
||||
* @param nsIDOMNode **aRetNode is the return location of the text dom node
|
||||
*
|
||||
* NOTE: this method will probably be removed.
|
||||
*/
|
||||
NS_IMETHOD GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode);
|
||||
|
||||
/** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed
|
||||
* in aStartNode parameter of type aTag.
|
||||
* It can also return NS_ERROR_FAILURE if no such nodes are available
|
||||
* @param nsIDOMNode *aStartNode is the node to start looking from
|
||||
* @param nsIAtom *aTag is the type of node we are searching for
|
||||
* @param nsIDOMNode **aResult is the node we found, or nsnull if there is none
|
||||
*/
|
||||
NS_IMETHOD GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
||||
|
||||
/*END public methods of nsEditor*/
|
||||
|
||||
|
||||
/*BEGIN private methods used by the implementations of the above functions*/
|
||||
protected:
|
||||
/** create a transaction for setting aAttribute to aValue on aElement
|
||||
|
@ -278,28 +256,10 @@ protected:
|
|||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn);
|
||||
|
||||
NS_IMETHOD SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
|
||||
NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn);
|
||||
|
||||
NS_IMETHOD JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
NS_IMETHOD GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/** Create an aggregate transaction for deleting current selection
|
||||
* Used by all methods that need to delete current selection,
|
||||
* then insert something new to replace it
|
||||
|
@ -321,11 +281,152 @@ protected:
|
|||
// of an error in Gecko which is not rendering the
|
||||
// document after a change via the DOM - gpk 2/13/99
|
||||
void HACKForceRedraw(void);
|
||||
|
||||
PRBool mIMEFirstTransaction;
|
||||
|
||||
|
||||
NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode, PRInt32& offsetOfNewNode);
|
||||
|
||||
public:
|
||||
/**
|
||||
* SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
|
||||
* @param aExistingRightNode the node to split. It will become the new node's next sibling.
|
||||
* @param aOffset the offset of aExistingRightNode's content|children to do the split at
|
||||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
* @param aParent the parent of aExistingRightNode
|
||||
*/
|
||||
static nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
* @param aNodeToKeep The node that will remain after the join.
|
||||
* @param aNodeToJoin The node that will be joined with aNodeToKeep.
|
||||
* There is no requirement that the two nodes be of the same type.
|
||||
* @param aParent The parent of aExistingRightNode
|
||||
* @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the
|
||||
* contents|children of aNodeToJoin, otherwise their positions are switched.
|
||||
*/
|
||||
static nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
/**
|
||||
* Set aOffset to the offset of aChild in aParent.
|
||||
* Returns an error if aChild is not an immediate child of aParent.
|
||||
*/
|
||||
static nsresult GetChildOffset(nsIDOMNode *aChild,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 &aOffset);
|
||||
|
||||
/** set aIsInline to PR_TRUE if aNode is inline as defined by HTML DTD */
|
||||
static nsresult IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline);
|
||||
|
||||
/** returns the closest block parent of aNode, not including aNode itself.
|
||||
* can return null, for example if aNode is in a document fragment.
|
||||
* @param aNode The node whose parent we seek.
|
||||
* @param aBlockParent [OUT] The block parent, if any.
|
||||
* @return a success value unless an unexpected error occurs.
|
||||
*/
|
||||
static nsresult GetBlockParent(nsIDOMNode *aNode,
|
||||
nsIDOMElement **aBlockParent);
|
||||
|
||||
/** Determines the bounding nodes for the block section containing aNode.
|
||||
* The calculation is based on some nodes intrinsically being block elements
|
||||
* acording to HTML. Style sheets are not considered in this calculation.
|
||||
* <BR> tags separate block content sections. So the HTML markup:
|
||||
* <PRE>
|
||||
* <P>text1<BR>text2<B>text3</B></P>
|
||||
* </PRE>
|
||||
* contains two block content sections. The first has the text node "text1"
|
||||
* for both endpoints. The second has "text2" as the left endpoint and
|
||||
* "text3" as the right endpoint.
|
||||
* Notice that offsets aren't required, only leaf nodes. Offsets are implicit.
|
||||
*
|
||||
* @param aNode the block content returned includes aNode
|
||||
* @param aLeftNode [OUT] the left endpoint of the block content containing aNode
|
||||
* @param aRightNode [OUT] the right endpoint of the block content containing aNode
|
||||
*
|
||||
*/
|
||||
static nsresult GetBlockSection(nsIDOMNode *aNode,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode);
|
||||
|
||||
/** Compute the set of block sections in a given range.
|
||||
* A block section is the set of (leftNode, rightNode) pairs given
|
||||
* by GetBlockSection. The set is computed by computing the
|
||||
* block section for every leaf node in the range and throwing
|
||||
* out duplicates.
|
||||
*
|
||||
* @param aRange The range to compute block sections for.
|
||||
* @param aSections Allocated storage for the resulting set, stored as nsIDOMRanges.
|
||||
*/
|
||||
static nsresult GetBlockSectionsForRange(nsIDOMRange *aRange,
|
||||
nsISupportsArray *aSections);
|
||||
|
||||
/** returns PR_TRUE in out-param aResult if all nodes between (aStartNode, aStartOffset)
|
||||
* and (aEndNode, aEndOffset) are inline as defined by HTML DTD.
|
||||
*/
|
||||
static nsresult IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult);
|
||||
|
||||
/** returns the number of things inside aNode in the out-param aCount.
|
||||
* @param aNode is the node to get the length of.
|
||||
* If aNode is text, returns number of characters.
|
||||
* If not, returns number of children nodes.
|
||||
* @param aCount [OUT] the result of the above calculation.
|
||||
*/
|
||||
static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/** GetFirstTextNode ADDREFFS and will get the next available text node from the passed
|
||||
* in node parameter it can also return NS_ERROR_FAILURE if no text nodes are available
|
||||
* now it simply returns the first node in the dom
|
||||
* @param nsIDOMNode *aNode is the node to start looking from
|
||||
* @param nsIDOMNode **aRetNode is the return location of the text dom node
|
||||
*
|
||||
* NOTE: this method will probably be removed.
|
||||
*/
|
||||
static nsresult GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode);
|
||||
|
||||
/** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed
|
||||
* in aStartNode parameter of type aTag.
|
||||
* It can also return NS_ERROR_FAILURE if no such nodes are available
|
||||
* @param aStartNode is the node to start looking from
|
||||
* @param aTag is the type of node we are searching for
|
||||
* @param aResult is the node we found, or nsnull if there is none
|
||||
*/
|
||||
static nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode,
|
||||
const nsString &aTag,
|
||||
nsIDOMNode **aResult);
|
||||
|
||||
/** returns PR_TRUE if aNode is of the type implied by aTag */
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
|
||||
/** returns PR_TRUE if aNode is an editable node */
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIStringStream.h"
|
||||
|
||||
|
@ -599,7 +600,39 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
|
|||
nsCOMPtr<nsIHTMLEditor>htmlEditor;
|
||||
htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor) {
|
||||
htmlEditor->RemoveBlockParent();
|
||||
htmlEditor->RemoveParagraphStyle();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// hard-coded change structure test -- GetParagraphStyle
|
||||
case nsIDOMEvent::VK_0:
|
||||
if (PR_TRUE==ctrlKey)
|
||||
{
|
||||
aProcessed=PR_TRUE;
|
||||
if (mEditor)
|
||||
{
|
||||
nsCOMPtr<nsIHTMLEditor>htmlEditor;
|
||||
htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
printf("testing GetParagraphStyle\n");
|
||||
nsStringArray styles;
|
||||
nsresult result = htmlEditor->GetParagraphStyle(&styles);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
PRInt32 count = styles.Count();
|
||||
PRInt32 i;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
nsString *tag = styles.StringAt(i);
|
||||
char *tagCString = tag->ToNewCString();
|
||||
printf("%s ", tagCString);
|
||||
delete [] tagCString;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITableCellLayout.h" //For GetColIndexForCell
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
||||
|
@ -59,7 +58,7 @@ static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
|||
static NS_DEFINE_IID(kIContentIteratorIID, NS_ICONTENTITERTOR_IID);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
@ -205,7 +204,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
|||
if (-1==offsetInParent)
|
||||
{
|
||||
nextNode->GetParentNode(getter_AddRefs(parent));
|
||||
result = nsIEditorSupport::GetChildOffset(nextNode, parent, offsetInParent);
|
||||
result = GetChildOffset(nextNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
||||
}
|
||||
|
@ -395,17 +394,17 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and get the block parent of each
|
||||
nsISupportsArray *subRanges;
|
||||
result = NS_NewISupportsArray(&subRanges);
|
||||
if ((NS_SUCCEEDED(result)) && subRanges)
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockRanges(range, subRanges);
|
||||
result = GetBlockSectionsForRange(range, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
|
@ -418,17 +417,19 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
|||
{
|
||||
nsAutoString blockParentTag;
|
||||
blockParent->GetTagName(blockParentTag);
|
||||
if (-1==aTagList->IndexOf(blockParentTag)) {
|
||||
PRBool isRoot;
|
||||
IsRootTag(blockParentTag, isRoot);
|
||||
if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) {
|
||||
aTagList->AppendString(blockParentTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRange);
|
||||
subRanges->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRanges);
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +466,7 @@ nsHTMLEditor::AddBlockParent(nsString& aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and apply the transformation to them
|
||||
result = ReParentContentOfRange(range, aParentTag, eInsertParent);
|
||||
}
|
||||
|
@ -510,47 +511,30 @@ nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and apply the transformation to them
|
||||
result = ReParentContentOfRange(range, aParentTag, eReplaceParent);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // set the selection
|
||||
// XXX: can't do anything until I can create ranges
|
||||
}
|
||||
}
|
||||
if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IsRootTag(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString bodyTag = "body";
|
||||
static nsAutoString tdTag = "td";
|
||||
static nsAutoString thTag = "th";
|
||||
static nsAutoString captionTag = "caption";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(bodyTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(tdTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(thTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(captionTag) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
||||
nsString &aParentTag,
|
||||
BlockTransformationType aTransformation)
|
||||
{
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
if (gNoisy)
|
||||
{
|
||||
char *tag = aParentTag.ToNewCString();
|
||||
printf("---------- ReParentContentOfNode(%p,%s,%d) -----------\n", aNode, tag, aTransformation);
|
||||
delete [] tag;
|
||||
}
|
||||
// find the current block parent, or just use aNode if it is a block node
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement;
|
||||
nsCOMPtr<nsIDOMNode>nodeToReParent; // this is the node we'll operate on, by default it's aNode
|
||||
|
@ -606,7 +590,7 @@ nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
|||
{ // this is the case of an insertion point between 2 non-text objects
|
||||
// XXX: how to you know it's an insertion point???
|
||||
PRInt32 offsetInParent=0;
|
||||
result = nsIEditorSupport::GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
||||
result = GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
// otherwise, just create the block parent at the selection
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent,
|
||||
|
@ -654,10 +638,14 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
nsString &aParentTag,
|
||||
nsIDOMNode *aBlockParentNode,
|
||||
nsString &aBlockParentTag,
|
||||
BlockTransformationType aTranformation,
|
||||
BlockTransformationType aTransformation,
|
||||
nsIDOMNode **aNewParentNode)
|
||||
{
|
||||
if (!aNode || !aBlockParentNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; }
|
||||
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(aBlockParentNode);
|
||||
PRBool removeBlockParent = PR_FALSE;
|
||||
PRBool removeBreakBefore = PR_FALSE;
|
||||
PRBool removeBreakAfter = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMNode>ancestor;
|
||||
nsresult result = aNode->GetParentNode(getter_AddRefs(ancestor));
|
||||
nsCOMPtr<nsIDOMNode>previousAncestor = do_QueryInterface(aNode);
|
||||
|
@ -675,46 +663,87 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
}
|
||||
// now, previousAncestor is the node we are operating on
|
||||
nsCOMPtr<nsIDOMNode>leftNode, rightNode;
|
||||
result = GetBlockDelimitedContent(previousAncestor,
|
||||
result = GetBlockSection(previousAncestor,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode)
|
||||
{
|
||||
PRInt32 offsetInParent=0;
|
||||
if (eInsertParent==aTranformation)
|
||||
// determine some state for managing <BR>s around the new block
|
||||
PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block
|
||||
PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement = do_QueryInterface(blockParentNode);
|
||||
if (blockParentElement)
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(leftNode, aBlockParentNode, offsetInParent);
|
||||
nsAutoString blockParentTag;
|
||||
blockParentElement->GetTagName(blockParentTag);
|
||||
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
||||
IsRootTag(blockParentTag, isRootBlock);
|
||||
}
|
||||
|
||||
if (PR_TRUE==isRootBlock)
|
||||
{ // we're creating a block element where a block element did not previously exist
|
||||
removeBreakBefore = PR_TRUE;
|
||||
removeBreakAfter = PR_TRUE;
|
||||
}
|
||||
|
||||
// apply the transformation
|
||||
PRInt32 offsetInParent=0;
|
||||
if (eInsertParent==aTransformation || PR_TRUE==isRootBlock)
|
||||
{
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, aBlockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in aBlockParentNode at offset %d\n", offsetInParent); }
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> grandParent;
|
||||
result = aBlockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
result = blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
if ((NS_SUCCEEDED(result)) && grandParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>firstChildNode, lastChildNode;
|
||||
aBlockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
||||
aBlockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
||||
blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
||||
blockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
||||
if (firstChildNode==leftNode && lastChildNode==rightNode)
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(aBlockParentNode, grandParent, offsetInParent);
|
||||
result = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); }
|
||||
}
|
||||
else
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(leftNode, aBlockParentNode, offsetInParent);
|
||||
// We're in the case where the content of blockParentNode is separated by <BR>'s,
|
||||
// creating multiple block content ranges.
|
||||
// Split blockParentNode around the blockContent
|
||||
if (gNoisy) { printf("splitting a node because of <BR>s\n"); }
|
||||
nsCOMPtr<nsIDOMNode> newLeftNode;
|
||||
if (firstChildNode!=leftNode)
|
||||
{
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
if (gNoisy) { printf("splitting left at %d\n", offsetInParent); }
|
||||
result = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
||||
// after this split, blockParentNode still contains leftNode and rightNode
|
||||
}
|
||||
if (lastChildNode!=rightNode)
|
||||
{
|
||||
result = GetChildOffset(rightNode, blockParentNode, offsetInParent);
|
||||
offsetInParent++;
|
||||
if (gNoisy) { printf("splitting right at %d\n", offsetInParent); }
|
||||
result = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
||||
blockParentNode = do_QueryInterface(newLeftNode);
|
||||
}
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, aBlockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in aBlockParentNode at offset %d\n", offsetInParent); }
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
||||
// what we need to do here is remove the existing block parent when we're all done.
|
||||
removeBlockParent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((NS_SUCCEEDED(result)) && *aNewParentNode)
|
||||
{ // move all the children/contents of aBlockParentNode to aNewParentNode
|
||||
{ // move all the children/contents of blockParentNode to aNewParentNode
|
||||
nsCOMPtr<nsIDOMNode>childNode = do_QueryInterface(rightNode);
|
||||
nsCOMPtr<nsIDOMNode>previousSiblingNode;
|
||||
while (NS_SUCCEEDED(result) && childNode)
|
||||
|
@ -737,6 +766,73 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
childNode = do_QueryInterface(previousSiblingNode);
|
||||
} // end while loop
|
||||
}
|
||||
// clean up the surrounding content to maintain vertical whitespace
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// if the prior node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
result = GetPriorNode(leftNode, getter_AddRefs(brNode));
|
||||
if (NS_SUCCEEDED(result) && brNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
||||
if (brContent)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> brContentTag;
|
||||
brContent->GetTag(*getter_AddRefs(brContentTag));
|
||||
if (nsIEditProperty::br==brContentTag) {
|
||||
result = DeleteNode(brNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the next node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = GetNextNode(rightNode, getter_AddRefs(brNode));
|
||||
if (NS_SUCCEEDED(result) && brNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
||||
if (brContent)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> brContentTag;
|
||||
brContent->GetTag(*getter_AddRefs(brContentTag));
|
||||
if (nsIEditProperty::br==brContentTag) {
|
||||
result = DeleteNode(brNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((NS_SUCCEEDED(result)) && (PR_TRUE==removeBlockParent))
|
||||
{ // we determined we need to remove the previous block parent. Do it!
|
||||
// go through list backwards so deletes don't interfere with the iteration
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = blockParentNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
result = nsTextEditor::DeleteNode(childNode);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); }
|
||||
result = nsTextEditor::DeleteNode(blockParentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -748,29 +844,30 @@ nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange,
|
|||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *subRanges;
|
||||
result = NS_NewISupportsArray(&subRanges);
|
||||
if ((NS_SUCCEEDED(result)) && subRanges)
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockRanges(aRange, subRanges);
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
result = subRange->GetStartParent(getter_AddRefs(startParent));
|
||||
if (NS_SUCCEEDED(result) && startParent)
|
||||
{
|
||||
if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); }
|
||||
result = ReParentContentOfNode(startParent, aParentTag, aTranformation);
|
||||
}
|
||||
NS_RELEASE(subRange);
|
||||
subRanges->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRanges);
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -793,10 +890,10 @@ nsHTMLEditor::CanContainBlock(nsString &aBlockChild, nsString &aBlockParent, PRB
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveBlockParent()
|
||||
nsHTMLEditor::RemoveParagraphStyle()
|
||||
{
|
||||
if (gNoisy) {
|
||||
printf("---------- nsHTMLEditor::RemoveBlockParent ----------\n");
|
||||
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
||||
}
|
||||
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -815,28 +912,57 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIDOMNode>commonParent;
|
||||
result = range->GetCommonParent(getter_AddRefs(commonParent));
|
||||
if ((NS_SUCCEEDED(result)) && commonParent)
|
||||
result = RemoveParagraphStyleFromRange(range);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
|
||||
range->GetStartParent(getter_AddRefs(startParent));
|
||||
range->GetEndParent(getter_AddRefs(endParent));
|
||||
if (startParent.get()==endParent.get())
|
||||
{ // the range is entirely contained within a single node
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = RemoveParagraphStyleFromBlockContent(subRange);
|
||||
NS_RELEASE(subRange);
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
aRange->GetStartParent(getter_AddRefs(startParent));
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement;
|
||||
result = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
||||
while ((NS_SUCCEEDED(result)) && blockParentElement)
|
||||
{
|
||||
nsAutoString childTag; // leave as empty string
|
||||
nsAutoString blockParentTag;
|
||||
blockParentElement->GetTagName(blockParentTag);
|
||||
PRBool canContain;
|
||||
CanContainBlock(childTag, blockParentTag, canContain);
|
||||
if (PR_TRUE==canContain) {
|
||||
PRBool isSubordinateBlock;
|
||||
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
||||
if (PR_FALSE==isSubordinateBlock) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -849,7 +975,7 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
blockParentElement->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
||||
result = GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
|
@ -872,20 +998,15 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
}
|
||||
result = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
||||
{
|
||||
if (gNoisy) {
|
||||
printf("---------- nsHTMLEditor::RemoveParent %s----------\n", aParentTag);
|
||||
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
||||
}
|
||||
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -904,29 +1025,60 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIDOMNode>commonParent;
|
||||
result = range->GetCommonParent(getter_AddRefs(commonParent));
|
||||
if ((NS_SUCCEEDED(result)) && commonParent)
|
||||
result = RemoveParentFromRange(aParentTag, range);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = RemoveParentFromBlockContent(aParentTag, subRange);
|
||||
NS_RELEASE(subRange);
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
result = aRange->GetStartParent(getter_AddRefs(startParent));
|
||||
if ((NS_SUCCEEDED(result)) && startParent)
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
|
||||
range->GetStartParent(getter_AddRefs(startParent));
|
||||
range->GetEndParent(getter_AddRefs(endParent));
|
||||
if (startParent.get()==endParent.get())
|
||||
{ // the range is entirely contained within a single node
|
||||
nsCOMPtr<nsIDOMNode>parentNode;
|
||||
nsCOMPtr<nsIDOMElement>parentElement;
|
||||
result = startParent->GetParentNode(getter_AddRefs(parentNode));
|
||||
while ((NS_SUCCEEDED(result)) && parentNode)
|
||||
{
|
||||
parentElement = do_QueryInterface(parentNode);
|
||||
nsAutoString childTag; // leave as empty string
|
||||
nsAutoString parentTag;
|
||||
parentElement->GetTagName(parentTag);
|
||||
PRBool canContain;
|
||||
CanContainBlock(childTag, parentTag, canContain);
|
||||
PRBool isRoot;
|
||||
IsRootTag(parentTag, isRoot);
|
||||
if (aParentTag.EqualsIgnoreCase(parentTag))
|
||||
{
|
||||
// go through list backwards so deletes don't interfere with the iteration
|
||||
|
@ -937,7 +1089,7 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
parentElement->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(parentElement, grandParent, offsetInParent);
|
||||
result = GetChildOffset(parentElement, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
|
@ -959,21 +1111,15 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
}
|
||||
break;
|
||||
}
|
||||
else if (PR_TRUE==canContain) { // hit a subdoc, terminate?
|
||||
else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop
|
||||
break;
|
||||
}
|
||||
result = parentElement->GetParentNode(getter_AddRefs(parentNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::InsertLink(nsString& aURL)
|
||||
{
|
||||
|
@ -1331,6 +1477,62 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection, ns
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::IsRootTag(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString bodyTag = "body";
|
||||
static nsAutoString tdTag = "td";
|
||||
static nsAutoString thTag = "th";
|
||||
static nsAutoString captionTag = "caption";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(bodyTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(tdTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(thTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(captionTag) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::IsSubordinateBlock(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString p = "p";
|
||||
static nsAutoString h1 = "h1";
|
||||
static nsAutoString h2 = "h2";
|
||||
static nsAutoString h3 = "h3";
|
||||
static nsAutoString h4 = "h4";
|
||||
static nsAutoString h5 = "h5";
|
||||
static nsAutoString h6 = "h6";
|
||||
static nsAutoString address = "address";
|
||||
static nsAutoString pre = "pre";
|
||||
static nsAutoString li = "li";
|
||||
static nsAutoString dt = "dt";
|
||||
static nsAutoString dd = "dd";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(p) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h1) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h2) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h3) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h4) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h5) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h6) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(address) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(pre) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(li) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(dt) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(dd) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::BeginComposition(void)
|
||||
{
|
||||
return nsTextEditor::BeginComposition();
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
NS_IMETHOD GetParagraphStyle(nsStringArray *aTagList);
|
||||
NS_IMETHOD AddBlockParent(nsString& aParentTag);
|
||||
NS_IMETHOD ReplaceBlockParent(nsString& aParentTag);
|
||||
NS_IMETHOD RemoveBlockParent();
|
||||
NS_IMETHOD RemoveParagraphStyle();
|
||||
NS_IMETHOD RemoveParent(const nsString &aParentTag);
|
||||
|
||||
NS_IMETHOD InsertLink(nsString& aURL);
|
||||
|
@ -163,8 +163,22 @@ protected:
|
|||
nsString &aParentTag,
|
||||
BlockTransformationType aTranformation);
|
||||
|
||||
NS_IMETHOD RemoveParagraphStyleFromRange(nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD CanContainBlock(nsString &aBlockChild, nsString &aBlockParent, PRBool &aCanContain);
|
||||
|
||||
|
||||
NS_IMETHOD IsRootTag(nsString &aTag, PRBool &aIsTag);
|
||||
|
||||
NS_IMETHOD IsSubordinateBlock(nsString &aTag, PRBool &aIsTag);
|
||||
|
||||
|
||||
// EVENT LISTENERS AND COMMAND ROUTING NEEDS WORK
|
||||
// For now, the listners are tied to the nsTextEditor class
|
||||
//
|
||||
|
|
|
@ -73,6 +73,7 @@ SUP places text in superscript style
|
|||
|
||||
// block tags
|
||||
static nsIAtom *blockquote;
|
||||
static nsIAtom *br;
|
||||
static nsIAtom *h1;
|
||||
static nsIAtom *h2;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsEditor.h"
|
||||
#include "PlaceholderTxn.h"
|
||||
#include "InsertTextTxn.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -31,69 +32,8 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIEditProperty.h"
|
||||
|
||||
const static char* kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
|
||||
const static char* kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
|
||||
|
||||
/********************************************************
|
||||
* Helper Functions
|
||||
********************************************************/
|
||||
|
||||
PRBool nsTextEditRules::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
element->GetTagName(tag);
|
||||
if (tag.Equals(aTag->GetUnicode()))
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool nsTextEditRules::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>text;
|
||||
text = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
if (0==data.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if ('\n'==data.CharAt(0)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************
|
||||
|
@ -437,7 +377,7 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode,
|
|||
nsCOMPtr<nsIDOMNode>parent;
|
||||
aNode->GetParentNode(getter_AddRefs(parent));
|
||||
PRInt32 offsetInParent;
|
||||
nsIEditorSupport::GetChildOffset(aNode, parent, offsetInParent);
|
||||
nsEditor::GetChildOffset(aNode, parent, offsetInParent);
|
||||
nsAutoString tag;
|
||||
aTag->ToString(tag);
|
||||
result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode);
|
||||
|
@ -563,7 +503,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
while ((NS_SUCCEEDED(result)) && bodyChild)
|
||||
{
|
||||
if (PR_TRUE==IsEditable(bodyChild))
|
||||
if (PR_TRUE==nsEditor::IsEditable(bodyChild))
|
||||
{
|
||||
needsBogusContent = PR_FALSE;
|
||||
break;
|
||||
|
@ -599,8 +539,8 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
newPElement = do_QueryInterface(mBogusNode);
|
||||
if (newPElement)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val(kMOZEditorBogusNodeValue);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val(nsEditor::kMOZEditorBogusNodeValue);
|
||||
newPElement->SetAttribute(att, val);
|
||||
}
|
||||
}
|
||||
|
@ -706,10 +646,10 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
|
@ -752,10 +692,10 @@ nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,8 +85,6 @@ protected:
|
|||
nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
// helper functions
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
/** insert aNode into a new style node of type aTag.
|
||||
* aSelection is optional. If provided, aSelection is set to (aNode, 0)
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsEditorEventListeners.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsEditProperty.h" // temporary, to get html atoms
|
||||
|
@ -96,7 +95,7 @@ static NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
|
|||
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
@ -601,7 +600,7 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
|
|||
{
|
||||
nsString tag;
|
||||
element->GetTagName(tag);
|
||||
if (propName.Equals(tag))
|
||||
if (propName.EqualsIgnoreCase(tag))
|
||||
{
|
||||
PRBool found = PR_FALSE;
|
||||
if (aAttribute)
|
||||
|
@ -613,7 +612,7 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
|
|||
if (!aValue) {
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else if (aValue->Equals(value)) {
|
||||
else if (aValue->EqualsIgnoreCase(value)) {
|
||||
found = PR_TRUE;
|
||||
}
|
||||
else { // we found the prop with the attribute, but the value doesn't match
|
||||
|
@ -1243,7 +1242,7 @@ NS_IMETHODIMP nsTextEditor::MoveContentOfNodeIntoNewParent(nsIDOMNode *aNode,
|
|||
result = nsEditor::DeleteNode(aNewParentNode);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // must get child offset AFTER delete of aNewParentNode!
|
||||
result = nsIEditorSupport::GetChildOffset(aNode, parentNode, offsetInParent);
|
||||
result = GetChildOffset(aNode, parentNode, offsetInParent);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = nsEditor::InsertNode(aNewParentNode, parentNode, offsetInParent);
|
||||
|
@ -1278,298 +1277,6 @@ NS_IMETHODIMP nsTextEditor::MoveContentOfNodeIntoNewParent(nsIDOMNode *aNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
// returns the number of things inside aNode.
|
||||
// If aNode is text, returns number of characters. If not, returns number of children nodes.
|
||||
NS_IMETHODIMP nsTextEditor::GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount) const
|
||||
{
|
||||
aCount = 0;
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result=NS_OK;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
|
||||
nodeAsChar = do_QueryInterface(aNode);
|
||||
if (nodeAsChar) {
|
||||
nodeAsChar->GetLength(&aCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool hasChildNodes;
|
||||
aNode->HasChildNodes(&hasChildNodes);
|
||||
if (PR_TRUE==hasChildNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
result = aNode->GetChildNodes(getter_AddRefs(nodeList));
|
||||
if (NS_SUCCEEDED(result) && nodeList) {
|
||||
nodeList->GetLength(&aCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// content-based inline vs. block query
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const
|
||||
{
|
||||
// this is a content-based implementation
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsresult result;
|
||||
aIsInline = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
result = element->GetTagName(tag);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIAtom *tagAtom = NS_NewAtom(tag);
|
||||
if (!tagAtom) { return NS_ERROR_NULL_POINTER; }
|
||||
if (tagAtom==nsIEditProperty::a ||
|
||||
tagAtom==nsIEditProperty::b ||
|
||||
tagAtom==nsIEditProperty::big ||
|
||||
tagAtom==nsIEditProperty::font ||
|
||||
tagAtom==nsIEditProperty::i ||
|
||||
tagAtom==nsIEditProperty::span ||
|
||||
tagAtom==nsIEditProperty::small ||
|
||||
tagAtom==nsIEditProperty::strike ||
|
||||
tagAtom==nsIEditProperty::sub ||
|
||||
tagAtom==nsIEditProperty::sup ||
|
||||
tagAtom==nsIEditProperty::tt ||
|
||||
tagAtom==nsIEditProperty::u )
|
||||
{
|
||||
aIsInline = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::GetBlockParent(nsIDOMNode *aNode, nsIDOMElement **aBlockParent) const
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aBlockParent) {return NS_ERROR_NULL_POINTER;}
|
||||
*aBlockParent = nsnull;
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
nsCOMPtr<nsIDOMNode>temp;
|
||||
result = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
while (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRBool isInline;
|
||||
result = IsNodeInline(parent, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
parent->QueryInterface(nsIDOMElement::GetIID(), (void**)aBlockParent);
|
||||
break;
|
||||
}
|
||||
result = parent->GetParentNode(getter_AddRefs(temp));
|
||||
parent = do_QueryInterface(temp);
|
||||
}
|
||||
if (gNoisy) { printf("GetBlockParent for %p returning parent %p\n", aNode, *aBlockParent); }
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::GetBlockDelimitedContent(nsIDOMNode *aChild,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode) const
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aChild || !aLeftNode || !aRightNode) {return NS_ERROR_NULL_POINTER;}
|
||||
*aLeftNode = aChild;
|
||||
*aRightNode = aChild;
|
||||
|
||||
nsCOMPtr<nsIDOMNode>sibling;
|
||||
result = aChild->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*aLeftNode = sibling;
|
||||
result = (*aLeftNode)->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aLeftNode));
|
||||
// now do the right side
|
||||
result = aChild->GetNextSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*aRightNode = sibling;
|
||||
result = (*aRightNode)->GetNextSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aRightNode));
|
||||
if (gNoisy) { printf("GetBlockDelimitedContent returning %p %p\n",
|
||||
(*aLeftNode), (*aRightNode)); }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::GetBlockRanges(nsIDOMRange *aRange, nsISupportsArray *aSubRanges) const
|
||||
{
|
||||
if (!aRange || !aSubRanges) {return NS_ERROR_NULL_POINTER;}
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> lastRange;
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> currentContent;
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode = do_QueryInterface(currentContent);
|
||||
if (currentNode)
|
||||
{
|
||||
PRBool isInlineOrText;
|
||||
result = IsNodeInline(currentNode, isInlineOrText);
|
||||
if (PR_FALSE==isInlineOrText)
|
||||
{
|
||||
PRUint16 nodeType;
|
||||
currentNode->GetNodeType(&nodeType);
|
||||
if (nsIDOMNode::TEXT_NODE == nodeType) {
|
||||
isInlineOrText = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==isInlineOrText)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>leftNode;
|
||||
nsCOMPtr<nsIDOMNode>rightNode;
|
||||
result = GetBlockDelimitedContent(currentNode,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if (gNoisy) {printf("currentNode %p has block content (%p,%p)\n", currentNode.get(), leftNode.get(), rightNode.get());}
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode)
|
||||
{
|
||||
// add range to the list if it doesn't overlap with the previous range
|
||||
PRBool addRange=PR_TRUE;
|
||||
if (lastRange)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> lastStartNode;
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLastStartNode;
|
||||
lastRange->GetStartParent(getter_AddRefs(lastStartNode));
|
||||
result = GetBlockParent(lastStartNode, getter_AddRefs(blockParentOfLastStartNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLastStartNode)
|
||||
{
|
||||
if (gNoisy) {printf("lastStartNode %p has block parent %p\n", lastStartNode.get(), blockParentOfLastStartNode.get());}
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLeftNode;
|
||||
result = GetBlockParent(leftNode, getter_AddRefs(blockParentOfLeftNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLeftNode)
|
||||
{
|
||||
if (gNoisy) {printf("leftNode %p has block parent %p\n", leftNode.get(), blockParentOfLeftNode.get());}
|
||||
if (blockParentOfLastStartNode==blockParentOfLeftNode) {
|
||||
addRange = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==addRange)
|
||||
{
|
||||
if (gNoisy) {printf("adding range, setting lastRange with start node %p\n", leftNode.get());}
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
result = nsComponentManager::CreateInstance(kCRangeCID, nsnull,
|
||||
kIDOMRangeIID, getter_AddRefs(range));
|
||||
if ((NS_SUCCEEDED(result)) && range)
|
||||
{ // initialize the range
|
||||
range->SetStart(leftNode, 0);
|
||||
range->SetEnd(rightNode, 0);
|
||||
aSubRanges->AppendElement(range);
|
||||
lastRange = do_QueryInterface(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult) const
|
||||
{
|
||||
aResult = PR_TRUE; // init out param. we assume the condition is true unless we find a node that violates it
|
||||
if (!aStartNode || !aEndNode || !aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
nsresult result;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
//XXX: maybe CreateInstance is expensive, and I should keep around a static iter?
|
||||
// as long as this method can't be called recursively or re-entrantly!
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIContent>startContent;
|
||||
startContent = do_QueryInterface(aStartNode);
|
||||
nsCOMPtr<nsIContent>endContent;
|
||||
endContent = do_QueryInterface(aEndNode);
|
||||
if (startContent && endContent)
|
||||
{
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> content;
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
if ((content.get() != startContent.get()) &&
|
||||
(content.get() != endContent.get()))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode;
|
||||
currentNode = do_QueryInterface(content);
|
||||
PRBool isInline=PR_FALSE;
|
||||
IsNodeInline(currentNode, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(currentNode);
|
||||
if (!nodeAsText) // text nodes don't count in this check, so ignore them
|
||||
{
|
||||
aResult = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* this should only get called if the only intervening nodes are inline style nodes */
|
||||
NS_IMETHODIMP
|
||||
nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
|
||||
|
@ -1641,7 +1348,7 @@ NS_IMETHODIMP nsTextEditor::MoveContiguousContentIntoNewParent(nsIDOMNode *aSta
|
|||
{
|
||||
PRInt32 offsetInParent;
|
||||
if (newLeftNode) {
|
||||
result = nsIEditorSupport::GetChildOffset(newLeftNode, aGrandParentNode, offsetInParent);
|
||||
result = GetChildOffset(newLeftNode, aGrandParentNode, offsetInParent);
|
||||
}
|
||||
else {
|
||||
offsetInParent = -1; // relies on +1 below in call to CreateNode
|
||||
|
@ -1903,10 +1610,10 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
|
|||
if (gNoisy) { printf("* parent has tag %s\n", tag.ToNewCString()); } // XXX leak!
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (PR_FALSE==tag.Equals(aPropName->GetUnicode()))
|
||||
if (PR_FALSE==tag.EqualsIgnoreCase(aPropName->GetUnicode()))
|
||||
{
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent);
|
||||
result = GetChildOffset(newMiddleNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (0!=offsetInParent) {
|
||||
|
@ -1947,7 +1654,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
|
|||
{
|
||||
if (gNoisy) { printf("* this is the style node\n");}
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent);
|
||||
result = GetChildOffset(newMiddleNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>childNodes;
|
||||
|
@ -1980,7 +1687,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
|
|||
{ // promote the selection to the grandparent
|
||||
// first, determine the child's position in it's parent
|
||||
PRInt32 childPositionInParent;
|
||||
nsIEditorSupport::GetChildOffset(newMiddleNode, parent, childPositionInParent);
|
||||
GetChildOffset(newMiddleNode, parent, childPositionInParent);
|
||||
// compare childPositionInParent to the number of children in parent
|
||||
PRUint32 count=0;
|
||||
nsCOMPtr<nsIDOMNodeList>childNodes;
|
||||
|
@ -2004,7 +1711,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
|
|||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
PRInt32 position;
|
||||
result = nsIEditorSupport::GetChildOffset(parent, grandParent, position);
|
||||
result = GetChildOffset(parent, grandParent, position);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (PR_TRUE==insertAfter)
|
||||
|
@ -2242,7 +1949,7 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar
|
|||
{
|
||||
nsString tag;
|
||||
element->GetTagName(tag);
|
||||
if (propName.Equals(tag))
|
||||
if (propName.EqualsIgnoreCase(tag))
|
||||
{
|
||||
if (-1==nodeList.IndexOf(content.get())) {
|
||||
nodeList.AppendElement((void *)(content.get()));
|
||||
|
@ -2272,7 +1979,7 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStar
|
|||
if (NS_SUCCEEDED(result) && parentNode)
|
||||
{
|
||||
PRInt32 position;
|
||||
result = nsIEditorSupport::GetChildOffset(styleNode, parentNode, position);
|
||||
result = GetChildOffset(styleNode, parentNode, position);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>previousSiblingNode;
|
||||
|
|
|
@ -145,39 +145,6 @@ protected:
|
|||
const nsString *aAttributes,
|
||||
PRBool &aIsSet) const;
|
||||
|
||||
/** returns PR_TRUE in out-param aIsInline if aNode is inline as defined by HTML DTD */
|
||||
NS_IMETHOD IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const;
|
||||
|
||||
/** returns the closest block parent of aNode, not including aNode itself.
|
||||
* can return null, for example if aNode is in a document fragment.
|
||||
* @param aNode The node whose parent we seek.
|
||||
* @param aBlockParent [OUT] The block parent, if any.
|
||||
* @return a success value unless an unexpected error occurs.
|
||||
*/
|
||||
NS_IMETHOD GetBlockParent(nsIDOMNode *aNode, nsIDOMElement **aBlockParent) const;
|
||||
|
||||
NS_IMETHOD GetBlockDelimitedContent(nsIDOMNode *aChild,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode) const;
|
||||
|
||||
NS_IMETHOD GetBlockRanges(nsIDOMRange *aRange, nsISupportsArray *aSubRanges) const;
|
||||
|
||||
/** returns PR_TRUE in out-param aResult if all nodes between (aStartNode, aStartOffset)
|
||||
* and (aEndNode, aEndOffset) are inline as defined by HTML DTD.
|
||||
*/
|
||||
NS_IMETHOD IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult) const;
|
||||
|
||||
/** returns the number of things inside aNode in the out-param aCount.
|
||||
* If aNode is text, returns number of characters.
|
||||
* If not, returns number of children nodes.
|
||||
*/
|
||||
NS_IMETHOD GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount) const;
|
||||
|
||||
/** Moves the content between (aNode, aStartOffset) and (aNode, aEndOffset)
|
||||
* into aNewParentNode, splitting aNode as necessary to maintain the relative
|
||||
* position of all leaf content.
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
*/
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -125,7 +125,7 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ NS_IMETHODIMP CreateElementTxn::Undo(void)
|
|||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
PRInt32 offset=0;
|
||||
if (mRefNode) {
|
||||
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mRefNode, mParent, offset);
|
||||
}
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
|
@ -183,7 +183,7 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsresult selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
*/
|
||||
|
||||
#include "JoinElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -28,9 +28,6 @@ static PRBool gNoisy = PR_FALSE;
|
|||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
|
||||
JoinElementTxn::JoinElementTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
|
@ -84,10 +81,7 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
leftNodeAsText->GetLength(&mOffset);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor) {
|
||||
result = editor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); }
|
||||
|
@ -99,7 +93,6 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "2 nodes do not have same parent");
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
*/
|
||||
|
||||
#include "SplitElementTxn.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -28,7 +28,6 @@ static PRBool gNoisy = PR_FALSE;
|
|||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
|
||||
// note that aEditor is not refcounted
|
||||
SplitElementTxn::SplitElementTxn()
|
||||
|
@ -69,11 +68,7 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
// insert the new node
|
||||
if ((NS_SUCCEEDED(result)) && (mParent))
|
||||
{
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor)
|
||||
{
|
||||
result = editor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
if (NS_SUCCEEDED(result) && mNewLeftNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
|
@ -83,7 +78,6 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
selection->Collapse(mNewLeftNode, mOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -105,11 +99,7 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIEditorSupport> editor;
|
||||
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
|
||||
if (NS_SUCCEEDED(result) && editor)
|
||||
{
|
||||
result = editor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
result = nsEditor::JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
||||
|
@ -125,7 +115,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
selection->Collapse(mExistingRightNode, mOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsEditor.h"
|
||||
#include "nsIEditProperty.h" // to be removed XXX
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMAttr.h"
|
||||
|
@ -41,6 +42,7 @@
|
|||
#include "nsIEnumerator.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsICaret.h"
|
||||
|
||||
#include "nsIEditActionListener.h"
|
||||
|
@ -98,6 +100,7 @@ static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID);
|
|||
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
||||
static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID);
|
||||
static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIPresShellIID, NS_IPRESSHELL_IID);
|
||||
|
@ -106,7 +109,6 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID);
|
|||
static NS_DEFINE_IID(kITextEditFactoryIID, NS_ITEXTEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIHTMLEditFactoryIID, NS_IHTMLEDITORFACTORY_IID);
|
||||
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
|
||||
static NS_DEFINE_IID(kIEditorSupportIID, NS_IEDITORSUPPORT_IID);
|
||||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID);
|
||||
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
|
||||
|
@ -144,8 +146,11 @@ static NS_DEFINE_CID(kCDOMRangeCID, NS_RANGE_CID);
|
|||
#define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
|
||||
#define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
|
||||
|
||||
const char* nsEditor::kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
|
||||
const char* nsEditor::kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
#ifdef NS_DEBUG_EDITOR
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
@ -324,7 +329,7 @@ nsEditor::~nsEditor()
|
|||
|
||||
|
||||
|
||||
//BEGIN nsIEditor interface implementations
|
||||
// BEGIN nsEditor core implementation
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(nsEditor)
|
||||
|
@ -351,11 +356,6 @@ nsEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIEditorSupportIID)) {
|
||||
*aInstancePtr = (void*)(nsIEditorSupport*)this;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
|
@ -665,109 +665,6 @@ nsEditor::InsertBreak()
|
|||
|
||||
//BEGIN nsEditor Private methods
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult)
|
||||
{
|
||||
nsresult result=NS_OK;
|
||||
|
||||
if (!mDoc)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
/* If no node set, get root node */
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
|
||||
if (nsnull==aStartNode)
|
||||
{
|
||||
mDoc->GetDocumentElement(getter_AddRefs(element));
|
||||
result = element->QueryInterface(kIDOMNodeIID,getter_AddRefs(node));
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
if (!node)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
else
|
||||
node = do_QueryInterface(aStartNode);
|
||||
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = node->GetFirstChild(getter_AddRefs(childNode));
|
||||
while (childNode)
|
||||
{
|
||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||
nsAutoString tag;
|
||||
if (NS_SUCCEEDED(result) && (element))
|
||||
{
|
||||
element->GetTagName(tag);
|
||||
if (PR_TRUE==aTag.Equals(tag))
|
||||
{
|
||||
return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref
|
||||
}
|
||||
else
|
||||
{
|
||||
nsresult result = GetFirstNodeOfType(childNode, aTag, aResult);
|
||||
if (nsnull!=*aResult)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||
{
|
||||
if (!aNode || !aRetNode)
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRUint16 mType;
|
||||
PRBool mCNodes;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> answer;
|
||||
|
||||
aNode->GetNodeType(&mType);
|
||||
|
||||
if (nsIDOMNode::ELEMENT_NODE == mType) {
|
||||
if (NS_SUCCEEDED(aNode->HasChildNodes(&mCNodes)) && PR_TRUE == mCNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node1;
|
||||
nsCOMPtr<nsIDOMNode> node2;
|
||||
|
||||
if (!NS_SUCCEEDED(aNode->GetFirstChild(getter_AddRefs(node1))))
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
}
|
||||
while(!answer && node1)
|
||||
{
|
||||
GetFirstTextNode(node1, getter_AddRefs(answer));
|
||||
node1->GetNextSibling(getter_AddRefs(node2));
|
||||
node1 = node2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsIDOMNode::TEXT_NODE == mType) {
|
||||
answer = do_QueryInterface(aNode);
|
||||
}
|
||||
|
||||
// OK, now return the answer, if any
|
||||
*aRetNode = answer;
|
||||
if (*aRetNode)
|
||||
NS_IF_ADDREF(*aRetNode);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::Do(nsITransaction *aTxn)
|
||||
|
@ -1510,7 +1407,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
selectedNode = do_QueryInterface(parentSelectedNode);
|
||||
selectedNode->GetParentNode(getter_AddRefs(parentSelectedNode));
|
||||
selectedParentNodeAsText->GetLength(&selectedNodeContentCount);
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, indexOfTextNodeInParent);
|
||||
|
||||
if ((offsetOfSelectedNode!=0) && (((PRUint32)offsetOfSelectedNode)!=selectedNodeContentCount))
|
||||
{
|
||||
|
@ -1518,7 +1415,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode));
|
||||
// now get the node's offset in it's parent, and insert the new tag there
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1527,7 +1424,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
offsetOfNewNode = indexOfTextNodeInParent; // insert new node as previous sibling to selection parent
|
||||
}
|
||||
else { // insert new node as last child
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node
|
||||
}
|
||||
}
|
||||
|
@ -1560,7 +1457,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
result = SplitNode(selectedNode, offsetOfSelectedNode, getter_AddRefs(newSiblingNode));
|
||||
// now get the node's offset in it's parent, and insert the new tag there
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
result = GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1569,7 +1466,7 @@ NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNod
|
|||
offsetOfNewNode = 0; // insert new node as first child
|
||||
}
|
||||
else { // insert new node as last child
|
||||
nsIEditorSupport::GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
GetChildOffset(selectedNode, parentSelectedNode, offsetOfNewNode);
|
||||
offsetOfNewNode++; // offsets are 0-based, and we need the index of the new node
|
||||
}
|
||||
}
|
||||
|
@ -1821,108 +1718,6 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetPreviousSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetRightmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetPreviousSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
|
||||
return GetRightmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetNextSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetLeftmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetNextSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
return GetLeftmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetLastChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetFirstChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::SplitNode(nsIDOMNode * aNode,
|
||||
|
@ -2037,7 +1832,12 @@ NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
||||
// END nsEditor core implementation
|
||||
|
||||
// BEGIN nsEditor public static helper methods
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode* aNewLeftNode,
|
||||
|
@ -2113,7 +1913,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsresult
|
||||
nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
|
@ -2203,7 +2003,8 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
return result;
|
||||
}
|
||||
|
||||
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
nsresult
|
||||
nsEditor::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
{
|
||||
NS_ASSERTION((aChild && aParent), "bad args");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
|
@ -2236,8 +2037,478 @@ nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParen
|
|||
return result;
|
||||
}
|
||||
|
||||
// returns the number of things inside aNode.
|
||||
// If aNode is text, returns number of characters. If not, returns number of children nodes.
|
||||
nsresult
|
||||
nsEditor::GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount)
|
||||
{
|
||||
aCount = 0;
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result=NS_OK;
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
|
||||
nodeAsChar = do_QueryInterface(aNode);
|
||||
if (nodeAsChar) {
|
||||
nodeAsChar->GetLength(&aCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool hasChildNodes;
|
||||
aNode->HasChildNodes(&hasChildNodes);
|
||||
if (PR_TRUE==hasChildNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList>nodeList;
|
||||
result = aNode->GetChildNodes(getter_AddRefs(nodeList));
|
||||
if (NS_SUCCEEDED(result) && nodeList) {
|
||||
nodeList->GetLength(&aCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// content-based inline vs. block query
|
||||
nsresult
|
||||
nsEditor::IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline)
|
||||
{
|
||||
// this is a content-based implementation
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsresult result;
|
||||
aIsInline = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
result = element->GetTagName(tag);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIAtom *tagAtom = NS_NewAtom(tag);
|
||||
if (!tagAtom) { return NS_ERROR_NULL_POINTER; }
|
||||
if (tagAtom==nsIEditProperty::a ||
|
||||
tagAtom==nsIEditProperty::b ||
|
||||
tagAtom==nsIEditProperty::big ||
|
||||
tagAtom==nsIEditProperty::font ||
|
||||
tagAtom==nsIEditProperty::i ||
|
||||
tagAtom==nsIEditProperty::span ||
|
||||
tagAtom==nsIEditProperty::small ||
|
||||
tagAtom==nsIEditProperty::strike ||
|
||||
tagAtom==nsIEditProperty::sub ||
|
||||
tagAtom==nsIEditProperty::sup ||
|
||||
tagAtom==nsIEditProperty::tt ||
|
||||
tagAtom==nsIEditProperty::u )
|
||||
{
|
||||
aIsInline = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockParent(nsIDOMNode *aNode, nsIDOMElement **aBlockParent)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aBlockParent) {return NS_ERROR_NULL_POINTER;}
|
||||
*aBlockParent = nsnull;
|
||||
nsCOMPtr<nsIDOMNode>parent;
|
||||
nsCOMPtr<nsIDOMNode>temp;
|
||||
result = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
while (NS_SUCCEEDED(result) && parent)
|
||||
{
|
||||
PRBool isInline;
|
||||
result = IsNodeInline(parent, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
parent->QueryInterface(nsIDOMElement::GetIID(), (void**)aBlockParent);
|
||||
break;
|
||||
}
|
||||
result = parent->GetParentNode(getter_AddRefs(temp));
|
||||
parent = do_QueryInterface(temp);
|
||||
}
|
||||
if (gNoisy) { printf("GetBlockParent for %p returning parent %p\n", aNode, *aBlockParent); }
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockSection(nsIDOMNode *aChild,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (!aChild || !aLeftNode || !aRightNode) {return NS_ERROR_NULL_POINTER;}
|
||||
*aLeftNode = aChild;
|
||||
*aRightNode = aChild;
|
||||
|
||||
nsCOMPtr<nsIDOMNode>sibling;
|
||||
result = aChild->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
// XXX: needs some logic to work for other leaf nodes besides text!
|
||||
}
|
||||
*aLeftNode = sibling;
|
||||
result = (*aLeftNode)->GetPreviousSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aLeftNode));
|
||||
// now do the right side
|
||||
result = aChild->GetNextSibling(getter_AddRefs(sibling));
|
||||
while ((NS_SUCCEEDED(result)) && sibling)
|
||||
{
|
||||
PRBool isInline;
|
||||
IsNodeInline(sibling, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(sibling);
|
||||
if (!nodeAsText) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*aRightNode = sibling;
|
||||
result = (*aRightNode)->GetNextSibling(getter_AddRefs(sibling));
|
||||
}
|
||||
NS_ADDREF((*aRightNode));
|
||||
if (gNoisy) { printf("GetBlockSection returning %p %p\n",
|
||||
(*aLeftNode), (*aRightNode)); }
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetBlockSectionsForRange(nsIDOMRange *aRange, nsISupportsArray *aSections)
|
||||
{
|
||||
if (!aRange || !aSections) {return NS_ERROR_NULL_POINTER;}
|
||||
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> lastRange;
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> currentContent;
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode = do_QueryInterface(currentContent);
|
||||
if (currentNode)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> currentContentTag;
|
||||
currentContent->GetTag(*getter_AddRefs(currentContentTag));
|
||||
// <BR> divides block content ranges. We can achieve this by nulling out lastRange
|
||||
if (nsIEditProperty::br==currentContentTag)
|
||||
{
|
||||
lastRange = do_QueryInterface(nsnull);
|
||||
}
|
||||
else
|
||||
{
|
||||
PRBool isInlineOrText;
|
||||
result = IsNodeInline(currentNode, isInlineOrText);
|
||||
if (PR_FALSE==isInlineOrText)
|
||||
{
|
||||
PRUint16 nodeType;
|
||||
currentNode->GetNodeType(&nodeType);
|
||||
if (nsIDOMNode::TEXT_NODE == nodeType) {
|
||||
isInlineOrText = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==isInlineOrText)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>leftNode;
|
||||
nsCOMPtr<nsIDOMNode>rightNode;
|
||||
result = GetBlockSection(currentNode,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if (gNoisy) {printf("currentNode %p has block content (%p,%p)\n", currentNode.get(), leftNode.get(), rightNode.get());}
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode)
|
||||
{
|
||||
// add range to the list if it doesn't overlap with the previous range
|
||||
PRBool addRange=PR_TRUE;
|
||||
if (lastRange)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> lastStartNode;
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLastStartNode;
|
||||
lastRange->GetStartParent(getter_AddRefs(lastStartNode));
|
||||
result = GetBlockParent(lastStartNode, getter_AddRefs(blockParentOfLastStartNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLastStartNode)
|
||||
{
|
||||
if (gNoisy) {printf("lastStartNode %p has block parent %p\n", lastStartNode.get(), blockParentOfLastStartNode.get());}
|
||||
nsCOMPtr<nsIDOMElement> blockParentOfLeftNode;
|
||||
result = GetBlockParent(leftNode, getter_AddRefs(blockParentOfLeftNode));
|
||||
if ((NS_SUCCEEDED(result)) && blockParentOfLeftNode)
|
||||
{
|
||||
if (gNoisy) {printf("leftNode %p has block parent %p\n", leftNode.get(), blockParentOfLeftNode.get());}
|
||||
if (blockParentOfLastStartNode==blockParentOfLeftNode) {
|
||||
addRange = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PR_TRUE==addRange)
|
||||
{
|
||||
if (gNoisy) {printf("adding range, setting lastRange with start node %p\n", leftNode.get());}
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
result = nsComponentManager::CreateInstance(kCRangeCID, nsnull,
|
||||
kIDOMRangeIID, getter_AddRefs(range));
|
||||
if ((NS_SUCCEEDED(result)) && range)
|
||||
{ // initialize the range
|
||||
range->SetStart(leftNode, 0);
|
||||
range->SetEnd(rightNode, 0);
|
||||
aSections->AppendElement(range);
|
||||
lastRange = do_QueryInterface(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(currentContent));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult)
|
||||
{
|
||||
aResult = PR_TRUE; // init out param. we assume the condition is true unless we find a node that violates it
|
||||
if (!aStartNode || !aEndNode || !aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsCOMPtr<nsIContentIterator>iter;
|
||||
nsresult result;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
kIContentIteratorIID, getter_AddRefs(iter));
|
||||
//XXX: maybe CreateInstance is expensive, and I should keep around a static iter?
|
||||
// as long as this method can't be called recursively or re-entrantly!
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && iter)
|
||||
{
|
||||
nsCOMPtr<nsIContent>startContent;
|
||||
startContent = do_QueryInterface(aStartNode);
|
||||
nsCOMPtr<nsIContent>endContent;
|
||||
endContent = do_QueryInterface(aEndNode);
|
||||
if (startContent && endContent)
|
||||
{
|
||||
iter->Init(aRange);
|
||||
nsCOMPtr<nsIContent> content;
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
while (NS_COMFALSE == iter->IsDone())
|
||||
{
|
||||
if ((content.get() != startContent.get()) &&
|
||||
(content.get() != endContent.get()))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>currentNode;
|
||||
currentNode = do_QueryInterface(content);
|
||||
PRBool isInline=PR_FALSE;
|
||||
IsNodeInline(currentNode, isInline);
|
||||
if (PR_FALSE==isInline)
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
nodeAsText = do_QueryInterface(currentNode);
|
||||
if (!nodeAsText) // text nodes don't count in this check, so ignore them
|
||||
{
|
||||
aResult = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* do not check result here, and especially do not return the result code.
|
||||
* we rely on iter->IsDone to tell us when the iteration is complete
|
||||
*/
|
||||
iter->Next();
|
||||
iter->CurrentNode(getter_AddRefs(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a left sibling, return that sibling's rightmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetPreviousSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetRightmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetPreviousSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
|
||||
return GetRightmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result;
|
||||
*aResultNode = nsnull;
|
||||
// if aCurrentNode has a right sibling, return that sibling's leftmost child (or itself if it has no children)
|
||||
result = aCurrentNode->GetNextSibling(aResultNode);
|
||||
if ((NS_SUCCEEDED(result)) && *aResultNode)
|
||||
return GetLeftmostChild(*aResultNode, aResultNode);
|
||||
|
||||
// otherwise, walk up the parent change until there is a child that comes before
|
||||
// the ancestor of aCurrentNode. Then return that node's rightmost child
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent(do_QueryInterface(aCurrentNode));
|
||||
do {
|
||||
nsCOMPtr<nsIDOMNode> node(parent);
|
||||
result = node->GetParentNode(getter_AddRefs(parent));
|
||||
if ((NS_SUCCEEDED(result)) && parent)
|
||||
{
|
||||
result = parent->GetNextSibling(getter_AddRefs(node));
|
||||
if ((NS_SUCCEEDED(result)) && node)
|
||||
{
|
||||
return GetLeftmostChild(node, aResultNode);
|
||||
}
|
||||
}
|
||||
} while ((NS_SUCCEEDED(result)) && parent);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetLastChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> resultNode(do_QueryInterface(aCurrentNode));
|
||||
PRBool hasChildren;
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
while ((NS_SUCCEEDED(result)) && (PR_TRUE==hasChildren))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> temp(resultNode);
|
||||
temp->GetFirstChild(getter_AddRefs(resultNode));
|
||||
resultNode->HasChildNodes(&hasChildren);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
*aResultNode = resultNode;
|
||||
NS_ADDREF(*aResultNode);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
element->GetTagName(tag);
|
||||
if (tag.Equals(aTag->GetUnicode()))
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>text;
|
||||
text = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
PRUint32 length = data.Length();
|
||||
if (0==length) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
// if the node contains only newlines, it's not editable
|
||||
PRUint32 i;
|
||||
for (i=0; i<length; i++)
|
||||
{
|
||||
if ('\n'!=data.CharAt(0)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
//END nsEditor static utility methods
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
void nsEditor::HACKForceRedraw()
|
||||
{
|
||||
|
@ -2398,42 +2669,96 @@ nsEditor::DebugDumpContent() const
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
/* ----- TEST METHODS ----- */
|
||||
// Methods defined here are TEMPORARY
|
||||
|
||||
/* ORIGINAL version by Steve - KEEP FOR REFERENCE
|
||||
NS_IMETHODIMP GetColIndexForCell(nsIPresShell *aPresShell, nsIDOMNode *aCellNode, PRInt32 &aCellIndex)
|
||||
nsresult
|
||||
nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode,
|
||||
const nsString &aTag,
|
||||
nsIDOMNode **aResult)
|
||||
{
|
||||
aCellIndex=0; // initialize out param
|
||||
nsresult result = NS_ERROR_FAILURE; // we return an error unless we get the index
|
||||
if ((nsnull!=aCellNode) && (nsnull!=aPresShell))
|
||||
{ // get the content interface
|
||||
nsCOMPtr<nsIContent> nodeAsContent(aCellNode);
|
||||
if (nodeAsContent)
|
||||
{ // get the frame from the content interface
|
||||
nsISupports *layoutObject=nsnull; // frames are not ref counted, so don't use an nsCOMPtr
|
||||
result = aPresShell->GetLayoutObjectFor(nodeAsContent, &layoutObject);
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=layoutObject))
|
||||
{ // get the table cell interface from the frame
|
||||
nsITableCellLayout *cellLayoutObject=nsnull; // again, frames are not ref-counted
|
||||
result = layoutObject->QueryInterface(nsITableCellLayout::GetIID(), (void**)(&cellLayoutObject));
|
||||
if ((NS_SUCCEEDED(result)) && (nsnull!=cellLayoutObject))
|
||||
{ // get the index
|
||||
result = cellLayoutObject->GetColIndex(aCellIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
*/
|
||||
nsresult result=NS_OK;
|
||||
|
||||
/* ----- END TEST METHODS ----- */
|
||||
if (!aStartNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
*aResult = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = aStartNode->GetFirstChild(getter_AddRefs(childNode));
|
||||
while (childNode)
|
||||
{
|
||||
result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element));
|
||||
nsAutoString tag;
|
||||
if (NS_SUCCEEDED(result) && (element))
|
||||
{
|
||||
element->GetTagName(tag);
|
||||
if (PR_TRUE==aTag.Equals(tag))
|
||||
{
|
||||
return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref
|
||||
}
|
||||
else
|
||||
{
|
||||
nsresult result = GetFirstNodeOfType(childNode, aTag, aResult);
|
||||
if (nsnull!=*aResult)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> temp = childNode;
|
||||
temp->GetNextSibling(getter_AddRefs(childNode));
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode)
|
||||
{
|
||||
if (!aNode || !aRetNode)
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
PRUint16 mType;
|
||||
PRBool mCNodes;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> answer;
|
||||
|
||||
aNode->GetNodeType(&mType);
|
||||
|
||||
if (nsIDOMNode::ELEMENT_NODE == mType) {
|
||||
if (NS_SUCCEEDED(aNode->HasChildNodes(&mCNodes)) && PR_TRUE == mCNodes)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node1;
|
||||
nsCOMPtr<nsIDOMNode> node2;
|
||||
|
||||
if (!NS_SUCCEEDED(aNode->GetFirstChild(getter_AddRefs(node1))))
|
||||
{
|
||||
NS_NOTREACHED("GetFirstTextNode Failed");
|
||||
}
|
||||
while(!answer && node1)
|
||||
{
|
||||
GetFirstTextNode(node1, getter_AddRefs(answer));
|
||||
node1->GetNextSibling(getter_AddRefs(node2));
|
||||
node1 = node2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsIDOMNode::TEXT_NODE == mType) {
|
||||
answer = do_QueryInterface(aNode);
|
||||
}
|
||||
|
||||
// OK, now return the answer, if any
|
||||
*aRetNode = answer;
|
||||
if (*aRetNode)
|
||||
NS_IF_ADDREF(*aRetNode);
|
||||
else
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
NS_IMETHODIMP nsEditor::DoInitialPreeeditInsert(const nsString& aStringToInsert)
|
||||
{
|
||||
|
@ -2601,3 +2926,4 @@ nsEditor::SetPreeditText(const nsString& aStringToInsert)
|
|||
EndTransaction();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "prmon.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsIContextLoader.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
@ -46,6 +45,7 @@ class SplitElementTxn;
|
|||
class JoinElementTxn;
|
||||
class EditAggregateTxn;
|
||||
class nsVoidArray;
|
||||
class nsISupportsArray;
|
||||
|
||||
//This is the monitor for the editor.
|
||||
PRMonitor *getEditorMonitor();
|
||||
|
@ -56,7 +56,7 @@ PRMonitor *getEditorMonitor();
|
|||
* manager, event interfaces. the idea for the event interfaces is to have them
|
||||
* delegate the actual commands to the editor independent of the XPFE implementation.
|
||||
*/
|
||||
class nsEditor : public nsIEditor, public nsIEditorSupport
|
||||
class nsEditor : public nsIEditor
|
||||
{
|
||||
private:
|
||||
nsIPresShell *mPresShell;
|
||||
|
@ -75,6 +75,10 @@ protected:
|
|||
nsIDOMDocument * mDoc;
|
||||
|
||||
public:
|
||||
|
||||
const static char* nsEditor::kMOZEditorBogusNodeAttr;
|
||||
const static char* nsEditor::kMOZEditorBogusNodeValue;
|
||||
|
||||
/** The default constructor. This should suffice. the setting of the interfaces is done
|
||||
* after the construction of the editor class.
|
||||
*/
|
||||
|
@ -186,32 +190,6 @@ public:
|
|||
/*END nsIEditor interfaces*/
|
||||
|
||||
|
||||
/*BEGIN public methods unique to nsEditor. These will get moved to an interface
|
||||
if they survive.
|
||||
*/
|
||||
|
||||
/** GetFirstTextNode ADDREFFS and will get the next available text node from the passed
|
||||
* in node parameter it can also return NS_ERROR_FAILURE if no text nodes are available
|
||||
* now it simply returns the first node in the dom
|
||||
* @param nsIDOMNode *aNode is the node to start looking from
|
||||
* @param nsIDOMNode **aRetNode is the return location of the text dom node
|
||||
*
|
||||
* NOTE: this method will probably be removed.
|
||||
*/
|
||||
NS_IMETHOD GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode);
|
||||
|
||||
/** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed
|
||||
* in aStartNode parameter of type aTag.
|
||||
* It can also return NS_ERROR_FAILURE if no such nodes are available
|
||||
* @param nsIDOMNode *aStartNode is the node to start looking from
|
||||
* @param nsIAtom *aTag is the type of node we are searching for
|
||||
* @param nsIDOMNode **aResult is the node we found, or nsnull if there is none
|
||||
*/
|
||||
NS_IMETHOD GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult);
|
||||
|
||||
/*END public methods of nsEditor*/
|
||||
|
||||
|
||||
/*BEGIN private methods used by the implementations of the above functions*/
|
||||
protected:
|
||||
/** create a transaction for setting aAttribute to aValue on aElement
|
||||
|
@ -278,28 +256,10 @@ protected:
|
|||
PRUint32 aOffset,
|
||||
SplitElementTxn **aTxn);
|
||||
|
||||
NS_IMETHOD SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode * aNewLeftNode,
|
||||
nsIDOMNode * aParent);
|
||||
|
||||
NS_IMETHOD CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode,
|
||||
JoinElementTxn **aTxn);
|
||||
|
||||
NS_IMETHOD JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
nsIDOMNode * aNodeToJoin,
|
||||
nsIDOMNode * aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
NS_IMETHOD GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
NS_IMETHOD GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/** Create an aggregate transaction for deleting current selection
|
||||
* Used by all methods that need to delete current selection,
|
||||
* then insert something new to replace it
|
||||
|
@ -321,11 +281,152 @@ protected:
|
|||
// of an error in Gecko which is not rendering the
|
||||
// document after a change via the DOM - gpk 2/13/99
|
||||
void HACKForceRedraw(void);
|
||||
|
||||
PRBool mIMEFirstTransaction;
|
||||
|
||||
|
||||
NS_IMETHOD DeleteSelectionAndPrepareToCreateNode(nsCOMPtr<nsIDOMNode> &parentSelectedNode, PRInt32& offsetOfNewNode);
|
||||
|
||||
public:
|
||||
/**
|
||||
* SplitNode() creates a new node identical to an existing node, and split the contents between the two nodes
|
||||
* @param aExistingRightNode the node to split. It will become the new node's next sibling.
|
||||
* @param aOffset the offset of aExistingRightNode's content|children to do the split at
|
||||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
* @param aParent the parent of aExistingRightNode
|
||||
*/
|
||||
static nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
* @param aNodeToKeep The node that will remain after the join.
|
||||
* @param aNodeToJoin The node that will be joined with aNodeToKeep.
|
||||
* There is no requirement that the two nodes be of the same type.
|
||||
* @param aParent The parent of aExistingRightNode
|
||||
* @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the
|
||||
* contents|children of aNodeToJoin, otherwise their positions are switched.
|
||||
*/
|
||||
static nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
/**
|
||||
* Set aOffset to the offset of aChild in aParent.
|
||||
* Returns an error if aChild is not an immediate child of aParent.
|
||||
*/
|
||||
static nsresult GetChildOffset(nsIDOMNode *aChild,
|
||||
nsIDOMNode *aParent,
|
||||
PRInt32 &aOffset);
|
||||
|
||||
/** set aIsInline to PR_TRUE if aNode is inline as defined by HTML DTD */
|
||||
static nsresult IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline);
|
||||
|
||||
/** returns the closest block parent of aNode, not including aNode itself.
|
||||
* can return null, for example if aNode is in a document fragment.
|
||||
* @param aNode The node whose parent we seek.
|
||||
* @param aBlockParent [OUT] The block parent, if any.
|
||||
* @return a success value unless an unexpected error occurs.
|
||||
*/
|
||||
static nsresult GetBlockParent(nsIDOMNode *aNode,
|
||||
nsIDOMElement **aBlockParent);
|
||||
|
||||
/** Determines the bounding nodes for the block section containing aNode.
|
||||
* The calculation is based on some nodes intrinsically being block elements
|
||||
* acording to HTML. Style sheets are not considered in this calculation.
|
||||
* <BR> tags separate block content sections. So the HTML markup:
|
||||
* <PRE>
|
||||
* <P>text1<BR>text2<B>text3</B></P>
|
||||
* </PRE>
|
||||
* contains two block content sections. The first has the text node "text1"
|
||||
* for both endpoints. The second has "text2" as the left endpoint and
|
||||
* "text3" as the right endpoint.
|
||||
* Notice that offsets aren't required, only leaf nodes. Offsets are implicit.
|
||||
*
|
||||
* @param aNode the block content returned includes aNode
|
||||
* @param aLeftNode [OUT] the left endpoint of the block content containing aNode
|
||||
* @param aRightNode [OUT] the right endpoint of the block content containing aNode
|
||||
*
|
||||
*/
|
||||
static nsresult GetBlockSection(nsIDOMNode *aNode,
|
||||
nsIDOMNode **aLeftNode,
|
||||
nsIDOMNode **aRightNode);
|
||||
|
||||
/** Compute the set of block sections in a given range.
|
||||
* A block section is the set of (leftNode, rightNode) pairs given
|
||||
* by GetBlockSection. The set is computed by computing the
|
||||
* block section for every leaf node in the range and throwing
|
||||
* out duplicates.
|
||||
*
|
||||
* @param aRange The range to compute block sections for.
|
||||
* @param aSections Allocated storage for the resulting set, stored as nsIDOMRanges.
|
||||
*/
|
||||
static nsresult GetBlockSectionsForRange(nsIDOMRange *aRange,
|
||||
nsISupportsArray *aSections);
|
||||
|
||||
/** returns PR_TRUE in out-param aResult if all nodes between (aStartNode, aStartOffset)
|
||||
* and (aEndNode, aEndOffset) are inline as defined by HTML DTD.
|
||||
*/
|
||||
static nsresult IntermediateNodesAreInline(nsIDOMRange *aRange,
|
||||
nsIDOMNode *aStartNode,
|
||||
PRInt32 aStartOffset,
|
||||
nsIDOMNode *aEndNode,
|
||||
PRInt32 aEndOffset,
|
||||
PRBool &aResult);
|
||||
|
||||
/** returns the number of things inside aNode in the out-param aCount.
|
||||
* @param aNode is the node to get the length of.
|
||||
* If aNode is text, returns number of characters.
|
||||
* If not, returns number of children nodes.
|
||||
* @param aCount [OUT] the result of the above calculation.
|
||||
*/
|
||||
static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetPriorNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetNextNode(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetRightmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/**
|
||||
*/
|
||||
static nsresult GetLeftmostChild(nsIDOMNode *aCurrentNode, nsIDOMNode **aResultNode);
|
||||
|
||||
/** GetFirstTextNode ADDREFFS and will get the next available text node from the passed
|
||||
* in node parameter it can also return NS_ERROR_FAILURE if no text nodes are available
|
||||
* now it simply returns the first node in the dom
|
||||
* @param nsIDOMNode *aNode is the node to start looking from
|
||||
* @param nsIDOMNode **aRetNode is the return location of the text dom node
|
||||
*
|
||||
* NOTE: this method will probably be removed.
|
||||
*/
|
||||
static nsresult GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode);
|
||||
|
||||
/** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed
|
||||
* in aStartNode parameter of type aTag.
|
||||
* It can also return NS_ERROR_FAILURE if no such nodes are available
|
||||
* @param aStartNode is the node to start looking from
|
||||
* @param aTag is the type of node we are searching for
|
||||
* @param aResult is the node we found, or nsnull if there is none
|
||||
*/
|
||||
static nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode,
|
||||
const nsString &aTag,
|
||||
nsIDOMNode **aResult);
|
||||
|
||||
/** returns PR_TRUE if aNode is of the type implied by aTag */
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
|
||||
/** returns PR_TRUE if aNode is an editable node */
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@ SUP places text in superscript style
|
|||
|
||||
// block tags
|
||||
static nsIAtom *blockquote;
|
||||
static nsIAtom *br;
|
||||
static nsIAtom *h1;
|
||||
static nsIAtom *h2;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ nsIAtom * nsIEditProperty::tt;
|
|||
nsIAtom * nsIEditProperty::u;
|
||||
// block tags
|
||||
nsIAtom * nsIEditProperty::blockquote;
|
||||
nsIAtom * nsIEditProperty::br;
|
||||
nsIAtom * nsIEditProperty::h1;
|
||||
nsIAtom * nsIEditProperty::h2;
|
||||
// properties
|
||||
|
@ -56,28 +57,29 @@ void
|
|||
nsEditProperty::InstanceInit()
|
||||
{
|
||||
// tags
|
||||
nsIEditProperty::a = NS_NewAtom("A");
|
||||
nsIEditProperty::b = NS_NewAtom("B");
|
||||
nsIEditProperty::big = NS_NewAtom("BIG");
|
||||
nsIEditProperty::font = NS_NewAtom("FONT");
|
||||
nsIEditProperty::i = NS_NewAtom("I");
|
||||
nsIEditProperty::span = NS_NewAtom("SPAN");
|
||||
nsIEditProperty::small =NS_NewAtom("SMALL");
|
||||
nsIEditProperty::strike=NS_NewAtom("STRIKE");
|
||||
nsIEditProperty::sub = NS_NewAtom("SUB");
|
||||
nsIEditProperty::sup = NS_NewAtom("SUP");
|
||||
nsIEditProperty::tt = NS_NewAtom("TT");
|
||||
nsIEditProperty::u = NS_NewAtom("U");
|
||||
nsIEditProperty::a = NS_NewAtom("a");
|
||||
nsIEditProperty::b = NS_NewAtom("b");
|
||||
nsIEditProperty::big = NS_NewAtom("big");
|
||||
nsIEditProperty::font = NS_NewAtom("font");
|
||||
nsIEditProperty::i = NS_NewAtom("i");
|
||||
nsIEditProperty::span = NS_NewAtom("span");
|
||||
nsIEditProperty::small =NS_NewAtom("small");
|
||||
nsIEditProperty::strike=NS_NewAtom("strike");
|
||||
nsIEditProperty::sub = NS_NewAtom("sub");
|
||||
nsIEditProperty::sup = NS_NewAtom("sup");
|
||||
nsIEditProperty::tt = NS_NewAtom("tt");
|
||||
nsIEditProperty::u = NS_NewAtom("u");
|
||||
// tags
|
||||
nsIEditProperty::blockquote = NS_NewAtom("BLOCKQUOTE");
|
||||
nsIEditProperty::h1 = NS_NewAtom("H1");
|
||||
nsIEditProperty::h2 = NS_NewAtom("H2");
|
||||
nsIEditProperty::blockquote = NS_NewAtom("blockquote");
|
||||
nsIEditProperty::br = NS_NewAtom("br");
|
||||
nsIEditProperty::h1 = NS_NewAtom("h1");
|
||||
nsIEditProperty::h2 = NS_NewAtom("h2");
|
||||
// properties
|
||||
nsIEditProperty::color= NS_NewAtom("COLOR");
|
||||
nsIEditProperty::face = NS_NewAtom("FACE");
|
||||
nsIEditProperty::size = NS_NewAtom("SIZE");
|
||||
nsIEditProperty::color= NS_NewAtom("color");
|
||||
nsIEditProperty::face = NS_NewAtom("face");
|
||||
nsIEditProperty::size = NS_NewAtom("size");
|
||||
// special
|
||||
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
|
||||
nsIEditProperty::allProperties = new nsString("moz_allproperties");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -98,6 +100,7 @@ nsEditProperty::InstanceShutdown()
|
|||
NS_IF_RELEASE(nsIEditProperty::u);
|
||||
// tags
|
||||
NS_IF_RELEASE(nsIEditProperty::blockquote);
|
||||
NS_IF_RELEASE(nsIEditProperty::br);
|
||||
NS_IF_RELEASE(nsIEditProperty::h1);
|
||||
NS_IF_RELEASE(nsIEditProperty::h2);
|
||||
// properties
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsITableCellLayout.h" //For GetColIndexForCell
|
||||
|
||||
|
||||
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
|
||||
|
@ -59,7 +58,7 @@ static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
|||
static NS_DEFINE_IID(kIContentIteratorIID, NS_ICONTENTITERTOR_IID);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
@ -205,7 +204,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
|||
if (-1==offsetInParent)
|
||||
{
|
||||
nextNode->GetParentNode(getter_AddRefs(parent));
|
||||
result = nsIEditorSupport::GetChildOffset(nextNode, parent, offsetInParent);
|
||||
result = GetChildOffset(nextNode, parent, offsetInParent);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
||||
}
|
||||
|
@ -395,17 +394,17 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and get the block parent of each
|
||||
nsISupportsArray *subRanges;
|
||||
result = NS_NewISupportsArray(&subRanges);
|
||||
if ((NS_SUCCEEDED(result)) && subRanges)
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockRanges(range, subRanges);
|
||||
result = GetBlockSectionsForRange(range, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
|
@ -418,17 +417,19 @@ nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
|||
{
|
||||
nsAutoString blockParentTag;
|
||||
blockParent->GetTagName(blockParentTag);
|
||||
if (-1==aTagList->IndexOf(blockParentTag)) {
|
||||
PRBool isRoot;
|
||||
IsRootTag(blockParentTag, isRoot);
|
||||
if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) {
|
||||
aTagList->AppendString(blockParentTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRange);
|
||||
subRanges->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRanges);
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -465,7 +466,7 @@ nsHTMLEditor::AddBlockParent(nsString& aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and apply the transformation to them
|
||||
result = ReParentContentOfRange(range, aParentTag, eInsertParent);
|
||||
}
|
||||
|
@ -510,47 +511,30 @@ nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
// scan the range for all the independent block content subranges
|
||||
// scan the range for all the independent block content blockSections
|
||||
// and apply the transformation to them
|
||||
result = ReParentContentOfRange(range, aParentTag, eReplaceParent);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // set the selection
|
||||
// XXX: can't do anything until I can create ranges
|
||||
}
|
||||
}
|
||||
if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IsRootTag(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString bodyTag = "body";
|
||||
static nsAutoString tdTag = "td";
|
||||
static nsAutoString thTag = "th";
|
||||
static nsAutoString captionTag = "caption";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(bodyTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(tdTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(thTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(captionTag) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
||||
nsString &aParentTag,
|
||||
BlockTransformationType aTransformation)
|
||||
{
|
||||
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
||||
if (gNoisy)
|
||||
{
|
||||
char *tag = aParentTag.ToNewCString();
|
||||
printf("---------- ReParentContentOfNode(%p,%s,%d) -----------\n", aNode, tag, aTransformation);
|
||||
delete [] tag;
|
||||
}
|
||||
// find the current block parent, or just use aNode if it is a block node
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement;
|
||||
nsCOMPtr<nsIDOMNode>nodeToReParent; // this is the node we'll operate on, by default it's aNode
|
||||
|
@ -606,7 +590,7 @@ nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
|||
{ // this is the case of an insertion point between 2 non-text objects
|
||||
// XXX: how to you know it's an insertion point???
|
||||
PRInt32 offsetInParent=0;
|
||||
result = nsIEditorSupport::GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
||||
result = GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
// otherwise, just create the block parent at the selection
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent,
|
||||
|
@ -654,10 +638,14 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
nsString &aParentTag,
|
||||
nsIDOMNode *aBlockParentNode,
|
||||
nsString &aBlockParentTag,
|
||||
BlockTransformationType aTranformation,
|
||||
BlockTransformationType aTransformation,
|
||||
nsIDOMNode **aNewParentNode)
|
||||
{
|
||||
if (!aNode || !aBlockParentNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; }
|
||||
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(aBlockParentNode);
|
||||
PRBool removeBlockParent = PR_FALSE;
|
||||
PRBool removeBreakBefore = PR_FALSE;
|
||||
PRBool removeBreakAfter = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMNode>ancestor;
|
||||
nsresult result = aNode->GetParentNode(getter_AddRefs(ancestor));
|
||||
nsCOMPtr<nsIDOMNode>previousAncestor = do_QueryInterface(aNode);
|
||||
|
@ -675,46 +663,87 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
}
|
||||
// now, previousAncestor is the node we are operating on
|
||||
nsCOMPtr<nsIDOMNode>leftNode, rightNode;
|
||||
result = GetBlockDelimitedContent(previousAncestor,
|
||||
result = GetBlockSection(previousAncestor,
|
||||
getter_AddRefs(leftNode),
|
||||
getter_AddRefs(rightNode));
|
||||
if ((NS_SUCCEEDED(result)) && leftNode && rightNode)
|
||||
{
|
||||
PRInt32 offsetInParent=0;
|
||||
if (eInsertParent==aTranformation)
|
||||
// determine some state for managing <BR>s around the new block
|
||||
PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block
|
||||
PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement = do_QueryInterface(blockParentNode);
|
||||
if (blockParentElement)
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(leftNode, aBlockParentNode, offsetInParent);
|
||||
nsAutoString blockParentTag;
|
||||
blockParentElement->GetTagName(blockParentTag);
|
||||
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
||||
IsRootTag(blockParentTag, isRootBlock);
|
||||
}
|
||||
|
||||
if (PR_TRUE==isRootBlock)
|
||||
{ // we're creating a block element where a block element did not previously exist
|
||||
removeBreakBefore = PR_TRUE;
|
||||
removeBreakAfter = PR_TRUE;
|
||||
}
|
||||
|
||||
// apply the transformation
|
||||
PRInt32 offsetInParent=0;
|
||||
if (eInsertParent==aTransformation || PR_TRUE==isRootBlock)
|
||||
{
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, aBlockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in aBlockParentNode at offset %d\n", offsetInParent); }
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> grandParent;
|
||||
result = aBlockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
result = blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
if ((NS_SUCCEEDED(result)) && grandParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>firstChildNode, lastChildNode;
|
||||
aBlockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
||||
aBlockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
||||
blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
||||
blockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
||||
if (firstChildNode==leftNode && lastChildNode==rightNode)
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(aBlockParentNode, grandParent, offsetInParent);
|
||||
result = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); }
|
||||
}
|
||||
else
|
||||
{
|
||||
result = nsIEditorSupport::GetChildOffset(leftNode, aBlockParentNode, offsetInParent);
|
||||
// We're in the case where the content of blockParentNode is separated by <BR>'s,
|
||||
// creating multiple block content ranges.
|
||||
// Split blockParentNode around the blockContent
|
||||
if (gNoisy) { printf("splitting a node because of <BR>s\n"); }
|
||||
nsCOMPtr<nsIDOMNode> newLeftNode;
|
||||
if (firstChildNode!=leftNode)
|
||||
{
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
if (gNoisy) { printf("splitting left at %d\n", offsetInParent); }
|
||||
result = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
||||
// after this split, blockParentNode still contains leftNode and rightNode
|
||||
}
|
||||
if (lastChildNode!=rightNode)
|
||||
{
|
||||
result = GetChildOffset(rightNode, blockParentNode, offsetInParent);
|
||||
offsetInParent++;
|
||||
if (gNoisy) { printf("splitting right at %d\n", offsetInParent); }
|
||||
result = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
||||
blockParentNode = do_QueryInterface(newLeftNode);
|
||||
}
|
||||
result = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "bad result from GetChildOffset");
|
||||
result = nsTextEditor::CreateNode(aParentTag, aBlockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in aBlockParentNode at offset %d\n", offsetInParent); }
|
||||
result = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
||||
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
||||
// what we need to do here is remove the existing block parent when we're all done.
|
||||
removeBlockParent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((NS_SUCCEEDED(result)) && *aNewParentNode)
|
||||
{ // move all the children/contents of aBlockParentNode to aNewParentNode
|
||||
{ // move all the children/contents of blockParentNode to aNewParentNode
|
||||
nsCOMPtr<nsIDOMNode>childNode = do_QueryInterface(rightNode);
|
||||
nsCOMPtr<nsIDOMNode>previousSiblingNode;
|
||||
while (NS_SUCCEEDED(result) && childNode)
|
||||
|
@ -737,6 +766,73 @@ nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|||
childNode = do_QueryInterface(previousSiblingNode);
|
||||
} // end while loop
|
||||
}
|
||||
// clean up the surrounding content to maintain vertical whitespace
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// if the prior node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
result = GetPriorNode(leftNode, getter_AddRefs(brNode));
|
||||
if (NS_SUCCEEDED(result) && brNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
||||
if (brContent)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> brContentTag;
|
||||
brContent->GetTag(*getter_AddRefs(brContentTag));
|
||||
if (nsIEditProperty::br==brContentTag) {
|
||||
result = DeleteNode(brNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the next node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
result = GetNextNode(rightNode, getter_AddRefs(brNode));
|
||||
if (NS_SUCCEEDED(result) && brNode)
|
||||
{
|
||||
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
||||
if (brContent)
|
||||
{
|
||||
nsCOMPtr<nsIAtom> brContentTag;
|
||||
brContent->GetTag(*getter_AddRefs(brContentTag));
|
||||
if (nsIEditProperty::br==brContentTag) {
|
||||
result = DeleteNode(brNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((NS_SUCCEEDED(result)) && (PR_TRUE==removeBlockParent))
|
||||
{ // we determined we need to remove the previous block parent. Do it!
|
||||
// go through list backwards so deletes don't interfere with the iteration
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = blockParentNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
for ( ; ((NS_SUCCEEDED(result)) && (0<=i)); i--)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
result = nsTextEditor::DeleteNode(childNode);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); }
|
||||
result = nsTextEditor::DeleteNode(blockParentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -748,29 +844,30 @@ nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange,
|
|||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *subRanges;
|
||||
result = NS_NewISupportsArray(&subRanges);
|
||||
if ((NS_SUCCEEDED(result)) && subRanges)
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockRanges(aRange, subRanges);
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
result = subRange->GetStartParent(getter_AddRefs(startParent));
|
||||
if (NS_SUCCEEDED(result) && startParent)
|
||||
{
|
||||
if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); }
|
||||
result = ReParentContentOfNode(startParent, aParentTag, aTranformation);
|
||||
}
|
||||
NS_RELEASE(subRange);
|
||||
subRanges->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(subRanges->ElementAt(0));
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(subRanges);
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -793,10 +890,10 @@ nsHTMLEditor::CanContainBlock(nsString &aBlockChild, nsString &aBlockParent, PRB
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveBlockParent()
|
||||
nsHTMLEditor::RemoveParagraphStyle()
|
||||
{
|
||||
if (gNoisy) {
|
||||
printf("---------- nsHTMLEditor::RemoveBlockParent ----------\n");
|
||||
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
||||
}
|
||||
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -815,28 +912,57 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIDOMNode>commonParent;
|
||||
result = range->GetCommonParent(getter_AddRefs(commonParent));
|
||||
if ((NS_SUCCEEDED(result)) && commonParent)
|
||||
result = RemoveParagraphStyleFromRange(range);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
|
||||
range->GetStartParent(getter_AddRefs(startParent));
|
||||
range->GetEndParent(getter_AddRefs(endParent));
|
||||
if (startParent.get()==endParent.get())
|
||||
{ // the range is entirely contained within a single node
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = RemoveParagraphStyleFromBlockContent(subRange);
|
||||
NS_RELEASE(subRange);
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
aRange->GetStartParent(getter_AddRefs(startParent));
|
||||
nsCOMPtr<nsIDOMElement>blockParentElement;
|
||||
result = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
||||
while ((NS_SUCCEEDED(result)) && blockParentElement)
|
||||
{
|
||||
nsAutoString childTag; // leave as empty string
|
||||
nsAutoString blockParentTag;
|
||||
blockParentElement->GetTagName(blockParentTag);
|
||||
PRBool canContain;
|
||||
CanContainBlock(childTag, blockParentTag, canContain);
|
||||
if (PR_TRUE==canContain) {
|
||||
PRBool isSubordinateBlock;
|
||||
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
||||
if (PR_FALSE==isSubordinateBlock) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -849,7 +975,7 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
blockParentElement->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
||||
result = GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
|
@ -872,20 +998,15 @@ nsHTMLEditor::RemoveBlockParent()
|
|||
}
|
||||
result = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
||||
{
|
||||
if (gNoisy) {
|
||||
printf("---------- nsHTMLEditor::RemoveParent %s----------\n", aParentTag);
|
||||
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
||||
}
|
||||
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
|
@ -904,29 +1025,60 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
if ((NS_SUCCEEDED(result)) && (nsnull!=currentItem))
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIDOMNode>commonParent;
|
||||
result = range->GetCommonParent(getter_AddRefs(commonParent));
|
||||
if ((NS_SUCCEEDED(result)) && commonParent)
|
||||
result = RemoveParentFromRange(aParentTag, range);
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsISupportsArray *blockSections;
|
||||
result = NS_NewISupportsArray(&blockSections);
|
||||
if ((NS_SUCCEEDED(result)) && blockSections)
|
||||
{
|
||||
result = GetBlockSectionsForRange(aRange, blockSections);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsIDOMRange *subRange;
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
while (subRange && (NS_SUCCEEDED(result)))
|
||||
{
|
||||
result = RemoveParentFromBlockContent(aParentTag, subRange);
|
||||
NS_RELEASE(subRange);
|
||||
blockSections->RemoveElementAt(0);
|
||||
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
||||
}
|
||||
}
|
||||
NS_RELEASE(blockSections);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
||||
nsresult result;
|
||||
nsCOMPtr<nsIDOMNode>startParent;
|
||||
result = aRange->GetStartParent(getter_AddRefs(startParent));
|
||||
if ((NS_SUCCEEDED(result)) && startParent)
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
|
||||
range->GetStartParent(getter_AddRefs(startParent));
|
||||
range->GetEndParent(getter_AddRefs(endParent));
|
||||
if (startParent.get()==endParent.get())
|
||||
{ // the range is entirely contained within a single node
|
||||
nsCOMPtr<nsIDOMNode>parentNode;
|
||||
nsCOMPtr<nsIDOMElement>parentElement;
|
||||
result = startParent->GetParentNode(getter_AddRefs(parentNode));
|
||||
while ((NS_SUCCEEDED(result)) && parentNode)
|
||||
{
|
||||
parentElement = do_QueryInterface(parentNode);
|
||||
nsAutoString childTag; // leave as empty string
|
||||
nsAutoString parentTag;
|
||||
parentElement->GetTagName(parentTag);
|
||||
PRBool canContain;
|
||||
CanContainBlock(childTag, parentTag, canContain);
|
||||
PRBool isRoot;
|
||||
IsRootTag(parentTag, isRoot);
|
||||
if (aParentTag.EqualsIgnoreCase(parentTag))
|
||||
{
|
||||
// go through list backwards so deletes don't interfere with the iteration
|
||||
|
@ -937,7 +1089,7 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
nsCOMPtr<nsIDOMNode>grandParent;
|
||||
parentElement->GetParentNode(getter_AddRefs(grandParent));
|
||||
PRInt32 offsetInParent;
|
||||
result = nsIEditorSupport::GetChildOffset(parentElement, grandParent, offsetInParent);
|
||||
result = GetChildOffset(parentElement, grandParent, offsetInParent);
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
PRInt32 i=childCount-1;
|
||||
|
@ -959,21 +1111,15 @@ nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|||
}
|
||||
break;
|
||||
}
|
||||
else if (PR_TRUE==canContain) { // hit a subdoc, terminate?
|
||||
else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop
|
||||
break;
|
||||
}
|
||||
result = parentElement->GetParentNode(getter_AddRefs(parentNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsEditor::EndTransaction();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::InsertLink(nsString& aURL)
|
||||
{
|
||||
|
@ -1331,6 +1477,62 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection, ns
|
|||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::IsRootTag(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString bodyTag = "body";
|
||||
static nsAutoString tdTag = "td";
|
||||
static nsAutoString thTag = "th";
|
||||
static nsAutoString captionTag = "caption";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(bodyTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(tdTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(thTag) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(captionTag) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::IsSubordinateBlock(nsString &aTag, PRBool &aIsTag)
|
||||
{
|
||||
static nsAutoString p = "p";
|
||||
static nsAutoString h1 = "h1";
|
||||
static nsAutoString h2 = "h2";
|
||||
static nsAutoString h3 = "h3";
|
||||
static nsAutoString h4 = "h4";
|
||||
static nsAutoString h5 = "h5";
|
||||
static nsAutoString h6 = "h6";
|
||||
static nsAutoString address = "address";
|
||||
static nsAutoString pre = "pre";
|
||||
static nsAutoString li = "li";
|
||||
static nsAutoString dt = "dt";
|
||||
static nsAutoString dd = "dd";
|
||||
if (PR_TRUE==aTag.EqualsIgnoreCase(p) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h1) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h2) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h3) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h4) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h5) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(h6) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(address) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(pre) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(li) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(dt) ||
|
||||
PR_TRUE==aTag.EqualsIgnoreCase(dd) )
|
||||
{
|
||||
aIsTag = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
aIsTag = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::BeginComposition(void)
|
||||
{
|
||||
return nsTextEditor::BeginComposition();
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
NS_IMETHOD GetParagraphStyle(nsStringArray *aTagList);
|
||||
NS_IMETHOD AddBlockParent(nsString& aParentTag);
|
||||
NS_IMETHOD ReplaceBlockParent(nsString& aParentTag);
|
||||
NS_IMETHOD RemoveBlockParent();
|
||||
NS_IMETHOD RemoveParagraphStyle();
|
||||
NS_IMETHOD RemoveParent(const nsString &aParentTag);
|
||||
|
||||
NS_IMETHOD InsertLink(nsString& aURL);
|
||||
|
@ -163,8 +163,22 @@ protected:
|
|||
nsString &aParentTag,
|
||||
BlockTransformationType aTranformation);
|
||||
|
||||
NS_IMETHOD RemoveParagraphStyleFromRange(nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange);
|
||||
|
||||
NS_IMETHOD CanContainBlock(nsString &aBlockChild, nsString &aBlockParent, PRBool &aCanContain);
|
||||
|
||||
|
||||
NS_IMETHOD IsRootTag(nsString &aTag, PRBool &aIsTag);
|
||||
|
||||
NS_IMETHOD IsSubordinateBlock(nsString &aTag, PRBool &aIsTag);
|
||||
|
||||
|
||||
// EVENT LISTENERS AND COMMAND ROUTING NEEDS WORK
|
||||
// For now, the listners are tied to the nsTextEditor class
|
||||
//
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIStringStream.h"
|
||||
|
||||
|
@ -599,7 +600,39 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
|
|||
nsCOMPtr<nsIHTMLEditor>htmlEditor;
|
||||
htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor) {
|
||||
htmlEditor->RemoveBlockParent();
|
||||
htmlEditor->RemoveParagraphStyle();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// hard-coded change structure test -- GetParagraphStyle
|
||||
case nsIDOMEvent::VK_0:
|
||||
if (PR_TRUE==ctrlKey)
|
||||
{
|
||||
aProcessed=PR_TRUE;
|
||||
if (mEditor)
|
||||
{
|
||||
nsCOMPtr<nsIHTMLEditor>htmlEditor;
|
||||
htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
printf("testing GetParagraphStyle\n");
|
||||
nsStringArray styles;
|
||||
nsresult result = htmlEditor->GetParagraphStyle(&styles);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
PRInt32 count = styles.Count();
|
||||
PRInt32 i;
|
||||
for (i=0; i<count; i++)
|
||||
{
|
||||
nsString *tag = styles.StringAt(i);
|
||||
char *tagCString = tag->ToNewCString();
|
||||
printf("%s ", tagCString);
|
||||
delete [] tagCString;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "nsTextEditRules.h"
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsEditor.h"
|
||||
#include "PlaceholderTxn.h"
|
||||
#include "InsertTextTxn.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
@ -31,69 +32,8 @@
|
|||
#include "nsIContent.h"
|
||||
#include "nsIEditProperty.h"
|
||||
|
||||
const static char* kMOZEditorBogusNodeAttr="MOZ_EDITOR_BOGUS_NODE";
|
||||
const static char* kMOZEditorBogusNodeValue="TRUE";
|
||||
|
||||
static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID);
|
||||
|
||||
/********************************************************
|
||||
* Helper Functions
|
||||
********************************************************/
|
||||
|
||||
PRBool nsTextEditRules::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString tag;
|
||||
element->GetTagName(tag);
|
||||
if (tag.Equals(aTag->GetUnicode()))
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool nsTextEditRules::IsEditable(nsIDOMNode *aNode)
|
||||
{
|
||||
if (!aNode) return PR_FALSE;
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(aNode);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData>text;
|
||||
text = do_QueryInterface(aNode);
|
||||
if (text)
|
||||
{
|
||||
nsAutoString data;
|
||||
text->GetData(data);
|
||||
if (0==data.Length()) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
if ('\n'==data.CharAt(0)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************
|
||||
|
@ -437,7 +377,7 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode,
|
|||
nsCOMPtr<nsIDOMNode>parent;
|
||||
aNode->GetParentNode(getter_AddRefs(parent));
|
||||
PRInt32 offsetInParent;
|
||||
nsIEditorSupport::GetChildOffset(aNode, parent, offsetInParent);
|
||||
nsEditor::GetChildOffset(aNode, parent, offsetInParent);
|
||||
nsAutoString tag;
|
||||
aTag->ToString(tag);
|
||||
result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode);
|
||||
|
@ -563,7 +503,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
result = bodyNode->GetFirstChild(getter_AddRefs(bodyChild));
|
||||
while ((NS_SUCCEEDED(result)) && bodyChild)
|
||||
{
|
||||
if (PR_TRUE==IsEditable(bodyChild))
|
||||
if (PR_TRUE==nsEditor::IsEditable(bodyChild))
|
||||
{
|
||||
needsBogusContent = PR_FALSE;
|
||||
break;
|
||||
|
@ -599,8 +539,8 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
|
|||
newPElement = do_QueryInterface(mBogusNode);
|
||||
if (newPElement)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val(kMOZEditorBogusNodeValue);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val(nsEditor::kMOZEditorBogusNodeValue);
|
||||
newPElement->SetAttribute(att, val);
|
||||
}
|
||||
}
|
||||
|
@ -706,10 +646,10 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
|
@ -752,10 +692,10 @@ nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
element = do_QueryInterface(node);
|
||||
if (element)
|
||||
{
|
||||
nsAutoString att(kMOZEditorBogusNodeAttr);
|
||||
nsAutoString att(nsEditor::kMOZEditorBogusNodeAttr);
|
||||
nsAutoString val;
|
||||
(void)element->GetAttribute(att, val);
|
||||
if (val.Equals(kMOZEditorBogusNodeValue)) {
|
||||
if (val.Equals(nsEditor::kMOZEditorBogusNodeValue)) {
|
||||
mBogusNode = do_QueryInterface(element);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,8 +85,6 @@ protected:
|
|||
nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
|
||||
|
||||
// helper functions
|
||||
static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag);
|
||||
static PRBool IsEditable(nsIDOMNode *aNode);
|
||||
|
||||
/** insert aNode into a new style node of type aTag.
|
||||
* aSelection is optional. If provided, aSelection is set to (aNode, 0)
|
||||
|
|
|
@ -226,9 +226,9 @@ public:
|
|||
* @param aOffset the offset of aExistingRightNode's content|children to do the split at
|
||||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
*/
|
||||
NS_IMETHOD SplitNode(nsIDOMNode * aExistingRightNode,
|
||||
NS_IMETHOD SplitNode(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode ** aNewLeftNode)=0;
|
||||
nsIDOMNode **aNewLeftNode)=0;
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
|
@ -348,14 +348,13 @@ public:
|
|||
*/
|
||||
NS_IMETHOD Paste()=0;
|
||||
|
||||
/** add an EditActionListener to the editors list of listeners.
|
||||
*/
|
||||
/** add an EditActionListener to the editors list of listeners. */
|
||||
NS_IMETHOD AddEditActionListener(nsIEditActionListener *aListener)=0;
|
||||
|
||||
/** Remove an EditActionListener from the editor's list of listeners.
|
||||
*/
|
||||
/** Remove an EditActionListener from the editor's list of listeners. */
|
||||
NS_IMETHOD RemoveEditActionListener(nsIEditActionListener *aListener)=0;
|
||||
|
||||
/** Dumps a text representation of the content tree to standard out */
|
||||
NS_IMETHOD DebugDumpContent() const =0;
|
||||
|
||||
};
|
||||
|
|
|
@ -123,11 +123,13 @@ public:
|
|||
*/
|
||||
NS_IMETHOD ReplaceBlockParent(nsString& aParentTag)=0;
|
||||
|
||||
/** remove the paragraph style from the selection */
|
||||
NS_IMETHOD RemoveParagraphStyle()=0;
|
||||
|
||||
/** remove block parent of type aTagToRemove from the selection.
|
||||
* if aTagToRemove is null, the nearest enclosing block that
|
||||
* is <B>not</B> a sub-document is removed.
|
||||
* is <B>not</B> a root is removed.
|
||||
*/
|
||||
NS_IMETHOD RemoveBlockParent()=0;
|
||||
NS_IMETHOD RemoveParent(const nsString &aParentTag)=0;
|
||||
|
||||
NS_IMETHOD InsertLink(nsString& aURL)=0;
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "nsIEditor.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIEditorCallback;
|
||||
class nsISupportsArray;
|
||||
class nsIAtom;
|
||||
class nsIOutputStream;
|
||||
|
|
Загрузка…
Ссылка в новой задаче