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:
buster%netscape.com 1999-05-05 04:05:19 +00:00
Родитель 150cb9c442
Коммит 99a96a39ec
29 изменённых файлов: 2484 добавлений и 1610 удалений

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

@ -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;