1998-04-13 20:24:54 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
#include "nsIHTMLContentSink.h"
|
1998-12-11 17:02:37 +00:00
|
|
|
#include "nsIParser.h"
|
1998-11-26 01:29:10 +00:00
|
|
|
#include "nsICSSStyleSheet.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIUnicharInputStream.h"
|
1998-12-18 01:36:41 +00:00
|
|
|
#include "nsIUnicharStreamLoader.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIHTMLContent.h"
|
|
|
|
#include "nsIURL.h"
|
1998-12-15 06:10:59 +00:00
|
|
|
#include "nsIURLGroup.h"
|
1998-12-16 08:56:10 +00:00
|
|
|
#include "nsIHttpURL.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsHTMLDocument.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsIPresContext.h"
|
1998-06-23 01:34:25 +00:00
|
|
|
#include "nsIViewManager.h"
|
1998-06-23 00:52:21 +00:00
|
|
|
#include "nsHTMLTokens.h"
|
1998-08-11 00:19:11 +00:00
|
|
|
#include "nsHTMLEntities.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsCRT.h"
|
|
|
|
#include "prtime.h"
|
|
|
|
#include "prlog.h"
|
|
|
|
|
|
|
|
#include "nsHTMLParts.h"
|
1998-09-06 00:20:59 +00:00
|
|
|
#include "nsITextContent.h"
|
|
|
|
|
1998-06-27 22:57:52 +00:00
|
|
|
#include "nsIDOMText.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
#include "nsIDOMHTMLFormElement.h"
|
|
|
|
#include "nsIDOMHTMLTextAreaElement.h"
|
|
|
|
#include "nsIDOMHTMLOptionElement.h"
|
1998-05-08 20:18:06 +00:00
|
|
|
#include "nsIFormControl.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
#include "nsIImageMap.h"
|
|
|
|
|
1998-04-22 22:12:24 +00:00
|
|
|
#include "nsRepository.h"
|
|
|
|
|
1998-07-22 23:42:47 +00:00
|
|
|
#include "nsIScrollableView.h"
|
|
|
|
#include "nsHTMLAtoms.h"
|
|
|
|
#include "nsIFrame.h"
|
|
|
|
|
1998-07-18 21:47:56 +00:00
|
|
|
#include "nsIWebShell.h"
|
1998-09-23 17:16:51 +00:00
|
|
|
#include "nsIHTMLDocument.h"
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
// XXX Go through a factory for this one
|
|
|
|
#include "nsICSSParser.h"
|
|
|
|
|
1998-09-03 22:23:09 +00:00
|
|
|
#include "nsIDOMHTMLTitleElement.h"
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIDOMHTMLTitleElementIID, NS_IDOMHTMLTITLEELEMENT_IID);
|
1998-11-26 01:29:10 +00:00
|
|
|
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
1998-09-03 22:23:09 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
#define XXX_ART_HACK 1
|
|
|
|
|
|
|
|
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
1998-09-23 17:16:51 +00:00
|
|
|
static NS_DEFINE_IID(kIHTMLContentIID, NS_IHTMLCONTENT_IID);
|
1998-09-06 00:20:59 +00:00
|
|
|
static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID);
|
1998-09-23 17:16:51 +00:00
|
|
|
static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID);
|
|
|
|
static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID);
|
|
|
|
static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID);
|
1998-08-28 16:20:16 +00:00
|
|
|
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
|
|
|
|
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
|
1998-12-16 05:40:20 +00:00
|
|
|
static NS_DEFINE_IID(kIHTTPURLIID, NS_IHTTPURL_IID);
|
1998-08-28 16:20:16 +00:00
|
|
|
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
|
1998-09-23 17:16:51 +00:00
|
|
|
static NS_DEFINE_IID(kIHTMLDocumentIID, NS_IHTMLDOCUMENT_IID);
|
1998-12-15 06:10:59 +00:00
|
|
|
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
|
1998-08-28 16:20:16 +00:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
#ifdef NS_DEBUG
|
1998-06-30 23:51:53 +00:00
|
|
|
static PRLogModuleInfo* gSinkLogModuleInfo;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-06-30 23:51:53 +00:00
|
|
|
#define SINK_TRACE_CALLS 0x1
|
|
|
|
#define SINK_TRACE_REFLOW 0x2
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-06-30 23:51:53 +00:00
|
|
|
#define SINK_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-06-30 23:51:53 +00:00
|
|
|
#define SINK_TRACE(_bit,_args) \
|
|
|
|
PR_BEGIN_MACRO \
|
|
|
|
if (SINK_LOG_TEST(gSinkLogModuleInfo,_bit)) { \
|
|
|
|
PR_LogPrint _args; \
|
|
|
|
} \
|
|
|
|
PR_END_MACRO
|
1998-07-11 03:51:50 +00:00
|
|
|
|
1998-09-06 00:20:59 +00:00
|
|
|
#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 = NS_EnumToTag(nsHTMLTag(aNode.GetNodeType()));
|
|
|
|
} else {
|
|
|
|
aNode.GetText().ToCString(cbuf, sizeof(cbuf));
|
|
|
|
cp = cbuf;
|
|
|
|
}
|
|
|
|
PR_LogPrint("%s: this=%p node='%s'", aMsg, aThis, cp);
|
|
|
|
}
|
|
|
|
}
|
1998-07-11 03:51:50 +00:00
|
|
|
|
1998-06-30 23:51:53 +00:00
|
|
|
#else
|
|
|
|
#define SINK_TRACE(_bit,_args)
|
1998-07-11 03:51:50 +00:00
|
|
|
#define SINK_TRACE_NODE(_bit,_msg,_node)
|
1998-06-30 23:51:53 +00:00
|
|
|
#endif
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
class SinkContext;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
class HTMLContentSink : public nsIHTMLContentSink {
|
|
|
|
public:
|
|
|
|
void* operator new(size_t size) {
|
|
|
|
void* rv = ::operator new(size);
|
|
|
|
nsCRT::zero(rv, size);
|
|
|
|
return (void*) rv;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink();
|
|
|
|
~HTMLContentSink();
|
|
|
|
|
1998-07-18 21:47:56 +00:00
|
|
|
nsresult Init(nsIDocument* aDoc,
|
|
|
|
nsIURL* aURL,
|
|
|
|
nsIWebShell* aContainer);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
// nsISupports
|
|
|
|
NS_DECL_ISUPPORTS
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
// nsIContentSink
|
|
|
|
NS_IMETHOD WillBuildModel(void);
|
|
|
|
NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel);
|
|
|
|
NS_IMETHOD WillInterrupt(void);
|
|
|
|
NS_IMETHOD WillResume(void);
|
1998-12-11 17:02:37 +00:00
|
|
|
NS_IMETHOD SetParser(nsIParser* aParser);
|
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
// nsIHTMLContentSink
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHOD BeginContext(PRInt32 aID);
|
|
|
|
NS_IMETHOD EndContext(PRInt32 aID);
|
|
|
|
NS_IMETHOD SetContext(PRInt32 aID);
|
1998-07-15 22:31:10 +00:00
|
|
|
NS_IMETHOD SetTitle(const nsString& aValue);
|
|
|
|
NS_IMETHOD OpenHTML(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseHTML(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD OpenHead(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseHead(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD OpenBody(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseBody(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD OpenForm(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseForm(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD OpenFrameset(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseFrameset(const nsIParserNode& aNode);
|
1998-07-20 18:52:40 +00:00
|
|
|
NS_IMETHOD OpenMap(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseMap(const nsIParserNode& aNode);
|
1998-07-15 22:31:10 +00:00
|
|
|
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
|
1998-11-11 22:06:16 +00:00
|
|
|
NS_IMETHOD NotifyError(nsresult aErrorResult);
|
1998-11-10 04:13:59 +00:00
|
|
|
NS_IMETHOD AddComment(const nsIParserNode& aNode);
|
|
|
|
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
|
1998-05-07 21:11:07 +00:00
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
nsIDocument* mDocument;
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptObjectOwner* mDocumentScript;
|
1998-04-13 20:24:54 +00:00
|
|
|
nsIURL* mDocumentURL;
|
1998-08-28 16:20:16 +00:00
|
|
|
nsIWebShell* mWebShell;
|
1998-12-11 17:02:37 +00:00
|
|
|
nsIParser* mParser;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
nsIHTMLContent* mRoot;
|
|
|
|
nsIHTMLContent* mBody;
|
1998-09-10 19:32:14 +00:00
|
|
|
PRInt32 mBodyChildCount;
|
1998-07-20 18:52:40 +00:00
|
|
|
nsIHTMLContent* mFrameset;
|
1998-06-04 21:33:44 +00:00
|
|
|
nsIHTMLContent* mHead;
|
1998-08-28 16:20:16 +00:00
|
|
|
nsString* mTitle;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-06-03 15:58:52 +00:00
|
|
|
PRInt32 mInMonolithicContainer;
|
1998-08-28 16:20:16 +00:00
|
|
|
PRBool mDirty;
|
1998-09-12 19:33:48 +00:00
|
|
|
PRBool mLayoutStarted;
|
1998-09-23 17:16:51 +00:00
|
|
|
nsIDOMHTMLFormElement* mCurrentForm;
|
1998-08-28 16:20:16 +00:00
|
|
|
nsIImageMap* mCurrentMap;
|
|
|
|
|
|
|
|
SinkContext** mContexts;
|
|
|
|
PRInt32 mNumContexts;
|
|
|
|
nsVoidArray mContextStack;
|
|
|
|
SinkContext* mCurrentContext;
|
|
|
|
SinkContext* mHeadContext;
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-07-22 23:42:47 +00:00
|
|
|
nsString* mRef;
|
|
|
|
nsScrollPreference mOriginalScrollPreference;
|
|
|
|
PRBool mNotAtRef;
|
|
|
|
nsIHTMLContent* mRefContent;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsString mBaseHREF;
|
|
|
|
nsString mBaseTarget;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void StartLayout();
|
1998-07-22 23:42:47 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void ScrollToRef();
|
1998-05-08 20:18:06 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void AddBaseTagInfo(nsIHTMLContent* aContent);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult LoadStyleSheet(nsIURL* aURL,
|
|
|
|
nsIUnicharInputStream* aUIN,
|
1998-11-26 01:29:10 +00:00
|
|
|
PRBool aActive,
|
|
|
|
const nsString& aTitle,
|
|
|
|
const nsString& aMedia,
|
|
|
|
nsIHTMLContent* aOwner);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Routines for tags that require special handling
|
|
|
|
nsresult ProcessATag(const nsIParserNode& aNode, nsIHTMLContent* aContent);
|
|
|
|
nsresult ProcessAREATag(const nsIParserNode& aNode);
|
|
|
|
nsresult ProcessBASETag(const nsIParserNode& aNode);
|
|
|
|
nsresult ProcessLINKTag(const nsIParserNode& aNode);
|
|
|
|
nsresult ProcessMETATag(const nsIParserNode& aNode);
|
|
|
|
nsresult ProcessSCRIPTTag(const nsIParserNode& aNode);
|
|
|
|
nsresult ProcessSTYLETag(const nsIParserNode& aNode);
|
1998-12-15 06:10:59 +00:00
|
|
|
|
|
|
|
// Script processing related routines
|
|
|
|
nsresult ResumeParsing();
|
|
|
|
nsresult EvaluateScript(nsString& aScript,
|
|
|
|
PRInt32 aLineNo);
|
1998-08-28 16:20:16 +00:00
|
|
|
};
|
1998-06-23 22:25:28 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
class SinkContext {
|
|
|
|
public:
|
|
|
|
SinkContext(HTMLContentSink* aSink);
|
|
|
|
~SinkContext();
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Normally when OpenContainer's are done the container is not
|
|
|
|
// appended to it's parent until the container is closed. By setting
|
|
|
|
// pre-append to true, the container will be appended when it is
|
|
|
|
// created.
|
|
|
|
void SetPreAppend(PRBool aPreAppend) {
|
1998-08-31 17:51:32 +00:00
|
|
|
mPreAppend = aPreAppend;
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult Begin(nsHTMLTag aNodeType, nsIHTMLContent* aRoot);
|
|
|
|
nsresult OpenContainer(const nsIParserNode& aNode);
|
|
|
|
nsresult CloseContainer(const nsIParserNode& aNode);
|
|
|
|
nsresult AddLeaf(const nsIParserNode& aNode);
|
|
|
|
nsresult End();
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult GrowStack();
|
|
|
|
nsresult AddText(const nsString& aText);
|
|
|
|
nsresult FlushText(PRBool* aDidFlush = nsnull);
|
1998-11-28 23:51:06 +00:00
|
|
|
nsresult FlushTags();
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void MaybeMarkSinkDirty();
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink* mSink;
|
|
|
|
PRBool mPreAppend;
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
struct Node {
|
|
|
|
nsHTMLTag mType;
|
|
|
|
nsIHTMLContent* mContent;
|
|
|
|
PRUint32 mFlags;
|
|
|
|
};
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Node.mFlags
|
|
|
|
#define APPENDED 0x1
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
Node* mStack;
|
|
|
|
PRInt32 mStackSize;
|
|
|
|
PRInt32 mStackPos;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
PRUnichar* mText;
|
|
|
|
PRInt32 mTextLength;
|
|
|
|
PRInt32 mTextSize;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
};
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
//----------------------------------------------------------------------
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
static void
|
1998-11-17 16:29:25 +00:00
|
|
|
ReduceEntities(nsString& aString)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-31 17:51:32 +00:00
|
|
|
// 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;
|
1998-11-17 16:29:25 +00:00
|
|
|
while (index < aString.Length()) {
|
1998-08-31 22:00:04 +00:00
|
|
|
// 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.
|
1998-11-17 16:29:25 +00:00
|
|
|
if ((aString.CharAt(index++) == '&') && (index < aString.Length())) {
|
1998-08-31 17:51:32 +00:00
|
|
|
PRInt32 start = index - 1;
|
1998-11-17 16:29:25 +00:00
|
|
|
PRUnichar e = aString.CharAt(index);
|
1998-08-31 17:51:32 +00:00
|
|
|
if (e == '#') {
|
|
|
|
// Convert a numeric character reference
|
|
|
|
index++;
|
|
|
|
char* cp = cbuf;
|
|
|
|
char* limit = cp + sizeof(cbuf) - 1;
|
|
|
|
PRBool ok = PR_FALSE;
|
1998-11-17 16:29:25 +00:00
|
|
|
PRInt32 slen = aString.Length();
|
1998-08-31 17:51:32 +00:00
|
|
|
while ((index < slen) && (cp < limit)) {
|
1998-11-17 16:29:25 +00:00
|
|
|
PRUnichar e = aString.CharAt(index);
|
1998-08-31 17:51:32 +00:00
|
|
|
if (e == ';') {
|
|
|
|
index++;
|
|
|
|
ok = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((e >= '0') && (e <= '9')) {
|
|
|
|
*cp++ = char(e);
|
|
|
|
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.
|
1998-11-17 16:29:25 +00:00
|
|
|
aString.Cut(start, index - start);
|
|
|
|
aString.Insert(PRUnichar(ch), start);
|
1998-08-31 17:51:32 +00:00
|
|
|
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;
|
1998-11-17 16:29:25 +00:00
|
|
|
PRInt32 slen = aString.Length();
|
1998-08-31 17:51:32 +00:00
|
|
|
while ((index < slen) && (cp < limit)) {
|
1998-11-17 16:29:25 +00:00
|
|
|
PRUnichar e = aString.CharAt(index);
|
1998-08-31 17:51:32 +00:00
|
|
|
if (e == ';') {
|
|
|
|
index++;
|
|
|
|
ok = PR_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (((e >= '0') && (e <= '9')) ||
|
|
|
|
((e >= 'A') && (e <= 'Z')) ||
|
|
|
|
((e >= 'a') && (e <= 'z'))) {
|
|
|
|
*cp++ = char(e);
|
|
|
|
index++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!ok || (cp == cbuf)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*cp = '\0';
|
|
|
|
PRInt32 ch = NS_EntityToUnicode(cbuf);
|
|
|
|
if (ch < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove entity from string and replace it with the integer
|
|
|
|
// value.
|
1998-11-17 16:29:25 +00:00
|
|
|
aString.Cut(start, index - start);
|
|
|
|
aString.Insert(PRUnichar(ch), start);
|
1998-08-31 17:51:32 +00:00
|
|
|
index = start + 1;
|
|
|
|
}
|
|
|
|
else if (e == '{') {
|
|
|
|
// Convert a script entity
|
|
|
|
// XXX write me!
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-07-15 22:31:10 +00:00
|
|
|
}
|
|
|
|
|
1998-11-17 16:29:25 +00:00
|
|
|
// Temporary factory code to create content objects
|
|
|
|
|
|
|
|
static void
|
|
|
|
GetAttributeValueAt(const nsIParserNode& aNode,
|
|
|
|
PRInt32 aIndex,
|
|
|
|
nsString& aResult,
|
|
|
|
nsIScriptContextOwner* aScriptContextOwner)
|
|
|
|
{
|
|
|
|
// Copy value
|
|
|
|
const nsString& value = aNode.GetValueAt(aIndex);
|
|
|
|
aResult.Truncate();
|
|
|
|
aResult.Append(value);
|
|
|
|
|
|
|
|
// Strip quotes if present
|
|
|
|
PRUnichar first = aResult.First();
|
|
|
|
if ((first == '"') || (first == '\'')) {
|
|
|
|
if (aResult.Last() == first) {
|
|
|
|
aResult.Cut(0, 1);
|
|
|
|
PRInt32 pos = aResult.Length() - 1;
|
|
|
|
if (pos >= 0) {
|
|
|
|
aResult.Cut(pos, 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Mismatched quotes - leave them in
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReduceEntities(aResult);
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
static PRBool
|
|
|
|
FindAttribute(const nsIParserNode& aNode,
|
|
|
|
const nsString& aKeyName,
|
|
|
|
nsString& aResult)
|
1998-07-15 22:31:10 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
PRInt32 ac = aNode.GetAttributeCount();
|
|
|
|
for (PRInt32 i = 0; i < ac; i++) {
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
|
|
|
if (key.EqualsIgnoreCase(aKeyName)) {
|
1998-08-31 17:51:32 +00:00
|
|
|
// Get value and remove mandatory quotes.
|
|
|
|
|
|
|
|
// NOTE: we do <b>not</b> evaluate any script entities here
|
|
|
|
// because to do so would result in double evaluations since
|
|
|
|
// attribute values found here are not stored. The unfortunate
|
|
|
|
// implication is that these attributes cannot support script
|
|
|
|
// entities.
|
|
|
|
GetAttributeValueAt(aNode, i, aResult, nsnull);
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
static nsresult
|
|
|
|
AddAttributes(const nsIParserNode& aNode,
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIHTMLContent* aContent,
|
|
|
|
nsIScriptContextOwner* aScriptContextOwner)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
// Add tag attributes to the content attributes
|
|
|
|
nsAutoString k, v;
|
|
|
|
PRInt32 ac = aNode.GetAttributeCount();
|
|
|
|
for (PRInt32 i = 0; i < ac; i++) {
|
|
|
|
// Get upper-cased key
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
|
|
|
k.Truncate();
|
|
|
|
k.Append(key);
|
|
|
|
k.ToUpperCase();
|
1998-09-22 02:09:26 +00:00
|
|
|
|
|
|
|
nsIAtom* keyAtom = NS_NewAtom(k);
|
|
|
|
nsHTMLValue value;
|
1998-08-28 16:20:16 +00:00
|
|
|
|
1998-09-22 02:09:26 +00:00
|
|
|
if (NS_CONTENT_ATTR_NOT_THERE ==
|
|
|
|
aContent->GetAttribute(keyAtom, value)) {
|
|
|
|
// Get value and remove mandatory quotes
|
|
|
|
GetAttributeValueAt(aNode, i, v, aScriptContextOwner);
|
1998-06-26 16:12:51 +00:00
|
|
|
|
1998-09-22 02:09:26 +00:00
|
|
|
// Add attribute to content
|
|
|
|
aContent->SetAttribute(keyAtom, v, PR_FALSE);
|
|
|
|
}
|
|
|
|
NS_RELEASE(keyAtom);
|
1998-06-26 16:12:51 +00:00
|
|
|
}
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
void SetForm(nsIHTMLContent* aContent, nsIDOMHTMLFormElement* aForm)
|
|
|
|
{
|
|
|
|
nsIFormControl* formControl = nsnull;
|
|
|
|
nsresult result = aContent->QueryInterface(kIFormControlIID, (void**)&formControl);
|
|
|
|
if ((NS_OK == result) && formControl) {
|
|
|
|
formControl->SetForm(aForm);
|
|
|
|
NS_RELEASE(formControl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-09-03 22:23:09 +00:00
|
|
|
// XXX compare switch statement against nsHTMLTags.h's list
|
1998-08-28 16:20:16 +00:00
|
|
|
static nsresult
|
1998-09-01 01:37:17 +00:00
|
|
|
MakeContentObject(nsHTMLTag aNodeType,
|
|
|
|
nsIAtom* aAtom,
|
1998-09-23 17:16:51 +00:00
|
|
|
nsIDOMHTMLFormElement* aForm,
|
1998-09-01 01:37:17 +00:00
|
|
|
nsIWebShell* aWebShell,
|
1998-09-23 17:16:51 +00:00
|
|
|
nsIHTMLContent** aResult,
|
|
|
|
const nsString* aContent = nsnull)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult rv = NS_OK;
|
|
|
|
switch (aNodeType) {
|
1998-09-03 22:23:09 +00:00
|
|
|
default:
|
|
|
|
rv = NS_NewHTMLSpanElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
|
1998-08-29 03:17:02 +00:00
|
|
|
case eHTMLTag_a:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLAnchorElement(aResult, aAtom);
|
1998-08-29 03:17:02 +00:00
|
|
|
break;
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_applet:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLAppletElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_area:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLAreaElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_base:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLBaseElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_basefont:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLBaseFontElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_blockquote:/* XXX need a real object??? how does type=cite work? */
|
|
|
|
rv = NS_NewHTMLSpanElement(aResult, aAtom);
|
|
|
|
break;
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_body:
|
1998-09-03 22:23:09 +00:00
|
|
|
rv = NS_NewHTMLBodyElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_br:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLBRElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
1998-10-13 21:31:26 +00:00
|
|
|
case eHTMLTag_button:
|
|
|
|
rv = NS_NewHTMLButtonElement(aResult, aAtom);
|
|
|
|
SetForm(*aResult, aForm);
|
|
|
|
break;
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_caption:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableCaptionElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_col:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableColElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_colgroup:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableColGroupElement(aResult, aAtom);
|
1998-09-03 22:23:09 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_dir:
|
|
|
|
rv = NS_NewHTMLDirectoryElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_div:
|
|
|
|
rv = NS_NewHTMLDivElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_dl:
|
|
|
|
rv = NS_NewHTMLDListElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_embed:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLEmbedElement(aResult, aAtom);
|
|
|
|
break;
|
1998-10-08 04:38:41 +00:00
|
|
|
case eHTMLTag_fieldset:
|
|
|
|
rv = NS_NewHTMLFieldSetElement(aResult, aAtom);
|
|
|
|
SetForm(*aResult, aForm);
|
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_font:
|
|
|
|
rv = NS_NewHTMLFontElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-02 23:53:49 +00:00
|
|
|
case eHTMLTag_form:
|
1998-09-23 17:16:51 +00:00
|
|
|
// the form was already created
|
|
|
|
if (aForm) {
|
|
|
|
rv = aForm->QueryInterface(kIHTMLContentIID, (void**)aResult);
|
|
|
|
}
|
1998-11-16 06:16:17 +00:00
|
|
|
else {
|
|
|
|
rv = NS_NewHTMLFormElement(aResult, aAtom);
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_frame:
|
1998-09-09 23:30:30 +00:00
|
|
|
rv = NS_NewHTMLFrameElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_frameset:
|
1998-09-09 23:30:30 +00:00
|
|
|
rv = NS_NewHTMLFrameSetElement(aResult, aAtom);
|
1998-09-03 22:23:09 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_h1:
|
|
|
|
case eHTMLTag_h2:
|
|
|
|
case eHTMLTag_h3:
|
|
|
|
case eHTMLTag_h4:
|
|
|
|
case eHTMLTag_h5:
|
|
|
|
case eHTMLTag_h6:
|
|
|
|
rv = NS_NewHTMLHeadingElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
1998-09-02 23:53:49 +00:00
|
|
|
case eHTMLTag_head:
|
|
|
|
rv = NS_NewHTMLHeadElement(aResult, aAtom);
|
|
|
|
break;
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_hr:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLHRElement(aResult, aAtom);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_iframe:
|
1998-09-09 23:30:30 +00:00
|
|
|
rv = NS_NewHTMLIFrameElement(aResult, aAtom);
|
1998-09-03 22:23:09 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_img:
|
|
|
|
rv = NS_NewHTMLImageElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_input:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLInputElement(aResult, aAtom);
|
1998-09-23 17:16:51 +00:00
|
|
|
SetForm(*aResult, aForm);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_isindex:
|
|
|
|
rv = NS_NewHTMLIsIndexElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_label:
|
|
|
|
rv = NS_NewHTMLLabelElement(aResult, aAtom);
|
1998-10-22 23:00:37 +00:00
|
|
|
SetForm(*aResult, aForm);
|
1998-09-03 22:23:09 +00:00
|
|
|
break;
|
1998-10-23 04:20:08 +00:00
|
|
|
case eHTMLTag_layer:
|
|
|
|
rv = NS_NewHTMLLayerElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_legend:
|
|
|
|
rv = NS_NewHTMLLegendElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_li:
|
|
|
|
rv = NS_NewHTMLLIElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-01 01:37:17 +00:00
|
|
|
case eHTMLTag_link:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLLinkElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_map:
|
|
|
|
rv = NS_NewHTMLMapElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_menu:
|
|
|
|
rv = NS_NewHTMLMenuElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-01 01:37:17 +00:00
|
|
|
case eHTMLTag_meta:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLMetaElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_object:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLObjectElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_ol:
|
|
|
|
rv = NS_NewHTMLOListElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_optgroup:
|
|
|
|
rv = NS_NewHTMLOptGroupElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-01 01:37:17 +00:00
|
|
|
case eHTMLTag_option:
|
1998-09-23 17:16:51 +00:00
|
|
|
rv = NS_NewHTMLOptionElement(aResult, aAtom);
|
1998-09-03 22:23:09 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_p:
|
|
|
|
rv = NS_NewHTMLParagraphElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_pre:
|
|
|
|
rv = NS_NewHTMLPreElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_param:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLParamElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_q:
|
|
|
|
rv = NS_NewHTMLQuoteElement(aResult, aAtom);
|
|
|
|
break;
|
1998-09-01 01:37:17 +00:00
|
|
|
case eHTMLTag_script:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLScriptElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_select:
|
1998-09-23 17:16:51 +00:00
|
|
|
rv = NS_NewHTMLSelectElement(aResult, aAtom);
|
|
|
|
SetForm(*aResult, aForm);
|
1998-08-28 16:20:16 +00:00
|
|
|
break;
|
1998-09-01 01:37:17 +00:00
|
|
|
case eHTMLTag_spacer:
|
1998-09-04 00:52:49 +00:00
|
|
|
rv = NS_NewHTMLSpacerElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_style:
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLStyleElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_table:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_tbody:
|
|
|
|
case eHTMLTag_thead:
|
|
|
|
case eHTMLTag_tfoot:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableSectionElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
case eHTMLTag_td:
|
|
|
|
case eHTMLTag_th:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableCellElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_textarea:
|
|
|
|
rv = NS_NewHTMLTextAreaElement(aResult, aAtom);
|
1998-09-23 17:16:51 +00:00
|
|
|
// XXX why is textarea not a container. If it were, this code would not be necessary
|
|
|
|
// If the text area has some content, set it
|
|
|
|
if (aContent && (aContent->Length() > 0)) {
|
|
|
|
nsIDOMHTMLTextAreaElement* taElem;
|
|
|
|
rv = (*aResult)->QueryInterface(kIDOMHTMLTextAreaElementIID, (void **)&taElem);
|
|
|
|
if ((NS_OK == rv) && taElem) {
|
|
|
|
taElem->SetDefaultValue(*aContent);
|
|
|
|
NS_RELEASE(taElem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetForm(*aResult, aForm);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_title:
|
|
|
|
rv = NS_NewHTMLTitleElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_tr:
|
1998-09-15 17:58:24 +00:00
|
|
|
rv = NS_NewHTMLTableRowElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
1998-09-03 22:23:09 +00:00
|
|
|
case eHTMLTag_ul:
|
|
|
|
rv = NS_NewHTMLUListElement(aResult, aAtom);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_wbr:
|
1998-09-04 01:03:20 +00:00
|
|
|
rv = NS_NewHTMLWBRElement(aResult, aAtom);
|
1998-09-01 01:37:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
#if 0
|
|
|
|
// XXX is this logic needed by nsDOMHTMLOptionElement?
|
|
|
|
void
|
|
|
|
GetOptionText(const nsIParserNode& aNode, nsString& aText)
|
|
|
|
{
|
|
|
|
aText.SetLength(0);
|
|
|
|
switch (aNode.GetTokenType()) {
|
|
|
|
case eToken_text:
|
|
|
|
case eToken_whitespace:
|
|
|
|
case eToken_newline:
|
|
|
|
aText.Append(aNode.GetText());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eToken_entity:
|
|
|
|
{
|
|
|
|
nsAutoString tmp2("");
|
|
|
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp2);
|
|
|
|
if (unicode < 0) {
|
|
|
|
aText.Append(aNode.GetText());
|
|
|
|
} else {
|
|
|
|
aText.Append(tmp2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
nsAutoString x;
|
|
|
|
char* y = aText.ToNewCString();
|
|
|
|
printf("foo");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-09-01 01:37:17 +00:00
|
|
|
/**
|
|
|
|
* Factory subroutine to create all of the html content objects.
|
|
|
|
*/
|
|
|
|
static nsresult
|
|
|
|
CreateContentObject(const nsIParserNode& aNode,
|
|
|
|
nsHTMLTag aNodeType,
|
1998-09-23 17:16:51 +00:00
|
|
|
nsIDOMHTMLFormElement* aForm,
|
1998-09-01 01:37:17 +00:00
|
|
|
nsIWebShell* aWebShell,
|
|
|
|
nsIHTMLContent** aResult)
|
|
|
|
{
|
|
|
|
// Find/create atom for the tag name
|
|
|
|
nsAutoString tmp;
|
|
|
|
if (eHTMLTag_userdefined == aNodeType) {
|
|
|
|
tmp.Append(aNode.GetText());
|
|
|
|
tmp.ToUpperCase();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tmp.Append(NS_EnumToTag(aNodeType));
|
|
|
|
}
|
|
|
|
nsIAtom* atom = NS_NewAtom(tmp);
|
|
|
|
if (nsnull == atom) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make the content object
|
|
|
|
nsresult rv;
|
1998-09-23 17:16:51 +00:00
|
|
|
|
1998-09-01 01:37:17 +00:00
|
|
|
// XXX right now this code is here because we need aNode to create
|
|
|
|
// images, textareas and input form elements. As soon as all of the
|
|
|
|
// generic content code is in use, it can be moved up into
|
|
|
|
// MakeContentObject
|
|
|
|
switch (aNodeType) {
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_img:
|
|
|
|
#ifdef XXX_ART_HACK
|
|
|
|
{
|
|
|
|
/* HACK - Jim Dunn 8/6
|
|
|
|
* Check to see if this is an ART image type
|
|
|
|
* If so then process it using the ART plugin
|
|
|
|
* Otherwise treat it like a normal image
|
|
|
|
*/
|
|
|
|
|
|
|
|
PRBool bArt = PR_FALSE;
|
|
|
|
nsAutoString v;
|
|
|
|
PRInt32 ac = aNode.GetAttributeCount();
|
|
|
|
for (PRInt32 i = 0; i < ac; i++) /* Go through all of this tag's attributes */
|
|
|
|
{
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
if (!key.Compare("SRC", PR_TRUE)) /* Find the SRC (source) tag */
|
|
|
|
{
|
|
|
|
const nsString& key2 = aNode.GetValueAt(i);
|
|
|
|
|
|
|
|
v.Truncate();
|
|
|
|
v.Append(key2);
|
|
|
|
v.ToLowerCase();
|
|
|
|
if (-1 != v.Find(".art")) /* See if it has an ART extension */
|
|
|
|
{
|
|
|
|
bArt = PR_TRUE; /* Treat this like an embed */
|
|
|
|
break;
|
|
|
|
}
|
1998-04-22 22:12:24 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
if (!key.Compare("TYPE", PR_TRUE)) /* Find the TYPE (mimetype) tag */
|
|
|
|
{
|
|
|
|
const nsString& key2 = aNode.GetValueAt(i);
|
|
|
|
|
|
|
|
v.Truncate();
|
|
|
|
v.Append(key2);
|
|
|
|
v.ToLowerCase();
|
|
|
|
if ((-1 != v.Find("image/x-art")) /* See if it has an ART Mimetype */
|
|
|
|
|| (-1 != v.Find("image/art"))
|
|
|
|
|| (-1 != v.Find("image/x-jg")))
|
|
|
|
{
|
|
|
|
bArt = PR_TRUE; /* Treat this like an embed */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bArt)
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLEmbedElement(aResult, atom);
|
1998-08-28 16:20:16 +00:00
|
|
|
else
|
1998-09-04 00:20:14 +00:00
|
|
|
rv = NS_NewHTMLImageElement(aResult, atom);
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
|
|
|
#else
|
1998-09-04 00:20:14 +00:00
|
|
|
rv = NS_NewHTMLImageElement(aResult, atom);
|
1998-08-28 16:20:16 +00:00
|
|
|
#endif /* XXX */
|
|
|
|
break;
|
1998-09-23 17:16:51 +00:00
|
|
|
default:
|
1998-09-01 01:37:17 +00:00
|
|
|
{
|
1998-09-23 17:16:51 +00:00
|
|
|
// XXX why is textarea not a container?
|
|
|
|
nsAutoString content;
|
|
|
|
if (eHTMLTag_textarea == aNodeType) {
|
|
|
|
content = aNode.GetSkippedContent();
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-09-23 17:16:51 +00:00
|
|
|
rv = MakeContentObject(aNodeType, atom, aForm, aWebShell, aResult, &content);
|
|
|
|
break;
|
1998-04-22 22:12:24 +00:00
|
|
|
}
|
1998-09-01 01:37:17 +00:00
|
|
|
}
|
|
|
|
NS_RELEASE(atom);
|
1998-04-22 22:12:24 +00:00
|
|
|
|
1998-09-01 01:37:17 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
NS_CreateHTMLElement(nsIHTMLContent** aResult, const nsString& aTag)
|
|
|
|
{
|
|
|
|
// Find tag in tag table
|
|
|
|
nsAutoString tmp(aTag);
|
|
|
|
tmp.ToUpperCase();
|
|
|
|
char cbuf[20];
|
|
|
|
tmp.ToCString(cbuf, sizeof(cbuf));
|
|
|
|
nsHTMLTag id = NS_TagToEnum(cbuf);
|
|
|
|
if (eHTMLTag_userdefined == id) {
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
1998-04-22 22:12:24 +00:00
|
|
|
}
|
1998-09-01 01:37:17 +00:00
|
|
|
|
|
|
|
// Create atom for tag and then create content object
|
|
|
|
nsIAtom* atom = NS_NewAtom(tmp);
|
|
|
|
nsresult rv = MakeContentObject(id, atom, nsnull, nsnull, aResult);
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(atom);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return rv;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
SinkContext::SinkContext(HTMLContentSink* aSink)
|
|
|
|
{
|
|
|
|
mSink = aSink;
|
|
|
|
mPreAppend = PR_FALSE;
|
1998-08-31 18:40:39 +00:00
|
|
|
mStack = nsnull;
|
1998-08-28 16:20:16 +00:00
|
|
|
mStackSize = 0;
|
|
|
|
mStackPos = 0;
|
|
|
|
mText = nsnull;
|
|
|
|
mTextLength = 0;
|
|
|
|
mTextSize = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SinkContext::~SinkContext()
|
|
|
|
{
|
|
|
|
if (nsnull != mStack) {
|
|
|
|
for (PRInt32 i = 0; i < mStackPos; i++) {
|
|
|
|
NS_RELEASE(mStack[i].mContent);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
delete [] mStack;
|
|
|
|
}
|
|
|
|
if (nsnull != mText) {
|
|
|
|
delete [] mText;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
SinkContext::Begin(nsHTMLTag aNodeType, nsIHTMLContent* aRoot)
|
|
|
|
{
|
|
|
|
if (1 > mStackSize) {
|
|
|
|
nsresult rv = GrowStack();
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
1998-08-07 23:08:00 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
mStack[0].mType = aNodeType;
|
|
|
|
mStack[0].mContent = aRoot;
|
|
|
|
mStack[0].mFlags = APPENDED;
|
|
|
|
NS_ADDREF(aRoot);
|
|
|
|
mStackPos = 1;
|
|
|
|
mTextLength = 0;
|
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void
|
|
|
|
SinkContext::MaybeMarkSinkDirty()
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
if (!mSink->mDirty &&
|
|
|
|
(2 == mStackPos) &&
|
|
|
|
(mSink->mBody == mStack[1].mContent)) {
|
|
|
|
// We just finished adding something to the body
|
|
|
|
mSink->mDirty = PR_TRUE;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
SinkContext::OpenContainer(const nsIParserNode& aNode)
|
1998-07-20 18:52:40 +00:00
|
|
|
{
|
|
|
|
FlushText();
|
|
|
|
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
1998-08-28 16:20:16 +00:00
|
|
|
"SinkContext::OpenContainer", aNode);
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult rv;
|
|
|
|
if (mStackPos + 1 > mStackSize) {
|
|
|
|
rv = GrowStack();
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Create new container content object
|
|
|
|
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
|
|
|
nsIHTMLContent* content;
|
|
|
|
rv = CreateContentObject(aNode, nodeType,
|
|
|
|
mSink->mCurrentForm,
|
|
|
|
mSink->mFrameset ? mSink->mWebShell : nsnull,
|
|
|
|
&content);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
1998-07-20 18:52:40 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mStack[mStackPos].mType = nodeType;
|
|
|
|
mStack[mStackPos].mContent = content;
|
|
|
|
mStack[mStackPos].mFlags = 0;
|
1998-10-26 23:26:01 +00:00
|
|
|
content->SetDocument(mSink->mDocument, PR_FALSE);
|
1998-09-03 01:23:12 +00:00
|
|
|
|
|
|
|
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
|
|
|
|
rv = AddAttributes(aNode, content, sco);
|
|
|
|
NS_IF_RELEASE(sco);
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
if (mPreAppend) {
|
|
|
|
NS_ASSERTION(mStackPos > 0, "container w/o parent");
|
|
|
|
nsIHTMLContent* parent = mStack[mStackPos-1].mContent;
|
|
|
|
parent->AppendChildTo(content, PR_FALSE);
|
|
|
|
mStack[mStackPos].mFlags |= APPENDED;
|
|
|
|
}
|
|
|
|
mStackPos++;
|
1998-07-20 18:52:40 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Special handling for certain tags
|
|
|
|
switch (nodeType) {
|
|
|
|
case eHTMLTag_a:
|
|
|
|
mSink->ProcessATag(aNode, content);
|
|
|
|
break;
|
|
|
|
case eHTMLTag_table:
|
|
|
|
mSink->mInMonolithicContainer++;
|
|
|
|
break;
|
|
|
|
}
|
1998-07-20 18:52:40 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
SinkContext::CloseContainer(const nsIParserNode& aNode)
|
1998-07-20 18:52:40 +00:00
|
|
|
{
|
|
|
|
FlushText();
|
|
|
|
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
1998-08-28 16:20:16 +00:00
|
|
|
"SinkContext::CloseContainer", aNode);
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
--mStackPos;
|
|
|
|
nsHTMLTag nodeType = mStack[mStackPos].mType;
|
|
|
|
nsIHTMLContent* content = mStack[mStackPos].mContent;
|
|
|
|
content->Compact();
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Add container to its parent if we haven't already done it
|
|
|
|
if (0 == (mStack[mStackPos].mFlags & APPENDED)) {
|
|
|
|
NS_ASSERTION(mStackPos > 0, "container w/o parent");
|
|
|
|
nsIHTMLContent* parent = mStack[mStackPos-1].mContent;
|
|
|
|
parent->AppendChildTo(content, PR_FALSE);
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(content);
|
|
|
|
|
|
|
|
// Special handling for certain tags
|
|
|
|
switch (nodeType) {
|
|
|
|
case eHTMLTag_table:
|
|
|
|
mSink->mInMonolithicContainer--;
|
|
|
|
break;
|
1998-07-20 18:52:40 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Mark sink dirty if it can safely reflow something
|
|
|
|
MaybeMarkSinkDirty();
|
|
|
|
|
1998-07-20 18:52:40 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
SinkContext::AddLeaf(const nsIParserNode& aNode)
|
1998-07-15 22:31:10 +00:00
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
1998-08-28 16:20:16 +00:00
|
|
|
"SinkContext::AddLeaf", aNode);
|
1998-07-15 22:31:10 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult rv = NS_OK;
|
1998-07-15 22:31:10 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
switch (aNode.GetTokenType()) {
|
|
|
|
case eToken_start:
|
|
|
|
{
|
|
|
|
FlushText();
|
1998-07-15 22:31:10 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Create new leaf content object
|
|
|
|
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
|
|
|
nsIHTMLContent* content;
|
|
|
|
rv = CreateContentObject(aNode, nodeType,
|
|
|
|
mSink->mCurrentForm, mSink->mWebShell,
|
|
|
|
&content);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
1998-09-03 01:23:12 +00:00
|
|
|
|
|
|
|
// Set the content's document
|
1998-10-26 23:26:01 +00:00
|
|
|
content->SetDocument(mSink->mDocument, PR_FALSE);
|
1998-09-03 01:23:12 +00:00
|
|
|
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptContextOwner* sco = mSink->mDocument->GetScriptContextOwner();
|
|
|
|
rv = AddAttributes(aNode, content, sco);
|
|
|
|
NS_IF_RELEASE(sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
NS_RELEASE(content);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
switch (nodeType) {
|
|
|
|
case eHTMLTag_img:
|
1998-11-24 02:01:45 +00:00
|
|
|
case eHTMLTag_frame:
|
|
|
|
case eHTMLTag_input:
|
1998-08-28 16:20:16 +00:00
|
|
|
mSink->AddBaseTagInfo(content);
|
|
|
|
break;
|
|
|
|
}
|
1998-07-15 22:31:10 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Add new leaf to its parent
|
|
|
|
NS_ASSERTION(mStackPos > 0, "leaf w/o container");
|
|
|
|
nsIHTMLContent* parent = mStack[mStackPos-1].mContent;
|
|
|
|
parent->AppendChildTo(content, PR_FALSE);
|
1998-08-29 03:17:02 +00:00
|
|
|
NS_RELEASE(content);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Mark sink dirty if it can safely reflow something
|
|
|
|
MaybeMarkSinkDirty();
|
|
|
|
}
|
|
|
|
break;
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eToken_text:
|
|
|
|
case eToken_whitespace:
|
|
|
|
case eToken_newline:
|
|
|
|
return AddText(aNode.GetText());
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eToken_entity:
|
|
|
|
{
|
|
|
|
nsAutoString tmp;
|
|
|
|
PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp);
|
|
|
|
if (unicode < 0) {
|
|
|
|
return AddText(aNode.GetText());
|
|
|
|
}
|
|
|
|
return AddText(tmp);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eToken_skippedcontent:
|
1998-04-22 23:24:43 +00:00
|
|
|
break;
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
return rv;
|
|
|
|
}
|
1998-04-22 23:24:43 +00:00
|
|
|
|
1998-11-10 04:13:59 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
SinkContext::End()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(mStackPos == 1, "insufficient close container calls");
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
for (PRInt32 i = 0; i < mStackPos; i++) {
|
|
|
|
NS_RELEASE(mStack[i].mContent);
|
|
|
|
}
|
|
|
|
mStackPos = 0;
|
|
|
|
mTextLength = 0;
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
SinkContext::GrowStack()
|
|
|
|
{
|
|
|
|
PRInt32 newSize = mStackSize * 2;
|
|
|
|
if (0 == newSize) {
|
|
|
|
newSize = 32;
|
|
|
|
}
|
|
|
|
Node* stack = new Node[newSize];
|
|
|
|
if (nsnull == stack) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
if (0 != mStackPos) {
|
|
|
|
memcpy(stack, mStack, sizeof(Node) * mStackPos);
|
|
|
|
delete [] mStack;
|
|
|
|
}
|
|
|
|
mStack = stack;
|
|
|
|
mStackSize = newSize;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
/**
|
|
|
|
* Add textual content to the current running text buffer. If the text buffer
|
|
|
|
* overflows, flush out the text by creating a text content object and adding
|
|
|
|
* it to the content tree.
|
|
|
|
*/
|
|
|
|
// XXX If we get a giant string grow the buffer instead of chopping it up???
|
|
|
|
nsresult
|
|
|
|
SinkContext::AddText(const nsString& aText)
|
|
|
|
{
|
|
|
|
PRInt32 addLen = aText.Length();
|
|
|
|
if (0 == addLen) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Create buffer when we first need it
|
|
|
|
if (0 == mTextSize) {
|
|
|
|
mText = new PRUnichar[4096];
|
|
|
|
if (nsnull == mText) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
mTextSize = 4096;
|
|
|
|
}
|
|
|
|
// else if (mTextLength + addLen > mTextSize) {
|
|
|
|
// }
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Copy data from string into our buffer; flush buffer when it fills up
|
|
|
|
PRInt32 offset = 0;
|
|
|
|
while (0 != addLen) {
|
|
|
|
PRInt32 amount = mTextSize - mTextLength;
|
|
|
|
if (amount > addLen) {
|
|
|
|
amount = addLen;
|
|
|
|
}
|
|
|
|
if (0 == amount) {
|
|
|
|
nsresult rv = FlushText();
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(&mText[mTextLength], aText.GetUnicode() + offset,
|
|
|
|
sizeof(PRUnichar) * amount);
|
|
|
|
mTextLength += amount;
|
|
|
|
offset += amount;
|
|
|
|
addLen -= amount;
|
|
|
|
}
|
1998-04-22 23:24:43 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-22 23:24:43 +00:00
|
|
|
|
1998-11-28 23:51:06 +00:00
|
|
|
/**
|
|
|
|
* Flush all elements that have been seen so far such that
|
|
|
|
* they are visible in the tree. Specifically, make sure
|
|
|
|
* that they are all added to their respective parents.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
SinkContext::FlushTags()
|
|
|
|
{
|
|
|
|
FlushText();
|
|
|
|
|
|
|
|
PRInt32 stackPos = mStackPos-1;
|
|
|
|
while ((stackPos > 0) && (0 == (mStack[stackPos].mFlags & APPENDED))) {
|
|
|
|
nsIHTMLContent* content = mStack[stackPos].mContent;
|
|
|
|
nsIHTMLContent* parent = mStack[stackPos-1].mContent;
|
|
|
|
|
|
|
|
parent->AppendChildTo(content, PR_FALSE);
|
|
|
|
mStack[stackPos].mFlags |= APPENDED;
|
|
|
|
stackPos--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
/**
|
|
|
|
* Flush any buffered text out by creating a text content object and
|
|
|
|
* adding it to the content.
|
|
|
|
*/
|
|
|
|
nsresult
|
|
|
|
SinkContext::FlushText(PRBool* aDidFlush)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
PRBool didFlush = PR_FALSE;
|
|
|
|
if (0 != mTextLength) {
|
|
|
|
nsIHTMLContent* content;
|
1998-09-06 00:20:59 +00:00
|
|
|
rv = NS_NewTextNode(&content);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK == rv) {
|
1998-09-03 01:23:12 +00:00
|
|
|
// Set the content's document
|
1998-10-26 23:26:01 +00:00
|
|
|
content->SetDocument(mSink->mDocument, PR_FALSE);
|
1998-09-06 00:20:59 +00:00
|
|
|
|
|
|
|
// Set the text in the text node
|
|
|
|
static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID);
|
|
|
|
nsITextContent* text = nsnull;
|
|
|
|
content->QueryInterface(kITextContentIID, (void**) &text);
|
|
|
|
text->SetText(mText, mTextLength, PR_FALSE);
|
|
|
|
NS_RELEASE(text);
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Add text to its parent
|
|
|
|
NS_ASSERTION(mStackPos > 0, "leaf w/o container");
|
|
|
|
nsIHTMLContent* parent = mStack[mStackPos - 1].mContent;
|
|
|
|
parent->AppendChildTo(content, PR_FALSE);
|
|
|
|
NS_RELEASE(content);
|
1998-06-11 16:46:33 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Mark sink dirty if it can safely reflow something
|
|
|
|
MaybeMarkSinkDirty();
|
1998-07-20 18:52:40 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mTextLength = 0;
|
|
|
|
didFlush = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (nsnull != aDidFlush) {
|
|
|
|
*aDidFlush = didFlush;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
1998-07-20 18:52:40 +00:00
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
NS_NewHTMLContentSink(nsIHTMLContentSink** aResult,
|
|
|
|
nsIDocument* aDoc,
|
|
|
|
nsIURL* aURL,
|
|
|
|
nsIWebShell* aWebShell)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull != aResult, "null ptr");
|
|
|
|
if (nsnull == aResult) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-09-12 19:33:48 +00:00
|
|
|
HTMLContentSink* it;
|
|
|
|
NS_NEWXPCOM(it, HTMLContentSink);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (nsnull == it) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult rv = it->Init(aDoc, aURL, aWebShell);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
delete it;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return it->QueryInterface(kIHTMLContentSinkIID, (void **)aResult);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink::HTMLContentSink()
|
|
|
|
{
|
|
|
|
#ifdef NS_DEBUG
|
|
|
|
if (nsnull == gSinkLogModuleInfo) {
|
|
|
|
gSinkLogModuleInfo = PR_NewLogModule("htmlcontentsink");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
mNotAtRef = PR_TRUE;
|
1998-12-11 17:02:37 +00:00
|
|
|
mParser = nsnull;
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-04-22 23:24:43 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink::~HTMLContentSink()
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(mHead);
|
|
|
|
NS_IF_RELEASE(mBody);
|
|
|
|
NS_IF_RELEASE(mFrameset);
|
|
|
|
NS_IF_RELEASE(mRoot);
|
1998-04-22 23:24:43 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IF_RELEASE(mDocument);
|
|
|
|
NS_IF_RELEASE(mDocumentURL);
|
|
|
|
NS_IF_RELEASE(mWebShell);
|
1998-12-11 17:02:37 +00:00
|
|
|
NS_IF_RELEASE(mParser);
|
1998-06-03 15:58:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IF_RELEASE(mCurrentForm);
|
|
|
|
NS_IF_RELEASE(mCurrentMap);
|
|
|
|
NS_IF_RELEASE(mRefContent);
|
1998-06-03 15:58:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
for (PRInt32 i = 0; i < mNumContexts; i++) {
|
|
|
|
SinkContext* sc = mContexts[i];
|
|
|
|
sc->End();
|
|
|
|
delete sc;
|
|
|
|
if (sc == mCurrentContext) {
|
|
|
|
mCurrentContext = nsnull;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
if (nsnull != mContexts) {
|
|
|
|
delete [] mContexts;
|
|
|
|
}
|
|
|
|
if (mCurrentContext == mHeadContext) {
|
|
|
|
mCurrentContext = nsnull;
|
|
|
|
}
|
|
|
|
if (nsnull != mCurrentContext) {
|
|
|
|
delete mCurrentContext;
|
|
|
|
}
|
|
|
|
if (nsnull != mHeadContext) {
|
|
|
|
delete mHeadContext;
|
|
|
|
}
|
|
|
|
if (nsnull != mTitle) {
|
|
|
|
delete mTitle;
|
|
|
|
}
|
|
|
|
if (nsnull != mRef) {
|
|
|
|
delete mRef;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 21:29:50 +00:00
|
|
|
NS_IMPL_ISUPPORTS(HTMLContentSink, kIHTMLContentSinkIID)
|
1998-08-28 16:20:16 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
HTMLContentSink::Init(nsIDocument* aDoc,
|
|
|
|
nsIURL* aURL,
|
|
|
|
nsIWebShell* aContainer)
|
1998-06-27 22:57:52 +00:00
|
|
|
{
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_PRECONDITION(nsnull != aDoc, "null ptr");
|
|
|
|
NS_PRECONDITION(nsnull != aURL, "null ptr");
|
|
|
|
NS_PRECONDITION(nsnull != aContainer, "null ptr");
|
|
|
|
if ((nsnull == aDoc) || (nsnull == aURL) || (nsnull == aContainer)) {
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
mDocument = aDoc;
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_ADDREF(aDoc);
|
1998-08-28 16:20:16 +00:00
|
|
|
mDocumentURL = aURL;
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_ADDREF(aURL);
|
1998-08-28 16:20:16 +00:00
|
|
|
mWebShell = aContainer;
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_ADDREF(aContainer);
|
1998-08-28 16:20:16 +00:00
|
|
|
|
1998-07-30 16:06:22 +00:00
|
|
|
// Make root part
|
1998-09-08 22:38:17 +00:00
|
|
|
nsresult rv = NS_NewHTMLHtmlElement(&mRoot, nsHTMLAtoms::html);
|
1998-07-30 16:06:22 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
1998-10-26 23:26:01 +00:00
|
|
|
mRoot->SetDocument(mDocument, PR_FALSE);
|
1998-09-08 22:38:17 +00:00
|
|
|
mDocument->SetRootContent(mRoot);
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Make head part
|
1998-07-30 16:06:22 +00:00
|
|
|
nsIAtom* atom = NS_NewAtom("HEAD");
|
|
|
|
if (nsnull == atom) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1998-09-02 23:53:49 +00:00
|
|
|
rv = NS_NewHTMLHeadElement(&mHead, atom);
|
1998-07-30 16:06:22 +00:00
|
|
|
NS_RELEASE(atom);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
1998-08-21 21:38:26 +00:00
|
|
|
mRoot->AppendChildTo(mHead, PR_FALSE);
|
1998-07-30 16:06:22 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
mCurrentContext = new SinkContext(this);
|
|
|
|
mCurrentContext->Begin(eHTMLTag_html, mRoot);
|
|
|
|
mContextStack.AppendElement(mCurrentContext);
|
|
|
|
|
1998-12-16 05:40:20 +00:00
|
|
|
const char* spec;
|
|
|
|
(void)aURL->GetSpec(&spec);
|
1998-08-28 16:20:16 +00:00
|
|
|
SINK_TRACE(SINK_TRACE_CALLS,
|
|
|
|
("HTMLContentSink::Init: this=%p url='%s'",
|
1998-12-16 05:40:20 +00:00
|
|
|
this, spec));
|
1998-07-30 16:06:22 +00:00
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::WillBuildModel(void)
|
|
|
|
{
|
|
|
|
// Notify document that the load is beginning
|
|
|
|
mDocument->BeginLoad();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-06-27 22:57:52 +00:00
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
NS_IMETHODIMP
|
1998-06-30 23:51:53 +00:00
|
|
|
HTMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
|
|
|
|
{
|
1998-08-10 17:39:48 +00:00
|
|
|
if (nsnull == mTitle) {
|
|
|
|
((nsHTMLDocument*)mDocument)->SetTitle("");
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// XXX this is silly; who cares?
|
1998-06-27 22:57:52 +00:00
|
|
|
PRInt32 i, ns = mDocument->GetNumberOfShells();
|
|
|
|
for (i = 0; i < ns; i++) {
|
|
|
|
nsIPresShell* shell = mDocument->GetShellAt(i);
|
|
|
|
if (nsnull != shell) {
|
|
|
|
nsIViewManager* vm = shell->GetViewManager();
|
|
|
|
if(vm) {
|
|
|
|
vm->SetQuality(nsContentQuality(aQualityLevel));
|
|
|
|
}
|
|
|
|
NS_RELEASE(vm);
|
|
|
|
NS_RELEASE(shell);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-06-30 23:51:53 +00:00
|
|
|
SINK_TRACE(SINK_TRACE_REFLOW,
|
1998-08-31 17:51:32 +00:00
|
|
|
("HTMLContentSink::DidBuildModel: layout final content"));
|
1998-07-15 22:31:10 +00:00
|
|
|
|
1998-08-31 17:51:32 +00:00
|
|
|
// Reflow the last batch of content
|
1998-09-10 20:37:19 +00:00
|
|
|
if (nsnull != mBody) {
|
|
|
|
mDocument->ContentAppended(mBody, mBodyChildCount);
|
|
|
|
mBody->ChildCount(mBodyChildCount);
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
ScrollToRef();
|
|
|
|
|
|
|
|
mDocument->EndLoad();
|
1998-12-11 17:02:37 +00:00
|
|
|
// Drop our reference to the parser to get rid of a circular
|
|
|
|
// reference.
|
|
|
|
NS_IF_RELEASE(mParser);
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
NS_IMETHODIMP
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink::WillInterrupt()
|
1998-06-27 22:57:52 +00:00
|
|
|
{
|
1998-07-27 18:04:38 +00:00
|
|
|
SINK_TRACE(SINK_TRACE_CALLS,
|
|
|
|
("HTMLContentSink::WillInterrupt: this=%p", this));
|
1998-09-25 17:30:59 +00:00
|
|
|
if (mDirty) {
|
1998-09-12 19:33:48 +00:00
|
|
|
if (nsnull != mBody) {
|
|
|
|
mDocument->ContentAppended(mBody, mBodyChildCount);
|
|
|
|
mBody->ChildCount(mBodyChildCount);
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mDirty = PR_FALSE;
|
|
|
|
}
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
1998-07-15 22:31:10 +00:00
|
|
|
NS_IMETHODIMP
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink::WillResume()
|
1998-06-27 22:57:52 +00:00
|
|
|
{
|
1998-07-27 18:04:38 +00:00
|
|
|
SINK_TRACE(SINK_TRACE_CALLS,
|
|
|
|
("HTMLContentSink::WillResume: this=%p", this));
|
1998-07-15 22:31:10 +00:00
|
|
|
return NS_OK;
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
1998-12-11 17:02:37 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::SetParser(nsIParser* aParser)
|
|
|
|
{
|
|
|
|
NS_IF_RELEASE(mParser);
|
|
|
|
mParser = aParser;
|
|
|
|
NS_IF_ADDREF(mParser);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::BeginContext(PRInt32 aID)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_PRECONDITION(aID >= 0, "bad context ID");
|
1998-07-30 16:06:22 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Create new context
|
|
|
|
SinkContext* sc = new SinkContext(this);
|
|
|
|
if (nsnull == sc) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1998-07-22 23:42:47 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Put it into our context array. Grow the array if necessary.
|
|
|
|
if (aID >= mNumContexts) {
|
|
|
|
PRInt32 newSize = aID + 10;
|
|
|
|
SinkContext** contexts = new SinkContext*[newSize];
|
|
|
|
if (nsnull == contexts) {
|
|
|
|
delete sc;
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1998-07-27 05:59:37 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
memset(contexts, 0, sizeof(SinkContext*) * newSize);
|
|
|
|
if (0 != mNumContexts) {
|
|
|
|
memcpy(contexts, mContexts, sizeof(SinkContext*) * mNumContexts);
|
|
|
|
delete [] mContexts;
|
1998-07-27 05:59:37 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mNumContexts = newSize;
|
|
|
|
mContexts = contexts;
|
|
|
|
}
|
|
|
|
mContexts[aID] = sc;
|
1998-07-27 05:59:37 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Push the old current context and make the new context the current one
|
|
|
|
mContextStack.AppendElement(mCurrentContext);
|
|
|
|
mCurrentContext = sc;
|
1998-07-22 23:42:47 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-07-22 23:42:47 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::EndContext(PRInt32 aID)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION((aID >= 0) && (aID < mNumContexts) &&
|
|
|
|
(mCurrentContext == mContexts[aID]), "bad context ID");
|
|
|
|
|
|
|
|
// Destroy the context
|
|
|
|
SinkContext* sc = mCurrentContext;
|
|
|
|
sc->End();
|
|
|
|
delete sc;
|
|
|
|
mContexts[aID] = nsnull;
|
|
|
|
|
|
|
|
// Pop off the previous context and make it our current context
|
|
|
|
PRInt32 n = mContextStack.Count() - 1;
|
|
|
|
mCurrentContext = (SinkContext*) mContextStack.ElementAt(n);
|
|
|
|
mContextStack.RemoveElementAt(n);
|
|
|
|
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::SetContext(PRInt32 aID)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_PRECONDITION((aID >= 0) && (aID < mNumContexts), "bad context ID");
|
|
|
|
SinkContext* sc = mContexts[aID];
|
|
|
|
mCurrentContext = sc;
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::SetTitle(const nsString& aValue)
|
1998-07-22 23:42:47 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_ASSERTION(mCurrentContext == mHeadContext, "SetTitle not in head");
|
1998-07-22 23:42:47 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
if (nsnull == mTitle) {
|
|
|
|
mTitle = new nsString(aValue);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*mTitle = aValue;
|
|
|
|
}
|
1998-11-17 16:29:25 +00:00
|
|
|
ReduceEntities(*mTitle);
|
1998-08-28 16:20:16 +00:00
|
|
|
mTitle->CompressWhitespace(PR_TRUE, PR_TRUE);
|
|
|
|
((nsHTMLDocument*)mDocument)->SetTitle(*mTitle);
|
|
|
|
|
|
|
|
nsIAtom* atom = NS_NewAtom("TITLE");
|
|
|
|
nsIHTMLContent* it = nsnull;
|
1998-09-03 22:23:09 +00:00
|
|
|
nsresult rv = NS_NewHTMLTitleElement(&it, atom);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK == rv) {
|
1998-09-03 22:23:09 +00:00
|
|
|
nsIDOMHTMLTitleElement* domtitle = nsnull;
|
|
|
|
it->QueryInterface(kIDOMHTMLTitleElementIID, (void**) &domtitle);
|
|
|
|
if (nsnull != domtitle) {
|
|
|
|
domtitle->SetText(aValue);
|
|
|
|
NS_RELEASE(domtitle);
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mHead->AppendChildTo(it, PR_FALSE);
|
|
|
|
NS_RELEASE(it);
|
1998-07-22 23:42:47 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(atom);
|
|
|
|
return NS_OK;
|
1998-07-22 23:42:47 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenHTML(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenHTML", aNode);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseHTML(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::CloseHTML", aNode);
|
|
|
|
if (nsnull != mHeadContext) {
|
|
|
|
mHeadContext->End();
|
|
|
|
delete mHeadContext;
|
|
|
|
mHeadContext = nsnull;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenHead(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenHead", aNode);
|
|
|
|
if (nsnull == mHeadContext) {
|
|
|
|
mHeadContext = new SinkContext(this);
|
|
|
|
if (nsnull == mHeadContext) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
mHeadContext->SetPreAppend(PR_TRUE);
|
|
|
|
nsresult rv = mHeadContext->Begin(eHTMLTag_head, mHead);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
1998-07-20 18:52:40 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
mContextStack.AppendElement(mCurrentContext);
|
|
|
|
mCurrentContext = mHeadContext;
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseHead(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::CloseHead", aNode);
|
|
|
|
PRInt32 n = mContextStack.Count() - 1;
|
|
|
|
mCurrentContext = (SinkContext*) mContextStack.ElementAt(n);
|
|
|
|
mContextStack.RemoveElementAt(n);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenBody(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull == mBody, "parser called OpenBody twice");
|
|
|
|
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenBody", aNode);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Open body. Note that we pre-append the body to the root so that
|
|
|
|
// incremental reflow during document loading will work properly.
|
|
|
|
mCurrentContext->SetPreAppend(PR_TRUE);
|
|
|
|
nsresult rv = mCurrentContext->OpenContainer(aNode);
|
|
|
|
mCurrentContext->SetPreAppend(PR_FALSE);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mBody = mCurrentContext->mStack[mCurrentContext->mStackPos - 1].mContent;
|
1998-09-10 19:32:14 +00:00
|
|
|
mBodyChildCount = 0;
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_ADDREF(mBody);
|
|
|
|
|
|
|
|
StartLayout();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseBody(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-07-11 03:51:50 +00:00
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
1998-08-28 16:20:16 +00:00
|
|
|
"HTMLContentSink::CloseBody", aNode);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
PRBool didFlush;
|
|
|
|
nsresult rv = mCurrentContext->FlushText(&didFlush);
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mCurrentContext->CloseContainer(aNode);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
if (didFlush) {
|
|
|
|
// Trigger a reflow for the flushed text
|
1998-09-10 19:32:14 +00:00
|
|
|
mDocument->ContentAppended(mBody, mBodyChildCount);
|
|
|
|
mBody->ChildCount(mBodyChildCount);
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-06-26 15:08:55 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenForm(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
mCurrentContext->FlushText();
|
1998-07-24 18:20:27 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenForm", aNode);
|
1998-08-10 23:02:39 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Close out previous form if it's there
|
|
|
|
NS_IF_RELEASE(mCurrentForm);
|
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
// set the current form
|
1998-08-28 16:20:16 +00:00
|
|
|
nsAutoString tmp("FORM");
|
|
|
|
nsIAtom* atom = NS_NewAtom(tmp);
|
1998-09-23 17:16:51 +00:00
|
|
|
nsIHTMLContent* iContent = nsnull;
|
|
|
|
nsresult rv = NS_NewHTMLFormElement(&iContent, atom);
|
|
|
|
if ((NS_OK == rv) && iContent) {
|
|
|
|
iContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm);
|
|
|
|
NS_RELEASE(iContent);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(atom);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-09-23 17:16:51 +00:00
|
|
|
AddLeaf(aNode);
|
|
|
|
|
|
|
|
// add the form to the document
|
1998-10-22 23:00:37 +00:00
|
|
|
nsIHTMLDocument* htmlDoc = nsnull;
|
|
|
|
if (mDocument && mCurrentForm) {
|
|
|
|
rv = mDocument->QueryInterface(kIHTMLDocumentIID, (void**)&htmlDoc);
|
|
|
|
if ((NS_OK == rv) && htmlDoc) {
|
|
|
|
htmlDoc->AddForm(mCurrentForm);
|
|
|
|
NS_RELEASE(htmlDoc);
|
|
|
|
}
|
|
|
|
}
|
1998-05-08 20:18:06 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-07-22 17:40:05 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// XXX MAYBE add code to place close form tag into the content model
|
|
|
|
// for navigator layout compatability.
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseForm(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::CloseForm", aNode);
|
|
|
|
NS_IF_RELEASE(mCurrentForm);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenFrameset(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenFrameset", aNode);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult rv = mCurrentContext->OpenContainer(aNode);
|
|
|
|
if ((NS_OK == rv) && (nsnull == mFrameset)) {
|
|
|
|
mFrameset = mCurrentContext->mStack[mCurrentContext->mStackPos-1].mContent;
|
|
|
|
NS_ADDREF(mFrameset);
|
|
|
|
}
|
|
|
|
mInMonolithicContainer++;
|
|
|
|
return rv;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseFrameset(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::CloseFrameset", aNode);
|
|
|
|
|
|
|
|
SinkContext* sc = mCurrentContext;
|
|
|
|
nsIHTMLContent* fs = sc->mStack[sc->mStackPos-1].mContent;
|
|
|
|
PRBool done = fs == mFrameset;
|
|
|
|
nsresult rv = sc->CloseContainer(aNode);
|
|
|
|
if (done) {
|
|
|
|
StartLayout();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenMap(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
|
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::OpenMap", aNode);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Close out previous map if it's there
|
|
|
|
NS_IF_RELEASE(mCurrentMap);
|
|
|
|
|
|
|
|
nsAutoString tmp("MAP");
|
|
|
|
nsIAtom* atom = NS_NewAtom(tmp);
|
|
|
|
nsresult rv = NS_NewImageMap(&mCurrentMap, atom);
|
|
|
|
NS_RELEASE(atom);
|
1998-04-13 20:24:54 +00:00
|
|
|
if (NS_OK == rv) {
|
1998-08-31 17:51:32 +00:00
|
|
|
// XXX rewrite to use AddAttributes and don't use FindAttribute
|
1998-08-28 16:20:16 +00:00
|
|
|
// Look for name attribute and set the map name
|
|
|
|
nsAutoString name;
|
|
|
|
if (FindAttribute(aNode, "name", name)) {
|
|
|
|
// XXX leading, trailing, interior non=-space ws is removed
|
|
|
|
name.StripWhitespace();
|
|
|
|
mCurrentMap->SetName(name);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Add the map to the document
|
|
|
|
((nsHTMLDocument*)mDocument)->AddImageMap(mCurrentMap);
|
|
|
|
|
|
|
|
// XXX Add a content object for the map too
|
|
|
|
}
|
1998-07-15 22:31:10 +00:00
|
|
|
return rv;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseMap(const nsIParserNode& aNode)
|
1998-07-12 00:18:26 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
SINK_TRACE_NODE(SINK_TRACE_CALLS,
|
|
|
|
"HTMLContentSink::CloseMap", aNode);
|
|
|
|
NS_IF_RELEASE(mCurrentMap);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-07-12 00:18:26 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::OpenContainer(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
// XXX work around parser bug
|
|
|
|
if (eHTMLTag_frameset == aNode.GetNodeType()) {
|
|
|
|
return OpenFrameset(aNode);
|
|
|
|
}
|
|
|
|
return mCurrentContext->OpenContainer(aNode);
|
|
|
|
}
|
1998-07-12 00:18:26 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::CloseContainer(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
// XXX work around parser bug
|
|
|
|
if (eHTMLTag_frameset == aNode.GetNodeType()) {
|
|
|
|
return CloseFrameset(aNode);
|
|
|
|
}
|
|
|
|
return mCurrentContext->CloseContainer(aNode);
|
|
|
|
}
|
1998-07-12 00:18:26 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::AddLeaf(const nsIParserNode& aNode)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
1998-07-12 00:18:26 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
|
|
|
|
switch (nodeType) {
|
|
|
|
case eHTMLTag_area:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessAREATag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_base:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessBASETag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_link:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessLINKTag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_meta:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessMETATag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_style:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessSTYLETag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
case eHTMLTag_script:
|
|
|
|
mCurrentContext->FlushText();
|
|
|
|
rv = ProcessSCRIPTTag(aNode);
|
1998-07-12 00:18:26 +00:00
|
|
|
break;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
default:
|
|
|
|
rv = mCurrentContext->AddLeaf(aNode);
|
|
|
|
break;
|
1998-07-22 23:42:47 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
return rv;
|
1998-07-12 00:18:26 +00:00
|
|
|
}
|
|
|
|
|
1998-11-10 04:13:59 +00:00
|
|
|
/**
|
|
|
|
* This gets called by the parsing system when we find a comment
|
|
|
|
* @update gess11/9/98
|
|
|
|
* @param aNode contains a comment token
|
|
|
|
* @return error code
|
|
|
|
*/
|
|
|
|
nsresult HTMLContentSink::AddComment(const nsIParserNode& aNode) {
|
|
|
|
nsresult result= NS_OK;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This gets called by the parsing system when we find a PI
|
|
|
|
* @update gess11/9/98
|
|
|
|
* @param aNode contains a comment token
|
|
|
|
* @return error code
|
|
|
|
*/
|
|
|
|
nsresult HTMLContentSink::AddProcessingInstruction(const nsIParserNode& aNode) {
|
|
|
|
nsresult result= NS_OK;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void
|
|
|
|
HTMLContentSink::StartLayout()
|
1998-07-12 00:18:26 +00:00
|
|
|
{
|
1998-09-12 19:33:48 +00:00
|
|
|
if (mLayoutStarted) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mLayoutStarted = PR_TRUE;
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
PRInt32 i, ns = mDocument->GetNumberOfShells();
|
|
|
|
for (i = 0; i < ns; i++) {
|
|
|
|
nsIPresShell* shell = mDocument->GetShellAt(i);
|
|
|
|
if (nsnull != shell) {
|
|
|
|
// Make shell an observer for next time
|
|
|
|
shell->BeginObservingDocument();
|
1998-07-12 00:18:26 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Resize-reflow this time
|
|
|
|
nsIPresContext* cx = shell->GetPresContext();
|
|
|
|
nsRect r;
|
|
|
|
cx->GetVisibleArea(r);
|
1998-09-10 19:32:14 +00:00
|
|
|
shell->InitialReflow(r.width, r.height);
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(cx);
|
|
|
|
|
|
|
|
// Now trigger a refresh
|
|
|
|
nsIViewManager* vm = shell->GetViewManager();
|
|
|
|
if (nsnull != vm) {
|
|
|
|
vm->EnableRefresh();
|
|
|
|
NS_RELEASE(vm);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_RELEASE(shell);
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// If the document we are loading has a reference or it is a top level
|
|
|
|
// frameset document, disable the scroll bars on the views.
|
1998-12-16 05:40:20 +00:00
|
|
|
const char* ref;
|
|
|
|
nsresult rv = mDocumentURL->GetRef(&ref);
|
|
|
|
if (rv == NS_OK) {
|
1998-08-28 16:20:16 +00:00
|
|
|
mRef = new nsString(ref);
|
|
|
|
}
|
|
|
|
PRBool topLevelFrameset = PR_FALSE;
|
|
|
|
if (mFrameset && mWebShell) {
|
|
|
|
nsIWebShell* rootWebShell;
|
|
|
|
mWebShell->GetRootWebShell(rootWebShell);
|
|
|
|
if (mWebShell == rootWebShell) {
|
|
|
|
topLevelFrameset = PR_TRUE;
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(rootWebShell);
|
1998-06-27 22:57:52 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
if ((nsnull != ref) || topLevelFrameset) {
|
|
|
|
// XXX support more than one presentation-shell here
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
// Get initial scroll preference and save it away; disable the
|
|
|
|
// scroll bars.
|
|
|
|
PRInt32 i, ns = mDocument->GetNumberOfShells();
|
|
|
|
for (i = 0; i < ns; i++) {
|
|
|
|
nsIPresShell* shell = mDocument->GetShellAt(i);
|
|
|
|
if (nsnull != shell) {
|
|
|
|
nsIViewManager* vm = shell->GetViewManager();
|
|
|
|
if (nsnull != vm) {
|
|
|
|
nsIView* rootView = nsnull;
|
|
|
|
vm->GetRootView(rootView);
|
|
|
|
if (nsnull != rootView) {
|
|
|
|
nsIScrollableView* sview = nsnull;
|
|
|
|
rootView->QueryInterface(kIScrollableViewIID, (void**) &sview);
|
|
|
|
if (nsnull != sview) {
|
1998-08-30 19:16:11 +00:00
|
|
|
if (topLevelFrameset)
|
|
|
|
mOriginalScrollPreference = nsScrollPreference_kNeverScroll;
|
|
|
|
else
|
|
|
|
sview->GetScrollPreference(mOriginalScrollPreference);
|
1998-08-28 16:20:16 +00:00
|
|
|
sview->SetScrollPreference(nsScrollPreference_kNeverScroll);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(vm);
|
|
|
|
}
|
|
|
|
NS_RELEASE(shell);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
void
|
|
|
|
HTMLContentSink::ScrollToRef()
|
1998-04-22 22:12:24 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
if (mNotAtRef && (nsnull != mRef) && (nsnull != mRefContent)) {
|
|
|
|
// See if the ref content has been reflowed by finding it's frame
|
|
|
|
PRInt32 i, ns = mDocument->GetNumberOfShells();
|
|
|
|
for (i = 0; i < ns; i++) {
|
|
|
|
nsIPresShell* shell = mDocument->GetShellAt(i);
|
|
|
|
if (nsnull != shell) {
|
|
|
|
nsIFrame* frame = shell->FindFrameWithContent(mRefContent);
|
|
|
|
if (nsnull != frame) {
|
|
|
|
nsIViewManager* vm = shell->GetViewManager();
|
|
|
|
if (nsnull != vm) {
|
|
|
|
nsIView* rootView = nsnull;
|
|
|
|
vm->GetRootView(rootView);
|
|
|
|
if (nsnull != rootView) {
|
|
|
|
nsIScrollableView* sview = nsnull;
|
|
|
|
rootView->QueryInterface(kIScrollableViewIID, (void**) &sview);
|
|
|
|
if (nsnull != sview) {
|
|
|
|
// Determine the x,y scroll offsets for the given
|
|
|
|
// frame. The offsets are relative to the
|
|
|
|
// ScrollableView's upper left corner so we need frame
|
|
|
|
// coordinates that are relative to that.
|
|
|
|
nsPoint offset;
|
|
|
|
nsIView* view;
|
|
|
|
frame->GetOffsetFromView(offset, view);
|
|
|
|
if (view == rootView) {
|
|
|
|
// XXX write me!
|
|
|
|
// printf("view==rootView ");
|
|
|
|
}
|
|
|
|
nscoord x = 0;
|
|
|
|
nscoord y = offset.y;
|
|
|
|
#if 0
|
|
|
|
nsIPresContext* cx = shell->GetPresContext();
|
|
|
|
float t2p = cx->GetTwipsToPixels();
|
|
|
|
printf("x=%d y=%d\n", NSTwipsToIntPixels(x, t2p), NSTwipsToIntPixels(y, t2p));
|
|
|
|
NS_RELEASE(cx);
|
|
|
|
#endif
|
|
|
|
sview->SetScrollPreference(mOriginalScrollPreference);
|
|
|
|
sview->ScrollTo(x, y, NS_VMREFRESH_IMMEDIATE);
|
|
|
|
|
|
|
|
// Note that we did this so that we don't bother doing it again
|
|
|
|
mNotAtRef = PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(vm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(shell);
|
|
|
|
}
|
1998-04-22 22:12:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-07-24 18:20:27 +00:00
|
|
|
void
|
|
|
|
HTMLContentSink::AddBaseTagInfo(nsIHTMLContent* aContent)
|
|
|
|
{
|
|
|
|
if (mBaseHREF.Length() > 0) {
|
|
|
|
nsHTMLValue value(mBaseHREF);
|
1998-08-29 20:20:38 +00:00
|
|
|
aContent->SetAttribute(nsHTMLAtoms::_baseHref, value, PR_FALSE);
|
1998-07-24 18:20:27 +00:00
|
|
|
}
|
|
|
|
if (mBaseTarget.Length() > 0) {
|
|
|
|
nsHTMLValue value(mBaseTarget);
|
1998-08-29 20:20:38 +00:00
|
|
|
aContent->SetAttribute(nsHTMLAtoms::_baseTarget, value, PR_FALSE);
|
1998-07-24 18:20:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessATag(const nsIParserNode& aNode,
|
|
|
|
nsIHTMLContent* aContent)
|
|
|
|
{
|
|
|
|
AddBaseTagInfo(aContent);
|
|
|
|
if ((nsnull != mRef) && (nsnull == mRefContent)) {
|
|
|
|
nsHTMLValue value;
|
|
|
|
aContent->GetAttribute(nsHTMLAtoms::name, value);
|
|
|
|
if (eHTMLUnit_String == value.GetUnit()) {
|
|
|
|
nsAutoString tmp;
|
|
|
|
value.GetStringValue(tmp);
|
|
|
|
if (mRef->EqualsIgnoreCase(tmp)) {
|
|
|
|
// Winner. We just found the content that is the named anchor
|
|
|
|
mRefContent = aContent;
|
|
|
|
NS_ADDREF(aContent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX add area content object to map content object instead
|
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessAREATag(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
if (nsnull != mCurrentMap) {
|
|
|
|
nsAutoString shape, coords, href, target(mBaseTarget), alt;
|
|
|
|
PRInt32 ac = aNode.GetAttributeCount();
|
|
|
|
PRBool suppress = PR_FALSE;
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
|
1998-04-13 20:24:54 +00:00
|
|
|
for (PRInt32 i = 0; i < ac; i++) {
|
|
|
|
// Get upper-cased key
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
|
|
|
if (key.EqualsIgnoreCase("shape")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, shape, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("coords")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, coords, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("href")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, href, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
href.StripWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("target")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, target, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("alt")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, alt, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("suppress")) {
|
|
|
|
suppress = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_RELEASE(sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
mCurrentMap->AddArea(mBaseHREF, shape, coords, href, target, alt,
|
|
|
|
suppress);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessBASETag(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
|
1998-04-13 20:24:54 +00:00
|
|
|
PRInt32 ac = aNode.GetAttributeCount();
|
|
|
|
for (PRInt32 i = 0; i < ac; i++) {
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
|
|
|
if (key.EqualsIgnoreCase("href")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, mBaseHREF, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
} else if (key.EqualsIgnoreCase("target")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, i, mBaseTarget, sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
1998-08-31 17:51:32 +00:00
|
|
|
NS_RELEASE(sco);
|
1998-04-13 20:24:54 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
typedef struct {
|
|
|
|
nsString mTitle;
|
|
|
|
nsString mMedia;
|
|
|
|
PRBool mIsActive;
|
|
|
|
nsIURL* mURL;
|
|
|
|
nsIHTMLContent* mElement;
|
|
|
|
HTMLContentSink* mSink;
|
1998-12-18 01:36:41 +00:00
|
|
|
} nsAsyncStyleProcessingDataHTML;
|
1998-12-15 06:10:59 +00:00
|
|
|
|
|
|
|
static void
|
1998-12-18 01:36:41 +00:00
|
|
|
nsDoneLoadingStyle(nsIUnicharStreamLoader* aLoader,
|
1998-12-15 06:10:59 +00:00
|
|
|
nsString& aData,
|
|
|
|
void* aRef,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
1998-12-18 01:36:41 +00:00
|
|
|
nsAsyncStyleProcessingDataHTML* d = (nsAsyncStyleProcessingDataHTML*)aRef;
|
1998-12-15 06:10:59 +00:00
|
|
|
nsIUnicharInputStream* uin = nsnull;
|
|
|
|
|
|
|
|
if ((NS_OK == aStatus) && (0 < aData.Length())) {
|
|
|
|
// wrap the string with the CSS data up in a unicode
|
|
|
|
// input stream.
|
|
|
|
rv = NS_NewStringUnicharInputStream(&uin, new nsString(aData));
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
// XXX We have no way of indicating failure. Silently fail?
|
|
|
|
rv = d->mSink->LoadStyleSheet(d->mURL, uin, d->mIsActive,
|
|
|
|
d->mTitle, d->mMedia, d->mElement);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
d->mSink->ResumeParsing();
|
|
|
|
|
|
|
|
NS_RELEASE(d->mURL);
|
|
|
|
NS_IF_RELEASE(d->mElement);
|
|
|
|
NS_RELEASE(d->mSink);
|
|
|
|
delete d;
|
|
|
|
|
|
|
|
// We added a reference when the loader was created. This
|
|
|
|
// release should destroy it.
|
|
|
|
NS_RELEASE(aLoader);
|
|
|
|
}
|
|
|
|
|
1998-06-26 15:08:55 +00:00
|
|
|
nsresult
|
1998-08-28 16:20:16 +00:00
|
|
|
HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
|
1998-06-26 15:08:55 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult result = NS_OK;
|
|
|
|
PRInt32 index;
|
|
|
|
PRInt32 count = aNode.GetAttributeCount();
|
1998-08-13 20:09:10 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsAutoString href;
|
|
|
|
nsAutoString rel;
|
|
|
|
nsAutoString title;
|
|
|
|
nsAutoString type;
|
1998-11-26 01:29:10 +00:00
|
|
|
nsAutoString media;
|
1998-08-13 20:09:10 +00:00
|
|
|
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
|
1998-08-28 16:20:16 +00:00
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
const nsString& key = aNode.GetKeyAt(index);
|
|
|
|
if (key.EqualsIgnoreCase("href")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, index, href, sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
href.StripWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("rel")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, index, rel, sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
rel.CompressWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("title")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, index, title, sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
title.CompressWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("type")) {
|
1998-08-31 17:51:32 +00:00
|
|
|
GetAttributeValueAt(aNode, index, type, sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
type.StripWhitespace();
|
1998-06-26 15:08:55 +00:00
|
|
|
}
|
1998-11-26 01:29:10 +00:00
|
|
|
else if (key.EqualsIgnoreCase("media")) {
|
|
|
|
GetAttributeValueAt(aNode, index, media, sco);
|
1998-12-02 00:35:03 +00:00
|
|
|
media.ToUpperCase();
|
1998-11-26 01:29:10 +00:00
|
|
|
}
|
1998-06-26 15:08:55 +00:00
|
|
|
}
|
1998-08-13 20:09:10 +00:00
|
|
|
|
1998-11-26 01:29:10 +00:00
|
|
|
// Create content object
|
|
|
|
nsAutoString tag("LINK");
|
|
|
|
nsIHTMLContent* element = nsnull;
|
|
|
|
result = NS_CreateHTMLElement(&element, tag);
|
|
|
|
if (NS_SUCCEEDED(result)) {
|
|
|
|
// Add in the attributes and add the style content object to the
|
|
|
|
// head container.
|
|
|
|
result = AddAttributes(aNode, element, sco);
|
|
|
|
if (NS_FAILED(result)) {
|
|
|
|
NS_RELEASE(element);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
mHead->AppendChildTo(element, PR_FALSE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_IF_RELEASE(sco);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(sco);
|
|
|
|
|
|
|
|
if (rel.EqualsIgnoreCase("stylesheet") || rel.EqualsIgnoreCase("alternate stylesheet")) {
|
1998-10-13 19:11:42 +00:00
|
|
|
if ((0 == type.Length()) || type.EqualsIgnoreCase("text/css")) {
|
1998-08-28 16:20:16 +00:00
|
|
|
nsIURL* url = nsnull;
|
|
|
|
nsAutoString absURL;
|
1998-12-16 05:40:20 +00:00
|
|
|
nsIURLGroup* urlGroup;
|
|
|
|
(void)mDocumentURL->GetURLGroup(&urlGroup);
|
1998-12-15 06:10:59 +00:00
|
|
|
result = NS_MakeAbsoluteURL(mDocumentURL, mBaseHREF, href, absURL);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK != result) {
|
|
|
|
return result;
|
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
if (urlGroup) {
|
|
|
|
result = urlGroup->CreateURL(&url, nsnull, absURL, nsnull);
|
|
|
|
NS_RELEASE(urlGroup);
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
else {
|
1998-12-16 05:40:20 +00:00
|
|
|
result = NS_NewURL(&url, absURL);
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
|
|
|
if (NS_OK != result) {
|
|
|
|
return result;
|
|
|
|
}
|
1998-06-26 15:08:55 +00:00
|
|
|
|
1998-12-18 01:36:41 +00:00
|
|
|
nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML;
|
1998-12-15 06:10:59 +00:00
|
|
|
if (nsnull == d) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
d->mTitle.SetString(title);
|
|
|
|
d->mMedia.SetString(media);
|
|
|
|
d->mIsActive = rel.EqualsIgnoreCase("stylesheet");
|
|
|
|
d->mURL = url;
|
|
|
|
NS_ADDREF(url);
|
|
|
|
d->mElement = element;
|
|
|
|
NS_ADDREF(element);
|
|
|
|
d->mSink = this;
|
|
|
|
NS_ADDREF(this);
|
|
|
|
|
1998-12-18 01:36:41 +00:00
|
|
|
nsIUnicharStreamLoader* loader;
|
|
|
|
result = NS_NewUnicharStreamLoader(&loader,
|
|
|
|
url,
|
|
|
|
(nsStreamCompleteFunc)nsDoneLoadingStyle,
|
|
|
|
(void *)d);
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(url);
|
1998-12-18 01:36:41 +00:00
|
|
|
if (NS_OK == result) {
|
|
|
|
result = NS_ERROR_HTMLPARSER_BLOCK;
|
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
}
|
1998-07-15 00:49:26 +00:00
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
NS_RELEASE(element);
|
1998-08-28 16:20:16 +00:00
|
|
|
return result;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
1998-08-28 16:20:16 +00:00
|
|
|
if (nsnull != mHead) {
|
|
|
|
// Create content object
|
|
|
|
nsAutoString tmp("META");
|
|
|
|
nsIAtom* atom = NS_NewAtom(tmp);
|
|
|
|
if (nsnull == atom) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
nsIHTMLContent* it;
|
1998-09-02 23:53:49 +00:00
|
|
|
nsresult rv = NS_NewHTMLMetaElement(&it, atom);
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(atom);
|
|
|
|
if (NS_OK == rv) {
|
|
|
|
// Add in the attributes and add the meta content object to the
|
|
|
|
// head container.
|
1998-08-31 17:51:32 +00:00
|
|
|
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
|
|
|
|
rv = AddAttributes(aNode, it, sco);
|
|
|
|
NS_IF_RELEASE(sco);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
NS_RELEASE(it);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mHead->AppendChildTo(it, PR_FALSE);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-10-20 00:18:19 +00:00
|
|
|
// If we are processing an HTTP url, handle meta http-equiv cases
|
1998-12-16 05:40:20 +00:00
|
|
|
nsIHttpURL* httpUrl = nsnull;
|
|
|
|
rv = mDocumentURL->QueryInterface(kIHTTPURLIID, (void **)&httpUrl);
|
1998-08-28 16:20:16 +00:00
|
|
|
if (NS_OK == rv) {
|
1998-10-20 00:18:19 +00:00
|
|
|
nsAutoString header;
|
|
|
|
it->GetAttribute(nsHTMLAtoms::httpEquiv, header);
|
|
|
|
if (header.Length() > 0) {
|
|
|
|
nsAutoString result;
|
1998-08-28 16:20:16 +00:00
|
|
|
it->GetAttribute(nsHTMLAtoms::content, result);
|
|
|
|
if (result.Length() > 0) {
|
1998-10-20 00:18:19 +00:00
|
|
|
char* value = result.ToNewCString(), *csHeader;
|
1998-08-28 16:20:16 +00:00
|
|
|
if (!value) {
|
|
|
|
NS_RELEASE(it);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
1998-10-20 00:18:19 +00:00
|
|
|
csHeader = header.ToNewCString();
|
|
|
|
if (!csHeader) {
|
|
|
|
delete value;
|
|
|
|
NS_RELEASE(it);
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
httpUrl->AddMimeHeader(csHeader, value);
|
|
|
|
delete csHeader;
|
1998-08-28 16:20:16 +00:00
|
|
|
delete value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(httpUrl);
|
|
|
|
}
|
1998-08-27 00:48:53 +00:00
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
NS_RELEASE(it);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-08-28 16:20:16 +00:00
|
|
|
|
|
|
|
return NS_OK;
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-10-30 03:36:35 +00:00
|
|
|
// Returns PR_TRUE if the language name is a version of JavaScript and
|
|
|
|
// PR_FALSE otherwise
|
|
|
|
static PRBool
|
|
|
|
IsJavaScriptLanguage(const nsString& aName)
|
|
|
|
{
|
|
|
|
if (aName.EqualsIgnoreCase("JavaScript") ||
|
|
|
|
aName.EqualsIgnoreCase("LiveScript") ||
|
|
|
|
aName.EqualsIgnoreCase("Mocha")) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else if (aName.EqualsIgnoreCase("JavaScript1.1")) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else if (aName.EqualsIgnoreCase("JavaScript1.2")) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else if (aName.EqualsIgnoreCase("JavaScript1.3")) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else if (aName.EqualsIgnoreCase("JavaScript1.4")) {
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ResumeParsing()
|
|
|
|
{
|
|
|
|
if (nsnull != mParser) {
|
|
|
|
mParser->EnableParser(PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
HTMLContentSink::EvaluateScript(nsString& aScript,
|
|
|
|
PRInt32 aLineNo)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
if (aScript.Length() > 0) {
|
|
|
|
nsIScriptContextOwner *owner;
|
|
|
|
nsIScriptContext *context;
|
|
|
|
owner = mDocument->GetScriptContextOwner();
|
|
|
|
if (nsnull != owner) {
|
|
|
|
|
|
|
|
rv = owner->GetScriptContext(&context);
|
|
|
|
if (rv != NS_OK) {
|
|
|
|
NS_RELEASE(owner);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString ret;
|
|
|
|
nsIURL* docURL = mDocument->GetDocumentURL();
|
|
|
|
const char* url;
|
|
|
|
if (docURL) {
|
1998-12-16 05:40:20 +00:00
|
|
|
(void)docURL->GetSpec(&url);
|
1998-12-15 06:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool isUndefined;
|
|
|
|
PRBool result = context->EvaluateString(aScript, url, aLineNo,
|
|
|
|
ret, &isUndefined);
|
|
|
|
|
|
|
|
NS_IF_RELEASE(docURL);
|
|
|
|
|
|
|
|
NS_RELEASE(context);
|
|
|
|
NS_RELEASE(owner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-12-18 01:36:41 +00:00
|
|
|
nsDoneLoadingScript(nsIUnicharStreamLoader* aLoader,
|
1998-12-15 06:10:59 +00:00
|
|
|
nsString& aData,
|
|
|
|
void* aRef,
|
|
|
|
nsresult aStatus)
|
|
|
|
{
|
|
|
|
HTMLContentSink* sink = (HTMLContentSink*)aRef;
|
|
|
|
|
|
|
|
if (NS_OK == aStatus) {
|
|
|
|
// XXX We have no way of indicating failure. Silently fail?
|
|
|
|
sink->EvaluateScript(aData, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
sink->ResumeParsing();
|
|
|
|
|
|
|
|
// The url loader held a reference to the sink
|
|
|
|
NS_RELEASE(sink);
|
|
|
|
|
|
|
|
// We added a reference when the loader was created. This
|
|
|
|
// release should destroy it.
|
|
|
|
NS_RELEASE(aLoader);
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
|
1998-06-25 22:26:52 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
1998-10-30 03:36:35 +00:00
|
|
|
PRBool isJavaScript = PR_TRUE;
|
1998-06-25 22:26:52 +00:00
|
|
|
PRInt32 i, ac = aNode.GetAttributeCount();
|
|
|
|
|
1998-10-30 03:36:35 +00:00
|
|
|
// Look for SRC attribute and look for a LANGUAGE attribute
|
1998-10-01 22:23:48 +00:00
|
|
|
nsAutoString src;
|
1998-06-25 22:26:52 +00:00
|
|
|
for (i = 0; i < ac; i++) {
|
|
|
|
const nsString& key = aNode.GetKeyAt(i);
|
|
|
|
if (key.EqualsIgnoreCase("src")) {
|
1998-12-15 06:10:59 +00:00
|
|
|
GetAttributeValueAt(aNode, i, src, nsnull);
|
1998-06-25 22:26:52 +00:00
|
|
|
}
|
1998-10-30 03:36:35 +00:00
|
|
|
else if (key.EqualsIgnoreCase("type")) {
|
|
|
|
nsAutoString type;
|
1998-06-25 22:26:52 +00:00
|
|
|
|
1998-10-30 03:36:35 +00:00
|
|
|
GetAttributeValueAt(aNode, i, type, nsnull);
|
1998-11-23 23:06:57 +00:00
|
|
|
isJavaScript = type.EqualsIgnoreCase("text/javascript") ||
|
|
|
|
type.EqualsIgnoreCase("application/x-javascript");
|
1998-06-25 22:26:52 +00:00
|
|
|
}
|
1998-10-30 03:36:35 +00:00
|
|
|
else if (key.EqualsIgnoreCase("language")) {
|
|
|
|
nsAutoString lang;
|
|
|
|
|
|
|
|
GetAttributeValueAt(aNode, i, lang, nsnull);
|
|
|
|
isJavaScript = IsJavaScriptLanguage(lang);
|
1998-06-25 22:26:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-30 03:36:35 +00:00
|
|
|
// Don't process scripts that aren't JavaScript
|
|
|
|
if (isJavaScript) {
|
|
|
|
nsAutoString script;
|
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
mCurrentContext->FlushTags();
|
|
|
|
|
|
|
|
// If there is a SRC attribute...
|
|
|
|
if (src.Length() > 0) {
|
1998-12-18 01:36:41 +00:00
|
|
|
// Use the SRC attribute value to load the URL
|
1998-10-30 03:36:35 +00:00
|
|
|
nsIURL* url = nsnull;
|
|
|
|
nsAutoString absURL;
|
1998-12-16 05:40:20 +00:00
|
|
|
nsIURLGroup* urlGroup;
|
|
|
|
(void)mDocumentURL->GetURLGroup(&urlGroup);
|
1998-12-15 06:10:59 +00:00
|
|
|
rv = NS_MakeAbsoluteURL(mDocumentURL, mBaseHREF, src, absURL);
|
1998-10-30 03:36:35 +00:00
|
|
|
if (NS_OK != rv) {
|
1998-06-25 22:26:52 +00:00
|
|
|
return rv;
|
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
if (urlGroup) {
|
|
|
|
rv = urlGroup->CreateURL(&url, nsnull, absURL, nsnull);
|
|
|
|
NS_RELEASE(urlGroup);
|
1998-08-12 23:37:50 +00:00
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
else {
|
1998-12-16 05:40:20 +00:00
|
|
|
rv = NS_NewURL(&url, absURL);
|
1998-10-30 03:36:35 +00:00
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
1998-10-30 03:36:35 +00:00
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
|
|
|
|
// Add a reference to this since the url loader is holding
|
|
|
|
// onto it as opaque data.
|
|
|
|
NS_ADDREF(this);
|
|
|
|
|
1998-12-18 01:36:41 +00:00
|
|
|
nsIUnicharStreamLoader* loader;
|
|
|
|
rv = NS_NewUnicharStreamLoader(&loader,
|
|
|
|
url,
|
|
|
|
(nsStreamCompleteFunc)nsDoneLoadingScript,
|
1998-12-15 06:10:59 +00:00
|
|
|
(void *)this);
|
1998-10-30 03:36:35 +00:00
|
|
|
NS_RELEASE(url);
|
1998-12-18 01:36:41 +00:00
|
|
|
if (NS_OK == rv) {
|
|
|
|
rv = NS_ERROR_HTMLPARSER_BLOCK;
|
|
|
|
}
|
1998-10-30 03:36:35 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Otherwise, get the text content of the script tag
|
|
|
|
script = aNode.GetSkippedContent();
|
1998-11-28 23:51:06 +00:00
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
PRUint32 lineNo = (PRUint32)aNode.GetSourceLineNumber();
|
1998-11-28 23:51:06 +00:00
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
EvaluateScript(script, lineNo);
|
1998-06-25 22:26:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1998-12-15 06:10:59 +00:00
|
|
|
|
1998-04-13 20:24:54 +00:00
|
|
|
// 3 ways to load a style sheet: inline, style src=, link tag
|
1998-08-28 16:20:16 +00:00
|
|
|
// XXX What does nav do if we have SRC= and some style data inline?
|
1998-07-24 18:20:27 +00:00
|
|
|
// XXX This code and ProcessSCRIPTTag share alot in common; clean that up!
|
1998-08-28 16:20:16 +00:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
1998-11-26 01:29:10 +00:00
|
|
|
PRInt32 index, count = aNode.GetAttributeCount();
|
1998-04-13 20:24:54 +00:00
|
|
|
|
1998-11-26 01:29:10 +00:00
|
|
|
nsAutoString src;
|
|
|
|
nsAutoString title;
|
|
|
|
nsAutoString type;
|
|
|
|
nsAutoString media;
|
1998-08-10 23:02:39 +00:00
|
|
|
|
1998-11-26 01:29:10 +00:00
|
|
|
nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner();
|
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
const nsString& key = aNode.GetKeyAt(index);
|
1998-04-13 20:24:54 +00:00
|
|
|
if (key.EqualsIgnoreCase("src")) {
|
1998-11-26 01:29:10 +00:00
|
|
|
GetAttributeValueAt(aNode, index, src, sco);
|
|
|
|
src.StripWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("title")) {
|
|
|
|
GetAttributeValueAt(aNode, index, title, sco);
|
|
|
|
title.CompressWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("type")) {
|
|
|
|
GetAttributeValueAt(aNode, index, type, sco);
|
|
|
|
type.StripWhitespace();
|
|
|
|
}
|
|
|
|
else if (key.EqualsIgnoreCase("media")) {
|
|
|
|
GetAttributeValueAt(aNode, index, media, sco);
|
1998-12-02 00:35:03 +00:00
|
|
|
media.ToUpperCase();
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-11-26 01:29:10 +00:00
|
|
|
// Create content object
|
|
|
|
nsAutoString tag("STYLE");
|
|
|
|
nsIHTMLContent* element = nsnull;
|
|
|
|
rv = NS_CreateHTMLElement(&element, tag);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Add in the attributes and add the style content object to the
|
|
|
|
// head container.
|
|
|
|
rv = AddAttributes(aNode, element, sco);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
NS_RELEASE(element);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
mHead->AppendChildTo(element, PR_FALSE);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NS_IF_RELEASE(sco);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
NS_IF_RELEASE(sco);
|
|
|
|
|
|
|
|
// The skipped content contains the inline style data
|
1998-04-13 20:24:54 +00:00
|
|
|
const nsString& content = aNode.GetSkippedContent();
|
|
|
|
|
|
|
|
nsIURL* url = nsnull;
|
|
|
|
nsIUnicharInputStream* uin = nsnull;
|
1998-11-26 01:29:10 +00:00
|
|
|
if (0 == src.Length()) {
|
1998-04-13 20:24:54 +00:00
|
|
|
// Create a string to hold the data and wrap it up in a unicode
|
|
|
|
// input stream.
|
|
|
|
rv = NS_NewStringUnicharInputStream(&uin, new nsString(content));
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Use the document's url since the style data came from there
|
1998-12-11 02:46:25 +00:00
|
|
|
if (0 < mBaseHREF.Length()) { // use base URL
|
|
|
|
rv = NS_NewURL(&url, mBaseHREF);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
url = mDocumentURL;
|
|
|
|
NS_IF_ADDREF(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
url = mDocumentURL;
|
|
|
|
NS_IF_ADDREF(url);
|
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
|
|
|
|
// Now that we have a url and a unicode input stream, parse the
|
|
|
|
// style sheet.
|
|
|
|
rv = LoadStyleSheet(url, uin, PR_TRUE, title, media, element);
|
|
|
|
NS_RELEASE(url);
|
|
|
|
NS_RELEASE(uin);
|
1998-04-13 20:24:54 +00:00
|
|
|
} else {
|
|
|
|
// src with immediate style data doesn't add up
|
|
|
|
// XXX what does nav do?
|
1998-12-18 01:36:41 +00:00
|
|
|
// Use the SRC attribute value to load the URL
|
1998-07-24 18:20:27 +00:00
|
|
|
nsAutoString absURL;
|
1998-12-16 05:40:20 +00:00
|
|
|
nsIURLGroup* urlGroup;
|
|
|
|
(void)mDocumentURL->GetURLGroup(&urlGroup);
|
1998-12-15 06:10:59 +00:00
|
|
|
rv = NS_MakeAbsoluteURL(mDocumentURL, mBaseHREF, src, absURL);
|
1998-07-24 18:20:27 +00:00
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
if (urlGroup) {
|
|
|
|
rv = urlGroup->CreateURL(&url, nsnull, absURL, nsnull);
|
|
|
|
NS_RELEASE(urlGroup);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
else {
|
1998-12-16 05:40:20 +00:00
|
|
|
rv = NS_NewURL(&url, absURL);
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
if (NS_OK != rv) {
|
|
|
|
return rv;
|
|
|
|
}
|
1998-12-15 06:10:59 +00:00
|
|
|
|
1998-12-18 01:36:41 +00:00
|
|
|
nsAsyncStyleProcessingDataHTML* d = new nsAsyncStyleProcessingDataHTML;
|
1998-12-15 06:10:59 +00:00
|
|
|
if (nsnull == d) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
d->mTitle.SetString(title);
|
|
|
|
d->mMedia.SetString(media);
|
|
|
|
d->mIsActive = PR_TRUE;
|
|
|
|
d->mURL = url;
|
|
|
|
NS_ADDREF(url);
|
|
|
|
d->mElement = element;
|
|
|
|
NS_ADDREF(element);
|
|
|
|
d->mSink = this;
|
|
|
|
NS_ADDREF(this);
|
|
|
|
|
1998-12-18 01:36:41 +00:00
|
|
|
nsIUnicharStreamLoader* loader;
|
|
|
|
rv = NS_NewUnicharStreamLoader(&loader,
|
|
|
|
url,
|
|
|
|
(nsStreamCompleteFunc)nsDoneLoadingStyle,
|
|
|
|
(void *)d);
|
1998-12-15 06:10:59 +00:00
|
|
|
NS_RELEASE(url);
|
1998-12-18 01:36:41 +00:00
|
|
|
if (NS_OK == rv) {
|
|
|
|
rv = NS_ERROR_HTMLPARSER_BLOCK;
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
|
|
|
|
1998-12-03 16:46:56 +00:00
|
|
|
NS_RELEASE(element);
|
1998-04-13 20:24:54 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1998-11-26 01:29:10 +00:00
|
|
|
|
|
|
|
typedef PRBool (*nsStringEnumFunc)(const nsString& aSubString, void *aData);
|
|
|
|
|
|
|
|
const PRUnichar kNullCh = PRUnichar('\0');
|
|
|
|
const PRUnichar kSingleQuote = PRUnichar('\'');
|
|
|
|
const PRUnichar kDoubleQuote = PRUnichar('\"');
|
|
|
|
const PRUnichar kComma = PRUnichar(',');
|
|
|
|
|
|
|
|
static PRBool EnumerateString(const nsString& aStringList, nsStringEnumFunc aFunc, void* aData)
|
|
|
|
{
|
|
|
|
PRBool running = PR_TRUE;
|
|
|
|
|
|
|
|
nsAutoString stringList(aStringList); // copy to work buffer
|
|
|
|
nsAutoString subStr;
|
|
|
|
|
|
|
|
stringList.Append(kNullCh); // put an extra null at the end
|
|
|
|
|
|
|
|
PRUnichar* start = (PRUnichar*)stringList;
|
|
|
|
PRUnichar* end = start;
|
|
|
|
|
|
|
|
while (running && (kNullCh != *start)) {
|
|
|
|
PRBool quoted = PR_FALSE;
|
|
|
|
|
|
|
|
while ((kNullCh != *start) && nsString::IsSpace(*start)) { // skip leading space
|
|
|
|
start++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((kSingleQuote == *start) || (kDoubleQuote == *start)) { // quoted string
|
|
|
|
PRUnichar quote = *start++;
|
|
|
|
quoted = PR_TRUE;
|
|
|
|
end = start;
|
|
|
|
while (kNullCh != *end) {
|
|
|
|
if (quote == *end) { // found closing quote
|
|
|
|
*end++ = kNullCh; // end string here
|
|
|
|
while ((kNullCh != *end) && (kComma != *end)) { // keep going until comma
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // non-quoted string or ended
|
|
|
|
end = start;
|
|
|
|
|
|
|
|
while ((kNullCh != *end) && (kComma != *end)) { // look for comma
|
|
|
|
end++;
|
|
|
|
}
|
|
|
|
*end = kNullCh; // end string here
|
|
|
|
}
|
|
|
|
|
|
|
|
subStr = start;
|
|
|
|
|
|
|
|
if (PR_FALSE == quoted) {
|
|
|
|
subStr.CompressWhitespace(PR_FALSE, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 < subStr.Length()) {
|
|
|
|
running = (*aFunc)(subStr, aData);
|
|
|
|
}
|
|
|
|
|
|
|
|
start = ++end;
|
|
|
|
}
|
|
|
|
|
|
|
|
return running;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PRBool MediumEnumFunc(const nsString& aSubString, void *aData)
|
|
|
|
{
|
1998-12-02 00:35:03 +00:00
|
|
|
nsIAtom* medium = NS_NewAtom(aSubString);
|
|
|
|
((nsICSSStyleSheet*)aData)->AppendMedium(medium);
|
1998-11-26 01:29:10 +00:00
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
|
1998-08-28 16:20:16 +00:00
|
|
|
nsresult
|
|
|
|
HTMLContentSink::LoadStyleSheet(nsIURL* aURL,
|
|
|
|
nsIUnicharInputStream* aUIN,
|
1998-11-26 01:29:10 +00:00
|
|
|
PRBool aActive,
|
|
|
|
const nsString& aTitle,
|
|
|
|
const nsString& aMedia,
|
|
|
|
nsIHTMLContent* aOwner)
|
1998-04-13 20:24:54 +00:00
|
|
|
{
|
|
|
|
/* XXX use repository */
|
|
|
|
nsICSSParser* parser;
|
|
|
|
nsresult rv = NS_NewCSSParser(&parser);
|
|
|
|
if (NS_OK == rv) {
|
1998-11-26 01:29:10 +00:00
|
|
|
nsICSSStyleSheet* sheet = nsnull;
|
1998-05-28 18:40:23 +00:00
|
|
|
// XXX note: we are ignoring rv until the error code stuff in the
|
|
|
|
// input routines is converted to use nsresult's
|
1998-12-11 02:46:25 +00:00
|
|
|
parser->SetCaseSensative(PR_FALSE);
|
1998-08-10 23:02:39 +00:00
|
|
|
parser->Parse(aUIN, aURL, sheet);
|
1998-04-13 20:24:54 +00:00
|
|
|
if (nsnull != sheet) {
|
1998-11-26 01:29:10 +00:00
|
|
|
sheet->SetTitle(aTitle);
|
|
|
|
sheet->SetEnabled(aActive);
|
|
|
|
if (0 < aMedia.Length()) {
|
|
|
|
EnumerateString(aMedia, MediumEnumFunc, sheet);
|
1998-08-10 23:02:39 +00:00
|
|
|
}
|
1998-11-26 01:29:10 +00:00
|
|
|
if (nsnull != aOwner) {
|
|
|
|
nsIDOMNode* domNode = nsnull;
|
|
|
|
if (NS_SUCCEEDED(aOwner->QueryInterface(kIDOMNodeIID, (void**)&domNode))) {
|
|
|
|
sheet->SetOwningNode(domNode);
|
|
|
|
NS_RELEASE(domNode);
|
|
|
|
}
|
1998-04-13 20:24:54 +00:00
|
|
|
}
|
1998-11-26 01:29:10 +00:00
|
|
|
mDocument->AddStyleSheet(sheet);
|
|
|
|
NS_RELEASE(sheet);
|
1998-04-13 20:24:54 +00:00
|
|
|
rv = NS_OK;
|
|
|
|
} else {
|
|
|
|
rv = NS_ERROR_OUT_OF_MEMORY;/* XXX */
|
|
|
|
}
|
|
|
|
NS_RELEASE(parser);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
1998-11-11 22:06:16 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
HTMLContentSink::NotifyError(nsresult aErrorResult)
|
|
|
|
{
|
|
|
|
// Errors in HTML? Who would have thought!
|
|
|
|
// Why are you telling us, parser. Deal with it yourself.
|
|
|
|
PR_ASSERT(0);
|
|
|
|
return NS_OK;
|
|
|
|
}
|