summaryrefslogtreecommitdiffabout
path: root/microkde/kdecore
authorzautrix <zautrix>2004-06-26 19:01:18 (UTC)
committer zautrix <zautrix>2004-06-26 19:01:18 (UTC)
commitb9aad1f15dc600e4dbe4c62d3fcced6363188ba3 (patch) (side-by-side diff)
tree2c3d4004fb21c72cba65793859f9bcd8ffd3a49c /microkde/kdecore
downloadkdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.zip
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.gz
kdepimpi-b9aad1f15dc600e4dbe4c62d3fcced6363188ba3.tar.bz2
Initial revision
Diffstat (limited to 'microkde/kdecore') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/kdecore/kcatalogue.cpp131
-rw-r--r--microkde/kdecore/kcatalogue.h104
-rw-r--r--microkde/kdecore/kconfigbase.h102
-rw-r--r--microkde/kdecore/klibloader.cpp626
-rw-r--r--microkde/kdecore/klibloader.h405
-rw-r--r--microkde/kdecore/klocale.cpp881
-rw-r--r--microkde/kdecore/klocale.h110
-rw-r--r--microkde/kdecore/klocale_new.cpp2441
-rw-r--r--microkde/kdecore/klocale_new.h1224
-rw-r--r--microkde/kdecore/kmdcodec.cpp1127
-rw-r--r--microkde/kdecore/kmdcodec.h572
-rw-r--r--microkde/kdecore/ksharedptr.h171
-rw-r--r--microkde/kdecore/kshell.cpp386
-rw-r--r--microkde/kdecore/kshell.h143
-rw-r--r--microkde/kdecore/kshortcut.h846
-rw-r--r--microkde/kdecore/kstandarddirs.cpp1620
-rw-r--r--microkde/kdecore/kstandarddirs.h681
-rw-r--r--microkde/kdecore/kstringhandler.cpp650
-rw-r--r--microkde/kdecore/kstringhandler.h417
19 files changed, 12637 insertions, 0 deletions
diff --git a/microkde/kdecore/kcatalogue.cpp b/microkde/kdecore/kcatalogue.cpp
new file mode 100644
index 0000000..97ac326
--- a/dev/null
+++ b/microkde/kdecore/kcatalogue.cpp
@@ -0,0 +1,131 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//US #include <config.h>
+
+#include <qfile.h>
+
+#include <kdebug.h>
+
+#include "kcatalogue.h"
+
+char *k_nl_find_msg(struct kde_loaded_l10nfile *domain_file,
+ const char *msgid);
+void k_nl_unload_domain (struct loaded_domain *domain);
+
+#ifndef KDE_USE_FINAL // with --enable-final, we're getting this from libintl.cpp
+struct kde_loaded_l10nfile
+{
+ const char *filename;
+ int decided;
+
+ const void *data;
+
+ kde_loaded_l10nfile() : filename(0), decided(0), data(0) {}
+};
+#endif
+
+class KCataloguePrivate
+{
+public:
+ QString name;
+
+ kde_loaded_l10nfile domain;
+};
+
+KCatalogue::KCatalogue(const QString & name)
+ : d( new KCataloguePrivate )
+{
+ d->name = name;
+}
+
+KCatalogue::KCatalogue(const KCatalogue & rhs)
+ : d( new KCataloguePrivate )
+{
+ *this = rhs;
+}
+
+KCatalogue & KCatalogue::operator=(const KCatalogue & rhs)
+{
+ d->name = rhs.d->name;
+ setFileName( rhs.fileName() );
+
+ return *this;
+}
+
+KCatalogue::~KCatalogue()
+{
+ doUnload();
+
+ delete d;
+}
+
+QString KCatalogue::name() const
+{
+ return d->name;
+}
+
+void KCatalogue::setFileName( const QString & fileName )
+{
+ // nothing to do if the file name is already the same
+ if ( this->fileName() == fileName ) return;
+
+ doUnload();
+
+ QCString newFileName = QFile::encodeName( fileName );
+
+ if ( !fileName.isEmpty() )
+ {
+ // set file name
+ char *filename = new char[ newFileName.length() + 1 ];
+ ::qstrcpy( filename, newFileName );
+ d->domain.filename = filename;
+ }
+}
+
+QString KCatalogue::fileName() const
+{
+ return QFile::decodeName( d->domain.filename );
+}
+
+const char * KCatalogue::translate(const char * msgid) const
+{
+ qDebug("KCatalogue::translate has to be fixed %s",msgid );
+//US return ::k_nl_find_msg( &d->domain, msgid );
+ return msgid;
+
+}
+
+void KCatalogue::doUnload()
+{
+ // use gettext's unloader
+ if ( d->domain.data )
+ {
+//US ::k_nl_unload_domain( (struct loaded_domain *)d->domain.data );
+ qDebug("KCatalogue::doUnload has to be fixed" );
+
+ }
+ d->domain.data = 0;
+
+ // free name
+ delete [] const_cast<char *>(d->domain.filename);
+ d->domain.filename = 0;
+
+ d->domain.decided = 0;
+}
diff --git a/microkde/kdecore/kcatalogue.h b/microkde/kdecore/kcatalogue.h
new file mode 100644
index 0000000..e229cc8
--- a/dev/null
+++ b/microkde/kdecore/kcatalogue.h
@@ -0,0 +1,104 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KCATALOGUE_H
+#define KCATALOGUE_H
+
+#include <qstring.h>
+
+struct kde_loaded_l10nfile;
+
+class KCataloguePrivate;
+
+/**
+ * This class abstracts a gettext message catalogue. It will take care of
+ * opening the file and reading the catalogue.
+ *
+ * @see KLocale
+ */
+//REVISED: hausmann
+class KCatalogue
+{
+public:
+ /**
+ * Constructor.
+ *
+ * @param name The name of the catalogue
+ */
+ explicit KCatalogue(const QString & name = QString::null);
+
+ /**
+ * Copy constructor.
+ */
+ KCatalogue(const KCatalogue & rhs);
+
+ /**
+ * Assignment operator.
+ */
+ KCatalogue & operator = ( const KCatalogue & rhs);
+
+ /**
+ * Destructor.
+ */
+ virtual ~KCatalogue();
+
+ /**
+ * Returns the name of the catalogue.
+ *
+ * @return The name of the catalogue
+ */
+ QString name() const;
+
+ /**
+ * Changes the current file name.
+ *
+ * @param fileName The new file name
+ */
+
+ void setFileName( const QString & fileName );
+
+ /**
+ * Retrieves a translation of the specified message id.
+ *
+ * Do not pass 0 or "" strings as message ids.
+ *
+ * @param msgid The message id
+ *
+ * @return The translated message, in utf8 encoding, or 0 if not found
+ */
+ const char * translate( const char * msgid ) const;
+
+private:
+ /**
+ * @internal Retrieves the current file name.
+ *
+ * @return The current file name, if any.
+ */
+ QString fileName() const;
+
+ /**
+ * @internal Unloads the current file.
+ */
+ void doUnload();
+
+private:
+ KCataloguePrivate * d;
+};
+
+#endif
diff --git a/microkde/kdecore/kconfigbase.h b/microkde/kdecore/kconfigbase.h
new file mode 100644
index 0000000..7e56d11
--- a/dev/null
+++ b/microkde/kdecore/kconfigbase.h
@@ -0,0 +1,102 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
+ Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+// $Id$
+
+#ifndef _KCONFIGBASE_H
+#define _KCONFIGBASE_H
+
+#include "kconfig.h"
+
+/**
+ * Helper class to facilitate working with @ref KConfig / @ref KSimpleConfig
+ * groups.
+ *
+ * Careful programmers always set the group of a
+ * @ref KConfig @ref KSimpleConfig object to the group they want to read from
+ * and set it back to the old one of afterwards. This is usually
+ * written as:
+ * <pre>
+ *
+ * QString oldgroup config->group();
+ * config->setGroup( "TheGroupThatIWant" );
+ * ...
+ * config->writeEntry( "Blah", "Blubb" );
+ *
+ * config->setGroup( oldgroup );
+ * </pre>
+ *
+ * In order to facilitate this task, you can use
+ * KConfigGroupSaver. Simply construct such an object ON THE STACK
+ * when you want to switch to a new group. Then, when the object goes
+ * out of scope, the group will automatically be restored. If you
+ * want to use several different groups within a function or method,
+ * you can still use KConfigGroupSaver: Simply enclose all work with
+ * one group (including the creation of the KConfigGroupSaver object)
+ * in one block.
+ *
+ * @author Matthias Kalle Dalheimer <kalle@kde.org>
+ * @version $Id$
+ * @see KConfigBase, KConfig, KSimpleConfig
+ * @short Helper class for easier use of KConfig/KSimpleConfig groups
+ */
+//US I converted the class in a way that it can be used with KConfig objects of microkde
+
+class KConfigGroupSaver
+{
+public:
+ /**
+ * Constructor. You pass a pointer to the KConfigBase-derived
+ * object you want to work with and a string indicating the _new_
+ * group.
+ *
+ * @param config The KConfigBase-derived object this
+ * KConfigGroupSaver works on.
+ * @param group The new group that the config object should switch to.
+ */
+ KConfigGroupSaver( KConfig* config, QString group )
+ /* KDE 4 : make the second parameter const QString & */
+ : _config(config), _oldgroup(config->group())
+ { _config->setGroup( group ); }
+
+ KConfigGroupSaver( KConfig* config, const char *group )
+ : _config(config), _oldgroup(config->group())
+ { _config->setGroup( group ); }
+
+ KConfigGroupSaver( KConfig* config, const QCString &group )
+ : _config(config), _oldgroup(config->group())
+ { _config->setGroup( group ); }
+
+ ~KConfigGroupSaver() { _config->setGroup( _oldgroup ); }
+
+ KConfig* config() { return _config; };
+
+private:
+ KConfig* _config;
+ QString _oldgroup;
+
+ KConfigGroupSaver(const KConfigGroupSaver&);
+ KConfigGroupSaver& operator=(const KConfigGroupSaver&);
+
+};
+
+#endif
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 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Torben Weis <weis@kde.org>
+ Copyright (C) 2000 Michael Matz <matz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+//US #include <config.h>
+#include <qclipboard.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <qobjectdict.h>
+#include <qwidgetlist.h>
+#include <qwidget.h>
+
+#include "kapplication.h"
+#include "klibloader.h"
+#include "kstandarddirs.h"
+#include "kdebug.h"
+#include "klocale.h"
+
+//US #include "ltdl.h"
+
+//US do everything through qlibrary
+#ifndef DESKTOP_VERSION
+#include <qpe/qpeapplication.h>
+#include <qtopia/qlibrary.h>
+#endif
+
+/*US
+#ifdef Q_WS_X11
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#endif
+*/
+template class QAsciiDict<KLibrary>;
+
+#include <stdlib.h> //getenv
+
+/*US
+#if HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#ifdef RTLD_GLOBAL
+# define LT_GLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_GLOBAL DL_GLOBAL
+# endif
+#endif
+#ifndef LT_GLOBAL
+# define LT_GLOBAL 0
+#endif
+*/
+
+/*US
+extern "C" {
+extern int lt_dlopen_flag;
+}
+*/
+
+KLibFactory::KLibFactory( QObject* parent, const char* name )
+ : QObject( parent, name )
+{
+}
+
+KLibFactory::~KLibFactory()
+{
+// kdDebug(150) << "Deleting KLibFactory " << this << endl;
+}
+
+QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args )
+{
+ QObject* obj = createObject( parent, name, classname, args );
+ if ( obj )
+ emit objectCreated( obj );
+ return obj;
+}
+
+
+QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &)
+{
+ return 0;
+}
+
+
+// -----------------------------------------------
+
+//US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle )
+KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle )
+{
+ /* Make sure, we have a KLibLoader */
+ (void) KLibLoader::self();
+ m_libname = libname;
+ m_filename = filename;
+ m_handle = handle;
+ m_factory = 0;
+ m_timer = 0;
+}
+
+KLibrary::~KLibrary()
+{
+// kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl;
+ if ( m_timer && m_timer->isActive() )
+ m_timer->stop();
+
+ // If any object is remaining, delete
+ if ( m_objs.count() > 0 )
+ {
+ QPtrListIterator<QObject> it( m_objs );
+ for ( ; it.current() ; ++it )
+ {
+ kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl;
+ disconnect( it.current(), SIGNAL( destroyed() ),
+ this, SLOT( slotObjectDestroyed() ) );
+ }
+ m_objs.setAutoDelete(true);
+ m_objs.clear();
+ }
+
+ if ( m_factory ) {
+// kdDebug(150) << " ... deleting the factory " << m_factory << endl;
+ delete m_factory;
+ }
+}
+
+QString KLibrary::name() const
+{
+ return m_libname;
+}
+
+QString KLibrary::fileName() const
+{
+ return m_filename;
+}
+
+KLibFactory* KLibrary::factory()
+{
+ if ( m_factory )
+ return m_factory;
+
+ QCString symname;
+ symname.sprintf("init_%s", name().latin1() );
+
+ void* sym = symbol( symname );
+ if ( !sym )
+ {
+ kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl;
+ return 0;
+ }
+
+ typedef KLibFactory* (*t_func)();
+ t_func func = (t_func)sym;
+ m_factory = func();
+
+ if( !m_factory )
+ {
+ kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl;
+ return 0;
+ }
+
+ connect( m_factory, SIGNAL( objectCreated( QObject * ) ),
+ this, SLOT( slotObjectCreated( QObject * ) ) );
+
+ return m_factory;
+}
+
+void* KLibrary::symbol( const char* symname ) const
+{
+//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
+ void* sym = m_handle->resolve( symname );
+ if ( !sym )
+ {
+//US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl;
+ kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl;
+ return 0;
+ }
+
+ return sym;
+}
+
+bool KLibrary::hasSymbol( const char* symname ) const
+{
+//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
+ void* sym = m_handle->resolve( symname );
+ return (sym != 0L );
+}
+
+void KLibrary::unload() const
+{
+ if (KLibLoader::s_self)
+ KLibLoader::s_self->unloadLibrary(QFile::encodeName(name()));
+}
+
+void KLibrary::slotObjectCreated( QObject *obj )
+{
+ if ( !obj )
+ return;
+
+ if ( m_timer && m_timer->isActive() )
+ m_timer->stop();
+
+ if ( m_objs.containsRef( obj ) )
+ return; // we know this object already
+
+ connect( obj, SIGNAL( destroyed() ),
+ this, SLOT( slotObjectDestroyed() ) );
+
+ m_objs.append( obj );
+}
+
+void KLibrary::slotObjectDestroyed()
+{
+ m_objs.removeRef( sender() );
+
+ if ( m_objs.count() == 0 )
+ {
+// kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!"
+// << endl;
+
+ if ( !m_timer )
+ {
+ m_timer = new QTimer( this, "klibrary_shutdown_timer" );
+ connect( m_timer, SIGNAL( timeout() ),
+ this, SLOT( slotTimeout() ) );
+ }
+
+ // as long as it's not stable make the timeout short, for debugging
+ // pleasure (matz)
+ //m_timer->start( 1000*60, true );
+ m_timer->start( 1000*10, true );
+ }
+}
+
+void KLibrary::slotTimeout()
+{
+ if ( m_objs.count() != 0 )
+ return;
+
+ /* Don't go through KLibLoader::unloadLibrary(), because that uses the
+ ref counter, but this timeout means to unconditionally close this library
+ The destroyed() signal will take care to remove us from all lists.
+ */
+ delete this;
+}
+
+// -------------------------------------------------
+
+/* This helper class is needed, because KLibraries can go away without
+ being unloaded. So we need some info about KLibraries even after its
+ death. */
+class KLibWrapPrivate
+{
+public:
+//US KLibWrapPrivate(KLibrary *l, lt_dlhandle h);
+ KLibWrapPrivate(KLibrary *l, QLibrary* h);
+
+ KLibrary *lib;
+ enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
+ int ref_count;
+//US lt_dlhandle handle;
+ QLibrary *handle;
+ QString name;
+ QString filename;
+};
+
+//US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h)
+KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h)
+ : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName())
+{
+ unload_mode = UNKNOWN;
+/*US
+ if (lt_dlsym(handle, "__kde_do_not_unload") != 0) {
+// kdDebug(150) << "Will not unload " << name << endl;
+ unload_mode = DONT_UNLOAD;
+ } else if (lt_dlsym(handle, "__kde_do_unload") != 0) {
+ unload_mode = UNLOAD;
+ }
+*/
+//US use instead:
+ if (h->resolve("__kde_do_not_unload") != 0) {
+// kdDebug(150) << "Will not unload " << name << endl;
+ unload_mode = DONT_UNLOAD;
+ } else if (h->resolve("__kde_do_unload") != 0) {
+ unload_mode = UNLOAD;
+ }
+}
+
+class KLibLoaderPrivate
+{
+public:
+ QPtrList<KLibWrapPrivate> loaded_stack;
+ QPtrList<KLibWrapPrivate> pending_close;
+ enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
+
+ QString errorMessage;
+};
+
+KLibLoader* KLibLoader::s_self = 0;
+
+KLibLoader* KLibLoader::self()
+{
+ if ( !s_self )
+ s_self = new KLibLoader;
+ return s_self;
+}
+
+void KLibLoader::cleanUp()
+{
+ if ( !s_self )
+ return;
+
+ delete s_self;
+ s_self = 0;
+}
+
+KLibLoader::KLibLoader( QObject* parent, const char* name )
+ : QObject( parent, name )
+{
+ s_self = this;
+ d = new KLibLoaderPrivate;
+//US lt_dlinit();
+ d->unload_mode = KLibLoaderPrivate::UNKNOWN;
+ if (getenv("KDE_NOUNLOAD") != 0)
+ d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD;
+ else if (getenv("KDE_DOUNLOAD") != 0)
+ d->unload_mode = KLibLoaderPrivate::UNLOAD;
+ d->loaded_stack.setAutoDelete( true );
+}
+
+KLibLoader::~KLibLoader()
+{
+// kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl;
+
+ QAsciiDictIterator<KLibWrapPrivate> it( m_libs );
+ for (; it.current(); ++it )
+ {
+ kdDebug(150) << "The KLibLoader contains the library " << it.current()->name
+ << " (" << it.current()->lib << ")" << endl;
+ d->pending_close.append(it.current());
+ }
+
+ close_pending(0);
+
+ delete d;
+}
+
+//static
+QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ )
+{
+ QCString libname( name );
+
+ // only append ".la" if there is no extension
+ // this allows to load non-libtool libraries as well
+ // (mhk, 20000228)
+ int pos = libname.findRev('/');
+ if (pos < 0)
+ pos = 0;
+ if (libname.find('.', pos) < 0)
+ libname += ".la";
+
+ // only look up the file if it is not an absolute filename
+ // (mhk, 20000228)
+ QString libfile;
+ if (libname[0] == '/')
+ libfile = libname;
+ else
+ {
+//US libfile = instance->dirs()->findResource( "module", libname );
+ libfile = KGlobal::dirs()->findResource( "module", libname );
+ if ( libfile.isEmpty() )
+ {
+//US libfile = instance->dirs()->findResource( "lib", libname );
+ libfile = KGlobal::dirs()->findResource( "lib", libname );
+#ifndef NDEBUG
+ if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules
+ kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl;
+#endif
+ }
+ if ( libfile.isEmpty() )
+ {
+#ifndef NDEBUG
+ kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl;
+#endif
+ self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname);
+ }
+ else
+ self()->d->errorMessage = QString::null;
+ }
+ return libfile;
+}
+
+
+KLibrary* KLibLoader::globalLibrary( const char *name )
+{
+KLibrary *tmp;
+/*US
+int olt_dlopen_flag = lt_dlopen_flag;
+
+ lt_dlopen_flag |= LT_GLOBAL;
+ kdDebug(150) << "Loading the next library global with flag "
+ << lt_dlopen_flag
+ << "." << endl;
+*/
+ tmp = library(name);
+/*US
+ lt_dlopen_flag = olt_dlopen_flag;
+*/
+return tmp;
+}
+
+
+KLibrary* KLibLoader::library( const char *name )
+{
+ if (!name)
+ return 0;
+
+ KLibWrapPrivate* wrap = m_libs[name];
+ if (wrap) {
+ /* Nothing to do to load the library. */
+ wrap->ref_count++;
+ return wrap->lib;
+ }
+
+ /* Test if this library was loaded at some time, but got
+ unloaded meanwhile, whithout being dlclose()'ed. */
+ QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack);
+ for (; it.current(); ++it) {
+ if (it.current()->name == name)
+ wrap = it.current();
+ }
+
+ if (wrap) {
+ d->pending_close.removeRef(wrap);
+ if (!wrap->lib) {
+ /* This lib only was in loaded_stack, but not in m_libs. */
+ wrap->lib = new KLibrary( name, wrap->filename, wrap->handle );
+ }
+ wrap->ref_count++;
+ } else {
+ QString libfile = findLibrary( name );
+ if ( libfile.isEmpty() )
+ return 0;
+
+ const QString & qpeDir = QPEApplication::qpeDir();
+ libfile = qpeDir + libfile;
+//US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately );
+ QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately );
+
+//US lt_dlhandle handle = lt_dlopen( libfile.latin1() );
+//US if ( !handle )
+ if ( !qlib )
+ {
+//US const char* errmsg = lt_dlerror();
+ char* errmsg;
+ sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1());
+ qDebug(errmsg);
+
+ if(errmsg)
+ d->errorMessage = QString::fromLatin1(errmsg);
+ else
+ d->errorMessage = QString::null;
+ kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl;
+ return 0;
+ }
+ else
+ d->errorMessage = QString::null;
+
+ KLibrary *lib = new KLibrary( name, libfile, qlib );
+ wrap = new KLibWrapPrivate(lib, qlib);
+ d->loaded_stack.prepend(wrap);
+ }
+ m_libs.insert( name, wrap );
+
+ connect( wrap->lib, SIGNAL( destroyed() ),
+ this, SLOT( slotLibraryDestroyed() ) );
+
+ return wrap->lib;
+}
+
+QString KLibLoader::lastErrorMessage() const
+{
+ return d->errorMessage;
+}
+
+void KLibLoader::unloadLibrary( const char *libname )
+{
+ KLibWrapPrivate *wrap = m_libs[ libname ];
+ if (!wrap)
+ return;
+ if (--wrap->ref_count)
+ return;
+
+// kdDebug(150) << "closing library " << libname << endl;
+
+ m_libs.remove( libname );
+
+ disconnect( wrap->lib, SIGNAL( destroyed() ),
+ this, SLOT( slotLibraryDestroyed() ) );
+ close_pending( wrap );
+}
+
+KLibFactory* KLibLoader::factory( const char* name )
+{
+ KLibrary* lib = library( name );
+ if ( !lib )
+ return 0;
+
+ return lib->factory();
+}
+
+void KLibLoader::slotLibraryDestroyed()
+{
+ const KLibrary *lib = static_cast<const KLibrary *>( sender() );
+
+ QAsciiDictIterator<KLibWrapPrivate> it( m_libs );
+ for (; it.current(); ++it )
+ if ( it.current()->lib == lib )
+ {
+ KLibWrapPrivate *wrap = it.current();
+ wrap->lib = 0; /* the KLibrary object is already away */
+ m_libs.remove( it.currentKey() );
+ close_pending( wrap );
+ return;
+ }
+}
+
+void KLibLoader::close_pending(KLibWrapPrivate *wrap)
+{
+ if (wrap && !d->pending_close.containsRef( wrap ))
+ d->pending_close.append( wrap );
+
+ /* First delete all KLibrary objects in pending_close, but _don't_ unload
+ the DSO behind it. */
+ QPtrListIterator<KLibWrapPrivate> it(d->pending_close);
+ for (; it.current(); ++it) {
+ wrap = it.current();
+ if (wrap->lib) {
+ disconnect( wrap->lib, SIGNAL( destroyed() ),
+ this, SLOT( slotLibraryDestroyed() ) );
+ delete wrap->lib;
+ wrap->lib = 0;
+ }
+ }
+
+ if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return;
+
+ bool deleted_one = false;
+ while ((wrap = d->loaded_stack.first())) {
+ /* Let's first see, if we want to try to unload this lib.
+ If the env. var KDE_DOUNLOAD is set, we try to unload every lib.
+ If not, we look at the lib itself, and unload it only, if it exports
+ the symbol __kde_do_unload. */
+ if (d->unload_mode != KLibLoaderPrivate::UNLOAD
+ && wrap->unload_mode != KLibWrapPrivate::UNLOAD)
+ break;
+
+ /* Now ensure, that the libs are only unloaded in the reverse direction
+ they were loaded. */
+ if (!d->pending_close.containsRef( wrap )) {
+ if (!deleted_one)
+ /* Only diagnose, if we really haven't deleted anything. */
+// kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl;
+ break;
+ }
+
+// kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl;
+
+#ifndef Q_WS_QWS
+ if ( !deleted_one ) {
+ /* Only do the hack once in this loop.
+ WABA: *HACK*
+ We need to make sure to clear the clipboard before unloading a DSO
+ because the DSO could have defined an object derived from QMimeSource
+ and placed that on the clipboard. */
+ /*kapp->clipboard()->clear();*/
+
+ /* Well.. let's do something more subtle... convert the clipboard context
+ to text. That should be safe as it only uses objects defined by Qt. */
+
+ QWidgetList *widgetlist = QApplication::topLevelWidgets();
+ QWidget *co = widgetlist->first();
+ while (co) {
+ if (qstrcmp(co->name(), "internal clipboard owner") == 0) {
+ if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId())
+ kapp->clipboard()->setText(kapp->clipboard()->text());
+
+ break;
+ }
+ co = widgetlist->next();
+ }
+ delete widgetlist;
+ }
+#else
+ // FIXME(E): Implement in Qt Embedded
+#endif
+
+ deleted_one = true;
+//US lt_dlclose(wrap->handle);
+ wrap->handle->unload();
+
+ d->pending_close.removeRef(wrap);
+ /* loaded_stack is AutoDelete, so wrap is freed */
+ d->loaded_stack.remove();
+ }
+}
+
+void KLibLoader::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void KLibFactory::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+//US #include "klibloader.moc"
diff --git a/microkde/kdecore/klibloader.h b/microkde/kdecore/klibloader.h
new file mode 100644
index 0000000..ed57109
--- a/dev/null
+++ b/microkde/kdecore/klibloader.h
@@ -0,0 +1,405 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef KLIBLOADER_H
+#define KLIBLOADER_H
+
+#include <qobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qasciidict.h>
+#include <qptrlist.h>
+#include <kglobal.h>
+
+#include <stdlib.h> // For backwards compatibility
+
+class KInstance;
+class QTimer;
+class KLibrary;
+class KLibFactory;
+class KLibFactoryPrivate;
+class KLibLoaderPrivate;
+class KLibraryPrivate;
+
+class QLibrary;
+
+#define K_EXPORT_COMPONENT_FACTORY( libname, factory ) \
+ extern "C" { void *init_##libname() { return new factory; } }
+
+/**
+ * @short Represents a dynamically loaded library.
+ *
+ * KLibrary allows you to look up symbols of the shared library.
+ * Use @ref KLibLoader to create a new instance of KLibrary.
+ *
+ * @see KLibLoader
+ * @author Torben Weis <weis@kde.org>
+ */
+class KLibrary : public QObject
+{
+ friend class KLibLoader;
+ friend class QAsciiDict<KLibrary>;
+
+ Q_OBJECT
+public:
+ /**
+ * @internal
+ * Don't create KLibrary objects on your own. Instead use @ref KLibLoader.
+ */
+//US KLibrary( const QString& libname, const QString& filename, void * handle );
+ KLibrary( const QString& libname, const QString& filename, QLibrary* handle );
+
+ /**
+ * Returns the name of the library.
+ * @return The name of the library like "libkspread".
+ */
+ QString name() const;
+
+ /**
+ * Returns the file name of the library.
+ * @return The filename of the library, for example "/opt/kde2&/lib/libkspread.la"
+ */
+ QString fileName() const;
+
+ /**
+ * Returns the factory of the library.
+ * @return The factory of the library if there is any, otherwise 0
+ */
+ KLibFactory* factory();
+
+ /**
+ * Looks up a symbol from the library. This is a very low level
+ * function that you usually don't want to use. Usually you should
+ * check using @ref hasSymbol() whether the symbol actually exists,
+ * otherwise a warning will be printed.
+ * @param name the name of the symbol to look up
+ * @return the address of the symbol, or 0 if it does not exist
+ * @see #hasSymbol
+ */
+ void* symbol( const char* name ) const;
+
+ /**
+ * Looks up a symbol from the library. This is a very low level
+ * function that you usually don't want to use.
+ * Unlike @ref symbol(), this method doesn't warn if the symbol doesn't exist,
+ * so if the symbol might or might not exist, better use hasSymbol() before symbol().
+ * @param name the name of the symbol to check
+ * @return true if the symbol exists
+ * @since 3.1
+ */
+ bool hasSymbol( const char* name ) const;
+
+ /**
+ * Unloads the library.
+ * This typically results in the deletion of this object. You should
+ * not reference its pointer after calling this function.
+ */
+ void unload() const;
+
+private slots:
+ void slotObjectCreated( QObject *obj );
+ void slotObjectDestroyed();
+ void slotTimeout();
+
+private:
+ /**
+ * @internal
+ * Don't destruct KLibrary objects yourself. Instead use @ref unload() instead.
+ */
+ ~KLibrary();
+
+ QString m_libname;
+ QString m_filename;
+ KLibFactory* m_factory;
+//US void * m_handle;
+ QLibrary* m_handle;
+ QPtrList<QObject> m_objs;
+ QTimer *m_timer;
+ KLibraryPrivate *d;
+};
+
+class KLibWrapPrivate;
+
+/**
+ * The KLibLoader allows you to load libraries dynamically at runtime.
+ * Dependent libraries are loaded automatically.
+ *
+ * KLibLoader follows the singleton pattern. You can not create multiple
+ * instances. Use @ref self() to get a pointer to the loader.
+ *
+ * @see KLibrary
+ * @author Torben Weis <weis@kde.org>
+ */
+class KLibLoader : public QObject
+{
+ friend class KLibrary;
+
+ Q_OBJECT
+public:
+ /**
+ * You should NEVER destruct an instance of KLibLoader
+ * until you know what you are doing. This will release
+ * the loaded libraries.
+ */
+ ~KLibLoader();
+
+ /**
+ * Loads and initializes a library. Loading a library multiple times is
+ * handled gracefully.
+ *
+ * This is a convenience function that returns the factory immediately
+ * @param libname This is the library name without extension. Usually that is something like
+ * "libkspread". The function will then search for a file named
+ * "libkspread.la" in the KDE library paths.
+ * The *.la files are created by libtool and contain
+ * important information especially about the libraries dependencies
+ * on other shared libs. Loading a "libfoo.so" could not solve the
+ * dependencies problem.
+ *
+ * You can, however, give a library name ending in ".so"
+ * (or whatever is used on your platform), and the library
+ * will be loaded without resolving dependencies. USE WITH CARE :)
+ * @return the @ref KLibFactory, or 0 if the library does not exist or it does
+ * not have a factory
+ * @see #library
+ */
+ KLibFactory* factory( const char* libname );
+
+ /**
+ * Loads and initializes a library. Loading a library multiple times is
+ * handled gracefully.
+ *
+ * @param libname This is the library name without extension. Usually that is something like
+ * "libkspread". The function will then search for a file named
+ * "libkspread.la" in the KDE library paths.
+ * The *.la files are created by libtool and contain
+ * important information especially about the libraries dependencies
+ * on other shared libs. Loading a "libfoo.so" could not solve the
+ * dependencies problem.
+ *
+ * You can, however, give a library name ending in ".so"
+ * (or whatever is used on your platform), and the library
+ * will be loaded without resolving dependencies. USE WITH CARE :)
+ * @return @ref KLibrary is invalid (0) when the library couldn't be dlopened. in such
+ * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage()
+ *
+ * @see #factory
+ */
+ virtual KLibrary* library( const char* libname );
+
+ /**
+ * Loads and initializes a library. Loading a library multiple times is
+ * handled gracefully. The library is loaded such that the symbols are
+ * globally accessible so libraries with dependencies can be loaded
+ * sequentially.
+ *
+ * @param name This is the library name without extension. Usually that is something like
+ * "libkspread". The function will then search for a file named
+ * "libkspread.la" in the KDE library paths.
+ * The *.la files are created by libtool and contain
+ * important information especially about the libraries dependencies
+ * on other shared libs. Loading a "libfoo.so" could not solve the
+ * dependencies problem.
+ *
+ * You can, however, give a library name ending in ".so"
+ * (or whatever is used on your platform), and the library
+ * will be loaded without resolving dependencies. USE WITH CARE :)
+ * @return KLibrariy is invalid (0) when the library couldn't be dlopened. in such
+ * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage()
+ *
+ * @see #factory
+ */
+ KLibrary* globalLibrary( const char *name );
+
+ /*
+ * Returns an error message that can be useful to debug the problem.
+ * Returns QString::null if the last call to @ref #library() was successful.
+ * You can call this function more than once. The error message is only
+ * reset by a new call to library().
+ * @return the last error message, or QString::null if there was no error
+ */
+ QString lastErrorMessage() const;
+
+ /**
+ * Unloads the library with the given name.
+ * @param libname This is the library name without extension. Usually that is something like
+ * "libkspread". The function will then search for a file named
+ * "libkspread.la" in the KDE library paths.
+ * The *.la files are created by libtool and contain
+ * important information especially about the libraries dependencies
+ * on other shared libs. Loading a "libfoo.so" could not solve the
+ * dependencies problem.
+ *
+ * You can, however, give a library name ending in ".so"
+ * (or whatever is used on your platform), and the library
+ * will be loaded without resolving dependencies. USE WITH CARE :)
+ */
+ virtual void unloadLibrary( const char *libname );
+
+ /**
+ * Returns a pointer to the factory. Use this function to get an instance
+ * of KLibLoader.
+ * @return a pointer to the loader. If no loader exists until now
+ * then one is created.
+ */
+ static KLibLoader* self();
+
+ /**
+ * @internal
+ * Internal Method, called by the KApplication destructor.
+ * Do not call it.
+ * This is what makes it possible to rely on ~KLibFactory
+ * being called in all cases, whether the library is unloaded
+ * while the application is running or when exiting.
+ */
+ static void cleanUp();
+
+ /**
+ * Helper method which looks for a library in the standard paths
+ * ("module" and "lib" resources).
+ * Made public for code that doesn't use KLibLoader itself, but still
+ * wants to open modules.
+ * @param name of the library. If it is not a path, the function searches in
+ * the "module" and "lib" resources. If there is no extension,
+ * ".la" will be appended.
+ * @param instance a KInstance used to get the standard paths
+ */
+ static QString findLibrary( const char * name/*US , const KInstance * instance = KGlobal::instance()*/ );
+
+protected:
+ KLibLoader( QObject* parent = 0, const char* name = 0 );
+
+private slots:
+ void slotLibraryDestroyed();
+private:
+ void close_pending( KLibWrapPrivate * );
+ QAsciiDict<KLibWrapPrivate> m_libs;
+
+ static KLibLoader* s_self;
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KLibLoaderPrivate *d;
+};
+
+/**
+ * If you develop a library that is to be loaded dynamically at runtime, then
+ * you should return a pointer to your factory. The K_EXPORT_COMPONENT_FACTORY
+ * macro is provided for this purpose:
+ * <pre>
+ * K_EXPORT_COMPONENT_FACTORY( libkspread, KSpreadFactory )
+ * </pre>
+ *
+ * The first macro argument is the name of your library, the second specifies the name
+ * of your factory.
+ *
+ * In the constructor of your factory you should create an instance of @ref KInstance
+ * like this:
+ * <pre>
+ * s_global = new KInstance( "kspread" );
+ * </pre>
+ * This @ref KInstance is comparable to @ref KGlobal used by normal applications.
+ * It allows you to find resource files (images, XML, sound etc.) belonging
+ * to the library.
+ *
+ * If you want to load a library, use @ref KLibLoader. You can query @ref KLibLoader
+ * directly for a pointer to the libraries factory by using the @ref KLibLoader::factory()
+ * function.
+ *
+ * The KLibFactory is used to create the components, the library has to offer.
+ * The factory of KSpread for example will create instances of KSpreadDoc,
+ * while the Konqueror factory will create KonqView widgets.
+ * All objects created by the factory must be derived from @ref QObject, since @ref QObject
+ * offers type safe casting.
+ *
+ * KLibFactory is an abstract class. Reimplement the @ref
+ * createObject() method to give it functionality.
+ *
+ * @author Torben Weis <weis@kde.org>
+ */
+class KLibFactory : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Create a new factory.
+ * @param parent the parent of the QObject, 0 for no parent
+ * @param name the name of the QObject, 0 for no name
+ */
+ KLibFactory( QObject* parent = 0, const char* name = 0 );
+ virtual ~KLibFactory();
+
+ /**
+ * Creates a new object. The returned object has to be derived from
+ * the requested classname.
+ *
+ * It is valid behavior to create different kinds of objects
+ * depending on the requested @p classname. For example a koffice
+ * library may usually return a pointer to KoDocument. But
+ * if asked for a "QWidget", it could create a wrapper widget,
+ * that encapsulates the Koffice specific features.
+ *
+ * create() automatically emits a signal @ref objectCreated to tell
+ * the library about its newly created object. This is very
+ * important for reference counting, and allows unloading the
+ * library automatically once all its objects have been destroyed.
+ *
+ * @param parent the parent of the QObject, 0 for no parent
+ * @param name the name of the QObject, 0 for no name
+ * @param classname the name of the class
+ * @param args a list of arguments
+ */
+
+ QObject* create( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() );
+
+signals:
+ /**
+ * Emitted in #create
+ * @param obj the new object
+ */
+ void objectCreated( QObject *obj );
+
+
+protected:
+
+ /**
+ * Creates a new object. The returned object has to be derived from
+ * the requested classname.
+ *
+ * It is valid behavior to create different kinds of objects
+ * depending on the requested @p classname. For example a koffice
+ * library may usually return a pointer to KoDocument. But
+ * if asked for a "QWidget", it could create a wrapper widget,
+ * that encapsulates the Koffice specific features.
+ *
+ * This function is called by #create()
+ * @param parent the parent of the QObject, 0 for no parent
+ * @param name the name of the QObject, 0 for no name
+ * @param classname the name of the class
+ * @param args a list of arguments
+ */
+ virtual QObject* createObject( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ) = 0;
+
+
+protected:
+ virtual void virtual_hook( int id, void* data );
+private:
+ KLibFactoryPrivate *d;
+};
+
+#endif
diff --git a/microkde/kdecore/klocale.cpp b/microkde/kdecore/klocale.cpp
new file mode 100644
index 0000000..d77e251
--- a/dev/null
+++ b/microkde/kdecore/klocale.cpp
@@ -0,0 +1,881 @@
+#include <qregexp.h>
+#include <qapplication.h>
+
+#include "kdebug.h"
+#include "kcalendarsystemgregorian.h"
+
+#include "klocale.h"
+
+
+QDict<QString> *mLocaleDict = 0;
+void setLocaleDict( QDict<QString> * dict )
+{
+ mLocaleDict = dict;
+
+}
+QString i18n(const char *text)
+{
+ if ( ! mLocaleDict )
+ return QString( text );
+ else {
+ QString* ret = mLocaleDict->find(QString(text)) ;
+ if ( ret == 0 ) {
+ return QString( text );
+ }
+ else {
+ if ( (*ret).isEmpty() )
+ return QString( text );
+ else
+ return (*ret);
+ }
+ }
+
+}
+
+QString i18n(const char *,const char *text)
+{
+ return i18n( text );
+}
+
+QString i18n(const char *text1, const char *textn, int num)
+{
+ if ( num == 1 ) return i18n( text1 );
+ else {
+ QString text = i18n( textn );
+ int pos = text.find( "%n" );
+ if ( pos >= 0 ) text.replace( pos, 2, QString::number( num ) );
+ return text;
+ }
+}
+
+inline void put_it_in( QChar *buffer, uint& index, const QString &s )
+{
+ for ( uint l = 0; l < s.length(); l++ )
+ buffer[index++] = s.at( l );
+}
+
+inline void put_it_in( QChar *buffer, uint& index, int number )
+{
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+}
+
+static int readInt(const QString &str, uint &pos)
+{
+ if (!str.at(pos).isDigit()) return -1;
+ int result = 0;
+ for (; str.length() > pos && str.at(pos).isDigit(); pos++)
+ {
+ result *= 10;
+ result += str.at(pos).digitValue();
+ }
+
+ return result;
+}
+
+KLocale::KLocale() : mCalendarSystem( 0 )
+{
+
+ m_decimalSymbol = ".";
+ m_positiveSign = "";
+ m_negativeSign = "-";
+ m_thousandsSeparator = ",";
+
+
+
+
+ mWeekStartsMonday = true;
+ mHourF24Format = true;
+ mIntDateFormat = 0;
+ mLanguage = 0;
+ mDateFormat = "%a %Y %b %d";
+ mDateFormatShort = "%Y-%m-%d";
+ mTimeZoneList << i18n ("-11:00 US/Samoa")
+ << i18n ("-10:00 US/Hawaii")
+ << i18n ("-09:00 US/Alaska")
+ << i18n ("-08:00 US/Pacific")
+ << i18n ("-07:00 US/Mountain")
+ << i18n ("-06:00 US/Central")
+ << i18n ("-05:00 US/Eastern")
+ << i18n ("-04:00 Brazil/West")
+ << i18n ("-03:00 Brazil/East")
+ << i18n ("-02:00 Brazil/DeNoronha")
+ << i18n ("-01:00 Atlantic/Azores")
+ << i18n (" 00:00 Europe/London(UTC)")
+ << i18n ("+01:00 Europe/Oslo(CET)")
+ << i18n ("+02:00 Europe/Helsinki")
+ << i18n ("+03:00 Europe/Moscow")
+ << i18n ("+04:00 Indian/Mauritius")
+ << i18n ("+05:00 Indian/Maldives")
+ << i18n ("+06:00 Indian/Chagos")
+ << i18n ("+07:00 Asia/Bangkok")
+ << i18n ("+08:00 Asia/Hongkong")
+ << i18n ("+09:00 Asia/Tokyo")
+ << i18n ("+10:00 Asia/Vladivostok")
+ << i18n ("+11:00 Asia/Magadan")
+ << i18n ("+12:00 Asia/Kamchatka")
+ // << i18n (" xx:xx User defined offset")
+ << i18n (" Local Time");
+ mSouthDaylight = false;
+ mTimeZoneOffset = 0;
+ daylightEnabled = false;
+}
+
+void KLocale::setDateFormat( QString s )
+{
+ mDateFormat = s;
+}
+
+void KLocale::setDateFormatShort( QString s )
+{
+ mDateFormatShort = s;
+}
+
+void KLocale::setHore24Format ( bool b )
+{
+ mHourF24Format = b;
+}
+void KLocale::setWeekStartMonday( bool b )
+{
+ mWeekStartsMonday = b;
+}
+int KLocale::getIntDateFormat( )
+{
+ return mIntDateFormat ;
+
+}
+void KLocale::setIntDateFormat( int i )
+{
+ mIntDateFormat = i;
+}
+void KLocale::setLanguage( int i )
+{
+ mLanguage = i;
+}
+QString KLocale::translate( const char *index ) const
+{
+ return i18n( index );
+}
+
+QString KLocale::translate( const char *, const char *fallback) const
+{
+ return i18n( fallback );
+}
+
+QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
+{
+ const QString rst = timeFormat();
+
+ // only "pm/am" here can grow, the rest shrinks, but
+ // I'm rather safe than sorry
+ QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
+
+ uint index = 0;
+ bool escape = false;
+ int number = 0;
+
+ for ( uint format_index = 0; format_index < rst.length(); format_index++ )
+ {
+ if ( !escape )
+ {
+ if ( rst.at( format_index ).unicode() == '%' )
+ escape = true;
+ else
+ buffer[index++] = rst.at( format_index );
+ }
+ else
+ {
+ switch ( rst.at( format_index ).unicode() )
+ {
+ case '%':
+ buffer[index++] = '%';
+ break;
+ case 'H':
+ put_it_in( buffer, index, pTime.hour() );
+ break;
+ case 'I':
+ put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
+ break;
+ case 'M':
+ put_it_in( buffer, index, pTime.minute() );
+ break;
+ case 'S':
+ if (includeSecs)
+ put_it_in( buffer, index, pTime.second() );
+ else
+ {
+ // we remove the seperator sign before the seconds and
+ // assume that works everywhere
+ --index;
+ break;
+ }
+ break;
+ case 'k':
+ number = pTime.hour();
+ case 'l':
+ // to share the code
+ if ( rst.at( format_index ).unicode() == 'l' )
+ number = (pTime.hour() + 11) % 12 + 1;
+ if ( number / 10 )
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+ break;
+ case 'p':
+ {
+ QString s;
+ if ( pTime.hour() >= 12 )
+ put_it_in( buffer, index, i18n("pm") );
+ else
+ put_it_in( buffer, index, i18n("am") );
+ break;
+ }
+ default:
+ buffer[index++] = rst.at( format_index );
+ break;
+ }
+ escape = false;
+ }
+ }
+ QString ret( buffer, index );
+ delete [] buffer;
+ return ret;
+}
+
+QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
+{
+ const QString rst = shortFormat?dateFormatShort():dateFormat();
+
+ // I'm rather safe than sorry
+ QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
+
+ unsigned int index = 0;
+ bool escape = false;
+ int number = 0;
+
+ for ( uint format_index = 0; format_index < rst.length(); ++format_index )
+ {
+ if ( !escape )
+ {
+ if ( rst.at( format_index ).unicode() == '%' )
+ escape = true;
+ else
+ buffer[index++] = rst.at( format_index );
+ }
+ else
+ {
+ switch ( rst.at( format_index ).unicode() )
+ {
+ case '%':
+ buffer[index++] = '%';
+ break;
+ case 'Y':
+ put_it_in( buffer, index, pDate.year() / 100 );
+ case 'y':
+ put_it_in( buffer, index, pDate.year() % 100 );
+ break;
+ case 'n':
+ number = pDate.month();
+ case 'e':
+ // to share the code
+ if ( rst.at( format_index ).unicode() == 'e' )
+ number = pDate.day();
+ if ( number / 10 )
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+ break;
+ case 'm':
+ put_it_in( buffer, index, pDate.month() );
+ break;
+ case 'b':
+ put_it_in( buffer, index, monthName(pDate.month(), true) );
+ break;
+ case 'B':
+ put_it_in( buffer, index, monthName(pDate.month(), false) );
+ break;
+ case 'd':
+ put_it_in( buffer, index, pDate.day() );
+ break;
+ case 'a':
+ put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) );
+ break;
+ case 'A':
+ put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) );
+ break;
+ default:
+ buffer[index++] = rst.at( format_index );
+ break;
+ }
+ escape = false;
+ }
+ }
+ QString ret( buffer, index );
+ delete [] buffer;
+ return ret;
+}
+
+QString KLocale::formatDateTime(const QDateTime &pDateTime,
+ bool shortFormat,
+ bool includeSeconds) const
+{
+ return QString( "%1 %2")
+ .arg( formatDate( pDateTime.date(), shortFormat ) )
+ .arg( formatTime( pDateTime.time(), includeSeconds ) );
+}
+
+QString KLocale::formatDateTime(const QDateTime &pDateTime) const
+{
+ return formatDateTime(pDateTime, true);
+}
+
+QDate KLocale::readDate(const QString &intstr, bool* ok) const
+{
+ QDate date;
+ date = readDate(intstr, true, ok);
+ if (date.isValid()) return date;
+ return readDate(intstr, false, ok);
+}
+
+QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const
+{
+ QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
+ return readDate( intstr, fmt, ok );
+}
+
+QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
+{
+ //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
+ QString str = intstr.simplifyWhiteSpace().lower();
+ int day = -1, month = -1;
+ // allow the year to be omitted if not in the format
+ int year = QDate::currentDate().year();
+ uint strpos = 0;
+ uint fmtpos = 0;
+
+ while (fmt.length() > fmtpos || str.length() > strpos)
+ {
+ if ( !(fmt.length() > fmtpos && str.length() > strpos) )
+ goto error;
+
+ QChar c = fmt.at(fmtpos++);
+
+ if (c != '%') {
+ if (c.isSpace())
+ strpos++;
+ else if (c != str.at(strpos++))
+ goto error;
+ continue;
+ }
+
+ // remove space at the begining
+ if (str.length() > strpos && str.at(strpos).isSpace())
+ strpos++;
+
+ c = fmt.at(fmtpos++);
+ switch (c)
+ {
+ case 'a':
+ case 'A':
+ // this will just be ignored
+ { // Cristian Tache: porting to Win: Block added because of "j" redefinition
+ for (int j = 1; j < 8; j++) {
+ QString s = weekDayName(j, c == 'a').lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s)
+ strpos += len;
+ }
+ break;
+ }
+ case 'b':
+ case 'B':
+ { // Cristian Tache: porting to Win: Block added because of "j" redefinition
+ for (int j = 1; j < 13; j++) {
+ QString s = monthName(j, c == 'b').lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s) {
+ month = j;
+ strpos += len;
+ }
+ }
+ break;
+ }
+ case 'd':
+ case 'e':
+ day = readInt(str, strpos);
+ if (day < 1 || day > 31)
+ goto error;
+
+ break;
+
+ case 'n':
+ case 'm':
+ month = readInt(str, strpos);
+ if (month < 1 || month > 12)
+ goto error;
+
+ break;
+
+ case 'Y':
+ case 'y':
+ year = readInt(str, strpos);
+ if (year < 0)
+ goto error;
+ // Qt treats a year in the range 0-100 as 1900-1999.
+ // It is nicer for the user if we treat 0-68 as 2000-2068
+ if (year < 69)
+ year += 2000;
+ else if (c == 'y')
+ year += 1900;
+
+ break;
+ }
+ }
+ //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
+ if ( year != -1 && month != -1 && day != -1 )
+ {
+ if (ok) *ok = true;
+ return QDate(year, month, day);
+ }
+ error:
+ if (ok) *ok = false;
+ return QDate(); // invalid date
+}
+
+QTime KLocale::readTime(const QString &intstr, bool *ok) const
+{
+ QTime _time;
+ _time = readTime(intstr, true, ok);
+ if (_time.isValid()) return _time;
+ return readTime(intstr, false, ok);
+}
+
+QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const
+{
+ QString str = intstr.simplifyWhiteSpace().lower();
+ QString Format = timeFormat().simplifyWhiteSpace();
+ if (!seconds)
+ Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null);
+
+ int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds
+ bool g_12h = false;
+ bool pm = false;
+ uint strpos = 0;
+ uint Formatpos = 0;
+
+ while (Format.length() > Formatpos || str.length() > strpos)
+ {
+ if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
+
+ QChar c = Format.at(Formatpos++);
+
+ if (c != '%')
+ {
+ if (c.isSpace())
+ strpos++;
+ else if (c != str.at(strpos++))
+ goto error;
+ continue;
+ }
+
+ // remove space at the begining
+ if (str.length() > strpos && str.at(strpos).isSpace())
+ strpos++;
+
+ c = Format.at(Formatpos++);
+ switch (c)
+ {
+ case 'p':
+ {
+ QString s;
+ s = i18n("pm").lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s)
+ {
+ pm = true;
+ strpos += len;
+ }
+ else
+ {
+ s = i18n("am").lower();
+ len = s.length();
+ if (str.mid(strpos, len) == s) {
+ pm = false;
+ strpos += len;
+ }
+ else
+ goto error;
+ }
+ }
+ break;
+
+ case 'k':
+ case 'H':
+ g_12h = false;
+ hour = readInt(str, strpos);
+ if (hour < 0 || hour > 23)
+ goto error;
+
+ break;
+
+ case 'l':
+ case 'I':
+ g_12h = true;
+ hour = readInt(str, strpos);
+ if (hour < 1 || hour > 12)
+ goto error;
+
+ break;
+
+ case 'M':
+ minute = readInt(str, strpos);
+ if (minute < 0 || minute > 59)
+ goto error;
+
+ break;
+
+ case 'S':
+ second = readInt(str, strpos);
+ if (second < 0 || second > 59)
+ goto error;
+
+ break;
+ }
+ }
+ if (g_12h)
+ {
+ hour %= 12;
+ if (pm) hour += 12;
+ }
+
+ if (ok) *ok = true;
+ return QTime(hour, minute, second);
+
+ error:
+ if (ok) *ok = false;
+ return QTime(-1, -1, -1); // return invalid date if it didn't work
+ // This will be removed in the near future, since it gives a warning on stderr.
+ // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime.
+}
+
+bool KLocale::use12Clock() const
+{
+ return !mHourF24Format ;;
+}
+
+bool KLocale::weekStartsMonday() const
+{
+ return mWeekStartsMonday;
+}
+
+int KLocale::weekStartDay() const
+{
+ if ( mWeekStartsMonday )
+ return 1;
+ return 7;
+}
+
+QString KLocale::weekDayName(int i,bool shortName) const
+{
+ if ( shortName )
+ switch ( i )
+ {
+ case 1: return i18n("Monday", "Mon");
+ case 2: return i18n("Tuesday", "Tue");
+ case 3: return i18n("Wednesday", "Wed");
+ case 4: return i18n("Thursday", "Thu");
+ case 5: return i18n("Friday", "Fri");
+ case 6: return i18n("Saturday", "Sat");
+ case 7: return i18n("Sunday", "Sun");
+ }
+ else
+ switch ( i )
+ {
+ case 1: return i18n("Monday");
+ case 2: return i18n("Tuesday");
+ case 3: return i18n("Wednesday");
+ case 4: return i18n("Thursday");
+ case 5: return i18n("Friday");
+ case 6: return i18n("Saturday");
+ case 7: return i18n("Sunday");
+ }
+
+ return QString::null;
+}
+
+QString KLocale::monthName(int i,bool shortName) const
+{
+ if ( shortName )
+ switch ( i )
+ {
+ case 1: return i18n("January", "Jan");
+ case 2: return i18n("February", "Feb");
+ case 3: return i18n("March", "Mar");
+ case 4: return i18n("April", "Apr");
+ case 5: return i18n("May short", "May");
+ case 6: return i18n("June", "Jun");
+ case 7: return i18n("July", "Jul");
+ case 8: return i18n("August", "Aug");
+ case 9: return i18n("September", "Sep");
+ case 10: return i18n("October", "Oct");
+ case 11: return i18n("November", "Nov");
+ case 12: return i18n("December", "Dec");
+ }
+ else
+ switch (i)
+ {
+ case 1: return i18n("January");
+ case 2: return i18n("February");
+ case 3: return i18n("March");
+ case 4: return i18n("April");
+ case 5: return i18n("May long", "May");
+ case 6: return i18n("June");
+ case 7: return i18n("July");
+ case 8: return i18n("August");
+ case 9: return i18n("September");
+ case 10: return i18n("October");
+ case 11: return i18n("November");
+ case 12: return i18n("December");
+ }
+
+ return QString::null;
+}
+
+QString KLocale::country() const
+{
+ return QString::null;
+}
+
+QString KLocale::dateFormat() const
+{
+ if ( QApplication::desktop()->width() < 480 ) {
+ if ( mIntDateFormat == 0 )
+ return "%a %d %b %Y";
+ else if ( mIntDateFormat == 1 )
+ return "%a %b %d %Y";
+ else if ( mIntDateFormat == 2 )
+ return "%a %Y %b %d";
+ } else {
+
+ if ( mIntDateFormat == 0 )
+ return "%A %d %B %Y";
+ else if ( mIntDateFormat == 1 )
+ return "%A %B %d %Y";
+ else if ( mIntDateFormat == 2 )
+ return "%A %Y %B %d";
+ }
+ return mDateFormat ;
+}
+
+QString KLocale::dateFormatShort() const
+{
+
+ if ( mIntDateFormat == 0 )
+ return "%d.%m.%Y";
+ else if ( mIntDateFormat == 1 )
+ return "%m.%d.%Y";
+ else if ( mIntDateFormat == 2 )
+ return "%Y-%m-%d";
+ return mDateFormatShort ;
+
+}
+
+
+QString KLocale::timeFormat() const
+{
+ if ( mHourF24Format)
+ return "%H:%M:%S";
+ return "%I:%M:%S%p";
+}
+
+void KLocale::insertCatalogue ( const QString & )
+{
+}
+
+KCalendarSystem *KLocale::calendar()
+{
+ if ( !mCalendarSystem ) {
+ mCalendarSystem = new KCalendarSystemGregorian;
+ }
+
+ return mCalendarSystem;
+}
+
+int KLocale::timezoneOffset( QString timeZone )
+{
+ int ret = 1001;
+ int index = mTimeZoneList.findIndex( timeZone );
+ if ( index < 24 )
+ ret = ( index-11 ) * 60 ;
+ return ret;
+}
+
+QStringList KLocale::timeZoneList() const
+{
+ return mTimeZoneList;
+}
+void KLocale::setTimezone( const QString &timeZone )
+{
+ mTimeZoneOffset = timezoneOffset( timeZone );
+}
+
+void KLocale::setDaylightSaving( bool b, int start , int end )
+{
+ daylightEnabled = b;
+ daylightStart = start;
+ daylightEnd = end;
+ mSouthDaylight = (end < start);
+ // qDebug("klocale daylight %d %d %d ", b, start , end );
+}
+
+int KLocale::localTimeOffset( const QDateTime &dt )
+{
+ bool addDaylight = false;
+ if ( daylightEnabled ) {
+ int d_end, d_start;
+ int dayofyear = dt.date().dayOfYear();
+ int year = dt.date().year();
+ int add = 0;
+ if ( QDate::leapYear(year) )
+ add = 1;
+ QDate date ( year,1,1 );
+ if ( daylightEnd > 59 )
+ d_end = daylightEnd +add;
+ else
+ d_end = daylightEnd;
+ if ( daylightStart > 59 )
+ d_start = daylightStart +add;
+ else
+ d_start = daylightStart;
+ QDate s_date = date.addDays( d_start -1 );
+ QDate e_date = date.addDays( d_end -1 );
+ int dof = s_date.dayOfWeek();
+ if ( dof < 7 )
+ s_date = s_date.addDays( -dof );
+ dof = e_date.dayOfWeek();
+ if ( dof < 7 )
+ e_date = e_date.addDays( -dof );
+ QTime startTime ( 3,0,0 );
+ QDateTime startDt( s_date, startTime );
+ QDateTime endDt( e_date, startTime );
+ //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( ));
+ if ( mSouthDaylight ) {
+ if ( ! ( endDt < dt && dt < startDt) )
+ addDaylight = true;
+ } else {
+ if ( startDt < dt && dt < endDt )
+ addDaylight = true;
+
+
+ }
+ }
+ int addMin = 0;
+ if ( addDaylight )
+ addMin = 60;
+ return mTimeZoneOffset + addMin;
+}
+// ******************************************************************
+// added LR
+QString KLocale::formatNumber(double num, int precision) const
+{
+ bool neg = num < 0;
+ if (precision == -1) precision = 2;
+ QString res = QString::number(neg?-num:num, 'f', precision);
+ int pos = res.find('.');
+ if (pos == -1) pos = res.length();
+ else res.replace(pos, 1, decimalSymbol());
+
+ while (0 < (pos -= 3))
+ res.insert(pos, thousandsSeparator()); // thousand sep
+
+ // How can we know where we should put the sign?
+ res.prepend(neg?negativeSign():positiveSign());
+
+ return res;
+}
+QString KLocale::formatNumber(const QString &numStr) const
+{
+ return formatNumber(numStr.toDouble());
+}
+double KLocale::readNumber(const QString &_str, bool * ok) const
+{
+ QString str = _str.stripWhiteSpace();
+ bool neg = str.find(negativeSign()) == 0;
+ if (neg)
+ str.remove( 0, negativeSign().length() );
+
+ /* will hold the scientific notation portion of the number.
+ Example, with 2.34E+23, exponentialPart == "E+23"
+ */
+ QString exponentialPart;
+ int EPos;
+
+ EPos = str.find('E', 0, false);
+
+ if (EPos != -1)
+ {
+ exponentialPart = str.mid(EPos);
+ str = str.left(EPos);
+ }
+
+ int pos = str.find(decimalSymbol());
+ QString major;
+ QString minor;
+ if ( pos == -1 )
+ major = str;
+ else
+ {
+ major = str.left(pos);
+ minor = str.mid(pos + decimalSymbol().length());
+ }
+
+ // Remove thousand separators
+ int thlen = thousandsSeparator().length();
+ int lastpos = 0;
+ while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
+ {
+ // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
+ int fromEnd = major.length() - pos;
+ if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
+ || pos - lastpos > 3 // More than 3 digits between two separators -> error
+ || pos == 0 // Can't start with a separator
+ || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+
+ lastpos = pos;
+ major.remove( pos, thlen );
+ }
+ if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+
+ QString tot;
+ if (neg) tot = '-';
+
+ tot += major + '.' + minor + exponentialPart;
+
+ return tot.toDouble(ok);
+}
+QString KLocale::decimalSymbol() const
+{
+
+ return m_decimalSymbol;
+}
+
+QString KLocale::thousandsSeparator() const
+{
+
+ return m_thousandsSeparator;
+}
+QString KLocale::positiveSign() const
+{
+ return m_positiveSign;
+}
+
+QString KLocale::negativeSign() const
+{
+ return m_negativeSign;
+}
diff --git a/microkde/kdecore/klocale.h b/microkde/kdecore/klocale.h
new file mode 100644
index 0000000..7470cd2
--- a/dev/null
+++ b/microkde/kdecore/klocale.h
@@ -0,0 +1,110 @@
+#ifndef MINIKDE_KLOCALE_H
+#define MINIKDE_KLOCALE_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdatetime.h>
+#include <qdict.h>
+
+#ifndef I18N_NOOP
+#define I18N_NOOP(x) (x)
+#endif
+
+class KCalendarSystem;
+void setLocaleDict( QDict<QString> * dict );
+QString i18n(const char *text);
+QString i18n(const char *hint, const char *text);
+QString i18n(const char *text1, const char *textn, int num);
+
+// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict
+// with our i18n method. we use uic -tr tr2i18n to redirect
+// to the right i18n() function
+inline QString tr2i18n(const char* message, const char* =0) {
+ return i18n( message);
+}
+
+class KLocale
+{
+ public:
+ KLocale();
+
+ QString formatNumber(double num, int precision = -1) const;
+ QString formatNumber(const QString &numStr) const;
+ double readNumber(const QString &numStr, bool * ok = 0) const;
+
+ QString decimalSymbol() const;
+ QString thousandsSeparator() const;
+ QString positiveSign() const;
+ QString negativeSign() const;
+
+
+ QString translate( const char *index ) const;
+ QString translate( const char *index, const char *fallback) const;
+
+ QString formatDate(const QDate &pDate, bool shortFormat = false) const;
+ QString formatTime(const QTime &pTime, bool includeSecs = false) const;
+ QString formatDateTime(const QDateTime &pDateTime) const;
+ QString formatDateTime(const QDateTime &pDateTime,
+ bool shortFormat,
+ bool includeSecs = false) const;
+
+ QDate readDate(const QString &str, bool* ok = 0) const;
+ QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const;
+ QTime readTime(const QString &str, bool* ok = 0) const;
+
+ bool use12Clock() const;
+ bool weekStartsMonday() const;
+ int weekStartDay() const;
+
+ QString weekDayName(int,bool=false) const;
+ QString monthName(int,bool=false) const;
+
+ QString country() const;
+
+ QString dateFormat() const;
+ QString dateFormatShort() const;
+ QString timeFormat() const;
+
+ void insertCatalogue ( const QString & );
+
+ KCalendarSystem *calendar();
+ void setHore24Format ( bool );
+ void setWeekStartMonday( bool );
+ void setIntDateFormat( int );
+ int getIntDateFormat( );
+ void setLanguage( int );
+ void setDateFormat( QString );
+ void setDateFormatShort( QString );
+
+ QString m_decimalSymbol;
+ QString m_thousandsSeparator;
+ QString m_currencySymbol;
+ QString m_monetaryDecimalSymbol;
+ QString m_monetaryThousandsSeparator;
+ QString m_positiveSign;
+ QString m_negativeSign;
+
+ int timezoneOffset( QString );
+ QStringList timeZoneList() const;
+ void setDaylightSaving( bool, int , int );
+ int localTimeOffset(const QDateTime &);
+ void setTimezone( const QString &timeZone );
+ private:
+ QTime readTime(const QString &str, bool seconds, bool *ok) const;
+ QDate readDate(const QString &str, bool shortFormat, bool *ok) const;
+ KCalendarSystem *mCalendarSystem;
+ bool mWeekStartsMonday;
+ bool mHourF24Format;
+ int mIntDateFormat;
+ int mLanguage;
+ QString mDateFormat;
+ QString mDateFormatShort;
+ QStringList mTimeZoneList;
+ bool daylightEnabled;
+ int mDaylightTZoffset;
+ int mNondaylightTZoffset;
+ bool mSouthDaylight;
+ int daylightStart, daylightEnd, mTimeZoneOffset;
+};
+
+#endif
diff --git a/microkde/kdecore/klocale_new.cpp b/microkde/kdecore/klocale_new.cpp
new file mode 100644
index 0000000..223b6c4
--- a/dev/null
+++ b/microkde/kdecore/klocale_new.cpp
@@ -0,0 +1,2441 @@
+// -*- c-basic-offset: 2 -*-
+/* This file is part of the KDE libraries
+ Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org>
+ Copyright (c) 1999 Preston Brown <pbrown@kde.org>
+ Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org>
+ Copyright (c) 2002 Lukas Tinkl <lukas@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//US#include <config.h>
+
+#include <stdlib.h> // getenv
+#include <assert.h>
+
+#include <qtextcodec.h>
+#include <qfile.h>
+#include <qdict.h>
+#include <qprinter.h>
+#include <qdatetime.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+
+#include "kcatalogue.h"
+#include "kglobal.h"
+#include "kstandarddirs.h"
+#include "ksimpleconfig.h"
+//US #include "kinstance.h"
+#include "kconfig.h"
+#include "kconfigbase.h"
+#include "kdebug.h"
+#include "kcalendarsystem.h"
+
+//US we use no factory. Simply use the gregorian calendar
+//US #include "kcalendarsystemfactory.h"
+#include "kcalendarsystemgregorian.h"
+
+#include "klocale.h"
+
+static const char * const SYSTEM_MESSAGES = "kdelibs";
+
+static const char *maincatalogue = 0;
+
+QDict<char> *mLocaleDict = 0;
+
+void setLocaleDict( QDict<char> * dict )
+{
+ mLocaleDict = dict;
+
+}
+
+class KLocalePrivate
+{
+public:
+ int weekStartDay;
+ int plural_form;
+ bool nounDeclension;
+ bool dateMonthNamePossessive;
+ QStringList languageList;
+ QValueList<KCatalogue> catalogues;
+ QString encoding;
+ QTextCodec * codecForEncoding;
+ KConfig * config;
+ bool formatInited;
+ int /*QPrinter::PageSize*/ pageSize;
+ KLocale::MeasureSystem measureSystem;
+ QStringList langTwoAlpha;
+ KConfig *languages;
+
+ QString calendarType;
+ KCalendarSystem * calendar;
+ QString first_language;
+ bool utf8FileEncoding;
+};
+
+static KLocale *this_klocale = 0;
+
+KLocale::KLocale( const QString & catalogue, KConfig * config )
+{
+ d = new KLocalePrivate;
+ d->config = config;
+ d->languages = 0;
+ d->calendar = 0;
+
+ initCatalogue(catalogue);
+ initEncoding(0);
+ initFileNameEncoding(0);
+
+ KConfig *cfg = d->config;
+ this_klocale = this;
+//US if (!cfg) cfg = KGlobal::instance()->config();
+ if (!cfg) cfg = KGlobal::config();
+ this_klocale = 0;
+//US Q_ASSERT( cfg );
+ ASSERT( cfg );
+
+ if (m_language.isEmpty())
+ initLanguage(cfg, config == 0);
+
+
+/*US
+//US mDateFormat = "%a %Y %b %d";
+//US mDateFormatShort = "%Y-%m-%d";
+ mTimeZoneList << i18n ("-11:00 US/Samoa")
+ << i18n ("-10:00 US/Hawaii")
+ << i18n ("-09:00 US/Alaska")
+ << i18n ("-08:00 US/Pacific")
+ << i18n ("-07:00 US/Mountain")
+ << i18n ("-06:00 US/Central")
+ << i18n ("-05:00 US/Eastern")
+ << i18n ("-04:00 Brazil/West")
+ << i18n ("-03:00 Brazil/East")
+ << i18n ("-02:00 Brazil/DeNoronha")
+ << i18n ("-01:00 Atlantic/Azores")
+ << i18n (" 00:00 Europe/London(UTC)")
+ << i18n ("+01:00 Europe/Oslo(CET)")
+ << i18n ("+02:00 Europe/Helsinki")
+ << i18n ("+03:00 Europe/Moscow")
+ << i18n ("+04:00 Indian/Mauritius")
+ << i18n ("+05:00 Indian/Maldives")
+ << i18n ("+06:00 Indian/Chagos")
+ << i18n ("+07:00 Asia/Bangkok")
+ << i18n ("+08:00 Asia/Hongkong")
+ << i18n ("+09:00 Asia/Tokyo")
+ << i18n ("+10:00 Asia/Vladivostok")
+ << i18n ("+11:00 Asia/Magadan")
+ << i18n ("+12:00 Asia/Kamchatka")
+ // << i18n (" xx:xx User defined offset")
+ << i18n (" Local Time");
+*/
+ mTimeZoneList << "-11:00 US/Samoa"
+ << "-10:00 US/Hawaii"
+ << "-09:00 US/Alaska"
+ << "-08:00 US/Pacific"
+ << "-07:00 US/Mountain"
+ << "-06:00 US/Central"
+ << "-05:00 US/Eastern"
+ << "-04:00 Brazil/West"
+ << "-03:00 Brazil/East"
+ << "-02:00 Brazil/DeNoronha"
+ << "-01:00 Atlantic/Azores"
+ << " 00:00 Europe/London(UTC)"
+ << "+01:00 Europe/Oslo(CET)"
+ << "+02:00 Europe/Helsinki"
+ << "+03:00 Europe/Moscow"
+ << "+04:00 Indian/Mauritius"
+ << "+05:00 Indian/Maldives"
+ << "+06:00 Indian/Chagos"
+ << "+07:00 Asia/Bangkok"
+ << "+08:00 Asia/Hongkong"
+ << "+09:00 Asia/Tokyo"
+ << "+10:00 Asia/Vladivostok"
+ << "+11:00 Asia/Magadan"
+ << "+12:00 Asia/Kamchatka"
+ // << " xx:xx User defined offset"
+ << " Local Time";
+
+ mSouthDaylight = false;
+ mTimeZoneOffset = 0;
+ daylightEnabled = false;
+
+ mWeekStartsMonday = true;
+ mHourF24Format = true;
+ mIntDateFormat = 0;
+ mLanguage = 0;
+
+}
+
+
+QString KLocale::_initLanguage(KConfigBase *config)
+{
+ if (this_klocale)
+ {
+ // ### HPB Why this cast??
+ this_klocale->initLanguage((KConfig *) config, true);
+ return this_klocale->language();
+ }
+ return QString::null;
+}
+
+void KLocale::initCatalogue(const QString & catalogue)
+{
+ // Use the first non-null string.
+ QString mainCatalogue = catalogue;
+ if (maincatalogue)
+ mainCatalogue = QString::fromLatin1(maincatalogue);
+
+ if (mainCatalogue.isEmpty()) {
+ kdDebug(173) << "KLocale instance created called without valid "
+ << "catalogue! Give an argument or call setMainCatalogue "
+ << "before init" << endl;
+ }
+ else
+ d->catalogues.append( KCatalogue(mainCatalogue ) );
+
+ // always include kdelibs.mo
+ d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) );
+}
+
+void KLocale::initLanguage(KConfig * config, bool useEnv)
+{
+ KConfigGroupSaver saver(config, "Locale");
+
+ m_country = config->readEntry( "Country" );
+ if ( m_country.isEmpty() )
+ m_country = defaultCountry();
+
+ // Reset the list and add the new languages
+ QStringList languageList;
+ if ( useEnv )
+ languageList += QStringList::split
+ (':', QFile::decodeName( ::getenv("KDE_LANG") ));
+
+//US languageList += config->readListEntry("Language", ':');
+ languageList += config->readListEntry("Language");
+
+ // same order as setlocale use
+ if ( useEnv )
+ {
+ // HPB: Only run splitLocale on the environment variables..
+ QStringList langs;
+
+ langs << QFile::decodeName( ::getenv("LC_ALL") );
+ langs << QFile::decodeName( ::getenv("LC_MESSAGES") );
+ langs << QFile::decodeName( ::getenv("LANG") );
+ langs << QFile::decodeName( ::getenv("LC_CTYPE") );
+
+ for ( QStringList::Iterator it = langs.begin();
+ it != langs.end();
+ ++it )
+ {
+ QString ln, ct, chrset;
+ splitLocale(*it, ln, ct, chrset);
+
+ if (!ct.isEmpty()) {
+ langs.insert(it, ln + '_' + ct);
+ if (!chrset.isEmpty())
+ langs.insert(it, ln + '_' + ct + '.' + chrset);
+ }
+
+ langs.insert(it, ln);
+ }
+
+ languageList += langs;
+ }
+
+ // now we have a language list -- let's use the first OK language
+ setLanguage( languageList );
+}
+
+void KLocale::doBindInit()
+{
+ return; // LR
+ for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
+ it != d->catalogues.end();
+ ++it )
+ initCatalogue( *it );
+
+ if ( useDefaultLanguage() )
+ d->plural_form = -1;
+ else
+ {
+ QString pf = translate_priv
+ ( I18N_NOOP("_: Dear translator, please do not translate this string "
+ "in any form, but pick the _right_ value out of "
+ "NoPlural/TwoForms/French... If not sure what to do mail "
+ "thd@kde.org and coolo@kde.org, they will tell you. "
+ "Better leave that out if unsure, the programs will "
+ "crash!!\nDefinition of PluralForm - to be set by the "
+ "translator of kdelibs.po"), 0);
+ if ( pf.isEmpty() ) {
+ kdWarning(173) << "found no definition of PluralForm for " << m_language << endl;
+ d->plural_form = -1;
+ } else if ( pf == "NoPlural" )
+ d->plural_form = 0;
+ else if ( pf == "TwoForms" )
+ d->plural_form = 1;
+ else if ( pf == "French" )
+ d->plural_form = 2;
+ else if ( pf == "OneTwoRest" || pf == "Gaeilge" ) // Gaelige is the old name
+ d->plural_form = 3;
+ else if ( pf == "Russian" )
+ d->plural_form = 4;
+ else if ( pf == "Polish" )
+ d->plural_form = 5;
+ else if ( pf == "Slovenian" )
+ d->plural_form = 6;
+ else if ( pf == "Lithuanian" )
+ d->plural_form = 7;
+ else if ( pf == "Czech" )
+ d->plural_form = 8;
+ else if ( pf == "Slovak" )
+ d->plural_form = 9;
+ else if ( pf == "Maltese" )
+ d->plural_form = 10;
+ else if ( pf == "Arabic" )
+ d->plural_form = 11;
+ else if ( pf == "Balcan" )
+ d->plural_form = 12;
+ else {
+ kdWarning(173) << "Definition of PluralForm is none of "
+ << "NoPlural/"
+ << "TwoForms/"
+ << "French/"
+ << "OneTwoRest/"
+ << "Russian/"
+ << "Polish/"
+ << "Slovenian/"
+ << "Lithuanian/"
+ << "Czech/"
+ << "Slovak/"
+ << "Arabic/"
+ << "Balcan/"
+ << "Maltese: " << pf << endl;
+ exit(1);
+ }
+ }
+
+ d->formatInited = false;
+}
+
+void KLocale::doFormatInit() const
+{
+ if ( d->formatInited ) return;
+
+ KLocale * that = const_cast<KLocale *>(this);
+ that->initFormat();
+
+ d->formatInited = true;
+}
+
+void KLocale::initFormat()
+{
+ KConfig *config = d->config;
+//US if (!config) config = KGlobal::instance()->config();
+ if (!config) config = KGlobal::config();
+ ASSERT( config );
+
+ kdDebug(173) << "KLocale::initFormat" << endl;
+
+ // make sure the config files are read using the correct locale
+ // ### Why not add a KConfigBase::setLocale( const KLocale * )?
+ // ### Then we could remove this hack
+//US
+//US KLocale *lsave = KGlobal::_locale;
+//US KGlobal::_locale = this;
+ KLocale *lsave = KGlobal::locale();
+ KGlobal::setLocale(this);
+
+ KConfigGroupSaver saver(config, "Locale");
+
+
+
+//US in kabc/adress.cpp we have a similar setup. Check there in case of problems
+ KSimpleConfig entry(locateLocal("locale",
+ QString::fromLatin1("l10n/%1/entry.desktop")
+ .arg(m_country)) );
+
+ entry.setGroup("KCM Locale");
+
+ // Numeric
+#define readConfigEntry(key, default, save) \
+ save = entry.readEntry(key, QString::fromLatin1(default)); \
+ save = config->readEntry(key, save);
+
+#define readConfigNumEntry(key, default, save, type) \
+ save = (type)entry.readNumEntry(key, default); \
+ save = (type)config->readNumEntry(key, save);
+
+#define readConfigBoolEntry(key, default, save) \
+ save = entry.readBoolEntry(key, default); \
+ save = config->readBoolEntry(key, save);
+
+ readConfigEntry("DecimalSymbol", ".", m_decimalSymbol);
+ readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator);
+ m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null );
+ //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl;
+
+ readConfigEntry("PositiveSign", "", m_positiveSign);
+ readConfigEntry("NegativeSign", "-", m_negativeSign);
+
+ // Monetary
+ readConfigEntry("CurrencySymbol", "$", m_currencySymbol);
+ readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol);
+ readConfigEntry("MonetaryThousandsSeparator", ",",
+ m_monetaryThousandsSeparator);
+ m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null);
+
+ readConfigNumEntry("FracDigits", 2, m_fracDigits, int);
+ readConfigBoolEntry("PositivePrefixCurrencySymbol", true,
+ m_positivePrefixCurrencySymbol);
+ readConfigBoolEntry("NegativePrefixCurrencySymbol", true,
+ m_negativePrefixCurrencySymbol);
+ readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney,
+ m_positiveMonetarySignPosition, SignPosition);
+ readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround,
+ m_negativeMonetarySignPosition, SignPosition);
+
+ //Grammatical
+ readConfigBoolEntry("NounDeclension", false, d->nounDeclension);
+
+ // Date and time
+ readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat);
+ readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat);
+ readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort);
+ readConfigBoolEntry("DateMonthNamePossessive", false,
+ d->dateMonthNamePossessive);
+ readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int);
+
+ // other
+//US readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int);
+ readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem,
+ MeasureSystem);
+ readConfigEntry("CalendarSystem", "gregorian", d->calendarType);
+ delete d->calendar;
+ d->calendar = 0; // ### HPB Is this the correct place?
+
+ // end of hack
+//US KGlobal::_locale = lsave;
+ KGlobal::setLocale(lsave);
+}
+
+bool KLocale::setCountry(const QString & country)
+{
+ // Check if the file exists too??
+ if ( country.isEmpty() )
+ return false;
+
+ m_country = country;
+
+ d->formatInited = false;
+
+ return true;
+}
+
+QString KLocale::catalogueFileName(const QString & language,
+ const KCatalogue & catalogue)
+{
+ QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo")
+ .arg( language )
+ .arg( catalogue.name() );
+
+ return locate( "locale", path );
+}
+
+bool KLocale::isLanguageInstalled(const QString & language) const
+{
+ // Do not allow empty languages
+ if ( language.isEmpty() ) return false;
+
+ bool bRes = true;
+ if ( language != defaultLanguage() )
+ for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
+ it != d->catalogues.end() && bRes;
+ ++it )
+ {
+ bRes = !catalogueFileName( language, *it ).isNull();
+ if ( !bRes )
+ kdDebug(173) << "message catalogue not found: "
+ << (*it).name() << endl;
+ }
+
+ return bRes;
+}
+
+bool KLocale::setLanguage(const QString & language)
+{
+ bool bRes = true;
+
+ if (d->first_language.isNull() || language != d->first_language)
+ bRes = isLanguageInstalled( language );
+
+ if ( bRes )
+ {
+ m_language = language;
+
+ // remember our first time - it will be our true love
+ if (d->first_language.isNull())
+ d->first_language = language;
+
+ doBindInit();
+ }
+
+ return bRes;
+}
+
+bool KLocale::setLanguage(const QStringList & languages)
+{
+ QStringList languageList(languages);
+
+ // Remove duplicate entries in reverse so that we
+ // can keep user's language preference order intact. (DA)
+ for( QStringList::Iterator it = languageList.fromLast();
+ it != languageList.begin();
+ --it )
+ if ( languageList.contains(*it) > 1 || (*it).isEmpty() )
+ it = languageList.remove( it );
+
+ bool bRes = false;
+ for ( QStringList::ConstIterator it = languageList.begin();
+ it != languageList.end();
+ ++it )
+ if ( bRes = setLanguage( *it ) )
+ break;
+
+ if ( !bRes )
+ setLanguage(defaultLanguage());
+
+ d->languageList = languageList;
+ d->langTwoAlpha.clear(); // Flush cache
+
+ return bRes;
+}
+
+void KLocale::splitLocale(const QString & aStr,
+ QString & language,
+ QString & country,
+ QString & chrset)
+{
+ QString str = aStr;
+
+ // just in case, there is another language appended
+ int f = str.find(':');
+ if (f >= 0)
+ str.truncate(f);
+
+ country = QString::null;
+ chrset = QString::null;
+ language = QString::null;
+
+ f = str.find('.');
+ if (f >= 0)
+ {
+ chrset = str.mid(f + 1);
+ str.truncate(f);
+ }
+
+ f = str.find('_');
+ if (f >= 0)
+ {
+ country = str.mid(f + 1);
+ str.truncate(f);
+ }
+
+ language = str;
+}
+
+QString KLocale::language() const
+{
+ return m_language;
+}
+
+QString KLocale::country() const
+{
+ return m_country;
+}
+
+QString KLocale::monthName(int i, bool shortName) const
+{
+ if ( shortName )
+ switch ( i )
+ {
+ case 1: return translate("January", "Jan");
+ case 2: return translate("February", "Feb");
+ case 3: return translate("March", "Mar");
+ case 4: return translate("April", "Apr");
+ case 5: return translate("May short", "May");
+ case 6: return translate("June", "Jun");
+ case 7: return translate("July", "Jul");
+ case 8: return translate("August", "Aug");
+ case 9: return translate("September", "Sep");
+ case 10: return translate("October", "Oct");
+ case 11: return translate("November", "Nov");
+ case 12: return translate("December", "Dec");
+ }
+ else
+ switch (i)
+ {
+ case 1: return translate("January");
+ case 2: return translate("February");
+ case 3: return translate("March");
+ case 4: return translate("April");
+ case 5: return translate("May long", "May");
+ case 6: return translate("June");
+ case 7: return translate("July");
+ case 8: return translate("August");
+ case 9: return translate("September");
+ case 10: return translate("October");
+ case 11: return translate("November");
+ case 12: return translate("December");
+ }
+
+ return QString::null;
+}
+
+QString KLocale::monthNamePossessive(int i, bool shortName) const
+{
+ if ( shortName )
+ switch ( i )
+ {
+ case 1: return translate("of January", "of Jan");
+ case 2: return translate("of February", "of Feb");
+ case 3: return translate("of March", "of Mar");
+ case 4: return translate("of April", "of Apr");
+ case 5: return translate("of May short", "of May");
+ case 6: return translate("of June", "of Jun");
+ case 7: return translate("of July", "of Jul");
+ case 8: return translate("of August", "of Aug");
+ case 9: return translate("of September", "of Sep");
+ case 10: return translate("of October", "of Oct");
+ case 11: return translate("of November", "of Nov");
+ case 12: return translate("of December", "of Dec");
+ }
+ else
+ switch (i)
+ {
+ case 1: return translate("of January");
+ case 2: return translate("of February");
+ case 3: return translate("of March");
+ case 4: return translate("of April");
+ case 5: return translate("of May long", "of May");
+ case 6: return translate("of June");
+ case 7: return translate("of July");
+ case 8: return translate("of August");
+ case 9: return translate("of September");
+ case 10: return translate("of October");
+ case 11: return translate("of November");
+ case 12: return translate("of December");
+ }
+
+ return QString::null;
+}
+
+QString KLocale::weekDayName (int i, bool shortName) const
+{
+ if ( shortName )
+ switch ( i )
+ {
+ case 1: return translate("Monday", "Mon");
+ case 2: return translate("Tuesday", "Tue");
+ case 3: return translate("Wednesday", "Wed");
+ case 4: return translate("Thursday", "Thu");
+ case 5: return translate("Friday", "Fri");
+ case 6: return translate("Saturday", "Sat");
+ case 7: return translate("Sunday", "Sun");
+ }
+ else
+ switch ( i )
+ {
+ case 1: return translate("Monday");
+ case 2: return translate("Tuesday");
+ case 3: return translate("Wednesday");
+ case 4: return translate("Thursday");
+ case 5: return translate("Friday");
+ case 6: return translate("Saturday");
+ case 7: return translate("Sunday");
+ }
+
+ return QString::null;
+}
+
+void KLocale::insertCatalogue( const QString & catalogue )
+{
+ KCatalogue cat( catalogue );
+
+ initCatalogue( cat );
+
+ d->catalogues.append( cat );
+}
+
+void KLocale::removeCatalogue(const QString &catalogue)
+{
+ for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
+ it != d->catalogues.end(); )
+ if ((*it).name() == catalogue) {
+ it = d->catalogues.remove(it);
+ return;
+ } else
+ ++it;
+}
+
+void KLocale::setActiveCatalogue(const QString &catalogue)
+{
+ for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
+ it != d->catalogues.end(); ++it)
+ if ((*it).name() == catalogue) {
+ KCatalogue save = *it;
+ d->catalogues.remove(it);
+ d->catalogues.prepend(save);
+ return;
+ }
+}
+
+KLocale::~KLocale()
+{
+ delete d->languages;
+ delete d;
+}
+
+QString KLocale::translate_priv(const char *msgid,
+ const char *fallback,
+ const char **translated) const
+{
+ if (!msgid || !msgid[0])
+ {
+ kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
+ << "Fix the program" << endl;
+ return QString::null;
+ }
+
+ if ( useDefaultLanguage() )
+ return QString::fromUtf8( fallback );
+
+ for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
+ it != d->catalogues.end();
+ ++it )
+ {
+ // kdDebug(173) << "translate " << msgid << " " << (*it).name() << " " << (!KGlobal::activeInstance() ? QCString("no instance") : KGlobal::activeInstance()->instanceName()) << endl;
+ const char * text = (*it).translate( msgid );
+
+ if ( text )
+ {
+ // we found it
+ if (translated)
+ *translated = text;
+ return QString::fromUtf8( text );
+ }
+ }
+
+ // Always use UTF-8 if the string was not found
+ return QString::fromUtf8( fallback );
+}
+
+QString KLocale::translate(const char* msgid) const
+{
+ return translate_priv(msgid, msgid);
+}
+
+QString KLocale::translate( const char *index, const char *fallback) const
+{
+ if (!index || !index[0] || !fallback || !fallback[0])
+ {
+ kdDebug(173) << "KLocale: trying to look up \"\" in catalogue. "
+ << "Fix the program" << endl;
+ return QString::null;
+ }
+
+ if ( useDefaultLanguage() )
+ return QString::fromUtf8( fallback );
+
+ char *newstring = new char[strlen(index) + strlen(fallback) + 5];
+ sprintf(newstring, "_: %s\n%s", index, fallback);
+ // as copying QString is very fast, it looks slower as it is ;/
+ QString r = translate_priv(newstring, fallback);
+ delete [] newstring;
+
+ return r;
+}
+
+static QString put_n_in(const QString &orig, unsigned long n)
+{
+ QString ret = orig;
+ int index = ret.find("%n");
+ if (index == -1)
+ return ret;
+ ret.replace(index, 2, QString::number(n));
+ return ret;
+}
+
+#define EXPECT_LENGTH(x) \
+ if (forms.count() != x) { \
+ kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \
+ return QString( "BROKEN TRANSLATION %1" ).arg( singular ); }
+
+QString KLocale::translate( const char *singular, const char *plural,
+ unsigned long n ) const
+{
+ if (!singular || !singular[0] || !plural || !plural[0])
+ {
+ kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
+ << "Fix the program" << endl;
+ return QString::null;
+ }
+
+ char *newstring = new char[strlen(singular) + strlen(plural) + 6];
+ sprintf(newstring, "_n: %s\n%s", singular, plural);
+ // as copying QString is very fast, it looks slower as it is ;/
+ QString r = translate_priv(newstring, 0);
+ delete [] newstring;
+
+ if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) {
+ if ( n == 1 ) {
+ return put_n_in( QString::fromUtf8( singular ), n );
+ } else {
+ QString tmp = QString::fromUtf8( plural );
+#ifndef NDEBUG
+ if (tmp.find("%n") == -1) {
+ kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl;
+ }
+#endif
+ return put_n_in( tmp, n );
+ }
+ }
+
+ QStringList forms = QStringList::split( "\n", r, false );
+ switch ( d->plural_form ) {
+ case 0: // NoPlural
+ EXPECT_LENGTH( 1 );
+ return put_n_in( forms[0], n);
+ case 1: // TwoForms
+ EXPECT_LENGTH( 2 );
+ if ( n == 1 )
+ return put_n_in( forms[0], n);
+ else
+ return put_n_in( forms[1], n);
+ case 2: // French
+ EXPECT_LENGTH( 2 );
+ if ( n == 1 || n == 0 )
+ return put_n_in( forms[0], n);
+ else
+ return put_n_in( forms[1], n);
+ case 3: // Gaeilge
+ EXPECT_LENGTH( 3 );
+ if ( n == 1 )
+ return put_n_in( forms[0], n);
+ else if ( n == 2 )
+ return put_n_in( forms[1], n);
+ else
+ return put_n_in( forms[2], n);
+ case 4: // Russian, corrected by mok
+ EXPECT_LENGTH( 3 );
+ if ( n%10 == 1 && n%100 != 11)
+ return put_n_in( forms[0], n); // odin fail
+ else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20))
+ return put_n_in( forms[1], n); // dva faila
+ else
+ return put_n_in( forms[2], n); // desyat' failov
+ case 5: // Polish
+ EXPECT_LENGTH( 3 );
+ if ( n == 1 )
+ return put_n_in( forms[0], n);
+ else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) )
+ return put_n_in( forms[1], n);
+ else
+ return put_n_in( forms[2], n);
+ case 6: // Slovenian
+ EXPECT_LENGTH( 4 );
+ if ( n%100 == 1 )
+ return put_n_in( forms[1], n); // ena datoteka
+ else if ( n%100 == 2 )
+ return put_n_in( forms[2], n); // dve datoteki
+ else if ( n%100 == 3 || n%100 == 4 )
+ return put_n_in( forms[3], n); // tri datoteke
+ else
+ return put_n_in( forms[0], n); // sto datotek
+ case 7: // Lithuanian
+ EXPECT_LENGTH( 3 );
+ if ( n%10 == 0 || (n%100>=11 && n%100<=19) )
+ return put_n_in( forms[2], n);
+ else if ( n%10 == 1 )
+ return put_n_in( forms[0], n);
+ else
+ return put_n_in( forms[1], n);
+ case 8: // Czech
+ EXPECT_LENGTH( 3 );
+ if ( n%100 == 1 )
+ return put_n_in( forms[0], n);
+ else if (( n%100 >= 2 ) && ( n%100 <= 4 ))
+ return put_n_in( forms[1], n);
+ else
+ return put_n_in( forms[2], n);
+ case 9: // Slovak
+ EXPECT_LENGTH( 3 );
+ if ( n == 1 )
+ return put_n_in( forms[0], n);
+ else if (( n >= 2 ) && ( n <= 4 ))
+ return put_n_in( forms[1], n);
+ else
+ return put_n_in( forms[2], n);
+ case 10: // Maltese
+ EXPECT_LENGTH( 4 );
+ if ( n == 1 )
+ return put_n_in( forms[0], n );
+ else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) )
+ return put_n_in( forms[1], n );
+ else if ( n%100 > 10 && n%100 < 20 )
+ return put_n_in( forms[2], n );
+ else
+ return put_n_in( forms[3], n );
+ case 11: // Arabic
+ EXPECT_LENGTH( 4 );
+ if (n == 1)
+ return put_n_in(forms[0], n);
+ else if (n == 2)
+ return put_n_in(forms[1], n);
+ else if ( n < 11)
+ return put_n_in(forms[2], n);
+ else
+ return put_n_in(forms[3], n);
+ case 12: // Balcan
+ EXPECT_LENGTH( 3 );
+ if (n != 11 && n % 10 == 1)
+ return put_n_in(forms[0], n);
+ else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4)
+ return put_n_in(forms[1], n);
+ else
+ return put_n_in(forms[2], n);
+ }
+ kdError() << "The function should have been returned in another way\n";
+
+ return QString::null;
+}
+
+QString KLocale::translateQt( const char *context, const char *source,
+ const char *message) const
+{
+ if (!source || !source[0]) {
+ kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
+ << "Fix the program" << endl;
+ return QString::null;
+ }
+
+ if ( useDefaultLanguage() ) {
+ return QString::null;
+ }
+
+ char *newstring = 0;
+ const char *translation = 0;
+ QString r;
+
+ if ( message && message[0]) {
+ char *newstring = new char[strlen(source) + strlen(message) + 5];
+ sprintf(newstring, "_: %s\n%s", source, message);
+ const char *translation = 0;
+ // as copying QString is very fast, it looks slower as it is ;/
+ r = translate_priv(newstring, source, &translation);
+ delete [] newstring;
+ if (translation)
+ return r;
+ }
+
+ if ( context && context[0] && message && message[0]) {
+ newstring = new char[strlen(context) + strlen(message) + 5];
+ sprintf(newstring, "_: %s\n%s", context, message);
+ // as copying QString is very fast, it looks slower as it is ;/
+ r = translate_priv(newstring, source, &translation);
+ delete [] newstring;
+ if (translation)
+ return r;
+ }
+
+ r = translate_priv(source, source, &translation);
+ if (translation)
+ return r;
+ return QString::null;
+}
+
+bool KLocale::nounDeclension() const
+{
+ doFormatInit();
+ return d->nounDeclension;
+}
+
+bool KLocale::dateMonthNamePossessive() const
+{
+ doFormatInit();
+ return d->dateMonthNamePossessive;
+}
+
+int KLocale::weekStartDay() const
+{
+ doFormatInit();
+ return d->weekStartDay;
+}
+
+bool KLocale::weekStartsMonday() const //deprecated
+{
+ doFormatInit();
+ return (d->weekStartDay==1);
+}
+
+QString KLocale::decimalSymbol() const
+{
+ doFormatInit();
+ return m_decimalSymbol;
+}
+
+QString KLocale::thousandsSeparator() const
+{
+ doFormatInit();
+ return m_thousandsSeparator;
+}
+
+QString KLocale::currencySymbol() const
+{
+ doFormatInit();
+ return m_currencySymbol;
+}
+
+QString KLocale::monetaryDecimalSymbol() const
+{
+ doFormatInit();
+ return m_monetaryDecimalSymbol;
+}
+
+QString KLocale::monetaryThousandsSeparator() const
+{
+ doFormatInit();
+ return m_monetaryThousandsSeparator;
+}
+
+QString KLocale::positiveSign() const
+{
+ doFormatInit();
+ return m_positiveSign;
+}
+
+QString KLocale::negativeSign() const
+{
+ doFormatInit();
+ return m_negativeSign;
+}
+
+int KLocale::fracDigits() const
+{
+ doFormatInit();
+ return m_fracDigits;
+}
+
+bool KLocale::positivePrefixCurrencySymbol() const
+{
+ doFormatInit();
+ return m_positivePrefixCurrencySymbol;
+}
+
+bool KLocale::negativePrefixCurrencySymbol() const
+{
+ doFormatInit();
+ return m_negativePrefixCurrencySymbol;
+}
+
+KLocale::SignPosition KLocale::positiveMonetarySignPosition() const
+{
+ doFormatInit();
+ return m_positiveMonetarySignPosition;
+}
+
+KLocale::SignPosition KLocale::negativeMonetarySignPosition() const
+{
+ doFormatInit();
+ return m_negativeMonetarySignPosition;
+}
+
+static inline void put_it_in( QChar *buffer, uint& index, const QString &s )
+{
+ for ( uint l = 0; l < s.length(); l++ )
+ buffer[index++] = s.at( l );
+}
+
+static inline void put_it_in( QChar *buffer, uint& index, int number )
+{
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+}
+
+QString KLocale::formatMoney(double num,
+ const QString & symbol,
+ int precision) const
+{
+ // some defaults
+ QString currency = symbol.isNull()
+ ? currencySymbol()
+ : symbol;
+ if (precision < 0) precision = fracDigits();
+
+ // the number itself
+ bool neg = num < 0;
+ QString res = QString::number(neg?-num:num, 'f', precision);
+ int pos = res.find('.');
+ if (pos == -1) pos = res.length();
+ else res.replace(pos, 1, monetaryDecimalSymbol());
+
+ while (0 < (pos -= 3))
+ res.insert(pos, monetaryThousandsSeparator()); // thousend sep
+
+ // set some variables we need later
+ int signpos = neg
+ ? negativeMonetarySignPosition()
+ : positiveMonetarySignPosition();
+ QString sign = neg
+ ? negativeSign()
+ : positiveSign();
+
+ switch (signpos)
+ {
+ case ParensAround:
+ res.prepend('(');
+ res.append (')');
+ break;
+ case BeforeQuantityMoney:
+ res.prepend(sign);
+ break;
+ case AfterQuantityMoney:
+ res.append(sign);
+ break;
+ case BeforeMoney:
+ currency.prepend(sign);
+ break;
+ case AfterMoney:
+ currency.append(sign);
+ break;
+ }
+
+ if (neg?negativePrefixCurrencySymbol():
+ positivePrefixCurrencySymbol())
+ {
+ res.prepend(' ');
+ res.prepend(currency);
+ } else {
+ res.append (' ');
+ res.append (currency);
+ }
+
+ return res;
+}
+
+QString KLocale::formatMoney(const QString &numStr) const
+{
+ return formatMoney(numStr.toDouble());
+}
+
+QString KLocale::formatNumber(double num, int precision) const
+{
+ bool neg = num < 0;
+ if (precision == -1) precision = 2;
+ QString res = QString::number(neg?-num:num, 'f', precision);
+ int pos = res.find('.');
+ if (pos == -1) pos = res.length();
+ else res.replace(pos, 1, decimalSymbol());
+
+ while (0 < (pos -= 3))
+ res.insert(pos, thousandsSeparator()); // thousand sep
+
+ // How can we know where we should put the sign?
+ res.prepend(neg?negativeSign():positiveSign());
+
+ return res;
+}
+
+QString KLocale::formatLong(long num) const
+{
+ return formatNumber((double)num, 0);
+}
+
+QString KLocale::formatNumber(const QString &numStr) const
+{
+ return formatNumber(numStr.toDouble());
+}
+
+QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
+{
+ const QString rst = shortFormat?dateFormatShort():dateFormat();
+
+ // I'm rather safe than sorry
+ QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
+
+ unsigned int index = 0;
+ bool escape = false;
+ int number = 0;
+
+ int year = calendar()->year(pDate);
+ int month = calendar()->month(pDate);
+ int day = calendar()->day(pDate);
+
+ for ( uint format_index = 0; format_index < rst.length(); ++format_index )
+ {
+ if ( !escape )
+ {
+ if ( rst.at( format_index ).unicode() == '%' )
+ escape = true;
+ else
+ buffer[index++] = rst.at( format_index );
+ }
+ else
+ {
+ switch ( rst.at( format_index ).unicode() )
+ {
+ case '%':
+ buffer[index++] = '%';
+ break;
+ case 'Y':
+ put_it_in( buffer, index, year / 100 );
+ case 'y':
+ put_it_in( buffer, index, year % 100 );
+ break;
+ case 'n':
+ number = month;
+ case 'e':
+ // to share the code
+ if ( rst.at( format_index ).unicode() == 'e' )
+ number = day;
+ if ( number / 10 )
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+ break;
+ case 'm':
+ put_it_in( buffer, index, month );
+ break;
+ case 'b':
+ if (d->nounDeclension && d->dateMonthNamePossessive)
+//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, true) );
+ put_it_in( buffer, index, calendar()->monthNamePossessive(month, true) );
+ else
+//US put_it_in( buffer, index, calendar()->monthName(month, year, true) );
+ put_it_in( buffer, index, calendar()->monthName(month, true) );
+ break;
+ case 'B':
+ if (d->nounDeclension && d->dateMonthNamePossessive)
+//US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, false) );
+ put_it_in( buffer, index, calendar()->monthNamePossessive(month, false) );
+ else
+//US put_it_in( buffer, index, calendar()->monthName(month, year, false) );
+ put_it_in( buffer, index, calendar()->monthName(month, false) );
+ break;
+ case 'd':
+ put_it_in( buffer, index, day );
+ break;
+ case 'a':
+ put_it_in( buffer, index, calendar()->weekDayName(pDate, true) );
+ break;
+ case 'A':
+ put_it_in( buffer, index, calendar()->weekDayName(pDate, false) );
+ break;
+ default:
+ buffer[index++] = rst.at( format_index );
+ break;
+ }
+ escape = false;
+ }
+ }
+ QString ret( buffer, index );
+ delete [] buffer;
+ return ret;
+}
+
+void KLocale::setMainCatalogue(const char *catalogue)
+{
+ maincatalogue = catalogue;
+}
+
+double KLocale::readNumber(const QString &_str, bool * ok) const
+{
+ QString str = _str.stripWhiteSpace();
+ bool neg = str.find(negativeSign()) == 0;
+ if (neg)
+ str.remove( 0, negativeSign().length() );
+
+ /* will hold the scientific notation portion of the number.
+ Example, with 2.34E+23, exponentialPart == "E+23"
+ */
+ QString exponentialPart;
+ int EPos;
+
+ EPos = str.find('E', 0, false);
+
+ if (EPos != -1)
+ {
+ exponentialPart = str.mid(EPos);
+ str = str.left(EPos);
+ }
+
+ int pos = str.find(decimalSymbol());
+ QString major;
+ QString minor;
+ if ( pos == -1 )
+ major = str;
+ else
+ {
+ major = str.left(pos);
+ minor = str.mid(pos + decimalSymbol().length());
+ }
+
+ // Remove thousand separators
+ int thlen = thousandsSeparator().length();
+ int lastpos = 0;
+ while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
+ {
+ // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
+ int fromEnd = major.length() - pos;
+ if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
+ || pos - lastpos > 3 // More than 3 digits between two separators -> error
+ || pos == 0 // Can't start with a separator
+ || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+
+ lastpos = pos;
+ major.remove( pos, thlen );
+ }
+ if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+
+ QString tot;
+ if (neg) tot = '-';
+
+ tot += major + '.' + minor + exponentialPart;
+
+ return tot.toDouble(ok);
+}
+
+double KLocale::readMoney(const QString &_str, bool * ok) const
+{
+ QString str = _str.stripWhiteSpace();
+ bool neg = false;
+ bool currencyFound = false;
+ // First try removing currency symbol from either end
+ int pos = str.find(currencySymbol());
+ if ( pos == 0 || pos == (int) str.length()-1 )
+ {
+ str.remove(pos,currencySymbol().length());
+ str = str.stripWhiteSpace();
+ currencyFound = true;
+ }
+ if (str.isEmpty())
+ {
+ if (ok) *ok = false;
+ return 0;
+ }
+ // Then try removing negative sign from either end
+ // (with a special case for parenthesis)
+ if (negativeMonetarySignPosition() == ParensAround)
+ {
+ if (str.at(0) == '(' && str.at(str.length()-1) == ')')
+ {
+ neg = true;
+ str.remove(str.length()-1,1);
+ str.remove(0,1);
+ }
+ }
+ else
+ {
+ int i1 = str.find(negativeSign());
+ if ( i1 == 0 || i1 == (int) str.length()-1 )
+ {
+ neg = true;
+ str.remove(i1,negativeSign().length());
+ }
+ }
+ if (neg) str = str.stripWhiteSpace();
+
+ // Finally try again for the currency symbol, if we didn't find
+ // it already (because of the negative sign being in the way).
+ if ( !currencyFound )
+ {
+ pos = str.find(currencySymbol());
+ if ( pos == 0 || pos == (int) str.length()-1 )
+ {
+ str.remove(pos,currencySymbol().length());
+ str = str.stripWhiteSpace();
+ }
+ }
+
+ // And parse the rest as a number
+ pos = str.find(monetaryDecimalSymbol());
+ QString major;
+ QString minior;
+ if (pos == -1)
+ major = str;
+ else
+ {
+ major = str.left(pos);
+ minior = str.mid(pos + monetaryDecimalSymbol().length());
+ }
+
+ // Remove thousand separators
+ int thlen = monetaryThousandsSeparator().length();
+ int lastpos = 0;
+ while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 )
+ {
+ // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
+ int fromEnd = major.length() - pos;
+ if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
+ || pos - lastpos > 3 // More than 3 digits between two separators -> error
+ || pos == 0 // Can't start with a separator
+ || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+ lastpos = pos;
+ major.remove( pos, thlen );
+ }
+ if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
+ {
+ if (ok) *ok = false;
+ return 0.0;
+ }
+
+ QString tot;
+ if (neg) tot = '-';
+ tot += major + '.' + minior;
+ return tot.toDouble(ok);
+}
+
+/**
+ * helper function to read integers
+ * @param str
+ * @param pos the position to start at. It will be updated when we parse it.
+ * @return the integer read in the string, or -1 if no string
+ */
+static int readInt(const QString &str, uint &pos)
+{
+ if (!str.at(pos).isDigit()) return -1;
+ int result = 0;
+ for (; str.length() > pos && str.at(pos).isDigit(); pos++)
+ {
+ result *= 10;
+ result += str.at(pos).digitValue();
+ }
+
+ return result;
+}
+
+QDate KLocale::readDate(const QString &intstr, bool* ok) const
+{
+ QDate date;
+ date = readDate(intstr, ShortFormat, ok);
+ if (date.isValid()) return date;
+ return readDate(intstr, NormalFormat, ok);
+}
+
+QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const
+{
+ QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
+ return readDate( intstr, fmt, ok );
+}
+
+QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
+{
+ //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
+ QString str = intstr.simplifyWhiteSpace().lower();
+ int day = -1, month = -1;
+ // allow the year to be omitted if not in the format
+ int year = calendar()->year(QDate::currentDate());
+ uint strpos = 0;
+ uint fmtpos = 0;
+
+ bool error = false;
+
+ while (fmt.length() > fmtpos && str.length() > strpos && !error)
+ {
+
+ QChar c = fmt.at(fmtpos++);
+
+ if (c != '%') {
+ if (c.isSpace() && str.at(strpos).isSpace())
+ strpos++;
+ else if (c != str.at(strpos++))
+ error = true;
+ }
+ else
+ {
+ int j;
+ // remove space at the begining
+ if (str.length() > strpos && str.at(strpos).isSpace())
+ strpos++;
+
+ c = fmt.at(fmtpos++);
+ switch (c)
+ {
+ case 'a':
+ case 'A':
+
+ error = true;
+ j = 1;
+ while (error && (j < 8)) {
+ QString s = weekDayName(j, c == 'a').lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s)
+ {
+ strpos += len;
+ error = false;
+ }
+ j++;
+ }
+ break;
+ case 'b':
+ case 'B':
+
+ error = true;
+ if (d->nounDeclension && d->dateMonthNamePossessive) {
+ j = 1;
+ while (error && (j < 13)) {
+//US QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower();
+ QString s = calendar()->monthNamePossessive(j, c == 'b').lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s) {
+ month = j;
+ strpos += len;
+ error = false;
+ }
+ j++;
+ }
+ }
+ j = 1;
+ while (error && (j < 13)) {
+//US QString s = calendar()->monthName(j, year, c == 'b').lower();
+ QString s = calendar()->monthName(j, c == 'b').lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s) {
+ month = j;
+ strpos += len;
+ error = false;
+ }
+ j++;
+ }
+ break;
+ case 'd':
+ case 'e':
+ day = readInt(str, strpos);
+ error = (day < 1 || day > 31);
+ break;
+
+ case 'n':
+ case 'm':
+ month = readInt(str, strpos);
+ error = (month < 1 || month > 12);
+ break;
+
+ case 'Y':
+ case 'y':
+ year = readInt(str, strpos);
+ error = (year < 0);
+ // Qt treats a year in the range 0-100 as 1900-1999.
+ // It is nicer for the user if we treat 0-68 as 2000-2068
+ if (c == 'y' && year < 69)
+ // eg. gregorian += 2000
+ year += (calendar()->year(QDate::currentDate()) / 100) * 100;
+ else if (c == 'y' && year < 100)
+ // eg. gregorian += 1900
+ year += (calendar()->year(QDate::currentDate()) / 100) * 100 - 100;
+ break;
+ }
+ }
+ }
+
+ /* for a match, we should reach the end of both strings, not just one of
+ them */
+ if ( fmt.length() > fmtpos || str.length() > strpos )
+ {
+ error = true;
+ }
+
+ //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
+ if ( year != -1 && month != -1 && day != -1 && !error)
+ {
+ if (ok) *ok = true;
+
+ QDate result;
+ calendar()->setYMD(result, year, month, day);
+
+ return result;
+ }
+ else
+ {
+ if (ok) *ok = false;
+ return QDate(); // invalid date
+ }
+}
+
+QTime KLocale::readTime(const QString &intstr, bool *ok) const
+{
+ QTime _time;
+ _time = readTime(intstr, WithSeconds, ok);
+ if (_time.isValid()) return _time;
+ return readTime(intstr, WithoutSeconds, ok);
+}
+
+QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const
+{
+ QString str = intstr.simplifyWhiteSpace().lower();
+ QString Format = timeFormat().simplifyWhiteSpace();
+ if (flags & WithoutSeconds)
+ {
+//US remove not available in my QT version
+//US Format.remove(QRegExp(".%S"));
+ Format.replace(QRegExp(".%S"), "");
+ }
+
+ int hour = -1, minute = -1;
+ int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds
+ bool g_12h = false;
+ bool pm = false;
+ uint strpos = 0;
+ uint Formatpos = 0;
+
+ while (Format.length() > Formatpos || str.length() > strpos)
+ {
+ if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
+
+ QChar c = Format.at(Formatpos++);
+
+ if (c != '%')
+ {
+ if (c.isSpace())
+ strpos++;
+ else if (c != str.at(strpos++))
+ goto error;
+ continue;
+ }
+
+ // remove space at the begining
+ if (str.length() > strpos && str.at(strpos).isSpace())
+ strpos++;
+
+ c = Format.at(Formatpos++);
+ switch (c)
+ {
+ case 'p':
+ {
+ QString s;
+ s = translate("pm").lower();
+ int len = s.length();
+ if (str.mid(strpos, len) == s)
+ {
+ pm = true;
+ strpos += len;
+ }
+ else
+ {
+ s = translate("am").lower();
+ len = s.length();
+ if (str.mid(strpos, len) == s) {
+ pm = false;
+ strpos += len;
+ }
+ else
+ goto error;
+ }
+ }
+ break;
+
+ case 'k':
+ case 'H':
+ g_12h = false;
+ hour = readInt(str, strpos);
+ if (hour < 0 || hour > 23)
+ goto error;
+
+ break;
+
+ case 'l':
+ case 'I':
+ g_12h = true;
+ hour = readInt(str, strpos);
+ if (hour < 1 || hour > 12)
+ goto error;
+
+ break;
+
+ case 'M':
+ minute = readInt(str, strpos);
+ if (minute < 0 || minute > 59)
+ goto error;
+
+ break;
+
+ case 'S':
+ second = readInt(str, strpos);
+ if (second < 0 || second > 59)
+ goto error;
+
+ break;
+ }
+ }
+ if (g_12h) {
+ hour %= 12;
+ if (pm) hour += 12;
+ }
+
+ if (ok) *ok = true;
+ return QTime(hour, minute, second);
+
+ error:
+ if (ok) *ok = false;
+ return QTime(-1, -1, -1); // return invalid date if it didn't work
+}
+
+QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
+{
+ const QString rst = timeFormat();
+
+ // only "pm/am" here can grow, the rest shrinks, but
+ // I'm rather safe than sorry
+ QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
+
+ uint index = 0;
+ bool escape = false;
+ int number = 0;
+
+ for ( uint format_index = 0; format_index < rst.length(); format_index++ )
+ {
+ if ( !escape )
+ {
+ if ( rst.at( format_index ).unicode() == '%' )
+ escape = true;
+ else
+ buffer[index++] = rst.at( format_index );
+ }
+ else
+ {
+ switch ( rst.at( format_index ).unicode() )
+ {
+ case '%':
+ buffer[index++] = '%';
+ break;
+ case 'H':
+ put_it_in( buffer, index, pTime.hour() );
+ break;
+ case 'I':
+ put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
+ break;
+ case 'M':
+ put_it_in( buffer, index, pTime.minute() );
+ break;
+ case 'S':
+ if (includeSecs)
+ put_it_in( buffer, index, pTime.second() );
+ else if ( index > 0 )
+ {
+ // we remove the seperator sign before the seconds and
+ // assume that works everywhere
+ --index;
+ break;
+ }
+ break;
+ case 'k':
+ number = pTime.hour();
+ case 'l':
+ // to share the code
+ if ( rst.at( format_index ).unicode() == 'l' )
+ number = (pTime.hour() + 11) % 12 + 1;
+ if ( number / 10 )
+ buffer[index++] = number / 10 + '0';
+ buffer[index++] = number % 10 + '0';
+ break;
+ case 'p':
+ {
+ QString s;
+ if ( pTime.hour() >= 12 )
+ put_it_in( buffer, index, translate("pm") );
+ else
+ put_it_in( buffer, index, translate("am") );
+ break;
+ }
+ default:
+ buffer[index++] = rst.at( format_index );
+ break;
+ }
+ escape = false;
+ }
+ }
+ QString ret( buffer, index );
+ delete [] buffer;
+ return ret;
+}
+
+bool KLocale::use12Clock() const
+{
+ if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) ||
+ (timeFormat().contains(QString::fromLatin1("%l")) > 0))
+ return true;
+ else
+ return false;
+}
+
+QString KLocale::languages() const
+{
+ return d->languageList.join( QString::fromLatin1(":") );
+}
+
+QStringList KLocale::languageList() const
+{
+ return d->languageList;
+}
+
+QString KLocale::formatDateTime(const QDateTime &pDateTime,
+ bool shortFormat,
+ bool includeSeconds) const
+{
+ return translate("concatenation of dates and time", "%1 %2")
+ .arg( formatDate( pDateTime.date(), shortFormat ) )
+ .arg( formatTime( pDateTime.time(), includeSeconds ) );
+}
+
+QString i18n(const char* text)
+{
+ /*
+ register KLocale *instance = KGlobal::locale();
+ if (instance)
+ return instance->translate(text);
+ */
+ return QString::fromUtf8(text);
+}
+
+QString i18n(const char* index, const char *text)
+{
+ /*
+ register KLocale *instance = KGlobal::locale();
+ if (instance)
+ return instance->translate(index, text);
+ */
+ return QString::fromUtf8(text);
+}
+
+QString i18n(const char* singular, const char* plural, unsigned long n)
+{
+ return (QString::fromUtf8(plural)); // hack! remove this line!
+ register KLocale *instance = KGlobal::locale();
+ if (instance)
+ return instance->translate(singular, plural, n);
+ if (n == 1)
+ return put_n_in(QString::fromUtf8(singular), n);
+ else
+ return put_n_in(QString::fromUtf8(plural), n);
+}
+
+void KLocale::initInstance()
+{
+ if (KGlobal::locale())
+ return;
+
+/*US lets change the whole way how to create a KLocale
+ KInstance *app = KGlobal::instance();
+ if (app) {
+ KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName()));
+
+ // only do this for the global instance
+ QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding());
+ }
+ else
+ kdDebug(173) << "no app name available using KLocale - nothing to do\n";
+*/
+//US new implementation
+ QString appname = KGlobal::getAppName();
+ if (appname) {
+ KLocale *l = new KLocale(appname);
+ KGlobal::setLocale(l);
+
+ // only do this for the global instance
+//US
+//US QTextCodec::setCodecForLocale(KGlobal::locale())->codecForEncoding());
+//US qt_set_locale_codec( KGlobal::locale()->codecForEncoding() );
+ qDebug("KLocale::initInstance we have to do here something !!!");
+ }
+ else
+ kdDebug(173) << "no app name available using KLocale - nothing to do\n";
+
+}
+
+QString KLocale::langLookup(const QString &fname, const char *rtype)
+{
+ QStringList search;
+
+ // assemble the local search paths
+//US we have only one resourcedir. So use it !!
+/*US original
+ const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype);
+ // look up the different languages
+ for (int id=localDoc.count()-1; id >= 0; --id)
+ {
+ QStringList langs = KGlobal::locale()->languageList();
+ langs.append( "en" );
+ langs.remove( defaultLanguage() );
+ QStringList::ConstIterator lang;
+ for (lang = langs.begin(); lang != langs.end(); ++lang)
+ search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
+ }
+*/
+//US new code
+//US What is here correct??? const QString localDoc = KGlobal::dirs()->findResourceDir(rtype);
+ const QString localDoc = rtype;
+ // look up the different languages
+ QStringList langs = KGlobal::locale()->languageList();
+ langs.append( "en" );
+ langs.remove( defaultLanguage() );
+ QStringList::ConstIterator lang;
+ for (lang = langs.begin(); lang != langs.end(); ++lang)
+ search.append(QString("%1%2/%3").arg(localDoc).arg(*lang).arg(fname));
+
+ // try to locate the file
+ QStringList::Iterator it;
+ for (it = search.begin(); it != search.end(); ++it)
+ {
+ kdDebug(173) << "Looking for help in: " << *it << endl;
+
+ QFileInfo info(*it);
+ if (info.exists() && info.isFile() && info.isReadable())
+ return *it;
+ }
+
+ return QString::null;
+}
+
+bool KLocale::useDefaultLanguage() const
+{
+ return language() == defaultLanguage();
+}
+
+void KLocale::initEncoding(KConfig *)
+{
+ const int mibDefault = 4; // ISO 8859-1
+
+ // This all made more sense when we still had the EncodingEnum config key.
+ setEncoding( QTextCodec::codecForLocale()->mibEnum() );
+
+ if ( !d->codecForEncoding )
+ {
+ kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl;
+ setEncoding(mibDefault);
+ }
+
+ ASSERT( d->codecForEncoding );
+}
+
+void KLocale::initFileNameEncoding(KConfig *)
+{
+ // If the following environment variable is set, assume all filenames
+ // are in UTF-8 regardless of the current C locale.
+ d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0;
+ if (d->utf8FileEncoding)
+ {
+ QFile::setEncodingFunction(KLocale::encodeFileNameUTF8);
+ QFile::setDecodingFunction(KLocale::decodeFileNameUTF8);
+ }
+ // Otherwise, stay with QFile's default filename encoding functions
+ // which, on Unix platforms, use the locale's codec.
+}
+
+QCString KLocale::encodeFileNameUTF8( const QString & fileName )
+{
+ return fileName.utf8();
+}
+
+QString KLocale::decodeFileNameUTF8( const QCString & localFileName )
+{
+ return QString::fromUtf8(localFileName);
+}
+
+void KLocale::initCatalogue( KCatalogue & catalogue )
+{
+ catalogue.setFileName( catalogueFileName( language(), catalogue ) );
+}
+
+void KLocale::setDateFormat(const QString & format)
+{
+ doFormatInit();
+ m_dateFormat = format.stripWhiteSpace();
+}
+
+void KLocale::setDateFormatShort(const QString & format)
+{
+ doFormatInit();
+ m_dateFormatShort = format.stripWhiteSpace();
+}
+
+void KLocale::setDateMonthNamePossessive(bool possessive)
+{
+ doFormatInit();
+ d->dateMonthNamePossessive = possessive;
+}
+
+void KLocale::setTimeFormat(const QString & format)
+{
+ doFormatInit();
+ m_timeFormat = format.stripWhiteSpace();
+}
+
+void KLocale::setWeekStartsMonday(bool start) //deprecated
+{
+ doFormatInit();
+ if (start)
+ d->weekStartDay = 1;
+ else
+ d->weekStartDay = 7;
+}
+
+void KLocale::setWeekStartDay(int day)
+{
+ doFormatInit();
+ if (day>7 || day<1)
+ d->weekStartDay = 1; //Monday is default
+ else
+ d->weekStartDay = day;
+}
+
+QString KLocale::dateFormat() const
+{
+ doFormatInit();
+ return m_dateFormat;
+}
+
+QString KLocale::dateFormatShort() const
+{
+ doFormatInit();
+ return m_dateFormatShort;
+}
+
+QString KLocale::timeFormat() const
+{
+ doFormatInit();
+ return m_timeFormat;
+}
+
+void KLocale::setDecimalSymbol(const QString & symbol)
+{
+ doFormatInit();
+ m_decimalSymbol = symbol.stripWhiteSpace();
+}
+
+void KLocale::setThousandsSeparator(const QString & separator)
+{
+ doFormatInit();
+ // allow spaces here
+ m_thousandsSeparator = separator;
+}
+
+void KLocale::setPositiveSign(const QString & sign)
+{
+ doFormatInit();
+ m_positiveSign = sign.stripWhiteSpace();
+}
+
+void KLocale::setNegativeSign(const QString & sign)
+{
+ doFormatInit();
+ m_negativeSign = sign.stripWhiteSpace();
+}
+
+void KLocale::setPositiveMonetarySignPosition(SignPosition signpos)
+{
+ doFormatInit();
+ m_positiveMonetarySignPosition = signpos;
+}
+
+void KLocale::setNegativeMonetarySignPosition(SignPosition signpos)
+{
+ doFormatInit();
+ m_negativeMonetarySignPosition = signpos;
+}
+
+void KLocale::setPositivePrefixCurrencySymbol(bool prefix)
+{
+ doFormatInit();
+ m_positivePrefixCurrencySymbol = prefix;
+}
+
+void KLocale::setNegativePrefixCurrencySymbol(bool prefix)
+{
+ doFormatInit();
+ m_negativePrefixCurrencySymbol = prefix;
+}
+
+void KLocale::setFracDigits(int digits)
+{
+ doFormatInit();
+ m_fracDigits = digits;
+}
+
+void KLocale::setMonetaryThousandsSeparator(const QString & separator)
+{
+ doFormatInit();
+ // allow spaces here
+ m_monetaryThousandsSeparator = separator;
+}
+
+void KLocale::setMonetaryDecimalSymbol(const QString & symbol)
+{
+ doFormatInit();
+ m_monetaryDecimalSymbol = symbol.stripWhiteSpace();
+}
+
+void KLocale::setCurrencySymbol(const QString & symbol)
+{
+ doFormatInit();
+ m_currencySymbol = symbol.stripWhiteSpace();
+}
+
+int KLocale::pageSize() const
+{
+ doFormatInit();
+ return d->pageSize;
+}
+
+void KLocale::setPageSize(int pageSize)
+{
+ // #### check if it's in range??
+ doFormatInit();
+ d->pageSize = pageSize;
+}
+
+KLocale::MeasureSystem KLocale::measureSystem() const
+{
+ doFormatInit();
+ return d->measureSystem;
+}
+
+void KLocale::setMeasureSystem(MeasureSystem value)
+{
+ doFormatInit();
+ d->measureSystem = value;
+}
+
+QString KLocale::defaultLanguage()
+{
+ return QString::fromLatin1("en_US");
+}
+
+QString KLocale::defaultCountry()
+{
+ return QString::fromLatin1("C");
+}
+
+const char * KLocale::encoding() const
+{
+ return codecForEncoding()->name();
+}
+
+int KLocale::encodingMib() const
+{
+ return codecForEncoding()->mibEnum();
+}
+
+int KLocale::fileEncodingMib() const
+{
+ if (d->utf8FileEncoding)
+ return 106;
+ return codecForEncoding()->mibEnum();
+}
+
+QTextCodec * KLocale::codecForEncoding() const
+{
+ return d->codecForEncoding;
+}
+
+bool KLocale::setEncoding(int mibEnum)
+{
+ QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
+ if (codec)
+ d->codecForEncoding = codec;
+
+ return codec != 0;
+}
+
+QStringList KLocale::languagesTwoAlpha() const
+{
+ if (d->langTwoAlpha.count())
+ return d->langTwoAlpha;
+
+ const QStringList &origList = languageList();
+
+ QStringList result;
+
+//US KConfig config(QString::fromLatin1("language.codes"), true, false);
+ KConfig config(locateLocal("config", QString::fromLatin1("language.codes")));
+ config.setGroup("TwoLetterCodes");
+
+ for ( QStringList::ConstIterator it = origList.begin();
+ it != origList.end();
+ ++it )
+ {
+ QString lang = *it;
+ QStringList langLst;
+
+/*US I changed the following code, because hasKey is not available.
+!!! check if my version is correct
+ if (config.hasKey( lang ))
+ langLst = config.readListEntry( lang );
+ else
+ {
+ int i = lang.find('_');
+ if (i >= 0)
+ lang.truncate(i);
+ langLst << lang;
+ }
+*/
+ langLst = config.readListEntry( lang );
+ if (langLst.isEmpty())
+ {
+ int i = lang.find('_');
+ if (i >= 0)
+ lang.truncate(i);
+ langLst << lang;
+ }
+
+
+ for ( QStringList::ConstIterator langIt = langLst.begin();
+ langIt != langLst.end();
+ ++langIt )
+ {
+ if ( !(*langIt).isEmpty() && !result.contains( *langIt ) )
+ result += *langIt;
+ }
+ }
+ d->langTwoAlpha = result;
+ return result;
+}
+
+QStringList KLocale::allLanguagesTwoAlpha() const
+{
+ if (!d->languages)
+//US d->languages = new KConfig("all_languages", true, false, "locale");
+ d->languages = new KConfig(locateLocal( "locale", "all_languages"));
+
+//US return d->languages->groupList();
+ qDebug("KLocale::allLanguagesTwoAlpha has to be fixed.");
+ return *(new QStringList());
+
+}
+
+QString KLocale::twoAlphaToLanguageName(const QString &code) const
+{
+ if (!d->languages)
+//US d->languages = new KConfig("all_languages", true, false, "locale");
+ d->languages = new KConfig(locateLocal( "locale", "all_languages"));
+
+ d->languages->setGroup(code.lower());
+ return d->languages->readEntry("Name");
+}
+
+QStringList KLocale::allCountriesTwoAlpha() const
+{
+ QStringList countries;
+
+ qDebug("KLocale::allCountriesTwoAlpha has to be fixed.");
+//US QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
+ QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop", true, true);
+
+ for(QStringList::ConstIterator it = paths.begin();
+ it != paths.end(); ++it)
+ {
+ QString code = (*it).mid((*it).length()-16, 2);
+ if (code != "/C")
+ countries.append(code);
+ }
+ return countries;
+}
+
+QString KLocale::twoAlphaToCountryName(const QString &code) const
+{
+//US KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale");
+ KConfig cfg(locateLocal("locale", "l10n/"+code.lower()+"/entry.desktop"));
+ cfg.setGroup("KCM Locale");
+ return cfg.readEntry("Name");
+}
+
+void KLocale::setCalendar(const QString & calType)
+{
+ doFormatInit();
+
+ d->calendarType = calType;
+
+ delete d->calendar;
+ d->calendar = 0;
+}
+
+QString KLocale::calendarType() const
+{
+ doFormatInit();
+
+ return d->calendarType;
+}
+
+const KCalendarSystem * KLocale::calendar() const
+{
+ doFormatInit();
+
+ // Check if it's the correct calendar?!?
+//US we are always using the gregorian calendar
+//US if ( !d->calendar )
+//US d->calendar = KCalendarSystemFactory::create( d->calendarType, this );
+ if ( !d->calendar )
+ d->calendar = new KCalendarSystemGregorian;
+
+ return d->calendar;
+}
+
+KLocale::KLocale(const KLocale & rhs)
+{
+ d = new KLocalePrivate;
+
+ *this = rhs;
+}
+
+KLocale & KLocale::operator=(const KLocale & rhs)
+{
+ // Numbers and money
+ m_decimalSymbol = rhs.m_decimalSymbol;
+ m_thousandsSeparator = rhs.m_thousandsSeparator;
+ m_currencySymbol = rhs.m_currencySymbol;
+ m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
+ m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
+ m_positiveSign = rhs.m_positiveSign;
+ m_negativeSign = rhs.m_negativeSign;
+ m_fracDigits = rhs.m_fracDigits;
+ m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
+ m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
+ m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
+ m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
+
+ // Date and time
+ m_timeFormat = rhs.m_timeFormat;
+ m_dateFormat = rhs.m_dateFormat;
+ m_dateFormatShort = rhs.m_dateFormatShort;
+
+ m_language = rhs.m_language;
+ m_country = rhs.m_country;
+
+ // the assignment operator works here
+ *d = *rhs.d;
+ d->languages = 0; // Don't copy languages
+ d->calendar = 0; // Don't copy the calendar
+
+ return *this;
+}
+
+bool KLocale::setCharset(const QString & ) { return true; }
+QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); }
+
+
+int KLocale::timezoneOffset( QString timeZone )
+{
+ int ret = 1001;
+ int index = mTimeZoneList.findIndex( timeZone );
+ if ( index < 24 )
+ ret = ( index-11 ) * 60 ;
+ return ret;
+}
+
+QStringList KLocale::timeZoneList() const
+{
+ return mTimeZoneList;
+}
+void KLocale::setTimezone( const QString &timeZone )
+{
+ mTimeZoneOffset = timezoneOffset( timeZone );
+}
+
+void KLocale::setDaylightSaving( bool b, int start , int end )
+{
+ daylightEnabled = b;
+ daylightStart = start;
+ daylightEnd = end;
+ mSouthDaylight = (end < start);
+ // qDebug("klocale daylight %d %d %d ", b, start , end );
+}
+
+int KLocale::localTimeOffset( const QDateTime &dt )
+{
+ bool addDaylight = false;
+ if ( daylightEnabled ) {
+ int d_end, d_start;
+ int dayofyear = dt.date().dayOfYear();
+ int year = dt.date().year();
+ int add = 0;
+ if ( QDate::leapYear(year) )
+ add = 1;
+ QDate date ( year,1,1 );
+ if ( daylightEnd > 59 )
+ d_end = daylightEnd +add;
+ else
+ d_end = daylightEnd;
+ if ( daylightStart > 59 )
+ d_start = daylightStart +add;
+ else
+ d_start = daylightStart;
+ QDate s_date = date.addDays( d_start -1 );
+ QDate e_date = date.addDays( d_end -1 );
+ int dof = s_date.dayOfWeek();
+ if ( dof < 7 )
+ s_date = s_date.addDays( -dof );
+ dof = e_date.dayOfWeek();
+ if ( dof < 7 )
+ e_date = e_date.addDays( -dof );
+ QTime startTime ( 3,0,0 );
+ QDateTime startDt( s_date, startTime );
+ QDateTime endDt( e_date, startTime );
+ //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( ));
+ if ( mSouthDaylight ) {
+ if ( ! ( endDt < dt && dt < startDt) )
+ addDaylight = true;
+ } else {
+ if ( startDt < dt && dt < endDt )
+ addDaylight = true;
+
+
+ }
+ }
+ int addMin = 0;
+ if ( addDaylight )
+ addMin = 60;
+ return mTimeZoneOffset + addMin;
+}
+
+void KLocale::setHore24Format ( bool b )
+{
+ mHourF24Format = b;
+}
+void KLocale::setWeekStartMonday( bool b )
+{
+ mWeekStartsMonday = b;
+}
+void KLocale::setIntDateFormat( int i )
+{
+ mIntDateFormat = i;
+}
+void KLocale::setLanguage( int i )
+{
+ mLanguage = i;
+}
+
+
+
diff --git a/microkde/kdecore/klocale_new.h b/microkde/kdecore/klocale_new.h
new file mode 100644
index 0000000..777c0bd
--- a/dev/null
+++ b/microkde/kdecore/klocale_new.h
@@ -0,0 +1,1224 @@
+#ifndef MINIKDE_KLOCALE_H
+#define MINIKDE_KLOCALE_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdict.h>
+
+class QStringList;
+class QTextCodec;
+class QDate;
+class QTime;
+class QDateTime;
+
+class KGlobal;
+class KConfig;
+class KConfigBase;
+class KLocalePrivate;
+class KCatalogue;
+class KCalendarSystem;
+
+#ifndef I18N_NOOP
+#define I18N_NOOP(x) (x)
+#endif
+
+void setLocaleDict( QDict<char> * dict );
+
+/**
+ * i18n is the function that does everything you need to translate
+ * a string. You just wrap around every user visible string a i18n
+ * call to get a QString with the string in the user's preferred
+ * language.
+ *
+ * The argument must be an UTF-8 encoded string (If you only use
+ * characters that are in US-ASCII, you're on the safe side. But
+ * for e.g. german umlauts or french accents should be recoded to
+ * UTF-8)
+ **/
+QString i18n(const char *text);
+
+/**
+ * If the string is too ambiguous to be translated well to a non-english
+ * language, use this form of i18n to separate lookup string and english
+ * text.
+ * @see translate
+ **/
+QString i18n(const char *index, const char *text);
+
+/**
+ * If you want to handle plural forms, use this form of i18n.
+ * The plural has to contain a %n where n fits into.
+ * @see translate
+ **/
+QString i18n(const char *singular, const char *plural, unsigned long n);
+
+/**
+ * Qt3's uic generates i18n( "msg", "comment" ) calls which conflict
+ * with our i18n method. We use uic -tr tr2i18n to redirect
+ * to the right i18n() function
+**/
+inline QString tr2i18n(const char* message, const char* =0) {
+ return i18n(message);
+}
+
+/**
+ *
+ * KLocale provides support for country specific stuff like
+ * the national language.
+ *
+ * KLocale supports translating, as well as specifying the format
+ * for numbers, currency, time, and date.
+ *
+ * @author Stephan Kulow <coolo@kde.org>, Preston Brown <pbrown@kde.org>,
+ * Hans Petter Bieker <bieker@kde.org>, Lukas Tinkl <lukas.tinkl@suse.cz>
+ * @short class for supporting locale settings and national language
+ */
+class KLocale
+{
+ friend class KGlobal; // for initInstance()
+public:
+ /**
+ * Constructs a KLocale with the given catalogue name.
+ * The constructor looks for an entry Locale/Language in the
+ * configuration file.
+ * If no config file is specified, it will also look for languages
+ * using the environment variables (KDE_LANG, LC_MESSAGES, LC_ALL, LANG),
+ * as well as the global configuration fie. If we were not able to use
+ * non of the specified languages, the default language (en_US) will be
+ * used.
+ *
+ * If you specify a configuration file, it has to be valid until
+ * the KLocale object is destroyed.
+ *
+ * @param catalogue The name of the main language file
+ * @param config The configuration file to use.
+ */
+ KLocale( const QString& catalogue, KConfig *config = 0 );
+
+ /**
+ * Copy constructor.
+ */
+ KLocale( const KLocale & rhs );
+
+ /**
+ * Assignment operator.
+ */
+ KLocale& operator= ( const KLocale & rhs );
+
+ /**
+ * Destructor.
+ */
+ ~KLocale();
+
+ /**
+ * Translates the string into the corresponding string in
+ * the national language, if available. If not, returns
+ * the string itself.
+ * There is a KDE wide message file that contains the most
+ * often used phrases, so we can avoid duplicating the
+ * translation of these phrases. If a phrase is not found
+ * in the catalogue given to the constructor, it will search
+ * in the system catalog. This makes it possible to override
+ * some phrases for your needs.
+ *
+ * The argument must be an UTF-8 encoded string (If you only use
+ * characters that are in US-ASCII you're on the safe side. But
+ * for e.g. german umlauts or french accents should be recoded to
+ * UTF-8)
+ *
+ * @param index The lookup text and default text, if not found.
+ */
+ QString translate( const char *index ) const;
+
+ /**
+ * Translates the string into the corresponding string in the
+ * national language, if available.
+ *
+ * The real contents of the string is in the argument fallback,
+ * but the meaning of it is coded into the argument index.
+ * In some cases you'll need this function, when english is
+ * too ambiguous to express it.
+ *
+ * Most of the times the translators will tell you if it can't
+ * be translated as it, but think of cases as "New", where the
+ * translations differs depending on what is New.
+ * Or simple cases as "Open", that can be used to express something
+ * is open or it can be used to express that you want something to
+ * open... There are tons of such examples.
+ *
+ * If translate("Open") is not enough to translate it well, use
+ * translate("To Open", "Open") or translate("Is Open", "Open").
+ * The english user will see "Open" in both cases, but the translated
+ * version may vary. Of course you can also use i18n()
+ *
+ * @param index The lookup text
+ * @param fallback the default text, if not found
+ * @return translation
+ */
+ QString translate( const char *index, const char *fallback) const;
+
+ /**
+ * Used to get the correct, translated singular or plural of a
+ * word.
+ * @param singular the singular form of the word, for example "file".
+ * @param plural the plural form of the word. Must contain a "%n" that will
+ * be replaced by the number @n, for example "%n files"
+ * @param n the number
+ * @return the correct singular or plural for the selected language,
+ * depending on n
+ */
+ QString translate( const char *singular, const char *plural,
+ unsigned long n) const;
+
+ /**
+ * Changes the current encoding.
+ *
+ * @param mibEnum The mib of the preferred codec
+ *
+ * @return True on success.
+ */
+ bool setEncoding(int mibEnum);
+
+ /**
+ * Changes the current language. The current language will be left
+ * unchanged if failed. It will force a reload of the country specific
+ * configuration as well.
+ *
+ * @param language The language code.
+ *
+ * @return True on success.
+ */
+ bool setLanguage(const QString & language);
+
+ /**
+ * Changes the list of prefed languages for the locale. The first valid
+ * language in the list will be used, or the default (en_US) language
+ * will be used if non of the specified languages were available.
+ *
+ * @param languages The list of language codes.
+ *
+ * @return True if one of the specified languages were used.
+ */
+ bool setLanguage(const QStringList & languages);
+
+ /**
+ * Changes the current country. The current country will be left
+ * unchanged if failed. It will force a reload of the country specific
+ * configuration.
+ *
+ * @param country The ISO 3166 country code.
+ *
+ * @return True on success.
+ */
+ bool setCountry(const QString & country);
+
+ /**
+ * Various positions for where to place the positive or negative
+ * sign when they are related to a monetary value.
+ */
+ enum SignPosition { ParensAround = 0, BeforeQuantityMoney = 1,
+ AfterQuantityMoney = 2,
+ BeforeMoney = 3, AfterMoney = 4 };
+
+ /**
+ * Returns what a decimal point should look like ("." or "," etc.)
+ * according to the current locale or user settings.
+ *
+ * @return The decimal symbol used by locale.
+ */
+ QString decimalSymbol() const;
+
+ /**
+ * Returns what the thousands separator should look
+ * like ("," or "." etc.)
+ * according to the current locale or user settings.
+ *
+ * @return The thousands separator used by locale.
+ */
+ QString thousandsSeparator() const;
+
+ /**
+ * Returns what the symbol denoting currency in the current locale
+ * as as defined by user settings should look like.
+ *
+ * @return The default currency symbol used by locale.
+ */
+ QString currencySymbol() const;
+
+ /**
+ * Returns what a decimal point should look like ("." or "," etc.)
+ * for monetary values, according to the current locale or user
+ * settings.
+ *
+ * @return The monetary decimal symbol used by locale.
+ */
+ QString monetaryDecimalSymbol() const;
+
+ /**
+ * Returns what a thousands separator for monetary values should
+ * look like ("," or " " etc.) according to the current locale or
+ * user settings.
+ *
+ * @return The monetary thousands separator used by locale.
+ */
+ QString monetaryThousandsSeparator() const;
+
+ /**
+ * Returns what a positive sign should look like ("+", " ", etc.)
+ * according to the current locale or user settings.
+ *
+ * @return The positive sign used by locale.
+ */
+ QString positiveSign() const;
+
+ /**
+ * Returns what a negative sign should look like ("-", etc.)
+ * according to the current locale or user settings.
+ *
+ * @return The negative sign used by locale.
+ */
+ QString negativeSign() const;
+
+ /**
+ * The number of fractional digits to include in numeric/monetary
+ * values (usually 2).
+ *
+ * @return Default number of fractional digits used by locale.
+ */
+ int fracDigits() const;
+
+ /**
+ * If and only if the currency symbol precedes a positive value,
+ * this will be true.
+ *
+ * @return Where to print the currency symbol for positive numbers.
+ */
+ bool positivePrefixCurrencySymbol() const;
+
+ /**
+ * If and only if the currency symbol precedes a negative value,
+ * this will be true.
+ *
+ * @return True if the currency symbol precedes negative numbers.
+ */
+ bool negativePrefixCurrencySymbol() const;
+
+ /**
+ * Returns the position of a positive sign in relation to a
+ * monetary value.
+ *
+ * @return Where/how to print the positive sign.
+ * @see SignPosition
+ */
+ SignPosition positiveMonetarySignPosition() const;
+
+ /**
+ * Denotes where to place a negative sign in relation to a
+ * monetary value.
+ *
+ * @return Where/how to print the negative sign.
+ * @see SignPosition
+ */
+ SignPosition negativeMonetarySignPosition() const;
+
+ /**
+ * Given a double, converts that to a numeric string containing
+ * the localized monetary equivalent.
+ *
+ * e.g. given 123456, return "$ 123,456.00".
+ *
+ * @param num The number we want to format
+ * @param currency The currency symbol you want.
+ * @param digits Number of fractional digits, or -1 for the default
+ * value
+ *
+ * @return The number of money as a localized string
+ * @see fracDigits()
+ */
+ QString formatMoney(double num,
+ const QString & currency = QString::null,
+ int digits = -1) const;
+
+ /**
+ * Given a double, converts that to a numeric string containing
+ * the localized numeric equivalent.
+ *
+ * e.g. given 123456.78F, return "123,456.78" (for some European country).
+ * If precision isn't specified, 2 is used.
+ *
+ * @param num The number to convert
+ * @param precision Number of fractional digits used.
+ *
+ * @return The number as a localized string
+ */
+ QString formatNumber(double num, int precision = -1) const;
+
+ /**
+ * Given an integer, converts that to a numeric string containing
+ * the localized numeric equivalent.
+ *
+ * e.g. given 123456L, return "123,456" (for some European country).
+ *
+ * @param num The number to convert
+ *
+ * @return The number as a localized string
+ * @since 3.2
+ */
+ QString formatLong(long num) const;
+
+ /**
+ * Use this to determine whether nouns are declined in
+ * locale's language. This property should remain
+ * read-only (no setter function)
+ *
+ * @return If nouns are declined
+ * @since 3.1
+ */
+ bool nounDeclension() const;
+
+ /**
+ * Returns a string formatted to the current locale's conventions
+ * regarding dates.
+ *
+ * @param pDate The date to be formated.
+ * @param shortFormat True for non text dates.
+ *
+ * @return The date as a string
+ */
+ QString formatDate(const QDate &pDate, bool shortFormat = false) const;
+
+ /**
+ * Use this to determine whether in dates a possessive form of month
+ * name is preferred ("of January" rather than "January")
+ *
+ * @return If possessive form should be used
+ * @since 3.1
+ */
+ bool dateMonthNamePossessive() const;
+
+ /**
+ * Returns a string formatted to the current locale's conventions
+ * regarding times.
+ *
+ * @param pTime The time to be formated.
+ * @param includeSecs if true, seconds are included in the output,
+ * otherwise only hours and minutes are formatted.
+ *
+ * @return The time as a string
+ */
+ QString formatTime(const QTime &pTime, bool includeSecs = false) const;
+
+ /**
+ * Use this to determine if the user wants a 12 hour clock.
+ *
+ * @return If the user wants 12h clock
+ */
+ bool use12Clock() const;
+
+ /**
+ * @deprecated
+ *
+ * Please use the @ref weekStartDay method instead.
+ *
+ * Use this to determine if the user wants the week to start on Monday.
+ *
+ * @return true if the week starts on Monday
+ */
+ bool weekStartsMonday() const; //### remove for KDE 4.0
+
+ /**
+ * Use this to determine which day is the first day of the week.
+ *
+ * @return an integer (Monday=1..Sunday=7)
+ * @since 3.1
+ */
+ int weekStartDay() const;
+
+ /**
+ * @deprecated
+ *
+ * Returns a string containing the name of the month name used in the Gregorian calendar.
+ *
+ * @param i the month number of the year starting at 1/January.
+ * @param shortName we will return the short version of the string.
+ *
+ * @return The name of the month
+ */
+ QString monthName(int i, bool shortName = false) const;
+
+ /**
+ * @deprecated
+ *
+ * Returns a string containing the possessive form of the month name used in the Gregorian calendar.
+ * ("of January", "of February", etc.)
+ * It's needed in long format dates in some languages.
+ *
+ * @param i the month number of the year starting at 1/January.
+ * @param shortName we will return the short version of the string.
+ *
+ * @return The possessive form of the name of the month
+ * @since 3.1
+ */
+ QString monthNamePossessive(int i, bool shortName = false) const;
+
+ /**
+ * @deprecated
+ *
+ * Returns a string containing the name of the week day used in the Gregorian calendar.
+ *
+ * @param i the day number of the week starting at 1/Monday.
+ * @param shortName we will return the short version of the string.
+ *
+ * @return The name of the day
+ */
+ QString weekDayName(int i, bool shortName = false) const;
+
+ /**
+ * Returns a pointer to the calendar system object.
+ *
+ * @return the current calendar system instance
+ * @since 3.2
+ */
+ const KCalendarSystem * calendar() const;
+
+ /**
+ * Returns the name of the calendar system that is currently being
+ * used by the system.
+ *
+ * @return the name of the calendar system
+ * @since 3.2
+ */
+ QString calendarType() const;
+
+ /**
+ * Changes the current calendar system to the calendar specified.
+ * Currently is "gregorian" and "hijri" supported. If the calendar
+ * system specified is not found, gregorian will be used.
+ *
+ * @param calendarType the name of the calendar type
+ * @since 3.2
+ */
+ void setCalendar(const QString & calendarType);
+
+ /**
+ * Returns a string formated to the current locale's conventions
+ * regarding both date and time.
+ *
+ * @param pDateTime The date and time to be formated.
+ * @param shortFormat using the short date format.
+ * @param includeSecs using the short date format.
+ *
+ * @return The date and time as a string
+ */
+ QString formatDateTime(const QDateTime &pDateTime,
+ bool shortFormat = true,
+ bool includeSecs = false) const;
+
+ /**
+ * Converts a localized monetary string to a double.
+ *
+ * @param numStr the string we want to convert.
+ * @param ok the boolean that is set to false if it's not a number.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a double
+ */
+ double readMoney(const QString &numStr, bool * ok = 0) const;
+
+ /**
+ * Converts a localized numeric string to a double.
+ *
+ * @param numStr the string we want to convert.
+ * @param ok the boolean that is set to false if it's not a number.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a double
+ */
+ double readNumber(const QString &numStr, bool * ok = 0) const;
+
+ /**
+ * Converts a localized date string to a QDate.
+ * The bool pointed by ok will be invalid if the date entered was not valid.
+ *
+ * @param str the string we want to convert.
+ * @param ok the boolean that is set to false if it's not a valid date.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a QDate
+ */
+ QDate readDate(const QString &str, bool* ok = 0) const;
+
+ /**
+ * Converts a localized date string to a QDate, using the specified format.
+ * You will usually not want to use this method.
+ */
+ QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const;
+
+ enum ReadDateFlags {
+ NormalFormat = 1,
+ ShortFormat = 2
+ };
+
+ /**
+ * Converts a localized date string to a QDate.
+ * This method is stricter than readDate(str,&ok): it will either accept
+ * a date in full format or a date in short format, depending on @p flags.
+ *
+ * @param str the string we want to convert.
+ * @param flags whether the date string is to be in full format or in short format.
+ * @param ok the boolean that is set to false if it's not a valid date.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a QDate
+ * @since 3.2
+ */
+ QDate readDate(const QString &str, ReadDateFlags flags, bool *ok = 0) const;
+
+ /**
+ * Converts a localized time string to a QTime.
+ * This method will try to parse it with seconds, then without seconds.
+ * The bool pointed by ok will be false if the time entered was not valid.
+ *
+ * @param str the string we want to convert.
+ * @param ok the boolean that is set to false if it's not a valid time.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a QTime
+ */
+ QTime readTime(const QString &str, bool* ok = 0) const;
+
+ enum ReadTimeFlags {
+ WithSeconds = 0, // default (no flag set)
+ WithoutSeconds = 1
+ }; // (maybe use this enum as a bitfield, if adding independent features?)
+ /**
+ * Converts a localized time string to a QTime.
+ * This method is stricter than readTime(str,&ok): it will either accept
+ * a time with seconds or a time without seconds.
+ * Use this method when the format is known by the application.
+ *
+ * @param str the string we want to convert.
+ * @param flags whether the time string is expected to contain seconds or not.
+ * @param ok the boolean that is set to false if it's not a valid time.
+ * If @p ok is 0, it will be ignored
+ *
+ * @return The string converted to a QTime
+ * @since 3.2
+ */
+ QTime readTime(const QString &str, ReadTimeFlags flags, bool *ok = 0) const;
+
+ /**
+ * Returns the language used by this object. The domain AND the
+ * library translation must be available in this language.
+ * @ref defaultLanguage() is returned by default, if no other available.
+ *
+ * @return The currently used language.
+ */
+ QString language() const;
+
+ /**
+ * Returns the country code of the country where the user lives.
+ * @ref defaultCountry() is returned by default, if no other available.
+ *
+ * @return The country code for the user.
+ */
+ QString country() const;
+
+ /**
+ * Returns the preferred languages as ISO 639-1 codes. This means
+ * that information about country is removed. If the internal language
+ * code might be represented by more than one 639-1 code, they will all be
+ * listed (but only once).
+ *
+ * If the selected languages are "nn, nb, pt_BR", you will get:
+ * "nn, no, nb, pt".
+ *
+ * @return List of language codes
+ *
+ * @see languageList
+ */
+ QStringList languagesTwoAlpha() const;
+
+ /**
+ * Returns the languages selected by user. The codes returned here is the
+ * internal language codes.
+ *
+ * @return List of language codes
+ *
+ * @see languagesTwoAlpha
+ */
+ QStringList languageList() const;
+
+ /**
+ * Returns the user's preferred encoding.
+ *
+ * @return The name of the preferred encoding
+ *
+ * @see codecForEncoding
+ * @see encodingMib
+ */
+ const char * encoding() const;
+
+ /**
+ * Returns the user's preferred encoding.
+ *
+ * @return The Mib of the preferred encoding
+ *
+ * @see encoding
+ * @see codecForEncoding
+ */
+ int encodingMib() const;
+ /**
+ * Returns the user's preferred encoding. Should never be NULL.
+ *
+ * @return The codec for the preferred encoding
+ *
+ * @see encoding
+ * @see encodingMib
+ */
+ QTextCodec * codecForEncoding() const;
+
+ /**
+ * Returns the file encoding.
+ *
+ * @return The Mib of the file encoding
+ *
+ * @see QFile::encodeName
+ * @see QFile::decodeName
+ */
+ int fileEncodingMib() const;
+
+ /**
+ * Changes the current date format.
+ *
+ * The format of the date is a string which contains variables that will
+ * be replaced:
+ * @li %Y with the century (e.g. "19" for "1984")
+ * @li %y with the lower 2 digits of the year (e.g. "84" for "1984")
+ * @li %n with the month (January="1", December="12")
+ * @li %m with the month with two digits (January="01", December="12")
+ * @li %e with the day of the month (e.g. "1" on the first of march)
+ * @li %d with the day of the month with two digits(e.g. "01" on the first of march)
+ * @li %b with the short form of the month (e.g. "Jan" for January)
+ * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday)
+ * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday)
+ * Everything else in the format string will be taken as is.
+ * For example, March 20th 1989 with the format "%y:%m:%d" results
+ * in "89:03:20".
+ *
+ * @param format The new date format
+ */
+ void setDateFormat(const QString & format);
+ /**
+ * Changes the current short date format.
+ *
+ * The format of the date is a string which contains variables that will
+ * be replaced:
+ * @li %Y with the century (e.g. "19" for "1984")
+ * @li %y with the lower 2 digits of the year (e.g. "84" for "1984")
+ * @li %n with the month (January="1", December="12")
+ * @li %m with the month with two digits (January="01", December="12")
+ * @li %e with the day of the month (e.g. "1" on the first of march)
+ * @li %d with the day of the month with two digits(e.g. "01" on the first of march)
+ * @li %b with the short form of the month (e.g. "Jan" for January)
+ * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday)
+ * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday)
+ * Everything else in the format string will be taken as is.
+ * For example, March 20th 1989 with the format "%y:%m:%d" results
+ * in "89:03:20".
+ *
+ * @param format The new short date format
+ */
+ void setDateFormatShort(const QString & format);
+ /**
+ * Changes the form of month name used in dates.
+ *
+ * @param possessive True if possessive forms should be used
+ * @since 3.1
+ */
+ void setDateMonthNamePossessive(bool possessive);
+ /**
+ * Changes the current time format.
+ *
+ * The format of the time is string a which contains variables that will
+ * be replaced:
+ * @li %H with the hour in 24h format and 2 digits (e.g. 5pm is "17", 5am is "05")
+ * @li %k with the hour in 24h format and one digits (e.g. 5pm is "17", 5am is "5")
+ * @li %I with the hour in 12h format and 2 digits (e.g. 5pm is "05", 5am is "05")
+ * @li %l with the hour in 12h format and one digits (e.g. 5pm is "5", 5am is "5")
+ * @li %M with the minute with 2 digits (e.g. the minute of 07:02:09 is "02")
+ * @li %S with the seconds with 2 digits (e.g. the minute of 07:02:09 is "09")
+ * @li %p with pm or am (e.g. 17.00 is "pm", 05.00 is "am")
+ * Everything else in the format string will be taken as is.
+ * For example, 5.23pm with the format "%H:%M" results
+ * in "17:23".
+ *
+ * @param format The new time format
+ */
+ void setTimeFormat(const QString & format);
+
+ /**
+ * @deprecated
+ *
+ * Please use @ref setWeekStartDay instead.
+ *
+ * Changes how KLocale defines the first day in week.
+ *
+ * @param start True if Monday is the first day in the week
+ */
+ void setWeekStartsMonday(bool start); //### remove for KDE 4.0
+
+ /**
+ * Changes how KLocale defines the first day in week.
+ *
+ * @param day first day of the week (Monday=1..Sunday=7) as integer
+ * @since 3.1
+ */
+ void setWeekStartDay(int day);
+ /**
+ * Returns the currently selected date format.
+ *
+ * @return Current date format.
+ * @see setDateFormat()
+ */
+ QString dateFormat() const;
+ /**
+ * Returns the currently selected short date format.
+ *
+ * @return Current short date format.
+ * @see setDateFormatShort()
+ */
+ QString dateFormatShort() const;
+ /**
+ * Returns the currently selected time format.
+ *
+ * @return Current time format.
+ * @see setTimeFormat()
+ */
+ QString timeFormat() const;
+
+ /**
+ * Changes the symbol used to identify the decimal pointer.
+ *
+ * @param symbol The new decimal symbol.
+ */
+ void setDecimalSymbol(const QString & symbol);
+ /**
+ * Changes the separator used to group digits when formating numbers.
+ *
+ * @param separator The new thousands separator.
+ */
+ void setThousandsSeparator(const QString & separator);
+ /**
+ * Changes the sign used to identify a positive number. Normally this is
+ * left blank.
+ *
+ * @param sign Sign used for positive numbers.
+ */
+ void setPositiveSign(const QString & sign);
+ /**
+ * Changes the sign used to identify a negative number.
+ *
+ * @param sign Sign used for negative numbers.
+ */
+ void setNegativeSign(const QString & sign);
+ /**
+ * Changes the sign position used for positive monetary values.
+ *
+ * @param signpos The new sign position
+ */
+ void setPositiveMonetarySignPosition(SignPosition signpos);
+ /**
+ * Changes the sign position used for negative monetary values.
+ *
+ * @param signpos The new sign position
+ */
+ void setNegativeMonetarySignPosition(SignPosition signpos);
+ /**
+ * Changes the position where the currency symbol should be printed for
+ * positive monetary values.
+ *
+ * @param prefix True if the currency symbol should be prefixed instead of
+ * postfixed
+ */
+ void setPositivePrefixCurrencySymbol(bool prefix);
+ /**
+ * Changes the position where the currency symbol should be printed for
+ * negative monetary values.
+ *
+ * @param prefix True if the currency symbol should be prefixed instead of
+ * postfixed
+ */
+ void setNegativePrefixCurrencySymbol(bool prefix);
+ /**
+ * Changes the number of digits used when formating numbers.
+ *
+ * @param digits The default number of digits to use.
+ */
+ void setFracDigits(int digits);
+ /**
+ * Changes the separator used to group digits when formating monetary values.
+ *
+ * @param separator The new thousands separator.
+ */
+ void setMonetaryThousandsSeparator(const QString & separator);
+ /**
+ * Changes the symbol used to identify the decimal pointer for monetary
+ * values.
+ *
+ * @param symbol The new decimal symbol.
+ */
+ void setMonetaryDecimalSymbol(const QString & symbol);
+ /**
+ * Changes the current currency symbol.
+ *
+ * @param symbol The new currency symbol
+ */
+ void setCurrencySymbol(const QString & symbol);
+
+ /**
+ * Returns the preferred page size for printing.
+ *
+ * @return The preferred page size, cast it to QPrinter::PageSize
+ */
+ int pageSize() const;
+
+ /**
+ * Changes the preferred page size when printing.
+ *
+ * @param paperFormat the new preferred page size in the format QPrinter::PageSize
+ */
+ void setPageSize(int paperFormat);
+
+ /**
+ * The Metric system will give you information in mm, while the
+ * Imperial system will give you information in inches.
+ */
+ enum MeasureSystem { Metric, Imperial };
+
+ /**
+ * Returns which measuring system we use.
+ *
+ * @return The preferred measuring system
+ */
+ MeasureSystem measureSystem() const;
+
+ /**
+ * Changes the preferred measuring system.
+ *
+ * @return value The preferred measuring system
+ */
+ void setMeasureSystem(MeasureSystem value);
+
+ /**
+ * Adds another catalogue to search for translation lookup.
+ * This function is useful for extern libraries and/or code,
+ * that provides its own messages.
+ *
+ * If the catalogue does not exist for the chosen language,
+ * it will be ignored and en_US will be used.
+ *
+ * @param catalogue The catalogue to add.
+ */
+ void insertCatalogue(const QString& catalogue);
+
+ /**
+ * Removes a catalog for translation lookup.
+ * @param catalogue The catalogue to remove.
+ * @see insertCatalogue()
+ */
+ void removeCatalogue(const QString &catalogue);
+
+ /**
+ * Sets the active catalog for translation lookup.
+ * @param catalogue The catalogue to activate.
+ */
+ void setActiveCatalogue(const QString &catalogue);
+
+ /**
+ * Translates a message as a QTranslator is supposed to.
+ * The parameters are similar to i18n(), but the result
+ * value has other semantics (it can be QString::null)
+ * @since 3.1
+ **/
+ QString translateQt(const char *context,
+ const char *sourceText,
+ const char *message) const;
+
+ /**
+ * Returns list of all known ISO 639-1 codes.
+ * @return a list of all language codes
+ * @since 3.1
+ */
+ QStringList allLanguagesTwoAlpha() const;
+
+ /**
+ * Convert a ISO 639-1 code to a human readable form.
+ * @param code the language ISO 639-1 code
+ * @return the human readable form
+ * @since 3.1
+ */
+ QString twoAlphaToLanguageName(const QString &code) const;
+
+ /**
+ * Returns list of all known country codes.
+ * @return a list of all country codes
+ * @since 3.1
+ */
+ QStringList allCountriesTwoAlpha() const;
+
+ /**
+ * Convert a country code to a human readable form.
+ * @param code the country code
+ * @return the human readable form of the country name
+ * @since 3.1
+ */
+ QString twoAlphaToCountryName(const QString &code) const;
+
+
+
+ int timezoneOffset( QString );
+ QStringList timeZoneList() const;
+ void setDaylightSaving( bool, int , int );
+ int localTimeOffset(const QDateTime &);
+ void setTimezone( const QString &timeZone );
+
+ void setHore24Format ( bool );
+ void setWeekStartMonday( bool );
+ void setIntDateFormat( int );
+ void setLanguage( int );
+
+
+
+ /**
+ * Returns the parts of the parameter str understood as language setting
+ * the format is language_COUNTRY.charset
+ *
+ * @param str The string to split.
+ * @param language This will be set to the language part of the string.
+ * @param country This will be set to the country part of the string.
+ * @param charset This will be set to the charset part of the string.
+ */
+ static void splitLocale(const QString & str,
+ QString & language,
+ QString & country,
+ QString & charset);
+
+ /**
+ * Use this to as main catalogue for *all* KLocales, if not the appname
+ * will be used. This function is best to be the very first instruction
+ * in your program's main function as it only has an effect before the
+ * first KLocale object is created (and this is in common KDE applications
+ * quite early).
+ *
+ * @param catalogue Catalogue to override all other main catalogues.
+ */
+ static void setMainCatalogue(const char *catalogue);
+
+ /**
+ * Finds localized resource in resourceDir( rtype ) + \<lang> + fname.
+ *
+ * @param fname relative path to find
+ * @param rtype resource type to use
+ */
+ static QString langLookup(const QString &fname, const char *rtype = "html");
+
+ /**
+ * Returns the name of the internal language.
+ *
+ * @return Name of the default language
+ */
+ static QString defaultLanguage();
+
+ /**
+ * Returns the name of the default country.
+ *
+ * @return Name of the default country
+ */
+ static QString defaultCountry();
+
+
+ /**
+ * @internal Called from KConfigBackend to initialize language.
+ */
+ static QString _initLanguage(KConfigBase *config);
+
+#ifdef KDE_NO_COMPAT
+private:
+#endif
+ /**
+ * @deprecated
+ * use formatMoney(double)
+ */
+ QString formatMoney(const QString &numStr) const;
+
+ /**
+ * @deprecated
+ * use formatNumber(double)
+ */
+ QString formatNumber(const QString &numStr) const;
+
+ /**
+ * @deprecated
+ * Use languageList()
+ *
+ * @return String containing language codes separated by colons
+ */
+ QString languages() const;
+
+ /**
+ * @deprecated
+ * @return True
+ */
+ bool setCharset(const QString & charset);
+
+ /**
+ * @deprecated
+ * @see encoding
+ */
+ QString charset() const;
+
+protected:
+ /**
+ * @internal Creates a KLocale object for KGlobal and inits the locale
+ * pointer.
+ */
+ static void initInstance();
+
+private:
+ /**
+ * @internal Inits the localization part of the instance with the config
+ * object.
+ *
+ * @param config The configuration object used for init.
+ */
+ void initFormat(KConfig *config);
+
+ /**
+ * @internal Inits the language part of the instance with the given config
+ * object. It should be valid and contain the global entries.
+ *
+ * @param config The configuration object used for init
+ * @param useEnv True if we should use environment variables
+ */
+ void initLanguage(KConfig * config, bool useEnv);
+
+ /**
+ * @internal Figures out which encoding the user prefers.
+ *
+ * @param config The configuration object used for init
+ */
+ void initEncoding(KConfig * config);
+
+ /**
+ * @internal Figures out which catalogues to use.
+ *
+ * @param catalogue The name of the main catalogue
+ */
+ void initCatalogue(const QString & catalogue);
+
+ /**
+ * @internal Figures out which encoding the user prefers for filenames
+ * and sets up the appropriate QFile encoding and decoding functions.
+ */
+ void initFileNameEncoding(KConfig *config);
+
+ /**
+ * @internal A QFile filename encoding function (QFile::encodeFn).
+ */
+ static QCString encodeFileNameUTF8( const QString & fileName );
+
+ /**
+ * @internal QFile filename decoding function (QFile::decodeFn).
+ */
+ static QString decodeFileNameUTF8( const QCString & localFileName );
+
+ /**
+ * @internal Changes the file name of the catalogue to the correct
+ * one.
+ */
+ void initCatalogue( KCatalogue & catalogue );
+
+ /**
+ * @internal Reads the language and format configuration form disk.
+ */
+ void doBindInit();
+
+ /**
+ * @internal Ensures that the format configuration is read.
+ */
+ void doFormatInit() const;
+
+ /**
+ * @internal Reads the format configuration from disk.
+ */
+ void initFormat();
+
+ /**
+ * @internal function used by the two translate versions
+ */
+ QString translate_priv(const char *index,
+ const char *text,
+ const char ** original = 0) const;
+
+ /**
+ * @internal function used to determine if we are using the en_US translation
+ */
+ bool useDefaultLanguage() const;
+
+ /**
+ * @internal Checks if the specified language is installed
+ */
+ bool isLanguageInstalled(const QString & language) const;
+
+ /**
+ * @internal Retrieves the file name of the catalogue, or QString::null
+ * if not found.
+ */
+ static QString catalogueFileName(const QString & language,
+ const KCatalogue & catalogue);
+
+
+private:
+ // Numbers and money
+ QString m_decimalSymbol;
+ QString m_thousandsSeparator;
+ QString m_currencySymbol;
+ QString m_monetaryDecimalSymbol;
+ QString m_monetaryThousandsSeparator;
+ QString m_positiveSign;
+ QString m_negativeSign;
+ int m_fracDigits;
+ SignPosition m_positiveMonetarySignPosition;
+ SignPosition m_negativeMonetarySignPosition;
+
+ // Date and time
+ QString m_timeFormat;
+ QString m_dateFormat;
+ QString m_dateFormatShort;
+
+ QString m_language;
+ QString m_country;
+
+ QStringList mTimeZoneList;
+ bool daylightEnabled;
+ int mDaylightTZoffset;
+ int mNondaylightTZoffset;
+ bool mSouthDaylight;
+ int daylightStart, daylightEnd, mTimeZoneOffset;
+ bool mWeekStartsMonday;
+ bool mHourF24Format;
+ int mIntDateFormat;
+ int mLanguage;
+
+
+
+
+ bool m_weekStartsMonday; //### remove for KDE 4.0
+ bool m_positivePrefixCurrencySymbol;
+ bool m_negativePrefixCurrencySymbol;
+
+ KLocalePrivate *d;
+};
+
+#endif
diff --git a/microkde/kdecore/kmdcodec.cpp b/microkde/kdecore/kmdcodec.cpp
new file mode 100644
index 0000000..bc03569
--- a/dev/null
+++ b/microkde/kdecore/kmdcodec.cpp
@@ -0,0 +1,1127 @@
+/*
+ Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License (LGPL)
+ version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
+ RSA Data Security, Inc. Created 1991. All rights reserved.
+
+ The KMD5 class is based on a C++ implementation of
+ "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
+ Mordechai T. Abzug, Copyright (c) 1995. This implementation
+ passes the test-suite as defined in RFC 1321.
+
+ The encoding and decoding utilities in KCodecs with the exception of
+ quoted-printable are based on the java implementation in HTTPClient
+ package by Ronald Tschal� Copyright (C) 1996-1999.
+
+ The quoted-printable codec as described in RFC 2045, section 6.7. is by
+ Rik Hemsley (C) 2001.
+*/
+
+//US #include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <kdebug.h>
+#include "kmdcodec.h"
+
+#define KMD5_S11 7
+#define KMD5_S12 12
+#define KMD5_S13 17
+#define KMD5_S14 22
+#define KMD5_S21 5
+#define KMD5_S22 9
+#define KMD5_S23 14
+#define KMD5_S24 20
+#define KMD5_S31 4
+#define KMD5_S32 11
+#define KMD5_S33 16
+#define KMD5_S34 23
+#define KMD5_S41 6
+#define KMD5_S42 10
+#define KMD5_S43 15
+#define KMD5_S44 21
+
+const char KCodecs::Base64EncMap[64] =
+{
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
+ 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
+ 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
+ 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
+};
+
+const char KCodecs::Base64DecMap[128] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
+ 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+ 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
+ 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const char KCodecs::UUEncMap[64] =
+{
+ 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
+};
+
+const char KCodecs::UUDecMap[128] =
+{
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+const char KCodecs::hexChars[16] =
+{
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+const unsigned int KCodecs::maxQPLineLength = 70;
+
+
+/******************************** KCodecs ********************************/
+// strchr(3) for broken systems.
+static int rikFindChar(register const char * _s, const char c)
+{
+ register const char * s = _s;
+
+ while (true)
+ {
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ if ((0 == *s) || (c == *s)) break; ++s;
+ }
+
+ return s - _s;
+}
+
+QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
+{
+ QByteArray out;
+ quotedPrintableEncode (in, out, useCRLF);
+ return QCString (out.data(), out.size()+1);
+}
+
+QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF)
+{
+ if (str.isEmpty())
+ return "";
+
+ QByteArray in (str.length());
+ memcpy (in.data(), str.data(), str.length());
+ return quotedPrintableEncode(in, useCRLF);
+}
+
+void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF)
+{
+ out.resize (0);
+ if (in.isEmpty())
+ return;
+
+ char *cursor;
+ const char *data;
+ unsigned int lineLength;
+ unsigned int pos;
+
+ const unsigned int length = in.size();
+ const unsigned int end = length - 1;
+
+
+ // Reasonable guess for output size when we're encoding
+ // mostly-ASCII data. It doesn't really matter, because
+ // the underlying allocation routines are quite efficient,
+ // but it's nice to have 0 allocations in many cases.
+ out.resize ((length*12)/10);
+ cursor = out.data();
+ data = in.data();
+ lineLength = 0;
+ pos = 0;
+
+ for (unsigned int i = 0; i < length; i++)
+ {
+ unsigned char c (data[i]);
+
+ // check if we have to enlarge the output buffer, use
+ // a safety margin of 16 byte
+ pos = cursor-out.data();
+ if (out.size()-pos < 16) {
+ out.resize(out.size()+4096);
+ cursor = out.data()+pos;
+ }
+
+ // Plain ASCII chars just go straight out.
+
+ if ((c >= 33) && (c <= 126) && ('=' != c))
+ {
+ *cursor++ = c;
+ ++lineLength;
+ }
+
+ // Spaces need some thought. We have to encode them at eol (or eof).
+
+ else if (' ' == c)
+ {
+ if
+ (
+ (i >= length)
+ ||
+ ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2]))
+ ||
+ (!useCRLF && ('\n' == data[i + 1]))))
+ )
+ {
+ *cursor++ = '=';
+ *cursor++ = '2';
+ *cursor++ = '0';
+
+ lineLength += 3;
+ }
+ else
+ {
+ *cursor++ = ' ';
+ ++lineLength;
+ }
+ }
+ // If we find a line break, just let it through.
+ else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) ||
+ (!useCRLF && ('\n' == c)))
+ {
+ lineLength = 0;
+
+ if (useCRLF) {
+ *cursor++ = '\r';
+ *cursor++ = '\n';
+ ++i;
+ } else {
+ *cursor++ = '\n';
+ }
+ }
+
+ // Anything else is converted to =XX.
+
+ else
+ {
+ *cursor++ = '=';
+ *cursor++ = hexChars[c / 16];
+ *cursor++ = hexChars[c % 16];
+
+ lineLength += 3;
+ }
+
+ // If we're approaching the maximum line length, do a soft line break.
+
+ if ((lineLength > maxQPLineLength) && (i < end))
+ {
+ if (useCRLF) {
+ *cursor++ = '=';
+ *cursor++ = '\r';
+ *cursor++ = '\n';
+ } else {
+ *cursor++ = '=';
+ *cursor++ = '\n';
+ }
+
+ lineLength = 0;
+ }
+ }
+
+ out.truncate(cursor - out.data());
+}
+
+QCString KCodecs::quotedPrintableDecode(const QByteArray & in)
+{
+ QByteArray out;
+ quotedPrintableDecode (in, out);
+ return QCString (out.data(), out.size()+1);
+}
+
+QCString KCodecs::quotedPrintableDecode(const QCString & str)
+{
+ if (str.isEmpty())
+ return "";
+
+ QByteArray in (str.length());
+ memcpy (in.data(), str.data(), str.length());
+ return quotedPrintableDecode (in);
+}
+
+void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
+{
+ // clear out the output buffer
+ out.resize (0);
+ if (in.isEmpty())
+ return;
+
+ char *cursor;
+ const char *data;
+ const unsigned int length = in.size();
+
+ data = in.data();
+ out.resize (length);
+ cursor = out.data();
+
+ for (unsigned int i = 0; i < length; i++)
+ {
+ char c(in.at(i));
+
+ if ('=' == c)
+ {
+ if (i < length - 2)
+ {
+ char c1 = in.at(i + 1);
+ char c2 = in.at(i + 2);
+
+ if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
+ {
+ // Soft line break. No output.
+ if ('\r' == c1)
+ i += 2; // CRLF line breaks
+ else
+ i += 1;
+ }
+ else
+ {
+ // =XX encoded byte.
+
+ int hexChar0 = rikFindChar(hexChars, c1);
+ int hexChar1 = rikFindChar(hexChars, c2);
+
+ if (hexChar0 < 16 && hexChar1 < 16)
+ {
+ *cursor++ = char((hexChar0 * 16) | hexChar1);
+ i += 2;
+ }
+ }
+ }
+ }
+ else
+ {
+ *cursor++ = c;
+ }
+ }
+
+ out.truncate(cursor - out.data());
+}
+
+QCString KCodecs::base64Encode( const QCString& str, bool insertLFs )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in (str.length());
+ memcpy( in.data(), str.data(), str.length() );
+ return base64Encode( in, insertLFs );
+}
+
+QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs )
+{
+ QByteArray out;
+ base64Encode( in, out, insertLFs );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::base64Encode( const QByteArray& in, QByteArray& out,
+ bool insertLFs )
+{
+ // clear out the output buffer
+ out.resize (0);
+ if ( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ const char* data = in.data();
+ const unsigned int len = in.size();
+
+ unsigned int out_len = ((len+2)/3)*4;
+
+ // Deal with the 76 characters or less per
+ // line limit specified in RFC 2045 on a
+ // pre request basis.
+ insertLFs = (insertLFs && out_len > 76);
+ if ( insertLFs )
+ out_len += ((out_len-1)/76);
+
+ int count = 0;
+ out.resize( out_len );
+
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ if ( len > 1 )
+ {
+ while (sidx < len-2)
+ {
+ if ( insertLFs )
+ {
+ if ( count && (count%76) == 0 )
+ out.at(didx++) = '\n';
+ count += 4;
+ }
+ out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077];
+ out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out.at(didx++) = Base64EncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out.at(didx++) = Base64EncMap[data[sidx+2] & 077];
+ sidx += 3;
+ }
+ }
+
+ if (sidx < len)
+ {
+ if ( insertLFs && (count > 0) && (count%76) == 0 )
+ out.at(didx++) = '\n';
+
+ out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077];
+ if (sidx < len-1)
+ {
+ out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out.at(didx++) = Base64EncMap[(data[sidx+1] << 2) & 077];
+ }
+ else
+ {
+ out.at(didx++) = Base64EncMap[(data[sidx] << 4) & 077];
+ }
+ }
+
+ // Add padding
+ while (didx < out.size())
+ {
+ out.at(didx) = '=';
+ didx++;
+ }
+}
+
+QCString KCodecs::base64Decode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return base64Decode( in );
+}
+
+QCString KCodecs::base64Decode( const QByteArray& in )
+{
+ QByteArray out;
+ base64Decode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::base64Decode( const QByteArray& in, QByteArray& out )
+{
+ out.resize(0);
+ if ( in.isEmpty() )
+ return;
+
+ unsigned int count = 0;
+ unsigned int len = in.size(), tail = len;
+ const char* data = in.data();
+
+ // Deal with possible *nix "BEGIN" marker!!
+ while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
+ data[count] == '\t' || data[count] == ' ') )
+ count++;
+
+ if ( QString(data+count).left(5).lower() == "begin" )
+ {
+ count += 5;
+ while ( count < len && data[count] != '\n' && data[count] != '\r' )
+ count++;
+
+ while ( count < len && (data[count] == '\n' || data[count] == '\r') )
+ count ++;
+
+ data += count;
+ tail = (len -= count);
+ }
+
+ // Find the tail end of the actual encoded data even if
+ // there is/are trailing CR and/or LF.
+ while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
+ data[tail-1] == '\r' )
+ if ( data[--tail] != '=' ) len = tail;
+
+ unsigned int outIdx = 0;
+ out.resize( (count=len) );
+ for (unsigned int idx = 0; idx < count; idx++)
+ {
+ // Adhere to RFC 2045 and ignore characters
+ // that are not part of the encoding table.
+ unsigned char ch = data[idx];
+ if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
+ (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
+ {
+ out.at(outIdx++) = Base64DecMap[ch];
+ }
+ else
+ {
+ len--;
+ tail--;
+ }
+ }
+
+ // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
+
+ // 4-byte to 3-byte conversion
+ len = (tail>(len/4)) ? tail-(len/4) : 0;
+ unsigned int sidx = 0, didx = 0;
+ if ( len > 1 )
+ {
+ while (didx < len-2)
+ {
+ out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
+ out.at(didx+1) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
+ out.at(didx+2) = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077));
+ sidx += 4;
+ didx += 3;
+ }
+ }
+
+ if (didx < len)
+ out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
+
+ if (++didx < len )
+ out.at(didx) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
+
+ // Resize the output buffer
+ if ( len == 0 || len < out.size() )
+ out.resize(len);
+}
+
+QCString KCodecs::uuencode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in;
+ in.resize( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return uuencode( in );
+}
+
+QCString KCodecs::uuencode( const QByteArray& in )
+{
+ QByteArray out;
+ uuencode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::uuencode( const QByteArray& in, QByteArray& out )
+{
+ out.resize( 0 );
+ if( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ unsigned int line_len = 45;
+
+ const char nl[] = "\n";
+ const char* data = in.data();
+ const unsigned int nl_len = strlen(nl);
+ const unsigned int len = in.size();
+
+ out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
+ // split into lines, adding line-length and line terminator
+ while (sidx+line_len < len)
+ {
+ // line length
+ out.at(didx++) = UUEncMap[line_len];
+
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
+ {
+ out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out.at(didx++) = UUEncMap[data[sidx+2] & 077];
+ }
+
+ // line terminator
+ //for (unsigned int idx=0; idx < nl_len; idx++)
+ //out.at(didx++) = nl[idx];
+ memcpy(out.data()+didx, nl, nl_len);
+ didx += nl_len;
+ }
+
+ // line length
+ out.at(didx++) = UUEncMap[len-sidx];
+ // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
+ while (sidx+2 < len)
+ {
+ out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 |
+ (data[sidx+1] << 2) & 077];
+ out.at(didx++) = UUEncMap[data[sidx+2] & 077];
+ sidx += 3;
+ }
+
+ if (sidx < len-1)
+ {
+ out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
+ (data[sidx] << 4) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx+1] << 2) & 077];
+ out.at(didx++) = UUEncMap[0];
+ }
+ else if (sidx < len)
+ {
+ out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
+ out.at(didx++) = UUEncMap[(data[sidx] << 4) & 077];
+ out.at(didx++) = UUEncMap[0];
+ out.at(didx++) = UUEncMap[0];
+ }
+
+ // line terminator
+ memcpy(out.data()+didx, nl, nl_len);
+ didx += nl_len;
+
+ // sanity check
+ if ( didx != out.size() )
+ out.resize( 0 );
+}
+
+QCString KCodecs::uudecode( const QCString& str )
+{
+ if ( str.isEmpty() )
+ return "";
+
+ QByteArray in;
+ in.resize( str.length() );
+ memcpy( in.data(), str.data(), str.length() );
+ return uudecode( in );
+}
+
+QCString KCodecs::uudecode( const QByteArray& in )
+{
+ QByteArray out;
+ uudecode( in, out );
+ return QCString( out.data(), out.size()+1 );
+}
+
+void KCodecs::uudecode( const QByteArray& in, QByteArray& out )
+{
+ out.resize( 0 );
+ if( in.isEmpty() )
+ return;
+
+ unsigned int sidx = 0;
+ unsigned int didx = 0;
+ unsigned int len = in.size();
+ unsigned int line_len, end;
+ const char* data = in.data();
+
+ // Deal with *nix "BEGIN"/"END" separators!!
+ unsigned int count = 0;
+ while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
+ data[count] == '\t' || data[count] == ' ') )
+ count ++;
+
+ bool hasLF = false;
+ if ( QString( data+count).left(5).lower() == "begin" )
+ {
+ count += 5;
+ while ( count < len && data[count] != '\n' && data[count] != '\r' )
+ count ++;
+
+ while ( count < len && (data[count] == '\n' || data[count] == '\r') )
+ count ++;
+
+ data += count;
+ len -= count;
+ hasLF = true;
+ }
+
+ out.resize( len/4*3 );
+ while ( sidx < len )
+ {
+ // get line length (in number of encoded octets)
+ line_len = UUDecMap[ (unsigned char) data[sidx++]];
+ // ascii printable to 0-63 and 4-byte to 3-byte conversion
+ end = didx+line_len;
+ char A, B, C, D;
+ if (end > 2) {
+ while (didx < end-2)
+ {
+ A = UUDecMap[(unsigned char) data[sidx]];
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ C = UUDecMap[(unsigned char) data[sidx+2]];
+ D = UUDecMap[(unsigned char) data[sidx+3]];
+ out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) );
+ out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) );
+ out.at(didx++) = ( ((C << 6) & 255) | (D & 077) );
+ sidx += 4;
+ }
+ }
+
+ if (didx < end)
+ {
+ A = UUDecMap[(unsigned char) data[sidx]];
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) );
+ }
+
+ if (didx < end)
+ {
+ B = UUDecMap[(unsigned char) data[sidx+1]];
+ C = UUDecMap[(unsigned char) data[sidx+2]];
+ out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) );
+ }
+
+ // skip padding
+ while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r')
+ sidx++;
+
+ // skip end of line
+ while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r'))
+ sidx++;
+
+ // skip the "END" separator when present.
+ if ( hasLF && QString( data+sidx).left(3).lower() == "end" )
+ break;
+ }
+
+ if ( didx < out.size() )
+ out.resize( didx );
+}
+
+/******************************** KMD5 ********************************/
+KMD5::KMD5()
+{
+ init();
+}
+
+KMD5::KMD5(const char *in, int len)
+{
+ init();
+ update(in, len);
+}
+
+KMD5::KMD5(const QByteArray& in)
+{
+ init();
+ update( in );
+}
+
+KMD5::KMD5(const QCString& in)
+{
+ init();
+ update( in );
+}
+
+void KMD5::update(const QByteArray& in)
+{
+ update(in.data(), int(in.size()));
+}
+
+void KMD5::update(const QCString& in)
+{
+ update(in.data(), int(in.length()));
+}
+
+void KMD5::update(const unsigned char* in, int len)
+{
+ if (len < 0)
+ len = qstrlen(reinterpret_cast<const char*>(in));
+
+ if (!len)
+ return;
+
+ if (m_finalized) {
+ kdWarning() << "KMD5::update called after state was finalized!" << endl;
+ return;
+ }
+
+ Q_UINT32 in_index;
+ Q_UINT32 buffer_index;
+ Q_UINT32 buffer_space;
+ Q_UINT32 in_length = static_cast<Q_UINT32>( len );
+
+ buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
+
+ if ( (m_count[0] += (in_length << 3))<(in_length << 3) )
+ m_count[1]++;
+
+ m_count[1] += (in_length >> 29);
+ buffer_space = 64 - buffer_index;
+
+ if (in_length >= buffer_space)
+ {
+ memcpy (m_buffer + buffer_index, in, buffer_space);
+ transform (m_buffer);
+
+ for (in_index = buffer_space; in_index + 63 < in_length;
+ in_index += 64)
+ transform (reinterpret_cast<const unsigned char*>(in+in_index));
+
+ buffer_index = 0;
+ }
+ else
+ in_index=0;
+
+ memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
+}
+
+bool KMD5::update(QIODevice& file)
+{
+ char buffer[1024];
+ int len;
+
+ while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
+ update(buffer, len);
+
+ return file.atEnd();
+}
+
+void KMD5::finalize ()
+{
+ if (m_finalized) return;
+
+ Q_UINT8 bits[8];
+ Q_UINT32 index, padLen;
+ static unsigned char PADDING[64]=
+ {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ encode (bits, m_count, 8);
+ //memcpy( bits, m_count, 8 );
+
+ // Pad out to 56 mod 64.
+ index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
+ padLen = (index < 56) ? (56 - index) : (120 - index);
+ update (reinterpret_cast<const char*>(PADDING), padLen);
+
+ // Append length (before padding)
+ update (reinterpret_cast<const char*>(bits), 8);
+
+ // Store state in digest
+ encode (m_digest, m_state, 16);
+ //memcpy( m_digest, m_state, 16 );
+
+ // Fill sensitive information with zero's
+ memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
+
+ m_finalized = true;
+}
+
+
+bool KMD5::verify( const KMD5::Digest& digest)
+{
+ finalize();
+ return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
+}
+
+bool KMD5::verify( const QCString& hexdigest)
+{
+ finalize();
+ return (0 == strcmp(hexDigest().data(), hexdigest));
+}
+
+const KMD5::Digest& KMD5::rawDigest()
+{
+ finalize();
+ return m_digest;
+}
+
+void KMD5::rawDigest( KMD5::Digest& bin )
+{
+ finalize();
+ memcpy( bin, m_digest, 16 );
+}
+
+
+QCString KMD5::hexDigest()
+{
+ QCString s(33);
+
+ finalize();
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+
+ return s;
+}
+
+void KMD5::hexDigest(QCString& s)
+{
+ finalize();
+ s.resize(33);
+ sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
+ m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
+ m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
+}
+
+QCString KMD5::base64Digest()
+{
+ QByteArray ba(16);
+
+ finalize();
+ memcpy(ba.data(), m_digest, 16);
+ return KCodecs::base64Encode(ba);
+}
+
+
+void KMD5::init()
+{
+ d = 0;
+ reset();
+}
+
+void KMD5::reset()
+{
+ m_finalized = false;
+
+ m_count[0] = 0;
+ m_count[1] = 0;
+
+ m_state[0] = 0x67452301;
+ m_state[1] = 0xefcdab89;
+ m_state[2] = 0x98badcfe;
+ m_state[3] = 0x10325476;
+
+ memset ( m_buffer, 0, sizeof(*m_buffer));
+ memset ( m_digest, 0, sizeof(*m_digest));
+}
+
+void KMD5::transform( const unsigned char block[64] )
+{
+
+ Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
+
+ decode (x, block, 64);
+ //memcpy( x, block, 64 );
+
+//US Q_ASSERT(!m_finalized); // not just a user error, since the method is private
+ ASSERT(!m_finalized); // not just a user error, since the method is private
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
+
+ m_state[0] += a;
+ m_state[1] += b;
+ m_state[2] += c;
+ m_state[3] += d;
+
+ memset ( static_cast<void *>(x), 0, sizeof(x) );
+}
+
+inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
+{
+ return (x << n) | (x >> (32-n)) ;
+}
+
+inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return (x & y) | (~x & z);
+}
+
+inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return (x & z) | (y & ~z);
+}
+
+inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return x ^ y ^ z;
+}
+
+inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
+{
+ return y ^ (x | ~z);
+}
+
+void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += F(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac)
+{
+ a += G(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += H(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
+ Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
+{
+ a += I(b, c, d) + x + ac;
+ a = rotate_left (a, s) +b;
+}
+
+
+void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(output, in, len);
+
+#else
+ Q_UINT32 i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ {
+ output[j] = static_cast<Q_UINT8>((in[i] & 0xff));
+ output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
+ output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
+ output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
+ }
+#endif
+}
+
+// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
+// multiple of 4.
+void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
+{
+#if !defined(WORDS_BIGENDIAN)
+ memcpy(output, in, len);
+
+#else
+ Q_UINT32 i, j;
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = static_cast<Q_UINT32>(in[j]) |
+ (static_cast<Q_UINT32>(in[j+1]) << 8) |
+ (static_cast<Q_UINT32>(in[j+2]) << 16) |
+ (static_cast<Q_UINT32>(in[j+3]) << 24);
+#endif
+}
diff --git a/microkde/kdecore/kmdcodec.h b/microkde/kdecore/kmdcodec.h
new file mode 100644
index 0000000..2c4d611
--- a/dev/null
+++ b/microkde/kdecore/kmdcodec.h
@@ -0,0 +1,572 @@
+/*
+ Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
+ Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License (LGPL)
+ version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
+ RSA Data Security, Inc. Created 1991. All rights reserved.
+
+ The KMD5 class is based on a C++ implementation of
+ "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
+ Mordechai T. Abzug, Copyright (c) 1995. This implementation
+ passes the test-suite as defined in RFC 1321.
+
+ The encoding and decoding utilities in KCodecs with the exception of
+ quoted-printable are based on the java implementation in HTTPClient
+ package by Ronald Tschalär Copyright (C) 1996-1999.
+
+ The quoted-printable codec as described in RFC 2045, section 6.7. is by
+ Rik Hemsley (C) 2001.
+*/
+
+#ifndef _KMDBASE_H
+#define _KMDBASE_H
+
+#define KBase64 KCodecs
+
+#include <qglobal.h>
+#include <qstring.h>
+#include <qiodevice.h>
+
+/**
+ * A wrapper class for the most commonly used encoding and
+ * decoding algorithms. Currently there is support for encoding
+ * and decoding input using base64, uu and the quoted-printable
+ * specifications.
+ *
+ * @sect Usage:
+ *
+ * <PRE>
+ * QCString input = "Aladdin:open sesame";
+ * QCString result = KCodecs::base64Encode(input);
+ * cout << "Result: " << result.data() << endl;
+ *
+ * Output should be
+ * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+ * </PRE>
+ *
+ * The above example makes use of the convenience functions
+ * (ones that accept/return null-terminated strings) to encode/decode
+ * a string. If what you need is to encode or decode binary data, then
+ * it is highly recommended that you use the functions that take an input
+ * and output QByteArray as arguments. These functions are specifically
+ * tailored for encoding and decoding binary data.
+ *
+ * @short A collection of commonly used encoding and decoding algorithms.
+ * @author Dawit Alemayehu <adawit@kde.org>
+ * @author Rik Hemsley <rik@kde.org>
+ */
+class KCodecs
+{
+public:
+
+ /**
+ * Encodes the given data using the quoted-printable algorithm.
+ *
+ * @param in data to be encoded.
+ * @param useCRLF if true the input data is expected to have
+ * CRLF line breaks and the output will have CRLF line
+ * breaks, too.
+ * @return quoted-printable encoded data.
+ */
+ static QCString quotedPrintableEncode(const QByteArray & in,
+ bool useCRLF = true);
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a null terminated
+ * string instead an array.
+ *
+ * @param str data to be encoded.
+ * @param useCRLF if true the input data is expected to have
+ * CRLF line breaks and the output will have CRLF line
+ * breaks, too.
+ * @return quoted-printable encoded data.
+ */
+ static QCString quotedPrintableEncode(const QCString & str,
+ bool useCRLF = true);
+
+ /**
+ * Encodes the given data using the quoted-printable algorithm.
+ *
+ * Use this function if you want the result of the encoding
+ * to be placed in another array which cuts down the number
+ * of copy operation that have to be performed in the process.
+ * This is also the preferred method for encoding binary data.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in data to be encoded.
+ * @param out decoded data.
+ * @param useCRLF if true the input data is expected to have
+ * CRLF line breaks and the output will have CRLF line
+ * breaks, too.
+ * @return quoted-printable encoded data.
+ */
+ static void quotedPrintableEncode(const QByteArray & in, QByteArray& out,
+ bool useCRLF);
+
+ /**
+ * Decodes a quoted-printable encoded string.
+ *
+ * Accepts data with CRLF or standard unix line breaks.
+ *
+ * @param in the data to be decoded.
+ * @return decoded data.
+ */
+ static QCString quotedPrintableDecode(const QByteArray & in);
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a null terminated
+ * string instead an array.
+ *
+ * @param str the data to be decoded.
+ * @return decoded data.
+ */
+ static QCString quotedPrintableDecode(const QCString & str);
+
+ /**
+ * Decodes a quoted-printable encoded data.
+ *
+ * Accepts data with CRLF or standard unix line breaks.
+ * Use this function if you want the result of the decoding
+ * to be placed in another array which cuts down the number
+ * of copy operation that have to be performed in the process.
+ * This is also the preferred method for decoding an encoded
+ * binary data.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in data to be encoded.
+ * @param out decoded data.
+ *
+ * @return quoted-printable encoded data.
+ */
+ static void quotedPrintableDecode(const QByteArray & in, QByteArray& out);
+
+
+ /**
+ * Encodes the given data using the uuencode algorithm.
+ *
+ * The output is split into lines starting with the number of
+ * encoded octets in the line and ending with a newline. No
+ * line is longer than 45 octets (60 characters), excluding the
+ * line terminator.
+ *
+ * @param in the data to be uuencoded
+ * @return a uuencoded data.
+ */
+ static QCString uuencode( const QByteArray& in );
+
+ /**
+ * @overload
+ *
+ * Same as the above functions except it accepts
+ * a null terminated string instead an array.
+ *
+ * @param str the string to be uuencoded.
+ * @return the encoded string.
+ */
+ static QCString uuencode( const QCString& str );
+
+ /**
+ * Encodes the given data using the uuencode algorithm.
+ *
+ * Use this function if you want the result of the encoding
+ * to be placed in another array and cut down the number of
+ * copy operation that have to be performed in the process.
+ * This is the preffered method for encoding binary data.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in the data to be uuencoded.
+ * @param out the container for the uudecoded data.
+ */
+ static void uuencode( const QByteArray& in, QByteArray& out );
+
+ /**
+ * Decodes the given data using the uuencode algorithm.
+ *
+ * Any 'begin' and 'end' lines like those generated by
+ * the utilities in unix and unix-like OS will be
+ * automatically ignored.
+ *
+ * @param in the data uuencoded data to be decoded.
+ * @return a decoded string.
+ */
+ static QCString uudecode( const QByteArray& in );
+
+ /**
+ * @overload
+ *
+ * Same as the above functions except it accepts
+ * a null terminated string instead an array.
+ *
+ * @param str the string to be decoded.
+ * @return a uudecoded string.
+ */
+ static QCString uudecode( const QCString& str );
+
+ /**
+ * Decodes the given data using the uudecode algorithm.
+ *
+ * Use this function if you want the result of the decoding
+ * to be placed in another array which cuts down the number
+ * of copy operation that have to be performed in the process.
+ * This is the preferred method for decoding binary data.
+ *
+ * Any 'begin' and 'end' lines like those generated by
+ * the utilities in unix and unix-like OS will be
+ * automatically ignored.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in the uuencoded-data to be decoded.
+ * @param out the container for the uudecoded data.
+ */
+ static void uudecode( const QByteArray& in, QByteArray& out );
+
+
+ /**
+ * Encodes the given data using the base64 algorithm.
+ *
+ * The boolean argument determines if the encoded data is
+ * going to be restricted to 76 characters or less per line
+ * as specified by RFC 2045. If @p insertLFs is true, then
+ * there will be 76 characters or less per line.
+ *
+ * @param in the data to be encoded.
+ * @param insertLFs limit the number of characters per line.
+ *
+ * @return a base64 encoded string.
+ */
+ static QCString base64Encode( const QByteArray& in, bool insertLFs = false);
+
+ /**
+ * @overload
+ *
+ * Same as the above functions except it accepts
+ * a null terminated string instead an array.
+ *
+ * @param str the string to be encoded.
+ * @param insertLFs limit the number of characters per line.
+ * @return the decoded string.
+ */
+ static QCString base64Encode( const QCString& str, bool insertLFs = false );
+
+ /**
+ * Encodes the given data using the base64 algorithm.
+ *
+ * Use this function if you want the result of the encoding
+ * to be placed in another array which cuts down the number
+ * of copy operation that have to be performed in the process.
+ * This is also the preferred method for encoding binary data.
+ *
+ * The boolean argument determines if the encoded data is going
+ * to be restricted to 76 characters or less per line as specified
+ * by RFC 2045. If @p insertLFs is true, then there will be 76
+ * characters or less per line.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in the data to be encoded using base64.
+ * @param out the container for the encoded data.
+ * @param insertLFs limit the number of characters per line.
+ */
+ static void base64Encode( const QByteArray& in, QByteArray& out,
+ bool insertLFs = false );
+
+ /**
+ * Decodes the given data that was encoded using the
+ * base64 algorithm.
+ *
+ * @param in the base64-encoded data to be decoded.
+ * @return the decoded data.
+ */
+ static QCString base64Decode( const QByteArray& in );
+
+ /**
+ * @overload
+ *
+ * Same as the above functions except it accepts
+ * a null terminated string instead an array.
+ *
+ * @param str the base64-encoded string.
+ * @return the decoded string.
+ */
+ static QCString base64Decode( const QCString& str );
+
+ /**
+ * Decodes the given data that was encoded with the base64
+ * algorithm.
+ *
+ * Use this function if you want the result of the decoding
+ * to be placed in another array which cuts down the number
+ * of copy operation that have to be performed in the process.
+ * This is also the preferred method for decoding an encoded
+ * binary data.
+ *
+ * NOTE: the output array is first reset and then resized
+ * appropriately before use, hence, all data stored in the
+ * output array will be lost.
+ *
+ * @param in the encoded data to be decoded.
+ * @param out the container for the decoded data.
+ */
+ static void base64Decode( const QByteArray& in, QByteArray& out );
+
+
+private:
+ KCodecs();
+
+private:
+ static const char UUEncMap[64];
+ static const char UUDecMap[128];
+ static const char Base64EncMap[64];
+ static const char Base64DecMap[128];
+ static const char hexChars[16];
+ static const unsigned int maxQPLineLength;
+};
+
+class KMD5Private;
+/**
+ * Provides an easy to use C++ implementation of RSA's
+ * MD5 algorithm.
+ *
+ * The default constructor is designed to provide much the same
+ * functionality as the most commonly used C-implementation, while
+ * the other three constructors are meant to further simplify the
+ * process of obtaining a digest by calculating the result in a
+ * single step.
+ *
+ * KMD5 is state-based, that means you can add new contents with
+ * update() as long as you didn't request the digest value yet.
+ * After the digest value was requested, the object is "finalized"
+ * and you have to call reset() to be able to do another calculation
+ * with it. The reason for this behaviour is that upon requesting
+ * the message digest KMD5 has to pad the received contents up to a
+ * 64 byte boundary to calculate its value. After this operation it
+ * is not possible to resume consuming data.
+ *
+ * @sect Usage:
+ *
+ * A common usage of this class:
+ *
+ * <PRE>
+ * const char* test1;
+ * KMD5::Digest rawResult;
+ *
+ * test1 = "This is a simple test.";
+ * KMD5 context (test1);
+ * cout << "Hex Digest output: " << context.hexDigest().data() << endl;
+ * </PRE>
+ *
+ * To cut down on the unnecessary overhead of creating multiple KMD5
+ * objects, you can simply invoke @ref reset() to reuse the same object
+ * in making another calculation:
+ *
+ * <PRE>
+ * context.reset ();
+ * context.update ("TWO");
+ * context.update ("THREE");
+ * cout << "Hex Digest output: " << context.hexDigest().data() << endl;
+ * </PRE>
+ *
+ * @short An adapted C++ implementation of RSA Data Securities MD5 algorithm.
+ * @author Dirk Mueller <mueller@kde.org>, Dawit Alemayehu <adawit@kde.org>
+ */
+
+class KMD5
+{
+public:
+
+ typedef unsigned char Digest[16];
+
+ KMD5();
+
+ /**
+ * Constructor that updates the digest for the given string.
+ *
+ * @param in C string or binary data
+ * @param len if negative, calculates the length by using
+ * strlen on the first parameter, otherwise
+ * it trusts the given length (does not stop on NUL byte).
+ */
+ KMD5(const char* in, int len = -1);
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a QByteArray as its argument.
+ */
+ KMD5(const QByteArray& a );
+
+ /**
+ * @overload
+ *
+ * Same as above except it accepts a QByteArray as its argument.
+ */
+ KMD5(const QCString& a );
+
+ /**
+ * Updates the message to be digested. Be sure to add all data
+ * before you read the digest. After reading the digest, you
+ * can <b>not</b> add more data!
+ *
+ * @param in message to be added to digest
+ * @param len the length of the given message.
+ */
+ void update(const char* in, int len = -1) { update(reinterpret_cast<const unsigned char*>(in), len); }
+
+ /**
+ * @overload
+ */
+ void update(const unsigned char* in, int len = -1);
+
+ /**
+ * @overload
+ *
+ * @param in message to be added to the digest (QByteArray).
+ */
+ void update(const QByteArray& in );
+
+ /**
+ * @overload
+ *
+ * @param in message to be added to the digest (QByteArray).
+ */
+ void update(const QCString& in );
+
+ /**
+ * @overload
+ *
+ * reads the data from an I/O device, i.e. from a file (QFile).
+ *
+ * NOTE that the file must be open for reading.
+ *
+ * @param file a pointer to FILE as returned by calls like f{d,re}open
+ *
+ * @returns false if an error occured during reading.
+ */
+ bool update(QIODevice& file);
+
+ /**
+ * Calling this function will reset the calculated message digest.
+ * Use this method to perform another message digest calculation
+ * without recreating the KMD5 object.
+ */
+ void reset();
+
+ /**
+ * @return the raw representation of the digest
+ */
+ const Digest& rawDigest ();
+
+ /**
+ * Fills the given array with the binary representation of the
+ * message digest.
+ *
+ * Use this method if you do not want to worry about making
+ * copy of the digest once you obtain it.
+ *
+ * @param bin an array of 16 characters ( char[16] )
+ */
+ void rawDigest( KMD5::Digest& bin );
+
+ /**
+ * Returns the value of the calculated message digest in
+ * a hexadecimal representation.
+ */
+ QCString hexDigest ();
+
+ /**
+ * @overload
+ */
+ void hexDigest(QCString&);
+
+ /**
+ * Returns the value of the calculated message digest in
+ * a base64-encoded representation.
+ */
+ QCString base64Digest ();
+
+ /**
+ * returns true if the calculated digest for the given
+ * message matches the given one.
+ */
+ bool verify( const KMD5::Digest& digest);
+
+ /**
+ * @overload
+ */
+ bool verify(const QCString&);
+
+protected:
+ /**
+ * Performs the real update work. Note
+ * that length is implied to be 64.
+ */
+ void transform( const unsigned char buffer[64] );
+
+ /**
+ * finalizes the digest
+ */
+ void finalize();
+
+private:
+ KMD5(const KMD5& u);
+ KMD5& operator=(const KMD5& md);
+
+ void init();
+ void encode( unsigned char* output, Q_UINT32 *in, Q_UINT32 len );
+ void decode( Q_UINT32 *output, const unsigned char* in, Q_UINT32 len );
+
+ Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n );
+ Q_UINT32 F( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
+ Q_UINT32 G( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
+ Q_UINT32 H( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
+ Q_UINT32 I( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
+ void FF( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
+ Q_UINT32 s, Q_UINT32 ac );
+ void GG( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
+ Q_UINT32 s, Q_UINT32 ac );
+ void HH( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
+ Q_UINT32 s, Q_UINT32 ac );
+ void II( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
+ Q_UINT32 s, Q_UINT32 ac );
+
+private:
+ Q_UINT32 m_state[4];
+ Q_UINT32 m_count[2];
+ Q_UINT8 m_buffer[64];
+ Digest m_digest;
+ bool m_finalized;
+
+ KMD5Private* d;
+};
+#endif
diff --git a/microkde/kdecore/ksharedptr.h b/microkde/kdecore/ksharedptr.h
new file mode 100644
index 0000000..545058a
--- a/dev/null
+++ b/microkde/kdecore/ksharedptr.h
@@ -0,0 +1,171 @@
+/* This file is part of the KDE libraries
+ Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef KSharedPTR_H
+#define KSharedPTR_H
+
+/**
+ * Reference counting for shared objects. If you derive your object
+ * from this class, then you may use it in conjunction with
+ * @ref KSharedPtr to control the lifetime of your object.
+ *
+ * Specifically, all classes that derive from KShared have an internal
+ * counter keeping track of how many other objects have a reference to
+ * their object. If used with @ref KSharedPtr, then your object will
+ * not be deleted until all references to the object have been
+ * released.
+ *
+ * You should probably not ever use any of the methods in this class
+ * directly -- let the @ref KSharedPtr take care of that. Just derive
+ * your class from KShared and forget about it.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ * @version $Id$
+ */
+class KShared {
+public:
+ /**
+ * Standard constructor. This will initialize the reference count
+ * on this object to 0.
+ */
+ KShared() : count(0) { }
+
+ /**
+ * Copy constructor. This will @em not actually copy the objects
+ * but it will initialize the reference count on this object to 0.
+ */
+ KShared( const KShared & ) : count(0) { }
+
+ /**
+ * Overloaded assignment operator.
+ */
+ KShared &operator=(const KShared & ) { return *this; }
+
+ /**
+ * Increases the reference count by one.
+ */
+ void _KShared_ref() const { count++; }
+
+ /**
+ * Releases a reference (decreases the reference count by one). If
+ * the count goes to 0, this object will delete itself.
+ */
+ void _KShared_unref() const { if (!--count) delete this; }
+
+ /**
+ * Return the current number of references held.
+ *
+ * @return Number of references
+ */
+ int _KShared_count() const { return count; }
+
+protected:
+ virtual ~KShared() { }
+private:
+ mutable int count;
+};
+
+/**
+ * Can be used to control the lifetime of an object that has derived
+ * @ref KShared. As long a someone holds a KSharedPtr on some @ref KShared
+ * object it won't become deleted but is deleted once its reference
+ * count is 0. This struct emulates C++ pointers perfectly. So just
+ * use it like a simple C++ pointer.
+ *
+ * KShared and KSharedPtr are preferred over QShared / QSharedPtr
+ * since they are more safe.
+ *
+ * @author Waldo Bastian <bastian@kde.org>
+ * @version $Id$
+ */
+template< class T >
+struct KSharedPtr
+{
+public:
+/**
+ * Creates a null pointer.
+ */
+ KSharedPtr()
+ : ptr(0) { }
+ /**
+ * Creates a new pointer.
+ * @param the pointer
+ */
+ KSharedPtr( T* t )
+ : ptr(t) { if ( ptr ) ptr->_KShared_ref(); }
+
+ /**
+ * Copies a pointer.
+ * @param the pointer to copy
+ */
+ KSharedPtr( const KSharedPtr& p )
+ : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); }
+
+ /**
+ * Unreferences the object that this pointer points to. If it was
+ * the last reference, the object will be deleted.
+ */
+ ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); }
+
+ KSharedPtr<T>& operator= ( const KSharedPtr<T>& p ) {
+ if ( ptr == p.ptr ) return *this;
+ if ( ptr ) ptr->_KShared_unref();
+ ptr = p.ptr;
+ if ( ptr ) ptr->_KShared_ref();
+ return *this;
+ }
+ KSharedPtr<T>& operator= ( T* p ) {
+ if ( ptr == p ) return *this;
+ if ( ptr ) ptr->_KShared_unref();
+ ptr = p;
+ if ( ptr ) ptr->_KShared_ref();
+ return *this;
+ }
+ bool operator== ( const KSharedPtr<T>& p ) const { return ( ptr == p.ptr ); }
+ bool operator!= ( const KSharedPtr<T>& p ) const { return ( ptr != p.ptr ); }
+ bool operator== ( const T* p ) const { return ( ptr == p ); }
+ bool operator!= ( const T* p ) const { return ( ptr != p ); }
+ bool operator!() const { return ( ptr == 0 ); }
+ operator T*() const { return ptr; }
+
+ /**
+ * Returns the pointer.
+ * @return the pointer
+ */
+ T* data() { return ptr; }
+
+ /**
+ * Returns the pointer.
+ * @return the pointer
+ */
+ const T* data() const { return ptr; }
+
+ const T& operator*() const { return *ptr; }
+ T& operator*() { return *ptr; }
+ const T* operator->() const { return ptr; }
+ T* operator->() { return ptr; }
+
+ /**
+ * Returns the number of references.
+ * @return the number of references
+ */
+ int count() const { return ptr->_KShared_count(); } // for debugging purposes
+private:
+ T* ptr;
+};
+
+#endif
diff --git a/microkde/kdecore/kshell.cpp b/microkde/kdecore/kshell.cpp
new file mode 100644
index 0000000..efc007a
--- a/dev/null
+++ b/microkde/kdecore/kshell.cpp
@@ -0,0 +1,386 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#include <kshell.h>
+
+#include <qfile.h>
+#include <qdir.h>
+
+#include <stdlib.h>
+#ifndef _WIN32_
+#include <pwd.h>
+#endif
+//US #include <sys/types.h>
+
+/*US
+static int fromHex( QChar c )
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return -1;
+}
+
+inline static bool isQuoteMeta( uint c )
+{
+#if 0 // it's not worth it, especially after seeing gcc's asm output ...
+ static const uchar iqm[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00
+ }; // \'"$
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+#else
+ return c == '\\' || c == '\'' || c == '"' || c == '$';
+#endif
+}
+
+inline static bool isMeta( uint c )
+{
+ static const uchar iqm[] = {
+ 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
+ }; // \'"$`<>|;&(){}*?#
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+QStringList KShell::splitArgs( const QString &args, int flags, int *err )
+{
+ QStringList ret;
+ bool firstword = flags & AbortOnMeta;
+
+ for (uint pos = 0; ; ) {
+ QChar c;
+ do {
+ if (pos >= args.length())
+ goto okret;
+ c = args.unicode()[pos++];
+ } while (c.isSpace());
+ QString cret;
+ if ((flags & TildeExpand) && c == '~') {
+ uint opos = pos;
+ for (; ; pos++) {
+ if (pos >= args.length())
+ break;
+ c = args.unicode()[pos];
+ if (c == '/' || c.isSpace())
+ break;
+ if (isQuoteMeta( c )) {
+ pos = opos;
+ c = '~';
+ goto notilde;
+ }
+ if ((flags & AbortOnMeta) && isMeta( c ))
+ goto metaerr;
+ }
+ QString ccret = homeDir( QConstString( args.unicode() + opos, pos - opos ).string() );
+ if (ccret.isEmpty()) {
+ pos = opos;
+ c = '~';
+ goto notilde;
+ }
+ if (pos >= args.length()) {
+ ret += ccret;
+ goto okret;
+ }
+ pos++;
+ if (c.isSpace()) {
+ ret += ccret;
+ firstword = false;
+ continue;
+ }
+ cret = ccret;
+ }
+ // before the notilde label, as a tilde does not match anyway
+ if (firstword) {
+ if (c == '_' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
+ uint pos2 = pos;
+ QChar cc;
+ do
+ cc = args[pos2++];
+ while (cc == '_' || (cc >= 'A' && cc <= 'Z') ||
+ (cc >= 'a' && cc <= 'z') || (cc >= '0' && cc <= '9'));
+ if (cc == '=')
+ goto metaerr;
+ }
+ }
+ notilde:
+ do {
+ if (c == '\'') {
+ uint spos = pos;
+ do {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ } while (c != '\'');
+ cret += QConstString( args.unicode() + spos, pos - spos - 1 ).string();
+ } else if (c == '"') {
+ for (;;) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ if (c != '"' && c != '\\' &&
+ !((flags & AbortOnMeta) && (c == '$' || c == '`')))
+ cret += '\\';
+ } else if ((flags & AbortOnMeta) && (c == '$' || c == '`'))
+ goto metaerr;
+ cret += c;
+ }
+ } else if (c == '$' && args[pos] == '\'') {
+ pos++;
+ for (;;) {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ if (c == '\'')
+ break;
+ if (c == '\\') {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ switch (c) {
+ case 'a': cret += '\a'; break;
+ case 'b': cret += '\b'; break;
+ case 'e': cret += '\033'; break;
+ case 'f': cret += '\f'; break;
+ case 'n': cret += '\n'; break;
+ case 'r': cret += '\r'; break;
+ case 't': cret += '\t'; break;
+ case '\\': cret += '\\'; break;
+ case '\'': cret += '\''; break;
+ case 'c': cret += args[pos++] & 31; break;
+ case 'x':
+ {
+ int hv = fromHex( args[pos] );
+ if (hv < 0) {
+ cret += "\\x";
+ } else {
+ int hhv = fromHex( args[++pos] );
+ if (hhv > 0) {
+ hv = hv * 16 + hhv;
+ pos++;
+ }
+ cret += QChar( hv );
+ }
+ break;
+ }
+ default:
+ if (c >= '0' && c <= '7') {
+ int hv = c - '0';
+ for (int i = 0; i < 2; i++) {
+ c = args[pos];
+ if (c < '0' || c > '7')
+ break;
+ hv = hv * 8 + (c - '0');
+ pos++;
+ }
+ cret += QChar( hv );
+ } else {
+ cret += '\\';
+ cret += c;
+ }
+ break;
+ }
+ } else
+ cret += c;
+ }
+ } else {
+ if (c == '\\') {
+ if (pos >= args.length())
+ goto quoteerr;
+ c = args.unicode()[pos++];
+ if (!c.isSpace() &&
+ !((flags & AbortOnMeta) ? isMeta( c ) : isQuoteMeta( c )))
+ cret += '\\';
+ } else if ((flags & AbortOnMeta) && isMeta( c ))
+ goto metaerr;
+ cret += c;
+ }
+ if (pos >= args.length())
+ break;
+ c = args.unicode()[pos++];
+ } while (!c.isSpace());
+ ret += cret;
+ firstword = false;
+ }
+
+ okret:
+ if (err)
+ *err = NoError;
+ return ret;
+
+ quoteerr:
+ if (err)
+ *err = BadQuoting;
+ return QStringList();
+
+ metaerr:
+ if (err)
+ *err = FoundMeta;
+ return QStringList();
+}
+
+inline static bool isSpecial( uint c )
+{
+ static const uchar iqm[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xdd, 0x07, 0x00, 0xd8,
+ 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
+ }; // 0-32 \'"$`<>|;&(){}*?#
+
+ return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
+}
+
+QString KShell::joinArgs( const QStringList &args )
+{
+ QChar q( '\'' );
+ QString ret;
+ for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
+ if (!ret.isEmpty())
+ ret += ' ';
+ if (!(*it).length())
+ ret.append( q ).append( q );
+ else {
+ for (uint i = 0; i < (*it).length(); i++)
+ if (isSpecial((*it).unicode()[i])) {
+ QString tmp(*it);
+ tmp.replace( q, "'\\''" );
+ ret += q;
+ tmp += q;
+ ret += tmp;
+ goto ex;
+ }
+ ret += *it;
+ ex: ;
+ }
+ }
+ return ret;
+}
+
+QString KShell::joinArgs( const char * const *args, int nargs )
+{
+ if (!args)
+ return QString::null; // well, QString::empty, in fact. qt sucks ;)
+ QChar q( '\'' );
+ QString ret;
+ for (const char * const *argp = args; nargs && *argp; argp++, nargs--) {
+ if (!ret.isEmpty())
+ ret += ' ';
+ if (!**argp)
+ ret.append( q ).append( q );
+ else {
+ QString tmp( QFile::decodeName( *argp ) );
+ for (uint i = 0; i < tmp.length(); i++)
+ if (isSpecial(tmp.unicode()[i])) {
+ tmp.replace( q, "'\\''" );
+ ret += q;
+ tmp += q;
+ ret += tmp;
+ goto ex;
+ }
+ ret += tmp;
+ ex: ;
+ }
+ }
+ return ret;
+}
+
+QString KShell::joinArgsDQ( const QStringList &args )
+{
+ QChar q( '\'' ), sp( ' ' ), bs( '\\' );
+ QString ret;
+ for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
+ if (!ret.isEmpty())
+ ret += sp;
+ if (!(*it).length())
+ ret.append( q ).append( q );
+ else {
+ for (uint i = 0; i < (*it).length(); i++)
+ if (isSpecial((*it).unicode()[i])) {
+ ret.append( '$' ).append( q );
+ for (uint pos = 0; pos < (*it).length(); pos++) {
+ int c = (*it).unicode()[pos];
+ if (c < 32) {
+ ret += bs;
+ switch (c) {
+ case '\a': ret += 'a'; break;
+ case '\b': ret += 'b'; break;
+ case '\033': ret += 'e'; break;
+ case '\f': ret += 'f'; break;
+ case '\n': ret += 'n'; break;
+ case '\r': ret += 'r'; break;
+ case '\t': ret += 't'; break;
+ case '\034': ret += 'c'; ret += '|'; break;
+ default: ret += 'c'; ret += c + '@'; break;
+ }
+ } else {
+ if (c == '\'' || c == '\\')
+ ret += bs;
+ ret += c;
+ }
+ }
+ ret.append( q );
+ goto ex;
+ }
+ ret += *it;
+ ex: ;
+ }
+ }
+ return ret;
+}
+*/
+
+QString KShell::tildeExpand( const QString &fname )
+{
+ if (fname[0] == '~') {
+ int pos = fname.find( '/' );
+ if (pos < 0)
+ return homeDir( QConstString( (QChar*)(fname.unicode() + 1), fname.length() - 1 ).string() );
+ QString ret = homeDir( QConstString( (QChar*)(fname.unicode() + 1), pos - 1 ).string() );
+ if (!ret.isNull())
+ ret += QConstString( (QChar*)(fname.unicode() + pos), fname.length() - pos ).string();
+ return ret;
+ }
+ return fname;
+}
+
+QString KShell::homeDir( const QString &user )
+{
+#ifdef _WIN32_
+ return QDir::homeDirPath();
+#else
+ if (user.isEmpty())
+ return QFile::decodeName( getenv( "HOME" ) );
+ struct passwd *pw = getpwnam( QFile::encodeName( user ).data() );
+ if (!pw)
+ return QString::null;
+ return QFile::decodeName( pw->pw_dir );
+#endif
+}
diff --git a/microkde/kdecore/kshell.h b/microkde/kdecore/kshell.h
new file mode 100644
index 0000000..35d8217
--- a/dev/null
+++ b/microkde/kdecore/kshell.h
@@ -0,0 +1,143 @@
+/*
+ This file is part of the KDE libraries
+
+ Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef _KSHELL_H
+#define _KSHELL_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+/**
+ * Provides some basic POSIX shell and bash functionality.
+ * @see KStringHandler
+ */
+namespace KShell {
+
+ /**
+ * Flags for @ref splitArgs().
+ */
+ enum Options {
+ NoOptions = 0,
+
+ /**
+ * Perform tilde expansion.
+ */
+ TildeExpand = 1,
+
+ /**
+ * Bail out if a non-quoting and not quoted shell meta character is encoutered.
+ * Meta characters are the command separators @p semicolon and @p ampersand,
+ * the redirection symbols @p less-than, @p greater-than and the @p pipe @p symbol,
+ * the grouping symbols opening and closing @p parens and @p braces, the command
+ * substitution symbol @p backquote, the generic substitution symbol @p dollar
+ * (if not followed by an apostrophe), the wildcards @p asterisk and
+ * @p question @p mark, and the comment symbol @p hash @p mark. Additionally,
+ * a variable assignment in the first word is recognized.
+ */
+ AbortOnMeta = 2
+ };
+
+ /**
+ * Status codes from @ref splitArgs()
+ */
+ enum Errors {
+ /**
+ * Success.
+ */
+ NoError = 0,
+
+ /**
+ * Indicates a parsing error, like an unterminated quoted string.
+ */
+ BadQuoting,
+
+ /**
+ * The AbortOnMeta flag was set and a shell meta character
+ * was encoutered.
+ */
+ FoundMeta
+ };
+
+ /**
+ * Splits @p cmd according to POSIX shell word splitting and quoting rules.
+ * Can optionally perform tilde expansion and/or abort if it finds shell
+ * meta characters it cannot process.
+ *
+ * @param cmd the command to split
+ * @param flags operation flags, see @ref Options
+ * @param err if not NULL, a status code will be stored at the pointer
+ * target, see @ref Errors
+ * @return a list of unquoted words or an empty list if an error occured
+ */
+ QStringList splitArgs( const QString &cmd, int flags = 0, int *err = 0 );
+
+ /**
+ * Quotes and joins @p args together according to POSIX shell rules.
+ *
+ * @param args a list of strings to quote and join
+ * @return a command suitable for shell execution
+ */
+ QString joinArgs( const QStringList &args );
+
+ /**
+ * Same as above, but $'' is used instead of '' for the quoting.
+ * The output is suitable for @ref splitArgs(), bash, zsh and possibly
+ * other bourne-compatible shells, but not for plain sh. The advantage
+ * is, that control characters (ASCII less than 32) are escaped into
+ * human-readable strings.
+ *
+ * @param args a list of strings to quote and join
+ * @return a command suitable for shell execution
+ */
+ QString joinArgsDQ( const QStringList &args );
+
+ /**
+ * Quotes and joins @p argv together according to POSIX shell rules.
+ *
+ * @param argv an array of c strings to quote and join.
+ * The strings are expected to be in local-8-bit encoding.
+ * @param argc maximal number of strings in @p argv. if not supplied,
+ * @p argv must be null-terminated.
+ * @return a command suitable for shell execution
+ */
+ QString joinArgs( const char * const *argv, int argc = -1 );
+
+ /**
+ * Performs tilde expansion on @p path. Interprets "~/path" and
+ * "~user/path".
+ *
+ * @param path the path to tilde-expand
+ * @return the expanded path
+ */
+ QString tildeExpand( const QString &path );
+
+ /**
+ * Obtain a @p user's home directory.
+ *
+ * @param user The name of the user whose home dir should be obtained.
+ * An empty string denotes the current user.
+ * @return The user's home directory.
+ */
+ QString homeDir( const QString &user );
+
+}
+
+
+#endif /* _KSHELL_H */
diff --git a/microkde/kdecore/kshortcut.h b/microkde/kdecore/kshortcut.h
new file mode 100644
index 0000000..4813734
--- a/dev/null
+++ b/microkde/kdecore/kshortcut.h
@@ -0,0 +1,846 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __KSHORTCUT_H
+#define __KSHORTCUT_H
+/*US
+#include <qkeysequence.h>
+#include <qstring.h>
+
+class QKeyEvent;
+class KKeyNative;
+*/
+/**
+* A KKey object represents a single key with possible modifiers
+* (Shift, Ctrl, Alt, Win). It can represent both keys which are
+* understood by Qt as well as those which are additionally supported
+* by the underlying system (e.g. X11).
+* @see KKeyNative
+* @see KKeySequence
+* @see KShortcut
+*/
+/*US
+class KKey
+{
+ public:
+*/
+ /**
+ * The number of flags.
+ * @see ModFlag
+ */
+/*US
+ enum { MOD_FLAG_COUNT = 4 };
+ enum { QtWIN = (Qt::ALT << 1) };
+*/
+ /**
+ * Flags to represent the modifiers. You can combine modifiers
+ * by ORing them.
+ */
+/*US
+ enum ModFlag {
+ SHIFT = 0x01,
+ CTRL = 0x02,
+ ALT = 0x04,
+ WIN = 0x08
+ };
+*/
+ /**
+ * Creates a new null KKey.
+ * @see clear()
+ * @see isNull()
+ * @see null()
+ */
+//US KKey();
+
+ /**
+ * Creates a new key for the given Qt key code.
+ * @param keyQt the qt keycode
+ * @see Qt::Key
+ */
+//US KKey( int keyQt );
+
+ /**
+ * Creates a new key from the first key code of the given key sequence.
+ * @param keySeq the key sequence that contains the key
+ */
+//US KKey( const QKeySequence& keySeq );
+
+ /**
+ * Extracts the key from the given key event.
+ * @param keyEvent the key event to get the key from
+ */
+//US KKey( const QKeyEvent* keyEvent );
+
+ /**
+ * Copy constructor.
+ */
+//US KKey( const KKey& key );
+
+ /**
+ * Creates a new key from the given description. The form of the description
+ * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or
+ * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and
+ * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive.
+ * @param key the description of the key
+ * @see KKeyServer::Sym::init()
+ */
+//US KKey( const QString& key );
+ /**
+ * @internal
+ */
+//US KKey( uint key, uint mod );
+//US ~KKey();
+
+ // Initialization methods
+ /**
+ * Clears the key. The key is null after calling this function.
+ * @see isNull()
+ */
+//US void clear();
+
+ /**
+ * Initializes the key with the given Qt key code.
+ * @param keyQt the qt keycode
+ * @return true if successful, false otherwise
+ * @see Qt::Key
+ */
+//US bool init( int keyQt );
+
+ /**
+ * Initializes the key with the first key code of the given key sequence.
+ * @param keySeq the key sequence that contains the key
+ * @return true if successful, false otherwise
+ */
+//US bool init( const QKeySequence& keySeq );
+
+ /**
+ * Initializes the key by extracting the code from the given key event.
+ * @param keyEvent the key event to get the key from
+ * @return true if successful, false otherwise
+ */
+//US bool init( const QKeyEvent* keyEvent );
+
+ /**
+ * Copies the given key.
+ * @param key the key to copy
+ * @return true if successful, false otherwise
+ */
+//US bool init( const KKey& key );
+
+ /**
+ * Initializes the key with the given description. The form of the description
+ * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or
+ * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and
+ * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive.
+ * @param key the description of the key
+ * @return true if successful, false otherwise
+ * @see KKeyServer::Sym::init()
+ */
+//US bool init( const QString& );
+
+ /**
+ * @internal
+ */
+//US bool init( uint key, uint mod );
+
+ /**
+ * Copies the key.
+ */
+//US KKey& operator =( const KKey& key )
+//US { init( key ); return *this; }
+
+ // Query methods.
+ /**
+ * Returns true if the key is null (after @ref clear() or empty
+ * constructor).
+ * @return true if the key is null
+ * @see clear()
+ * @see null()
+ */
+//US bool isNull() const;
+
+ /**
+ * @internal
+ */
+//US bool isValidQt() const;
+
+ /**
+ * @internal
+ */
+//US bool isValidNative() const;
+
+ /**
+ * @internal
+ */
+//US uint sym() const;
+ /**
+ * @internal
+ */
+//US uint modFlags() const;
+
+ // Comparison Methods
+ /**
+ * Compares this key with the given KKey object. Returns a negative
+ * number if the given KKey is larger, 0 if they are equal and
+ * a positive number this KKey is larger. The returned value
+ * is the difference between the symbol or, if the symbols
+ * are equal, the difference between the encoded modifiers.
+ * @param key the key to compare with this key
+ * @return a negative number if the given KKey is larger, 0 if
+ * they are equal and a positive number this KKey is larger
+ */
+//US int compare( const KKey& key ) const;
+
+ /**
+ * Compares the symbol and modifiers of both keys.
+ * @see compare()
+ */
+//US bool operator == ( const KKey& key ) const
+//US { return compare( key ) == 0; }
+ /**
+ * Compares the symbol and modifiers of both keys.
+ * @see compare()
+ */
+//US bool operator != ( const KKey& key ) const
+//US { return compare( key ) != 0; }
+ /**
+ * Compares the symbol and modifiers of both keys.
+ * @see compare()
+ */
+//US bool operator < ( const KKey& key ) const
+//US { return compare( key ) < 0; }
+
+ // Conversion methods.
+ /**
+ * Returns the qt key code.
+ * @return the qt key code or 0 if there is no key set.
+ * @see Qt::Key
+ */
+//US int keyCodeQt() const;
+
+ /**
+ * Returns a human-readable representation of the key in the form
+ * "modifier+key".
+ * @return the string representation of the key
+ */
+//US QString toString() const;
+
+ /**
+ * @internal
+ */
+//US QString toStringInternal() const;
+
+ // Operation methods
+ /**
+ * @internal
+ */
+//US void simplify();
+
+ /**
+ * Returns a null key.
+ * @return the null key
+ * @see isNull()
+ * @see clear()
+ */
+//US static KKey& null();
+
+ /**
+ * Returns a user-readable representation of the given modifiers.
+ * @param f the modifiers to convert
+ * @return the string representation of the modifiers
+ */
+//US static QString modFlagLabel( ModFlag f );
+
+//US private:
+ /*
+ * Under X11, m_key will hold an X11 key symbol.
+ * For Qt/Embedded, it will hold the Qt key code.
+ */
+ /**
+ * Returns the native key symbol value key. Under X11, this is the X
+ * keycode. Under Qt/Embedded, this is the Qt keycode.
+ * @see /usr/include/X11/keysymdef.h
+ * @see qnamespace.h
+ */
+//US uint m_sym;
+ /**
+ * m_mod holds the
+ */
+//US uint m_mod;
+
+//US private:
+//US friend class KKeyNative;
+//US};
+
+/**
+* A KKeySequence object holds a sequence of up to 4 keys.
+* Ex: Ctrl+X,I
+* @see KKey
+* @see KShortcut
+*/
+
+//USclass KKeySequence
+//US{
+//US public:
+ /// Defines the maximum length of the key sequence
+//US enum { MAX_KEYS = 4 };
+
+ /**
+ * Create a new null key sequence.
+ * @see isNull()
+ * @see null()
+ * @see clear()
+ */
+//US KKeySequence();
+
+ /**
+ * Copies the given qt key sequence.
+ * @param keySeq the qt key sequence to copy
+ */
+//US KKeySequence( const QKeySequence& keySeq );
+
+ /**
+ * Create a new key sequence that only contains the given key.
+ * @param key the key to add
+ */
+//US KKeySequence( const KKey& key );
+
+ /**
+ * Create a new key sequence that only contains the given key.
+ * @param key the key to add
+ */
+//US KKeySequence( const KKeyNative& key );
+
+ /**
+ * Copies the given key sequence.
+ * @param keySeq the key sequence to copy
+ */
+//US KKeySequence( const KKeySequence& keySeq );
+
+ /**
+ * Creates a new key sequence that contains the given key sequence.
+ * The description consists of comma-separated keys as
+ * required by @ref KKey::KKey(const QString&).
+ * @param keySeq the description of the key
+ * @see KKeyServer::Sym::init()
+ * @see KKey::KKey(const QString&)
+ */
+//US KKeySequence( const QString& keySeq );
+
+//US ~KKeySequence();
+
+ /**
+ * Clears the key sequence. The key sequence is null after calling this
+ * function.
+ * @see isNull()
+ */
+//US void clear();
+
+ /**
+ * Copies the given qt key sequence over this key sequence.
+ * @param keySeq the qt key sequence to copy
+ * @return true if successful, false otherwise
+ */
+//US bool init( const QKeySequence& keySeq );
+
+ /**
+ * Initializes the key sequence to only contain the given key.
+ * @param key the key to set
+ * @return true if successful, false otherwise
+ */
+//US bool init( const KKey& key );
+
+ /**
+ * Initializes the key sequence to only contain the given key.
+ * @param key the key to set
+ * @return true if successful, false otherwise
+ */
+//US bool init( const KKeyNative& key );
+
+ /**
+ * Copies the given key sequence over this key sequence.
+ * @param keySeq the key sequence to copy
+ * @return true if successful, false otherwise
+ */
+//US bool init( const KKeySequence& keySeq );
+
+ /**
+ * Initializes this key sequence to contain the given key sequence.
+ * The description consists of comma-separated keys as
+ * required by @ref KKey::KKey(const QString&).
+ * @param key the description of the key
+ * @return true if successful, false otherwise
+ * @see KKeyServer::Sym::init()
+ * @see KKey::KKey(const QString&)
+ */
+//US bool init( const QString& key );
+
+ /**
+ * Copy the given key sequence into this sequence.
+ */
+//US KKeySequence& operator =( const KKeySequence& seq )
+//US { init( seq ); return *this; }
+
+ /**
+ * Returns the number of key strokes of this sequence.
+ * @return the number of key strokes
+ * @see MAX_KEYS
+ */
+//US uint count() const;
+
+ /**
+ * Return the @p i'th key of this sequence, or a null key if there
+ * are less then i keys.
+ * @param i the key to retrieve
+ * @return the @p i'th key, or @ref KKey::null() if there are less
+ * than i keys
+ * @see MAX_KEYS
+ */
+//US const KKey& key( uint i ) const;
+
+ /**
+ * @internal
+ */
+//US bool isTriggerOnRelease() const;
+
+ /**
+ * Sets the @p i'th key of the sequence. You can not introduce gaps
+ * in a sequence, so you must use an @p i <= @ref count(). Also note that
+ * the maximum length of a key sequence is @ref MAX_KEYS.
+ * @param i the position of the new key (<= @ref count(), <= @ref MAX_KEYS)
+ * @param key the key to set
+ * @return true if successful, false otherwise
+ */
+//US bool setKey( uint i, const KKey& key );
+
+ /**
+ * @internal
+ */
+//US void setTriggerOnRelease( bool );
+
+ /**
+ * Returns true if the key sequence is null (after @ref clear() or empty
+ * constructor).
+ * @return true if the key sequence is null
+ * @see clear()
+ * @see null()
+ */
+//US bool isNull() const;
+
+ /**
+ * Returns true if this key sequence begins with the given sequence.
+ * @param keySeq the key sequence to search
+ * @return true if this key sequence begins with the given sequence
+ */
+//US bool startsWith( const KKeySequence& keySeq ) const;
+
+ /**
+ * Compares this object with the given key sequence. Returns a negative
+ * number if the given KKeySequence is larger, 0 if they are equal and
+ * a positive number this KKeySequence is larger. Key sequences are
+ * compared by comparing the individual keys, starting from the beginning
+ * until an unequal key has been found. If a sequence contains more
+ * keys, it is considered larger.
+ * @param keySeq the key sequence to compare to
+ * @return a negative number if the given KKeySequence is larger, 0 if
+ * they are equal and a positive number this KKeySequence is larger
+ * @see KKey::sequence
+ */
+//US int compare( const KKeySequence& keySeq ) const;
+
+ /**
+ * Compares the keys of both sequences.
+ * @see compare()
+ */
+//US bool operator == ( const KKeySequence& seq ) const
+//US { return compare( seq ) == 0; }
+
+ /**
+ * Compares the keys of both sequences.
+ * @see compare()
+ */
+//US bool operator != ( const KKeySequence& seq ) const
+//US { return compare( seq ) != 0; }
+
+ /**
+ * Compares the keys of both sequences.
+ * @see compare()
+ */
+//US bool operator < ( const KKeySequence& seq ) const
+//US { return compare( seq ) < 0; }
+ // TODO: consider adding Qt::SequenceMatch matches(...) methods for QKeySequence equivalence
+
+ /**
+ * Converts this key sequence to a QKeySequence.
+ * @return the QKeySequence
+ */
+//US QKeySequence qt() const;
+
+ /**
+ * Returns the qt key code of the first key.
+ * @return the qt key code of the first key
+ * @see Qt::Key
+ * @see KKey::keyCodeQt()
+ */
+//US int keyCodeQt() const;
+
+ /**
+ * Returns the key sequence as a number of key presses as
+ * returned by @ref KKey::toString(), seperated by commas.
+ * @return the string represenation of this key sequence
+ * @see KKey::toString()
+ */
+//US QString toString() const;
+
+ /**
+ * @internal
+ */
+//US QString toStringInternal() const;
+
+ /**
+ * Returns a null key sequence.
+ * @return the null key sequence
+ * @see isNull()
+ * @see clear()
+ */
+//US static KKeySequence& null();
+
+//US protected:
+//US uchar m_nKeys;
+//US uchar m_bTriggerOnRelease;
+ // BCI: m_rgvar should be renamed to m_rgkey for KDE 4.0
+//US KKey m_rgvar[MAX_KEYS];
+
+//US private:
+//US class KKeySequencePrivate* d;
+//US friend class KKeyNative;
+//US};
+
+/**
+* The KShortcut class is used to represent a keyboard shortcut to an action.
+* A shortcut is normally a single key with modifiers, such as Ctrl+V.
+* A KShortcut object may also contain an alternate key which will also
+* activate the action it's associated to, as long as no other actions have
+* defined that key as their primary key. Ex: Ctrl+V;Shift+Insert.
+*/
+
+class KShortcut
+{
+ public:
+ /**
+ * The maximum number of key sequences that can be contained in
+ * a KShortcut.
+ */
+ enum { MAX_SEQUENCES = 2 };
+
+ /**
+ * Creates a new null shortcut.
+ * @see null()
+ * @see isNull()
+ * @see clear()
+ */
+ KShortcut() {}
+
+ /**
+ * Creates a new shortcut with the given Qt key code
+ * as the only key sequence.
+ * @param keyQt the qt keycode
+ * @see Qt::Key
+ */
+ KShortcut( int keyQt ) {}
+
+ /**
+ * Creates a new shortcut that contains only the given qt key
+ * sequence.
+ * @param keySeq the qt key sequence to add
+ */
+//US KShortcut( const QKeySequence& keySeq ) {}
+
+ /**
+ * Creates a new shortcut that contains only the given key
+ * in its only sequence.
+ * @param key the key to add
+ */
+//US KShortcut( const KKey& key );
+
+ /**
+ * Creates a new shortcut that contains only the given key
+ * sequence.
+ * @param keySeq the key sequence to add
+ */
+//US KShortcut( const KKeySequence& keySeq );
+
+ /**
+ * Copies the given shortcut.
+ * @param shortcut the shortcut to add
+ */
+//US KShortcut( const KShortcut& shortcut );
+
+ /**
+ * Creates a new key sequence that contains the given key sequence.
+ * The description consists of semicolon-separated keys as
+ * used in @ref KKeySequence::KKeySequence(const QString&).
+ * @param shortcut the description of the key
+ * @see KKeySequence::KKeySequence(const QString&)
+ */
+ KShortcut( const char* shortcut ) {}
+
+ /**
+ * Creates a new key sequence that contains the given key sequence.
+ * The description consists of semicolon-separated keys as
+ * used in @ref KKeySequence::KKeySequence(const QString&).
+ * @param shortcut the description of the key
+ * @see KKeySequence::KKeySequence(const QString&)
+ */
+ KShortcut( const QString& shortcut ) {}
+ ~KShortcut() {}
+
+ /**
+ * Clears the shortcut. The shortcut is null after calling this
+ * function.
+ * @see isNull()
+ */
+//US void clear();
+
+ /**
+ * Initializes the shortcut with the given Qt key code
+ * as the only key sequence.
+ * @param keyQt the qt keycode
+ * @see Qt::Key
+ */
+//US bool init( int keyQt );
+
+ /**
+ * Initializes the shortcut with the given qt key sequence.
+ * @param keySeq the qt key sequence to add
+ */
+//US bool init( const QKeySequence& keySeq );
+
+ /**
+ * Initializes the shortcut with the given key as its only sequence.
+ * @param key the key to add
+ */
+//US bool init( const KKey& key );
+
+ /**
+ * Initializes the shortcut with the given qt key sequence.
+ * @param keySeq the qt key sequence to add
+ */
+//US bool init( const KKeySequence& keySeq );
+
+ /**
+ * Copies the given shortcut.
+ * @param shortcut the shortcut to add
+ */
+//US bool init( const KShortcut& shortcut );
+
+ /**
+ * Initializes the key sequence with the given key sequence.
+ * The description consists of semicolon-separated keys as
+ * used in @ref KKeySequence::KKeySequence(const QString&).
+ * @param shortcut the description of the key
+ * @see KKeySequence::KKeySequence(const QString&)
+ */
+//US bool init( const QString& shortcut );
+
+ /**
+ * Copies the given shortcut over this shortcut.
+ */
+//US KShortcut& operator =( const KShortcut& cut )
+//US { init( cut ); return *this; }
+
+ /**
+ * Returns the number of sequences that are in this
+ * shortcut.
+ * @return the number of sequences
+ * @ref MAX_SEQUENCES
+ */
+//US uint count() const;
+
+ /**
+ * Returns the @p i'th key sequence of this shortcut.
+ * @param i the number of the key sequence to retrieve
+ * @return the @p i'th sequence or @ref KKeySequence::null() if
+ * there are less than @p i key sequences
+ * @ref MAX_SEQUENCES
+ */
+//US const KKeySequence& seq( uint i ) const;
+
+ /**
+ * Returns the key code of the first key sequence, or
+ * null if there is no first key sequence.
+ * @return the key code of the first sequence's first key
+ * @see Qt::Key
+ * @see KKeySequence::keyCodeQt()
+ */
+//US int keyCodeQt() const;
+
+ /**
+ * Returns true if the shortcut is null (after @ref clear() or empty
+ * constructor).
+ * @return true if the shortcut is null
+ * @see clear()
+ * @see null()
+ */
+ bool isNull() const { return true; }
+
+ /**
+ * Compares this object with the given shortcut. Returns a negative
+ * number if the given shortcut is larger, 0 if they are equal and
+ * a positive number this shortcut is larger. Shortcuts are
+ * compared by comparing the individual key sequences, starting from the
+ * beginning until an unequal key sequences has been found. If a shortcut
+ * contains more key sequences, it is considered larger.
+ * @param shortcut the shortcut to compare to
+ * @return a negative number if the given KShortcut is larger, 0 if
+ * they are equal and a positive number this KShortcut is larger
+ * @see KKey::compare()
+ * @see KKeyShortcut::compare()
+ */
+//US int compare( const KShortcut& shortcut ) const;
+
+ /**
+ * Compares the sequences of both shortcuts.
+ * @see compare()
+ */
+//US bool operator == ( const KShortcut& cut ) const
+//US { return compare( cut ) == 0; }
+
+ /**
+ * Compares the sequences of both shortcuts.
+ * @see compare()
+ */
+//US bool operator != ( const KShortcut& cut ) const
+//US { return compare( cut ) != 0; }
+
+ /**
+ * Compares the sequences of both shortcuts.
+ * @see compare()
+ */
+//US bool operator < ( const KShortcut& cut ) const
+//US { return compare( cut ) < 0; }
+
+ /**
+ * Checks whether this shortcut contains a sequence that starts
+ * with the given key.
+ * @param key the key to check
+ * @return true if a key sequence starts with the key
+ */
+//US bool contains( const KKey& key ) const;
+
+ /**
+ * Checks whether this shortcut contains a sequence that starts
+ * with the given key.
+ * @param key the key to check
+ * @return true if a key sequence starts with the key
+ */
+//US bool contains( const KKeyNative& key ) const;
+
+ /**
+ * Checks whether this shortcut contains the given sequence.
+ * @param keySeq the key sequence to check
+ * @return true if the shortcut has the given key sequence
+ */
+//US bool contains( const KKeySequence& keySeq ) const;
+
+ /**
+ * Sets the @p i'th key sequence of the shortcut. You can not introduce
+ * gaps in the list of sequences, so you must use an @i <= @ref count().
+ * Also note that the maximum number of key sequences is @ref MAX_SEQUENCES.
+ * @param i the position of the new key sequence(<= @ref count(),
+ * <= @ref MAX_SEQUENCES)
+ * @param keySeq the key sequence to set
+ * @return true if successful, false otherwise
+ */
+//US bool setSeq( uint i, const KKeySequence& keySeq );
+
+ /**
+ * Appends the given key sequence.
+ * @param keySeq the key sequence to add
+ * @return true if successful, false otherwise
+ * @see setSeq()
+ * @see MAX_SEQUENCES
+ */
+//US bool append( const KKeySequence& keySeq );
+
+ /**
+ * Appends the given key
+ * @param spec the key to add
+ * @return true if successful, false otherwise
+ * @see setSeq()
+ * @see MAX_SEQUENCES
+ * @since 3.2
+ */
+//US bool append( const KKey& spec );
+
+ /**
+ * Appends the sequences from the given shortcut.
+ * @param cut the shortcut to append
+ * @return true if successful, false otherwise
+ * @see MAX_SEQUENCES
+ * @since 3.2
+ */
+//US bool append( const KShortcut& cut );
+
+ /**
+ * Converts this shortcut to a key sequence. The first key sequence
+ * will be taken.
+ */
+//US operator QKeySequence () const;
+
+ /**
+ * Returns a description of the shortcut as semicolon-separated
+ * ket sequences, as returned by @ref KKeySequence::toString().
+ * @return the string represenation of this shortcut
+ * @see KKey::toString()
+ * @see KKeySequence::toString()
+ */
+//US QString toString() const;
+
+ /**
+ * @internal
+ */
+ QString toStringInternal( const KShortcut* pcutDefault = 0 ) const
+ {
+ return "EMPTY IMPL.";
+ }
+
+ /**
+ * Returns a null shortcut.
+ * @return the null shortcut
+ * @see isNull()
+ * @see clear()
+ */
+//US static KShortcut& null();
+
+//US protected:
+//US uint m_nSeqs;
+//US KKeySequence m_rgseq[MAX_SEQUENCES];
+
+//US private:
+//US class KShortcutPrivate* d;
+//US friend class KKeyNative;
+
+//US#ifndef KDE_NO_COMPAT
+//US public:
+//US operator int () const { return keyCodeQt(); }
+//US#endif
+};
+
+#endif // __KSHORTCUT_H
diff --git a/microkde/kdecore/kstandarddirs.cpp b/microkde/kdecore/kstandarddirs.cpp
new file mode 100644
index 0000000..5abe05c
--- a/dev/null
+++ b/microkde/kdecore/kstandarddirs.cpp
@@ -0,0 +1,1620 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
+ Copyright (C) 1999 Stephan Kulow <coolo@kde.org>
+ Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/*
+ * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
+ * Version: $Id$
+ * Generated: Thu Mar 5 16:05:28 EST 1998
+ */
+
+//US #include "config.h"
+
+#include <stdlib.h>
+#include <assert.h>
+//US#include <errno.h>
+//US #ifdef HAVE_SYS_STAT_H
+//US #include <sys/stat.h>
+//US #endif
+//US#include <sys/types.h>
+//US#include <dirent.h>
+//US#include <pwd.h>
+
+#include <qregexp.h>
+#include <qasciidict.h>
+#include <qdict.h>
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include "kstandarddirs.h"
+#include "kconfig.h"
+#include "kdebug.h"
+//US #include "kinstance.h"
+#include "kshell.h"
+//US#include <sys/param.h>
+//US#include <unistd.h>
+
+//US
+QString KStandardDirs::mAppDir = QString::null;
+
+
+template class QDict<QStringList>;
+
+#if 0
+#include <qtextedit.h>
+void ddd( QString op )
+{
+ static QTextEdit * dot = 0;
+ if ( ! dot )
+ dot = new QTextEdit();
+
+ dot->show();
+
+ dot->append( op );
+
+}
+#endif
+class KStandardDirs::KStandardDirsPrivate
+{
+public:
+ KStandardDirsPrivate()
+ : restrictionsActive(false),
+ dataRestrictionActive(false)
+ { }
+
+ bool restrictionsActive;
+ bool dataRestrictionActive;
+ QAsciiDict<bool> restrictions;
+ QStringList xdgdata_prefixes;
+ QStringList xdgconf_prefixes;
+};
+
+static const char* const types[] = {"html", "icon", "apps", "sound",
+ "data", "locale", "services", "mime",
+ "servicetypes", "config", "exe",
+ "wallpaper", "lib", "pixmap", "templates",
+ "module", "qtplugins",
+ "xdgdata-apps", "xdgdata-dirs", "xdgconf-menu", 0 };
+
+static int tokenize( QStringList& token, const QString& str,
+ const QString& delim );
+
+KStandardDirs::KStandardDirs( ) : addedCustoms(false)
+{
+ d = new KStandardDirsPrivate;
+ dircache.setAutoDelete(true);
+ relatives.setAutoDelete(true);
+ absolutes.setAutoDelete(true);
+ savelocations.setAutoDelete(true);
+ addKDEDefaults();
+}
+
+KStandardDirs::~KStandardDirs()
+{
+ delete d;
+}
+
+bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
+{
+ if (!d || !d->restrictionsActive)
+ return false;
+
+ if (d->restrictions[type])
+ return true;
+
+ if (strcmp(type, "data")==0)
+ {
+ applyDataRestrictions(relPath);
+ if (d->dataRestrictionActive)
+ {
+ d->dataRestrictionActive = false;
+ return true;
+ }
+ }
+ return false;
+}
+
+void KStandardDirs::applyDataRestrictions(const QString &relPath) const
+{
+ QString key;
+ int i = relPath.find('/');
+ if (i != -1)
+ key = "data_"+relPath.left(i);
+ else
+ key = "data_"+relPath;
+
+ if (d && d->restrictions[key.latin1()])
+ d->dataRestrictionActive = true;
+}
+
+
+QStringList KStandardDirs::allTypes() const
+{
+ QStringList list;
+ for (int i = 0; types[i] != 0; ++i)
+ list.append(QString::fromLatin1(types[i]));
+ return list;
+}
+
+void KStandardDirs::addPrefix( const QString& _dir )
+{
+ if (_dir.isNull())
+ return;
+
+ QString dir = _dir;
+ if (dir.at(dir.length() - 1) != '/')
+ dir += '/';
+
+ if (!prefixes.contains(dir)) {
+ prefixes.append(dir);
+ dircache.clear();
+ }
+}
+
+void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
+{
+ if (_dir.isNull())
+ return;
+
+ QString dir = _dir;
+ if (dir.at(dir.length() - 1) != '/')
+ dir += '/';
+
+ if (!d->xdgconf_prefixes.contains(dir)) {
+ d->xdgconf_prefixes.append(dir);
+ dircache.clear();
+ }
+}
+
+void KStandardDirs::addXdgDataPrefix( const QString& _dir )
+{
+ if (_dir.isNull())
+ return;
+
+ QString dir = _dir;
+ if (dir.at(dir.length() - 1) != '/')
+ dir += '/';
+
+ if (!d->xdgdata_prefixes.contains(dir)) {
+ d->xdgdata_prefixes.append(dir);
+ dircache.clear();
+ }
+}
+
+
+QString KStandardDirs::kfsstnd_prefixes()
+{
+ return prefixes.join(":");
+}
+
+bool KStandardDirs::addResourceType( const char *type,
+ const QString& relativename )
+{
+ if (relativename.isNull())
+ return false;
+
+ QStringList *rels = relatives.find(type);
+ if (!rels) {
+ rels = new QStringList();
+ relatives.insert(type, rels);
+ }
+ QString copy = relativename;
+ if (copy.at(copy.length() - 1) != '/')
+ copy += '/';
+ if (!rels->contains(copy)) {
+ rels->prepend(copy);
+ dircache.remove(type); // clean the cache
+ return true;
+ }
+ return false;
+}
+
+bool KStandardDirs::addResourceDir( const char *type,
+ const QString& absdir)
+{
+ QStringList *paths = absolutes.find(type);
+ if (!paths) {
+ paths = new QStringList();
+ absolutes.insert(type, paths);
+ }
+ QString copy = absdir;
+ if (copy.at(copy.length() - 1) != '/')
+ copy += '/';
+
+ if (!paths->contains(copy)) {
+ paths->append(copy);
+ dircache.remove(type); // clean the cache
+ return true;
+ }
+ return false;
+}
+
+QString KStandardDirs::findResource( const char *type,
+ const QString& filename ) const
+{
+ if (filename.at(0) == '/')
+ return filename; // absolute dirs are absolute dirs, right? :-/
+
+#if 0
+kdDebug() << "Find resource: " << type << endl;
+for (QStringList::ConstIterator pit = prefixes.begin();
+ pit != prefixes.end();
+ pit++)
+{
+ kdDebug() << "Prefix: " << *pit << endl;
+}
+#endif
+
+ QString dir = findResourceDir(type, filename);
+ if (dir.isNull())
+ return dir;
+ else return dir + filename;
+}
+/*US
+static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash)
+{
+ QCString cFile = QFile::encodeName(file);
+//US struct stat buff;
+//US if ((access(cFile, R_OK) == 0) &&
+//US (stat( cFile, &buff ) == 0) &&
+//US (S_ISREG( buff.st_mode )))
+ QFileInfo pathfnInfo(cFile);
+ if (( pathfnInfo.isReadable() == true ) &&
+ ( pathfnInfo.isFile()) )
+ {
+//US hash = hash + (Q_UINT32) buff.st_ctime;
+ hash = hash + (Q_UINT32) pathfnInfo.lastModified();
+ }
+ return hash;
+}
+*/
+/*US
+Q_UINT32 KStandardDirs::calcResourceHash( const char *type,
+ const QString& filename, bool deep) const
+{
+ Q_UINT32 hash = 0;
+
+ if (filename.at(0) == '/')
+ {
+ // absolute dirs are absolute dirs, right? :-/
+ return updateHash(filename, hash);
+ }
+ if (d && d->restrictionsActive && (strcmp(type, "data")==0))
+ applyDataRestrictions(filename);
+ QStringList candidates = resourceDirs(type);
+ QString fullPath;
+
+ for (QStringList::ConstIterator it = candidates.begin();
+ it != candidates.end(); it++)
+ {
+ hash = updateHash(*it + filename, hash);
+ if (!deep && hash)
+ return hash;
+ }
+ return hash;
+}
+*/
+
+QStringList KStandardDirs::findDirs( const char *type,
+ const QString& reldir ) const
+{
+ QStringList list;
+
+ checkConfig();
+
+ if (d && d->restrictionsActive && (strcmp(type, "data")==0))
+ applyDataRestrictions(reldir);
+ QStringList candidates = resourceDirs(type);
+ QDir testdir;
+
+ for (QStringList::ConstIterator it = candidates.begin();
+ it != candidates.end(); it++) {
+ testdir.setPath(*it + reldir);
+ if (testdir.exists())
+ list.append(testdir.absPath() + '/');
+ }
+
+ return list;
+}
+
+QString KStandardDirs::findResourceDir( const char *type,
+ const QString& filename) const
+{
+#ifndef NDEBUG
+ if (filename.isEmpty()) {
+ kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl;
+ return QString::null;
+ }
+#endif
+
+ if (d && d->restrictionsActive && (strcmp(type, "data")==0))
+ applyDataRestrictions(filename);
+ QStringList candidates = resourceDirs(type);
+ QString fullPath;
+
+ for (QStringList::ConstIterator it = candidates.begin();
+ it != candidates.end(); it++)
+ if (exists(*it + filename))
+ return *it;
+
+#ifndef NDEBUG
+ if(false && type != "locale")
+ kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl;
+#endif
+
+ return QString::null;
+}
+
+bool KStandardDirs::exists(const QString &fullPath)
+{
+//US struct stat buff;
+ QFileInfo fullPathInfo(QFile::encodeName(fullPath));
+
+//US if (access(QFile::encodeName(fullPath), R_OK) == 0 && fullPathInfo.isReadable())
+ if (fullPathInfo.isReadable())
+ {
+ if (fullPath.at(fullPath.length() - 1) != '/') {
+//US if (S_ISREG( buff.st_mode ))
+ if (fullPathInfo.isFile())
+ return true;
+ }
+ else {
+//US if (S_ISDIR( buff.st_mode ))
+ if (fullPathInfo.isDir())
+ return true;
+ }
+ }
+ return false;
+}
+
+static void lookupDirectory(const QString& path, const QString &relPart,
+ const QRegExp &regexp,
+ QStringList& list,
+ QStringList& relList,
+ bool recursive, bool uniq)
+{
+ QString pattern = regexp.pattern();
+ if (recursive || pattern.contains('?') || pattern.contains('*'))
+ {
+ // We look for a set of files.
+//US DIR *dp = opendir( QFile::encodeName(path));
+ QDir dp(QFile::encodeName(path));
+ if (!dp.exists())
+ return;
+ static int iii = 0;
+ ++iii;
+ if ( iii == 5 )
+ abort();
+ assert(path.at(path.length() - 1) == '/');
+
+//US struct dirent *ep;
+//US struct stat buff;
+
+ QString _dot(".");
+ QString _dotdot("..");
+
+//US while( ( ep = readdir( dp ) ) != 0L )
+ QStringList direntries = dp.entryList();
+ QStringList::Iterator it = direntries.begin();
+
+ while ( it != list.end() ) // for each file...
+ {
+
+//US QString fn( QFile::decodeName(ep->d_name));
+ QString fn = (*it); // dp.entryList already decodes
+ it++;
+ if ( fn.isNull() )
+ break;
+
+ if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~' )
+ continue;
+
+/*US
+ if (!recursive && !regexp.exactMatch(fn))
+ continue; // No match
+*/
+//US this should do the same:
+ int pos = regexp.match(fn);
+ if (!recursive && !pos == 0)
+ continue; // No match
+
+ QString pathfn = path + fn;
+/*US
+ if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
+ kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
+ continue; // Couldn't stat (e.g. no read permissions)
+ }
+
+ if ( recursive )
+ {
+ if ( S_ISDIR( buff.st_mode )) {
+ lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq);
+ }
+*/
+//US replacement:
+ QFileInfo pathfnInfo(QFile::encodeName(pathfn));
+ if ( pathfnInfo.isReadable() == false )
+ {
+//US kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
+ continue; // Couldn't stat (e.g. no read permissions)
+ }
+
+ if ( recursive )
+ {
+ if ( pathfnInfo.isDir()) {
+ lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq);
+ }
+
+
+/*US
+ if (!regexp.exactMatch(fn))
+ continue; // No match
+*/
+//US this should do the same:
+ pos = regexp.match(fn);
+ if (!pos == 0)
+ continue; // No match
+ }
+
+//US if ( S_ISREG( buff.st_mode))
+ if ( pathfnInfo.isFile())
+ {
+ if (!uniq || !relList.contains(relPart + fn))
+ {
+ list.append( pathfn );
+ relList.append( relPart + fn );
+ }
+ }
+ }
+//US closedir( dp );
+ }
+ else
+ {
+ // We look for a single file.
+ QString fn = pattern;
+ QString pathfn = path + fn;
+//US struct stat buff;
+ QFileInfo pathfnInfo(QFile::encodeName(pathfn));
+
+
+//US if ( stat( QFile::encodeName(pathfn), &buff ) != 0 )
+ if ( pathfnInfo.isReadable() == false )
+ return; // File not found
+
+//US if ( S_ISREG( buff.st_mode))
+ if ( pathfnInfo.isFile())
+ {
+ if (!uniq || !relList.contains(relPart + fn))
+ {
+ list.append( pathfn );
+ relList.append( relPart + fn );
+ }
+ }
+ }
+}
+
+static void lookupPrefix(const QString& prefix, const QString& relpath,
+ const QString& relPart,
+ const QRegExp &regexp,
+ QStringList& list,
+ QStringList& relList,
+ bool recursive, bool uniq)
+{
+ if (relpath.isNull()) {
+ lookupDirectory(prefix, relPart, regexp, list,
+ relList, recursive, uniq);
+ return;
+ }
+ QString path;
+ QString rest;
+
+ if (relpath.length())
+ {
+ int slash = relpath.find('/');
+ if (slash < 0)
+ rest = relpath.left(relpath.length() - 1);
+ else {
+ path = relpath.left(slash);
+ rest = relpath.mid(slash + 1);
+ }
+ }
+ assert(prefix.at(prefix.length() - 1) == '/');
+
+//US struct stat buff;
+
+ if (path.contains('*') || path.contains('?')) {
+ QRegExp pathExp(path, true, true);
+//US DIR *dp = opendir( QFile::encodeName(prefix) );
+ QDir dp(QFile::encodeName(prefix));
+
+//US if (!dp)
+ if (!dp.exists())
+ {
+ return;
+ }
+
+//US struct dirent *ep;
+
+ QString _dot(".");
+ QString _dotdot("..");
+
+//US while( ( ep = readdir( dp ) ) != 0L )
+ QStringList direntries = dp.entryList();
+ QStringList::Iterator it = direntries.begin();
+
+ while ( it != list.end() ) // for each file...
+ {
+//US QString fn( QFile::decodeName(ep->d_name));
+ QString fn = (*it); // dp.entryList() already encodes the strings
+ it++;
+
+ if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~')
+ continue;
+
+#ifdef DESKTOP_VERSION
+
+ if (pathExp.search(fn) == -1)
+ continue; // No match
+
+#else
+//US this should do the same:
+ if (pathExp.find(fn, 0) == -1)
+ continue; // No match
+#endif
+ QString rfn = relPart+fn;
+ fn = prefix + fn;
+//US if ( stat( QFile::encodeName(fn), &buff ) != 0 )
+ QFileInfo fnInfo(QFile::encodeName(fn));
+ if ( fnInfo.isReadable() == false )
+ {
+//US kdDebug() << "Error statting " << fn << " : " << perror << endl;
+ continue; // Couldn't stat (e.g. no permissions)
+ }
+//US if ( S_ISDIR( buff.st_mode ))
+ if ( fnInfo.isDir() )
+
+ lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, uniq);
+ }
+
+//US closedir( dp );
+ } else {
+ // Don't stat, if the dir doesn't exist we will find out
+ // when we try to open it.
+ lookupPrefix(prefix + path + '/', rest,
+ relPart + path + '/', regexp, list,
+ relList, recursive, uniq);
+ }
+}
+
+QStringList
+KStandardDirs::findAllResources( const char *type,
+ const QString& filter,
+ bool recursive,
+ bool uniq,
+ QStringList &relList) const
+{
+ QStringList list;
+ if (filter.at(0) == '/') // absolute paths we return
+ {
+ list.append( filter);
+ return list;
+ }
+
+ QString filterPath;
+ QString filterFile;
+
+ if (filter.length())
+ {
+ int slash = filter.findRev('/');
+ if (slash < 0)
+ filterFile = filter;
+ else {
+ filterPath = filter.left(slash + 1);
+ filterFile = filter.mid(slash + 1);
+ }
+ }
+ checkConfig();
+
+ if (d && d->restrictionsActive && (strcmp(type, "data")==0))
+ applyDataRestrictions(filter);
+ QStringList candidates = resourceDirs(type);
+ if (filterFile.isEmpty())
+ filterFile = "*";
+
+ QRegExp regExp(filterFile, true, true);
+ for (QStringList::ConstIterator it = candidates.begin();
+ it != candidates.end(); it++)
+ {
+ lookupPrefix(*it, filterPath, "", regExp, list,
+ relList, recursive, uniq);
+ }
+ return list;
+}
+
+QStringList
+KStandardDirs::findAllResources( const char *type,
+ const QString& filter,
+ bool recursive,
+ bool uniq) const
+{
+ QStringList relList;
+ return findAllResources(type, filter, recursive, uniq, relList);
+}
+
+QString
+KStandardDirs::realPath(const QString &dirname)
+{
+#ifdef _WIN32_
+ return dirname;
+#else
+//US char realpath_buffer[MAXPATHLEN + 1];
+//US memset(realpath_buffer, 0, MAXPATHLEN + 1);
+ char realpath_buffer[250 + 1];
+ memset(realpath_buffer, 0, 250 + 1);
+
+ /* If the path contains symlinks, get the real name */
+ if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) {
+ // succes, use result from realpath
+ int len = strlen(realpath_buffer);
+ realpath_buffer[len] = '/';
+ realpath_buffer[len+1] = 0;
+ return QFile::decodeName(realpath_buffer);
+ }
+
+ return dirname;
+#endif
+}
+/*US
+void KStandardDirs::createSpecialResource(const char *type)
+{
+ char hostname[256];
+ hostname[0] = 0;
+ gethostname(hostname, 255);
+ QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname);
+ char link[1024];
+ link[1023] = 0;
+ int result = readlink(QFile::encodeName(dir).data(), link, 1023);
+ if ((result == -1) && (errno == ENOENT))
+ {
+ QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin"));
+ if (srv.isEmpty())
+ srv = findExe(QString::fromLatin1("lnusertemp"));
+ if (!srv.isEmpty())
+ {
+ system(QFile::encodeName(srv)+" "+type);
+ result = readlink(QFile::encodeName(dir).data(), link, 1023);
+ }
+ }
+ if (result > 0)
+ {
+ link[result] = 0;
+ if (link[0] == '/')
+ dir = QFile::decodeName(link);
+ else
+ dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
+ }
+ addResourceDir(type, dir+'/');
+}
+*/
+
+QStringList KStandardDirs::resourceDirs(const char *type) const
+{
+ QStringList *candidates = dircache.find(type);
+
+ if (!candidates) { // filling cache
+/*US
+ if (strcmp(type, "socket") == 0)
+ const_cast<KStandardDirs *>(this)->createSpecialResource(type);
+ else if (strcmp(type, "tmp") == 0)
+ const_cast<KStandardDirs *>(this)->createSpecialResource(type);
+ else if (strcmp(type, "cache") == 0)
+ const_cast<KStandardDirs *>(this)->createSpecialResource(type);
+*/
+ QDir testdir;
+
+ candidates = new QStringList();
+ QStringList *dirs;
+
+ bool restrictionActive = false;
+ if (d && d->restrictionsActive)
+ {
+ if (d->dataRestrictionActive)
+ restrictionActive = true;
+ else if (d->restrictions["all"])
+ restrictionActive = true;
+ else if (d->restrictions[type])
+ restrictionActive = true;
+ d->dataRestrictionActive = false; // Reset
+ }
+
+ dirs = relatives.find(type);
+ if (dirs)
+ {
+ bool local = true;
+ const QStringList *prefixList = 0;
+ if (strncmp(type, "xdgdata-", 8) == 0)
+ prefixList = &(d->xdgdata_prefixes);
+ else if (strncmp(type, "xdgconf-", 8) == 0)
+ prefixList = &(d->xdgconf_prefixes);
+ else
+ prefixList = &prefixes;
+
+ for (QStringList::ConstIterator pit = prefixList->begin();
+ pit != prefixList->end();
+ pit++)
+ {
+ for (QStringList::ConstIterator it = dirs->begin();
+ it != dirs->end(); ++it) {
+ QString path = realPath(*pit + *it);
+ testdir.setPath(path);
+ if (local && restrictionActive)
+ continue;
+ if ((local || testdir.exists()) && !candidates->contains(path))
+ candidates->append(path);
+ }
+ local = false;
+ }
+ }
+ dirs = absolutes.find(type);
+ if (dirs)
+ for (QStringList::ConstIterator it = dirs->begin();
+ it != dirs->end(); ++it)
+ {
+ testdir.setPath(*it);
+ if (testdir.exists())
+ {
+ QString filename = realPath(*it);
+ if (!candidates->contains(filename))
+ candidates->append(filename);
+ }
+ }
+ dircache.insert(type, candidates);
+ }
+
+#if 0
+ kdDebug() << "found dirs for resource " << type << ":" << endl;
+ for (QStringList::ConstIterator pit = candidates->begin();
+ pit != candidates->end();
+ pit++)
+ {
+ fprintf(stderr, "%s\n", (*pit).latin1());
+ }
+#endif
+
+
+ return *candidates;
+}
+
+/*US
+QString KStandardDirs::findExe( const QString& appname,
+ const QString& pstr, bool ignore)
+{
+ QFileInfo info;
+
+ // absolute path ?
+ if (appname.startsWith(QString::fromLatin1("/")))
+ {
+ info.setFile( appname );
+ if( info.exists() && ( ignore || info.isExecutable() )
+ && info.isFile() ) {
+ return appname;
+ }
+ return QString::null;
+ }
+
+//US QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname);
+ QString p = QString("%1/%2").arg(appname).arg(appname);
+ qDebug("KStandardDirs::findExe this is probably wrong");
+
+ info.setFile( p );
+ if( info.exists() && ( ignore || info.isExecutable() )
+ && ( info.isFile() || info.isSymLink() ) ) {
+ return p;
+ }
+
+ QStringList tokens;
+ p = pstr;
+
+ if( p.isNull() ) {
+ p = getenv( "PATH" );
+ }
+
+ tokenize( tokens, p, ":\b" );
+
+ // split path using : or \b as delimiters
+ for( unsigned i = 0; i < tokens.count(); i++ ) {
+ p = tokens[ i ];
+
+ if ( p[ 0 ] == '~' )
+ {
+ int len = p.find( '/' );
+ if ( len == -1 )
+ len = p.length();
+ if ( len == 1 )
+ p.replace( 0, 1, QDir::homeDirPath() );
+ else
+ {
+ QString user = p.mid( 1, len - 1 );
+ struct passwd *dir = getpwnam( user.local8Bit().data() );
+ if ( dir && strlen( dir->pw_dir ) )
+ p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
+ }
+ }
+
+ p += "/";
+ p += appname;
+
+ // Check for executable in this tokenized path
+ info.setFile( p );
+
+ if( info.exists() && ( ignore || info.isExecutable() )
+ && ( info.isFile() || info.isSymLink() ) ) {
+ return p;
+ }
+ }
+
+ // If we reach here, the executable wasn't found.
+ // So return empty string.
+
+ return QString::null;
+}
+
+int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
+ const QString& pstr, bool ignore )
+{
+ QString p = pstr;
+ QFileInfo info;
+ QStringList tokens;
+
+ if( p.isNull() ) {
+ p = getenv( "PATH" );
+ }
+
+ list.clear();
+ tokenize( tokens, p, ":\b" );
+
+ for ( unsigned i = 0; i < tokens.count(); i++ ) {
+ p = tokens[ i ];
+ p += "/";
+ p += appname;
+
+ info.setFile( p );
+
+ if( info.exists() && (ignore || info.isExecutable())
+ && info.isFile() ) {
+ list.append( p );
+ }
+
+ }
+
+ return list.count();
+}
+*/
+
+static int tokenize( QStringList& tokens, const QString& str,
+ const QString& delim )
+{
+ int len = str.length();
+ QString token = "";
+
+ for( int index = 0; index < len; index++)
+ {
+ if ( delim.find( str[ index ] ) >= 0 )
+ {
+ tokens.append( token );
+ token = "";
+ }
+ else
+ {
+ token += str[ index ];
+ }
+ }
+ if ( token.length() > 0 )
+ {
+ tokens.append( token );
+ }
+
+ return tokens.count();
+}
+
+QString KStandardDirs::kde_default(const char *type) {
+ if (!strcmp(type, "data"))
+ return "apps/";
+ if (!strcmp(type, "html"))
+ return "share/doc/HTML/";
+ if (!strcmp(type, "icon"))
+ return "share/icons/";
+ if (!strcmp(type, "config"))
+ return "config/";
+ if (!strcmp(type, "pixmap"))
+ return "share/pixmaps/";
+ if (!strcmp(type, "apps"))
+ return "share/applnk/";
+ if (!strcmp(type, "sound"))
+ return "share/sounds/";
+ if (!strcmp(type, "locale"))
+ return "share/locale/";
+ if (!strcmp(type, "services"))
+ return "share/services/";
+ if (!strcmp(type, "servicetypes"))
+ return "share/servicetypes/";
+ if (!strcmp(type, "mime"))
+ return "share/mimelnk/";
+ if (!strcmp(type, "cgi"))
+ return "cgi-bin/";
+ if (!strcmp(type, "wallpaper"))
+ return "share/wallpapers/";
+ if (!strcmp(type, "templates"))
+ return "share/templates/";
+ if (!strcmp(type, "exe"))
+ return "bin/";
+ if (!strcmp(type, "lib"))
+ return "lib/";
+ if (!strcmp(type, "module"))
+ return "lib/kde3/";
+ if (!strcmp(type, "qtplugins"))
+ return "lib/kde3/plugins";
+ if (!strcmp(type, "xdgdata-apps"))
+ return "applications/";
+ if (!strcmp(type, "xdgdata-dirs"))
+ return "desktop-directories/";
+ if (!strcmp(type, "xdgconf-menu"))
+ return "menus/";
+ qFatal("unknown resource type %s", type);
+ return QString::null;
+}
+
+QString KStandardDirs::saveLocation(const char *type,
+ const QString& suffix,
+ bool create) const
+{
+ //qDebug("KStandardDirs::saveLocation called %s %s", type,suffix.latin1() );
+ //return "";
+ checkConfig();
+
+ QString *pPath = savelocations.find(type);
+ if (!pPath)
+ {
+ QStringList *dirs = relatives.find(type);
+ if (!dirs && (
+ (strcmp(type, "socket") == 0) ||
+ (strcmp(type, "tmp") == 0) ||
+ (strcmp(type, "cache") == 0) ))
+ {
+ (void) resourceDirs(type); // Generate socket|tmp|cache resource.
+ dirs = relatives.find(type); // Search again.
+ }
+ if (dirs)
+ {
+ // Check for existance of typed directory + suffix
+ if (strncmp(type, "xdgdata-", 8) == 0)
+ pPath = new QString(realPath(localxdgdatadir() + dirs->last()));
+ else if (strncmp(type, "xdgconf-", 8) == 0)
+ pPath = new QString(realPath(localxdgconfdir() + dirs->last()));
+ else
+ pPath = new QString(realPath(localkdedir() + dirs->last()));
+ }
+ else {
+ dirs = absolutes.find(type);
+ if (!dirs)
+ qFatal("KStandardDirs: The resource type %s is not registered", type);
+ pPath = new QString(realPath(dirs->last()));
+ }
+
+ savelocations.insert(type, pPath);
+ }
+
+ QString fullPath = *pPath + suffix;
+//US struct stat st;
+//US if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode)))
+ QFileInfo fullPathInfo(QFile::encodeName(fullPath));
+ if (fullPathInfo.isReadable() || !fullPathInfo.isDir())
+
+
+ {
+ if(!create) {
+#ifndef NDEBUG
+ qDebug("save location %s doesn't exist", fullPath.latin1());
+#endif
+ return fullPath;
+ }
+ if(!makeDir(fullPath, 0700)) {
+ qWarning("failed to create %s", fullPath.latin1());
+ return fullPath;
+ }
+ dircache.remove(type);
+ }
+ return fullPath;
+}
+
+QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
+{
+ QString fullPath = absPath;
+ int i = absPath.findRev('/');
+ if (i != -1)
+ {
+ fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize
+ }
+
+ QStringList candidates = resourceDirs(type);
+
+ for (QStringList::ConstIterator it = candidates.begin();
+ it != candidates.end(); it++)
+ if (fullPath.startsWith(*it))
+ {
+ return fullPath.mid((*it).length());
+ }
+
+ return absPath;
+}
+
+
+bool KStandardDirs::makeDir(const QString& dir2, int mode)
+{
+ QString dir = QDir::convertSeparators( dir2 );
+#if 0
+ //LR
+
+ // we want an absolute path
+ if (dir.at(0) != '/')
+ return false;
+
+ QString target = dir;
+ uint len = target.length();
+
+ // append trailing slash if missing
+ if (dir.at(len - 1) != '/')
+ target += '/';
+
+ QString base("");
+ uint i = 1;
+
+ while( i < len )
+ {
+//US struct stat st;
+ int pos = target.find('/', i);
+ base += target.mid(i - 1, pos - i + 1);
+ QCString baseEncoded = QFile::encodeName(base);
+ // bail out if we encountered a problem
+//US if (stat(baseEncoded, &st) != 0)
+ QFileInfo baseEncodedInfo(baseEncoded);
+ if (!baseEncodedInfo.exists())
+ {
+ // Directory does not exist....
+ // Or maybe a dangling symlink ?
+//US if (lstat(baseEncoded, &st) == 0)
+ if (baseEncodedInfo.isSymLink()) {
+//US (void)unlink(baseEncoded); // try removing
+ QFile(baseEncoded).remove();
+ }
+
+//US if ( mkdir(baseEncoded, (mode_t) mode) != 0)
+ QDir dirObj;
+ if ( dirObj.mkdir(baseEncoded) != true )
+ {
+//US perror("trying to create local folder");
+ return false; // Couldn't create it :-(
+ }
+ }
+ i = pos + 1;
+ }
+ return true;
+#endif
+
+ // ********************************************
+ // new code for WIN32
+ QDir dirObj;
+
+
+ // we want an absolute path
+#ifndef _WIN32_
+ if (dir.at(0) != '/')
+ return false;
+#endif
+
+ QString target = dir;
+ uint len = target.length();
+#ifndef _WIN32_
+ // append trailing slash if missing
+ if (dir.at(len - 1) != '/')
+ target += '/';
+#endif
+
+ QString base("");
+ uint i = 1;
+
+ while( i < len )
+ {
+//US struct stat st;
+#ifndef _WIN32_
+ int pos = target.find('/', i);
+#else
+ int pos = target.find('\\', i);
+#endif
+ if ( pos < 0 )
+ return true;
+ base += target.mid(i - 1, pos - i + 1);
+ //QMessageBox::information( 0,"cap111", base, 1 );
+/*US
+ QCString baseEncoded = QFile::encodeName(base);
+ // bail out if we encountered a problem
+ if (stat(baseEncoded, &st) != 0)
+ {
+ // Directory does not exist....
+ // Or maybe a dangling symlink ?
+ if (lstat(baseEncoded, &st) == 0)
+ (void)unlink(baseEncoded); // try removing
+
+
+ if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
+ perror("trying to create local folder");
+ return false; // Couldn't create it :-(
+ }
+ }
+*/
+
+ if (dirObj.exists(base) == false)
+ {
+ //qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1());
+ if (dirObj.mkdir(base) != true)
+ {
+ qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1());
+ return false;
+ }
+ }
+
+ i = pos + 1;
+ }
+ return true;
+
+}
+
+static QString readEnvPath(const char *env)
+{
+#ifdef _WIN32_
+ return "";
+#else
+ QCString c_path = getenv(env);
+ if (c_path.isEmpty())
+ return QString::null;
+ return QFile::decodeName(c_path);
+#endif
+}
+
+void KStandardDirs::addKDEDefaults()
+{
+ //qDebug("ERROR: KStandardDirs::addKDEDefaults() called ");
+ //return;
+ QStringList kdedirList;
+
+ // begin KDEDIRS
+ QString kdedirs = readEnvPath("MICROKDEDIRS");
+ if (!kdedirs.isEmpty())
+ {
+ tokenize(kdedirList, kdedirs, ":");
+ }
+ else
+ {
+ QString kdedir = readEnvPath("MICROKDEDIR");
+ if (!kdedir.isEmpty())
+ {
+ kdedir = KShell::tildeExpand(kdedir);
+ kdedirList.append(kdedir);
+ }
+ }
+//US kdedirList.append(KDEDIR);
+
+#ifdef __KDE_EXECPREFIX
+ QString execPrefix(__KDE_EXECPREFIX);
+ if (execPrefix!="NONE")
+ kdedirList.append(execPrefix);
+#endif
+
+ QString localKdeDir;
+
+//US if (getuid())
+ if (true)
+ {
+ localKdeDir = readEnvPath("MICROKDEHOME");
+ if (!localKdeDir.isEmpty())
+ {
+ if (localKdeDir.at(localKdeDir.length()-1) != '/')
+ localKdeDir += '/';
+ }
+ else
+ {
+ localKdeDir = QDir::homeDirPath() + "/kdepim/";
+ }
+ }
+ else
+ {
+ // We treat root different to prevent root messing up the
+ // file permissions in the users home directory.
+ localKdeDir = readEnvPath("MICROKDEROOTHOME");
+ if (!localKdeDir.isEmpty())
+ {
+ if (localKdeDir.at(localKdeDir.length()-1) != '/')
+ localKdeDir += '/';
+ }
+ else
+ {
+//US struct passwd *pw = getpwuid(0);
+//US localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.microkde/";
+ qDebug("KStandardDirs::addKDEDefaults: 1 has to be fixed");
+ }
+
+ }
+
+//US localKdeDir = appDir();
+
+//US
+// qDebug("KStandardDirs::addKDEDefaults: localKdeDir=%s", localKdeDir.latin1());
+ if (localKdeDir != "-/")
+ {
+ localKdeDir = KShell::tildeExpand(localKdeDir);
+ addPrefix(localKdeDir);
+ }
+
+ for (QStringList::ConstIterator it = kdedirList.begin();
+ it != kdedirList.end(); it++)
+ {
+ QString dir = KShell::tildeExpand(*it);
+ addPrefix(dir);
+ }
+ // end KDEDIRS
+
+ // begin XDG_CONFIG_XXX
+ QStringList xdgdirList;
+ QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
+ if (!xdgdirs.isEmpty())
+ {
+ tokenize(xdgdirList, xdgdirs, ":");
+ }
+ else
+ {
+ xdgdirList.clear();
+ xdgdirList.append("/etc/xdg");
+ }
+
+ QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
+ if (!localXdgDir.isEmpty())
+ {
+ if (localXdgDir.at(localXdgDir.length()-1) != '/')
+ localXdgDir += '/';
+ }
+ else
+ {
+//US if (getuid())
+ if (true)
+ {
+ localXdgDir = QDir::homeDirPath() + "/.config/";
+ }
+ else
+ {
+//US struct passwd *pw = getpwuid(0);
+//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.config/";
+ qDebug("KStandardDirs::addKDEDefaults: 2 has to be fixed");
+ }
+ }
+
+ localXdgDir = KShell::tildeExpand(localXdgDir);
+ addXdgConfigPrefix(localXdgDir);
+
+ for (QStringList::ConstIterator it = xdgdirList.begin();
+ it != xdgdirList.end(); it++)
+ {
+ QString dir = KShell::tildeExpand(*it);
+ addXdgConfigPrefix(dir);
+ }
+ // end XDG_CONFIG_XXX
+
+ // begin XDG_DATA_XXX
+ xdgdirs = readEnvPath("XDG_DATA_DIRS");
+ if (!xdgdirs.isEmpty())
+ {
+ tokenize(xdgdirList, xdgdirs, ":");
+ }
+ else
+ {
+ xdgdirList.clear();
+ for (QStringList::ConstIterator it = kdedirList.begin();
+ it != kdedirList.end(); it++)
+ {
+ QString dir = *it;
+ if (dir.at(dir.length()-1) != '/')
+ dir += '/';
+ xdgdirList.append(dir+"share/");
+ }
+
+ xdgdirList.append("/usr/local/share/");
+ xdgdirList.append("/usr/share/");
+ }
+
+ localXdgDir = readEnvPath("XDG_DATA_HOME");
+ if (!localXdgDir.isEmpty())
+ {
+ if (localXdgDir.at(localXdgDir.length()-1) != '/')
+ localXdgDir += '/';
+ }
+ else
+ {
+//US if (getuid())
+ if (true)
+ {
+ localXdgDir = QDir::homeDirPath() + "/.local/share/";
+ }
+ else
+ {
+//US struct passwd *pw = getpwuid(0);
+//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.local/share/";
+ qDebug("KStandardDirs::addKDEDefaults: 3 has to be fixed");
+ }
+ }
+
+ localXdgDir = KShell::tildeExpand(localXdgDir);
+ addXdgDataPrefix(localXdgDir);
+
+ for (QStringList::ConstIterator it = xdgdirList.begin();
+ it != xdgdirList.end(); it++)
+ {
+ QString dir = KShell::tildeExpand(*it);
+
+ addXdgDataPrefix(dir);
+ }
+ // end XDG_DATA_XXX
+
+
+ uint index = 0;
+ while (types[index] != 0) {
+ addResourceType(types[index], kde_default(types[index]));
+ index++;
+ }
+
+ addResourceDir("home", QDir::homeDirPath());
+}
+
+void KStandardDirs::checkConfig() const
+{
+/*US
+ if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config)
+ const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config);
+*/
+ if (!addedCustoms && KGlobal::config())
+ const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::config());
+}
+
+bool KStandardDirs::addCustomized(KConfig *config)
+{
+ if (addedCustoms) // there are already customized entries
+ return false; // we just quite and hope they are the right ones
+
+ // save the numbers of config directories. If this changes,
+ // we will return true to give KConfig a chance to reparse
+ uint configdirs = resourceDirs("config").count();
+
+ // reading the prefixes in
+ QString oldGroup = config->group();
+ config->setGroup("Directories");
+
+ QStringList list;
+ QStringList::ConstIterator it;
+ list = config->readListEntry("prefixes");
+ for (it = list.begin(); it != list.end(); it++)
+ addPrefix(*it);
+
+ // iterating over all entries in the group Directories
+ // to find entries that start with dir_$type
+/*US
+ QMap<QString, QString> entries = config->entryMap("Directories");
+
+ QMap<QString, QString>::ConstIterator it2;
+ for (it2 = entries.begin(); it2 != entries.end(); it2++)
+ {
+ QString key = it2.key();
+ if (key.left(4) == "dir_") {
+ // generate directory list, there may be more than 1.
+ QStringList dirs = QStringList::split(',', *it2);
+ QStringList::Iterator sIt(dirs.begin());
+ QString resType = key.mid(4, key.length());
+ for (; sIt != dirs.end(); ++sIt) {
+ addResourceDir(resType.latin1(), *sIt);
+ }
+ }
+ }
+
+ // Process KIOSK restrictions.
+ config->setGroup("KDE Resource Restrictions");
+ entries = config->entryMap("KDE Resource Restrictions");
+ for (it2 = entries.begin(); it2 != entries.end(); it2++)
+ {
+ QString key = it2.key();
+ if (!config->readBoolEntry(key, true))
+ {
+ d->restrictionsActive = true;
+ d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do
+ dircache.remove(key.latin1());
+ }
+ }
+*/
+ // save it for future calls - that will return
+ addedCustoms = true;
+ config->setGroup(oldGroup);
+
+ // return true if the number of config dirs changed
+ return (resourceDirs("config").count() != configdirs);
+}
+
+QString KStandardDirs::localkdedir() const
+{
+ // Return the prefix to use for saving
+ return prefixes.first();
+}
+
+QString KStandardDirs::localxdgdatadir() const
+{
+ // Return the prefix to use for saving
+ return d->xdgdata_prefixes.first();
+}
+
+QString KStandardDirs::localxdgconfdir() const
+{
+ // Return the prefix to use for saving
+ return d->xdgconf_prefixes.first();
+}
+
+void KStandardDirs::setAppDir( const QString &appDir )
+{
+ mAppDir = appDir;
+
+ if ( mAppDir.right( 1 ) != "/" )
+ mAppDir += "/";
+}
+
+QString KStandardDirs::appDir()
+{
+ return mAppDir;
+}
+
+// just to make code more readable without macros
+QString locate( const char *type,
+ const QString& filename/*US , const KInstance* inst*/ )
+{
+//US return inst->dirs()->findResource(type, filename);
+ return KGlobal::dirs()->findResource(type, filename);
+}
+
+QString locateLocal( const char *type,
+ const QString& filename/*US , const KInstance* inst*/ )
+{
+
+ QString path = locateLocal(type, filename, true /*US, inst*/);
+
+
+/*
+ static int ccc = 0;
+ ++ccc;
+ if ( ccc > 13 )
+ abort();
+*/
+ qDebug("locatelocal: %s" , path.latin1());
+ return path;
+
+/*US why do we put all files into one directory. It is quit complicated.
+why not staying with the original directorystructure ?
+
+
+ QString escapedFilename = filename;
+ escapedFilename.replace( QRegExp( "/" ), "_" );
+
+ QString path = KStandardDirs::appDir() + type + "_" + escapedFilename;
+
+ kdDebug() << "locate: '" << path << "'" << endl;
+ qDebug("locate: %s" , path.latin1());
+ return path;
+*/
+//US so my proposal is this:
+
+// QString escapedFilename = filename;
+// escapedFilename.replace( QRegExp( "/" ), "_" );
+
+#if 0
+#ifdef _WIN32_
+ QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename);
+#else
+ QString path = KStandardDirs::appDir() + type + "/" + filename;
+#endif
+
+ //US Create the containing dir if needed
+ QFileInfo fi ( path );
+
+ // QString dir=pathurl.directory();
+ // QMessageBox::information( 0,"path", path, 1 );
+
+#ifdef _WIN32_
+ KStandardDirs::makeDir(path);
+#else
+ KStandardDirs::makeDir(fi.dirPath( true ));
+#endif
+
+ qDebug("locate22: %s" , path.latin1());
+ return path;
+
+#endif
+
+}
+
+QString locateLocal( const char *type,
+ const QString& filename, bool createDir/*US , const KInstance* inst*/ )
+{
+ // try to find slashes. If there are some, we have to
+ // create the subdir first
+ int slash = filename.findRev('/')+1;
+ if (!slash) // only one filename
+//US return inst->dirs()->saveLocation(type, QString::null, createDir) + filename;
+ return KGlobal::dirs()->saveLocation(type, QString::null, createDir) + filename;
+
+ // split path from filename
+ QString dir = filename.left(slash);
+ QString file = filename.mid(slash);
+//US return inst->dirs()->saveLocation(type, dir, createDir) + file;
+ return KGlobal::dirs()->saveLocation(type, dir, createDir) + file;
+
+ // ***************************************************************
+#if 0
+
+/*US why do we put all files into one directory. It is quit complicated.
+why not staying with the original directorystructure ?
+
+
+ QString escapedFilename = filename;
+ escapedFilename.replace( QRegExp( "/" ), "_" );
+
+ QString path = KStandardDirs::appDir() + type + "_" + escapedFilename;
+
+ kdDebug() << "locate: '" << path << "'" << endl;
+ qDebug("locate: %s" , path.latin1());
+ return path;
+*/
+//US so my proposal is this:
+
+// QString escapedFilename = filename;
+// escapedFilename.replace( QRegExp( "/" ), "_" );
+
+#ifdef _WIN32_
+ QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename);
+#else
+ QString path = KStandardDirs::appDir() + type + "/" + filename;
+#endif
+
+ //US Create the containing dir if needed
+ KURL pathurl;
+ pathurl.setPath(path);
+ QString dir=pathurl.directory();
+ // QMessageBox::information( 0,"path", path, 1 );
+#ifdef _WIN32_
+ KStandardDirs::makeDir(path);
+#else
+ KStandardDirs::makeDir(dir);
+#endif
+
+ return path;
+#endif
+}
diff --git a/microkde/kdecore/kstandarddirs.h b/microkde/kdecore/kstandarddirs.h
new file mode 100644
index 0000000..c4e1108
--- a/dev/null
+++ b/microkde/kdecore/kstandarddirs.h
@@ -0,0 +1,681 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
+ Stephan Kulow <coolo@kde.org>
+ Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef SSK_KSTDDIRS_H
+#define SSK_KSTDDIRS_H
+
+#include <qstring.h>
+#include <qdict.h>
+#include <qstringlist.h>
+#include <kglobal.h>
+
+class KConfig;
+class KStandardDirsPrivate;
+
+
+/**
+ * @short Site-independent access to standard KDE directories.
+ * @author Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
+ * @version $Id$
+ *
+ * This is one of the most central classes in kdelibs as
+ * it provides a basic service: It knows where the files
+ * reside on the user's hard disk. And it's meant to be the
+ * only one that knows -- to make the real location as
+ * transparent as possible to both the user and the applications.
+ *
+ * To this end it insulates the application from all information
+ * and applications always refer to a file with a resource type
+ * (e.g. icon) and a filename (e.g. khexdit.xpm). In an ideal world
+ * the application would make no assumption where this file is and
+ * leave it up to @ref KStandardDirs::findResource("apps", "Home.desktop")
+ * to apply this knowledge to return /opt/kde/share/applnk/Home.desktop
+ * or ::locate("data", "kgame/background.jpg") to return
+ * /opt/kde/share/apps/kgame/background.jpg
+ *
+ * The main idea behind KStandardDirs is that there are several
+ * toplevel prefixes below which the files lie. One of these prefixes is
+ * the one where the user installed kdelibs, one is where the
+ * application was installed, and one is $HOME/.kde, but there
+ * may be even more. Under these prefixes there are several well
+ * defined suffixes where specific resource types are to be found.
+ * For example, for the resource type "html" the suffixes could be
+ * share/doc/HTML and share/doc/kde/HTML.
+ * So the search algorithm basicly appends to each prefix each registered
+ * suffix and tries to locate the file there.
+ * To make the thing even more complex, it's also possible to register
+ * absolute paths that KStandardDirs looks up after not finding anything
+ * in the former steps. They can be useful if the user wants to provide
+ * specific directories that aren't in his $HOME/.kde directory for,
+ * for example, icons.
+ *
+ * @sect Standard resources that kdelibs allocates are:
+ *
+ * @li apps - Applications menu (.desktop files).
+ * @li cache - Cached information (e.g. favicons, web-pages)
+ * @li cgi - CGIs to run from kdehelp.
+ * @li config - Configuration files.
+ * @li data - Where applications store data.
+ * @li exe - Executables in $prefix/bin. @ref findExe() for a function that takes $PATH into account.
+ * @li html - HTML documentation.
+ * @li icon - Icons, see @ref KIconLoader.
+ * @li lib - Libraries.
+ * @li locale - Translation files for @ref KLocale.
+ * @li mime - Mime types.
+ * @li module - Module (dynamically loaded library).
+ * @li qtplugins - Qt plugins (dynamically loaded objects for Qt)
+ * @li services - Services.
+ * @li servicetypes - Service types.
+ * @li scripts - Application scripting additions.
+ * @li sound - Application sounds.
+ * @li templates - Templates
+ * @li wallpaper - Wallpapers.
+ * @li tmp - Temporary files (specfic for both current host and current user)
+ * @li socket - UNIX Sockets (specific for both current host and current user)
+ *
+ * A type that is added by the class @ref KApplication if you use it, is
+ * appdata. This one makes the use of the type data a bit easier as it
+ * appends the name of the application.
+ * So while you had to ::locate("data", "appname/filename") so you can
+ * also write ::locate("appdata", "filename") if your KApplication instance
+ * is called "appname" (as set via KApplication's constructor or KAboutData, if
+ * you use the global KStandardDirs object @ref KGlobal::dirs()).
+ * Please note though that you cannot use the "appdata"
+ * type if you intend to use it in an applet for Kicker because 'appname' would
+ * be "Kicker" instead of the applet's name. Therefore, for applets, you've got
+ * to work around this by using ::locate("data", "appletname/filename").
+ *
+ * @sect KStandardDirs supports the following environment variables:
+ *
+ * @li KDEDIRS: This may set an additional number of directory prefixes to
+ * search for resources. The directories should be seperated
+ * by ':'. The directories are searched in the order they are
+ * specified.
+ * @li KDEDIR: Used for backwards compatibility. As KDEDIRS but only a single
+ * directory may be specified. If KDEDIRS is set KDEDIR is
+ * ignored.
+ * @li KDEHOME: The directory where changes are saved to. This directory is
+ * used to search for resources first. If KDEHOME is not
+ * specified it defaults to "$HOME/.kde"
+ * @li KDEROOTHOME: Like KDEHOME, but used for the root user.
+ * If KDEROOTHOME is not set it defaults to the .kde directory in the
+ * home directory of root, usually "/root/.kde".
+ * Note that the setting of $HOME is ignored in this case.
+ *
+ * @see KGlobalSettings
+ */
+class KStandardDirs
+{
+public:
+ /**
+ * KStandardDirs' constructor. It just initializes the caches.
+ **/
+ KStandardDirs( );
+
+ /**
+ * KStandardDirs' destructor.
+ */
+ virtual ~KStandardDirs();
+
+ /**
+ * Adds another search dir to front of the @p fsstnd list.
+ *
+ * @li When compiling kdelibs, the prefix is added to this.
+ * @li KDEDIRS or KDEDIR is taking into account
+ * @li Additional dirs may be loaded from kdeglobals.
+ *
+ * @param dir The directory to append relative paths to.
+ */
+ void addPrefix( const QString& dir );
+
+ /**
+ * Adds another search dir to front of the XDG_CONFIG_XXX list
+ * of prefixes.
+ * This prefix is only used for resources that start with "xdgconf-"
+ *
+ * @param dir The directory to append relative paths to.
+ */
+ void addXdgConfigPrefix( const QString& dir );
+
+ /**
+ * Adds another search dir to front of the XDG_DATA_XXX list
+ * of prefixes.
+ * This prefix is only used for resources that start with "xdgdata-"
+ *
+ * @param dir The directory to append relative paths to.
+ */
+ void addXdgDataPrefix( const QString& dir );
+
+ /**
+ * Adds suffixes for types.
+ *
+ * You may add as many as you need, but it is advised that there
+ * is exactly one to make writing definite.
+ * All basic types (@ref kde_default) are added by @ref addKDEDefaults(),
+ * but for those you can add more relative paths as well.
+ *
+ * The later a suffix is added, the higher its priority. Note, that the
+ * suffix should end with / but doesn't have to start with one (as prefixes
+ * should end with one). So adding a suffix for app_pics would look
+ * like KGlobal::dirs()->addResourceType("app_pics", "share/app/pics");
+ *
+ * @param type Specifies a short descriptive string to access
+ * files of this type.
+ * @param relativename Specifies a directory relative to the root
+ * of the KFSSTND.
+ * @return true if successful, false otherwise.
+ */
+ bool addResourceType( const char *type,
+ const QString& relativename );
+
+ /**
+ * Adds absolute path at the end of the search path for
+ * particular types (for example in case of icons where
+ * the user specifies extra paths).
+ *
+ * You shouldn't need this
+ * function in 99% of all cases besides adding user-given
+ * paths.
+ *
+ * @param type Specifies a short descriptive string to access files
+ * of this type.
+ * @param absdir Points to directory where to look for this specific
+ * type. Non-existant directories may be saved but pruned.
+ * @return true if successful, false otherwise.
+ */
+ bool addResourceDir( const char *type,
+ const QString& absdir);
+
+ /**
+ * Tries to find a resource in the following order:
+ * @li All PREFIX/\<relativename> paths (most recent first).
+ * @li All absolute paths (most recent first).
+ *
+ * The filename should be a filename relative to the base dir
+ * for resources. So is a way to get the path to libkdecore.la
+ * to findResource("lib", "libkdecore.la"). KStandardDirs will
+ * then look into the subdir lib of all elements of all prefixes
+ * ($KDEDIRS) for a file libkdecore.la and return the path to
+ * the first one it finds (e.g. /opt/kde/lib/libkdecore.la)
+ *
+ * @param type The type of the wanted resource
+ * @param filename A relative filename of the resource.
+ *
+ * @return A full path to the filename specified in the second
+ * argument, or QString::null if not found.
+ */
+ QString findResource( const char *type,
+ const QString& filename ) const;
+
+ /**
+ * Checks whether a resource is restricted as part of the KIOSK
+ * framework. When a resource is restricted it means that user-
+ * specific files in the resource are ignored.
+ *
+ * E.g. by restricting the "wallpaper" resource, only system-wide
+ * installed wallpapers will be found by this class. Wallpapers
+ * installed under the $KDEHOME directory will be ignored.
+ *
+ * @param type The type of the resource to check
+ * @param relPath A relative path in the resource.
+ *
+ * @return True if the resource is restricted.
+ * @since 3.1
+ */
+ bool isRestrictedResource( const char *type,
+ const QString& relPath=QString::null ) const;
+
+ /**
+ * Returns a number that identifies this version of the resource.
+ * When a change is made to the resource this number will change.
+ *
+ * @param type The type of the wanted resource
+ * @param filename A relative filename of the resource.
+ * @param deep If true, all resources are taken into account
+ * otherwise only the one returned by findResource().
+ *
+ * @return A number identifying the current version of the
+ * resource.
+ */
+/*US
+ Q_UINT32 calcResourceHash( const char *type,
+ const QString& filename, bool deep) const;
+*/
+ /**
+ * Tries to find all directories whose names consist of the
+ * specified type and a relative path. So would
+ * findDirs("apps", "Settings") return
+ * @li /opt/kde/share/applnk/Settings/
+ * @li /home/joe/.kde/share/applnk/Settings/
+ *
+ * Note that it appends / to the end of the directories,
+ * so you can use this right away as directory names.
+ *
+ * @param type The type of the base directory.
+ * @param reldir Relative directory.
+ *
+ * @return A list of matching directories, or an empty
+ * list if the resource specified is not found.
+ */
+ QStringList findDirs( const char *type,
+ const QString& reldir ) const;
+
+ /**
+ * Tries to find the directory the file is in.
+ * It works the same as @ref findResource(), but it doesn't
+ * return the filename but the name of the directory.
+ *
+ * This way the application can access a couple of files
+ * that have been installed into the same directory without
+ * having to look for each file.
+ *
+ * findResourceDir("lib", "libkdecore.la") would return the
+ * path of the subdir libkdecore.la is found first in
+ * (e.g. /opt/kde/lib/)
+ *
+ * @param type The type of the wanted resource
+ * @param filename A relative filename of the resource.
+ * @return The directory where the file specified in the second
+ * argument is located, or QString::null if the type
+ * of resource specified is unknown or the resource
+ * cannot be found.
+ */
+ QString findResourceDir( const char *type,
+ const QString& filename) const;
+
+
+ /**
+ * Tries to find all resources with the specified type.
+ *
+ * The function will look into all specified directories
+ * and return all filenames in these directories.
+ *
+ * @param type The type of resource to locate directories for.
+ * @param filter Only accept filenames that fit to filter. The filter
+ * may consist of an optional directory and a @ref QRegExp
+ * wildcard expression. E.g. "images\*.jpg". Use QString::null
+ * if you do not want a filter.
+ * @param recursive Specifies if the function should decend
+ * into subdirectories.
+ * @param uniq If specified, only return items which have
+ * unique suffixes - suppressing duplicated filenames.
+ *
+ * @return A list of directories matching the resource specified,
+ * or an empty list if the resource type is unknown.
+ */
+ QStringList findAllResources( const char *type,
+ const QString& filter = QString::null,
+ bool recursive = false,
+ bool uniq = false) const;
+
+ /**
+ * Tries to find all resources with the specified type.
+ *
+ * The function will look into all specified directories
+ * and return all filenames (full and relative paths) in
+ * these directories.
+ *
+ * @param type The type of resource to locate directories for.
+ * @param filter Only accept filenames that fit to filter. The filter
+ * may consist of an optional directory and a @ref QRegExp
+ * wildcard expression. E.g. "images\*.jpg". Use QString::null
+ * if you do not want a filter.
+ * @param recursive Specifies if the function should decend
+ * into subdirectories.
+ * @param uniq If specified, only return items which have
+ * unique suffixes.
+ * @param list Of relative paths for the given type.
+ * @param relPaths The list to store the relative paths into
+ * These can be used later to ::locate() the file
+ *
+ * @return A list of directories matching the resource specified,
+ * or an empty list if the resource type is unknown.
+ */
+ QStringList findAllResources( const char *type,
+ const QString& filter,
+ bool recursive,
+ bool uniq,
+ QStringList &relPaths) const;
+
+ /**
+ * Finds the executable in the system path.
+ *
+ * A valid executable must
+ * be a file and have its executable bit set.
+ *
+ * @param appname The name of the executable file for which to search.
+ * @param pathstr The path which will be searched. If this is
+ * null (default), the $PATH environment variable will
+ * be searched.
+ * @param ignoreExecBit If true, an existing file will be returned
+ * even if its executable bit is not set.
+ *
+ * @return The path of the executable. If it was not found,
+ * it will return QString::null.
+ * @see findAllExe()
+ */
+/*US
+ static QString findExe( const QString& appname,
+ const QString& pathstr=QString::null,
+ bool ignoreExecBit=false );
+*/
+
+ /**
+ * Finds all occurences of an executable in the system path.
+ *
+ * @param list Will be filled with the pathnames of all the
+ * executables found. Will be empty if the executable
+ * was not found.
+ * @param appname The name of the executable for which to
+ * search.
+ * @param pathstr The path list which will be searched. If this
+ * is 0 (default), the $PATH environment variable will
+ * be searched.
+ * @param ignoreExecBit If true, an existing file will be returned
+ * even if its executable bit is not set.
+ *
+ * @return The number of executables found, 0 if none were found.
+ *
+ * @see findExe()
+ */
+ static int findAllExe( QStringList& list, const QString& appname,
+ const QString& pathstr=QString::null,
+ bool ignoreExecBit=false );
+
+ /**
+ * This function adds the defaults that are used by the current
+ * KDE version.
+ *
+ * It's a series of @ref addResourceTypes()
+ * and @ref addPrefix() calls.
+ * You normally wouldn't call this function because it's called
+ * for you from @ref KGlobal.
+ */
+ void addKDEDefaults();
+
+ /**
+ * Reads customized entries out of the given config object and add
+ * them via @ref addResourceDirs().
+ *
+ * @param config The object the entries are read from. This should
+ * contain global config files
+ * @return true if new config paths have been added
+ * from @p config.
+ **/
+ bool addCustomized(KConfig *config);
+
+ /**
+ * This function is used internally by almost all other function as
+ * it serves and fills the directories cache.
+ *
+ * @param type The type of resource
+ * @return The list of possible directories for the specified @p type.
+ * The function updates the cache if possible. If the resource
+ * type specified is unknown, it will return an empty list.
+ * Note, that the directories are assured to exist beside the save
+ * location, which may not exist, but is returned anyway.
+ */
+ QStringList resourceDirs(const char *type) const;
+
+ /**
+ * This function will return a list of all the types that KStandardDirs
+ * supports.
+ *
+ * @return All types that KDE supports
+ */
+ QStringList allTypes() const;
+
+ /**
+ * Finds a location to save files into for the given type
+ * in the user's home directory.
+ *
+ * @param type The type of location to return.
+ * @param suffix A subdirectory name.
+ * Makes it easier for you to create subdirectories.
+ * You can't pass filenames here, you _have_ to pass
+ * directory names only and add possible filename in
+ * that directory yourself. A directory name always has a
+ * trailing slash ('/').
+ * @param create If set, saveLocation() will create the directories
+ * needed (including those given by @p suffix).
+ *
+ * @return A path where resources of the specified type should be
+ * saved, or QString::null if the resource type is unknown.
+ */
+ QString saveLocation(const char *type,
+ const QString& suffix = QString::null,
+ bool create = true) const;
+
+ /**
+ * Converts an absolute path to a path relative to a certain
+ * resource.
+ *
+ * If "abs = ::locate(resource, rel)"
+ * then "rel = relativeLocation(resource, abs)" and vice versa.
+ *
+ * @param type The type of resource.
+ *
+ * @param absPath An absolute path to make relative.
+ *
+ * @return A relative path relative to resource @p type that
+ * will find @p absPath. If no such relative path exists, absPath
+ * will be returned unchanged.
+ */
+ QString relativeLocation(const char *type, const QString &absPath);
+
+ /**
+ * Recursively creates still-missing directories in the given path.
+ *
+ * The resulting permissions will depend on the current umask setting.
+ * permission = mode & ~umask.
+ *
+ * @param dir Absolute path of the directory to be made.
+ * @param mode Directory permissions.
+ * @return true if successful, false otherwise
+ */
+ static bool makeDir(const QString& dir, int mode = 0755);
+
+ /**
+ * This returns a default relative path for the standard KDE
+ * resource types. Below is a list of them so you get an idea
+ * of what this is all about.
+ *
+ * @li data - share/apps
+ * @li html - share/doc/HTML
+ * @li icon - share/icon
+ * @li config - share/config
+ * @li pixmap - share/pixmaps
+ * @li apps - share/applnk
+ * @li sound - share/sounds
+ * @li locale - share/locale
+ * @li services - share/services
+ * @li servicetypes - share/servicetypes
+ * @li mime - share/mimelnk
+ * @li wallpaper - share/wallpapers
+ * @li templates - share/templates
+ * @li exe - bin
+ * @li lib - lib
+ *
+ * @returns Static default for the specified resource. You
+ * should probably be using locate() or locateLocal()
+ * instead.
+ * @see locate()
+ * @see locateLocal()
+ */
+ static QString kde_default(const char *type);
+
+ /**
+ * @internal (for use by sycoca only)
+ */
+ QString kfsstnd_prefixes();
+
+ /**
+ * Returns the toplevel directory in which KStandardDirs
+ * will store things. Most likely $HOME/.kde
+ * Don't use this function if you can use locateLocal
+ * @return the toplevel directory
+ */
+ QString localkdedir() const;
+
+ /**
+ * @return $XDG_DATA_HOME
+ * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html
+ */
+ QString localxdgdatadir() const;
+
+ /**
+ * @return $XDG_CONFIG_HOME
+ * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html
+ */
+ QString localxdgconfdir() const;
+
+ /**
+ * Checks for existence and accessability.
+ * Faster than creating a QFileInfo first.
+ * @param fullPath the path to check
+ * @return true if the directory exists
+ */
+ static bool exists(const QString &fullPath);
+
+ /**
+ * Expands all symbolic links and resolves references to
+ * '/./', '/../' and extra '/' characters in @p dirname
+ * and returns the canonicalized absolute pathname.
+ * The resulting path will have no symbolic link, '/./'
+ * or '/../' components.
+ * @since 3.1
+ */
+ static QString realPath(const QString &dirname);
+
+ static void setAppDir( const QString & );
+ static QString appDir();
+
+ private:
+
+ QStringList prefixes;
+
+ // Directory dictionaries
+ QDict<QStringList> absolutes;
+ QDict<QStringList> relatives;
+
+ mutable QDict<QStringList> dircache;
+ mutable QDict<QString> savelocations;
+
+ // Disallow assignment and copy-construction
+ KStandardDirs( const KStandardDirs& );
+ KStandardDirs& operator= ( const KStandardDirs& );
+
+ bool addedCustoms;
+
+ class KStandardDirsPrivate;
+ KStandardDirsPrivate *d;
+//US
+ static QString mAppDir;
+
+ void checkConfig() const;
+ void applyDataRestrictions(const QString &) const;
+//US void createSpecialResource(const char*);
+};
+
+/**
+ * \addtogroup locates Locate Functions
+ * @{
+ * On The Usage Of 'locate' and 'locateLocal'
+ *
+ * Typical KDE applications use resource files in one out of
+ * three ways:
+ *
+ * 1) A resource file is read but is never written. A system
+ * default is supplied but the user can override this
+ * default in his local .kde directory:
+ *
+ * \code
+ * // Code example
+ * myFile = locate("appdata", "groups.lst");
+ * myData = myReadGroups(myFile); // myFile may be null
+ * \endcode
+ *
+ * 2) A resource file is read and written. If the user has no
+ * local version of the file the system default is used.
+ * The resource file is always written to the users local
+ * .kde directory.
+ *
+ * \code
+ * // Code example
+ * myFile = locate("appdata", "groups.lst")
+ * myData = myReadGroups(myFile);
+ * ...
+ * doSomething(myData);
+ * ...
+ * myFile = locateLocal("appdata", "groups.lst");
+ * myWriteGroups(myFile, myData);
+ * \endcode
+ *
+ * 3) A resource file is read and written. No system default
+ * is used if the user has no local version of the file.
+ * The resource file is always written to the users local
+ * .kde directory.
+ *
+ * \code
+ * // Code example
+ * myFile = locateLocal("appdata", "groups.lst");
+ * myData = myReadGroups(myFile);
+ * ...
+ * doSomething(myData);
+ * ...
+ * myFile = locateLocal("appdata", "groups.lst");
+ * myWriteGroups(myFile, myData);
+ * \endcode
+ **/
+
+/*!
+ * \relates KStandardDirs
+ * This function is just for convenience. It simply calls
+ *instance->dirs()->\link KStandardDirs::findResource() findResource\endlink(type, filename).
+ **/
+QString locate( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance()*/ );
+
+/*!
+ * \relates KStandardDirs
+ * This function is much like locate. However it returns a
+ * filename suitable for writing to. No check is made if the
+ * specified filename actually exists. Missing directories
+ * are created. If filename is only a directory, without a
+ * specific file, filename must have a trailing slash.
+ *
+ **/
+QString locateLocal( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance() */ );
+
+/*!
+ * \relates KStandardDirs
+ * This function is much like locate. No check is made if the
+ * specified filename actually exists. Missing directories
+ * are created if @p createDir is true. If filename is only
+ * a directory, without a specific file,
+ * filename must have a trailing slash.
+ *
+ **/
+QString locateLocal( const char *type, const QString& filename, bool createDir /*US , const KInstance* instance = KGlobal::instance() */);
+
+/*! @} */
+
+#endif // SSK_KSTDDIRS_H
diff --git a/microkde/kdecore/kstringhandler.cpp b/microkde/kdecore/kstringhandler.cpp
new file mode 100644
index 0000000..b737e97
--- a/dev/null
+++ b/microkde/kdecore/kstringhandler.cpp
@@ -0,0 +1,650 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Ian Zepp (icszepp@islc.net)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+/* AIX needs strings.h for str*casecmp(), and our config.h loads it on AIX
+ So we don't need to include strings.h explicitly */
+
+//US #include "config.h"
+
+#include "kstringhandler.h"
+/*US
+QString KStringHandler::word( const QString &text , uint pos )
+{
+ QStringList list = QStringList::split( " ", text , true );
+
+ if ( pos < list.count() )
+ return list[ pos ];
+
+ return "";
+}
+
+QString KStringHandler::word( const QString &text , const char *range )
+{
+ // Format in: START:END
+ // Note index starts a 0 (zero)
+ //
+ // 0: first word to end
+ // 1:3 second to fourth words
+ QStringList list = QStringList::split( " ", text , true );
+ QString tmp = "";
+ QString r = range;
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ // do stuff here
+ QRegExp reg;
+
+ int at = 0;
+ int pos = 0;
+ int cnt = 0;
+
+ if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 )
+ {
+ at = r.find(":");
+ pos = atoi( r.left(at).ascii() );
+ cnt = atoi( r.remove(0,at+1).ascii() );
+ }
+ else if ( r.find(QRegExp(":+[0-9]+")) != -1 )
+ {
+ at = r.find(":");
+ pos = 0;
+ cnt = atoi( r.remove(0,at+1).ascii() );
+ }
+ else if ( r.find(QRegExp("[0-9]+:+")) != -1 )
+ {
+ at = r.find(":");
+ pos = atoi( r.left(at).ascii() );
+ cnt = list.count(); // zero index
+ }
+ else if ( r.find(QRegExp("[0-9]+")) != -1 )
+ {
+ pos = atoi( r.ascii() );
+ cnt = pos;
+ }
+ else
+ {
+ return tmp; // not found/implemented
+ }
+
+ //
+ // Extract words
+ //
+ int wordsToExtract = cnt-pos+1;
+ QStringList::Iterator it = list.at( pos);
+
+ while ( (it != list.end()) && (wordsToExtract-- > 0))
+ {
+ tmp += *it;
+ tmp += " ";
+ it++;
+ }
+
+ return tmp.stripWhiteSpace();
+}
+
+//
+// Insertion and removal routines
+//
+QString KStringHandler::insword( const QString &text , const QString &word , uint pos )
+{
+ if ( text.isEmpty() )
+ return word;
+
+ if ( word.isEmpty() )
+ return text;
+
+ // Split words and add into list
+ QStringList list = QStringList::split( " ", text, true );
+
+ if ( pos >= list.count() )
+ list.append( word );
+ else
+ list.insert( list.at(pos) , word );
+
+ // Rejoin
+ return list.join( " " );
+}
+
+QString KStringHandler::setword( const QString &text , const QString &word , uint pos )
+{
+ if ( text.isEmpty() )
+ return word;
+
+ if ( word.isEmpty() )
+ return text;
+
+ // Split words and add into list
+ QStringList list = QStringList::split( " ", text, true );
+
+ if ( pos >= list.count() )
+ list.append( word );
+ else
+ {
+ list.insert( list.remove( list.at(pos) ) , word );
+ }
+
+ // Rejoin
+ return list.join( " " );
+}
+
+QString KStringHandler::remrange( const QString &text , const char *range )
+{
+ // Format in: START:END
+ // Note index starts a 0 (zero)
+ //
+ // 0: first word to end
+ // 1:3 second to fourth words
+ QStringList list = QStringList::split( " ", text , true );
+ QString tmp = "";
+ QString r = range;
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ // do stuff here
+ QRegExp reg;
+
+ int at = 0;
+ int pos = 0;
+ int cnt = 0;
+
+ if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 )
+ {
+ at = r.find(':');
+ pos = atoi( r.left(at).ascii() );
+ cnt = atoi( r.remove(0,at+1).ascii() );
+ }
+ else if ( r.find(QRegExp(":+[0-9]+")) != -1 )
+ {
+ at = r.find(':');
+ pos = 0;
+ cnt = atoi( r.remove(0,at+1).ascii() );
+ }
+ else if ( r.find(QRegExp("[0-9]+:+")) != -1 )
+ {
+ at = r.find(':');
+ pos = atoi( r.left(at).ascii() );
+ cnt = list.count(); // zero index
+ }
+ else if ( r.find(QRegExp("[0-9]+")) != -1 )
+ {
+ pos = atoi( r.ascii() );
+ cnt = pos;
+ }
+ else
+ {
+ return text; // not found/implemented
+ }
+
+ //
+ // Remove that range of words
+ //
+ int wordsToDelete = cnt-pos+1;
+ QStringList::Iterator it = list.at( pos);
+
+ while ( (it != list.end()) && (wordsToDelete-- > 0))
+ it = list.remove( it );
+
+ return list.join( " " );
+}
+
+QString KStringHandler::remword( const QString &text , uint pos )
+{
+ QString tmp = "";
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ // Split words and add into list
+ QStringList list = QStringList::split( " ", text, true );
+
+ if ( pos < list.count() )
+ list.remove( list.at( pos ) );
+
+ // Rejoin
+ return list.join( " " );
+}
+
+QString KStringHandler::remword( const QString &text , const QString &word )
+{
+ QString tmp = "";
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ if ( word.isEmpty() )
+ return text;
+
+ // Split words and add into list
+ QStringList list = QStringList::split( " ", text, true );
+
+ QStringList::Iterator it = list.find(word);
+
+ if (it != list.end())
+ list.remove( it );
+
+ // Rejoin
+ return list.join( " " );
+}
+
+//
+// Capitalization routines
+//
+QString KStringHandler::capwords( const QString &text )
+{
+ QString tmp = "";
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ QStringList list = QStringList::split( " ", text, true );
+
+ return capwords( QStringList::split( " ", text, true )).join( " " );
+}
+
+QStringList KStringHandler::capwords( const QStringList &list )
+{
+ QStringList tmp;
+ QString word;
+
+ if ( list.count() == 0 )
+ return tmp;
+
+ for ( QStringList::ConstIterator it= list.begin();
+ it != list.end();
+ it++)
+ {
+ word = *it;
+ word = word.left(1).upper() + word.remove(0,1);
+
+ tmp.append( word ); // blank list to start with
+ }
+
+ return tmp;
+}
+
+//
+// Reverse routines
+//
+QString KStringHandler::reverse( const QString &text )
+{
+ QString tmp;
+
+ if ( text.isEmpty() )
+ return tmp;
+
+ QStringList list;
+ list = QStringList::split( " ", text, true );
+ list = reverse( list );
+
+ return list.join( " " );
+}
+
+QStringList KStringHandler::reverse( const QStringList &list )
+{
+ QStringList tmp;
+
+ if ( list.count() == 0 )
+ return tmp;
+
+ for ( QStringList::ConstIterator it= list.begin();
+ it != list.end();
+ it++)
+ tmp.prepend( *it );
+
+ return tmp;
+}
+
+//
+// Left, Right, Center justification
+//
+QString KStringHandler::ljust( const QString &text , uint width )
+{
+ QString tmp = text;
+ tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
+
+ if ( tmp.length() >= width )
+ return tmp;
+
+ for ( uint pos = tmp.length() ; pos < width ; pos++ )
+ tmp.append(" ");
+
+ return tmp;
+}
+
+QString KStringHandler::rjust( const QString &text , uint width )
+{
+ QString tmp = text;
+ tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
+
+ if ( tmp.length() >= width )
+ return tmp;
+
+ for ( uint pos = tmp.length() ; pos < width ; pos++ )
+ tmp.prepend(" ");
+
+ return tmp;
+}
+
+QString KStringHandler::center( const QString &text , uint width )
+{
+ // Center is slightly different, in that it will add
+ // spaces to the RIGHT side (left-justified) before
+ // it adds a space to the LEFT side.
+
+ QString tmp = text;
+ tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
+
+ if ( tmp.length() >= width )
+ return tmp;
+
+ bool left = false; // start at right side.
+
+ for ( uint pos = tmp.length() ; pos < width ; pos++ )
+ {
+ if ( left )
+ tmp.prepend(" ");
+ else
+ tmp.append(" ");
+
+ // Reverse bool
+ left = !left;
+ }
+
+ return tmp;
+}
+
+QString KStringHandler::lsqueeze( const QString & str, uint maxlen )
+{
+ if (str.length() > maxlen) {
+ int part = maxlen-3;
+ return QString("..." + str.right(part));
+ }
+ else return str;
+}
+
+QString KStringHandler::csqueeze( const QString & str, uint maxlen )
+{
+ if (str.length() > maxlen && maxlen > 3) {
+ int part = (maxlen-3)/2;
+ return QString(str.left(part) + "..." + str.right(part));
+ }
+ else return str;
+}
+
+QString KStringHandler::rsqueeze( const QString & str, uint maxlen )
+{
+ if (str.length() > maxlen) {
+ int part = maxlen-3;
+ return QString(str.left(part) + "...");
+ }
+ else return str;
+}
+
+QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen)
+{
+ return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
+}
+
+static inline int emSqueezeLimit(int delta, int min, int max)
+{
+ if (delta < min) return min;
+ if (delta > max) return max;
+ return delta;
+}
+
+QString KStringHandler::lPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
+{
+ uint nameWidth = fontMetrics.width(name);
+
+ if (maxPixels < nameWidth)
+ {
+ QString tmp = name;
+ const uint em = fontMetrics.maxWidth();
+ maxPixels -= fontMetrics.width("...");
+
+ while (maxPixels < nameWidth && !tmp.isEmpty())
+ {
+ int delta = (nameWidth - maxPixels) / em;
+ delta = emSqueezeLimit(delta, 1, delta); // no max
+
+ tmp.remove(0, delta);
+ nameWidth = fontMetrics.width(tmp);
+ }
+
+ return ("..." + tmp);
+ }
+
+ return name;
+}
+
+QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
+{
+ return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
+}
+
+QString KStringHandler::cPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
+{
+ uint nameWidth = fontMetrics.width(name);
+
+ if (maxPixels < nameWidth)
+ {
+ QString tmp = name;
+ const uint em = fontMetrics.maxWidth();
+ maxPixels -= fontMetrics.width("...");
+
+ while (maxPixels < nameWidth && !tmp.isEmpty())
+ {
+ int length = tmp.length();
+ int delta = (nameWidth - maxPixels) / em;
+ delta = emSqueezeLimit(delta, 1, length) ;
+
+ tmp.remove((length / 2) - (delta / 2), delta);
+ nameWidth = fontMetrics.width(tmp);
+ }
+
+ return tmp.insert((tmp.length() + 1) / 2, "...");
+ }
+
+ return name;
+}
+
+QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
+{
+ return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
+}
+
+QString KStringHandler::rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
+{
+ uint nameWidth = fontMetrics.width(name);
+
+ if (maxPixels < nameWidth)
+ {
+ QString tmp = name;
+ const uint em = fontMetrics.maxWidth();
+ maxPixels -= fontMetrics.width("...");
+
+ while (maxPixels < nameWidth && !tmp.isEmpty())
+ {
+ int length = tmp.length();
+ int delta = (nameWidth - maxPixels) / em;
+ delta = emSqueezeLimit(delta, 1, length) ;
+
+ tmp.remove(length - delta, delta);
+ nameWidth = fontMetrics.width(tmp);
+ }
+
+ return (tmp + "...");
+ }
+
+ return name;
+}
+
+///// File name patterns (like *.txt)
+
+bool KStringHandler::matchFileName( const QString& filename, const QString& pattern )
+{
+ int len = filename.length();
+ int pattern_len = pattern.length();
+
+ if (!pattern_len)
+ return false;
+
+ // Patterns like "Makefile*"
+ if ( pattern[ pattern_len - 1 ] == '*' && len + 1 >= pattern_len ) {
+ const QChar *c1 = pattern.unicode();
+ const QChar *c2 = filename.unicode();
+ int cnt = 1;
+ while ( cnt < pattern_len && *c1++ == *c2++ )
+ ++cnt;
+ return cnt == pattern_len;
+ }
+
+ // Patterns like "*~", "*.extension"
+ if ( pattern[ 0 ] == '*' && len + 1 >= pattern_len )
+ {
+ const QChar *c1 = pattern.unicode() + pattern_len - 1;
+ const QChar *c2 = filename.unicode() + len - 1;
+ int cnt = 1;
+ while ( cnt < pattern_len && *c1-- == *c2-- )
+ ++cnt;
+ return cnt == pattern_len;
+ }
+
+ // Patterns like "Makefile"
+ return ( filename == pattern );
+}
+
+ QStringList
+KStringHandler::perlSplit(const QString & sep, const QString & s, uint max)
+{
+ bool ignoreMax = 0 == max;
+
+ QStringList l;
+
+ int searchStart = 0;
+
+ int tokenStart = s.find(sep, searchStart);
+
+ while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
+ {
+ if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
+ l << s.mid(searchStart, tokenStart - searchStart);
+
+ searchStart = tokenStart + sep.length();
+ tokenStart = s.find(sep, searchStart);
+ }
+
+ if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
+ l << s.mid(searchStart, s.length() - searchStart);
+
+ return l;
+}
+
+ QStringList
+KStringHandler::perlSplit(const QChar & sep, const QString & s, uint max)
+{
+ bool ignoreMax = 0 == max;
+
+ QStringList l;
+
+ int searchStart = 0;
+
+ int tokenStart = s.find(sep, searchStart);
+
+ while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
+ {
+ if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
+ l << s.mid(searchStart, tokenStart - searchStart);
+
+ searchStart = tokenStart + 1;
+ tokenStart = s.find(sep, searchStart);
+ }
+
+ if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
+ l << s.mid(searchStart, s.length() - searchStart);
+
+ return l;
+}
+
+ QStringList
+KStringHandler::perlSplit(const QRegExp & sep, const QString & s, uint max)
+{
+ bool ignoreMax = 0 == max;
+
+ QStringList l;
+
+ int searchStart = 0;
+ int tokenStart = sep.search(s, searchStart);
+ int len = sep.matchedLength();
+
+ while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
+ {
+ if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
+ l << s.mid(searchStart, tokenStart - searchStart);
+
+ searchStart = tokenStart + len;
+ tokenStart = sep.search(s, searchStart);
+ len = sep.matchedLength();
+ }
+
+ if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
+ l << s.mid(searchStart, s.length() - searchStart);
+
+ return l;
+}
+US end */
+
+/*US
+ QString
+KStringHandler::tagURLs( const QString& text )
+{
+ QRegExp urlEx("(www\\.(?!\\.)|(f|ht)tp(|s)://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%]+[\\d\\w/]");
+
+ QString richText( text );
+ int urlPos = 0, urlLen;
+ while ((urlPos = urlEx.search(richText, urlPos)) >= 0)
+ {
+ urlLen = urlEx.matchedLength();
+ QString href = richText.mid( urlPos, urlLen );
+ // Qt doesn't support (?<=pattern) so we do it here
+ if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){
+ urlPos++;
+ continue;
+ }
+ // Don't use QString::arg since %01, %20, etc could be in the string
+ QString anchor = "<a href=\"" + href + "\">" + href + "</a>";
+ richText.replace( urlPos, urlLen, anchor );
+
+
+ urlPos += anchor.length();
+ }
+ return richText;
+}
+*/
+QString KStringHandler::obscure( const QString &str )
+{
+ QString result;
+ for ( uint i = 0; i < str.length(); ++i )
+ result += ( str.at( i ).unicode() < 0x20 ) ? str.at( i ) :
+ QChar( 0x1001F - str.at( i ).unicode() );
+
+ return result;
+}
diff --git a/microkde/kdecore/kstringhandler.h b/microkde/kdecore/kstringhandler.h
new file mode 100644
index 0000000..d07b1e2
--- a/dev/null
+++ b/microkde/kdecore/kstringhandler.h
@@ -0,0 +1,417 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1999 Ian Zepp (icszepp@islc.net)
+ Copyright (C) 2000 Rik Hemsley (rikkus) <rik@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+#ifndef KSTRINGHANDLER_H
+#define KSTRINGHANDLER_H
+
+#include <stdlib.h> // for atoi()
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qregexp.h> // for the word ranges
+#include <qfontmetrics.h>
+
+/**
+ * This class contains utility functions for handling strings.
+ *
+ * This class is @em not a substitute for the @ref QString class. What
+ * I tried to do with this class is provide an easy way to
+ * cut/slice/splice words inside sentences in whatever order desired.
+ * While the main focus of this class are words (ie characters
+ * separated by spaces/tabs), the two core functions here (@ref split()
+ * and @ref join() ) will function given any char to use as a separator.
+ * This will make it easy to redefine what a 'word' means in the
+ * future if needed.
+ *
+ * I freely stole some of the function names from python. I also think
+ * some of these were influenced by mIRC (yes, believe it if you will, I
+ * used to write a LOT of scripts in mIRC).
+ *
+ * The ranges are a fairly powerful way of getting/stripping words from
+ * a string. These ranges function, for the large part, as they would in
+ * python. See the @ref word(const QString&, int) and @ref remword(const QString&, int) functions for more detail.
+ *
+ * This class contains no data members of it own. All strings are cut
+ * on the fly and returned as new qstrings/qstringlists.
+ *
+ * Quick example on how to use:
+ *
+ * <pre>
+ * KStringHandler kstr;
+ * QString line = "This is a test of the strings";
+ *
+ * cout << "1> " << kstr.word( line , "4:" ) << "\n";
+ * cout << "2> " << kstr.remrange( line , "2:5" ) << "\n";
+ * cout << "2> " << kstr.reverse( line ) << "\n";
+ * cout << "2> " << kstr.center( kstr.word( line , 4 ) , 15 ) << "\n";
+ * </pre>
+ *
+ * and so forth.
+ *
+ * @short Class for manipulating words and sentences in strings
+ * @author Ian Zepp <icszepp@islc.net>
+ */
+class KStringHandler
+{
+public:
+ /** Returns the nth word in the string if found
+ * Returns a EMPTY (not null) string otherwise.
+ * Note that the FIRST index is 0.
+ * @param text the string to search for the words
+ * @param pos the position of the word to search
+ * @return the word, or an empty string if not found
+ */
+//US static QString word( const QString &text , uint pos );
+
+ /** Returns a range of words from that string.
+ * Ie:
+ * @li "0" returns the very first word
+ * @li "0:" returns the first to the last word
+ * @li "0:3" returns the first to fourth words
+ * @li ":3" returns everything up to the fourth word
+ *
+ * If you grok python, you're set.
+ * @param text the string to search for the words
+ * @param range the words to return (see description)
+ * @return the words, or an empty string if not found
+ */
+//US static QString word( const QString &text , const char *range );
+
+ /** Inserts a word into the string, and returns
+ * a new string with the word included. the first
+ * index is zero (0). If there are not @p pos words in the original
+ * string, the new word will be appended to the end.
+ * @param text the original text
+ * @param word the word to insert
+ * @param pos the position (in words) for the new word
+ * @return the resulting string
+ */
+//US static QString insword( const QString &text , const QString &word , uint pos );
+
+ /** Replaces a word in the string, and returns
+ * a new string with the word included. the first
+ * index is zero (0). If there are not @p pos words in the original
+ * string, the new word will be appended to the end.
+ * @param text the original text
+ * @param word the word to insert
+ * @param pos the position (in words) for the new word
+ * @return the resulting string
+ */
+//US static QString setword( const QString &text , const QString &word , uint pos );
+
+ /** Removes a word or ranges of words from the string,
+ * and returns a new string. The ranges definitions
+ * follow the definitions for the word() function.
+ *
+ * @li "0" removes the very first word
+ * @li "0:" removes the first the the last word
+ * @li "0:3" removes the first to fourth words
+ * @li ":3" removes everything up to the fourth word
+ * @param text the original text
+ * @param range the words to remove (see description)
+ * @return the resulting string
+ */
+//US static QString remrange( const QString &text , const char *range );
+
+
+ /** Removes a word at the given index, and returns a
+ * new string. The first index is zero (0).
+ * @param text the original text
+ * @param pos the position (in words) of thw word to delete
+ * @return the resulting string
+ */
+//US static QString remword( const QString &text , uint pos );
+
+ /** Removes a matching word from the string, and returns
+ * a new string. Note that only ONE match is removed.
+ * @param text the original text
+ * @param word the word to remove
+ * @return the resulting string
+ */
+//US static QString remword( const QString &text , const QString &word );
+
+ /** Capitalizes each word in the string
+ * "hello there" becomes "Hello There" (string)
+ * @param text the text to capitalize
+ * @return the resulting string
+ */
+//US static QString capwords( const QString &text );
+
+ /** Capitalizes each word in the list
+ * [hello, there] becomes [Hello, There] (list)
+ * @param list the list to capitalize
+ * @return the resulting list
+ */
+//US static QStringList capwords( const QStringList &list );
+
+ /** Reverses the order of the words in a string
+ * "hello there" becomes "there hello" (string)
+ * @param text the text to reverse
+ * @return the resulting string
+ */
+//US static QString reverse( const QString &text );
+
+ /** Reverses the order of the words in a list
+ * [hello, there] becomes [there, hello] (list)
+ * @param list the list to reverse
+ * @return the resulting list
+ */
+//US static QStringList reverse( const QStringList &list );
+
+ /** Left-justifies a string and returns a string at least 'width' characters
+ * wide.
+ * If the string is longer than the @p width, the original
+ * string is returned. It is never truncated.
+ * @param text the text to justify
+ * @param width the desired width of the new string
+ * @return the resulting string
+ */
+//US static QString ljust( const QString &text , uint width );
+
+ /** Right-justifies a string and returns a string at least 'width' characters
+ * wide.
+ * If the string is longer than the @p width, the original
+ * string is returned. It is never truncated.
+ * @param text the text to justify
+ * @param width the desired width of the new string
+ * @return the resulting string
+ */
+//US static QString rjust( const QString &text , uint width );
+
+ /** Centers a string and returns a string at least 'width' characters
+ * wide.
+ * If the string is longer than the @p width, the original
+ * string is returned. It is never truncated.
+ * @param text the text to justify
+ * @param width the desired width of the new string
+ * @return the resulting string
+ */
+//US static QString center( const QString &text , uint width );
+
+ /** Substitute characters at the beginning of a string by "...".
+ * @param str is the string to modify
+ * @param maxlen is the maximum length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ */
+//US static QString lsqueeze( const QString & str, uint maxlen = 40 );
+
+ /** Substitute characters at the beginning of a string by "...". Similar to
+ * method above, except that it truncates based on pixel width rather than
+ * the number of characters
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxlen is the maximum length in ems the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString lEmSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxlen = 30 );
+
+ /** Substitute characters at the beginning of a string by "...". Similar to
+ * method above, except that maxlen is the width in pixels to truncate to
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxPixels is the maximum pixel length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString lPixelSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxPixels );
+
+ /** Substitute characters at the middle of a string by "...".
+ * @param str is the string to modify
+ * @param maxlen is the maximum length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ */
+//US static QString csqueeze( const QString & str, uint maxlen = 40 );
+
+ /** Substitute characters in the middle of a string by "...". Similar to
+ * method above, except that it truncates based on pixel width rather than
+ * the number of characters
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxlen is the maximum length in ems the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString cEmSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxlen = 30 );
+
+ /** Substitute characters in the middle of a string by "...". Similar to
+ * method above, except that maxlen is the width in pixels to truncate to
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxPixels is the maximum pixel length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString cPixelSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxPixels );
+
+ /** Substitute characters at the end of a string by "...".
+ * @param str is the string to modify
+ * @param maxlen is the maximum length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ */
+ static QString rsqueeze( const QString & str, uint maxlen = 40 );
+
+ /** Substitute characters at the end of a string by "...". Similar to
+ * method above, except that it truncates based on pixel width rather than
+ * the number of characters
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxlen is the maximum length in ems the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString rEmSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxlen = 30 );
+
+ /** Substitute characters at the end of a string by "...". Similar to
+ * method above, except that maxlen is the width in pixels to truncate to
+ * @param name is the string to modify
+ * @param fontMetrics is the font metrics to use to calculate character sizes
+ * @param maxPixels is the maximum pixel length the modified string will have
+ * If the original string is shorter than "maxlen", it is returned verbatim
+ * @return the modified string
+ * @since 3.2
+ */
+//US static QString rPixelSqueeze( const QString & name,
+//US const QFontMetrics& fontMetrics,
+//US uint maxPixels );
+
+ /**
+ * Match a filename.
+ * @param filename is the real decoded filename (or dirname
+ * without trailing '/').
+ * @param pattern is a pattern like *.txt, *.tar.gz, Makefile.*, etc.
+ * Patterns with two asterisks like "*.*pk" are not supported.
+ * @return true if the given filename matches the given pattern
+ */
+//US static bool matchFileName( const QString& filename, const QString& pattern );
+
+ /**
+ * Split a QString into a QStringList in a similar fashion to the static
+ * QStringList function in Qt, except you can specify a maximum number
+ * of tokens. If max is specified (!= 0) then only that number of tokens
+ * will be extracted. The final token will be the remainder of the string.
+ *
+ * Example:
+ * <pre>
+ * perlSplit("__", "some__string__for__you__here", 4)
+ * QStringList contains: "some", "string", "for", "you__here"
+ * </pre>
+ *
+ * @param sep is the string to use to delimit s.
+ * @param s is the input string
+ * @param max is the maximum number of extractions to perform, or 0.
+ * @return A QStringList containing tokens extracted from s.
+ */
+//US static QStringList perlSplit
+//US (const QString & sep, const QString & s, uint max = 0);
+
+ /**
+ * Split a QString into a QStringList in a similar fashion to the static
+ * QStringList function in Qt, except you can specify a maximum number
+ * of tokens. If max is specified (!= 0) then only that number of tokens
+ * will be extracted. The final token will be the remainder of the string.
+ *
+ * Example:
+ * <pre>
+ * perlSplit(' ', "kparts reaches the parts other parts can't", 3)
+ * QStringList contains: "kparts", "reaches", "the parts other parts can't"
+ * </pre>
+ *
+ * @param sep is the character to use to delimit s.
+ * @param s is the input string
+ * @param max is the maximum number of extractions to perform, or 0.
+ * @return A QStringList containing tokens extracted from s.
+ */
+//US static QStringList perlSplit
+//US (const QChar & sep, const QString & s, uint max = 0);
+
+ /**
+ * Split a QString into a QStringList in a similar fashion to the static
+ * QStringList function in Qt, except you can specify a maximum number
+ * of tokens. If max is specified (!= 0) then only that number of tokens
+ * will be extracted. The final token will be the remainder of the string.
+ *
+ * Example:
+ * <pre>
+ * perlSplit(QRegExp("[! ]", "Split me up ! I'm bored ! OK ?", 3)
+ * QStringList contains: "Split", "me", "up ! I'm bored, OK ?"
+ * </pre>
+ *
+ * @param sep is the regular expression to use to delimit s.
+ * @param s is the input string
+ * @param max is the maximum number of extractions to perform, or 0.
+ * @return A QStringList containing tokens extracted from s.
+ */
+//US static QStringList perlSplit
+//US (const QRegExp & sep, const QString & s, uint max = 0);
+
+ /**
+ * This method auto-detects URLs in strings, and adds HTML markup to them
+ * so that richtext or HTML-enabled widgets (such as KActiveLabel)
+ * will display the URL correctly.
+ * @param text the string which may contain URLs
+ * @return the resulting text
+ * @since 3.1
+ */
+//US static QString tagURLs( const QString& text );
+
+ /**
+ Obscure string by using a simple symmetric encryption. Applying the
+ function to a string obscured by this function will result in the original
+ string.
+
+ The function can be used to obscure passwords stored to configuration
+ files. Note that this won't give you any more security than preventing
+ that the password is directly copied and pasted.
+
+ @param str string to be obscured
+ @return obscured string
+ @since 3.2
+ */
+ static QString obscure( const QString &str );
+
+#ifdef KDE_NO_COMPAT
+private:
+#endif
+ /**
+ * @deprecated Use @see matchFileName () instead.
+ */
+/*US static bool matchFilename( const QString& filename, const QString& pattern )
+ {
+ return matchFileName (filename, pattern);
+ };
+*/
+};
+#endif