22 #include <tqclipboard.h>
26 #include <tqobjectdict.h>
28 #include "kapplication.h"
29 #include "klibloader.h"
30 #include "kstandarddirs.h"
36 template class TQAsciiDict<KLibrary>;
46 # define LT_GLOBAL RTLD_GLOBAL
49 # define LT_GLOBAL DL_GLOBAL
57 class KLibLoaderPrivate
60 TQPtrList<KLibWrapPrivate> loaded_stack;
61 TQPtrList<KLibWrapPrivate> pending_close;
62 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
64 TQString errorMessage;
72 : TQObject( parent, name )
76 KLibFactory::~KLibFactory()
81 TQObject*
KLibFactory::create( TQObject* parent,
const char* name,
const char* classname,
const TQStringList &args )
83 TQObject* obj =
createObject( parent, name, classname, args );
103 m_filename = filename;
109 KLibrary::~KLibrary()
112 if ( m_timer && m_timer->isActive() )
116 if ( m_objs.count() > 0 )
118 TQPtrListIterator<TQObject> it( m_objs );
119 for ( ; it.current() ; ++it )
121 kdDebug(150) <<
"Factory still has object " << it.current() <<
" " << it.current()->name () <<
" Library = " << m_libname <<
endl;
122 disconnect( it.current(), TQT_SIGNAL( destroyed() ),
123 this, TQT_SLOT( slotObjectDestroyed() ) );
125 m_objs.setAutoDelete(
true);
152 symname.sprintf(
"init_%s",
name().latin1() );
154 void* sym =
symbol( symname );
157 KLibLoader::self()->d->errorMessage = i18n(
"The library %1 does not offer an %2 function." ).arg(
name(),
"init_" +
name() );
163 t_func func = (t_func)sym;
168 KLibLoader::self()->d->errorMessage = i18n(
"The library %1 does not offer a KDE compatible factory." ).arg(
name() );
173 connect( m_factory, TQT_SIGNAL( objectCreated( TQObject * ) ),
174 this, TQT_SLOT( slotObjectCreated( TQObject * ) ) );
181 void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
184 KLibLoader::self()->d->errorMessage =
"KLibrary: " + TQString::fromLocal8Bit( lt_dlerror() );
194 void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
200 if (KLibLoader::s_self)
204 void KLibrary::slotObjectCreated( TQObject *obj )
209 if ( m_timer && m_timer->isActive() )
212 if ( m_objs.containsRef( obj ) )
215 connect( obj, TQT_SIGNAL( destroyed() ),
216 this, TQT_SLOT( slotObjectDestroyed() ) );
218 m_objs.append( obj );
221 void KLibrary::slotObjectDestroyed()
223 m_objs.removeRef( TQT_TQOBJECT_CONST(sender()) );
225 if ( m_objs.count() == 0 )
232 m_timer =
new TQTimer(
this,
"klibrary_shutdown_timer" );
233 connect( m_timer, TQT_SIGNAL( timeout() ),
234 this, TQT_SLOT( slotTimeout() ) );
240 m_timer->start( 1000*10,
true );
244 void KLibrary::slotTimeout()
246 if ( m_objs.count() != 0 )
261 class KLibWrapPrivate
264 KLibWrapPrivate(
KLibrary *l, lt_dlhandle h);
267 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
274 KLibWrapPrivate::KLibWrapPrivate(
KLibrary *l, lt_dlhandle h)
275 : lib(l), ref_count(1), handle(h),
name(l->
name()), filename(l->fileName())
277 unload_mode = UNKNOWN;
278 if (lt_dlsym(handle,
"__kde_do_not_unload") != 0) {
280 unload_mode = DONT_UNLOAD;
281 }
else if (lt_dlsym(handle,
"__kde_do_unload") != 0) {
282 unload_mode = UNLOAD;
293 void KLibLoader::cleanUp()
302 KLibLoader::KLibLoader( TQObject* parent,
const char* name )
303 : TQObject( parent, name )
306 d =
new KLibLoaderPrivate;
308 d->unload_mode = KLibLoaderPrivate::UNKNOWN;
309 if (getenv(
"KDE_NOUNLOAD") != 0)
310 d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD;
311 else if (getenv(
"KDE_DOUNLOAD") != 0)
312 d->unload_mode = KLibLoaderPrivate::UNLOAD;
313 d->loaded_stack.setAutoDelete(
true );
320 TQAsciiDictIterator<KLibWrapPrivate> it( m_libs );
321 for (; it.current(); ++it )
323 kdDebug(150) <<
"The KLibLoader contains the library " << it.current()->name
324 <<
" (" << it.current()->lib <<
")" <<
endl;
325 d->pending_close.append(it.current());
334 static inline TQCString makeLibName(
const char* name )
336 TQCString libname(name);
340 int pos = libname.findRev(
'/');
343 if (libname.find(
'.', pos) < 0)
351 TQCString libname = makeLibName( name );
356 if (!TQDir::isRelativePath(libname))
357 libfile = TQFile::decodeName( libname );
361 if ( libfile.isEmpty() )
365 if ( !libfile.isEmpty() && libname.left(3) ==
"lib" )
366 kdDebug(150) <<
"library " << libname <<
" not found under 'module' but under 'lib'" <<
endl;
377 int olt_dlopen_flag = lt_dlopen_flag;
379 lt_dlopen_flag |= LT_GLOBAL;
380 kdDebug(150) <<
"Loading the next library global with flag "
384 lt_dlopen_flag = olt_dlopen_flag;
395 KLibWrapPrivate* wrap = m_libs[name];
404 TQPtrListIterator<KLibWrapPrivate> it(d->loaded_stack);
405 for (; it.current(); ++it) {
406 if (it.current()->name == name)
411 d->pending_close.removeRef(wrap);
414 wrap->lib =
new KLibrary( name, wrap->filename, wrap->handle );
419 if ( libfile.isEmpty() )
421 const TQCString libname = makeLibName( name );
423 kdDebug(150) <<
"library=" << name <<
": No file named " << libname <<
" found in paths." <<
endl;
425 d->errorMessage = i18n(
"Library files for \"%1\" not found in paths.").arg(TQString(libname));
429 lt_dlhandle handle = lt_dlopen( TQFile::encodeName(libfile) );
432 const char* errmsg = lt_dlerror();
434 d->errorMessage = TQString::fromLocal8Bit(errmsg);
436 d->errorMessage = TQString::null;
440 d->errorMessage = TQString::null;
443 wrap =
new KLibWrapPrivate(lib, handle);
444 d->loaded_stack.prepend(wrap);
446 m_libs.insert( name, wrap );
448 connect( wrap->lib, TQT_SIGNAL( destroyed() ),
449 this, TQT_SLOT( slotLibraryDestroyed() ) );
456 return d->errorMessage;
461 KLibWrapPrivate *wrap = m_libs[ libname ];
464 if (--wrap->ref_count)
469 m_libs.remove( libname );
471 disconnect( wrap->lib, TQT_SIGNAL( destroyed() ),
472 this, TQT_SLOT( slotLibraryDestroyed() ) );
473 close_pending( wrap );
485 void KLibLoader::slotLibraryDestroyed()
489 TQAsciiDictIterator<KLibWrapPrivate> it( m_libs );
490 for (; it.current(); ++it )
491 if ( it.current()->lib == lib )
493 KLibWrapPrivate *wrap = it.current();
495 m_libs.remove( it.currentKey() );
496 close_pending( wrap );
501 void KLibLoader::close_pending(KLibWrapPrivate *wrap)
503 if (wrap && !d->pending_close.containsRef( wrap ))
504 d->pending_close.append( wrap );
508 TQPtrListIterator<KLibWrapPrivate> it(d->pending_close);
509 for (; it.current(); ++it) {
512 disconnect( wrap->lib, TQT_SIGNAL( destroyed() ),
513 this, TQT_SLOT( slotLibraryDestroyed() ) );
520 if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) {
521 d->pending_close.clear();
525 bool deleted_one =
false;
526 while ((wrap = d->loaded_stack.first())) {
531 if (d->unload_mode != KLibLoaderPrivate::UNLOAD
532 && wrap->unload_mode != KLibWrapPrivate::UNLOAD)
537 if (!d->pending_close.containsRef( wrap )) {
546 if ( !deleted_one ) {
556 if( kapp->clipboard()->ownsSelection()) {
557 kapp->clipboard()->setText(
558 kapp->clipboard()->text( TQClipboard::Selection ), TQClipboard::Selection );
560 if( kapp->clipboard()->ownsClipboard()) {
561 kapp->clipboard()->setText(
562 kapp->clipboard()->text( TQClipboard::Clipboard ), TQClipboard::Clipboard );
567 lt_dlclose(wrap->handle);
568 d->pending_close.removeRef(wrap);
570 d->loaded_stack.remove();
574 void KLibLoader::virtual_hook(
int,
void* )
577 void KLibFactory::virtual_hook(
int,
void* )
580 #include "klibloader.moc"