diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index b015fd40575..c7d62a08449 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -3494,7 +3494,8 @@ nsEditor::IsEditable(nsIDOMNode *aNode) if (!shell) return PR_FALSE; if (IsMozEditorBogusNode(aNode)) return PR_FALSE; - + +/* THIS DOESN'T WORK! // it's not the bogus node, so see if it is an irrelevant text node if (PR_TRUE==IsTextNode(aNode)) { @@ -3521,7 +3522,7 @@ nsEditor::IsEditable(nsIDOMNode *aNode) return PR_FALSE; } } - +*/ // we got this far, so see if it has a frame. If so, we'll edit it. nsIFrame *resultFrame; nsCOMPtrcontent; diff --git a/mozilla/editor/base/nsHTMLDataTransfer.cpp b/mozilla/editor/base/nsHTMLDataTransfer.cpp index 76798a07f1c..5cfcb6a55f1 100644 --- a/mozilla/editor/base/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/base/nsHTMLDataTransfer.cpp @@ -186,6 +186,8 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & { if (!mRules) return NS_ERROR_NOT_INITIALIZED; +/* all this is unneeded: parser handles this for us + // First, make sure there are no return chars in the document. // Bad things happen if you insert returns (instead of dom newlines, \n) // into an editor document. @@ -198,6 +200,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & // Mac linebreaks: Map any remaining CR to LF: inputString.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r"), NS_ConvertASCIItoUCS2("\n")); +*/ // force IME commit; set up rules sniffing and batching ForceCompositionEnd(); @@ -223,7 +226,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & // create a dom document fragment that represents the structure to paste nsCOMPtr fragmentAsNode; PRInt32 rangeStartHint, rangeEndHint; - res = CreateDOMFragmentFromPaste(nsrange, inputString, aContextStr, aInfoStr, + res = CreateDOMFragmentFromPaste(nsrange, aInputString, aContextStr, aInfoStr, address_of(fragmentAsNode), &rangeStartHint, &rangeEndHint); NS_ENSURE_SUCCESS(res, res); diff --git a/mozilla/editor/base/nsHTMLEditRules.cpp b/mozilla/editor/base/nsHTMLEditRules.cpp index 9ddf6e35da1..7ca7d9d081a 100644 --- a/mozilla/editor/base/nsHTMLEditRules.cpp +++ b/mozilla/editor/base/nsHTMLEditRules.cpp @@ -883,15 +883,16 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, PRBool *aCancel) else block1 = mHTMLEditor->GetBlockNodeParent(selNode); block2 = mHTMLEditor->GetBlockNodeParent(priorNode); - if (block1 != block2) return NS_OK; - - // if we are here then the selection is right after a mozBR - // that is in the same block as the selection. We need to move - // the selection start to be before the mozBR. - res = nsEditor::GetNodeLocation(priorNode, address_of(selNode), &selOffset); - if (NS_FAILED(res)) return res; - res = aSelection->Collapse(selNode,selOffset); - if (NS_FAILED(res)) return res; + if (block1 == block2) + { + // if we are here then the selection is right after a mozBR + // that is in the same block as the selection. We need to move + // the selection start to be before the mozBR. + res = nsEditor::GetNodeLocation(priorNode, address_of(selNode), &selOffset); + if (NS_FAILED(res)) return res; + res = aSelection->Collapse(selNode,selOffset); + if (NS_FAILED(res)) return res; + } } // we need to get the doc @@ -901,8 +902,7 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, PRBool *aCancel) if (!doc) return NS_ERROR_NULL_POINTER; // for every property that is set, insert a new inline style node - res = CreateStyleForInsertText(aSelection, doc); - return res; + return CreateStyleForInsertText(aSelection, doc); } nsresult @@ -998,7 +998,7 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, // dont spaz my selection in subtransactions nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); nsSubsumeStr subStr; - const nsPromiseFlatString &tString = PromiseFlatString(*inString);////MJUDGE SCC NEED HELP + nsAutoString tString(*inString); const PRUnichar *unicodeBuf = tString.get(); nsCOMPtr unused; PRInt32 pos = 0; @@ -1008,21 +1008,13 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, // it is to search for both tabs and newlines. if (isPRE) { - nsAutoString newlineChar(NS_LITERAL_STRING("\n")); + char newlineChar = '\n'; while (unicodeBuf && (pos != -1) && (pos < (PRInt32)(*inString).Length())) { PRInt32 oldPos = pos; PRInt32 subStrLen; - pos = -1; - nsReadingIterator beginFindIter, endFindIter, beginIter; - inString->BeginReading(beginIter); - beginFindIter = beginIter; - inString->EndReading(endFindIter); - beginFindIter.advance(oldPos); - if (FindInReadable(newlineChar,beginFindIter,endFindIter)) - { - pos = Distance(beginIter,beginFindIter); - } + pos = tString.FindChar(newlineChar, PR_FALSE, oldPos); + if (pos != -1) { subStrLen = pos - oldPos; @@ -1032,8 +1024,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - subStrLen = (*inString).Length() - oldPos; - pos = (*inString).Length(); + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); } subStr.Subsume((PRUnichar*)&unicodeBuf[oldPos], PR_FALSE, subStrLen); @@ -1053,22 +1045,13 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - nsAutoString specialChars; - specialChars = NS_LITERAL_STRING("\t\n"); + char specialChars[] = {'\t','\n',0}; nsAutoString tabString; tabString.AssignWithConversion(" "); - while (unicodeBuf && (pos != -1) && (pos < (PRInt32)(*inString).Length())) + while (unicodeBuf && (pos != -1) && (pos < (PRInt32)inString->Length())) { PRInt32 oldPos = pos; PRInt32 subStrLen; - nsReadingIterator beginFindIter,endFindIter; - (*inString).BeginReading(beginFindIter); - beginFindIter.advance(oldPos); - (*inString).EndReading(endFindIter); - nsReadingIterator distanceIter; - (*inString).BeginReading(distanceIter); - pos = -1; - if (FindInReadable((const nsAString &)specialChars,beginFindIter,endFindIter)) - pos = Distance(distanceIter,beginFindIter); + pos = tString.FindCharInSet(specialChars, oldPos); if (pos != -1) { @@ -1079,8 +1062,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - subStrLen = (*inString).Length() - oldPos; - pos = (*inString).Length(); + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); } subStr.Subsume((PRUnichar*)&unicodeBuf[oldPos], PR_FALSE, subStrLen); @@ -1435,7 +1418,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, res = mHTMLEditor->GetPriorHTMLNode(startNode, address_of(priorNode)); if (NS_FAILED(res)) return res; // are they in same block? - if (mHTMLEditor->HasSameBlockNodeParent(startNode, priorNode)) + if (priorNode && mHTMLEditor->HasSameBlockNodeParent(startNode, priorNode)) { // are they same type? if (mHTMLEditor->IsTextNode(priorNode)) @@ -1546,7 +1529,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, res = mHTMLEditor->GetNextHTMLNode(startNode, address_of(nextNode)); if (NS_FAILED(res)) return res; // are they in same block? - if (mHTMLEditor->HasSameBlockNodeParent(startNode, nextNode)) + if (nextNode && mHTMLEditor->HasSameBlockNodeParent(startNode, nextNode)) { // are they same type? if ( mHTMLEditor->IsTextNode(nextNode) ) @@ -1703,7 +1686,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, { nsCOMPtr brNode; res = mHTMLEditor->GetPriorHTMLNode(nodeToDelete, address_of(brNode)); - if (nsTextEditUtils::IsBreak(brNode)) + if (brNode && nsTextEditUtils::IsBreak(brNode)) { // is brNode also a descendant of same block? nsCOMPtr block, brBlock; @@ -5273,6 +5256,33 @@ nsHTMLEditRules::RemoveEmptyNodes() PRBool bIsEmptyNode; res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; + + // only consider certain nodes to be empty for purposes of removal + if (!( + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("b")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("i")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("u")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("tt")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("s")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("strike")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("big")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("small")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("blink")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("sub")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("sup")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("font")) || + nsHTMLEditUtils::IsList(node) || + nsHTMLEditUtils::IsParagraph(node) || + nsHTMLEditUtils::IsHeader(node) || + nsHTMLEditUtils::IsListItem(node) || + nsHTMLEditUtils::IsBlockquote(node)|| + nsHTMLEditUtils::IsDiv(node) || + nsHTMLEditUtils::IsPre(node) || + nsHTMLEditUtils::IsAddress(node) ) ) + { + bIsEmptyNode = PR_FALSE; + } + if (bIsEmptyNode && !nsTextEditUtils::IsBody(node)) { if (nsHTMLEditUtils::IsParagraph(node) || diff --git a/mozilla/editor/base/nsHTMLEditor.cpp b/mozilla/editor/base/nsHTMLEditor.cpp index 530b415c3bf..8578f2e6916 100644 --- a/mozilla/editor/base/nsHTMLEditor.cpp +++ b/mozilla/editor/base/nsHTMLEditor.cpp @@ -603,6 +603,14 @@ nsHTMLEditor::NodeIsBlock(nsIDOMNode *aNode, PRBool *aIsBlock) return NodeIsBlockStatic(aNode, aIsBlock); } +PRBool +nsHTMLEditor::IsBlockNode(nsIDOMNode *aNode) +{ + PRBool isBlock; + NodeIsBlockStatic(aNode, &isBlock); + return isBlock; +} + // Non-static version for the nsIEditor interface and JavaScript NS_IMETHODIMP nsHTMLEditor::SetDocumentTitle(const nsAReadableString &aTitle) @@ -4451,7 +4459,6 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, // want to treat them as such. Also, don't call ListItems or table // cells empty if caller desires. if (!IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) || - nsHTMLEditUtils::IsTextarea(aNode) || nsHTMLEditUtils::IsMap(aNode) || (aListOrCellNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) || (aListOrCellNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) ) { @@ -4459,6 +4466,15 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, return NS_OK; } + // are we checking a block node? + PRBool isBlock = IsBlockNode(aNode); + // if so, we allow one br without violating emptiness + PRBool seenBR = PR_FALSE; + + // need this for later + PRBool isListItemOrCell = + nsHTMLEditUtils::IsListItem(aNode) || nsHTMLEditUtils::IsTableCell(aNode); + // iterate over node. if no children, or all children are either // empty text nodes or non-editable, then node qualifies as empty nsCOMPtr iter; @@ -4522,9 +4538,28 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, // is it the node we are iterating over? if (node.get() == aNode) break; // is it a moz-BR and did the caller ask us not to consider those relevant? - if (!(aMozBRDoesntCount && nsTextEditUtils::IsMozBR(node))) + if ((aMozBRDoesntCount && nsTextEditUtils::IsMozBR(node))) + { + // do nothing + } + else if (isBlock && !seenBR && nsTextEditUtils::IsBreak(node)) + { + // the first br in a block doesn't count + seenBR = PR_TRUE; + } + else { // is it an empty node of some sort? + // note: list items or table cells are not considered empty + // if they contain other lists or tables + if (isListItemOrCell) + { + if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node)) + { + *outIsEmptyNode = PR_FALSE; + break; + } + } PRBool isEmptyNode; res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListOrCellNotEmpty); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index 5434e6a96bd..9ce6a66ed46 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -383,6 +383,8 @@ public: PRBool aMozBRDoesntCount = PR_FALSE, PRBool aListOrCellNotEmpty = PR_FALSE, PRBool aSafeToAskFrames = PR_FALSE); + + PRBool IsBlockNode(nsIDOMNode *aNode); protected: diff --git a/mozilla/editor/base/nsHTMLEditorStyle.cpp b/mozilla/editor/base/nsHTMLEditorStyle.cpp index fd4f1f45894..a0389043635 100644 --- a/mozilla/editor/base/nsHTMLEditorStyle.cpp +++ b/mozilla/editor/base/nsHTMLEditorStyle.cpp @@ -486,7 +486,8 @@ nsresult nsHTMLEditor::SplitStyleAbovePoint(nsCOMPtr *aNode, // split any matching style nodes above the node/offset nsCOMPtr parent, tmp = *aNode; PRInt32 offset; - while (tmp && !nsTextEditUtils::IsBody(tmp)) + + while (tmp && !IsBlockNode(tmp)) { if ( (aProperty && NodeIsType(tmp, aProperty)) || // node is the correct inline prop (aProperty == nsIEditProperty::href && nsHTMLEditUtils::IsLink(tmp)) || // node is href - test if really content; diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index 76798a07f1c..5cfcb6a55f1 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -186,6 +186,8 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & { if (!mRules) return NS_ERROR_NOT_INITIALIZED; +/* all this is unneeded: parser handles this for us + // First, make sure there are no return chars in the document. // Bad things happen if you insert returns (instead of dom newlines, \n) // into an editor document. @@ -198,6 +200,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & // Mac linebreaks: Map any remaining CR to LF: inputString.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r"), NS_ConvertASCIItoUCS2("\n")); +*/ // force IME commit; set up rules sniffing and batching ForceCompositionEnd(); @@ -223,7 +226,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString & // create a dom document fragment that represents the structure to paste nsCOMPtr fragmentAsNode; PRInt32 rangeStartHint, rangeEndHint; - res = CreateDOMFragmentFromPaste(nsrange, inputString, aContextStr, aInfoStr, + res = CreateDOMFragmentFromPaste(nsrange, aInputString, aContextStr, aInfoStr, address_of(fragmentAsNode), &rangeStartHint, &rangeEndHint); NS_ENSURE_SUCCESS(res, res); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp index 9ddf6e35da1..7ca7d9d081a 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp @@ -883,15 +883,16 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, PRBool *aCancel) else block1 = mHTMLEditor->GetBlockNodeParent(selNode); block2 = mHTMLEditor->GetBlockNodeParent(priorNode); - if (block1 != block2) return NS_OK; - - // if we are here then the selection is right after a mozBR - // that is in the same block as the selection. We need to move - // the selection start to be before the mozBR. - res = nsEditor::GetNodeLocation(priorNode, address_of(selNode), &selOffset); - if (NS_FAILED(res)) return res; - res = aSelection->Collapse(selNode,selOffset); - if (NS_FAILED(res)) return res; + if (block1 == block2) + { + // if we are here then the selection is right after a mozBR + // that is in the same block as the selection. We need to move + // the selection start to be before the mozBR. + res = nsEditor::GetNodeLocation(priorNode, address_of(selNode), &selOffset); + if (NS_FAILED(res)) return res; + res = aSelection->Collapse(selNode,selOffset); + if (NS_FAILED(res)) return res; + } } // we need to get the doc @@ -901,8 +902,7 @@ nsHTMLEditRules::WillInsert(nsISelection *aSelection, PRBool *aCancel) if (!doc) return NS_ERROR_NULL_POINTER; // for every property that is set, insert a new inline style node - res = CreateStyleForInsertText(aSelection, doc); - return res; + return CreateStyleForInsertText(aSelection, doc); } nsresult @@ -998,7 +998,7 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, // dont spaz my selection in subtransactions nsAutoTxnsConserveSelection dontSpazMySelection(mHTMLEditor); nsSubsumeStr subStr; - const nsPromiseFlatString &tString = PromiseFlatString(*inString);////MJUDGE SCC NEED HELP + nsAutoString tString(*inString); const PRUnichar *unicodeBuf = tString.get(); nsCOMPtr unused; PRInt32 pos = 0; @@ -1008,21 +1008,13 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, // it is to search for both tabs and newlines. if (isPRE) { - nsAutoString newlineChar(NS_LITERAL_STRING("\n")); + char newlineChar = '\n'; while (unicodeBuf && (pos != -1) && (pos < (PRInt32)(*inString).Length())) { PRInt32 oldPos = pos; PRInt32 subStrLen; - pos = -1; - nsReadingIterator beginFindIter, endFindIter, beginIter; - inString->BeginReading(beginIter); - beginFindIter = beginIter; - inString->EndReading(endFindIter); - beginFindIter.advance(oldPos); - if (FindInReadable(newlineChar,beginFindIter,endFindIter)) - { - pos = Distance(beginIter,beginFindIter); - } + pos = tString.FindChar(newlineChar, PR_FALSE, oldPos); + if (pos != -1) { subStrLen = pos - oldPos; @@ -1032,8 +1024,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - subStrLen = (*inString).Length() - oldPos; - pos = (*inString).Length(); + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); } subStr.Subsume((PRUnichar*)&unicodeBuf[oldPos], PR_FALSE, subStrLen); @@ -1053,22 +1045,13 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - nsAutoString specialChars; - specialChars = NS_LITERAL_STRING("\t\n"); + char specialChars[] = {'\t','\n',0}; nsAutoString tabString; tabString.AssignWithConversion(" "); - while (unicodeBuf && (pos != -1) && (pos < (PRInt32)(*inString).Length())) + while (unicodeBuf && (pos != -1) && (pos < (PRInt32)inString->Length())) { PRInt32 oldPos = pos; PRInt32 subStrLen; - nsReadingIterator beginFindIter,endFindIter; - (*inString).BeginReading(beginFindIter); - beginFindIter.advance(oldPos); - (*inString).EndReading(endFindIter); - nsReadingIterator distanceIter; - (*inString).BeginReading(distanceIter); - pos = -1; - if (FindInReadable((const nsAString &)specialChars,beginFindIter,endFindIter)) - pos = Distance(distanceIter,beginFindIter); + pos = tString.FindCharInSet(specialChars, oldPos); if (pos != -1) { @@ -1079,8 +1062,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction, } else { - subStrLen = (*inString).Length() - oldPos; - pos = (*inString).Length(); + subStrLen = tString.Length() - oldPos; + pos = tString.Length(); } subStr.Subsume((PRUnichar*)&unicodeBuf[oldPos], PR_FALSE, subStrLen); @@ -1435,7 +1418,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, res = mHTMLEditor->GetPriorHTMLNode(startNode, address_of(priorNode)); if (NS_FAILED(res)) return res; // are they in same block? - if (mHTMLEditor->HasSameBlockNodeParent(startNode, priorNode)) + if (priorNode && mHTMLEditor->HasSameBlockNodeParent(startNode, priorNode)) { // are they same type? if (mHTMLEditor->IsTextNode(priorNode)) @@ -1546,7 +1529,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, res = mHTMLEditor->GetNextHTMLNode(startNode, address_of(nextNode)); if (NS_FAILED(res)) return res; // are they in same block? - if (mHTMLEditor->HasSameBlockNodeParent(startNode, nextNode)) + if (nextNode && mHTMLEditor->HasSameBlockNodeParent(startNode, nextNode)) { // are they same type? if ( mHTMLEditor->IsTextNode(nextNode) ) @@ -1703,7 +1686,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, { nsCOMPtr brNode; res = mHTMLEditor->GetPriorHTMLNode(nodeToDelete, address_of(brNode)); - if (nsTextEditUtils::IsBreak(brNode)) + if (brNode && nsTextEditUtils::IsBreak(brNode)) { // is brNode also a descendant of same block? nsCOMPtr block, brBlock; @@ -5273,6 +5256,33 @@ nsHTMLEditRules::RemoveEmptyNodes() PRBool bIsEmptyNode; res = mHTMLEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE); if (NS_FAILED(res)) return res; + + // only consider certain nodes to be empty for purposes of removal + if (!( + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("b")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("i")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("u")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("tt")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("s")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("strike")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("big")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("small")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("blink")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("sub")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("sup")) || + nsTextEditUtils::NodeIsType(node, NS_LITERAL_STRING("font")) || + nsHTMLEditUtils::IsList(node) || + nsHTMLEditUtils::IsParagraph(node) || + nsHTMLEditUtils::IsHeader(node) || + nsHTMLEditUtils::IsListItem(node) || + nsHTMLEditUtils::IsBlockquote(node)|| + nsHTMLEditUtils::IsDiv(node) || + nsHTMLEditUtils::IsPre(node) || + nsHTMLEditUtils::IsAddress(node) ) ) + { + bIsEmptyNode = PR_FALSE; + } + if (bIsEmptyNode && !nsTextEditUtils::IsBody(node)) { if (nsHTMLEditUtils::IsParagraph(node) || diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 530b415c3bf..8578f2e6916 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -603,6 +603,14 @@ nsHTMLEditor::NodeIsBlock(nsIDOMNode *aNode, PRBool *aIsBlock) return NodeIsBlockStatic(aNode, aIsBlock); } +PRBool +nsHTMLEditor::IsBlockNode(nsIDOMNode *aNode) +{ + PRBool isBlock; + NodeIsBlockStatic(aNode, &isBlock); + return isBlock; +} + // Non-static version for the nsIEditor interface and JavaScript NS_IMETHODIMP nsHTMLEditor::SetDocumentTitle(const nsAReadableString &aTitle) @@ -4451,7 +4459,6 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, // want to treat them as such. Also, don't call ListItems or table // cells empty if caller desires. if (!IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) || - nsHTMLEditUtils::IsTextarea(aNode) || nsHTMLEditUtils::IsMap(aNode) || (aListOrCellNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) || (aListOrCellNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) ) { @@ -4459,6 +4466,15 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, return NS_OK; } + // are we checking a block node? + PRBool isBlock = IsBlockNode(aNode); + // if so, we allow one br without violating emptiness + PRBool seenBR = PR_FALSE; + + // need this for later + PRBool isListItemOrCell = + nsHTMLEditUtils::IsListItem(aNode) || nsHTMLEditUtils::IsTableCell(aNode); + // iterate over node. if no children, or all children are either // empty text nodes or non-editable, then node qualifies as empty nsCOMPtr iter; @@ -4522,9 +4538,28 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode, // is it the node we are iterating over? if (node.get() == aNode) break; // is it a moz-BR and did the caller ask us not to consider those relevant? - if (!(aMozBRDoesntCount && nsTextEditUtils::IsMozBR(node))) + if ((aMozBRDoesntCount && nsTextEditUtils::IsMozBR(node))) + { + // do nothing + } + else if (isBlock && !seenBR && nsTextEditUtils::IsBreak(node)) + { + // the first br in a block doesn't count + seenBR = PR_TRUE; + } + else { // is it an empty node of some sort? + // note: list items or table cells are not considered empty + // if they contain other lists or tables + if (isListItemOrCell) + { + if (nsHTMLEditUtils::IsList(node) || nsHTMLEditUtils::IsTable(node)) + { + *outIsEmptyNode = PR_FALSE; + break; + } + } PRBool isEmptyNode; res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListOrCellNotEmpty); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 5434e6a96bd..9ce6a66ed46 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -383,6 +383,8 @@ public: PRBool aMozBRDoesntCount = PR_FALSE, PRBool aListOrCellNotEmpty = PR_FALSE, PRBool aSafeToAskFrames = PR_FALSE); + + PRBool IsBlockNode(nsIDOMNode *aNode); protected: diff --git a/mozilla/editor/libeditor/html/nsHTMLEditorStyle.cpp b/mozilla/editor/libeditor/html/nsHTMLEditorStyle.cpp index fd4f1f45894..a0389043635 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditorStyle.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditorStyle.cpp @@ -486,7 +486,8 @@ nsresult nsHTMLEditor::SplitStyleAbovePoint(nsCOMPtr *aNode, // split any matching style nodes above the node/offset nsCOMPtr parent, tmp = *aNode; PRInt32 offset; - while (tmp && !nsTextEditUtils::IsBody(tmp)) + + while (tmp && !IsBlockNode(tmp)) { if ( (aProperty && NodeIsType(tmp, aProperty)) || // node is the correct inline prop (aProperty == nsIEditProperty::href && nsHTMLEditUtils::IsLink(tmp)) || // node is href - test if really