KHtml

css_stylesheetimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999-2003 Lars Knoll ([email protected])
5  * (C) 2004 Apple Computer, Inc.
6  * (C) 2008 Germain Garand <[email protected]>
7  *
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.
12  *
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.
17  *
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.
22  *
23  */
24 
25 //#define CSS_STYLESHEET_DEBUG
26 
27 #include "css_stylesheetimpl.h"
28 #include "css_ruleimpl.h"
29 #include "css_valueimpl.h"
30 #include "cssparser.h"
31 #include "css_mediaquery.h"
32 
33 #include <dom/dom_string.h>
34 #include <dom/dom_exception.h>
35 #include <dom/css_stylesheet.h>
36 #include <dom/css_rule.h>
37 #include <dom/dom_exception.h>
38 
39 #include <xml/dom_nodeimpl.h>
40 #include <html/html_documentimpl.h>
41 #include <misc/loader.h>
42 
43 #include "khtml_debug.h"
44 
45 using namespace DOM;
46 using namespace khtml;
47 // --------------------------------------------------------------------------------
48 
49 StyleSheetImpl::StyleSheetImpl(StyleSheetImpl *parentSheet, DOMString href)
50  : StyleListImpl(parentSheet)
51 {
52  m_disabled = false;
53  m_media = nullptr;
54  m_parentNode = nullptr;
55  m_strHref = href;
56 }
57 
58 StyleSheetImpl::StyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href)
59  : StyleListImpl()
60 {
61  m_parentNode = parentNode;
62  m_disabled = false;
63  m_media = nullptr;
64  m_strHref = href;
65 }
66 
67 StyleSheetImpl::StyleSheetImpl(StyleBaseImpl *owner, DOMString href)
68  : StyleListImpl(owner)
69 {
70  m_disabled = false;
71  m_media = nullptr;
72  m_parentNode = nullptr;
73  m_strHref = href;
74 }
75 
76 StyleSheetImpl::~StyleSheetImpl()
77 {
78  if (m_media) {
79  m_media->setParent(nullptr);
80  m_media->deref();
81  }
82 }
83 
84 StyleSheetImpl *StyleSheetImpl::parentStyleSheet() const
85 {
86  if (!m_parent) {
87  return nullptr;
88  }
89  if (m_parent->isStyleSheet()) {
90  return static_cast<StyleSheetImpl *>(m_parent);
91  }
92  if (m_parent->isRule()) {
93  return m_parent->stylesheet();
94  }
95  return nullptr;
96 }
97 
98 void StyleSheetImpl::setMedia(MediaListImpl *media)
99 {
100  if (media) {
101  media->ref();
102  }
103  if (m_media) {
104  m_media->setParent(nullptr);
105  m_media->deref();
106  }
107  m_media = media;
108  if (m_media) {
109  m_media->setParent(this);
110  }
111 }
112 
113 void StyleSheetImpl::setDisabled(bool disabled)
114 {
115  bool updateStyle = isCSSStyleSheet() && m_parentNode && disabled != m_disabled;
116  m_disabled = disabled;
117  if (updateStyle) {
118  m_parentNode->document()->updateStyleSelector();
119  }
120 }
121 
122 // -----------------------------------------------------------------------
123 
124 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSStyleSheetImpl *parentSheet, DOMString href)
125  : StyleSheetImpl(parentSheet, href)
126 {
127  m_lstChildren = new QList<StyleBaseImpl *>;
128  m_doc = parentSheet ? parentSheet->doc() : nullptr;
129  m_implicit = false;
130  m_namespaces = nullptr;
131  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
132  m_loadedHint = false;
133 }
134 
135 CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, DOMString href, bool _implicit)
136  : StyleSheetImpl(parentNode, href)
137 {
138  m_lstChildren = new QList<StyleBaseImpl *>;
139  m_doc = parentNode->document();
140  m_implicit = _implicit;
141  m_namespaces = nullptr;
142  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
143  m_loadedHint = false;
144 }
145 
146 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, DOMString href)
147  : StyleSheetImpl(ownerRule, href)
148 {
149  m_lstChildren = new QList<StyleBaseImpl *>;
150  m_doc = static_cast<CSSStyleSheetImpl *>(ownerRule->stylesheet())->doc();
151  m_implicit = false;
152  m_namespaces = nullptr;
153  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
154  m_loadedHint = false;
155 }
156 
157 CSSStyleSheetImpl::CSSStyleSheetImpl(DOM::NodeImpl *parentNode, CSSStyleSheetImpl *orig)
158  : StyleSheetImpl(parentNode, orig->m_strHref)
159 {
160  m_lstChildren = new QList<StyleBaseImpl *>;
161  StyleBaseImpl *rule;
162  QListIterator<StyleBaseImpl *> it(*orig->m_lstChildren);
163  while (it.hasNext()) {
164  rule = it.next();
165  m_lstChildren->append(rule);
166  rule->setParent(this);
167  }
168  m_doc = parentNode->document();
169  m_implicit = false;
170  m_namespaces = nullptr;
171  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
172  m_loadedHint = false;
173 
174  recomputeNamespaceInfo(); // as we cloned kids
175 }
176 
177 CSSStyleSheetImpl::CSSStyleSheetImpl(CSSRuleImpl *ownerRule, CSSStyleSheetImpl *orig)
178  : StyleSheetImpl(ownerRule, orig->m_strHref)
179 {
180  // m_lstChildren is deleted in StyleListImpl
181  m_lstChildren = new QList<StyleBaseImpl *>;
182  StyleBaseImpl *rule;
183  QListIterator<StyleBaseImpl *> it(*orig->m_lstChildren);
184  while (it.hasNext()) {
185  rule = it.next();
186  m_lstChildren->append(rule);
187  rule->setParent(this);
188  }
189  m_doc = static_cast<CSSStyleSheetImpl *>(ownerRule->stylesheet())->doc();
190  m_implicit = false;
191  m_namespaces = nullptr;
192  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
193  m_loadedHint = false;
194 
195  recomputeNamespaceInfo(); // as we cloned kids
196 }
197 
198 CSSRuleImpl *CSSStyleSheetImpl::ownerRule() const
199 {
200  if (!m_parent) {
201  return nullptr;
202  }
203  if (m_parent->isRule()) {
204  return static_cast<CSSRuleImpl *>(m_parent);
205  }
206  return nullptr;
207 }
208 
209 unsigned long CSSStyleSheetImpl::insertRule(const DOMString &rule, unsigned long index, int &exceptioncode)
210 {
211  exceptioncode = 0;
212  if (index > (unsigned) m_lstChildren->count()) {
213  exceptioncode = DOMException::INDEX_SIZE_ERR;
214  return 0;
215  }
216  CSSParser p(strictParsing);
217  CSSRuleImpl *r = p.parseRule(this, rule);
218 
219  if (!r) {
220  exceptioncode = CSSException::SYNTAX_ERR + CSSException::_EXCEPTION_OFFSET;
221  return 0;
222  }
223  // ###
224  // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an
225  //@import rule is inserted after a standard rule set or other at-rule.
226  m_lstChildren->insert(index, r);
227  if (m_doc) {
228  m_doc->updateStyleSelector(true /*shallow*/);
229  }
230 
231  if (r->type() == DOM::CSSRule::NAMESPACE_RULE) {
232  dirtyNamespaceInfo();
233  if (static_cast<CSSNamespaceRuleImpl *>(r)->isDefault()) {
234  recomputeNamespaceInfo(); // default may have changed
235  }
236  // ### too late for some rules?
237  }
238 
239  return index;
240 }
241 
242 void CSSStyleSheetImpl::appendNamespaceRule(CSSNamespaceRuleImpl *ns)
243 {
244  append(ns);
245  dirtyNamespaceInfo();
246  if (ns->isDefault()) {
247  recomputeNamespaceInfo();
248  }
249 }
250 
251 CSSRuleListImpl *CSSStyleSheetImpl::cssRules(bool omitCharsetRules)
252 {
253  return new CSSRuleListImpl(this, omitCharsetRules);
254 }
255 
256 void CSSStyleSheetImpl::deleteRule(unsigned long index, int &exceptioncode)
257 {
258  exceptioncode = 0;
259  if (index + 1 > (unsigned) m_lstChildren->count()) {
260  exceptioncode = DOMException::INDEX_SIZE_ERR;
261  return;
262  }
263  StyleBaseImpl *b = m_lstChildren->takeAt(index);
264 
265  if (b->isRule() && static_cast<CSSRuleImpl *>(b)->type() == DOM::CSSRule::NAMESPACE_RULE) {
266  dirtyNamespaceInfo();
267  if (static_cast<CSSNamespaceRuleImpl *>(b)->isDefault()) {
268  recomputeNamespaceInfo(); // default may have changed
269  }
270  // ### too late for some rules?
271  }
272 
273  // TreeShared requires delete not deref when removed from tree
274  b->setParent(nullptr);
275  if (!b->refCount()) {
276  delete b;
277  }
278  if (m_doc) {
279  m_doc->updateStyleSelector(true /*shallow*/);
280  }
281 }
282 
283 void CSSStyleSheetImpl::recomputeNamespaceInfo()
284 {
285  assert(!m_namespaces);
286 
287  m_namespaces = new QList<CSSNamespaceRuleImpl *>;
288  m_defaultNamespace = NamespaceName::fromId(anyNamespace);
289 
290  // Compute list of all the @namespace nodes, as well as the default one.
291  for (int i = 0; i < m_lstChildren->count(); ++i) {
292  StyleBaseImpl *b = m_lstChildren->at(i);
293  if (b->isRule() && static_cast<CSSRuleImpl *>(b)->type() == DOM::CSSRule::NAMESPACE_RULE) {
294  CSSNamespaceRuleImpl *nr = static_cast<CSSNamespaceRuleImpl *>(b);
295  DOM::DOMString prefix = nr->prefix();
296  DOM::DOMString uri = nr->namespaceURI();
297 
298  if (uri.isNull()) {
299  continue;
300  }
301 
302  if (nr->isDefault()) {
303  m_defaultNamespace = NamespaceName::fromString(uri);
304  }
305 
306  m_namespaces->append(nr);
307  }
308  }
309 }
310 
311 void CSSStyleSheetImpl::determineNamespace(NamespaceName &namespacename, const DOM::DOMString &prefix)
312 {
313  if (prefix.isEmpty()) {
314  namespacename = NamespaceName::fromId(emptyNamespace); // No namespace. If an element/attribute has a namespace, we won't match it.
315  } else if (prefix == "*") {
316  namespacename = NamespaceName::fromId(anyNamespace); // We'll match any namespace.
317  } else {
318  if (!m_namespaces) {
319  recomputeNamespaceInfo();
320  }
321 
322  // To lookup the name, we go backwards, so the latest one wins
323  for (int p = m_namespaces->count() - 1; p >= 0; --p) {
324  CSSNamespaceRuleImpl *ns = m_namespaces->at(p);
325  if (ns->prefix() == prefix) {
326  namespacename = NamespaceName::fromString(ns->namespaceURI());
327  return;
328  }
329  }
330  }
331 }
332 
333 bool CSSStyleSheetImpl::parseString(const DOMString &string, bool strict)
334 {
335 #ifdef CSS_STYLESHEET_DEBUG
336  qCDebug(KHTML_LOG) << "parsing sheet, len=" << string.length() << ", sheet is " << string.string();
337 #endif
338 
339  strictParsing = strict;
340  CSSParser p(strict);
341  p.parseSheet(this, string);
342  return true;
343 }
344 
345 bool CSSStyleSheetImpl::isLoading() const
346 {
347  StyleBaseImpl *rule;
348  QListIterator<StyleBaseImpl *> it(*m_lstChildren);
349  while (it.hasNext()) {
350  rule = it.next();
351  if (rule->isImportRule()) {
352  CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(rule);
353 #ifdef CSS_STYLESHEET_DEBUG
354  qCDebug(KHTML_LOG) << "found import";
355 #endif
356  if (import->isLoading()) {
357 #ifdef CSS_STYLESHEET_DEBUG
358  qCDebug(KHTML_LOG) << "--> not loaded";
359 #endif
360  m_loadedHint = false;
361  return true;
362  }
363  }
364  }
365  m_loadedHint = true;
366  return false;
367 }
368 
369 void CSSStyleSheetImpl::checkLoaded() const
370 {
371  if (isLoading()) {
372  return;
373  }
374  if (m_parent) {
375  m_parent->checkLoaded();
376  }
377  if (m_parentNode) {
378  m_loadedHint = m_parentNode->checkRemovePendingSheet();
379  } else if (parentStyleSheet() && parentStyleSheet()->isCSSStyleSheet()) {
380  m_loadedHint = static_cast<CSSStyleSheetImpl *>(parentStyleSheet())->loadedHint();
381  } else {
382  m_loadedHint = true;
383  }
384 }
385 
386 void CSSStyleSheetImpl::checkPending() const
387 {
388  if (!m_loadedHint) {
389  return;
390  }
391  if (m_parent) {
392  m_parent->checkPending();
393  } else if (m_parentNode) {
394  m_parentNode->checkAddPendingSheet();
395  }
396 }
397 
398 // ---------------------------------------------------------------------------
399 
400 StyleSheetListImpl::~StyleSheetListImpl()
401 {
402  foreach (StyleSheetImpl *sh, styleSheets) {
403  sh->deref();
404  }
405 }
406 
407 void StyleSheetListImpl::add(StyleSheetImpl *s)
408 {
409  if (managerDocument) {
410  managerDocument->ensureStyleSheetListUpToDate();
411  }
412 
413  // ### in cases this is document.styleSheets, maybe
414  // we should route to DocumentImpl::addStyleSheets?
415 
416  if (!styleSheets.contains(s)) {
417  s->ref();
418  styleSheets.append(s);
419  }
420 }
421 
422 void StyleSheetListImpl::remove(StyleSheetImpl *s)
423 {
424  if (managerDocument) {
425  managerDocument->ensureStyleSheetListUpToDate();
426  }
427 
428  if (styleSheets.removeAll(s)) {
429  s->deref();
430  }
431 }
432 
433 unsigned long StyleSheetListImpl::length() const
434 {
435  if (managerDocument) {
436  managerDocument->ensureStyleSheetListUpToDate();
437  }
438 
439  // hack so implicit BODY stylesheets don't get counted here
440  unsigned long l = 0;
441  foreach (StyleSheetImpl *sh, styleSheets) {
442  if (!sh->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl *>(sh)->implicit()) {
443  ++l;
444  }
445  }
446  return l;
447 }
448 
449 StyleSheetImpl *StyleSheetListImpl::item(unsigned long index)
450 {
451  if (managerDocument) {
452  managerDocument->ensureStyleSheetListUpToDate();
453  }
454 
455  unsigned long l = 0;
456  foreach (StyleSheetImpl *sh, styleSheets) {
457  if (!sh->isCSSStyleSheet() || !static_cast<CSSStyleSheetImpl *>(sh)->implicit()) {
458  if (l == index) {
459  return sh;
460  }
461  ++l;
462  }
463  }
464  return nullptr;
465 }
466 
467 // --------------------------------------------------------------------------------------------
468 
469 /* MediaList is used to store 3 types of media related entities which mean the same:
470  * Media Queries, Media Types and Media Descriptors.
471  * Currently MediaList always tries to parse media queries and if parsing fails,
472  * tries to fallback to Media Descriptors if m_fallback flag is set.
473  * Slight problem with syntax error handling:
474  * CSS 2.1 Spec (https://www.w3.org/TR/CSS21/media.html)
475  * specifies that failing media type parsing is a syntax error
476  * CSS 3 Media Queries Spec (https://www.w3.org/TR/css3-mediaqueries/)
477  * specifies that failing media query is a syntax error
478  * HTML 4.01 spec (https://www.w3.org/TR/REC-html40/present/styles.html#adef-media)
479  * specifies that Media Descriptors should be parsed with forward-compatible syntax
480  * DOM Level 2 Style Sheet spec (https://www.w3.org/TR/DOM-Level-2-Style/)
481  * talks about MediaList.mediaText and refers
482  * - to Media Descriptors of HTML 4.0 in context of StyleSheet
483  * - to Media Types of CSS 2.0 in context of CSSMediaRule and CSSImportRule
484  *
485  * These facts create situation where same (illegal) media specification may result in
486  * different parses depending on whether it is media attr of style element or part of
487  * css @media rule.
488  * <style media="screen and resolution > 40dpi"> ..</style> will be enabled on screen devices where as
489  * @media screen and resolution > 40dpi {..} will not.
490  * This gets more counter-intuitive in JavaScript:
491  * document.styleSheets[0].media.mediaText = "screen and resolution > 40dpi" will be ok and
492  * enabled, while
493  * document.styleSheets[0].cssRules[0].media.mediaText = "screen and resolution > 40dpi" will
494  * throw SYNTAX_ERR exception.
495  */
496 
497 MediaListImpl::MediaListImpl(CSSStyleSheetImpl *parentSheet,
498  const DOMString &media, bool fallbackToDescriptor)
499  : StyleBaseImpl(parentSheet)
500  , m_fallback(fallbackToDescriptor)
501 {
502  int ec = 0;
503  setMediaText(media, ec);
504  // FIXME: parsing can fail. The problem with failing constructor is that
505  // we would need additional flag saying MediaList is not valid
506  // Parse can fail only when fallbackToDescriptor == false, i.e when HTML4 media descriptor
507  // forward-compatible syntax is not in use.
508  // DOMImplementationCSS seems to mandate that media descriptors are used
509  // for both html and svg, even though svg:style doesn't use media descriptors
510  // Currently the only places where parsing can fail are
511  // creating <svg:style>, creating css media / import rules from js
512  if (ec) {
513  setMediaText("invalid", ec);
514  }
515 }
516 
517 MediaListImpl::MediaListImpl(CSSRuleImpl *parentRule, const DOMString &media, bool fallbackToDescriptor)
518  : StyleBaseImpl(parentRule)
519  , m_fallback(fallbackToDescriptor)
520 {
521  int ec = 0;
522  setMediaText(media, ec);
523  // FIXME: parsing can fail. The problem with failing constructor is that
524  // we would need additional flag saying MediaList is not valid
525  // Parse can fail only when fallbackToDescriptor == false, i.e when HTML4 media descriptor
526  // forward-compatible syntax is not in use.
527  // DOMImplementationCSS seems to mandate that media descriptors are used
528  // for both html and svg, even though svg:style doesn't use media descriptors
529  // Currently the only places where parsing can fail are
530  // creating <svg:style>, creating css media / import rules from js
531  if (ec) {
532  setMediaText("invalid", ec);
533  }
534 }
535 
536 MediaListImpl::~MediaListImpl()
537 {
538  qDeleteAll(m_queries);
539 }
540 
541 CSSStyleSheetImpl *MediaListImpl::parentStyleSheet() const
542 {
543  if (m_parent->isCSSStyleSheet()) {
544  return static_cast<CSSStyleSheetImpl *>(m_parent);
545  }
546  return nullptr;
547 }
548 
549 CSSRuleImpl *MediaListImpl::parentRule() const
550 {
551  if (m_parent->isRule()) {
552  return static_cast<CSSRuleImpl *>(m_parent);
553  }
554  return nullptr;
555 }
556 
557 static DOMString parseMediaDescriptor(const DOMString &s)
558 {
559  int len = s.length();
560 
561  // https://www.w3.org/TR/REC-html40/types.html#type-media-descriptors
562  // "Each entry is truncated just before the first character that isn't a
563  // US ASCII letter [a-zA-Z] (ISO 10646 hex 41-5a, 61-7a), digit [0-9] (hex 30-39),
564  // or hyphen (hex 2d)."
565  int i;
566  unsigned short c;
567  for (i = 0; i < len; ++i) {
568  c = s[i].unicode();
569  if (!((c >= 'a' && c <= 'z')
570  || (c >= 'A' && c <= 'Z')
571  || (c >= '1' && c <= '9')
572  || (c == '-'))) {
573  break;
574  }
575  }
576  return s.implementation()->substring(0, i);
577 }
578 
579 void MediaListImpl::deleteMedium(const DOMString &oldMedium, int &ec)
580 {
581  MediaListImpl tempMediaList;
582  CSSParser p(true);
583 
584  MediaQuery *oldQuery = nullptr;
585  bool deleteOldQuery = false;
586 
587  if (p.parseMediaQuery(&tempMediaList, oldMedium)) {
588  if (tempMediaList.m_queries.size() > 0) {
589  oldQuery = tempMediaList.m_queries[0];
590  }
591  } else if (m_fallback) {
592  DOMString medium = parseMediaDescriptor(oldMedium);
593  if (!medium.isNull()) {
594  oldQuery = new MediaQuery(MediaQuery::None, medium, nullptr);
595  deleteOldQuery = true;
596  }
597  }
598 
599  // DOM Style Sheets spec doesn't allow SYNTAX_ERR to be thrown in deleteMedium
600  ec = DOMException::NOT_FOUND_ERR;
601 
602  if (oldQuery) {
603  for (int i = 0; i < m_queries.size(); ++i) {
604  MediaQuery *a = m_queries[i];
605  if (*a == *oldQuery) {
606  m_queries.removeAt(i);
607  delete a;
608  ec = 0;
609  break;
610  }
611  }
612  if (deleteOldQuery) {
613  delete oldQuery;
614  }
615  }
616 }
617 
618 DOM::DOMString MediaListImpl::mediaText() const
619 {
620  DOMString text;
621  bool first = true;
622  const QList<MediaQuery *>::ConstIterator itEnd = m_queries.end();
623 
624  for (QList<MediaQuery *>::ConstIterator it = m_queries.begin(); it != itEnd; ++it) {
625  if (!first) {
626  text += ", ";
627  }
628  text += (*it)->cssText();
629  first = false;
630  }
631  return text;
632 }
633 
634 void MediaListImpl::setMediaText(const DOM::DOMString &value, int &ec)
635 {
636  MediaListImpl tempMediaList;
637  CSSParser p(true);
638 
639  const QString val = value.string();
640  const QStringList list = val.split(',');
641 
642  const QStringList::ConstIterator itEnd = list.end();
643 
644  for (QStringList::ConstIterator it = list.begin(); it != itEnd; ++it) {
645  const DOMString medium = (*it).trimmed();
646  if (!medium.isEmpty()) {
647  if (!p.parseMediaQuery(&tempMediaList, medium)) {
648  if (m_fallback) {
649  DOMString mediaDescriptor = parseMediaDescriptor(medium);
650  if (!mediaDescriptor.isNull()) {
651  tempMediaList.m_queries.append(new MediaQuery(MediaQuery::None, mediaDescriptor, nullptr));
652  }
653  } else {
654  ec = CSSException::SYNTAX_ERR;
655  return;
656  }
657  }
658  } else if (!m_fallback) {
659  ec = CSSException::SYNTAX_ERR;
660  return;
661  }
662  }
663  // ",,,," falls straight through, but is not valid unless fallback
664  if (!m_fallback && list.begin() == list.end()) {
665  DOMString s = value.string().trimmed();
666  if (!s.isEmpty()) {
667  ec = CSSException::SYNTAX_ERR;
668  return;
669  }
670  }
671 
672  ec = 0;
673  qDeleteAll(m_queries);
674  m_queries = tempMediaList.m_queries;
675  tempMediaList.m_queries.clear();
676 }
677 
678 DOMString MediaListImpl::item(unsigned long index) const
679 {
680  if (index < (unsigned)m_queries.size()) {
681  MediaQuery *query = m_queries[index];
682  return query->cssText();
683  }
684 
685  return DOMString();
686 }
687 
688 void MediaListImpl::appendMedium(const DOMString &newMedium, int &ec)
689 {
690  ec = DOMException::INVALID_CHARACTER_ERR;
691  CSSParser p(true);
692  if (p.parseMediaQuery(this, newMedium)) {
693  ec = 0;
694  } else if (m_fallback) {
695  DOMString medium = parseMediaDescriptor(newMedium);
696  if (!medium.isNull()) {
697  m_queries.append(new MediaQuery(MediaQuery::None, medium, nullptr));
698  ec = 0;
699  }
700  }
701 }
702 
703 void MediaListImpl::appendMediaQuery(MediaQuery *mediaQuery)
704 {
705  m_queries.append(mediaQuery);
706 }
707 
The CSSNamespaceRule interface represents an.
Definition: css_rule.h:455
std::optional< QSqlQuery > query(const QString &queryStatement)
This file is part of the HTML rendering engine for KDE.
void setMediaText(const DOM::DOMString &value)
see mediaText
Type type(const QSqlDatabase &db)
QString trimmed() const const
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
QList::iterator end()
This library provides a full-featured HTML parser and widget.
typedef ConstIterator
DOMStringImpl * implementation() const
Definition: dom_string.h:145
QList::iterator begin()
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:47:59 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.