Make createContextualFragment work for XML. Bug 133827, patch by

steve.swanson@mackichan.com, r=bzbarsky, sr=jst
This commit is contained in:
bzbarsky%mit.edu 2004-09-30 22:27:45 +00:00
Родитель 72576ab1aa
Коммит e2c56f9785
18 изменённых файлов: 662 добавлений и 109 удалений

Просмотреть файл

@ -217,6 +217,14 @@
#define NS_HTMLFRAGMENTSINK2_CID \
{ 0x13111d00, 0xce81, 0x11d6, { 0x80, 0x82, 0xec, 0xf3, 0x66, 0x5a, 0xf6, 0x7c } }
// {4B664E54-72A2-4bbf-A5C2-66D4DC3066A0}
#define NS_XMLFRAGMENTSINK_CID \
{ 0x4b664e54, 0x72a2, 0x4bbf, { 0xa5, 0xc2, 0x66, 0xd4, 0xdc, 0x30, 0x66, 0xa0 } }
// {4DC30689-929D-425e-A709-082C6294E542}
#define NS_XMLFRAGMENTSINK2_CID \
{ 0x4dc30689, 0x929d, 0x425e, { 0xa7, 0x9, 0x8, 0x2c, 0x62, 0x94, 0xe5, 0x42 } }
// {3986B301-097C-11d3-BF87-00105A1B0627}
#define NS_XULPOPUPLISTENER_CID \
{ 0x3986b301, 0x97c, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }

Просмотреть файл

