1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright 1999-2003 Lars Knoll (knoll@kde.org)
5  * Copyright 2004 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., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 #ifndef _CSS_css_stylesheetimpl_h_
24 #define _CSS_css_stylesheetimpl_h_
25 
26 #include "dom/dom_string.h"
27 #include "css/css_base.h"
28 #include "misc/loader_client.h"
29 #include "xml/dom_docimpl.h"
30 #include <QPointer>
31 
32 namespace khtml
33 {
34 class CachedCSSStyleSheet;
35 class DocLoader;
36 class MediaQuery;
37 }
38 
39 namespace DOM
40 {
41 
42 class StyleSheet;
43 class CSSStyleSheet;
44 class CSSParser;
45 class MediaListImpl;
46 class CSSRuleImpl;
47 class CSSNamespaceRuleImpl;
48 class CSSRuleListImpl;
49 class NodeImpl;
50 class DocumentImpl;
51 
52 class StyleSheetImpl : public StyleListImpl
53 {
54 public:
55     StyleSheetImpl(DOM::NodeImpl *ownerNode, DOM::DOMString href = DOMString());
56     StyleSheetImpl(StyleSheetImpl *parentSheet, DOM::DOMString href = DOMString());
57     StyleSheetImpl(StyleBaseImpl *owner, DOM::DOMString href  = DOMString());
58     StyleSheetImpl(khtml::CachedCSSStyleSheet *cached, DOM::DOMString href  = DOMString());
59     virtual ~StyleSheetImpl();
60 
isStyleSheet()61     bool isStyleSheet() const override
62     {
63         return true;
64     }
65 
type()66     virtual DOM::DOMString type() const
67     {
68         return DOMString();
69     }
70 
disabled()71     bool disabled() const
72     {
73         return m_disabled;
74     }
75     void setDisabled(bool disabled);
ownerNode()76     DOM::NodeImpl *ownerNode() const
77     {
78         return m_parentNode;
79     }
80     StyleSheetImpl *parentStyleSheet() const;
href()81     DOM::DOMString href() const
82     {
83         return m_strHref;
84     }
setHref(const DOM::DOMString & href)85     void setHref(const DOM::DOMString &href)
86     {
87         m_strHref = href;
88     }
title()89     DOM::DOMString title() const
90     {
91         return m_strTitle;
92     }
media()93     MediaListImpl *media() const
94     {
95         return m_media;
96     }
97     void setMedia(MediaListImpl *media);
setTitle(const DOM::DOMString & title)98     void setTitle(const DOM::DOMString &title)
99     {
100         m_strTitle = title;
101     }
102 
103 protected:
104     DOM::NodeImpl *m_parentNode;
105     DOM::DOMString m_strHref;
106     DOM::DOMString m_strTitle;
107     MediaListImpl *m_media;
108     bool m_disabled;
109 };
110 
111 class CSSStyleSheetImpl : public StyleSheetImpl
112 {
113 public:
114     CSSStyleSheetImpl(DOM::NodeImpl *parentNode, DOM::DOMString href = DOMString(), bool _implicit = false);
115     CSSStyleSheetImpl(CSSStyleSheetImpl *parentSheet, DOM::DOMString href = DOMString());
116     CSSStyleSheetImpl(CSSRuleImpl *ownerRule, DOM::DOMString href = DOMString());
117     // clone from a cached version of the sheet
118     CSSStyleSheetImpl(DOM::NodeImpl *parentNode, CSSStyleSheetImpl *orig);
119     CSSStyleSheetImpl(CSSRuleImpl *ownerRule, CSSStyleSheetImpl *orig);
120 
~CSSStyleSheetImpl()121     ~CSSStyleSheetImpl()
122     {
123         delete m_namespaces;
124     }
125 
isCSSStyleSheet()126     bool isCSSStyleSheet() const override
127     {
128         return true;
129     }
130 
type()131     DOM::DOMString type() const override
132     {
133         return "text/css";
134     }
135 
136     CSSRuleImpl *ownerRule() const;
137     CSSRuleListImpl *cssRules(bool omitCharsetRule = false);
138     unsigned long insertRule(const DOM::DOMString &rule, unsigned long index, int &exceptioncode);
139     void deleteRule(unsigned long index, int &exceptioncode);
140 
141     void determineNamespace(NamespaceName &namespacename, const DOM::DOMString &prefix);
defaultNamespace()142     quint32 defaultNamespace()
143     {
144         return m_defaultNamespace.id();
145     }
146     void appendNamespaceRule(CSSNamespaceRuleImpl *ns);
147 
setCharset(const DOMString & charset)148     void setCharset(const DOMString &charset)
149     {
150         m_charset = charset;
151     }
charset()152     const DOMString &charset() const
153     {
154         return m_charset;
155     }
156 
157     bool parseString(const DOMString &string, bool strict = true) override;
158 
159     bool isLoading() const;
160 
161     void checkLoaded() const override;
162     void checkPending() const override;
loadedHint()163     bool loadedHint() const
164     {
165         return m_loadedHint;
166     }
167 
168     // ### remove? (clients should use sheet->doc()->docLoader())
docLoader()169     khtml::DocLoader *docLoader() const
170     {
171         return m_doc ? m_doc->docLoader() : nullptr;
172     }
173 
doc()174     DocumentImpl *doc() const
175     {
176         return m_doc;
177     }
implicit()178     bool implicit() const
179     {
180         return m_implicit;
181     }
182 protected:
183     void recomputeNamespaceInfo(); // updates m_defaultNamespace and m_namespaces
184     // we update m_namespaces lazily, but
185     // m_defaulNamespace eagerly.
dirtyNamespaceInfo()186     void dirtyNamespaceInfo()
187     {
188         delete m_namespaces;
189         m_namespaces = nullptr;
190     }
191 
192     DocumentImpl *m_doc;
193     bool m_implicit;
194     mutable bool m_loadedHint;
195     NamespaceName m_defaultNamespace;
196     QList<CSSNamespaceRuleImpl *> *m_namespaces;
197     DOMString m_charset;
198 };
199 
200 // ----------------------------------------------------------------------------
201 
202 class StyleSheetListImpl : public khtml::Shared<StyleSheetListImpl>
203 {
204 public:
205     // the manager argument should be passed only when this is
206     // document.styleSheets.
managerDocument(manager)207     StyleSheetListImpl(DocumentImpl *manager = nullptr): managerDocument(manager) {}
208     ~StyleSheetListImpl();
209 
210     // the following two ignore implicit stylesheets
211     unsigned long length() const;
212     StyleSheetImpl *item(unsigned long index);
213 
214     void add(StyleSheetImpl *s);
215     void remove(StyleSheetImpl *s);
216 
217     QList<StyleSheetImpl *> styleSheets;
218 
219     // we need the document pointer to make it update the stylesheet list
220     // if needed for the global list. Luckily, we don't care about that if the
221     // document dies, so we use QPointer to break the cycle
222     QPointer<DocumentImpl> managerDocument;
223 };
224 
225 // ----------------------------------------------------------------------------
226 
227 class MediaListImpl : public StyleBaseImpl
228 {
229 public:
230     MediaListImpl(bool fallbackToDescription = false)
StyleBaseImpl(nullptr)231         : StyleBaseImpl(nullptr), m_fallback(fallbackToDescription) {}
232     MediaListImpl(CSSStyleSheetImpl *parentSheet, bool fallbackToDescription = false)
StyleBaseImpl(parentSheet)233         : StyleBaseImpl(parentSheet), m_fallback(fallbackToDescription) {}
234     MediaListImpl(CSSStyleSheetImpl *parentSheet,
235                   const DOM::DOMString &media, bool fallbackToDescription = false);
236     MediaListImpl(CSSRuleImpl *parentRule, const DOM::DOMString &media, bool fallbackToDescription = false);
237     ~MediaListImpl();
238 
isMediaList()239     bool isMediaList() const override
240     {
241         return true;
242     }
243 
244     CSSStyleSheetImpl *parentStyleSheet() const;
245     CSSRuleImpl *parentRule() const;
length()246     unsigned long length() const
247     {
248         return  m_queries.size();
249     }
250     DOM::DOMString item(unsigned long index) const;
251     void deleteMedium(const DOM::DOMString &oldMedium, int &ec);
252     void appendMedium(const DOM::DOMString &newMedium, int &ec);
253 
254     DOM::DOMString mediaText() const;
255     void setMediaText(const DOM::DOMString &value, int &ec);
256 
257     void appendMediaQuery(khtml::MediaQuery *mediaQuery);
mediaQueries()258     const QList<khtml::MediaQuery *> *mediaQueries() const
259     {
260         return &m_queries;
261     }
262 
263 protected:
264     QList<khtml::MediaQuery *> m_queries;
265     bool m_fallback; // true if failed media query parsing should fallback to media description parsing
266 };
267 
268 } // namespace
269 
270 #endif
271 
272