/* -*- 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 "nsIHTMLCSSStyleSheet.h" #include "nsIArena.h" #include "nsCRT.h" #include "nsIAtom.h" #include "nsIURL.h" #include "nsISupportsArray.h" #include "nsHTMLAtoms.h" #include "nsIHTMLContent.h" #include "nsIStyleRule.h" #include "nsIFrame.h" #include "nsHTMLIIDs.h" #include "nsICSSStyleRule.h" #include "nsIStyleContext.h" #include "nsIPresContext.h" #include "nsIDocument.h" static NS_DEFINE_IID(kIHTMLCSSStyleSheetIID, NS_IHTML_CSS_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); static NS_DEFINE_IID(kICSSStyleRuleIID, NS_ICSS_STYLE_RULE_IID); static NS_DEFINE_IID(kIStyleRuleIID, NS_ISTYLE_RULE_IID); class HTMLCSSStyleSheetImpl : public nsIHTMLCSSStyleSheet { public: void* operator new(size_t size); void* operator new(size_t size, nsIArena* aArena); void operator delete(void* ptr); HTMLCSSStyleSheetImpl(); NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); NS_IMETHOD_(nsrefcnt) AddRef(); NS_IMETHOD_(nsrefcnt) Release(); // basic style sheet data NS_IMETHOD Init(nsIURL* aURL, nsIDocument* aDocument); NS_IMETHOD GetURL(nsIURL*& aURL) const; NS_IMETHOD GetTitle(nsString& aTitle) const; NS_IMETHOD GetType(nsString& aType) const; NS_IMETHOD GetMediumCount(PRInt32& aCount) const; NS_IMETHOD GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const; NS_IMETHOD GetEnabled(PRBool& aEnabled) const; NS_IMETHOD SetEnabled(PRBool aEnabled); // style sheet owner info NS_IMETHOD GetParentSheet(nsIStyleSheet*& aParent) const; // will be null NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const; NS_IMETHOD SetOwningDocument(nsIDocument* aDocument); virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, nsIContent* aContent, nsIStyleContext* aParentContext, nsISupportsArray* aResults); virtual PRInt32 RulesMatching(nsIPresContext* aPresContext, nsIContent* aParentContent, nsIAtom* aPseudoTag, nsIStyleContext* aParentContext, nsISupportsArray* aResults); // XXX style rule enumerations virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const; private: // These are not supported and are not implemented! HTMLCSSStyleSheetImpl(const HTMLCSSStyleSheetImpl& aCopy); HTMLCSSStyleSheetImpl& operator=(const HTMLCSSStyleSheetImpl& aCopy); protected: virtual ~HTMLCSSStyleSheetImpl(); protected: PRUint32 mInHeap : 1; PRUint32 mRefCnt : 31; nsIURL* mURL; nsIDocument* mDocument; }; void* HTMLCSSStyleSheetImpl::operator new(size_t size) { HTMLCSSStyleSheetImpl* rv = (HTMLCSSStyleSheetImpl*) ::operator new(size); #ifdef NS_DEBUG if (nsnull != rv) { nsCRT::memset(rv, 0xEE, size); } #endif rv->mInHeap = 1; return (void*) rv; } void* HTMLCSSStyleSheetImpl::operator new(size_t size, nsIArena* aArena) { HTMLCSSStyleSheetImpl* rv = (HTMLCSSStyleSheetImpl*) aArena->Alloc(PRInt32(size)); #ifdef NS_DEBUG if (nsnull != rv) { nsCRT::memset(rv, 0xEE, size); } #endif rv->mInHeap = 0; return (void*) rv; } void HTMLCSSStyleSheetImpl::operator delete(void* ptr) { HTMLCSSStyleSheetImpl* sheet = (HTMLCSSStyleSheetImpl*) ptr; if (nsnull != sheet) { if (sheet->mInHeap) { ::delete ptr; } } } HTMLCSSStyleSheetImpl::HTMLCSSStyleSheetImpl() : nsIHTMLCSSStyleSheet(), mURL(nsnull), mDocument(nsnull) { NS_INIT_REFCNT(); } HTMLCSSStyleSheetImpl::~HTMLCSSStyleSheetImpl() { NS_RELEASE(mURL); } NS_IMPL_ADDREF(HTMLCSSStyleSheetImpl) NS_IMPL_RELEASE(HTMLCSSStyleSheetImpl) nsresult HTMLCSSStyleSheetImpl::QueryInterface(const nsIID& aIID, void** aInstancePtrResult) { NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); if (nsnull == aInstancePtrResult) { return NS_ERROR_NULL_POINTER; } static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); if (aIID.Equals(kIHTMLCSSStyleSheetIID)) { *aInstancePtrResult = (void*) ((nsIHTMLCSSStyleSheet*)this); NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(kIStyleSheetIID)) { *aInstancePtrResult = (void*) ((nsIStyleSheet*)this); NS_ADDREF_THIS(); return NS_OK; } if (aIID.Equals(kISupportsIID)) { *aInstancePtrResult = (void*) ((nsISupports*)this); NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, nsIContent* aContent, nsIStyleContext* aParentContext, nsISupportsArray* aResults) { NS_PRECONDITION(nsnull != aPresContext, "null arg"); NS_PRECONDITION(nsnull != aContent, "null arg"); NS_PRECONDITION(nsnull != aResults, "null arg"); PRInt32 matchCount = 0; nsIHTMLContent* htmlContent; // just get the one and only style rule from the content's STYLE attribute if (NS_OK == aContent->QueryInterface(kIHTMLContentIID, (void**)&htmlContent)) { nsIStyleRule* rule = nsnull; if (NS_SUCCEEDED(htmlContent->GetInlineStyleRule(rule))) { if (nsnull != rule) { aResults->AppendElement(rule); matchCount++; nsICSSStyleRule* cssRule; if (NS_SUCCEEDED(rule->QueryInterface(kICSSStyleRuleIID, (void**)&cssRule))) { nsIStyleRule* important = cssRule->GetImportantRule(); if (nsnull != important) { aResults->AppendElement(important); matchCount++; NS_RELEASE(important); } NS_RELEASE(cssRule); } NS_RELEASE(rule); } } NS_RELEASE(htmlContent); } return matchCount; } PRInt32 HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext* aPresContext, nsIContent* aParentContent, nsIAtom* aPseudoTag, nsIStyleContext* aParentContext, nsISupportsArray* aResults) { // no pseudo frame style... return 0; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::Init(nsIURL* aURL, nsIDocument* aDocument) { NS_PRECONDITION(aURL && aDocument, "null ptr"); if (! aURL || ! aDocument) return NS_ERROR_NULL_POINTER; if (mURL || mDocument) return NS_ERROR_ALREADY_INITIALIZED; mDocument = aDocument; // not refcounted! mURL = aURL; NS_ADDREF(mURL); return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetURL(nsIURL*& aURL) const { NS_IF_ADDREF(mURL); aURL = mURL; return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetTitle(nsString& aTitle) const { aTitle.Truncate(); aTitle.Append("Internal HTML/CSS Style Sheet"); return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetType(nsString& aType) const { aType.Truncate(); aType.Append("text/html"); return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetMediumCount(PRInt32& aCount) const { aCount = 0; return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetMediumAt(PRInt32 aIndex, nsIAtom*& aMedium) const { aMedium = nsnull; return NS_ERROR_INVALID_ARG; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetEnabled(PRBool& aEnabled) const { aEnabled = PR_TRUE; return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::SetEnabled(PRBool aEnabled) { // these can't be disabled return NS_OK; } // style sheet owner info NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetParentSheet(nsIStyleSheet*& aParent) const { aParent = nsnull; return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::GetOwningDocument(nsIDocument*& aDocument) const { NS_IF_ADDREF(mDocument); aDocument = mDocument; return NS_OK; } NS_IMETHODIMP HTMLCSSStyleSheetImpl::SetOwningDocument(nsIDocument* aDocument) { mDocument = aDocument; return NS_OK; } void HTMLCSSStyleSheetImpl::List(FILE* out, PRInt32 aIndent) const { PRUnichar* buffer; // Indent for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out); fputs("HTML CSS Style Sheet: ", out); mURL->ToString(&buffer); fputs(buffer, out); fputs("\n", out); delete buffer; } // XXX For backwards compatibility and convenience NS_HTML nsresult NS_NewHTMLCSSStyleSheet(nsIHTMLCSSStyleSheet** aInstancePtrResult, nsIURL* aURL, nsIDocument* aDocument) { nsresult rv; nsIHTMLCSSStyleSheet* sheet; if (NS_FAILED(rv = NS_NewHTMLCSSStyleSheet(&sheet))) return rv; if (NS_FAILED(rv = sheet->Init(aURL, aDocument))) { NS_RELEASE(sheet); return rv; } *aInstancePtrResult = sheet; return NS_OK; } NS_HTML nsresult NS_NewHTMLCSSStyleSheet(nsIHTMLCSSStyleSheet** aInstancePtrResult) { if (aInstancePtrResult == nsnull) { return NS_ERROR_NULL_POINTER; } HTMLCSSStyleSheetImpl* it = new HTMLCSSStyleSheetImpl(); if (nsnull == it) { return NS_ERROR_OUT_OF_MEMORY; } NS_ADDREF(it); *aInstancePtrResult = it; return NS_OK; }