@ -58,7 +58,8 @@
#include "nsIParser.h"
#include "nsIComponentManager.h"
#include "nsParserCIID.h"
#include "nsIHTMLFragmentContentSink.h"
#include "nsIFragmentContentSink.h"
#include "nsIContentSink.h"
#include "nsIEnumerator.h"
#include "nsIScriptSecurityManager.h"
#include "nsIScriptGlobalObject.h"
@ -2366,8 +2367,40 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
parent->GetNodeType(&nodeType);
if (nsIDOMNode::ELEMENT_NODE == nodeType) {
nsAutoString tagName;
PRInt32 namespaceID;
nsAutoString tagName, uriStr;
parent->GetNodeName(tagName);
// see if we need to add xmlns declarations
nsCOMPtr<nsIContent> content( do_QueryInterface(parent) );
PRUint32 count = content->GetAttrCount();
if (count > 0) {
PRUint32 index;
nsAutoString nameStr, prefixStr, valueStr;
nsCOMPtr<nsIAtom> attrName, attrPrefix;
for (index = 0; index < count; index++) {
content->GetAttrNameAt(index,
&namespaceID,
getter_AddRefs(attrName),
getter_AddRefs(attrPrefix));
if (namespaceID == kNameSpaceID_XMLNS) {
content->GetAttr(namespaceID, attrName, uriStr);
// really want something like nsXMLContentSerializer::SerializeAttr()
tagName.Append(NS_LITERAL_STRING(" xmlns")); // space important
if (attrPrefix) {
tagName.Append(PRUnichar(':'));
attrName->ToString(nameStr);
tagName.Append(nameStr);
}
tagName.Append(NS_LITERAL_STRING("=\"") + uriStr + NS_LITERAL_STRING("\""));
}
}
}
// XXX Wish we didn't have to allocate here
PRUnichar* name = ToNewUnicode(tagName);
if (name) {
@ -2387,22 +2420,29 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
if (NS_SUCCEEDED(result)) {
nsCAutoString contentType;
nsCOMPtr<nsIHTMLFragmentContentSink> sink;
PRBool bCaseSensitive = PR_TRUE;
if (document) {
nsAutoString buf;
document->GetContentType(buf);
CopyUCS2toASCII(buf, contentType);
bCaseSensitive = document->IsCaseSensitive();
}
else {
contentType.AssignLiteral("text/xml");
}
result = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(domDocument));
PRBool bHTML = htmlDoc && !bCaseSensitive;
nsCOMPtr<nsIFragmentContentSink> sink;
if (bHTML) {
result = NS_NewHTMLFragmentContentSink(getter_AddRefs(sink));
} else {
result = NS_NewXMLFragmentContentSink(getter_AddRefs(sink));
}
if (NS_SUCCEEDED(result)) {
sink->SetTargetDocument(document);
parser->SetContentSink(sink);
nsCOMPtr<nsIDOMNSDocument> domnsDocument(do_QueryInterface(document));
if (domnsDocument) {
nsAutoString buf;
domnsDocument->GetContentType(buf);
CopyUCS2toASCII(buf, contentType);
}
else {
// Who're we kidding. This only works for html.
contentType.AssignLiteral("text/html");
}
nsCOMPtr<nsIContentSink> contentsink( do_QueryInterface(sink) );
parser->SetContentSink(contentsink);
// If there's no JS or system JS running,
// push the current document's context on the JS context stack
@ -2445,7 +2485,7 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
nsDTDMode mode = eDTDMode_autodetect;
nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(domDocument));
if (htmlDoc) {
if (bHTML) {
switch (htmlDoc->GetCompatibilityMode()) {
case eCompatibility_NavQuirks:
mode = eDTDMode_quirks;
@ -2460,10 +2500,12 @@ nsRange::CreateContextualFragment(const nsAString& aFragment,
NS_NOTREACHED("unknown mode");
break;
}
} else {
mode = eDTDMode_full_standards;
}
result = parser->ParseFragment(aFragment, (void*)0,
tagStack,
0, contentType, mode);
!bHTML, contentType, mode);
if (ContextStack) {
JSContext *notused;

Просмотреть файл

@ -134,6 +134,7 @@ HTML_ATOM(em, "em")
HTML_ATOM(embed, "embed")
HTML_ATOM(encoding, "encoding")
HTML_ATOM(enctype, "enctype")
HTML_ATOM(endnote, "endnote") // contextual fragments
HTML_ATOM(_event, "event")
HTML_ATOM(face, "face")
HTML_ATOM(fieldset, "fieldset")

Просмотреть файл

@ -36,7 +36,8 @@
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsIHTMLFragmentContentSink.h"
#include "nsIFragmentContentSink.h"
#include "nsIHTMLContentSink.h"
#include "nsIParser.h"
#include "nsIParserService.h"
#include "nsIHTMLContent.h"
@ -68,9 +69,10 @@
// at some pointe really soon!
//
class nsHTMLFragmentContentSink : public nsIHTMLFragmentContentSink {
class nsHTMLFragmentContentSink : public nsIFragmentContentSink,
public nsIHTMLContentSink {
public:
nsHTMLFragmentContentSink();
nsHTMLFragmentContentSink(PRBool aAllContent = PR_FALSE);
virtual ~nsHTMLFragmentContentSink();
// nsISupports
@ -119,7 +121,7 @@ public:
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode);
// nsIHTMLFragmentContentSink
// nsIFragmentContentSink
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment);
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
@ -160,43 +162,45 @@ public:
nsRefPtr<nsNodeInfoManager> mNodeInfoManager;
};
class nsHTMLFragmentContentSink2 : public nsHTMLFragmentContentSink
{
public:
nsHTMLFragmentContentSink2() { mHitSentinel = PR_TRUE; mSeenBody = PR_FALSE;}
virtual ~nsHTMLFragmentContentSink2() {}
};
nsresult
NS_NewHTMLFragmentContentSink2(nsIHTMLFragmentContentSink** aResult)
static nsresult
NewHTMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aResult)
{
NS_PRECONDITION(aResult, "Null out ptr");
if (nsnull == aResult) {
return NS_ERROR_NULL_POINTER;
}
*aResult = new nsHTMLFragmentContentSink2();
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
nsHTMLFragmentContentSink* it = new nsHTMLFragmentContentSink(aAllContent);
if (nsnull == it) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult = it);
return NS_OK;
}
nsresult
NS_NewHTMLFragmentContentSink(nsIHTMLFragmentContentSink** aResult)
NS_NewHTMLFragmentContentSink2(nsIFragmentContentSink** aResult)
{
NS_PRECONDITION(aResult, "Null out ptr");
*aResult = new nsHTMLFragmentContentSink();
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
NS_ADDREF(*aResult);
return NS_OK;
return NewHTMLFragmentContentSinkHelper(PR_TRUE,aResult);
}
nsHTMLFragmentContentSink::nsHTMLFragmentContentSink()
nsresult
NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aResult)
{
mHitSentinel = PR_FALSE;
mSeenBody = PR_TRUE;
return NewHTMLFragmentContentSinkHelper(PR_FALSE,aResult);
}
nsHTMLFragmentContentSink::nsHTMLFragmentContentSink(PRBool aAllContent)
{
if (aAllContent) {
mHitSentinel = PR_TRUE;
mSeenBody = PR_FALSE;
} else {
mHitSentinel = PR_FALSE;
mSeenBody = PR_TRUE;
}
mRoot = nsnull;
mParser = nsnull;
mCurrentForm = nsnull;
@ -233,10 +237,10 @@ NS_IMPL_ADDREF(nsHTMLFragmentContentSink)
NS_IMPL_RELEASE(nsHTMLFragmentContentSink)
NS_INTERFACE_MAP_BEGIN(nsHTMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIHTMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
NS_INTERFACE_MAP_ENTRY(nsIHTMLContentSink)
NS_INTERFACE_MAP_ENTRY(nsIContentSink)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHTMLFragmentContentSink)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFragmentContentSink)
NS_INTERFACE_MAP_END
@ -441,8 +445,6 @@ nsHTMLFragmentContentSink::AddBaseTagInfo(nsIContent* aContent)
}
}
static const char kSentinelStr[] = "endnote";
NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
{
@ -452,7 +454,8 @@ nsHTMLFragmentContentSink::OpenContainer(const nsIParserNode& aNode)
nsresult result = NS_OK;
tag.Assign(aNode.GetText());
if (tag.EqualsIgnoreCase(kSentinelStr)) {
if (nsHTMLAtoms::endnote->Equals(tag)) {
mHitSentinel = PR_TRUE;
}
else if (mHitSentinel) {

Просмотреть файл

@ -134,6 +134,7 @@ HTML_ATOM(em, "em")
HTML_ATOM(embed, "embed")
HTML_ATOM(encoding, "encoding")
HTML_ATOM(enctype, "enctype")
HTML_ATOM(endnote, "endnote") // contextual fragments
HTML_ATOM(_event, "event")
HTML_ATOM(face, "face")
HTML_ATOM(fieldset, "fieldset")

Просмотреть файл

@ -72,6 +72,7 @@ REQUIRES = xpcom \
CPPSRCS = \
nsXMLContentSink.cpp \
nsXMLFragmentContentSink.cpp \
nsXMLDocument.cpp \
nsXMLPrettyPrinter.cpp \
$(NULL)

Просмотреть файл

@ -911,6 +911,43 @@ NS_NewMathMLElement(nsIContent** aResult, nsINodeInfo* aNodeInfo)
////////////////////////////////////////////////////////////////////////
PRBool
nsXMLContentSink::SetDocElement(PRInt32 aNameSpaceID,
nsIAtom* aTagName,
nsIContent *aContent)
{
if (mDocElement)
return PR_FALSE;
// check for root elements that needs special handling for
// prettyprinting
if ((aNameSpaceID == kNameSpaceID_XBL &&
aTagName == nsXBLAtoms::bindings) ||
(aNameSpaceID == kNameSpaceID_XSLT &&
(aTagName == nsLayoutAtoms::stylesheet ||
aTagName == nsLayoutAtoms::transform))) {
mPrettyPrintHasSpecialRoot = PR_TRUE;
if (mPrettyPrintXML) {
// In this case, disable script execution, stylesheet
// loading, and auto XLinks since we plan to prettyprint.
mAllowAutoXLinks = PR_FALSE;
nsIScriptLoader* scriptLoader = mDocument->GetScriptLoader();
if (scriptLoader) {
scriptLoader->SetEnabled(PR_FALSE);
}
if (mCSSLoader) {
mCSSLoader->SetEnabled(PR_FALSE);
}
}
}
mDocElement = aContent;
NS_ADDREF(mDocElement);
mDocument->SetRootContent(mDocElement);
return PR_TRUE;
}
NS_IMETHODIMP
nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
const PRUnichar **aAtts,
@ -967,44 +1004,17 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
getter_AddRefs(content), &appendContent);
NS_ENSURE_SUCCESS(result, result);
content->SetContentID(mDocument->GetAndIncrementContentID());
if (mDocument) {
content->SetContentID(mDocument->GetAndIncrementContentID());
}
content->SetDocument(mDocument, PR_FALSE, PR_TRUE);
// Set the attributes on the new content element
result = AddAttributes(aAtts, content);
if (NS_OK == result) {
// If this is the document element
if (!mDocElement) {
// check for root elements that needs special handling for
// prettyprinting
if ((nameSpaceID == kNameSpaceID_XBL &&
tagAtom == nsXBLAtoms::bindings) ||
(nameSpaceID == kNameSpaceID_XSLT &&
(tagAtom == nsLayoutAtoms::stylesheet ||
tagAtom == nsLayoutAtoms::transform))) {
mPrettyPrintHasSpecialRoot = PR_TRUE;
if (mPrettyPrintXML) {
// In this case, disable script execution, stylesheet
// loading, and auto XLinks since we plan to prettyprint.
mAllowAutoXLinks = PR_FALSE;
nsIScriptLoader* scriptLoader = mDocument->GetScriptLoader();
if (scriptLoader) {
scriptLoader->SetEnabled(PR_FALSE);
}
if (mCSSLoader) {
mCSSLoader->SetEnabled(PR_FALSE);
}
}
}
mDocElement = content;
NS_ADDREF(mDocElement);
mDocument->SetRootContent(mDocElement);
}
else if (appendContent) {
// Store the element
if (!SetDocElement(nameSpaceID,tagAtom,content) && appendContent) {
nsCOMPtr<nsIContent> parent = GetCurrentContent();
NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED);
@ -1265,6 +1275,15 @@ nsXMLContentSink::HandleXMLDeclaration(const PRUnichar *aData,
NS_IMETHODIMP
nsXMLContentSink::ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText)
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
return ReportErrorFrom( aErrorText, aSourceText, node );
}
NS_IMETHODIMP
nsXMLContentSink::ReportErrorFrom(const PRUnichar* aErrorText,
const PRUnichar* aSourceText,
nsIDOMNode* aNode)
{
nsresult rv = NS_OK;
@ -1278,14 +1297,13 @@ nsXMLContentSink::ReportError(const PRUnichar* aErrorText,
// Clear the current content and
// prepare to set <parsererror> as the document root
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mDocument));
if (node) {
if (aNode) {
for (;;) {
nsCOMPtr<nsIDOMNode> child, dummy;
node->GetLastChild(getter_AddRefs(child));
aNode->GetLastChild(getter_AddRefs(child));
if (!child)
break;
node->RemoveChild(child, getter_AddRefs(dummy));
aNode->RemoveChild(child, getter_AddRefs(dummy));
}
}
NS_IF_RELEASE(mDocElement);

Просмотреть файл

@ -107,6 +107,12 @@ protected:
PRInt32 aNameSpaceID,
nsIAtom* aTagName,
PRUint32 aLineNumber) { return PR_TRUE; }
// Set the given content as the root element for the created document
// don't set if root element was already set.
// return TRUE if this call set the root element
virtual PRBool SetDocElement(PRInt32 aNameSpaceID,
nsIAtom *aTagName,
nsIContent *aContent);
virtual nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
nsIContent** aResult, PRBool* aAppendContent);
@ -125,6 +131,11 @@ protected:
PRInt32 PushContent(nsIContent *aContent);
already_AddRefed<nsIContent> PopContent();
// node is the base content which will be cleared out and an error fragment will be inserted
// return value indicates whether fragment was successfully created
NS_IMETHOD ReportErrorFrom(const PRUnichar* aErrorText,
const PRUnichar* aSourceText,
nsIDOMNode* aNode);
nsresult ProcessBASETag(nsIContent* aContent);

Просмотреть файл

@ -0,0 +1,344 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Steve Swanson steve.swanson@mackichan.com.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsCOMPtr.h"
#include "nsXMLContentSink.h"
#include "nsIFragmentContentSink.h"
#include "nsIXMLContentSink.h"
#include "nsContentSink.h"
#include "nsIExpatSink.h"
#include "nsIParser.h"
#include "nsIDocument.h"
#include "nsIDOMDocumentFragment.h"
#include "nsIXMLContent.h"
#include "nsHTMLAtoms.h"
#include "nsINodeInfo.h"
#include "nsNodeInfoManager.h"
#include "nsContentCreatorFunctions.h"
class nsXMLFragmentContentSink : public nsXMLContentSink,
public nsIFragmentContentSink
{
public:
nsXMLFragmentContentSink(PRBool aAllContent = PR_FALSE);
virtual ~nsXMLFragmentContentSink();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIExpatSink
NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset,
const nsAString & aName,
const nsAString & aSystemId,
const nsAString & aPublicId,
nsISupports* aCatalogData);
NS_IMETHOD HandleProcessingInstruction(const PRUnichar *aTarget,
const PRUnichar *aData);
NS_IMETHOD HandleXMLDeclaration(const PRUnichar *aData,
PRUint32 aLength);
NS_IMETHOD ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText);
// nsIContentSink
NS_IMETHOD WillBuildModel(void);
NS_IMETHOD DidBuildModel();
NS_IMETHOD SetDocumentCharset(nsACString& aCharset);
// nsIXMLContentSink
// nsIFragmentContentSink
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment);
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
protected:
virtual PRBool SetDocElement(PRInt32 aNameSpaceID,
nsIAtom *aTagName,
nsIContent *aContent);
virtual nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
nsIContent** aResult, PRBool* aAppendContent);
virtual nsresult CloseElement(nsIContent* aContent, PRBool* aAppendContent);
// nsContentSink overrides
virtual nsresult ProcessStyleLink(nsIContent* aElement,
const nsAString& aHref,
PRBool aAlternate,
const nsAString& aTitle,
const nsAString& aType,
const nsAString& aMedia);
nsresult LoadXSLStyleSheet(nsIURI* aUrl);
void StartLayout();
nsCOMPtr<nsIDocument> mTargetDocument;
// the fragment
nsCOMPtr<nsIContent> mRoot;
// if FALSE, take content inside endnote tag
PRBool mAllContent;
nsCOMPtr<nsIContent> mEndnote;
};
static nsresult
NewXMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aResult)
{
nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink(aAllContent);
if (!it) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*aResult = it);
return NS_OK;
}
nsresult
NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aResult)
{
return NewXMLFragmentContentSinkHelper(PR_TRUE, aResult);
}
nsresult
NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult)
{
return NewXMLFragmentContentSinkHelper(PR_FALSE, aResult);
}
nsXMLFragmentContentSink::nsXMLFragmentContentSink(PRBool aAllContent)
: mAllContent(aAllContent)
{
}
nsXMLFragmentContentSink::~nsXMLFragmentContentSink()
{
}
NS_IMPL_ISUPPORTS_INHERITED1(nsXMLFragmentContentSink,
nsXMLContentSink,
nsIFragmentContentSink)
NS_IMETHODIMP
nsXMLFragmentContentSink::WillBuildModel(void)
{
if (mRoot) {
return NS_OK;
}
mState = eXMLContentSinkState_InDocumentElement;
NS_ASSERTION(mTargetDocument, "Need a document!");
nsCOMPtr<nsIDOMDocumentFragment> frag;
nsresult rv = NS_NewDocumentFragment(getter_AddRefs(frag), mTargetDocument);
NS_ENSURE_SUCCESS(rv, rv);
mRoot = do_QueryInterface(frag);
PushContent(mRoot); // preload content stack because we know all content goes in the fragment
return rv;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::DidBuildModel()
{
PopContent(); // remove mRoot pushed above
if (!mAllContent) {
NS_ASSERTION(mEndnote, "<endnote> missing in fragment string.");
if (mEndnote) {
NS_ASSERTION(mRoot->GetChildCount() == 1, "contents have too many children!");
// move guts
for (PRUint32 child = mEndnote->GetChildCount(); child > 0; child--) {
nsCOMPtr<nsIContent> firstchild = mEndnote->GetChildAt(0);
mEndnote->RemoveChildAt( 0, PR_FALSE );
mRoot->AppendChildTo( firstchild, PR_FALSE, PR_FALSE );
}
// delete outer content
mRoot->RemoveChildAt( 0, PR_FALSE );
}
// else just leave the content in the fragment. or should we fail?
}
nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
// Drop our reference to the parser to get rid of a circular
// reference.
mParser = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset)
{
NS_NOTREACHED("fragments shouldn't set charset");
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
PRBool
nsXMLFragmentContentSink::SetDocElement(PRInt32 aNameSpaceID,
nsIAtom* aTagName,
nsIContent *aContent)
{
// this is a fragment, not a document
return PR_FALSE;
}
nsresult
nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
nsIContent** aResult, PRBool* aAppendContent)
{
nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
aNodeInfo, aLineNumber,
aResult, aAppendContent);
*aAppendContent = PR_TRUE; // make sure scripts added immediately, not on close.
if (NS_SUCCEEDED(rv) && aNodeInfo->Equals(nsHTMLAtoms::endnote))
mEndnote = *aResult;
return rv;
}
nsresult
nsXMLFragmentContentSink::CloseElement(nsIContent* aContent, PRBool* aAppendContent)
{
// don't do fancy stuff in nsXMLContentSink
*aAppendContent = PR_FALSE;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString & aSubset,
const nsAString & aName,
const nsAString & aSystemId,
const nsAString & aPublicId,
nsISupports* aCatalogData)
{
NS_NOTREACHED("fragments shouldn't have doctype declarations");
return NS_OK;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
const PRUnichar *aData)
{
FlushText();
nsresult result = NS_OK;
const nsDependentString target(aTarget);
const nsDependentString data(aData);
nsCOMPtr<nsIContent> node;
result = NS_NewXMLProcessingInstruction(getter_AddRefs(node), target, data);
if (NS_SUCCEEDED(result)) {
// no special processing here. that should happen when the fragment moves into the document
result = AddContentAsLeaf(node);
}
return result;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::HandleXMLDeclaration(const PRUnichar *aData,
PRUint32 aLength)
{
NS_NOTREACHED("fragments shouldn't have XML declarations");
return NS_OK;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::ReportError(const PRUnichar* aErrorText,
const PRUnichar* aSourceText)
{
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot));
return ReportErrorFrom( aErrorText, aSourceText, node );
}
nsresult
nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement,
const nsAString& aHref,
PRBool aAlternate,
const nsAString& aTitle,
const nsAString& aType,
const nsAString& aMedia)
{
// don't process until moved to document
return NS_OK;
}
nsresult
nsXMLFragmentContentSink::LoadXSLStyleSheet(nsIURI* aUrl)
{
NS_NOTREACHED("fragments shouldn't have XSL style sheets");
return NS_ERROR_UNEXPECTED;
}
void
nsXMLFragmentContentSink::StartLayout()
{
NS_NOTREACHED("fragments shouldn't layout");
}
////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsXMLFragmentContentSink::GetFragment(nsIDOMDocumentFragment** aFragment)
{
if (mRoot) {
return CallQueryInterface(mRoot, aFragment);
}
*aFragment = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
{
NS_ENSURE_ARG_POINTER(aTargetDocument);
mTargetDocument = aTargetDocument;
mNodeInfoManager = aTargetDocument->NodeInfoManager();
return NS_OK;
}

Просмотреть файл

@ -93,7 +93,8 @@
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsLinebreakConverter.h"
#include "nsIHTMLFragmentContentSink.h"
#include "nsIFragmentContentSink.h"
#include "nsIContentSink.h"
// netwerk
#include "nsIURI.h"
@ -2529,7 +2530,7 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK_CONTRACTID);
NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE);
nsCOMPtr<nsIHTMLFragmentContentSink> fragSink(do_QueryInterface(sink));
nsCOMPtr<nsIFragmentContentSink> fragSink(do_QueryInterface(sink));
NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
fragSink->SetTargetDocument(aTargetDocument);
@ -2539,7 +2540,7 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
if (bContext)
parser->Parse(aFragStr, (void*)0, NS_LITERAL_CSTRING("text/html"), PR_FALSE, PR_TRUE, eDTDMode_fragment);
else
parser->ParseFragment(aFragStr, 0, aTagStack, 0, NS_LITERAL_CSTRING("text/html"), eDTDMode_quirks);
parser->ParseFragment(aFragStr, 0, aTagStack, PR_FALSE, NS_LITERAL_CSTRING("text/html"), eDTDMode_quirks);
// get the fragment node
nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
res = fragSink->GetFragment(getter_AddRefs(contextfrag));

