зеркало из https://github.com/mozilla/gecko-dev.git
* ported the html editor work for the "caret doesn't move when i hit return" bug (16715) back to the plaintext editor.
This commit is contained in:
Родитель
8abfb4a29e
Коммит
d4edc684b8
|
@ -88,6 +88,26 @@ nsHTMLEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
nsresult res = nsTextEditRules::Init(aEditor, aFlags);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// pass over document and add any needed mozBRs
|
||||
// first turn off undo
|
||||
mEditor->EnableUndo(PR_FALSE);
|
||||
// set up mDocChangeRange to be whole doc
|
||||
nsCOMPtr<nsIDOMElement> bodyElem;
|
||||
nsCOMPtr<nsIDOMNode> bodyNode;
|
||||
mEditor->GetBodyElement(getter_AddRefs(bodyElem));
|
||||
bodyNode = do_QueryInterface(bodyElem);
|
||||
if (bodyNode)
|
||||
{
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, nsIDOMRange::GetIID(),
|
||||
getter_AddRefs(mDocChangeRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!mDocChangeRange) return NS_ERROR_NULL_POINTER;
|
||||
mDocChangeRange->SelectNode(bodyNode);
|
||||
AdjustSpecialBreaks();
|
||||
}
|
||||
// turn on undo
|
||||
mEditor->EnableUndo(PR_TRUE);
|
||||
|
||||
// make a listener
|
||||
res = NS_NewEditListener(getter_AddRefs(mListener), mEditor, this);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -198,8 +218,11 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
|
|||
}
|
||||
|
||||
// do default:
|
||||
res = nsTextEditRules::DidDoAction(aSelection, aInfo, aResult);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (aInfo->action != kInsertBreak) // nsTextEditRules::DidInsertBreak() not usable by html rules
|
||||
{
|
||||
res = nsTextEditRules::DidDoAction(aSelection, aInfo, aResult);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// adjust selection
|
||||
res = AdjustSelection(aSelection,info->collapsedAction);
|
||||
return res;
|
||||
|
@ -211,52 +234,6 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
|
|||
********************************************************/
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = nsTextEditRules::WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// this next only works for collapsed selections right now,
|
||||
// because selection is a pain to work with when not collapsed.
|
||||
// (no good way to extend start or end of selection)
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed) return NS_OK;
|
||||
|
||||
// if we are after a mozBR in the same block, then move selection
|
||||
// to be before it
|
||||
nsCOMPtr<nsIDOMNode> selNode, priorNode;
|
||||
PRInt32 selOffset;
|
||||
// get the (collapsed) selection location
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get prior node
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
else block1 = mEditor->GetBlockNodeParent(selNode);
|
||||
if (mEditor->IsBlockNode(priorNode)) block2 = priorNode;
|
||||
else block2 = mEditor->GetBlockNodeParent(priorNode);
|
||||
|
||||
if (block1 != block2) return NS_OK;
|
||||
if (!IsMozBR(priorNode)) return NS_OK;
|
||||
|
||||
// if we are here then the selection is right after a mozBR
|
||||
// that is in the same block as the selection. We need to move
|
||||
// the selection start to be before the mozBR.
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
||||
nsIDOMSelection *aSelection,
|
||||
|
@ -266,7 +243,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
|||
nsString *outString,
|
||||
TypeInState typeInState,
|
||||
PRInt32 aMaxLength)
|
||||
{ if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
|
@ -332,19 +310,6 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
|||
// find a nearby text node if possible
|
||||
nsCOMPtr<nsIDOMNode> priorNode, nextNode;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
// are we after a mozBR?
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode)
|
||||
&& (blockParent == mEditor->GetBlockNodeParent(priorNode)))
|
||||
{
|
||||
// uhh, lets be before it instead of after it. Now
|
||||
// walk away reeeal slow...
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode, selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// we know we are still not in a text node, so fall through to rest of this case
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
}
|
||||
if (NS_SUCCEEDED(res) && priorNode && mEditor->IsTextNode(priorNode)
|
||||
&& (blockParent == mEditor->GetBlockNodeParent(priorNode)))
|
||||
{
|
||||
|
@ -464,17 +429,10 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
*aCancel = PR_FALSE;
|
||||
*aHandled = PR_FALSE;
|
||||
|
||||
nsresult res;
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
|
@ -482,6 +440,14 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
|
||||
// split any mailcites in the way
|
||||
if (mFlags & nsIHTMLEditor::eEditorMailMask)
|
||||
{
|
||||
|
@ -592,23 +558,6 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
// its something else (body, div, td, ...): insert a normal br
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode;
|
||||
res = GetPriorHTMLNode(node, offset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && IsMozBR(nearNode))
|
||||
{
|
||||
// is nearNode also a descendant of same block?
|
||||
nsCOMPtr<nsIDOMNode> nearBlock = mEditor->GetBlockNodeParent(nearNode);
|
||||
if (blockParent == nearBlock)
|
||||
{
|
||||
// need to insert special BEFORE the moz BR. Why? Because if we don't
|
||||
// the selectin adjusting code will add an extra BR. doh.
|
||||
res = nsEditor::GetNodeLocation(nearNode, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(node, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mEditor->CreateBR(node, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -1830,42 +1779,6 @@ nsHTMLEditRules::IsUnorderedList(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBlockquote: true if node an html blockquote node
|
||||
//
|
||||
|
@ -1942,39 +1855,6 @@ nsHTMLEditRules::IsMozDiv(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMailCite: true if node an html blockquote with type=cite
|
||||
|
@ -2000,26 +1880,6 @@ nsHTMLEditRules::IsMailCite(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyBlock: figure out if aNode is (or is inside) an empty block.
|
||||
// A block can have children and still be considered empty,
|
||||
|
@ -2181,143 +2041,6 @@ nsHTMLEditRules::CreateMozDiv(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<n
|
|||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetPreviousSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLSibling: returns the next editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNHTMLextNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetTabAsNBSPs: stuff the right number of nbsp's into outString
|
||||
//
|
||||
|
@ -2352,17 +2075,27 @@ nsHTMLEditRules::IsFirstNode(nsIDOMNode *aNode)
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset, j=0;
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
nsresult res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsFirstNode");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!offset) // easy case, we are first dom child
|
||||
return PR_TRUE;
|
||||
if (!parent)
|
||||
return PR_TRUE;
|
||||
|
||||
// ok, so there are earlier children. But are they editable???
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
||||
if (!parent) return PR_TRUE;
|
||||
|
||||
parent->GetChildNodes(getter_AddRefs(childList));
|
||||
res = parent->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_FAILED(res) || !childList)
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsFirstNode");
|
||||
return PR_TRUE;
|
||||
}
|
||||
while (j < offset)
|
||||
{
|
||||
childList->Item(j, getter_AddRefs(child));
|
||||
|
@ -2383,16 +2116,28 @@ nsHTMLEditRules::IsLastNode(nsIDOMNode *aNode)
|
|||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset, j;
|
||||
PRUint32 numChildren;
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
nsresult res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsLastNode");
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsEditor::GetLengthOfDOMNode(parent, numChildren);
|
||||
if (offset+1 == (PRInt32)numChildren) // easy case, we are last dom child
|
||||
return PR_TRUE;
|
||||
|
||||
if (!parent)
|
||||
return PR_TRUE;
|
||||
|
||||
// ok, so there are later children. But are they editable???
|
||||
j = offset+1;
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
parent->GetChildNodes(getter_AddRefs(childList));
|
||||
res = parent->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_FAILED(res) || !childList)
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsLastNode");
|
||||
return PR_TRUE;
|
||||
}
|
||||
while (j < (PRInt32)numChildren)
|
||||
{
|
||||
childList->Item(j, getter_AddRefs(child));
|
||||
|
@ -2434,7 +2179,7 @@ nsHTMLEditRules::AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aB
|
|||
{
|
||||
PRUint32 strLength;
|
||||
nodeAsText->GetLength(&strLength);
|
||||
if (strLength > aOffset) return PR_FALSE; // there are chars in after us
|
||||
if ((PRInt32)strLength > aOffset) return PR_FALSE; // there are chars in after us
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
nsresult res = GetNextHTMLNode(aNode, aOffset, &nextNode);
|
||||
|
@ -2549,7 +2294,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
|
||||
// finding the real start for this point. look up the tree for as long as we are the
|
||||
// first node in the container, and as long as we haven't hit the body node.
|
||||
nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
while ((IsFirstNode(node)) && (!IsBody(parent)))
|
||||
{
|
||||
|
@ -2567,7 +2312,8 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
// some special casing for text nodes
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2608,7 +2354,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
|
||||
// finding the real end for this point. look up the tree for as long as we are the
|
||||
// last node in the container, and as long as we haven't hit the body node.
|
||||
nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
while ((IsLastNode(node)) && (!IsBody(parent)))
|
||||
{
|
||||
|
@ -2782,6 +2528,7 @@ nsHTMLEditRules::GetChildNodesForOperation(nsIDOMNode *inNode,
|
|||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
res = inNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!childNodes) return NS_ERROR_NULL_POINTER;
|
||||
PRUint32 childCount;
|
||||
res = childNodes->GetLength(&childCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -3070,27 +2817,6 @@ nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection,
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode)
|
||||
{
|
||||
if (!inParent || !outBRNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = mEditor->CreateBR(inParent, inOffset, outBRNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// give it special moz attr
|
||||
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(*outBRNode);
|
||||
if (brElem)
|
||||
{
|
||||
res = mEditor->SetAttribute(brElem, "type", "_moz");
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReturnInHeader: do the right thing for returns pressed in headers
|
||||
//
|
||||
|
@ -3186,7 +2912,7 @@ nsHTMLEditRules::ReturnInParagraph(nsIDOMSelection *aSelection,
|
|||
return res;
|
||||
}
|
||||
// at end of text node?
|
||||
if (aOffset == strLength)
|
||||
if (aOffset == (PRInt32)strLength)
|
||||
{
|
||||
// is there a BR after to it?
|
||||
res = GetNextHTMLSibling(aNode, &sibling);
|
||||
|
@ -3300,7 +3026,7 @@ nsHTMLEditRules::ReturnInListItem(nsIDOMSelection *aSelection,
|
|||
{
|
||||
// time to insert a break
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
nsresult res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -3591,104 +3317,6 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsFirst || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsFirst = PR_FALSE;
|
||||
|
||||
// find first editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, firstChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetFirstEditableChild(parent, &firstChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsFirst = (firstChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsLast || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsLast = PR_FALSE;
|
||||
|
||||
// find last editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, lastChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetLastEditableChild(parent, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsLast = (lastChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstChild = nsnull;
|
||||
|
||||
// find first editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetNextSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutFirstChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastChild = nsnull;
|
||||
|
||||
// find last editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetLastChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutLastChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3846,7 +3474,7 @@ nsHTMLEditRules::AdjustSpecialBreaks()
|
|||
// put moz-br's into these empty li's and td's
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> brNode, theNode( do_QueryInterface(isupports ) );
|
||||
|
@ -3929,7 +3557,7 @@ nsHTMLEditRules::AdjustWhitespace()
|
|||
// now adjust whitespace on node we found
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode( do_QueryInterface(isupports ) );
|
||||
|
@ -3968,7 +3596,7 @@ nsHTMLEditRules::AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::ESelect
|
|||
// do we need to insert a special mozBR? We do if we are:
|
||||
// 1) in a collapsed selection AND
|
||||
// 2) after a normal (non-moz) br AND
|
||||
// 3) that br in the last editable node in it's block AND
|
||||
// 3) that br is the last editable node in it's block AND
|
||||
// 4) that block is same block where selection is
|
||||
nsCOMPtr<nsIDOMNode> nearNode;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
|
@ -4103,7 +3731,7 @@ nsHTMLEditRules::RemoveEmptyNodes()
|
|||
// now delete the empty nodes
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> delNode( do_QueryInterface(isupports ) );
|
||||
|
|
|
@ -55,7 +55,6 @@ protected:
|
|||
|
||||
|
||||
// nsHTMLEditRules implementation methods
|
||||
nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
nsresult WillInsertText( PRInt32 aAction,
|
||||
nsIDOMSelection *aSelection,
|
||||
PRBool *aCancel,
|
||||
|
@ -92,18 +91,13 @@ protected:
|
|||
static PRBool IsList(nsIDOMNode *aNode);
|
||||
static PRBool IsUnorderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsOrderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBlockquote(nsIDOMNode *aNode);
|
||||
static PRBool IsAnchor(nsIDOMNode *aNode);
|
||||
static PRBool IsDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsNormalDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
|
@ -118,15 +112,7 @@ protected:
|
|||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
PRBool AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
||||
nsresult GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt32 aOffset,
|
||||
PRInt32 actionID, nsCOMPtr<nsIDOMNode> *outNode, PRInt32 *outOffset);
|
||||
nsresult GetPromotedRanges(nsIDOMSelection *inSelection,
|
||||
|
@ -148,11 +134,6 @@ protected:
|
|||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst);
|
||||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
nsIDOMNode *aNodeRight,
|
||||
nsCOMPtr<nsIDOMNode> *aOutMergeParent,
|
||||
|
|
|
@ -390,12 +390,6 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|||
}
|
||||
}
|
||||
|
||||
// Init the rules system
|
||||
// XXX: ERROR CHECKING should InitRules return an error, and then we could check it here?
|
||||
InitRules();
|
||||
|
||||
EnableUndo(PR_TRUE);
|
||||
|
||||
// Set up a DTD XXX XXX
|
||||
// HACK: This should have happened in a document specific way
|
||||
// in nsEditor::Init(), but we dont' have a way to do that yet
|
||||
|
@ -403,6 +397,12 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|||
nsIDTD::GetIID(), getter_AddRefs(mDTD));
|
||||
if (!mDTD) result = NS_ERROR_FAILURE;
|
||||
|
||||
// Init the rules system
|
||||
// XXX: ERROR CHECKING should InitRules return an error, and then we could check it here?
|
||||
InitRules();
|
||||
|
||||
EnableUndo(PR_TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1349,97 +1349,99 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString)
|
|||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
|
||||
// Call the rules code in case there's anything we need to do first
|
||||
// (e.g. delete the bogus node):
|
||||
// Call the rules code in case there's anything we need to do first
|
||||
// (e.g. delete the bogus node):
|
||||
if (!mRules) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
|
||||
PRBool cancel, handled;
|
||||
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
PRInt32 offsetOfNewNode;
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentNode, offsetOfNewNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// give rules a chance to handle or cancel
|
||||
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
|
||||
PRBool cancel, handled;
|
||||
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (cancel) return NS_OK; // rules canceled the operation
|
||||
if (!handled)
|
||||
{
|
||||
// Get the first range in the selection, for context:
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = selection->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
|
||||
if (!nsrange)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
||||
res = nsrange->CreateContextualFragment(aInputString,
|
||||
getter_AddRefs(docfrag));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Couldn't create contextual fragment: error was %d\n", res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("============ Fragment dump :===========\n");
|
||||
|
||||
nsCOMPtr<nsIContent> fragc (do_QueryInterface(docfrag));
|
||||
if (!fragc)
|
||||
printf("Couldn't get fragment is nsIContent\n");
|
||||
else
|
||||
fragc->List(stdout);
|
||||
#endif
|
||||
|
||||
// Insert the contents of the document fragment:
|
||||
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
|
||||
|
||||
// Loop over the contents of the fragment:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
printf("GetFirstChild failed!\n");
|
||||
return res;
|
||||
}
|
||||
while (child)
|
||||
{
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("About to try to insert this node:\n");
|
||||
nsCOMPtr<nsIContent> nodec (do_QueryInterface(child));
|
||||
if (nodec) nodec->List(stdout);
|
||||
printf("-----\n");
|
||||
#endif
|
||||
// Get the next sibling before inserting the node;
|
||||
// when we insert the node, it moves into the main doc tree
|
||||
// so we'll no longer be able to get the siblings in the doc frag.
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
// Ignore the return value, we'll check child when we loop around again.
|
||||
|
||||
// Now we can insert the node.
|
||||
res = InsertNode(child, parentNode, offsetOfNewNode++);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = selection->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_FAILED(res))
|
||||
break;
|
||||
child = nextSib;
|
||||
return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
|
||||
if (!nsrange)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
||||
res = nsrange->CreateContextualFragment(aInputString,
|
||||
getter_AddRefs(docfrag));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Couldn't create contextual fragment: error was %d\n", res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("============ Fragment dump :===========\n");
|
||||
|
||||
nsCOMPtr<nsIContent> fragc (do_QueryInterface(docfrag));
|
||||
if (!fragc)
|
||||
printf("Couldn't get fragment is nsIContent\n");
|
||||
else
|
||||
fragc->List(stdout);
|
||||
#endif
|
||||
|
||||
// Insert the contents of the document fragment:
|
||||
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
|
||||
|
||||
// Loop over the contents of the fragment:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
printf("GetFirstChild failed!\n");
|
||||
return res;
|
||||
}
|
||||
while (child)
|
||||
{
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("About to try to insert this node:\n");
|
||||
nsCOMPtr<nsIContent> nodec (do_QueryInterface(child));
|
||||
if (nodec) nodec->List(stdout);
|
||||
printf("-----\n");
|
||||
#endif
|
||||
// Get the next sibling before inserting the node;
|
||||
// when we insert the node, it moves into the main doc tree
|
||||
// so we'll no longer be able to get the siblings in the doc frag.
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
// Ignore the return value, we'll check child when we loop around again.
|
||||
|
||||
// Now we can insert the node.
|
||||
res = InsertNode(child, parentNode, offsetOfNewNode++);
|
||||
if (NS_FAILED(res))
|
||||
break;
|
||||
child = nextSib;
|
||||
}
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// Now collapse the selection to the end of what we just inserted:
|
||||
selection->Collapse(parentNode, offsetOfNewNode);
|
||||
}
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// Now collapse the selection to the end of what we just inserted:
|
||||
selection->Collapse(parentNode, offsetOfNewNode);
|
||||
|
||||
|
||||
res = mRules->DidDoAction(selection, &ruleInfo, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,42 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
|||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// this next only works for collapsed selections right now,
|
||||
// because selection is a pain to work with when not collapsed.
|
||||
// (no good way to extend start or end of selection)
|
||||
PRBool bCollapsed;
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed) return NS_OK;
|
||||
|
||||
// if we are after a mozBR in the same block, then move selection
|
||||
// to be before it
|
||||
nsCOMPtr<nsIDOMNode> selNode, priorNode;
|
||||
PRInt32 selOffset;
|
||||
// get the (collapsed) selection location
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get next node
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
else block1 = mEditor->GetBlockNodeParent(selNode);
|
||||
block2 = mEditor->GetBlockNodeParent(priorNode);
|
||||
|
||||
if (block1 != block2) return NS_OK;
|
||||
|
||||
// if we are here then the selection is right after a mozBR
|
||||
// that is in the same block as the selection. We need to move
|
||||
// the selection start to be before the mozBR.
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -291,7 +326,26 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
if (mFlags & nsIHTMLEditor::eEditorSingleLineMask) {
|
||||
*aCancel = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
res = mEditor->DeleteSelection(nsIEditor::eDoNothing);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// Mail rule: split any <pre> tags in the way,
|
||||
// since they're probably quoted text.
|
||||
// For now, do this for all plaintext since mail is our main customer
|
||||
|
@ -300,7 +354,6 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> preNode, selNode;
|
||||
PRInt32 selOffset, newOffset;
|
||||
nsresult res;
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
|
@ -317,9 +370,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
res = aSelection->Collapse(selNode, newOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aCancel = PR_FALSE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -327,7 +378,53 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
nsresult
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
return NS_OK;
|
||||
// if we are at the end of the document, we need to insert
|
||||
// a special mozBR following the normal br, and then set the
|
||||
// selection to after the mozBR.
|
||||
PRInt32 selOffset;
|
||||
nsCOMPtr<nsIDOMNode> nearNode, selNode;
|
||||
nsresult res;
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && !IsMozBR(nearNode))
|
||||
{
|
||||
PRBool bIsLast;
|
||||
res = IsLastEditableChild(nearNode, &bIsLast);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsLast)
|
||||
{
|
||||
// need to insert special moz BR. Why? Because if we don't
|
||||
// the user will see no new line for the break. Also, things
|
||||
// like table cells won't grow in height.
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset+1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ok, the br inst the last child. But it might be second-to-last
|
||||
// with a mozBR already exiting after it. In this case we have to
|
||||
// move the selection to after the mozBR so it will show up on the
|
||||
// empty line.
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
res = GetNextHTMLNode(nearNode, &nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (IsMozBR(nextNode))
|
||||
{
|
||||
res = nsEditor::GetNodeLocation(nextNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset+1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -361,6 +458,23 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
|
|||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
res = mEditor->DeleteSelection(nsIEditor::eDoNothing);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// do text insertion
|
||||
PRBool bCancel;
|
||||
res = DoTextInsertion(aSelection, &bCancel, aOutString, aTypeInState);
|
||||
|
@ -1246,3 +1360,354 @@ nsTextEditRules::DoTextInsertion(nsIDOMSelection *aSelection,
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetPreviousSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLSibling: returns the next editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNHTMLextNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsFirst || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsFirst = PR_FALSE;
|
||||
|
||||
// find first editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, firstChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetFirstEditableChild(parent, &firstChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsFirst = (firstChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsLast || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsLast = PR_FALSE;
|
||||
|
||||
// find last editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, lastChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetLastEditableChild(parent, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsLast = (lastChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstChild = nsnull;
|
||||
|
||||
// find first editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetNextSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutFirstChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastChild = nsnull;
|
||||
|
||||
// find last editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetLastChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutLastChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsMozBR");
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode)
|
||||
{
|
||||
if (!inParent || !outBRNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = mEditor->CreateBR(inParent, inOffset, outBRNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// give it special moz attr
|
||||
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(*outBRNode);
|
||||
if (brElem)
|
||||
{
|
||||
res = mEditor->SetAttribute(brElem, "type", "_moz");
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -200,6 +200,28 @@ protected:
|
|||
const nsString *aInString,
|
||||
TypeInState aTypeInState);
|
||||
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
||||
nsresult IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst);
|
||||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
|
||||
// data
|
||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
||||
nsString mPasswordText; // a buffer we use to store the real value of password editors
|
||||
|
|
|
@ -88,6 +88,26 @@ nsHTMLEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
nsresult res = nsTextEditRules::Init(aEditor, aFlags);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// pass over document and add any needed mozBRs
|
||||
// first turn off undo
|
||||
mEditor->EnableUndo(PR_FALSE);
|
||||
// set up mDocChangeRange to be whole doc
|
||||
nsCOMPtr<nsIDOMElement> bodyElem;
|
||||
nsCOMPtr<nsIDOMNode> bodyNode;
|
||||
mEditor->GetBodyElement(getter_AddRefs(bodyElem));
|
||||
bodyNode = do_QueryInterface(bodyElem);
|
||||
if (bodyNode)
|
||||
{
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, nsIDOMRange::GetIID(),
|
||||
getter_AddRefs(mDocChangeRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!mDocChangeRange) return NS_ERROR_NULL_POINTER;
|
||||
mDocChangeRange->SelectNode(bodyNode);
|
||||
AdjustSpecialBreaks();
|
||||
}
|
||||
// turn on undo
|
||||
mEditor->EnableUndo(PR_TRUE);
|
||||
|
||||
// make a listener
|
||||
res = NS_NewEditListener(getter_AddRefs(mListener), mEditor, this);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -198,8 +218,11 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
|
|||
}
|
||||
|
||||
// do default:
|
||||
res = nsTextEditRules::DidDoAction(aSelection, aInfo, aResult);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (aInfo->action != kInsertBreak) // nsTextEditRules::DidInsertBreak() not usable by html rules
|
||||
{
|
||||
res = nsTextEditRules::DidDoAction(aSelection, aInfo, aResult);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// adjust selection
|
||||
res = AdjustSelection(aSelection,info->collapsedAction);
|
||||
return res;
|
||||
|
@ -211,52 +234,6 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
|
|||
********************************************************/
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
{
|
||||
if (!aSelection || !aCancel)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = nsTextEditRules::WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// this next only works for collapsed selections right now,
|
||||
// because selection is a pain to work with when not collapsed.
|
||||
// (no good way to extend start or end of selection)
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed) return NS_OK;
|
||||
|
||||
// if we are after a mozBR in the same block, then move selection
|
||||
// to be before it
|
||||
nsCOMPtr<nsIDOMNode> selNode, priorNode;
|
||||
PRInt32 selOffset;
|
||||
// get the (collapsed) selection location
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get prior node
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
else block1 = mEditor->GetBlockNodeParent(selNode);
|
||||
if (mEditor->IsBlockNode(priorNode)) block2 = priorNode;
|
||||
else block2 = mEditor->GetBlockNodeParent(priorNode);
|
||||
|
||||
if (block1 != block2) return NS_OK;
|
||||
if (!IsMozBR(priorNode)) return NS_OK;
|
||||
|
||||
// if we are here then the selection is right after a mozBR
|
||||
// that is in the same block as the selection. We need to move
|
||||
// the selection start to be before the mozBR.
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
||||
nsIDOMSelection *aSelection,
|
||||
|
@ -266,7 +243,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
|||
nsString *outString,
|
||||
TypeInState typeInState,
|
||||
PRInt32 aMaxLength)
|
||||
{ if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// initialize out param
|
||||
*aCancel = PR_FALSE;
|
||||
|
@ -332,19 +310,6 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
|||
// find a nearby text node if possible
|
||||
nsCOMPtr<nsIDOMNode> priorNode, nextNode;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
// are we after a mozBR?
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode)
|
||||
&& (blockParent == mEditor->GetBlockNodeParent(priorNode)))
|
||||
{
|
||||
// uhh, lets be before it instead of after it. Now
|
||||
// walk away reeeal slow...
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode, selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// we know we are still not in a text node, so fall through to rest of this case
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
}
|
||||
if (NS_SUCCEEDED(res) && priorNode && mEditor->IsTextNode(priorNode)
|
||||
&& (blockParent == mEditor->GetBlockNodeParent(priorNode)))
|
||||
{
|
||||
|
@ -464,17 +429,10 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
*aCancel = PR_FALSE;
|
||||
*aHandled = PR_FALSE;
|
||||
|
||||
nsresult res;
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
|
@ -482,6 +440,14 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
|
||||
// split any mailcites in the way
|
||||
if (mFlags & nsIHTMLEditor::eEditorMailMask)
|
||||
{
|
||||
|
@ -592,23 +558,6 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
// its something else (body, div, td, ...): insert a normal br
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode;
|
||||
res = GetPriorHTMLNode(node, offset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && IsMozBR(nearNode))
|
||||
{
|
||||
// is nearNode also a descendant of same block?
|
||||
nsCOMPtr<nsIDOMNode> nearBlock = mEditor->GetBlockNodeParent(nearNode);
|
||||
if (blockParent == nearBlock)
|
||||
{
|
||||
// need to insert special BEFORE the moz BR. Why? Because if we don't
|
||||
// the selectin adjusting code will add an extra BR. doh.
|
||||
res = nsEditor::GetNodeLocation(nearNode, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(node, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mEditor->CreateBR(node, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -1830,42 +1779,6 @@ nsHTMLEditRules::IsUnorderedList(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBlockquote: true if node an html blockquote node
|
||||
//
|
||||
|
@ -1942,39 +1855,6 @@ nsHTMLEditRules::IsMozDiv(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMailCite: true if node an html blockquote with type=cite
|
||||
|
@ -2000,26 +1880,6 @@ nsHTMLEditRules::IsMailCite(nsIDOMNode *node)
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsHTMLEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsEmptyBlock: figure out if aNode is (or is inside) an empty block.
|
||||
// A block can have children and still be considered empty,
|
||||
|
@ -2181,143 +2041,6 @@ nsHTMLEditRules::CreateMozDiv(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<n
|
|||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetPreviousSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLSibling: returns the next editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNHTMLextNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetTabAsNBSPs: stuff the right number of nbsp's into outString
|
||||
//
|
||||
|
@ -2352,17 +2075,27 @@ nsHTMLEditRules::IsFirstNode(nsIDOMNode *aNode)
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset, j=0;
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
nsresult res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsFirstNode");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!offset) // easy case, we are first dom child
|
||||
return PR_TRUE;
|
||||
if (!parent)
|
||||
return PR_TRUE;
|
||||
|
||||
// ok, so there are earlier children. But are they editable???
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
||||
if (!parent) return PR_TRUE;
|
||||
|
||||
parent->GetChildNodes(getter_AddRefs(childList));
|
||||
res = parent->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_FAILED(res) || !childList)
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsFirstNode");
|
||||
return PR_TRUE;
|
||||
}
|
||||
while (j < offset)
|
||||
{
|
||||
childList->Item(j, getter_AddRefs(child));
|
||||
|
@ -2383,16 +2116,28 @@ nsHTMLEditRules::IsLastNode(nsIDOMNode *aNode)
|
|||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset, j;
|
||||
PRUint32 numChildren;
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
nsresult res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsLastNode");
|
||||
return PR_FALSE;
|
||||
}
|
||||
nsEditor::GetLengthOfDOMNode(parent, numChildren);
|
||||
if (offset+1 == (PRInt32)numChildren) // easy case, we are last dom child
|
||||
return PR_TRUE;
|
||||
|
||||
if (!parent)
|
||||
return PR_TRUE;
|
||||
|
||||
// ok, so there are later children. But are they editable???
|
||||
j = offset+1;
|
||||
nsCOMPtr<nsIDOMNodeList>childList;
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
parent->GetChildNodes(getter_AddRefs(childList));
|
||||
res = parent->GetChildNodes(getter_AddRefs(childList));
|
||||
if (NS_FAILED(res) || !childList)
|
||||
{
|
||||
NS_NOTREACHED("failure in nsHTMLEditRules::IsLastNode");
|
||||
return PR_TRUE;
|
||||
}
|
||||
while (j < (PRInt32)numChildren)
|
||||
{
|
||||
childList->Item(j, getter_AddRefs(child));
|
||||
|
@ -2434,7 +2179,7 @@ nsHTMLEditRules::AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aB
|
|||
{
|
||||
PRUint32 strLength;
|
||||
nodeAsText->GetLength(&strLength);
|
||||
if (strLength > aOffset) return PR_FALSE; // there are chars in after us
|
||||
if ((PRInt32)strLength > aOffset) return PR_FALSE; // there are chars in after us
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
nsresult res = GetNextHTMLNode(aNode, aOffset, &nextNode);
|
||||
|
@ -2549,7 +2294,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
|
||||
// finding the real start for this point. look up the tree for as long as we are the
|
||||
// first node in the container, and as long as we haven't hit the body node.
|
||||
nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
while ((IsFirstNode(node)) && (!IsBody(parent)))
|
||||
{
|
||||
|
@ -2567,7 +2312,8 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
// some special casing for text nodes
|
||||
if (nsEditor::IsTextNode(aNode))
|
||||
{
|
||||
nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(aNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2608,7 +2354,7 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt
|
|||
|
||||
// finding the real end for this point. look up the tree for as long as we are the
|
||||
// last node in the container, and as long as we haven't hit the body node.
|
||||
nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
res = nsEditor::GetNodeLocation(node, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
while ((IsLastNode(node)) && (!IsBody(parent)))
|
||||
{
|
||||
|
@ -2782,6 +2528,7 @@ nsHTMLEditRules::GetChildNodesForOperation(nsIDOMNode *inNode,
|
|||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
res = inNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!childNodes) return NS_ERROR_NULL_POINTER;
|
||||
PRUint32 childCount;
|
||||
res = childNodes->GetLength(&childCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -3070,27 +2817,6 @@ nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection,
|
|||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode)
|
||||
{
|
||||
if (!inParent || !outBRNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = mEditor->CreateBR(inParent, inOffset, outBRNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// give it special moz attr
|
||||
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(*outBRNode);
|
||||
if (brElem)
|
||||
{
|
||||
res = mEditor->SetAttribute(brElem, "type", "_moz");
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReturnInHeader: do the right thing for returns pressed in headers
|
||||
//
|
||||
|
@ -3186,7 +2912,7 @@ nsHTMLEditRules::ReturnInParagraph(nsIDOMSelection *aSelection,
|
|||
return res;
|
||||
}
|
||||
// at end of text node?
|
||||
if (aOffset == strLength)
|
||||
if (aOffset == (PRInt32)strLength)
|
||||
{
|
||||
// is there a BR after to it?
|
||||
res = GetNextHTMLSibling(aNode, &sibling);
|
||||
|
@ -3300,7 +3026,7 @@ nsHTMLEditRules::ReturnInListItem(nsIDOMSelection *aSelection,
|
|||
{
|
||||
// time to insert a break
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
nsresult res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -3591,104 +3317,6 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsFirst || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsFirst = PR_FALSE;
|
||||
|
||||
// find first editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, firstChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetFirstEditableChild(parent, &firstChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsFirst = (firstChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsLast || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsLast = PR_FALSE;
|
||||
|
||||
// find last editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, lastChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetLastEditableChild(parent, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsLast = (lastChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstChild = nsnull;
|
||||
|
||||
// find first editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetNextSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutFirstChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastChild = nsnull;
|
||||
|
||||
// find last editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetLastChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutLastChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3846,7 +3474,7 @@ nsHTMLEditRules::AdjustSpecialBreaks()
|
|||
// put moz-br's into these empty li's and td's
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> brNode, theNode( do_QueryInterface(isupports ) );
|
||||
|
@ -3929,7 +3557,7 @@ nsHTMLEditRules::AdjustWhitespace()
|
|||
// now adjust whitespace on node we found
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode( do_QueryInterface(isupports ) );
|
||||
|
@ -3968,7 +3596,7 @@ nsHTMLEditRules::AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::ESelect
|
|||
// do we need to insert a special mozBR? We do if we are:
|
||||
// 1) in a collapsed selection AND
|
||||
// 2) after a normal (non-moz) br AND
|
||||
// 3) that br in the last editable node in it's block AND
|
||||
// 3) that br is the last editable node in it's block AND
|
||||
// 4) that block is same block where selection is
|
||||
nsCOMPtr<nsIDOMNode> nearNode;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
|
@ -4103,7 +3731,7 @@ nsHTMLEditRules::RemoveEmptyNodes()
|
|||
// now delete the empty nodes
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < (PRInt32)nodeCount; j++)
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> delNode( do_QueryInterface(isupports ) );
|
||||
|
|
|
@ -55,7 +55,6 @@ protected:
|
|||
|
||||
|
||||
// nsHTMLEditRules implementation methods
|
||||
nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel);
|
||||
nsresult WillInsertText( PRInt32 aAction,
|
||||
nsIDOMSelection *aSelection,
|
||||
PRBool *aCancel,
|
||||
|
@ -92,18 +91,13 @@ protected:
|
|||
static PRBool IsList(nsIDOMNode *aNode);
|
||||
static PRBool IsUnorderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsOrderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBlockquote(nsIDOMNode *aNode);
|
||||
static PRBool IsAnchor(nsIDOMNode *aNode);
|
||||
static PRBool IsDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsNormalDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
|
@ -118,15 +112,7 @@ protected:
|
|||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
PRBool AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
||||
nsresult GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt32 aOffset,
|
||||
PRInt32 actionID, nsCOMPtr<nsIDOMNode> *outNode, PRInt32 *outOffset);
|
||||
nsresult GetPromotedRanges(nsIDOMSelection *inSelection,
|
||||
|
@ -148,11 +134,6 @@ protected:
|
|||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst);
|
||||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
nsIDOMNode *aNodeRight,
|
||||
nsCOMPtr<nsIDOMNode> *aOutMergeParent,
|
||||
|
|
|
@ -390,12 +390,6 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|||
}
|
||||
}
|
||||
|
||||
// Init the rules system
|
||||
// XXX: ERROR CHECKING should InitRules return an error, and then we could check it here?
|
||||
InitRules();
|
||||
|
||||
EnableUndo(PR_TRUE);
|
||||
|
||||
// Set up a DTD XXX XXX
|
||||
// HACK: This should have happened in a document specific way
|
||||
// in nsEditor::Init(), but we dont' have a way to do that yet
|
||||
|
@ -403,6 +397,12 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|||
nsIDTD::GetIID(), getter_AddRefs(mDTD));
|
||||
if (!mDTD) result = NS_ERROR_FAILURE;
|
||||
|
||||
// Init the rules system
|
||||
// XXX: ERROR CHECKING should InitRules return an error, and then we could check it here?
|
||||
InitRules();
|
||||
|
||||
EnableUndo(PR_TRUE);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1349,97 +1349,99 @@ NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString)
|
|||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
|
||||
// Call the rules code in case there's anything we need to do first
|
||||
// (e.g. delete the bogus node):
|
||||
// Call the rules code in case there's anything we need to do first
|
||||
// (e.g. delete the bogus node):
|
||||
if (!mRules) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
|
||||
PRBool cancel, handled;
|
||||
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
PRInt32 offsetOfNewNode;
|
||||
res = DeleteSelectionAndPrepareToCreateNode(parentNode, offsetOfNewNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// give rules a chance to handle or cancel
|
||||
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
|
||||
PRBool cancel, handled;
|
||||
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (cancel) return NS_OK; // rules canceled the operation
|
||||
if (!handled)
|
||||
{
|
||||
// Get the first range in the selection, for context:
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = selection->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
|
||||
if (!nsrange)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
||||
res = nsrange->CreateContextualFragment(aInputString,
|
||||
getter_AddRefs(docfrag));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Couldn't create contextual fragment: error was %d\n", res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("============ Fragment dump :===========\n");
|
||||
|
||||
nsCOMPtr<nsIContent> fragc (do_QueryInterface(docfrag));
|
||||
if (!fragc)
|
||||
printf("Couldn't get fragment is nsIContent\n");
|
||||
else
|
||||
fragc->List(stdout);
|
||||
#endif
|
||||
|
||||
// Insert the contents of the document fragment:
|
||||
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
|
||||
|
||||
// Loop over the contents of the fragment:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
printf("GetFirstChild failed!\n");
|
||||
return res;
|
||||
}
|
||||
while (child)
|
||||
{
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("About to try to insert this node:\n");
|
||||
nsCOMPtr<nsIContent> nodec (do_QueryInterface(child));
|
||||
if (nodec) nodec->List(stdout);
|
||||
printf("-----\n");
|
||||
#endif
|
||||
// Get the next sibling before inserting the node;
|
||||
// when we insert the node, it moves into the main doc tree
|
||||
// so we'll no longer be able to get the siblings in the doc frag.
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
// Ignore the return value, we'll check child when we loop around again.
|
||||
|
||||
// Now we can insert the node.
|
||||
res = InsertNode(child, parentNode, offsetOfNewNode++);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = selection->GetRangeAt(0, getter_AddRefs(range));
|
||||
if (NS_FAILED(res))
|
||||
break;
|
||||
child = nextSib;
|
||||
return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
|
||||
if (!nsrange)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
||||
res = nsrange->CreateContextualFragment(aInputString,
|
||||
getter_AddRefs(docfrag));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Couldn't create contextual fragment: error was %d\n", res);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("============ Fragment dump :===========\n");
|
||||
|
||||
nsCOMPtr<nsIContent> fragc (do_QueryInterface(docfrag));
|
||||
if (!fragc)
|
||||
printf("Couldn't get fragment is nsIContent\n");
|
||||
else
|
||||
fragc->List(stdout);
|
||||
#endif
|
||||
|
||||
// Insert the contents of the document fragment:
|
||||
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
|
||||
|
||||
// Loop over the contents of the fragment:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = fragmentAsNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res))
|
||||
{
|
||||
printf("GetFirstChild failed!\n");
|
||||
return res;
|
||||
}
|
||||
while (child)
|
||||
{
|
||||
#if defined(DEBUG_akkana_verbose)
|
||||
printf("About to try to insert this node:\n");
|
||||
nsCOMPtr<nsIContent> nodec (do_QueryInterface(child));
|
||||
if (nodec) nodec->List(stdout);
|
||||
printf("-----\n");
|
||||
#endif
|
||||
// Get the next sibling before inserting the node;
|
||||
// when we insert the node, it moves into the main doc tree
|
||||
// so we'll no longer be able to get the siblings in the doc frag.
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
// Ignore the return value, we'll check child when we loop around again.
|
||||
|
||||
// Now we can insert the node.
|
||||
res = InsertNode(child, parentNode, offsetOfNewNode++);
|
||||
if (NS_FAILED(res))
|
||||
break;
|
||||
child = nextSib;
|
||||
}
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// Now collapse the selection to the end of what we just inserted:
|
||||
selection->Collapse(parentNode, offsetOfNewNode);
|
||||
}
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
|
||||
// Now collapse the selection to the end of what we just inserted:
|
||||
selection->Collapse(parentNode, offsetOfNewNode);
|
||||
|
||||
|
||||
res = mRules->DidDoAction(selection, &ruleInfo, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,42 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
|||
mBogusNode = do_QueryInterface(nsnull);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// this next only works for collapsed selections right now,
|
||||
// because selection is a pain to work with when not collapsed.
|
||||
// (no good way to extend start or end of selection)
|
||||
PRBool bCollapsed;
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed) return NS_OK;
|
||||
|
||||
// if we are after a mozBR in the same block, then move selection
|
||||
// to be before it
|
||||
nsCOMPtr<nsIDOMNode> selNode, priorNode;
|
||||
PRInt32 selOffset;
|
||||
// get the (collapsed) selection location
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get next node
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
else block1 = mEditor->GetBlockNodeParent(selNode);
|
||||
block2 = mEditor->GetBlockNodeParent(priorNode);
|
||||
|
||||
if (block1 != block2) return NS_OK;
|
||||
|
||||
// if we are here then the selection is right after a mozBR
|
||||
// that is in the same block as the selection. We need to move
|
||||
// the selection start to be before the mozBR.
|
||||
res = nsEditor::GetNodeLocation(priorNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -291,7 +326,26 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
if (mFlags & nsIHTMLEditor::eEditorSingleLineMask) {
|
||||
*aCancel = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
res = mEditor->DeleteSelection(nsIEditor::eDoNothing);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// Mail rule: split any <pre> tags in the way,
|
||||
// since they're probably quoted text.
|
||||
// For now, do this for all plaintext since mail is our main customer
|
||||
|
@ -300,7 +354,6 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> preNode, selNode;
|
||||
PRInt32 selOffset, newOffset;
|
||||
nsresult res;
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
|
@ -317,9 +370,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
res = aSelection->Collapse(selNode, newOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aCancel = PR_FALSE;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -327,7 +378,53 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
|
|||
nsresult
|
||||
nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
{
|
||||
return NS_OK;
|
||||
// if we are at the end of the document, we need to insert
|
||||
// a special mozBR following the normal br, and then set the
|
||||
// selection to after the mozBR.
|
||||
PRInt32 selOffset;
|
||||
nsCOMPtr<nsIDOMNode> nearNode, selNode;
|
||||
nsresult res;
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && !IsMozBR(nearNode))
|
||||
{
|
||||
PRBool bIsLast;
|
||||
res = IsLastEditableChild(nearNode, &bIsLast);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (bIsLast)
|
||||
{
|
||||
// need to insert special moz BR. Why? Because if we don't
|
||||
// the user will see no new line for the break. Also, things
|
||||
// like table cells won't grow in height.
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = CreateMozBR(selNode, selOffset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = nsEditor::GetNodeLocation(brNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset+1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ok, the br inst the last child. But it might be second-to-last
|
||||
// with a mozBR already exiting after it. In this case we have to
|
||||
// move the selection to after the mozBR so it will show up on the
|
||||
// empty line.
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
res = GetNextHTMLNode(nearNode, &nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (IsMozBR(nextNode))
|
||||
{
|
||||
res = nsEditor::GetNodeLocation(nextNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(selNode,selOffset+1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -361,6 +458,23 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
|
|||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
|
||||
// if the selection isn't collapsed, delete it.
|
||||
PRBool bCollapsed;
|
||||
res = aSelection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bCollapsed)
|
||||
{
|
||||
res = mEditor->DeleteSelection(nsIEditor::eDoNothing);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
|
||||
// do text insertion
|
||||
PRBool bCancel;
|
||||
res = DoTextInsertion(aSelection, &bCancel, aOutString, aTypeInState);
|
||||
|
@ -1246,3 +1360,354 @@ nsTextEditRules::DoTextInsertion(nsIDOMSelection *aSelection,
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetPreviousSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLSibling: returns the next editable sibling, if there is
|
||||
// one within the parent
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
*outNode = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> temp, node = do_QueryInterface(inNode);
|
||||
|
||||
while (1)
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
// if it's editable, we're done
|
||||
if (mEditor->IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
node = temp;
|
||||
}
|
||||
*outNode = temp;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetPriorNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNextHTMLNode: returns the previous editable leaf node, if there is
|
||||
// one within the <body>
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inNode, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetNHTMLextNode: same as above but takes {parent,offset} instead of node
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode)
|
||||
{
|
||||
if (!outNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = mEditor->GetNextNode(inParent, inOffset, PR_TRUE, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsFirst || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsFirst = PR_FALSE;
|
||||
|
||||
// find first editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, firstChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetFirstEditableChild(parent, &firstChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsFirst = (firstChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutIsLast || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutIsLast = PR_FALSE;
|
||||
|
||||
// find last editable child and compare it to aNode
|
||||
nsCOMPtr<nsIDOMNode> parent, lastChild;
|
||||
nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!parent) return NS_ERROR_FAILURE;
|
||||
res = GetLastEditableChild(parent, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
*aOutIsLast = (lastChild.get() == aNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutFirstChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutFirstChild = nsnull;
|
||||
|
||||
// find first editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetNextSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutFirstChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild)
|
||||
{
|
||||
// check parms
|
||||
if (!aOutLastChild || !aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// init out parms
|
||||
*aOutLastChild = nsnull;
|
||||
|
||||
// find last editable child
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
nsresult res = aNode->GetLastChild(getter_AddRefs(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
while (child && !mEditor->IsEditable(child))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
res = child->GetPreviousSibling(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!tmp) return NS_ERROR_FAILURE;
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
*aOutLastChild = child;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsMozBR");
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
nsresult
|
||||
nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode)
|
||||
{
|
||||
if (!inParent || !outBRNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = mEditor->CreateBR(inParent, inOffset, outBRNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// give it special moz attr
|
||||
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(*outBRNode);
|
||||
if (brElem)
|
||||
{
|
||||
res = mEditor->SetAttribute(brElem, "type", "_moz");
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -200,6 +200,28 @@ protected:
|
|||
const nsString *aInString,
|
||||
TypeInState aTypeInState);
|
||||
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
||||
nsresult IsFirstEditableChild( nsIDOMNode *aNode, PRBool *aOutIsFirst);
|
||||
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
|
||||
// data
|
||||
nsHTMLEditor *mEditor; // note that we do not refcount the editor
|
||||
nsString mPasswordText; // a buffer we use to store the real value of password editors
|
||||
|
|
Загрузка…
Ссылка в новой задаче