diff --git a/mozilla/editor/base/nsComposerCommands.cpp b/mozilla/editor/base/nsComposerCommands.cpp index aae1aab7b36..ffb13cfff54 100644 --- a/mozilla/editor/base/nsComposerCommands.cpp +++ b/mozilla/editor/base/nsComposerCommands.cpp @@ -380,7 +380,7 @@ nsListCommand::ToggleState(nsIEditorShell *aEditorShell, const char* aTagName) if (inList) rv = aEditorShell->RemoveList(listType.GetUnicode()); else - rv = aEditorShell->MakeOrChangeList(listType.GetUnicode()); + rv = aEditorShell->MakeOrChangeList(listType.GetUnicode(), PR_FALSE); return rv; } diff --git a/mozilla/editor/base/nsEditorShell.cpp b/mozilla/editor/base/nsEditorShell.cpp index 76ebde96f0a..881bdcf076b 100644 --- a/mozilla/editor/base/nsEditorShell.cpp +++ b/mozilla/editor/base/nsEditorShell.cpp @@ -3412,7 +3412,7 @@ nsEditorShell::GetDocumentLength(PRInt32 *aDocumentLength) NS_IMETHODIMP -nsEditorShell::MakeOrChangeList(const PRUnichar *listType) +nsEditorShell::MakeOrChangeList(const PRUnichar *listType, PRBool entireList) { nsresult err = NS_NOINTERFACE; @@ -3432,7 +3432,7 @@ nsEditorShell::MakeOrChangeList(const PRUnichar *listType) } } else - err = mEditor->MakeOrChangeList(aListType); + err = mEditor->MakeOrChangeList(aListType, entireList); break; case ePlainTextEditorType: diff --git a/mozilla/editor/base/nsHTMLEditRules.cpp b/mozilla/editor/base/nsHTMLEditRules.cpp index eadbda482c1..987d827062e 100644 --- a/mozilla/editor/base/nsHTMLEditRules.cpp +++ b/mozilla/editor/base/nsHTMLEditRules.cpp @@ -408,7 +408,7 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, case kDeleteSelection: return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled); case kMakeList: - return WillMakeList(aSelection, info->blockType, aCancel, aHandled); + return WillMakeList(aSelection, info->blockType, info->entireList, aCancel, aHandled); case kIndent: return WillIndent(aSelection, aCancel, aHandled); case kOutdent: @@ -420,7 +420,7 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, case kRemoveList: return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled); case kMakeDefListItem: - return WillMakeDefListItem(aSelection, info->blockType, aCancel, aHandled); + return WillMakeDefListItem(aSelection, info->blockType, info->entireList, aCancel, aHandled); case kInsertElement: return WillInsert(aSelection, aCancel); } @@ -460,7 +460,7 @@ nsHTMLEditRules::GetListState(PRBool &aMixed, PRBool &aOL, PRBool &aUL, PRBool & PRBool bNonList = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine list type for nodes in selection @@ -512,7 +512,7 @@ nsHTMLEditRules::GetListItemState(PRBool &aMixed, PRBool &aLI, PRBool &aDT, PRBo PRBool bNonList = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine list type for nodes in selection @@ -649,7 +649,7 @@ nsHTMLEditRules::GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent) aCanOutdent = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine nodes in selection for blockquotes or list elements; @@ -1719,6 +1719,7 @@ nsHTMLEditRules::DeleteNonTableElements(nsIDOMNode *aNode) nsresult nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, + PRBool aEntireList, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType) @@ -1752,7 +1753,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, nsAutoSelectionReset selectionResetter(aSelection, mEditor); nsCOMPtr arrayOfNodes; - res = GetListActionNodes(&arrayOfNodes); + res = GetListActionNodes(&arrayOfNodes, aEntireList); if (NS_FAILED(res)) return res; PRUint32 listCount; @@ -2132,13 +2133,14 @@ nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, nsresult nsHTMLEditRules::WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aItemType, + PRBool aEntireList, PRBool *aCancel, PRBool *aHandled) { // for now we let WillMakeList handle this nsAutoString listType; listType.AssignWithConversion("dl"); - return WillMakeList(aSelection, &listType, aCancel, aHandled, aItemType); + return WillMakeList(aSelection, &listType, aEntireList, aCancel, aHandled, aItemType); } nsresult @@ -2487,12 +2489,18 @@ nsHTMLEditRules::ConvertListType(nsIDOMNode *aList, aList->GetFirstChild(getter_AddRefs(child)); while (child) { - if (!mEditor->NodeIsType(child, aItemType)) + if (nsHTMLEditUtils::IsListItem(child) && !mEditor->NodeIsType(child, aItemType)) { res = mEditor->ReplaceContainer(child, &temp, aItemType); if (NS_FAILED(res)) return res; child = temp; } + else if (nsHTMLEditUtils::IsList(child) && !mEditor->NodeIsType(child, aListType)) + { + res = mEditor->ReplaceContainer(child, &temp, aListType); + if (NS_FAILED(res)) return res; + child = temp; + } child->GetNextSibling(getter_AddRefs(temp)); child = temp; } @@ -2685,9 +2693,22 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, res = GetNodesForOperation(arrayOfRanges, &arrayOfNodes, kAlign); if (NS_FAILED(res)) return res; + // if we don't have any nodes, or we have only a single br, then we are + // creating an empty alignment div. We have to do some different things for these. + PRBool emptyDiv = PR_FALSE; PRUint32 listCount; arrayOfNodes->Count(&listCount); - if (!listCount) + if (!listCount) emptyDiv = PR_TRUE; + if (listCount == 1) + { + nsCOMPtr isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0)); + nsCOMPtr theNode( do_QueryInterface(isupports ) ); + if (nsHTMLEditUtils::IsBreak(theNode)) + { + emptyDiv = PR_TRUE; + } + } + if (emptyDiv) { PRInt32 offset; nsCOMPtr brNode, parent, theDiv, sib; @@ -3180,6 +3201,11 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt if (NS_FAILED(res)) return res; while ((IsFirstNode(node)) && (!nsHTMLEditUtils::IsBody(parent))) { + // some cutoffs are here: we don't need to also include them in the aWhere == kEnd case. + // as long as they are in one or the other it will work. + + // dont cross table cell boundaries + if (nsHTMLEditUtils::IsTableCell(parent)) break; // special case for outdent: don't keep looking up // if we have found a blockquote element to act on if ((actionID == kOutdent) && nsHTMLEditUtils::IsBlockquote(parent)) @@ -3545,14 +3571,63 @@ nsHTMLEditRules::GetChildNodesForOperation(nsIDOMNode *inNode, // nsresult nsHTMLEditRules::GetListActionNodes(nsCOMPtr *outArrayOfNodes, + PRBool aEntireList, PRBool aDontTouchContent) { if (!outArrayOfNodes) return NS_ERROR_NULL_POINTER; + nsresult res = NS_OK; nsCOMPtrselection; - nsresult res = mEditor->GetSelection(getter_AddRefs(selection)); + res = mEditor->GetSelection(getter_AddRefs(selection)); if (NS_FAILED(res)) return res; + // added this in so that ui code can ask to change an entire list, even if selection + // is only in part of it. used by list item dialog. + if (aEntireList) + { + res = NS_NewISupportsArray(getter_AddRefs(*outArrayOfNodes)); + if (NS_FAILED(res)) return res; + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_UNEXPECTED; + + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(res)) return res; + if (!currentItem) return NS_ERROR_UNEXPECTED; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr commonParent, parent, tmp; + range->GetCommonAncestorContainer(getter_AddRefs(commonParent)); + if (commonParent) + { + parent = commonParent; + while (parent) + { + if (nsHTMLEditUtils::IsList(parent)) + { + nsCOMPtr isupports = do_QueryInterface(parent); + (*outArrayOfNodes)->AppendElement(isupports); + break; + } + parent->GetParentNode(getter_AddRefs(tmp)); + parent = tmp; + } + } + } + // if we didn't find any nodes this way, then try the normal way. perhaps the + // selection spans multiple lists but with no common list parent. + if (*outArrayOfNodes) + { + PRUint32 nodeCount; + (*outArrayOfNodes)->Count(&nodeCount); + if (nodeCount) return NS_OK; + } + } + nsCOMPtr arrayOfRanges; res = GetPromotedRanges(selection, &arrayOfRanges, kMakeList); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/base/nsHTMLEditRules.h b/mozilla/editor/base/nsHTMLEditRules.h index 7bd901d562e..7d98a752a52 100644 --- a/mozilla/editor/base/nsHTMLEditRules.h +++ b/mozilla/editor/base/nsHTMLEditRules.h @@ -101,12 +101,12 @@ protected: nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aAction, PRBool *aCancel, PRBool *aHandled); nsresult DeleteNonTableElements(nsIDOMNode *aNode); - nsresult WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType=nsnull); + nsresult WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType=nsnull); nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled); nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel, PRBool *aHandled); - nsresult WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled); + nsresult WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled); nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled); nsresult DidMakeBasicBlock(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); @@ -144,7 +144,7 @@ protected: PRBool aDontTouchContent=PR_FALSE); nsresult GetChildNodesForOperation(nsIDOMNode *inNode, nsCOMPtr *outArrayOfNodes); - nsresult GetListActionNodes(nsCOMPtr *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE); + nsresult GetListActionNodes(nsCOMPtr *outArrayOfNodes, PRBool aEntireList, PRBool aDontTouchContent=PR_FALSE); nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD); nsresult GetParagraphFormatNodes(nsCOMPtr *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE); nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange); diff --git a/mozilla/editor/base/nsHTMLEditor.cpp b/mozilla/editor/base/nsHTMLEditor.cpp index bc6f272c909..140c80b2272 100644 --- a/mozilla/editor/base/nsHTMLEditor.cpp +++ b/mozilla/editor/base/nsHTMLEditor.cpp @@ -3349,7 +3349,7 @@ nsHTMLEditor::GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent) } NS_IMETHODIMP -nsHTMLEditor::MakeOrChangeList(const nsString& aListType) +nsHTMLEditor::MakeOrChangeList(const nsString& aListType, PRBool entireList) { nsresult res; if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } @@ -3367,6 +3367,7 @@ nsHTMLEditor::MakeOrChangeList(const nsString& aListType) nsTextRulesInfo ruleInfo(nsTextEditRules::kMakeList); ruleInfo.blockType = &aListType; + ruleInfo.entireList = entireList; res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); if (cancel || (NS_FAILED(res))) return res; diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index b8bf71496c6..6054d93ee23 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -143,7 +143,7 @@ public: NS_IMETHOD GetAlignment(PRBool &aMixed, nsIHTMLEditor::EAlignment &aAlign); NS_IMETHOD GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent); - NS_IMETHOD MakeOrChangeList(const nsString& aListType); + NS_IMETHOD MakeOrChangeList(const nsString& aListType, PRBool entireList); NS_IMETHOD RemoveList(const nsString& aListType); NS_IMETHOD Indent(const nsString& aIndent); NS_IMETHOD Align(const nsString& aAlign); diff --git a/mozilla/editor/base/nsHTMLEditorLog.cpp b/mozilla/editor/base/nsHTMLEditorLog.cpp index 1b9244a4cd2..deba9cf3348 100644 --- a/mozilla/editor/base/nsHTMLEditorLog.cpp +++ b/mozilla/editor/base/nsHTMLEditorLog.cpp @@ -681,7 +681,7 @@ nsHTMLEditorLog::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMEle } NS_IMETHODIMP -nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType) +nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType, PRBool entireList) { nsAutoHTMLEditorLogLock logLock(this); @@ -695,7 +695,7 @@ nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType) Flush(); } - return nsHTMLEditor::MakeOrChangeList(aListType); + return nsHTMLEditor::MakeOrChangeList(aListType, entireList); } NS_IMETHODIMP diff --git a/mozilla/editor/base/nsHTMLEditorLog.h b/mozilla/editor/base/nsHTMLEditorLog.h index e01fa5af579..f309d290ff0 100644 --- a/mozilla/editor/base/nsHTMLEditorLog.h +++ b/mozilla/editor/base/nsHTMLEditorLog.h @@ -84,7 +84,7 @@ public: NS_IMETHOD SetBackgroundColor(const nsString& aColor); NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue); - NS_IMETHOD MakeOrChangeList(const nsString& aListType); + NS_IMETHOD MakeOrChangeList(const nsString& aListType, PRBool entireList); NS_IMETHOD Indent(const nsString& aIndent); NS_IMETHOD Align(const nsString& aAlign); NS_IMETHOD InsertElementAtSelection(nsIDOMElement* aElement, PRBool aDeleteSelection); diff --git a/mozilla/editor/base/nsTextEditRules.h b/mozilla/editor/base/nsTextEditRules.h index 92cd8ea44f5..9c3194b5d44 100644 --- a/mozilla/editor/base/nsTextEditRules.h +++ b/mozilla/editor/base/nsTextEditRules.h @@ -192,6 +192,8 @@ class nsTextRulesInfo : public nsRulesInfo outputFormat(0), maxLength(-1), collapsedAction(nsIEditor::eNext), + bOrdered(PR_FALSE), + entireList(PR_FALSE), alignType(0), blockType(0), insertElement(0) @@ -210,7 +212,8 @@ class nsTextRulesInfo : public nsRulesInfo // kMakeList PRBool bOrdered; - + PRBool entireList; + // kAlign const nsString *alignType; diff --git a/mozilla/editor/composer/src/nsComposerCommands.cpp b/mozilla/editor/composer/src/nsComposerCommands.cpp index aae1aab7b36..ffb13cfff54 100644 --- a/mozilla/editor/composer/src/nsComposerCommands.cpp +++ b/mozilla/editor/composer/src/nsComposerCommands.cpp @@ -380,7 +380,7 @@ nsListCommand::ToggleState(nsIEditorShell *aEditorShell, const char* aTagName) if (inList) rv = aEditorShell->RemoveList(listType.GetUnicode()); else - rv = aEditorShell->MakeOrChangeList(listType.GetUnicode()); + rv = aEditorShell->MakeOrChangeList(listType.GetUnicode(), PR_FALSE); return rv; } diff --git a/mozilla/editor/composer/src/nsEditorShell.cpp b/mozilla/editor/composer/src/nsEditorShell.cpp index 76ebde96f0a..881bdcf076b 100644 --- a/mozilla/editor/composer/src/nsEditorShell.cpp +++ b/mozilla/editor/composer/src/nsEditorShell.cpp @@ -3412,7 +3412,7 @@ nsEditorShell::GetDocumentLength(PRInt32 *aDocumentLength) NS_IMETHODIMP -nsEditorShell::MakeOrChangeList(const PRUnichar *listType) +nsEditorShell::MakeOrChangeList(const PRUnichar *listType, PRBool entireList) { nsresult err = NS_NOINTERFACE; @@ -3432,7 +3432,7 @@ nsEditorShell::MakeOrChangeList(const PRUnichar *listType) } } else - err = mEditor->MakeOrChangeList(aListType); + err = mEditor->MakeOrChangeList(aListType, entireList); break; case ePlainTextEditorType: diff --git a/mozilla/editor/idl/nsIEditorShell.idl b/mozilla/editor/idl/nsIEditorShell.idl index f37be46acdb..c991095fd22 100644 --- a/mozilla/editor/idl/nsIEditorShell.idl +++ b/mozilla/editor/idl/nsIEditorShell.idl @@ -206,7 +206,7 @@ interface nsIEditorShell : nsISupports void InsertBreak(); - void MakeOrChangeList(in wstring listType); + void MakeOrChangeList(in wstring listType, in PRBool entireList); void RemoveList(in wstring listType); void Indent(in wstring indent); void Align(in wstring align); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp index eadbda482c1..987d827062e 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp @@ -408,7 +408,7 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, case kDeleteSelection: return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled); case kMakeList: - return WillMakeList(aSelection, info->blockType, aCancel, aHandled); + return WillMakeList(aSelection, info->blockType, info->entireList, aCancel, aHandled); case kIndent: return WillIndent(aSelection, aCancel, aHandled); case kOutdent: @@ -420,7 +420,7 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, case kRemoveList: return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled); case kMakeDefListItem: - return WillMakeDefListItem(aSelection, info->blockType, aCancel, aHandled); + return WillMakeDefListItem(aSelection, info->blockType, info->entireList, aCancel, aHandled); case kInsertElement: return WillInsert(aSelection, aCancel); } @@ -460,7 +460,7 @@ nsHTMLEditRules::GetListState(PRBool &aMixed, PRBool &aOL, PRBool &aUL, PRBool & PRBool bNonList = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine list type for nodes in selection @@ -512,7 +512,7 @@ nsHTMLEditRules::GetListItemState(PRBool &aMixed, PRBool &aLI, PRBool &aDT, PRBo PRBool bNonList = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine list type for nodes in selection @@ -649,7 +649,7 @@ nsHTMLEditRules::GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent) aCanOutdent = PR_FALSE; nsCOMPtr arrayOfNodes; - nsresult res = GetListActionNodes(&arrayOfNodes, PR_TRUE); + nsresult res = GetListActionNodes(&arrayOfNodes, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; // examine nodes in selection for blockquotes or list elements; @@ -1719,6 +1719,7 @@ nsHTMLEditRules::DeleteNonTableElements(nsIDOMNode *aNode) nsresult nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, + PRBool aEntireList, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType) @@ -1752,7 +1753,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, nsAutoSelectionReset selectionResetter(aSelection, mEditor); nsCOMPtr arrayOfNodes; - res = GetListActionNodes(&arrayOfNodes); + res = GetListActionNodes(&arrayOfNodes, aEntireList); if (NS_FAILED(res)) return res; PRUint32 listCount; @@ -2132,13 +2133,14 @@ nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, nsresult nsHTMLEditRules::WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aItemType, + PRBool aEntireList, PRBool *aCancel, PRBool *aHandled) { // for now we let WillMakeList handle this nsAutoString listType; listType.AssignWithConversion("dl"); - return WillMakeList(aSelection, &listType, aCancel, aHandled, aItemType); + return WillMakeList(aSelection, &listType, aEntireList, aCancel, aHandled, aItemType); } nsresult @@ -2487,12 +2489,18 @@ nsHTMLEditRules::ConvertListType(nsIDOMNode *aList, aList->GetFirstChild(getter_AddRefs(child)); while (child) { - if (!mEditor->NodeIsType(child, aItemType)) + if (nsHTMLEditUtils::IsListItem(child) && !mEditor->NodeIsType(child, aItemType)) { res = mEditor->ReplaceContainer(child, &temp, aItemType); if (NS_FAILED(res)) return res; child = temp; } + else if (nsHTMLEditUtils::IsList(child) && !mEditor->NodeIsType(child, aListType)) + { + res = mEditor->ReplaceContainer(child, &temp, aListType); + if (NS_FAILED(res)) return res; + child = temp; + } child->GetNextSibling(getter_AddRefs(temp)); child = temp; } @@ -2685,9 +2693,22 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, res = GetNodesForOperation(arrayOfRanges, &arrayOfNodes, kAlign); if (NS_FAILED(res)) return res; + // if we don't have any nodes, or we have only a single br, then we are + // creating an empty alignment div. We have to do some different things for these. + PRBool emptyDiv = PR_FALSE; PRUint32 listCount; arrayOfNodes->Count(&listCount); - if (!listCount) + if (!listCount) emptyDiv = PR_TRUE; + if (listCount == 1) + { + nsCOMPtr isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0)); + nsCOMPtr theNode( do_QueryInterface(isupports ) ); + if (nsHTMLEditUtils::IsBreak(theNode)) + { + emptyDiv = PR_TRUE; + } + } + if (emptyDiv) { PRInt32 offset; nsCOMPtr brNode, parent, theDiv, sib; @@ -3180,6 +3201,11 @@ nsHTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt if (NS_FAILED(res)) return res; while ((IsFirstNode(node)) && (!nsHTMLEditUtils::IsBody(parent))) { + // some cutoffs are here: we don't need to also include them in the aWhere == kEnd case. + // as long as they are in one or the other it will work. + + // dont cross table cell boundaries + if (nsHTMLEditUtils::IsTableCell(parent)) break; // special case for outdent: don't keep looking up // if we have found a blockquote element to act on if ((actionID == kOutdent) && nsHTMLEditUtils::IsBlockquote(parent)) @@ -3545,14 +3571,63 @@ nsHTMLEditRules::GetChildNodesForOperation(nsIDOMNode *inNode, // nsresult nsHTMLEditRules::GetListActionNodes(nsCOMPtr *outArrayOfNodes, + PRBool aEntireList, PRBool aDontTouchContent) { if (!outArrayOfNodes) return NS_ERROR_NULL_POINTER; + nsresult res = NS_OK; nsCOMPtrselection; - nsresult res = mEditor->GetSelection(getter_AddRefs(selection)); + res = mEditor->GetSelection(getter_AddRefs(selection)); if (NS_FAILED(res)) return res; + // added this in so that ui code can ask to change an entire list, even if selection + // is only in part of it. used by list item dialog. + if (aEntireList) + { + res = NS_NewISupportsArray(getter_AddRefs(*outArrayOfNodes)); + if (NS_FAILED(res)) return res; + nsCOMPtr enumerator; + res = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_FAILED(res)) return res; + if (!enumerator) return NS_ERROR_UNEXPECTED; + + for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next()) + { + nsCOMPtr currentItem; + res = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if (NS_FAILED(res)) return res; + if (!currentItem) return NS_ERROR_UNEXPECTED; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + nsCOMPtr commonParent, parent, tmp; + range->GetCommonAncestorContainer(getter_AddRefs(commonParent)); + if (commonParent) + { + parent = commonParent; + while (parent) + { + if (nsHTMLEditUtils::IsList(parent)) + { + nsCOMPtr isupports = do_QueryInterface(parent); + (*outArrayOfNodes)->AppendElement(isupports); + break; + } + parent->GetParentNode(getter_AddRefs(tmp)); + parent = tmp; + } + } + } + // if we didn't find any nodes this way, then try the normal way. perhaps the + // selection spans multiple lists but with no common list parent. + if (*outArrayOfNodes) + { + PRUint32 nodeCount; + (*outArrayOfNodes)->Count(&nodeCount); + if (nodeCount) return NS_OK; + } + } + nsCOMPtr arrayOfRanges; res = GetPromotedRanges(selection, &arrayOfRanges, kMakeList); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.h b/mozilla/editor/libeditor/html/nsHTMLEditRules.h index 7bd901d562e..7d98a752a52 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditRules.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.h @@ -101,12 +101,12 @@ protected: nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aAction, PRBool *aCancel, PRBool *aHandled); nsresult DeleteNonTableElements(nsIDOMNode *aNode); - nsresult WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType=nsnull); + nsresult WillMakeList(nsIDOMSelection *aSelection, const nsString *aListType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled, const nsString *aItemType=nsnull); nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled); nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled); nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel, PRBool *aHandled); - nsresult WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled); + nsresult WillMakeDefListItem(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled); nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled); nsresult DidMakeBasicBlock(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); @@ -144,7 +144,7 @@ protected: PRBool aDontTouchContent=PR_FALSE); nsresult GetChildNodesForOperation(nsIDOMNode *inNode, nsCOMPtr *outArrayOfNodes); - nsresult GetListActionNodes(nsCOMPtr *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE); + nsresult GetListActionNodes(nsCOMPtr *outArrayOfNodes, PRBool aEntireList, PRBool aDontTouchContent=PR_FALSE); nsresult GetDefinitionListItemTypes(nsIDOMNode *aNode, PRBool &aDT, PRBool &aDD); nsresult GetParagraphFormatNodes(nsCOMPtr *outArrayOfNodes, PRBool aDontTouchContent=PR_FALSE); nsresult BustUpInlinesAtRangeEndpoints(nsRangeStore &inRange); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index bc6f272c909..140c80b2272 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -3349,7 +3349,7 @@ nsHTMLEditor::GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent) } NS_IMETHODIMP -nsHTMLEditor::MakeOrChangeList(const nsString& aListType) +nsHTMLEditor::MakeOrChangeList(const nsString& aListType, PRBool entireList) { nsresult res; if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } @@ -3367,6 +3367,7 @@ nsHTMLEditor::MakeOrChangeList(const nsString& aListType) nsTextRulesInfo ruleInfo(nsTextEditRules::kMakeList); ruleInfo.blockType = &aListType; + ruleInfo.entireList = entireList; res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); if (cancel || (NS_FAILED(res))) return res; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index b8bf71496c6..6054d93ee23 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -143,7 +143,7 @@ public: NS_IMETHOD GetAlignment(PRBool &aMixed, nsIHTMLEditor::EAlignment &aAlign); NS_IMETHOD GetIndentState(PRBool &aCanIndent, PRBool &aCanOutdent); - NS_IMETHOD MakeOrChangeList(const nsString& aListType); + NS_IMETHOD MakeOrChangeList(const nsString& aListType, PRBool entireList); NS_IMETHOD RemoveList(const nsString& aListType); NS_IMETHOD Indent(const nsString& aIndent); NS_IMETHOD Align(const nsString& aAlign); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditorLog.cpp b/mozilla/editor/libeditor/html/nsHTMLEditorLog.cpp index 1b9244a4cd2..deba9cf3348 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditorLog.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditorLog.cpp @@ -681,7 +681,7 @@ nsHTMLEditorLog::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMEle } NS_IMETHODIMP -nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType) +nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType, PRBool entireList) { nsAutoHTMLEditorLogLock logLock(this); @@ -695,7 +695,7 @@ nsHTMLEditorLog::MakeOrChangeList(const nsString& aListType) Flush(); } - return nsHTMLEditor::MakeOrChangeList(aListType); + return nsHTMLEditor::MakeOrChangeList(aListType, entireList); } NS_IMETHODIMP diff --git a/mozilla/editor/libeditor/html/nsHTMLEditorLog.h b/mozilla/editor/libeditor/html/nsHTMLEditorLog.h index e01fa5af579..f309d290ff0 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditorLog.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditorLog.h @@ -84,7 +84,7 @@ public: NS_IMETHOD SetBackgroundColor(const nsString& aColor); NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue); - NS_IMETHOD MakeOrChangeList(const nsString& aListType); + NS_IMETHOD MakeOrChangeList(const nsString& aListType, PRBool entireList); NS_IMETHOD Indent(const nsString& aIndent); NS_IMETHOD Align(const nsString& aAlign); NS_IMETHOD InsertElementAtSelection(nsIDOMElement* aElement, PRBool aDeleteSelection); diff --git a/mozilla/editor/libeditor/text/nsTextEditRules.h b/mozilla/editor/libeditor/text/nsTextEditRules.h index 92cd8ea44f5..9c3194b5d44 100644 --- a/mozilla/editor/libeditor/text/nsTextEditRules.h +++ b/mozilla/editor/libeditor/text/nsTextEditRules.h @@ -192,6 +192,8 @@ class nsTextRulesInfo : public nsRulesInfo outputFormat(0), maxLength(-1), collapsedAction(nsIEditor::eNext), + bOrdered(PR_FALSE), + entireList(PR_FALSE), alignType(0), blockType(0), insertElement(0) @@ -210,7 +212,8 @@ class nsTextRulesInfo : public nsRulesInfo // kMakeList PRBool bOrdered; - + PRBool entireList; + // kAlign const nsString *alignType; diff --git a/mozilla/editor/public/nsIHTMLEditor.h b/mozilla/editor/public/nsIHTMLEditor.h index ac81c16a78e..7c2c109ac06 100644 --- a/mozilla/editor/public/nsIHTMLEditor.h +++ b/mozilla/editor/public/nsIHTMLEditor.h @@ -377,7 +377,7 @@ public: * Document me! * */ - NS_IMETHOD MakeOrChangeList(const nsString& aListType)=0; + NS_IMETHOD MakeOrChangeList(const nsString& aListType, PRBool entireList)=0; /** * Document me! diff --git a/mozilla/editor/ui/dialogs/content/EdListProps.js b/mozilla/editor/ui/dialogs/content/EdListProps.js index e3b816cc846..afecab491f2 100644 --- a/mozilla/editor/ui/dialogs/content/EdListProps.js +++ b/mozilla/editor/ui/dialogs/content/EdListProps.js @@ -320,9 +320,6 @@ function onOK() var changeList; if (ListElement && dialog.ChangeAllRadio.checked) { - // Select the entire list element so all items are - // changed to the requested new type - editorShell.SelectElement(ListElement); changeList = true; } else @@ -330,7 +327,7 @@ function onOK() if (changeList) { - editorShell.MakeOrChangeList(ListType); + editorShell.MakeOrChangeList(ListType, dialog.ChangeAllRadio.checked); // Get the new list created: ListElement = editorShell.GetElementOrParentByTagName(ListType, null);