KHtml

css_ruleimpl.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright 1999-2003 Lars Knoll ([email protected])
5  * Copyright 2002-2003 Dirk Mueller ([email protected])
6  * Copyright 2002-2008 Apple Computer, Inc.
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 #include "css_ruleimpl.h"
25 #include "css_stylesheetimpl.h"
26 #include "css_valueimpl.h"
27 #include "cssparser.h"
28 
29 #include <dom/css_rule.h>
30 #include <dom/css_stylesheet.h>
31 #include <dom/dom_exception.h>
32 #include <dom/dom_string.h>
33 
34 #include <xml/dom_docimpl.h>
35 
36 using namespace DOM;
37 
38 CSSStyleSheetImpl *CSSRuleImpl::parentStyleSheet() const
39 {
40  return (m_parent && m_parent->isCSSStyleSheet()) ?
41  static_cast<CSSStyleSheetImpl *>(m_parent) : nullptr;
42 }
43 
44 CSSRuleImpl *CSSRuleImpl::parentRule() const
45 {
46  return (m_parent && m_parent->isRule()) ?
47  static_cast<CSSRuleImpl *>(m_parent) : nullptr;
48 }
49 
50 DOM::DOMString CSSRuleImpl::cssText() const
51 {
52  // ###
53  return DOMString();
54 }
55 
56 void CSSRuleImpl::setCssText(DOM::DOMString /*str*/)
57 {
58  // ###
59 }
60 
61 // ---------------------------------------------------------------------------
62 
63 CSSFontFaceRuleImpl::CSSFontFaceRuleImpl(StyleBaseImpl *parent)
64  : CSSRuleImpl(parent)
65 {
66  m_type = CSSRule::FONT_FACE_RULE;
67  m_style = nullptr;
68 }
69 
70 CSSFontFaceRuleImpl::~CSSFontFaceRuleImpl()
71 {
72  if (m_style) {
73  m_style->deref();
74  }
75 }
76 
77 void CSSFontFaceRuleImpl::setDeclaration(CSSStyleDeclarationImpl *decl)
78 {
79  assert(!m_style);
80  m_style = decl;
81  if (m_style) {
82  m_style->ref();
83  }
84 }
85 
86 DOMString CSSFontFaceRuleImpl::cssText() const
87 {
88  DOMString result("@font-face");
89 
90  result += " { ";
91  result += m_style->cssText();
92  result += "}";
93 
94  return result;
95 }
96 
97 // --------------------------------------------------------------------------
98 
99 CSSImportRuleImpl::CSSImportRuleImpl(StyleBaseImpl *parent,
100  const DOM::DOMString &href,
101  MediaListImpl *media)
102  : CSSRuleImpl(parent)
103 {
104  m_type = CSSRule::IMPORT_RULE;
105 
106  m_lstMedia = media;
107  if (!m_lstMedia) {
108  m_lstMedia = new MediaListImpl(this, DOMString());
109  }
110  m_lstMedia->setParent(this);
111  m_lstMedia->ref();
112 
113  m_strHref = href;
114  m_styleSheet = nullptr;
115 
116  m_cachedSheet = nullptr;
117 
118  init();
119 }
120 CSSImportRuleImpl::CSSImportRuleImpl(StyleBaseImpl *parent,
121  const DOM::DOMString &href,
122  const DOM::DOMString &media)
123  : CSSRuleImpl(parent)
124 {
125  m_type = CSSRule::IMPORT_RULE;
126 
127  m_lstMedia = new MediaListImpl(this, media);
128  m_lstMedia->ref();
129 
130  m_strHref = href;
131  m_styleSheet = nullptr;
132 
133  m_cachedSheet = nullptr;
134 
135  init();
136 }
137 
138 CSSImportRuleImpl::~CSSImportRuleImpl()
139 {
140  if (m_lstMedia) {
141  m_lstMedia->setParent(nullptr);
142  m_lstMedia->deref();
143  }
144  if (m_styleSheet) {
145  m_styleSheet->setParent(nullptr);
146  m_styleSheet->deref();
147  }
148 
149  if (m_cachedSheet) {
150  m_cachedSheet->deref(this);
151  }
152 }
153 
154 void CSSImportRuleImpl::checkLoaded() const
155 {
156  if (isLoading()) {
157  return;
158  }
159  CSSRuleImpl::checkLoaded();
160 }
161 
162 void CSSImportRuleImpl::setStyleSheet(const DOM::DOMString &url, const DOM::DOMString &sheetStr, const DOM::DOMString &charset, const DOM::DOMString &mimetype)
163 {
164  if (m_styleSheet) {
165  m_styleSheet->setParent(nullptr);
166  m_styleSheet->deref();
167  }
168  m_styleSheet = new CSSStyleSheetImpl(this, url);
169  m_styleSheet->setCharset(charset);
170  m_styleSheet->ref();
171 
172  CSSStyleSheetImpl *parent = parentStyleSheet();
173  bool strict = parent ? parent->useStrictParsing() : true;
174  DOMString sheet = sheetStr;
175  if (strict && !khtml::isAcceptableCSSMimetype(mimetype)) {
176  sheet = "";
177  }
178  m_styleSheet->parseString(sheet, strict);
179  m_loading = false;
180  m_done = true;
181 
182  checkLoaded();
183 }
184 
185 void CSSImportRuleImpl::error(int /*err*/, const QString &/*text*/)
186 {
187  if (m_styleSheet) {
188  m_styleSheet->setParent(nullptr);
189  m_styleSheet->deref();
190  }
191  m_styleSheet = nullptr;
192 
193  m_loading = false;
194  m_done = true;
195 
196  checkLoaded();
197 }
198 
199 bool CSSImportRuleImpl::isLoading() const
200 {
201  return (m_loading || (m_styleSheet && m_styleSheet->isLoading()));
202 }
203 
204 void CSSImportRuleImpl::init()
205 {
206  m_loading = 0;
207  m_done = false;
208  khtml::DocLoader *docLoader = nullptr;
209  StyleBaseImpl *root = this;
210  StyleBaseImpl *parent;
211  while ((parent = root->parent())) {
212  root = parent;
213  }
214  if (root->isCSSStyleSheet()) {
215  docLoader = static_cast<CSSStyleSheetImpl *>(root)->docLoader();
216  }
217 
218  DOMString absHref = m_strHref;
219  CSSStyleSheetImpl *parentSheet = parentStyleSheet();
220  if (!parentSheet->href().isNull()) {
221  // use parent styleheet's URL as the base URL
222  absHref = QUrl(parentSheet->href().string()).resolved(QUrl(m_strHref.string())).toString();
223  }
224  /*
225  else {
226  // use documents's URL as the base URL
227  DocumentImpl *doc = static_cast<CSSStyleSheetImpl*>(root)->doc();
228  absHref = QUrl(doc->URL()).resolved(QUrl(m_strHref.string())).toString();
229  }
230  */
231  // Check for a cycle in our import chain. If we encounter a stylesheet
232  // in our parent chain with the same URL, then just bail.
233  for (parent = static_cast<StyleBaseImpl *>(this)->parent();
234  parent;
235  parent = parent->parent())
236  if (absHref == parent->baseURL().url()) {
237  return;
238  }
239 
240  m_cachedSheet = docLoader->requestStyleSheet(absHref, parentStyleSheet()->charset().string());
241 
242  if (m_cachedSheet) {
243  // if the import rule is issued dynamically, the sheet may have already been
244  // removed from the pending sheet count, so let the doc know
245  // the sheet being imported is pending.
246  checkPending();
247 
248  m_loading = true;
249  m_cachedSheet->ref(this);
250  }
251 }
252 
253 DOMString CSSImportRuleImpl::cssText() const
254 {
255  DOMString result = "@import url(\"";
256  result += m_strHref;
257  result += "\")";
258 
259  if (m_lstMedia) {
260  result += " ";
261  result += m_lstMedia->mediaText();
262  }
263  result += ";";
264 
265  return result;
266 }
267 
268 // --------------------------------------------------------------------------
269 CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent, MediaListImpl *mediaList, CSSRuleListImpl *ruleList)
270  : CSSRuleImpl(parent)
271 {
272  m_type = CSSRule::MEDIA_RULE;
273  m_lstMedia = mediaList;
274  if (m_lstMedia) {
275  m_lstMedia->ref();
276  }
277  m_lstCSSRules = ruleList;
278  m_lstCSSRules->ref();
279 }
280 
281 CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent)
282  : CSSRuleImpl(parent)
283 {
284  m_type = CSSRule::MEDIA_RULE;
285  m_lstMedia = nullptr;
286  m_lstCSSRules = new CSSRuleListImpl();
287  m_lstCSSRules->ref();
288 }
289 
290 CSSMediaRuleImpl::CSSMediaRuleImpl(StyleBaseImpl *parent, const DOM::DOMString &media)
291  : CSSRuleImpl(parent)
292 {
293  m_type = CSSRule::MEDIA_RULE;
294  m_lstMedia = new MediaListImpl(this, media);
295  m_lstMedia->ref();
296  m_lstCSSRules = new CSSRuleListImpl();
297  m_lstCSSRules->ref();
298 }
299 
300 CSSMediaRuleImpl::~CSSMediaRuleImpl()
301 {
302  if (m_lstMedia) {
303  m_lstMedia->setParent(nullptr);
304  m_lstMedia->deref();
305  }
306  for (unsigned int i = 0; i < m_lstCSSRules->length(); ++i) {
307  m_lstCSSRules->item(i)->setParent(nullptr);
308  }
309  m_lstCSSRules->deref();
310 }
311 
312 unsigned long CSSMediaRuleImpl::append(CSSRuleImpl *rule)
313 {
314  return rule ? m_lstCSSRules->insertRule(rule, m_lstCSSRules->length()) : 0;
315 }
316 
317 unsigned long CSSMediaRuleImpl::insertRule(const DOMString &rule,
318  unsigned long index)
319 {
320  CSSParser p(strictParsing);
321  CSSRuleImpl *newRule = p.parseRule(parentStyleSheet(), rule);
322 
323  return newRule ? m_lstCSSRules->insertRule(newRule, index) : 0;
324 }
325 
326 DOM::DOMString CSSMediaRuleImpl::cssText() const
327 {
328  DOMString result("@media ");
329  if (m_lstMedia) {
330  result += m_lstMedia->mediaText();
331  result += " ";
332  }
333  result += "{ \n";
334 
335  if (m_lstCSSRules) {
336  unsigned len = m_lstCSSRules->length();
337  for (unsigned i = 0; i < len; i++) {
338  result += " ";
339  result += m_lstCSSRules->item(i)->cssText();
340  result += "\n";
341  }
342  }
343 
344  result += "}";
345  return result;
346 }
347 
348 // ---------------------------------------------------------------------------
349 
350 CSSPageRuleImpl::CSSPageRuleImpl(StyleBaseImpl *parent)
351  : CSSRuleImpl(parent)
352 {
353  m_type = CSSRule::PAGE_RULE;
354  m_style = nullptr;
355 }
356 
357 CSSPageRuleImpl::~CSSPageRuleImpl()
358 {
359  if (m_style) {
360  m_style->deref();
361  }
362 }
363 
364 DOM::DOMString CSSPageRuleImpl::selectorText() const
365 {
366  // ###
367  return DOMString();
368 }
369 
370 void CSSPageRuleImpl::setSelectorText(DOM::DOMString /*str*/)
371 {
372  // ###
373 }
374 
375 // --------------------------------------------------------------------------
376 
377 CSSStyleRuleImpl::CSSStyleRuleImpl(StyleBaseImpl *parent)
378  : CSSRuleImpl(parent)
379 {
380  m_type = CSSRule::STYLE_RULE;
381  m_style = nullptr;
382  m_selector = nullptr;
383 }
384 
385 CSSStyleRuleImpl::~CSSStyleRuleImpl()
386 {
387  if (m_style) {
388  m_style->setParent(nullptr);
389  m_style->deref();
390  }
391  qDeleteAll(*m_selector);
392  delete m_selector;
393 }
394 
395 DOMString CSSStyleRuleImpl::cssText() const
396 {
397  DOMString result(selectorText());
398 
399  result += " { ";
400  result += m_style->cssText();
401  result += "}";
402 
403  return result;
404 }
405 
406 DOM::DOMString CSSStyleRuleImpl::selectorText() const
407 {
408  if (m_selector) {
409  DOMString str;
410  foreach (CSSSelector *s, *m_selector) {
411  if (s != m_selector->at(0)) {
412  str += ", ";
413  }
414  str += s->selectorText();
415  }
416  return str;
417  }
418  return DOMString();
419 }
420 
421 void CSSStyleRuleImpl::setSelectorText(DOM::DOMString /*str*/)
422 {
423  // ###
424 }
425 
426 bool CSSStyleRuleImpl::parseString(const DOMString &/*string*/, bool)
427 {
428  // ###
429  return false;
430 }
431 
432 void CSSStyleRuleImpl::setDeclaration(CSSStyleDeclarationImpl *style)
433 {
434  if (m_style != style) {
435  if (m_style) {
436  m_style->deref();
437  }
438  m_style = style;
439  if (m_style) {
440  m_style->ref();
441  }
442  }
443 }
444 
445 // --------------------------------------------------------------------
446 
447 CSSNamespaceRuleImpl::CSSNamespaceRuleImpl(StyleBaseImpl *parent, const DOMString &prefix, const DOMString &ns)
448  : CSSRuleImpl(parent)
449 {
450  m_type = CSSRule::NAMESPACE_RULE;
451  m_prefix = prefix;
452  m_namespace = ns;
453 }
454 
455 // --------------------------------------------------------------------
456 
457 CSSRuleListImpl::CSSRuleListImpl(StyleListImpl *const list, bool omitCharsetRules)
458 {
459  m_list = list;
460  if (list && omitCharsetRules) {
461  m_list = nullptr;
462  unsigned len = list->length();
463  for (unsigned i = 0; i < len; ++i) {
464  StyleBaseImpl *rule = list->item(i);
465  if (rule->isRule() && !rule->isCharsetRule()) {
466  append(static_cast<CSSRuleImpl *>(rule));
467  }
468  }
469  } else if (m_list) {
470  m_list->ref();
471  }
472 }
473 
474 CSSRuleListImpl::~CSSRuleListImpl()
475 {
476  CSSRuleImpl *rule;
477  while (!m_lstCSSRules.isEmpty() && (rule = m_lstCSSRules.takeFirst())) {
478  rule->deref();
479  }
480  if (m_list) {
481  m_list->deref();
482  }
483 }
484 
485 unsigned long CSSRuleListImpl::length() const
486 {
487  return m_list ? m_list->length() : m_lstCSSRules.count();
488 }
489 
490 CSSRuleImpl *CSSRuleListImpl::item(unsigned long index)
491 {
492  if (m_list) {
493  StyleBaseImpl *rule = m_list->item(index);
494  assert(!rule || rule->isRule());
495  return static_cast<CSSRuleImpl *>(rule);
496  }
497  return index < length() ? m_lstCSSRules.at(index) : nullptr;
498 }
499 
500 void CSSRuleListImpl::deleteRule(unsigned long index)
501 {
502  assert(!m_list);
503  if (index + 1 > (unsigned) m_lstCSSRules.size()) {
504  return;
505  // ### Throw INDEX_SIZE_ERR exception here (TODO)
506  }
507  CSSRuleImpl *rule = m_lstCSSRules.takeAt(index);
508  rule->deref();
509 }
510 
511 void CSSRuleListImpl::append(CSSRuleImpl *rule)
512 {
513  assert(!m_list);
514  rule->ref();
515  m_lstCSSRules.append(rule);
516 }
517 
518 unsigned long CSSRuleListImpl::insertRule(CSSRuleImpl *rule,
519  unsigned long index)
520 {
521  assert(!m_list);
522  if (index > (unsigned) m_lstCSSRules.size()) {
523  return 0;
524  // ### Throw INDEX_SIZE_ERR exception here (TODO)
525  }
526 
527  if (rule) {
528  m_lstCSSRules.insert(index, rule);
529  rule->ref();
530  return index;
531  }
532 
533  return 0;
534 }
535 
The CSSNamespaceRule interface represents an.
Definition: css_rule.h:455
QString toString(QUrl::FormattingOptions options) const const
This class implements the basic string we use in the DOM.
Definition: dom_string.h:44
QCA_EXPORT void init()
This library provides a full-featured HTML parser and widget.
unsigned long length() const
The number of CSSRule s in the list.
Definition: css_rule.cpp:618
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.