summaryrefslogtreecommitdiffabout
path: root/microkde/kdecore
Unidiff
Diffstat (limited to 'microkde/kdecore') (more/less context) (show 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 @@
1/* This file is part of the KDE libraries
2 Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20//US #include <config.h>
21
22#include <qfile.h>
23
24#include <kdebug.h>
25
26#include "kcatalogue.h"
27
28char *k_nl_find_msg(struct kde_loaded_l10nfile *domain_file,
29 const char *msgid);
30void k_nl_unload_domain (struct loaded_domain *domain);
31
32#ifndef KDE_USE_FINAL // with --enable-final, we're getting this from libintl.cpp
33struct kde_loaded_l10nfile
34{
35 const char *filename;
36 int decided;
37
38 const void *data;
39
40 kde_loaded_l10nfile() : filename(0), decided(0), data(0) {}
41};
42#endif
43
44class KCataloguePrivate
45{
46public:
47 QString name;
48
49 kde_loaded_l10nfile domain;
50};
51
52KCatalogue::KCatalogue(const QString & name)
53 : d( new KCataloguePrivate )
54{
55 d->name = name;
56}
57
58KCatalogue::KCatalogue(const KCatalogue & rhs)
59 : d( new KCataloguePrivate )
60{
61 *this = rhs;
62}
63
64KCatalogue & KCatalogue::operator=(const KCatalogue & rhs)
65{
66 d->name = rhs.d->name;
67 setFileName( rhs.fileName() );
68
69 return *this;
70}
71
72KCatalogue::~KCatalogue()
73{
74 doUnload();
75
76 delete d;
77}
78
79QString KCatalogue::name() const
80{
81 return d->name;
82}
83
84void KCatalogue::setFileName( const QString & fileName )
85{
86 // nothing to do if the file name is already the same
87 if ( this->fileName() == fileName ) return;
88
89 doUnload();
90
91 QCString newFileName = QFile::encodeName( fileName );
92
93 if ( !fileName.isEmpty() )
94 {
95 // set file name
96 char *filename = new char[ newFileName.length() + 1 ];
97 ::qstrcpy( filename, newFileName );
98 d->domain.filename = filename;
99 }
100}
101
102QString KCatalogue::fileName() const
103{
104 return QFile::decodeName( d->domain.filename );
105}
106
107const char * KCatalogue::translate(const char * msgid) const
108{
109 qDebug("KCatalogue::translate has to be fixed %s",msgid );
110//US return ::k_nl_find_msg( &d->domain, msgid );
111 return msgid;
112
113}
114
115void KCatalogue::doUnload()
116{
117 // use gettext's unloader
118 if ( d->domain.data )
119 {
120//US ::k_nl_unload_domain( (struct loaded_domain *)d->domain.data );
121 qDebug("KCatalogue::doUnload has to be fixed" );
122
123 }
124 d->domain.data = 0;
125
126 // free name
127 delete [] const_cast<char *>(d->domain.filename);
128 d->domain.filename = 0;
129
130 d->domain.decided = 0;
131}
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 @@
1/* This file is part of the KDE libraries
2 Copyright (c) 2001 Hans Petter Bieker <bieker@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#ifndef KCATALOGUE_H
21#define KCATALOGUE_H
22
23#include <qstring.h>
24
25struct kde_loaded_l10nfile;
26
27class KCataloguePrivate;
28
29/**
30 * This class abstracts a gettext message catalogue. It will take care of
31 * opening the file and reading the catalogue.
32 *
33 * @see KLocale
34 */
35//REVISED: hausmann
36class KCatalogue
37{
38public:
39 /**
40 * Constructor.
41 *
42 * @param name The name of the catalogue
43 */
44 explicit KCatalogue(const QString & name = QString::null);
45
46 /**
47 * Copy constructor.
48 */
49 KCatalogue(const KCatalogue & rhs);
50
51 /**
52 * Assignment operator.
53 */
54 KCatalogue & operator = ( const KCatalogue & rhs);
55
56 /**
57 * Destructor.
58 */
59 virtual ~KCatalogue();
60
61 /**
62 * Returns the name of the catalogue.
63 *
64 * @return The name of the catalogue
65 */
66 QString name() const;
67
68 /**
69 * Changes the current file name.
70 *
71 * @param fileName The new file name
72 */
73
74 void setFileName( const QString & fileName );
75
76 /**
77 * Retrieves a translation of the specified message id.
78 *
79 * Do not pass 0 or "" strings as message ids.
80 *
81 * @param msgid The message id
82 *
83 * @return The translated message, in utf8 encoding, or 0 if not found
84 */
85 const char * translate( const char * msgid ) const;
86
87private:
88 /**
89 * @internal Retrieves the current file name.
90 *
91 * @return The current file name, if any.
92 */
93 QString fileName() const;
94
95 /**
96 * @internal Unloads the current file.
97 */
98 void doUnload();
99
100private:
101 KCataloguePrivate * d;
102};
103
104#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 @@
1/*
2 This file is part of the KDE libraries
3 Copyright (c) 1999 Preston Brown <pbrown@kde.org>
4 Copyright (c) 1997 Matthias Kalle Dalheimer <kalle@kde.org>
5 Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21*/
22
23// $Id$
24
25#ifndef _KCONFIGBASE_H
26#define _KCONFIGBASE_H
27
28#include "kconfig.h"
29
30/**
31 * Helper class to facilitate working with @ref KConfig / @ref KSimpleConfig
32 * groups.
33 *
34 * Careful programmers always set the group of a
35 * @ref KConfig @ref KSimpleConfig object to the group they want to read from
36 * and set it back to the old one of afterwards. This is usually
37 * written as:
38 * <pre>
39 *
40 * QString oldgroup config->group();
41 * config->setGroup( "TheGroupThatIWant" );
42 * ...
43 * config->writeEntry( "Blah", "Blubb" );
44 *
45 * config->setGroup( oldgroup );
46 * </pre>
47 *
48 * In order to facilitate this task, you can use
49 * KConfigGroupSaver. Simply construct such an object ON THE STACK
50 * when you want to switch to a new group. Then, when the object goes
51 * out of scope, the group will automatically be restored. If you
52 * want to use several different groups within a function or method,
53 * you can still use KConfigGroupSaver: Simply enclose all work with
54 * one group (including the creation of the KConfigGroupSaver object)
55 * in one block.
56 *
57 * @author Matthias Kalle Dalheimer <kalle@kde.org>
58 * @version $Id$
59 * @see KConfigBase, KConfig, KSimpleConfig
60 * @short Helper class for easier use of KConfig/KSimpleConfig groups
61 */
62//US I converted the class in a way that it can be used with KConfig objects of microkde
63
64class KConfigGroupSaver
65{
66public:
67 /**
68 * Constructor. You pass a pointer to the KConfigBase-derived
69 * object you want to work with and a string indicating the _new_
70 * group.
71 *
72 * @param config The KConfigBase-derived object this
73 * KConfigGroupSaver works on.
74 * @param group The new group that the config object should switch to.
75 */
76 KConfigGroupSaver( KConfig* config, QString group )
77 /* KDE 4 : make the second parameter const QString & */
78 : _config(config), _oldgroup(config->group())
79 { _config->setGroup( group ); }
80
81 KConfigGroupSaver( KConfig* config, const char *group )
82 : _config(config), _oldgroup(config->group())
83 { _config->setGroup( group ); }
84
85 KConfigGroupSaver( KConfig* config, const QCString &group )
86 : _config(config), _oldgroup(config->group())
87 { _config->setGroup( group ); }
88
89 ~KConfigGroupSaver() { _config->setGroup( _oldgroup ); }
90
91 KConfig* config() { return _config; };
92
93private:
94 KConfig* _config;
95 QString _oldgroup;
96
97 KConfigGroupSaver(const KConfigGroupSaver&);
98 KConfigGroupSaver& operator=(const KConfigGroupSaver&);
99
100};
101
102#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Torben Weis <weis@kde.org>
3 Copyright (C) 2000 Michael Matz <matz@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19//US #include <config.h>
20#include <qclipboard.h>
21#include <qfile.h>
22#include <qtimer.h>
23#include <qobjectdict.h>
24#include <qwidgetlist.h>
25#include <qwidget.h>
26
27#include "kapplication.h"
28#include "klibloader.h"
29#include "kstandarddirs.h"
30#include "kdebug.h"
31#include "klocale.h"
32
33//US #include "ltdl.h"
34
35//US do everything through qlibrary
36#ifndef DESKTOP_VERSION
37#include <qpe/qpeapplication.h>
38#include <qtopia/qlibrary.h>
39#endif
40
41/*US
42#ifdef Q_WS_X11
43#include <X11/Xlib.h>
44#include <X11/Xatom.h>
45#endif
46*/
47template class QAsciiDict<KLibrary>;
48
49#include <stdlib.h> //getenv
50
51/*US
52#if HAVE_DLFCN_H
53# include <dlfcn.h>
54#endif
55
56#ifdef RTLD_GLOBAL
57# define LT_GLOBAL RTLD_GLOBAL
58#else
59# ifdef DL_GLOBAL
60# define LT_GLOBAL DL_GLOBAL
61# endif
62#endif
63#ifndef LT_GLOBAL
64# define LT_GLOBAL 0
65#endif
66*/
67
68/*US
69extern "C" {
70extern int lt_dlopen_flag;
71}
72*/
73
74KLibFactory::KLibFactory( QObject* parent, const char* name )
75 : QObject( parent, name )
76{
77}
78
79KLibFactory::~KLibFactory()
80{
81// kdDebug(150) << "Deleting KLibFactory " << this << endl;
82}
83
84QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args )
85{
86 QObject* obj = createObject( parent, name, classname, args );
87 if ( obj )
88 emit objectCreated( obj );
89 return obj;
90}
91
92
93QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &)
94{
95 return 0;
96}
97
98
99// -----------------------------------------------
100
101//US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle )
102KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle )
103{
104 /* Make sure, we have a KLibLoader */
105 (void) KLibLoader::self();
106 m_libname = libname;
107 m_filename = filename;
108 m_handle = handle;
109 m_factory = 0;
110 m_timer = 0;
111}
112
113KLibrary::~KLibrary()
114{
115// kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl;
116 if ( m_timer && m_timer->isActive() )
117 m_timer->stop();
118
119 // If any object is remaining, delete
120 if ( m_objs.count() > 0 )
121 {
122 QPtrListIterator<QObject> it( m_objs );
123 for ( ; it.current() ; ++it )
124 {
125 kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl;
126 disconnect( it.current(), SIGNAL( destroyed() ),
127 this, SLOT( slotObjectDestroyed() ) );
128 }
129 m_objs.setAutoDelete(true);
130 m_objs.clear();
131 }
132
133 if ( m_factory ) {
134 //kdDebug(150) << " ... deleting the factory " << m_factory << endl;
135 delete m_factory;
136 }
137}
138
139QString KLibrary::name() const
140{
141 return m_libname;
142}
143
144QString KLibrary::fileName() const
145{
146 return m_filename;
147}
148
149KLibFactory* KLibrary::factory()
150{
151 if ( m_factory )
152 return m_factory;
153
154 QCString symname;
155 symname.sprintf("init_%s", name().latin1() );
156
157 void* sym = symbol( symname );
158 if ( !sym )
159 {
160 kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl;
161 return 0;
162 }
163
164 typedef KLibFactory* (*t_func)();
165 t_func func = (t_func)sym;
166 m_factory = func();
167
168 if( !m_factory )
169 {
170 kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl;
171 return 0;
172 }
173
174 connect( m_factory, SIGNAL( objectCreated( QObject * ) ),
175 this, SLOT( slotObjectCreated( QObject * ) ) );
176
177 return m_factory;
178}
179
180void* KLibrary::symbol( const char* symname ) const
181{
182//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
183 void* sym = m_handle->resolve( symname );
184 if ( !sym )
185 {
186//US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl;
187 kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl;
188 return 0;
189 }
190
191 return sym;
192}
193
194bool KLibrary::hasSymbol( const char* symname ) const
195{
196//US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname );
197 void* sym = m_handle->resolve( symname );
198 return (sym != 0L );
199}
200
201void KLibrary::unload() const
202{
203 if (KLibLoader::s_self)
204 KLibLoader::s_self->unloadLibrary(QFile::encodeName(name()));
205}
206
207void KLibrary::slotObjectCreated( QObject *obj )
208{
209 if ( !obj )
210 return;
211
212 if ( m_timer && m_timer->isActive() )
213 m_timer->stop();
214
215 if ( m_objs.containsRef( obj ) )
216 return; // we know this object already
217
218 connect( obj, SIGNAL( destroyed() ),
219 this, SLOT( slotObjectDestroyed() ) );
220
221 m_objs.append( obj );
222}
223
224void KLibrary::slotObjectDestroyed()
225{
226 m_objs.removeRef( sender() );
227
228 if ( m_objs.count() == 0 )
229 {
230// kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!"
231// << endl;
232
233 if ( !m_timer )
234 {
235 m_timer = new QTimer( this, "klibrary_shutdown_timer" );
236 connect( m_timer, SIGNAL( timeout() ),
237 this, SLOT( slotTimeout() ) );
238 }
239
240 // as long as it's not stable make the timeout short, for debugging
241 // pleasure (matz)
242 //m_timer->start( 1000*60, true );
243 m_timer->start( 1000*10, true );
244 }
245}
246
247void KLibrary::slotTimeout()
248{
249 if ( m_objs.count() != 0 )
250 return;
251
252 /* Don't go through KLibLoader::unloadLibrary(), because that uses the
253 ref counter, but this timeout means to unconditionally close this library
254 The destroyed() signal will take care to remove us from all lists.
255 */
256 delete this;
257}
258
259// -------------------------------------------------
260
261/* This helper class is needed, because KLibraries can go away without
262 being unloaded. So we need some info about KLibraries even after its
263 death. */
264class KLibWrapPrivate
265{
266public:
267//US KLibWrapPrivate(KLibrary *l, lt_dlhandle h);
268 KLibWrapPrivate(KLibrary *l, QLibrary* h);
269
270 KLibrary *lib;
271 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
272 int ref_count;
273//US lt_dlhandle handle;
274 QLibrary *handle;
275 QString name;
276 QString filename;
277};
278
279//US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h)
280KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h)
281 : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName())
282{
283 unload_mode = UNKNOWN;
284/*US
285 if (lt_dlsym(handle, "__kde_do_not_unload") != 0) {
286// kdDebug(150) << "Will not unload " << name << endl;
287 unload_mode = DONT_UNLOAD;
288 } else if (lt_dlsym(handle, "__kde_do_unload") != 0) {
289 unload_mode = UNLOAD;
290 }
291*/
292//US use instead:
293 if (h->resolve("__kde_do_not_unload") != 0) {
294// kdDebug(150) << "Will not unload " << name << endl;
295 unload_mode = DONT_UNLOAD;
296 } else if (h->resolve("__kde_do_unload") != 0) {
297 unload_mode = UNLOAD;
298 }
299}
300
301class KLibLoaderPrivate
302{
303public:
304 QPtrList<KLibWrapPrivate> loaded_stack;
305 QPtrList<KLibWrapPrivate> pending_close;
306 enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode;
307
308 QString errorMessage;
309};
310
311KLibLoader* KLibLoader::s_self = 0;
312
313KLibLoader* KLibLoader::self()
314{
315 if ( !s_self )
316 s_self = new KLibLoader;
317 return s_self;
318}
319
320void KLibLoader::cleanUp()
321{
322 if ( !s_self )
323 return;
324
325 delete s_self;
326 s_self = 0;
327}
328
329KLibLoader::KLibLoader( QObject* parent, const char* name )
330 : QObject( parent, name )
331{
332 s_self = this;
333 d = new KLibLoaderPrivate;
334//US lt_dlinit();
335 d->unload_mode = KLibLoaderPrivate::UNKNOWN;
336 if (getenv("KDE_NOUNLOAD") != 0)
337 d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD;
338 else if (getenv("KDE_DOUNLOAD") != 0)
339 d->unload_mode = KLibLoaderPrivate::UNLOAD;
340 d->loaded_stack.setAutoDelete( true );
341}
342
343KLibLoader::~KLibLoader()
344{
345// kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl;
346
347 QAsciiDictIterator<KLibWrapPrivate> it( m_libs );
348 for (; it.current(); ++it )
349 {
350 kdDebug(150) << "The KLibLoader contains the library " << it.current()->name
351 << " (" << it.current()->lib << ")" << endl;
352 d->pending_close.append(it.current());
353 }
354
355 close_pending(0);
356
357 delete d;
358}
359
360//static
361QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ )
362{
363 QCString libname( name );
364
365 // only append ".la" if there is no extension
366 // this allows to load non-libtool libraries as well
367 // (mhk, 20000228)
368 int pos = libname.findRev('/');
369 if (pos < 0)
370 pos = 0;
371 if (libname.find('.', pos) < 0)
372 libname += ".la";
373
374 // only look up the file if it is not an absolute filename
375 // (mhk, 20000228)
376 QString libfile;
377 if (libname[0] == '/')
378 libfile = libname;
379 else
380 {
381//US libfile = instance->dirs()->findResource( "module", libname );
382 libfile = KGlobal::dirs()->findResource( "module", libname );
383 if ( libfile.isEmpty() )
384 {
385//US libfile = instance->dirs()->findResource( "lib", libname );
386 libfile = KGlobal::dirs()->findResource( "lib", libname );
387#ifndef NDEBUG
388 if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules
389 kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl;
390#endif
391 }
392 if ( libfile.isEmpty() )
393 {
394#ifndef NDEBUG
395 kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl;
396#endif
397 self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname);
398 }
399 else
400 self()->d->errorMessage = QString::null;
401 }
402 return libfile;
403}
404
405
406KLibrary* KLibLoader::globalLibrary( const char *name )
407{
408KLibrary *tmp;
409/*US
410int olt_dlopen_flag = lt_dlopen_flag;
411
412 lt_dlopen_flag |= LT_GLOBAL;
413 kdDebug(150) << "Loading the next library global with flag "
414 << lt_dlopen_flag
415 << "." << endl;
416*/
417 tmp = library(name);
418/*US
419 lt_dlopen_flag = olt_dlopen_flag;
420*/
421return tmp;
422}
423
424
425KLibrary* KLibLoader::library( const char *name )
426{
427 if (!name)
428 return 0;
429
430 KLibWrapPrivate* wrap = m_libs[name];
431 if (wrap) {
432 /* Nothing to do to load the library. */
433 wrap->ref_count++;
434 return wrap->lib;
435 }
436
437 /* Test if this library was loaded at some time, but got
438 unloaded meanwhile, whithout being dlclose()'ed. */
439 QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack);
440 for (; it.current(); ++it) {
441 if (it.current()->name == name)
442 wrap = it.current();
443 }
444
445 if (wrap) {
446 d->pending_close.removeRef(wrap);
447 if (!wrap->lib) {
448 /* This lib only was in loaded_stack, but not in m_libs. */
449 wrap->lib = new KLibrary( name, wrap->filename, wrap->handle );
450 }
451 wrap->ref_count++;
452 } else {
453 QString libfile = findLibrary( name );
454 if ( libfile.isEmpty() )
455 return 0;
456
457 const QString & qpeDir = QPEApplication::qpeDir();
458 libfile = qpeDir + libfile;
459//US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately );
460 QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately );
461
462//US lt_dlhandle handle = lt_dlopen( libfile.latin1() );
463//US if ( !handle )
464 if ( !qlib )
465 {
466//US const char* errmsg = lt_dlerror();
467 char* errmsg;
468 sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1());
469 qDebug(errmsg);
470
471 if(errmsg)
472 d->errorMessage = QString::fromLatin1(errmsg);
473 else
474 d->errorMessage = QString::null;
475 kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl;
476 return 0;
477 }
478 else
479 d->errorMessage = QString::null;
480
481 KLibrary *lib = new KLibrary( name, libfile, qlib );
482 wrap = new KLibWrapPrivate(lib, qlib);
483 d->loaded_stack.prepend(wrap);
484 }
485 m_libs.insert( name, wrap );
486
487 connect( wrap->lib, SIGNAL( destroyed() ),
488 this, SLOT( slotLibraryDestroyed() ) );
489
490 return wrap->lib;
491}
492
493QString KLibLoader::lastErrorMessage() const
494{
495 return d->errorMessage;
496}
497
498void KLibLoader::unloadLibrary( const char *libname )
499{
500 KLibWrapPrivate *wrap = m_libs[ libname ];
501 if (!wrap)
502 return;
503 if (--wrap->ref_count)
504 return;
505
506// kdDebug(150) << "closing library " << libname << endl;
507
508 m_libs.remove( libname );
509
510 disconnect( wrap->lib, SIGNAL( destroyed() ),
511 this, SLOT( slotLibraryDestroyed() ) );
512 close_pending( wrap );
513}
514
515KLibFactory* KLibLoader::factory( const char* name )
516{
517 KLibrary* lib = library( name );
518 if ( !lib )
519 return 0;
520
521 return lib->factory();
522}
523
524void KLibLoader::slotLibraryDestroyed()
525{
526 const KLibrary *lib = static_cast<const KLibrary *>( sender() );
527
528 QAsciiDictIterator<KLibWrapPrivate> it( m_libs );
529 for (; it.current(); ++it )
530 if ( it.current()->lib == lib )
531 {
532 KLibWrapPrivate *wrap = it.current();
533 wrap->lib = 0; /* the KLibrary object is already away */
534 m_libs.remove( it.currentKey() );
535 close_pending( wrap );
536 return;
537 }
538}
539
540void KLibLoader::close_pending(KLibWrapPrivate *wrap)
541{
542 if (wrap && !d->pending_close.containsRef( wrap ))
543 d->pending_close.append( wrap );
544
545 /* First delete all KLibrary objects in pending_close, but _don't_ unload
546 the DSO behind it. */
547 QPtrListIterator<KLibWrapPrivate> it(d->pending_close);
548 for (; it.current(); ++it) {
549 wrap = it.current();
550 if (wrap->lib) {
551 disconnect( wrap->lib, SIGNAL( destroyed() ),
552 this, SLOT( slotLibraryDestroyed() ) );
553 delete wrap->lib;
554 wrap->lib = 0;
555 }
556 }
557
558 if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return;
559
560 bool deleted_one = false;
561 while ((wrap = d->loaded_stack.first())) {
562 /* Let's first see, if we want to try to unload this lib.
563 If the env. var KDE_DOUNLOAD is set, we try to unload every lib.
564 If not, we look at the lib itself, and unload it only, if it exports
565 the symbol __kde_do_unload. */
566 if (d->unload_mode != KLibLoaderPrivate::UNLOAD
567 && wrap->unload_mode != KLibWrapPrivate::UNLOAD)
568 break;
569
570 /* Now ensure, that the libs are only unloaded in the reverse direction
571 they were loaded. */
572 if (!d->pending_close.containsRef( wrap )) {
573 if (!deleted_one)
574 /* Only diagnose, if we really haven't deleted anything. */
575// kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl;
576 break;
577 }
578
579// kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl;
580
581#ifndef Q_WS_QWS
582 if ( !deleted_one ) {
583 /* Only do the hack once in this loop.
584 WABA: *HACK*
585 We need to make sure to clear the clipboard before unloading a DSO
586 because the DSO could have defined an object derived from QMimeSource
587 and placed that on the clipboard. */
588 /*kapp->clipboard()->clear();*/
589
590 /* Well.. let's do something more subtle... convert the clipboard context
591 to text. That should be safe as it only uses objects defined by Qt. */
592
593 QWidgetList *widgetlist = QApplication::topLevelWidgets();
594 QWidget *co = widgetlist->first();
595 while (co) {
596 if (qstrcmp(co->name(), "internal clipboard owner") == 0) {
597 if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId())
598 kapp->clipboard()->setText(kapp->clipboard()->text());
599
600 break;
601 }
602 co = widgetlist->next();
603 }
604 delete widgetlist;
605 }
606#else
607 // FIXME(E): Implement in Qt Embedded
608#endif
609
610 deleted_one = true;
611//US lt_dlclose(wrap->handle);
612 wrap->handle->unload();
613
614 d->pending_close.removeRef(wrap);
615 /* loaded_stack is AutoDelete, so wrap is freed */
616 d->loaded_stack.remove();
617 }
618}
619
620void KLibLoader::virtual_hook( int, void* )
621{ /*BASE::virtual_hook( id, data );*/ }
622
623void KLibFactory::virtual_hook( int, void* )
624{ /*BASE::virtual_hook( id, data );*/ }
625
626//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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Torben Weis <weis@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA.
17*/
18#ifndef KLIBLOADER_H
19#define KLIBLOADER_H
20
21#include <qobject.h>
22#include <qstring.h>
23#include <qstringlist.h>
24#include <qasciidict.h>
25#include <qptrlist.h>
26#include <kglobal.h>
27
28#include <stdlib.h> // For backwards compatibility
29
30class KInstance;
31class QTimer;
32class KLibrary;
33class KLibFactory;
34class KLibFactoryPrivate;
35class KLibLoaderPrivate;
36class KLibraryPrivate;
37
38class QLibrary;
39
40#define K_EXPORT_COMPONENT_FACTORY( libname, factory ) \
41 extern "C" { void *init_##libname() { return new factory; } }
42
43/**
44 * @short Represents a dynamically loaded library.
45 *
46 * KLibrary allows you to look up symbols of the shared library.
47 * Use @ref KLibLoader to create a new instance of KLibrary.
48 *
49 * @see KLibLoader
50 * @author Torben Weis <weis@kde.org>
51 */
52class KLibrary : public QObject
53{
54 friend class KLibLoader;
55 friend class QAsciiDict<KLibrary>;
56
57 Q_OBJECT
58public:
59 /**
60 * @internal
61 * Don't create KLibrary objects on your own. Instead use @ref KLibLoader.
62 */
63//US KLibrary( const QString& libname, const QString& filename, void * handle );
64 KLibrary( const QString& libname, const QString& filename, QLibrary* handle );
65
66 /**
67 * Returns the name of the library.
68 * @return The name of the library like "libkspread".
69 */
70 QString name() const;
71
72 /**
73 * Returns the file name of the library.
74 * @return The filename of the library, for example "/opt/kde2&/lib/libkspread.la"
75 */
76 QString fileName() const;
77
78 /**
79 * Returns the factory of the library.
80 * @return The factory of the library if there is any, otherwise 0
81 */
82 KLibFactory* factory();
83
84 /**
85 * Looks up a symbol from the library. This is a very low level
86 * function that you usually don't want to use. Usually you should
87 * check using @ref hasSymbol() whether the symbol actually exists,
88 * otherwise a warning will be printed.
89 * @param name the name of the symbol to look up
90 * @return the address of the symbol, or 0 if it does not exist
91 * @see #hasSymbol
92 */
93 void* symbol( const char* name ) const;
94
95 /**
96 * Looks up a symbol from the library. This is a very low level
97 * function that you usually don't want to use.
98 * Unlike @ref symbol(), this method doesn't warn if the symbol doesn't exist,
99 * so if the symbol might or might not exist, better use hasSymbol() before symbol().
100 * @param name the name of the symbol to check
101 * @return true if the symbol exists
102 * @since 3.1
103 */
104 bool hasSymbol( const char* name ) const;
105
106 /**
107 * Unloads the library.
108 * This typically results in the deletion of this object. You should
109 * not reference its pointer after calling this function.
110 */
111 void unload() const;
112
113private slots:
114 void slotObjectCreated( QObject *obj );
115 void slotObjectDestroyed();
116 void slotTimeout();
117
118private:
119 /**
120 * @internal
121 * Don't destruct KLibrary objects yourself. Instead use @ref unload() instead.
122 */
123 ~KLibrary();
124
125 QString m_libname;
126 QString m_filename;
127 KLibFactory* m_factory;
128//US void * m_handle;
129 QLibrary* m_handle;
130 QPtrList<QObject> m_objs;
131 QTimer *m_timer;
132 KLibraryPrivate *d;
133};
134
135class KLibWrapPrivate;
136
137/**
138 * The KLibLoader allows you to load libraries dynamically at runtime.
139 * Dependent libraries are loaded automatically.
140 *
141 * KLibLoader follows the singleton pattern. You can not create multiple
142 * instances. Use @ref self() to get a pointer to the loader.
143 *
144 * @see KLibrary
145 * @author Torben Weis <weis@kde.org>
146 */
147class KLibLoader : public QObject
148{
149 friend class KLibrary;
150
151 Q_OBJECT
152public:
153 /**
154 * You should NEVER destruct an instance of KLibLoader
155 * until you know what you are doing. This will release
156 * the loaded libraries.
157 */
158 ~KLibLoader();
159
160 /**
161 * Loads and initializes a library. Loading a library multiple times is
162 * handled gracefully.
163 *
164 * This is a convenience function that returns the factory immediately
165 * @param libname This is the library name without extension. Usually that is something like
166 * "libkspread". The function will then search for a file named
167 * "libkspread.la" in the KDE library paths.
168 * The *.la files are created by libtool and contain
169 * important information especially about the libraries dependencies
170 * on other shared libs. Loading a "libfoo.so" could not solve the
171 * dependencies problem.
172 *
173 * You can, however, give a library name ending in ".so"
174 * (or whatever is used on your platform), and the library
175 * will be loaded without resolving dependencies. USE WITH CARE :)
176 * @return the @ref KLibFactory, or 0 if the library does not exist or it does
177 * not have a factory
178 * @see #library
179 */
180 KLibFactory* factory( const char* libname );
181
182 /**
183 * Loads and initializes a library. Loading a library multiple times is
184 * handled gracefully.
185 *
186 * @param libname This is the library name without extension. Usually that is something like
187 * "libkspread". The function will then search for a file named
188 * "libkspread.la" in the KDE library paths.
189 * The *.la files are created by libtool and contain
190 * important information especially about the libraries dependencies
191 * on other shared libs. Loading a "libfoo.so" could not solve the
192 * dependencies problem.
193 *
194 * You can, however, give a library name ending in ".so"
195 * (or whatever is used on your platform), and the library
196 * will be loaded without resolving dependencies. USE WITH CARE :)
197 * @return @ref KLibrary is invalid (0) when the library couldn't be dlopened. in such
198 * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage()
199 *
200 * @see #factory
201 */
202 virtual KLibrary* library( const char* libname );
203
204 /**
205 * Loads and initializes a library. Loading a library multiple times is
206 * handled gracefully. The library is loaded such that the symbols are
207 * globally accessible so libraries with dependencies can be loaded
208 * sequentially.
209 *
210 * @param name This is the library name without extension. Usually that is something like
211 * "libkspread". The function will then search for a file named
212 * "libkspread.la" in the KDE library paths.
213 * The *.la files are created by libtool and contain
214 * important information especially about the libraries dependencies
215 * on other shared libs. Loading a "libfoo.so" could not solve the
216 * dependencies problem.
217 *
218 * You can, however, give a library name ending in ".so"
219 * (or whatever is used on your platform), and the library
220 * will be loaded without resolving dependencies. USE WITH CARE :)
221 * @return KLibrariy is invalid (0) when the library couldn't be dlopened. in such
222 * a case you can retrieve the error message by calling KLibLoader::lastErrorMessage()
223 *
224 * @see #factory
225 */
226 KLibrary* globalLibrary( const char *name );
227
228 /*
229 * Returns an error message that can be useful to debug the problem.
230 * Returns QString::null if the last call to @ref #library() was successful.
231 * You can call this function more than once. The error message is only
232 * reset by a new call to library().
233 * @return the last error message, or QString::null if there was no error
234 */
235 QString lastErrorMessage() const;
236
237 /**
238 * Unloads the library with the given name.
239 * @param libname This is the library name without extension. Usually that is something like
240 * "libkspread". The function will then search for a file named
241 * "libkspread.la" in the KDE library paths.
242 * The *.la files are created by libtool and contain
243 * important information especially about the libraries dependencies
244 * on other shared libs. Loading a "libfoo.so" could not solve the
245 * dependencies problem.
246 *
247 * You can, however, give a library name ending in ".so"
248 * (or whatever is used on your platform), and the library
249 * will be loaded without resolving dependencies. USE WITH CARE :)
250 */
251 virtual void unloadLibrary( const char *libname );
252
253 /**
254 * Returns a pointer to the factory. Use this function to get an instance
255 * of KLibLoader.
256 * @return a pointer to the loader. If no loader exists until now
257 * then one is created.
258 */
259 static KLibLoader* self();
260
261 /**
262 * @internal
263 * Internal Method, called by the KApplication destructor.
264 * Do not call it.
265 * This is what makes it possible to rely on ~KLibFactory
266 * being called in all cases, whether the library is unloaded
267 * while the application is running or when exiting.
268 */
269 static void cleanUp();
270
271 /**
272 * Helper method which looks for a library in the standard paths
273 * ("module" and "lib" resources).
274 * Made public for code that doesn't use KLibLoader itself, but still
275 * wants to open modules.
276 * @param name of the library. If it is not a path, the function searches in
277 * the "module" and "lib" resources. If there is no extension,
278 * ".la" will be appended.
279 * @param instance a KInstance used to get the standard paths
280 */
281 static QString findLibrary( const char * name/*US , const KInstance * instance = KGlobal::instance()*/ );
282
283protected:
284 KLibLoader( QObject* parent = 0, const char* name = 0 );
285
286private slots:
287 void slotLibraryDestroyed();
288private:
289 void close_pending( KLibWrapPrivate * );
290 QAsciiDict<KLibWrapPrivate> m_libs;
291
292 static KLibLoader* s_self;
293
294protected:
295 virtual void virtual_hook( int id, void* data );
296private:
297 KLibLoaderPrivate *d;
298};
299
300/**
301 * If you develop a library that is to be loaded dynamically at runtime, then
302 * you should return a pointer to your factory. The K_EXPORT_COMPONENT_FACTORY
303 * macro is provided for this purpose:
304 * <pre>
305 * K_EXPORT_COMPONENT_FACTORY( libkspread, KSpreadFactory )
306 * </pre>
307 *
308 * The first macro argument is the name of your library, the second specifies the name
309 * of your factory.
310 *
311 * In the constructor of your factory you should create an instance of @ref KInstance
312 * like this:
313 * <pre>
314 * s_global = new KInstance( "kspread" );
315 * </pre>
316 * This @ref KInstance is comparable to @ref KGlobal used by normal applications.
317 * It allows you to find resource files (images, XML, sound etc.) belonging
318 * to the library.
319 *
320 * If you want to load a library, use @ref KLibLoader. You can query @ref KLibLoader
321 * directly for a pointer to the libraries factory by using the @ref KLibLoader::factory()
322 * function.
323 *
324 * The KLibFactory is used to create the components, the library has to offer.
325 * The factory of KSpread for example will create instances of KSpreadDoc,
326 * while the Konqueror factory will create KonqView widgets.
327 * All objects created by the factory must be derived from @ref QObject, since @ref QObject
328 * offers type safe casting.
329 *
330 * KLibFactory is an abstract class. Reimplement the @ref
331 * createObject() method to give it functionality.
332 *
333 * @author Torben Weis <weis@kde.org>
334 */
335class KLibFactory : public QObject
336{
337 Q_OBJECT
338public:
339 /**
340 * Create a new factory.
341 * @param parent the parent of the QObject, 0 for no parent
342 * @param name the name of the QObject, 0 for no name
343 */
344 KLibFactory( QObject* parent = 0, const char* name = 0 );
345 virtual ~KLibFactory();
346
347 /**
348 * Creates a new object. The returned object has to be derived from
349 * the requested classname.
350 *
351 * It is valid behavior to create different kinds of objects
352 * depending on the requested @p classname. For example a koffice
353 * library may usually return a pointer to KoDocument. But
354 * if asked for a "QWidget", it could create a wrapper widget,
355 * that encapsulates the Koffice specific features.
356 *
357 * create() automatically emits a signal @ref objectCreated to tell
358 * the library about its newly created object. This is very
359 * important for reference counting, and allows unloading the
360 * library automatically once all its objects have been destroyed.
361 *
362 * @param parent the parent of the QObject, 0 for no parent
363 * @param name the name of the QObject, 0 for no name
364 * @param classname the name of the class
365 * @param args a list of arguments
366 */
367
368 QObject* create( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() );
369
370signals:
371 /**
372 * Emitted in #create
373 * @param obj the new object
374 */
375 void objectCreated( QObject *obj );
376
377
378protected:
379
380 /**
381 * Creates a new object. The returned object has to be derived from
382 * the requested classname.
383 *
384 * It is valid behavior to create different kinds of objects
385 * depending on the requested @p classname. For example a koffice
386 * library may usually return a pointer to KoDocument. But
387 * if asked for a "QWidget", it could create a wrapper widget,
388 * that encapsulates the Koffice specific features.
389 *
390 * This function is called by #create()
391 * @param parent the parent of the QObject, 0 for no parent
392 * @param name the name of the QObject, 0 for no name
393 * @param classname the name of the class
394 * @param args a list of arguments
395 */
396 virtual QObject* createObject( QObject* parent = 0, const char* name = 0, const char* classname = "QObject", const QStringList &args = QStringList() ) = 0;
397
398
399protected:
400 virtual void virtual_hook( int id, void* data );
401private:
402 KLibFactoryPrivate *d;
403};
404
405#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 @@
1#include <qregexp.h>
2#include <qapplication.h>
3
4#include "kdebug.h"
5#include "kcalendarsystemgregorian.h"
6
7#include "klocale.h"
8
9
10QDict<QString> *mLocaleDict = 0;
11void setLocaleDict( QDict<QString> * dict )
12{
13 mLocaleDict = dict;
14
15}
16QString i18n(const char *text)
17{
18 if ( ! mLocaleDict )
19 return QString( text );
20 else {
21 QString* ret = mLocaleDict->find(QString(text)) ;
22 if ( ret == 0 ) {
23 return QString( text );
24 }
25 else {
26 if ( (*ret).isEmpty() )
27 return QString( text );
28 else
29 return (*ret);
30 }
31 }
32
33}
34
35QString i18n(const char *,const char *text)
36{
37 return i18n( text );
38}
39
40QString i18n(const char *text1, const char *textn, int num)
41{
42 if ( num == 1 ) return i18n( text1 );
43 else {
44 QString text = i18n( textn );
45 int pos = text.find( "%n" );
46 if ( pos >= 0 ) text.replace( pos, 2, QString::number( num ) );
47 return text;
48 }
49}
50
51inline void put_it_in( QChar *buffer, uint& index, const QString &s )
52{
53 for ( uint l = 0; l < s.length(); l++ )
54 buffer[index++] = s.at( l );
55}
56
57inline void put_it_in( QChar *buffer, uint& index, int number )
58{
59 buffer[index++] = number / 10 + '0';
60 buffer[index++] = number % 10 + '0';
61}
62
63static int readInt(const QString &str, uint &pos)
64{
65 if (!str.at(pos).isDigit()) return -1;
66 int result = 0;
67 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
68 {
69 result *= 10;
70 result += str.at(pos).digitValue();
71 }
72
73 return result;
74}
75
76KLocale::KLocale() : mCalendarSystem( 0 )
77{
78
79 m_decimalSymbol = ".";
80 m_positiveSign = "";
81 m_negativeSign = "-";
82 m_thousandsSeparator = ",";
83
84
85
86
87 mWeekStartsMonday = true;
88 mHourF24Format = true;
89 mIntDateFormat = 0;
90 mLanguage = 0;
91 mDateFormat = "%a %Y %b %d";
92 mDateFormatShort = "%Y-%m-%d";
93 mTimeZoneList << i18n ("-11:00 US/Samoa")
94 << i18n ("-10:00 US/Hawaii")
95 << i18n ("-09:00 US/Alaska")
96 << i18n ("-08:00 US/Pacific")
97 << i18n ("-07:00 US/Mountain")
98 << i18n ("-06:00 US/Central")
99 << i18n ("-05:00 US/Eastern")
100 << i18n ("-04:00 Brazil/West")
101 << i18n ("-03:00 Brazil/East")
102 << i18n ("-02:00 Brazil/DeNoronha")
103 << i18n ("-01:00 Atlantic/Azores")
104 << i18n (" 00:00 Europe/London(UTC)")
105 << i18n ("+01:00 Europe/Oslo(CET)")
106 << i18n ("+02:00 Europe/Helsinki")
107 << i18n ("+03:00 Europe/Moscow")
108 << i18n ("+04:00 Indian/Mauritius")
109 << i18n ("+05:00 Indian/Maldives")
110 << i18n ("+06:00 Indian/Chagos")
111 << i18n ("+07:00 Asia/Bangkok")
112 << i18n ("+08:00 Asia/Hongkong")
113 << i18n ("+09:00 Asia/Tokyo")
114 << i18n ("+10:00 Asia/Vladivostok")
115 << i18n ("+11:00 Asia/Magadan")
116 << i18n ("+12:00 Asia/Kamchatka")
117 // << i18n (" xx:xx User defined offset")
118 << i18n (" Local Time");
119 mSouthDaylight = false;
120 mTimeZoneOffset = 0;
121 daylightEnabled = false;
122}
123
124void KLocale::setDateFormat( QString s )
125{
126 mDateFormat = s;
127}
128
129void KLocale::setDateFormatShort( QString s )
130{
131 mDateFormatShort = s;
132}
133
134void KLocale::setHore24Format ( bool b )
135{
136 mHourF24Format = b;
137}
138void KLocale::setWeekStartMonday( bool b )
139{
140 mWeekStartsMonday = b;
141}
142int KLocale::getIntDateFormat( )
143{
144 return mIntDateFormat ;
145
146}
147void KLocale::setIntDateFormat( int i )
148{
149 mIntDateFormat = i;
150}
151void KLocale::setLanguage( int i )
152{
153 mLanguage = i;
154}
155QString KLocale::translate( const char *index ) const
156{
157 return i18n( index );
158}
159
160QString KLocale::translate( const char *, const char *fallback) const
161{
162 return i18n( fallback );
163}
164
165QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
166{
167 const QString rst = timeFormat();
168
169 // only "pm/am" here can grow, the rest shrinks, but
170 // I'm rather safe than sorry
171 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
172
173 uint index = 0;
174 bool escape = false;
175 int number = 0;
176
177 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
178 {
179 if ( !escape )
180 {
181 if ( rst.at( format_index ).unicode() == '%' )
182 escape = true;
183 else
184 buffer[index++] = rst.at( format_index );
185 }
186 else
187 {
188 switch ( rst.at( format_index ).unicode() )
189 {
190 case '%':
191 buffer[index++] = '%';
192 break;
193 case 'H':
194 put_it_in( buffer, index, pTime.hour() );
195 break;
196 case 'I':
197 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
198 break;
199 case 'M':
200 put_it_in( buffer, index, pTime.minute() );
201 break;
202 case 'S':
203 if (includeSecs)
204 put_it_in( buffer, index, pTime.second() );
205 else
206 {
207 // we remove the seperator sign before the seconds and
208 // assume that works everywhere
209 --index;
210 break;
211 }
212 break;
213 case 'k':
214 number = pTime.hour();
215 case 'l':
216 // to share the code
217 if ( rst.at( format_index ).unicode() == 'l' )
218 number = (pTime.hour() + 11) % 12 + 1;
219 if ( number / 10 )
220 buffer[index++] = number / 10 + '0';
221 buffer[index++] = number % 10 + '0';
222 break;
223 case 'p':
224 {
225 QString s;
226 if ( pTime.hour() >= 12 )
227 put_it_in( buffer, index, i18n("pm") );
228 else
229 put_it_in( buffer, index, i18n("am") );
230 break;
231 }
232 default:
233 buffer[index++] = rst.at( format_index );
234 break;
235 }
236 escape = false;
237 }
238 }
239 QString ret( buffer, index );
240 delete [] buffer;
241 return ret;
242}
243
244QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
245{
246 const QString rst = shortFormat?dateFormatShort():dateFormat();
247
248 // I'm rather safe than sorry
249 QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
250
251 unsigned int index = 0;
252 bool escape = false;
253 int number = 0;
254
255 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
256 {
257 if ( !escape )
258 {
259 if ( rst.at( format_index ).unicode() == '%' )
260 escape = true;
261 else
262 buffer[index++] = rst.at( format_index );
263 }
264 else
265 {
266 switch ( rst.at( format_index ).unicode() )
267 {
268 case '%':
269 buffer[index++] = '%';
270 break;
271 case 'Y':
272 put_it_in( buffer, index, pDate.year() / 100 );
273 case 'y':
274 put_it_in( buffer, index, pDate.year() % 100 );
275 break;
276 case 'n':
277 number = pDate.month();
278 case 'e':
279 // to share the code
280 if ( rst.at( format_index ).unicode() == 'e' )
281 number = pDate.day();
282 if ( number / 10 )
283 buffer[index++] = number / 10 + '0';
284 buffer[index++] = number % 10 + '0';
285 break;
286 case 'm':
287 put_it_in( buffer, index, pDate.month() );
288 break;
289 case 'b':
290 put_it_in( buffer, index, monthName(pDate.month(), true) );
291 break;
292 case 'B':
293 put_it_in( buffer, index, monthName(pDate.month(), false) );
294 break;
295 case 'd':
296 put_it_in( buffer, index, pDate.day() );
297 break;
298 case 'a':
299 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), true) );
300 break;
301 case 'A':
302 put_it_in( buffer, index, weekDayName(pDate.dayOfWeek(), false) );
303 break;
304 default:
305 buffer[index++] = rst.at( format_index );
306 break;
307 }
308 escape = false;
309 }
310 }
311 QString ret( buffer, index );
312 delete [] buffer;
313 return ret;
314}
315
316QString KLocale::formatDateTime(const QDateTime &pDateTime,
317 bool shortFormat,
318 bool includeSeconds) const
319{
320 return QString( "%1 %2")
321 .arg( formatDate( pDateTime.date(), shortFormat ) )
322 .arg( formatTime( pDateTime.time(), includeSeconds ) );
323}
324
325QString KLocale::formatDateTime(const QDateTime &pDateTime) const
326{
327 return formatDateTime(pDateTime, true);
328}
329
330QDate KLocale::readDate(const QString &intstr, bool* ok) const
331{
332 QDate date;
333 date = readDate(intstr, true, ok);
334 if (date.isValid()) return date;
335 return readDate(intstr, false, ok);
336}
337
338QDate KLocale::readDate(const QString &intstr, bool shortFormat, bool* ok) const
339{
340 QString fmt = (shortFormat ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
341 return readDate( intstr, fmt, ok );
342}
343
344QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
345{
346 //kdDebug(173) << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
347 QString str = intstr.simplifyWhiteSpace().lower();
348 int day = -1, month = -1;
349 // allow the year to be omitted if not in the format
350 int year = QDate::currentDate().year();
351 uint strpos = 0;
352 uint fmtpos = 0;
353
354 while (fmt.length() > fmtpos || str.length() > strpos)
355 {
356 if ( !(fmt.length() > fmtpos && str.length() > strpos) )
357 goto error;
358
359 QChar c = fmt.at(fmtpos++);
360
361 if (c != '%') {
362 if (c.isSpace())
363 strpos++;
364 else if (c != str.at(strpos++))
365 goto error;
366 continue;
367 }
368
369 // remove space at the begining
370 if (str.length() > strpos && str.at(strpos).isSpace())
371 strpos++;
372
373 c = fmt.at(fmtpos++);
374 switch (c)
375 {
376 case 'a':
377 case 'A':
378 // this will just be ignored
379 { // Cristian Tache: porting to Win: Block added because of "j" redefinition
380 for (int j = 1; j < 8; j++) {
381 QString s = weekDayName(j, c == 'a').lower();
382 int len = s.length();
383 if (str.mid(strpos, len) == s)
384 strpos += len;
385 }
386 break;
387 }
388 case 'b':
389 case 'B':
390 { // Cristian Tache: porting to Win: Block added because of "j" redefinition
391 for (int j = 1; j < 13; j++) {
392 QString s = monthName(j, c == 'b').lower();
393 int len = s.length();
394 if (str.mid(strpos, len) == s) {
395 month = j;
396 strpos += len;
397 }
398 }
399 break;
400 }
401 case 'd':
402 case 'e':
403 day = readInt(str, strpos);
404 if (day < 1 || day > 31)
405 goto error;
406
407 break;
408
409 case 'n':
410 case 'm':
411 month = readInt(str, strpos);
412 if (month < 1 || month > 12)
413 goto error;
414
415 break;
416
417 case 'Y':
418 case 'y':
419 year = readInt(str, strpos);
420 if (year < 0)
421 goto error;
422 // Qt treats a year in the range 0-100 as 1900-1999.
423 // It is nicer for the user if we treat 0-68 as 2000-2068
424 if (year < 69)
425 year += 2000;
426 else if (c == 'y')
427 year += 1900;
428
429 break;
430 }
431 }
432 //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
433 if ( year != -1 && month != -1 && day != -1 )
434 {
435 if (ok) *ok = true;
436 return QDate(year, month, day);
437 }
438 error:
439 if (ok) *ok = false;
440 return QDate(); // invalid date
441}
442
443QTime KLocale::readTime(const QString &intstr, bool *ok) const
444{
445 QTime _time;
446 _time = readTime(intstr, true, ok);
447 if (_time.isValid()) return _time;
448 return readTime(intstr, false, ok);
449}
450
451QTime KLocale::readTime(const QString &intstr, bool seconds, bool *ok) const
452{
453 QString str = intstr.simplifyWhiteSpace().lower();
454 QString Format = timeFormat().simplifyWhiteSpace();
455 if (!seconds)
456 Format.replace(QRegExp(QString::fromLatin1(".%S")), QString::null);
457
458 int hour = -1, minute = -1, second = seconds ? -1 : 0; // don't require seconds
459 bool g_12h = false;
460 bool pm = false;
461 uint strpos = 0;
462 uint Formatpos = 0;
463
464 while (Format.length() > Formatpos || str.length() > strpos)
465 {
466 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
467
468 QChar c = Format.at(Formatpos++);
469
470 if (c != '%')
471 {
472 if (c.isSpace())
473 strpos++;
474 else if (c != str.at(strpos++))
475 goto error;
476 continue;
477 }
478
479 // remove space at the begining
480 if (str.length() > strpos && str.at(strpos).isSpace())
481 strpos++;
482
483 c = Format.at(Formatpos++);
484 switch (c)
485 {
486 case 'p':
487 {
488 QString s;
489 s = i18n("pm").lower();
490 int len = s.length();
491 if (str.mid(strpos, len) == s)
492 {
493 pm = true;
494 strpos += len;
495 }
496 else
497 {
498 s = i18n("am").lower();
499 len = s.length();
500 if (str.mid(strpos, len) == s) {
501 pm = false;
502 strpos += len;
503 }
504 else
505 goto error;
506 }
507 }
508 break;
509
510 case 'k':
511 case 'H':
512 g_12h = false;
513 hour = readInt(str, strpos);
514 if (hour < 0 || hour > 23)
515 goto error;
516
517 break;
518
519 case 'l':
520 case 'I':
521 g_12h = true;
522 hour = readInt(str, strpos);
523 if (hour < 1 || hour > 12)
524 goto error;
525
526 break;
527
528 case 'M':
529 minute = readInt(str, strpos);
530 if (minute < 0 || minute > 59)
531 goto error;
532
533 break;
534
535 case 'S':
536 second = readInt(str, strpos);
537 if (second < 0 || second > 59)
538 goto error;
539
540 break;
541 }
542 }
543 if (g_12h)
544 {
545 hour %= 12;
546 if (pm) hour += 12;
547 }
548
549 if (ok) *ok = true;
550 return QTime(hour, minute, second);
551
552 error:
553 if (ok) *ok = false;
554 return QTime(-1, -1, -1); // return invalid date if it didn't work
555 // This will be removed in the near future, since it gives a warning on stderr.
556 // The presence of the bool* (since KDE-3.0) removes the need for an invalid QTime.
557}
558
559bool KLocale::use12Clock() const
560{
561 return !mHourF24Format ;;
562}
563
564bool KLocale::weekStartsMonday() const
565{
566 return mWeekStartsMonday;
567}
568
569int KLocale::weekStartDay() const
570{
571 if ( mWeekStartsMonday )
572 return 1;
573 return 7;
574}
575
576QString KLocale::weekDayName(int i,bool shortName) const
577{
578 if ( shortName )
579 switch ( i )
580 {
581 case 1: return i18n("Monday", "Mon");
582 case 2: return i18n("Tuesday", "Tue");
583 case 3: return i18n("Wednesday", "Wed");
584 case 4: return i18n("Thursday", "Thu");
585 case 5: return i18n("Friday", "Fri");
586 case 6: return i18n("Saturday", "Sat");
587 case 7: return i18n("Sunday", "Sun");
588 }
589 else
590 switch ( i )
591 {
592 case 1: return i18n("Monday");
593 case 2: return i18n("Tuesday");
594 case 3: return i18n("Wednesday");
595 case 4: return i18n("Thursday");
596 case 5: return i18n("Friday");
597 case 6: return i18n("Saturday");
598 case 7: return i18n("Sunday");
599 }
600
601 return QString::null;
602}
603
604QString KLocale::monthName(int i,bool shortName) const
605{
606 if ( shortName )
607 switch ( i )
608 {
609 case 1: return i18n("January", "Jan");
610 case 2: return i18n("February", "Feb");
611 case 3: return i18n("March", "Mar");
612 case 4: return i18n("April", "Apr");
613 case 5: return i18n("May short", "May");
614 case 6: return i18n("June", "Jun");
615 case 7: return i18n("July", "Jul");
616 case 8: return i18n("August", "Aug");
617 case 9: return i18n("September", "Sep");
618 case 10: return i18n("October", "Oct");
619 case 11: return i18n("November", "Nov");
620 case 12: return i18n("December", "Dec");
621 }
622 else
623 switch (i)
624 {
625 case 1: return i18n("January");
626 case 2: return i18n("February");
627 case 3: return i18n("March");
628 case 4: return i18n("April");
629 case 5: return i18n("May long", "May");
630 case 6: return i18n("June");
631 case 7: return i18n("July");
632 case 8: return i18n("August");
633 case 9: return i18n("September");
634 case 10: return i18n("October");
635 case 11: return i18n("November");
636 case 12: return i18n("December");
637 }
638
639 return QString::null;
640}
641
642QString KLocale::country() const
643{
644 return QString::null;
645}
646
647QString KLocale::dateFormat() const
648{
649 if ( QApplication::desktop()->width() < 480 ) {
650 if ( mIntDateFormat == 0 )
651 return "%a %d %b %Y";
652 else if ( mIntDateFormat == 1 )
653 return "%a %b %d %Y";
654 else if ( mIntDateFormat == 2 )
655 return "%a %Y %b %d";
656 } else {
657
658 if ( mIntDateFormat == 0 )
659 return "%A %d %B %Y";
660 else if ( mIntDateFormat == 1 )
661 return "%A %B %d %Y";
662 else if ( mIntDateFormat == 2 )
663 return "%A %Y %B %d";
664 }
665 return mDateFormat ;
666}
667
668QString KLocale::dateFormatShort() const
669{
670
671 if ( mIntDateFormat == 0 )
672 return "%d.%m.%Y";
673 else if ( mIntDateFormat == 1 )
674 return "%m.%d.%Y";
675 else if ( mIntDateFormat == 2 )
676 return "%Y-%m-%d";
677 return mDateFormatShort ;
678
679}
680
681
682QString KLocale::timeFormat() const
683{
684 if ( mHourF24Format)
685 return "%H:%M:%S";
686 return "%I:%M:%S%p";
687}
688
689void KLocale::insertCatalogue ( const QString & )
690{
691}
692
693KCalendarSystem *KLocale::calendar()
694{
695 if ( !mCalendarSystem ) {
696 mCalendarSystem = new KCalendarSystemGregorian;
697 }
698
699 return mCalendarSystem;
700}
701
702int KLocale::timezoneOffset( QString timeZone )
703{
704 int ret = 1001;
705 int index = mTimeZoneList.findIndex( timeZone );
706 if ( index < 24 )
707 ret = ( index-11 ) * 60 ;
708 return ret;
709}
710
711QStringList KLocale::timeZoneList() const
712{
713 return mTimeZoneList;
714}
715void KLocale::setTimezone( const QString &timeZone )
716{
717 mTimeZoneOffset = timezoneOffset( timeZone );
718}
719
720void KLocale::setDaylightSaving( bool b, int start , int end )
721{
722 daylightEnabled = b;
723 daylightStart = start;
724 daylightEnd = end;
725 mSouthDaylight = (end < start);
726 // qDebug("klocale daylight %d %d %d ", b, start , end );
727}
728
729int KLocale::localTimeOffset( const QDateTime &dt )
730{
731 bool addDaylight = false;
732 if ( daylightEnabled ) {
733 int d_end, d_start;
734 int dayofyear = dt.date().dayOfYear();
735 int year = dt.date().year();
736 int add = 0;
737 if ( QDate::leapYear(year) )
738 add = 1;
739 QDate date ( year,1,1 );
740 if ( daylightEnd > 59 )
741 d_end = daylightEnd +add;
742 else
743 d_end = daylightEnd;
744 if ( daylightStart > 59 )
745 d_start = daylightStart +add;
746 else
747 d_start = daylightStart;
748 QDate s_date = date.addDays( d_start -1 );
749 QDate e_date = date.addDays( d_end -1 );
750 int dof = s_date.dayOfWeek();
751 if ( dof < 7 )
752 s_date = s_date.addDays( -dof );
753 dof = e_date.dayOfWeek();
754 if ( dof < 7 )
755 e_date = e_date.addDays( -dof );
756 QTime startTime ( 3,0,0 );
757 QDateTime startDt( s_date, startTime );
758 QDateTime endDt( e_date, startTime );
759 //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( ));
760 if ( mSouthDaylight ) {
761 if ( ! ( endDt < dt && dt < startDt) )
762 addDaylight = true;
763 } else {
764 if ( startDt < dt && dt < endDt )
765 addDaylight = true;
766
767
768 }
769 }
770 int addMin = 0;
771 if ( addDaylight )
772 addMin = 60;
773 return mTimeZoneOffset + addMin;
774}
775// ******************************************************************
776// added LR
777QString KLocale::formatNumber(double num, int precision) const
778{
779 bool neg = num < 0;
780 if (precision == -1) precision = 2;
781 QString res = QString::number(neg?-num:num, 'f', precision);
782 int pos = res.find('.');
783 if (pos == -1) pos = res.length();
784 else res.replace(pos, 1, decimalSymbol());
785
786 while (0 < (pos -= 3))
787 res.insert(pos, thousandsSeparator()); // thousand sep
788
789 // How can we know where we should put the sign?
790 res.prepend(neg?negativeSign():positiveSign());
791
792 return res;
793}
794QString KLocale::formatNumber(const QString &numStr) const
795{
796 return formatNumber(numStr.toDouble());
797}
798double KLocale::readNumber(const QString &_str, bool * ok) const
799{
800 QString str = _str.stripWhiteSpace();
801 bool neg = str.find(negativeSign()) == 0;
802 if (neg)
803 str.remove( 0, negativeSign().length() );
804
805 /* will hold the scientific notation portion of the number.
806 Example, with 2.34E+23, exponentialPart == "E+23"
807 */
808 QString exponentialPart;
809 int EPos;
810
811 EPos = str.find('E', 0, false);
812
813 if (EPos != -1)
814 {
815 exponentialPart = str.mid(EPos);
816 str = str.left(EPos);
817 }
818
819 int pos = str.find(decimalSymbol());
820 QString major;
821 QString minor;
822 if ( pos == -1 )
823 major = str;
824 else
825 {
826 major = str.left(pos);
827 minor = str.mid(pos + decimalSymbol().length());
828 }
829
830 // Remove thousand separators
831 int thlen = thousandsSeparator().length();
832 int lastpos = 0;
833 while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
834 {
835 // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
836 int fromEnd = major.length() - pos;
837 if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
838 || pos - lastpos > 3 // More than 3 digits between two separators -> error
839 || pos == 0 // Can't start with a separator
840 || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
841 {
842 if (ok) *ok = false;
843 return 0.0;
844 }
845
846 lastpos = pos;
847 major.remove( pos, thlen );
848 }
849 if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
850 {
851 if (ok) *ok = false;
852 return 0.0;
853 }
854
855 QString tot;
856 if (neg) tot = '-';
857
858 tot += major + '.' + minor + exponentialPart;
859
860 return tot.toDouble(ok);
861}
862QString KLocale::decimalSymbol() const
863{
864
865 return m_decimalSymbol;
866}
867
868QString KLocale::thousandsSeparator() const
869{
870
871 return m_thousandsSeparator;
872}
873QString KLocale::positiveSign() const
874{
875 return m_positiveSign;
876}
877
878QString KLocale::negativeSign() const
879{
880 return m_negativeSign;
881}
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 @@
1#ifndef MINIKDE_KLOCALE_H
2#define MINIKDE_KLOCALE_H
3
4#include <qstring.h>
5#include <qstringlist.h>
6#include <qdatetime.h>
7#include <qdict.h>
8
9#ifndef I18N_NOOP
10#define I18N_NOOP(x) (x)
11#endif
12
13class KCalendarSystem;
14void setLocaleDict( QDict<QString> * dict );
15QString i18n(const char *text);
16QString i18n(const char *hint, const char *text);
17QString i18n(const char *text1, const char *textn, int num);
18
19// Qt3's uic generates i18n( "msg", "comment" ) calls which conflict
20// with our i18n method. we use uic -tr tr2i18n to redirect
21// to the right i18n() function
22inline QString tr2i18n(const char* message, const char* =0) {
23 return i18n( message);
24}
25
26class KLocale
27{
28 public:
29 KLocale();
30
31 QString formatNumber(double num, int precision = -1) const;
32 QString formatNumber(const QString &numStr) const;
33 double readNumber(const QString &numStr, bool * ok = 0) const;
34
35 QString decimalSymbol() const;
36 QString thousandsSeparator() const;
37 QString positiveSign() const;
38 QString negativeSign() const;
39
40
41 QString translate( const char *index ) const;
42 QString translate( const char *index, const char *fallback) const;
43
44 QString formatDate(const QDate &pDate, bool shortFormat = false) const;
45 QString formatTime(const QTime &pTime, bool includeSecs = false) const;
46 QString formatDateTime(const QDateTime &pDateTime) const;
47 QString formatDateTime(const QDateTime &pDateTime,
48 bool shortFormat,
49 bool includeSecs = false) const;
50
51 QDate readDate(const QString &str, bool* ok = 0) const;
52 QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const;
53 QTime readTime(const QString &str, bool* ok = 0) const;
54
55 bool use12Clock() const;
56 bool weekStartsMonday() const;
57 int weekStartDay() const;
58
59 QString weekDayName(int,bool=false) const;
60 QString monthName(int,bool=false) const;
61
62 QString country() const;
63
64 QString dateFormat() const;
65 QString dateFormatShort() const;
66 QString timeFormat() const;
67
68 void insertCatalogue ( const QString & );
69
70 KCalendarSystem *calendar();
71 void setHore24Format ( bool );
72 void setWeekStartMonday( bool );
73 void setIntDateFormat( int );
74 int getIntDateFormat( );
75 void setLanguage( int );
76 void setDateFormat( QString );
77 void setDateFormatShort( QString );
78
79 QString m_decimalSymbol;
80 QString m_thousandsSeparator;
81 QString m_currencySymbol;
82 QString m_monetaryDecimalSymbol;
83 QString m_monetaryThousandsSeparator;
84 QString m_positiveSign;
85 QString m_negativeSign;
86
87 int timezoneOffset( QString );
88 QStringList timeZoneList() const;
89 void setDaylightSaving( bool, int , int );
90 int localTimeOffset(const QDateTime &);
91 void setTimezone( const QString &timeZone );
92 private:
93 QTime readTime(const QString &str, bool seconds, bool *ok) const;
94 QDate readDate(const QString &str, bool shortFormat, bool *ok) const;
95 KCalendarSystem *mCalendarSystem;
96 bool mWeekStartsMonday;
97 bool mHourF24Format;
98 int mIntDateFormat;
99 int mLanguage;
100 QString mDateFormat;
101 QString mDateFormatShort;
102 QStringList mTimeZoneList;
103 bool daylightEnabled;
104 int mDaylightTZoffset;
105 int mNondaylightTZoffset;
106 bool mSouthDaylight;
107 int daylightStart, daylightEnd, mTimeZoneOffset;
108};
109
110#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 @@
1// -*- c-basic-offset: 2 -*-
2/* This file is part of the KDE libraries
3 Copyright (c) 1997,2001 Stephan Kulow <coolo@kde.org>
4 Copyright (c) 1999 Preston Brown <pbrown@kde.org>
5 Copyright (c) 1999-2002 Hans Petter Bieker <bieker@kde.org>
6 Copyright (c) 2002 Lukas Tinkl <lukas@kde.org>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
17
18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
22*/
23
24//US#include <config.h>
25
26#include <stdlib.h> // getenv
27#include <assert.h>
28
29#include <qtextcodec.h>
30#include <qfile.h>
31#include <qdict.h>
32#include <qprinter.h>
33#include <qdatetime.h>
34#include <qfileinfo.h>
35#include <qregexp.h>
36
37#include "kcatalogue.h"
38#include "kglobal.h"
39#include "kstandarddirs.h"
40#include "ksimpleconfig.h"
41//US #include "kinstance.h"
42#include "kconfig.h"
43#include "kconfigbase.h"
44#include "kdebug.h"
45#include "kcalendarsystem.h"
46
47//US we use no factory. Simply use the gregorian calendar
48//US #include "kcalendarsystemfactory.h"
49#include "kcalendarsystemgregorian.h"
50
51#include "klocale.h"
52
53static const char * const SYSTEM_MESSAGES = "kdelibs";
54
55static const char *maincatalogue = 0;
56
57QDict<char> *mLocaleDict = 0;
58
59void setLocaleDict( QDict<char> * dict )
60{
61 mLocaleDict = dict;
62
63}
64
65class KLocalePrivate
66{
67public:
68 int weekStartDay;
69 int plural_form;
70 bool nounDeclension;
71 bool dateMonthNamePossessive;
72 QStringList languageList;
73 QValueList<KCatalogue> catalogues;
74 QString encoding;
75 QTextCodec * codecForEncoding;
76 KConfig * config;
77 bool formatInited;
78 int /*QPrinter::PageSize*/ pageSize;
79 KLocale::MeasureSystem measureSystem;
80 QStringList langTwoAlpha;
81 KConfig *languages;
82
83 QString calendarType;
84 KCalendarSystem * calendar;
85 QString first_language;
86 bool utf8FileEncoding;
87};
88
89static KLocale *this_klocale = 0;
90
91KLocale::KLocale( const QString & catalogue, KConfig * config )
92{
93 d = new KLocalePrivate;
94 d->config = config;
95 d->languages = 0;
96 d->calendar = 0;
97
98 initCatalogue(catalogue);
99 initEncoding(0);
100 initFileNameEncoding(0);
101
102 KConfig *cfg = d->config;
103 this_klocale = this;
104//US if (!cfg) cfg = KGlobal::instance()->config();
105 if (!cfg) cfg = KGlobal::config();
106 this_klocale = 0;
107//US Q_ASSERT( cfg );
108 ASSERT( cfg );
109
110 if (m_language.isEmpty())
111 initLanguage(cfg, config == 0);
112
113
114/*US
115//US mDateFormat = "%a %Y %b %d";
116//US mDateFormatShort = "%Y-%m-%d";
117 mTimeZoneList << i18n ("-11:00 US/Samoa")
118 << i18n ("-10:00 US/Hawaii")
119 << i18n ("-09:00 US/Alaska")
120 << i18n ("-08:00 US/Pacific")
121 << i18n ("-07:00 US/Mountain")
122 << i18n ("-06:00 US/Central")
123 << i18n ("-05:00 US/Eastern")
124 << i18n ("-04:00 Brazil/West")
125 << i18n ("-03:00 Brazil/East")
126 << i18n ("-02:00 Brazil/DeNoronha")
127 << i18n ("-01:00 Atlantic/Azores")
128 << i18n (" 00:00 Europe/London(UTC)")
129 << i18n ("+01:00 Europe/Oslo(CET)")
130 << i18n ("+02:00 Europe/Helsinki")
131 << i18n ("+03:00 Europe/Moscow")
132 << i18n ("+04:00 Indian/Mauritius")
133 << i18n ("+05:00 Indian/Maldives")
134 << i18n ("+06:00 Indian/Chagos")
135 << i18n ("+07:00 Asia/Bangkok")
136 << i18n ("+08:00 Asia/Hongkong")
137 << i18n ("+09:00 Asia/Tokyo")
138 << i18n ("+10:00 Asia/Vladivostok")
139 << i18n ("+11:00 Asia/Magadan")
140 << i18n ("+12:00 Asia/Kamchatka")
141 // << i18n (" xx:xx User defined offset")
142 << i18n (" Local Time");
143*/
144 mTimeZoneList << "-11:00 US/Samoa"
145 << "-10:00 US/Hawaii"
146 << "-09:00 US/Alaska"
147 << "-08:00 US/Pacific"
148 << "-07:00 US/Mountain"
149 << "-06:00 US/Central"
150 << "-05:00 US/Eastern"
151 << "-04:00 Brazil/West"
152 << "-03:00 Brazil/East"
153 << "-02:00 Brazil/DeNoronha"
154 << "-01:00 Atlantic/Azores"
155 << " 00:00 Europe/London(UTC)"
156 << "+01:00 Europe/Oslo(CET)"
157 << "+02:00 Europe/Helsinki"
158 << "+03:00 Europe/Moscow"
159 << "+04:00 Indian/Mauritius"
160 << "+05:00 Indian/Maldives"
161 << "+06:00 Indian/Chagos"
162 << "+07:00 Asia/Bangkok"
163 << "+08:00 Asia/Hongkong"
164 << "+09:00 Asia/Tokyo"
165 << "+10:00 Asia/Vladivostok"
166 << "+11:00 Asia/Magadan"
167 << "+12:00 Asia/Kamchatka"
168 // << " xx:xx User defined offset"
169 << " Local Time";
170
171 mSouthDaylight = false;
172 mTimeZoneOffset = 0;
173 daylightEnabled = false;
174
175 mWeekStartsMonday = true;
176 mHourF24Format = true;
177 mIntDateFormat = 0;
178 mLanguage = 0;
179
180}
181
182
183QString KLocale::_initLanguage(KConfigBase *config)
184{
185 if (this_klocale)
186 {
187 // ### HPB Why this cast??
188 this_klocale->initLanguage((KConfig *) config, true);
189 return this_klocale->language();
190 }
191 return QString::null;
192}
193
194void KLocale::initCatalogue(const QString & catalogue)
195{
196 // Use the first non-null string.
197 QString mainCatalogue = catalogue;
198 if (maincatalogue)
199 mainCatalogue = QString::fromLatin1(maincatalogue);
200
201 if (mainCatalogue.isEmpty()) {
202 kdDebug(173) << "KLocale instance created called without valid "
203 << "catalogue! Give an argument or call setMainCatalogue "
204 << "before init" << endl;
205 }
206 else
207 d->catalogues.append( KCatalogue(mainCatalogue ) );
208
209 // always include kdelibs.mo
210 d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) );
211}
212
213void KLocale::initLanguage(KConfig * config, bool useEnv)
214{
215 KConfigGroupSaver saver(config, "Locale");
216
217 m_country = config->readEntry( "Country" );
218 if ( m_country.isEmpty() )
219 m_country = defaultCountry();
220
221 // Reset the list and add the new languages
222 QStringList languageList;
223 if ( useEnv )
224 languageList += QStringList::split
225 (':', QFile::decodeName( ::getenv("KDE_LANG") ));
226
227//US languageList += config->readListEntry("Language", ':');
228 languageList += config->readListEntry("Language");
229
230 // same order as setlocale use
231 if ( useEnv )
232 {
233 // HPB: Only run splitLocale on the environment variables..
234 QStringList langs;
235
236 langs << QFile::decodeName( ::getenv("LC_ALL") );
237 langs << QFile::decodeName( ::getenv("LC_MESSAGES") );
238 langs << QFile::decodeName( ::getenv("LANG") );
239 langs << QFile::decodeName( ::getenv("LC_CTYPE") );
240
241 for ( QStringList::Iterator it = langs.begin();
242 it != langs.end();
243 ++it )
244 {
245 QString ln, ct, chrset;
246 splitLocale(*it, ln, ct, chrset);
247
248 if (!ct.isEmpty()) {
249 langs.insert(it, ln + '_' + ct);
250 if (!chrset.isEmpty())
251 langs.insert(it, ln + '_' + ct + '.' + chrset);
252 }
253
254 langs.insert(it, ln);
255 }
256
257 languageList += langs;
258 }
259
260 // now we have a language list -- let's use the first OK language
261 setLanguage( languageList );
262}
263
264void KLocale::doBindInit()
265{
266 return; // LR
267 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
268 it != d->catalogues.end();
269 ++it )
270 initCatalogue( *it );
271
272 if ( useDefaultLanguage() )
273 d->plural_form = -1;
274 else
275 {
276 QString pf = translate_priv
277 ( I18N_NOOP("_: Dear translator, please do not translate this string "
278 "in any form, but pick the _right_ value out of "
279 "NoPlural/TwoForms/French... If not sure what to do mail "
280 "thd@kde.org and coolo@kde.org, they will tell you. "
281 "Better leave that out if unsure, the programs will "
282 "crash!!\nDefinition of PluralForm - to be set by the "
283 "translator of kdelibs.po"), 0);
284 if ( pf.isEmpty() ) {
285 kdWarning(173) << "found no definition of PluralForm for " << m_language << endl;
286 d->plural_form = -1;
287 } else if ( pf == "NoPlural" )
288 d->plural_form = 0;
289 else if ( pf == "TwoForms" )
290 d->plural_form = 1;
291 else if ( pf == "French" )
292 d->plural_form = 2;
293 else if ( pf == "OneTwoRest" || pf == "Gaeilge" ) // Gaelige is the old name
294 d->plural_form = 3;
295 else if ( pf == "Russian" )
296 d->plural_form = 4;
297 else if ( pf == "Polish" )
298 d->plural_form = 5;
299 else if ( pf == "Slovenian" )
300 d->plural_form = 6;
301 else if ( pf == "Lithuanian" )
302 d->plural_form = 7;
303 else if ( pf == "Czech" )
304 d->plural_form = 8;
305 else if ( pf == "Slovak" )
306 d->plural_form = 9;
307 else if ( pf == "Maltese" )
308 d->plural_form = 10;
309 else if ( pf == "Arabic" )
310 d->plural_form = 11;
311 else if ( pf == "Balcan" )
312 d->plural_form = 12;
313 else {
314 kdWarning(173) << "Definition of PluralForm is none of "
315 << "NoPlural/"
316 << "TwoForms/"
317 << "French/"
318 << "OneTwoRest/"
319 << "Russian/"
320 << "Polish/"
321 << "Slovenian/"
322 << "Lithuanian/"
323 << "Czech/"
324 << "Slovak/"
325 << "Arabic/"
326 << "Balcan/"
327 << "Maltese: " << pf << endl;
328 exit(1);
329 }
330 }
331
332 d->formatInited = false;
333}
334
335void KLocale::doFormatInit() const
336{
337 if ( d->formatInited ) return;
338
339 KLocale * that = const_cast<KLocale *>(this);
340 that->initFormat();
341
342 d->formatInited = true;
343}
344
345void KLocale::initFormat()
346{
347 KConfig *config = d->config;
348//US if (!config) config = KGlobal::instance()->config();
349 if (!config) config = KGlobal::config();
350 ASSERT( config );
351
352 kdDebug(173) << "KLocale::initFormat" << endl;
353
354 // make sure the config files are read using the correct locale
355 // ### Why not add a KConfigBase::setLocale( const KLocale * )?
356 // ### Then we could remove this hack
357//US
358//US KLocale *lsave = KGlobal::_locale;
359//US KGlobal::_locale = this;
360 KLocale *lsave = KGlobal::locale();
361 KGlobal::setLocale(this);
362
363 KConfigGroupSaver saver(config, "Locale");
364
365
366
367//US in kabc/adress.cpp we have a similar setup. Check there in case of problems
368 KSimpleConfig entry(locateLocal("locale",
369 QString::fromLatin1("l10n/%1/entry.desktop")
370 .arg(m_country)) );
371
372 entry.setGroup("KCM Locale");
373
374 // Numeric
375#define readConfigEntry(key, default, save) \
376 save = entry.readEntry(key, QString::fromLatin1(default)); \
377 save = config->readEntry(key, save);
378
379#define readConfigNumEntry(key, default, save, type) \
380 save = (type)entry.readNumEntry(key, default); \
381 save = (type)config->readNumEntry(key, save);
382
383#define readConfigBoolEntry(key, default, save) \
384 save = entry.readBoolEntry(key, default); \
385 save = config->readBoolEntry(key, save);
386
387 readConfigEntry("DecimalSymbol", ".", m_decimalSymbol);
388 readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator);
389 m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null );
390 //kdDebug(173) << "m_thousandsSeparator=" << m_thousandsSeparator << endl;
391
392 readConfigEntry("PositiveSign", "", m_positiveSign);
393 readConfigEntry("NegativeSign", "-", m_negativeSign);
394
395 // Monetary
396 readConfigEntry("CurrencySymbol", "$", m_currencySymbol);
397 readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol);
398 readConfigEntry("MonetaryThousandsSeparator", ",",
399 m_monetaryThousandsSeparator);
400 m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null);
401
402 readConfigNumEntry("FracDigits", 2, m_fracDigits, int);
403 readConfigBoolEntry("PositivePrefixCurrencySymbol", true,
404 m_positivePrefixCurrencySymbol);
405 readConfigBoolEntry("NegativePrefixCurrencySymbol", true,
406 m_negativePrefixCurrencySymbol);
407 readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney,
408 m_positiveMonetarySignPosition, SignPosition);
409 readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround,
410 m_negativeMonetarySignPosition, SignPosition);
411
412 //Grammatical
413 readConfigBoolEntry("NounDeclension", false, d->nounDeclension);
414
415 // Date and time
416 readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat);
417 readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat);
418 readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort);
419 readConfigBoolEntry("DateMonthNamePossessive", false,
420 d->dateMonthNamePossessive);
421 readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int);
422
423 // other
424//US readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int);
425 readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem,
426 MeasureSystem);
427 readConfigEntry("CalendarSystem", "gregorian", d->calendarType);
428 delete d->calendar;
429 d->calendar = 0; // ### HPB Is this the correct place?
430
431 // end of hack
432//US KGlobal::_locale = lsave;
433 KGlobal::setLocale(lsave);
434}
435
436bool KLocale::setCountry(const QString & country)
437{
438 // Check if the file exists too??
439 if ( country.isEmpty() )
440 return false;
441
442 m_country = country;
443
444 d->formatInited = false;
445
446 return true;
447}
448
449QString KLocale::catalogueFileName(const QString & language,
450 const KCatalogue & catalogue)
451{
452 QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo")
453 .arg( language )
454 .arg( catalogue.name() );
455
456 return locate( "locale", path );
457}
458
459bool KLocale::isLanguageInstalled(const QString & language) const
460{
461 // Do not allow empty languages
462 if ( language.isEmpty() ) return false;
463
464 bool bRes = true;
465 if ( language != defaultLanguage() )
466 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
467 it != d->catalogues.end() && bRes;
468 ++it )
469 {
470 bRes = !catalogueFileName( language, *it ).isNull();
471 if ( !bRes )
472 kdDebug(173) << "message catalogue not found: "
473 << (*it).name() << endl;
474 }
475
476 return bRes;
477}
478
479bool KLocale::setLanguage(const QString & language)
480{
481 bool bRes = true;
482
483 if (d->first_language.isNull() || language != d->first_language)
484 bRes = isLanguageInstalled( language );
485
486 if ( bRes )
487 {
488 m_language = language;
489
490 // remember our first time - it will be our true love
491 if (d->first_language.isNull())
492 d->first_language = language;
493
494 doBindInit();
495 }
496
497 return bRes;
498}
499
500bool KLocale::setLanguage(const QStringList & languages)
501{
502 QStringList languageList(languages);
503
504 // Remove duplicate entries in reverse so that we
505 // can keep user's language preference order intact. (DA)
506 for( QStringList::Iterator it = languageList.fromLast();
507 it != languageList.begin();
508 --it )
509 if ( languageList.contains(*it) > 1 || (*it).isEmpty() )
510 it = languageList.remove( it );
511
512 bool bRes = false;
513 for ( QStringList::ConstIterator it = languageList.begin();
514 it != languageList.end();
515 ++it )
516 if ( bRes = setLanguage( *it ) )
517 break;
518
519 if ( !bRes )
520 setLanguage(defaultLanguage());
521
522 d->languageList = languageList;
523 d->langTwoAlpha.clear(); // Flush cache
524
525 return bRes;
526}
527
528void KLocale::splitLocale(const QString & aStr,
529 QString & language,
530 QString & country,
531 QString & chrset)
532{
533 QString str = aStr;
534
535 // just in case, there is another language appended
536 int f = str.find(':');
537 if (f >= 0)
538 str.truncate(f);
539
540 country = QString::null;
541 chrset = QString::null;
542 language = QString::null;
543
544 f = str.find('.');
545 if (f >= 0)
546 {
547 chrset = str.mid(f + 1);
548 str.truncate(f);
549 }
550
551 f = str.find('_');
552 if (f >= 0)
553 {
554 country = str.mid(f + 1);
555 str.truncate(f);
556 }
557
558 language = str;
559}
560
561QString KLocale::language() const
562{
563 return m_language;
564}
565
566QString KLocale::country() const
567{
568 return m_country;
569}
570
571QString KLocale::monthName(int i, bool shortName) const
572{
573 if ( shortName )
574 switch ( i )
575 {
576 case 1: return translate("January", "Jan");
577 case 2: return translate("February", "Feb");
578 case 3: return translate("March", "Mar");
579 case 4: return translate("April", "Apr");
580 case 5: return translate("May short", "May");
581 case 6: return translate("June", "Jun");
582 case 7: return translate("July", "Jul");
583 case 8: return translate("August", "Aug");
584 case 9: return translate("September", "Sep");
585 case 10: return translate("October", "Oct");
586 case 11: return translate("November", "Nov");
587 case 12: return translate("December", "Dec");
588 }
589 else
590 switch (i)
591 {
592 case 1: return translate("January");
593 case 2: return translate("February");
594 case 3: return translate("March");
595 case 4: return translate("April");
596 case 5: return translate("May long", "May");
597 case 6: return translate("June");
598 case 7: return translate("July");
599 case 8: return translate("August");
600 case 9: return translate("September");
601 case 10: return translate("October");
602 case 11: return translate("November");
603 case 12: return translate("December");
604 }
605
606 return QString::null;
607}
608
609QString KLocale::monthNamePossessive(int i, bool shortName) const
610{
611 if ( shortName )
612 switch ( i )
613 {
614 case 1: return translate("of January", "of Jan");
615 case 2: return translate("of February", "of Feb");
616 case 3: return translate("of March", "of Mar");
617 case 4: return translate("of April", "of Apr");
618 case 5: return translate("of May short", "of May");
619 case 6: return translate("of June", "of Jun");
620 case 7: return translate("of July", "of Jul");
621 case 8: return translate("of August", "of Aug");
622 case 9: return translate("of September", "of Sep");
623 case 10: return translate("of October", "of Oct");
624 case 11: return translate("of November", "of Nov");
625 case 12: return translate("of December", "of Dec");
626 }
627 else
628 switch (i)
629 {
630 case 1: return translate("of January");
631 case 2: return translate("of February");
632 case 3: return translate("of March");
633 case 4: return translate("of April");
634 case 5: return translate("of May long", "of May");
635 case 6: return translate("of June");
636 case 7: return translate("of July");
637 case 8: return translate("of August");
638 case 9: return translate("of September");
639 case 10: return translate("of October");
640 case 11: return translate("of November");
641 case 12: return translate("of December");
642 }
643
644 return QString::null;
645}
646
647QString KLocale::weekDayName (int i, bool shortName) const
648{
649 if ( shortName )
650 switch ( i )
651 {
652 case 1: return translate("Monday", "Mon");
653 case 2: return translate("Tuesday", "Tue");
654 case 3: return translate("Wednesday", "Wed");
655 case 4: return translate("Thursday", "Thu");
656 case 5: return translate("Friday", "Fri");
657 case 6: return translate("Saturday", "Sat");
658 case 7: return translate("Sunday", "Sun");
659 }
660 else
661 switch ( i )
662 {
663 case 1: return translate("Monday");
664 case 2: return translate("Tuesday");
665 case 3: return translate("Wednesday");
666 case 4: return translate("Thursday");
667 case 5: return translate("Friday");
668 case 6: return translate("Saturday");
669 case 7: return translate("Sunday");
670 }
671
672 return QString::null;
673}
674
675void KLocale::insertCatalogue( const QString & catalogue )
676{
677 KCatalogue cat( catalogue );
678
679 initCatalogue( cat );
680
681 d->catalogues.append( cat );
682}
683
684void KLocale::removeCatalogue(const QString &catalogue)
685{
686 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
687 it != d->catalogues.end(); )
688 if ((*it).name() == catalogue) {
689 it = d->catalogues.remove(it);
690 return;
691 } else
692 ++it;
693}
694
695void KLocale::setActiveCatalogue(const QString &catalogue)
696{
697 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
698 it != d->catalogues.end(); ++it)
699 if ((*it).name() == catalogue) {
700 KCatalogue save = *it;
701 d->catalogues.remove(it);
702 d->catalogues.prepend(save);
703 return;
704 }
705}
706
707KLocale::~KLocale()
708{
709 delete d->languages;
710 delete d;
711}
712
713QString KLocale::translate_priv(const char *msgid,
714 const char *fallback,
715 const char **translated) const
716{
717 if (!msgid || !msgid[0])
718 {
719 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
720 << "Fix the program" << endl;
721 return QString::null;
722 }
723
724 if ( useDefaultLanguage() )
725 return QString::fromUtf8( fallback );
726
727 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
728 it != d->catalogues.end();
729 ++it )
730 {
731 // kdDebug(173) << "translate " << msgid << " " << (*it).name() << " " << (!KGlobal::activeInstance() ? QCString("no instance") : KGlobal::activeInstance()->instanceName()) << endl;
732 const char * text = (*it).translate( msgid );
733
734 if ( text )
735 {
736 // we found it
737 if (translated)
738 *translated = text;
739 return QString::fromUtf8( text );
740 }
741 }
742
743 // Always use UTF-8 if the string was not found
744 return QString::fromUtf8( fallback );
745}
746
747QString KLocale::translate(const char* msgid) const
748{
749 return translate_priv(msgid, msgid);
750}
751
752QString KLocale::translate( const char *index, const char *fallback) const
753{
754 if (!index || !index[0] || !fallback || !fallback[0])
755 {
756 kdDebug(173) << "KLocale: trying to look up \"\" in catalogue. "
757 << "Fix the program" << endl;
758 return QString::null;
759 }
760
761 if ( useDefaultLanguage() )
762 return QString::fromUtf8( fallback );
763
764 char *newstring = new char[strlen(index) + strlen(fallback) + 5];
765 sprintf(newstring, "_: %s\n%s", index, fallback);
766 // as copying QString is very fast, it looks slower as it is ;/
767 QString r = translate_priv(newstring, fallback);
768 delete [] newstring;
769
770 return r;
771}
772
773static QString put_n_in(const QString &orig, unsigned long n)
774{
775 QString ret = orig;
776 int index = ret.find("%n");
777 if (index == -1)
778 return ret;
779 ret.replace(index, 2, QString::number(n));
780 return ret;
781}
782
783#define EXPECT_LENGTH(x) \
784 if (forms.count() != x) { \
785 kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \
786 return QString( "BROKEN TRANSLATION %1" ).arg( singular ); }
787
788QString KLocale::translate( const char *singular, const char *plural,
789 unsigned long n ) const
790{
791 if (!singular || !singular[0] || !plural || !plural[0])
792 {
793 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
794 << "Fix the program" << endl;
795 return QString::null;
796 }
797
798 char *newstring = new char[strlen(singular) + strlen(plural) + 6];
799 sprintf(newstring, "_n: %s\n%s", singular, plural);
800 // as copying QString is very fast, it looks slower as it is ;/
801 QString r = translate_priv(newstring, 0);
802 delete [] newstring;
803
804 if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) {
805 if ( n == 1 ) {
806 return put_n_in( QString::fromUtf8( singular ), n );
807 } else {
808 QString tmp = QString::fromUtf8( plural );
809#ifndef NDEBUG
810 if (tmp.find("%n") == -1) {
811 kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl;
812 }
813#endif
814 return put_n_in( tmp, n );
815 }
816 }
817
818 QStringList forms = QStringList::split( "\n", r, false );
819 switch ( d->plural_form ) {
820 case 0: // NoPlural
821 EXPECT_LENGTH( 1 );
822 return put_n_in( forms[0], n);
823 case 1: // TwoForms
824 EXPECT_LENGTH( 2 );
825 if ( n == 1 )
826 return put_n_in( forms[0], n);
827 else
828 return put_n_in( forms[1], n);
829 case 2: // French
830 EXPECT_LENGTH( 2 );
831 if ( n == 1 || n == 0 )
832 return put_n_in( forms[0], n);
833 else
834 return put_n_in( forms[1], n);
835 case 3: // Gaeilge
836 EXPECT_LENGTH( 3 );
837 if ( n == 1 )
838 return put_n_in( forms[0], n);
839 else if ( n == 2 )
840 return put_n_in( forms[1], n);
841 else
842 return put_n_in( forms[2], n);
843 case 4: // Russian, corrected by mok
844 EXPECT_LENGTH( 3 );
845 if ( n%10 == 1 && n%100 != 11)
846 return put_n_in( forms[0], n); // odin fail
847 else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20))
848 return put_n_in( forms[1], n); // dva faila
849 else
850 return put_n_in( forms[2], n); // desyat' failov
851 case 5: // Polish
852 EXPECT_LENGTH( 3 );
853 if ( n == 1 )
854 return put_n_in( forms[0], n);
855 else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) )
856 return put_n_in( forms[1], n);
857 else
858 return put_n_in( forms[2], n);
859 case 6: // Slovenian
860 EXPECT_LENGTH( 4 );
861 if ( n%100 == 1 )
862 return put_n_in( forms[1], n); // ena datoteka
863 else if ( n%100 == 2 )
864 return put_n_in( forms[2], n); // dve datoteki
865 else if ( n%100 == 3 || n%100 == 4 )
866 return put_n_in( forms[3], n); // tri datoteke
867 else
868 return put_n_in( forms[0], n); // sto datotek
869 case 7: // Lithuanian
870 EXPECT_LENGTH( 3 );
871 if ( n%10 == 0 || (n%100>=11 && n%100<=19) )
872 return put_n_in( forms[2], n);
873 else if ( n%10 == 1 )
874 return put_n_in( forms[0], n);
875 else
876 return put_n_in( forms[1], n);
877 case 8: // Czech
878 EXPECT_LENGTH( 3 );
879 if ( n%100 == 1 )
880 return put_n_in( forms[0], n);
881 else if (( n%100 >= 2 ) && ( n%100 <= 4 ))
882 return put_n_in( forms[1], n);
883 else
884 return put_n_in( forms[2], n);
885 case 9: // Slovak
886 EXPECT_LENGTH( 3 );
887 if ( n == 1 )
888 return put_n_in( forms[0], n);
889 else if (( n >= 2 ) && ( n <= 4 ))
890 return put_n_in( forms[1], n);
891 else
892 return put_n_in( forms[2], n);
893 case 10: // Maltese
894 EXPECT_LENGTH( 4 );
895 if ( n == 1 )
896 return put_n_in( forms[0], n );
897 else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) )
898 return put_n_in( forms[1], n );
899 else if ( n%100 > 10 && n%100 < 20 )
900 return put_n_in( forms[2], n );
901 else
902 return put_n_in( forms[3], n );
903 case 11: // Arabic
904 EXPECT_LENGTH( 4 );
905 if (n == 1)
906 return put_n_in(forms[0], n);
907 else if (n == 2)
908 return put_n_in(forms[1], n);
909 else if ( n < 11)
910 return put_n_in(forms[2], n);
911 else
912 return put_n_in(forms[3], n);
913 case 12: // Balcan
914 EXPECT_LENGTH( 3 );
915 if (n != 11 && n % 10 == 1)
916 return put_n_in(forms[0], n);
917 else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4)
918 return put_n_in(forms[1], n);
919 else
920 return put_n_in(forms[2], n);
921 }
922 kdError() << "The function should have been returned in another way\n";
923
924 return QString::null;
925}
926
927QString KLocale::translateQt( const char *context, const char *source,
928 const char *message) const
929{
930 if (!source || !source[0]) {
931 kdWarning() << "KLocale: trying to look up \"\" in catalogue. "
932 << "Fix the program" << endl;
933 return QString::null;
934 }
935
936 if ( useDefaultLanguage() ) {
937 return QString::null;
938 }
939
940 char *newstring = 0;
941 const char *translation = 0;
942 QString r;
943
944 if ( message && message[0]) {
945 char *newstring = new char[strlen(source) + strlen(message) + 5];
946 sprintf(newstring, "_: %s\n%s", source, message);
947 const char *translation = 0;
948 // as copying QString is very fast, it looks slower as it is ;/
949 r = translate_priv(newstring, source, &translation);
950 delete [] newstring;
951 if (translation)
952 return r;
953 }
954
955 if ( context && context[0] && message && message[0]) {
956 newstring = new char[strlen(context) + strlen(message) + 5];
957 sprintf(newstring, "_: %s\n%s", context, message);
958 // as copying QString is very fast, it looks slower as it is ;/
959 r = translate_priv(newstring, source, &translation);
960 delete [] newstring;
961 if (translation)
962 return r;
963 }
964
965 r = translate_priv(source, source, &translation);
966 if (translation)
967 return r;
968 return QString::null;
969}
970
971bool KLocale::nounDeclension() const
972{
973 doFormatInit();
974 return d->nounDeclension;
975}
976
977bool KLocale::dateMonthNamePossessive() const
978{
979 doFormatInit();
980 return d->dateMonthNamePossessive;
981}
982
983int KLocale::weekStartDay() const
984{
985 doFormatInit();
986 return d->weekStartDay;
987}
988
989bool KLocale::weekStartsMonday() const //deprecated
990{
991 doFormatInit();
992 return (d->weekStartDay==1);
993}
994
995QString KLocale::decimalSymbol() const
996{
997 doFormatInit();
998 return m_decimalSymbol;
999}
1000
1001QString KLocale::thousandsSeparator() const
1002{
1003 doFormatInit();
1004 return m_thousandsSeparator;
1005}
1006
1007QString KLocale::currencySymbol() const
1008{
1009 doFormatInit();
1010 return m_currencySymbol;
1011}
1012
1013QString KLocale::monetaryDecimalSymbol() const
1014{
1015 doFormatInit();
1016 return m_monetaryDecimalSymbol;
1017}
1018
1019QString KLocale::monetaryThousandsSeparator() const
1020{
1021 doFormatInit();
1022 return m_monetaryThousandsSeparator;
1023}
1024
1025QString KLocale::positiveSign() const
1026{
1027 doFormatInit();
1028 return m_positiveSign;
1029}
1030
1031QString KLocale::negativeSign() const
1032{
1033 doFormatInit();
1034 return m_negativeSign;
1035}
1036
1037int KLocale::fracDigits() const
1038{
1039 doFormatInit();
1040 return m_fracDigits;
1041}
1042
1043bool KLocale::positivePrefixCurrencySymbol() const
1044{
1045 doFormatInit();
1046 return m_positivePrefixCurrencySymbol;
1047}
1048
1049bool KLocale::negativePrefixCurrencySymbol() const
1050{
1051 doFormatInit();
1052 return m_negativePrefixCurrencySymbol;
1053}
1054
1055KLocale::SignPosition KLocale::positiveMonetarySignPosition() const
1056{
1057 doFormatInit();
1058 return m_positiveMonetarySignPosition;
1059}
1060
1061KLocale::SignPosition KLocale::negativeMonetarySignPosition() const
1062{
1063 doFormatInit();
1064 return m_negativeMonetarySignPosition;
1065}
1066
1067static inline void put_it_in( QChar *buffer, uint& index, const QString &s )
1068{
1069 for ( uint l = 0; l < s.length(); l++ )
1070 buffer[index++] = s.at( l );
1071}
1072
1073static inline void put_it_in( QChar *buffer, uint& index, int number )
1074{
1075 buffer[index++] = number / 10 + '0';
1076 buffer[index++] = number % 10 + '0';
1077}
1078
1079QString KLocale::formatMoney(double num,
1080 const QString & symbol,
1081 int precision) const
1082{
1083 // some defaults
1084 QString currency = symbol.isNull()
1085 ? currencySymbol()
1086 : symbol;
1087 if (precision < 0) precision = fracDigits();
1088
1089 // the number itself
1090 bool neg = num < 0;
1091 QString res = QString::number(neg?-num:num, 'f', precision);
1092 int pos = res.find('.');
1093 if (pos == -1) pos = res.length();
1094 else res.replace(pos, 1, monetaryDecimalSymbol());
1095
1096 while (0 < (pos -= 3))
1097 res.insert(pos, monetaryThousandsSeparator()); // thousend sep
1098
1099 // set some variables we need later
1100 int signpos = neg
1101 ? negativeMonetarySignPosition()
1102 : positiveMonetarySignPosition();
1103 QString sign = neg
1104 ? negativeSign()
1105 : positiveSign();
1106
1107 switch (signpos)
1108 {
1109 case ParensAround:
1110 res.prepend('(');
1111 res.append (')');
1112 break;
1113 case BeforeQuantityMoney:
1114 res.prepend(sign);
1115 break;
1116 case AfterQuantityMoney:
1117 res.append(sign);
1118 break;
1119 case BeforeMoney:
1120 currency.prepend(sign);
1121 break;
1122 case AfterMoney:
1123 currency.append(sign);
1124 break;
1125 }
1126
1127 if (neg?negativePrefixCurrencySymbol():
1128 positivePrefixCurrencySymbol())
1129 {
1130 res.prepend(' ');
1131 res.prepend(currency);
1132 } else {
1133 res.append (' ');
1134 res.append (currency);
1135 }
1136
1137 return res;
1138}
1139
1140QString KLocale::formatMoney(const QString &numStr) const
1141{
1142 return formatMoney(numStr.toDouble());
1143}
1144
1145QString KLocale::formatNumber(double num, int precision) const
1146{
1147 bool neg = num < 0;
1148 if (precision == -1) precision = 2;
1149 QString res = QString::number(neg?-num:num, 'f', precision);
1150 int pos = res.find('.');
1151 if (pos == -1) pos = res.length();
1152 else res.replace(pos, 1, decimalSymbol());
1153
1154 while (0 < (pos -= 3))
1155 res.insert(pos, thousandsSeparator()); // thousand sep
1156
1157 // How can we know where we should put the sign?
1158 res.prepend(neg?negativeSign():positiveSign());
1159
1160 return res;
1161}
1162
1163QString KLocale::formatLong(long num) const
1164{
1165 return formatNumber((double)num, 0);
1166}
1167
1168QString KLocale::formatNumber(const QString &numStr) const
1169{
1170 return formatNumber(numStr.toDouble());
1171}
1172
1173QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
1174{
1175 const QString rst = shortFormat?dateFormatShort():dateFormat();
1176
1177 // I'm rather safe than sorry
1178 QChar *buffer = new QChar[rst.length() * 3 / 2 + 50];
1179
1180 unsigned int index = 0;
1181 bool escape = false;
1182 int number = 0;
1183
1184 int year = calendar()->year(pDate);
1185 int month = calendar()->month(pDate);
1186 int day = calendar()->day(pDate);
1187
1188 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
1189 {
1190 if ( !escape )
1191 {
1192 if ( rst.at( format_index ).unicode() == '%' )
1193 escape = true;
1194 else
1195 buffer[index++] = rst.at( format_index );
1196 }
1197 else
1198 {
1199 switch ( rst.at( format_index ).unicode() )
1200 {
1201 case '%':
1202 buffer[index++] = '%';
1203 break;
1204 case 'Y':
1205 put_it_in( buffer, index, year / 100 );
1206 case 'y':
1207 put_it_in( buffer, index, year % 100 );
1208 break;
1209 case 'n':
1210 number = month;
1211 case 'e':
1212 // to share the code
1213 if ( rst.at( format_index ).unicode() == 'e' )
1214 number = day;
1215 if ( number / 10 )
1216 buffer[index++] = number / 10 + '0';
1217 buffer[index++] = number % 10 + '0';
1218 break;
1219 case 'm':
1220 put_it_in( buffer, index, month );
1221 break;
1222 case 'b':
1223 if (d->nounDeclension && d->dateMonthNamePossessive)
1224 //US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, true) );
1225 put_it_in( buffer, index, calendar()->monthNamePossessive(month, true) );
1226 else
1227 //US put_it_in( buffer, index, calendar()->monthName(month, year, true) );
1228 put_it_in( buffer, index, calendar()->monthName(month, true) );
1229 break;
1230 case 'B':
1231 if (d->nounDeclension && d->dateMonthNamePossessive)
1232 //US put_it_in( buffer, index, calendar()->monthNamePossessive(month, year, false) );
1233 put_it_in( buffer, index, calendar()->monthNamePossessive(month, false) );
1234 else
1235 //US put_it_in( buffer, index, calendar()->monthName(month, year, false) );
1236 put_it_in( buffer, index, calendar()->monthName(month, false) );
1237 break;
1238 case 'd':
1239 put_it_in( buffer, index, day );
1240 break;
1241 case 'a':
1242 put_it_in( buffer, index, calendar()->weekDayName(pDate, true) );
1243 break;
1244 case 'A':
1245 put_it_in( buffer, index, calendar()->weekDayName(pDate, false) );
1246 break;
1247 default:
1248 buffer[index++] = rst.at( format_index );
1249 break;
1250 }
1251 escape = false;
1252 }
1253 }
1254 QString ret( buffer, index );
1255 delete [] buffer;
1256 return ret;
1257}
1258
1259void KLocale::setMainCatalogue(const char *catalogue)
1260{
1261 maincatalogue = catalogue;
1262}
1263
1264double KLocale::readNumber(const QString &_str, bool * ok) const
1265{
1266 QString str = _str.stripWhiteSpace();
1267 bool neg = str.find(negativeSign()) == 0;
1268 if (neg)
1269 str.remove( 0, negativeSign().length() );
1270
1271 /* will hold the scientific notation portion of the number.
1272 Example, with 2.34E+23, exponentialPart == "E+23"
1273 */
1274 QString exponentialPart;
1275 int EPos;
1276
1277 EPos = str.find('E', 0, false);
1278
1279 if (EPos != -1)
1280 {
1281 exponentialPart = str.mid(EPos);
1282 str = str.left(EPos);
1283 }
1284
1285 int pos = str.find(decimalSymbol());
1286 QString major;
1287 QString minor;
1288 if ( pos == -1 )
1289 major = str;
1290 else
1291 {
1292 major = str.left(pos);
1293 minor = str.mid(pos + decimalSymbol().length());
1294 }
1295
1296 // Remove thousand separators
1297 int thlen = thousandsSeparator().length();
1298 int lastpos = 0;
1299 while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
1300 {
1301 // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
1302 int fromEnd = major.length() - pos;
1303 if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
1304 || pos - lastpos > 3 // More than 3 digits between two separators -> error
1305 || pos == 0 // Can't start with a separator
1306 || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
1307 {
1308 if (ok) *ok = false;
1309 return 0.0;
1310 }
1311
1312 lastpos = pos;
1313 major.remove( pos, thlen );
1314 }
1315 if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
1316 {
1317 if (ok) *ok = false;
1318 return 0.0;
1319 }
1320
1321 QString tot;
1322 if (neg) tot = '-';
1323
1324 tot += major + '.' + minor + exponentialPart;
1325
1326 return tot.toDouble(ok);
1327}
1328
1329double KLocale::readMoney(const QString &_str, bool * ok) const
1330{
1331 QString str = _str.stripWhiteSpace();
1332 bool neg = false;
1333 bool currencyFound = false;
1334 // First try removing currency symbol from either end
1335 int pos = str.find(currencySymbol());
1336 if ( pos == 0 || pos == (int) str.length()-1 )
1337 {
1338 str.remove(pos,currencySymbol().length());
1339 str = str.stripWhiteSpace();
1340 currencyFound = true;
1341 }
1342 if (str.isEmpty())
1343 {
1344 if (ok) *ok = false;
1345 return 0;
1346 }
1347 // Then try removing negative sign from either end
1348 // (with a special case for parenthesis)
1349 if (negativeMonetarySignPosition() == ParensAround)
1350 {
1351 if (str.at(0) == '(' && str.at(str.length()-1) == ')')
1352 {
1353 neg = true;
1354 str.remove(str.length()-1,1);
1355 str.remove(0,1);
1356 }
1357 }
1358 else
1359 {
1360 int i1 = str.find(negativeSign());
1361 if ( i1 == 0 || i1 == (int) str.length()-1 )
1362 {
1363 neg = true;
1364 str.remove(i1,negativeSign().length());
1365 }
1366 }
1367 if (neg) str = str.stripWhiteSpace();
1368
1369 // Finally try again for the currency symbol, if we didn't find
1370 // it already (because of the negative sign being in the way).
1371 if ( !currencyFound )
1372 {
1373 pos = str.find(currencySymbol());
1374 if ( pos == 0 || pos == (int) str.length()-1 )
1375 {
1376 str.remove(pos,currencySymbol().length());
1377 str = str.stripWhiteSpace();
1378 }
1379 }
1380
1381 // And parse the rest as a number
1382 pos = str.find(monetaryDecimalSymbol());
1383 QString major;
1384 QString minior;
1385 if (pos == -1)
1386 major = str;
1387 else
1388 {
1389 major = str.left(pos);
1390 minior = str.mid(pos + monetaryDecimalSymbol().length());
1391 }
1392
1393 // Remove thousand separators
1394 int thlen = monetaryThousandsSeparator().length();
1395 int lastpos = 0;
1396 while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 )
1397 {
1398 // e.g. 12,,345,,678,,922 Acceptable positions (from the end) are 5, 10, 15... i.e. (3+thlen)*N
1399 int fromEnd = major.length() - pos;
1400 if ( fromEnd % (3+thlen) != 0 // Needs to be a multiple, otherwise it's an error
1401 || pos - lastpos > 3 // More than 3 digits between two separators -> error
1402 || pos == 0 // Can't start with a separator
1403 || (lastpos>0 && pos-lastpos!=3)) // Must have exactly 3 digits between two separators
1404 {
1405 if (ok) *ok = false;
1406 return 0.0;
1407 }
1408 lastpos = pos;
1409 major.remove( pos, thlen );
1410 }
1411 if (lastpos>0 && major.length()-lastpos!=3) // Must have exactly 3 digits after the last separator
1412 {
1413 if (ok) *ok = false;
1414 return 0.0;
1415 }
1416
1417 QString tot;
1418 if (neg) tot = '-';
1419 tot += major + '.' + minior;
1420 return tot.toDouble(ok);
1421}
1422
1423/**
1424 * helper function to read integers
1425 * @param str
1426 * @param pos the position to start at. It will be updated when we parse it.
1427 * @return the integer read in the string, or -1 if no string
1428 */
1429static int readInt(const QString &str, uint &pos)
1430{
1431 if (!str.at(pos).isDigit()) return -1;
1432 int result = 0;
1433 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
1434 {
1435 result *= 10;
1436 result += str.at(pos).digitValue();
1437 }
1438
1439 return result;
1440}
1441
1442QDate KLocale::readDate(const QString &intstr, bool* ok) const
1443{
1444 QDate date;
1445 date = readDate(intstr, ShortFormat, ok);
1446 if (date.isValid()) return date;
1447 return readDate(intstr, NormalFormat, ok);
1448}
1449
1450QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const
1451{
1452 QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
1453 return readDate( intstr, fmt, ok );
1454}
1455
1456QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
1457{
1458 //kdDebug() << "KLocale::readDate intstr=" << intstr << " fmt=" << fmt << endl;
1459 QString str = intstr.simplifyWhiteSpace().lower();
1460 int day = -1, month = -1;
1461 // allow the year to be omitted if not in the format
1462 int year = calendar()->year(QDate::currentDate());
1463 uint strpos = 0;
1464 uint fmtpos = 0;
1465
1466 bool error = false;
1467
1468 while (fmt.length() > fmtpos && str.length() > strpos && !error)
1469 {
1470
1471 QChar c = fmt.at(fmtpos++);
1472
1473 if (c != '%') {
1474 if (c.isSpace() && str.at(strpos).isSpace())
1475 strpos++;
1476 else if (c != str.at(strpos++))
1477 error = true;
1478 }
1479 else
1480 {
1481 int j;
1482 // remove space at the begining
1483 if (str.length() > strpos && str.at(strpos).isSpace())
1484 strpos++;
1485
1486 c = fmt.at(fmtpos++);
1487 switch (c)
1488 {
1489 case 'a':
1490 case 'A':
1491
1492 error = true;
1493 j = 1;
1494 while (error && (j < 8)) {
1495 QString s = weekDayName(j, c == 'a').lower();
1496 int len = s.length();
1497 if (str.mid(strpos, len) == s)
1498 {
1499 strpos += len;
1500 error = false;
1501 }
1502 j++;
1503 }
1504 break;
1505 case 'b':
1506 case 'B':
1507
1508 error = true;
1509 if (d->nounDeclension && d->dateMonthNamePossessive) {
1510 j = 1;
1511 while (error && (j < 13)) {
1512 //US QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower();
1513 QString s = calendar()->monthNamePossessive(j, c == 'b').lower();
1514 int len = s.length();
1515 if (str.mid(strpos, len) == s) {
1516 month = j;
1517 strpos += len;
1518 error = false;
1519 }
1520 j++;
1521 }
1522 }
1523 j = 1;
1524 while (error && (j < 13)) {
1525 //US QString s = calendar()->monthName(j, year, c == 'b').lower();
1526 QString s = calendar()->monthName(j, c == 'b').lower();
1527 int len = s.length();
1528 if (str.mid(strpos, len) == s) {
1529 month = j;
1530 strpos += len;
1531 error = false;
1532 }
1533 j++;
1534 }
1535 break;
1536 case 'd':
1537 case 'e':
1538 day = readInt(str, strpos);
1539 error = (day < 1 || day > 31);
1540 break;
1541
1542 case 'n':
1543 case 'm':
1544 month = readInt(str, strpos);
1545 error = (month < 1 || month > 12);
1546 break;
1547
1548 case 'Y':
1549 case 'y':
1550 year = readInt(str, strpos);
1551 error = (year < 0);
1552 // Qt treats a year in the range 0-100 as 1900-1999.
1553 // It is nicer for the user if we treat 0-68 as 2000-2068
1554 if (c == 'y' && year < 69)
1555 // eg. gregorian += 2000
1556 year += (calendar()->year(QDate::currentDate()) / 100) * 100;
1557 else if (c == 'y' && year < 100)
1558 // eg. gregorian += 1900
1559 year += (calendar()->year(QDate::currentDate()) / 100) * 100 - 100;
1560 break;
1561 }
1562 }
1563 }
1564
1565 /* for a match, we should reach the end of both strings, not just one of
1566 them */
1567 if ( fmt.length() > fmtpos || str.length() > strpos )
1568 {
1569 error = true;
1570 }
1571
1572 //kdDebug(173) << "KLocale::readDate day=" << day << " month=" << month << " year=" << year << endl;
1573 if ( year != -1 && month != -1 && day != -1 && !error)
1574 {
1575 if (ok) *ok = true;
1576
1577 QDate result;
1578 calendar()->setYMD(result, year, month, day);
1579
1580 return result;
1581 }
1582 else
1583 {
1584 if (ok) *ok = false;
1585 return QDate(); // invalid date
1586 }
1587}
1588
1589QTime KLocale::readTime(const QString &intstr, bool *ok) const
1590{
1591 QTime _time;
1592 _time = readTime(intstr, WithSeconds, ok);
1593 if (_time.isValid()) return _time;
1594 return readTime(intstr, WithoutSeconds, ok);
1595}
1596
1597QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const
1598{
1599 QString str = intstr.simplifyWhiteSpace().lower();
1600 QString Format = timeFormat().simplifyWhiteSpace();
1601 if (flags & WithoutSeconds)
1602 {
1603//US remove not available in my QT version
1604//US Format.remove(QRegExp(".%S"));
1605 Format.replace(QRegExp(".%S"), "");
1606 }
1607
1608 int hour = -1, minute = -1;
1609 int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0; // don't require seconds
1610 bool g_12h = false;
1611 bool pm = false;
1612 uint strpos = 0;
1613 uint Formatpos = 0;
1614
1615 while (Format.length() > Formatpos || str.length() > strpos)
1616 {
1617 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
1618
1619 QChar c = Format.at(Formatpos++);
1620
1621 if (c != '%')
1622 {
1623 if (c.isSpace())
1624 strpos++;
1625 else if (c != str.at(strpos++))
1626 goto error;
1627 continue;
1628 }
1629
1630 // remove space at the begining
1631 if (str.length() > strpos && str.at(strpos).isSpace())
1632 strpos++;
1633
1634 c = Format.at(Formatpos++);
1635 switch (c)
1636 {
1637 case 'p':
1638 {
1639 QString s;
1640 s = translate("pm").lower();
1641 int len = s.length();
1642 if (str.mid(strpos, len) == s)
1643 {
1644 pm = true;
1645 strpos += len;
1646 }
1647 else
1648 {
1649 s = translate("am").lower();
1650 len = s.length();
1651 if (str.mid(strpos, len) == s) {
1652 pm = false;
1653 strpos += len;
1654 }
1655 else
1656 goto error;
1657 }
1658 }
1659 break;
1660
1661 case 'k':
1662 case 'H':
1663 g_12h = false;
1664 hour = readInt(str, strpos);
1665 if (hour < 0 || hour > 23)
1666 goto error;
1667
1668 break;
1669
1670 case 'l':
1671 case 'I':
1672 g_12h = true;
1673 hour = readInt(str, strpos);
1674 if (hour < 1 || hour > 12)
1675 goto error;
1676
1677 break;
1678
1679 case 'M':
1680 minute = readInt(str, strpos);
1681 if (minute < 0 || minute > 59)
1682 goto error;
1683
1684 break;
1685
1686 case 'S':
1687 second = readInt(str, strpos);
1688 if (second < 0 || second > 59)
1689 goto error;
1690
1691 break;
1692 }
1693 }
1694 if (g_12h) {
1695 hour %= 12;
1696 if (pm) hour += 12;
1697 }
1698
1699 if (ok) *ok = true;
1700 return QTime(hour, minute, second);
1701
1702 error:
1703 if (ok) *ok = false;
1704 return QTime(-1, -1, -1); // return invalid date if it didn't work
1705}
1706
1707QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
1708{
1709 const QString rst = timeFormat();
1710
1711 // only "pm/am" here can grow, the rest shrinks, but
1712 // I'm rather safe than sorry
1713 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
1714
1715 uint index = 0;
1716 bool escape = false;
1717 int number = 0;
1718
1719 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
1720 {
1721 if ( !escape )
1722 {
1723 if ( rst.at( format_index ).unicode() == '%' )
1724 escape = true;
1725 else
1726 buffer[index++] = rst.at( format_index );
1727 }
1728 else
1729 {
1730 switch ( rst.at( format_index ).unicode() )
1731 {
1732 case '%':
1733 buffer[index++] = '%';
1734 break;
1735 case 'H':
1736 put_it_in( buffer, index, pTime.hour() );
1737 break;
1738 case 'I':
1739 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
1740 break;
1741 case 'M':
1742 put_it_in( buffer, index, pTime.minute() );
1743 break;
1744 case 'S':
1745 if (includeSecs)
1746 put_it_in( buffer, index, pTime.second() );
1747 else if ( index > 0 )
1748 {
1749 // we remove the seperator sign before the seconds and
1750 // assume that works everywhere
1751 --index;
1752 break;
1753 }
1754 break;
1755 case 'k':
1756 number = pTime.hour();
1757 case 'l':
1758 // to share the code
1759 if ( rst.at( format_index ).unicode() == 'l' )
1760 number = (pTime.hour() + 11) % 12 + 1;
1761 if ( number / 10 )
1762 buffer[index++] = number / 10 + '0';
1763 buffer[index++] = number % 10 + '0';
1764 break;
1765 case 'p':
1766 {
1767 QString s;
1768 if ( pTime.hour() >= 12 )
1769 put_it_in( buffer, index, translate("pm") );
1770 else
1771 put_it_in( buffer, index, translate("am") );
1772 break;
1773 }
1774 default:
1775 buffer[index++] = rst.at( format_index );
1776 break;
1777 }
1778 escape = false;
1779 }
1780 }
1781 QString ret( buffer, index );
1782 delete [] buffer;
1783 return ret;
1784}
1785
1786bool KLocale::use12Clock() const
1787{
1788 if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) ||
1789 (timeFormat().contains(QString::fromLatin1("%l")) > 0))
1790 return true;
1791 else
1792 return false;
1793}
1794
1795QString KLocale::languages() const
1796{
1797 return d->languageList.join( QString::fromLatin1(":") );
1798}
1799
1800QStringList KLocale::languageList() const
1801{
1802 return d->languageList;
1803}
1804
1805QString KLocale::formatDateTime(const QDateTime &pDateTime,
1806 bool shortFormat,
1807 bool includeSeconds) const
1808{
1809 return translate("concatenation of dates and time", "%1 %2")
1810 .arg( formatDate( pDateTime.date(), shortFormat ) )
1811 .arg( formatTime( pDateTime.time(), includeSeconds ) );
1812}
1813
1814QString i18n(const char* text)
1815{
1816 /*
1817 register KLocale *instance = KGlobal::locale();
1818 if (instance)
1819 return instance->translate(text);
1820 */
1821 return QString::fromUtf8(text);
1822}
1823
1824QString i18n(const char* index, const char *text)
1825{
1826 /*
1827 register KLocale *instance = KGlobal::locale();
1828 if (instance)
1829 return instance->translate(index, text);
1830 */
1831 return QString::fromUtf8(text);
1832}
1833
1834QString i18n(const char* singular, const char* plural, unsigned long n)
1835{
1836 return (QString::fromUtf8(plural)); // hack! remove this line!
1837 register KLocale *instance = KGlobal::locale();
1838 if (instance)
1839 return instance->translate(singular, plural, n);
1840 if (n == 1)
1841 return put_n_in(QString::fromUtf8(singular), n);
1842 else
1843 return put_n_in(QString::fromUtf8(plural), n);
1844}
1845
1846void KLocale::initInstance()
1847{
1848 if (KGlobal::locale())
1849 return;
1850
1851/*US lets change the whole way how to create a KLocale
1852 KInstance *app = KGlobal::instance();
1853 if (app) {
1854 KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName()));
1855
1856 // only do this for the global instance
1857 QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding());
1858 }
1859 else
1860 kdDebug(173) << "no app name available using KLocale - nothing to do\n";
1861*/
1862//US new implementation
1863 QString appname = KGlobal::getAppName();
1864 if (appname) {
1865 KLocale *l = new KLocale(appname);
1866 KGlobal::setLocale(l);
1867
1868 // only do this for the global instance
1869//US
1870//US QTextCodec::setCodecForLocale(KGlobal::locale())->codecForEncoding());
1871//US qt_set_locale_codec( KGlobal::locale()->codecForEncoding() );
1872 qDebug("KLocale::initInstance we have to do here something !!!");
1873 }
1874 else
1875 kdDebug(173) << "no app name available using KLocale - nothing to do\n";
1876
1877}
1878
1879QString KLocale::langLookup(const QString &fname, const char *rtype)
1880{
1881 QStringList search;
1882
1883 // assemble the local search paths
1884//US we have only one resourcedir. So use it !!
1885/*US original
1886 const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype);
1887 // look up the different languages
1888 for (int id=localDoc.count()-1; id >= 0; --id)
1889 {
1890 QStringList langs = KGlobal::locale()->languageList();
1891 langs.append( "en" );
1892 langs.remove( defaultLanguage() );
1893 QStringList::ConstIterator lang;
1894 for (lang = langs.begin(); lang != langs.end(); ++lang)
1895 search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
1896 }
1897*/
1898//US new code
1899//US What is here correct??? const QString localDoc = KGlobal::dirs()->findResourceDir(rtype);
1900 const QString localDoc = rtype;
1901 // look up the different languages
1902 QStringList langs = KGlobal::locale()->languageList();
1903 langs.append( "en" );
1904 langs.remove( defaultLanguage() );
1905 QStringList::ConstIterator lang;
1906 for (lang = langs.begin(); lang != langs.end(); ++lang)
1907 search.append(QString("%1%2/%3").arg(localDoc).arg(*lang).arg(fname));
1908
1909 // try to locate the file
1910 QStringList::Iterator it;
1911 for (it = search.begin(); it != search.end(); ++it)
1912 {
1913 kdDebug(173) << "Looking for help in: " << *it << endl;
1914
1915 QFileInfo info(*it);
1916 if (info.exists() && info.isFile() && info.isReadable())
1917 return *it;
1918 }
1919
1920 return QString::null;
1921}
1922
1923bool KLocale::useDefaultLanguage() const
1924{
1925 return language() == defaultLanguage();
1926}
1927
1928void KLocale::initEncoding(KConfig *)
1929{
1930 const int mibDefault = 4; // ISO 8859-1
1931
1932 // This all made more sense when we still had the EncodingEnum config key.
1933 setEncoding( QTextCodec::codecForLocale()->mibEnum() );
1934
1935 if ( !d->codecForEncoding )
1936 {
1937 kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl;
1938 setEncoding(mibDefault);
1939 }
1940
1941 ASSERT( d->codecForEncoding );
1942}
1943
1944void KLocale::initFileNameEncoding(KConfig *)
1945{
1946 // If the following environment variable is set, assume all filenames
1947 // are in UTF-8 regardless of the current C locale.
1948 d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0;
1949 if (d->utf8FileEncoding)
1950 {
1951 QFile::setEncodingFunction(KLocale::encodeFileNameUTF8);
1952 QFile::setDecodingFunction(KLocale::decodeFileNameUTF8);
1953 }
1954 // Otherwise, stay with QFile's default filename encoding functions
1955 // which, on Unix platforms, use the locale's codec.
1956}
1957
1958QCString KLocale::encodeFileNameUTF8( const QString & fileName )
1959{
1960 return fileName.utf8();
1961}
1962
1963QString KLocale::decodeFileNameUTF8( const QCString & localFileName )
1964{
1965 return QString::fromUtf8(localFileName);
1966}
1967
1968void KLocale::initCatalogue( KCatalogue & catalogue )
1969{
1970 catalogue.setFileName( catalogueFileName( language(), catalogue ) );
1971}
1972
1973void KLocale::setDateFormat(const QString & format)
1974{
1975 doFormatInit();
1976 m_dateFormat = format.stripWhiteSpace();
1977}
1978
1979void KLocale::setDateFormatShort(const QString & format)
1980{
1981 doFormatInit();
1982 m_dateFormatShort = format.stripWhiteSpace();
1983}
1984
1985void KLocale::setDateMonthNamePossessive(bool possessive)
1986{
1987 doFormatInit();
1988 d->dateMonthNamePossessive = possessive;
1989}
1990
1991void KLocale::setTimeFormat(const QString & format)
1992{
1993 doFormatInit();
1994 m_timeFormat = format.stripWhiteSpace();
1995}
1996
1997void KLocale::setWeekStartsMonday(bool start) //deprecated
1998{
1999 doFormatInit();
2000 if (start)
2001 d->weekStartDay = 1;
2002 else
2003 d->weekStartDay = 7;
2004}
2005
2006void KLocale::setWeekStartDay(int day)
2007{
2008 doFormatInit();
2009 if (day>7 || day<1)
2010 d->weekStartDay = 1; //Monday is default
2011 else
2012 d->weekStartDay = day;
2013}
2014
2015QString KLocale::dateFormat() const
2016{
2017 doFormatInit();
2018 return m_dateFormat;
2019}
2020
2021QString KLocale::dateFormatShort() const
2022{
2023 doFormatInit();
2024 return m_dateFormatShort;
2025}
2026
2027QString KLocale::timeFormat() const
2028{
2029 doFormatInit();
2030 return m_timeFormat;
2031}
2032
2033void KLocale::setDecimalSymbol(const QString & symbol)
2034{
2035 doFormatInit();
2036 m_decimalSymbol = symbol.stripWhiteSpace();
2037}
2038
2039void KLocale::setThousandsSeparator(const QString & separator)
2040{
2041 doFormatInit();
2042 // allow spaces here
2043 m_thousandsSeparator = separator;
2044}
2045
2046void KLocale::setPositiveSign(const QString & sign)
2047{
2048 doFormatInit();
2049 m_positiveSign = sign.stripWhiteSpace();
2050}
2051
2052void KLocale::setNegativeSign(const QString & sign)
2053{
2054 doFormatInit();
2055 m_negativeSign = sign.stripWhiteSpace();
2056}
2057
2058void KLocale::setPositiveMonetarySignPosition(SignPosition signpos)
2059{
2060 doFormatInit();
2061 m_positiveMonetarySignPosition = signpos;
2062}
2063
2064void KLocale::setNegativeMonetarySignPosition(SignPosition signpos)
2065{
2066 doFormatInit();
2067 m_negativeMonetarySignPosition = signpos;
2068}
2069
2070void KLocale::setPositivePrefixCurrencySymbol(bool prefix)
2071{
2072 doFormatInit();
2073 m_positivePrefixCurrencySymbol = prefix;
2074}
2075
2076void KLocale::setNegativePrefixCurrencySymbol(bool prefix)
2077{
2078 doFormatInit();
2079 m_negativePrefixCurrencySymbol = prefix;
2080}
2081
2082void KLocale::setFracDigits(int digits)
2083{
2084 doFormatInit();
2085 m_fracDigits = digits;
2086}
2087
2088void KLocale::setMonetaryThousandsSeparator(const QString & separator)
2089{
2090 doFormatInit();
2091 // allow spaces here
2092 m_monetaryThousandsSeparator = separator;
2093}
2094
2095void KLocale::setMonetaryDecimalSymbol(const QString & symbol)
2096{
2097 doFormatInit();
2098 m_monetaryDecimalSymbol = symbol.stripWhiteSpace();
2099}
2100
2101void KLocale::setCurrencySymbol(const QString & symbol)
2102{
2103 doFormatInit();
2104 m_currencySymbol = symbol.stripWhiteSpace();
2105}
2106
2107int KLocale::pageSize() const
2108{
2109 doFormatInit();
2110 return d->pageSize;
2111}
2112
2113void KLocale::setPageSize(int pageSize)
2114{
2115 // #### check if it's in range??
2116 doFormatInit();
2117 d->pageSize = pageSize;
2118}
2119
2120KLocale::MeasureSystem KLocale::measureSystem() const
2121{
2122 doFormatInit();
2123 return d->measureSystem;
2124}
2125
2126void KLocale::setMeasureSystem(MeasureSystem value)
2127{
2128 doFormatInit();
2129 d->measureSystem = value;
2130}
2131
2132QString KLocale::defaultLanguage()
2133{
2134 return QString::fromLatin1("en_US");
2135}
2136
2137QString KLocale::defaultCountry()
2138{
2139 return QString::fromLatin1("C");
2140}
2141
2142const char * KLocale::encoding() const
2143{
2144 return codecForEncoding()->name();
2145}
2146
2147int KLocale::encodingMib() const
2148{
2149 return codecForEncoding()->mibEnum();
2150}
2151
2152int KLocale::fileEncodingMib() const
2153{
2154 if (d->utf8FileEncoding)
2155 return 106;
2156 return codecForEncoding()->mibEnum();
2157}
2158
2159QTextCodec * KLocale::codecForEncoding() const
2160{
2161 return d->codecForEncoding;
2162}
2163
2164bool KLocale::setEncoding(int mibEnum)
2165{
2166 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
2167 if (codec)
2168 d->codecForEncoding = codec;
2169
2170 return codec != 0;
2171}
2172
2173QStringList KLocale::languagesTwoAlpha() const
2174{
2175 if (d->langTwoAlpha.count())
2176 return d->langTwoAlpha;
2177
2178 const QStringList &origList = languageList();
2179
2180 QStringList result;
2181
2182//US KConfig config(QString::fromLatin1("language.codes"), true, false);
2183 KConfig config(locateLocal("config", QString::fromLatin1("language.codes")));
2184 config.setGroup("TwoLetterCodes");
2185
2186 for ( QStringList::ConstIterator it = origList.begin();
2187 it != origList.end();
2188 ++it )
2189 {
2190 QString lang = *it;
2191 QStringList langLst;
2192
2193/*US I changed the following code, because hasKey is not available.
2194!!! check if my version is correct
2195 if (config.hasKey( lang ))
2196 langLst = config.readListEntry( lang );
2197 else
2198 {
2199 int i = lang.find('_');
2200 if (i >= 0)
2201 lang.truncate(i);
2202 langLst << lang;
2203 }
2204*/
2205 langLst = config.readListEntry( lang );
2206 if (langLst.isEmpty())
2207 {
2208 int i = lang.find('_');
2209 if (i >= 0)
2210 lang.truncate(i);
2211 langLst << lang;
2212 }
2213
2214
2215 for ( QStringList::ConstIterator langIt = langLst.begin();
2216 langIt != langLst.end();
2217 ++langIt )
2218 {
2219 if ( !(*langIt).isEmpty() && !result.contains( *langIt ) )
2220 result += *langIt;
2221 }
2222 }
2223 d->langTwoAlpha = result;
2224 return result;
2225}
2226
2227QStringList KLocale::allLanguagesTwoAlpha() const
2228{
2229 if (!d->languages)
2230//US d->languages = new KConfig("all_languages", true, false, "locale");
2231 d->languages = new KConfig(locateLocal( "locale", "all_languages"));
2232
2233//US return d->languages->groupList();
2234 qDebug("KLocale::allLanguagesTwoAlpha has to be fixed.");
2235 return *(new QStringList());
2236
2237}
2238
2239QString KLocale::twoAlphaToLanguageName(const QString &code) const
2240{
2241 if (!d->languages)
2242//US d->languages = new KConfig("all_languages", true, false, "locale");
2243 d->languages = new KConfig(locateLocal( "locale", "all_languages"));
2244
2245 d->languages->setGroup(code.lower());
2246 return d->languages->readEntry("Name");
2247}
2248
2249QStringList KLocale::allCountriesTwoAlpha() const
2250{
2251 QStringList countries;
2252
2253 qDebug("KLocale::allCountriesTwoAlpha has to be fixed.");
2254//US QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
2255 QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop", true, true);
2256
2257 for(QStringList::ConstIterator it = paths.begin();
2258 it != paths.end(); ++it)
2259 {
2260 QString code = (*it).mid((*it).length()-16, 2);
2261 if (code != "/C")
2262 countries.append(code);
2263 }
2264 return countries;
2265}
2266
2267QString KLocale::twoAlphaToCountryName(const QString &code) const
2268{
2269//US KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale");
2270 KConfig cfg(locateLocal("locale", "l10n/"+code.lower()+"/entry.desktop"));
2271 cfg.setGroup("KCM Locale");
2272 return cfg.readEntry("Name");
2273}
2274
2275void KLocale::setCalendar(const QString & calType)
2276{
2277 doFormatInit();
2278
2279 d->calendarType = calType;
2280
2281 delete d->calendar;
2282 d->calendar = 0;
2283}
2284
2285QString KLocale::calendarType() const
2286{
2287 doFormatInit();
2288
2289 return d->calendarType;
2290}
2291
2292const KCalendarSystem * KLocale::calendar() const
2293{
2294 doFormatInit();
2295
2296 // Check if it's the correct calendar?!?
2297//US we are always using the gregorian calendar
2298//US if ( !d->calendar )
2299//US d->calendar = KCalendarSystemFactory::create( d->calendarType, this );
2300 if ( !d->calendar )
2301 d->calendar = new KCalendarSystemGregorian;
2302
2303 return d->calendar;
2304}
2305
2306KLocale::KLocale(const KLocale & rhs)
2307{
2308 d = new KLocalePrivate;
2309
2310 *this = rhs;
2311}
2312
2313KLocale & KLocale::operator=(const KLocale & rhs)
2314{
2315 // Numbers and money
2316 m_decimalSymbol = rhs.m_decimalSymbol;
2317 m_thousandsSeparator = rhs.m_thousandsSeparator;
2318 m_currencySymbol = rhs.m_currencySymbol;
2319 m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
2320 m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
2321 m_positiveSign = rhs.m_positiveSign;
2322 m_negativeSign = rhs.m_negativeSign;
2323 m_fracDigits = rhs.m_fracDigits;
2324 m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
2325 m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
2326 m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
2327 m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
2328
2329 // Date and time
2330 m_timeFormat = rhs.m_timeFormat;
2331 m_dateFormat = rhs.m_dateFormat;
2332 m_dateFormatShort = rhs.m_dateFormatShort;
2333
2334 m_language = rhs.m_language;
2335 m_country = rhs.m_country;
2336
2337 // the assignment operator works here
2338 *d = *rhs.d;
2339 d->languages = 0; // Don't copy languages
2340 d->calendar = 0; // Don't copy the calendar
2341
2342 return *this;
2343}
2344
2345bool KLocale::setCharset(const QString & ) { return true; }
2346QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); }
2347
2348
2349int KLocale::timezoneOffset( QString timeZone )
2350{
2351 int ret = 1001;
2352 int index = mTimeZoneList.findIndex( timeZone );
2353 if ( index < 24 )
2354 ret = ( index-11 ) * 60 ;
2355 return ret;
2356}
2357
2358QStringList KLocale::timeZoneList() const
2359{
2360 return mTimeZoneList;
2361}
2362void KLocale::setTimezone( const QString &timeZone )
2363{
2364 mTimeZoneOffset = timezoneOffset( timeZone );
2365}
2366
2367void KLocale::setDaylightSaving( bool b, int start , int end )
2368{
2369 daylightEnabled = b;
2370 daylightStart = start;
2371 daylightEnd = end;
2372 mSouthDaylight = (end < start);
2373 // qDebug("klocale daylight %d %d %d ", b, start , end );
2374}
2375
2376int KLocale::localTimeOffset( const QDateTime &dt )
2377{
2378 bool addDaylight = false;
2379 if ( daylightEnabled ) {
2380 int d_end, d_start;
2381 int dayofyear = dt.date().dayOfYear();
2382 int year = dt.date().year();
2383 int add = 0;
2384 if ( QDate::leapYear(year) )
2385 add = 1;
2386 QDate date ( year,1,1 );
2387 if ( daylightEnd > 59 )
2388 d_end = daylightEnd +add;
2389 else
2390 d_end = daylightEnd;
2391 if ( daylightStart > 59 )
2392 d_start = daylightStart +add;
2393 else
2394 d_start = daylightStart;
2395 QDate s_date = date.addDays( d_start -1 );
2396 QDate e_date = date.addDays( d_end -1 );
2397 int dof = s_date.dayOfWeek();
2398 if ( dof < 7 )
2399 s_date = s_date.addDays( -dof );
2400 dof = e_date.dayOfWeek();
2401 if ( dof < 7 )
2402 e_date = e_date.addDays( -dof );
2403 QTime startTime ( 3,0,0 );
2404 QDateTime startDt( s_date, startTime );
2405 QDateTime endDt( e_date, startTime );
2406 //qDebug("dayligt saving start %s end %s ",startDt.toString().latin1(),endDt.toString().latin1( ));
2407 if ( mSouthDaylight ) {
2408 if ( ! ( endDt < dt && dt < startDt) )
2409 addDaylight = true;
2410 } else {
2411 if ( startDt < dt && dt < endDt )
2412 addDaylight = true;
2413
2414
2415 }
2416 }
2417 int addMin = 0;
2418 if ( addDaylight )
2419 addMin = 60;
2420 return mTimeZoneOffset + addMin;
2421}
2422
2423void KLocale::setHore24Format ( bool b )
2424{
2425 mHourF24Format = b;
2426}
2427void KLocale::setWeekStartMonday( bool b )
2428{
2429 mWeekStartsMonday = b;
2430}
2431void KLocale::setIntDateFormat( int i )
2432{
2433 mIntDateFormat = i;
2434}
2435void KLocale::setLanguage( int i )
2436{
2437 mLanguage = i;
2438}
2439
2440
2441
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 @@
1#ifndef MINIKDE_KLOCALE_H
2#define MINIKDE_KLOCALE_H
3
4#include <qstring.h>
5#include <qstringlist.h>
6#include <qdict.h>
7
8class QStringList;
9class QTextCodec;
10class QDate;
11class QTime;
12class QDateTime;
13
14class KGlobal;
15class KConfig;
16class KConfigBase;
17class KLocalePrivate;
18class KCatalogue;
19class KCalendarSystem;
20
21#ifndef I18N_NOOP
22#define I18N_NOOP(x) (x)
23#endif
24
25void setLocaleDict( QDict<char> * dict );
26
27/**
28 * i18n is the function that does everything you need to translate
29 * a string. You just wrap around every user visible string a i18n
30 * call to get a QString with the string in the user's preferred
31 * language.
32 *
33 * The argument must be an UTF-8 encoded string (If you only use
34 * characters that are in US-ASCII, you're on the safe side. But
35 * for e.g. german umlauts or french accents should be recoded to
36 * UTF-8)
37 **/
38QString i18n(const char *text);
39
40/**
41 * If the string is too ambiguous to be translated well to a non-english
42 * language, use this form of i18n to separate lookup string and english
43 * text.
44 * @see translate
45 **/
46QString i18n(const char *index, const char *text);
47
48/**
49 * If you want to handle plural forms, use this form of i18n.
50 * The plural has to contain a %n where n fits into.
51 * @see translate
52 **/
53QString i18n(const char *singular, const char *plural, unsigned long n);
54
55/**
56 * Qt3's uic generates i18n( "msg", "comment" ) calls which conflict
57 * with our i18n method. We use uic -tr tr2i18n to redirect
58 * to the right i18n() function
59**/
60inline QString tr2i18n(const char* message, const char* =0) {
61 return i18n(message);
62}
63
64/**
65 *
66 * KLocale provides support for country specific stuff like
67 * the national language.
68 *
69 * KLocale supports translating, as well as specifying the format
70 * for numbers, currency, time, and date.
71 *
72 * @author Stephan Kulow <coolo@kde.org>, Preston Brown <pbrown@kde.org>,
73 * Hans Petter Bieker <bieker@kde.org>, Lukas Tinkl <lukas.tinkl@suse.cz>
74 * @short class for supporting locale settings and national language
75 */
76class KLocale
77{
78 friend class KGlobal; // for initInstance()
79public:
80 /**
81 * Constructs a KLocale with the given catalogue name.
82 * The constructor looks for an entry Locale/Language in the
83 * configuration file.
84 * If no config file is specified, it will also look for languages
85 * using the environment variables (KDE_LANG, LC_MESSAGES, LC_ALL, LANG),
86 * as well as the global configuration fie. If we were not able to use
87 * non of the specified languages, the default language (en_US) will be
88 * used.
89 *
90 * If you specify a configuration file, it has to be valid until
91 * the KLocale object is destroyed.
92 *
93 * @param catalogue The name of the main language file
94 * @param config The configuration file to use.
95 */
96 KLocale( const QString& catalogue, KConfig *config = 0 );
97
98 /**
99 * Copy constructor.
100 */
101 KLocale( const KLocale & rhs );
102
103 /**
104 * Assignment operator.
105 */
106 KLocale& operator= ( const KLocale & rhs );
107
108 /**
109 * Destructor.
110 */
111 ~KLocale();
112
113 /**
114 * Translates the string into the corresponding string in
115 * the national language, if available. If not, returns
116 * the string itself.
117 * There is a KDE wide message file that contains the most
118 * often used phrases, so we can avoid duplicating the
119 * translation of these phrases. If a phrase is not found
120 * in the catalogue given to the constructor, it will search
121 * in the system catalog. This makes it possible to override
122 * some phrases for your needs.
123 *
124 * The argument must be an UTF-8 encoded string (If you only use
125 * characters that are in US-ASCII you're on the safe side. But
126 * for e.g. german umlauts or french accents should be recoded to
127 * UTF-8)
128 *
129 * @param index The lookup text and default text, if not found.
130 */
131 QString translate( const char *index ) const;
132
133 /**
134 * Translates the string into the corresponding string in the
135 * national language, if available.
136 *
137 * The real contents of the string is in the argument fallback,
138 * but the meaning of it is coded into the argument index.
139 * In some cases you'll need this function, when english is
140 * too ambiguous to express it.
141 *
142 * Most of the times the translators will tell you if it can't
143 * be translated as it, but think of cases as "New", where the
144 * translations differs depending on what is New.
145 * Or simple cases as "Open", that can be used to express something
146 * is open or it can be used to express that you want something to
147 * open... There are tons of such examples.
148 *
149 * If translate("Open") is not enough to translate it well, use
150 * translate("To Open", "Open") or translate("Is Open", "Open").
151 * The english user will see "Open" in both cases, but the translated
152 * version may vary. Of course you can also use i18n()
153 *
154 * @param index The lookup text
155 * @param fallback the default text, if not found
156 * @return translation
157 */
158 QString translate( const char *index, const char *fallback) const;
159
160 /**
161 * Used to get the correct, translated singular or plural of a
162 * word.
163 * @param singular the singular form of the word, for example "file".
164 * @param plural the plural form of the word. Must contain a "%n" that will
165 * be replaced by the number @n, for example "%n files"
166 * @param n the number
167 * @return the correct singular or plural for the selected language,
168 * depending on n
169 */
170 QString translate( const char *singular, const char *plural,
171 unsigned long n) const;
172
173 /**
174 * Changes the current encoding.
175 *
176 * @param mibEnum The mib of the preferred codec
177 *
178 * @return True on success.
179 */
180 bool setEncoding(int mibEnum);
181
182 /**
183 * Changes the current language. The current language will be left
184 * unchanged if failed. It will force a reload of the country specific
185 * configuration as well.
186 *
187 * @param language The language code.
188 *
189 * @return True on success.
190 */
191 bool setLanguage(const QString & language);
192
193 /**
194 * Changes the list of prefed languages for the locale. The first valid
195 * language in the list will be used, or the default (en_US) language
196 * will be used if non of the specified languages were available.
197 *
198 * @param languages The list of language codes.
199 *
200 * @return True if one of the specified languages were used.
201 */
202 bool setLanguage(const QStringList & languages);
203
204 /**
205 * Changes the current country. The current country will be left
206 * unchanged if failed. It will force a reload of the country specific
207 * configuration.
208 *
209 * @param country The ISO 3166 country code.
210 *
211 * @return True on success.
212 */
213 bool setCountry(const QString & country);
214
215 /**
216 * Various positions for where to place the positive or negative
217 * sign when they are related to a monetary value.
218 */
219 enum SignPosition { ParensAround = 0, BeforeQuantityMoney = 1,
220 AfterQuantityMoney = 2,
221 BeforeMoney = 3, AfterMoney = 4 };
222
223 /**
224 * Returns what a decimal point should look like ("." or "," etc.)
225 * according to the current locale or user settings.
226 *
227 * @return The decimal symbol used by locale.
228 */
229 QString decimalSymbol() const;
230
231 /**
232 * Returns what the thousands separator should look
233 * like ("," or "." etc.)
234 * according to the current locale or user settings.
235 *
236 * @return The thousands separator used by locale.
237 */
238 QString thousandsSeparator() const;
239
240 /**
241 * Returns what the symbol denoting currency in the current locale
242 * as as defined by user settings should look like.
243 *
244 * @return The default currency symbol used by locale.
245 */
246 QString currencySymbol() const;
247
248 /**
249 * Returns what a decimal point should look like ("." or "," etc.)
250 * for monetary values, according to the current locale or user
251 * settings.
252 *
253 * @return The monetary decimal symbol used by locale.
254 */
255 QString monetaryDecimalSymbol() const;
256
257 /**
258 * Returns what a thousands separator for monetary values should
259 * look like ("," or " " etc.) according to the current locale or
260 * user settings.
261 *
262 * @return The monetary thousands separator used by locale.
263 */
264 QString monetaryThousandsSeparator() const;
265
266 /**
267 * Returns what a positive sign should look like ("+", " ", etc.)
268 * according to the current locale or user settings.
269 *
270 * @return The positive sign used by locale.
271 */
272 QString positiveSign() const;
273
274 /**
275 * Returns what a negative sign should look like ("-", etc.)
276 * according to the current locale or user settings.
277 *
278 * @return The negative sign used by locale.
279 */
280 QString negativeSign() const;
281
282 /**
283 * The number of fractional digits to include in numeric/monetary
284 * values (usually 2).
285 *
286 * @return Default number of fractional digits used by locale.
287 */
288 int fracDigits() const;
289
290 /**
291 * If and only if the currency symbol precedes a positive value,
292 * this will be true.
293 *
294 * @return Where to print the currency symbol for positive numbers.
295 */
296 bool positivePrefixCurrencySymbol() const;
297
298 /**
299 * If and only if the currency symbol precedes a negative value,
300 * this will be true.
301 *
302 * @return True if the currency symbol precedes negative numbers.
303 */
304 bool negativePrefixCurrencySymbol() const;
305
306 /**
307 * Returns the position of a positive sign in relation to a
308 * monetary value.
309 *
310 * @return Where/how to print the positive sign.
311 * @see SignPosition
312 */
313 SignPosition positiveMonetarySignPosition() const;
314
315 /**
316 * Denotes where to place a negative sign in relation to a
317 * monetary value.
318 *
319 * @return Where/how to print the negative sign.
320 * @see SignPosition
321 */
322 SignPosition negativeMonetarySignPosition() const;
323
324 /**
325 * Given a double, converts that to a numeric string containing
326 * the localized monetary equivalent.
327 *
328 * e.g. given 123456, return "$ 123,456.00".
329 *
330 * @param num The number we want to format
331 * @param currency The currency symbol you want.
332 * @param digits Number of fractional digits, or -1 for the default
333 * value
334 *
335 * @return The number of money as a localized string
336 * @see fracDigits()
337 */
338 QString formatMoney(double num,
339 const QString & currency = QString::null,
340 int digits = -1) const;
341
342 /**
343 * Given a double, converts that to a numeric string containing
344 * the localized numeric equivalent.
345 *
346 * e.g. given 123456.78F, return "123,456.78" (for some European country).
347 * If precision isn't specified, 2 is used.
348 *
349 * @param num The number to convert
350 * @param precision Number of fractional digits used.
351 *
352 * @return The number as a localized string
353 */
354 QString formatNumber(double num, int precision = -1) const;
355
356 /**
357 * Given an integer, converts that to a numeric string containing
358 * the localized numeric equivalent.
359 *
360 * e.g. given 123456L, return "123,456" (for some European country).
361 *
362 * @param num The number to convert
363 *
364 * @return The number as a localized string
365 * @since 3.2
366 */
367 QString formatLong(long num) const;
368
369 /**
370 * Use this to determine whether nouns are declined in
371 * locale's language. This property should remain
372 * read-only (no setter function)
373 *
374 * @return If nouns are declined
375 * @since 3.1
376 */
377 bool nounDeclension() const;
378
379 /**
380 * Returns a string formatted to the current locale's conventions
381 * regarding dates.
382 *
383 * @param pDate The date to be formated.
384 * @param shortFormat True for non text dates.
385 *
386 * @return The date as a string
387 */
388 QString formatDate(const QDate &pDate, bool shortFormat = false) const;
389
390 /**
391 * Use this to determine whether in dates a possessive form of month
392 * name is preferred ("of January" rather than "January")
393 *
394 * @return If possessive form should be used
395 * @since 3.1
396 */
397 bool dateMonthNamePossessive() const;
398
399 /**
400 * Returns a string formatted to the current locale's conventions
401 * regarding times.
402 *
403 * @param pTime The time to be formated.
404 * @param includeSecs if true, seconds are included in the output,
405 * otherwise only hours and minutes are formatted.
406 *
407 * @return The time as a string
408 */
409 QString formatTime(const QTime &pTime, bool includeSecs = false) const;
410
411 /**
412 * Use this to determine if the user wants a 12 hour clock.
413 *
414 * @return If the user wants 12h clock
415 */
416 bool use12Clock() const;
417
418 /**
419 * @deprecated
420 *
421 * Please use the @ref weekStartDay method instead.
422 *
423 * Use this to determine if the user wants the week to start on Monday.
424 *
425 * @return true if the week starts on Monday
426 */
427 bool weekStartsMonday() const; //### remove for KDE 4.0
428
429 /**
430 * Use this to determine which day is the first day of the week.
431 *
432 * @return an integer (Monday=1..Sunday=7)
433 * @since 3.1
434 */
435 int weekStartDay() const;
436
437 /**
438 * @deprecated
439 *
440 * Returns a string containing the name of the month name used in the Gregorian calendar.
441 *
442 * @param i the month number of the year starting at 1/January.
443 * @param shortName we will return the short version of the string.
444 *
445 * @return The name of the month
446 */
447 QString monthName(int i, bool shortName = false) const;
448
449 /**
450 * @deprecated
451 *
452 * Returns a string containing the possessive form of the month name used in the Gregorian calendar.
453 * ("of January", "of February", etc.)
454 * It's needed in long format dates in some languages.
455 *
456 * @param i the month number of the year starting at 1/January.
457 * @param shortName we will return the short version of the string.
458 *
459 * @return The possessive form of the name of the month
460 * @since 3.1
461 */
462 QString monthNamePossessive(int i, bool shortName = false) const;
463
464 /**
465 * @deprecated
466 *
467 * Returns a string containing the name of the week day used in the Gregorian calendar.
468 *
469 * @param i the day number of the week starting at 1/Monday.
470 * @param shortName we will return the short version of the string.
471 *
472 * @return The name of the day
473 */
474 QString weekDayName(int i, bool shortName = false) const;
475
476 /**
477 * Returns a pointer to the calendar system object.
478 *
479 * @return the current calendar system instance
480 * @since 3.2
481 */
482 const KCalendarSystem * calendar() const;
483
484 /**
485 * Returns the name of the calendar system that is currently being
486 * used by the system.
487 *
488 * @return the name of the calendar system
489 * @since 3.2
490 */
491 QString calendarType() const;
492
493 /**
494 * Changes the current calendar system to the calendar specified.
495 * Currently is "gregorian" and "hijri" supported. If the calendar
496 * system specified is not found, gregorian will be used.
497 *
498 * @param calendarType the name of the calendar type
499 * @since 3.2
500 */
501 void setCalendar(const QString & calendarType);
502
503 /**
504 * Returns a string formated to the current locale's conventions
505 * regarding both date and time.
506 *
507 * @param pDateTime The date and time to be formated.
508 * @param shortFormat using the short date format.
509 * @param includeSecs using the short date format.
510 *
511 * @return The date and time as a string
512 */
513 QString formatDateTime(const QDateTime &pDateTime,
514 bool shortFormat = true,
515 bool includeSecs = false) const;
516
517 /**
518 * Converts a localized monetary string to a double.
519 *
520 * @param numStr the string we want to convert.
521 * @param ok the boolean that is set to false if it's not a number.
522 * If @p ok is 0, it will be ignored
523 *
524 * @return The string converted to a double
525 */
526 double readMoney(const QString &numStr, bool * ok = 0) const;
527
528 /**
529 * Converts a localized numeric string to a double.
530 *
531 * @param numStr the string we want to convert.
532 * @param ok the boolean that is set to false if it's not a number.
533 * If @p ok is 0, it will be ignored
534 *
535 * @return The string converted to a double
536 */
537 double readNumber(const QString &numStr, bool * ok = 0) const;
538
539 /**
540 * Converts a localized date string to a QDate.
541 * The bool pointed by ok will be invalid if the date entered was not valid.
542 *
543 * @param str the string we want to convert.
544 * @param ok the boolean that is set to false if it's not a valid date.
545 * If @p ok is 0, it will be ignored
546 *
547 * @return The string converted to a QDate
548 */
549 QDate readDate(const QString &str, bool* ok = 0) const;
550
551 /**
552 * Converts a localized date string to a QDate, using the specified format.
553 * You will usually not want to use this method.
554 */
555 QDate readDate( const QString &intstr, const QString &fmt, bool* ok = 0) const;
556
557 enum ReadDateFlags {
558 NormalFormat = 1,
559 ShortFormat = 2
560 };
561
562 /**
563 * Converts a localized date string to a QDate.
564 * This method is stricter than readDate(str,&ok): it will either accept
565 * a date in full format or a date in short format, depending on @p flags.
566 *
567 * @param str the string we want to convert.
568 * @param flags whether the date string is to be in full format or in short format.
569 * @param ok the boolean that is set to false if it's not a valid date.
570 * If @p ok is 0, it will be ignored
571 *
572 * @return The string converted to a QDate
573 * @since 3.2
574 */
575 QDate readDate(const QString &str, ReadDateFlags flags, bool *ok = 0) const;
576
577 /**
578 * Converts a localized time string to a QTime.
579 * This method will try to parse it with seconds, then without seconds.
580 * The bool pointed by ok will be false if the time entered was not valid.
581 *
582 * @param str the string we want to convert.
583 * @param ok the boolean that is set to false if it's not a valid time.
584 * If @p ok is 0, it will be ignored
585 *
586 * @return The string converted to a QTime
587 */
588 QTime readTime(const QString &str, bool* ok = 0) const;
589
590 enum ReadTimeFlags {
591 WithSeconds = 0, // default (no flag set)
592 WithoutSeconds = 1
593 }; // (maybe use this enum as a bitfield, if adding independent features?)
594 /**
595 * Converts a localized time string to a QTime.
596 * This method is stricter than readTime(str,&ok): it will either accept
597 * a time with seconds or a time without seconds.
598 * Use this method when the format is known by the application.
599 *
600 * @param str the string we want to convert.
601 * @param flags whether the time string is expected to contain seconds or not.
602 * @param ok the boolean that is set to false if it's not a valid time.
603 * If @p ok is 0, it will be ignored
604 *
605 * @return The string converted to a QTime
606 * @since 3.2
607 */
608 QTime readTime(const QString &str, ReadTimeFlags flags, bool *ok = 0) const;
609
610 /**
611 * Returns the language used by this object. The domain AND the
612 * library translation must be available in this language.
613 * @ref defaultLanguage() is returned by default, if no other available.
614 *
615 * @return The currently used language.
616 */
617 QString language() const;
618
619 /**
620 * Returns the country code of the country where the user lives.
621 * @ref defaultCountry() is returned by default, if no other available.
622 *
623 * @return The country code for the user.
624 */
625 QString country() const;
626
627 /**
628 * Returns the preferred languages as ISO 639-1 codes. This means
629 * that information about country is removed. If the internal language
630 * code might be represented by more than one 639-1 code, they will all be
631 * listed (but only once).
632 *
633 * If the selected languages are "nn, nb, pt_BR", you will get:
634 * "nn, no, nb, pt".
635 *
636 * @return List of language codes
637 *
638 * @see languageList
639 */
640 QStringList languagesTwoAlpha() const;
641
642 /**
643 * Returns the languages selected by user. The codes returned here is the
644 * internal language codes.
645 *
646 * @return List of language codes
647 *
648 * @see languagesTwoAlpha
649 */
650 QStringList languageList() const;
651
652 /**
653 * Returns the user's preferred encoding.
654 *
655 * @return The name of the preferred encoding
656 *
657 * @see codecForEncoding
658 * @see encodingMib
659 */
660 const char * encoding() const;
661
662 /**
663 * Returns the user's preferred encoding.
664 *
665 * @return The Mib of the preferred encoding
666 *
667 * @see encoding
668 * @see codecForEncoding
669 */
670 int encodingMib() const;
671 /**
672 * Returns the user's preferred encoding. Should never be NULL.
673 *
674 * @return The codec for the preferred encoding
675 *
676 * @see encoding
677 * @see encodingMib
678 */
679 QTextCodec * codecForEncoding() const;
680
681 /**
682 * Returns the file encoding.
683 *
684 * @return The Mib of the file encoding
685 *
686 * @see QFile::encodeName
687 * @see QFile::decodeName
688 */
689 int fileEncodingMib() const;
690
691 /**
692 * Changes the current date format.
693 *
694 * The format of the date is a string which contains variables that will
695 * be replaced:
696 * @li %Y with the century (e.g. "19" for "1984")
697 * @li %y with the lower 2 digits of the year (e.g. "84" for "1984")
698 * @li %n with the month (January="1", December="12")
699 * @li %m with the month with two digits (January="01", December="12")
700 * @li %e with the day of the month (e.g. "1" on the first of march)
701 * @li %d with the day of the month with two digits(e.g. "01" on the first of march)
702 * @li %b with the short form of the month (e.g. "Jan" for January)
703 * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday)
704 * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday)
705 * Everything else in the format string will be taken as is.
706 * For example, March 20th 1989 with the format "%y:%m:%d" results
707 * in "89:03:20".
708 *
709 * @param format The new date format
710 */
711 void setDateFormat(const QString & format);
712 /**
713 * Changes the current short date format.
714 *
715 * The format of the date is a string which contains variables that will
716 * be replaced:
717 * @li %Y with the century (e.g. "19" for "1984")
718 * @li %y with the lower 2 digits of the year (e.g. "84" for "1984")
719 * @li %n with the month (January="1", December="12")
720 * @li %m with the month with two digits (January="01", December="12")
721 * @li %e with the day of the month (e.g. "1" on the first of march)
722 * @li %d with the day of the month with two digits(e.g. "01" on the first of march)
723 * @li %b with the short form of the month (e.g. "Jan" for January)
724 * @li %a with the short form of the weekday (e.g. "Wed" for Wednesday)
725 * @li %A with the long form of the weekday (e.g. "Wednesday" for Wednesday)
726 * Everything else in the format string will be taken as is.
727 * For example, March 20th 1989 with the format "%y:%m:%d" results
728 * in "89:03:20".
729 *
730 * @param format The new short date format
731 */
732 void setDateFormatShort(const QString & format);
733 /**
734 * Changes the form of month name used in dates.
735 *
736 * @param possessive True if possessive forms should be used
737 * @since 3.1
738 */
739 void setDateMonthNamePossessive(bool possessive);
740 /**
741 * Changes the current time format.
742 *
743 * The format of the time is string a which contains variables that will
744 * be replaced:
745 * @li %H with the hour in 24h format and 2 digits (e.g. 5pm is "17", 5am is "05")
746 * @li %k with the hour in 24h format and one digits (e.g. 5pm is "17", 5am is "5")
747 * @li %I with the hour in 12h format and 2 digits (e.g. 5pm is "05", 5am is "05")
748 * @li %l with the hour in 12h format and one digits (e.g. 5pm is "5", 5am is "5")
749 * @li %M with the minute with 2 digits (e.g. the minute of 07:02:09 is "02")
750 * @li %S with the seconds with 2 digits (e.g. the minute of 07:02:09 is "09")
751 * @li %p with pm or am (e.g. 17.00 is "pm", 05.00 is "am")
752 * Everything else in the format string will be taken as is.
753 * For example, 5.23pm with the format "%H:%M" results
754 * in "17:23".
755 *
756 * @param format The new time format
757 */
758 void setTimeFormat(const QString & format);
759
760 /**
761 * @deprecated
762 *
763 * Please use @ref setWeekStartDay instead.
764 *
765 * Changes how KLocale defines the first day in week.
766 *
767 * @param start True if Monday is the first day in the week
768 */
769 void setWeekStartsMonday(bool start); //### remove for KDE 4.0
770
771 /**
772 * Changes how KLocale defines the first day in week.
773 *
774 * @param day first day of the week (Monday=1..Sunday=7) as integer
775 * @since 3.1
776 */
777 void setWeekStartDay(int day);
778 /**
779 * Returns the currently selected date format.
780 *
781 * @return Current date format.
782 * @see setDateFormat()
783 */
784 QString dateFormat() const;
785 /**
786 * Returns the currently selected short date format.
787 *
788 * @return Current short date format.
789 * @see setDateFormatShort()
790 */
791 QString dateFormatShort() const;
792 /**
793 * Returns the currently selected time format.
794 *
795 * @return Current time format.
796 * @see setTimeFormat()
797 */
798 QString timeFormat() const;
799
800 /**
801 * Changes the symbol used to identify the decimal pointer.
802 *
803 * @param symbol The new decimal symbol.
804 */
805 void setDecimalSymbol(const QString & symbol);
806 /**
807 * Changes the separator used to group digits when formating numbers.
808 *
809 * @param separator The new thousands separator.
810 */
811 void setThousandsSeparator(const QString & separator);
812 /**
813 * Changes the sign used to identify a positive number. Normally this is
814 * left blank.
815 *
816 * @param sign Sign used for positive numbers.
817 */
818 void setPositiveSign(const QString & sign);
819 /**
820 * Changes the sign used to identify a negative number.
821 *
822 * @param sign Sign used for negative numbers.
823 */
824 void setNegativeSign(const QString & sign);
825 /**
826 * Changes the sign position used for positive monetary values.
827 *
828 * @param signpos The new sign position
829 */
830 void setPositiveMonetarySignPosition(SignPosition signpos);
831 /**
832 * Changes the sign position used for negative monetary values.
833 *
834 * @param signpos The new sign position
835 */
836 void setNegativeMonetarySignPosition(SignPosition signpos);
837 /**
838 * Changes the position where the currency symbol should be printed for
839 * positive monetary values.
840 *
841 * @param prefix True if the currency symbol should be prefixed instead of
842 * postfixed
843 */
844 void setPositivePrefixCurrencySymbol(bool prefix);
845 /**
846 * Changes the position where the currency symbol should be printed for
847 * negative monetary values.
848 *
849 * @param prefix True if the currency symbol should be prefixed instead of
850 * postfixed
851 */
852 void setNegativePrefixCurrencySymbol(bool prefix);
853 /**
854 * Changes the number of digits used when formating numbers.
855 *
856 * @param digits The default number of digits to use.
857 */
858 void setFracDigits(int digits);
859 /**
860 * Changes the separator used to group digits when formating monetary values.
861 *
862 * @param separator The new thousands separator.
863 */
864 void setMonetaryThousandsSeparator(const QString & separator);
865 /**
866 * Changes the symbol used to identify the decimal pointer for monetary
867 * values.
868 *
869 * @param symbol The new decimal symbol.
870 */
871 void setMonetaryDecimalSymbol(const QString & symbol);
872 /**
873 * Changes the current currency symbol.
874 *
875 * @param symbol The new currency symbol
876 */
877 void setCurrencySymbol(const QString & symbol);
878
879 /**
880 * Returns the preferred page size for printing.
881 *
882 * @return The preferred page size, cast it to QPrinter::PageSize
883 */
884 int pageSize() const;
885
886 /**
887 * Changes the preferred page size when printing.
888 *
889 * @param paperFormat the new preferred page size in the format QPrinter::PageSize
890 */
891 void setPageSize(int paperFormat);
892
893 /**
894 * The Metric system will give you information in mm, while the
895 * Imperial system will give you information in inches.
896 */
897 enum MeasureSystem { Metric, Imperial };
898
899 /**
900 * Returns which measuring system we use.
901 *
902 * @return The preferred measuring system
903 */
904 MeasureSystem measureSystem() const;
905
906 /**
907 * Changes the preferred measuring system.
908 *
909 * @return value The preferred measuring system
910 */
911 void setMeasureSystem(MeasureSystem value);
912
913 /**
914 * Adds another catalogue to search for translation lookup.
915 * This function is useful for extern libraries and/or code,
916 * that provides its own messages.
917 *
918 * If the catalogue does not exist for the chosen language,
919 * it will be ignored and en_US will be used.
920 *
921 * @param catalogue The catalogue to add.
922 */
923 void insertCatalogue(const QString& catalogue);
924
925 /**
926 * Removes a catalog for translation lookup.
927 * @param catalogue The catalogue to remove.
928 * @see insertCatalogue()
929 */
930 void removeCatalogue(const QString &catalogue);
931
932 /**
933 * Sets the active catalog for translation lookup.
934 * @param catalogue The catalogue to activate.
935 */
936 void setActiveCatalogue(const QString &catalogue);
937
938 /**
939 * Translates a message as a QTranslator is supposed to.
940 * The parameters are similar to i18n(), but the result
941 * value has other semantics (it can be QString::null)
942 * @since 3.1
943 **/
944 QString translateQt(const char *context,
945 const char *sourceText,
946 const char *message) const;
947
948 /**
949 * Returns list of all known ISO 639-1 codes.
950 * @return a list of all language codes
951 * @since 3.1
952 */
953 QStringList allLanguagesTwoAlpha() const;
954
955 /**
956 * Convert a ISO 639-1 code to a human readable form.
957 * @param code the language ISO 639-1 code
958 * @return the human readable form
959 * @since 3.1
960 */
961 QString twoAlphaToLanguageName(const QString &code) const;
962
963 /**
964 * Returns list of all known country codes.
965 * @return a list of all country codes
966 * @since 3.1
967 */
968 QStringList allCountriesTwoAlpha() const;
969
970 /**
971 * Convert a country code to a human readable form.
972 * @param code the country code
973 * @return the human readable form of the country name
974 * @since 3.1
975 */
976 QString twoAlphaToCountryName(const QString &code) const;
977
978
979
980 int timezoneOffset( QString );
981 QStringList timeZoneList() const;
982 void setDaylightSaving( bool, int , int );
983 int localTimeOffset(const QDateTime &);
984 void setTimezone( const QString &timeZone );
985
986 void setHore24Format ( bool );
987 void setWeekStartMonday( bool );
988 void setIntDateFormat( int );
989 void setLanguage( int );
990
991
992
993 /**
994 * Returns the parts of the parameter str understood as language setting
995 * the format is language_COUNTRY.charset
996 *
997 * @param str The string to split.
998 * @param language This will be set to the language part of the string.
999 * @param country This will be set to the country part of the string.
1000 * @param charset This will be set to the charset part of the string.
1001 */
1002 static void splitLocale(const QString & str,
1003 QString & language,
1004 QString & country,
1005 QString & charset);
1006
1007 /**
1008 * Use this to as main catalogue for *all* KLocales, if not the appname
1009 * will be used. This function is best to be the very first instruction
1010 * in your program's main function as it only has an effect before the
1011 * first KLocale object is created (and this is in common KDE applications
1012 * quite early).
1013 *
1014 * @param catalogue Catalogue to override all other main catalogues.
1015 */
1016 static void setMainCatalogue(const char *catalogue);
1017
1018 /**
1019 * Finds localized resource in resourceDir( rtype ) + \<lang> + fname.
1020 *
1021 * @param fname relative path to find
1022 * @param rtype resource type to use
1023 */
1024 static QString langLookup(const QString &fname, const char *rtype = "html");
1025
1026 /**
1027 * Returns the name of the internal language.
1028 *
1029 * @return Name of the default language
1030 */
1031 static QString defaultLanguage();
1032
1033 /**
1034 * Returns the name of the default country.
1035 *
1036 * @return Name of the default country
1037 */
1038 static QString defaultCountry();
1039
1040
1041 /**
1042 * @internal Called from KConfigBackend to initialize language.
1043 */
1044 static QString _initLanguage(KConfigBase *config);
1045
1046#ifdef KDE_NO_COMPAT
1047private:
1048#endif
1049 /**
1050 * @deprecated
1051 * use formatMoney(double)
1052 */
1053 QString formatMoney(const QString &numStr) const;
1054
1055 /**
1056 * @deprecated
1057 * use formatNumber(double)
1058 */
1059 QString formatNumber(const QString &numStr) const;
1060
1061 /**
1062 * @deprecated
1063 * Use languageList()
1064 *
1065 * @return String containing language codes separated by colons
1066 */
1067 QString languages() const;
1068
1069 /**
1070 * @deprecated
1071 * @return True
1072 */
1073 bool setCharset(const QString & charset);
1074
1075 /**
1076 * @deprecated
1077 * @see encoding
1078 */
1079 QString charset() const;
1080
1081protected:
1082 /**
1083 * @internal Creates a KLocale object for KGlobal and inits the locale
1084 * pointer.
1085 */
1086 static void initInstance();
1087
1088private:
1089 /**
1090 * @internal Inits the localization part of the instance with the config
1091 * object.
1092 *
1093 * @param config The configuration object used for init.
1094 */
1095 void initFormat(KConfig *config);
1096
1097 /**
1098 * @internal Inits the language part of the instance with the given config
1099 * object. It should be valid and contain the global entries.
1100 *
1101 * @param config The configuration object used for init
1102 * @param useEnv True if we should use environment variables
1103 */
1104 void initLanguage(KConfig * config, bool useEnv);
1105
1106 /**
1107 * @internal Figures out which encoding the user prefers.
1108 *
1109 * @param config The configuration object used for init
1110 */
1111 void initEncoding(KConfig * config);
1112
1113 /**
1114 * @internal Figures out which catalogues to use.
1115 *
1116 * @param catalogue The name of the main catalogue
1117 */
1118 void initCatalogue(const QString & catalogue);
1119
1120 /**
1121 * @internal Figures out which encoding the user prefers for filenames
1122 * and sets up the appropriate QFile encoding and decoding functions.
1123 */
1124 void initFileNameEncoding(KConfig *config);
1125
1126 /**
1127 * @internal A QFile filename encoding function (QFile::encodeFn).
1128 */
1129 static QCString encodeFileNameUTF8( const QString & fileName );
1130
1131 /**
1132 * @internal QFile filename decoding function (QFile::decodeFn).
1133 */
1134 static QString decodeFileNameUTF8( const QCString & localFileName );
1135
1136 /**
1137 * @internal Changes the file name of the catalogue to the correct
1138 * one.
1139 */
1140 void initCatalogue( KCatalogue & catalogue );
1141
1142 /**
1143 * @internal Reads the language and format configuration form disk.
1144 */
1145 void doBindInit();
1146
1147 /**
1148 * @internal Ensures that the format configuration is read.
1149 */
1150 void doFormatInit() const;
1151
1152 /**
1153 * @internal Reads the format configuration from disk.
1154 */
1155 void initFormat();
1156
1157 /**
1158 * @internal function used by the two translate versions
1159 */
1160 QString translate_priv(const char *index,
1161 const char *text,
1162 const char ** original = 0) const;
1163
1164 /**
1165 * @internal function used to determine if we are using the en_US translation
1166 */
1167 bool useDefaultLanguage() const;
1168
1169 /**
1170 * @internal Checks if the specified language is installed
1171 */
1172 bool isLanguageInstalled(const QString & language) const;
1173
1174 /**
1175 * @internal Retrieves the file name of the catalogue, or QString::null
1176 * if not found.
1177 */
1178 static QString catalogueFileName(const QString & language,
1179 const KCatalogue & catalogue);
1180
1181
1182private:
1183 // Numbers and money
1184 QString m_decimalSymbol;
1185 QString m_thousandsSeparator;
1186 QString m_currencySymbol;
1187 QString m_monetaryDecimalSymbol;
1188 QString m_monetaryThousandsSeparator;
1189 QString m_positiveSign;
1190 QString m_negativeSign;
1191 int m_fracDigits;
1192 SignPosition m_positiveMonetarySignPosition;
1193 SignPosition m_negativeMonetarySignPosition;
1194
1195 // Date and time
1196 QString m_timeFormat;
1197 QString m_dateFormat;
1198 QString m_dateFormatShort;
1199
1200 QString m_language;
1201 QString m_country;
1202
1203 QStringList mTimeZoneList;
1204 bool daylightEnabled;
1205 int mDaylightTZoffset;
1206 int mNondaylightTZoffset;
1207 bool mSouthDaylight;
1208 int daylightStart, daylightEnd, mTimeZoneOffset;
1209 bool mWeekStartsMonday;
1210 bool mHourF24Format;
1211 int mIntDateFormat;
1212 int mLanguage;
1213
1214
1215
1216
1217 bool m_weekStartsMonday; //### remove for KDE 4.0
1218 bool m_positivePrefixCurrencySymbol;
1219 bool m_negativePrefixCurrencySymbol;
1220
1221 KLocalePrivate *d;
1222};
1223
1224#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 @@
1/*
2 Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License (LGPL)
7 version 2 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
19 RSA Data Security, Inc. Created 1991. All rights reserved.
20
21 The KMD5 class is based on a C++ implementation of
22 "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
23 Mordechai T. Abzug,Copyright (c) 1995. This implementation
24 passes the test-suite as defined in RFC 1321.
25
26 The encoding and decoding utilities in KCodecs with the exception of
27 quoted-printable are based on the java implementation in HTTPClient
28 package by Ronald Tschal� Copyright (C) 1996-1999.
29
30 The quoted-printable codec as described in RFC 2045, section 6.7. is by
31 Rik Hemsley (C) 2001.
32*/
33
34//US #include <config.h>
35
36#include <stdio.h>
37#include <string.h>
38#include <stdlib.h>
39
40#include <kdebug.h>
41#include "kmdcodec.h"
42
43#define KMD5_S11 7
44#define KMD5_S12 12
45#define KMD5_S13 17
46#define KMD5_S14 22
47#define KMD5_S21 5
48#define KMD5_S22 9
49#define KMD5_S23 14
50#define KMD5_S24 20
51#define KMD5_S31 4
52#define KMD5_S32 11
53#define KMD5_S33 16
54#define KMD5_S34 23
55#define KMD5_S41 6
56#define KMD5_S42 10
57#define KMD5_S43 15
58#define KMD5_S44 21
59
60const char KCodecs::Base64EncMap[64] =
61{
62 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
63 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
64 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
65 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66,
66 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
67 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
68 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
69 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F
70};
71
72const char KCodecs::Base64DecMap[128] =
73{
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
80 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
81 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
83 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
84 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
85 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20,
87 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
88 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
89 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00
90};
91
92const char KCodecs::UUEncMap[64] =
93{
94 0x60, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
95 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
96 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
97 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
98 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
99 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
100 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
101 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F
102};
103
104const char KCodecs::UUDecMap[128] =
105{
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
111 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
112 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
113 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
114 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
115 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
116 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
117 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
122};
123
124const char KCodecs::hexChars[16] =
125{
126 '0', '1', '2', '3', '4', '5', '6', '7',
127 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
128};
129
130const unsigned int KCodecs::maxQPLineLength = 70;
131
132
133/******************************** KCodecs ********************************/
134// strchr(3) for broken systems.
135static int rikFindChar(register const char * _s, const char c)
136{
137 register const char * s = _s;
138
139 while (true)
140 {
141 if ((0 == *s) || (c == *s)) break; ++s;
142 if ((0 == *s) || (c == *s)) break; ++s;
143 if ((0 == *s) || (c == *s)) break; ++s;
144 if ((0 == *s) || (c == *s)) break; ++s;
145 }
146
147 return s - _s;
148}
149
150QCString KCodecs::quotedPrintableEncode(const QByteArray& in, bool useCRLF)
151{
152 QByteArray out;
153 quotedPrintableEncode (in, out, useCRLF);
154 return QCString (out.data(), out.size()+1);
155}
156
157QCString KCodecs::quotedPrintableEncode(const QCString& str, bool useCRLF)
158{
159 if (str.isEmpty())
160 return "";
161
162 QByteArray in (str.length());
163 memcpy (in.data(), str.data(), str.length());
164 return quotedPrintableEncode(in, useCRLF);
165}
166
167void KCodecs::quotedPrintableEncode(const QByteArray& in, QByteArray& out, bool useCRLF)
168{
169 out.resize (0);
170 if (in.isEmpty())
171 return;
172
173 char *cursor;
174 const char *data;
175 unsigned int lineLength;
176 unsigned int pos;
177
178 const unsigned int length = in.size();
179 const unsigned int end = length - 1;
180
181
182 // Reasonable guess for output size when we're encoding
183 // mostly-ASCII data. It doesn't really matter, because
184 // the underlying allocation routines are quite efficient,
185 // but it's nice to have 0 allocations in many cases.
186 out.resize ((length*12)/10);
187 cursor = out.data();
188 data = in.data();
189 lineLength = 0;
190 pos = 0;
191
192 for (unsigned int i = 0; i < length; i++)
193 {
194 unsigned char c (data[i]);
195
196 // check if we have to enlarge the output buffer, use
197 // a safety margin of 16 byte
198 pos = cursor-out.data();
199 if (out.size()-pos < 16) {
200 out.resize(out.size()+4096);
201 cursor = out.data()+pos;
202 }
203
204 // Plain ASCII chars just go straight out.
205
206 if ((c >= 33) && (c <= 126) && ('=' != c))
207 {
208 *cursor++ = c;
209 ++lineLength;
210 }
211
212 // Spaces need some thought. We have to encode them at eol (or eof).
213
214 else if (' ' == c)
215 {
216 if
217 (
218 (i >= length)
219 ||
220 ((i < end) && ((useCRLF && ('\r' == data[i + 1]) && ('\n' == data[i + 2]))
221 ||
222 (!useCRLF && ('\n' == data[i + 1]))))
223 )
224 {
225 *cursor++ = '=';
226 *cursor++ = '2';
227 *cursor++ = '0';
228
229 lineLength += 3;
230 }
231 else
232 {
233 *cursor++ = ' ';
234 ++lineLength;
235 }
236 }
237 // If we find a line break, just let it through.
238 else if ((useCRLF && ('\r' == c) && (i < end) && ('\n' == data[i + 1])) ||
239 (!useCRLF && ('\n' == c)))
240 {
241 lineLength = 0;
242
243 if (useCRLF) {
244 *cursor++ = '\r';
245 *cursor++ = '\n';
246 ++i;
247 } else {
248 *cursor++ = '\n';
249 }
250 }
251
252 // Anything else is converted to =XX.
253
254 else
255 {
256 *cursor++ = '=';
257 *cursor++ = hexChars[c / 16];
258 *cursor++ = hexChars[c % 16];
259
260 lineLength += 3;
261 }
262
263 // If we're approaching the maximum line length, do a soft line break.
264
265 if ((lineLength > maxQPLineLength) && (i < end))
266 {
267 if (useCRLF) {
268 *cursor++ = '=';
269 *cursor++ = '\r';
270 *cursor++ = '\n';
271 } else {
272 *cursor++ = '=';
273 *cursor++ = '\n';
274 }
275
276 lineLength = 0;
277 }
278 }
279
280 out.truncate(cursor - out.data());
281}
282
283QCString KCodecs::quotedPrintableDecode(const QByteArray & in)
284{
285 QByteArray out;
286 quotedPrintableDecode (in, out);
287 return QCString (out.data(), out.size()+1);
288}
289
290QCString KCodecs::quotedPrintableDecode(const QCString & str)
291{
292 if (str.isEmpty())
293 return "";
294
295 QByteArray in (str.length());
296 memcpy (in.data(), str.data(), str.length());
297 return quotedPrintableDecode (in);
298}
299
300void KCodecs::quotedPrintableDecode(const QByteArray& in, QByteArray& out)
301{
302 // clear out the output buffer
303 out.resize (0);
304 if (in.isEmpty())
305 return;
306
307 char *cursor;
308 const char *data;
309 const unsigned int length = in.size();
310
311 data = in.data();
312 out.resize (length);
313 cursor = out.data();
314
315 for (unsigned int i = 0; i < length; i++)
316 {
317 char c(in.at(i));
318
319 if ('=' == c)
320 {
321 if (i < length - 2)
322 {
323 char c1 = in.at(i + 1);
324 char c2 = in.at(i + 2);
325
326 if (('\n' == c1) || ('\r' == c1 && '\n' == c2))
327 {
328 // Soft line break. No output.
329 if ('\r' == c1)
330 i += 2; // CRLF line breaks
331 else
332 i += 1;
333 }
334 else
335 {
336 // =XX encoded byte.
337
338 int hexChar0 = rikFindChar(hexChars, c1);
339 int hexChar1 = rikFindChar(hexChars, c2);
340
341 if (hexChar0 < 16 && hexChar1 < 16)
342 {
343 *cursor++ = char((hexChar0 * 16) | hexChar1);
344 i += 2;
345 }
346 }
347 }
348 }
349 else
350 {
351 *cursor++ = c;
352 }
353 }
354
355 out.truncate(cursor - out.data());
356}
357
358QCString KCodecs::base64Encode( const QCString& str, bool insertLFs )
359{
360 if ( str.isEmpty() )
361 return "";
362
363 QByteArray in (str.length());
364 memcpy( in.data(), str.data(), str.length() );
365 return base64Encode( in, insertLFs );
366}
367
368QCString KCodecs::base64Encode( const QByteArray& in, bool insertLFs )
369{
370 QByteArray out;
371 base64Encode( in, out, insertLFs );
372 return QCString( out.data(), out.size()+1 );
373}
374
375void KCodecs::base64Encode( const QByteArray& in, QByteArray& out,
376 bool insertLFs )
377{
378 // clear out the output buffer
379 out.resize (0);
380 if ( in.isEmpty() )
381 return;
382
383 unsigned int sidx = 0;
384 unsigned int didx = 0;
385 const char* data = in.data();
386 const unsigned int len = in.size();
387
388 unsigned int out_len = ((len+2)/3)*4;
389
390 // Deal with the 76 characters or less per
391 // line limit specified in RFC 2045 on a
392 // pre request basis.
393 insertLFs = (insertLFs && out_len > 76);
394 if ( insertLFs )
395 out_len += ((out_len-1)/76);
396
397 int count = 0;
398 out.resize( out_len );
399
400 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
401 if ( len > 1 )
402 {
403 while (sidx < len-2)
404 {
405 if ( insertLFs )
406 {
407 if ( count && (count%76) == 0 )
408 out.at(didx++) = '\n';
409 count += 4;
410 }
411 out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077];
412 out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 |
413 (data[sidx] << 4) & 077];
414 out.at(didx++) = Base64EncMap[(data[sidx+2] >> 6) & 003 |
415 (data[sidx+1] << 2) & 077];
416 out.at(didx++) = Base64EncMap[data[sidx+2] & 077];
417 sidx += 3;
418 }
419 }
420
421 if (sidx < len)
422 {
423 if ( insertLFs && (count > 0) && (count%76) == 0 )
424 out.at(didx++) = '\n';
425
426 out.at(didx++) = Base64EncMap[(data[sidx] >> 2) & 077];
427 if (sidx < len-1)
428 {
429 out.at(didx++) = Base64EncMap[(data[sidx+1] >> 4) & 017 |
430 (data[sidx] << 4) & 077];
431 out.at(didx++) = Base64EncMap[(data[sidx+1] << 2) & 077];
432 }
433 else
434 {
435 out.at(didx++) = Base64EncMap[(data[sidx] << 4) & 077];
436 }
437 }
438
439 // Add padding
440 while (didx < out.size())
441 {
442 out.at(didx) = '=';
443 didx++;
444 }
445}
446
447QCString KCodecs::base64Decode( const QCString& str )
448{
449 if ( str.isEmpty() )
450 return "";
451
452 QByteArray in( str.length() );
453 memcpy( in.data(), str.data(), str.length() );
454 return base64Decode( in );
455}
456
457QCString KCodecs::base64Decode( const QByteArray& in )
458{
459 QByteArray out;
460 base64Decode( in, out );
461 return QCString( out.data(), out.size()+1 );
462}
463
464void KCodecs::base64Decode( const QByteArray& in, QByteArray& out )
465{
466 out.resize(0);
467 if ( in.isEmpty() )
468 return;
469
470 unsigned int count = 0;
471 unsigned int len = in.size(), tail = len;
472 const char* data = in.data();
473
474 // Deal with possible *nix "BEGIN" marker!!
475 while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
476 data[count] == '\t' || data[count] == ' ') )
477 count++;
478
479 if ( QString(data+count).left(5).lower() == "begin" )
480 {
481 count += 5;
482 while ( count < len && data[count] != '\n' && data[count] != '\r' )
483 count++;
484
485 while ( count < len && (data[count] == '\n' || data[count] == '\r') )
486 count ++;
487
488 data += count;
489 tail = (len -= count);
490 }
491
492 // Find the tail end of the actual encoded data even if
493 // there is/are trailing CR and/or LF.
494 while ( data[tail-1] == '=' || data[tail-1] == '\n' ||
495 data[tail-1] == '\r' )
496 if ( data[--tail] != '=' ) len = tail;
497
498 unsigned int outIdx = 0;
499 out.resize( (count=len) );
500 for (unsigned int idx = 0; idx < count; idx++)
501 {
502 // Adhere to RFC 2045 and ignore characters
503 // that are not part of the encoding table.
504 unsigned char ch = data[idx];
505 if ((ch > 47 && ch < 58) || (ch > 64 && ch < 91) ||
506 (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=')
507 {
508 out.at(outIdx++) = Base64DecMap[ch];
509 }
510 else
511 {
512 len--;
513 tail--;
514 }
515 }
516
517 // kdDebug() << "Tail size = " << tail << ", Length size = " << len << endl;
518
519 // 4-byte to 3-byte conversion
520 len = (tail>(len/4)) ? tail-(len/4) : 0;
521 unsigned int sidx = 0, didx = 0;
522 if ( len > 1 )
523 {
524 while (didx < len-2)
525 {
526 out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
527 out.at(didx+1) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
528 out.at(didx+2) = (((out.at(sidx+2) << 6) & 255) | (out.at(sidx+3) & 077));
529 sidx += 4;
530 didx += 3;
531 }
532 }
533
534 if (didx < len)
535 out.at(didx) = (((out.at(sidx) << 2) & 255) | ((out.at(sidx+1) >> 4) & 003));
536
537 if (++didx < len )
538 out.at(didx) = (((out.at(sidx+1) << 4) & 255) | ((out.at(sidx+2) >> 2) & 017));
539
540 // Resize the output buffer
541 if ( len == 0 || len < out.size() )
542 out.resize(len);
543}
544
545QCString KCodecs::uuencode( const QCString& str )
546{
547 if ( str.isEmpty() )
548 return "";
549
550 QByteArray in;
551 in.resize( str.length() );
552 memcpy( in.data(), str.data(), str.length() );
553 return uuencode( in );
554}
555
556QCString KCodecs::uuencode( const QByteArray& in )
557{
558 QByteArray out;
559 uuencode( in, out );
560 return QCString( out.data(), out.size()+1 );
561}
562
563void KCodecs::uuencode( const QByteArray& in, QByteArray& out )
564{
565 out.resize( 0 );
566 if( in.isEmpty() )
567 return;
568
569 unsigned int sidx = 0;
570 unsigned int didx = 0;
571 unsigned int line_len = 45;
572
573 const char nl[] = "\n";
574 const char* data = in.data();
575 const unsigned int nl_len = strlen(nl);
576 const unsigned int len = in.size();
577
578 out.resize( (len+2)/3*4 + ((len+line_len-1)/line_len)*(nl_len+1) );
579 // split into lines, adding line-length and line terminator
580 while (sidx+line_len < len)
581 {
582 // line length
583 out.at(didx++) = UUEncMap[line_len];
584
585 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
586 for (unsigned int end = sidx+line_len; sidx < end; sidx += 3)
587 {
588 out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
589 out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
590 (data[sidx] << 4) & 077];
591 out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 |
592 (data[sidx+1] << 2) & 077];
593 out.at(didx++) = UUEncMap[data[sidx+2] & 077];
594 }
595
596 // line terminator
597 //for (unsigned int idx=0; idx < nl_len; idx++)
598 //out.at(didx++) = nl[idx];
599 memcpy(out.data()+didx, nl, nl_len);
600 didx += nl_len;
601 }
602
603 // line length
604 out.at(didx++) = UUEncMap[len-sidx];
605 // 3-byte to 4-byte conversion + 0-63 to ascii printable conversion
606 while (sidx+2 < len)
607 {
608 out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
609 out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
610 (data[sidx] << 4) & 077];
611 out.at(didx++) = UUEncMap[(data[sidx+2] >> 6) & 003 |
612 (data[sidx+1] << 2) & 077];
613 out.at(didx++) = UUEncMap[data[sidx+2] & 077];
614 sidx += 3;
615 }
616
617 if (sidx < len-1)
618 {
619 out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
620 out.at(didx++) = UUEncMap[(data[sidx+1] >> 4) & 017 |
621 (data[sidx] << 4) & 077];
622 out.at(didx++) = UUEncMap[(data[sidx+1] << 2) & 077];
623 out.at(didx++) = UUEncMap[0];
624 }
625 else if (sidx < len)
626 {
627 out.at(didx++) = UUEncMap[(data[sidx] >> 2) & 077];
628 out.at(didx++) = UUEncMap[(data[sidx] << 4) & 077];
629 out.at(didx++) = UUEncMap[0];
630 out.at(didx++) = UUEncMap[0];
631 }
632
633 // line terminator
634 memcpy(out.data()+didx, nl, nl_len);
635 didx += nl_len;
636
637 // sanity check
638 if ( didx != out.size() )
639 out.resize( 0 );
640}
641
642QCString KCodecs::uudecode( const QCString& str )
643{
644 if ( str.isEmpty() )
645 return "";
646
647 QByteArray in;
648 in.resize( str.length() );
649 memcpy( in.data(), str.data(), str.length() );
650 return uudecode( in );
651}
652
653QCString KCodecs::uudecode( const QByteArray& in )
654{
655 QByteArray out;
656 uudecode( in, out );
657 return QCString( out.data(), out.size()+1 );
658}
659
660void KCodecs::uudecode( const QByteArray& in, QByteArray& out )
661{
662 out.resize( 0 );
663 if( in.isEmpty() )
664 return;
665
666 unsigned int sidx = 0;
667 unsigned int didx = 0;
668 unsigned int len = in.size();
669 unsigned int line_len, end;
670 const char* data = in.data();
671
672 // Deal with *nix "BEGIN"/"END" separators!!
673 unsigned int count = 0;
674 while ( count < len && (data[count] == '\n' || data[count] == '\r' ||
675 data[count] == '\t' || data[count] == ' ') )
676 count ++;
677
678 bool hasLF = false;
679 if ( QString( data+count).left(5).lower() == "begin" )
680 {
681 count += 5;
682 while ( count < len && data[count] != '\n' && data[count] != '\r' )
683 count ++;
684
685 while ( count < len && (data[count] == '\n' || data[count] == '\r') )
686 count ++;
687
688 data += count;
689 len -= count;
690 hasLF = true;
691 }
692
693 out.resize( len/4*3 );
694 while ( sidx < len )
695 {
696 // get line length (in number of encoded octets)
697 line_len = UUDecMap[ (unsigned char) data[sidx++]];
698 // ascii printable to 0-63 and 4-byte to 3-byte conversion
699 end = didx+line_len;
700 char A, B, C, D;
701 if (end > 2) {
702 while (didx < end-2)
703 {
704 A = UUDecMap[(unsigned char) data[sidx]];
705 B = UUDecMap[(unsigned char) data[sidx+1]];
706 C = UUDecMap[(unsigned char) data[sidx+2]];
707 D = UUDecMap[(unsigned char) data[sidx+3]];
708 out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) );
709 out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) );
710 out.at(didx++) = ( ((C << 6) & 255) | (D & 077) );
711 sidx += 4;
712 }
713 }
714
715 if (didx < end)
716 {
717 A = UUDecMap[(unsigned char) data[sidx]];
718 B = UUDecMap[(unsigned char) data[sidx+1]];
719 out.at(didx++) = ( ((A << 2) & 255) | ((B >> 4) & 003) );
720 }
721
722 if (didx < end)
723 {
724 B = UUDecMap[(unsigned char) data[sidx+1]];
725 C = UUDecMap[(unsigned char) data[sidx+2]];
726 out.at(didx++) = ( ((B << 4) & 255) | ((C >> 2) & 017) );
727 }
728
729 // skip padding
730 while (sidx < len && data[sidx] != '\n' && data[sidx] != '\r')
731 sidx++;
732
733 // skip end of line
734 while (sidx < len && (data[sidx] == '\n' || data[sidx] == '\r'))
735 sidx++;
736
737 // skip the "END" separator when present.
738 if ( hasLF && QString( data+sidx).left(3).lower() == "end" )
739 break;
740 }
741
742 if ( didx < out.size() )
743 out.resize( didx );
744}
745
746/******************************** KMD5 ********************************/
747KMD5::KMD5()
748{
749 init();
750}
751
752KMD5::KMD5(const char *in, int len)
753{
754 init();
755 update(in, len);
756}
757
758KMD5::KMD5(const QByteArray& in)
759{
760 init();
761 update( in );
762}
763
764KMD5::KMD5(const QCString& in)
765{
766 init();
767 update( in );
768}
769
770void KMD5::update(const QByteArray& in)
771{
772 update(in.data(), int(in.size()));
773}
774
775void KMD5::update(const QCString& in)
776{
777 update(in.data(), int(in.length()));
778}
779
780void KMD5::update(const unsigned char* in, int len)
781{
782 if (len < 0)
783 len = qstrlen(reinterpret_cast<const char*>(in));
784
785 if (!len)
786 return;
787
788 if (m_finalized) {
789 kdWarning() << "KMD5::update called after state was finalized!" << endl;
790 return;
791 }
792
793 Q_UINT32 in_index;
794 Q_UINT32 buffer_index;
795 Q_UINT32 buffer_space;
796 Q_UINT32 in_length = static_cast<Q_UINT32>( len );
797
798 buffer_index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3F);
799
800 if ( (m_count[0] += (in_length << 3))<(in_length << 3) )
801 m_count[1]++;
802
803 m_count[1] += (in_length >> 29);
804 buffer_space = 64 - buffer_index;
805
806 if (in_length >= buffer_space)
807 {
808 memcpy (m_buffer + buffer_index, in, buffer_space);
809 transform (m_buffer);
810
811 for (in_index = buffer_space; in_index + 63 < in_length;
812 in_index += 64)
813 transform (reinterpret_cast<const unsigned char*>(in+in_index));
814
815 buffer_index = 0;
816 }
817 else
818 in_index=0;
819
820 memcpy(m_buffer+buffer_index, in+in_index, in_length-in_index);
821}
822
823bool KMD5::update(QIODevice& file)
824{
825 char buffer[1024];
826 int len;
827
828 while ((len=file.readBlock(reinterpret_cast<char*>(buffer), sizeof(buffer))) > 0)
829 update(buffer, len);
830
831 return file.atEnd();
832}
833
834void KMD5::finalize ()
835{
836 if (m_finalized) return;
837
838 Q_UINT8 bits[8];
839 Q_UINT32 index, padLen;
840 static unsigned char PADDING[64]=
841 {
842 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
846 };
847
848 encode (bits, m_count, 8);
849 //memcpy( bits, m_count, 8 );
850
851 // Pad out to 56 mod 64.
852 index = static_cast<Q_UINT32>((m_count[0] >> 3) & 0x3f);
853 padLen = (index < 56) ? (56 - index) : (120 - index);
854 update (reinterpret_cast<const char*>(PADDING), padLen);
855
856 // Append length (before padding)
857 update (reinterpret_cast<const char*>(bits), 8);
858
859 // Store state in digest
860 encode (m_digest, m_state, 16);
861 //memcpy( m_digest, m_state, 16 );
862
863 // Fill sensitive information with zero's
864 memset ( (void *)m_buffer, 0, sizeof(*m_buffer));
865
866 m_finalized = true;
867}
868
869
870bool KMD5::verify( const KMD5::Digest& digest)
871{
872 finalize();
873 return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest)));
874}
875
876bool KMD5::verify( const QCString& hexdigest)
877{
878 finalize();
879 return (0 == strcmp(hexDigest().data(), hexdigest));
880}
881
882const KMD5::Digest& KMD5::rawDigest()
883{
884 finalize();
885 return m_digest;
886}
887
888void KMD5::rawDigest( KMD5::Digest& bin )
889{
890 finalize();
891 memcpy( bin, m_digest, 16 );
892}
893
894
895QCString KMD5::hexDigest()
896{
897 QCString s(33);
898
899 finalize();
900 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
901 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
902 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
903 m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
904
905 return s;
906}
907
908void KMD5::hexDigest(QCString& s)
909{
910 finalize();
911 s.resize(33);
912 sprintf(s.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
913 m_digest[0], m_digest[1], m_digest[2], m_digest[3], m_digest[4], m_digest[5],
914 m_digest[6], m_digest[7], m_digest[8], m_digest[9], m_digest[10], m_digest[11],
915 m_digest[12], m_digest[13], m_digest[14], m_digest[15]);
916}
917
918QCString KMD5::base64Digest()
919{
920 QByteArray ba(16);
921
922 finalize();
923 memcpy(ba.data(), m_digest, 16);
924 return KCodecs::base64Encode(ba);
925}
926
927
928void KMD5::init()
929{
930 d = 0;
931 reset();
932}
933
934void KMD5::reset()
935{
936 m_finalized = false;
937
938 m_count[0] = 0;
939 m_count[1] = 0;
940
941 m_state[0] = 0x67452301;
942 m_state[1] = 0xefcdab89;
943 m_state[2] = 0x98badcfe;
944 m_state[3] = 0x10325476;
945
946 memset ( m_buffer, 0, sizeof(*m_buffer));
947 memset ( m_digest, 0, sizeof(*m_digest));
948}
949
950void KMD5::transform( const unsigned char block[64] )
951{
952
953 Q_UINT32 a = m_state[0], b = m_state[1], c = m_state[2], d = m_state[3], x[16];
954
955 decode (x, block, 64);
956 //memcpy( x, block, 64 );
957
958//US Q_ASSERT(!m_finalized); // not just a user error, since the method is private
959 ASSERT(!m_finalized); // not just a user error, since the method is private
960
961 /* Round 1 */
962 FF (a, b, c, d, x[ 0], KMD5_S11, 0xd76aa478); /* 1 */
963 FF (d, a, b, c, x[ 1], KMD5_S12, 0xe8c7b756); /* 2 */
964 FF (c, d, a, b, x[ 2], KMD5_S13, 0x242070db); /* 3 */
965 FF (b, c, d, a, x[ 3], KMD5_S14, 0xc1bdceee); /* 4 */
966 FF (a, b, c, d, x[ 4], KMD5_S11, 0xf57c0faf); /* 5 */
967 FF (d, a, b, c, x[ 5], KMD5_S12, 0x4787c62a); /* 6 */
968 FF (c, d, a, b, x[ 6], KMD5_S13, 0xa8304613); /* 7 */
969 FF (b, c, d, a, x[ 7], KMD5_S14, 0xfd469501); /* 8 */
970 FF (a, b, c, d, x[ 8], KMD5_S11, 0x698098d8); /* 9 */
971 FF (d, a, b, c, x[ 9], KMD5_S12, 0x8b44f7af); /* 10 */
972 FF (c, d, a, b, x[10], KMD5_S13, 0xffff5bb1); /* 11 */
973 FF (b, c, d, a, x[11], KMD5_S14, 0x895cd7be); /* 12 */
974 FF (a, b, c, d, x[12], KMD5_S11, 0x6b901122); /* 13 */
975 FF (d, a, b, c, x[13], KMD5_S12, 0xfd987193); /* 14 */
976 FF (c, d, a, b, x[14], KMD5_S13, 0xa679438e); /* 15 */
977 FF (b, c, d, a, x[15], KMD5_S14, 0x49b40821); /* 16 */
978
979 /* Round 2 */
980 GG (a, b, c, d, x[ 1], KMD5_S21, 0xf61e2562); /* 17 */
981 GG (d, a, b, c, x[ 6], KMD5_S22, 0xc040b340); /* 18 */
982 GG (c, d, a, b, x[11], KMD5_S23, 0x265e5a51); /* 19 */
983 GG (b, c, d, a, x[ 0], KMD5_S24, 0xe9b6c7aa); /* 20 */
984 GG (a, b, c, d, x[ 5], KMD5_S21, 0xd62f105d); /* 21 */
985 GG (d, a, b, c, x[10], KMD5_S22, 0x2441453); /* 22 */
986 GG (c, d, a, b, x[15], KMD5_S23, 0xd8a1e681); /* 23 */
987 GG (b, c, d, a, x[ 4], KMD5_S24, 0xe7d3fbc8); /* 24 */
988 GG (a, b, c, d, x[ 9], KMD5_S21, 0x21e1cde6); /* 25 */
989 GG (d, a, b, c, x[14], KMD5_S22, 0xc33707d6); /* 26 */
990 GG (c, d, a, b, x[ 3], KMD5_S23, 0xf4d50d87); /* 27 */
991 GG (b, c, d, a, x[ 8], KMD5_S24, 0x455a14ed); /* 28 */
992 GG (a, b, c, d, x[13], KMD5_S21, 0xa9e3e905); /* 29 */
993 GG (d, a, b, c, x[ 2], KMD5_S22, 0xfcefa3f8); /* 30 */
994 GG (c, d, a, b, x[ 7], KMD5_S23, 0x676f02d9); /* 31 */
995 GG (b, c, d, a, x[12], KMD5_S24, 0x8d2a4c8a); /* 32 */
996
997 /* Round 3 */
998 HH (a, b, c, d, x[ 5], KMD5_S31, 0xfffa3942); /* 33 */
999 HH (d, a, b, c, x[ 8], KMD5_S32, 0x8771f681); /* 34 */
1000 HH (c, d, a, b, x[11], KMD5_S33, 0x6d9d6122); /* 35 */
1001 HH (b, c, d, a, x[14], KMD5_S34, 0xfde5380c); /* 36 */
1002 HH (a, b, c, d, x[ 1], KMD5_S31, 0xa4beea44); /* 37 */
1003 HH (d, a, b, c, x[ 4], KMD5_S32, 0x4bdecfa9); /* 38 */
1004 HH (c, d, a, b, x[ 7], KMD5_S33, 0xf6bb4b60); /* 39 */
1005 HH (b, c, d, a, x[10], KMD5_S34, 0xbebfbc70); /* 40 */
1006 HH (a, b, c, d, x[13], KMD5_S31, 0x289b7ec6); /* 41 */
1007 HH (d, a, b, c, x[ 0], KMD5_S32, 0xeaa127fa); /* 42 */
1008 HH (c, d, a, b, x[ 3], KMD5_S33, 0xd4ef3085); /* 43 */
1009 HH (b, c, d, a, x[ 6], KMD5_S34, 0x4881d05); /* 44 */
1010 HH (a, b, c, d, x[ 9], KMD5_S31, 0xd9d4d039); /* 45 */
1011 HH (d, a, b, c, x[12], KMD5_S32, 0xe6db99e5); /* 46 */
1012 HH (c, d, a, b, x[15], KMD5_S33, 0x1fa27cf8); /* 47 */
1013 HH (b, c, d, a, x[ 2], KMD5_S34, 0xc4ac5665); /* 48 */
1014
1015 /* Round 4 */
1016 II (a, b, c, d, x[ 0], KMD5_S41, 0xf4292244); /* 49 */
1017 II (d, a, b, c, x[ 7], KMD5_S42, 0x432aff97); /* 50 */
1018 II (c, d, a, b, x[14], KMD5_S43, 0xab9423a7); /* 51 */
1019 II (b, c, d, a, x[ 5], KMD5_S44, 0xfc93a039); /* 52 */
1020 II (a, b, c, d, x[12], KMD5_S41, 0x655b59c3); /* 53 */
1021 II (d, a, b, c, x[ 3], KMD5_S42, 0x8f0ccc92); /* 54 */
1022 II (c, d, a, b, x[10], KMD5_S43, 0xffeff47d); /* 55 */
1023 II (b, c, d, a, x[ 1], KMD5_S44, 0x85845dd1); /* 56 */
1024 II (a, b, c, d, x[ 8], KMD5_S41, 0x6fa87e4f); /* 57 */
1025 II (d, a, b, c, x[15], KMD5_S42, 0xfe2ce6e0); /* 58 */
1026 II (c, d, a, b, x[ 6], KMD5_S43, 0xa3014314); /* 59 */
1027 II (b, c, d, a, x[13], KMD5_S44, 0x4e0811a1); /* 60 */
1028 II (a, b, c, d, x[ 4], KMD5_S41, 0xf7537e82); /* 61 */
1029 II (d, a, b, c, x[11], KMD5_S42, 0xbd3af235); /* 62 */
1030 II (c, d, a, b, x[ 2], KMD5_S43, 0x2ad7d2bb); /* 63 */
1031 II (b, c, d, a, x[ 9], KMD5_S44, 0xeb86d391); /* 64 */
1032
1033 m_state[0] += a;
1034 m_state[1] += b;
1035 m_state[2] += c;
1036 m_state[3] += d;
1037
1038 memset ( static_cast<void *>(x), 0, sizeof(x) );
1039}
1040
1041inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n)
1042{
1043 return (x << n) | (x >> (32-n)) ;
1044}
1045
1046inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1047{
1048 return (x & y) | (~x & z);
1049}
1050
1051inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1052{
1053 return (x & z) | (y & ~z);
1054}
1055
1056inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1057{
1058 return x ^ y ^ z;
1059}
1060
1061inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z)
1062{
1063 return y ^ (x | ~z);
1064}
1065
1066void KMD5::FF ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1067 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
1068{
1069 a += F(b, c, d) + x + ac;
1070 a = rotate_left (a, s) +b;
1071}
1072
1073void KMD5::GG ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1074 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac)
1075{
1076 a += G(b, c, d) + x + ac;
1077 a = rotate_left (a, s) +b;
1078}
1079
1080void KMD5::HH ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1081 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
1082{
1083 a += H(b, c, d) + x + ac;
1084 a = rotate_left (a, s) +b;
1085}
1086
1087void KMD5::II ( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d,
1088 Q_UINT32 x, Q_UINT32 s, Q_UINT32 ac )
1089{
1090 a += I(b, c, d) + x + ac;
1091 a = rotate_left (a, s) +b;
1092}
1093
1094
1095void KMD5::encode ( unsigned char* output, Q_UINT32 *in, Q_UINT32 len )
1096{
1097#if !defined(WORDS_BIGENDIAN)
1098 memcpy(output, in, len);
1099
1100#else
1101 Q_UINT32 i, j;
1102 for (i = 0, j = 0; j < len; i++, j += 4)
1103 {
1104 output[j] = static_cast<Q_UINT8>((in[i] & 0xff));
1105 output[j+1] = static_cast<Q_UINT8>(((in[i] >> 8) & 0xff));
1106 output[j+2] = static_cast<Q_UINT8>(((in[i] >> 16) & 0xff));
1107 output[j+3] = static_cast<Q_UINT8>(((in[i] >> 24) & 0xff));
1108 }
1109#endif
1110}
1111
1112// Decodes in (Q_UINT8) into output (Q_UINT32). Assumes len is a
1113// multiple of 4.
1114void KMD5::decode (Q_UINT32 *output, const unsigned char* in, Q_UINT32 len)
1115{
1116#if !defined(WORDS_BIGENDIAN)
1117 memcpy(output, in, len);
1118
1119#else
1120 Q_UINT32 i, j;
1121 for (i = 0, j = 0; j < len; i++, j += 4)
1122 output[i] = static_cast<Q_UINT32>(in[j]) |
1123 (static_cast<Q_UINT32>(in[j+1]) << 8) |
1124 (static_cast<Q_UINT32>(in[j+2]) << 16) |
1125 (static_cast<Q_UINT32>(in[j+3]) << 24);
1126#endif
1127}
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 @@
1/*
2 Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
3 Copyright (C) 2001 Rik Hemsley (rikkus) <rik@kde.org>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License (LGPL)
7 version 2 as published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 RFC 1321 "MD5 Message-Digest Algorithm" Copyright (C) 1991-1992.
19 RSA Data Security, Inc. Created 1991. All rights reserved.
20
21 The KMD5 class is based on a C++ implementation of
22 "RSA Data Security, Inc. MD5 Message-Digest Algorithm" by
23 Mordechai T. Abzug,Copyright (c) 1995. This implementation
24 passes the test-suite as defined in RFC 1321.
25
26 The encoding and decoding utilities in KCodecs with the exception of
27 quoted-printable are based on the java implementation in HTTPClient
28 package by Ronald Tschalär Copyright (C) 1996-1999.
29
30 The quoted-printable codec as described in RFC 2045, section 6.7. is by
31 Rik Hemsley (C) 2001.
32*/
33
34#ifndef _KMDBASE_H
35#define _KMDBASE_H
36
37#define KBase64 KCodecs
38
39#include <qglobal.h>
40#include <qstring.h>
41#include <qiodevice.h>
42
43/**
44 * A wrapper class for the most commonly used encoding and
45 * decoding algorithms. Currently there is support for encoding
46 * and decoding input using base64, uu and the quoted-printable
47 * specifications.
48 *
49 * @sect Usage:
50 *
51 * <PRE>
52 * QCString input = "Aladdin:open sesame";
53 * QCString result = KCodecs::base64Encode(input);
54 * cout << "Result: " << result.data() << endl;
55 *
56 * Output should be
57 * Result: QWxhZGRpbjpvcGVuIHNlc2FtZQ==
58 * </PRE>
59 *
60 * The above example makes use of the convenience functions
61 * (ones that accept/return null-terminated strings) to encode/decode
62 * a string. If what you need is to encode or decode binary data, then
63 * it is highly recommended that you use the functions that take an input
64 * and output QByteArray as arguments. These functions are specifically
65 * tailored for encoding and decoding binary data.
66 *
67 * @short A collection of commonly used encoding and decoding algorithms.
68 * @author Dawit Alemayehu <adawit@kde.org>
69 * @author Rik Hemsley <rik@kde.org>
70 */
71class KCodecs
72{
73public:
74
75 /**
76 * Encodes the given data using the quoted-printable algorithm.
77 *
78 * @param in data to be encoded.
79 * @param useCRLF if true the input data is expected to have
80 * CRLF line breaks and the output will have CRLF line
81 * breaks, too.
82 * @return quoted-printable encoded data.
83 */
84 static QCString quotedPrintableEncode(const QByteArray & in,
85 bool useCRLF = true);
86
87 /**
88 * @overload
89 *
90 * Same as above except it accepts a null terminated
91 * string instead an array.
92 *
93 * @param str data to be encoded.
94 * @param useCRLF if true the input data is expected to have
95 * CRLF line breaks and the output will have CRLF line
96 * breaks, too.
97 * @return quoted-printable encoded data.
98 */
99 static QCString quotedPrintableEncode(const QCString & str,
100 bool useCRLF = true);
101
102 /**
103 * Encodes the given data using the quoted-printable algorithm.
104 *
105 * Use this function if you want the result of the encoding
106 * to be placed in another array which cuts down the number
107 * of copy operation that have to be performed in the process.
108 * This is also the preferred method for encoding binary data.
109 *
110 * NOTE: the output array is first reset and then resized
111 * appropriately before use, hence, all data stored in the
112 * output array will be lost.
113 *
114 * @param in data to be encoded.
115 * @param out decoded data.
116 * @param useCRLF if true the input data is expected to have
117 * CRLF line breaks and the output will have CRLF line
118 * breaks, too.
119 * @return quoted-printable encoded data.
120 */
121 static void quotedPrintableEncode(const QByteArray & in, QByteArray& out,
122 bool useCRLF);
123
124 /**
125 * Decodes a quoted-printable encoded string.
126 *
127 * Accepts data with CRLF or standard unix line breaks.
128 *
129 * @param in the data to be decoded.
130 * @return decoded data.
131 */
132 static QCString quotedPrintableDecode(const QByteArray & in);
133
134 /**
135 * @overload
136 *
137 * Same as above except it accepts a null terminated
138 * string instead an array.
139 *
140 * @param str the data to be decoded.
141 * @return decoded data.
142 */
143 static QCString quotedPrintableDecode(const QCString & str);
144
145 /**
146 * Decodes a quoted-printable encoded data.
147 *
148 * Accepts data with CRLF or standard unix line breaks.
149 * Use this function if you want the result of the decoding
150 * to be placed in another array which cuts down the number
151 * of copy operation that have to be performed in the process.
152 * This is also the preferred method for decoding an encoded
153 * binary data.
154 *
155 * NOTE: the output array is first reset and then resized
156 * appropriately before use, hence, all data stored in the
157 * output array will be lost.
158 *
159 * @param in data to be encoded.
160 * @param out decoded data.
161 *
162 * @return quoted-printable encoded data.
163 */
164 static void quotedPrintableDecode(const QByteArray & in, QByteArray& out);
165
166
167 /**
168 * Encodes the given data using the uuencode algorithm.
169 *
170 * The output is split into lines starting with the number of
171 * encoded octets in the line and ending with a newline. No
172 * line is longer than 45 octets (60 characters), excluding the
173 * line terminator.
174 *
175 * @param in the data to be uuencoded
176 * @return a uuencoded data.
177 */
178 static QCString uuencode( const QByteArray& in );
179
180 /**
181 * @overload
182 *
183 * Same as the above functions except it accepts
184 * a null terminated string instead an array.
185 *
186 * @param str the string to be uuencoded.
187 * @return the encoded string.
188 */
189 static QCString uuencode( const QCString& str );
190
191 /**
192 * Encodes the given data using the uuencode algorithm.
193 *
194 * Use this function if you want the result of the encoding
195 * to be placed in another array and cut down the number of
196 * copy operation that have to be performed in the process.
197 * This is the preffered method for encoding binary data.
198 *
199 * NOTE: the output array is first reset and then resized
200 * appropriately before use, hence, all data stored in the
201 * output array will be lost.
202 *
203 * @param in the data to be uuencoded.
204 * @param out the container for the uudecoded data.
205 */
206 static void uuencode( const QByteArray& in, QByteArray& out );
207
208 /**
209 * Decodes the given data using the uuencode algorithm.
210 *
211 * Any 'begin' and 'end' lines like those generated by
212 * the utilities in unix and unix-like OS will be
213 * automatically ignored.
214 *
215 * @param in the data uuencoded data to be decoded.
216 * @return a decoded string.
217 */
218 static QCString uudecode( const QByteArray& in );
219
220 /**
221 * @overload
222 *
223 * Same as the above functions except it accepts
224 * a null terminated string instead an array.
225 *
226 * @param str the string to be decoded.
227 * @return a uudecoded string.
228 */
229 static QCString uudecode( const QCString& str );
230
231 /**
232 * Decodes the given data using the uudecode algorithm.
233 *
234 * Use this function if you want the result of the decoding
235 * to be placed in another array which cuts down the number
236 * of copy operation that have to be performed in the process.
237 * This is the preferred method for decoding binary data.
238 *
239 * Any 'begin' and 'end' lines like those generated by
240 * the utilities in unix and unix-like OS will be
241 * automatically ignored.
242 *
243 * NOTE: the output array is first reset and then resized
244 * appropriately before use, hence, all data stored in the
245 * output array will be lost.
246 *
247 * @param in the uuencoded-data to be decoded.
248 * @param out the container for the uudecoded data.
249 */
250 static void uudecode( const QByteArray& in, QByteArray& out );
251
252
253 /**
254 * Encodes the given data using the base64 algorithm.
255 *
256 * The boolean argument determines if the encoded data is
257 * going to be restricted to 76 characters or less per line
258 * as specified by RFC 2045. If @p insertLFs is true, then
259 * there will be 76 characters or less per line.
260 *
261 * @param in the data to be encoded.
262 * @param insertLFs limit the number of characters per line.
263 *
264 * @return a base64 encoded string.
265 */
266 static QCString base64Encode( const QByteArray& in, bool insertLFs = false);
267
268 /**
269 * @overload
270 *
271 * Same as the above functions except it accepts
272 * a null terminated string instead an array.
273 *
274 * @param str the string to be encoded.
275 * @param insertLFs limit the number of characters per line.
276 * @return the decoded string.
277 */
278 static QCString base64Encode( const QCString& str, bool insertLFs = false );
279
280 /**
281 * Encodes the given data using the base64 algorithm.
282 *
283 * Use this function if you want the result of the encoding
284 * to be placed in another array which cuts down the number
285 * of copy operation that have to be performed in the process.
286 * This is also the preferred method for encoding binary data.
287 *
288 * The boolean argument determines if the encoded data is going
289 * to be restricted to 76 characters or less per line as specified
290 * by RFC 2045. If @p insertLFs is true, then there will be 76
291 * characters or less per line.
292 *
293 * NOTE: the output array is first reset and then resized
294 * appropriately before use, hence, all data stored in the
295 * output array will be lost.
296 *
297 * @param in the data to be encoded using base64.
298 * @param out the container for the encoded data.
299 * @param insertLFs limit the number of characters per line.
300 */
301 static void base64Encode( const QByteArray& in, QByteArray& out,
302 bool insertLFs = false );
303
304 /**
305 * Decodes the given data that was encoded using the
306 * base64 algorithm.
307 *
308 * @param in the base64-encoded data to be decoded.
309 * @return the decoded data.
310 */
311 static QCString base64Decode( const QByteArray& in );
312
313 /**
314 * @overload
315 *
316 * Same as the above functions except it accepts
317 * a null terminated string instead an array.
318 *
319 * @param str the base64-encoded string.
320 * @return the decoded string.
321 */
322 static QCString base64Decode( const QCString& str );
323
324 /**
325 * Decodes the given data that was encoded with the base64
326 * algorithm.
327 *
328 * Use this function if you want the result of the decoding
329 * to be placed in another array which cuts down the number
330 * of copy operation that have to be performed in the process.
331 * This is also the preferred method for decoding an encoded
332 * binary data.
333 *
334 * NOTE: the output array is first reset and then resized
335 * appropriately before use, hence, all data stored in the
336 * output array will be lost.
337 *
338 * @param in the encoded data to be decoded.
339 * @param out the container for the decoded data.
340 */
341 static void base64Decode( const QByteArray& in, QByteArray& out );
342
343
344private:
345 KCodecs();
346
347private:
348 static const char UUEncMap[64];
349 static const char UUDecMap[128];
350 static const char Base64EncMap[64];
351 static const char Base64DecMap[128];
352 static const char hexChars[16];
353 static const unsigned int maxQPLineLength;
354};
355
356class KMD5Private;
357/**
358 * Provides an easy to use C++ implementation of RSA's
359 * MD5 algorithm.
360 *
361 * The default constructor is designed to provide much the same
362 * functionality as the most commonly used C-implementation, while
363 * the other three constructors are meant to further simplify the
364 * process of obtaining a digest by calculating the result in a
365 * single step.
366 *
367 * KMD5 is state-based, that means you can add new contents with
368 * update() as long as you didn't request the digest value yet.
369 * After the digest value was requested, the object is "finalized"
370 * and you have to call reset() to be able to do another calculation
371 * with it. The reason for this behaviour is that upon requesting
372 * the message digest KMD5 has to pad the received contents up to a
373 * 64 byte boundary to calculate its value. After this operation it
374 * is not possible to resume consuming data.
375 *
376 * @sect Usage:
377 *
378 * A common usage of this class:
379 *
380 * <PRE>
381 * const char* test1;
382 * KMD5::Digest rawResult;
383 *
384 * test1 = "This is a simple test.";
385 * KMD5 context (test1);
386 * cout << "Hex Digest output: " << context.hexDigest().data() << endl;
387 * </PRE>
388 *
389 * To cut down on the unnecessary overhead of creating multiple KMD5
390 * objects, you can simply invoke @ref reset() to reuse the same object
391 * in making another calculation:
392 *
393 * <PRE>
394 * context.reset ();
395 * context.update ("TWO");
396 * context.update ("THREE");
397 * cout << "Hex Digest output: " << context.hexDigest().data() << endl;
398 * </PRE>
399 *
400 * @short An adapted C++ implementation of RSA Data Securities MD5 algorithm.
401 * @author Dirk Mueller <mueller@kde.org>, Dawit Alemayehu <adawit@kde.org>
402 */
403
404class KMD5
405{
406public:
407
408 typedef unsigned char Digest[16];
409
410 KMD5();
411
412 /**
413 * Constructor that updates the digest for the given string.
414 *
415 * @param in C string or binary data
416 * @param len if negative, calculates the length by using
417 * strlen on the first parameter, otherwise
418 * it trusts the given length (does not stop on NUL byte).
419 */
420 KMD5(const char* in, int len = -1);
421
422 /**
423 * @overload
424 *
425 * Same as above except it accepts a QByteArray as its argument.
426 */
427 KMD5(const QByteArray& a );
428
429 /**
430 * @overload
431 *
432 * Same as above except it accepts a QByteArray as its argument.
433 */
434 KMD5(const QCString& a );
435
436 /**
437 * Updates the message to be digested. Be sure to add all data
438 * before you read the digest. After reading the digest, you
439 * can <b>not</b> add more data!
440 *
441 * @param in message to be added to digest
442 * @param len the length of the given message.
443 */
444 void update(const char* in, int len = -1) { update(reinterpret_cast<const unsigned char*>(in), len); }
445
446 /**
447 * @overload
448 */
449 void update(const unsigned char* in, int len = -1);
450
451 /**
452 * @overload
453 *
454 * @param in message to be added to the digest (QByteArray).
455 */
456 void update(const QByteArray& in );
457
458 /**
459 * @overload
460 *
461 * @param in message to be added to the digest (QByteArray).
462 */
463 void update(const QCString& in );
464
465 /**
466 * @overload
467 *
468 * reads the data from an I/O device, i.e. from a file (QFile).
469 *
470 * NOTE that the file must be open for reading.
471 *
472 * @param file a pointer to FILE as returned by calls like f{d,re}open
473 *
474 * @returns false if an error occured during reading.
475 */
476 bool update(QIODevice& file);
477
478 /**
479 * Calling this function will reset the calculated message digest.
480 * Use this method to perform another message digest calculation
481 * without recreating the KMD5 object.
482 */
483 void reset();
484
485 /**
486 * @return the raw representation of the digest
487 */
488 const Digest& rawDigest ();
489
490 /**
491 * Fills the given array with the binary representation of the
492 * message digest.
493 *
494 * Use this method if you do not want to worry about making
495 * copy of the digest once you obtain it.
496 *
497 * @param bin an array of 16 characters ( char[16] )
498 */
499 void rawDigest( KMD5::Digest& bin );
500
501 /**
502 * Returns the value of the calculated message digest in
503 * a hexadecimal representation.
504 */
505 QCString hexDigest ();
506
507 /**
508 * @overload
509 */
510 void hexDigest(QCString&);
511
512 /**
513 * Returns the value of the calculated message digest in
514 * a base64-encoded representation.
515 */
516 QCString base64Digest ();
517
518 /**
519 * returns true if the calculated digest for the given
520 * message matches the given one.
521 */
522 bool verify( const KMD5::Digest& digest);
523
524 /**
525 * @overload
526 */
527 bool verify(const QCString&);
528
529protected:
530 /**
531 * Performs the real update work. Note
532 * that length is implied to be 64.
533 */
534 void transform( const unsigned char buffer[64] );
535
536 /**
537 * finalizes the digest
538 */
539 void finalize();
540
541private:
542 KMD5(const KMD5& u);
543 KMD5& operator=(const KMD5& md);
544
545 void init();
546 void encode( unsigned char* output, Q_UINT32 *in, Q_UINT32 len );
547 void decode( Q_UINT32 *output, const unsigned char* in, Q_UINT32 len );
548
549 Q_UINT32 rotate_left( Q_UINT32 x, Q_UINT32 n );
550 Q_UINT32 F( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
551 Q_UINT32 G( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
552 Q_UINT32 H( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
553 Q_UINT32 I( Q_UINT32 x, Q_UINT32 y, Q_UINT32 z );
554 void FF( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
555 Q_UINT32 s, Q_UINT32 ac );
556 void GG( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
557 Q_UINT32 s, Q_UINT32 ac );
558 void HH( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
559 Q_UINT32 s, Q_UINT32 ac );
560 void II( Q_UINT32& a, Q_UINT32 b, Q_UINT32 c, Q_UINT32 d, Q_UINT32 x,
561 Q_UINT32 s, Q_UINT32 ac );
562
563private:
564 Q_UINT32 m_state[4];
565 Q_UINT32 m_count[2];
566 Q_UINT8 m_buffer[64];
567 Digest m_digest;
568 bool m_finalized;
569
570 KMD5Private* d;
571};
572#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 @@
1/* This file is part of the KDE libraries
2 Copyright (c) 1999 Waldo Bastian <bastian@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 Boston, MA 02111-1307, USA.
17*/
18#ifndef KSharedPTR_H
19#define KSharedPTR_H
20
21/**
22 * Reference counting for shared objects. If you derive your object
23 * from this class, then you may use it in conjunction with
24 * @ref KSharedPtr to control the lifetime of your object.
25 *
26 * Specifically, all classes that derive from KShared have an internal
27 * counter keeping track of how many other objects have a reference to
28 * their object. If used with @ref KSharedPtr, then your object will
29 * not be deleted until all references to the object have been
30 * released.
31 *
32 * You should probably not ever use any of the methods in this class
33 * directly -- let the @ref KSharedPtr take care of that. Just derive
34 * your class from KShared and forget about it.
35 *
36 * @author Waldo Bastian <bastian@kde.org>
37 * @version $Id$
38 */
39class KShared {
40public:
41 /**
42 * Standard constructor. This will initialize the reference count
43 * on this object to 0.
44 */
45 KShared() : count(0) { }
46
47 /**
48 * Copy constructor. This will @em not actually copy the objects
49 * but it will initialize the reference count on this object to 0.
50 */
51 KShared( const KShared & ) : count(0) { }
52
53 /**
54 * Overloaded assignment operator.
55 */
56 KShared &operator=(const KShared & ) { return *this; }
57
58 /**
59 * Increases the reference count by one.
60 */
61 void _KShared_ref() const { count++; }
62
63 /**
64 * Releases a reference (decreases the reference count by one). If
65 * the count goes to 0, this object will delete itself.
66 */
67 void _KShared_unref() const { if (!--count) delete this; }
68
69 /**
70 * Return the current number of references held.
71 *
72 * @return Number of references
73 */
74 int _KShared_count() const { return count; }
75
76protected:
77 virtual ~KShared() { }
78private:
79 mutable int count;
80};
81
82/**
83 * Can be used to control the lifetime of an object that has derived
84 * @ref KShared. As long a someone holds a KSharedPtr on some @ref KShared
85 * object it won't become deleted but is deleted once its reference
86 * count is 0. This struct emulates C++ pointers perfectly. So just
87 * use it like a simple C++ pointer.
88 *
89 * KShared and KSharedPtr are preferred over QShared / QSharedPtr
90 * since they are more safe.
91 *
92 * @author Waldo Bastian <bastian@kde.org>
93 * @version $Id$
94 */
95template< class T >
96struct KSharedPtr
97{
98public:
99/**
100 * Creates a null pointer.
101 */
102 KSharedPtr()
103 : ptr(0) { }
104 /**
105 * Creates a new pointer.
106 * @param the pointer
107 */
108 KSharedPtr( T* t )
109 : ptr(t) { if ( ptr ) ptr->_KShared_ref(); }
110
111 /**
112 * Copies a pointer.
113 * @param the pointer to copy
114 */
115 KSharedPtr( const KSharedPtr& p )
116 : ptr(p.ptr) { if ( ptr ) ptr->_KShared_ref(); }
117
118 /**
119 * Unreferences the object that this pointer points to. If it was
120 * the last reference, the object will be deleted.
121 */
122 ~KSharedPtr() { if ( ptr ) ptr->_KShared_unref(); }
123
124 KSharedPtr<T>& operator= ( const KSharedPtr<T>& p ) {
125 if ( ptr == p.ptr ) return *this;
126 if ( ptr ) ptr->_KShared_unref();
127 ptr = p.ptr;
128 if ( ptr ) ptr->_KShared_ref();
129 return *this;
130 }
131 KSharedPtr<T>& operator= ( T* p ) {
132 if ( ptr == p ) return *this;
133 if ( ptr ) ptr->_KShared_unref();
134 ptr = p;
135 if ( ptr ) ptr->_KShared_ref();
136 return *this;
137 }
138 bool operator== ( const KSharedPtr<T>& p ) const { return ( ptr == p.ptr ); }
139 bool operator!= ( const KSharedPtr<T>& p ) const { return ( ptr != p.ptr ); }
140 bool operator== ( const T* p ) const { return ( ptr == p ); }
141 bool operator!= ( const T* p ) const { return ( ptr != p ); }
142 bool operator!() const { return ( ptr == 0 ); }
143 operator T*() const { return ptr; }
144
145 /**
146 * Returns the pointer.
147 * @return the pointer
148 */
149 T* data() { return ptr; }
150
151 /**
152 * Returns the pointer.
153 * @return the pointer
154 */
155 const T* data() const { return ptr; }
156
157 const T& operator*() const { return *ptr; }
158 T& operator*() { return *ptr; }
159 const T* operator->() const { return ptr; }
160 T* operator->() { return ptr; }
161
162 /**
163 * Returns the number of references.
164 * @return the number of references
165 */
166 int count() const { return ptr->_KShared_count(); } // for debugging purposes
167private:
168 T* ptr;
169};
170
171#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 @@
1/*
2 This file is part of the KDE libraries
3
4 Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20*/
21
22#include <kshell.h>
23
24#include <qfile.h>
25#include <qdir.h>
26
27#include <stdlib.h>
28#ifndef _WIN32_
29#include <pwd.h>
30#endif
31//US #include <sys/types.h>
32
33/*US
34static int fromHex( QChar c )
35{
36 if (c >= '0' && c <= '9')
37 return c - '0';
38 else if (c >= 'A' && c <= 'F')
39 return c - 'A' + 10;
40 else if (c >= 'a' && c <= 'f')
41 return c - 'a' + 10;
42 return -1;
43}
44
45inline static bool isQuoteMeta( uint c )
46{
47#if 0 // it's not worth it, especially after seeing gcc's asm output ...
48 static const uchar iqm[] = {
49 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00
51 }; // \'"$
52
53 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
54#else
55 return c == '\\' || c == '\'' || c == '"' || c == '$';
56#endif
57}
58
59inline static bool isMeta( uint c )
60{
61 static const uchar iqm[] = {
62 0x00, 0x00, 0x00, 0x00, 0xdc, 0x07, 0x00, 0xd8,
63 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
64 }; // \'"$`<>|;&(){}*?#
65
66 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
67}
68
69QStringList KShell::splitArgs( const QString &args, int flags, int *err )
70{
71 QStringList ret;
72 bool firstword = flags & AbortOnMeta;
73
74 for (uint pos = 0; ; ) {
75 QChar c;
76 do {
77 if (pos >= args.length())
78 goto okret;
79 c = args.unicode()[pos++];
80 } while (c.isSpace());
81 QString cret;
82 if ((flags & TildeExpand) && c == '~') {
83 uint opos = pos;
84 for (; ; pos++) {
85 if (pos >= args.length())
86 break;
87 c = args.unicode()[pos];
88 if (c == '/' || c.isSpace())
89 break;
90 if (isQuoteMeta( c )) {
91 pos = opos;
92 c = '~';
93 goto notilde;
94 }
95 if ((flags & AbortOnMeta) && isMeta( c ))
96 goto metaerr;
97 }
98 QString ccret = homeDir( QConstString( args.unicode() + opos, pos - opos ).string() );
99 if (ccret.isEmpty()) {
100 pos = opos;
101 c = '~';
102 goto notilde;
103 }
104 if (pos >= args.length()) {
105 ret += ccret;
106 goto okret;
107 }
108 pos++;
109 if (c.isSpace()) {
110 ret += ccret;
111 firstword = false;
112 continue;
113 }
114 cret = ccret;
115 }
116 // before the notilde label, as a tilde does not match anyway
117 if (firstword) {
118 if (c == '_' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
119 uint pos2 = pos;
120 QChar cc;
121 do
122 cc = args[pos2++];
123 while (cc == '_' || (cc >= 'A' && cc <= 'Z') ||
124 (cc >= 'a' && cc <= 'z') || (cc >= '0' && cc <= '9'));
125 if (cc == '=')
126 goto metaerr;
127 }
128 }
129 notilde:
130 do {
131 if (c == '\'') {
132 uint spos = pos;
133 do {
134 if (pos >= args.length())
135 goto quoteerr;
136 c = args.unicode()[pos++];
137 } while (c != '\'');
138 cret += QConstString( args.unicode() + spos, pos - spos - 1 ).string();
139 } else if (c == '"') {
140 for (;;) {
141 if (pos >= args.length())
142 goto quoteerr;
143 c = args.unicode()[pos++];
144 if (c == '"')
145 break;
146 if (c == '\\') {
147 if (pos >= args.length())
148 goto quoteerr;
149 c = args.unicode()[pos++];
150 if (c != '"' && c != '\\' &&
151 !((flags & AbortOnMeta) && (c == '$' || c == '`')))
152 cret += '\\';
153 } else if ((flags & AbortOnMeta) && (c == '$' || c == '`'))
154 goto metaerr;
155 cret += c;
156 }
157 } else if (c == '$' && args[pos] == '\'') {
158 pos++;
159 for (;;) {
160 if (pos >= args.length())
161 goto quoteerr;
162 c = args.unicode()[pos++];
163 if (c == '\'')
164 break;
165 if (c == '\\') {
166 if (pos >= args.length())
167 goto quoteerr;
168 c = args.unicode()[pos++];
169 switch (c) {
170 case 'a': cret += '\a'; break;
171 case 'b': cret += '\b'; break;
172 case 'e': cret += '\033'; break;
173 case 'f': cret += '\f'; break;
174 case 'n': cret += '\n'; break;
175 case 'r': cret += '\r'; break;
176 case 't': cret += '\t'; break;
177 case '\\': cret += '\\'; break;
178 case '\'': cret += '\''; break;
179 case 'c': cret += args[pos++] & 31; break;
180 case 'x':
181 {
182 int hv = fromHex( args[pos] );
183 if (hv < 0) {
184 cret += "\\x";
185 } else {
186 int hhv = fromHex( args[++pos] );
187 if (hhv > 0) {
188 hv = hv * 16 + hhv;
189 pos++;
190 }
191 cret += QChar( hv );
192 }
193 break;
194 }
195 default:
196 if (c >= '0' && c <= '7') {
197 int hv = c - '0';
198 for (int i = 0; i < 2; i++) {
199 c = args[pos];
200 if (c < '0' || c > '7')
201 break;
202 hv = hv * 8 + (c - '0');
203 pos++;
204 }
205 cret += QChar( hv );
206 } else {
207 cret += '\\';
208 cret += c;
209 }
210 break;
211 }
212 } else
213 cret += c;
214 }
215 } else {
216 if (c == '\\') {
217 if (pos >= args.length())
218 goto quoteerr;
219 c = args.unicode()[pos++];
220 if (!c.isSpace() &&
221 !((flags & AbortOnMeta) ? isMeta( c ) : isQuoteMeta( c )))
222 cret += '\\';
223 } else if ((flags & AbortOnMeta) && isMeta( c ))
224 goto metaerr;
225 cret += c;
226 }
227 if (pos >= args.length())
228 break;
229 c = args.unicode()[pos++];
230 } while (!c.isSpace());
231 ret += cret;
232 firstword = false;
233 }
234
235 okret:
236 if (err)
237 *err = NoError;
238 return ret;
239
240 quoteerr:
241 if (err)
242 *err = BadQuoting;
243 return QStringList();
244
245 metaerr:
246 if (err)
247 *err = FoundMeta;
248 return QStringList();
249}
250
251inline static bool isSpecial( uint c )
252{
253 static const uchar iqm[] = {
254 0xff, 0xff, 0xff, 0xff, 0xdd, 0x07, 0x00, 0xd8,
255 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x38
256 }; // 0-32 \'"$`<>|;&(){}*?#
257
258 return (c < sizeof(iqm) * 8) && (iqm[c / 8] & (1 << (c & 7)));
259}
260
261QString KShell::joinArgs( const QStringList &args )
262{
263 QChar q( '\'' );
264 QString ret;
265 for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
266 if (!ret.isEmpty())
267 ret += ' ';
268 if (!(*it).length())
269 ret.append( q ).append( q );
270 else {
271 for (uint i = 0; i < (*it).length(); i++)
272 if (isSpecial((*it).unicode()[i])) {
273 QString tmp(*it);
274 tmp.replace( q, "'\\''" );
275 ret += q;
276 tmp += q;
277 ret += tmp;
278 goto ex;
279 }
280 ret += *it;
281 ex: ;
282 }
283 }
284 return ret;
285}
286
287QString KShell::joinArgs( const char * const *args, int nargs )
288{
289 if (!args)
290 return QString::null; // well, QString::empty, in fact. qt sucks ;)
291 QChar q( '\'' );
292 QString ret;
293 for (const char * const *argp = args; nargs && *argp; argp++, nargs--) {
294 if (!ret.isEmpty())
295 ret += ' ';
296 if (!**argp)
297 ret.append( q ).append( q );
298 else {
299 QString tmp( QFile::decodeName( *argp ) );
300 for (uint i = 0; i < tmp.length(); i++)
301 if (isSpecial(tmp.unicode()[i])) {
302 tmp.replace( q, "'\\''" );
303 ret += q;
304 tmp += q;
305 ret += tmp;
306 goto ex;
307 }
308 ret += tmp;
309 ex: ;
310 }
311 }
312 return ret;
313}
314
315QString KShell::joinArgsDQ( const QStringList &args )
316{
317 QChar q( '\'' ), sp( ' ' ), bs( '\\' );
318 QString ret;
319 for (QStringList::ConstIterator it = args.begin(); it != args.end(); ++it) {
320 if (!ret.isEmpty())
321 ret += sp;
322 if (!(*it).length())
323 ret.append( q ).append( q );
324 else {
325 for (uint i = 0; i < (*it).length(); i++)
326 if (isSpecial((*it).unicode()[i])) {
327 ret.append( '$' ).append( q );
328 for (uint pos = 0; pos < (*it).length(); pos++) {
329 int c = (*it).unicode()[pos];
330 if (c < 32) {
331 ret += bs;
332 switch (c) {
333 case '\a': ret += 'a'; break;
334 case '\b': ret += 'b'; break;
335 case '\033': ret += 'e'; break;
336 case '\f': ret += 'f'; break;
337 case '\n': ret += 'n'; break;
338 case '\r': ret += 'r'; break;
339 case '\t': ret += 't'; break;
340 case '\034': ret += 'c'; ret += '|'; break;
341 default: ret += 'c'; ret += c + '@'; break;
342 }
343 } else {
344 if (c == '\'' || c == '\\')
345 ret += bs;
346 ret += c;
347 }
348 }
349 ret.append( q );
350 goto ex;
351 }
352 ret += *it;
353 ex: ;
354 }
355 }
356 return ret;
357}
358*/
359
360QString KShell::tildeExpand( const QString &fname )
361{
362 if (fname[0] == '~') {
363 int pos = fname.find( '/' );
364 if (pos < 0)
365 return homeDir( QConstString( (QChar*)(fname.unicode() + 1), fname.length() - 1 ).string() );
366 QString ret = homeDir( QConstString( (QChar*)(fname.unicode() + 1), pos - 1 ).string() );
367 if (!ret.isNull())
368 ret += QConstString( (QChar*)(fname.unicode() + pos), fname.length() - pos ).string();
369 return ret;
370 }
371 return fname;
372}
373
374QString KShell::homeDir( const QString &user )
375{
376#ifdef _WIN32_
377 return QDir::homeDirPath();
378#else
379 if (user.isEmpty())
380 return QFile::decodeName( getenv( "HOME" ) );
381 struct passwd *pw = getpwnam( QFile::encodeName( user ).data() );
382 if (!pw)
383 return QString::null;
384 return QFile::decodeName( pw->pw_dir );
385#endif
386}
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 @@
1/*
2 This file is part of the KDE libraries
3
4 Copyright (c) 2003 Oswald Buddenhagen <ossi@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20*/
21#ifndef _KSHELL_H
22#define _KSHELL_H
23
24#include <qstring.h>
25#include <qstringlist.h>
26
27/**
28 * Provides some basic POSIX shell and bash functionality.
29 * @see KStringHandler
30 */
31namespace KShell {
32
33 /**
34 * Flags for @ref splitArgs().
35 */
36 enum Options {
37 NoOptions = 0,
38
39 /**
40 * Perform tilde expansion.
41 */
42 TildeExpand = 1,
43
44 /**
45 * Bail out if a non-quoting and not quoted shell meta character is encoutered.
46 * Meta characters are the command separators @p semicolon and @p ampersand,
47 * the redirection symbols @p less-than, @p greater-than and the @p pipe @p symbol,
48 * the grouping symbols opening and closing @p parens and @p braces, the command
49 * substitution symbol @p backquote, the generic substitution symbol @p dollar
50 * (if not followed by an apostrophe), the wildcards @p asterisk and
51 * @p question @p mark, and the comment symbol @p hash @p mark. Additionally,
52 * a variable assignment in the first word is recognized.
53 */
54 AbortOnMeta = 2
55 };
56
57 /**
58 * Status codes from @ref splitArgs()
59 */
60 enum Errors {
61 /**
62 * Success.
63 */
64 NoError = 0,
65
66 /**
67 * Indicates a parsing error, like an unterminated quoted string.
68 */
69 BadQuoting,
70
71 /**
72 * The AbortOnMeta flag was set and a shell meta character
73 * was encoutered.
74 */
75 FoundMeta
76 };
77
78 /**
79 * Splits @p cmd according to POSIX shell word splitting and quoting rules.
80 * Can optionally perform tilde expansion and/or abort if it finds shell
81 * meta characters it cannot process.
82 *
83 * @param cmd the command to split
84 * @param flags operation flags, see @ref Options
85 * @param err if not NULL, a status code will be stored at the pointer
86 * target, see @ref Errors
87 * @return a list of unquoted words or an empty list if an error occured
88 */
89 QStringList splitArgs( const QString &cmd, int flags = 0, int *err = 0 );
90
91 /**
92 * Quotes and joins @p args together according to POSIX shell rules.
93 *
94 * @param args a list of strings to quote and join
95 * @return a command suitable for shell execution
96 */
97 QString joinArgs( const QStringList &args );
98
99 /**
100 * Same as above, but $'' is used instead of '' for the quoting.
101 * The output is suitable for @ref splitArgs(), bash, zsh and possibly
102 * other bourne-compatible shells, but not for plain sh. The advantage
103 * is, that control characters (ASCII less than 32) are escaped into
104 * human-readable strings.
105 *
106 * @param args a list of strings to quote and join
107 * @return a command suitable for shell execution
108 */
109 QString joinArgsDQ( const QStringList &args );
110
111 /**
112 * Quotes and joins @p argv together according to POSIX shell rules.
113 *
114 * @param argv an array of c strings to quote and join.
115 * The strings are expected to be in local-8-bit encoding.
116 * @param argc maximal number of strings in @p argv. if not supplied,
117 * @p argv must be null-terminated.
118 * @return a command suitable for shell execution
119 */
120 QString joinArgs( const char * const *argv, int argc = -1 );
121
122 /**
123 * Performs tilde expansion on @p path. Interprets "~/path" and
124 * "~user/path".
125 *
126 * @param path the path to tilde-expand
127 * @return the expanded path
128 */
129 QString tildeExpand( const QString &path );
130
131 /**
132 * Obtain a @p user's home directory.
133 *
134 * @param user The name of the user whose home dir should be obtained.
135 * An empty string denotes the current user.
136 * @return The user's home directory.
137 */
138 QString homeDir( const QString &user );
139
140}
141
142
143#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 2001,2002 Ellis Whitehead <ellis@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20#ifndef __KSHORTCUT_H
21#define __KSHORTCUT_H
22/*US
23#include <qkeysequence.h>
24#include <qstring.h>
25
26class QKeyEvent;
27class KKeyNative;
28*/
29/**
30* A KKey object represents a single key with possible modifiers
31* (Shift, Ctrl, Alt, Win). It can represent both keys which are
32* understood by Qt as well as those which are additionally supported
33* by the underlying system (e.g. X11).
34* @see KKeyNative
35* @see KKeySequence
36* @see KShortcut
37*/
38/*US
39class KKey
40{
41 public:
42*/
43 /**
44 * The number of flags.
45 * @see ModFlag
46 */
47/*US
48 enum { MOD_FLAG_COUNT = 4 };
49 enum { QtWIN = (Qt::ALT << 1) };
50*/
51 /**
52 * Flags to represent the modifiers. You can combine modifiers
53 * by ORing them.
54 */
55/*US
56 enum ModFlag {
57 SHIFT = 0x01,
58 CTRL = 0x02,
59 ALT = 0x04,
60 WIN = 0x08
61 };
62*/
63 /**
64 * Creates a new null KKey.
65 * @see clear()
66 * @see isNull()
67 * @see null()
68 */
69 //USKKey();
70
71 /**
72 * Creates a new key for the given Qt key code.
73 * @param keyQt the qt keycode
74 * @see Qt::Key
75 */
76 //USKKey( int keyQt );
77
78 /**
79 * Creates a new key from the first key code of the given key sequence.
80 * @param keySeq the key sequence that contains the key
81 */
82 //USKKey( const QKeySequence& keySeq );
83
84 /**
85 * Extracts the key from the given key event.
86 * @param keyEvent the key event to get the key from
87 */
88 //USKKey( const QKeyEvent* keyEvent );
89
90 /**
91 * Copy constructor.
92 */
93 //USKKey( const KKey& key );
94
95 /**
96 * Creates a new key from the given description. The form of the description
97 * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or
98 * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and
99 * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive.
100 * @param key the description of the key
101 * @see KKeyServer::Sym::init()
102 */
103 //USKKey( const QString& key );
104 /**
105 * @internal
106 */
107 //USKKey( uint key, uint mod );
108 //US~KKey();
109
110 // Initialization methods
111 /**
112 * Clears the key. The key is null after calling this function.
113 * @see isNull()
114 */
115 //USvoid clear();
116
117 /**
118 * Initializes the key with the given Qt key code.
119 * @param keyQt the qt keycode
120 * @return true if successful, false otherwise
121 * @see Qt::Key
122 */
123 //USbool init( int keyQt );
124
125 /**
126 * Initializes the key with the first key code of the given key sequence.
127 * @param keySeq the key sequence that contains the key
128 * @return true if successful, false otherwise
129 */
130 //USbool init( const QKeySequence& keySeq );
131
132 /**
133 * Initializes the key by extracting the code from the given key event.
134 * @param keyEvent the key event to get the key from
135 * @return true if successful, false otherwise
136 */
137 //USbool init( const QKeyEvent* keyEvent );
138
139 /**
140 * Copies the given key.
141 * @param key the key to copy
142 * @return true if successful, false otherwise
143 */
144 //USbool init( const KKey& key );
145
146 /**
147 * Initializes the key with the given description. The form of the description
148 * is "[modifier+[modifier+]]+key", for example "e", "CTRL+q" or
149 * "CTRL+ALT+DEL". Allowed modifiers are "SHIFT", "CTRL", "ALT", "WIN" and
150 * "META". "WIN" and "META" are equivalent. Modifiers are not case-sensitive.
151 * @param key the description of the key
152 * @return true if successful, false otherwise
153 * @see KKeyServer::Sym::init()
154 */
155 //USbool init( const QString& );
156
157 /**
158 * @internal
159 */
160 //USbool init( uint key, uint mod );
161
162 /**
163 * Copies the key.
164 */
165 //USKKey& operator =( const KKey& key )
166 //US { init( key ); return *this; }
167
168 // Query methods.
169 /**
170 * Returns true if the key is null (after @ref clear() or empty
171 * constructor).
172 * @return true if the key is null
173 * @see clear()
174 * @see null()
175 */
176 //USbool isNull() const;
177
178 /**
179 * @internal
180 */
181 //USbool isValidQt() const;
182
183 /**
184 * @internal
185 */
186 //USbool isValidNative() const;
187
188 /**
189 * @internal
190 */
191 //USuint sym() const;
192 /**
193 * @internal
194 */
195 //USuint modFlags() const;
196
197 // Comparison Methods
198 /**
199 * Compares this key with the given KKey object. Returns a negative
200 * number if the given KKey is larger, 0 if they are equal and
201 * a positive number this KKey is larger. The returned value
202 * is the difference between the symbol or, if the symbols
203 * are equal, the difference between the encoded modifiers.
204 * @param key the key to compare with this key
205 * @return a negative number if the given KKey is larger, 0 if
206 * they are equal and a positive number this KKey is larger
207 */
208 //USint compare( const KKey& key ) const;
209
210 /**
211 * Compares the symbol and modifiers of both keys.
212 * @see compare()
213 */
214 //USbool operator == ( const KKey& key ) const
215 //US { return compare( key ) == 0; }
216 /**
217 * Compares the symbol and modifiers of both keys.
218 * @see compare()
219 */
220 //USbool operator != ( const KKey& key ) const
221 //US { return compare( key ) != 0; }
222 /**
223 * Compares the symbol and modifiers of both keys.
224 * @see compare()
225 */
226 //USbool operator < ( const KKey& key ) const
227 //US { return compare( key ) < 0; }
228
229 // Conversion methods.
230 /**
231 * Returns the qt key code.
232 * @return the qt key code or 0 if there is no key set.
233 * @see Qt::Key
234 */
235 //USint keyCodeQt() const;
236
237 /**
238 * Returns a human-readable representation of the key in the form
239 * "modifier+key".
240 * @return the string representation of the key
241 */
242 //USQString toString() const;
243
244 /**
245 * @internal
246 */
247//US QString toStringInternal() const;
248
249 // Operation methods
250 /**
251 * @internal
252 */
253 //USvoid simplify();
254
255 /**
256 * Returns a null key.
257 * @return the null key
258 * @see isNull()
259 * @see clear()
260 */
261 //USstatic KKey& null();
262
263 /**
264 * Returns a user-readable representation of the given modifiers.
265 * @param f the modifiers to convert
266 * @return the string representation of the modifiers
267 */
268 //USstatic QString modFlagLabel( ModFlag f );
269
270//US private:
271 /*
272 * Under X11, m_key will hold an X11 key symbol.
273 * For Qt/Embedded, it will hold the Qt key code.
274 */
275 /**
276 * Returns the native key symbol value key. Under X11, this is the X
277 * keycode. Under Qt/Embedded, this is the Qt keycode.
278 * @see /usr/include/X11/keysymdef.h
279 * @see qnamespace.h
280 */
281 //USuint m_sym;
282 /**
283 * m_mod holds the
284 */
285 //USuint m_mod;
286
287//US private:
288 //USfriend class KKeyNative;
289//US};
290
291/**
292* A KKeySequence object holds a sequence of up to 4 keys.
293* Ex: Ctrl+X,I
294* @see KKey
295* @see KShortcut
296*/
297
298//USclass KKeySequence
299//US{
300//US public:
301 /// Defines the maximum length of the key sequence
302//US enum { MAX_KEYS = 4 };
303
304 /**
305 * Create a new null key sequence.
306 * @see isNull()
307 * @see null()
308 * @see clear()
309 */
310 //USKKeySequence();
311
312 /**
313 * Copies the given qt key sequence.
314 * @param keySeq the qt key sequence to copy
315 */
316 //USKKeySequence( const QKeySequence& keySeq );
317
318 /**
319 * Create a new key sequence that only contains the given key.
320 * @param key the key to add
321 */
322 //USKKeySequence( const KKey& key );
323
324 /**
325 * Create a new key sequence that only contains the given key.
326 * @param key the key to add
327 */
328 //USKKeySequence( const KKeyNative& key );
329
330 /**
331 * Copies the given key sequence.
332 * @param keySeq the key sequence to copy
333 */
334 //USKKeySequence( const KKeySequence& keySeq );
335
336 /**
337 * Creates a new key sequence that contains the given key sequence.
338 * The description consists of comma-separated keys as
339 * required by @ref KKey::KKey(const QString&).
340 * @param keySeq the description of the key
341 * @see KKeyServer::Sym::init()
342 * @see KKey::KKey(const QString&)
343 */
344 //USKKeySequence( const QString& keySeq );
345
346 //US~KKeySequence();
347
348 /**
349 * Clears the key sequence. The key sequence is null after calling this
350 * function.
351 * @see isNull()
352 */
353 //USvoid clear();
354
355 /**
356 * Copies the given qt key sequence over this key sequence.
357 * @param keySeq the qt key sequence to copy
358 * @return true if successful, false otherwise
359 */
360 //USbool init( const QKeySequence& keySeq );
361
362 /**
363 * Initializes the key sequence to only contain the given key.
364 * @param key the key to set
365 * @return true if successful, false otherwise
366 */
367 //USbool init( const KKey& key );
368
369 /**
370 * Initializes the key sequence to only contain the given key.
371 * @param key the key to set
372 * @return true if successful, false otherwise
373 */
374 //USbool init( const KKeyNative& key );
375
376 /**
377 * Copies the given key sequence over this key sequence.
378 * @param keySeq the key sequence to copy
379 * @return true if successful, false otherwise
380 */
381 //USbool init( const KKeySequence& keySeq );
382
383 /**
384 * Initializes this key sequence to contain the given key sequence.
385 * The description consists of comma-separated keys as
386 * required by @ref KKey::KKey(const QString&).
387 * @param key the description of the key
388 * @return true if successful, false otherwise
389 * @see KKeyServer::Sym::init()
390 * @see KKey::KKey(const QString&)
391 */
392 //USbool init( const QString& key );
393
394 /**
395 * Copy the given key sequence into this sequence.
396 */
397 //USKKeySequence& operator =( const KKeySequence& seq )
398 //US { init( seq ); return *this; }
399
400 /**
401 * Returns the number of key strokes of this sequence.
402 * @return the number of key strokes
403 * @see MAX_KEYS
404 */
405 //USuint count() const;
406
407 /**
408 * Return the @p i'th key of this sequence, or a null key if there
409 * are less then i keys.
410 * @param i the key to retrieve
411 * @return the @p i'th key, or @ref KKey::null() if there are less
412 * than i keys
413 * @see MAX_KEYS
414 */
415 //USconst KKey& key( uint i ) const;
416
417 /**
418 * @internal
419 */
420 //USbool isTriggerOnRelease() const;
421
422 /**
423 * Sets the @p i'th key of the sequence. You can not introduce gaps
424 * in a sequence, so you must use an @p i <= @ref count(). Also note that
425 * the maximum length of a key sequence is @ref MAX_KEYS.
426 * @param i the position of the new key (<= @ref count(), <= @ref MAX_KEYS)
427 * @param key the key to set
428 * @return true if successful, false otherwise
429 */
430 //USbool setKey( uint i, const KKey& key );
431
432 /**
433 * @internal
434 */
435 //USvoid setTriggerOnRelease( bool );
436
437 /**
438 * Returns true if the key sequence is null (after @ref clear() or empty
439 * constructor).
440 * @return true if the key sequence is null
441 * @see clear()
442 * @see null()
443 */
444//US bool isNull() const;
445
446 /**
447 * Returns true if this key sequence begins with the given sequence.
448 * @param keySeq the key sequence to search
449 * @return true if this key sequence begins with the given sequence
450 */
451 //USbool startsWith( const KKeySequence& keySeq ) const;
452
453 /**
454 * Compares this object with the given key sequence. Returns a negative
455 * number if the given KKeySequence is larger, 0 if they are equal and
456 * a positive number this KKeySequence is larger. Key sequences are
457 * compared by comparing the individual keys, starting from the beginning
458 * until an unequal key has been found. If a sequence contains more
459 * keys, it is considered larger.
460 * @param keySeq the key sequence to compare to
461 * @return a negative number if the given KKeySequence is larger, 0 if
462 * they are equal and a positive number this KKeySequence is larger
463 * @see KKey::sequence
464 */
465 //USint compare( const KKeySequence& keySeq ) const;
466
467 /**
468 * Compares the keys of both sequences.
469 * @see compare()
470 */
471 //USbool operator == ( const KKeySequence& seq ) const
472 //US { return compare( seq ) == 0; }
473
474 /**
475 * Compares the keys of both sequences.
476 * @see compare()
477 */
478 //USbool operator != ( const KKeySequence& seq ) const
479 //US { return compare( seq ) != 0; }
480
481 /**
482 * Compares the keys of both sequences.
483 * @see compare()
484 */
485 //USbool operator < ( const KKeySequence& seq ) const
486 //US { return compare( seq ) < 0; }
487 // TODO: consider adding Qt::SequenceMatch matches(...) methods for QKeySequence equivalence
488
489 /**
490 * Converts this key sequence to a QKeySequence.
491 * @return the QKeySequence
492 */
493 //USQKeySequence qt() const;
494
495 /**
496 * Returns the qt key code of the first key.
497 * @return the qt key code of the first key
498 * @see Qt::Key
499 * @see KKey::keyCodeQt()
500 */
501 //USint keyCodeQt() const;
502
503 /**
504 * Returns the key sequence as a number of key presses as
505 * returned by @ref KKey::toString(), seperated by commas.
506 * @return the string represenation of this key sequence
507 * @see KKey::toString()
508 */
509 //USQString toString() const;
510
511 /**
512 * @internal
513 */
514//US QString toStringInternal() const;
515
516 /**
517 * Returns a null key sequence.
518 * @return the null key sequence
519 * @see isNull()
520 * @see clear()
521 */
522 //USstatic KKeySequence& null();
523
524//US protected:
525 //USuchar m_nKeys;
526 //USuchar m_bTriggerOnRelease;
527 // BCI: m_rgvar should be renamed to m_rgkey for KDE 4.0
528 //USKKey m_rgvar[MAX_KEYS];
529
530//US private:
531 //USclass KKeySequencePrivate* d;
532 //USfriend class KKeyNative;
533//US};
534
535/**
536* The KShortcut class is used to represent a keyboard shortcut to an action.
537* A shortcut is normally a single key with modifiers, such as Ctrl+V.
538* A KShortcut object may also contain an alternate key which will also
539* activate the action it's associated to, as long as no other actions have
540* defined that key as their primary key. Ex: Ctrl+V;Shift+Insert.
541*/
542
543class KShortcut
544{
545 public:
546 /**
547 * The maximum number of key sequences that can be contained in
548 * a KShortcut.
549 */
550 enum { MAX_SEQUENCES = 2 };
551
552 /**
553 * Creates a new null shortcut.
554 * @see null()
555 * @see isNull()
556 * @see clear()
557 */
558 KShortcut() {}
559
560 /**
561 * Creates a new shortcut with the given Qt key code
562 * as the only key sequence.
563 * @param keyQt the qt keycode
564 * @see Qt::Key
565 */
566 KShortcut( int keyQt ) {}
567
568 /**
569 * Creates a new shortcut that contains only the given qt key
570 * sequence.
571 * @param keySeq the qt key sequence to add
572 */
573 //USKShortcut( const QKeySequence& keySeq ) {}
574
575 /**
576 * Creates a new shortcut that contains only the given key
577 * in its only sequence.
578 * @param key the key to add
579 */
580 //USKShortcut( const KKey& key );
581
582 /**
583 * Creates a new shortcut that contains only the given key
584 * sequence.
585 * @param keySeq the key sequence to add
586 */
587 //USKShortcut( const KKeySequence& keySeq );
588
589 /**
590 * Copies the given shortcut.
591 * @param shortcut the shortcut to add
592 */
593 //USKShortcut( const KShortcut& shortcut );
594
595 /**
596 * Creates a new key sequence that contains the given key sequence.
597 * The description consists of semicolon-separated keys as
598 * used in @ref KKeySequence::KKeySequence(const QString&).
599 * @param shortcut the description of the key
600 * @see KKeySequence::KKeySequence(const QString&)
601 */
602 KShortcut( const char* shortcut ) {}
603
604 /**
605 * Creates a new key sequence that contains the given key sequence.
606 * The description consists of semicolon-separated keys as
607 * used in @ref KKeySequence::KKeySequence(const QString&).
608 * @param shortcut the description of the key
609 * @see KKeySequence::KKeySequence(const QString&)
610 */
611 KShortcut( const QString& shortcut ) {}
612 ~KShortcut() {}
613
614 /**
615 * Clears the shortcut. The shortcut is null after calling this
616 * function.
617 * @see isNull()
618 */
619 //USvoid clear();
620
621 /**
622 * Initializes the shortcut with the given Qt key code
623 * as the only key sequence.
624 * @param keyQt the qt keycode
625 * @see Qt::Key
626 */
627 //USbool init( int keyQt );
628
629 /**
630 * Initializes the shortcut with the given qt key sequence.
631 * @param keySeq the qt key sequence to add
632 */
633 //USbool init( const QKeySequence& keySeq );
634
635 /**
636 * Initializes the shortcut with the given key as its only sequence.
637 * @param key the key to add
638 */
639 //USbool init( const KKey& key );
640
641 /**
642 * Initializes the shortcut with the given qt key sequence.
643 * @param keySeq the qt key sequence to add
644 */
645 //USbool init( const KKeySequence& keySeq );
646
647 /**
648 * Copies the given shortcut.
649 * @param shortcut the shortcut to add
650 */
651 //USbool init( const KShortcut& shortcut );
652
653 /**
654 * Initializes the key sequence with the given key sequence.
655 * The description consists of semicolon-separated keys as
656 * used in @ref KKeySequence::KKeySequence(const QString&).
657 * @param shortcut the description of the key
658 * @see KKeySequence::KKeySequence(const QString&)
659 */
660 //USbool init( const QString& shortcut );
661
662 /**
663 * Copies the given shortcut over this shortcut.
664 */
665 //USKShortcut& operator =( const KShortcut& cut )
666 //US { init( cut ); return *this; }
667
668 /**
669 * Returns the number of sequences that are in this
670 * shortcut.
671 * @return the number of sequences
672 * @ref MAX_SEQUENCES
673 */
674 //USuint count() const;
675
676 /**
677 * Returns the @p i'th key sequence of this shortcut.
678 * @param i the number of the key sequence to retrieve
679 * @return the @p i'th sequence or @ref KKeySequence::null() if
680 * there are less than @p i key sequences
681 * @ref MAX_SEQUENCES
682 */
683 //USconst KKeySequence& seq( uint i ) const;
684
685 /**
686 * Returns the key code of the first key sequence, or
687 * null if there is no first key sequence.
688 * @return the key code of the first sequence's first key
689 * @see Qt::Key
690 * @see KKeySequence::keyCodeQt()
691 */
692 //USint keyCodeQt() const;
693
694 /**
695 * Returns true if the shortcut is null (after @ref clear() or empty
696 * constructor).
697 * @return true if the shortcut is null
698 * @see clear()
699 * @see null()
700 */
701 bool isNull() const { return true; }
702
703 /**
704 * Compares this object with the given shortcut. Returns a negative
705 * number if the given shortcut is larger, 0 if they are equal and
706 * a positive number this shortcut is larger. Shortcuts are
707 * compared by comparing the individual key sequences, starting from the
708 * beginning until an unequal key sequences has been found. If a shortcut
709 * contains more key sequences, it is considered larger.
710 * @param shortcut the shortcut to compare to
711 * @return a negative number if the given KShortcut is larger, 0 if
712 * they are equal and a positive number this KShortcut is larger
713 * @see KKey::compare()
714 * @see KKeyShortcut::compare()
715 */
716 //USint compare( const KShortcut& shortcut ) const;
717
718 /**
719 * Compares the sequences of both shortcuts.
720 * @see compare()
721 */
722 //USbool operator == ( const KShortcut& cut ) const
723 //US { return compare( cut ) == 0; }
724
725 /**
726 * Compares the sequences of both shortcuts.
727 * @see compare()
728 */
729 //USbool operator != ( const KShortcut& cut ) const
730 //US { return compare( cut ) != 0; }
731
732 /**
733 * Compares the sequences of both shortcuts.
734 * @see compare()
735 */
736 //USbool operator < ( const KShortcut& cut ) const
737 //US { return compare( cut ) < 0; }
738
739 /**
740 * Checks whether this shortcut contains a sequence that starts
741 * with the given key.
742 * @param key the key to check
743 * @return true if a key sequence starts with the key
744 */
745 //USbool contains( const KKey& key ) const;
746
747 /**
748 * Checks whether this shortcut contains a sequence that starts
749 * with the given key.
750 * @param key the key to check
751 * @return true if a key sequence starts with the key
752 */
753 //USbool contains( const KKeyNative& key ) const;
754
755 /**
756 * Checks whether this shortcut contains the given sequence.
757 * @param keySeq the key sequence to check
758 * @return true if the shortcut has the given key sequence
759 */
760 //USbool contains( const KKeySequence& keySeq ) const;
761
762 /**
763 * Sets the @p i'th key sequence of the shortcut. You can not introduce
764 * gaps in the list of sequences, so you must use an @i <= @ref count().
765 * Also note that the maximum number of key sequences is @ref MAX_SEQUENCES.
766 * @param i the position of the new key sequence(<= @ref count(),
767 * <= @ref MAX_SEQUENCES)
768 * @param keySeq the key sequence to set
769 * @return true if successful, false otherwise
770 */
771 //USbool setSeq( uint i, const KKeySequence& keySeq );
772
773 /**
774 * Appends the given key sequence.
775 * @param keySeq the key sequence to add
776 * @return true if successful, false otherwise
777 * @see setSeq()
778 * @see MAX_SEQUENCES
779 */
780 //USbool append( const KKeySequence& keySeq );
781
782 /**
783 * Appends the given key
784 * @param spec the key to add
785 * @return true if successful, false otherwise
786 * @see setSeq()
787 * @see MAX_SEQUENCES
788 * @since 3.2
789 */
790 //USbool append( const KKey& spec );
791
792 /**
793 * Appends the sequences from the given shortcut.
794 * @param cut the shortcut to append
795 * @return true if successful, false otherwise
796 * @see MAX_SEQUENCES
797 * @since 3.2
798 */
799 //USbool append( const KShortcut& cut );
800
801 /**
802 * Converts this shortcut to a key sequence. The first key sequence
803 * will be taken.
804 */
805 //USoperator QKeySequence () const;
806
807 /**
808 * Returns a description of the shortcut as semicolon-separated
809 * ket sequences, as returned by @ref KKeySequence::toString().
810 * @return the string represenation of this shortcut
811 * @see KKey::toString()
812 * @see KKeySequence::toString()
813 */
814 //USQString toString() const;
815
816 /**
817 * @internal
818 */
819 QString toStringInternal( const KShortcut* pcutDefault = 0 ) const
820 {
821 return "EMPTY IMPL.";
822 }
823
824 /**
825 * Returns a null shortcut.
826 * @return the null shortcut
827 * @see isNull()
828 * @see clear()
829 */
830 //USstatic KShortcut& null();
831
832//US protected:
833 //USuint m_nSeqs;
834 //USKKeySequence m_rgseq[MAX_SEQUENCES];
835
836//US private:
837 //USclass KShortcutPrivate* d;
838 //USfriend class KKeyNative;
839
840//US#ifndef KDE_NO_COMPAT
841//US public:
842 //USoperator int () const { return keyCodeQt(); }
843//US#endif
844};
845
846#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
3 Copyright (C) 1999 Stephan Kulow <coolo@kde.org>
4 Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License version 2 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/*
22 * Author: Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
23 * Version:$Id$
24 * Generated:Thu Mar 5 16:05:28 EST 1998
25 */
26
27//US #include "config.h"
28
29#include <stdlib.h>
30#include <assert.h>
31//US#include <errno.h>
32//US #ifdef HAVE_SYS_STAT_H
33//US #include <sys/stat.h>
34//US #endif
35//US#include <sys/types.h>
36//US#include <dirent.h>
37//US#include <pwd.h>
38
39#include <qregexp.h>
40#include <qasciidict.h>
41#include <qdict.h>
42#include <qdir.h>
43#include <qfileinfo.h>
44#include <qstring.h>
45#include <qstringlist.h>
46
47#include "kstandarddirs.h"
48#include "kconfig.h"
49#include "kdebug.h"
50//US #include "kinstance.h"
51#include "kshell.h"
52//US#include <sys/param.h>
53//US#include <unistd.h>
54
55//US
56QString KStandardDirs::mAppDir = QString::null;
57
58
59template class QDict<QStringList>;
60
61#if 0
62#include <qtextedit.h>
63void ddd( QString op )
64{
65 static QTextEdit * dot = 0;
66 if ( ! dot )
67 dot = new QTextEdit();
68
69 dot->show();
70
71 dot->append( op );
72
73}
74#endif
75class KStandardDirs::KStandardDirsPrivate
76{
77public:
78 KStandardDirsPrivate()
79 : restrictionsActive(false),
80 dataRestrictionActive(false)
81 { }
82
83 bool restrictionsActive;
84 bool dataRestrictionActive;
85 QAsciiDict<bool> restrictions;
86 QStringList xdgdata_prefixes;
87 QStringList xdgconf_prefixes;
88};
89
90static const char* const types[] = {"html", "icon", "apps", "sound",
91 "data", "locale", "services", "mime",
92 "servicetypes", "config", "exe",
93 "wallpaper", "lib", "pixmap", "templates",
94 "module", "qtplugins",
95 "xdgdata-apps", "xdgdata-dirs", "xdgconf-menu", 0 };
96
97static int tokenize( QStringList& token, const QString& str,
98 const QString& delim );
99
100KStandardDirs::KStandardDirs( ) : addedCustoms(false)
101{
102 d = new KStandardDirsPrivate;
103 dircache.setAutoDelete(true);
104 relatives.setAutoDelete(true);
105 absolutes.setAutoDelete(true);
106 savelocations.setAutoDelete(true);
107 addKDEDefaults();
108}
109
110KStandardDirs::~KStandardDirs()
111{
112 delete d;
113}
114
115bool KStandardDirs::isRestrictedResource(const char *type, const QString& relPath) const
116{
117 if (!d || !d->restrictionsActive)
118 return false;
119
120 if (d->restrictions[type])
121 return true;
122
123 if (strcmp(type, "data")==0)
124 {
125 applyDataRestrictions(relPath);
126 if (d->dataRestrictionActive)
127 {
128 d->dataRestrictionActive = false;
129 return true;
130 }
131 }
132 return false;
133}
134
135void KStandardDirs::applyDataRestrictions(const QString &relPath) const
136{
137 QString key;
138 int i = relPath.find('/');
139 if (i != -1)
140 key = "data_"+relPath.left(i);
141 else
142 key = "data_"+relPath;
143
144 if (d && d->restrictions[key.latin1()])
145 d->dataRestrictionActive = true;
146}
147
148
149QStringList KStandardDirs::allTypes() const
150{
151 QStringList list;
152 for (int i = 0; types[i] != 0; ++i)
153 list.append(QString::fromLatin1(types[i]));
154 return list;
155}
156
157void KStandardDirs::addPrefix( const QString& _dir )
158{
159 if (_dir.isNull())
160 return;
161
162 QString dir = _dir;
163 if (dir.at(dir.length() - 1) != '/')
164 dir += '/';
165
166 if (!prefixes.contains(dir)) {
167 prefixes.append(dir);
168 dircache.clear();
169 }
170}
171
172void KStandardDirs::addXdgConfigPrefix( const QString& _dir )
173{
174 if (_dir.isNull())
175 return;
176
177 QString dir = _dir;
178 if (dir.at(dir.length() - 1) != '/')
179 dir += '/';
180
181 if (!d->xdgconf_prefixes.contains(dir)) {
182 d->xdgconf_prefixes.append(dir);
183 dircache.clear();
184 }
185}
186
187void KStandardDirs::addXdgDataPrefix( const QString& _dir )
188{
189 if (_dir.isNull())
190 return;
191
192 QString dir = _dir;
193 if (dir.at(dir.length() - 1) != '/')
194 dir += '/';
195
196 if (!d->xdgdata_prefixes.contains(dir)) {
197 d->xdgdata_prefixes.append(dir);
198 dircache.clear();
199 }
200}
201
202
203QString KStandardDirs::kfsstnd_prefixes()
204{
205 return prefixes.join(":");
206}
207
208bool KStandardDirs::addResourceType( const char *type,
209 const QString& relativename )
210{
211 if (relativename.isNull())
212 return false;
213
214 QStringList *rels = relatives.find(type);
215 if (!rels) {
216 rels = new QStringList();
217 relatives.insert(type, rels);
218 }
219 QString copy = relativename;
220 if (copy.at(copy.length() - 1) != '/')
221 copy += '/';
222 if (!rels->contains(copy)) {
223 rels->prepend(copy);
224 dircache.remove(type); // clean the cache
225 return true;
226 }
227 return false;
228}
229
230bool KStandardDirs::addResourceDir( const char *type,
231 const QString& absdir)
232{
233 QStringList *paths = absolutes.find(type);
234 if (!paths) {
235 paths = new QStringList();
236 absolutes.insert(type, paths);
237 }
238 QString copy = absdir;
239 if (copy.at(copy.length() - 1) != '/')
240 copy += '/';
241
242 if (!paths->contains(copy)) {
243 paths->append(copy);
244 dircache.remove(type); // clean the cache
245 return true;
246 }
247 return false;
248}
249
250QString KStandardDirs::findResource( const char *type,
251 const QString& filename ) const
252{
253 if (filename.at(0) == '/')
254 return filename; // absolute dirs are absolute dirs, right? :-/
255
256#if 0
257kdDebug() << "Find resource: " << type << endl;
258for (QStringList::ConstIterator pit = prefixes.begin();
259 pit != prefixes.end();
260 pit++)
261{
262 kdDebug() << "Prefix: " << *pit << endl;
263}
264#endif
265
266 QString dir = findResourceDir(type, filename);
267 if (dir.isNull())
268 return dir;
269 else return dir + filename;
270}
271/*US
272static Q_UINT32 updateHash(const QString &file, Q_UINT32 hash)
273{
274 QCString cFile = QFile::encodeName(file);
275//US struct stat buff;
276//US if ((access(cFile, R_OK) == 0) &&
277//US (stat( cFile, &buff ) == 0) &&
278//US (S_ISREG( buff.st_mode )))
279 QFileInfo pathfnInfo(cFile);
280 if (( pathfnInfo.isReadable() == true ) &&
281 ( pathfnInfo.isFile()) )
282 {
283//US hash = hash + (Q_UINT32) buff.st_ctime;
284 hash = hash + (Q_UINT32) pathfnInfo.lastModified();
285 }
286 return hash;
287}
288*/
289/*US
290Q_UINT32 KStandardDirs::calcResourceHash( const char *type,
291 const QString& filename, bool deep) const
292{
293 Q_UINT32 hash = 0;
294
295 if (filename.at(0) == '/')
296 {
297 // absolute dirs are absolute dirs, right? :-/
298 return updateHash(filename, hash);
299 }
300 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
301 applyDataRestrictions(filename);
302 QStringList candidates = resourceDirs(type);
303 QString fullPath;
304
305 for (QStringList::ConstIterator it = candidates.begin();
306 it != candidates.end(); it++)
307 {
308 hash = updateHash(*it + filename, hash);
309 if (!deep && hash)
310 return hash;
311 }
312 return hash;
313}
314*/
315
316QStringList KStandardDirs::findDirs( const char *type,
317 const QString& reldir ) const
318{
319 QStringList list;
320
321 checkConfig();
322
323 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
324 applyDataRestrictions(reldir);
325 QStringList candidates = resourceDirs(type);
326 QDir testdir;
327
328 for (QStringList::ConstIterator it = candidates.begin();
329 it != candidates.end(); it++) {
330 testdir.setPath(*it + reldir);
331 if (testdir.exists())
332 list.append(testdir.absPath() + '/');
333 }
334
335 return list;
336}
337
338QString KStandardDirs::findResourceDir( const char *type,
339 const QString& filename) const
340{
341#ifndef NDEBUG
342 if (filename.isEmpty()) {
343 kdWarning() << "filename for type " << type << " in KStandardDirs::findResourceDir is not supposed to be empty!!" << endl;
344 return QString::null;
345 }
346#endif
347
348 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
349 applyDataRestrictions(filename);
350 QStringList candidates = resourceDirs(type);
351 QString fullPath;
352
353 for (QStringList::ConstIterator it = candidates.begin();
354 it != candidates.end(); it++)
355 if (exists(*it + filename))
356 return *it;
357
358#ifndef NDEBUG
359 if(false && type != "locale")
360 kdDebug() << "KStdDirs::findResDir(): can't find \"" << filename << "\" in type \"" << type << "\"." << endl;
361#endif
362
363 return QString::null;
364}
365
366bool KStandardDirs::exists(const QString &fullPath)
367{
368//US struct stat buff;
369 QFileInfo fullPathInfo(QFile::encodeName(fullPath));
370
371//US if (access(QFile::encodeName(fullPath), R_OK) == 0 && fullPathInfo.isReadable())
372 if (fullPathInfo.isReadable())
373 {
374 if (fullPath.at(fullPath.length() - 1) != '/') {
375 //US if (S_ISREG( buff.st_mode ))
376 if (fullPathInfo.isFile())
377 return true;
378 }
379 else {
380 //US if (S_ISDIR( buff.st_mode ))
381 if (fullPathInfo.isDir())
382 return true;
383 }
384 }
385 return false;
386}
387
388static void lookupDirectory(const QString& path, const QString &relPart,
389 const QRegExp &regexp,
390 QStringList& list,
391 QStringList& relList,
392 bool recursive, bool uniq)
393{
394 QString pattern = regexp.pattern();
395 if (recursive || pattern.contains('?') || pattern.contains('*'))
396 {
397 // We look for a set of files.
398//US DIR *dp = opendir( QFile::encodeName(path));
399 QDir dp(QFile::encodeName(path));
400 if (!dp.exists())
401 return;
402 static int iii = 0;
403 ++iii;
404 if ( iii == 5 )
405 abort();
406 assert(path.at(path.length() - 1) == '/');
407
408//US struct dirent *ep;
409//US struct stat buff;
410
411 QString _dot(".");
412 QString _dotdot("..");
413
414//US while( ( ep = readdir( dp ) ) != 0L )
415 QStringList direntries = dp.entryList();
416 QStringList::Iterator it = direntries.begin();
417
418 while ( it != list.end() ) // for each file...
419 {
420
421//US QString fn( QFile::decodeName(ep->d_name));
422 QString fn = (*it); // dp.entryList already decodes
423 it++;
424 if ( fn.isNull() )
425 break;
426
427 if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1).latin1() == '~' )
428 continue;
429
430/*US
431 if (!recursive && !regexp.exactMatch(fn))
432 continue; // No match
433*/
434//US this should do the same:
435 int pos = regexp.match(fn);
436 if (!recursive && !pos == 0)
437 continue; // No match
438
439 QString pathfn = path + fn;
440/*US
441 if ( stat( QFile::encodeName(pathfn), &buff ) != 0 ) {
442 kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
443 continue; // Couldn't stat (e.g. no read permissions)
444 }
445
446 if ( recursive )
447 {
448 if ( S_ISDIR( buff.st_mode )) {
449 lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq);
450 }
451*/
452//US replacement:
453 QFileInfo pathfnInfo(QFile::encodeName(pathfn));
454 if ( pathfnInfo.isReadable() == false )
455 {
456//US kdDebug() << "Error stat'ing " << pathfn << " : " << perror << endl;
457 continue; // Couldn't stat (e.g. no read permissions)
458 }
459
460 if ( recursive )
461 {
462 if ( pathfnInfo.isDir()) {
463 lookupDirectory(pathfn + '/', relPart + fn + '/', regexp, list, relList, recursive, uniq);
464 }
465
466
467/*US
468 if (!regexp.exactMatch(fn))
469 continue; // No match
470*/
471//US this should do the same:
472 pos = regexp.match(fn);
473 if (!pos == 0)
474 continue; // No match
475 }
476
477//US if ( S_ISREG( buff.st_mode))
478 if ( pathfnInfo.isFile())
479 {
480 if (!uniq || !relList.contains(relPart + fn))
481 {
482 list.append( pathfn );
483 relList.append( relPart + fn );
484 }
485 }
486 }
487//US closedir( dp );
488 }
489 else
490 {
491 // We look for a single file.
492 QString fn = pattern;
493 QString pathfn = path + fn;
494//US struct stat buff;
495 QFileInfo pathfnInfo(QFile::encodeName(pathfn));
496
497
498//US if ( stat( QFile::encodeName(pathfn), &buff ) != 0 )
499 if ( pathfnInfo.isReadable() == false )
500 return; // File not found
501
502//US if ( S_ISREG( buff.st_mode))
503 if ( pathfnInfo.isFile())
504 {
505 if (!uniq || !relList.contains(relPart + fn))
506 {
507 list.append( pathfn );
508 relList.append( relPart + fn );
509 }
510 }
511 }
512}
513
514static void lookupPrefix(const QString& prefix, const QString& relpath,
515 const QString& relPart,
516 const QRegExp &regexp,
517 QStringList& list,
518 QStringList& relList,
519 bool recursive, bool uniq)
520{
521 if (relpath.isNull()) {
522 lookupDirectory(prefix, relPart, regexp, list,
523 relList, recursive, uniq);
524 return;
525 }
526 QString path;
527 QString rest;
528
529 if (relpath.length())
530 {
531 int slash = relpath.find('/');
532 if (slash < 0)
533 rest = relpath.left(relpath.length() - 1);
534 else {
535 path = relpath.left(slash);
536 rest = relpath.mid(slash + 1);
537 }
538 }
539 assert(prefix.at(prefix.length() - 1) == '/');
540
541//US struct stat buff;
542
543 if (path.contains('*') || path.contains('?')) {
544 QRegExp pathExp(path, true, true);
545 //USDIR *dp = opendir( QFile::encodeName(prefix) );
546 QDir dp(QFile::encodeName(prefix));
547
548 //USif (!dp)
549 if (!dp.exists())
550 {
551 return;
552 }
553
554 //USstruct dirent *ep;
555
556 QString _dot(".");
557 QString _dotdot("..");
558
559 //USwhile( ( ep = readdir( dp ) ) != 0L )
560 QStringList direntries = dp.entryList();
561 QStringList::Iterator it = direntries.begin();
562
563 while ( it != list.end() ) // for each file...
564 {
565//US QString fn( QFile::decodeName(ep->d_name));
566 QString fn = (*it); // dp.entryList() already encodes the strings
567 it++;
568
569 if (fn == _dot || fn == _dotdot || fn.at(fn.length() - 1) == '~')
570 continue;
571
572#ifdef DESKTOP_VERSION
573
574 if (pathExp.search(fn) == -1)
575 continue; // No match
576
577#else
578//US this should do the same:
579 if (pathExp.find(fn, 0) == -1)
580 continue; // No match
581#endif
582 QString rfn = relPart+fn;
583 fn = prefix + fn;
584//US if ( stat( QFile::encodeName(fn), &buff ) != 0 )
585 QFileInfo fnInfo(QFile::encodeName(fn));
586 if ( fnInfo.isReadable() == false )
587 {
588//US kdDebug() << "Error statting " << fn << " : " << perror << endl;
589 continue; // Couldn't stat (e.g. no permissions)
590 }
591 //US if ( S_ISDIR( buff.st_mode ))
592 if ( fnInfo.isDir() )
593
594 lookupPrefix(fn + '/', rest, rfn + '/', regexp, list, relList, recursive, uniq);
595 }
596
597 //USclosedir( dp );
598 } else {
599 // Don't stat, if the dir doesn't exist we will find out
600 // when we try to open it.
601 lookupPrefix(prefix + path + '/', rest,
602 relPart + path + '/', regexp, list,
603 relList, recursive, uniq);
604 }
605}
606
607QStringList
608KStandardDirs::findAllResources( const char *type,
609 const QString& filter,
610 bool recursive,
611 bool uniq,
612 QStringList &relList) const
613{
614 QStringList list;
615 if (filter.at(0) == '/') // absolute paths we return
616 {
617 list.append( filter);
618 return list;
619 }
620
621 QString filterPath;
622 QString filterFile;
623
624 if (filter.length())
625 {
626 int slash = filter.findRev('/');
627 if (slash < 0)
628 filterFile = filter;
629 else {
630 filterPath = filter.left(slash + 1);
631 filterFile = filter.mid(slash + 1);
632 }
633 }
634 checkConfig();
635
636 if (d && d->restrictionsActive && (strcmp(type, "data")==0))
637 applyDataRestrictions(filter);
638 QStringList candidates = resourceDirs(type);
639 if (filterFile.isEmpty())
640 filterFile = "*";
641
642 QRegExp regExp(filterFile, true, true);
643 for (QStringList::ConstIterator it = candidates.begin();
644 it != candidates.end(); it++)
645 {
646 lookupPrefix(*it, filterPath, "", regExp, list,
647 relList, recursive, uniq);
648 }
649 return list;
650}
651
652QStringList
653KStandardDirs::findAllResources( const char *type,
654 const QString& filter,
655 bool recursive,
656 bool uniq) const
657{
658 QStringList relList;
659 return findAllResources(type, filter, recursive, uniq, relList);
660}
661
662QString
663KStandardDirs::realPath(const QString &dirname)
664{
665#ifdef _WIN32_
666 return dirname;
667#else
668//US char realpath_buffer[MAXPATHLEN + 1];
669//US memset(realpath_buffer, 0, MAXPATHLEN + 1);
670 char realpath_buffer[250 + 1];
671 memset(realpath_buffer, 0, 250 + 1);
672
673 /* If the path contains symlinks, get the real name */
674 if (realpath( QFile::encodeName(dirname).data(), realpath_buffer) != 0) {
675 // succes, use result from realpath
676 int len = strlen(realpath_buffer);
677 realpath_buffer[len] = '/';
678 realpath_buffer[len+1] = 0;
679 return QFile::decodeName(realpath_buffer);
680 }
681
682 return dirname;
683#endif
684}
685/*US
686void KStandardDirs::createSpecialResource(const char *type)
687{
688 char hostname[256];
689 hostname[0] = 0;
690 gethostname(hostname, 255);
691 QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname);
692 char link[1024];
693 link[1023] = 0;
694 int result = readlink(QFile::encodeName(dir).data(), link, 1023);
695 if ((result == -1) && (errno == ENOENT))
696 {
697 QString srv = findExe(QString::fromLatin1("lnusertemp"), KDEDIR+QString::fromLatin1("/bin"));
698 if (srv.isEmpty())
699 srv = findExe(QString::fromLatin1("lnusertemp"));
700 if (!srv.isEmpty())
701 {
702 system(QFile::encodeName(srv)+" "+type);
703 result = readlink(QFile::encodeName(dir).data(), link, 1023);
704 }
705 }
706 if (result > 0)
707 {
708 link[result] = 0;
709 if (link[0] == '/')
710 dir = QFile::decodeName(link);
711 else
712 dir = QDir::cleanDirPath(dir+QFile::decodeName(link));
713 }
714 addResourceDir(type, dir+'/');
715}
716*/
717
718QStringList KStandardDirs::resourceDirs(const char *type) const
719{
720 QStringList *candidates = dircache.find(type);
721
722 if (!candidates) { // filling cache
723/*US
724 if (strcmp(type, "socket") == 0)
725 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
726 else if (strcmp(type, "tmp") == 0)
727 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
728 else if (strcmp(type, "cache") == 0)
729 const_cast<KStandardDirs *>(this)->createSpecialResource(type);
730*/
731 QDir testdir;
732
733 candidates = new QStringList();
734 QStringList *dirs;
735
736 bool restrictionActive = false;
737 if (d && d->restrictionsActive)
738 {
739 if (d->dataRestrictionActive)
740 restrictionActive = true;
741 else if (d->restrictions["all"])
742 restrictionActive = true;
743 else if (d->restrictions[type])
744 restrictionActive = true;
745 d->dataRestrictionActive = false; // Reset
746 }
747
748 dirs = relatives.find(type);
749 if (dirs)
750 {
751 bool local = true;
752 const QStringList *prefixList = 0;
753 if (strncmp(type, "xdgdata-", 8) == 0)
754 prefixList = &(d->xdgdata_prefixes);
755 else if (strncmp(type, "xdgconf-", 8) == 0)
756 prefixList = &(d->xdgconf_prefixes);
757 else
758 prefixList = &prefixes;
759
760 for (QStringList::ConstIterator pit = prefixList->begin();
761 pit != prefixList->end();
762 pit++)
763 {
764 for (QStringList::ConstIterator it = dirs->begin();
765 it != dirs->end(); ++it) {
766 QString path = realPath(*pit + *it);
767 testdir.setPath(path);
768 if (local && restrictionActive)
769 continue;
770 if ((local || testdir.exists()) && !candidates->contains(path))
771 candidates->append(path);
772 }
773 local = false;
774 }
775 }
776 dirs = absolutes.find(type);
777 if (dirs)
778 for (QStringList::ConstIterator it = dirs->begin();
779 it != dirs->end(); ++it)
780 {
781 testdir.setPath(*it);
782 if (testdir.exists())
783 {
784 QString filename = realPath(*it);
785 if (!candidates->contains(filename))
786 candidates->append(filename);
787 }
788 }
789 dircache.insert(type, candidates);
790 }
791
792#if 0
793 kdDebug() << "found dirs for resource " << type << ":" << endl;
794 for (QStringList::ConstIterator pit = candidates->begin();
795 pit != candidates->end();
796 pit++)
797 {
798 fprintf(stderr, "%s\n", (*pit).latin1());
799 }
800#endif
801
802
803 return *candidates;
804}
805
806/*US
807QString KStandardDirs::findExe( const QString& appname,
808 const QString& pstr, bool ignore)
809{
810 QFileInfo info;
811
812 // absolute path ?
813 if (appname.startsWith(QString::fromLatin1("/")))
814 {
815 info.setFile( appname );
816 if( info.exists() && ( ignore || info.isExecutable() )
817 && info.isFile() ) {
818 return appname;
819 }
820 return QString::null;
821 }
822
823//US QString p = QString("%1/%2").arg(__KDE_BINDIR).arg(appname);
824 QString p = QString("%1/%2").arg(appname).arg(appname);
825 qDebug("KStandardDirs::findExe this is probably wrong");
826
827 info.setFile( p );
828 if( info.exists() && ( ignore || info.isExecutable() )
829 && ( info.isFile() || info.isSymLink() ) ) {
830 return p;
831 }
832
833 QStringList tokens;
834 p = pstr;
835
836 if( p.isNull() ) {
837 p = getenv( "PATH" );
838 }
839
840 tokenize( tokens, p, ":\b" );
841
842 // split path using : or \b as delimiters
843 for( unsigned i = 0; i < tokens.count(); i++ ) {
844 p = tokens[ i ];
845
846 if ( p[ 0 ] == '~' )
847 {
848 int len = p.find( '/' );
849 if ( len == -1 )
850 len = p.length();
851 if ( len == 1 )
852 p.replace( 0, 1, QDir::homeDirPath() );
853 else
854 {
855 QString user = p.mid( 1, len - 1 );
856 struct passwd *dir = getpwnam( user.local8Bit().data() );
857 if ( dir && strlen( dir->pw_dir ) )
858 p.replace( 0, len, QString::fromLocal8Bit( dir->pw_dir ) );
859 }
860 }
861
862 p += "/";
863 p += appname;
864
865 // Check for executable in this tokenized path
866 info.setFile( p );
867
868 if( info.exists() && ( ignore || info.isExecutable() )
869 && ( info.isFile() || info.isSymLink() ) ) {
870 return p;
871 }
872 }
873
874 // If we reach here, the executable wasn't found.
875 // So return empty string.
876
877 return QString::null;
878}
879
880int KStandardDirs::findAllExe( QStringList& list, const QString& appname,
881 const QString& pstr, bool ignore )
882{
883 QString p = pstr;
884 QFileInfo info;
885 QStringList tokens;
886
887 if( p.isNull() ) {
888 p = getenv( "PATH" );
889 }
890
891 list.clear();
892 tokenize( tokens, p, ":\b" );
893
894 for ( unsigned i = 0; i < tokens.count(); i++ ) {
895 p = tokens[ i ];
896 p += "/";
897 p += appname;
898
899 info.setFile( p );
900
901 if( info.exists() && (ignore || info.isExecutable())
902 && info.isFile() ) {
903 list.append( p );
904 }
905
906 }
907
908 return list.count();
909}
910*/
911
912static int tokenize( QStringList& tokens, const QString& str,
913 const QString& delim )
914{
915 int len = str.length();
916 QString token = "";
917
918 for( int index = 0; index < len; index++)
919 {
920 if ( delim.find( str[ index ] ) >= 0 )
921 {
922 tokens.append( token );
923 token = "";
924 }
925 else
926 {
927 token += str[ index ];
928 }
929 }
930 if ( token.length() > 0 )
931 {
932 tokens.append( token );
933 }
934
935 return tokens.count();
936}
937
938QString KStandardDirs::kde_default(const char *type) {
939 if (!strcmp(type, "data"))
940 return "apps/";
941 if (!strcmp(type, "html"))
942 return "share/doc/HTML/";
943 if (!strcmp(type, "icon"))
944 return "share/icons/";
945 if (!strcmp(type, "config"))
946 return "config/";
947 if (!strcmp(type, "pixmap"))
948 return "share/pixmaps/";
949 if (!strcmp(type, "apps"))
950 return "share/applnk/";
951 if (!strcmp(type, "sound"))
952 return "share/sounds/";
953 if (!strcmp(type, "locale"))
954 return "share/locale/";
955 if (!strcmp(type, "services"))
956 return "share/services/";
957 if (!strcmp(type, "servicetypes"))
958 return "share/servicetypes/";
959 if (!strcmp(type, "mime"))
960 return "share/mimelnk/";
961 if (!strcmp(type, "cgi"))
962 return "cgi-bin/";
963 if (!strcmp(type, "wallpaper"))
964 return "share/wallpapers/";
965 if (!strcmp(type, "templates"))
966 return "share/templates/";
967 if (!strcmp(type, "exe"))
968 return "bin/";
969 if (!strcmp(type, "lib"))
970 return "lib/";
971 if (!strcmp(type, "module"))
972 return "lib/kde3/";
973 if (!strcmp(type, "qtplugins"))
974 return "lib/kde3/plugins";
975 if (!strcmp(type, "xdgdata-apps"))
976 return "applications/";
977 if (!strcmp(type, "xdgdata-dirs"))
978 return "desktop-directories/";
979 if (!strcmp(type, "xdgconf-menu"))
980 return "menus/";
981 qFatal("unknown resource type %s", type);
982 return QString::null;
983}
984
985QString KStandardDirs::saveLocation(const char *type,
986 const QString& suffix,
987 bool create) const
988{
989 //qDebug("KStandardDirs::saveLocation called %s %s", type,suffix.latin1() );
990 //return "";
991 checkConfig();
992
993 QString *pPath = savelocations.find(type);
994 if (!pPath)
995 {
996 QStringList *dirs = relatives.find(type);
997 if (!dirs && (
998 (strcmp(type, "socket") == 0) ||
999 (strcmp(type, "tmp") == 0) ||
1000 (strcmp(type, "cache") == 0) ))
1001 {
1002 (void) resourceDirs(type); // Generate socket|tmp|cache resource.
1003 dirs = relatives.find(type); // Search again.
1004 }
1005 if (dirs)
1006 {
1007 // Check for existance of typed directory + suffix
1008 if (strncmp(type, "xdgdata-", 8) == 0)
1009 pPath = new QString(realPath(localxdgdatadir() + dirs->last()));
1010 else if (strncmp(type, "xdgconf-", 8) == 0)
1011 pPath = new QString(realPath(localxdgconfdir() + dirs->last()));
1012 else
1013 pPath = new QString(realPath(localkdedir() + dirs->last()));
1014 }
1015 else {
1016 dirs = absolutes.find(type);
1017 if (!dirs)
1018 qFatal("KStandardDirs: The resource type %s is not registered", type);
1019 pPath = new QString(realPath(dirs->last()));
1020 }
1021
1022 savelocations.insert(type, pPath);
1023 }
1024
1025 QString fullPath = *pPath + suffix;
1026//US struct stat st;
1027//US if (stat(QFile::encodeName(fullPath), &st) != 0 || !(S_ISDIR(st.st_mode)))
1028 QFileInfo fullPathInfo(QFile::encodeName(fullPath));
1029 if (fullPathInfo.isReadable() || !fullPathInfo.isDir())
1030
1031
1032 {
1033 if(!create) {
1034#ifndef NDEBUG
1035 qDebug("save location %s doesn't exist", fullPath.latin1());
1036#endif
1037 return fullPath;
1038 }
1039 if(!makeDir(fullPath, 0700)) {
1040 qWarning("failed to create %s", fullPath.latin1());
1041 return fullPath;
1042 }
1043 dircache.remove(type);
1044 }
1045 return fullPath;
1046}
1047
1048QString KStandardDirs::relativeLocation(const char *type, const QString &absPath)
1049{
1050 QString fullPath = absPath;
1051 int i = absPath.findRev('/');
1052 if (i != -1)
1053 {
1054 fullPath = realPath(absPath.left(i+1))+absPath.mid(i+1); // Normalize
1055 }
1056
1057 QStringList candidates = resourceDirs(type);
1058
1059 for (QStringList::ConstIterator it = candidates.begin();
1060 it != candidates.end(); it++)
1061 if (fullPath.startsWith(*it))
1062 {
1063 return fullPath.mid((*it).length());
1064 }
1065
1066 return absPath;
1067}
1068
1069
1070bool KStandardDirs::makeDir(const QString& dir2, int mode)
1071{
1072 QString dir = QDir::convertSeparators( dir2 );
1073#if 0
1074 //LR
1075
1076 // we want an absolute path
1077 if (dir.at(0) != '/')
1078 return false;
1079
1080 QString target = dir;
1081 uint len = target.length();
1082
1083 // append trailing slash if missing
1084 if (dir.at(len - 1) != '/')
1085 target += '/';
1086
1087 QString base("");
1088 uint i = 1;
1089
1090 while( i < len )
1091 {
1092//US struct stat st;
1093 int pos = target.find('/', i);
1094 base += target.mid(i - 1, pos - i + 1);
1095 QCString baseEncoded = QFile::encodeName(base);
1096 // bail out if we encountered a problem
1097//US if (stat(baseEncoded, &st) != 0)
1098 QFileInfo baseEncodedInfo(baseEncoded);
1099 if (!baseEncodedInfo.exists())
1100 {
1101 // Directory does not exist....
1102 // Or maybe a dangling symlink ?
1103//US if (lstat(baseEncoded, &st) == 0)
1104 if (baseEncodedInfo.isSymLink()) {
1105//US (void)unlink(baseEncoded); // try removing
1106 QFile(baseEncoded).remove();
1107 }
1108
1109 //US if ( mkdir(baseEncoded, (mode_t) mode) != 0)
1110 QDir dirObj;
1111 if ( dirObj.mkdir(baseEncoded) != true )
1112 {
1113 //US perror("trying to create local folder");
1114 return false; // Couldn't create it :-(
1115 }
1116 }
1117 i = pos + 1;
1118 }
1119 return true;
1120#endif
1121
1122 // ********************************************
1123 // new code for WIN32
1124 QDir dirObj;
1125
1126
1127 // we want an absolute path
1128#ifndef _WIN32_
1129 if (dir.at(0) != '/')
1130 return false;
1131#endif
1132
1133 QString target = dir;
1134 uint len = target.length();
1135#ifndef _WIN32_
1136 // append trailing slash if missing
1137 if (dir.at(len - 1) != '/')
1138 target += '/';
1139#endif
1140
1141 QString base("");
1142 uint i = 1;
1143
1144 while( i < len )
1145 {
1146//US struct stat st;
1147#ifndef _WIN32_
1148 int pos = target.find('/', i);
1149#else
1150 int pos = target.find('\\', i);
1151#endif
1152 if ( pos < 0 )
1153 return true;
1154 base += target.mid(i - 1, pos - i + 1);
1155 //QMessageBox::information( 0,"cap111", base, 1 );
1156/*US
1157 QCString baseEncoded = QFile::encodeName(base);
1158 // bail out if we encountered a problem
1159 if (stat(baseEncoded, &st) != 0)
1160 {
1161 // Directory does not exist....
1162 // Or maybe a dangling symlink ?
1163 if (lstat(baseEncoded, &st) == 0)
1164 (void)unlink(baseEncoded); // try removing
1165
1166
1167 if ( mkdir(baseEncoded, (mode_t) mode) != 0) {
1168 perror("trying to create local folder");
1169 return false; // Couldn't create it :-(
1170 }
1171 }
1172*/
1173
1174 if (dirObj.exists(base) == false)
1175 {
1176 //qDebug("KStandardDirs::makeDir try to create : %s" , base.latin1());
1177 if (dirObj.mkdir(base) != true)
1178 {
1179 qDebug("KStandardDirs::makeDir could not create: %s" , base.latin1());
1180 return false;
1181 }
1182 }
1183
1184 i = pos + 1;
1185 }
1186 return true;
1187
1188}
1189
1190static QString readEnvPath(const char *env)
1191{
1192#ifdef _WIN32_
1193 return "";
1194#else
1195 QCString c_path = getenv(env);
1196 if (c_path.isEmpty())
1197 return QString::null;
1198 return QFile::decodeName(c_path);
1199#endif
1200}
1201
1202void KStandardDirs::addKDEDefaults()
1203{
1204 //qDebug("ERROR: KStandardDirs::addKDEDefaults() called ");
1205 //return;
1206 QStringList kdedirList;
1207
1208 // begin KDEDIRS
1209 QString kdedirs = readEnvPath("MICROKDEDIRS");
1210 if (!kdedirs.isEmpty())
1211 {
1212 tokenize(kdedirList, kdedirs, ":");
1213 }
1214 else
1215 {
1216 QString kdedir = readEnvPath("MICROKDEDIR");
1217 if (!kdedir.isEmpty())
1218 {
1219 kdedir = KShell::tildeExpand(kdedir);
1220 kdedirList.append(kdedir);
1221 }
1222 }
1223//US kdedirList.append(KDEDIR);
1224
1225#ifdef __KDE_EXECPREFIX
1226 QString execPrefix(__KDE_EXECPREFIX);
1227 if (execPrefix!="NONE")
1228 kdedirList.append(execPrefix);
1229#endif
1230
1231 QString localKdeDir;
1232
1233//US if (getuid())
1234 if (true)
1235 {
1236 localKdeDir = readEnvPath("MICROKDEHOME");
1237 if (!localKdeDir.isEmpty())
1238 {
1239 if (localKdeDir.at(localKdeDir.length()-1) != '/')
1240 localKdeDir += '/';
1241 }
1242 else
1243 {
1244 localKdeDir = QDir::homeDirPath() + "/kdepim/";
1245 }
1246 }
1247 else
1248 {
1249 // We treat root different to prevent root messing up the
1250 // file permissions in the users home directory.
1251 localKdeDir = readEnvPath("MICROKDEROOTHOME");
1252 if (!localKdeDir.isEmpty())
1253 {
1254 if (localKdeDir.at(localKdeDir.length()-1) != '/')
1255 localKdeDir += '/';
1256 }
1257 else
1258 {
1259//US struct passwd *pw = getpwuid(0);
1260//US localKdeDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.microkde/";
1261 qDebug("KStandardDirs::addKDEDefaults: 1 has to be fixed");
1262 }
1263
1264 }
1265
1266//US localKdeDir = appDir();
1267
1268//US
1269// qDebug("KStandardDirs::addKDEDefaults: localKdeDir=%s", localKdeDir.latin1());
1270 if (localKdeDir != "-/")
1271 {
1272 localKdeDir = KShell::tildeExpand(localKdeDir);
1273 addPrefix(localKdeDir);
1274 }
1275
1276 for (QStringList::ConstIterator it = kdedirList.begin();
1277 it != kdedirList.end(); it++)
1278 {
1279 QString dir = KShell::tildeExpand(*it);
1280 addPrefix(dir);
1281 }
1282 // end KDEDIRS
1283
1284 // begin XDG_CONFIG_XXX
1285 QStringList xdgdirList;
1286 QString xdgdirs = readEnvPath("XDG_CONFIG_DIRS");
1287 if (!xdgdirs.isEmpty())
1288 {
1289 tokenize(xdgdirList, xdgdirs, ":");
1290 }
1291 else
1292 {
1293 xdgdirList.clear();
1294 xdgdirList.append("/etc/xdg");
1295 }
1296
1297 QString localXdgDir = readEnvPath("XDG_CONFIG_HOME");
1298 if (!localXdgDir.isEmpty())
1299 {
1300 if (localXdgDir.at(localXdgDir.length()-1) != '/')
1301 localXdgDir += '/';
1302 }
1303 else
1304 {
1305//US if (getuid())
1306 if (true)
1307 {
1308 localXdgDir = QDir::homeDirPath() + "/.config/";
1309 }
1310 else
1311 {
1312//US struct passwd *pw = getpwuid(0);
1313//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.config/";
1314 qDebug("KStandardDirs::addKDEDefaults: 2 has to be fixed");
1315 }
1316 }
1317
1318 localXdgDir = KShell::tildeExpand(localXdgDir);
1319 addXdgConfigPrefix(localXdgDir);
1320
1321 for (QStringList::ConstIterator it = xdgdirList.begin();
1322 it != xdgdirList.end(); it++)
1323 {
1324 QString dir = KShell::tildeExpand(*it);
1325 addXdgConfigPrefix(dir);
1326 }
1327 // end XDG_CONFIG_XXX
1328
1329 // begin XDG_DATA_XXX
1330 xdgdirs = readEnvPath("XDG_DATA_DIRS");
1331 if (!xdgdirs.isEmpty())
1332 {
1333 tokenize(xdgdirList, xdgdirs, ":");
1334 }
1335 else
1336 {
1337 xdgdirList.clear();
1338 for (QStringList::ConstIterator it = kdedirList.begin();
1339 it != kdedirList.end(); it++)
1340 {
1341 QString dir = *it;
1342 if (dir.at(dir.length()-1) != '/')
1343 dir += '/';
1344 xdgdirList.append(dir+"share/");
1345 }
1346
1347 xdgdirList.append("/usr/local/share/");
1348 xdgdirList.append("/usr/share/");
1349 }
1350
1351 localXdgDir = readEnvPath("XDG_DATA_HOME");
1352 if (!localXdgDir.isEmpty())
1353 {
1354 if (localXdgDir.at(localXdgDir.length()-1) != '/')
1355 localXdgDir += '/';
1356 }
1357 else
1358 {
1359//US if (getuid())
1360 if (true)
1361 {
1362 localXdgDir = QDir::homeDirPath() + "/.local/share/";
1363 }
1364 else
1365 {
1366//US struct passwd *pw = getpwuid(0);
1367//US localXdgDir = QFile::decodeName((pw && pw->pw_dir) ? pw->pw_dir : "/root") + "/.local/share/";
1368 qDebug("KStandardDirs::addKDEDefaults: 3 has to be fixed");
1369 }
1370 }
1371
1372 localXdgDir = KShell::tildeExpand(localXdgDir);
1373 addXdgDataPrefix(localXdgDir);
1374
1375 for (QStringList::ConstIterator it = xdgdirList.begin();
1376 it != xdgdirList.end(); it++)
1377 {
1378 QString dir = KShell::tildeExpand(*it);
1379
1380 addXdgDataPrefix(dir);
1381 }
1382 // end XDG_DATA_XXX
1383
1384
1385 uint index = 0;
1386 while (types[index] != 0) {
1387 addResourceType(types[index], kde_default(types[index]));
1388 index++;
1389 }
1390
1391 addResourceDir("home", QDir::homeDirPath());
1392}
1393
1394void KStandardDirs::checkConfig() const
1395{
1396/*US
1397 if (!addedCustoms && KGlobal::_instance && KGlobal::_instance->_config)
1398 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::_instance->_config);
1399*/
1400 if (!addedCustoms && KGlobal::config())
1401 const_cast<KStandardDirs*>(this)->addCustomized(KGlobal::config());
1402}
1403
1404bool KStandardDirs::addCustomized(KConfig *config)
1405{
1406 if (addedCustoms) // there are already customized entries
1407 return false; // we just quite and hope they are the right ones
1408
1409 // save the numbers of config directories. If this changes,
1410 // we will return true to give KConfig a chance to reparse
1411 uint configdirs = resourceDirs("config").count();
1412
1413 // reading the prefixes in
1414 QString oldGroup = config->group();
1415 config->setGroup("Directories");
1416
1417 QStringList list;
1418 QStringList::ConstIterator it;
1419 list = config->readListEntry("prefixes");
1420 for (it = list.begin(); it != list.end(); it++)
1421 addPrefix(*it);
1422
1423 // iterating over all entries in the group Directories
1424 // to find entries that start with dir_$type
1425/*US
1426 QMap<QString, QString> entries = config->entryMap("Directories");
1427
1428 QMap<QString, QString>::ConstIterator it2;
1429 for (it2 = entries.begin(); it2 != entries.end(); it2++)
1430 {
1431 QString key = it2.key();
1432 if (key.left(4) == "dir_") {
1433 // generate directory list, there may be more than 1.
1434 QStringList dirs = QStringList::split(',', *it2);
1435 QStringList::Iterator sIt(dirs.begin());
1436 QString resType = key.mid(4, key.length());
1437 for (; sIt != dirs.end(); ++sIt) {
1438 addResourceDir(resType.latin1(), *sIt);
1439 }
1440 }
1441 }
1442
1443 // Process KIOSK restrictions.
1444 config->setGroup("KDE Resource Restrictions");
1445 entries = config->entryMap("KDE Resource Restrictions");
1446 for (it2 = entries.begin(); it2 != entries.end(); it2++)
1447 {
1448 QString key = it2.key();
1449 if (!config->readBoolEntry(key, true))
1450 {
1451 d->restrictionsActive = true;
1452 d->restrictions.insert(key.latin1(), &d->restrictionsActive); // Anything will do
1453 dircache.remove(key.latin1());
1454 }
1455 }
1456*/
1457 // save it for future calls - that will return
1458 addedCustoms = true;
1459 config->setGroup(oldGroup);
1460
1461 // return true if the number of config dirs changed
1462 return (resourceDirs("config").count() != configdirs);
1463}
1464
1465QString KStandardDirs::localkdedir() const
1466{
1467 // Return the prefix to use for saving
1468 return prefixes.first();
1469}
1470
1471QString KStandardDirs::localxdgdatadir() const
1472{
1473 // Return the prefix to use for saving
1474 return d->xdgdata_prefixes.first();
1475}
1476
1477QString KStandardDirs::localxdgconfdir() const
1478{
1479 // Return the prefix to use for saving
1480 return d->xdgconf_prefixes.first();
1481}
1482
1483void KStandardDirs::setAppDir( const QString &appDir )
1484{
1485 mAppDir = appDir;
1486
1487 if ( mAppDir.right( 1 ) != "/" )
1488 mAppDir += "/";
1489}
1490
1491QString KStandardDirs::appDir()
1492{
1493 return mAppDir;
1494}
1495
1496// just to make code more readable without macros
1497QString locate( const char *type,
1498 const QString& filename/*US , const KInstance* inst*/ )
1499{
1500//US return inst->dirs()->findResource(type, filename);
1501 return KGlobal::dirs()->findResource(type, filename);
1502}
1503
1504QString locateLocal( const char *type,
1505 const QString& filename/*US , const KInstance* inst*/ )
1506{
1507
1508 QString path = locateLocal(type, filename, true /*US, inst*/);
1509
1510
1511/*
1512 static int ccc = 0;
1513 ++ccc;
1514 if ( ccc > 13 )
1515 abort();
1516*/
1517 qDebug("locatelocal: %s" , path.latin1());
1518 return path;
1519
1520/*US why do we put all files into one directory. It is quit complicated.
1521why not staying with the original directorystructure ?
1522
1523
1524 QString escapedFilename = filename;
1525 escapedFilename.replace( QRegExp( "/" ), "_" );
1526
1527 QString path = KStandardDirs::appDir() + type + "_" + escapedFilename;
1528
1529 kdDebug() << "locate: '" << path << "'" << endl;
1530 qDebug("locate: %s" , path.latin1());
1531 return path;
1532*/
1533//US so my proposal is this:
1534
1535// QString escapedFilename = filename;
1536// escapedFilename.replace( QRegExp( "/" ), "_" );
1537
1538#if 0
1539#ifdef _WIN32_
1540 QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename);
1541#else
1542 QString path = KStandardDirs::appDir() + type + "/" + filename;
1543#endif
1544
1545 //US Create the containing dir if needed
1546 QFileInfo fi ( path );
1547
1548 // QString dir=pathurl.directory();
1549 //QMessageBox::information( 0,"path", path, 1 );
1550
1551#ifdef _WIN32_
1552 KStandardDirs::makeDir(path);
1553#else
1554 KStandardDirs::makeDir(fi.dirPath( true ));
1555#endif
1556
1557 qDebug("locate22: %s" , path.latin1());
1558 return path;
1559
1560#endif
1561
1562}
1563
1564QString locateLocal( const char *type,
1565 const QString& filename, bool createDir/*US , const KInstance* inst*/ )
1566{
1567 // try to find slashes. If there are some, we have to
1568 // create the subdir first
1569 int slash = filename.findRev('/')+1;
1570 if (!slash) // only one filename
1571 //USreturn inst->dirs()->saveLocation(type, QString::null, createDir) + filename;
1572 return KGlobal::dirs()->saveLocation(type, QString::null, createDir) + filename;
1573
1574 // split path from filename
1575 QString dir = filename.left(slash);
1576 QString file = filename.mid(slash);
1577//US return inst->dirs()->saveLocation(type, dir, createDir) + file;
1578 return KGlobal::dirs()->saveLocation(type, dir, createDir) + file;
1579
1580 // ***************************************************************
1581#if 0
1582
1583/*US why do we put all files into one directory. It is quit complicated.
1584why not staying with the original directorystructure ?
1585
1586
1587 QString escapedFilename = filename;
1588 escapedFilename.replace( QRegExp( "/" ), "_" );
1589
1590 QString path = KStandardDirs::appDir() + type + "_" + escapedFilename;
1591
1592 kdDebug() << "locate: '" << path << "'" << endl;
1593 qDebug("locate: %s" , path.latin1());
1594 return path;
1595*/
1596//US so my proposal is this:
1597
1598// QString escapedFilename = filename;
1599// escapedFilename.replace( QRegExp( "/" ), "_" );
1600
1601#ifdef _WIN32_
1602 QString path = QDir::convertSeparators(KStandardDirs::appDir() + type + "/" + filename);
1603#else
1604 QString path = KStandardDirs::appDir() + type + "/" + filename;
1605#endif
1606
1607 //US Create the containing dir if needed
1608 KURL pathurl;
1609 pathurl.setPath(path);
1610 QString dir=pathurl.directory();
1611 //QMessageBox::information( 0,"path", path, 1 );
1612#ifdef _WIN32_
1613 KStandardDirs::makeDir(path);
1614#else
1615 KStandardDirs::makeDir(dir);
1616#endif
1617
1618 return path;
1619#endif
1620}
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 @@
1/*
2 This file is part of the KDE libraries
3 Copyright (C) 1999 Sirtaj Singh Kang <taj@kde.org>
4 Stephan Kulow <coolo@kde.org>
5 Waldo Bastian <bastian@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21*/
22
23#ifndef SSK_KSTDDIRS_H
24#define SSK_KSTDDIRS_H
25
26#include <qstring.h>
27#include <qdict.h>
28#include <qstringlist.h>
29#include <kglobal.h>
30
31class KConfig;
32class KStandardDirsPrivate;
33
34
35/**
36 * @short Site-independent access to standard KDE directories.
37 * @author Stephan Kulow <coolo@kde.org> and Sirtaj Singh Kang <taj@kde.org>
38 * @version $Id$
39 *
40 * This is one of the most central classes in kdelibs as
41 * it provides a basic service: It knows where the files
42 * reside on the user's hard disk. And it's meant to be the
43 * only one that knows -- to make the real location as
44 * transparent as possible to both the user and the applications.
45 *
46 * To this end it insulates the application from all information
47 * and applications always refer to a file with a resource type
48 * (e.g. icon) and a filename (e.g. khexdit.xpm). In an ideal world
49 * the application would make no assumption where this file is and
50 * leave it up to @ref KStandardDirs::findResource("apps", "Home.desktop")
51 * to apply this knowledge to return /opt/kde/share/applnk/Home.desktop
52 * or ::locate("data", "kgame/background.jpg") to return
53 * /opt/kde/share/apps/kgame/background.jpg
54 *
55 * The main idea behind KStandardDirs is that there are several
56 * toplevel prefixes below which the files lie. One of these prefixes is
57 * the one where the user installed kdelibs, one is where the
58 * application was installed, and one is $HOME/.kde, but there
59 * may be even more. Under these prefixes there are several well
60 * defined suffixes where specific resource types are to be found.
61 * For example, for the resource type "html" the suffixes could be
62 * share/doc/HTML and share/doc/kde/HTML.
63 * So the search algorithm basicly appends to each prefix each registered
64 * suffix and tries to locate the file there.
65 * To make the thing even more complex, it's also possible to register
66 * absolute paths that KStandardDirs looks up after not finding anything
67 * in the former steps. They can be useful if the user wants to provide
68 * specific directories that aren't in his $HOME/.kde directory for,
69 * for example, icons.
70 *
71 * @sect Standard resources that kdelibs allocates are:
72 *
73 * @li apps - Applications menu (.desktop files).
74 * @li cache - Cached information (e.g. favicons, web-pages)
75 * @li cgi - CGIs to run from kdehelp.
76 * @li config - Configuration files.
77 * @li data - Where applications store data.
78 * @li exe - Executables in $prefix/bin. @ref findExe() for a function that takes $PATH into account.
79 * @li html - HTML documentation.
80 * @li icon - Icons, see @ref KIconLoader.
81 * @li lib - Libraries.
82 * @li locale - Translation files for @ref KLocale.
83 * @li mime - Mime types.
84 * @li module - Module (dynamically loaded library).
85 * @li qtplugins - Qt plugins (dynamically loaded objects for Qt)
86 * @li services - Services.
87 * @li servicetypes - Service types.
88 * @li scripts - Application scripting additions.
89 * @li sound - Application sounds.
90 * @li templates - Templates
91 * @li wallpaper - Wallpapers.
92 * @li tmp - Temporary files (specfic for both current host and current user)
93 * @li socket - UNIX Sockets (specific for both current host and current user)
94 *
95 * A type that is added by the class @ref KApplication if you use it, is
96 * appdata. This one makes the use of the type data a bit easier as it
97 * appends the name of the application.
98 * So while you had to ::locate("data", "appname/filename") so you can
99 * also write ::locate("appdata", "filename") if your KApplication instance
100 * is called "appname" (as set via KApplication's constructor or KAboutData, if
101 * you use the global KStandardDirs object @ref KGlobal::dirs()).
102 * Please note though that you cannot use the "appdata"
103 * type if you intend to use it in an applet for Kicker because 'appname' would
104 * be "Kicker" instead of the applet's name. Therefore, for applets, you've got
105 * to work around this by using ::locate("data", "appletname/filename").
106 *
107 * @sect KStandardDirs supports the following environment variables:
108 *
109 * @li KDEDIRS: This may set an additional number of directory prefixes to
110 * search for resources. The directories should be seperated
111 * by ':'. The directories are searched in the order they are
112 * specified.
113 * @li KDEDIR: Used for backwards compatibility. As KDEDIRS but only a single
114 * directory may be specified. If KDEDIRS is set KDEDIR is
115 * ignored.
116 * @li KDEHOME: The directory where changes are saved to. This directory is
117 * used to search for resources first. If KDEHOME is not
118 * specified it defaults to "$HOME/.kde"
119 * @li KDEROOTHOME: Like KDEHOME, but used for the root user.
120 * If KDEROOTHOME is not set it defaults to the .kde directory in the
121 * home directory of root, usually "/root/.kde".
122 * Note that the setting of $HOME is ignored in this case.
123 *
124 * @see KGlobalSettings
125 */
126class KStandardDirs
127{
128public:
129 /**
130 * KStandardDirs' constructor. It just initializes the caches.
131 **/
132 KStandardDirs( );
133
134 /**
135 * KStandardDirs' destructor.
136 */
137 virtual ~KStandardDirs();
138
139 /**
140 * Adds another search dir to front of the @p fsstnd list.
141 *
142 * @li When compiling kdelibs, the prefix is added to this.
143 * @li KDEDIRS or KDEDIR is taking into account
144 * @li Additional dirs may be loaded from kdeglobals.
145 *
146 * @param dir The directory to append relative paths to.
147 */
148 void addPrefix( const QString& dir );
149
150 /**
151 * Adds another search dir to front of the XDG_CONFIG_XXX list
152 * of prefixes.
153 * This prefix is only used for resources that start with "xdgconf-"
154 *
155 * @param dir The directory to append relative paths to.
156 */
157 void addXdgConfigPrefix( const QString& dir );
158
159 /**
160 * Adds another search dir to front of the XDG_DATA_XXX list
161 * of prefixes.
162 * This prefix is only used for resources that start with "xdgdata-"
163 *
164 * @param dir The directory to append relative paths to.
165 */
166 void addXdgDataPrefix( const QString& dir );
167
168 /**
169 * Adds suffixes for types.
170 *
171 * You may add as many as you need, but it is advised that there
172 * is exactly one to make writing definite.
173 * All basic types (@ref kde_default) are added by @ref addKDEDefaults(),
174 * but for those you can add more relative paths as well.
175 *
176 * The later a suffix is added, the higher its priority. Note, that the
177 * suffix should end with / but doesn't have to start with one (as prefixes
178 * should end with one). So adding a suffix for app_pics would look
179 * like KGlobal::dirs()->addResourceType("app_pics", "share/app/pics");
180 *
181 * @param type Specifies a short descriptive string to access
182 * files of this type.
183 * @param relativename Specifies a directory relative to the root
184 * of the KFSSTND.
185 * @return true if successful, false otherwise.
186 */
187 bool addResourceType( const char *type,
188 const QString& relativename );
189
190 /**
191 * Adds absolute path at the end of the search path for
192 * particular types (for example in case of icons where
193 * the user specifies extra paths).
194 *
195 * You shouldn't need this
196 * function in 99% of all cases besides adding user-given
197 * paths.
198 *
199 * @param type Specifies a short descriptive string to access files
200 * of this type.
201 * @param absdir Points to directory where to look for this specific
202 * type. Non-existant directories may be saved but pruned.
203 * @return true if successful, false otherwise.
204 */
205 bool addResourceDir( const char *type,
206 const QString& absdir);
207
208 /**
209 * Tries to find a resource in the following order:
210 * @li All PREFIX/\<relativename> paths (most recent first).
211 * @li All absolute paths (most recent first).
212 *
213 * The filename should be a filename relative to the base dir
214 * for resources. So is a way to get the path to libkdecore.la
215 * to findResource("lib", "libkdecore.la"). KStandardDirs will
216 * then look into the subdir lib of all elements of all prefixes
217 * ($KDEDIRS) for a file libkdecore.la and return the path to
218 * the first one it finds (e.g. /opt/kde/lib/libkdecore.la)
219 *
220 * @param type The type of the wanted resource
221 * @param filename A relative filename of the resource.
222 *
223 * @return A full path to the filename specified in the second
224 * argument, or QString::null if not found.
225 */
226 QString findResource( const char *type,
227 const QString& filename ) const;
228
229 /**
230 * Checks whether a resource is restricted as part of the KIOSK
231 * framework. When a resource is restricted it means that user-
232 * specific files in the resource are ignored.
233 *
234 * E.g. by restricting the "wallpaper" resource, only system-wide
235 * installed wallpapers will be found by this class. Wallpapers
236 * installed under the $KDEHOME directory will be ignored.
237 *
238 * @param type The type of the resource to check
239 * @param relPath A relative path in the resource.
240 *
241 * @return True if the resource is restricted.
242 * @since 3.1
243 */
244 bool isRestrictedResource( const char *type,
245 const QString& relPath=QString::null ) const;
246
247 /**
248 * Returns a number that identifies this version of the resource.
249 * When a change is made to the resource this number will change.
250 *
251 * @param type The type of the wanted resource
252 * @param filename A relative filename of the resource.
253 * @param deep If true, all resources are taken into account
254 * otherwise only the one returned by findResource().
255 *
256 * @return A number identifying the current version of the
257 * resource.
258 */
259/*US
260 Q_UINT32 calcResourceHash( const char *type,
261 const QString& filename, bool deep) const;
262*/
263 /**
264 * Tries to find all directories whose names consist of the
265 * specified type and a relative path. So would
266 * findDirs("apps", "Settings") return
267 * @li /opt/kde/share/applnk/Settings/
268 * @li /home/joe/.kde/share/applnk/Settings/
269 *
270 * Note that it appends / to the end of the directories,
271 * so you can use this right away as directory names.
272 *
273 * @param type The type of the base directory.
274 * @param reldir Relative directory.
275 *
276 * @return A list of matching directories, or an empty
277 * list if the resource specified is not found.
278 */
279 QStringList findDirs( const char *type,
280 const QString& reldir ) const;
281
282 /**
283 * Tries to find the directory the file is in.
284 * It works the same as @ref findResource(), but it doesn't
285 * return the filename but the name of the directory.
286 *
287 * This way the application can access a couple of files
288 * that have been installed into the same directory without
289 * having to look for each file.
290 *
291 * findResourceDir("lib", "libkdecore.la") would return the
292 * path of the subdir libkdecore.la is found first in
293 * (e.g. /opt/kde/lib/)
294 *
295 * @param type The type of the wanted resource
296 * @param filename A relative filename of the resource.
297 * @return The directory where the file specified in the second
298 * argument is located, or QString::null if the type
299 * of resource specified is unknown or the resource
300 * cannot be found.
301 */
302 QString findResourceDir( const char *type,
303 const QString& filename) const;
304
305
306 /**
307 * Tries to find all resources with the specified type.
308 *
309 * The function will look into all specified directories
310 * and return all filenames in these directories.
311 *
312 * @param type The type of resource to locate directories for.
313 * @param filter Only accept filenames that fit to filter. The filter
314 * may consist of an optional directory and a @ref QRegExp
315 * wildcard expression. E.g. "images\*.jpg". Use QString::null
316 * if you do not want a filter.
317 * @param recursive Specifies if the function should decend
318 * into subdirectories.
319 * @param uniq If specified, only return items which have
320 * unique suffixes - suppressing duplicated filenames.
321 *
322 * @return A list of directories matching the resource specified,
323 * or an empty list if the resource type is unknown.
324 */
325 QStringList findAllResources( const char *type,
326 const QString& filter = QString::null,
327 bool recursive = false,
328 bool uniq = false) const;
329
330 /**
331 * Tries to find all resources with the specified type.
332 *
333 * The function will look into all specified directories
334 * and return all filenames (full and relative paths) in
335 * these directories.
336 *
337 * @param type The type of resource to locate directories for.
338 * @param filter Only accept filenames that fit to filter. The filter
339 * may consist of an optional directory and a @ref QRegExp
340 * wildcard expression. E.g. "images\*.jpg". Use QString::null
341 * if you do not want a filter.
342 * @param recursive Specifies if the function should decend
343 * into subdirectories.
344 * @param uniq If specified, only return items which have
345 * unique suffixes.
346 * @param list Of relative paths for the given type.
347 * @param relPaths The list to store the relative paths into
348 * These can be used later to ::locate() the file
349 *
350 * @return A list of directories matching the resource specified,
351 * or an empty list if the resource type is unknown.
352 */
353 QStringList findAllResources( const char *type,
354 const QString& filter,
355 bool recursive,
356 bool uniq,
357 QStringList &relPaths) const;
358
359 /**
360 * Finds the executable in the system path.
361 *
362 * A valid executable must
363 * be a file and have its executable bit set.
364 *
365 * @param appname The name of the executable file for which to search.
366 * @param pathstr The path which will be searched. If this is
367 * null (default), the $PATH environment variable will
368 * be searched.
369 * @param ignoreExecBitIf true, an existing file will be returned
370 * even if its executable bit is not set.
371 *
372 * @return The path of the executable. If it was not found,
373 * it will return QString::null.
374 * @see findAllExe()
375 */
376/*US
377 static QString findExe( const QString& appname,
378 const QString& pathstr=QString::null,
379 bool ignoreExecBit=false );
380*/
381
382 /**
383 * Finds all occurences of an executable in the system path.
384 *
385 * @param listWill be filled with the pathnames of all the
386 * executables found. Will be empty if the executable
387 * was not found.
388 * @param appnameThe name of the executable for which to
389 * search.
390 * @param pathstrThe path list which will be searched. If this
391 * is 0 (default), the $PATH environment variable will
392 * be searched.
393 * @param ignoreExecBit If true, an existing file will be returned
394 * even if its executable bit is not set.
395 *
396 * @return The number of executables found, 0 if none were found.
397 *
398 * @seefindExe()
399 */
400 static int findAllExe( QStringList& list, const QString& appname,
401 const QString& pathstr=QString::null,
402 bool ignoreExecBit=false );
403
404 /**
405 * This function adds the defaults that are used by the current
406 * KDE version.
407 *
408 * It's a series of @ref addResourceTypes()
409 * and @ref addPrefix() calls.
410 * You normally wouldn't call this function because it's called
411 * for you from @ref KGlobal.
412 */
413 void addKDEDefaults();
414
415 /**
416 * Reads customized entries out of the given config object and add
417 * them via @ref addResourceDirs().
418 *
419 * @param config The object the entries are read from. This should
420 * contain global config files
421 * @return true if new config paths have been added
422 * from @p config.
423 **/
424 bool addCustomized(KConfig *config);
425
426 /**
427 * This function is used internally by almost all other function as
428 * it serves and fills the directories cache.
429 *
430 * @param type The type of resource
431 * @return The list of possible directories for the specified @p type.
432 * The function updates the cache if possible. If the resource
433 * type specified is unknown, it will return an empty list.
434 * Note, that the directories are assured to exist beside the save
435 * location, which may not exist, but is returned anyway.
436 */
437 QStringList resourceDirs(const char *type) const;
438
439 /**
440 * This function will return a list of all the types that KStandardDirs
441 * supports.
442 *
443 * @return All types that KDE supports
444 */
445 QStringList allTypes() const;
446
447 /**
448 * Finds a location to save files into for the given type
449 * in the user's home directory.
450 *
451 * @param type The type of location to return.
452 * @param suffix A subdirectory name.
453 * Makes it easier for you to create subdirectories.
454 * You can't pass filenames here, you _have_ to pass
455 * directory names only and add possible filename in
456 * that directory yourself. A directory name always has a
457 * trailing slash ('/').
458 * @param create If set, saveLocation() will create the directories
459 * needed (including those given by @p suffix).
460 *
461 * @return A path where resources of the specified type should be
462 * saved, or QString::null if the resource type is unknown.
463 */
464 QString saveLocation(const char *type,
465 const QString& suffix = QString::null,
466 bool create = true) const;
467
468 /**
469 * Converts an absolute path to a path relative to a certain
470 * resource.
471 *
472 * If "abs = ::locate(resource, rel)"
473 * then "rel = relativeLocation(resource, abs)" and vice versa.
474 *
475 * @param type The type of resource.
476 *
477 * @param absPath An absolute path to make relative.
478 *
479 * @return A relative path relative to resource @p type that
480 * will find @p absPath. If no such relative path exists, absPath
481 * will be returned unchanged.
482 */
483 QString relativeLocation(const char *type, const QString &absPath);
484
485 /**
486 * Recursively creates still-missing directories in the given path.
487 *
488 * The resulting permissions will depend on the current umask setting.
489 * permission = mode & ~umask.
490 *
491 * @param dir Absolute path of the directory to be made.
492 * @param mode Directory permissions.
493 * @return true if successful, false otherwise
494 */
495 static bool makeDir(const QString& dir, int mode = 0755);
496
497 /**
498 * This returns a default relative path for the standard KDE
499 * resource types. Below is a list of them so you get an idea
500 * of what this is all about.
501 *
502 * @li data - share/apps
503 * @li html - share/doc/HTML
504 * @li icon - share/icon
505 * @li config - share/config
506 * @li pixmap - share/pixmaps
507 * @li apps - share/applnk
508 * @li sound - share/sounds
509 * @li locale - share/locale
510 * @li services - share/services
511 * @li servicetypes - share/servicetypes
512 * @li mime - share/mimelnk
513 * @li wallpaper - share/wallpapers
514 * @li templates - share/templates
515 * @li exe - bin
516 * @li lib - lib
517 *
518 * @returns Static default for the specified resource. You
519 * should probably be using locate() or locateLocal()
520 * instead.
521 * @see locate()
522 * @see locateLocal()
523 */
524 static QString kde_default(const char *type);
525
526 /**
527 * @internal (for use by sycoca only)
528 */
529 QString kfsstnd_prefixes();
530
531 /**
532 * Returns the toplevel directory in which KStandardDirs
533 * will store things. Most likely $HOME/.kde
534 * Don't use this function if you can use locateLocal
535 * @return the toplevel directory
536 */
537 QString localkdedir() const;
538
539 /**
540 * @return $XDG_DATA_HOME
541 * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html
542 */
543 QString localxdgdatadir() const;
544
545 /**
546 * @return $XDG_CONFIG_HOME
547 * See also http://www.freedesktop.org/standards/basedir/draft/basedir-spec/basedir-spec.html
548 */
549 QString localxdgconfdir() const;
550
551 /**
552 * Checks for existence and accessability.
553 * Faster than creating a QFileInfo first.
554 * @param fullPath the path to check
555 * @return true if the directory exists
556 */
557 static bool exists(const QString &fullPath);
558
559 /**
560 * Expands all symbolic links and resolves references to
561 * '/./', '/../' and extra '/' characters in @p dirname
562 * and returns the canonicalized absolute pathname.
563 * The resulting path will have no symbolic link, '/./'
564 * or '/../' components.
565 * @since 3.1
566 */
567 static QString realPath(const QString &dirname);
568
569 static void setAppDir( const QString & );
570 static QString appDir();
571
572 private:
573
574 QStringList prefixes;
575
576 // Directory dictionaries
577 QDict<QStringList> absolutes;
578 QDict<QStringList> relatives;
579
580 mutable QDict<QStringList> dircache;
581 mutable QDict<QString> savelocations;
582
583 // Disallow assignment and copy-construction
584 KStandardDirs( const KStandardDirs& );
585 KStandardDirs& operator= ( const KStandardDirs& );
586
587 bool addedCustoms;
588
589 class KStandardDirsPrivate;
590 KStandardDirsPrivate *d;
591//US
592 static QString mAppDir;
593
594 void checkConfig() const;
595 void applyDataRestrictions(const QString &) const;
596 //US void createSpecialResource(const char*);
597};
598
599/**
600 * \addtogroup locates Locate Functions
601 * @{
602 * On The Usage Of 'locate' and 'locateLocal'
603 *
604 * Typical KDE applications use resource files in one out of
605 * three ways:
606 *
607 * 1) A resource file is read but is never written. A system
608 * default is supplied but the user can override this
609 * default in his local .kde directory:
610 *
611 * \code
612 * // Code example
613 * myFile = locate("appdata", "groups.lst");
614 * myData = myReadGroups(myFile); // myFile may be null
615 * \endcode
616 *
617 * 2) A resource file is read and written. If the user has no
618 * local version of the file the system default is used.
619 * The resource file is always written to the users local
620 * .kde directory.
621 *
622 * \code
623 * // Code example
624 * myFile = locate("appdata", "groups.lst")
625 * myData = myReadGroups(myFile);
626 * ...
627 * doSomething(myData);
628 * ...
629 * myFile = locateLocal("appdata", "groups.lst");
630 * myWriteGroups(myFile, myData);
631 * \endcode
632 *
633 * 3) A resource file is read and written. No system default
634 * is used if the user has no local version of the file.
635 * The resource file is always written to the users local
636 * .kde directory.
637 *
638 * \code
639 * // Code example
640 * myFile = locateLocal("appdata", "groups.lst");
641 * myData = myReadGroups(myFile);
642 * ...
643 * doSomething(myData);
644 * ...
645 * myFile = locateLocal("appdata", "groups.lst");
646 * myWriteGroups(myFile, myData);
647 * \endcode
648 **/
649
650/*!
651 * \relates KStandardDirs
652 * This function is just for convenience. It simply calls
653 *instance->dirs()->\link KStandardDirs::findResource() findResource\endlink(type, filename).
654 **/
655QString locate( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance()*/ );
656
657/*!
658 * \relates KStandardDirs
659 * This function is much like locate. However it returns a
660 * filename suitable for writing to. No check is made if the
661 * specified filename actually exists. Missing directories
662 * are created. If filename is only a directory, without a
663 * specific file, filename must have a trailing slash.
664 *
665 **/
666QString locateLocal( const char *type, const QString& filename /*US , const KInstance* instance = KGlobal::instance() */ );
667
668/*!
669 * \relates KStandardDirs
670 * This function is much like locate. No check is made if the
671 * specified filename actually exists. Missing directories
672 * are created if @p createDir is true. If filename is only
673 * a directory, without a specific file,
674 * filename must have a trailing slash.
675 *
676 **/
677QString locateLocal( const char *type, const QString& filename, bool createDir /*US , const KInstance* instance = KGlobal::instance() */);
678
679/*! @} */
680
681#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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Ian Zepp (icszepp@islc.net)
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19
20/* AIX needs strings.h for str*casecmp(), and our config.h loads it on AIX
21 So we don't need to include strings.h explicitly */
22
23//US #include "config.h"
24
25#include "kstringhandler.h"
26/*US
27QString KStringHandler::word( const QString &text , uint pos )
28{
29 QStringList list = QStringList::split( " ", text , true );
30
31 if ( pos < list.count() )
32 return list[ pos ];
33
34 return "";
35}
36
37QString KStringHandler::word( const QString &text , const char *range )
38{
39 // Format in: START:END
40 // Note index starts a 0 (zero)
41 //
42 // 0: first word to end
43 // 1:3 second to fourth words
44 QStringList list = QStringList::split( " ", text , true );
45 QString tmp = "";
46 QString r = range;
47
48 if ( text.isEmpty() )
49 return tmp;
50
51 // do stuff here
52 QRegExp reg;
53
54 int at = 0;
55 int pos = 0;
56 int cnt = 0;
57
58 if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 )
59 {
60 at = r.find(":");
61 pos = atoi( r.left(at).ascii() );
62 cnt = atoi( r.remove(0,at+1).ascii() );
63 }
64 else if ( r.find(QRegExp(":+[0-9]+")) != -1 )
65 {
66 at = r.find(":");
67 pos = 0;
68 cnt = atoi( r.remove(0,at+1).ascii() );
69 }
70 else if ( r.find(QRegExp("[0-9]+:+")) != -1 )
71 {
72 at = r.find(":");
73 pos = atoi( r.left(at).ascii() );
74 cnt = list.count(); // zero index
75 }
76 else if ( r.find(QRegExp("[0-9]+")) != -1 )
77 {
78 pos = atoi( r.ascii() );
79 cnt = pos;
80 }
81 else
82 {
83 return tmp; // not found/implemented
84 }
85
86 //
87 // Extract words
88 //
89 int wordsToExtract = cnt-pos+1;
90 QStringList::Iterator it = list.at( pos);
91
92 while ( (it != list.end()) && (wordsToExtract-- > 0))
93 {
94 tmp += *it;
95 tmp += " ";
96 it++;
97 }
98
99 return tmp.stripWhiteSpace();
100}
101
102//
103// Insertion and removal routines
104//
105QString KStringHandler::insword( const QString &text , const QString &word , uint pos )
106{
107 if ( text.isEmpty() )
108 return word;
109
110 if ( word.isEmpty() )
111 return text;
112
113 // Split words and add into list
114 QStringList list = QStringList::split( " ", text, true );
115
116 if ( pos >= list.count() )
117 list.append( word );
118 else
119 list.insert( list.at(pos) , word );
120
121 // Rejoin
122 return list.join( " " );
123}
124
125QString KStringHandler::setword( const QString &text , const QString &word , uint pos )
126{
127 if ( text.isEmpty() )
128 return word;
129
130 if ( word.isEmpty() )
131 return text;
132
133 // Split words and add into list
134 QStringList list = QStringList::split( " ", text, true );
135
136 if ( pos >= list.count() )
137 list.append( word );
138 else
139 {
140 list.insert( list.remove( list.at(pos) ) , word );
141 }
142
143 // Rejoin
144 return list.join( " " );
145}
146
147QString KStringHandler::remrange( const QString &text , const char *range )
148{
149 // Format in: START:END
150 // Note index starts a 0 (zero)
151 //
152 // 0: first word to end
153 // 1:3 second to fourth words
154 QStringList list = QStringList::split( " ", text , true );
155 QString tmp = "";
156 QString r = range;
157
158 if ( text.isEmpty() )
159 return tmp;
160
161 // do stuff here
162 QRegExp reg;
163
164 int at = 0;
165 int pos = 0;
166 int cnt = 0;
167
168 if ( r.find(QRegExp("[0-9]+:[0-9]+")) != -1 )
169 {
170 at = r.find(':');
171 pos = atoi( r.left(at).ascii() );
172 cnt = atoi( r.remove(0,at+1).ascii() );
173 }
174 else if ( r.find(QRegExp(":+[0-9]+")) != -1 )
175 {
176 at = r.find(':');
177 pos = 0;
178 cnt = atoi( r.remove(0,at+1).ascii() );
179 }
180 else if ( r.find(QRegExp("[0-9]+:+")) != -1 )
181 {
182 at = r.find(':');
183 pos = atoi( r.left(at).ascii() );
184 cnt = list.count(); // zero index
185 }
186 else if ( r.find(QRegExp("[0-9]+")) != -1 )
187 {
188 pos = atoi( r.ascii() );
189 cnt = pos;
190 }
191 else
192 {
193 return text; // not found/implemented
194 }
195
196 //
197 // Remove that range of words
198 //
199 int wordsToDelete = cnt-pos+1;
200 QStringList::Iterator it = list.at( pos);
201
202 while ( (it != list.end()) && (wordsToDelete-- > 0))
203 it = list.remove( it );
204
205 return list.join( " " );
206}
207
208QString KStringHandler::remword( const QString &text , uint pos )
209{
210 QString tmp = "";
211
212 if ( text.isEmpty() )
213 return tmp;
214
215 // Split words and add into list
216 QStringList list = QStringList::split( " ", text, true );
217
218 if ( pos < list.count() )
219 list.remove( list.at( pos ) );
220
221 // Rejoin
222 return list.join( " " );
223}
224
225QString KStringHandler::remword( const QString &text , const QString &word )
226{
227 QString tmp = "";
228
229 if ( text.isEmpty() )
230 return tmp;
231
232 if ( word.isEmpty() )
233 return text;
234
235 // Split words and add into list
236 QStringList list = QStringList::split( " ", text, true );
237
238 QStringList::Iterator it = list.find(word);
239
240 if (it != list.end())
241 list.remove( it );
242
243 // Rejoin
244 return list.join( " " );
245}
246
247//
248// Capitalization routines
249//
250QString KStringHandler::capwords( const QString &text )
251{
252 QString tmp = "";
253
254 if ( text.isEmpty() )
255 return tmp;
256
257 QStringList list = QStringList::split( " ", text, true );
258
259 return capwords( QStringList::split( " ", text, true )).join( " " );
260}
261
262QStringList KStringHandler::capwords( const QStringList &list )
263{
264 QStringList tmp;
265 QString word;
266
267 if ( list.count() == 0 )
268 return tmp;
269
270 for ( QStringList::ConstIterator it= list.begin();
271 it != list.end();
272 it++)
273 {
274 word = *it;
275 word = word.left(1).upper() + word.remove(0,1);
276
277 tmp.append( word ); // blank list to start with
278 }
279
280 return tmp;
281}
282
283//
284// Reverse routines
285//
286QString KStringHandler::reverse( const QString &text )
287{
288 QString tmp;
289
290 if ( text.isEmpty() )
291 return tmp;
292
293 QStringList list;
294 list = QStringList::split( " ", text, true );
295 list = reverse( list );
296
297 return list.join( " " );
298}
299
300QStringList KStringHandler::reverse( const QStringList &list )
301{
302 QStringList tmp;
303
304 if ( list.count() == 0 )
305 return tmp;
306
307 for ( QStringList::ConstIterator it= list.begin();
308 it != list.end();
309 it++)
310 tmp.prepend( *it );
311
312 return tmp;
313}
314
315//
316// Left, Right, Center justification
317//
318QString KStringHandler::ljust( const QString &text , uint width )
319{
320 QString tmp = text;
321 tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
322
323 if ( tmp.length() >= width )
324 return tmp;
325
326 for ( uint pos = tmp.length() ; pos < width ; pos++ )
327 tmp.append(" ");
328
329 return tmp;
330}
331
332QString KStringHandler::rjust( const QString &text , uint width )
333{
334 QString tmp = text;
335 tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
336
337 if ( tmp.length() >= width )
338 return tmp;
339
340 for ( uint pos = tmp.length() ; pos < width ; pos++ )
341 tmp.prepend(" ");
342
343 return tmp;
344}
345
346QString KStringHandler::center( const QString &text , uint width )
347{
348 // Center is slightly different, in that it will add
349 // spaces to the RIGHT side (left-justified) before
350 // it adds a space to the LEFT side.
351
352 QString tmp = text;
353 tmp = tmp.stripWhiteSpace(); // remove leading/trailing spaces
354
355 if ( tmp.length() >= width )
356 return tmp;
357
358 bool left = false; // start at right side.
359
360 for ( uint pos = tmp.length() ; pos < width ; pos++ )
361 {
362 if ( left )
363 tmp.prepend(" ");
364 else
365 tmp.append(" ");
366
367 // Reverse bool
368 left = !left;
369 }
370
371 return tmp;
372}
373
374QString KStringHandler::lsqueeze( const QString & str, uint maxlen )
375{
376 if (str.length() > maxlen) {
377 int part = maxlen-3;
378 return QString("..." + str.right(part));
379 }
380 else return str;
381}
382
383QString KStringHandler::csqueeze( const QString & str, uint maxlen )
384{
385 if (str.length() > maxlen && maxlen > 3) {
386 int part = (maxlen-3)/2;
387 return QString(str.left(part) + "..." + str.right(part));
388 }
389 else return str;
390}
391
392QString KStringHandler::rsqueeze( const QString & str, uint maxlen )
393{
394 if (str.length() > maxlen) {
395 int part = maxlen-3;
396 return QString(str.left(part) + "...");
397 }
398 else return str;
399}
400
401QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen)
402{
403 return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
404}
405
406static inline int emSqueezeLimit(int delta, int min, int max)
407{
408 if (delta < min) return min;
409 if (delta > max) return max;
410 return delta;
411}
412
413QString KStringHandler::lPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
414{
415 uint nameWidth = fontMetrics.width(name);
416
417 if (maxPixels < nameWidth)
418 {
419 QString tmp = name;
420 const uint em = fontMetrics.maxWidth();
421 maxPixels -= fontMetrics.width("...");
422
423 while (maxPixels < nameWidth && !tmp.isEmpty())
424 {
425 int delta = (nameWidth - maxPixels) / em;
426 delta = emSqueezeLimit(delta, 1, delta); // no max
427
428 tmp.remove(0, delta);
429 nameWidth = fontMetrics.width(tmp);
430 }
431
432 return ("..." + tmp);
433 }
434
435 return name;
436}
437
438QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
439{
440 return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
441}
442
443QString KStringHandler::cPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
444{
445 uint nameWidth = fontMetrics.width(name);
446
447 if (maxPixels < nameWidth)
448 {
449 QString tmp = name;
450 const uint em = fontMetrics.maxWidth();
451 maxPixels -= fontMetrics.width("...");
452
453 while (maxPixels < nameWidth && !tmp.isEmpty())
454 {
455 int length = tmp.length();
456 int delta = (nameWidth - maxPixels) / em;
457 delta = emSqueezeLimit(delta, 1, length) ;
458
459 tmp.remove((length / 2) - (delta / 2), delta);
460 nameWidth = fontMetrics.width(tmp);
461 }
462
463 return tmp.insert((tmp.length() + 1) / 2, "...");
464 }
465
466 return name;
467}
468
469QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen)
470{
471 return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen);
472}
473
474QString KStringHandler::rPixelSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxPixels)
475{
476 uint nameWidth = fontMetrics.width(name);
477
478 if (maxPixels < nameWidth)
479 {
480 QString tmp = name;
481 const uint em = fontMetrics.maxWidth();
482 maxPixels -= fontMetrics.width("...");
483
484 while (maxPixels < nameWidth && !tmp.isEmpty())
485 {
486 int length = tmp.length();
487 int delta = (nameWidth - maxPixels) / em;
488 delta = emSqueezeLimit(delta, 1, length) ;
489
490 tmp.remove(length - delta, delta);
491 nameWidth = fontMetrics.width(tmp);
492 }
493
494 return (tmp + "...");
495 }
496
497 return name;
498}
499
500///// File name patterns (like *.txt)
501
502bool KStringHandler::matchFileName( const QString& filename, const QString& pattern )
503{
504 int len = filename.length();
505 int pattern_len = pattern.length();
506
507 if (!pattern_len)
508 return false;
509
510 // Patterns like "Makefile*"
511 if ( pattern[ pattern_len - 1 ] == '*' && len + 1 >= pattern_len ) {
512 const QChar *c1 = pattern.unicode();
513 const QChar *c2 = filename.unicode();
514 int cnt = 1;
515 while ( cnt < pattern_len && *c1++ == *c2++ )
516 ++cnt;
517 return cnt == pattern_len;
518 }
519
520 // Patterns like "*~", "*.extension"
521 if ( pattern[ 0 ] == '*' && len + 1 >= pattern_len )
522 {
523 const QChar *c1 = pattern.unicode() + pattern_len - 1;
524 const QChar *c2 = filename.unicode() + len - 1;
525 int cnt = 1;
526 while ( cnt < pattern_len && *c1-- == *c2-- )
527 ++cnt;
528 return cnt == pattern_len;
529 }
530
531 // Patterns like "Makefile"
532 return ( filename == pattern );
533}
534
535 QStringList
536KStringHandler::perlSplit(const QString & sep, const QString & s, uint max)
537{
538 bool ignoreMax = 0 == max;
539
540 QStringList l;
541
542 int searchStart = 0;
543
544 int tokenStart = s.find(sep, searchStart);
545
546 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
547 {
548 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
549 l << s.mid(searchStart, tokenStart - searchStart);
550
551 searchStart = tokenStart + sep.length();
552 tokenStart = s.find(sep, searchStart);
553 }
554
555 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
556 l << s.mid(searchStart, s.length() - searchStart);
557
558 return l;
559}
560
561 QStringList
562KStringHandler::perlSplit(const QChar & sep, const QString & s, uint max)
563{
564 bool ignoreMax = 0 == max;
565
566 QStringList l;
567
568 int searchStart = 0;
569
570 int tokenStart = s.find(sep, searchStart);
571
572 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
573 {
574 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
575 l << s.mid(searchStart, tokenStart - searchStart);
576
577 searchStart = tokenStart + 1;
578 tokenStart = s.find(sep, searchStart);
579 }
580
581 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
582 l << s.mid(searchStart, s.length() - searchStart);
583
584 return l;
585}
586
587 QStringList
588KStringHandler::perlSplit(const QRegExp & sep, const QString & s, uint max)
589{
590 bool ignoreMax = 0 == max;
591
592 QStringList l;
593
594 int searchStart = 0;
595 int tokenStart = sep.search(s, searchStart);
596 int len = sep.matchedLength();
597
598 while (-1 != tokenStart && (ignoreMax || l.count() < max - 1))
599 {
600 if (!s.mid(searchStart, tokenStart - searchStart).isEmpty())
601 l << s.mid(searchStart, tokenStart - searchStart);
602
603 searchStart = tokenStart + len;
604 tokenStart = sep.search(s, searchStart);
605 len = sep.matchedLength();
606 }
607
608 if (!s.mid(searchStart, s.length() - searchStart).isEmpty())
609 l << s.mid(searchStart, s.length() - searchStart);
610
611 return l;
612}
613US end */
614
615/*US
616 QString
617KStringHandler::tagURLs( const QString& text )
618{
619 QRegExp urlEx("(www\\.(?!\\.)|(f|ht)tp(|s)://)[\\d\\w\\./,:_~\\?=&;#@\\-\\+\\%]+[\\d\\w/]");
620
621 QString richText( text );
622 int urlPos = 0, urlLen;
623 while ((urlPos = urlEx.search(richText, urlPos)) >= 0)
624 {
625 urlLen = urlEx.matchedLength();
626 QString href = richText.mid( urlPos, urlLen );
627 // Qt doesn't support (?<=pattern) so we do it here
628 if((urlPos > 0) && richText[urlPos-1].isLetterOrNumber()){
629 urlPos++;
630 continue;
631 }
632 // Don't use QString::arg since %01, %20, etc could be in the string
633 QString anchor = "<a href=\"" + href + "\">" + href + "</a>";
634 richText.replace( urlPos, urlLen, anchor );
635
636
637 urlPos += anchor.length();
638 }
639 return richText;
640}
641*/
642QString KStringHandler::obscure( const QString &str )
643{
644 QString result;
645 for ( uint i = 0; i < str.length(); ++i )
646 result += ( str.at( i ).unicode() < 0x20 ) ? str.at( i ) :
647 QChar( 0x1001F - str.at( i ).unicode() );
648
649 return result;
650}
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1999 Ian Zepp (icszepp@islc.net)
3 Copyright (C) 2000 Rik Hemsley (rikkus) <rik@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18*/
19#ifndef KSTRINGHANDLER_H
20#define KSTRINGHANDLER_H
21
22#include <stdlib.h> // for atoi()
23#include <qstring.h>
24#include <qstringlist.h>
25#include <qregexp.h> // for the word ranges
26#include <qfontmetrics.h>
27
28/**
29 * This class contains utility functions for handling strings.
30 *
31 * This class is @em not a substitute for the @ref QString class. What
32 * I tried to do with this class is provide an easy way to
33 * cut/slice/splice words inside sentences in whatever order desired.
34 * While the main focus of this class are words (ie characters
35 * separated by spaces/tabs), the two core functions here (@ref split()
36 * and @ref join() ) will function given any char to use as a separator.
37 * This will make it easy to redefine what a 'word' means in the
38 * future if needed.
39 *
40 * I freely stole some of the function names from python. I also think
41 * some of these were influenced by mIRC (yes, believe it if you will, I
42 * used to write a LOT of scripts in mIRC).
43 *
44 * The ranges are a fairly powerful way of getting/stripping words from
45 * a string. These ranges function, for the large part, as they would in
46 * python. See the @ref word(const QString&, int) and @ref remword(const QString&, int) functions for more detail.
47 *
48 * This class contains no data members of it own. All strings are cut
49 * on the fly and returned as new qstrings/qstringlists.
50 *
51 * Quick example on how to use:
52 *
53 * <pre>
54 * KStringHandler kstr;
55 * QString line = "This is a test of the strings";
56 *
57 * cout << "1> " << kstr.word( line , "4:" ) << "\n";
58 * cout << "2> " << kstr.remrange( line , "2:5" ) << "\n";
59 * cout << "2> " << kstr.reverse( line ) << "\n";
60 * cout << "2> " << kstr.center( kstr.word( line , 4 ) , 15 ) << "\n";
61 * </pre>
62 *
63 * and so forth.
64 *
65 * @short Class for manipulating words and sentences in strings
66 * @author Ian Zepp <icszepp@islc.net>
67 */
68class KStringHandler
69{
70public:
71 /** Returns the nth word in the string if found
72 * Returns a EMPTY (not null) string otherwise.
73 * Note that the FIRST index is 0.
74 * @param text the string to search for the words
75 * @param pos the position of the word to search
76 * @return the word, or an empty string if not found
77 */
78//US static QString word( const QString &text , uint pos );
79
80 /** Returns a range of words from that string.
81 * Ie:
82 * @li "0" returns the very first word
83 * @li "0:" returns the first to the last word
84 * @li "0:3" returns the first to fourth words
85 * @li ":3" returns everything up to the fourth word
86 *
87 * If you grok python, you're set.
88 * @param text the string to search for the words
89 * @param range the words to return (see description)
90 * @return the words, or an empty string if not found
91 */
92//US static QString word( const QString &text , const char *range );
93
94 /** Inserts a word into the string, and returns
95 * a new string with the word included. the first
96 * index is zero (0). If there are not @p pos words in the original
97 * string, the new word will be appended to the end.
98 * @param text the original text
99 * @param word the word to insert
100 * @param pos the position (in words) for the new word
101 * @return the resulting string
102 */
103//US static QString insword( const QString &text , const QString &word , uint pos );
104
105 /** Replaces a word in the string, and returns
106 * a new string with the word included. the first
107 * index is zero (0). If there are not @p pos words in the original
108 * string, the new word will be appended to the end.
109 * @param text the original text
110 * @param word the word to insert
111 * @param pos the position (in words) for the new word
112 * @return the resulting string
113 */
114//US static QString setword( const QString &text , const QString &word , uint pos );
115
116 /** Removes a word or ranges of words from the string,
117 * and returns a new string. The ranges definitions
118 * follow the definitions for the word() function.
119 *
120 * @li "0" removes the very first word
121 * @li "0:" removes the first the the last word
122 * @li "0:3" removes the first to fourth words
123 * @li ":3" removes everything up to the fourth word
124 * @param text the original text
125 * @param range the words to remove (see description)
126 * @return the resulting string
127 */
128//US static QString remrange( const QString &text , const char *range );
129
130
131 /** Removes a word at the given index, and returns a
132 * new string. The first index is zero (0).
133 * @param text the original text
134 * @param pos the position (in words) of thw word to delete
135 * @return the resulting string
136 */
137//US static QString remword( const QString &text , uint pos );
138
139 /** Removes a matching word from the string, and returns
140 * a new string. Note that only ONE match is removed.
141 * @param text the original text
142 * @param word the word to remove
143 * @return the resulting string
144 */
145//US static QString remword( const QString &text , const QString &word );
146
147 /** Capitalizes each word in the string
148 * "hello there" becomes "Hello There" (string)
149 * @param text the text to capitalize
150 * @return the resulting string
151 */
152//US static QString capwords( const QString &text );
153
154 /** Capitalizes each word in the list
155 * [hello, there] becomes [Hello, There] (list)
156 * @param list the list to capitalize
157 * @return the resulting list
158 */
159//US static QStringList capwords( const QStringList &list );
160
161 /** Reverses the order of the words in a string
162 * "hello there" becomes "there hello" (string)
163 * @param text the text to reverse
164 * @return the resulting string
165 */
166//US static QString reverse( const QString &text );
167
168 /** Reverses the order of the words in a list
169 * [hello, there] becomes [there, hello] (list)
170 * @param list the list to reverse
171 * @return the resulting list
172 */
173//US static QStringList reverse( const QStringList &list );
174
175 /** Left-justifies a string and returns a string at least 'width' characters
176 * wide.
177 * If the string is longer than the @p width, the original
178 * string is returned. It is never truncated.
179 * @param text the text to justify
180 * @param width the desired width of the new string
181 * @return the resulting string
182 */
183//US static QString ljust( const QString &text , uint width );
184
185 /** Right-justifies a string and returns a string at least 'width' characters
186 * wide.
187 * If the string is longer than the @p width, the original
188 * string is returned. It is never truncated.
189 * @param text the text to justify
190 * @param width the desired width of the new string
191 * @return the resulting string
192 */
193//US static QString rjust( const QString &text , uint width );
194
195 /** Centers a string and returns a string at least 'width' characters
196 * wide.
197 * If the string is longer than the @p width, the original
198 * string is returned. It is never truncated.
199 * @param text the text to justify
200 * @param width the desired width of the new string
201 * @return the resulting string
202 */
203//US static QString center( const QString &text , uint width );
204
205 /** Substitute characters at the beginning of a string by "...".
206 * @param str is the string to modify
207 * @param maxlen is the maximum length the modified string will have
208 * If the original string is shorter than "maxlen", it is returned verbatim
209 * @return the modified string
210 */
211//US static QString lsqueeze( const QString & str, uint maxlen = 40 );
212
213 /** Substitute characters at the beginning of a string by "...". Similar to
214 * method above, except that it truncates based on pixel width rather than
215 * the number of characters
216 * @param name is the string to modify
217 * @param fontMetrics is the font metrics to use to calculate character sizes
218 * @param maxlen is the maximum length in ems the modified string will have
219 * If the original string is shorter than "maxlen", it is returned verbatim
220 * @return the modified string
221 * @since 3.2
222 */
223//US static QString lEmSqueeze( const QString & name,
224//US const QFontMetrics& fontMetrics,
225//US uint maxlen = 30 );
226
227 /** Substitute characters at the beginning of a string by "...". Similar to
228 * method above, except that maxlen is the width in pixels to truncate to
229 * @param name is the string to modify
230 * @param fontMetrics is the font metrics to use to calculate character sizes
231 * @param maxPixels is the maximum pixel length the modified string will have
232 * If the original string is shorter than "maxlen", it is returned verbatim
233 * @return the modified string
234 * @since 3.2
235 */
236//US static QString lPixelSqueeze( const QString & name,
237//US const QFontMetrics& fontMetrics,
238//US uint maxPixels );
239
240 /** Substitute characters at the middle of a string by "...".
241 * @param str is the string to modify
242 * @param maxlen is the maximum length the modified string will have
243 * If the original string is shorter than "maxlen", it is returned verbatim
244 * @return the modified string
245 */
246//US static QString csqueeze( const QString & str, uint maxlen = 40 );
247
248 /** Substitute characters in the middle of a string by "...". Similar to
249 * method above, except that it truncates based on pixel width rather than
250 * the number of characters
251 * @param name is the string to modify
252 * @param fontMetrics is the font metrics to use to calculate character sizes
253 * @param maxlen is the maximum length in ems the modified string will have
254 * If the original string is shorter than "maxlen", it is returned verbatim
255 * @return the modified string
256 * @since 3.2
257 */
258//US static QString cEmSqueeze( const QString & name,
259//US const QFontMetrics& fontMetrics,
260//US uint maxlen = 30 );
261
262 /** Substitute characters in the middle of a string by "...". Similar to
263 * method above, except that maxlen is the width in pixels to truncate to
264 * @param name is the string to modify
265 * @param fontMetrics is the font metrics to use to calculate character sizes
266 * @param maxPixels is the maximum pixel length the modified string will have
267 * If the original string is shorter than "maxlen", it is returned verbatim
268 * @return the modified string
269 * @since 3.2
270 */
271//US static QString cPixelSqueeze( const QString & name,
272//US const QFontMetrics& fontMetrics,
273//US uint maxPixels );
274
275 /** Substitute characters at the end of a string by "...".
276 * @param str is the string to modify
277 * @param maxlen is the maximum length the modified string will have
278 * If the original string is shorter than "maxlen", it is returned verbatim
279 * @return the modified string
280 */
281 static QString rsqueeze( const QString & str, uint maxlen = 40 );
282
283 /** Substitute characters at the end of a string by "...". Similar to
284 * method above, except that it truncates based on pixel width rather than
285 * the number of characters
286 * @param name is the string to modify
287 * @param fontMetrics is the font metrics to use to calculate character sizes
288 * @param maxlen is the maximum length in ems the modified string will have
289 * If the original string is shorter than "maxlen", it is returned verbatim
290 * @return the modified string
291 * @since 3.2
292 */
293//US static QString rEmSqueeze( const QString & name,
294//US const QFontMetrics& fontMetrics,
295//US uint maxlen = 30 );
296
297 /** Substitute characters at the end of a string by "...". Similar to
298 * method above, except that maxlen is the width in pixels to truncate to
299 * @param name is the string to modify
300 * @param fontMetrics is the font metrics to use to calculate character sizes
301 * @param maxPixels is the maximum pixel length the modified string will have
302 * If the original string is shorter than "maxlen", it is returned verbatim
303 * @return the modified string
304 * @since 3.2
305 */
306//US static QString rPixelSqueeze( const QString & name,
307//US const QFontMetrics& fontMetrics,
308//US uint maxPixels );
309
310 /**
311 * Match a filename.
312 * @param filename is the real decoded filename (or dirname
313 * without trailing '/').
314 * @param pattern is a pattern like *.txt, *.tar.gz, Makefile.*, etc.
315 * Patterns with two asterisks like "*.*pk" are not supported.
316 * @return true if the given filename matches the given pattern
317 */
318//US static bool matchFileName( const QString& filename, const QString& pattern );
319
320 /**
321 * Split a QString into a QStringList in a similar fashion to the static
322 * QStringList function in Qt, except you can specify a maximum number
323 * of tokens. If max is specified (!= 0) then only that number of tokens
324 * will be extracted. The final token will be the remainder of the string.
325 *
326 * Example:
327 * <pre>
328 * perlSplit("__", "some__string__for__you__here", 4)
329 * QStringList contains: "some", "string", "for", "you__here"
330 * </pre>
331 *
332 * @param sep is the string to use to delimit s.
333 * @param s is the input string
334 * @param max is the maximum number of extractions to perform, or 0.
335 * @return A QStringList containing tokens extracted from s.
336 */
337//US static QStringList perlSplit
338//US (const QString & sep, const QString & s, uint max = 0);
339
340 /**
341 * Split a QString into a QStringList in a similar fashion to the static
342 * QStringList function in Qt, except you can specify a maximum number
343 * of tokens. If max is specified (!= 0) then only that number of tokens
344 * will be extracted. The final token will be the remainder of the string.
345 *
346 * Example:
347 * <pre>
348 * perlSplit(' ', "kparts reaches the parts other parts can't", 3)
349 * QStringList contains: "kparts", "reaches", "the parts other parts can't"
350 * </pre>
351 *
352 * @param sep is the character to use to delimit s.
353 * @param s is the input string
354 * @param max is the maximum number of extractions to perform, or 0.
355 * @return A QStringList containing tokens extracted from s.
356 */
357//US static QStringList perlSplit
358//US (const QChar & sep, const QString & s, uint max = 0);
359
360 /**
361 * Split a QString into a QStringList in a similar fashion to the static
362 * QStringList function in Qt, except you can specify a maximum number
363 * of tokens. If max is specified (!= 0) then only that number of tokens
364 * will be extracted. The final token will be the remainder of the string.
365 *
366 * Example:
367 * <pre>
368 * perlSplit(QRegExp("[! ]", "Split me up ! I'm bored ! OK ?", 3)
369 * QStringList contains: "Split", "me", "up ! I'm bored, OK ?"
370 * </pre>
371 *
372 * @param sep is the regular expression to use to delimit s.
373 * @param s is the input string
374 * @param max is the maximum number of extractions to perform, or 0.
375 * @return A QStringList containing tokens extracted from s.
376 */
377//US static QStringList perlSplit
378//US (const QRegExp & sep, const QString & s, uint max = 0);
379
380 /**
381 * This method auto-detects URLs in strings, and adds HTML markup to them
382 * so that richtext or HTML-enabled widgets (such as KActiveLabel)
383 * will display the URL correctly.
384 * @param text the string which may contain URLs
385 * @return the resulting text
386 * @since 3.1
387 */
388//US static QString tagURLs( const QString& text );
389
390 /**
391 Obscure string by using a simple symmetric encryption. Applying the
392 function to a string obscured by this function will result in the original
393 string.
394
395 The function can be used to obscure passwords stored to configuration
396 files. Note that this won't give you any more security than preventing
397 that the password is directly copied and pasted.
398
399 @param str string to be obscured
400 @return obscured string
401 @since 3.2
402 */
403 static QString obscure( const QString &str );
404
405#ifdef KDE_NO_COMPAT
406private:
407#endif
408 /**
409 * @deprecated Use @see matchFileName () instead.
410 */
411/*US static bool matchFilename( const QString& filename, const QString& pattern )
412 {
413 return matchFileName (filename, pattern);
414 };
415*/
416};
417#endif