2 * This file is part of the DOM implementation for KDE.
4 * Copyright 1999-2003 Lars Knoll (knoll@kde.org)
5 * Copyright 2002-2003 Dirk Mueller (mueller@kde.org)
6 * Copyright 2002-2008 Apple Computer, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include "css_ruleimpl.h"
25 #include "css_stylesheetimpl.h"
26 #include "css_valueimpl.h"
27 #include "cssparser.h"
29 #include <dom/css_rule.h>
30 #include <dom/css_stylesheet.h>
31 #include <dom/dom_exception.h>
32 #include <dom/dom_string.h>
34 #include <misc/loader.h>
35 #include <misc/htmltags.h>
36 #include <misc/htmlattrs.h>
37 #include <xml/dom_docimpl.h>
43 CSSStyleSheetImpl
*CSSRuleImpl::parentStyleSheet() const
45 return ( m_parent
&& m_parent
->isCSSStyleSheet() ) ?
46 static_cast<CSSStyleSheetImpl
*>(m_parent
) : 0;
49 CSSRuleImpl
*CSSRuleImpl::parentRule() const
51 return ( m_parent
&& m_parent
->isRule() ) ?
52 static_cast<CSSRuleImpl
*>(m_parent
) : 0;
55 DOM::DOMString
CSSRuleImpl::cssText() const
61 void CSSRuleImpl::setCssText(DOM::DOMString
/*str*/)
66 // ---------------------------------------------------------------------------
68 CSSFontFaceRuleImpl::CSSFontFaceRuleImpl(StyleBaseImpl
*parent
)
71 m_type
= CSSRule::FONT_FACE_RULE
;
75 CSSFontFaceRuleImpl::~CSSFontFaceRuleImpl()
77 if(m_style
) m_style
->deref();
80 // --------------------------------------------------------------------------
82 CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl
*parent
,
83 const DOM::DOMString
&href
,
84 MediaListImpl
*media
)
87 m_type
= CSSRule::IMPORT_RULE
;
91 m_lstMedia
= new MediaListImpl( this, DOMString() );
92 m_lstMedia
->setParent( this );
102 CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl
*parent
,
103 const DOM::DOMString
&href
,
104 const DOM::DOMString
&media
)
105 : CSSRuleImpl(parent
)
107 m_type
= CSSRule::IMPORT_RULE
;
109 m_lstMedia
= new MediaListImpl( this, media
);
120 CSSImportRuleImpl::~CSSImportRuleImpl()
123 m_lstMedia
->setParent( 0 );
127 m_styleSheet
->setParent(0);
128 m_styleSheet
->deref();
131 if(m_cachedSheet
) m_cachedSheet
->deref(this);
134 void CSSImportRuleImpl::checkLoaded() const
138 CSSRuleImpl::checkLoaded();
141 void CSSImportRuleImpl::setStyleSheet(const DOM::DOMString
&url
, const DOM::DOMString
&sheetStr
, const DOM::DOMString
&charset
, const DOM::DOMString
&mimetype
)
143 if ( m_styleSheet
) {
144 m_styleSheet
->setParent(0);
145 m_styleSheet
->deref();
147 m_styleSheet
= new CSSStyleSheetImpl(this, url
);
148 m_styleSheet
->setCharset(charset
);
151 CSSStyleSheetImpl
*parent
= parentStyleSheet();
152 bool strict
= parent
? parent
->useStrictParsing() : true;
153 DOMString sheet
= sheetStr
;
154 if (strict
&& !khtml::isAcceptableCSSMimetype(mimetype
))
156 m_styleSheet
->parseString( sheet
, strict
);
163 void CSSImportRuleImpl::error(int /*err*/, const QString
&/*text*/)
165 if ( m_styleSheet
) {
166 m_styleSheet
->setParent(0);
167 m_styleSheet
->deref();
177 bool CSSImportRuleImpl::isLoading() const
179 return ( m_loading
|| (m_styleSheet
&& m_styleSheet
->isLoading()) );
182 void CSSImportRuleImpl::init()
186 khtml::DocLoader
*docLoader
= 0;
187 StyleBaseImpl
*root
= this;
188 StyleBaseImpl
*parent
;
189 while ( ( parent
= root
->parent()) )
191 if (root
->isCSSStyleSheet())
192 docLoader
= static_cast<CSSStyleSheetImpl
*>(root
)->docLoader();
194 DOMString absHref
= m_strHref
;
195 CSSStyleSheetImpl
*parentSheet
= parentStyleSheet();
196 if (!parentSheet
->href().isNull()) {
197 // use parent styleheet's URL as the base URL
198 absHref
= KUrl(KUrl( parentSheet
->href().string() ),m_strHref
.string()).url();
202 // use documents's URL as the base URL
203 DocumentImpl *doc = static_cast<CSSStyleSheetImpl*>(root)->doc();
204 absHref = KUrl(doc->URL(),m_strHref.string()).url();
207 // Check for a cycle in our import chain. If we encounter a stylesheet
208 // in our parent chain with the same URL, then just bail.
209 for ( parent
= static_cast<StyleBaseImpl
*>( this )->parent();
211 parent
= parent
->parent() )
212 if ( absHref
== parent
->baseURL().url() )
215 m_cachedSheet
= docLoader
->requestStyleSheet(absHref
, parentStyleSheet()->charset().string());
219 // if the import rule is issued dynamically, the sheet may have already been
220 // removed from the pending sheet count, so let the doc know
221 // the sheet being imported is pending.
225 m_cachedSheet
->ref(this);
229 DOMString
CSSImportRuleImpl::cssText() const
231 DOMString result
= "@import url(\"";
237 result
+= m_lstMedia
->mediaText();
244 // --------------------------------------------------------------------------
245 CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl
*parent
, MediaListImpl
*mediaList
, CSSRuleListImpl
*ruleList
)
246 : CSSRuleImpl( parent
)
248 m_type
= CSSRule::MEDIA_RULE
;
249 m_lstMedia
= mediaList
;
252 m_lstCSSRules
= ruleList
;
253 m_lstCSSRules
->ref();
256 CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl
*parent
)
257 : CSSRuleImpl( parent
)
259 m_type
= CSSRule::MEDIA_RULE
;
261 m_lstCSSRules
= new CSSRuleListImpl();
262 m_lstCSSRules
->ref();
265 CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl
*parent
, const DOM::DOMString
&media
)
266 : CSSRuleImpl( parent
)
268 m_type
= CSSRule::MEDIA_RULE
;
269 m_lstMedia
= new MediaListImpl( this, media
);
271 m_lstCSSRules
= new CSSRuleListImpl();
272 m_lstCSSRules
->ref();
275 CSSMediaRuleImpl::~CSSMediaRuleImpl()
278 m_lstMedia
->setParent( 0 );
281 for ( unsigned int i
= 0; i
< m_lstCSSRules
->length(); ++i
)
282 m_lstCSSRules
->item( i
)->setParent( 0 );
283 m_lstCSSRules
->deref();
286 unsigned long CSSMediaRuleImpl::append( CSSRuleImpl
*rule
)
288 return rule
? m_lstCSSRules
->insertRule( rule
, m_lstCSSRules
->length() ) : 0;
291 unsigned long CSSMediaRuleImpl::insertRule( const DOMString
&rule
,
292 unsigned long index
)
294 CSSParser
p( strictParsing
);
295 CSSRuleImpl
*newRule
= p
.parseRule( parentStyleSheet(), rule
);
297 return newRule
? m_lstCSSRules
->insertRule( newRule
, index
) : 0;
300 DOM::DOMString
CSSMediaRuleImpl::cssText() const
302 DOMString
result("@media ");
304 result
+= m_lstMedia
->mediaText();
310 unsigned len
= m_lstCSSRules
->length();
311 for (unsigned i
= 0; i
< len
; i
++) {
313 result
+= m_lstCSSRules
->item(i
)->cssText();
322 // ---------------------------------------------------------------------------
324 CSSPageRuleImpl::CSSPageRuleImpl(StyleBaseImpl
*parent
)
325 : CSSRuleImpl(parent
)
327 m_type
= CSSRule::PAGE_RULE
;
331 CSSPageRuleImpl::~CSSPageRuleImpl()
333 if(m_style
) m_style
->deref();
336 DOM::DOMString
CSSPageRuleImpl::selectorText() const
342 void CSSPageRuleImpl::setSelectorText(DOM::DOMString
/*str*/)
347 // --------------------------------------------------------------------------
349 CSSStyleRuleImpl::CSSStyleRuleImpl(StyleBaseImpl
*parent
)
350 : CSSRuleImpl(parent
)
352 m_type
= CSSRule::STYLE_RULE
;
357 CSSStyleRuleImpl::~CSSStyleRuleImpl()
360 m_style
->setParent( 0 );
363 qDeleteAll(*m_selector
);
367 DOMString
CSSStyleRuleImpl::cssText() const
369 DOMString
result(selectorText());
372 result
+= m_style
->cssText();
378 DOM::DOMString
CSSStyleRuleImpl::selectorText() const
382 foreach (CSSSelector
*s
, *m_selector
) {
383 if (s
!= m_selector
->at(0))
385 str
+= s
->selectorText();
392 void CSSStyleRuleImpl::setSelectorText(DOM::DOMString
/*str*/)
397 bool CSSStyleRuleImpl::parseString( const DOMString
&/*string*/, bool )
403 void CSSStyleRuleImpl::setDeclaration( CSSStyleDeclarationImpl
*style
)
405 if ( m_style
!= style
) {
406 if(m_style
) m_style
->deref();
408 if(m_style
) m_style
->ref();
412 // --------------------------------------------------------------------
414 CSSRuleListImpl::CSSRuleListImpl(StyleListImpl
* const list
, bool omitCharsetRules
)
417 if (list
&& omitCharsetRules
) {
419 unsigned len
= list
->length();
420 for (unsigned i
= 0; i
< len
; ++i
) {
421 StyleBaseImpl
* rule
= list
->item(i
);
422 if (rule
->isRule() && !rule
->isCharsetRule())
423 append(static_cast<CSSRuleImpl
*>(rule
));
430 CSSRuleListImpl::~CSSRuleListImpl()
433 while ( !m_lstCSSRules
.isEmpty() && ( rule
= m_lstCSSRules
.takeFirst() ) )
439 unsigned long CSSRuleListImpl::length() const
441 return m_list
? m_list
->length() : m_lstCSSRules
.count();
444 CSSRuleImpl
* CSSRuleListImpl::item(unsigned long index
)
447 StyleBaseImpl
* rule
= m_list
->item(index
);
448 assert(!rule
|| rule
->isRule());
449 return static_cast<CSSRuleImpl
*>(rule
);
451 return m_lstCSSRules
.at(index
);
454 void CSSRuleListImpl::deleteRule ( unsigned long index
)
457 if (index
+1 > (unsigned) m_lstCSSRules
.size()) {
459 // ### Throw INDEX_SIZE_ERR exception here (TODO)
461 CSSRuleImpl
*rule
= m_lstCSSRules
.takeAt( index
);
465 void CSSRuleListImpl::append(CSSRuleImpl
* rule
)
469 m_lstCSSRules
.append( rule
);
472 unsigned long CSSRuleListImpl::insertRule( CSSRuleImpl
*rule
,
473 unsigned long index
)
476 if (index
> (unsigned) m_lstCSSRules
.size()) {
478 // ### Throw INDEX_SIZE_ERR exception here (TODO)
483 m_lstCSSRules
.insert( index
, rule
);