Rolling in the last of the NOXIF changes from the Netscape 6 branch, code mostly written by jfrancis. Fixes bugs 50742, 55806, 56000 and 55669. sr=kin, scc. r=kandrot, jst.

This commit is contained in:
jst%netscape.com 2000-10-11 22:50:14 +00:00
parent 292cb40883
commit 17691505d4
14 changed files with 774 additions and 415 deletions

View file

@ -84,8 +84,8 @@ public:
// (Probably not well tested for HTML output.)
OutputFormatted = 2,
// OutputNoDoctype is obsolete, flag 4 available for other uses
//OutputNoDoctype = 4,
// OutputRaw is used by copying text from widgets
OutputRaw = 4,
// No html head tags
OutputBodyOnly = 8,

View file

@ -29,6 +29,7 @@
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsISelection.h"
#include "nsCOMPtr.h"
#include "nsIContentSerializer.h"
@ -48,6 +49,7 @@
#include "nsITextContent.h"
#include "nsIEnumerator.h"
#include "nsISelectionPrivate.h"
#include "nsIFrameSelection.h"
#include "nsIContentIterator.h"
#include "nsISupportsArray.h"
#include "nsIParserService.h"
@ -58,6 +60,7 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID,
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
enum nsRangeIterationDirection {
kDirectionOut = -1,
@ -104,8 +107,9 @@ protected:
nsresult SerializeRangeToString(nsIDOMRange *aRange,
nsAWritableString& aOutputString);
nsresult SerializeRangeNodes(nsIDOMRange* aRange,
nsIDOMNode* aCommonParent,
nsAWritableString& aString);
nsIDOMNode* aNode,
nsAWritableString& aString,
PRInt32 aDepth);
nsresult SerializeRangeContextStart(const nsVoidArray& aAncestorArray,
nsAWritableString& aString);
nsresult SerializeRangeContextEnd(const nsVoidArray& aAncestorArray,
@ -124,6 +128,7 @@ protected:
nsCOMPtr<nsIOutputStream> mStream;
nsCOMPtr<nsIContentSerializer> mSerializer;
nsCOMPtr<nsIUnicodeEncoder> mUnicodeEncoder;
nsCOMPtr<nsIDOMNode> mCommonParent;
nsString mMimeType;
nsString mCharset;
@ -131,8 +136,14 @@ protected:
PRUint32 mWrapColumn;
PRUint32 mStartDepth;
PRUint32 mEndDepth;
PRInt32 mStartRootIndex;
PRInt32 mEndRootIndex;
PRBool mHaltRangeHint;
nsVoidArray mCommonAncestors;
nsVoidArray mStartNodes;
nsVoidArray mStartOffsets;
nsVoidArray mEndNodes;
nsVoidArray mEndOffsets;
};
#ifdef XP_MAC
@ -566,40 +577,50 @@ static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount)
nsresult
nsDocumentEncoder::SerializeRangeNodes(nsIDOMRange* aRange,
nsIDOMNode* aNode,
nsAWritableString& aString)
nsAWritableString& aString,
PRInt32 aDepth)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
nsresult rv=NS_OK;
if (IsNodeIntersectsRange(content, aRange))
// get start and end nodes for this recursion level
nsCOMPtr<nsIContent> startNode, endNode;
startNode = NS_STATIC_CAST(nsIContent *, mStartNodes[mStartRootIndex - aDepth]);
endNode = NS_STATIC_CAST(nsIContent *, mEndNodes[mEndRootIndex - aDepth]);
if ((startNode != content) && (endNode != content))
{
PRBool nodeBefore, nodeAfter;
nsresult rv = CompareNodeToRange(content, aRange, &nodeBefore, &nodeAfter);
if (!nodeBefore && !nodeAfter) // node completely contained
// node is completely contained in range. Serialize the whole subtree
// rooted by this node.
rv = SerializeToStringRecursive(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
// due to implementation it is impossible for text node to be both start and end of
// range. We would have handled that case without getting here.
if (IsTextNode(aNode))
{
rv = SerializeToStringRecursive(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else // node intersects range, but is not contained. recurse if needed.
{
if (IsTextNode(aNode))
if (startNode == content)
{
if (nodeBefore)
{
PRInt32 startOffset;
aRange->GetStartOffset(&startOffset);
rv = SerializeNodeStart(aNode, startOffset, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
PRInt32 endOffset;
aRange->GetEndOffset(&endOffset);
rv = SerializeNodeStart(aNode, 0, endOffset, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
PRInt32 startOffset;
aRange->GetStartOffset(&startOffset);
rv = SerializeNodeStart(aNode, startOffset, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
PRInt32 endOffset;
aRange->GetEndOffset(&endOffset);
rv = SerializeNodeStart(aNode, 0, endOffset, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
}
else
{
if (aNode != mCommonParent.get())
{
if (IncludeInContext(aNode))
{
@ -607,25 +628,62 @@ nsDocumentEncoder::SerializeRangeNodes(nsIDOMRange* aRange,
// so paste client will include this node in paste.
mHaltRangeHint = PR_TRUE;
}
if (nodeBefore && !mHaltRangeHint) mStartDepth++;
if (nodeAfter && !mHaltRangeHint) mEndDepth++;
if ((startNode == content) && !mHaltRangeHint) mStartDepth++;
if ((endNode == content) && !mHaltRangeHint) mEndDepth++;
// serialize the start of this node
rv = SerializeNodeStart(aNode, 0, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIDOMNode> child, tmp;
aNode->GetFirstChild(getter_AddRefs(child));
while (child)
// do some calculations that will tell us which children of this node are in the range.
nsCOMPtr<nsIContent> child;
nsCOMPtr<nsIDOMNode> childAsNode;
PRInt32 startOffset = 0, endOffset = -1;
if (startNode == content)
startOffset = NS_REINTERPRET_CAST(PRInt32, mStartOffsets[mStartRootIndex - aDepth]);
if (endNode == content)
endOffset = NS_REINTERPRET_CAST(PRInt32, mEndOffsets[mEndRootIndex - aDepth]);
// generated content will cause offset values of -1 to be returned.
PRInt32 j, childCount=0;
rv = content->ChildCount(childCount);
NS_ENSURE_SUCCESS(rv, rv);
if (startOffset == -1) startOffset = 0;
if (endOffset == -1) endOffset = childCount;
else
{
// if we are at the "tip" of the selection, endOffset is fine.
// otherwise, we need to add one. This is because of the semantics
// of the offset list created by GetAncestorsAndOffsets(). The
// intermediate points on the list use the endOffset of the
// location of the ancestor, rather than just past it. So we need
// to add one here in order to include it in the children we serialize.
nsCOMPtr<nsIDOMNode> endParent;
aRange->GetEndContainer(getter_AddRefs(endParent));
if (aNode != endParent.get())
{
rv = SerializeRangeNodes(aRange, child, aString);
NS_ENSURE_SUCCESS(rv, rv);
child->GetNextSibling(getter_AddRefs(tmp));
child = tmp;
endOffset++;
}
}
// serialize the children of this node that are in the range
for (j=startOffset; j<endOffset; j++)
{
rv = content->ChildAt(j, *getter_AddRefs(child));
childAsNode = do_QueryInterface(child);
NS_ENSURE_SUCCESS(rv, rv);
if ((j==startOffset) || (j==endOffset-1))
rv = SerializeRangeNodes(aRange, childAsNode, aString, aDepth+1);
else
rv = SerializeToStringRecursive(childAsNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
// serialize the end of this node
if (aNode != mCommonParent.get())
{
rv = SerializeNodeEnd(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
}
return NS_OK;
@ -693,15 +751,15 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
if (collapsed)
return NS_OK;
nsCOMPtr<nsIDOMNode> commonParent, startParent, endParent;
nsCOMPtr<nsIDOMNode> startParent, endParent;
PRInt32 startOffset, endOffset;
aRange->GetCommonAncestorContainer(getter_AddRefs(commonParent));
aRange->GetCommonAncestorContainer(getter_AddRefs(mCommonParent));
if (!commonParent)
if (!mCommonParent)
return NS_OK;
AdjustCommonParent(&commonParent);
AdjustCommonParent(&mCommonParent);
aRange->GetStartContainer(getter_AddRefs(startParent));
NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
@ -712,9 +770,18 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
aRange->GetEndOffset(&endOffset);
mCommonAncestors.Clear();
mStartNodes.Clear();
mStartOffsets.Clear();
mEndNodes.Clear();
mEndOffsets.Clear();
nsRange::FillArrayWithAncestors(&mCommonAncestors, commonParent);
nsRange::FillArrayWithAncestors(&mCommonAncestors, mCommonParent);
nsRange::GetAncestorsAndOffsets(startParent, startOffset, &mStartNodes, &mStartOffsets);
nsRange::GetAncestorsAndOffsets(endParent, endOffset, &mEndNodes, &mEndOffsets);
nsCOMPtr<nsIContent> commonContent = do_QueryInterface(mCommonParent);
mStartRootIndex = mStartNodes.IndexOf(commonContent);
mEndRootIndex = mEndNodes.IndexOf(commonContent);
nsresult rv = NS_OK;
rv = SerializeRangeContextStart(mCommonAncestors, aOutputString);
@ -727,17 +794,9 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
}
else
{
nsCOMPtr<nsIDOMNode> child, tmp;
commonParent->GetFirstChild(getter_AddRefs(child));
while (child)
{
rv = SerializeRangeNodes(aRange, child, aOutputString);
NS_ENSURE_SUCCESS(rv, rv);
child->GetNextSibling(getter_AddRefs(tmp));
child = tmp;
}
rv = SerializeRangeNodes(aRange, mCommonParent, aOutputString, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = SerializeRangeContextEnd(mCommonAncestors, aOutputString);
NS_ENSURE_SUCCESS(rv, rv);
@ -888,12 +947,14 @@ protected:
nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, PRInt32 aOffset);
PRBool IsMozBR(nsIDOMNode* aNode);
nsresult GetNodeLocation(nsIDOMNode *inChild, nsCOMPtr<nsIDOMNode> *outParent, PRInt32 *outOffset);
PRBool IsRoot(nsIDOMNode* aNode);
PRBool IsFirstNode(nsIDOMNode *aNode);
PRBool IsLastNode(nsIDOMNode *aNode);
PRBool IsEmptyTextContent(nsIDOMNode* aNode);
virtual PRBool IncludeInContext(nsIDOMNode *aNode);
nsCOMPtr<nsIParserService> mParserService;
PRBool mIsTextWidget;
};
#ifdef XP_MAC
@ -903,6 +964,7 @@ protected:
nsHTMLCopyEncoder::nsHTMLCopyEncoder()
{
mIsTextWidget = PR_FALSE;
}
nsHTMLCopyEncoder::~nsHTMLCopyEncoder()
@ -911,7 +973,7 @@ nsHTMLCopyEncoder::~nsHTMLCopyEncoder()
NS_IMETHODIMP
nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
const nsAReadableString& aIgnored,
const nsAReadableString& aMimetype,
PRUint32 aFlags)
{
if (!aDocument)
@ -920,7 +982,7 @@ nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
mDocument = aDocument;
mMimeType = NS_LITERAL_STRING("text/html");
mFlags = aFlags;
nsresult rv;
@ -931,19 +993,50 @@ nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
NS_IMETHODIMP
nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
{
// normalize selection
// check for text widgets: we need to recognize these so that
// we don't tweak the selection to be outside of the magic
// div that ender-lite text widgets are embedded in.
nsCOMPtr<nsIDOMNode> selNode;
nsresult rv = aSelection->GetFocusNode(getter_AddRefs(selNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> tmp, selContent( do_QueryInterface(selNode) );
while (selContent)
{
nsCOMPtr<nsIAtom> atom;
selContent->GetTag(*getter_AddRefs(atom));
if (atom.get() == nsHTMLAtoms::input ||
atom.get() == nsHTMLAtoms::textarea)
{
mIsTextWidget = PR_TRUE;
break;
}
selContent->GetParent(*getter_AddRefs(tmp));
selContent = tmp;
}
// also consider ourselves in a text widget if we can't find an html document
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
if (!htmlDoc) mIsTextWidget = PR_TRUE;
// normalize selection if we are not in a widget
if (mIsTextWidget)
{
mSelection = aSelection;
mFlags |= OutputRaw;
return NS_OK;
}
// there's no Clone() for selection! fix...
//nsresult rv = aSelection->Clone(getter_AddRefs(mSelection);
//NS_ENSURE_SUCCESS(rv, rv);
mSelection = aSelection;
nsCOMPtr<nsISelectionPrivate> privSelection = do_QueryInterface(mSelection);
NS_NewDomSelection(getter_AddRefs(mSelection));
NS_ENSURE_TRUE(mSelection, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionPrivate> privSelection( do_QueryInterface(aSelection) );
NS_ENSURE_TRUE(privSelection, NS_ERROR_FAILURE);
// get selection range enumerator
nsCOMPtr<nsIEnumerator> enumerator;
nsresult rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
@ -957,11 +1050,18 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> myRange;
range->CloneRange(getter_AddRefs(myRange));
NS_ENSURE_TRUE(myRange, NS_ERROR_FAILURE);
// adjust range to include any ancestors who's children are entirely selected
rv = PromoteRange(range);
rv = PromoteRange(myRange);
NS_ENSURE_SUCCESS(rv, rv);
rv = mSelection->AddRange(myRange);
NS_ENSURE_SUCCESS(rv, rv);
enumerator->Next();
}
@ -975,7 +1075,17 @@ nsHTMLCopyEncoder::EncodeToStringWithContext(nsAWritableString& aEncodedString,
{
nsresult rv = EncodeToString(aEncodedString);
NS_ENSURE_SUCCESS(rv, rv);
if (mIsTextWidget) {
aEncodedString.Insert(NS_LITERAL_STRING("<pre>"), 0);
aEncodedString.Append(NS_LITERAL_STRING("</pre>"));
}
// do not encode any context info or range hints if we are not in an html document.
// do not encode any context info or range hints if we are in a text widget.
if (mIsTextWidget) return NS_OK;
// now encode common ancestors into aContextString. Note that the common ancestors
// will be for the last range in the selection in the case of multirange selections.
// encoding ancestors every range in a multirange selection in a way that could be
@ -1126,12 +1236,12 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, PRInt32
// finding the real start for this point. look up the tree for as long as we are the
// first node in the container, and as long as we haven't hit the body node.
if (!IsTag(node, nsHTMLAtoms::body))
if (!IsRoot(node))
{
rv = GetNodeLocation(node, &parent, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == -1) return NS_OK; // we hit generated content; STOP
while ((IsFirstNode(node)) && (!IsTag(parent, nsHTMLAtoms::body)))
while ((IsFirstNode(node)) && (!IsRoot(parent)))
{
if (bResetPromotion)
{
@ -1211,12 +1321,12 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, PRInt32
// finding the real end for this point. look up the tree for as long as we are the
// last node in the container, and as long as we haven't hit the body node.
if (!IsTag(node, nsHTMLAtoms::body))
if (!IsRoot(node))
{
rv = GetNodeLocation(node, &parent, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == -1) return NS_OK; // we hit generated content; STOP
while ((IsLastNode(node)) && (!IsTag(parent, nsHTMLAtoms::body)))
while ((IsLastNode(node)) && (!IsRoot(parent)))
{
if (bResetPromotion)
{
@ -1325,6 +1435,19 @@ nsHTMLCopyEncoder::GetNodeLocation(nsIDOMNode *inChild, nsCOMPtr<nsIDOMNode> *ou
return result;
}
PRBool
nsHTMLCopyEncoder::IsRoot(nsIDOMNode* aNode)
{
if (aNode)
{
if (mIsTextWidget)
return (IsTag(aNode, nsHTMLAtoms::div));
else
return (IsTag(aNode, nsHTMLAtoms::body));
}
return PR_FALSE;
}
PRBool
nsHTMLCopyEncoder::IsFirstNode(nsIDOMNode *aNode)
{

View file

@ -35,6 +35,7 @@
#include "nsHTMLAtoms.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsEscape.h"
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
@ -68,21 +69,6 @@ nsHTMLContentSerializer::~nsHTMLContentSerializer()
{
}
nsresult
nsHTMLContentSerializer::GetEntityConverter(nsIEntityConverter** aConverter)
{
if (!mEntityConverter) {
nsresult rv;
rv = nsComponentManager::CreateInstance(kEntityConverterCID, NULL,
NS_GET_IID(nsIEntityConverter),
getter_AddRefs(mEntityConverter));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
CallQueryInterface(mEntityConverter.get(), aConverter);
return NS_OK;
}
nsresult
nsHTMLContentSerializer::GetParserService(nsIParserService** aParserService)
{
@ -149,7 +135,8 @@ nsHTMLContentSerializer::AppendText(nsIDOMText* aText,
PRInt32 lastNewlineOffset = kNotFound;
PRBool hasLongLines = HasLongLines(data, lastNewlineOffset);
if (mPreLevel || (!mDoFormat && !hasLongLines)) {
if (mPreLevel || (!mDoFormat && !hasLongLines) ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
AppendToString(data, aStr);
if (lastNewlineOffset != kNotFound) {
@ -378,7 +365,6 @@ nsHTMLContentSerializer::AppendToStringWrapped(const nsAReadableString& aStr,
PRBool done = PR_FALSE;
PRInt32 indx = 0;
PRInt32 strOffset = 0;
PRInt32 oldLineOffset = 0;
PRInt32 lineLength, oldLineEnd;
// Make sure we haven't gone too far already
@ -468,26 +454,17 @@ nsHTMLContentSerializer::AppendToString(const nsAReadableString& aStr,
return;
}
nsresult rv;
if (aIncrColumn) {
mColPos += aStr.Length();
}
if (aTranslateEntities) {
nsCOMPtr<nsIEntityConverter> converter;
GetEntityConverter(getter_AddRefs(converter));
if (converter) {
PRUnichar *encodedBuffer;
rv = mEntityConverter->ConvertToEntities(nsPromiseFlatString(aStr),
nsIEntityConverter::html40Latin1,
&encodedBuffer);
if (NS_SUCCEEDED(rv)) {
aOutputStr.Append(encodedBuffer);
nsCRT::free(encodedBuffer);
return;
}
PRUnichar *encodedBuffer;
encodedBuffer = nsEscapeHTML2(nsPromiseFlatString(aStr), aStr.Length());
if (encodedBuffer) {
aOutputStr.Append(encodedBuffer);
nsCRT::free(encodedBuffer);
return;
}
}
@ -513,7 +490,8 @@ PRBool
nsHTMLContentSerializer::LineBreakBeforeOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -548,7 +526,8 @@ PRBool
nsHTMLContentSerializer::LineBreakAfterOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -576,7 +555,8 @@ PRBool
nsHTMLContentSerializer::LineBreakBeforeClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -598,7 +578,8 @@ PRBool
nsHTMLContentSerializer::LineBreakAfterClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}

View file

@ -281,6 +281,9 @@ nsPlainTextSerializer::AppendElementStart(nsIDOMElement *aElement,
mContent = 0;
mOutputString = nsnull;
if (!mInHead && id == eHTMLTag_head)
mInHead = PR_TRUE;
return rv;
}
@ -310,6 +313,9 @@ nsPlainTextSerializer::AppendElementEnd(nsIDOMElement *aElement,
mContent = 0;
mOutputString = nsnull;
if (mInHead && id == eHTMLTag_head)
mInHead = PR_FALSE;
return rv;
}
@ -326,8 +332,6 @@ NS_IMETHODIMP
nsPlainTextSerializer::OpenContainer(const nsIParserNode& aNode)
{
PRInt32 type = aNode.GetNodeType();
const nsString& namestr = aNode.GetText();
nsCOMPtr<nsIAtom> name = dont_AddRef(NS_NewAtom(namestr));
mParserNode = NS_CONST_CAST(nsIParserNode *, &aNode);
return DoOpenContainer(type);

View file

@ -150,6 +150,8 @@ public:
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
static PRInt32 IndexOf(nsIDOMNode* aNode);
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
static PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
static nsCOMPtr<nsIDOMNode> CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
static nsresult GetDOMNodeFromContent(nsIContent* inContentNode, nsCOMPtr<nsIDOMNode>* outDomNode);
static nsresult GetContentFromDOMNode(nsIDOMNode* inDomNode, nsCOMPtr<nsIContent>* outContentNode);
@ -173,9 +175,6 @@ public:
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
nsresult AddToListOf(nsIDOMNode* aNode);
nsresult RemoveFromListOf(nsIDOMNode* aNode);

View file

@ -2417,6 +2417,36 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
return result;
}
static nsCOMPtr<nsIDOMNode> GetListParent(nsIDOMNode* aNode)
{
if (!aNode) return nsnull;
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsList(parent)) return parent;
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nsnull;
}
static nsCOMPtr<nsIDOMNode> GetTableParent(nsIDOMNode* aNode)
{
if (!aNode) return nsnull;
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsTable(parent)) return parent;
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nsnull;
}
NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString)
{
nsAutoString charset;
@ -2476,8 +2506,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsString& aInputStr
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
if (!nsrange)
return NS_ERROR_NO_INTERFACE;
nsCAutoString foo; foo.AssignWithConversion(inputString);
printf ("fff = '%s'\n", (const char *)foo);
// create a dom document fragment that represents the structure to paste
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
res = nsrange->CreateContextualFragment(inputString,
@ -2485,11 +2514,6 @@ printf ("fff = '%s'\n", (const char *)foo);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
PRInt32 bar;
nsCOMPtr<nsIContent> f(do_QueryInterface(docfrag));
f->ChildCount(bar);
printf ("Child count %d\n", bar);
res = StripFormattingNodes(fragmentAsNode);
NS_ENSURE_SUCCESS(res, res);
@ -2657,100 +2681,152 @@ printf ("Child count %d\n", bar);
parentNode = temp;
}
// scan insertion list for table elements (other than table).
PRBool bHaveTableGuts = PR_FALSE;
PRBool bHaveListGuts = PR_FALSE;
PRUint32 listCount, j;
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
// build up list of parents of first node in lst that are either:
// lists, or tables.
nsCOMPtr<nsISupports> isup = nodeList->ElementAt(0);
nsCOMPtr<nsIDOMNode> pNode( do_QueryInterface(isup) );
nsCOMPtr<nsISupportsArray> listAndTableArray;
res = NS_NewISupportsArray(getter_AddRefs(listAndTableArray));
NS_ENSURE_SUCCESS(res, res);
while (pNode)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode))
if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode))
{
bHaveTableGuts = PR_TRUE;
isup = do_QueryInterface(pNode);
listAndTableArray->AppendElement(isup);
}
if (nsHTMLEditUtils::IsListItem(curNode))
{
bHaveListGuts = PR_TRUE;
}
if (bHaveTableGuts && bHaveListGuts) break; // no need to continue
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
// if we have pieces of tables to be inserted, then make sure beginning content
// is not in a table. If it is, let's force the paste to deal with table elements
// right away, so that it doesn't orphan some table contents outside the table.
if (bHaveTableGuts)
// remember number of lists and tables above us
PRUint32 listAndTableParents;
PRInt32 highWaterMark = -1;
listAndTableArray->Count(&listAndTableParents);
PRUint32 listCount, j;
if (listAndTableParents)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
if (!nsHTMLEditUtils::IsTableElement(curNode))
// scan insertion list for table elements (other than table).
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
{
nsCOMPtr<nsIDOMNode> parent, tmp;
curNode->GetParentNode(getter_AddRefs(parent));
while (parent)
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode))
{
if (nsHTMLEditUtils::IsTableElement(parent))
nsCOMPtr<nsIDOMNode> theTable = GetTableParent(curNode);
if (theTable)
{
isupports = do_QueryInterface(parent);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
nsCOMPtr<nsISupports> isupTable(do_QueryInterface(theTable));
PRInt32 indexT = listAndTableArray->IndexOf(isupTable);
if (indexT >= 0)
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (nsHTMLEditUtils::IsDescendantOf(tmp, parent))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
break;
highWaterMark = indexT;
if ((PRUint32)highWaterMark == listAndTableParents-1) break;
}
else
{
break;
}
}
}
if (nsHTMLEditUtils::IsListItem(curNode))
{
nsCOMPtr<nsIDOMNode> theList = GetListParent(curNode);
if (theList)
{
nsCOMPtr<nsISupports> isupList(do_QueryInterface(theList));
PRInt32 indexL = listAndTableArray->IndexOf(isupList);
if (indexL >= 0)
{
highWaterMark = indexL;
if ((PRUint32)highWaterMark == listAndTableParents-1) break;
}
else
{
break;
}
}
parent->GetParentNode(getter_AddRefs(curNode));
parent = curNode;
}
}
}
// same story as above, only for pieces of lists.
if (bHaveListGuts)
// if we have pieces of tables or lists to be inserted, let's force the paste
// to deal with table elements right away, so that it doesn't orphan some
// table or list contents outside the table or list.
if (highWaterMark >= 0)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0);
nsCOMPtr<nsISupports> isupports = listAndTableArray->ElementAt(highWaterMark);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
if (!nsHTMLEditUtils::IsListItem(curNode))
nsCOMPtr<nsIDOMNode> replaceNode;
if (nsHTMLEditUtils::IsTable(curNode))
{
nsCOMPtr<nsIDOMNode> parent;
curNode->GetParentNode(getter_AddRefs(parent));
while (parent)
// look upward from curNode for a piece of this table
isup = nodeList->ElementAt(0);
pNode = do_QueryInterface(isup);
while (pNode)
{
if (nsHTMLEditUtils::IsListItem(parent))
if (nsHTMLEditUtils::IsTableElement(pNode) && !nsHTMLEditUtils::IsTable(pNode))
{
isupports = do_QueryInterface(parent);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
nsCOMPtr<nsIDOMNode> tableP = GetTableParent(pNode);
if (tableP == curNode)
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (nsHTMLEditUtils::IsDescendantOf(tmp, parent))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
break;
replaceNode = pNode;
break;
}
}
parent->GetParentNode(getter_AddRefs(curNode));
parent = curNode;
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
}
else // list case
{
// look upward from curNode for a piece of this list
isup = nodeList->ElementAt(0);
pNode = do_QueryInterface(isup);
while (pNode)
{
if (nsHTMLEditUtils::IsListItem(pNode))
{
nsCOMPtr<nsIDOMNode> listP = GetListParent(pNode);
if (listP == curNode)
{
replaceNode = pNode;
break;
}
}
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
}
if (replaceNode)
{
isupports = do_QueryInterface(replaceNode);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (tmp && nsHTMLEditUtils::IsDescendantOf(tmp, replaceNode))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
}
}
// Loop over the node list and paste the nodes:
PRBool bDidInsert = PR_FALSE;
nsCOMPtr<nsIDOMNode> lastInsertNode, insertedContextParent;
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
@ -6147,8 +6223,6 @@ NS_IMETHODIMP nsHTMLEditor::OutputToString(nsAWritableString& aOutputString,
}
else if (nsHTMLEditUtils::IsBody(rootElement))
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDocumentEncoder> encoder;
nsCAutoString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
formatType.AppendWithConversion(aFormatType);

View file

@ -2417,6 +2417,36 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
return result;
}
static nsCOMPtr<nsIDOMNode> GetListParent(nsIDOMNode* aNode)
{
if (!aNode) return nsnull;
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsList(parent)) return parent;
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nsnull;
}
static nsCOMPtr<nsIDOMNode> GetTableParent(nsIDOMNode* aNode)
{
if (!aNode) return nsnull;
nsCOMPtr<nsIDOMNode> parent, tmp;
aNode->GetParentNode(getter_AddRefs(parent));
while (parent)
{
if (nsHTMLEditUtils::IsTable(parent)) return parent;
parent->GetParentNode(getter_AddRefs(tmp));
parent = tmp;
}
return nsnull;
}
NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString)
{
nsAutoString charset;
@ -2476,8 +2506,7 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsString& aInputStr
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
if (!nsrange)
return NS_ERROR_NO_INTERFACE;
nsCAutoString foo; foo.AssignWithConversion(inputString);
printf ("fff = '%s'\n", (const char *)foo);
// create a dom document fragment that represents the structure to paste
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
res = nsrange->CreateContextualFragment(inputString,
@ -2485,11 +2514,6 @@ printf ("fff = '%s'\n", (const char *)foo);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
PRInt32 bar;
nsCOMPtr<nsIContent> f(do_QueryInterface(docfrag));
f->ChildCount(bar);
printf ("Child count %d\n", bar);
res = StripFormattingNodes(fragmentAsNode);
NS_ENSURE_SUCCESS(res, res);
@ -2657,100 +2681,152 @@ printf ("Child count %d\n", bar);
parentNode = temp;
}
// scan insertion list for table elements (other than table).
PRBool bHaveTableGuts = PR_FALSE;
PRBool bHaveListGuts = PR_FALSE;
PRUint32 listCount, j;
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
// build up list of parents of first node in lst that are either:
// lists, or tables.
nsCOMPtr<nsISupports> isup = nodeList->ElementAt(0);
nsCOMPtr<nsIDOMNode> pNode( do_QueryInterface(isup) );
nsCOMPtr<nsISupportsArray> listAndTableArray;
res = NS_NewISupportsArray(getter_AddRefs(listAndTableArray));
NS_ENSURE_SUCCESS(res, res);
while (pNode)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode))
if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode))
{
bHaveTableGuts = PR_TRUE;
isup = do_QueryInterface(pNode);
listAndTableArray->AppendElement(isup);
}
if (nsHTMLEditUtils::IsListItem(curNode))
{
bHaveListGuts = PR_TRUE;
}
if (bHaveTableGuts && bHaveListGuts) break; // no need to continue
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
// if we have pieces of tables to be inserted, then make sure beginning content
// is not in a table. If it is, let's force the paste to deal with table elements
// right away, so that it doesn't orphan some table contents outside the table.
if (bHaveTableGuts)
// remember number of lists and tables above us
PRUint32 listAndTableParents;
PRInt32 highWaterMark = -1;
listAndTableArray->Count(&listAndTableParents);
PRUint32 listCount, j;
if (listAndTableParents)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
if (!nsHTMLEditUtils::IsTableElement(curNode))
// scan insertion list for table elements (other than table).
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
{
nsCOMPtr<nsIDOMNode> parent, tmp;
curNode->GetParentNode(getter_AddRefs(parent));
while (parent)
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
NS_ENSURE_TRUE(curNode, NS_ERROR_FAILURE);
if (nsHTMLEditUtils::IsTableElement(curNode) && !nsHTMLEditUtils::IsTable(curNode))
{
if (nsHTMLEditUtils::IsTableElement(parent))
nsCOMPtr<nsIDOMNode> theTable = GetTableParent(curNode);
if (theTable)
{
isupports = do_QueryInterface(parent);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
nsCOMPtr<nsISupports> isupTable(do_QueryInterface(theTable));
PRInt32 indexT = listAndTableArray->IndexOf(isupTable);
if (indexT >= 0)
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (nsHTMLEditUtils::IsDescendantOf(tmp, parent))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
break;
highWaterMark = indexT;
if ((PRUint32)highWaterMark == listAndTableParents-1) break;
}
else
{
break;
}
}
}
if (nsHTMLEditUtils::IsListItem(curNode))
{
nsCOMPtr<nsIDOMNode> theList = GetListParent(curNode);
if (theList)
{
nsCOMPtr<nsISupports> isupList(do_QueryInterface(theList));
PRInt32 indexL = listAndTableArray->IndexOf(isupList);
if (indexL >= 0)
{
highWaterMark = indexL;
if ((PRUint32)highWaterMark == listAndTableParents-1) break;
}
else
{
break;
}
}
parent->GetParentNode(getter_AddRefs(curNode));
parent = curNode;
}
}
}
// same story as above, only for pieces of lists.
if (bHaveListGuts)
// if we have pieces of tables or lists to be inserted, let's force the paste
// to deal with table elements right away, so that it doesn't orphan some
// table or list contents outside the table or list.
if (highWaterMark >= 0)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0);
nsCOMPtr<nsISupports> isupports = listAndTableArray->ElementAt(highWaterMark);
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) );
if (!nsHTMLEditUtils::IsListItem(curNode))
nsCOMPtr<nsIDOMNode> replaceNode;
if (nsHTMLEditUtils::IsTable(curNode))
{
nsCOMPtr<nsIDOMNode> parent;
curNode->GetParentNode(getter_AddRefs(parent));
while (parent)
// look upward from curNode for a piece of this table
isup = nodeList->ElementAt(0);
pNode = do_QueryInterface(isup);
while (pNode)
{
if (nsHTMLEditUtils::IsListItem(parent))
if (nsHTMLEditUtils::IsTableElement(pNode) && !nsHTMLEditUtils::IsTable(pNode))
{
isupports = do_QueryInterface(parent);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
nsCOMPtr<nsIDOMNode> tableP = GetTableParent(pNode);
if (tableP == curNode)
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (nsHTMLEditUtils::IsDescendantOf(tmp, parent))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
break;
replaceNode = pNode;
break;
}
}
parent->GetParentNode(getter_AddRefs(curNode));
parent = curNode;
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
}
else // list case
{
// look upward from curNode for a piece of this list
isup = nodeList->ElementAt(0);
pNode = do_QueryInterface(isup);
while (pNode)
{
if (nsHTMLEditUtils::IsListItem(pNode))
{
nsCOMPtr<nsIDOMNode> listP = GetListParent(pNode);
if (listP == curNode)
{
replaceNode = pNode;
break;
}
}
nsCOMPtr<nsIDOMNode> parent;
pNode->GetParentNode(getter_AddRefs(parent));
pNode = parent;
}
}
if (replaceNode)
{
isupports = do_QueryInterface(replaceNode);
nodeList->ReplaceElementAt(isupports, 0);
// postprocess list to remove any descendants of this node
// so that we dont insert them twice.
do
{
isupports = nodeList->ElementAt(1);
tmp = do_QueryInterface(isupports);
if (tmp && nsHTMLEditUtils::IsDescendantOf(tmp, replaceNode))
nodeList->RemoveElementAt(1);
else
break;
} while(tmp);
}
}
// Loop over the node list and paste the nodes:
PRBool bDidInsert = PR_FALSE;
nsCOMPtr<nsIDOMNode> lastInsertNode, insertedContextParent;
nodeList->Count(&listCount);
for (j=0; j<listCount; j++)
{
nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j);
@ -6147,8 +6223,6 @@ NS_IMETHODIMP nsHTMLEditor::OutputToString(nsAWritableString& aOutputString,
}
else if (nsHTMLEditUtils::IsBody(rootElement))
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDocumentEncoder> encoder;
nsCAutoString formatType(NS_DOC_ENCODER_CONTRACTID_BASE);
formatType.AppendWithConversion(aFormatType);

View file

@ -84,8 +84,8 @@ public:
// (Probably not well tested for HTML output.)
OutputFormatted = 2,
// OutputNoDoctype is obsolete, flag 4 available for other uses
//OutputNoDoctype = 4,
// OutputRaw is used by copying text from widgets
OutputRaw = 4,
// No html head tags
OutputBodyOnly = 8,

View file

@ -29,6 +29,7 @@
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIDocument.h"
#include "nsIHTMLDocument.h"
#include "nsISelection.h"
#include "nsCOMPtr.h"
#include "nsIContentSerializer.h"
@ -48,6 +49,7 @@
#include "nsITextContent.h"
#include "nsIEnumerator.h"
#include "nsISelectionPrivate.h"
#include "nsIFrameSelection.h"
#include "nsIContentIterator.h"
#include "nsISupportsArray.h"
#include "nsIParserService.h"
@ -58,6 +60,7 @@ static NS_DEFINE_CID(kCharsetConverterManagerCID,
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
nsresult NS_NewContentSubtreeIterator(nsIContentIterator** aInstancePtrResult);
nsresult NS_NewDomSelection(nsISelection **aDomSelection);
enum nsRangeIterationDirection {
kDirectionOut = -1,
@ -104,8 +107,9 @@ protected:
nsresult SerializeRangeToString(nsIDOMRange *aRange,
nsAWritableString& aOutputString);
nsresult SerializeRangeNodes(nsIDOMRange* aRange,
nsIDOMNode* aCommonParent,
nsAWritableString& aString);
nsIDOMNode* aNode,
nsAWritableString& aString,
PRInt32 aDepth);
nsresult SerializeRangeContextStart(const nsVoidArray& aAncestorArray,
nsAWritableString& aString);
nsresult SerializeRangeContextEnd(const nsVoidArray& aAncestorArray,
@ -124,6 +128,7 @@ protected:
nsCOMPtr<nsIOutputStream> mStream;
nsCOMPtr<nsIContentSerializer> mSerializer;
nsCOMPtr<nsIUnicodeEncoder> mUnicodeEncoder;
nsCOMPtr<nsIDOMNode> mCommonParent;
nsString mMimeType;
nsString mCharset;
@ -131,8 +136,14 @@ protected:
PRUint32 mWrapColumn;
PRUint32 mStartDepth;
PRUint32 mEndDepth;
PRInt32 mStartRootIndex;
PRInt32 mEndRootIndex;
PRBool mHaltRangeHint;
nsVoidArray mCommonAncestors;
nsVoidArray mStartNodes;
nsVoidArray mStartOffsets;
nsVoidArray mEndNodes;
nsVoidArray mEndOffsets;
};
#ifdef XP_MAC
@ -566,40 +577,50 @@ static nsresult GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount)
nsresult
nsDocumentEncoder::SerializeRangeNodes(nsIDOMRange* aRange,
nsIDOMNode* aNode,
nsAWritableString& aString)
nsAWritableString& aString,
PRInt32 aDepth)
{
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
nsresult rv=NS_OK;
if (IsNodeIntersectsRange(content, aRange))
// get start and end nodes for this recursion level
nsCOMPtr<nsIContent> startNode, endNode;
startNode = NS_STATIC_CAST(nsIContent *, mStartNodes[mStartRootIndex - aDepth]);
endNode = NS_STATIC_CAST(nsIContent *, mEndNodes[mEndRootIndex - aDepth]);
if ((startNode != content) && (endNode != content))
{
PRBool nodeBefore, nodeAfter;
nsresult rv = CompareNodeToRange(content, aRange, &nodeBefore, &nodeAfter);
if (!nodeBefore && !nodeAfter) // node completely contained
// node is completely contained in range. Serialize the whole subtree
// rooted by this node.
rv = SerializeToStringRecursive(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
// due to implementation it is impossible for text node to be both start and end of
// range. We would have handled that case without getting here.
if (IsTextNode(aNode))
{
rv = SerializeToStringRecursive(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else // node intersects range, but is not contained. recurse if needed.
{
if (IsTextNode(aNode))
if (startNode == content)
{
if (nodeBefore)
{
PRInt32 startOffset;
aRange->GetStartOffset(&startOffset);
rv = SerializeNodeStart(aNode, startOffset, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
PRInt32 endOffset;
aRange->GetEndOffset(&endOffset);
rv = SerializeNodeStart(aNode, 0, endOffset, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
PRInt32 startOffset;
aRange->GetStartOffset(&startOffset);
rv = SerializeNodeStart(aNode, startOffset, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
else
{
PRInt32 endOffset;
aRange->GetEndOffset(&endOffset);
rv = SerializeNodeStart(aNode, 0, endOffset, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
}
else
{
if (aNode != mCommonParent.get())
{
if (IncludeInContext(aNode))
{
@ -607,25 +628,62 @@ nsDocumentEncoder::SerializeRangeNodes(nsIDOMRange* aRange,
// so paste client will include this node in paste.
mHaltRangeHint = PR_TRUE;
}
if (nodeBefore && !mHaltRangeHint) mStartDepth++;
if (nodeAfter && !mHaltRangeHint) mEndDepth++;
if ((startNode == content) && !mHaltRangeHint) mStartDepth++;
if ((endNode == content) && !mHaltRangeHint) mEndDepth++;
// serialize the start of this node
rv = SerializeNodeStart(aNode, 0, -1, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIDOMNode> child, tmp;
aNode->GetFirstChild(getter_AddRefs(child));
while (child)
// do some calculations that will tell us which children of this node are in the range.
nsCOMPtr<nsIContent> child;
nsCOMPtr<nsIDOMNode> childAsNode;
PRInt32 startOffset = 0, endOffset = -1;
if (startNode == content)
startOffset = NS_REINTERPRET_CAST(PRInt32, mStartOffsets[mStartRootIndex - aDepth]);
if (endNode == content)
endOffset = NS_REINTERPRET_CAST(PRInt32, mEndOffsets[mEndRootIndex - aDepth]);
// generated content will cause offset values of -1 to be returned.
PRInt32 j, childCount=0;
rv = content->ChildCount(childCount);
NS_ENSURE_SUCCESS(rv, rv);
if (startOffset == -1) startOffset = 0;
if (endOffset == -1) endOffset = childCount;
else
{
// if we are at the "tip" of the selection, endOffset is fine.
// otherwise, we need to add one. This is because of the semantics
// of the offset list created by GetAncestorsAndOffsets(). The
// intermediate points on the list use the endOffset of the
// location of the ancestor, rather than just past it. So we need
// to add one here in order to include it in the children we serialize.
nsCOMPtr<nsIDOMNode> endParent;
aRange->GetEndContainer(getter_AddRefs(endParent));
if (aNode != endParent.get())
{
rv = SerializeRangeNodes(aRange, child, aString);
NS_ENSURE_SUCCESS(rv, rv);
child->GetNextSibling(getter_AddRefs(tmp));
child = tmp;
endOffset++;
}
}
// serialize the children of this node that are in the range
for (j=startOffset; j<endOffset; j++)
{
rv = content->ChildAt(j, *getter_AddRefs(child));
childAsNode = do_QueryInterface(child);
NS_ENSURE_SUCCESS(rv, rv);
if ((j==startOffset) || (j==endOffset-1))
rv = SerializeRangeNodes(aRange, childAsNode, aString, aDepth+1);
else
rv = SerializeToStringRecursive(childAsNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
// serialize the end of this node
if (aNode != mCommonParent.get())
{
rv = SerializeNodeEnd(aNode, aString);
NS_ENSURE_SUCCESS(rv, rv);
}
}
}
}
return NS_OK;
@ -693,15 +751,15 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
if (collapsed)
return NS_OK;
nsCOMPtr<nsIDOMNode> commonParent, startParent, endParent;
nsCOMPtr<nsIDOMNode> startParent, endParent;
PRInt32 startOffset, endOffset;
aRange->GetCommonAncestorContainer(getter_AddRefs(commonParent));
aRange->GetCommonAncestorContainer(getter_AddRefs(mCommonParent));
if (!commonParent)
if (!mCommonParent)
return NS_OK;
AdjustCommonParent(&commonParent);
AdjustCommonParent(&mCommonParent);
aRange->GetStartContainer(getter_AddRefs(startParent));
NS_ENSURE_TRUE(startParent, NS_ERROR_FAILURE);
@ -712,9 +770,18 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
aRange->GetEndOffset(&endOffset);
mCommonAncestors.Clear();
mStartNodes.Clear();
mStartOffsets.Clear();
mEndNodes.Clear();
mEndOffsets.Clear();
nsRange::FillArrayWithAncestors(&mCommonAncestors, commonParent);
nsRange::FillArrayWithAncestors(&mCommonAncestors, mCommonParent);
nsRange::GetAncestorsAndOffsets(startParent, startOffset, &mStartNodes, &mStartOffsets);
nsRange::GetAncestorsAndOffsets(endParent, endOffset, &mEndNodes, &mEndOffsets);
nsCOMPtr<nsIContent> commonContent = do_QueryInterface(mCommonParent);
mStartRootIndex = mStartNodes.IndexOf(commonContent);
mEndRootIndex = mEndNodes.IndexOf(commonContent);
nsresult rv = NS_OK;
rv = SerializeRangeContextStart(mCommonAncestors, aOutputString);
@ -727,17 +794,9 @@ nsDocumentEncoder::SerializeRangeToString(nsIDOMRange *aRange,
}
else
{
nsCOMPtr<nsIDOMNode> child, tmp;
commonParent->GetFirstChild(getter_AddRefs(child));
while (child)
{
rv = SerializeRangeNodes(aRange, child, aOutputString);
NS_ENSURE_SUCCESS(rv, rv);
child->GetNextSibling(getter_AddRefs(tmp));
child = tmp;
}
rv = SerializeRangeNodes(aRange, mCommonParent, aOutputString, 0);
NS_ENSURE_SUCCESS(rv, rv);
}
rv = SerializeRangeContextEnd(mCommonAncestors, aOutputString);
NS_ENSURE_SUCCESS(rv, rv);
@ -888,12 +947,14 @@ protected:
nsCOMPtr<nsIDOMNode> GetChildAt(nsIDOMNode *aParent, PRInt32 aOffset);
PRBool IsMozBR(nsIDOMNode* aNode);
nsresult GetNodeLocation(nsIDOMNode *inChild, nsCOMPtr<nsIDOMNode> *outParent, PRInt32 *outOffset);
PRBool IsRoot(nsIDOMNode* aNode);
PRBool IsFirstNode(nsIDOMNode *aNode);
PRBool IsLastNode(nsIDOMNode *aNode);
PRBool IsEmptyTextContent(nsIDOMNode* aNode);
virtual PRBool IncludeInContext(nsIDOMNode *aNode);
nsCOMPtr<nsIParserService> mParserService;
PRBool mIsTextWidget;
};
#ifdef XP_MAC
@ -903,6 +964,7 @@ protected:
nsHTMLCopyEncoder::nsHTMLCopyEncoder()
{
mIsTextWidget = PR_FALSE;
}
nsHTMLCopyEncoder::~nsHTMLCopyEncoder()
@ -911,7 +973,7 @@ nsHTMLCopyEncoder::~nsHTMLCopyEncoder()
NS_IMETHODIMP
nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
const nsAReadableString& aIgnored,
const nsAReadableString& aMimetype,
PRUint32 aFlags)
{
if (!aDocument)
@ -920,7 +982,7 @@ nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
mDocument = aDocument;
mMimeType = NS_LITERAL_STRING("text/html");
mFlags = aFlags;
nsresult rv;
@ -931,19 +993,50 @@ nsHTMLCopyEncoder::Init(nsIDocument* aDocument,
NS_IMETHODIMP
nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
{
// normalize selection
// check for text widgets: we need to recognize these so that
// we don't tweak the selection to be outside of the magic
// div that ender-lite text widgets are embedded in.
nsCOMPtr<nsIDOMNode> selNode;
nsresult rv = aSelection->GetFocusNode(getter_AddRefs(selNode));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIContent> tmp, selContent( do_QueryInterface(selNode) );
while (selContent)
{
nsCOMPtr<nsIAtom> atom;
selContent->GetTag(*getter_AddRefs(atom));
if (atom.get() == nsHTMLAtoms::input ||
atom.get() == nsHTMLAtoms::textarea)
{
mIsTextWidget = PR_TRUE;
break;
}
selContent->GetParent(*getter_AddRefs(tmp));
selContent = tmp;
}
// also consider ourselves in a text widget if we can't find an html document
nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
if (!htmlDoc) mIsTextWidget = PR_TRUE;
// normalize selection if we are not in a widget
if (mIsTextWidget)
{
mSelection = aSelection;
mFlags |= OutputRaw;
return NS_OK;
}
// there's no Clone() for selection! fix...
//nsresult rv = aSelection->Clone(getter_AddRefs(mSelection);
//NS_ENSURE_SUCCESS(rv, rv);
mSelection = aSelection;
nsCOMPtr<nsISelectionPrivate> privSelection = do_QueryInterface(mSelection);
NS_NewDomSelection(getter_AddRefs(mSelection));
NS_ENSURE_TRUE(mSelection, NS_ERROR_FAILURE);
nsCOMPtr<nsISelectionPrivate> privSelection( do_QueryInterface(aSelection) );
NS_ENSURE_TRUE(privSelection, NS_ERROR_FAILURE);
// get selection range enumerator
nsCOMPtr<nsIEnumerator> enumerator;
nsresult rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
rv = privSelection->GetEnumerator(getter_AddRefs(enumerator));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(enumerator, NS_ERROR_FAILURE);
@ -957,11 +1050,18 @@ nsHTMLCopyEncoder::SetSelection(nsISelection* aSelection)
NS_ENSURE_TRUE(currentItem, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMRange> myRange;
range->CloneRange(getter_AddRefs(myRange));
NS_ENSURE_TRUE(myRange, NS_ERROR_FAILURE);
// adjust range to include any ancestors who's children are entirely selected
rv = PromoteRange(range);
rv = PromoteRange(myRange);
NS_ENSURE_SUCCESS(rv, rv);
rv = mSelection->AddRange(myRange);
NS_ENSURE_SUCCESS(rv, rv);
enumerator->Next();
}
@ -975,7 +1075,17 @@ nsHTMLCopyEncoder::EncodeToStringWithContext(nsAWritableString& aEncodedString,
{
nsresult rv = EncodeToString(aEncodedString);
NS_ENSURE_SUCCESS(rv, rv);
if (mIsTextWidget) {
aEncodedString.Insert(NS_LITERAL_STRING("<pre>"), 0);
aEncodedString.Append(NS_LITERAL_STRING("</pre>"));
}
// do not encode any context info or range hints if we are not in an html document.
// do not encode any context info or range hints if we are in a text widget.
if (mIsTextWidget) return NS_OK;
// now encode common ancestors into aContextString. Note that the common ancestors
// will be for the last range in the selection in the case of multirange selections.
// encoding ancestors every range in a multirange selection in a way that could be
@ -1126,12 +1236,12 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, PRInt32
// finding the real start for this point. look up the tree for as long as we are the
// first node in the container, and as long as we haven't hit the body node.
if (!IsTag(node, nsHTMLAtoms::body))
if (!IsRoot(node))
{
rv = GetNodeLocation(node, &parent, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == -1) return NS_OK; // we hit generated content; STOP
while ((IsFirstNode(node)) && (!IsTag(parent, nsHTMLAtoms::body)))
while ((IsFirstNode(node)) && (!IsRoot(parent)))
{
if (bResetPromotion)
{
@ -1211,12 +1321,12 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, PRInt32
// finding the real end for this point. look up the tree for as long as we are the
// last node in the container, and as long as we haven't hit the body node.
if (!IsTag(node, nsHTMLAtoms::body))
if (!IsRoot(node))
{
rv = GetNodeLocation(node, &parent, &offset);
NS_ENSURE_SUCCESS(rv, rv);
if (offset == -1) return NS_OK; // we hit generated content; STOP
while ((IsLastNode(node)) && (!IsTag(parent, nsHTMLAtoms::body)))
while ((IsLastNode(node)) && (!IsRoot(parent)))
{
if (bResetPromotion)
{
@ -1325,6 +1435,19 @@ nsHTMLCopyEncoder::GetNodeLocation(nsIDOMNode *inChild, nsCOMPtr<nsIDOMNode> *ou
return result;
}
PRBool
nsHTMLCopyEncoder::IsRoot(nsIDOMNode* aNode)
{
if (aNode)
{
if (mIsTextWidget)
return (IsTag(aNode, nsHTMLAtoms::div));
else
return (IsTag(aNode, nsHTMLAtoms::body));
}
return PR_FALSE;
}
PRBool
nsHTMLCopyEncoder::IsFirstNode(nsIDOMNode *aNode)
{

View file

@ -35,6 +35,7 @@
#include "nsHTMLAtoms.h"
#include "nsIURI.h"
#include "nsNetUtil.h"
#include "nsEscape.h"
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
static NS_DEFINE_CID(kEntityConverterCID, NS_ENTITYCONVERTER_CID);
@ -68,21 +69,6 @@ nsHTMLContentSerializer::~nsHTMLContentSerializer()
{
}
nsresult
nsHTMLContentSerializer::GetEntityConverter(nsIEntityConverter** aConverter)
{
if (!mEntityConverter) {
nsresult rv;
rv = nsComponentManager::CreateInstance(kEntityConverterCID, NULL,
NS_GET_IID(nsIEntityConverter),
getter_AddRefs(mEntityConverter));
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
}
CallQueryInterface(mEntityConverter.get(), aConverter);
return NS_OK;
}
nsresult
nsHTMLContentSerializer::GetParserService(nsIParserService** aParserService)
{
@ -149,7 +135,8 @@ nsHTMLContentSerializer::AppendText(nsIDOMText* aText,
PRInt32 lastNewlineOffset = kNotFound;
PRBool hasLongLines = HasLongLines(data, lastNewlineOffset);
if (mPreLevel || (!mDoFormat && !hasLongLines)) {
if (mPreLevel || (!mDoFormat && !hasLongLines) ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
AppendToString(data, aStr);
if (lastNewlineOffset != kNotFound) {
@ -378,7 +365,6 @@ nsHTMLContentSerializer::AppendToStringWrapped(const nsAReadableString& aStr,
PRBool done = PR_FALSE;
PRInt32 indx = 0;
PRInt32 strOffset = 0;
PRInt32 oldLineOffset = 0;
PRInt32 lineLength, oldLineEnd;
// Make sure we haven't gone too far already
@ -468,26 +454,17 @@ nsHTMLContentSerializer::AppendToString(const nsAReadableString& aStr,
return;
}
nsresult rv;
if (aIncrColumn) {
mColPos += aStr.Length();
}
if (aTranslateEntities) {
nsCOMPtr<nsIEntityConverter> converter;
GetEntityConverter(getter_AddRefs(converter));
if (converter) {
PRUnichar *encodedBuffer;
rv = mEntityConverter->ConvertToEntities(nsPromiseFlatString(aStr),
nsIEntityConverter::html40Latin1,
&encodedBuffer);
if (NS_SUCCEEDED(rv)) {
aOutputStr.Append(encodedBuffer);
nsCRT::free(encodedBuffer);
return;
}
PRUnichar *encodedBuffer;
encodedBuffer = nsEscapeHTML2(nsPromiseFlatString(aStr), aStr.Length());
if (encodedBuffer) {
aOutputStr.Append(encodedBuffer);
nsCRT::free(encodedBuffer);
return;
}
}
@ -513,7 +490,8 @@ PRBool
nsHTMLContentSerializer::LineBreakBeforeOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -548,7 +526,8 @@ PRBool
nsHTMLContentSerializer::LineBreakAfterOpen(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -576,7 +555,8 @@ PRBool
nsHTMLContentSerializer::LineBreakBeforeClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel || !mColPos ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}
@ -598,7 +578,8 @@ PRBool
nsHTMLContentSerializer::LineBreakAfterClose(nsIAtom* aName,
PRBool aHasDirtyAttr)
{
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel) {
if ((!mDoFormat && !aHasDirtyAttr) || mPreLevel ||
(mFlags & nsIDocumentEncoder::OutputRaw)) {
return PR_FALSE;
}

View file

@ -281,6 +281,9 @@ nsPlainTextSerializer::AppendElementStart(nsIDOMElement *aElement,
mContent = 0;
mOutputString = nsnull;
if (!mInHead && id == eHTMLTag_head)
mInHead = PR_TRUE;
return rv;
}
@ -310,6 +313,9 @@ nsPlainTextSerializer::AppendElementEnd(nsIDOMElement *aElement,
mContent = 0;
mOutputString = nsnull;
if (mInHead && id == eHTMLTag_head)
mInHead = PR_FALSE;
return rv;
}
@ -326,8 +332,6 @@ NS_IMETHODIMP
nsPlainTextSerializer::OpenContainer(const nsIParserNode& aNode)
{
PRInt32 type = aNode.GetNodeType();
const nsString& namestr = aNode.GetText();
nsCOMPtr<nsIAtom> name = dont_AddRef(NS_NewAtom(namestr));
mParserNode = NS_CONST_CAST(nsIParserNode *, &aNode);
return DoOpenContainer(type);

View file

@ -150,6 +150,8 @@ public:
static PRBool InSameDoc(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
static PRInt32 IndexOf(nsIDOMNode* aNode);
static PRInt32 FillArrayWithAncestors(nsVoidArray* aArray,nsIDOMNode* aNode);
static PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
static nsCOMPtr<nsIDOMNode> CommonParent(nsIDOMNode* aNode1, nsIDOMNode* aNode2);
static nsresult GetDOMNodeFromContent(nsIContent* inContentNode, nsCOMPtr<nsIDOMNode>* outDomNode);
static nsresult GetContentFromDOMNode(nsIDOMNode* inDomNode, nsCOMPtr<nsIContent>* outContentNode);
@ -173,9 +175,6 @@ public:
nsresult ComparePointToRange(nsIDOMNode* aParent, PRInt32 aOffset, PRInt32* aResult);
PRInt32 GetAncestorsAndOffsets(nsIDOMNode* aNode, PRInt32 aOffset,
nsVoidArray* aAncestorNodes, nsVoidArray* aAncestorOffsets);
nsresult AddToListOf(nsIDOMNode* aNode);
nsresult RemoveFromListOf(nsIDOMNode* aNode);

View file

@ -224,55 +224,51 @@ nsEscapeHTML(const char * string)
}
NS_COM PRUnichar *
nsEscapeHTML2(const PRUnichar * string)
nsEscapeHTML2(const PRUnichar *aSourceBuffer, PRInt32 aSourceBufferLen)
{
PRUnichar *rv = (PRUnichar *) nsMemory::Alloc(nsCRT::strlen(string)*6*sizeof(PRUnichar) + sizeof(PRUnichar));
PRUnichar *ptr = rv;
// if the caller didn't calculate the length
if (aSourceBufferLen == -1) {
aSourceBufferLen = nsCRT::strlen(aSourceBuffer); // ...then I will
}
if(rv)
{
for(; *string != 0; string++)
{
if(*string == '<')
{
*ptr++ = '&';
*ptr++ = 'l';
*ptr++ = 't';
*ptr++ = ';';
}
else if(*string == '>')
{
*ptr++ = '&';
*ptr++ = 'g';
*ptr++ = 't';
*ptr++ = ';';
}
else if(*string == '&')
{
*ptr++ = '&';
*ptr++ = 'a';
*ptr++ = 'm';
*ptr++ = 'p';
*ptr++ = ';';
}
else if (*string == '"')
{
*ptr++ = '&';
*ptr++ = 'q';
*ptr++ = 'u';
*ptr++ = 'o';
*ptr++ = 't';
*ptr++ = ';';
}
else
{
*ptr++ = *string;
}
}
*ptr = 0;
}
PRUnichar *resultBuffer = (PRUnichar *)nsMemory::Alloc(aSourceBufferLen*6*sizeof(PRUnichar) + sizeof(PRUnichar('\0')));
PRUnichar *ptr = resultBuffer;
return(rv);
if (resultBuffer) {
PRInt32 i;
for(i = 0; i < aSourceBufferLen; i++) {
if(aSourceBuffer[i] == '<') {
*ptr++ = '&';
*ptr++ = 'l';
*ptr++ = 't';
*ptr++ = ';';
} else if(aSourceBuffer[i] == '>') {
*ptr++ = '&';
*ptr++ = 'g';
*ptr++ = 't';
*ptr++ = ';';
} else if(aSourceBuffer[i] == '&') {
*ptr++ = '&';
*ptr++ = 'a';
*ptr++ = 'm';
*ptr++ = 'p';
*ptr++ = ';';
} else if (aSourceBuffer[i] == '"') {
*ptr++ = '&';
*ptr++ = 'q';
*ptr++ = 'u';
*ptr++ = 'o';
*ptr++ = 't';
*ptr++ = ';';
} else {
*ptr++ = aSourceBuffer[i];
}
}
*ptr = 0;
}
return resultBuffer;
}

View file

@ -61,7 +61,8 @@ NS_COM char *
nsEscapeHTML(const char * string);
NS_COM PRUnichar *
nsEscapeHTML2(const PRUnichar * string);
nsEscapeHTML2(const PRUnichar *aSourceBuffer,
PRInt32 aSourceBufferLen = -1);
/*
* Escape problem char's for HTML display
*/