Converted parser into a module. Removed usage of static parser methods and used nsIParserService and nsIDTD methods instead. To be reviewed by RickG.

This commit is contained in:
vidur%netscape.com 1999-09-30 22:07:04 +00:00
parent 251497a82a
commit 140612e133
10 changed files with 964 additions and 746 deletions

View File

@ -49,6 +49,7 @@
#include "nsIFormControl.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIScrollableView.h"
#include "nsHTMLAtoms.h"
@ -66,6 +67,9 @@
#include "nsHTMLIIDs.h"
#include "nsTextFragment.h"
#include "nsIParserService.h"
#include "nsParserCIID.h"
// XXX Go through a factory for this one
#include "nsICSSParser.h"
@ -109,29 +113,7 @@ static PRLogModuleInfo* gSinkLogModuleInfo;
} \
PR_END_MACRO
#define SINK_TRACE_NODE(_bit,_msg,_node) SinkTraceNode(_bit,_msg,_node,this)
static void
SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis)
{
if (SINK_LOG_TEST(gSinkLogModuleInfo,aBit)) {
char cbuf[40];
const char* cp;
PRInt32 nt = aNode.GetNodeType();
if ((nt > PRInt32(eHTMLTag_unknown)) &&
(nt < PRInt32(eHTMLTag_text))) {
cp = nsHTMLTags::GetStringValue(nsHTMLTag(aNode.GetNodeType()));
} else {
aNode.GetText().ToCString(cbuf, sizeof(cbuf));
cp = cbuf;
}
PR_LogPrint("%s: this=%p node='%s'", aMsg, aThis, cp);
}
}
#define SINK_TRACE_NODE(_bit,_msg,_node,_obj) _obj->SinkTraceNode(_bit,_msg,_node,this)
#else
#define SINK_TRACE(_bit,_args)
@ -189,6 +171,27 @@ public:
NS_IMETHOD DoFragment(PRBool aFlag);
void ReduceEntities(nsString& aString);
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify = PR_FALSE);
nsresult CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult);
#ifdef NS_DEBUG
void SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis);
#endif
nsIDocument* mDocument;
nsIHTMLDocument* mHTMLDocument;
nsIURI* mDocumentURI;
@ -346,105 +349,144 @@ public:
//----------------------------------------------------------------------
static void
ReduceEntities(nsString& aString)
#ifdef NS_DEBUG
void
HTMLContentSink::SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis)
{
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 i = 0;
while (i < aString.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aString.CharAt(i++) == '&') && (i < aString.Length())) {
PRInt32 start = i - 1;
PRUnichar e = aString.CharAt(i);
if (e == '#') {
// Convert a numeric character reference
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
if (SINK_LOG_TEST(gSinkLogModuleInfo,aBit)) {
char cbuf[40];
const char* cp;
nsAutoString str;
PRInt32 nt = aNode.GetNodeType();
if ((nt > PRInt32(eHTMLTag_unknown)) &&
(nt < PRInt32(eHTMLTag_text)) && mParser) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
dtd->IntTagToStringTag(nsHTMLTag(aNode.GetNodeType()), str);
cp = str.ToCString(cbuf, sizeof(cbuf));
} else {
aNode.GetText().ToCString(cbuf, sizeof(cbuf));
cp = cbuf;
}
PR_LogPrint("%s: this=%p node='%s'", aMsg, aThis, cp);
}
}
#endif
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
void
HTMLContentSink::ReduceEntities(nsString& aString)
{
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 i = 0;
while (i < aString.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aString.CharAt(i++) == '&') && (i < aString.Length())) {
PRInt32 start = i - 1;
PRUnichar e = aString.CharAt(i);
if (e == '#') {
// Convert a numeric character reference
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}
}
}
@ -452,11 +494,11 @@ ReduceEntities(nsString& aString)
// Temporary factory code to create content objects
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner)
void
HTMLContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -479,11 +521,11 @@ GetAttributeValueAt(const nsIParserNode& aNode,
ReduceEntities(aResult);
}
static nsresult
AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify = PR_FALSE)
nsresult
HTMLContentSink::AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify)
{
// Add tag attributes to the content attributes
nsAutoString k, v;
@ -782,13 +824,15 @@ GetOptionText(const nsIParserNode& aNode, nsString& aText)
/**
* Factory subroutine to create all of the html content objects.
*/
static nsresult
CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult)
nsresult
HTMLContentSink::CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult)
{
nsresult rv = NS_OK;
// Find/create atom for the tag name
nsAutoString tmp;
if (eHTMLTag_userdefined == aNodeType) {
@ -796,41 +840,63 @@ CreateContentObject(const nsIParserNode& aNode,
tmp.ToLowerCase();
}
else {
tmp.Append(nsHTMLTags::GetStringValue(aNodeType));
}
nsIAtom* atom = NS_NewAtom(tmp);
if (nsnull == atom) {
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIDTD> dtd;
rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
nsAutoString str;
dtd->IntTagToStringTag(aNodeType, str);
tmp.Append(str);
}
}
// Make the content object
// XXX why is textarea not a container?
nsAutoString content;
if (eHTMLTag_textarea == aNodeType) {
content = aNode.GetSkippedContent();
}
nsresult rv = MakeContentObject(aNodeType, atom, aForm, aWebShell,
aResult, &content);
if (NS_SUCCEEDED(rv)) {
nsIAtom* atom = NS_NewAtom(tmp);
if (nsnull == atom) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_RELEASE(atom);
// Make the content object
// XXX why is textarea not a container?
nsAutoString content;
if (eHTMLTag_textarea == aNodeType) {
content = aNode.GetSkippedContent();
}
rv = MakeContentObject(aNodeType, atom, aForm, aWebShell,
aResult, &content);
NS_RELEASE(atom);
}
return rv;
}
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
nsresult
NS_CreateHTMLElement(nsIHTMLContent** aResult, const nsString& aTag)
{
// Find tag in tag table
nsHTMLTag id = nsHTMLTags::LookupTag(aTag);
if (eHTMLTag_userdefined == id) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = NS_OK;
// Create atom for tag and then create content object
const nsCString& tag = nsHTMLTags::GetStringValue(id);
nsIAtom* atom = NS_NewAtom((const char*)tag);
nsresult rv = MakeContentObject(id, atom, nsnull, nsnull, aResult);
NS_RELEASE(atom);
NS_WITH_SERVICE(nsIParserService,
parserService,
kParserServiceCID,
&rv);
if (NS_SUCCEEDED(rv)) {
// Find tag in tag table
PRInt32 id;
rv = parserService->HTMLStringTagToId(aTag, &id);
if (eHTMLTag_userdefined == nsHTMLTag(id)) {
return NS_ERROR_NOT_AVAILABLE;
}
// Create atom for tag and then create content object
nsAutoString tag;
rv = parserService->HTMLIdToStringTag(id, tag);
nsIAtom* atom = NS_NewAtom(tag.GetUnicode());
rv = MakeContentObject(nsHTMLTag(id), atom, nsnull, nsnull, aResult);
NS_RELEASE(atom);
}
return rv;
}
@ -994,7 +1060,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::OpenContainer", aNode);
"SinkContext::OpenContainer", aNode, mSink);
nsresult rv;
if (mStackPos + 1 > mStackSize) {
@ -1007,10 +1073,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
// Create new container content object
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsIHTMLContent* content;
rv = CreateContentObject(aNode, nodeType,
mSink->mCurrentForm,
mSink->mFrameset ? mSink->mWebShell : nsnull,
&content);
rv = mSink->CreateContentObject(aNode, nodeType,
mSink->mCurrentForm,
mSink->mFrameset ? mSink->mWebShell : nsnull,
&content);
if (NS_OK != rv) {
return rv;
}
@ -1022,7 +1088,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
content->SetDocument(mSink->mDocument, PR_FALSE);
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
rv = AddAttributes(aNode, content, sco);
rv = mSink->AddAttributes(aNode, content, sco);
NS_IF_RELEASE(sco);
if (mPreAppend) {
@ -1073,7 +1139,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::CloseContainer", aNode);
"SinkContext::CloseContainer", aNode, mSink);
--mStackPos;
nsHTMLTag nodeType = mStack[mStackPos].mType;
@ -1242,7 +1308,7 @@ nsresult
SinkContext::AddLeaf(const nsIParserNode& aNode)
{
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::AddLeaf", aNode);
"SinkContext::AddLeaf", aNode, mSink);
nsresult rv = NS_OK;
@ -1254,9 +1320,9 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
// Create new leaf content object
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsIHTMLContent* content;
rv = CreateContentObject(aNode, nodeType,
mSink->mCurrentForm, mSink->mWebShell,
&content);
rv = mSink->CreateContentObject(aNode, nodeType,
mSink->mCurrentForm, mSink->mWebShell,
&content);
if (NS_OK != rv) {
return rv;
}
@ -1266,7 +1332,7 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
content->SetDocument(mSink->mDocument, PR_FALSE);
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
rv = AddAttributes(aNode, content, sco);
rv = mSink->AddAttributes(aNode, content, sco);
NS_IF_RELEASE(sco);
if (NS_OK != rv) {
NS_RELEASE(content);
@ -1900,7 +1966,7 @@ HTMLContentSink::OpenHTML(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenHTML", aNode);
"HTMLContentSink::OpenHTML", aNode, this);
NS_STOP_STOPWATCH(mWatch)
return NS_OK;
@ -1911,7 +1977,7 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseHTML", aNode);
"HTMLContentSink::CloseHTML", aNode, this);
if (nsnull != mHeadContext) {
mHeadContext->End();
delete mHeadContext;
@ -1926,7 +1992,7 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenHead", aNode);
"HTMLContentSink::OpenHead", aNode, this);
nsresult rv = NS_OK;
if (nsnull == mHeadContext) {
mHeadContext = new SinkContext(this);
@ -1959,7 +2025,7 @@ HTMLContentSink::CloseHead(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseHead", aNode);
"HTMLContentSink::CloseHead", aNode, this);
PRInt32 n = mContextStack.Count() - 1;
mCurrentContext = (SinkContext*) mContextStack.ElementAt(n);
mContextStack.RemoveElementAt(n);
@ -1974,7 +2040,7 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode)
//NS_PRECONDITION(nsnull == mBody, "parser called OpenBody twice");
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenBody", aNode);
"HTMLContentSink::OpenBody", aNode, this);
// Add attributes, if any, to the current BODY node
if(mBody != nsnull){
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
@ -2007,7 +2073,7 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseBody", aNode);
"HTMLContentSink::CloseBody", aNode, this);
PRBool didFlush;
nsresult rv = mCurrentContext->FlushText(&didFlush);
@ -2036,7 +2102,7 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode)
mCurrentContext->FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenForm", aNode);
"HTMLContentSink::OpenForm", aNode, this);
// Close out previous form if it's there. If there is one
// around, it's probably because the last one wasn't well-formed.
@ -2096,7 +2162,7 @@ HTMLContentSink::CloseForm(const nsIParserNode& aNode)
mCurrentContext->FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseForm", aNode);
"HTMLContentSink::CloseForm", aNode, this);
if (nsnull != mCurrentForm) {
// Check if this is a well-formed form
@ -2125,7 +2191,7 @@ HTMLContentSink::OpenFrameset(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenFrameset", aNode);
"HTMLContentSink::OpenFrameset", aNode, this);
nsresult rv = mCurrentContext->OpenContainer(aNode);
if ((NS_OK == rv) && (nsnull == mFrameset)) {
@ -2142,7 +2208,7 @@ HTMLContentSink::CloseFrameset(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseFrameset", aNode);
"HTMLContentSink::CloseFrameset", aNode, this);
SinkContext* sc = mCurrentContext;
nsIHTMLContent* fs = sc->mStack[sc->mStackPos-1].mContent;
@ -2161,7 +2227,7 @@ HTMLContentSink::OpenMap(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
nsresult rv = NS_OK;
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenMap", aNode);
"HTMLContentSink::OpenMap", aNode, this);
// We used to treat MAP elements specially (i.e. they were
// only parent elements for AREAs), but we don't anymore.
// HTML 4.0 says that MAP elements can have block content
@ -2177,7 +2243,7 @@ HTMLContentSink::CloseMap(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
nsresult rv = NS_OK;
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseMap", aNode);
"HTMLContentSink::CloseMap", aNode, this);
NS_IF_RELEASE(mCurrentMap);
NS_IF_RELEASE(mCurrentDOMMap);

View File

@ -66,6 +66,7 @@
#include "nsICookieService.h"
#endif // NECKO
#include "nsIParserService.h"
#include "nsIServiceManager.h"
#include "nsIFormManager.h"
#include "nsIComponentManager.h"
@ -2297,7 +2298,8 @@ IsNamedItem(nsIContent* aContent, nsIAtom *aTag,
if ((aTag == nsHTMLAtoms::img) || (aTag == nsHTMLAtoms::form) ||
(!aInForm && ((aTag == nsHTMLAtoms::applet) ||
(aTag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, aName)) {
if ((NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, aName)) ||
(NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, aName))) {
return PR_TRUE;
}
}
@ -2759,6 +2761,8 @@ PRBool nsHTMLDocument::SearchBlock(BlockText & aBlockText,
return found;
}
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
////////////////////////////////////////////////////
// Check to see if a Content node is a block tag
////////////////////////////////////////////////////
@ -2775,7 +2779,19 @@ PRBool nsHTMLDocument::NodeIsBlock(nsIDOMNode * aNode)
domElement->GetTagName(tagName);
NS_RELEASE(domElement);
isBlock = IsBlockLevel(nsHTMLTags::LookupTag(tagName), mIsPreTag);
// XXX Should be done at a higher level than this routine
// since getting the service is not the cheapest operation.
// Waiting for mjudge to tell me where since it looks like
// this code is still in development.
NS_WITH_SERVICE(nsIParserService, service, kParserServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
PRInt32 id;
service->HTMLStringTagToId(tagName, &id);
isBlock = IsBlockLevel(nsHTMLTag(id), mIsPreTag);
}
return isBlock;
}

View File

@ -94,6 +94,9 @@ public:
PRInt32 PushContent(nsIContent *aContent);
nsIContent* PopContent();
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent);
@ -636,10 +639,10 @@ nsHTMLFragmentContentSink::FlushText()
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
void
nsHTMLFragmentContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -660,102 +663,113 @@ GetAttributeValueAt(const nsIParserNode& aNode,
}
}
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 indx = 0;
while (indx < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(indx++) == '&') && (indx < aResult.Length())) {
PRInt32 start = indx - 1;
PRUnichar e = aResult.CharAt(indx);
if (e == '#') {
// Convert a numeric character reference
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 indx = 0;
while (indx < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(indx++) == '&') && (indx < aResult.Length())) {
PRInt32 start = indx - 1;
PRUnichar e = aResult.CharAt(indx);
if (e == '#') {
// Convert a numeric character reference
indx++;
ok = PR_TRUE;
break;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
if ((e >= '0') && (e <= '9')) {
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
indx++;
continue;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}

View File

@ -410,10 +410,10 @@ nsXMLContentSink::SetParser(nsIParser* aParser)
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
void
nsXMLContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -434,102 +434,113 @@ GetAttributeValueAt(const nsIParserNode& aNode,
}
}
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 index = 0;
while (index < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) {
PRInt32 start = index - 1;
PRUnichar e = aResult.CharAt(index);
if (e == '#') {
// Convert a numeric character reference
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 index = 0;
while (index < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) {
PRInt32 start = index - 1;
PRUnichar e = aResult.CharAt(index);
if (e == '#') {
// Convert a numeric character reference
index++;
ok = PR_TRUE;
break;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
}
if ((ch >= '0') && (ch <= '9')) {
*cp++ = char(ch);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
if ((ch >= '0') && (ch <= '9')) {
*cp++ = char(ch);
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
}
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'Z')) ||
((ch >= 'a') && (ch <= 'z'))) {
*cp++ = char(ch);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'Z')) ||
((ch >= 'a') && (ch <= 'z'))) {
*cp++ = char(ch);
index++;
continue;
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}

View File

@ -102,7 +102,9 @@ protected:
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML);

