mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
fixes for:
61232 - Caret comes back to previous line after creating paragraph 54520 - Extra break with list items 54539 - Disappearing numbered list with outdent 60867 - Composer adds extra break when round-tripping empty document through View Source 62347 - Selecting Body Text doesn't work inside other blocks that have embedding breaks
This commit is contained in:
parent
754d037891
commit
bc37219a9a
@ -2108,41 +2108,10 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
|
||||
}
|
||||
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find what we want to make a list out of.
|
||||
if (listCount == 1)
|
||||
{
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
|
||||
|
||||
while (nsHTMLEditUtils::IsDiv(curNode)
|
||||
|| nsHTMLEditUtils::IsList(curNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
// dive as long as there is only one child, and it is a list, div, blockquote
|
||||
PRUint32 numChildren;
|
||||
res = mHTMLEditor->CountEditableChildren(curNode, numChildren);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (numChildren == 1)
|
||||
{
|
||||
// keep diving
|
||||
nsCOMPtr <nsIDOMNode> tmpNode = nsEditor::GetChildAt(curNode, 0);
|
||||
if (nsHTMLEditUtils::IsDiv(tmpNode)
|
||||
|| nsHTMLEditUtils::IsList(tmpNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(tmpNode))
|
||||
{
|
||||
// check editablility XXX floppy moose
|
||||
curNode = tmpNode;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// we've found innermost list/blockquote/div:
|
||||
// replace the one node in the array with this node
|
||||
isupports = do_QueryInterface(curNode);
|
||||
arrayOfNodes->ReplaceElementAt(isupports, 0);
|
||||
}
|
||||
// then look inside of it until we find inner list or content.
|
||||
|
||||
res = LookInsideDivBQandList(arrayOfNodes);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Next we detect all the transitions in the array, where a transition
|
||||
// means that adjacent nodes in the array don't have the same parent.
|
||||
@ -2209,7 +2178,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = ConvertListType(curNode, address_of(newBlock), *aListType, itemType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(newBlock);
|
||||
res = mHTMLEditor->RemoveBlockContainer(newBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
@ -2358,7 +2327,7 @@ nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
||||
|
||||
// use these ranges to contruct a list of nodes to act on.
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, address_of(arrayOfNodes), kMakeList);
|
||||
res = GetListActionNodes(address_of(arrayOfNodes), PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Remove all non-editable nodes. Leave them be.
|
||||
@ -2479,6 +2448,9 @@ nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
|
||||
nsString tString(*aBlockType);
|
||||
if (tString.EqualsWithConversion("blockquote"))
|
||||
res = MakeBlockquote(arrayOfNodes);
|
||||
else if (tString.EqualsWithConversion("normal") ||
|
||||
tString.IsEmpty() )
|
||||
res = RemoveBlockStyle(arrayOfNodes);
|
||||
else
|
||||
res = ApplyBlockStyle(arrayOfNodes, aBlockType);
|
||||
return res;
|
||||
@ -2660,20 +2632,15 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// use these ranges to contruct a list of nodes to act on.
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, address_of(arrayOfNodes), kOutdent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Next we detect all the transitions in the array, where a transition
|
||||
// means that adjacent nodes in the array don't have the same parent.
|
||||
|
||||
nsVoidArray transitionList;
|
||||
res = MakeTransitionList(arrayOfNodes, &transitionList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ok, now go through all the nodes and remove a level of blockquoting,
|
||||
// or whatever is appropriate. Wohoo!
|
||||
|
||||
nsCOMPtr<nsIDOMNode> curBlockQuote, firstBQChild, lastBQChild;
|
||||
PRUint32 listCount;
|
||||
PRInt32 i;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
@ -2687,78 +2654,175 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (nsHTMLEditUtils::IsList(curParent)) // move node out of list
|
||||
// is it a blockquote?
|
||||
if (nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
// if it is a blockquote, remove it.
|
||||
// So we need to finish up dealng with any curBlockQuote first.
|
||||
if (curBlockQuote)
|
||||
{
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
}
|
||||
else // we are moving a list item, but not whole list
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(curNode, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
while (child)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsListItem(child))
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(child, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(child))
|
||||
{
|
||||
// We have an embedded list, so move it out from under the
|
||||
// parent list. Be sure to put it after the parent list
|
||||
// because this loop iterates backwards through the parent's
|
||||
// list of children.
|
||||
|
||||
res = mHTMLEditor->MoveNode(child, curParent, offset + 1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any non- list items for now
|
||||
res = mHTMLEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
continue;
|
||||
}
|
||||
else if (transitionList[i]) // not list related - look for enclosing blockquotes and remove
|
||||
// is it a list item?
|
||||
if (nsHTMLEditUtils::IsListItem(curNode))
|
||||
{
|
||||
// look for a blockquote somewhere above us and remove it.
|
||||
// this is a hack until i think about outdent for real.
|
||||
nsCOMPtr<nsIDOMNode> n = curNode;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
while (!nsTextEditUtils::IsBody(n))
|
||||
// if it is a list item, that means we are not outdenting whole list.
|
||||
// So we need to finish up dealng with any curBlockQuote, and then
|
||||
// pop this list item.
|
||||
if (curBlockQuote)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
res = AddTerminatingBR(n);
|
||||
if (NS_FAILED(res)) return res;
|
||||
mHTMLEditor->RemoveContainer(n);
|
||||
break;
|
||||
}
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
n = tmp;
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
}
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(curNode, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
continue;
|
||||
}
|
||||
// do we have a blockquote that we are already committed to removing?
|
||||
if (curBlockQuote)
|
||||
{
|
||||
// if so, is this node a descendant?
|
||||
if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlockQuote))
|
||||
{
|
||||
lastBQChild = curNode;
|
||||
continue; // then we dont need to do anything different for this node
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, we have progressed beyond end of curBlockQuote,
|
||||
// so lets handle it now. We need to remove the portion of
|
||||
// curBlockQuote that contains [firstBQChild - lastBQChild].
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
// fall out and handle curNode
|
||||
}
|
||||
}
|
||||
|
||||
// are we inside a blockquote?
|
||||
nsCOMPtr<nsIDOMNode> n = curNode;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
while (!nsTextEditUtils::IsBody(n))
|
||||
{
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
n = tmp;
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
// if so, remember it, and remember first node we are taking out of it.
|
||||
curBlockQuote = n;
|
||||
firstBQChild = curNode;
|
||||
lastBQChild = curNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curBlockQuote)
|
||||
{
|
||||
// could not find an enclosing blockquote for this node. handle list cases.
|
||||
if (nsHTMLEditUtils::IsList(curParent)) // move node out of list
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
{
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// handled list item case above
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
while (child)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsListItem(child))
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(child, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(child))
|
||||
{
|
||||
// We have an embedded list, so move it out from under the
|
||||
// parent list. Be sure to put it after the parent list
|
||||
// because this loop iterates backwards through the parent's
|
||||
// list of children.
|
||||
|
||||
res = mHTMLEditor->MoveNode(child, curParent, offset + 1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any non- list items for now
|
||||
res = mHTMLEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curBlockQuote)
|
||||
{
|
||||
// we have a blockquote we haven't finished handling
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ConvertListType: convert list type and list item type.
|
||||
//
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemovePartOfBlock(nsIDOMNode *aBlock,
|
||||
nsIDOMNode *aStartChild,
|
||||
nsIDOMNode *aEndChild)
|
||||
{
|
||||
if (!aBlock || !aStartChild || !aEndChild)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startParent, endParent, leftNode, rightNode;
|
||||
PRInt32 startOffset, endOffset, offset;
|
||||
nsresult res;
|
||||
|
||||
// get split point location
|
||||
res = nsEditor::GetNodeLocation(aStartChild, address_of(startParent), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// do the splits!
|
||||
res = mHTMLEditor->SplitNodeDeep(aBlock, startParent, startOffset, &offset,
|
||||
PR_TRUE, address_of(leftNode), address_of(rightNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (rightNode) aBlock = rightNode;
|
||||
|
||||
// get split point location
|
||||
res = nsEditor::GetNodeLocation(aEndChild, address_of(endParent), &endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
endOffset++; // want to be after lastBQChild
|
||||
|
||||
// do the splits!
|
||||
res = mHTMLEditor->SplitNodeDeep(aBlock, endParent, endOffset, &offset,
|
||||
PR_TRUE, address_of(leftNode), address_of(rightNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (leftNode) aBlock = leftNode;
|
||||
|
||||
// get rid of part of blockquote we are outdenting
|
||||
res = mHTMLEditor->RemoveBlockContainer(aBlock);
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ConvertListType: convert list type and list item type.
|
||||
@ -3891,6 +3955,23 @@ nsHTMLEditRules::GetNodesForOperation(nsISupportsArray *inArrayOfRanges,
|
||||
}
|
||||
}
|
||||
}
|
||||
// outdent should look inside of divs.
|
||||
if (inOperationType == kOutdent)
|
||||
{
|
||||
PRUint32 listCount;
|
||||
(*outArrayOfNodes)->Count(&listCount);
|
||||
for (i=(PRInt32)listCount-1; i>=0; i--)
|
||||
{
|
||||
isupports = dont_AddRef((*outArrayOfNodes)->ElementAt(i));
|
||||
nsCOMPtr<nsIDOMNode> node( do_QueryInterface(isupports) );
|
||||
if (nsHTMLEditUtils::IsDiv(node))
|
||||
{
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
res = GetInnerContent(node, *outArrayOfNodes, PR_FALSE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// post process the list to break up inline containers that contain br's.
|
||||
@ -4057,15 +4138,77 @@ nsHTMLEditRules::GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes,
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
}
|
||||
|
||||
// scan for table elements. If we find table elements other than table,
|
||||
// scan for table elements and divs. If we find table elements other than table,
|
||||
// replace it with a list of any editable non-table content.
|
||||
if (nsHTMLEditUtils::IsTableElement(testNode) && !nsHTMLEditUtils::IsTable(testNode))
|
||||
if ( (nsHTMLEditUtils::IsTableElement(testNode) && !nsHTMLEditUtils::IsTable(testNode))
|
||||
|| nsHTMLEditUtils::IsDiv(testNode) )
|
||||
{
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
res = GetInnerContent(testNode, *outArrayOfNodes, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find inner list or content.
|
||||
res = LookInsideDivBQandList(*outArrayOfNodes);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// LookInsideDivBQandList:
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::LookInsideDivBQandList(nsISupportsArray *aNodeArray)
|
||||
{
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find inner list or content.
|
||||
nsresult res = NS_OK;
|
||||
PRUint32 listCount;
|
||||
aNodeArray->Count(&listCount);
|
||||
if (listCount == 1)
|
||||
{
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(aNodeArray->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
|
||||
|
||||
while (nsHTMLEditUtils::IsDiv(curNode)
|
||||
|| nsHTMLEditUtils::IsList(curNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
// dive as long as there is only one child, and it is a list, div, blockquote
|
||||
PRUint32 numChildren;
|
||||
res = mHTMLEditor->CountEditableChildren(curNode, numChildren);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (numChildren == 1)
|
||||
{
|
||||
// keep diving
|
||||
nsCOMPtr <nsIDOMNode> tmpNode = nsEditor::GetChildAt(curNode, 0);
|
||||
if (nsHTMLEditUtils::IsDiv(tmpNode)
|
||||
|| nsHTMLEditUtils::IsList(tmpNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(tmpNode))
|
||||
{
|
||||
// check editablility XXX floppy moose
|
||||
curNode = tmpNode;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// we've found innermost list/blockquote/div:
|
||||
// replace the one node in the array with these nodes
|
||||
aNodeArray->RemoveElementAt(0);
|
||||
if ((nsHTMLEditUtils::IsDiv(curNode) || nsHTMLEditUtils::IsBlockquote(curNode)))
|
||||
{
|
||||
res = GetInnerContent(curNode, aNodeArray, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsISupports> isuports (do_QueryInterface(curNode));
|
||||
res = aNodeArray->AppendElement(isuports);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4769,6 +4912,144 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveBlockStyle: make the list nodes have no special block type.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveBlockStyle(nsISupportsArray *arrayOfNodes)
|
||||
{
|
||||
// intent of this routine is to be used for converting to/from
|
||||
// headers, paragraphs, pre, and address. Those blocks
|
||||
// that pretty much just contain inline things...
|
||||
|
||||
if (!arrayOfNodes) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> curNode, curParent, curBlock, firstNode, lastNode;
|
||||
PRInt32 offset;
|
||||
PRUint32 listCount;
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
PRUint32 i;
|
||||
for (i=0; i<listCount; i++)
|
||||
{
|
||||
// get the node to act on, and it's location
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(i));
|
||||
curNode = do_QueryInterface(isupports);
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsAutoString curNodeTag;
|
||||
nsEditor::GetTagString(curNode, curNodeTag);
|
||||
curNodeTag.ToLowerCase();
|
||||
|
||||
// if curNode is a address, p, header, address, or pre, remove it
|
||||
if ((curNodeTag.EqualsWithConversion("pre")) ||
|
||||
(curNodeTag.EqualsWithConversion("p")) ||
|
||||
(curNodeTag.EqualsWithConversion("h1")) ||
|
||||
(curNodeTag.EqualsWithConversion("h2")) ||
|
||||
(curNodeTag.EqualsWithConversion("h3")) ||
|
||||
(curNodeTag.EqualsWithConversion("h4")) ||
|
||||
(curNodeTag.EqualsWithConversion("h5")) ||
|
||||
(curNodeTag.EqualsWithConversion("h6")) ||
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
// remove curent block
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if ((curNodeTag.EqualsWithConversion("table")) ||
|
||||
(curNodeTag.EqualsWithConversion("tbody")) ||
|
||||
(curNodeTag.EqualsWithConversion("tr")) ||
|
||||
(curNodeTag.EqualsWithConversion("td")) ||
|
||||
(curNodeTag.EqualsWithConversion("ol")) ||
|
||||
(curNodeTag.EqualsWithConversion("ul")) ||
|
||||
(curNodeTag.EqualsWithConversion("dl")) ||
|
||||
(curNodeTag.EqualsWithConversion("li")) ||
|
||||
(curNodeTag.EqualsWithConversion("blockquote")) ||
|
||||
(curNodeTag.EqualsWithConversion("div")))
|
||||
{
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
// recursion time
|
||||
nsCOMPtr<nsISupportsArray> childArray;
|
||||
res = GetChildNodesForOperation(curNode, address_of(childArray));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveBlockStyle(childArray);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (IsInlineNode(curNode))
|
||||
{
|
||||
if (curBlock)
|
||||
{
|
||||
// if so, is this node a descendant?
|
||||
if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlock))
|
||||
{
|
||||
lastNode = curNode;
|
||||
continue; // then we dont need to do anything different for this node
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, we have progressed beyond end of curBlock,
|
||||
// so lets handle it now. We need to remove the portion of
|
||||
// curBlock that contains [firstNode - lastNode].
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
// fall out and handle curNode
|
||||
}
|
||||
}
|
||||
curBlock = mHTMLEditor->GetBlockNodeParent(curNode);
|
||||
if ((curNodeTag.EqualsWithConversion("pre")) ||
|
||||
(curNodeTag.EqualsWithConversion("p")) ||
|
||||
(curNodeTag.EqualsWithConversion("h1")) ||
|
||||
(curNodeTag.EqualsWithConversion("h2")) ||
|
||||
(curNodeTag.EqualsWithConversion("h3")) ||
|
||||
(curNodeTag.EqualsWithConversion("h4")) ||
|
||||
(curNodeTag.EqualsWithConversion("h5")) ||
|
||||
(curNodeTag.EqualsWithConversion("h6")) ||
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
firstNode = curNode;
|
||||
lastNode = curNode;
|
||||
}
|
||||
else
|
||||
curBlock = 0; // not a block kind that we care about.
|
||||
}
|
||||
else
|
||||
{ // some node that is already sans block style. skip over it and
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ApplyBlockStyle: do whatever it takes to make the list of nodes into
|
||||
// one or more blocks of type blockTag.
|
||||
@ -4786,15 +5067,8 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
nsCOMPtr<nsIDOMNode> curNode, curParent, curBlock, newBlock;
|
||||
PRInt32 offset;
|
||||
PRUint32 listCount;
|
||||
PRBool bNoParent = PR_FALSE;
|
||||
|
||||
// we special case an empty tag name to mean "remove block parents".
|
||||
// This is used for the "normal" paragraph style in mail-compose
|
||||
nsString tString(*aBlockTag);////MJUDGE SCC NEED HELP
|
||||
if (tString.IsEmpty() ||
|
||||
!Compare(tString,NS_LITERAL_STRING("normal"),nsCaseInsensitiveStringComparator()))
|
||||
bNoParent = PR_TRUE;
|
||||
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
PRUint32 i;
|
||||
@ -4810,13 +5084,13 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
curNodeTag.ToLowerCase();
|
||||
|
||||
// is it already the right kind of block?
|
||||
if (!bNoParent && curNodeTag == *aBlockTag)
|
||||
if (curNodeTag == *aBlockTag)
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
continue; // do nothing to this block
|
||||
}
|
||||
|
||||
// if curNode is a mozdiv, p, header, address, or pre, replace
|
||||
// if curNode is a address, p, header, address, or pre, replace
|
||||
// it with a new block of correct type.
|
||||
// xxx floppy moose: pre cant hold everything the others can
|
||||
if (nsHTMLEditUtils::IsMozDiv(curNode) ||
|
||||
@ -4831,17 +5105,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (bNoParent)
|
||||
{
|
||||
// make sure we have a normal br at end of block
|
||||
res = AddTerminatingBR(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), *aBlockTag);
|
||||
}
|
||||
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), *aBlockTag);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if ((curNodeTag.EqualsWithConversion("table")) ||
|
||||
@ -4850,9 +5114,10 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
(curNodeTag.EqualsWithConversion("td")) ||
|
||||
(curNodeTag.EqualsWithConversion("ol")) ||
|
||||
(curNodeTag.EqualsWithConversion("ul")) ||
|
||||
(curNodeTag.EqualsWithConversion("dl")) ||
|
||||
(curNodeTag.EqualsWithConversion("li")) ||
|
||||
(curNodeTag.EqualsWithConversion("blockquote")) ||
|
||||
(curNodeTag.EqualsWithConversion("div"))) // div's other than mozdivs
|
||||
(curNodeTag.EqualsWithConversion("div")))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
// recursion time
|
||||
@ -4867,11 +5132,8 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
else if (curNodeTag.EqualsWithConversion("br"))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (!bNoParent)
|
||||
{
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
|
||||
@ -4882,7 +5144,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
// arrayOfNodes is contructed, but some additional logic should
|
||||
// be added here if that should change
|
||||
|
||||
else if (IsInlineNode(curNode) && !bNoParent)
|
||||
else if (IsInlineNode(curNode))
|
||||
{
|
||||
// if curNode is a non editable, drop it if we are going to <pre>
|
||||
if (!Compare(tString,NS_LITERAL_STRING("pre"),nsCaseInsensitiveStringComparator())
|
||||
@ -4958,43 +5220,6 @@ nsHTMLEditRules::SplitAsNeeded(const nsAReadableString *aTag,
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AddTerminatingBR: place an ordinary br node at the end of aBlock,
|
||||
// if it doens't already have one. If it has a moz-BR,
|
||||
// simply convertit to a normal br.
|
||||
nsresult
|
||||
nsHTMLEditRules::AddTerminatingBR(nsIDOMNode *aBlock)
|
||||
{
|
||||
if (!aBlock) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> last;
|
||||
nsresult res = mHTMLEditor->GetLastEditableLeaf(aBlock, address_of(last));
|
||||
if (last && nsTextEditUtils::IsBreak(last))
|
||||
{
|
||||
if (nsTextEditUtils::IsMozBR(last))
|
||||
{
|
||||
// need to convert a br
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(last);
|
||||
res = mHTMLEditor->RemoveAttribute(elem, NS_ConvertASCIItoUCS2("type"));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else // we have what we want, we're done
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else // need to add a br
|
||||
{
|
||||
PRUint32 len;
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mHTMLEditor->GetLengthOfDOMNode(aBlock, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->CreateBR(aBlock, len, address_of(brNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// JoinNodesSmart: join two nodes, doing whatever makes sense for their
|
||||
// children (which often means joining them, too).
|
||||
@ -5744,9 +5969,7 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
||||
if (!nsHTMLEditUtils::IsList(curParPar)
|
||||
&& nsHTMLEditUtils::IsListItem(curNode))
|
||||
{
|
||||
res = AddTerminatingBR(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
*aOutOfList = PR_TRUE;
|
||||
}
|
||||
@ -5788,7 +6011,7 @@ nsHTMLEditRules::RemoveListStructure(nsIDOMNode *aList)
|
||||
aList->GetFirstChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->DeleteNode(aList);
|
||||
res = mHTMLEditor->RemoveBlockContainer(aList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return res;
|
||||
@ -6128,12 +6351,3 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -122,6 +122,9 @@ protected:
|
||||
nsresult ReturnInParagraph(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult ReturnInListItem(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
nsresult AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
nsresult RemovePartOfBlock(nsIDOMNode *curBlockQuote,
|
||||
nsIDOMNode *firstBQChild,
|
||||
nsIDOMNode *lastBQChild);
|
||||
nsresult ConvertListType(nsIDOMNode *aList, nsCOMPtr<nsIDOMNode> *outList, const nsAReadableString& aListType, const nsAReadableString& aItemType);
|
||||
nsresult CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocument *aDoc);
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
@ -155,12 +158,14 @@ protected:
|
||||
nsresult GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aEntireList, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD);
|
||||
nsresult GetParagraphFormatNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult LookInsideDivBQandList(nsISupportsArray *aNodeArray);
|
||||
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
|
||||
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes);
|
||||
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
|
||||
nsresult MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
nsVoidArray *inTransitionArray);
|
||||
nsresult RemoveBlockStyle(nsISupportsArray *arrayOfNodes);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadableString *aBlockTag);
|
||||
nsresult MakeBlockquote(nsISupportsArray *arrayOfNodes);
|
||||
nsresult SplitAsNeeded(const nsAReadableString *aTag, nsCOMPtr<nsIDOMNode> *inOutParent, PRInt32 *inOutOffset);
|
||||
|
@ -4095,6 +4095,103 @@ nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveBlockContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode. In addition, INSERT ANY BR's NEEDED
|
||||
// TO PRESERVE IDENTITY OF REMOVED BLOCK.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditor::RemoveBlockContainer(nsIDOMNode *inNode)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> sibling, child, unused;
|
||||
|
||||
// Two possibilities: the container cold be empty of editable content.
|
||||
// If that is the case, we need to compare what is before and after inNode
|
||||
// to determine if we need a br.
|
||||
// Or it could not be empty, in which case we have to compare previous
|
||||
// sibling and first child to determine if we need a leading br,
|
||||
// and compare following sibling and last child to determine if we need a
|
||||
// trailing br.
|
||||
|
||||
res = GetFirstEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (child) // the case of inNode not being empty
|
||||
{
|
||||
// we need a br at start unless:
|
||||
// 1) previous sibling of inNode is a block, OR
|
||||
// 2) previous sibling of inNode is a br, OR
|
||||
// 3) first child of inNode is a block OR
|
||||
// 4) either is null
|
||||
|
||||
res = GetPriorHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
res = GetFirstEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (child && !IsBlockNode(child))
|
||||
{
|
||||
// insert br node
|
||||
res = CreateBR(inNode, 0, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// we need a br at end unless:
|
||||
// 1) following sibling of inNode is a block, OR
|
||||
// 2) last child of inNode is a block, OR
|
||||
// 3) last child of inNode is a block OR
|
||||
// 4) either is null
|
||||
|
||||
res = GetNextHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling))
|
||||
{
|
||||
res = GetLastEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (child && !IsBlockNode(child) && !nsTextEditUtils::IsBreak(child))
|
||||
{
|
||||
// insert br node
|
||||
PRUint32 len;
|
||||
res = GetLengthOfDOMNode(inNode, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = CreateBR(inNode, (PRInt32)len, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // the case of inNode being empty
|
||||
{
|
||||
// we need a br at start unless:
|
||||
// 1) previous sibling of inNode is a block, OR
|
||||
// 2) previous sibling of inNode is a br, OR
|
||||
// 3) following sibling of inNode is a block, OR
|
||||
// 4) following sibling of inNode is a br OR
|
||||
// 5) either is null
|
||||
res = GetPriorHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
res = GetNextHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
// insert br node
|
||||
res = CreateBR(inNode, 0, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now remove container
|
||||
return RemoveContainer(inNode);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
@ -4163,7 +4260,7 @@ nsHTMLEditor::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNo
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
if (!temp) return NS_OK; // return null sibling
|
||||
// if it's editable, we're done
|
||||
if (IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
|
@ -642,6 +642,7 @@ protected:
|
||||
PRBool HasMatchingAttributes(nsIDOMNode *aNode1,
|
||||
nsIDOMNode *aNode2);
|
||||
|
||||
nsresult RemoveBlockContainer(nsIDOMNode *inNode);
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
@ -2108,41 +2108,10 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
|
||||
}
|
||||
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find what we want to make a list out of.
|
||||
if (listCount == 1)
|
||||
{
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
|
||||
|
||||
while (nsHTMLEditUtils::IsDiv(curNode)
|
||||
|| nsHTMLEditUtils::IsList(curNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
// dive as long as there is only one child, and it is a list, div, blockquote
|
||||
PRUint32 numChildren;
|
||||
res = mHTMLEditor->CountEditableChildren(curNode, numChildren);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (numChildren == 1)
|
||||
{
|
||||
// keep diving
|
||||
nsCOMPtr <nsIDOMNode> tmpNode = nsEditor::GetChildAt(curNode, 0);
|
||||
if (nsHTMLEditUtils::IsDiv(tmpNode)
|
||||
|| nsHTMLEditUtils::IsList(tmpNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(tmpNode))
|
||||
{
|
||||
// check editablility XXX floppy moose
|
||||
curNode = tmpNode;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// we've found innermost list/blockquote/div:
|
||||
// replace the one node in the array with this node
|
||||
isupports = do_QueryInterface(curNode);
|
||||
arrayOfNodes->ReplaceElementAt(isupports, 0);
|
||||
}
|
||||
// then look inside of it until we find inner list or content.
|
||||
|
||||
res = LookInsideDivBQandList(arrayOfNodes);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Next we detect all the transitions in the array, where a transition
|
||||
// means that adjacent nodes in the array don't have the same parent.
|
||||
@ -2209,7 +2178,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = ConvertListType(curNode, address_of(newBlock), *aListType, itemType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(newBlock);
|
||||
res = mHTMLEditor->RemoveBlockContainer(newBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
@ -2358,7 +2327,7 @@ nsHTMLEditRules::WillRemoveList(nsISelection *aSelection,
|
||||
|
||||
// use these ranges to contruct a list of nodes to act on.
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, address_of(arrayOfNodes), kMakeList);
|
||||
res = GetListActionNodes(address_of(arrayOfNodes), PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Remove all non-editable nodes. Leave them be.
|
||||
@ -2479,6 +2448,9 @@ nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
|
||||
nsString tString(*aBlockType);
|
||||
if (tString.EqualsWithConversion("blockquote"))
|
||||
res = MakeBlockquote(arrayOfNodes);
|
||||
else if (tString.EqualsWithConversion("normal") ||
|
||||
tString.IsEmpty() )
|
||||
res = RemoveBlockStyle(arrayOfNodes);
|
||||
else
|
||||
res = ApplyBlockStyle(arrayOfNodes, aBlockType);
|
||||
return res;
|
||||
@ -2660,20 +2632,15 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// use these ranges to contruct a list of nodes to act on.
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, address_of(arrayOfNodes), kOutdent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Next we detect all the transitions in the array, where a transition
|
||||
// means that adjacent nodes in the array don't have the same parent.
|
||||
|
||||
nsVoidArray transitionList;
|
||||
res = MakeTransitionList(arrayOfNodes, &transitionList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ok, now go through all the nodes and remove a level of blockquoting,
|
||||
// or whatever is appropriate. Wohoo!
|
||||
|
||||
nsCOMPtr<nsIDOMNode> curBlockQuote, firstBQChild, lastBQChild;
|
||||
PRUint32 listCount;
|
||||
PRInt32 i;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
@ -2687,78 +2654,175 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (nsHTMLEditUtils::IsList(curParent)) // move node out of list
|
||||
// is it a blockquote?
|
||||
if (nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
// if it is a blockquote, remove it.
|
||||
// So we need to finish up dealng with any curBlockQuote first.
|
||||
if (curBlockQuote)
|
||||
{
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
}
|
||||
else // we are moving a list item, but not whole list
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(curNode, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
while (child)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsListItem(child))
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(child, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(child))
|
||||
{
|
||||
// We have an embedded list, so move it out from under the
|
||||
// parent list. Be sure to put it after the parent list
|
||||
// because this loop iterates backwards through the parent's
|
||||
// list of children.
|
||||
|
||||
res = mHTMLEditor->MoveNode(child, curParent, offset + 1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any non- list items for now
|
||||
res = mHTMLEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
continue;
|
||||
}
|
||||
else if (transitionList[i]) // not list related - look for enclosing blockquotes and remove
|
||||
// is it a list item?
|
||||
if (nsHTMLEditUtils::IsListItem(curNode))
|
||||
{
|
||||
// look for a blockquote somewhere above us and remove it.
|
||||
// this is a hack until i think about outdent for real.
|
||||
nsCOMPtr<nsIDOMNode> n = curNode;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
while (!nsTextEditUtils::IsBody(n))
|
||||
// if it is a list item, that means we are not outdenting whole list.
|
||||
// So we need to finish up dealng with any curBlockQuote, and then
|
||||
// pop this list item.
|
||||
if (curBlockQuote)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
res = AddTerminatingBR(n);
|
||||
if (NS_FAILED(res)) return res;
|
||||
mHTMLEditor->RemoveContainer(n);
|
||||
break;
|
||||
}
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
n = tmp;
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
}
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(curNode, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
continue;
|
||||
}
|
||||
// do we have a blockquote that we are already committed to removing?
|
||||
if (curBlockQuote)
|
||||
{
|
||||
// if so, is this node a descendant?
|
||||
if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlockQuote))
|
||||
{
|
||||
lastBQChild = curNode;
|
||||
continue; // then we dont need to do anything different for this node
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, we have progressed beyond end of curBlockQuote,
|
||||
// so lets handle it now. We need to remove the portion of
|
||||
// curBlockQuote that contains [firstBQChild - lastBQChild].
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlockQuote = 0; firstBQChild = 0; lastBQChild = 0;
|
||||
// fall out and handle curNode
|
||||
}
|
||||
}
|
||||
|
||||
// are we inside a blockquote?
|
||||
nsCOMPtr<nsIDOMNode> n = curNode;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
while (!nsTextEditUtils::IsBody(n))
|
||||
{
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
n = tmp;
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
// if so, remember it, and remember first node we are taking out of it.
|
||||
curBlockQuote = n;
|
||||
firstBQChild = curNode;
|
||||
lastBQChild = curNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!curBlockQuote)
|
||||
{
|
||||
// could not find an enclosing blockquote for this node. handle list cases.
|
||||
if (nsHTMLEditUtils::IsList(curParent)) // move node out of list
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
{
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// handled list item case above
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(curNode)) // node is a list, but parent is non-list: move list items out
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
while (child)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsListItem(child))
|
||||
{
|
||||
PRBool bOutOfList;
|
||||
res = PopListItem(child, &bOutOfList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(child))
|
||||
{
|
||||
// We have an embedded list, so move it out from under the
|
||||
// parent list. Be sure to put it after the parent list
|
||||
// because this loop iterates backwards through the parent's
|
||||
// list of children.
|
||||
|
||||
res = mHTMLEditor->MoveNode(child, curParent, offset + 1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any non- list items for now
|
||||
res = mHTMLEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
curNode->GetLastChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curBlockQuote)
|
||||
{
|
||||
// we have a blockquote we haven't finished handling
|
||||
res = RemovePartOfBlock(curBlockQuote, firstBQChild, lastBQChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ConvertListType: convert list type and list item type.
|
||||
//
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemovePartOfBlock(nsIDOMNode *aBlock,
|
||||
nsIDOMNode *aStartChild,
|
||||
nsIDOMNode *aEndChild)
|
||||
{
|
||||
if (!aBlock || !aStartChild || !aEndChild)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> startParent, endParent, leftNode, rightNode;
|
||||
PRInt32 startOffset, endOffset, offset;
|
||||
nsresult res;
|
||||
|
||||
// get split point location
|
||||
res = nsEditor::GetNodeLocation(aStartChild, address_of(startParent), &startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// do the splits!
|
||||
res = mHTMLEditor->SplitNodeDeep(aBlock, startParent, startOffset, &offset,
|
||||
PR_TRUE, address_of(leftNode), address_of(rightNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (rightNode) aBlock = rightNode;
|
||||
|
||||
// get split point location
|
||||
res = nsEditor::GetNodeLocation(aEndChild, address_of(endParent), &endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
endOffset++; // want to be after lastBQChild
|
||||
|
||||
// do the splits!
|
||||
res = mHTMLEditor->SplitNodeDeep(aBlock, endParent, endOffset, &offset,
|
||||
PR_TRUE, address_of(leftNode), address_of(rightNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (leftNode) aBlock = leftNode;
|
||||
|
||||
// get rid of part of blockquote we are outdenting
|
||||
res = mHTMLEditor->RemoveBlockContainer(aBlock);
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ConvertListType: convert list type and list item type.
|
||||
@ -3891,6 +3955,23 @@ nsHTMLEditRules::GetNodesForOperation(nsISupportsArray *inArrayOfRanges,
|
||||
}
|
||||
}
|
||||
}
|
||||
// outdent should look inside of divs.
|
||||
if (inOperationType == kOutdent)
|
||||
{
|
||||
PRUint32 listCount;
|
||||
(*outArrayOfNodes)->Count(&listCount);
|
||||
for (i=(PRInt32)listCount-1; i>=0; i--)
|
||||
{
|
||||
isupports = dont_AddRef((*outArrayOfNodes)->ElementAt(i));
|
||||
nsCOMPtr<nsIDOMNode> node( do_QueryInterface(isupports) );
|
||||
if (nsHTMLEditUtils::IsDiv(node))
|
||||
{
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
res = GetInnerContent(node, *outArrayOfNodes, PR_FALSE, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// post process the list to break up inline containers that contain br's.
|
||||
@ -4057,15 +4138,77 @@ nsHTMLEditRules::GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes,
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
}
|
||||
|
||||
// scan for table elements. If we find table elements other than table,
|
||||
// scan for table elements and divs. If we find table elements other than table,
|
||||
// replace it with a list of any editable non-table content.
|
||||
if (nsHTMLEditUtils::IsTableElement(testNode) && !nsHTMLEditUtils::IsTable(testNode))
|
||||
if ( (nsHTMLEditUtils::IsTableElement(testNode) && !nsHTMLEditUtils::IsTable(testNode))
|
||||
|| nsHTMLEditUtils::IsDiv(testNode) )
|
||||
{
|
||||
(*outArrayOfNodes)->RemoveElementAt(i);
|
||||
res = GetInnerContent(testNode, *outArrayOfNodes, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find inner list or content.
|
||||
res = LookInsideDivBQandList(*outArrayOfNodes);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// LookInsideDivBQandList:
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::LookInsideDivBQandList(nsISupportsArray *aNodeArray)
|
||||
{
|
||||
// if there is only one node in the array, and it is a list, div, or blockquote,
|
||||
// then look inside of it until we find inner list or content.
|
||||
nsresult res = NS_OK;
|
||||
PRUint32 listCount;
|
||||
aNodeArray->Count(&listCount);
|
||||
if (listCount == 1)
|
||||
{
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(aNodeArray->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
|
||||
|
||||
while (nsHTMLEditUtils::IsDiv(curNode)
|
||||
|| nsHTMLEditUtils::IsList(curNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(curNode))
|
||||
{
|
||||
// dive as long as there is only one child, and it is a list, div, blockquote
|
||||
PRUint32 numChildren;
|
||||
res = mHTMLEditor->CountEditableChildren(curNode, numChildren);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (numChildren == 1)
|
||||
{
|
||||
// keep diving
|
||||
nsCOMPtr <nsIDOMNode> tmpNode = nsEditor::GetChildAt(curNode, 0);
|
||||
if (nsHTMLEditUtils::IsDiv(tmpNode)
|
||||
|| nsHTMLEditUtils::IsList(tmpNode)
|
||||
|| nsHTMLEditUtils::IsBlockquote(tmpNode))
|
||||
{
|
||||
// check editablility XXX floppy moose
|
||||
curNode = tmpNode;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// we've found innermost list/blockquote/div:
|
||||
// replace the one node in the array with these nodes
|
||||
aNodeArray->RemoveElementAt(0);
|
||||
if ((nsHTMLEditUtils::IsDiv(curNode) || nsHTMLEditUtils::IsBlockquote(curNode)))
|
||||
{
|
||||
res = GetInnerContent(curNode, aNodeArray, PR_FALSE, PR_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsISupports> isuports (do_QueryInterface(curNode));
|
||||
res = aNodeArray->AppendElement(isuports);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4769,6 +4912,144 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveBlockStyle: make the list nodes have no special block type.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveBlockStyle(nsISupportsArray *arrayOfNodes)
|
||||
{
|
||||
// intent of this routine is to be used for converting to/from
|
||||
// headers, paragraphs, pre, and address. Those blocks
|
||||
// that pretty much just contain inline things...
|
||||
|
||||
if (!arrayOfNodes) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> curNode, curParent, curBlock, firstNode, lastNode;
|
||||
PRInt32 offset;
|
||||
PRUint32 listCount;
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
PRUint32 i;
|
||||
for (i=0; i<listCount; i++)
|
||||
{
|
||||
// get the node to act on, and it's location
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(i));
|
||||
curNode = do_QueryInterface(isupports);
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsAutoString curNodeTag;
|
||||
nsEditor::GetTagString(curNode, curNodeTag);
|
||||
curNodeTag.ToLowerCase();
|
||||
|
||||
// if curNode is a address, p, header, address, or pre, remove it
|
||||
if ((curNodeTag.EqualsWithConversion("pre")) ||
|
||||
(curNodeTag.EqualsWithConversion("p")) ||
|
||||
(curNodeTag.EqualsWithConversion("h1")) ||
|
||||
(curNodeTag.EqualsWithConversion("h2")) ||
|
||||
(curNodeTag.EqualsWithConversion("h3")) ||
|
||||
(curNodeTag.EqualsWithConversion("h4")) ||
|
||||
(curNodeTag.EqualsWithConversion("h5")) ||
|
||||
(curNodeTag.EqualsWithConversion("h6")) ||
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
// remove curent block
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if ((curNodeTag.EqualsWithConversion("table")) ||
|
||||
(curNodeTag.EqualsWithConversion("tbody")) ||
|
||||
(curNodeTag.EqualsWithConversion("tr")) ||
|
||||
(curNodeTag.EqualsWithConversion("td")) ||
|
||||
(curNodeTag.EqualsWithConversion("ol")) ||
|
||||
(curNodeTag.EqualsWithConversion("ul")) ||
|
||||
(curNodeTag.EqualsWithConversion("dl")) ||
|
||||
(curNodeTag.EqualsWithConversion("li")) ||
|
||||
(curNodeTag.EqualsWithConversion("blockquote")) ||
|
||||
(curNodeTag.EqualsWithConversion("div")))
|
||||
{
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
// recursion time
|
||||
nsCOMPtr<nsISupportsArray> childArray;
|
||||
res = GetChildNodesForOperation(curNode, address_of(childArray));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveBlockStyle(childArray);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (IsInlineNode(curNode))
|
||||
{
|
||||
if (curBlock)
|
||||
{
|
||||
// if so, is this node a descendant?
|
||||
if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlock))
|
||||
{
|
||||
lastNode = curNode;
|
||||
continue; // then we dont need to do anything different for this node
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise, we have progressed beyond end of curBlock,
|
||||
// so lets handle it now. We need to remove the portion of
|
||||
// curBlock that contains [firstNode - lastNode].
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
// fall out and handle curNode
|
||||
}
|
||||
}
|
||||
curBlock = mHTMLEditor->GetBlockNodeParent(curNode);
|
||||
if ((curNodeTag.EqualsWithConversion("pre")) ||
|
||||
(curNodeTag.EqualsWithConversion("p")) ||
|
||||
(curNodeTag.EqualsWithConversion("h1")) ||
|
||||
(curNodeTag.EqualsWithConversion("h2")) ||
|
||||
(curNodeTag.EqualsWithConversion("h3")) ||
|
||||
(curNodeTag.EqualsWithConversion("h4")) ||
|
||||
(curNodeTag.EqualsWithConversion("h5")) ||
|
||||
(curNodeTag.EqualsWithConversion("h6")) ||
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
firstNode = curNode;
|
||||
lastNode = curNode;
|
||||
}
|
||||
else
|
||||
curBlock = 0; // not a block kind that we care about.
|
||||
}
|
||||
else
|
||||
{ // some node that is already sans block style. skip over it and
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// process any partial progress saved
|
||||
if (curBlock)
|
||||
{
|
||||
res = RemovePartOfBlock(curBlock, firstNode, lastNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curBlock = 0; firstNode = 0; lastNode = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ApplyBlockStyle: do whatever it takes to make the list of nodes into
|
||||
// one or more blocks of type blockTag.
|
||||
@ -4786,15 +5067,8 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
nsCOMPtr<nsIDOMNode> curNode, curParent, curBlock, newBlock;
|
||||
PRInt32 offset;
|
||||
PRUint32 listCount;
|
||||
PRBool bNoParent = PR_FALSE;
|
||||
|
||||
// we special case an empty tag name to mean "remove block parents".
|
||||
// This is used for the "normal" paragraph style in mail-compose
|
||||
nsString tString(*aBlockTag);////MJUDGE SCC NEED HELP
|
||||
if (tString.IsEmpty() ||
|
||||
!Compare(tString,NS_LITERAL_STRING("normal"),nsCaseInsensitiveStringComparator()))
|
||||
bNoParent = PR_TRUE;
|
||||
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
PRUint32 i;
|
||||
@ -4810,13 +5084,13 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
curNodeTag.ToLowerCase();
|
||||
|
||||
// is it already the right kind of block?
|
||||
if (!bNoParent && curNodeTag == *aBlockTag)
|
||||
if (curNodeTag == *aBlockTag)
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
continue; // do nothing to this block
|
||||
}
|
||||
|
||||
// if curNode is a mozdiv, p, header, address, or pre, replace
|
||||
// if curNode is a address, p, header, address, or pre, replace
|
||||
// it with a new block of correct type.
|
||||
// xxx floppy moose: pre cant hold everything the others can
|
||||
if (nsHTMLEditUtils::IsMozDiv(curNode) ||
|
||||
@ -4831,17 +5105,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
(curNodeTag.EqualsWithConversion("address")))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (bNoParent)
|
||||
{
|
||||
// make sure we have a normal br at end of block
|
||||
res = AddTerminatingBR(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), *aBlockTag);
|
||||
}
|
||||
res = mHTMLEditor->ReplaceContainer(curNode, address_of(newBlock), *aBlockTag);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if ((curNodeTag.EqualsWithConversion("table")) ||
|
||||
@ -4850,9 +5114,10 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
(curNodeTag.EqualsWithConversion("td")) ||
|
||||
(curNodeTag.EqualsWithConversion("ol")) ||
|
||||
(curNodeTag.EqualsWithConversion("ul")) ||
|
||||
(curNodeTag.EqualsWithConversion("dl")) ||
|
||||
(curNodeTag.EqualsWithConversion("li")) ||
|
||||
(curNodeTag.EqualsWithConversion("blockquote")) ||
|
||||
(curNodeTag.EqualsWithConversion("div"))) // div's other than mozdivs
|
||||
(curNodeTag.EqualsWithConversion("div")))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
// recursion time
|
||||
@ -4867,11 +5132,8 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
else if (curNodeTag.EqualsWithConversion("br"))
|
||||
{
|
||||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (!bNoParent)
|
||||
{
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
|
||||
@ -4882,7 +5144,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
|
||||
// arrayOfNodes is contructed, but some additional logic should
|
||||
// be added here if that should change
|
||||
|
||||
else if (IsInlineNode(curNode) && !bNoParent)
|
||||
else if (IsInlineNode(curNode))
|
||||
{
|
||||
// if curNode is a non editable, drop it if we are going to <pre>
|
||||
if (!Compare(tString,NS_LITERAL_STRING("pre"),nsCaseInsensitiveStringComparator())
|
||||
@ -4958,43 +5220,6 @@ nsHTMLEditRules::SplitAsNeeded(const nsAReadableString *aTag,
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// AddTerminatingBR: place an ordinary br node at the end of aBlock,
|
||||
// if it doens't already have one. If it has a moz-BR,
|
||||
// simply convertit to a normal br.
|
||||
nsresult
|
||||
nsHTMLEditRules::AddTerminatingBR(nsIDOMNode *aBlock)
|
||||
{
|
||||
if (!aBlock) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode> last;
|
||||
nsresult res = mHTMLEditor->GetLastEditableLeaf(aBlock, address_of(last));
|
||||
if (last && nsTextEditUtils::IsBreak(last))
|
||||
{
|
||||
if (nsTextEditUtils::IsMozBR(last))
|
||||
{
|
||||
// need to convert a br
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(last);
|
||||
res = mHTMLEditor->RemoveAttribute(elem, NS_ConvertASCIItoUCS2("type"));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else // we have what we want, we're done
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else // need to add a br
|
||||
{
|
||||
PRUint32 len;
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mHTMLEditor->GetLengthOfDOMNode(aBlock, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->CreateBR(aBlock, len, address_of(brNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// JoinNodesSmart: join two nodes, doing whatever makes sense for their
|
||||
// children (which often means joining them, too).
|
||||
@ -5744,9 +5969,7 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
||||
if (!nsHTMLEditUtils::IsList(curParPar)
|
||||
&& nsHTMLEditUtils::IsListItem(curNode))
|
||||
{
|
||||
res = AddTerminatingBR(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->RemoveContainer(curNode);
|
||||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
*aOutOfList = PR_TRUE;
|
||||
}
|
||||
@ -5788,7 +6011,7 @@ nsHTMLEditRules::RemoveListStructure(nsIDOMNode *aList)
|
||||
aList->GetFirstChild(getter_AddRefs(child));
|
||||
}
|
||||
// delete the now-empty list
|
||||
res = mHTMLEditor->DeleteNode(aList);
|
||||
res = mHTMLEditor->RemoveBlockContainer(aList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return res;
|
||||
@ -6128,12 +6351,3 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -122,6 +122,9 @@ protected:
|
||||
nsresult ReturnInParagraph(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult ReturnInListItem(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
nsresult AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
nsresult RemovePartOfBlock(nsIDOMNode *curBlockQuote,
|
||||
nsIDOMNode *firstBQChild,
|
||||
nsIDOMNode *lastBQChild);
|
||||
nsresult ConvertListType(nsIDOMNode *aList, nsCOMPtr<nsIDOMNode> *outList, const nsAReadableString& aListType, const nsAReadableString& aItemType);
|
||||
nsresult CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocument *aDoc);
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
@ -155,12 +158,14 @@ protected:
|
||||
nsresult GetListActionNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aEntireList, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD);
|
||||
nsresult GetParagraphFormatNodes(nsCOMPtr<nsISupportsArray> *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE);
|
||||
nsresult LookInsideDivBQandList(nsISupportsArray *aNodeArray);
|
||||
nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange);
|
||||
nsresult BustUpInlinesAtBRs(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsISupportsArray> *outArrayOfNodes);
|
||||
nsCOMPtr<nsIDOMNode> GetHighestInlineParent(nsIDOMNode* aNode);
|
||||
nsresult MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
nsVoidArray *inTransitionArray);
|
||||
nsresult RemoveBlockStyle(nsISupportsArray *arrayOfNodes);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadableString *aBlockTag);
|
||||
nsresult MakeBlockquote(nsISupportsArray *arrayOfNodes);
|
||||
nsresult SplitAsNeeded(const nsAReadableString *aTag, nsCOMPtr<nsIDOMNode> *inOutParent, PRInt32 *inOutOffset);
|
||||
|
@ -4095,6 +4095,103 @@ nsHTMLEditor::SetSelectionAtDocumentStart(nsISelection *aSelection)
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveBlockContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode. In addition, INSERT ANY BR's NEEDED
|
||||
// TO PRESERVE IDENTITY OF REMOVED BLOCK.
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditor::RemoveBlockContainer(nsIDOMNode *inNode)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> sibling, child, unused;
|
||||
|
||||
// Two possibilities: the container cold be empty of editable content.
|
||||
// If that is the case, we need to compare what is before and after inNode
|
||||
// to determine if we need a br.
|
||||
// Or it could not be empty, in which case we have to compare previous
|
||||
// sibling and first child to determine if we need a leading br,
|
||||
// and compare following sibling and last child to determine if we need a
|
||||
// trailing br.
|
||||
|
||||
res = GetFirstEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (child) // the case of inNode not being empty
|
||||
{
|
||||
// we need a br at start unless:
|
||||
// 1) previous sibling of inNode is a block, OR
|
||||
// 2) previous sibling of inNode is a br, OR
|
||||
// 3) first child of inNode is a block OR
|
||||
// 4) either is null
|
||||
|
||||
res = GetPriorHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
res = GetFirstEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (child && !IsBlockNode(child))
|
||||
{
|
||||
// insert br node
|
||||
res = CreateBR(inNode, 0, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// we need a br at end unless:
|
||||
// 1) following sibling of inNode is a block, OR
|
||||
// 2) last child of inNode is a block, OR
|
||||
// 3) last child of inNode is a block OR
|
||||
// 4) either is null
|
||||
|
||||
res = GetNextHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling))
|
||||
{
|
||||
res = GetLastEditableChild(inNode, address_of(child));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (child && !IsBlockNode(child) && !nsTextEditUtils::IsBreak(child))
|
||||
{
|
||||
// insert br node
|
||||
PRUint32 len;
|
||||
res = GetLengthOfDOMNode(inNode, len);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = CreateBR(inNode, (PRInt32)len, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // the case of inNode being empty
|
||||
{
|
||||
// we need a br at start unless:
|
||||
// 1) previous sibling of inNode is a block, OR
|
||||
// 2) previous sibling of inNode is a br, OR
|
||||
// 3) following sibling of inNode is a block, OR
|
||||
// 4) following sibling of inNode is a br OR
|
||||
// 5) either is null
|
||||
res = GetPriorHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
res = GetNextHTMLSibling(inNode, address_of(sibling));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (sibling && !IsBlockNode(sibling) && !nsTextEditUtils::IsBreak(sibling))
|
||||
{
|
||||
// insert br node
|
||||
res = CreateBR(inNode, 0, address_of(unused));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now remove container
|
||||
return RemoveContainer(inNode);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// GetPriorHTMLSibling: returns the previous editable sibling, if there is
|
||||
// one within the parent
|
||||
@ -4163,7 +4260,7 @@ nsHTMLEditor::GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNo
|
||||
{
|
||||
res = node->GetNextSibling(getter_AddRefs(temp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!temp) return NS_ERROR_FAILURE;
|
||||
if (!temp) return NS_OK; // return null sibling
|
||||
// if it's editable, we're done
|
||||
if (IsEditable(temp)) break;
|
||||
// otherwise try again
|
||||
|
@ -642,6 +642,7 @@ protected:
|
||||
PRBool HasMatchingAttributes(nsIDOMNode *aNode1,
|
||||
nsIDOMNode *aNode2);
|
||||
|
||||
nsresult RemoveBlockContainer(nsIDOMNode *inNode);
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetPriorHTMLSibling(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
nsresult GetNextHTMLSibling(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode);
|
||||
|
Loading…
Reference in New Issue
Block a user