You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
9.9 KiB
392 lines
9.9 KiB
/**
|
|
* This file is part of the DOM implementation for KDE.
|
|
*
|
|
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
|
|
* (C) 2002-2003 Dirk Mueller (mueller@kde.org)
|
|
* Copyright (C) 2002 Apple Computer, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
#include "dom/css_rule.h"
|
|
#include "dom/css_stylesheet.h"
|
|
#include "dom/dom_exception.h"
|
|
#include "dom/dom_string.h"
|
|
|
|
#include "css/css_stylesheetimpl.h"
|
|
#include "css/css_valueimpl.h"
|
|
#include "css/cssparser.h"
|
|
#include "css/css_ruleimpl.h"
|
|
|
|
#include "misc/loader.h"
|
|
#include "misc/htmltags.h"
|
|
#include "misc/htmlattrs.h"
|
|
#include "xml/dom_docimpl.h"
|
|
|
|
using namespace DOM;
|
|
|
|
#include <kdebug.h>
|
|
|
|
CSSStyleSheetImpl *CSSRuleImpl::parentStyleSheet() const
|
|
{
|
|
return ( m_parent && m_parent->isCSSStyleSheet() ) ?
|
|
static_cast<CSSStyleSheetImpl *>(m_parent) : 0;
|
|
}
|
|
|
|
CSSRuleImpl *CSSRuleImpl::parentRule() const
|
|
{
|
|
return ( m_parent && m_parent->isRule() ) ?
|
|
static_cast<CSSRuleImpl *>(m_parent) : 0;
|
|
}
|
|
|
|
DOM::DOMString CSSRuleImpl::cssText() const
|
|
{
|
|
// ###
|
|
return DOMString();
|
|
}
|
|
|
|
void CSSRuleImpl::setCssText(DOM::DOMString /*str*/)
|
|
{
|
|
// ###
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CSSFontFaceRuleImpl::CSSFontFaceRuleImpl(StyleBaseImpl *parent)
|
|
: CSSRuleImpl(parent)
|
|
{
|
|
m_type = CSSRule::FONT_FACE_RULE;
|
|
m_style = 0;
|
|
}
|
|
|
|
CSSFontFaceRuleImpl::~CSSFontFaceRuleImpl()
|
|
{
|
|
if(m_style) m_style->deref();
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl *parent,
|
|
const DOM::DOMString &href,
|
|
MediaListImpl *media )
|
|
: CSSRuleImpl(parent)
|
|
{
|
|
m_type = CSSRule::IMPORT_RULE;
|
|
|
|
m_lstMedia = media;
|
|
if ( !m_lstMedia )
|
|
m_lstMedia = new MediaListImpl( this, DOMString() );
|
|
m_lstMedia->setParent( this );
|
|
m_lstMedia->ref();
|
|
|
|
m_strHref = href;
|
|
m_styleSheet = 0;
|
|
|
|
m_cachedSheet = 0;
|
|
|
|
init();
|
|
}
|
|
CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl *parent,
|
|
const DOM::DOMString &href,
|
|
const DOM::DOMString &media )
|
|
: CSSRuleImpl(parent)
|
|
{
|
|
m_type = CSSRule::IMPORT_RULE;
|
|
|
|
m_lstMedia = new MediaListImpl( this, media );
|
|
m_lstMedia->ref();
|
|
|
|
m_strHref = href;
|
|
m_styleSheet = 0;
|
|
|
|
m_cachedSheet = 0;
|
|
|
|
init();
|
|
}
|
|
|
|
CSSImportRuleImpl::~CSSImportRuleImpl()
|
|
{
|
|
if( m_lstMedia ) {
|
|
m_lstMedia->setParent( 0 );
|
|
m_lstMedia->deref();
|
|
}
|
|
if(m_styleSheet) {
|
|
m_styleSheet->setParent(0);
|
|
m_styleSheet->deref();
|
|
}
|
|
|
|
if(m_cachedSheet) m_cachedSheet->deref(this);
|
|
}
|
|
|
|
void CSSImportRuleImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheet, const DOM::DOMString &charset)
|
|
{
|
|
if ( m_styleSheet ) {
|
|
m_styleSheet->setParent(0);
|
|
m_styleSheet->deref();
|
|
}
|
|
m_styleSheet = new CSSStyleSheetImpl(this, url);
|
|
m_styleSheet->setCharset(charset);
|
|
m_styleSheet->ref();
|
|
|
|
CSSStyleSheetImpl *parent = parentStyleSheet();
|
|
m_styleSheet->parseString( sheet, parent ? parent->useStrictParsing() : true );
|
|
m_loading = false;
|
|
m_done = true;
|
|
|
|
checkLoaded();
|
|
}
|
|
|
|
void CSSImportRuleImpl::error(int /*err*/, const QString &/*text*/)
|
|
{
|
|
if ( m_styleSheet ) {
|
|
m_styleSheet->setParent(0);
|
|
m_styleSheet->deref();
|
|
}
|
|
m_styleSheet = 0;
|
|
|
|
m_loading = false;
|
|
m_done = true;
|
|
|
|
checkLoaded();
|
|
}
|
|
|
|
bool CSSImportRuleImpl::isLoading()
|
|
{
|
|
return ( m_loading || (m_styleSheet && m_styleSheet->isLoading()) );
|
|
}
|
|
|
|
void CSSImportRuleImpl::init()
|
|
{
|
|
m_loading = 0;
|
|
m_done = false;
|
|
khtml::DocLoader *docLoader = 0;
|
|
StyleBaseImpl *root = this;
|
|
StyleBaseImpl *parent;
|
|
while ( ( parent = root->parent()) )
|
|
root = parent;
|
|
if (root->isCSSStyleSheet())
|
|
docLoader = static_cast<CSSStyleSheetImpl*>(root)->docLoader();
|
|
|
|
DOMString absHref = m_strHref;
|
|
CSSStyleSheetImpl *parentSheet = parentStyleSheet();
|
|
if (!parentSheet->href().isNull()) {
|
|
// use parent styleheet's URL as the base URL
|
|
absHref = KURL(KURL( parentSheet->href().string() ),m_strHref.string()).url();
|
|
}
|
|
/*
|
|
else {
|
|
// use documents's URL as the base URL
|
|
DocumentImpl *doc = static_cast<CSSStyleSheetImpl*>(root)->doc();
|
|
absHref = KURL(doc->URL(),m_strHref.string()).url();
|
|
}
|
|
*/
|
|
// Check for a cycle in our import chain. If we encounter a stylesheet
|
|
// in our parent chain with the same URL, then just bail.
|
|
for ( parent = static_cast<StyleBaseImpl*>( this )->parent();
|
|
parent;
|
|
parent = parent->parent() )
|
|
if ( absHref == parent->baseURL().url() )
|
|
return;
|
|
|
|
m_cachedSheet = docLoader->requestStyleSheet(absHref, parentStyleSheet()->charset().string());
|
|
|
|
if (m_cachedSheet)
|
|
{
|
|
m_cachedSheet->ref(this);
|
|
|
|
// If the imported sheet is in the cache, then setStyleSheet gets called,
|
|
// and the sheet even gets parsed (via parseString). In this case we have
|
|
// loaded (even if our subresources haven't), so if we have stylesheet after
|
|
// checking the cache, then we've clearly loaded. -dwh
|
|
// This can also happen when error() is called from within ref(). In either case,
|
|
// m_done is set to true.
|
|
if (!m_done)
|
|
m_loading = true;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl *parent, MediaListImpl *mediaList, CSSRuleListImpl *ruleList )
|
|
: CSSRuleImpl( parent )
|
|
{
|
|
m_type = CSSRule::MEDIA_RULE;
|
|
m_lstMedia = mediaList;
|
|
m_lstMedia->ref();
|
|
m_lstCSSRules = ruleList;
|
|
m_lstCSSRules->ref();
|
|
}
|
|
|
|
CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent)
|
|
: CSSRuleImpl( parent )
|
|
{
|
|
m_type = CSSRule::MEDIA_RULE;
|
|
m_lstMedia = 0;
|
|
m_lstCSSRules = new CSSRuleListImpl();
|
|
m_lstCSSRules->ref();
|
|
}
|
|
|
|
CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl *parent, const DOM::DOMString &media )
|
|
: CSSRuleImpl( parent )
|
|
{
|
|
m_type = CSSRule::MEDIA_RULE;
|
|
m_lstMedia = new MediaListImpl( this, media );
|
|
m_lstMedia->ref();
|
|
m_lstCSSRules = new CSSRuleListImpl();
|
|
m_lstCSSRules->ref();
|
|
}
|
|
|
|
CSSMediaRuleImpl::~CSSMediaRuleImpl()
|
|
{
|
|
if( m_lstMedia ) {
|
|
m_lstMedia->setParent( 0 );
|
|
m_lstMedia->deref();
|
|
}
|
|
for ( unsigned int i = 0; i < m_lstCSSRules->length(); ++i )
|
|
m_lstCSSRules->item( i )->setParent( 0 );
|
|
m_lstCSSRules->deref();
|
|
}
|
|
|
|
unsigned long CSSMediaRuleImpl::append( CSSRuleImpl *rule )
|
|
{
|
|
return rule ? m_lstCSSRules->insertRule( rule, m_lstCSSRules->length() ) : 0;
|
|
}
|
|
|
|
unsigned long CSSMediaRuleImpl::insertRule( const DOMString &rule,
|
|
unsigned long index )
|
|
{
|
|
CSSParser p( strictParsing );
|
|
CSSRuleImpl *newRule = p.parseRule( parentStyleSheet(), rule );
|
|
|
|
return newRule ? m_lstCSSRules->insertRule( newRule, index ) : 0;
|
|
}
|
|
|
|
CSSRuleListImpl::~CSSRuleListImpl()
|
|
{
|
|
CSSRuleImpl* rule;
|
|
while ( !m_lstCSSRules.isEmpty() && ( rule = m_lstCSSRules.take( 0 ) ) )
|
|
rule->deref();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
CSSPageRuleImpl::CSSPageRuleImpl(StyleBaseImpl *parent)
|
|
: CSSRuleImpl(parent)
|
|
{
|
|
m_type = CSSRule::PAGE_RULE;
|
|
m_style = 0;
|
|
}
|
|
|
|
CSSPageRuleImpl::~CSSPageRuleImpl()
|
|
{
|
|
if(m_style) m_style->deref();
|
|
}
|
|
|
|
DOM::DOMString CSSPageRuleImpl::selectorText() const
|
|
{
|
|
// ###
|
|
return DOMString();
|
|
}
|
|
|
|
void CSSPageRuleImpl::setSelectorText(DOM::DOMString /*str*/)
|
|
{
|
|
// ###
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
CSSStyleRuleImpl::CSSStyleRuleImpl(StyleBaseImpl *parent)
|
|
: CSSRuleImpl(parent)
|
|
{
|
|
m_type = CSSRule::STYLE_RULE;
|
|
m_style = 0;
|
|
m_selector = 0;
|
|
}
|
|
|
|
CSSStyleRuleImpl::~CSSStyleRuleImpl()
|
|
{
|
|
if(m_style) {
|
|
m_style->setParent( 0 );
|
|
m_style->deref();
|
|
}
|
|
delete m_selector;
|
|
}
|
|
|
|
DOM::DOMString CSSStyleRuleImpl::selectorText() const
|
|
{
|
|
if (m_selector) {
|
|
DOMString str;
|
|
for (CSSSelector *s = m_selector->first(); s; s = m_selector->next()) {
|
|
if (s != m_selector->getFirst())
|
|
str += ", ";
|
|
str += s->selectorText();
|
|
}
|
|
return str;
|
|
}
|
|
return DOMString();
|
|
}
|
|
|
|
void CSSStyleRuleImpl::setSelectorText(DOM::DOMString /*str*/)
|
|
{
|
|
// ###
|
|
}
|
|
|
|
bool CSSStyleRuleImpl::parseString( const DOMString &/*string*/, bool )
|
|
{
|
|
// ###
|
|
return false;
|
|
}
|
|
|
|
void CSSStyleRuleImpl::setDeclaration( CSSStyleDeclarationImpl *style)
|
|
{
|
|
if ( m_style != style ) {
|
|
if(m_style) m_style->deref();
|
|
m_style = style;
|
|
if(m_style) m_style->ref();
|
|
}
|
|
}
|
|
|
|
void CSSStyleRuleImpl::setNonCSSHints()
|
|
{
|
|
CSSSelector *s = m_selector->first();
|
|
while ( s ) {
|
|
s->nonCSSHint = true;
|
|
s = m_selector->next();
|
|
}
|
|
}
|
|
|
|
void CSSRuleListImpl::deleteRule ( unsigned long index )
|
|
{
|
|
CSSRuleImpl *rule = m_lstCSSRules.take( index );
|
|
if( rule )
|
|
rule->deref();
|
|
else {
|
|
// ### Throw INDEX_SIZE_ERR exception here (TODO)
|
|
}
|
|
}
|
|
|
|
unsigned long CSSRuleListImpl::insertRule( CSSRuleImpl *rule,
|
|
unsigned long index )
|
|
{
|
|
if( rule && m_lstCSSRules.insert( index, rule ) )
|
|
{
|
|
rule->ref();
|
|
return index;
|
|
}
|
|
|
|
// ### Should throw INDEX_SIZE_ERR exception instead! (TODO)
|
|
return 0;
|
|
}
|
|
|