View File

@ -49,6 +49,7 @@
#include "nsIFormControl.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIScrollableView.h"
#include "nsHTMLAtoms.h"
@ -66,6 +67,9 @@
#include "nsHTMLIIDs.h"
#include "nsTextFragment.h"
#include "nsIParserService.h"
#include "nsParserCIID.h"
// XXX Go through a factory for this one
#include "nsICSSParser.h"
@ -109,29 +113,7 @@ static PRLogModuleInfo* gSinkLogModuleInfo;
} \
PR_END_MACRO
#define SINK_TRACE_NODE(_bit,_msg,_node) SinkTraceNode(_bit,_msg,_node,this)
static void
SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis)
{
if (SINK_LOG_TEST(gSinkLogModuleInfo,aBit)) {
char cbuf[40];
const char* cp;
PRInt32 nt = aNode.GetNodeType();
if ((nt > PRInt32(eHTMLTag_unknown)) &&
(nt < PRInt32(eHTMLTag_text))) {
cp = nsHTMLTags::GetStringValue(nsHTMLTag(aNode.GetNodeType()));
} else {
aNode.GetText().ToCString(cbuf, sizeof(cbuf));
cp = cbuf;
}
PR_LogPrint("%s: this=%p node='%s'", aMsg, aThis, cp);
}
}
#define SINK_TRACE_NODE(_bit,_msg,_node,_obj) _obj->SinkTraceNode(_bit,_msg,_node,this)
#else
#define SINK_TRACE(_bit,_args)
@ -189,6 +171,27 @@ public:
NS_IMETHOD DoFragment(PRBool aFlag);
void ReduceEntities(nsString& aString);
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify = PR_FALSE);
nsresult CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult);
#ifdef NS_DEBUG
void SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis);
#endif
nsIDocument* mDocument;
nsIHTMLDocument* mHTMLDocument;
nsIURI* mDocumentURI;
@ -346,105 +349,144 @@ public:
//----------------------------------------------------------------------
static void
ReduceEntities(nsString& aString)
#ifdef NS_DEBUG
void
HTMLContentSink::SinkTraceNode(PRUint32 aBit,
const char* aMsg,
const nsIParserNode& aNode,
void* aThis)
{
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 i = 0;
while (i < aString.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aString.CharAt(i++) == '&') && (i < aString.Length())) {
PRInt32 start = i - 1;
PRUnichar e = aString.CharAt(i);
if (e == '#') {
// Convert a numeric character reference
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
if (SINK_LOG_TEST(gSinkLogModuleInfo,aBit)) {
char cbuf[40];
const char* cp;
nsAutoString str;
PRInt32 nt = aNode.GetNodeType();
if ((nt > PRInt32(eHTMLTag_unknown)) &&
(nt < PRInt32(eHTMLTag_text)) && mParser) {
nsCOMPtr<nsIDTD> dtd;
mParser->GetDTD(getter_AddRefs(dtd));
dtd->IntTagToStringTag(nsHTMLTag(aNode.GetNodeType()), str);
cp = str.ToCString(cbuf, sizeof(cbuf));
} else {
aNode.GetText().ToCString(cbuf, sizeof(cbuf));
cp = cbuf;
}
PR_LogPrint("%s: this=%p node='%s'", aMsg, aThis, cp);
}
}
#endif
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
void
HTMLContentSink::ReduceEntities(nsString& aString)
{
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 i = 0;
while (i < aString.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aString.CharAt(i++) == '&') && (i < aString.Length())) {
PRInt32 start = i - 1;
PRUnichar e = aString.CharAt(i);
if (e == '#') {
// Convert a numeric character reference
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
i++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aString.Length();
while ((i < slen) && (cp < limit)) {
e = aString.CharAt(i);
if (e == ';') {
i++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
i++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aString.Cut(start, i - start);
aString.Insert(PRUnichar(ch), start);
i = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}
}
}
@ -452,11 +494,11 @@ ReduceEntities(nsString& aString)
// Temporary factory code to create content objects
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner)
void
HTMLContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult,
nsIScriptContextOwner* aScriptContextOwner)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -479,11 +521,11 @@ GetAttributeValueAt(const nsIParserNode& aNode,
ReduceEntities(aResult);
}
static nsresult
AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify = PR_FALSE)
nsresult
HTMLContentSink::AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aContent,
nsIScriptContextOwner* aScriptContextOwner,
PRBool aNotify)
{
// Add tag attributes to the content attributes
nsAutoString k, v;
@ -782,13 +824,15 @@ GetOptionText(const nsIParserNode& aNode, nsString& aText)
/**
* Factory subroutine to create all of the html content objects.
*/
static nsresult
CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult)
nsresult
HTMLContentSink::CreateContentObject(const nsIParserNode& aNode,
nsHTMLTag aNodeType,
nsIDOMHTMLFormElement* aForm,
nsIWebShell* aWebShell,
nsIHTMLContent** aResult)
{
nsresult rv = NS_OK;
// Find/create atom for the tag name
nsAutoString tmp;
if (eHTMLTag_userdefined == aNodeType) {
@ -796,41 +840,63 @@ CreateContentObject(const nsIParserNode& aNode,
tmp.ToLowerCase();
}
else {
tmp.Append(nsHTMLTags::GetStringValue(aNodeType));
}
nsIAtom* atom = NS_NewAtom(tmp);
if (nsnull == atom) {
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIDTD> dtd;
rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
nsAutoString str;
dtd->IntTagToStringTag(aNodeType, str);
tmp.Append(str);
}
}
// Make the content object
// XXX why is textarea not a container?
nsAutoString content;
if (eHTMLTag_textarea == aNodeType) {
content = aNode.GetSkippedContent();
}
nsresult rv = MakeContentObject(aNodeType, atom, aForm, aWebShell,
aResult, &content);
if (NS_SUCCEEDED(rv)) {
nsIAtom* atom = NS_NewAtom(tmp);
if (nsnull == atom) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_RELEASE(atom);
// Make the content object
// XXX why is textarea not a container?
nsAutoString content;
if (eHTMLTag_textarea == aNodeType) {
content = aNode.GetSkippedContent();
}
rv = MakeContentObject(aNodeType, atom, aForm, aWebShell,
aResult, &content);
NS_RELEASE(atom);
}
return rv;
}
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
nsresult
NS_CreateHTMLElement(nsIHTMLContent** aResult, const nsString& aTag)
{
// Find tag in tag table
nsHTMLTag id = nsHTMLTags::LookupTag(aTag);
if (eHTMLTag_userdefined == id) {
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv = NS_OK;
// Create atom for tag and then create content object
const nsCString& tag = nsHTMLTags::GetStringValue(id);
nsIAtom* atom = NS_NewAtom((const char*)tag);
nsresult rv = MakeContentObject(id, atom, nsnull, nsnull, aResult);
NS_RELEASE(atom);
NS_WITH_SERVICE(nsIParserService,
parserService,
kParserServiceCID,
&rv);
if (NS_SUCCEEDED(rv)) {
// Find tag in tag table
PRInt32 id;
rv = parserService->HTMLStringTagToId(aTag, &id);
if (eHTMLTag_userdefined == nsHTMLTag(id)) {
return NS_ERROR_NOT_AVAILABLE;
}
// Create atom for tag and then create content object
nsAutoString tag;
rv = parserService->HTMLIdToStringTag(id, tag);
nsIAtom* atom = NS_NewAtom(tag.GetUnicode());
rv = MakeContentObject(nsHTMLTag(id), atom, nsnull, nsnull, aResult);
NS_RELEASE(atom);
}
return rv;
}
@ -994,7 +1060,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::OpenContainer", aNode);
"SinkContext::OpenContainer", aNode, mSink);
nsresult rv;
if (mStackPos + 1 > mStackSize) {
@ -1007,10 +1073,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
// Create new container content object
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsIHTMLContent* content;
rv = CreateContentObject(aNode, nodeType,
mSink->mCurrentForm,
mSink->mFrameset ? mSink->mWebShell : nsnull,
&content);
rv = mSink->CreateContentObject(aNode, nodeType,
mSink->mCurrentForm,
mSink->mFrameset ? mSink->mWebShell : nsnull,
&content);
if (NS_OK != rv) {
return rv;
}
@ -1022,7 +1088,7 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
content->SetDocument(mSink->mDocument, PR_FALSE);
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
rv = AddAttributes(aNode, content, sco);
rv = mSink->AddAttributes(aNode, content, sco);
NS_IF_RELEASE(sco);
if (mPreAppend) {
@ -1073,7 +1139,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::CloseContainer", aNode);
"SinkContext::CloseContainer", aNode, mSink);
--mStackPos;
nsHTMLTag nodeType = mStack[mStackPos].mType;
@ -1242,7 +1308,7 @@ nsresult
SinkContext::AddLeaf(const nsIParserNode& aNode)
{
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"SinkContext::AddLeaf", aNode);
"SinkContext::AddLeaf", aNode, mSink);
nsresult rv = NS_OK;
@ -1254,9 +1320,9 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
// Create new leaf content object
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
nsIHTMLContent* content;
rv = CreateContentObject(aNode, nodeType,
mSink->mCurrentForm, mSink->mWebShell,
&content);
rv = mSink->CreateContentObject(aNode, nodeType,
mSink->mCurrentForm, mSink->mWebShell,
&content);
if (NS_OK != rv) {
return rv;
}
@ -1266,7 +1332,7 @@ SinkContext::AddLeaf(const nsIParserNode& aNode)
content->SetDocument(mSink->mDocument, PR_FALSE);
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
rv = AddAttributes(aNode, content, sco);
rv = mSink->AddAttributes(aNode, content, sco);
NS_IF_RELEASE(sco);
if (NS_OK != rv) {
NS_RELEASE(content);
@ -1900,7 +1966,7 @@ HTMLContentSink::OpenHTML(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenHTML", aNode);
"HTMLContentSink::OpenHTML", aNode, this);
NS_STOP_STOPWATCH(mWatch)
return NS_OK;
@ -1911,7 +1977,7 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseHTML", aNode);
"HTMLContentSink::CloseHTML", aNode, this);
if (nsnull != mHeadContext) {
mHeadContext->End();
delete mHeadContext;
@ -1926,7 +1992,7 @@ HTMLContentSink::OpenHead(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenHead", aNode);
"HTMLContentSink::OpenHead", aNode, this);
nsresult rv = NS_OK;
if (nsnull == mHeadContext) {
mHeadContext = new SinkContext(this);
@ -1959,7 +2025,7 @@ HTMLContentSink::CloseHead(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseHead", aNode);
"HTMLContentSink::CloseHead", aNode, this);
PRInt32 n = mContextStack.Count() - 1;
mCurrentContext = (SinkContext*) mContextStack.ElementAt(n);
mContextStack.RemoveElementAt(n);
@ -1974,7 +2040,7 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode)
//NS_PRECONDITION(nsnull == mBody, "parser called OpenBody twice");
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenBody", aNode);
"HTMLContentSink::OpenBody", aNode, this);
// Add attributes, if any, to the current BODY node
if(mBody != nsnull){
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
@ -2007,7 +2073,7 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseBody", aNode);
"HTMLContentSink::CloseBody", aNode, this);
PRBool didFlush;
nsresult rv = mCurrentContext->FlushText(&didFlush);
@ -2036,7 +2102,7 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode)
mCurrentContext->FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenForm", aNode);
"HTMLContentSink::OpenForm", aNode, this);
// Close out previous form if it's there. If there is one
// around, it's probably because the last one wasn't well-formed.
@ -2096,7 +2162,7 @@ HTMLContentSink::CloseForm(const nsIParserNode& aNode)
mCurrentContext->FlushText();
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseForm", aNode);
"HTMLContentSink::CloseForm", aNode, this);
if (nsnull != mCurrentForm) {
// Check if this is a well-formed form
@ -2125,7 +2191,7 @@ HTMLContentSink::OpenFrameset(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenFrameset", aNode);
"HTMLContentSink::OpenFrameset", aNode, this);
nsresult rv = mCurrentContext->OpenContainer(aNode);
if ((NS_OK == rv) && (nsnull == mFrameset)) {
@ -2142,7 +2208,7 @@ HTMLContentSink::CloseFrameset(const nsIParserNode& aNode)
{
NS_START_STOPWATCH(mWatch)
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseFrameset", aNode);
"HTMLContentSink::CloseFrameset", aNode, this);
SinkContext* sc = mCurrentContext;
nsIHTMLContent* fs = sc->mStack[sc->mStackPos-1].mContent;
@ -2161,7 +2227,7 @@ HTMLContentSink::OpenMap(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
nsresult rv = NS_OK;
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::OpenMap", aNode);
"HTMLContentSink::OpenMap", aNode, this);
// We used to treat MAP elements specially (i.e. they were
// only parent elements for AREAs), but we don't anymore.
// HTML 4.0 says that MAP elements can have block content
@ -2177,7 +2243,7 @@ HTMLContentSink::CloseMap(const nsIParserNode& aNode)
NS_START_STOPWATCH(mWatch)
nsresult rv = NS_OK;
SINK_TRACE_NODE(SINK_TRACE_CALLS,
"HTMLContentSink::CloseMap", aNode);
"HTMLContentSink::CloseMap", aNode, this);
NS_IF_RELEASE(mCurrentMap);
NS_IF_RELEASE(mCurrentDOMMap);

View File

@ -66,6 +66,7 @@
#include "nsICookieService.h"
#endif // NECKO
#include "nsIParserService.h"
#include "nsIServiceManager.h"
#include "nsIFormManager.h"
#include "nsIComponentManager.h"
@ -2297,7 +2298,8 @@ IsNamedItem(nsIContent* aContent, nsIAtom *aTag,
if ((aTag == nsHTMLAtoms::img) || (aTag == nsHTMLAtoms::form) ||
(!aInForm && ((aTag == nsHTMLAtoms::applet) ||
(aTag == nsHTMLAtoms::embed)))) {
if (NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, aName)) {
if ((NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::name, aName)) ||
(NS_CONTENT_ATTR_HAS_VALUE == aContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::id, aName))) {
return PR_TRUE;
}
}
@ -2759,6 +2761,8 @@ PRBool nsHTMLDocument::SearchBlock(BlockText & aBlockText,
return found;
}
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
////////////////////////////////////////////////////
// Check to see if a Content node is a block tag
////////////////////////////////////////////////////
@ -2775,7 +2779,19 @@ PRBool nsHTMLDocument::NodeIsBlock(nsIDOMNode * aNode)
domElement->GetTagName(tagName);
NS_RELEASE(domElement);
isBlock = IsBlockLevel(nsHTMLTags::LookupTag(tagName), mIsPreTag);
// XXX Should be done at a higher level than this routine
// since getting the service is not the cheapest operation.
// Waiting for mjudge to tell me where since it looks like
// this code is still in development.
NS_WITH_SERVICE(nsIParserService, service, kParserServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
PRInt32 id;
service->HTMLStringTagToId(tagName, &id);
isBlock = IsBlockLevel(nsHTMLTag(id), mIsPreTag);
}
return isBlock;
}

