forked from mirrors/gecko-dev
		
	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:
		
							parent
							
								
									292cb40883
								
							
						
					
					
						commit
						17691505d4
					
				
					 14 changed files with 774 additions and 415 deletions
				
			
		|  | @ -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, | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|   if (IsNodeIntersectsRange(content, aRange)) | ||||
|   nsresult rv=NS_OK; | ||||
|    | ||||
|   // 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,22 +628,59 @@ 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);  | ||||
|       } | ||||
|  | @ -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,8 +770,17 @@ 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; | ||||
| 
 | ||||
|  | @ -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) | ||||
|  | @ -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,9 +1050,16 @@ 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(); | ||||
|  | @ -976,6 +1076,16 @@ 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) | ||||
| { | ||||
|  |  | |||
|  | @ -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; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|     // 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) | ||||
|     { | ||||
|       if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode)) | ||||
|       { | ||||
|         isup = do_QueryInterface(pNode); | ||||
|         listAndTableArray->AppendElement(isup); | ||||
|       } | ||||
|       nsCOMPtr<nsIDOMNode> parent; | ||||
|       pNode->GetParentNode(getter_AddRefs(parent)); | ||||
|       pNode = parent; | ||||
|     } | ||||
|      | ||||
|     // remember number of lists and tables above us
 | ||||
|     PRUint32 listAndTableParents; | ||||
|     PRInt32 highWaterMark = -1; | ||||
|     listAndTableArray->Count(&listAndTableParents); | ||||
|      | ||||
|     PRUint32 listCount, j; | ||||
|     nodeList->Count(&listCount); | ||||
|     for (j=0; j<listCount; j++) | ||||
|     if (listAndTableParents) | ||||
|     { | ||||
|       nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j); | ||||
|       nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) ); | ||||
|       // scan insertion list for table elements (other than table).  
 | ||||
|       nodeList->Count(&listCount); | ||||
|       for (j=0; j<listCount; j++) | ||||
|       { | ||||
|         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)) | ||||
|       { | ||||
|         bHaveTableGuts = PR_TRUE; | ||||
|       } | ||||
|       if (nsHTMLEditUtils::IsListItem(curNode)) | ||||
|       { | ||||
|         bHaveListGuts = PR_TRUE; | ||||
|       } | ||||
|       if (bHaveTableGuts && bHaveListGuts) break; // no need to continue
 | ||||
|     } | ||||
|      | ||||
|     // 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) | ||||
|     { | ||||
|       nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0); | ||||
|       nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) ); | ||||
|       if (!nsHTMLEditUtils::IsTableElement(curNode)) | ||||
|       { | ||||
|         nsCOMPtr<nsIDOMNode> parent, tmp; | ||||
|         curNode->GetParentNode(getter_AddRefs(parent)); | ||||
|         while (parent) | ||||
|         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); | ||||
|  |  | |||
|  | @ -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; | ||||
|     // 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) | ||||
|     { | ||||
|       if (nsHTMLEditUtils::IsList(pNode) || nsHTMLEditUtils::IsTable(pNode)) | ||||
|       { | ||||
|         isup = do_QueryInterface(pNode); | ||||
|         listAndTableArray->AppendElement(isup); | ||||
|       } | ||||
|       nsCOMPtr<nsIDOMNode> parent; | ||||
|       pNode->GetParentNode(getter_AddRefs(parent)); | ||||
|       pNode = parent; | ||||
|     } | ||||
|      | ||||
|     // remember number of lists and tables above us
 | ||||
|     PRUint32 listAndTableParents; | ||||
|     PRInt32 highWaterMark = -1; | ||||
|     listAndTableArray->Count(&listAndTableParents); | ||||
|      | ||||
|     PRUint32 listCount, j; | ||||
|     nodeList->Count(&listCount); | ||||
|     for (j=0; j<listCount; j++) | ||||
|     if (listAndTableParents) | ||||
|     { | ||||
|       nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(j); | ||||
|       nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) ); | ||||
|       // scan insertion list for table elements (other than table).  
 | ||||
|       nodeList->Count(&listCount); | ||||
|       for (j=0; j<listCount; j++) | ||||
|       { | ||||
|         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)) | ||||
|       { | ||||
|         bHaveTableGuts = PR_TRUE; | ||||
|       } | ||||
|       if (nsHTMLEditUtils::IsListItem(curNode)) | ||||
|       { | ||||
|         bHaveListGuts = PR_TRUE; | ||||
|       } | ||||
|       if (bHaveTableGuts && bHaveListGuts) break; // no need to continue
 | ||||
|     } | ||||
|      | ||||
|     // 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) | ||||
|     { | ||||
|       nsCOMPtr<nsISupports> isupports = nodeList->ElementAt(0); | ||||
|       nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports) ); | ||||
|       if (!nsHTMLEditUtils::IsTableElement(curNode)) | ||||
|       { | ||||
|         nsCOMPtr<nsIDOMNode> parent, tmp; | ||||
|         curNode->GetParentNode(getter_AddRefs(parent)); | ||||
|         while (parent) | ||||
|         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); | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|   if (IsNodeIntersectsRange(content, aRange)) | ||||
|   nsresult rv=NS_OK; | ||||
|    | ||||
|   // 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,22 +628,59 @@ 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);  | ||||
|       } | ||||
|  | @ -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,8 +770,17 @@ 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; | ||||
| 
 | ||||
|  | @ -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) | ||||
|  | @ -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,9 +1050,16 @@ 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(); | ||||
|  | @ -976,6 +1076,16 @@ 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) | ||||
| { | ||||
|  |  | |||
|  | @ -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; | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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  | ||||
|   */ | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 jst%netscape.com
						jst%netscape.com