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 return index;
00198 }
00199
00200 CSSRuleList CSSStyleSheetImpl::cssRules()
00201 {
00202 return this;
00203 }
00204
00205 void CSSStyleSheetImpl::deleteRule( unsigned long index, int &exceptioncode )
00206 {
00207 exceptioncode = 0;
00208 StyleBaseImpl *b = m_lstChildren->take(index);
00209 if(!b) {
00210 exceptioncode = DOMException::INDEX_SIZE_ERR;
00211 return;
00212 }
00213 b->deref();
00214 }
00215
00216 void CSSStyleSheetImpl::addNamespace(CSSParser* p, const DOM::DOMString& prefix, const DOM::DOMString& uri)
00217 {
00218 int exceptioncode = 0;
00219 if (uri.isEmpty())
00220 return;
00221
00222 m_namespaces = new CSSNamespace(prefix, uri, m_namespaces);
00223
00224 if (prefix.isEmpty()) {
00225 Q_ASSERT(m_doc != 0);
00226
00227 m_defaultNamespace = m_doc->getId(NodeImpl::NamespaceId, uri.implementation(), false, false, &exceptioncode);
00228 }
00229 }
00230
00231 void CSSStyleSheetImpl::determineNamespace(Q_UINT32& id, const DOM::DOMString& prefix)
00232 {
00233
00234
00235 if (!m_namespaces)
00236 return;
00237
00238 if (prefix.isEmpty())
00239 id = makeId(emptyNamespace, localNamePart(id));
00240 else if (prefix == "*")
00241 id = makeId(anyNamespace, localNamePart(id));
00242 else {
00243 int exceptioncode = 0;
00244 CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix);
00245 if (ns) {
00246 Q_ASSERT(m_doc != 0);
00247
00248
00249 Q_UINT16 nsid = m_doc->getId(NodeImpl::NamespaceId, 0, 0, ns->uri().implementation(), false, false, &exceptioncode);
00250 id = makeId(nsid, localNamePart(id));
00251 }
00252 }
00253 }
00254
00255 bool CSSStyleSheetImpl::parseString(const DOMString &string, bool strict)
00256 {
00257 #ifdef CSS_STYLESHEET_DEBUG
00258 kdDebug( 6080 ) << "parsing sheet, len=" << string.length() << ", sheet is " << string.string() << endl;
00259 #endif
00260
00261 strictParsing = strict;
00262 CSSParser p( strict );
00263 p.parseSheet( this, string );
00264 return true;
00265 }
00266
00267 bool CSSStyleSheetImpl::isLoading() const
00268 {
00269 StyleBaseImpl *rule;
00270 for ( rule = m_lstChildren->first(); rule != 0; rule = m_lstChildren->next() )
00271 {
00272 if(rule->isImportRule())
00273 {
00274 CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(rule);
00275 #ifdef CSS_STYLESHEET_DEBUG
00276 kdDebug( 6080 ) << "found import" << endl;
00277 #endif
00278 if(import->isLoading())
00279 {
00280 #ifdef CSS_STYLESHEET_DEBUG
00281 kdDebug( 6080 ) << "--> not loaded" << endl;
00282 #endif
00283 return true;
00284 }
00285 }
00286 }
00287 return false;
00288 }
00289
00290 void CSSStyleSheetImpl::checkLoaded() const
00291 {
00292 if(isLoading()) return;
00293 if(m_parent) m_parent->checkLoaded();
00294 if(m_parentNode) m_parentNode->sheetLoaded();
00295 }
00296
00297 void CSSStyleSheetImpl::setNonCSSHints()
00298 {
00299 StyleBaseImpl *rule = m_lstChildren->first();
00300 while(rule) {
00301 if(rule->isStyleRule()) {
00302 static_cast<CSSStyleRuleImpl *>(rule)->setNonCSSHints();
00303 }
00304 rule = m_lstChildren->next();
00305 }
00306 }
00307
00308
00309
00310
00311
00312 StyleSheetListImpl::~StyleSheetListImpl()
00313 {
00314 for ( QPtrListIterator<StyleSheetImpl> it ( styleSheets ); it.current(); ++it )
00315 it.current()->deref();
00316 }
00317
00318 void StyleSheetListImpl::add( StyleSheetImpl* s )
00319 {
00320 if ( !styleSheets.containsRef( s ) ) {
00321 s->ref();
00322 styleSheets.append( s );
00323 }
00324 }
00325
00326 void StyleSheetListImpl::remove( StyleSheetImpl* s )
00327 {
00328 if ( styleSheets.removeRef( s ) )
00329 s->deref();
00330 }
00331
00332 unsigned long StyleSheetListImpl::length() const
00333 {
00334
00335 unsigned long l = 0;
00336 QPtrListIterator<StyleSheetImpl> it(styleSheets);
00337 for (; it.current(); ++it) {
00338 if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit())
00339 ++l;
00340 }
00341 return l;
00342 }
00343
00344 StyleSheetImpl *StyleSheetListImpl::item ( unsigned long index )
00345 {
00346 unsigned long l = 0;
00347 QPtrListIterator<StyleSheetImpl> it(styleSheets);
00348 for (; it.current(); ++it) {
00349 if (!it.current()->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl*>(it.current())->implicit()) {
00350 if (l == index)
00351 return it.current();
00352 ++l;
00353 }
00354 }
00355 return 0;
00356 }
00357
00358
00359
00360 MediaListImpl::MediaListImpl( CSSStyleSheetImpl *parentSheet,
00361 const DOMString &media )
00362 : StyleBaseImpl( parentSheet )
00363 {
00364 setMediaText( media );
00365 }
00366
00367 MediaListImpl::MediaListImpl( CSSRuleImpl *parentRule, const DOMString &media )
00368 : StyleBaseImpl(parentRule)
00369 {
00370 setMediaText( media );
00371 }
00372
00373 bool MediaListImpl::contains( const DOMString &medium ) const
00374 {
00375 return m_lstMedia.empty() || m_lstMedia.contains( medium ) ||
00376 m_lstMedia.contains( "all" );
00377 }
00378
00379 CSSStyleSheetImpl *MediaListImpl::parentStyleSheet() const
00380 {
00381 if( m_parent->isCSSStyleSheet() ) return static_cast<CSSStyleSheetImpl *>(m_parent);
00382 return 0;
00383 }
00384
00385 CSSRuleImpl *MediaListImpl::parentRule() const
00386 {
00387 if( m_parent->isRule() ) return static_cast<CSSRuleImpl *>(m_parent);
00388 return 0;
00389 }
00390
00391 void MediaListImpl::deleteMedium( const DOMString &oldMedium )
00392 {
00393 const QValueList<DOMString>::Iterator itEnd = m_lstMedia.end();
00394
00395 for ( QValueList<DOMString>::Iterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
00396 if( (*it) == oldMedium ) {
00397 m_lstMedia.remove( it );
00398 return;
00399 }
00400 }
00401 }
00402
00403 DOM::DOMString MediaListImpl::mediaText() const
00404 {
00405 DOMString text;
00406 const QValueList<DOMString>::ConstIterator itEnd = m_lstMedia.end();
00407
00408 for ( QValueList<DOMString>::ConstIterator it = m_lstMedia.begin(); it != itEnd; ++it ) {
00409 text += *it;
00410 text += ", ";
00411 }
00412 return text;
00413 }
00414
00415 void MediaListImpl::setMediaText(const DOM::DOMString &value)
00416 {
00417 m_lstMedia.clear();
00418 const QString val = value.string();
00419 const QStringList list = QStringList::split( ',', val );
00420
00421 const QStringList::ConstIterator itEnd = list.end();
00422
00423 for ( QStringList::ConstIterator it = list.begin(); it != itEnd; ++it )
00424 {
00425 const DOMString medium = (*it).stripWhiteSpace();
00426 if( !medium.isEmpty() )
00427 m_lstMedia.append( medium );
00428 }
00429 }