View File

@ -94,6 +94,9 @@ public:
PRInt32 PushContent(nsIContent *aContent);
nsIContent* PopContent();
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent);
@ -636,10 +639,10 @@ nsHTMLFragmentContentSink::FlushText()
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
void
nsHTMLFragmentContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -660,102 +663,113 @@ GetAttributeValueAt(const nsIParserNode& aNode,
}
}
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 indx = 0;
while (indx < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(indx++) == '&') && (indx < aResult.Length())) {
PRInt32 start = indx - 1;
PRUnichar e = aResult.CharAt(indx);
if (e == '#') {
// Convert a numeric character reference
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 indx = 0;
while (indx < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(indx++) == '&') && (indx < aResult.Length())) {
PRInt32 start = indx - 1;
PRUnichar e = aResult.CharAt(indx);
if (e == '#') {
// Convert a numeric character reference
indx++;
ok = PR_TRUE;
break;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
if ((e >= '0') && (e <= '9')) {
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
indx++;
continue;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
indx++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((indx < slen) && (cp < limit)) {
e = aResult.CharAt(indx);
if (e == ';') {
indx++;
ok = PR_TRUE;
break;
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
indx++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, indx - start);
aResult.Insert(PRUnichar(ch), start);
indx = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}

View File

@ -410,10 +410,10 @@ nsXMLContentSink::SetParser(nsIParser* aParser)
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
static void
GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
void
nsXMLContentSink::GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult)
{
// Copy value
const nsString& value = aNode.GetValueAt(aIndex);
@ -434,102 +434,113 @@ GetAttributeValueAt(const nsIParserNode& aNode,
}
}
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 index = 0;
while (index < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) {
PRInt32 start = index - 1;
PRUnichar e = aResult.CharAt(index);
if (e == '#') {
// Convert a numeric character reference
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
if (mParser) {
nsCOMPtr<nsIDTD> dtd;
nsresult rv = mParser->GetDTD(getter_AddRefs(dtd));
if (NS_SUCCEEDED(rv)) {
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 index = 0;
while (index < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) {
PRInt32 start = index - 1;
PRUnichar e = aResult.CharAt(index);
if (e == '#') {
// Convert a numeric character reference
index++;
ok = PR_TRUE;
break;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
}
if ((ch >= '0') && (ch <= '9')) {
*cp++ = char(ch);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
if ((ch >= '0') && (ch <= '9')) {
*cp++ = char(ch);
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
}
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'Z')) ||
((ch >= 'a') && (ch <= 'z'))) {
*cp++ = char(ch);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
nsAutoString str(cbuf);
dtd->ConvertEntityToUnicode(str, &ch);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar ch = aResult.CharAt(index);
if (ch == ';') {
index++;
ok = PR_TRUE;
break;
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
if (((ch >= '0') && (ch <= '9')) ||
((ch >= 'A') && (ch <= 'Z')) ||
((ch >= 'a') && (ch <= 'z'))) {
*cp++ = char(ch);
index++;
continue;
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch = nsHTMLEntities::EntityToUnicode(nsSubsumeCStr(cbuf, PR_FALSE));
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
}
}
}

View File

@ -102,7 +102,9 @@ protected:
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIContent* aContent,
PRBool aIsHTML);