fix logic
[personal-kdelibs.git] / khtml / css / css_ruleimpl.cpp
blob8f4a225c19d3e9458c04a4ba8202a69faef9f754
1 /**
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>
39 using namespace DOM;
41 #include <kdebug.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
57 // ###
58 return DOMString();
61 void CSSRuleImpl::setCssText(DOM::DOMString /*str*/)
63 // ###
66 // ---------------------------------------------------------------------------
68 CSSFontFaceRuleImpl::CSSFontFaceRuleImpl(StyleBaseImpl *parent)
69 : CSSRuleImpl(parent)
71 m_type = CSSRule::FONT_FACE_RULE;
72 m_style = 0;
75 CSSFontFaceRuleImpl::~CSSFontFaceRuleImpl()
77 if(m_style) m_style->deref();
80 // --------------------------------------------------------------------------
82 CSSImportRuleImpl::CSSImportRuleImpl( StyleBaseImpl *parent,
83 const DOM::DOMString &href,
84 MediaListImpl *media )
85 : CSSRuleImpl(parent)
87 m_type = CSSRule::IMPORT_RULE;
89 m_lstMedia = media;
90 if ( !m_lstMedia )
91 m_lstMedia = new MediaListImpl( this, DOMString() );
92 m_lstMedia->setParent( this );
93 m_lstMedia->ref();
95 m_strHref = href;
96 m_styleSheet = 0;
98 m_cachedSheet = 0;
100 init();
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 );
110 m_lstMedia->ref();
112 m_strHref = href;
113 m_styleSheet = 0;
115 m_cachedSheet = 0;
117 init();
120 CSSImportRuleImpl::~CSSImportRuleImpl()
122 if( m_lstMedia ) {
123 m_lstMedia->setParent( 0 );
124 m_lstMedia->deref();
126 if(m_styleSheet) {
127 m_styleSheet->setParent(0);
128 m_styleSheet->deref();
131 if(m_cachedSheet) m_cachedSheet->deref(this);
134 void CSSImportRuleImpl::checkLoaded() const
136 if (isLoading())
137 return;
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);
149 m_styleSheet->ref();
151 CSSStyleSheetImpl *parent = parentStyleSheet();
152 bool strict = parent ? parent->useStrictParsing() : true;
153 DOMString sheet = sheetStr;
154 if (strict && !khtml::isAcceptableCSSMimetype(mimetype))
155 sheet = "";
156 m_styleSheet->parseString( sheet, strict );
157 m_loading = false;
158 m_done = true;
160 checkLoaded();
163 void CSSImportRuleImpl::error(int /*err*/, const QString &/*text*/)
165 if ( m_styleSheet ) {
166 m_styleSheet->setParent(0);
167 m_styleSheet->deref();
169 m_styleSheet = 0;
171 m_loading = false;
172 m_done = true;
174 checkLoaded();
177 bool CSSImportRuleImpl::isLoading() const
179 return ( m_loading || (m_styleSheet && m_styleSheet->isLoading()) );
182 void CSSImportRuleImpl::init()
184 m_loading = 0;
185 m_done = false;
186 khtml::DocLoader *docLoader = 0;
187 StyleBaseImpl *root = this;
188 StyleBaseImpl *parent;
189 while ( ( parent = root->parent()) )
190 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();
201 else {
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();
210 parent;
211 parent = parent->parent() )
212 if ( absHref == parent->baseURL().url() )
213 return;
215 m_cachedSheet = docLoader->requestStyleSheet(absHref, parentStyleSheet()->charset().string());
217 if (m_cachedSheet)
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.
222 checkPending();
224 m_loading = true;
225 m_cachedSheet->ref(this);
229 DOMString CSSImportRuleImpl::cssText() const
231 DOMString result = "@import url(\"";
232 result += m_strHref;
233 result += "\")";
235 if (m_lstMedia) {
236 result += " ";
237 result += m_lstMedia->mediaText();
239 result += ";";
241 return result;
244 // --------------------------------------------------------------------------
245 CSSMediaRuleImpl::CSSMediaRuleImpl( StyleBaseImpl *parent, MediaListImpl *mediaList, CSSRuleListImpl *ruleList )
246 : CSSRuleImpl( parent )
248 m_type = CSSRule::MEDIA_RULE;
249 m_lstMedia = mediaList;
250 if (m_lstMedia)
251 m_lstMedia->ref();
252 m_lstCSSRules = ruleList;
253 m_lstCSSRules->ref();
256 CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent)
257 : CSSRuleImpl( parent )
259 m_type = CSSRule::MEDIA_RULE;
260 m_lstMedia = 0;
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 );
270 m_lstMedia->ref();
271 m_lstCSSRules = new CSSRuleListImpl();
272 m_lstCSSRules->ref();
275 CSSMediaRuleImpl::~CSSMediaRuleImpl()
277 if( m_lstMedia ) {
278 m_lstMedia->setParent( 0 );
279 m_lstMedia->deref();
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 ");
303 if (m_lstMedia) {
304 result += m_lstMedia->mediaText();
305 result += " ";
307 result += "{ \n";
309 if (m_lstCSSRules) {
310 unsigned len = m_lstCSSRules->length();
311 for (unsigned i = 0; i < len; i++) {
312 result += " ";
313 result += m_lstCSSRules->item(i)->cssText();
314 result += "\n";
318 result += "}";
319 return result;
322 // ---------------------------------------------------------------------------
324 CSSPageRuleImpl::CSSPageRuleImpl(StyleBaseImpl *parent)
325 : CSSRuleImpl(parent)
327 m_type = CSSRule::PAGE_RULE;
328 m_style = 0;
331 CSSPageRuleImpl::~CSSPageRuleImpl()
333 if(m_style) m_style->deref();
336 DOM::DOMString CSSPageRuleImpl::selectorText() const
338 // ###
339 return DOMString();
342 void CSSPageRuleImpl::setSelectorText(DOM::DOMString /*str*/)
344 // ###
347 // --------------------------------------------------------------------------
349 CSSStyleRuleImpl::CSSStyleRuleImpl(StyleBaseImpl *parent)
350 : CSSRuleImpl(parent)
352 m_type = CSSRule::STYLE_RULE;
353 m_style = 0;
354 m_selector = 0;
357 CSSStyleRuleImpl::~CSSStyleRuleImpl()
359 if(m_style) {
360 m_style->setParent( 0 );
361 m_style->deref();
363 qDeleteAll(*m_selector);
364 delete m_selector;
367 DOMString CSSStyleRuleImpl::cssText() const
369 DOMString result(selectorText());
371 result += " { ";
372 result += m_style->cssText();
373 result += "}";
375 return result;
378 DOM::DOMString CSSStyleRuleImpl::selectorText() const
380 if (m_selector) {
381 DOMString str;
382 foreach (CSSSelector *s, *m_selector) {
383 if (s != m_selector->at(0))
384 str += ", ";
385 str += s->selectorText();
387 return str;
389 return DOMString();
392 void CSSStyleRuleImpl::setSelectorText(DOM::DOMString /*str*/)
394 // ###
397 bool CSSStyleRuleImpl::parseString( const DOMString &/*string*/, bool )
399 // ###
400 return false;
403 void CSSStyleRuleImpl::setDeclaration( CSSStyleDeclarationImpl *style)
405 if ( m_style != style ) {
406 if(m_style) m_style->deref();
407 m_style = style;
408 if(m_style) m_style->ref();
412 // --------------------------------------------------------------------
414 CSSRuleListImpl::CSSRuleListImpl(StyleListImpl* const list, bool omitCharsetRules)
416 m_list = list;
417 if (list && omitCharsetRules) {
418 m_list = 0;
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));
425 } else if (m_list) {
426 m_list->ref();
430 CSSRuleListImpl::~CSSRuleListImpl()
432 CSSRuleImpl* rule;
433 while ( !m_lstCSSRules.isEmpty() && ( rule = m_lstCSSRules.takeFirst() ) )
434 rule->deref();
435 if (m_list)
436 m_list->deref();
439 unsigned long CSSRuleListImpl::length() const
441 return m_list ? m_list->length() : m_lstCSSRules.count();
444 CSSRuleImpl* CSSRuleListImpl::item(unsigned long index)
446 if (m_list) {
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 )
456 assert(!m_list);
457 if (index+1 > (unsigned) m_lstCSSRules.size()) {
458 return;
459 // ### Throw INDEX_SIZE_ERR exception here (TODO)
461 CSSRuleImpl *rule = m_lstCSSRules.takeAt( index );
462 rule->deref();
465 void CSSRuleListImpl::append(CSSRuleImpl* rule)
467 assert(!m_list);
468 rule->ref();
469 m_lstCSSRules.append( rule );
472 unsigned long CSSRuleListImpl::insertRule( CSSRuleImpl *rule,
473 unsigned long index )
475 assert(!m_list);
476 if (index > (unsigned) m_lstCSSRules.size()) {
477 return 0;
478 // ### Throw INDEX_SIZE_ERR exception here (TODO)
481 if( rule )
483 m_lstCSSRules.insert( index, rule );
484 rule->ref();
485 return index;
488 return 0;