1 | /* This file is part of the KDE project |
2 | * |
3 | * Copyright (C) 2000 Simon Hausmann <hausmann@kde.org> |
4 | * Copyright (C) 2007 David Faure <faure@kde.org> |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2 of the License, or (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Library General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Library General Public License |
17 | * along with this library; see the file COPYING.LIB. If not, write to |
18 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | * Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #include "khtml_global.h" |
23 | #include "khtml_part.h" |
24 | #include "khtml_settings.h" |
25 | |
26 | #include "css/cssstyleselector.h" |
27 | #include "css/css_mediaquery.h" |
28 | #include "html/html_imageimpl.h" |
29 | #include "rendering/render_style.h" |
30 | #include "rendering/break_lines.h" |
31 | #include "misc/htmlnames.h" |
32 | #include "misc/loader.h" |
33 | #include "misc/arena.h" |
34 | #include "misc/paintbuffer.h" |
35 | |
36 | #include <QtCore/QLinkedList> |
37 | |
38 | #include <kcomponentdata.h> |
39 | #include <kiconloader.h> |
40 | #include <kaboutdata.h> |
41 | #include <klocale.h> |
42 | |
43 | #include <assert.h> |
44 | |
45 | #include <kdebug.h> |
46 | |
47 | // SVG |
48 | #include "svg/SVGNames.h" |
49 | |
50 | KHTMLGlobal *KHTMLGlobal::s_self = 0; |
51 | unsigned long int KHTMLGlobal::s_refcnt = 0; |
52 | KComponentData *KHTMLGlobal::s_componentData = 0; |
53 | KIconLoader *KHTMLGlobal::s_iconLoader = 0; |
54 | KAboutData *KHTMLGlobal::s_about = 0; |
55 | KHTMLSettings *KHTMLGlobal::s_settings = 0; |
56 | |
57 | static QLinkedList<KHTMLPart*> *s_parts = 0; |
58 | static QLinkedList<DOM::DocumentImpl*> *s_docs = 0; |
59 | |
60 | KHTMLGlobal::KHTMLGlobal() |
61 | { |
62 | assert(!s_self); |
63 | s_self = this; |
64 | ref(); |
65 | |
66 | khtml::Cache::init(); |
67 | |
68 | khtml::NamespaceFactory::initIdTable(); |
69 | khtml::PrefixFactory::initIdTable(); |
70 | khtml::LocalNameFactory::initIdTable(); |
71 | DOM::emptyLocalName = DOM::LocalName::fromId(0); |
72 | DOM::emptyPrefixName = DOM::PrefixName::fromId(0); |
73 | DOM::emptyNamespaceName = DOM::NamespaceName::fromId(DOM::emptyNamespace); |
74 | WebCore::SVGNames::init(); |
75 | } |
76 | |
77 | KHTMLGlobal::~KHTMLGlobal() |
78 | { |
79 | //kDebug(6000) << this; |
80 | if ( s_self == this ) |
81 | { |
82 | finalCheck(); |
83 | delete s_iconLoader; |
84 | delete s_componentData; |
85 | delete s_about; |
86 | delete s_settings; |
87 | delete KHTMLSettings::avFamilies; |
88 | if (s_parts) { |
89 | assert(s_parts->isEmpty()); |
90 | delete s_parts; |
91 | } |
92 | if (s_docs) { |
93 | assert(s_docs->isEmpty()); |
94 | delete s_docs; |
95 | } |
96 | |
97 | s_iconLoader = 0; |
98 | s_componentData = 0; |
99 | s_about = 0; |
100 | s_settings = 0; |
101 | s_parts = 0; |
102 | s_docs = 0; |
103 | KHTMLSettings::avFamilies = 0; |
104 | |
105 | // clean up static data |
106 | khtml::CSSStyleSelector::clear(); |
107 | khtml::RenderStyle::cleanup(); |
108 | khtml::RenderObject::cleanup(); |
109 | khtml::PaintBuffer::cleanup(); |
110 | khtml::MediaQueryEvaluator::cleanup(); |
111 | khtml::Cache::clear(); |
112 | khtml::cleanup_thaibreaks(); |
113 | khtml::ArenaFinish(); |
114 | } |
115 | else |
116 | deref(); |
117 | } |
118 | |
119 | void KHTMLGlobal::ref() |
120 | { |
121 | if ( !s_refcnt && !s_self ) |
122 | { |
123 | //kDebug(6000) << "Creating KHTMLGlobal instance"; |
124 | // we can't use a staticdeleter here, because that would mean |
125 | // that the KHTMLGlobal instance gets deleted from within a qPostRoutine, called |
126 | // from the QApplication destructor. That however is too late, because |
127 | // we want to destruct a KComponentData object, which involves destructing |
128 | // a KConfig object, which might call KGlobal::dirs() (in sync()) which |
129 | // probably is not going to work ;-) |
130 | // well, perhaps I'm wrong here, but as I'm unsure I try to stay on the |
131 | // safe side ;-) -> let's use a simple reference counting scheme |
132 | // (Simon) |
133 | new KHTMLGlobal; // does initial ref() |
134 | } else { |
135 | ++s_refcnt; |
136 | } |
137 | //kDebug(6000) << "s_refcnt=" << s_refcnt; |
138 | } |
139 | |
140 | void KHTMLGlobal::deref() |
141 | { |
142 | //kDebug(6000) << "s_refcnt=" << s_refcnt - 1; |
143 | if ( !--s_refcnt && s_self ) |
144 | { |
145 | delete s_self; |
146 | s_self = 0; |
147 | } |
148 | } |
149 | |
150 | void KHTMLGlobal::registerPart( KHTMLPart *part ) |
151 | { |
152 | //kDebug(6000) << part; |
153 | if ( !s_parts ) |
154 | s_parts = new QLinkedList<KHTMLPart*>; |
155 | |
156 | if ( !s_parts->contains( part ) ) { |
157 | s_parts->append( part ); |
158 | ref(); |
159 | } |
160 | } |
161 | |
162 | void KHTMLGlobal::deregisterPart( KHTMLPart *part ) |
163 | { |
164 | //kDebug(6000) << part; |
165 | assert( s_parts ); |
166 | |
167 | if ( s_parts->removeAll( part ) ) { |
168 | if ( s_parts->isEmpty() ) { |
169 | delete s_parts; |
170 | s_parts = 0; |
171 | } |
172 | deref(); |
173 | } |
174 | } |
175 | |
176 | void KHTMLGlobal::registerDocumentImpl( DOM::DocumentImpl *doc ) |
177 | { |
178 | //kDebug(6000) << doc; |
179 | if ( !s_docs ) |
180 | s_docs = new QLinkedList<DOM::DocumentImpl*>; |
181 | |
182 | if ( !s_docs->contains( doc ) ) { |
183 | s_docs->append( doc ); |
184 | ref(); |
185 | } |
186 | } |
187 | |
188 | void KHTMLGlobal::deregisterDocumentImpl( DOM::DocumentImpl *doc ) |
189 | { |
190 | //kDebug(6000) << doc; |
191 | assert( s_docs ); |
192 | |
193 | if ( s_docs->removeAll( doc ) ) { |
194 | if ( s_docs->isEmpty() ) { |
195 | delete s_docs; |
196 | s_docs = 0; |
197 | } |
198 | deref(); |
199 | } |
200 | } |
201 | |
202 | const KComponentData &KHTMLGlobal::componentData() |
203 | { |
204 | assert( s_self ); |
205 | |
206 | if ( !s_componentData ) |
207 | { |
208 | s_about = new KAboutData( "khtml" , 0, ki18n( "KHTML" ), "4.0" , |
209 | ki18n( "Embeddable HTML component" ), |
210 | KAboutData::License_LGPL ); |
211 | s_about->addAuthor(ki18n("Lars Knoll" ), KLocalizedString(), "knoll@kde.org" ); |
212 | s_about->addAuthor(ki18n("Antti Koivisto" ), KLocalizedString(), "koivisto@kde.org" ); |
213 | s_about->addAuthor(ki18n("Waldo Bastian" ), KLocalizedString(), "bastian@kde.org" ); |
214 | s_about->addAuthor(ki18n("Dirk Mueller" ), KLocalizedString(), "mueller@kde.org" ); |
215 | s_about->addAuthor(ki18n("Peter Kelly" ), KLocalizedString(), "pmk@kde.org" ); |
216 | s_about->addAuthor(ki18n("Torben Weis" ), KLocalizedString(), "weis@kde.org" ); |
217 | s_about->addAuthor(ki18n("Martin Jones" ), KLocalizedString(), "mjones@kde.org" ); |
218 | s_about->addAuthor(ki18n("Simon Hausmann" ), KLocalizedString(), "hausmann@kde.org" ); |
219 | s_about->addAuthor(ki18n("Tobias Anton" ), KLocalizedString(), "anton@stud.fbi.fh-darmstadt.de" ); |
220 | |
221 | s_componentData = new KComponentData( s_about ); |
222 | } |
223 | |
224 | return *s_componentData; |
225 | } |
226 | |
227 | KIconLoader *KHTMLGlobal::iconLoader() |
228 | { |
229 | if ( !s_iconLoader ) |
230 | { |
231 | s_iconLoader = new KIconLoader(componentData().componentName(), componentData().dirs()); |
232 | } |
233 | |
234 | return s_iconLoader; |
235 | } |
236 | |
237 | KHTMLSettings *KHTMLGlobal::defaultHTMLSettings() |
238 | { |
239 | assert( s_self ); |
240 | if ( !s_settings ) |
241 | s_settings = new KHTMLSettings(); |
242 | |
243 | return s_settings; |
244 | } |
245 | |
246 | void KHTMLGlobal::finalCheck() |
247 | { |
248 | #ifndef NDEBUG |
249 | if (s_refcnt) { |
250 | if (s_parts && !s_parts->isEmpty()) { |
251 | Q_FOREACH(KHTMLPart *part, *s_parts) { |
252 | kWarning(6000) << "Part" << part->url() << "was not deleted" ; |
253 | } |
254 | } |
255 | if (s_docs && !s_docs->isEmpty()) { |
256 | Q_FOREACH(DOM::DocumentImpl *doc, *s_docs) { |
257 | kWarning(6000) << "Document" << doc->URL() << "was not deleted" ; |
258 | } |
259 | } |
260 | } |
261 | #endif |
262 | } |
263 | |