blob: 4c805f680977209fbd1a600c7dcf6001f5b2b392 [file] [log] [blame]
eseidelb3f42132006-05-16 02:08:51 +00001/**
2 * This file is part of the DOM implementation for KDE.
3 *
4 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2004, 2006 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22#include "config.h"
23#include "CSSStyleSheet.h"
24
eseidel13a64222006-05-16 05:33:34 +000025#include "CSSImportRule.h"
26#include "cssparser.h"
27#include "CSSRuleList.h"
eseidelb3f42132006-05-16 02:08:51 +000028#include "Document.h"
29#include "ExceptionCode.h"
30#include "Node.h"
31
32namespace WebCore {
33
34CSSStyleSheet::CSSStyleSheet(CSSStyleSheet* parentSheet, String href)
35 : StyleSheet(parentSheet, href)
36 , m_doc(parentSheet ? parentSheet->doc() : 0)
37 , m_implicit(false)
38 , m_namespaces(0)
39{
40}
41
42CSSStyleSheet::CSSStyleSheet(Node *parentNode, String href, bool _implicit)
43 : StyleSheet(parentNode, href)
44 , m_doc(parentNode->document())
45 , m_implicit(_implicit)
46 , m_namespaces(0)
47{
48}
49
50CSSStyleSheet::CSSStyleSheet(CSSRule *ownerRule, String href)
51 : StyleSheet(ownerRule, href)
52 , m_doc(0)
53 , m_implicit(false)
54 , m_namespaces(0)
55{
56}
57
58CSSRule *CSSStyleSheet::ownerRule() const
59{
eseidel13a64222006-05-16 05:33:34 +000060 return (parent() && parent()->isRule()) ? static_cast<CSSRule*>(parent()) : 0;
eseidelb3f42132006-05-16 02:08:51 +000061}
62
63unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, ExceptionCode& ec)
64{
65 ec = 0;
66 if (index > length()) {
67 ec = INDEX_SIZE_ERR;
68 return 0;
69 }
70 CSSParser p(useStrictParsing());
71 RefPtr<CSSRule> r = p.parseRule(this, rule);
72
73 if (!r) {
74 ec = SYNTAX_ERR;
75 return 0;
76 }
77
78 // ###
79 // HIERARCHY_REQUEST_ERR: Raised if the rule cannot be inserted at the specified index e.g. if an
80 //@import rule is inserted after a standard rule set or other at-rule.
81 insert(index, r.release());
82
83 styleSheetChanged();
84
85 return index;
86}
87
88unsigned CSSStyleSheet::addRule(const String &selector, const String &style, int index, ExceptionCode& ec)
89{
90 if (index == -1)
91 index = length();
92 return insertRule(selector + " { " + style + " }", index, ec);
93}
94
95CSSRuleList *CSSStyleSheet::cssRules()
96{
97 return new CSSRuleList(this);
98}
99
100void CSSStyleSheet::deleteRule(unsigned index, ExceptionCode& ec)
101{
102 if (index >= length()) {
103 ec = INDEX_SIZE_ERR;
104 return;
105 }
106
107 ec = 0;
108 remove(index);
109 styleSheetChanged();
110}
111
112void CSSStyleSheet::addNamespace(CSSParser* p, const AtomicString& prefix, const AtomicString& uri)
113{
114 if (uri.isEmpty())
115 return;
116
117 m_namespaces = new CSSNamespace(prefix, uri, m_namespaces);
118
119 if (prefix.isEmpty())
120 // Set the default namespace on the parser so that selectors that omit namespace info will
121 // be able to pick it up easily.
122 p->defaultNamespace = uri;
123}
124
125const AtomicString& CSSStyleSheet::determineNamespace(const AtomicString& prefix)
126{
127 if (prefix.isEmpty())
128 return nullAtom; // No namespace. If an element/attribute has a namespace, we won't match it.
129 else if (prefix == starAtom)
130 return starAtom; // We'll match any namespace.
131 else if (m_namespaces) {
132 CSSNamespace* ns = m_namespaces->namespaceForPrefix(prefix);
133 if (ns)
134 return ns->uri();
135 }
136 return nullAtom; // Assume we wont match any namespaces.
137}
138
139bool CSSStyleSheet::parseString(const String &string, bool strict)
140{
141 setStrictParsing(strict);
142 CSSParser p(strict);
143 p.parseSheet(this, string);
144 return true;
145}
146
147bool CSSStyleSheet::isLoading()
148{
149 unsigned len = length();
150 for (unsigned i = 0; i < len; ++i) {
151 StyleBase* rule = item(i);
152 if (rule->isImportRule() && static_cast<CSSImportRule*>(rule)->isLoading())
153 return true;
154 }
155 return false;
156}
157
158void CSSStyleSheet::checkLoaded()
159{
160 if (isLoading())
161 return;
162 if (parent())
163 parent()->checkLoaded();
164 if (m_parentNode)
165 m_parentNode->sheetLoaded();
166}
167
168DocLoader *CSSStyleSheet::docLoader()
169{
170 if (!m_doc) // doc is 0 for the user- and default-sheet!
171 return 0;
172
173 // ### remove? (clients just use sheet->doc()->docLoader())
174 return m_doc->docLoader();
175}
176
177void CSSStyleSheet::styleSheetChanged()
178{
179 /* FIXME: We don't need to do everything updateStyleSelector does,
180 * basically we just need to recreate the document's selector with the
181 * already existing style sheets.
182 */
183 if (m_doc)
184 m_doc->updateStyleSelector();
185}
186
187}