diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp
index cdbe3c45669..eb05631739e 100644
--- a/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -1346,6 +1346,14 @@ nsHTMLEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo
if (!blockParent) return NS_ERROR_FAILURE;
+ nsCOMPtr listItem = IsInListItem(blockParent);
+ if (listItem)
+ {
+ res = ReturnInListItem(aSelection, listItem, node, offset);
+ *aHandled = PR_TRUE;
+ return NS_OK;
+ }
+
// headers: close (or split) header
else if (nsHTMLEditUtils::IsHeader(blockParent))
{
@@ -1361,13 +1369,6 @@ nsHTMLEditRules::WillInsertBreak(nsISelection *aSelection, PRBool *aCancel, PRBo
return NS_OK;
}
- // list items: special rules to make new list items
- else if (nsHTMLEditUtils::IsListItem(blockParent))
- {
- res = ReturnInListItem(aSelection, blockParent, node, offset);
- *aHandled = PR_TRUE;
- return NS_OK;
- }
// its something else (body, div, td, ...): insert a normal br
else
{
@@ -2413,10 +2414,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
{
// this is a continuation of some inline nodes that belong together in
// the same list item. use prevListItem
- PRUint32 listItemLen;
- res = mHTMLEditor->GetLengthOfDOMNode(prevListItem, listItemLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, prevListItem, listItemLen);
+ res = mHTMLEditor->MoveNode(curNode, prevListItem, -1);
if (NS_FAILED(res)) return res;
}
else
@@ -2445,10 +2443,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
if (listItem) // if we made a new list item, deal with it
{
// tuck the listItem into the end of the active list
- PRUint32 listLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curList, listLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(listItem, curList, listLen);
+ res = mHTMLEditor->MoveNode(listItem, curList, -1);
if (NS_FAILED(res)) return res;
}
}
@@ -2782,19 +2777,10 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
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 put them in a blockquote,
// or whatever is appropriate. Wohoo!
PRInt32 i;
- nsCOMPtr curParent;
- nsCOMPtr curQuote;
- nsCOMPtr curList;
+ nsCOMPtr curParent, curQuote, curList, indentedLI, sibling;
PRUint32 listCount;
arrayOfNodes->Count(&listCount);
for (i=0; i<(PRInt32)listCount; i++)
@@ -2809,7 +2795,15 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
// some logic for putting list items into nested lists...
if (nsHTMLEditUtils::IsList(curParent))
{
- if (!curList || transitionList[i])
+ // check to see if curList is still appropriate. Which it is if
+ // curNode is still right after it in the same list.
+ if (curList)
+ {
+ sibling = nsnull;
+ mHTMLEditor->GetPriorHTMLSibling(curNode, address_of(sibling));
+ }
+
+ if (!curList || (sibling && sibling != curList) )
{
nsAutoString listTag;
nsEditor::GetTagString(curParent,listTag);
@@ -2824,43 +2818,71 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
mNewBlock = curList;
}
// tuck the node into the end of the active list
- PRUint32 listLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curList, listLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, curList, listLen);
+ res = mHTMLEditor->MoveNode(curNode, curList, -1);
if (NS_FAILED(res)) return res;
}
- else // not a list item, use blockquote
+ else // not a list item, use blockquote?
{
- // need to make a blockquote to put things in if we haven't already,
- // or if this node doesn't go in blockquote we used earlier.
- if (!curQuote) // || transitionList[i])
+ // if we are inside a list item, we dont want to blockquote, we want
+ // to sublist the list item. We may have several nodes listed in the
+ // array of nodes to act on, that are in the same list item. Since
+ // we only want to indent that li once, we must keep track of the most
+ // recent indented list item, and not indent it if we find another node
+ // to act on that is still inside the same li.
+ nsCOMPtr listitem=IsInListItem(curNode);
+ if (listitem)
{
- nsAutoString quoteType; quoteType.Assign(NS_LITERAL_STRING("blockquote"));
- res = SplitAsNeeded("eType, address_of(curParent), &offset);
+ if (indentedLI == listitem) continue; // already indented this list item
+ res = nsEditor::GetNodeLocation(listitem, address_of(curParent), &offset);
if (NS_FAILED(res)) return res;
- res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curQuote));
+ // check to see if curList is still appropriate. Which it is if
+ // curNode is still right after it in the same list.
+ if (curList)
+ {
+ sibling = nsnull;
+ mHTMLEditor->GetPriorHTMLSibling(curNode, address_of(sibling));
+ }
+
+ if (!curList || (sibling && sibling != curList) )
+ {
+ nsAutoString listTag;
+ nsEditor::GetTagString(curParent,listTag);
+ listTag.ToLowerCase();
+ // create a new nested list of correct type
+ res = SplitAsNeeded(&listTag, address_of(curParent), &offset);
+ if (NS_FAILED(res)) return res;
+ res = mHTMLEditor->CreateNode(listTag, curParent, offset, getter_AddRefs(curList));
+ if (NS_FAILED(res)) return res;
+ }
+ res = mHTMLEditor->MoveNode(listitem, curList, -1);
if (NS_FAILED(res)) return res;
- // remember our new block for postprocessing
- mNewBlock = curQuote;
-
-/* !!!!!!!!!!!!!!! TURNED OFF PER BUG 33213 !!!!!!!!!!!!!!!!!!!!
- // set style to not have unwanted vertical margins
- nsCOMPtr quoteElem = do_QueryInterface(curQuote);
- res = mHTMLEditor->SetAttribute(quoteElem, NS_LITERAL_STRING("style"), NS_LITERAL_STRING("margin: 0 0 0 40px;"));
- if (NS_FAILED(res)) return res;
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
-
- // curQuote is now the correct thing to put curNode in
+ // remember we indented this li
+ indentedLI = listitem;
+ }
+
+ else
+ {
+ // need to make a blockquote to put things in if we haven't already,
+ // or if this node doesn't go in blockquote we used earlier.
+ if (!curQuote)
+ {
+ nsAutoString quoteType; quoteType.Assign(NS_LITERAL_STRING("blockquote"));
+ res = SplitAsNeeded("eType, address_of(curParent), &offset);
+ if (NS_FAILED(res)) return res;
+ res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curQuote));
+ if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curQuote;
+ // curQuote is now the correct thing to put curNode in
+ }
+
+ // tuck the node into the end of the active blockquote
+ res = mHTMLEditor->MoveNode(curNode, curQuote, -1);
+ if (NS_FAILED(res)) return res;
+ // forget curList, if any
+ curList = nsnull;
}
-
- // tuck the node into the end of the active blockquote
- PRUint32 quoteLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curQuote, quoteLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, curQuote, quoteLen);
- if (NS_FAILED(res)) return res;
}
}
return res;
@@ -3482,10 +3504,7 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
}
// tuck the node into the end of the active div
- PRUint32 listLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curDiv, listLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, curDiv, listLen);
+ res = mHTMLEditor->MoveNode(curNode, curDiv, -1);
if (NS_FAILED(res)) return res;
}
@@ -4864,6 +4883,30 @@ nsHTMLEditRules::InsertTab(nsISelection *aSelection,
}
+///////////////////////////////////////////////////////////////////////////
+// IsInListItem: if aNode is the descendant of a listitem, return that li.
+// But table element boundaries are stoppers on the search.
+// Also test if aNode is an li itself.
+//
+nsCOMPtr
+nsHTMLEditRules::IsInListItem(nsIDOMNode *aNode)
+{
+ if (!aNode) return nsnull;
+ if (nsHTMLEditUtils::IsListItem(aNode)) return aNode;
+
+ nsCOMPtr parent, tmp;
+ aNode->GetParentNode(getter_AddRefs(parent));
+
+ while (parent)
+ {
+ if (nsHTMLEditUtils::IsTableElement(parent)) return nsnull;
+ if (nsHTMLEditUtils::IsListItem(parent)) return parent;
+ tmp=parent; tmp->GetParentNode(getter_AddRefs(parent));
+ }
+ return nsnull;
+}
+
+
///////////////////////////////////////////////////////////////////////////
// ReturnInHeader: do the right thing for returns pressed in headers
//
@@ -5260,10 +5303,7 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
// note: doesn't matter if we set mNewBlock multiple times.
}
- PRUint32 blockLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curBlock, blockLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, curBlock, blockLen);
+ res = mHTMLEditor->MoveNode(curNode, curBlock, -1);
if (NS_FAILED(res)) return res;
}
return res;
@@ -5485,16 +5525,49 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
nsCOMPtr childArray;
res = GetChildNodesForOperation(curNode, address_of(childArray));
if (NS_FAILED(res)) return res;
- res = ApplyBlockStyle(childArray, aBlockTag);
- if (NS_FAILED(res)) return res;
+ PRUint32 childCount;
+ childArray->Count(&childCount);
+ if (childCount)
+ {
+ res = ApplyBlockStyle(childArray, aBlockTag);
+ if (NS_FAILED(res)) return res;
+ }
+ else
+ {
+ // make sure we can put a block here
+ res = SplitAsNeeded(aBlockTag, address_of(curParent), &offset);
+ if (NS_FAILED(res)) return res;
+ nsCOMPtr theBlock;
+ res = mHTMLEditor->CreateNode(*aBlockTag, curParent, offset, getter_AddRefs(theBlock));
+ if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = theBlock;
+ }
}
// if the node is a break, we honor it by putting further nodes in a new parent
else if (curNodeTag.Equals(NS_LITERAL_STRING("br")))
{
- curBlock = 0; // forget any previous block used for previous inline nodes
- res = mHTMLEditor->DeleteNode(curNode);
- if (NS_FAILED(res)) return res;
+ if (curBlock)
+ {
+ curBlock = 0; // forget any previous block used for previous inline nodes
+ res = mHTMLEditor->DeleteNode(curNode);
+ if (NS_FAILED(res)) return res;
+ }
+ else
+ {
+ // the break is the first (or even only) node we encountered. Create a
+ // block for it.
+ res = SplitAsNeeded(aBlockTag, address_of(curParent), &offset);
+ if (NS_FAILED(res)) return res;
+ res = mHTMLEditor->CreateNode(*aBlockTag, curParent, offset, getter_AddRefs(curBlock));
+ if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curBlock;
+ // note: doesn't matter if we set mNewBlock multiple times.
+ res = mHTMLEditor->MoveNode(curNode, curBlock, -1);
+ if (NS_FAILED(res)) return res;
+ }
}
@@ -5529,10 +5602,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
// this is a continuation of some inline nodes that belong together in
// the same block item. use curBlock
- PRUint32 blockLen;
- res = mHTMLEditor->GetLengthOfDOMNode(curBlock, blockLen);
- if (NS_FAILED(res)) return res;
- res = mHTMLEditor->MoveNode(curNode, curBlock, blockLen);
+ res = mHTMLEditor->MoveNode(curNode, curBlock, -1);
if (NS_FAILED(res)) return res;
}
}
diff --git a/editor/libeditor/html/nsHTMLEditRules.h b/editor/libeditor/html/nsHTMLEditRules.h
index 9d9bba43f23..970d3906211 100644
--- a/editor/libeditor/html/nsHTMLEditRules.h
+++ b/editor/libeditor/html/nsHTMLEditRules.h
@@ -135,6 +135,7 @@ protected:
nsresult AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *alignType);
nsresult GetInnerContent(nsIDOMNode *aNode, nsISupportsArray *outArrayOfNodes, PRBool aList = PR_TRUE, PRBool aTble = PR_TRUE);
nsresult InsertTab(nsISelection *aSelection, nsAWritableString *outString);
+ nsCOMPtr IsInListItem(nsIDOMNode *aNode);
nsresult ReturnInHeader(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
nsresult ReturnInParagraph(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
nsresult ReturnInListItem(nsISelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);