00001
00024
00025
00026 #include "dom/dom_string.h"
00027 #include "dom/dom_exception.h"
00028 #include "dom/css_stylesheet.h"
00029 #include "dom/css_rule.h"
00030
00031 #include "css/css_ruleimpl.h"
00032 #include "css/css_valueimpl.h"
00033 #include "css/cssparser.h"
00034 #include "css/css_stylesheetimpl.h"
00035
00036 #include "xml/dom_nodeimpl.h"
00037 #include "html/html_documentimpl.h"
00038 #include "misc/loader.h"
00039
00040 #include <kdebug.h>
00041
00042 using namespace DOM;
00043 using namespace khtml;
00044
00045
00046 StyleSheetImpl::StyleSheetImpl(StyleSheetImpl *parentSheet, DOMString href)
00047 : StyleListImpl(parentSheet)
00048 {
00049 m_disabled = false;
00050 m_media = 0;
00051 m_parentNode = 0;
00052 m_strHref = href;
00053 }
00054
00055
00056 StyleSheetImpl::StyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href)
00057 : StyleListImpl()
00058 {
00059 m_parentNode = parentNode;
00060 m_disabled = false;
00061 m_media = 0;
00062 m_strHref = href;
00063 }
00064
00065 StyleSheetImpl::StyleSheetImpl(StyleBaseImpl *owner, DOMString href)
00066 : StyleListImpl(owner)
00067 {
00068 m_disabled = false;
00069 m_media = 0;
00070 m_parentNode = 0;
00071 m_strHref = href;
00072 }
00073
00074 StyleSheetImpl::~StyleSheetImpl()
00075 {
00076 if(m_media) {
00077 m_media->setParent( 0 );
00078 m_media->deref();
00079 }
00080 }
00081
00082 StyleSheetImpl *StyleSheetImpl::parentStyleSheet() const
00083 {
00084 if( !m_parent ) return 0;
00085 if( m_parent->isStyleSheet() ) return static_cast<StyleSheetImpl *>(m_parent);
00086 return 0;
00087 }
00088
00089 void StyleSheetImpl::setMedia( MediaListImpl *media )
00090 {
00091 if( media )
00092 media->ref();
00093 if( m_media )
00094 m_media->deref();
00095 m_media = media;
00096 }
00097
00098 void StyleSheetImpl::setDisabled( bool disabled )
00099 {
00100 bool updateStyle = isCSSStyleSheet() && m_parentNode && disabled != m_disabled;
00101 m_disabled = disabled;
00102 if (updateStyle)
00103 m_parentNode->getDocument()->updateStyleSelector();
00104 }
00105
00106
00107
00108
00109 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSStyleSheetImpl *parentSheet, DOMString href)
00110 : StyleSheetImpl(parentSheet, href)
00111 {
00112 m_lstChildren = new QPtrList<StyleBaseImpl>;
00113 m_doc = 0;
00114 m_implicit = false;
00115 m_namespaces = 0;
00116 m_defaultNamespace = anyNamespace;
00117 }
00118
00119 CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href, bool _implicit)
00120 : StyleSheetImpl(parentNode, href)
00121 {
00122 m_lstChildren = new QPtrList<StyleBaseImpl>;
00123 m_doc = parentNode->getDocument();
00124 m_implicit = _implicit;
00125 m_namespaces = 0;
00126 m_defaultNamespace = anyNamespace;
00127 }
00128
00129 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, DOMString href)
00130 : StyleSheetImpl(ownerRule, href)
00131 {
00132 m_lstChildren = new QPtrList<StyleBaseImpl>;
00133 m_doc = 0;
00134 m_implicit = false;
00135 m_namespaces = 0;
00136 m_defaultNamespace = anyNamespace;
00137 }
00138
00139 CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, CSSStyleSheetImpl *orig)
00140 : StyleSheetImpl(parentNode, orig->m_strHref)
00141 {
00142 m_lstChildren = new QPtrList<StyleBaseImpl>;
00143 StyleBaseImpl *rule;
00144 for ( rule = orig->m_lstChildren->first(); rule != 0; rule = orig->m_lstChildren->next() )
00145 {
00146 m_lstChildren->append(rule);
00147 rule->setParent(this);
00148 }
00149 m_doc = parentNode->getDocument();
00150 m_implicit = false;
00151 m_namespaces = 0;
00152 m_defaultNamespace = anyNamespace;
00153 }
00154
00155 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, CSSStyleSheetImpl *orig)
00156 : StyleSheetImpl(ownerRule, orig->m_strHref)
00157 {
00158
00159 m_lstChildren = new QPtrList<StyleBaseImpl>;
00160 StyleBaseImpl *rule;
00161 for ( rule = orig->m_lstChildren->first(); rule != 0; rule = orig->m_lstChildren->next() )
00162 {
00163 m_lstChildren->append(rule);
00164 rule->setParent(this);
00165 }
00166 m_doc = 0;
00167 m_implicit = false;
00168 m_namespaces = 0;
00169 m_defaultNamespace = anyNamespace;
00170 }
00171
00172 CSSRuleImpl *CSSStyleSheetImpl::ownerRule() const
00173 {
00174 if( !m_parent ) return 0;
00175 if( m_parent->isRule() ) return static_cast<CSSRuleImpl *>(m_parent);
00176 return 0;
00177 }
00178
00179 unsigned long CSSStyleSheetImpl::insertRule( const DOMString &rule, unsigned long index, int &exceptioncode )
00180 {
00181 exceptioncode = 0;
00182 if(index > m_lstChildren->count()) {
00183 exceptioncode = DOMException::INDEX_SIZE_ERR;
00184 return 0;
00185 }
00186 CSSParser p( strictParsing );
00187 CSSRuleImpl *r = p.parseRule( this, rule );
00188
00189 if(!r) {
00190 exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
00191 return 0;
00192 }
00193
00194
00195
00196 m_lstChildren->insert(index, r);
00197 if (m_doc)
00198 m_doc->updateStyleSelector(true );
00199 return index;
00200 }
00201
00202 CSSRuleList CSSStyleSheetImpl::cssRules()
00203 {
00204 return this;
00205 }
00206
00207 void CSSStyleSheetImpl::deleteRule( unsigned long index, int &exceptioncode )
00208 {
00209 exceptioncode = 0;
00210 StyleBaseImpl *b = m_lstChildren->take(index);
00211 if(!b) {
00212 exceptioncode = DOMException::INDEX_SIZE_ERR;
00213 return;
00214 }
00215 b->deref();
00216 if (m_doc)
00217 m_doc->updateStyleSelector(true );
00218 }
00219
00220 void CSSStyleSheetImpl::addNamespace(CSSParser* p, const DOM::DOMString& prefix, const DOM::DOMString& uri)
00221 {
00222 int exceptioncode = 0;
00223 if (uri.isEmpty())
00224 return;
00225
00226 m_namespaces = new CSSNamespace(prefix, uri, m_namespaces);
00227
00228 if (prefix.isEmpty()) {
00229 Q_ASSERT(m_doc != 0);
00230
00231 m_defaultNamespace = m_doc->getId(NodeImpl::NamespaceId, uri.implementation(), false, false, &exceptioncode);
00232 }
00233 }
00234
00235 void CSSStyleSheetImpl::determineNamespace(Q_UINT32& id, const DOM::DOMString& prefix)
00236 {
00237
00238
00239 if (!m_namespaces)
00240 return;
00241
00242 if (prefix.isEmpty())
00243 id = makeId(emptyNamespace, localNamePart(id));
00244 else if (prefix == "*")
00245 id = makeId(anyNamespace, localNamePart(id));
00246 else {
00247 int exceptioncode = 0;
00248 CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix);
00249 if (ns) {
00250 Q_ASSERT(m_doc != 0);
00251
00252
00253 Q_UINT16 nsid = m_doc->getId(NodeImpl::NamespaceId, 0, 0, ns->uri().implementation(), false, false, &exceptioncode);
00254 id = makeId(nsid, localNamePart(id));
00255 }
00256 }
00257 }
00258
00259 bool CSSStyleSheetImpl::parseString(const DOMString &string, bool strict)
00260 {
00261 #ifdef CSS_STYLESHEET_DEBUG
00262 kdDebug( 6080 ) << "parsing sheet, len=" << string.length() << ", sheet is " << string.string() << endl;
00263 #endif
00264
00265 strictParsing = strict;
00266 CSSParser p( strict );
00267 p.parseSheet( this, string );
00268 return true;
00269 }
00270
00271 bool CSSStyleSheetImpl::isLoading() const
00272 {
00273 StyleBaseImpl *rule;
00274 for ( rule = m_lstChildren->first(); rule != 0; rule = m_lstChildren->next() )
00275 {
00276 if(rule->isImportRule())
00277 {
00278 CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(rule);
00279 #ifdef CSS_STYLESHEET_DEBUG
00280 kdDebug( 6080 ) << "found import" << endl;
00281 #endif
00282 if(import->isLoading())
00283 {
00284 #ifdef CSS_STYLESHEET_DEBUG
00285 kdDebug( 6080 ) << "--> not loaded" << endl;
00286 #endif
00287 return true;
00288 }
00289 }
00290 }
00291 return false;
00292 }
00293
00294 void CSSStyleSheetImpl::checkLoaded() const
00295 {
00296 if(isLoading()) return;
00297 if(m_parent) m_parent->checkLoaded();
00298 if(m_parentNode) m_parentNode->sheetLoaded();
00299 }
00300
00301 void CSSStyleSheetImpl::setNonCSSHints()
00302 {
00303 StyleBaseImpl *rule = m_lstChildren->first();
00304 while(rule) {
00305 if(rule->isStyleRule()) {
00306 static_cast<CSSStyleRuleImpl *>(rule)->setNonCSSHints();
00307 }
00308 rule = m_lstChildren->next();
00309 }
00310 }
00311
00312
00313
00314
00315
00316 StyleSheetListImpl::~StyleSheetListImpl()
00317 {
00318 for ( QPtrListIterator<StyleSheetImpl> it ( styleSheets ); it.current(); ++it )
00319 it.current()->deref();
00320 }
00321
00322 void StyleSheetListImpl::add( StyleSheetImpl* s )
00323 {
00324 if ( !styleSheets.containsRef( s ) ) {
00325 s->ref();
00326 styleSheets.append( s );
00327 }
00328 }
00329
00330 void StyleSheetListImpl::remove( StyleSheetImpl* s )
00331 {
00332 if ( styleSheets.removeRef( s ) )
00333 s->deref();
00334 }
00335
00336 unsigned long StyleSheetListImpl::length() const
00337 {
00338
00339 unsigned long l = 0;
00340 QPtrListIterator<StyleSheetImpl> it(styleSheets);
00341 for (; it.current(); ++it) {
00342 if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit())
00343 ++l;
00344 }
00345 return l;
00346 }
00347
00348 StyleSheetImpl *StyleSheetListImpl::item ( unsigned long index )
00349 {
00350 unsigned long l = 0;
00351 QPtrListIterator<StyleSheetImpl> it(styleSheets);
00352 for (; it.current(); ++it) {
00353 if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit()) {
00354 if (l == index)
00355 return it.current();
00356 ++l;
00357 }
00358 }
00359 return 0;
00360 }
00361
00362
00363
00364 MediaListImpl::MediaListImpl( CSSStyleSheetImpl *parentSheet,
00365 const DOMString &media )
00366 : StyleBaseImpl( parentSheet )
00367 {
00368 setMediaText( media );
00369 }
00370
00371 MediaListImpl::MediaListImpl( CSSRuleImpl *parentRule, const DOMString &media )
00372 : StyleBaseImpl(parentRule)
00373 {
00374 setMediaText( media );
00375 }
00376
00377 bool MediaListImpl::contains( const DOMString &medium ) const
00378 {
00379 return m_lstMedia.empty() || m_lstMedia.contains( medium ) ||
00380 m_lstMedia.contains( "all" );
00381 }
00382
00383 CSSStyleSheetImpl *MediaListImpl::parentStyleSheet() const
00384 {
00385 if( m_parent->isCSSStyleSheet() ) return static_cast<CSSStyleSheetImpl *>(m_parent);
00386 return 0;
00387 }
00388
00389 CSSRuleImpl *MediaListImpl::parentRule() const
00390 {
00391 if( m_parent->isRule() ) return static_cast<CSSRuleImpl *>(m_parent);
00392 return 0;
00393 }
00394
00395 void MediaListImpl::deleteMedium( const DOMString &oldMedium )
00396 {
00397 const QValueList<DOMString>::Iterator itEnd = m_lstMedia.end();
00398
00399 for ( QValueList<DOMString>::Iterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
00400 if( (*it) == oldMedium ) {
00401 m_lstMedia.remove( it );
00402 return;
00403 }
00404 }
00405 }
00406
00407 DOM::DOMString MediaListImpl::mediaText() const
00408 {
00409 DOMString text;
00410 const QValueList<DOMString>::ConstIterator itEnd = m_lstMedia.end();
00411
00412 for ( QValueList<DOMString>::ConstIterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
00413 text += *it;
00414 text += ", ";
00415 }
00416 return text;
00417 }
00418
00419 void MediaListImpl::setMediaText(const DOM::DOMString &value)
00420 {
00421 m_lstMedia.clear();
00422 const QString val = value.string();
00423 const QStringList list = QStringList::split( ',', val );
00424
00425 const QStringList::ConstIterator itEnd = list.end();
00426
00427 for ( QStringList::ConstIterator it = list.begin(); it != itEnd; ++it )
00428 {
00429 const DOMString medium = (*it).stripWhiteSpace();
00430 if( !medium.isEmpty() )
00431 m_lstMedia.append( medium );
00432 }
00433 }