-rw-r--r-- | microkde/kdecore/kcatalogue.cpp | 131 | ||||
-rw-r--r-- | microkde/kdecore/kcatalogue.h | 104 | ||||
-rw-r--r-- | microkde/kdecore/kconfigbase.h | 102 | ||||
-rw-r--r-- | microkde/kdecore/klibloader.cpp | 626 | ||||
-rw-r--r-- | microkde/kdecore/klibloader.h | 405 | ||||
-rw-r--r-- | microkde/kdecore/klocale.cpp | 881 | ||||
-rw-r--r-- | microkde/kdecore/klocale.h | 110 | ||||
-rw-r--r-- | microkde/kdecore/klocale_new.cpp | 2441 | ||||
-rw-r--r-- | microkde/kdecore/klocale_new.h | 1224 | ||||
-rw-r--r-- | microkde/kdecore/kmdcodec.cpp | 1127 | ||||
-rw-r--r-- | microkde/kdecore/kmdcodec.h | 572 | ||||
-rw-r--r-- | microkde/kdecore/ksharedptr.h | 171 | ||||
-rw-r--r-- | microkde/kdecore/kshell.cpp | 386 | ||||
-rw-r--r-- | microkde/kdecore/kshell.h | 143 | ||||
-rw-r--r-- | microkde/kdecore/kshortcut.h | 846 | ||||
-rw-r--r-- | microkde/kdecore/kstandarddirs.cpp | 1620 | ||||
-rw-r--r-- | microkde/kdecore/kstandarddirs.h | 681 | ||||
-rw-r--r-- | microkde/kdecore/kstringhandler.cpp | 650 | ||||
-rw-r--r-- | microkde/kdecore/kstringhandler.h | 417 |
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 | |||
28 | char *k_nl_find_msg(struct kde_loaded_l10nfile *domain_file, | ||
29 | const char *msgid); | ||
30 | void k_nl_unload_domain (struct loaded_domain *domain); | ||
31 | |||
32 | #ifndef KDE_USE_FINAL // with --enable-final, we're getting this from libintl.cpp | ||
33 | struct 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 | |||
44 | class KCataloguePrivate | ||
45 | { | ||
46 | public: | ||
47 | QString name; | ||
48 | |||
49 | kde_loaded_l10nfile domain; | ||
50 | }; | ||
51 | |||
52 | KCatalogue::KCatalogue(const QString & name) | ||
53 | : d( new KCataloguePrivate ) | ||
54 | { | ||
55 | d->name = name; | ||
56 | } | ||
57 | |||
58 | KCatalogue::KCatalogue(const KCatalogue & rhs) | ||
59 | : d( new KCataloguePrivate ) | ||
60 | { | ||
61 | *this = rhs; | ||
62 | } | ||
63 | |||
64 | KCatalogue & KCatalogue::operator=(const KCatalogue & rhs) | ||
65 | { | ||
66 | d->name = rhs.d->name; | ||
67 | setFileName( rhs.fileName() ); | ||
68 | |||
69 | return *this; | ||
70 | } | ||
71 | |||
72 | KCatalogue::~KCatalogue() | ||
73 | { | ||
74 | doUnload(); | ||
75 | |||
76 | delete d; | ||
77 | } | ||
78 | |||
79 | QString KCatalogue::name() const | ||
80 | { | ||
81 | return d->name; | ||
82 | } | ||
83 | |||
84 | void 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 | |||
102 | QString KCatalogue::fileName() const | ||
103 | { | ||
104 | return QFile::decodeName( d->domain.filename ); | ||
105 | } | ||
106 | |||
107 | const 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 | |||
115 | void 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 | |||
25 | struct kde_loaded_l10nfile; | ||
26 | |||
27 | class 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 | ||
36 | class KCatalogue | ||
37 | { | ||
38 | public: | ||
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 | |||
87 | private: | ||
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 | |||
100 | private: | ||
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 | |||
64 | class KConfigGroupSaver | ||
65 | { | ||
66 | public: | ||
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 | |||
93 | private: | ||
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 | */ | ||
47 | template class QAsciiDict<KLibrary>; | ||
48 | |||
49 | #include <stdlib.h> //getenv | ||
50 | |||
51 | /*US | ||
52 | #if HAVE_DLFCN_H | ||
53 | # include <dlfcn.h> | ||
54 | #endif | ||
55 | |||
56 | #ifdef RTLD_GLOBAL | ||
57 | # define LT_GLOBAL RTLD_GLOBAL | ||
58 | #else | ||
59 | # ifdef DL_GLOBAL | ||
60 | # define LT_GLOBAL DL_GLOBAL | ||
61 | # endif | ||
62 | #endif | ||
63 | #ifndef LT_GLOBAL | ||
64 | # define LT_GLOBAL 0 | ||
65 | #endif | ||
66 | */ | ||
67 | |||
68 | /*US | ||
69 | extern "C" { | ||
70 | extern int lt_dlopen_flag; | ||
71 | } | ||
72 | */ | ||
73 | |||
74 | KLibFactory::KLibFactory( QObject* parent, const char* name ) | ||
75 | : QObject( parent, name ) | ||
76 | { | ||
77 | } | ||
78 | |||
79 | KLibFactory::~KLibFactory() | ||
80 | { | ||
81 | // kdDebug(150) << "Deleting KLibFactory " << this << endl; | ||
82 | } | ||
83 | |||
84 | QObject* KLibFactory::create( QObject* parent, const char* name, const char* classname, const QStringList &args ) | ||
85 | { | ||
86 | QObject* obj = createObject( parent, name, classname, args ); | ||
87 | if ( obj ) | ||
88 | emit objectCreated( obj ); | ||
89 | return obj; | ||
90 | } | ||
91 | |||
92 | |||
93 | QObject* KLibFactory::createObject( QObject*, const char*, const char*, const QStringList &) | ||
94 | { | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | |||
99 | // ----------------------------------------------- | ||
100 | |||
101 | //US KLibrary::KLibrary( const QString& libname, const QString& filename, void * handle ) | ||
102 | KLibrary::KLibrary( const QString& libname, const QString& filename, QLibrary* handle ) | ||
103 | { | ||
104 | /* Make sure, we have a KLibLoader */ | ||
105 | (void) KLibLoader::self(); | ||
106 | m_libname = libname; | ||
107 | m_filename = filename; | ||
108 | m_handle = handle; | ||
109 | m_factory = 0; | ||
110 | m_timer = 0; | ||
111 | } | ||
112 | |||
113 | KLibrary::~KLibrary() | ||
114 | { | ||
115 | // kdDebug(150) << "Deleting KLibrary " << this << " " << m_libname << endl; | ||
116 | if ( m_timer && m_timer->isActive() ) | ||
117 | m_timer->stop(); | ||
118 | |||
119 | // If any object is remaining, delete | ||
120 | if ( m_objs.count() > 0 ) | ||
121 | { | ||
122 | QPtrListIterator<QObject> it( m_objs ); | ||
123 | for ( ; it.current() ; ++it ) | ||
124 | { | ||
125 | kdDebug(150) << "Factory still has object " << it.current() << " " << it.current()->name () << " Library = " << m_libname << endl; | ||
126 | disconnect( it.current(), SIGNAL( destroyed() ), | ||
127 | this, SLOT( slotObjectDestroyed() ) ); | ||
128 | } | ||
129 | m_objs.setAutoDelete(true); | ||
130 | m_objs.clear(); | ||
131 | } | ||
132 | |||
133 | if ( m_factory ) { | ||
134 | //kdDebug(150) << " ... deleting the factory " << m_factory << endl; | ||
135 | delete m_factory; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | QString KLibrary::name() const | ||
140 | { | ||
141 | return m_libname; | ||
142 | } | ||
143 | |||
144 | QString KLibrary::fileName() const | ||
145 | { | ||
146 | return m_filename; | ||
147 | } | ||
148 | |||
149 | KLibFactory* KLibrary::factory() | ||
150 | { | ||
151 | if ( m_factory ) | ||
152 | return m_factory; | ||
153 | |||
154 | QCString symname; | ||
155 | symname.sprintf("init_%s", name().latin1() ); | ||
156 | |||
157 | void* sym = symbol( symname ); | ||
158 | if ( !sym ) | ||
159 | { | ||
160 | kdWarning(150) << "KLibrary: The library " << name() << " does not offer an init_" << name() << " function" << endl; | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | typedef KLibFactory* (*t_func)(); | ||
165 | t_func func = (t_func)sym; | ||
166 | m_factory = func(); | ||
167 | |||
168 | if( !m_factory ) | ||
169 | { | ||
170 | kdWarning(150) << "KLibrary: The library " << name() << " does not offer a KDE compatible factory" << endl; | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | connect( m_factory, SIGNAL( objectCreated( QObject * ) ), | ||
175 | this, SLOT( slotObjectCreated( QObject * ) ) ); | ||
176 | |||
177 | return m_factory; | ||
178 | } | ||
179 | |||
180 | void* KLibrary::symbol( const char* symname ) const | ||
181 | { | ||
182 | //US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); | ||
183 | void* sym = m_handle->resolve( symname ); | ||
184 | if ( !sym ) | ||
185 | { | ||
186 | //US kdWarning(150) << "KLibrary: " << lt_dlerror() << endl; | ||
187 | kdWarning(150) << "KLibrary: " << m_libname << ", symbol:" << symname << " not found " << endl; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | return sym; | ||
192 | } | ||
193 | |||
194 | bool KLibrary::hasSymbol( const char* symname ) const | ||
195 | { | ||
196 | //US void* sym = lt_dlsym( (lt_dlhandle) m_handle, symname ); | ||
197 | void* sym = m_handle->resolve( symname ); | ||
198 | return (sym != 0L ); | ||
199 | } | ||
200 | |||
201 | void KLibrary::unload() const | ||
202 | { | ||
203 | if (KLibLoader::s_self) | ||
204 | KLibLoader::s_self->unloadLibrary(QFile::encodeName(name())); | ||
205 | } | ||
206 | |||
207 | void KLibrary::slotObjectCreated( QObject *obj ) | ||
208 | { | ||
209 | if ( !obj ) | ||
210 | return; | ||
211 | |||
212 | if ( m_timer && m_timer->isActive() ) | ||
213 | m_timer->stop(); | ||
214 | |||
215 | if ( m_objs.containsRef( obj ) ) | ||
216 | return; // we know this object already | ||
217 | |||
218 | connect( obj, SIGNAL( destroyed() ), | ||
219 | this, SLOT( slotObjectDestroyed() ) ); | ||
220 | |||
221 | m_objs.append( obj ); | ||
222 | } | ||
223 | |||
224 | void KLibrary::slotObjectDestroyed() | ||
225 | { | ||
226 | m_objs.removeRef( sender() ); | ||
227 | |||
228 | if ( m_objs.count() == 0 ) | ||
229 | { | ||
230 | // kdDebug(150) << "KLibrary: shutdown timer for " << name() << " started!" | ||
231 | // << endl; | ||
232 | |||
233 | if ( !m_timer ) | ||
234 | { | ||
235 | m_timer = new QTimer( this, "klibrary_shutdown_timer" ); | ||
236 | connect( m_timer, SIGNAL( timeout() ), | ||
237 | this, SLOT( slotTimeout() ) ); | ||
238 | } | ||
239 | |||
240 | // as long as it's not stable make the timeout short, for debugging | ||
241 | // pleasure (matz) | ||
242 | //m_timer->start( 1000*60, true ); | ||
243 | m_timer->start( 1000*10, true ); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | void KLibrary::slotTimeout() | ||
248 | { | ||
249 | if ( m_objs.count() != 0 ) | ||
250 | return; | ||
251 | |||
252 | /* Don't go through KLibLoader::unloadLibrary(), because that uses the | ||
253 | ref counter, but this timeout means to unconditionally close this library | ||
254 | The destroyed() signal will take care to remove us from all lists. | ||
255 | */ | ||
256 | delete this; | ||
257 | } | ||
258 | |||
259 | // ------------------------------------------------- | ||
260 | |||
261 | /* This helper class is needed, because KLibraries can go away without | ||
262 | being unloaded. So we need some info about KLibraries even after its | ||
263 | death. */ | ||
264 | class KLibWrapPrivate | ||
265 | { | ||
266 | public: | ||
267 | //US KLibWrapPrivate(KLibrary *l, lt_dlhandle h); | ||
268 | KLibWrapPrivate(KLibrary *l, QLibrary* h); | ||
269 | |||
270 | KLibrary *lib; | ||
271 | enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; | ||
272 | int ref_count; | ||
273 | //US lt_dlhandle handle; | ||
274 | QLibrary *handle; | ||
275 | QString name; | ||
276 | QString filename; | ||
277 | }; | ||
278 | |||
279 | //US KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, lt_dlhandle h) | ||
280 | KLibWrapPrivate::KLibWrapPrivate(KLibrary *l, QLibrary* h) | ||
281 | : lib(l), ref_count(1), handle(h), name(l->name()), filename(l->fileName()) | ||
282 | { | ||
283 | unload_mode = UNKNOWN; | ||
284 | /*US | ||
285 | if (lt_dlsym(handle, "__kde_do_not_unload") != 0) { | ||
286 | // kdDebug(150) << "Will not unload " << name << endl; | ||
287 | unload_mode = DONT_UNLOAD; | ||
288 | } else if (lt_dlsym(handle, "__kde_do_unload") != 0) { | ||
289 | unload_mode = UNLOAD; | ||
290 | } | ||
291 | */ | ||
292 | //US use instead: | ||
293 | if (h->resolve("__kde_do_not_unload") != 0) { | ||
294 | // kdDebug(150) << "Will not unload " << name << endl; | ||
295 | unload_mode = DONT_UNLOAD; | ||
296 | } else if (h->resolve("__kde_do_unload") != 0) { | ||
297 | unload_mode = UNLOAD; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | class KLibLoaderPrivate | ||
302 | { | ||
303 | public: | ||
304 | QPtrList<KLibWrapPrivate> loaded_stack; | ||
305 | QPtrList<KLibWrapPrivate> pending_close; | ||
306 | enum {UNKNOWN, UNLOAD, DONT_UNLOAD} unload_mode; | ||
307 | |||
308 | QString errorMessage; | ||
309 | }; | ||
310 | |||
311 | KLibLoader* KLibLoader::s_self = 0; | ||
312 | |||
313 | KLibLoader* KLibLoader::self() | ||
314 | { | ||
315 | if ( !s_self ) | ||
316 | s_self = new KLibLoader; | ||
317 | return s_self; | ||
318 | } | ||
319 | |||
320 | void KLibLoader::cleanUp() | ||
321 | { | ||
322 | if ( !s_self ) | ||
323 | return; | ||
324 | |||
325 | delete s_self; | ||
326 | s_self = 0; | ||
327 | } | ||
328 | |||
329 | KLibLoader::KLibLoader( QObject* parent, const char* name ) | ||
330 | : QObject( parent, name ) | ||
331 | { | ||
332 | s_self = this; | ||
333 | d = new KLibLoaderPrivate; | ||
334 | //US lt_dlinit(); | ||
335 | d->unload_mode = KLibLoaderPrivate::UNKNOWN; | ||
336 | if (getenv("KDE_NOUNLOAD") != 0) | ||
337 | d->unload_mode = KLibLoaderPrivate::DONT_UNLOAD; | ||
338 | else if (getenv("KDE_DOUNLOAD") != 0) | ||
339 | d->unload_mode = KLibLoaderPrivate::UNLOAD; | ||
340 | d->loaded_stack.setAutoDelete( true ); | ||
341 | } | ||
342 | |||
343 | KLibLoader::~KLibLoader() | ||
344 | { | ||
345 | // kdDebug(150) << "Deleting KLibLoader " << this << " " << name() << endl; | ||
346 | |||
347 | QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); | ||
348 | for (; it.current(); ++it ) | ||
349 | { | ||
350 | kdDebug(150) << "The KLibLoader contains the library " << it.current()->name | ||
351 | << " (" << it.current()->lib << ")" << endl; | ||
352 | d->pending_close.append(it.current()); | ||
353 | } | ||
354 | |||
355 | close_pending(0); | ||
356 | |||
357 | delete d; | ||
358 | } | ||
359 | |||
360 | //static | ||
361 | QString KLibLoader::findLibrary( const char * name/*US , const KInstance * instance*/ ) | ||
362 | { | ||
363 | QCString libname( name ); | ||
364 | |||
365 | // only append ".la" if there is no extension | ||
366 | // this allows to load non-libtool libraries as well | ||
367 | // (mhk, 20000228) | ||
368 | int pos = libname.findRev('/'); | ||
369 | if (pos < 0) | ||
370 | pos = 0; | ||
371 | if (libname.find('.', pos) < 0) | ||
372 | libname += ".la"; | ||
373 | |||
374 | // only look up the file if it is not an absolute filename | ||
375 | // (mhk, 20000228) | ||
376 | QString libfile; | ||
377 | if (libname[0] == '/') | ||
378 | libfile = libname; | ||
379 | else | ||
380 | { | ||
381 | //US libfile = instance->dirs()->findResource( "module", libname ); | ||
382 | libfile = KGlobal::dirs()->findResource( "module", libname ); | ||
383 | if ( libfile.isEmpty() ) | ||
384 | { | ||
385 | //US libfile = instance->dirs()->findResource( "lib", libname ); | ||
386 | libfile = KGlobal::dirs()->findResource( "lib", libname ); | ||
387 | #ifndef NDEBUG | ||
388 | if ( !libfile.isEmpty() && libname.left(3) == "lib" ) // don't warn for kdeinit modules | ||
389 | kdDebug(150) << "library " << libname << " not found under 'module' but under 'lib'" << endl; | ||
390 | #endif | ||
391 | } | ||
392 | if ( libfile.isEmpty() ) | ||
393 | { | ||
394 | #ifndef NDEBUG | ||
395 | kdDebug(150) << "library=" << libname << ": No file names " << libname.data() << " found in paths." << endl; | ||
396 | #endif | ||
397 | self()->d->errorMessage = i18n("Library files for \"%1\" not found in paths").arg(libname); | ||
398 | } | ||
399 | else | ||
400 | self()->d->errorMessage = QString::null; | ||
401 | } | ||
402 | return libfile; | ||
403 | } | ||
404 | |||
405 | |||
406 | KLibrary* KLibLoader::globalLibrary( const char *name ) | ||
407 | { | ||
408 | KLibrary *tmp; | ||
409 | /*US | ||
410 | int olt_dlopen_flag = lt_dlopen_flag; | ||
411 | |||
412 | lt_dlopen_flag |= LT_GLOBAL; | ||
413 | kdDebug(150) << "Loading the next library global with flag " | ||
414 | << lt_dlopen_flag | ||
415 | << "." << endl; | ||
416 | */ | ||
417 | tmp = library(name); | ||
418 | /*US | ||
419 | lt_dlopen_flag = olt_dlopen_flag; | ||
420 | */ | ||
421 | return tmp; | ||
422 | } | ||
423 | |||
424 | |||
425 | KLibrary* KLibLoader::library( const char *name ) | ||
426 | { | ||
427 | if (!name) | ||
428 | return 0; | ||
429 | |||
430 | KLibWrapPrivate* wrap = m_libs[name]; | ||
431 | if (wrap) { | ||
432 | /* Nothing to do to load the library. */ | ||
433 | wrap->ref_count++; | ||
434 | return wrap->lib; | ||
435 | } | ||
436 | |||
437 | /* Test if this library was loaded at some time, but got | ||
438 | unloaded meanwhile, whithout being dlclose()'ed. */ | ||
439 | QPtrListIterator<KLibWrapPrivate> it(d->loaded_stack); | ||
440 | for (; it.current(); ++it) { | ||
441 | if (it.current()->name == name) | ||
442 | wrap = it.current(); | ||
443 | } | ||
444 | |||
445 | if (wrap) { | ||
446 | d->pending_close.removeRef(wrap); | ||
447 | if (!wrap->lib) { | ||
448 | /* This lib only was in loaded_stack, but not in m_libs. */ | ||
449 | wrap->lib = new KLibrary( name, wrap->filename, wrap->handle ); | ||
450 | } | ||
451 | wrap->ref_count++; | ||
452 | } else { | ||
453 | QString libfile = findLibrary( name ); | ||
454 | if ( libfile.isEmpty() ) | ||
455 | return 0; | ||
456 | |||
457 | const QString & qpeDir = QPEApplication::qpeDir(); | ||
458 | libfile = qpeDir + libfile; | ||
459 | //US QLibrary *lib = new QLibrary( qpeDir + "/plugins/korganizer/libopiekabc.so", QLibrary::Immediately ); | ||
460 | QLibrary *qlib = new QLibrary( libfile.latin1(), QLibrary::Immediately ); | ||
461 | |||
462 | //US lt_dlhandle handle = lt_dlopen( libfile.latin1() ); | ||
463 | //US if ( !handle ) | ||
464 | if ( !qlib ) | ||
465 | { | ||
466 | //US const char* errmsg = lt_dlerror(); | ||
467 | char* errmsg; | ||
468 | sprintf(errmsg, "KLibLoader::library could not load library: %s", libfile.latin1()); | ||
469 | qDebug(errmsg); | ||
470 | |||
471 | if(errmsg) | ||
472 | d->errorMessage = QString::fromLatin1(errmsg); | ||
473 | else | ||
474 | d->errorMessage = QString::null; | ||
475 | kdWarning(150) << "library=" << name << ": file=" << libfile << ": " << d->errorMessage << endl; | ||
476 | return 0; | ||
477 | } | ||
478 | else | ||
479 | d->errorMessage = QString::null; | ||
480 | |||
481 | KLibrary *lib = new KLibrary( name, libfile, qlib ); | ||
482 | wrap = new KLibWrapPrivate(lib, qlib); | ||
483 | d->loaded_stack.prepend(wrap); | ||
484 | } | ||
485 | m_libs.insert( name, wrap ); | ||
486 | |||
487 | connect( wrap->lib, SIGNAL( destroyed() ), | ||
488 | this, SLOT( slotLibraryDestroyed() ) ); | ||
489 | |||
490 | return wrap->lib; | ||
491 | } | ||
492 | |||
493 | QString KLibLoader::lastErrorMessage() const | ||
494 | { | ||
495 | return d->errorMessage; | ||
496 | } | ||
497 | |||
498 | void KLibLoader::unloadLibrary( const char *libname ) | ||
499 | { | ||
500 | KLibWrapPrivate *wrap = m_libs[ libname ]; | ||
501 | if (!wrap) | ||
502 | return; | ||
503 | if (--wrap->ref_count) | ||
504 | return; | ||
505 | |||
506 | // kdDebug(150) << "closing library " << libname << endl; | ||
507 | |||
508 | m_libs.remove( libname ); | ||
509 | |||
510 | disconnect( wrap->lib, SIGNAL( destroyed() ), | ||
511 | this, SLOT( slotLibraryDestroyed() ) ); | ||
512 | close_pending( wrap ); | ||
513 | } | ||
514 | |||
515 | KLibFactory* KLibLoader::factory( const char* name ) | ||
516 | { | ||
517 | KLibrary* lib = library( name ); | ||
518 | if ( !lib ) | ||
519 | return 0; | ||
520 | |||
521 | return lib->factory(); | ||
522 | } | ||
523 | |||
524 | void KLibLoader::slotLibraryDestroyed() | ||
525 | { | ||
526 | const KLibrary *lib = static_cast<const KLibrary *>( sender() ); | ||
527 | |||
528 | QAsciiDictIterator<KLibWrapPrivate> it( m_libs ); | ||
529 | for (; it.current(); ++it ) | ||
530 | if ( it.current()->lib == lib ) | ||
531 | { | ||
532 | KLibWrapPrivate *wrap = it.current(); | ||
533 | wrap->lib = 0; /* the KLibrary object is already away */ | ||
534 | m_libs.remove( it.currentKey() ); | ||
535 | close_pending( wrap ); | ||
536 | return; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | void KLibLoader::close_pending(KLibWrapPrivate *wrap) | ||
541 | { | ||
542 | if (wrap && !d->pending_close.containsRef( wrap )) | ||
543 | d->pending_close.append( wrap ); | ||
544 | |||
545 | /* First delete all KLibrary objects in pending_close, but _don't_ unload | ||
546 | the DSO behind it. */ | ||
547 | QPtrListIterator<KLibWrapPrivate> it(d->pending_close); | ||
548 | for (; it.current(); ++it) { | ||
549 | wrap = it.current(); | ||
550 | if (wrap->lib) { | ||
551 | disconnect( wrap->lib, SIGNAL( destroyed() ), | ||
552 | this, SLOT( slotLibraryDestroyed() ) ); | ||
553 | delete wrap->lib; | ||
554 | wrap->lib = 0; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | if (d->unload_mode == KLibLoaderPrivate::DONT_UNLOAD) return; | ||
559 | |||
560 | bool deleted_one = false; | ||
561 | while ((wrap = d->loaded_stack.first())) { | ||
562 | /* Let's first see, if we want to try to unload this lib. | ||
563 | If the env. var KDE_DOUNLOAD is set, we try to unload every lib. | ||
564 | If not, we look at the lib itself, and unload it only, if it exports | ||
565 | the symbol __kde_do_unload. */ | ||
566 | if (d->unload_mode != KLibLoaderPrivate::UNLOAD | ||
567 | && wrap->unload_mode != KLibWrapPrivate::UNLOAD) | ||
568 | break; | ||
569 | |||
570 | /* Now ensure, that the libs are only unloaded in the reverse direction | ||
571 | they were loaded. */ | ||
572 | if (!d->pending_close.containsRef( wrap )) { | ||
573 | if (!deleted_one) | ||
574 | /* Only diagnose, if we really haven't deleted anything. */ | ||
575 | // kdDebug(150) << "try to dlclose " << wrap->name << ": not yet" << endl; | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | // kdDebug(150) << "try to dlclose " << wrap->name << ": yes, done." << endl; | ||
580 | |||
581 | #ifndef Q_WS_QWS | ||
582 | if ( !deleted_one ) { | ||
583 | /* Only do the hack once in this loop. | ||
584 | WABA: *HACK* | ||
585 | We need to make sure to clear the clipboard before unloading a DSO | ||
586 | because the DSO could have defined an object derived from QMimeSource | ||
587 | and placed that on the clipboard. */ | ||
588 | /*kapp->clipboard()->clear();*/ | ||
589 | |||
590 | /* Well.. let's do something more subtle... convert the clipboard context | ||
591 | to text. That should be safe as it only uses objects defined by Qt. */ | ||
592 | |||
593 | QWidgetList *widgetlist = QApplication::topLevelWidgets(); | ||
594 | QWidget *co = widgetlist->first(); | ||
595 | while (co) { | ||
596 | if (qstrcmp(co->name(), "internal clipboard owner") == 0) { | ||
597 | if (XGetSelectionOwner(co->x11Display(), XA_PRIMARY) == co->winId()) | ||
598 | kapp->clipboard()->setText(kapp->clipboard()->text()); | ||
599 | |||
600 | break; | ||
601 | } | ||
602 | co = widgetlist->next(); | ||
603 | } | ||
604 | delete widgetlist; | ||
605 | } | ||
606 | #else | ||
607 | // FIXME(E): Implement in Qt Embedded | ||
608 | #endif | ||
609 | |||
610 | deleted_one = true; | ||
611 | //US lt_dlclose(wrap->handle); | ||
612 | wrap->handle->unload(); | ||
613 | |||
614 | d->pending_close.removeRef(wrap); | ||
615 | /* loaded_stack is AutoDelete, so wrap is freed */ | ||
616 | d->loaded_stack.remove(); | ||
617 | } | ||
618 | } | ||
619 | |||
620 | void KLibLoader::virtual_hook( int, void* ) | ||
621 | { /*BASE::virtual_hook( id, data );*/ } | ||
622 | |||
623 | void KLibFactory::virtual_hook( int, void* ) | ||
624 | { /*BASE::virtual_hook( id, data );*/ } | ||
625 | |||
626 | //US #include "klibloader.moc" | ||
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 | |||
30 | class KInstance; | ||
31 | class QTimer; | ||
32 | class KLibrary; | ||
33 | class KLibFactory; | ||
34 | class KLibFactoryPrivate; | ||
35 | class KLibLoaderPrivate; | ||
36 | class KLibraryPrivate; | ||
37 | |||
38 | class 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 | */ | ||
52 | class KLibrary : public QObject | ||
53 | { | ||
54 | friend class KLibLoader; | ||
55 | friend class QAsciiDict<KLibrary>; | ||
56 | |||
57 | Q_OBJECT | ||
58 | public: | ||
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 | |||
113 | private slots: | ||
114 | void slotObjectCreated( QObject *obj ); | ||
115 | void slotObjectDestroyed(); | ||
116 | void slotTimeout(); | ||
117 | |||
118 | private: | ||
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 | |||
135 | class 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 | */ | ||
147 | class KLibLoader : public QObject | ||
148 | { | ||
149 | friend class KLibrary; | ||
150 | |||
151 | Q_OBJECT | ||
152 | public: | ||
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 | |||
283 | protected: | ||
284 | KLibLoader( QObject* parent = 0, const char* name = 0 ); | ||
285 | |||
286 | private slots: | ||
287 | void slotLibraryDestroyed(); | ||
288 | private: | ||
289 | void close_pending( KLibWrapPrivate * ); | ||
290 | QAsciiDict<KLibWrapPrivate> m_libs; | ||
291 | |||
292 | static KLibLoader* s_self; | ||
293 | |||
294 | protected: | ||
295 | virtual void virtual_hook( int id, void* data ); | ||
296 | private: | ||
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 | */ | ||
335 | class KLibFactory : public QObject | ||
336 | { | ||
337 | Q_OBJECT | ||
338 | public: | ||
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 | |||
370 | signals: | ||
371 | /** | ||
372 | * Emitted in #create | ||
373 | * @param obj the new object | ||
374 | */ | ||
375 | void objectCreated( QObject *obj ); | ||
376 | |||
377 | |||
378 | protected: | ||
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 | |||
399 | protected: | ||
400 | virtual void virtual_hook( int id, void* data ); | ||
401 | private: | ||
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 | |||
10 | QDict<QString> *mLocaleDict = 0; | ||
11 | void setLocaleDict( QDict<QString> * dict ) | ||
12 | { | ||
13 | mLocaleDict = dict; | ||
14 | |||
15 | } | ||
16 | QString 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 | |||
35 | QString i18n(const char *,const char *text) | ||
36 | { | ||
37 | return i18n( text ); | ||
38 | } | ||
39 | |||
40 | QString 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 | |||
51 | inline 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 | |||
57 | inline 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 | |||
63 | static 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 | |||
76 | KLocale::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 | |||
124 | void KLocale::setDateFormat( QString s ) | ||
125 | { | ||
126 | mDateFormat = s; | ||
127 | } | ||
128 | |||
129 | void KLocale::setDateFormatShort( QString s ) | ||
130 | { | ||
131 | mDateFormatShort = s; | ||
132 | } | ||
133 | |||
134 | void KLocale::setHore24Format ( bool b ) | ||
135 | { | ||
136 | mHourF24Format = b; | ||
137 | } | ||
138 | void KLocale::setWeekStartMonday( bool b ) | ||
139 | { | ||
140 | mWeekStartsMonday = b; | ||
141 | } | ||
142 | int KLocale::getIntDateFormat( ) | ||
143 | { | ||
144 | return mIntDateFormat ; | ||
145 | |||
146 | } | ||
147 | void KLocale::setIntDateFormat( int i ) | ||
148 | { | ||
149 | mIntDateFormat = i; | ||
150 | } | ||
151 | void KLocale::setLanguage( int i ) | ||
152 | { | ||
153 | mLanguage = i; | ||
154 | } | ||
155 | QString KLocale::translate( const char *index ) const | ||
156 | { | ||
157 | return i18n( index ); | ||
158 | } | ||
159 | |||
160 | QString KLocale::translate( const char *, const char *fallback) const | ||
161 | { | ||
162 | return i18n( fallback ); | ||
163 | } | ||
164 | |||
165 | QString 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 | |||
244 | QString 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 | |||
316 | QString 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 | |||
325 | QString KLocale::formatDateTime(const QDateTime &pDateTime) const | ||
326 | { | ||
327 | return formatDateTime(pDateTime, true); | ||
328 | } | ||
329 | |||
330 | QDate 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 | |||
338 | QDate 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 | |||
344 | QDate 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 | |||
443 | QTime 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 | |||
451 | QTime 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 | |||
559 | bool KLocale::use12Clock() const | ||
560 | { | ||
561 | return !mHourF24Format ;; | ||
562 | } | ||
563 | |||
564 | bool KLocale::weekStartsMonday() const | ||
565 | { | ||
566 | return mWeekStartsMonday; | ||
567 | } | ||
568 | |||
569 | int KLocale::weekStartDay() const | ||
570 | { | ||
571 | if ( mWeekStartsMonday ) | ||
572 | return 1; | ||
573 | return 7; | ||
574 | } | ||
575 | |||
576 | QString 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 | |||
604 | QString 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 | |||
642 | QString KLocale::country() const | ||
643 | { | ||
644 | return QString::null; | ||
645 | } | ||
646 | |||
647 | QString 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 | |||
668 | QString 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 | |||
682 | QString KLocale::timeFormat() const | ||
683 | { | ||
684 | if ( mHourF24Format) | ||
685 | return "%H:%M:%S"; | ||
686 | return "%I:%M:%S%p"; | ||
687 | } | ||
688 | |||
689 | void KLocale::insertCatalogue ( const QString & ) | ||
690 | { | ||
691 | } | ||
692 | |||
693 | KCalendarSystem *KLocale::calendar() | ||
694 | { | ||
695 | if ( !mCalendarSystem ) { | ||
696 | mCalendarSystem = new KCalendarSystemGregorian; | ||
697 | } | ||
698 | |||
699 | return mCalendarSystem; | ||
700 | } | ||
701 | |||
702 | int 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 | |||
711 | QStringList KLocale::timeZoneList() const | ||
712 | { | ||
713 | return mTimeZoneList; | ||
714 | } | ||
715 | void KLocale::setTimezone( const QString &timeZone ) | ||
716 | { | ||
717 | mTimeZoneOffset = timezoneOffset( timeZone ); | ||
718 | } | ||
719 | |||
720 | void 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 | |||
729 | int 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 | ||
777 | QString 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 | } | ||
794 | QString KLocale::formatNumber(const QString &numStr) const | ||
795 | { | ||
796 | return formatNumber(numStr.toDouble()); | ||
797 | } | ||
798 | double 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 | } | ||
862 | QString KLocale::decimalSymbol() const | ||
863 | { | ||
864 | |||
865 | return m_decimalSymbol; | ||
866 | } | ||
867 | |||
868 | QString KLocale::thousandsSeparator() const | ||
869 | { | ||
870 | |||
871 | return m_thousandsSeparator; | ||
872 | } | ||
873 | QString KLocale::positiveSign() const | ||
874 | { | ||
875 | return m_positiveSign; | ||
876 | } | ||
877 | |||
878 | QString 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 | |||
13 | class KCalendarSystem; | ||
14 | void setLocaleDict( QDict<QString> * dict ); | ||
15 | QString i18n(const char *text); | ||
16 | QString i18n(const char *hint, const char *text); | ||
17 | QString 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 | ||
22 | inline QString tr2i18n(const char* message, const char* =0) { | ||
23 | return i18n( message); | ||
24 | } | ||
25 | |||
26 | class 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 | |||
53 | static const char * const SYSTEM_MESSAGES = "kdelibs"; | ||
54 | |||
55 | static const char *maincatalogue = 0; | ||
56 | |||
57 | QDict<char> *mLocaleDict = 0; | ||
58 | |||
59 | void setLocaleDict( QDict<char> * dict ) | ||
60 | { | ||
61 | mLocaleDict = dict; | ||
62 | |||
63 | } | ||
64 | |||
65 | class KLocalePrivate | ||
66 | { | ||
67 | public: | ||
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 | |||
89 | static KLocale *this_klocale = 0; | ||
90 | |||
91 | KLocale::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 | |||
183 | QString 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 | |||
194 | void 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 | |||
213 | void 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 | |||
264 | void 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 | |||
335 | void 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 | |||
345 | void 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 | |||
436 | bool 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 | |||
449 | QString 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 | |||
459 | bool 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 | |||
479 | bool 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 | |||
500 | bool 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 | |||
528 | void 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 | |||
561 | QString KLocale::language() const | ||
562 | { | ||
563 | return m_language; | ||
564 | } | ||
565 | |||
566 | QString KLocale::country() const | ||
567 | { | ||
568 | return m_country; | ||
569 | } | ||
570 | |||
571 | QString 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 | |||
609 | QString 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 | |||
647 | QString 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 | |||
675 | void KLocale::insertCatalogue( const QString & catalogue ) | ||
676 | { | ||
677 | KCatalogue cat( catalogue ); | ||
678 | |||
679 | initCatalogue( cat ); | ||
680 | |||
681 | d->catalogues.append( cat ); | ||
682 | } | ||
683 | |||
684 | void 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 | |||
695 | void 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 | |||
707 | KLocale::~KLocale() | ||
708 | { | ||
709 | delete d->languages; | ||
710 | delete d; | ||
711 | } | ||
712 | |||
713 | QString 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 | |||
747 | QString KLocale::translate(const char* msgid) const | ||
748 | { | ||
749 | return translate_priv(msgid, msgid); | ||
750 | } | ||
751 | |||
752 | QString 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 | |||
773 | static 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 | |||
788 | QString 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 | |||
927 | QString 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 | |||
971 | bool KLocale::nounDeclension() const | ||
972 | { | ||
973 | doFormatInit(); | ||
974 | return d->nounDeclension; | ||
975 | } | ||
976 | |||
977 | bool KLocale::dateMonthNamePossessive() const | ||
978 | { | ||
979 | doFormatInit(); | ||
980 | return d->dateMonthNamePossessive; | ||
981 | } | ||
982 | |||
983 | int KLocale::weekStartDay() const | ||
984 | { | ||
985 | doFormatInit(); | ||
986 | return d->weekStartDay; | ||
987 | } | ||
988 | |||
989 | bool KLocale::weekStartsMonday() const //deprecated | ||
990 | { | ||
991 | doFormatInit(); | ||
992 | return (d->weekStartDay==1); | ||
993 | } | ||
994 | |||
995 | QString KLocale::decimalSymbol() const | ||
996 | { | ||
997 | doFormatInit(); | ||
998 | return m_decimalSymbol; | ||
999 | } | ||
1000 | |||
1001 | QString KLocale::thousandsSeparator() const | ||
1002 | { | ||
1003 | doFormatInit(); | ||
1004 | return m_thousandsSeparator; | ||
1005 | } | ||
1006 | |||
1007 | QString KLocale::currencySymbol() const | ||
1008 | { | ||
1009 | doFormatInit(); | ||
1010 | return m_currencySymbol; | ||
1011 | } | ||
1012 | |||
1013 | QString KLocale::monetaryDecimalSymbol() const | ||
1014 | { | ||
1015 | doFormatInit(); | ||
1016 | return m_monetaryDecimalSymbol; | ||
1017 | } | ||
1018 | |||
1019 | QString KLocale::monetaryThousandsSeparator() const | ||
1020 | { | ||
1021 | doFormatInit(); | ||
1022 | return m_monetaryThousandsSeparator; | ||
1023 | } | ||
1024 | |||
1025 | QString KLocale::positiveSign() const | ||
1026 | { | ||
1027 | doFormatInit(); | ||
1028 | return m_positiveSign; | ||
1029 | } | ||
1030 | |||
1031 | QString KLocale::negativeSign() const | ||
1032 | { | ||
1033 | doFormatInit(); | ||
1034 | return m_negativeSign; | ||
1035 | } | ||
1036 | |||
1037 | int KLocale::fracDigits() const | ||
1038 | { | ||
1039 | doFormatInit(); | ||
1040 | return m_fracDigits; | ||
1041 | } | ||
1042 | |||
1043 | bool KLocale::positivePrefixCurrencySymbol() const | ||
1044 | { | ||
1045 | doFormatInit(); | ||
1046 | return m_positivePrefixCurrencySymbol; | ||
1047 | } | ||
1048 | |||
1049 | bool KLocale::negativePrefixCurrencySymbol() const | ||
1050 | { | ||
1051 | doFormatInit(); | ||
1052 | return m_negativePrefixCurrencySymbol; | ||
1053 | } | ||
1054 | |||
1055 | KLocale::SignPosition KLocale::positiveMonetarySignPosition() const | ||
1056 | { | ||
1057 | doFormatInit(); | ||
1058 | return m_positiveMonetarySignPosition; | ||
1059 | } | ||
1060 | |||
1061 | KLocale::SignPosition KLocale::negativeMonetarySignPosition() const | ||
1062 | { | ||
1063 | doFormatInit(); | ||
1064 | return m_negativeMonetarySignPosition; | ||
1065 | } | ||
1066 | |||
1067 | static 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 | |||
1073 | static 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 | |||
1079 | QString 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 | |||
1140 | QString KLocale::formatMoney(const QString &numStr) const | ||
1141 | { | ||
1142 | return formatMoney(numStr.toDouble()); | ||
1143 | } | ||
1144 | |||
1145 | QString 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 | |||
1163 | QString KLocale::formatLong(long num) const | ||
1164 | { | ||
1165 | return formatNumber((double)num, 0); | ||
1166 | } | ||
1167 | |||
1168 | QString KLocale::formatNumber(const QString &numStr) const | ||
1169 | { | ||
1170 | return formatNumber(numStr.toDouble()); | ||
1171 | } | ||
1172 | |||
1173 | QString 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 | |||
1259 | void KLocale::setMainCatalogue(const char *catalogue) | ||
1260 | { | ||
1261 | maincatalogue = catalogue; | ||
1262 | } | ||
1263 | |||
1264 | double 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 | |||
1329 | double 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 | */ | ||
1429 | static 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 | |||
1442 | QDate 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 | |||
1450 | QDate 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 | |||
1456 | QDate 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 | |||
1589 | QTime 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 | |||
1597 | QTime 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 | |||
1707 | QString 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 | |||
1786 | bool 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 | |||
1795 | QString KLocale::languages() const | ||
1796 | { | ||
1797 | return d->languageList.join( QString::fromLatin1(":") ); | ||
1798 | } | ||
1799 | |||
1800 | QStringList KLocale::languageList() const | ||
1801 | { | ||
1802 | return d->languageList; | ||
1803 | } | ||
1804 | |||
1805 | QString 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 | |||
1814 | QString 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 | |||
1824 | QString 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 | |||
1834 | QString 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 | |||
1846 | void 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 | |||
1879 | QString 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 | |||
1923 | bool KLocale::useDefaultLanguage() const | ||
1924 | { | ||
1925 | return language() == defaultLanguage(); | ||
1926 | } | ||
1927 | |||
1928 | void 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 | |||
1944 | void 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 | |||
1958 | QCString KLocale::encodeFileNameUTF8( const QString & fileName ) | ||
1959 | { | ||
1960 | return fileName.utf8(); | ||
1961 | } | ||
1962 | |||
1963 | QString KLocale::decodeFileNameUTF8( const QCString & localFileName ) | ||
1964 | { | ||
1965 | return QString::fromUtf8(localFileName); | ||
1966 | } | ||
1967 | |||
1968 | void KLocale::initCatalogue( KCatalogue & catalogue ) | ||
1969 | { | ||
1970 | catalogue.setFileName( catalogueFileName( language(), catalogue ) ); | ||
1971 | } | ||
1972 | |||
1973 | void KLocale::setDateFormat(const QString & format) | ||
1974 | { | ||
1975 | doFormatInit(); | ||
1976 | m_dateFormat = format.stripWhiteSpace(); | ||
1977 | } | ||
1978 | |||
1979 | void KLocale::setDateFormatShort(const QString & format) | ||
1980 | { | ||
1981 | doFormatInit(); | ||
1982 | m_dateFormatShort = format.stripWhiteSpace(); | ||
1983 | } | ||
1984 | |||
1985 | void KLocale::setDateMonthNamePossessive(bool possessive) | ||
1986 | { | ||
1987 | doFormatInit(); | ||
1988 | d->dateMonthNamePossessive = possessive; | ||
1989 | } | ||
1990 | |||
1991 | void KLocale::setTimeFormat(const QString & format) | ||
1992 | { | ||
1993 | doFormatInit(); | ||
1994 | m_timeFormat = format.stripWhiteSpace(); | ||
1995 | } | ||
1996 | |||
1997 | void KLocale::setWeekStartsMonday(bool start) //deprecated | ||
1998 | { | ||
1999 | doFormatInit(); | ||
2000 | if (start) | ||
2001 | d->weekStartDay = 1; | ||
2002 | else | ||
2003 | d->weekStartDay = 7; | ||
2004 | } | ||
2005 | |||
2006 | void 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 | |||
2015 | QString KLocale::dateFormat() const | ||
2016 | { | ||
2017 | doFormatInit(); | ||
2018 | return m_dateFormat; | ||
2019 | } | ||
2020 | |||
2021 | QString KLocale::dateFormatShort() const | ||
2022 | { | ||
2023 | doFormatInit(); | ||
2024 | return m_dateFormatShort; | ||
2025 | } | ||
2026 | |||
2027 | QString KLocale::timeFormat() const | ||
2028 | { | ||
2029 | doFormatInit(); | ||
2030 | return m_timeFormat; | ||
2031 | } | ||
2032 | |||
2033 | void KLocale::setDecimalSymbol(const QString & symbol) | ||
2034 | { | ||
2035 | doFormatInit(); | ||
2036 | m_decimalSymbol = symbol.stripWhiteSpace(); | ||
2037 | } | ||
2038 | |||
2039 | void KLocale::setThousandsSeparator(const QString & separator) | ||
2040 | { | ||
2041 | doFormatInit(); | ||
2042 | // allow spaces here | ||
2043 | m_thousandsSeparator = separator; | ||
2044 | } | ||
2045 | |||
2046 | void KLocale::setPositiveSign(const QString & sign) | ||
2047 | { | ||
2048 | doFormatInit(); | ||
2049 | m_positiveSign = sign.stripWhiteSpace(); | ||
2050 | } | ||
2051 | |||
2052 | void KLocale::setNegativeSign(const QString & sign) | ||
2053 | { | ||
2054 | doFormatInit(); | ||
2055 | m_negativeSign = sign.stripWhiteSpace(); | ||
2056 | } | ||
2057 | |||
2058 | void KLocale::setPositiveMonetarySignPosition(SignPosition signpos) | ||
2059 | { | ||
2060 | doFormatInit(); | ||
2061 | m_positiveMonetarySignPosition = signpos; | ||
2062 | } | ||
2063 | |||
2064 | void KLocale::setNegativeMonetarySignPosition(SignPosition signpos) | ||
2065 | { | ||
2066 | doFormatInit(); | ||
2067 | m_negativeMonetarySignPosition = signpos; | ||
2068 | } | ||
2069 | |||
2070 | void KLocale::setPositivePrefixCurrencySymbol(bool prefix) | ||
2071 | { | ||
2072 | doFormatInit(); | ||
2073 | m_positivePrefixCurrencySymbol = prefix; | ||
2074 | } | ||
2075 | |||
2076 | void KLocale::setNegativePrefixCurrencySymbol(bool prefix) | ||
2077 | { | ||
2078 | doFormatInit(); | ||
2079 | m_negativePrefixCurrencySymbol = prefix; | ||
2080 | } | ||
2081 | |||
2082 | void KLocale::setFracDigits(int digits) | ||
2083 | { | ||
2084 | doFormatInit(); | ||
2085 | m_fracDigits = digits; | ||
2086 | } | ||
2087 | |||
2088 | void KLocale::setMonetaryThousandsSeparator(const QString & separator) | ||
2089 | { | ||
2090 | doFormatInit(); | ||
2091 | // allow spaces here | ||
2092 | m_monetaryThousandsSeparator = separator; | ||
2093 | } | ||
2094 | |||
2095 | void KLocale::setMonetaryDecimalSymbol(const QString & symbol) | ||
2096 | { | ||
2097 | doFormatInit(); | ||
2098 | m_monetaryDecimalSymbol = symbol.stripWhiteSpace(); | ||
2099 | } | ||
2100 | |||
2101 | void KLocale::setCurrencySymbol(const QString & symbol) | ||
2102 | { | ||
2103 | doFormatInit(); | ||
2104 | m_currencySymbol = symbol.stripWhiteSpace(); | ||
2105 | } | ||
2106 | |||
2107 | int KLocale::pageSize() const | ||
2108 | { | ||
2109 | doFormatInit(); | ||
2110 | return d->pageSize; | ||
2111 | } | ||
2112 | |||
2113 | void KLocale::setPageSize(int pageSize) | ||
2114 | { | ||
2115 | // #### check if it's in range?? | ||
2116 | doFormatInit(); | ||
2117 | d->pageSize = pageSize; | ||
2118 | } | ||
2119 | |||
2120 | KLocale::MeasureSystem KLocale::measureSystem() const | ||
2121 | { | ||
2122 | doFormatInit(); | ||
2123 | return d->measureSystem; | ||
2124 | } | ||
2125 | |||
2126 | void KLocale::setMeasureSystem(MeasureSystem value) | ||
2127 | { | ||
2128 | doFormatInit(); | ||
2129 | d->measureSystem = value; | ||
2130 | } | ||
2131 | |||
2132 | QString KLocale::defaultLanguage() | ||
2133 | { | ||
2134 | return QString::fromLatin1("en_US"); | ||
2135 | } | ||
2136 | |||
2137 | QString KLocale::defaultCountry() | ||
2138 | { | ||
2139 | return QString::fromLatin1("C"); | ||
2140 | } | ||
2141 | |||
2142 | const char * KLocale::encoding() const | ||
2143 | { | ||
2144 | return codecForEncoding()->name(); | ||
2145 | } | ||
2146 | |||
2147 | int KLocale::encodingMib() const | ||
2148 | { | ||
2149 | return codecForEncoding()->mibEnum(); | ||
2150 | } | ||
2151 | |||
2152 | int KLocale::fileEncodingMib() const | ||
2153 | { | ||
2154 | if (d->utf8FileEncoding) | ||
2155 | return 106; | ||
2156 | return codecForEncoding()->mibEnum(); | ||
2157 | } | ||
2158 | |||
2159 | QTextCodec * KLocale::codecForEncoding() const | ||
2160 | { | ||
2161 | return d->codecForEncoding; | ||
2162 | } | ||
2163 | |||
2164 | bool 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 | |||
2173 | QStringList 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 | |||
2227 | QStringList 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 | |||
2239 | QString 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 | |||
2249 | QStringList 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 | |||
2267 | QString 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 | |||
2275 | void KLocale::setCalendar(const QString & calType) | ||
2276 | { | ||
2277 | doFormatInit(); | ||
2278 | |||
2279 | d->calendarType = calType; | ||
2280 | |||
2281 | delete d->calendar; | ||
2282 | d->calendar = 0; | ||
2283 | } | ||
2284 | |||
2285 | QString KLocale::calendarType() const | ||
2286 | { | ||
2287 | doFormatInit(); | ||
2288 | |||
2289 | return d->calendarType; | ||
2290 | } | ||
2291 | |||
2292 | const 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 | |||
2306 | KLocale::KLocale(const KLocale & rhs) | ||
2307 | { | ||
2308 | d = new KLocalePrivate; | ||
2309 | |||
2310 | *this = rhs; | ||
2311 | } | ||
2312 | |||
2313 | KLocale & 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 | |||
2345 | bool KLocale::setCharset(const QString & ) { return true; } | ||
2346 | QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); } | ||
2347 | |||
2348 | |||
2349 | int 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 | |||
2358 | QStringList KLocale::timeZoneList() const | ||
2359 | { | ||
2360 | return mTimeZoneList; | ||
2361 | } | ||
2362 | void KLocale::setTimezone( const QString &timeZone ) | ||
2363 | { | ||
2364 | mTimeZoneOffset = timezoneOffset( timeZone ); | ||
2365 | } | ||
2366 | |||
2367 | void 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 | |||
2376 | int 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 | |||
2423 | void KLocale::setHore24Format ( bool b ) | ||
2424 | { | ||
2425 | mHourF24Format = b; | ||
2426 | } | ||
2427 | void KLocale::setWeekStartMonday( bool b ) | ||
2428 | { | ||
2429 | mWeekStartsMonday = b; | ||
2430 | } | ||
2431 | void KLocale::setIntDateFormat( int i ) | ||
2432 | { | ||
2433 | mIntDateFormat = i; | ||
2434 | } | ||
2435 | void 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 | |||
8 | class QStringList; | ||
9 | class QTextCodec; | ||
10 | class QDate; | ||
11 | class QTime; | ||
12 | class QDateTime; | ||
13 | |||
14 | class KGlobal; | ||
15 | class KConfig; | ||
16 | class KConfigBase; | ||
17 | class KLocalePrivate; | ||
18 | class KCatalogue; | ||
19 | class KCalendarSystem; | ||
20 | |||
21 | #ifndef I18N_NOOP | ||
22 | #define I18N_NOOP(x) (x) | ||
23 | #endif | ||
24 | |||
25 | void 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 | **/ | ||
38 | QString 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 | **/ | ||
46 | QString 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 | **/ | ||
53 | QString 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 | **/ | ||
60 | inline 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 | */ | ||
76 | class KLocale | ||
77 | { | ||
78 | friend class KGlobal; // for initInstance() | ||
79 | public: | ||
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 | ||
1047 | private: | ||
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 | |||
1081 | protected: | ||
1082 | /** | ||
1083 | * @internal Creates a KLocale object for KGlobal and inits the locale | ||
1084 | * pointer. | ||
1085 | */ | ||
1086 | static void initInstance(); | ||
1087 | |||
1088 | private: | ||
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 | |||
1182 | private: | ||
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 | |||
60 | const 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 | |||
72 | const 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 | |||
92 | const 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 | |||
104 | const 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 | |||
124 | const 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 | |||
130 | const unsigned int KCodecs::maxQPLineLength = 70; | ||
131 | |||
132 | |||
133 | /******************************** KCodecs ********************************/ | ||
134 | // strchr(3) for broken systems. | ||
135 | static 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 | |||
150 | QCString 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 | |||
157 | QCString 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 | |||
167 | void 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 | |||
283 | QCString KCodecs::quotedPrintableDecode(const QByteArray & in) | ||
284 | { | ||
285 | QByteArray out; | ||
286 | quotedPrintableDecode (in, out); | ||
287 | return QCString (out.data(), out.size()+1); | ||
288 | } | ||
289 | |||
290 | QCString 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 | |||
300 | void 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 | |||
358 | QCString 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 | |||
368 | QCString 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 | |||
375 | void 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 | |||
447 | QCString 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 | |||
457 | QCString KCodecs::base64Decode( const QByteArray& in ) | ||
458 | { | ||
459 | QByteArray out; | ||
460 | base64Decode( in, out ); | ||
461 | return QCString( out.data(), out.size()+1 ); | ||
462 | } | ||
463 | |||
464 | void 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 | |||
545 | QCString 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 | |||
556 | QCString KCodecs::uuencode( const QByteArray& in ) | ||
557 | { | ||
558 | QByteArray out; | ||
559 | uuencode( in, out ); | ||
560 | return QCString( out.data(), out.size()+1 ); | ||
561 | } | ||
562 | |||
563 | void 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 | |||
642 | QCString 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 | |||
653 | QCString KCodecs::uudecode( const QByteArray& in ) | ||
654 | { | ||
655 | QByteArray out; | ||
656 | uudecode( in, out ); | ||
657 | return QCString( out.data(), out.size()+1 ); | ||
658 | } | ||
659 | |||
660 | void 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 ********************************/ | ||
747 | KMD5::KMD5() | ||
748 | { | ||
749 | init(); | ||
750 | } | ||
751 | |||
752 | KMD5::KMD5(const char *in, int len) | ||
753 | { | ||
754 | init(); | ||
755 | update(in, len); | ||
756 | } | ||
757 | |||
758 | KMD5::KMD5(const QByteArray& in) | ||
759 | { | ||
760 | init(); | ||
761 | update( in ); | ||
762 | } | ||
763 | |||
764 | KMD5::KMD5(const QCString& in) | ||
765 | { | ||
766 | init(); | ||
767 | update( in ); | ||
768 | } | ||
769 | |||
770 | void KMD5::update(const QByteArray& in) | ||
771 | { | ||
772 | update(in.data(), int(in.size())); | ||
773 | } | ||
774 | |||
775 | void KMD5::update(const QCString& in) | ||
776 | { | ||
777 | update(in.data(), int(in.length())); | ||
778 | } | ||
779 | |||
780 | void 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 | |||
823 | bool 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 | |||
834 | void 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 | |||
870 | bool KMD5::verify( const KMD5::Digest& digest) | ||
871 | { | ||
872 | finalize(); | ||
873 | return (0 == memcmp(rawDigest(), digest, sizeof(KMD5::Digest))); | ||
874 | } | ||
875 | |||
876 | bool KMD5::verify( const QCString& hexdigest) | ||
877 | { | ||
878 | finalize(); | ||
879 | return (0 == strcmp(hexDigest().data(), hexdigest)); | ||
880 | } | ||
881 | |||
882 | const KMD5::Digest& KMD5::rawDigest() | ||
883 | { | ||
884 | finalize(); | ||
885 | return m_digest; | ||
886 | } | ||
887 | |||
888 | void KMD5::rawDigest( KMD5::Digest& bin ) | ||
889 | { | ||
890 | finalize(); | ||
891 | memcpy( bin, m_digest, 16 ); | ||
892 | } | ||
893 | |||
894 | |||
895 | QCString 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 | |||
908 | void 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 | |||
918 | QCString 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 | |||
928 | void KMD5::init() | ||
929 | { | ||
930 | d = 0; | ||
931 | reset(); | ||
932 | } | ||
933 | |||
934 | void 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 | |||
950 | void 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 | |||
1041 | inline Q_UINT32 KMD5::rotate_left (Q_UINT32 x, Q_UINT32 n) | ||
1042 | { | ||
1043 | return (x << n) | (x >> (32-n)) ; | ||
1044 | } | ||
1045 | |||
1046 | inline Q_UINT32 KMD5::F (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1047 | { | ||
1048 | return (x & y) | (~x & z); | ||
1049 | } | ||
1050 | |||
1051 | inline Q_UINT32 KMD5::G (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1052 | { | ||
1053 | return (x & z) | (y & ~z); | ||
1054 | } | ||
1055 | |||
1056 | inline Q_UINT32 KMD5::H (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1057 | { | ||
1058 | return x ^ y ^ z; | ||
1059 | } | ||
1060 | |||
1061 | inline Q_UINT32 KMD5::I (Q_UINT32 x, Q_UINT32 y, Q_UINT32 z) | ||
1062 | { | ||
1063 | return y ^ (x | ~z); | ||
1064 | } | ||
1065 | |||
1066 | void 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 | |||
1073 | void 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 | |||
1080 | void 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 | |||
1087 | void 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 | |||
1095 | void 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. | ||
1114 | void 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 | */ | ||
71 | class KCodecs | ||
72 | { | ||
73 | public: | ||
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 | |||
344 | private: | ||
345 | KCodecs(); | ||
346 | |||
347 | private: | ||
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 | |||
356 | class 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 | |||
404 | class KMD5 | ||
405 | { | ||
406 | public: | ||
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 | |||
529 | protected: | ||
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 | |||
541 | private: | ||
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 | |||
563 | private: | ||
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 | */ | ||
39 | class KShared { | ||
40 | public: | ||
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 | |||
76 | protected: | ||
77 | virtual ~KShared() { } | ||
78 | private: | ||
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 | */ | ||
95 | template< class T > | ||
96 | struct KSharedPtr | ||
97 | { | ||
98 | public: | ||
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 | ||
167 | private: | ||
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 | ||
34 | static 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 | |||
45 | inline 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 | |||
59 | inline 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 | |||
69 | QStringList 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 | |||
251 | inline 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 | |||
261 | QString 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 | |||
287 | QString 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 | |||
315 | QString 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 | |||
360 | QString 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 | |||
374 | QString 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 | */ | ||
31 | namespace 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 | |||
26 | class QKeyEvent; | ||
27 | class 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 | ||
39 | class 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 | |||
543 | class 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 | ||
56 | QString KStandardDirs::mAppDir = QString::null; | ||
57 | |||
58 | |||
59 | template class QDict<QStringList>; | ||
60 | |||
61 | #if 0 | ||
62 | #include <qtextedit.h> | ||
63 | void 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 | ||
75 | class KStandardDirs::KStandardDirsPrivate | ||
76 | { | ||
77 | public: | ||
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 | |||
90 | static 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 | |||
97 | static int tokenize( QStringList& token, const QString& str, | ||
98 | const QString& delim ); | ||
99 | |||
100 | KStandardDirs::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 | |||
110 | KStandardDirs::~KStandardDirs() | ||
111 | { | ||
112 | delete d; | ||
113 | } | ||
114 | |||
115 | bool 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 | |||
135 | void 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 | |||
149 | QStringList 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 | |||
157 | void 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 | |||
172 | void 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 | |||
187 | void 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 | |||
203 | QString KStandardDirs::kfsstnd_prefixes() | ||
204 | { | ||
205 | return prefixes.join(":"); | ||
206 | } | ||
207 | |||
208 | bool 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 | |||
230 | bool 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 | |||
250 | QString 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 | ||
257 | kdDebug() << "Find resource: " << type << endl; | ||
258 | for (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 | ||
272 | static 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 | ||
290 | Q_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 | |||
316 | QStringList 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 | |||
338 | QString 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 | |||
366 | bool 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 | |||
388 | static void lookupDirectory(const QString& path, const QString &relPart, | ||
389 | const QRegExp ®exp, | ||
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 | |||
514 | static void lookupPrefix(const QString& prefix, const QString& relpath, | ||
515 | const QString& relPart, | ||
516 | const QRegExp ®exp, | ||
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 | |||
607 | QStringList | ||
608 | KStandardDirs::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 | |||
652 | QStringList | ||
653 | KStandardDirs::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 | |||
662 | QString | ||
663 | KStandardDirs::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 | ||
686 | void 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 | |||
718 | QStringList 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 | ||
807 | QString 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 | |||
880 | int 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 | |||
912 | static 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 | |||
938 | QString 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 | |||
985 | QString 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 | |||
1048 | QString 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 | |||
1070 | bool 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 | |||
1190 | static 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 | |||
1202 | void 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 | |||
1394 | void 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 | |||
1404 | bool 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 | |||
1465 | QString KStandardDirs::localkdedir() const | ||
1466 | { | ||
1467 | // Return the prefix to use for saving | ||
1468 | return prefixes.first(); | ||
1469 | } | ||
1470 | |||
1471 | QString KStandardDirs::localxdgdatadir() const | ||
1472 | { | ||
1473 | // Return the prefix to use for saving | ||
1474 | return d->xdgdata_prefixes.first(); | ||
1475 | } | ||
1476 | |||
1477 | QString KStandardDirs::localxdgconfdir() const | ||
1478 | { | ||
1479 | // Return the prefix to use for saving | ||
1480 | return d->xdgconf_prefixes.first(); | ||
1481 | } | ||
1482 | |||
1483 | void KStandardDirs::setAppDir( const QString &appDir ) | ||
1484 | { | ||
1485 | mAppDir = appDir; | ||
1486 | |||
1487 | if ( mAppDir.right( 1 ) != "/" ) | ||
1488 | mAppDir += "/"; | ||
1489 | } | ||
1490 | |||
1491 | QString KStandardDirs::appDir() | ||
1492 | { | ||
1493 | return mAppDir; | ||
1494 | } | ||
1495 | |||
1496 | // just to make code more readable without macros | ||
1497 | QString 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 | |||
1504 | QString 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. | ||
1521 | why 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 | |||
1564 | QString 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. | ||
1584 | why 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 | |||
31 | class KConfig; | ||
32 | class 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 | */ | ||
126 | class KStandardDirs | ||
127 | { | ||
128 | public: | ||
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 | **/ | ||
655 | QString 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 | **/ | ||
666 | QString 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 | **/ | ||
677 | QString 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 | ||
27 | QString 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 | |||
37 | QString 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 | // | ||
105 | QString 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 | |||
125 | QString 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 | |||
147 | QString 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 | |||
208 | QString 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 | |||
225 | QString 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 | // | ||
250 | QString 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 | |||
262 | QStringList 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 | // | ||
286 | QString 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 | |||
300 | QStringList 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 | // | ||
318 | QString 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 | |||
332 | QString 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 | |||
346 | QString 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 | |||
374 | QString 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 | |||
383 | QString 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 | |||
392 | QString 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 | |||
401 | QString KStringHandler::lEmSqueeze(const QString &name, const QFontMetrics& fontMetrics, uint maxlen) | ||
402 | { | ||
403 | return lPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); | ||
404 | } | ||
405 | |||
406 | static 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 | |||
413 | QString 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 | |||
438 | QString KStringHandler::cEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) | ||
439 | { | ||
440 | return cPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); | ||
441 | } | ||
442 | |||
443 | QString 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 | |||
469 | QString KStringHandler::rEmSqueeze(const QString& name, const QFontMetrics& fontMetrics, uint maxlen) | ||
470 | { | ||
471 | return rPixelSqueeze(name, fontMetrics, fontMetrics.maxWidth() * maxlen); | ||
472 | } | ||
473 | |||
474 | QString 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 | |||
502 | bool 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 | ||
536 | KStringHandler::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 | ||
562 | KStringHandler::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 | ||
588 | KStringHandler::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 | } | ||
613 | US end */ | ||
614 | |||
615 | /*US | ||
616 | QString | ||
617 | KStringHandler::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 | */ | ||
642 | QString 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 | */ | ||
68 | class KStringHandler | ||
69 | { | ||
70 | public: | ||
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 | ||
406 | private: | ||
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 | ||