/* -*- 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"
#include "nsIStyleSheet.h"
#include "nsIUnicharInputStream.h"
#include "nsIHTMLContent.h"
#include "nsIURL.h"
#include "nsIHttpUrl.h"
#include "nsHTMLDocument.h"
#include "nsIPresShell.h"
#include "nsIPresContext.h"
#include "nsIViewManager.h"
#include "nsHTMLTokens.h"
#include "nsHTMLEntities.h"
#include "nsCRT.h"
#include "prtime.h"
#include "prlog.h"
#include "nsHTMLParts.h"
#include "nsTablePart.h"
#include "nsTableRow.h"
#include "nsTableCell.h"
#include "nsIDOMText.h"
#include "nsHTMLForms.h"
#include "nsIFormManager.h"
#include "nsIFormControl.h"
#include "nsIImageMap.h"
#include "nsRepository.h"
#include "nsIScrollableView.h"
#include "nsHTMLAtoms.h"
#include "nsIFrame.h"
#include "nsIWebShell.h"
extern nsresult NS_NewHTMLIFrame(nsIHTMLContent** aInstancePtrResult,
nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move
extern nsresult NS_NewHTMLFrame(nsIHTMLContent** aInstancePtrResult,
nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move
extern nsresult NS_NewHTMLFrameset(nsIHTMLContent** aInstancePtrResult,
nsIAtom* aTag, nsIWebShell* aWebShell); // XXX move
// XXX attribute values have entities in them - use the parsers expander!
// XXX Go through a factory for this one
#include "nsICSSParser.h"
#ifdef NS_DEBUG
static PRLogModuleInfo* gSinkLogModuleInfo;
#define SINK_TRACE_CALLS 0x1
#define SINK_TRACE_REFLOW 0x2
#define SINK_LOG_TEST(_lm,_bit) (PRIntn((_lm)->level) & (_bit))
#define SINK_TRACE(_bit,_args) \
PR_BEGIN_MACRO \
if (SINK_LOG_TEST(gSinkLogModuleInfo,_bit)) { \
PR_LogPrint _args; \
} \
PR_END_MACRO
#define SINK_TRACE_NODE(_bit,_msg,_node) \
PR_BEGIN_MACRO \
if (SINK_LOG_TEST(gSinkLogModuleInfo,_bit)) { \
char cbuf[40]; \
const char* cp; \
PRInt32 nt = (_node).GetNodeType(); \
if ((nt > PRInt32(eHTMLTag_unknown)) && \
(nt < PRInt32(eHTMLTag_text))) { \
cp = NS_EnumToTag(nsHTMLTag((_node).GetNodeType())); \
} else { \
(_node).GetText().ToCString(cbuf, sizeof(cbuf)); \
cp = cbuf; \
} \
PR_LogPrint("%s: this=%p node='%s'", _msg, this, cp); \
} \
PR_END_MACRO
#else
#define SINK_TRACE(_bit,_args)
#define SINK_TRACE_NODE(_bit,_msg,_node)
#endif
//----------------------------------------------------------------------
static NS_DEFINE_IID(kIHTTPUrlIID, NS_IHTTPURL_IID);
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID);
static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID);
static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
class HTMLContentSink : public nsIHTMLContentSink {
public:
HTMLContentSink();
~HTMLContentSink();
void* operator new(size_t size) {
void* rv = ::operator new(size);
nsCRT::zero(rv, size);
return (void*) rv;
}
nsresult Init(nsIDocument* aDoc,
nsIURL* aURL,
nsIWebShell* aContainer);
nsIHTMLContent* GetCurrentContainer(eHTMLTags* aType);
nsIHTMLContent* GetTableParent();
// nsISupports
NS_DECL_ISUPPORTS
// nsIContentSink
NS_IMETHOD WillBuildModel(void);
NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel);
NS_IMETHOD WillInterrupt(void);
NS_IMETHOD WillResume(void);
// nsIHTMLContentSink
NS_IMETHOD PushMark();
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);
NS_IMETHOD OpenMap(const nsIParserNode& aNode);
NS_IMETHOD CloseMap(const nsIParserNode& aNode);
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
protected:
void StartLayout();
void ReflowNewContent();
//----------------------------------------------------------------------
// Leaf tag handler routines that translate a leaf tag into a
// content object, processing all of the tag attributes.
nsresult ProcessAREATag(const nsIParserNode& aNode);
nsresult ProcessBASETag(const nsIParserNode& aNode);
nsresult ProcessMETATag(const nsIParserNode& aNode);
nsresult ProcessSTYLETag(const nsIParserNode& aNode);
nsresult ProcessSCRIPTTag(const nsIParserNode& aNode);
nsresult ProcessLINKTag(const nsIParserNode& aNode);
nsresult ProcessBRTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessEMBEDTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessFrameTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessHRTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessINPUTTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessIMGTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessSPACERTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessCOLTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessTEXTAREATag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessWBRTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
//----------------------------------------------------------------------
nsresult ProcessOpenSELECTTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessCloseSELECTTag(const nsIParserNode& aNode);
nsresult ProcessOpenOPTIONTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessCloseOPTIONTag(const nsIParserNode& aNode);
nsresult ProcessOPTIONTagContent(const nsIParserNode& aNode);
nsresult ProcessIFRAMETag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
nsresult ProcessFRAMESETTag(nsIHTMLContent** aInstancePtrResult,
const nsIParserNode& aNode);
//----------------------------------------------------------------------
PRBool FlushText();
nsresult AddText(const nsString& aText, nsIHTMLContent** aContent);
void AppendToCorrectParent(nsHTMLTag aParentTag,
nsIHTMLContent* aParent,
nsHTMLTag aChildTag,
nsIHTMLContent* aChild,
PRBool aAllowReflow);
void GetAttributeValueAt(const nsIParserNode& aNode,
PRInt32 aIndex,
nsString& aResult);
PRBool FindAttribute(const nsIParserNode& aNode,
const nsString& aKeyName,
nsString& aResult);
nsresult AddAttributes(const nsIParserNode& aNode,
nsIHTMLContent* aInstancePtrResult);
void AddBaseTagInfo(nsIHTMLContent* aContent);
nsIHTMLContent* GetBodyOrFrameset() { if (mBody) return mBody; else return mFrameset; }
nsresult LoadStyleSheet(nsIURL* aURL,
nsIUnicharInputStream* aUIN,
PRBool aInline);
void ScrollToRef();
nsIDocument* mDocument;
nsIURL* mDocumentURL;
eHTMLTags mNodeStack[100];/* XXX */
nsIHTMLContent* mContainerStack[100];/* XXX */
PRInt32 mStackPos;
nsString* mTitle;
nsString mBaseHREF;
nsString mBaseTarget;
nsIStyleSheet* mStyleSheet;
nsIFormManager* mCurrentForm;
nsIImageMap* mCurrentMap;
nsIHTMLContent* mCurrentSelect;
nsIHTMLContent* mCurrentOption;
nsIDOMText* mCurrentText;
nsIHTMLContent* mRoot;
nsIHTMLContent* mBody;
nsIHTMLContent* mFrameset;
nsIHTMLContent* mHead;
PRTime mLastUpdateTime;
PRTime mUpdateDelta;
PRBool mLayoutStarted;
PRInt32 mInMonolithicContainer;
nsIWebShell* mWebShell;
nsString* mRef;
nsScrollPreference mOriginalScrollPreference;
PRBool mNotAtRef;
nsIHTMLContent* mRefContent;
// XXX The parser needs to keep track of body tags and frameset tags
// and tell the content sink if they are to be ignored. For example, in nav4
//