author | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-06-26 19:01:18 (UTC) |
commit | b9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (unidiff) | |
tree | 2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /microkde/kdecore/klibloader.cpp | |
download | kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2 |
Initial revision
Diffstat (limited to 'microkde/kdecore/klibloader.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | microkde/kdecore/klibloader.cpp | 626 |
1 files changed, 626 insertions, 0 deletions
diff --git a/microkde/kdecore/klibloader.cpp b/microkde/kdecore/klibloader.cpp new file mode 100644 index 0000000..1410308 --- a/dev/null +++ b/microkde/kdecore/klibloader.cpp | |||
@@ -0,0 +1,626 @@ | |||
1 | /* This file is part of the KDE libraries | ||
2 | Copyright (C) 1999 Torben Weis <weis@kde.org> | ||
3 | Copyright (C) 2000 Michael Matz <matz@kde.org> | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public | ||
7 | License version 2 as published by the Free Software Foundation. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this library; see the file COPYING.LIB. If not, write to | ||
16 | the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
17 | Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | //US #include <config.h> | ||
20 | #include <qclipboard.h> | ||
21 | #include <qfile.h> | ||
22 | #include <qtimer.h> | ||
23 | #include <qobjectdict.h> | ||
24 | #include <qwidgetlist.h> | ||
25 | #include <qwidget.h> | ||
26 | |||
27 | #include "kapplication.h" | ||
28 | #include "klibloader.h" | ||
29 | #include "kstandarddirs.h" | ||
30 | #include "kdebug.h" | ||
31 | #include "klocale.h" | ||
32 | |||
33 | //US #include "ltdl.h" | ||
34 | |||
35 | //US do everything through qlibrary | ||
36 | #ifndef DESKTOP_VERSION | ||
37 | #include <qpe/qpeapplication.h> | ||
38 | #include <qtopia/qlibrary.h> | ||
39 | #endif | ||
40 | |||
41 | /*US | ||
42 | #ifdef Q_WS_X11 | ||
43 | #include <X11/Xlib.h> | ||
44 | #include <X11/Xatom.h> | ||
45 | #endif | ||
46 | */ | ||
47 | template class QAsciiDict<KLibrary>; | ||
48 | |||
49 | #include <stdlib.h> //getenv | ||
50 | |||
51 | /*US | ||
52 | #if HAVE_DLFCN_H | ||
53 | # include <dlfcn.h> | ||
54 | #endif | ||
55 | |||
56 | #ifdef RTLD_GLOBAL | ||
57 | # define LT_GLOBAL RTLD_GLOBAL | ||
58 | #else | ||
59 | # ifdef DL_GLOBAL | ||
60 | # define LT_GLOBAL DL_GLOBAL | ||
61 | # endif | ||
62 | #endif | ||
63 | #ifndef LT_GLOBAL | ||
64 | # define LT_GLOBAL 0 | ||
65 | #endif | ||
66 | */ | ||
67 | |||
68 | /*US | ||
69 | extern "C" { | ||
70 | extern int lt_dlopen_flag; | ||
71 | } | ||
72 | */ | ||
73 | |||
74 | KLibFactory::KLibFactory( QObject* parent, const char* name ) | ||
75 | : QObject( parent, name ) | ||
76 | { | ||
77 | } | ||
78 | |||
79 | KLibFactory::~KLibFactory() | ||
80 | { | ||
81 | // kdDebug(150) << "Deleting KLibFactory " << this << endl; | ||
82 | } | ||
83 | |||
84 | QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args ) | ||
85 | { | ||
86 | QObject* obj = createObject( parent, name, classname, args ); | ||
87 | if ( obj ) | ||
88 | emit objectCreated( obj ); | ||
89 | return obj; | ||
90 | } | ||
91 | |||
92 | |||
93 | QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &) | ||
94 | { | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | |||
99 | // ----------------------------------------------- | ||
100 | |||
101 | //US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle ) | ||
102 | KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle ) | ||
103 | { | ||
104 | /* Make sure, we have a KLibLoader */ | ||
105 | (void) KLibLoader::self(); | ||
106 | m_libname = libname; | ||
107 | m_filename = filename; | ||
108 | m_handle = handle; | ||
109 | m_factory = 0; | ||
110 | m_timer = 0; | ||
111 | } | ||
112 | |||
113 | KLibrary::~KLibrary() | ||
114 | { | ||
115 | // kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl; | ||
116 | if ( m_timer && m_timer->isActive() ) | ||
117 | m_timer->stop(); | ||
118 | |||
119 | // If any object is remaining, delete | ||
120 | if ( m_objs.count() > 0 ) | ||
121 | { | ||
122 | QPtrListIterator<QObject> it( m_objs ); | ||
123 | for ( ; it.current() ; ++it ) | ||
124 | { | ||
125 | kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl; | ||
126 | disconnect( it.current(), SIGNAL( destroyed() ), | ||
127 | this, SLOT( slotObjectDestroyed() ) ); | ||
128 | } | ||
129 | m_objs.setAutoDelete(true); | ||
130 | m_objs.clear(); | ||
131 | } | ||
132 | |||
133 | if ( m_factory ) { | ||
134 | //kdDebug(150) << " ... deleting the factory " << m_factory << endl; | ||
135 | delete m_factory; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | QString KLibrary::name() const | ||
140 | { | ||
141 | return m_libname; | ||
142 | } | ||
143 | |||
144 | QString KLibrary::fileName() const | ||
145 | { | ||
146 | return m_filename; | ||
147 | } | ||
148 | |||
149 | KLibFactory* KLibrary::factory() | ||
150 | { | ||
151 | if ( m_factory ) | ||
152 | return m_factory; | ||
153 | |||
154 | QCString symname; | ||
155 | symname.sprintf("init_%s", name().latin1() ); | ||
156 | |||
157 | void* sym = symbol( symname ); | ||
158 | if ( !sym ) | ||
159 | { | ||
160 | kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | typedef KLibFactory* (*t_func)(); | ||
165 | t_func func = (t_func)sym; | ||
166 | m_factory = func(); | ||
167 | |||
168 | if( !m_factory ) | ||
169 | { | ||
170 | kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl; | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | connect( m_factory, SIGNAL( objectCreated( QObject * ) ), | ||
175 | this, SLOT( slotObjectCreated( QObject * ) ) ); | ||
176 | |||
177 | return m_factory; | ||
178 | } | ||
179 | |||
180 | void* KLibrary::symbol( const char* symname ) const | ||
181 | { | ||
182 | //US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); | ||
183 | void* sym = m_handle->resolve( symname ); | ||
184 | if ( !sym ) | ||
185 | { | ||
186 | //US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl; | ||
187 | kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | return sym; | ||
192 | } | ||
193 | |||
194 | bool KLibrary::hasSymbol( const char* symname ) const | ||
195 | { | ||
196 | //US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); | ||
197 | void* sym = m_handle->resolve( symname ); | ||
198 | return (sym != 0L ); | ||
199 | } | ||
200 | |||
201 | void KLibrary::unload() const | ||
202 | { | ||
203 | if (KLibLoader::s_self) | ||
204 | KLibLoader::s_self->unloadLibrary(QFile::encodeName(name())); | ||
205 | } | ||
206 | |||
207 | void KLibrary::slotObjectCreated( QObject *obj ) | ||
208 | { | ||
209 | if ( !obj ) | ||
210 | return; | ||
211 | |||
212 | if ( m_timer && m_timer->isActive() ) | ||
213 | m_timer->stop(); | ||
214 | |||
215 | if ( m_objs.containsRef( obj ) ) | ||
216 | return; // we know this object already | ||
217 | |||
218 | connect( obj, SIGNAL( destroyed() ), | ||
219 | this, SLOT( slotObjectDestroyed() ) ); | ||
220 | |||
221 | m_objs.append( obj ); | ||
222 | } | ||
223 | |||
224 | void KLibrary::slotObjectDestroyed() | ||
225 | { | ||
226 | m_objs.removeRef( sender() ); | ||
227 | |||
228 | if ( m_objs.count() == 0 ) | ||
229 | { | ||
230 | // kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!" | ||
231 | // << endl; | ||
232 | |||
233 | if ( !m_timer ) | ||
234 | { | ||
235 | m_timer = new QTimer( this, "klibrary_shutdown_timer" ); | ||
236 | connect( m_timer, SIGNAL( timeout() ), | ||
237 | this, SLOT( slotTimeout() ) ); | ||
238 | } | ||
239 | |||
240 | // as long as it's not stable make the timeout short, for debugging | ||
241 | // pleasure (matz) | ||
242 | //m_timer->start( 1000*60, true ); | ||
243 | m_timer->start( 1000*10, true ); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | void KLibrary::slotTimeout() | ||
248 | { | ||
249 | if ( m_objs.count() != 0 ) | ||
250 | return; | ||
251 | |||
252 | /* Don't go through KLibLoader::unloadLibrary(), because that uses the | ||
253 | ref counter, but this timeout means to unconditionally close this library | ||
254 | The destroyed() signal will take care to remove us from all lists. | ||
255 | */ | ||
256 | delete this; | ||
257 | } | ||
258 | |||
259 | // ------------------------------------------------- | ||
260 | |||
261 | /* This helper class is needed, because KLibraries can go away without | ||
262 | being unloaded. So we need some info about KLibraries even after its | ||
263 | death. */ | ||
264 | class KLibWrapPrivate | ||
265 | { | ||
266 | public: | ||
267 | //US KLibWrapPrivate(KLibrary *l, lt_dlhandle h); | ||
268 | KLibWrapPrivate(KLibrary *l, QLibrary* h); | ||
269 | |||
270 | KLibrary *lib; | ||
271 | enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; | ||
272 | int ref_count; | ||
273 | //US lt_dlhandle handle; | ||
274 | QLibrary *handle; | ||
275 | QString name; | ||
276 | QString filename; | ||
277 | }; | ||
278 | |||
279 | //US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h) | ||
280 | KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h) | ||
281 | : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName()) | ||
282 | { | ||
283 | unload_mode = UNKNOWN; | ||
284 | /*US | ||
285 | if (lt_dlsym(handle, "__kde_do_not_unload") != 0) { | ||
286 | // kdDebug(150) << "Will not unload " << name << endl; | ||
287 | unload_mode = DONT_UNLOAD; | ||
288 | } else if (lt_dlsym(handle, "__kde_do_unload") != 0) { | ||
289 | unload_mode = UNLOAD; | ||
290 | } | ||
291 | */ | ||
292 | //US use instead: | ||
293 | if (h->resolve("__kde_do_not_unload") != 0) { | ||
294 | // kdDebug(150) << "Will not unload " << name << endl; | ||
295 | unload_mode = DONT_UNLOAD; | ||
296 | } else if (h->resolve("__kde_do_unload") != 0) { | ||
297 | unload_mode = UNLOAD; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | class KLibLoaderPrivate | ||
302 | { | ||
303 | public: | ||
304 | QPtrList<KLibWrapPrivate> loaded_stack; | ||
305 | QPtrList<KLibWrapPrivate> pending_close; | ||
306 | enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; | ||
307 | |||
308 | QString errorMessage; | ||
309 | }; | ||
310 | |||
311 | KLibLoader* KLibLoader::s_self = 0; | ||
312 | |||
313 | KLibLoader* KLibLoader::self() | ||
314 | { | ||
315 | if ( !s_self ) | ||
316 | s_self = new KLibLoader; | ||
317 | return s_self; | ||
318 | } | ||
319 | |||
320 | void KLibLoader::cleanUp() | ||
321 | { | ||
322 | if ( !s_self ) | ||
323 | return; | ||
324 | |||
325 | delete s_self; | ||
326 | s_self = 0; | ||
327 | } | ||
328 | |||
329 | KLibLoader::KLibLoader( QObject* parent, const char* name ) | ||
330 | : QObject( parent, name ) | ||
331 | { | ||
332 | s_self = this; | ||
333 | d = new KLibLoaderPrivate; | ||
334 | //US lt_dlinit(); | ||
335 | d->unload_mode = KLibLoaderPrivate::UNKNOWN; | ||
336 | if (getenv("KDE_NOUNLOAD") != 0) | ||
337 | d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD; | ||
338 | else if (getenv("KDE_DOUNLOAD") != 0) | ||
339 | d->unload_mode = KLibLoaderPrivate::UNLOAD; | ||
340 | d->loaded_stack.setAutoDelete( true ); | ||
341 | } | ||
342 | |||
343 | KLibLoader::~KLibLoader() | ||
344 | { | ||
345 | // kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl; | ||
346 | |||
347 | QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); | ||
348 | for (; it.current(); ++it ) | ||
349 | { | ||
350 | kdDebug(150) << "The KLibLoader contains the library " << it.current()->name | ||
351 | << " (" << it.current()->lib << ")" << endl; | ||
352 | d->pending_close.append(it.current()); | ||
353 | } | ||
354 | |||
355 | close_pending(0); | ||
356 | |||
357 | delete d; | ||
358 | } | ||
359 | |||
360 | //static | ||
361 | QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ ) | ||
362 | { | ||
363 | QCString libname( name ); | ||
364 | |||
365 | // only append ".la" if there is no extension | ||
366 | // this allows to load non-libtool libraries as well | ||
367 | // (mhk, 20000228) | ||
368 | int pos = libname.findRev('/'); | ||
369 | if (pos < 0) | ||
370 | pos = 0; | ||
371 | if (libname.find('.', pos) < 0) | ||
372 | libname += ".la"; | ||
373 | |||
374 | // only look up the file if it is not an absolute filename | ||
375 | // (mhk, 20000228) | ||
376 | QString libfile; | ||
377 | if (libname[0] == '/') | ||
378 | libfile = libname; | ||
379 | else | ||
380 | { | ||
381 | //US libfile = instance->dirs()->findResource( "module", libname ); | ||
382 | libfile = KGlobal::dirs()->findResource( "module", libname ); | ||
383 | if ( libfile.isEmpty() ) | ||
384 | { | ||
385 | //US libfile = instance->dirs()->findResource( "lib", libname ); | ||
386 | libfile = KGlobal::dirs()->findResource( "lib", libname ); | ||
387 | #ifndef NDEBUG | ||
388 | if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules | ||
389 | kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl; | ||
390 | #endif | ||
391 | } | ||
392 | if ( libfile.isEmpty() ) | ||
393 | { | ||
394 | #ifndef NDEBUG | ||
395 | kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl; | ||
396 | #endif | ||
397 | self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname); | ||
398 | } | ||
399 | else | ||
400 | self()->d->errorMessage = QString::null; | ||
401 | } | ||
402 | return libfile; | ||
403 | } | ||
404 | |||
405 | |||
406 | KLibrary* KLibLoader::globalLibrary( const char *name ) | ||
407 | { | ||
408 | KLibrary *tmp; | ||
409 | /*US | ||
410 | int olt_dlopen_flag = lt_dlopen_flag; | ||
411 | |||
412 | lt_dlopen_flag |= LT_GLOBAL; | ||
413 | kdDebug(150) << "Loading the next library global with flag " | ||
414 | << lt_dlopen_flag | ||
415 | << "." << endl; | ||
416 | */ | ||
417 | tmp = library(name); | ||
418 | /*US | ||
419 | lt_dlopen_flag = olt_dlopen_flag; | ||
420 | */ | ||
421 | return tmp; | ||
422 | } | ||
423 | |||
424 | |||
425 | KLibrary* KLibLoader::library( const char *name ) | ||
426 | { | ||
427 | if (!name) | ||
428 | return 0; | ||
429 | |||
430 | KLibWrapPrivate* wrap = m_libs[name]; | ||
431 | if (wrap) { | ||
432 | /* Nothing to do to load the library. */ | ||
433 | wrap->ref_count++; | ||
434 | return wrap->lib; | ||
435 | } | ||
436 | |||
437 | /* Test if this library was loaded at some time, but got | ||
438 | unloaded meanwhile, whithout being dlclose()'ed. */ | ||
439 | QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack); | ||
440 | for (; it.current(); ++it) { | ||
441 | if (it.current()->name == name) | ||
442 | wrap = it.current(); | ||
443 | } | ||
444 | |||
445 | if (wrap) { | ||
446 | d->pending_close.removeRef(wrap); | ||
447 | if (!wrap->lib) { | ||
448 | /* This lib only was in loaded_stack, but not in m_libs. */ | ||
449 | wrap->lib = new KLibrary( name, wrap->filename, wrap->handle ); | ||
450 | } | ||
451 | wrap->ref_count++; | ||
452 | } else { | ||
453 | QString libfile = findLibrary( name ); | ||
454 | if ( libfile.isEmpty() ) | ||
455 | return 0; | ||
456 | |||
457 | const QString & qpeDir = QPEApplication::qpeDir(); | ||
458 | libfile = qpeDir + libfile; | ||
459 | //US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately ); | ||
460 | QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately ); | ||
461 | |||
462 | //US lt_dlhandle handle = lt_dlopen( libfile.latin1() ); | ||
463 | //US if ( !handle ) | ||
464 | if ( !qlib ) | ||
465 | { | ||
466 | //US const char* errmsg = lt_dlerror(); | ||
467 | char* errmsg; | ||
468 | sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1()); | ||
469 | qDebug(errmsg); | ||
470 | |||
471 | if(errmsg) | ||
472 | d->errorMessage = QString::fromLatin1(errmsg); | ||
473 | else | ||
474 | d->errorMessage = QString::null; | ||
475 | kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl; | ||
476 | return 0; | ||
477 | } | ||
478 | else | ||
479 | d->errorMessage = QString::null; | ||
480 | |||
481 | KLibrary *lib = new KLibrary( name, libfile, qlib ); | ||
482 | wrap = new KLibWrapPrivate(lib, qlib); | ||
483 | d->loaded_stack.prepend(wrap); | ||
484 | } | ||
485 | m_libs.insert( name, wrap ); | ||
486 | |||
487 | connect( wrap->lib, SIGNAL( destroyed() ), | ||
488 | this, SLOT( slotLibraryDestroyed() ) ); | ||
489 | |||
490 | return wrap->lib; | ||
491 | } | ||
492 | |||
493 | QString KLibLoader::lastErrorMessage() const | ||
494 | { | ||
495 | return d->errorMessage; | ||
496 | } | ||
497 | |||
498 | void KLibLoader::unloadLibrary( const char *libname ) | ||
499 | { | ||
500 | KLibWrapPrivate *wrap = m_libs[ libname ]; | ||
501 | if (!wrap) | ||
502 | return; | ||
503 | if (--wrap->ref_count) | ||
504 | return; | ||
505 | |||
506 | // kdDebug(150) << "closing library " << libname << endl; | ||
507 | |||
508 | m_libs.remove( libname ); | ||
509 | |||
510 | disconnect( wrap->lib, SIGNAL( destroyed() ), | ||
511 | this, SLOT( slotLibraryDestroyed() ) ); | ||
512 | close_pending( wrap ); | ||
513 | } | ||
514 | |||
515 | KLibFactory* KLibLoader::factory( const char* name ) | ||
516 | { | ||
517 | KLibrary* lib = library( name ); | ||
518 | if ( !lib ) | ||
519 | return 0; | ||
520 | |||
521 | return lib->factory(); | ||
522 | } | ||
523 | |||
524 | void KLibLoader::slotLibraryDestroyed() | ||
525 | { | ||
526 | const KLibrary *lib = static_cast<const KLibrary *>( sender() ); | ||
527 | |||
528 | QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); | ||
529 | for (; it.current(); ++it ) | ||
530 | if ( it.current()->lib == lib ) | ||
531 | { | ||
532 | KLibWrapPrivate *wrap = it.current(); | ||
533 | wrap->lib = 0; /* the KLibrary object is already away */ | ||
534 | m_libs.remove( it.currentKey() ); | ||
535 | close_pending( wrap ); | ||
536 | return; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | void KLibLoader::close_pending(KLibWrapPrivate *wrap) | ||
541 | { | ||
542 | if (wrap && !d->pending_close.containsRef( wrap )) | ||
543 | d->pending_close.append( wrap ); | ||
544 | |||
545 | /* First delete all KLibrary objects in pending_close, but _don't_ unload | ||
546 | the DSO behind it. */ | ||
547 | QPtrListIterator<KLibWrapPrivate> it(d->pending_close); | ||
548 | for (; it.current(); ++it) { | ||
549 | wrap = it.current(); | ||
550 | if (wrap->lib) { | ||
551 | disconnect( wrap->lib, SIGNAL( destroyed() ), | ||
552 | this, SLOT( slotLibraryDestroyed() ) ); | ||
553 | delete wrap->lib; | ||
554 | wrap->lib = 0; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return; | ||
559 | |||
560 | bool deleted_one = false; | ||
561 | while ((wrap = d->loaded_stack.first())) { | ||
562 | /* Let's first see, if we want to try to unload this lib. | ||
563 | If the env. var KDE_DOUNLOAD is set, we try to unload every lib. | ||
564 | If not, we look at the lib itself, and unload it only, if it exports | ||
565 | the symbol __kde_do_unload. */ | ||
566 | if (d->unload_mode != KLibLoaderPrivate::UNLOAD | ||
567 | && wrap->unload_mode != KLibWrapPrivate::UNLOAD) | ||
568 | break; | ||
569 | |||
570 | /* Now ensure, that the libs are only unloaded in the reverse direction | ||
571 | they were loaded. */ | ||
572 | if (!d->pending_close.containsRef( wrap )) { | ||
573 | if (!deleted_one) | ||
574 | /* Only diagnose, if we really haven't deleted anything. */ | ||
575 | // kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl; | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | // kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl; | ||
580 | |||
581 | #ifndef Q_WS_QWS | ||
582 | if ( !deleted_one ) { | ||
583 | /* Only do the hack once in this loop. | ||
584 | WABA: *HACK* | ||
585 | We need to make sure to clear the clipboard before unloading a DSO | ||
586 | because the DSO could have defined an object derived from QMimeSource | ||
587 | and placed that on the clipboard. */ | ||
588 | /*kapp->clipboard()->clear();*/ | ||
589 | |||
590 | /* Well.. let's do something more subtle... convert the clipboard context | ||
591 | to text. That should be safe as it only uses objects defined by Qt. */ | ||
592 | |||
593 | QWidgetList *widgetlist = QApplication::topLevelWidgets(); | ||
594 | QWidget *co = widgetlist->first(); | ||
595 | while (co) { | ||
596 | if (qstrcmp(co->name(), "internal clipboard owner") == 0) { | ||
597 | if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId()) | ||
598 | kapp->clipboard()->setText(kapp->clipboard()->text()); | ||
599 | |||
600 | break; | ||
601 | } | ||
602 | co = widgetlist->next(); | ||
603 | } | ||
604 | delete widgetlist; | ||
605 | } | ||
606 | #else | ||
607 | // FIXME(E): Implement in Qt Embedded | ||
608 | #endif | ||
609 | |||
610 | deleted_one = true; | ||
611 | //US lt_dlclose(wrap->handle); | ||
612 | wrap->handle->unload(); | ||
613 | |||
614 | d->pending_close.removeRef(wrap); | ||
615 | /* loaded_stack is AutoDelete, so wrap is freed */ | ||
616 | d->loaded_stack.remove(); | ||
617 | } | ||
618 | } | ||
619 | |||
620 | void KLibLoader::virtual_hook( int, void* ) | ||
621 | { /*BASE::virtual_hook( id, data );*/ } | ||
622 | |||
623 | void KLibFactory::virtual_hook( int, void* ) | ||
624 | { /*BASE::virtual_hook( id, data );*/ } | ||
625 | |||
626 | //US #include "klibloader.moc" | ||