Просмотреть файл

@ -83,7 +83,7 @@
#include "nsIGenericFactory.h"
#include "nsIHTMLCSSStyleSheet.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLFragmentContentSink.h"
#include "nsIFragmentContentSink.h"
#include "nsHTMLStyleSheet.h"
#include "nsIHTMLToTextSink.h"
#include "nsILayoutDebugger.h"
@ -575,8 +575,10 @@ MAKE_CTOR(CreateHTMLCopyTextEncoder, nsIDocumentEncoder, NS_NewHTM
MAKE_CTOR(CreateXMLContentSerializer, nsIContentSerializer, NS_NewXMLContentSerializer)
MAKE_CTOR(CreateHTMLContentSerializer, nsIContentSerializer, NS_NewHTMLContentSerializer)
MAKE_CTOR(CreatePlainTextSerializer, nsIContentSerializer, NS_NewPlainTextSerializer)
MAKE_CTOR(CreateHTMLFragmentSink, nsIHTMLFragmentContentSink, NS_NewHTMLFragmentContentSink)
MAKE_CTOR(CreateHTMLFragmentSink2, nsIHTMLFragmentContentSink, NS_NewHTMLFragmentContentSink2)
MAKE_CTOR(CreateHTMLFragmentSink, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink)
MAKE_CTOR(CreateHTMLFragmentSink2, nsIFragmentContentSink, NS_NewHTMLFragmentContentSink2)
MAKE_CTOR(CreateXMLFragmentSink, nsIFragmentContentSink, NS_NewXMLFragmentContentSink)
MAKE_CTOR(CreateXMLFragmentSink2, nsIFragmentContentSink, NS_NewXMLFragmentContentSink2)
MAKE_CTOR(CreateSanitizingHTMLSerializer, nsIContentSerializer, NS_NewSanitizingHTMLSerializer)
MAKE_CTOR(CreateXBLService, nsIXBLService, NS_NewXBLService)
MAKE_CTOR(CreateBindingManager, nsIBindingManager, NS_NewBindingManager)
@ -1144,6 +1146,16 @@ static const nsModuleComponentInfo gComponents[] = {
MOZ_SANITIZINGHTMLSERIALIZER_CONTRACTID,
CreateSanitizingHTMLSerializer },
{ "xml fragment sink",
NS_XMLFRAGMENTSINK_CID,
NS_XMLFRAGMENTSINK_CONTRACTID,
CreateXMLFragmentSink },
{ "xml fragment sink 2",
NS_XMLFRAGMENTSINK2_CID,
NS_XMLFRAGMENTSINK2_CONTRACTID,
CreateXMLFragmentSink2 },
{ "XBL Service",
NS_XBLSERVICE_CID,
"@mozilla.org/xbl;1",

Просмотреть файл

@ -49,7 +49,7 @@ class nsIDocument;
class nsIFrame;
class nsIHTMLContent;
class nsIHTMLContentSink;
class nsIHTMLFragmentContentSink;
class nsIFragmentContentSink;
class nsPresContext;
class nsITextContent;
class nsIURI;
@ -253,9 +253,9 @@ NS_NewHTMLContentSink(nsIHTMLContentSink** aInstancePtrResult,
nsISupports* aContainer, // e.g. docshell
nsIChannel* aChannel);
nsresult
NS_NewHTMLFragmentContentSink(nsIHTMLFragmentContentSink** aInstancePtrResult);
NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
nsresult
NS_NewHTMLFragmentContentSink2(nsIHTMLFragmentContentSink** aInstancePtrResult);
NS_NewHTMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
/** Create a new HTML reflow command */
nsresult

Просмотреть файл

@ -49,7 +49,7 @@ class nsIDocument;
class nsIFrame;
class nsIHTMLContent;
class nsIHTMLContentSink;
class nsIHTMLFragmentContentSink;
class nsIFragmentContentSink;
class nsPresContext;
class nsITextContent;
class nsIURI;
@ -253,9 +253,9 @@ NS_NewHTMLContentSink(nsIHTMLContentSink** aInstancePtrResult,
nsISupports* aContainer, // e.g. docshell
nsIChannel* aChannel);
nsresult
NS_NewHTMLFragmentContentSink(nsIHTMLFragmentContentSink** aInstancePtrResult);
NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
nsresult
NS_NewHTMLFragmentContentSink2(nsIHTMLFragmentContentSink** aInstancePtrResult);
NS_NewHTMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
/** Create a new HTML reflow command */
nsresult

Просмотреть файл

@ -53,7 +53,7 @@ EXPORTS = \
nsIContentSink.h \
nsITokenizer.h \
nsIHTMLContentSink.h \
nsIHTMLFragmentContentSink.h\
nsIFragmentContentSink.h \
nsIParserNode.h \
nsIParser.h \
nsIDTD.h \

Просмотреть файл

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIFragmentContentSink_h___
#define nsIFragmentContentSink_h___
#include "nsISupports.h"
class nsIDOMDocumentFragment;
class nsIDocument;
#define NS_I_FRAGMENT_CONTENT_SINK_IID \
{ 0x2b23c1fb, 0xb83c, 0x436b, \
{ 0xb7, 0x2a, 0x9c, 0xbe, 0xf1, 0xe9, 0x9b, 0x20 } };
class nsIFragmentContentSink : public nsISupports {
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_I_FRAGMENT_CONTENT_SINK_IID)
/**
* This method is used to obtain the fragment created by
* a fragment content sink. The value returned will be null
* if the content sink hasn't yet received parser notifications.
*
*/
NS_IMETHOD GetFragment(nsIDOMDocumentFragment** aFragment) = 0;
/**
* This method is used to set the target document for this fragment
* sink. This document's nodeinfo manager will be used to create
* the content objects. This MUST be called before the sink is used.
*
* @param aDocument the document the new nodes will belong to
* (should not be null)
*/
NS_IMETHOD SetTargetDocument(nsIDocument* aDocument) = 0;
};
/**
* Base version takes string nested in context, context ends with <endnote>.
* 2 version just loads whole string.
*/
#define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
#define NS_HTMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;2"
#define NS_XMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;1"
#define NS_XMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;2"
// the HTML versions are in nsHTMLParts.h
nsresult
NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
nsresult
NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
#endif

Просмотреть файл

@ -251,7 +251,7 @@ class nsIParser : public nsISupports {
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsVoidArray& aTagStack,
PRUint32 anInsertPos,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode = eDTDMode_autodetect) = 0;

Просмотреть файл

@ -1672,27 +1672,47 @@ NS_IMETHODIMP
nsParser::ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsVoidArray& aTagStack,
PRUint32 anInsertPos,
PRBool aXMLMode,
const nsACString& aMimeType,
nsDTDMode aMode)
{
nsresult result = NS_OK;
nsAutoString theContext;
nsAutoString theContext, endContext;
PRUint32 theCount = aTagStack.Count();
PRUint32 theIndex = 0;
while (theIndex++ < theCount){
for (theIndex = 0; theIndex < theCount; theIndex++) {
theContext.AppendLiteral("<");
theContext.Append((PRUnichar*)aTagStack.ElementAt(theCount - theIndex));
theContext.Append((PRUnichar*)aTagStack.ElementAt(theCount - theIndex - 1));
theContext.AppendLiteral(">");
}
theContext.AppendLiteral("<endnote>"); //XXXHack! I'll make this better later.
// Note duplication: nsHTMLAtoms::endnote == an atom in nsHTMLTags
theContext.AppendLiteral("<");
theContext.Append(nsHTMLTags::GetStringValue(eHTMLTag_endnote));
theContext.AppendLiteral(">");
if (aXMLMode) {
endContext.AppendLiteral("</");
endContext.Append(nsHTMLTags::GetStringValue(eHTMLTag_endnote));
endContext.AppendLiteral(">");
for (theIndex = 0; theIndex < theCount; theIndex++) {
endContext.AppendLiteral("</");
nsAutoString thisTag( (PRUnichar*)aTagStack.ElementAt(theIndex) );
PRInt32 endOfTag = thisTag.FindChar(PRUnichar(' ')); // was there an xmlns=?
if (endOfTag == -1)
endContext.Append( thisTag );
else
endContext.Append( Substring(thisTag,0,endOfTag) );
endContext.AppendLiteral(">");
}
}
//now it's time to try to build the model from this fragment
mFlags &= ~NS_PARSER_FLAG_OBSERVERS_ENABLED; //disable observers for fragments
result = Parse(theContext + aSourceBuffer,(void*)&theContext,aMimeType,PR_FALSE,PR_TRUE, aMode);
result = Parse(theContext + aSourceBuffer + endContext,(void*)&theContext,aMimeType,PR_FALSE,PR_TRUE, aMode);
mFlags |= NS_PARSER_FLAG_OBSERVERS_ENABLED; //now reenable.
return result;

Просмотреть файл

@ -218,10 +218,13 @@ class nsParser : public nsIParser,
PRBool aLastCall,
nsDTDMode aMode = eDTDMode_autodetect);
/**
* This method needs documentation
*/
NS_IMETHOD ParseFragment(const nsAString& aSourceBuffer,
void* aKey,
nsVoidArray& aTagStack,
PRUint32 anInsertPos,
PRBool aXMLMode,
const nsACString& aContentType,
nsDTDMode aMode = eDTDMode_autodetect);