summaryrefslogtreecommitdiff
path: root/library/backend
Unidiff
Diffstat (limited to 'library/backend') (more/less context) (ignore whitespace changes)
-rw-r--r--library/backend/categories.cpp327
-rw-r--r--library/backend/contact.cpp526
-rw-r--r--library/backend/contact.h102
-rw-r--r--library/backend/event.cpp539
-rw-r--r--library/backend/event.h173
-rw-r--r--library/backend/palmtoprecord.cpp42
-rw-r--r--library/backend/palmtoprecord.h33
-rw-r--r--library/backend/palmtopuidgen.h26
-rw-r--r--library/backend/qfiledirect_p.h72
-rw-r--r--library/backend/qpcglobal.h9
-rw-r--r--library/backend/recordfields.h24
-rw-r--r--library/backend/stringutil.cpp415
-rw-r--r--library/backend/stringutil.h57
-rw-r--r--library/backend/task.cpp173
-rw-r--r--library/backend/task.h21
-rw-r--r--library/backend/timeconversion.cpp237
-rw-r--r--library/backend/timeconversion.h45
-rw-r--r--library/backend/vcc.y2407
-rw-r--r--library/backend/vcc_yacc.cpp169
-rw-r--r--library/backend/vobject.cpp2534
-rw-r--r--library/backend/vobject_p.h810
21 files changed, 4871 insertions, 3870 deletions
diff --git a/library/backend/categories.cpp b/library/backend/categories.cpp
index 6e011c4..e37b3b9 100644
--- a/library/backend/categories.cpp
+++ b/library/backend/categories.cpp
@@ -1,677 +1,936 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free 7** GNU General Public License version 2 as published by the Free Software
8** Software Foundation and appearing in the file LICENSE.GPL included 8** Foundation and appearing in the file LICENSE.GPL included in the
9** in the packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** PARTICULAR PURPOSE.
14** 13**
15** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
16** 15**
17** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you. 17** not clear to you.
19** 18**
20**********************************************************************/ 19**********************************************************************/
21#include "categories.h" 20#include <qtopia/categories.h>
21#include <qtopia/stringutil.h>
22#include <qfile.h> 22#include <qfile.h>
23#include <qcstring.h> 23#include <qcstring.h>
24#include <qtextstream.h> 24#include <qtextstream.h>
25#include "stringutil.h"
26 25
27using namespace Qtopia; 26using namespace Qtopia;
28 27
29/*********************************************************** 28/***********************************************************
30 * 29 *
31 * CategoryGroup 30 * CategoryGroup
32 * 31 *
33 **********************************************************/ 32 **********************************************************/
34 33
35#ifdef PALMTOPCENTER 34#ifdef PALMTOPCENTER
36UidGen CategoryGroup::sUidGen( UidGen::PalmtopCenter ); 35UidGen CategoryGroup::sUidGen( UidGen::PalmtopCenter );
37#else 36#else
38UidGen CategoryGroup::sUidGen( UidGen::Qtopia ); 37UidGen CategoryGroup::sUidGen( UidGen::Qtopia );
39#endif 38#endif
40 39
40/*! \class CategoryGroup categories.h
41 \brief Helper class that is used by Categories
42
43 CategoryGroup is a group of categories that is associated with an
44 application or global set. Mainly it defines a map of ids to
45 category labels and category labels to ids. Lookups can be done with
46 labels or unique idenifiers.
47
48 \ingroup qtopiaemb
49 \ingroup qtopiadesktop
50 \warning Categories API will likely change between Qtopia 1.5 and Qtopia 3
51 \sa Categories::appGroupMap(), Categories::globalGroup()
52 */
53
54/*! Add \a label and return the UID. If failure, then 0 is returned. Note
55 that All and Unfiled are reserved labels.
56 \internal
57*/
41int CategoryGroup::add( const QString &label ) 58int CategoryGroup::add( const QString &label )
42{ 59{
43 if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") ) 60 if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
44 return 0; 61 return 0;
45 62
46 QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label ); 63 QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
47 if ( findIt != mLabelIdMap.end() ) 64 if ( findIt != mLabelIdMap.end() )
48 return 0; 65 return 0;
49 int newUid = uidGen().generate(); 66 int newUid = uidGen().generate();
50 insert( newUid, label ); 67 insert( newUid, label );
51 return newUid; 68 return newUid;
52} 69}
53 70
54void CategoryGroup::insert( int uid, const QString &label ) 71void CategoryGroup::insert( int uid, const QString &label )
55{ 72{
56 uidGen().store( uid ); 73 uidGen().store( uid );
57 mIdLabelMap[uid] = label; 74 mIdLabelMap[uid] = label;
58 mLabelIdMap[label] = uid; 75 mLabelIdMap[label] = uid;
59} 76}
60 77
78/*! \internal
79 */
61bool CategoryGroup::add( int uid, const QString &label ) 80bool CategoryGroup::add( int uid, const QString &label )
62{ 81{
63 if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") ) 82 if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
64 return FALSE; 83 return FALSE;
65 84
66 QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label ); 85 QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
67 if ( labelIt != mLabelIdMap.end() ) 86 if ( labelIt != mLabelIdMap.end() )
68 return FALSE; 87 return FALSE;
69 QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid ); 88 QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
70 if ( idIt != mIdLabelMap.end() ) 89 if ( idIt != mIdLabelMap.end() )
71 return FALSE; 90 return FALSE;
72 insert( uid, label ); 91 insert( uid, label );
73 return TRUE; 92 return TRUE;
74} 93}
75 94
95/*! Returns TRUE if \a label was removed from the group, FALSE if not.
96 \internal
97 */
76bool CategoryGroup::remove( const QString &label ) 98bool CategoryGroup::remove( const QString &label )
77{ 99{
78 QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label ); 100 QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
79 if ( findIt == mLabelIdMap.end() ) 101 if ( findIt == mLabelIdMap.end() )
80 return FALSE; 102 return FALSE;
81 103
82 mIdLabelMap.remove( *findIt ); 104 mIdLabelMap.remove( *findIt );
83 mLabelIdMap.remove( findIt ); 105 mLabelIdMap.remove( findIt );
84 106
85 return TRUE; 107 return TRUE;
86} 108}
87 109
110/*! Returns TRUE if \a uid was removed from the group, FALSE if not.
111 \internal
112 */
88bool CategoryGroup::remove( int uid ) 113bool CategoryGroup::remove( int uid )
89{ 114{
90 QMap<int,QString>::Iterator idIt = mIdLabelMap.find( uid ); 115 QMap<int,QString>::Iterator idIt = mIdLabelMap.find( uid );
91 if ( idIt == mIdLabelMap.end() ) 116 if ( idIt == mIdLabelMap.end() )
92 return FALSE; 117 return FALSE;
93 118
94 mLabelIdMap.remove( *idIt ); 119 mLabelIdMap.remove( *idIt );
95 mIdLabelMap.remove( idIt ); 120 mIdLabelMap.remove( idIt );
96 121
97 return TRUE; 122 return TRUE;
98} 123}
99 124
125/*! \internal
126 */
100bool CategoryGroup::rename( int uid, const QString &newLabel ) 127bool CategoryGroup::rename( int uid, const QString &newLabel )
101{ 128{
102 if ( newLabel == QObject::tr("All") || newLabel == QObject::tr("Unfiled") ) 129 if ( newLabel == QObject::tr("All") || newLabel == QObject::tr("Unfiled") )
103 return FALSE; 130 return FALSE;
104 131
105 QMap<int, QString>::Iterator idIt = mIdLabelMap.find( uid ); 132 QMap<int, QString>::Iterator idIt = mIdLabelMap.find( uid );
106 if ( idIt == mIdLabelMap.end() ) 133 if ( idIt == mIdLabelMap.end() )
107 return FALSE; 134 return FALSE;
108 135
109 mLabelIdMap.remove( *idIt ); 136 mLabelIdMap.remove( *idIt );
110 mLabelIdMap[newLabel] = uid; 137 mLabelIdMap[newLabel] = uid;
111 *idIt = newLabel; 138 *idIt = newLabel;
112 139
113 return TRUE; 140 return TRUE;
114} 141}
115 142
143/*! \internal
144 */
116bool CategoryGroup::rename( const QString &oldLabel, const QString &newLabel ) 145bool CategoryGroup::rename( const QString &oldLabel, const QString &newLabel )
117{ 146{
118 return rename( id(oldLabel), newLabel ); 147 return rename( id(oldLabel), newLabel );
119} 148}
120 149
150/*! Returns TRUE if \a uid is stored in this group, FALSE if not. */
121bool CategoryGroup::contains(int uid) const 151bool CategoryGroup::contains(int uid) const
122{ 152{
123 return ( mIdLabelMap.find( uid ) != mIdLabelMap.end() ); 153 return ( mIdLabelMap.find( uid ) != mIdLabelMap.end() );
124} 154}
125 155
156/*! Returns TRUE if \a label is stored in this group, FALSE if not. */
126bool CategoryGroup::contains(const QString &label) const 157bool CategoryGroup::contains(const QString &label) const
127{ 158{
128 return ( mLabelIdMap.find( label ) != mLabelIdMap.end() ); 159 return ( mLabelIdMap.find( label ) != mLabelIdMap.end() );
129} 160}
130 161
131/** Returns label associated with the uid or QString::null if 162/*! Returns label associated with the \a uid or QString::null if
132 * not found 163 not found
133 */ 164 */
134const QString &CategoryGroup::label(int uid) const 165const QString &CategoryGroup::label(int uid) const
135{ 166{
136 QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid ); 167 QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
137 if ( idIt == mIdLabelMap.end() ) 168 if ( idIt == mIdLabelMap.end() )
138 return QString::null; 169 return QString::null;
139 return *idIt; 170 return *idIt;
140} 171}
141 172
142/** Returns the uid associated with label or 0 if not found */ 173/*! Returns the uid associated with \a label or 0 if not found */
143int CategoryGroup::id(const QString &label) const 174int CategoryGroup::id(const QString &label) const
144{ 175{
145 QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label ); 176 QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
146 if ( labelIt == mLabelIdMap.end() ) 177 if ( labelIt == mLabelIdMap.end() )
147 return 0; 178 return 0;
148 return *labelIt; 179 return *labelIt;
149} 180}
150 181
182/*! Returns a list of all labels stored in this group. */
151QStringList CategoryGroup::labels() const 183QStringList CategoryGroup::labels() const
152{ 184{
153 QStringList labels; 185 QStringList labels;
154 for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin(); 186 for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
155 it != mIdLabelMap.end(); ++it ) 187 it != mIdLabelMap.end(); ++it )
156 labels += *it; 188 labels += *it;
157 // ### I don't think this is the place for this... 189 // ### I don't think this is the place for this...
158// labels.sort(); 190// labels.sort();
159 return labels; 191 return labels;
160} 192}
161 193
194/*! Returns a list of all labels associated with the \a catids */
162QStringList CategoryGroup::labels(const QArray<int> &catids ) const 195QStringList CategoryGroup::labels(const QArray<int> &catids ) const
163{ 196{
164 QStringList labels; 197 QStringList labels;
165 if ( catids.count() == 0 ) 198 if ( catids.count() == 0 )
166 return labels; 199 return labels;
167 for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin(); 200 for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
168 it != mIdLabelMap.end(); ++it ) 201 it != mIdLabelMap.end(); ++it )
169 if ( catids.find( it.key() ) != -1 ) 202 if ( catids.find( it.key() ) != -1 )
170 labels += *it; 203 labels += *it;
171 return labels; 204 return labels;
172} 205}
173 206
174/*********************************************************** 207/***********************************************************
175 * 208 *
176 * Categories 209 * Categories
177 * 210 *
178 **********************************************************/ 211 **********************************************************/
179 212
180/** Add the category name as long as it doesn't already exist locally 213/*!
181 * or globally. Return TRUE if added, FALSE if conflicts. 214 \class Categories categories.h
182 */ 215 \brief The Categories class is a database that groups categories and maps ids to names.
216
217 The Categories class is the low level Categories accessor class. To
218 add a category menu and filter for your application, see CategoryMenu.
219
220 The Categories class allows the developer to add, remove, and rename
221 categories. Categories can be created for an individual application
222 such as Todo List or to be used for all applications. Categories
223 that can be used by all applications are called global
224 categories. Each PalmtopRecord subclass stores categories as an
225 QArray<int> using PalmtopRecord::setCategories() and
226 PalmtopRecord::categories(). This allows each record to be assigned
227 to multiple categories. This also allows the user to rename a
228 category and for it to update automatically in all records.
229
230 This class provides several methods to convert between a category id
231 and it's associated string such as id(), ids(), label() and labels(). A
232 helper class called CategoryGroup is used to access categories of a
233 single application group, such as Todo List. Global categories can
234 also be accessed via CategoryGroup objects. See appGroupMap() and
235 globalGroup() for the appropriate accessor methods.
236
237 Categories are stored in an xml file in the Settings directory
238 (Categories.xml). A global function called categoryFileName() will
239 return to appropriate QString file location to be passed to load()
240 and save() for the master categories database.
241
242 \ingroup qtopiaemb
243 \ingroup qtopiadesktop
244 \warning Categories API will likely change between Qtopia 1.5 and Qtopia 3
245 \sa CategoryGroup, CategoryMenu
246*/
247
248
249/*!
250 Add the category name as long as it doesn't already exist locally or
251 globally. The \a uid is assigned to the category if successfully
252 added. Return \a uid if added, 0 if conflicts (error).
253
254 \internal
255*/
183int Categories::addCategory( const QString &appname, 256int Categories::addCategory( const QString &appname,
184 const QString &catname, 257 const QString &catname,
185 int uid ) 258 int uid )
186{ 259{
187 if ( mGlobalCats.contains(catname) ) 260 if ( mGlobalCats.contains(catname) )
188 return 0; 261 return 0;
189 262
190 QMap< QString, CategoryGroup >::Iterator 263 QMap< QString, CategoryGroup >::Iterator
191 appIt = mAppCats.find( appname ); 264 appIt = mAppCats.find( appname );
192 265
193 if ( appIt == mAppCats.end() ) { 266 if ( appIt == mAppCats.end() ) {
194 CategoryGroup newgroup; 267 CategoryGroup newgroup;
195 newgroup.add( uid, catname ); 268 newgroup.add( uid, catname );
196 mAppCats.insert( appname, newgroup ); 269 mAppCats.insert( appname, newgroup );
197 emit categoryAdded( *this, appname, uid ); 270 emit categoryAdded( *this, appname, uid );
198 return uid; 271 return uid;
199 } 272 }
200 273
201 CategoryGroup &cats = *appIt; 274 CategoryGroup &cats = *appIt;
202 cats.add( uid, catname ); 275 cats.add( uid, catname );
203 emit categoryAdded( *this, appname, uid ); 276 emit categoryAdded( *this, appname, uid );
204 return uid; 277 return uid;
205} 278}
206 279
280/*!
281 Add the category name as long as it doesn't already exist locally or
282 globally. Return UID if added, 0 if conflicts (error).
283*/
284
207int Categories::addCategory( const QString &appname, 285int Categories::addCategory( const QString &appname,
208 const QString &catname ) 286 const QString &catname )
209{ 287{
210 if ( mGlobalCats.contains(catname) ) 288 if ( mGlobalCats.contains(catname) )
211 return 0; 289 return 0;
212 290
213 QMap< QString, CategoryGroup >::Iterator 291 QMap< QString, CategoryGroup >::Iterator
214 appIt = mAppCats.find( appname ); 292 appIt = mAppCats.find( appname );
215 293
216 if ( appIt == mAppCats.end() ) { 294 if ( appIt == mAppCats.end() ) {
217 CategoryGroup newgroup; 295 CategoryGroup newgroup;
218 int uid = newgroup.add( catname ); 296 int uid = newgroup.add( catname );
219 mAppCats.insert( appname, newgroup ); 297 mAppCats.insert( appname, newgroup );
220 emit categoryAdded( *this, appname, uid ); 298 emit categoryAdded( *this, appname, uid );
221 return uid; 299 return uid;
222 } 300 }
223 301
224 CategoryGroup &cats = *appIt; 302 CategoryGroup &cats = *appIt;
225 int uid = cats.add( catname ); 303 int uid = cats.add( catname );
226 if ( !uid ) 304 if ( !uid )
227 return 0; 305 return 0;
228 emit categoryAdded( *this, appname, uid ); 306 emit categoryAdded( *this, appname, uid );
229 return uid; 307 return uid;
230} 308}
231 309
310/*!
311 \internal
312*/
232int Categories::addGlobalCategory( const QString &catname, int uid ) 313int Categories::addGlobalCategory( const QString &catname, int uid )
233{ 314{
234 mGlobalCats.add( uid, catname ); 315 mGlobalCats.add( uid, catname );
235 emit categoryAdded( *this, QString::null, uid ); 316 emit categoryAdded( *this, QString::null, uid );
236 return uid; 317 return uid;
237} 318}
238 319
320/*!
321 Add the global category \a catname while checking that it doesn't
322 already exist globally. Return UID if added, 0 if conflicts.
323
324 \sa addCategory()
325 */
239int Categories::addGlobalCategory( const QString &catname ) 326int Categories::addGlobalCategory( const QString &catname )
240{ 327{
241 int uid = mGlobalCats.add( catname ); 328 int uid = mGlobalCats.add( catname );
242 if ( !uid ) 329 if ( !uid )
243 return 0; 330 return 0;
244 emit categoryAdded( *this, QString::null, uid ); 331 emit categoryAdded( *this, QString::null, uid );
245 return uid; 332 return uid;
246} 333}
247 334
248/** Removes the category from the application; if it is not found 335/*!
249 * in the application, then it attempts to remove it from 336
250 * the global list 337 Removes the \a catname from the application group. If it is not
251 */ 338 found in the application group and \a checkGlobal is TRUE, then it
339 attempts to remove it from the global list
340*/
252bool Categories::removeCategory( const QString &appname, 341bool Categories::removeCategory( const QString &appname,
253 const QString &catname, 342 const QString &catname,
254 bool checkGlobal ) 343 bool checkGlobal )
255{ 344{
256 QMap< QString, CategoryGroup >::Iterator 345 QMap< QString, CategoryGroup >::Iterator
257 appIt = mAppCats.find( appname ); 346 appIt = mAppCats.find( appname );
258 if ( appIt != mAppCats.end() ) { 347 if ( appIt != mAppCats.end() ) {
259 CategoryGroup &cats = *appIt; 348 CategoryGroup &cats = *appIt;
260 int uid = cats.id( catname ); 349 int uid = cats.id( catname );
261 if ( cats.remove( uid ) ) { 350 if ( cats.remove( uid ) ) {
262 emit categoryRemoved( *this, appname, uid ); 351 emit categoryRemoved( *this, appname, uid );
263 return TRUE; 352 return TRUE;
264 } 353 }
265 } 354 }
266 if ( !checkGlobal ) 355 if ( !checkGlobal )
267 return FALSE; 356 return FALSE;
268 return removeGlobalCategory( catname ); 357 return removeGlobalCategory( catname );
269} 358}
270 359
360
361/*!
362 Removes the \a uid from the application group \a appname. Returns TRUE
363 if success, FALSE if not found.
364*/
271bool Categories::removeCategory( const QString &appname, int uid ) 365bool Categories::removeCategory( const QString &appname, int uid )
272{ 366{
273 QMap< QString, CategoryGroup >::Iterator 367 QMap< QString, CategoryGroup >::Iterator
274 appIt = mAppCats.find( appname ); 368 appIt = mAppCats.find( appname );
275 if ( appIt != mAppCats.end() ) { 369 if ( appIt != mAppCats.end() ) {
276 CategoryGroup &cats = *appIt; 370 CategoryGroup &cats = *appIt;
277 if ( cats.remove( uid ) ) { 371 if ( cats.remove( uid ) ) {
278 emit categoryRemoved( *this, appname, uid ); 372 emit categoryRemoved( *this, appname, uid );
279 return TRUE; 373 return TRUE;
280 } 374 }
281 } 375 }
282 return FALSE; 376 return FALSE;
283} 377}
284 378
379/*!
380 Removes the global category \a catname. Returns TRUE
381 if success, FALSE if not found.
382*/
285bool Categories::removeGlobalCategory( const QString &catname ) 383bool Categories::removeGlobalCategory( const QString &catname )
286{ 384{
287 int uid = mGlobalCats.id( catname ); 385 int uid = mGlobalCats.id( catname );
288 if ( mGlobalCats.remove( uid ) ) { 386 if ( mGlobalCats.remove( uid ) ) {
289 emit categoryRemoved( *this, QString::null, uid ); 387 emit categoryRemoved( *this, QString::null, uid );
290 return TRUE; 388 return TRUE;
291 } 389 }
292 return FALSE; 390 return FALSE;
293} 391}
294 392
295 393/*!
394 Removes the global category \a uid. Returns TRUE
395 if success, FALSE if not found.
396*/
296bool Categories::removeGlobalCategory( int uid ) 397bool Categories::removeGlobalCategory( int uid )
297{ 398{
298 if ( mGlobalCats.remove( uid ) ) { 399 if ( mGlobalCats.remove( uid ) ) {
299 emit categoryRemoved( *this, QString::null, uid ); 400 emit categoryRemoved( *this, QString::null, uid );
300 return TRUE; 401 return TRUE;
301 } 402 }
302 return FALSE; 403 return FALSE;
303} 404}
304 405
305/** Returns the sorted list of all categories that are associated with 406/*!
306 * the app. If includeGlobal parameter is TRUE then the returned 407 Returns the sorted list of all categories that are associated with
307 * categories will include the global category items. 408 the \a app. If \a includeGlobal is TRUE then the returned
409 categories will include the global category items.
308 */ 410 */
309QStringList Categories::labels( const QString &app, 411QStringList Categories::labels( const QString &app,
310 bool includeGlobal, 412 bool includeGlobal,
311 ExtraLabels extra ) const 413 ExtraLabels extra ) const
312{ 414{
313 QMap< QString, CategoryGroup >::ConstIterator 415 QMap< QString, CategoryGroup >::ConstIterator
314 appIt = mAppCats.find( app ); 416 appIt = mAppCats.find( app );
315 QStringList cats; 417 QStringList cats;
316 418
317 if ( appIt != mAppCats.end() ) 419 if ( appIt != mAppCats.end() )
318 cats += (*appIt).labels(); 420 cats += (*appIt).labels();
319 else qDebug("Categories::labels didn't find app %s", app.latin1() ); 421 //else qDebug("Categories::labels didn't find app %s", app.latin1() );
320 if ( includeGlobal ) 422 if ( includeGlobal )
321 cats += mGlobalCats.labels(); 423 cats += mGlobalCats.labels();
322 424
323 cats.sort(); 425 cats.sort();
324 switch ( extra ) { 426 switch ( extra ) {
325 case NoExtra: break; 427 case NoExtra: break;
326 case AllUnfiled: 428 case AllUnfiled:
327 cats.append( tr("All") ); 429 cats.append( tr("All") );
328 cats.append( tr("Unfiled") ); 430 cats.append( tr("Unfiled") );
329 break; 431 break;
330 case AllLabel: 432 case AllLabel:
331 cats.append( tr("All") ); 433 cats.append( tr("All") );
332 break; 434 break;
333 case UnfiledLabel: 435 case UnfiledLabel:
334 cats.append( tr("Unfiled") ); 436 cats.append( tr("Unfiled") );
335 break; 437 break;
336 } 438 }
337 439
338 return cats; 440 return cats;
339} 441}
340 442
443/*!
444 Returns the label associated with the id
445*/
341QString Categories::label( const QString &app, int id ) const 446QString Categories::label( const QString &app, int id ) const
342{ 447{
343 if ( mGlobalCats.contains( id ) ) 448 if ( mGlobalCats.contains( id ) )
344 return mGlobalCats.label( id ); 449 return mGlobalCats.label( id );
345 QMap< QString, CategoryGroup >::ConstIterator 450 QMap< QString, CategoryGroup >::ConstIterator
346 appIt = mAppCats.find( app ); 451 appIt = mAppCats.find( app );
347 if ( appIt == mAppCats.end() ) 452 if ( appIt == mAppCats.end() )
348 return QString::null; 453 return QString::null;
349 return (*appIt).label( id ); 454 return (*appIt).label( id );
350} 455}
351 456
352/** Returns a single string associated with the cat ids for display in 457/*!
353 * a combobox or any area that requires one string. If catids are empty 458 Returns a single string associated with \a catids for display in a
354 * then "Unfiled" will be returned. If multiple categories are assigned 459 combobox or any area that requires one string. If \a catids are empty
355 * the first cat id is shown with " (multi)" appended to the string. 460 then "Unfiled" will be returned. If multiple categories are
356 */ 461 assigned then the behavior depends on the DisplaySingle type.
462
463 If \a display is set to ShowMulti then " (multi)" appended to the
464 first string. If \a display is set to ShowAll, then a space
465 seperated string is returned with all categories. If ShowFirst is
466 set, the just the first string is returned.
467*/
357QString Categories::displaySingle( const QString &app, 468QString Categories::displaySingle( const QString &app,
358 const QArray<int> &catids, 469 const QArray<int> &catids,
359 DisplaySingle display ) const 470 DisplaySingle display ) const
360{ 471{
361 QStringList strs = labels( app, catids ); 472 QStringList strs = labels( app, catids );
362 if ( !strs.count() ) 473 if ( !strs.count() )
363 return tr("Unfiled"); 474 return tr("Unfiled");
364 strs.sort(); 475 strs.sort();
365 QString r; 476 QString r;
366 if ( strs.count() > 1 ) { 477 if ( strs.count() > 1 ) {
367 switch ( display ) { 478 switch ( display ) {
368 case ShowFirst: 479 case ShowFirst:
369 r = strs.first(); 480 r = strs.first();
370 break; 481 break;
371 case ShowMulti: 482 case ShowMulti:
372 r = strs.first() + tr(" (multi.)"); 483 r = strs.first() + tr(" (multi.)");
373 break; 484 break;
374 case ShowAll: 485 case ShowAll:
375 r = strs.join(" "); 486 r = strs.join(" ");
376 break; 487 break;
377 } 488 }
378 } 489 }
379 else r = strs.first(); 490 else r = strs.first();
380 return r; 491 return r;
381} 492}
382 493
494/*!
495
496 Returns all ids associated with the application CategoryGroup \a app
497 and the passed in \a labels in that group.
498*/
383QArray<int> Categories::ids( const QString &app, const QStringList &labels) const 499QArray<int> Categories::ids( const QString &app, const QStringList &labels) const
384{ 500{
385 QArray<int> results; 501 QArray<int> results;
386 QStringList::ConstIterator it; 502 QStringList::ConstIterator it;
387 int i; 503 int i;
388 504
389 for ( i=0, it=labels.begin(); it!=labels.end(); i++, ++it ) { 505 for ( i=0, it=labels.begin(); it!=labels.end(); i++, ++it ) {
390 int value = id( app, *it ); 506 int value = id( app, *it );
391 if ( value != 0 ) { 507 if ( value != 0 ) {
392 int tmp = results.size(); 508 int tmp = results.size();
393 results.resize( tmp + 1 ); 509 results.resize( tmp + 1 );
394 results[ tmp ] = value; 510 results[ tmp ] = value;
395 } 511 }
396 } 512 }
397 return results; 513 return results;
398} 514}
399 515
516/*!
517 Returns the id associated with the app. If the id is not found in the
518 application CategoryGroup, then it searches the global CategoryGroup.
519 If it is not found it either, 0 is returned.
520*/
400int Categories::id( const QString &app, const QString &cat ) const 521int Categories::id( const QString &app, const QString &cat ) const
401{ 522{
402 if ( cat == tr("Unfiled") || cat.contains( tr(" (multi.)") ) ) 523 if ( cat == tr("Unfiled") || cat.contains( tr(" (multi.)") ) )
403 return 0; 524 return 0;
404 int uid = mGlobalCats.id( cat ); 525 int uid = mGlobalCats.id( cat );
405 if ( uid != 0 ) 526 if ( uid != 0 )
406 return uid; 527 return uid;
407 return mAppCats[app].id( cat ); 528 return mAppCats[app].id( cat );
408} 529}
409 530
410 531
411/** Return TRUE if renaming succeeded; FALSE if app name not found, 532/*!
412 * or if there was a name conflict 533 Return TRUE if renaming succeeded; FALSE if \a appname or \a oldName
534 is not found, or if \a newName conflicts with an existing category
535 in the CategoryGroup.
536
537 It will first search the CategoryGroup associated with \a appname
538 and if not found it will try to replace in global CategoryGroup.
413 */ 539 */
414bool Categories::renameCategory( const QString &appname, 540bool Categories::renameCategory( const QString &appname,
415 const QString &oldName, 541 const QString &oldName,
416 const QString &newName ) 542 const QString &newName )
417{ 543{
418 QMap< QString, CategoryGroup >::Iterator 544 QMap< QString, CategoryGroup >::Iterator
419 appIt = mAppCats.find( appname ); 545 appIt = mAppCats.find( appname );
420 546
421 if ( appIt != mAppCats.end() ) { 547 if ( appIt != mAppCats.end() ) {
422 CategoryGroup &cats = *appIt; 548 CategoryGroup &cats = *appIt;
423 int id = cats.id( oldName ); 549 int id = cats.id( oldName );
424 if ( id != 0 && cats.rename( id, newName ) ) { 550 if ( id != 0 && cats.rename( id, newName ) ) {
425 emit categoryRenamed( *this, appname, id ); 551 emit categoryRenamed( *this, appname, id );
426 return TRUE; 552 return TRUE;
427 } 553 }
428 } 554 }
429 return renameGlobalCategory( oldName, newName ); 555 return renameGlobalCategory( oldName, newName );
430} 556}
431 557
558/*!
559 Return TRUE if renaming succeeded; FALSE if \a appname or \a oldName
560 is not found, or if \a newName conflicts with an existing category
561 in the CategoryGroup. This function will only rename categories found
562 in the global CategoryGroup.
563 */
432bool Categories::renameGlobalCategory( const QString &oldName, 564bool Categories::renameGlobalCategory( const QString &oldName,
433 const QString &newName ) 565 const QString &newName )
434{ 566{
435 int uid = mGlobalCats.id( oldName ); 567 int uid = mGlobalCats.id( oldName );
436 if ( uid != 0 && mGlobalCats.rename( uid, newName ) ) { 568 if ( uid != 0 && mGlobalCats.rename( uid, newName ) ) {
437 emit categoryRenamed( *this, QString::null, uid ); 569 emit categoryRenamed( *this, QString::null, uid );
438 return TRUE; 570 return TRUE;
439 } 571 }
440 return FALSE; 572 return FALSE;
441} 573}
442 574
575/*!
576 Changes the grouping of a category. If a category was global and \a global
577 is set to TRUE, then the \a catname will be moved to the \a appname group.
578*/
443void Categories::setGlobal( const QString &appname, 579void Categories::setGlobal( const QString &appname,
444 const QString &catname, 580 const QString &catname,
445 bool global ) 581 bool global )
446{ 582{
447 // if in global and should be in app; then move it 583 // if in global and should be in app; then move it
448 if ( mGlobalCats.contains( catname ) && !global ) { 584 if ( mGlobalCats.contains( catname ) && !global ) {
449 mGlobalCats.remove( catname ); 585 mGlobalCats.remove( catname );
450 addCategory( appname, catname ); 586 addCategory( appname, catname );
451 return ; 587 return ;
452 } 588 }
453 589
454 // if in app and should be in global, then move it 590 // if in app and should be in global, then move it
455 if ( !global ) 591 if ( !global )
456 return; 592 return;
457 if ( removeCategory( appname, catname, FALSE ) ) 593 if ( removeCategory( appname, catname, FALSE ) )
458 addGlobalCategory( catname ); 594 addGlobalCategory( catname );
459} 595}
460 596
597/*!
598 Returns TRUE if the \a catname is in the global CategoryGroup, FALSE if not.
599*/
461bool Categories::isGlobal( const QString &catname ) const 600bool Categories::isGlobal( const QString &catname ) const
462{ 601{
463 return mGlobalCats.contains( catname ); 602 return mGlobalCats.contains( catname );
464} 603}
465 604
466 605
467/** Returns true if the catname is associated with any application 606/*!
607 Returns true if the \a catname is associated with any CategoryGroup,
608 including global.
468 */ 609 */
469bool Categories::exists( const QString &catname ) const 610bool Categories::exists( const QString &catname ) const
470{ 611{
471 if ( isGlobal(catname) ) 612 if ( isGlobal(catname) )
472 return TRUE; 613 return TRUE;
473 614
474 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) 615 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt )
475 if ( exists( appsIt.key(), catname ) ) 616 if ( exists( appsIt.key(), catname ) )
476 return TRUE; 617 return TRUE;
477 618
478 return FALSE; 619 return FALSE;
479} 620}
480 621
622/*!
623 Returns TRUE if the \a catname is associated with the \a appname
624 CategoryGroup, FALSE if not found.
625 */
481bool Categories::exists( const QString &appname, 626bool Categories::exists( const QString &appname,
482 const QString &catname) const 627 const QString &catname) const
483{ 628{
484 QMap< QString, CategoryGroup >::ConstIterator 629 QMap< QString, CategoryGroup >::ConstIterator
485 appIt = mAppCats.find( appname ); 630 appIt = mAppCats.find( appname );
486 631
487 if ( appIt == mAppCats.end() ) 632 if ( appIt == mAppCats.end() )
488 return FALSE; 633 return FALSE;
489 634
490 return (*appIt).contains( catname ); 635 return (*appIt).contains( catname );
491} 636}
492 637
638/*!
639 Saves the Categories database to the \a fname. See categoryFileName()
640 for the default file name string used for the shared category database.
493 641
642 Returns FALSE if there is error writing the file or TRUE on success.
643 */
494bool Categories::save( const QString &fname ) const 644bool Categories::save( const QString &fname ) const
495{ 645{
496 QString strNewFile = fname + ".new"; 646 QString strNewFile = fname + ".new";
497 QFile f( strNewFile ); 647 QFile f( strNewFile );
498 QString out; 648 QString out;
499 int total_written; 649 int total_written;
500 650
501 if ( !f.open( IO_WriteOnly|IO_Raw ) ) { 651 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
502 qWarning("Unable to write to %s", fname.latin1()); 652 qWarning("Unable to write to %s", fname.latin1());
503 return FALSE; 653 return FALSE;
504 } 654 }
505 655
506 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 656 out = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
507 out += "<!DOCTYPE CategoryList>\n"; 657 out += "<!DOCTYPE CategoryList>\n";
508 658
509 out += "<Categories>\n"; 659 out += "<Categories>\n";
510 660
511 for ( QMap<int, QString>::ConstIterator git = mGlobalCats.idMap().begin(); 661 for ( QMap<int, QString>::ConstIterator git = mGlobalCats.idMap().begin();
512 git != mGlobalCats.idMap().end(); ++git ) 662 git != mGlobalCats.idMap().end(); ++git )
513 out += "<Category id=\"" + QString::number(git.key()) + "\"" + 663 out += "<Category id=\"" + QString::number(git.key()) + "\"" +
514 " name=\"" + escapeString(*git) + "\" />\n"; 664 " name=\"" + escapeString(*git) + "\" />\n";
515 665
516 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt=mAppCats.begin(); 666 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt=mAppCats.begin();
517 appsIt != mAppCats.end(); ++appsIt ) { 667 appsIt != mAppCats.end(); ++appsIt ) {
518 const QString &app = appsIt.key(); 668 const QString &app = appsIt.key();
519 const QMap<int, QString> &appcats = (*appsIt).idMap(); 669 const QMap<int, QString> &appcats = (*appsIt).idMap();
520 for ( QMap<int, QString>::ConstIterator appcatit = appcats.begin(); 670 for ( QMap<int, QString>::ConstIterator appcatit = appcats.begin();
521 appcatit != appcats.end(); ++appcatit ) 671 appcatit != appcats.end(); ++appcatit )
522 out += "<Category id=\"" + QString::number(appcatit.key()) + "\"" + 672 out += "<Category id=\"" + QString::number(appcatit.key()) + "\"" +
523 " app=\"" + escapeString(app) + "\"" + 673 " app=\"" + escapeString(app) + "\"" +
524 " name=\"" + escapeString(*appcatit) + "\" />\n"; 674 " name=\"" + escapeString(*appcatit) + "\" />\n";
525 } 675 }
526 out += "</Categories>\n"; 676 out += "</Categories>\n";
527 677
528 QCString cstr = out.utf8(); 678 QCString cstr = out.utf8();
529 total_written = f.writeBlock( cstr.data(), cstr.length() ); 679 total_written = f.writeBlock( cstr.data(), cstr.length() );
530 if ( total_written != int(cstr.length()) ) { 680 if ( total_written != int(cstr.length()) ) {
531 f.close(); 681 f.close();
532 QFile::remove( strNewFile ); 682 QFile::remove( strNewFile );
533 return FALSE; 683 return FALSE;
534 } 684 }
535 f.close(); 685 f.close();
536 686
687#ifdef Q_OS_WIN32
688 QFile::remove( fname );
689#endif
537 if ( ::rename( strNewFile.latin1(), fname.latin1() ) < 0 ) { 690 if ( ::rename( strNewFile.latin1(), fname.latin1() ) < 0 ) {
538 qWarning( "problem renaming file %s to %s", 691 qWarning( "problem renaming file %s to %s",
539 strNewFile.latin1(), fname.latin1()); 692 strNewFile.latin1(), fname.latin1());
540 // remove the tmp file... 693 // remove the tmp file...
541 QFile::remove( strNewFile ); 694 QFile::remove( strNewFile );
542 } 695 }
543 696
544 return TRUE; 697 return TRUE;
545} 698}
546 699
700/*!
701 Loads the Categories database using \a fname. See categoryFileName()
702 for the default file name string used for the shared category database.
703
704 Returns FALSE if there is error reading the file or TRUE on success.
705 */
547bool Categories::load( const QString &fname ) 706bool Categories::load( const QString &fname )
548{ 707{
549 QFile file( fname ); 708 QFile file( fname );
550 if ( !file.open( IO_ReadOnly ) ) { 709 if ( !file.open( IO_ReadOnly ) ) {
551 qWarning("Unable to open %s", fname.latin1()); 710 qWarning("Unable to open %s", fname.latin1());
552 711
553 addGlobalCategory(tr("Business")); 712 addGlobalCategory(tr("Business"));
554 addGlobalCategory(tr("Personal")); 713 addGlobalCategory(tr("Personal"));
555 save(fname); 714 save(fname);
556 715
557 return FALSE; 716 return FALSE;
558 } 717 }
559 718
560 clear(); 719 clear();
561 QByteArray ba = file.readAll(); 720 QByteArray ba = file.readAll();
562 QString data = QString::fromUtf8( ba.data(), ba.size() ); 721 QString data = QString::fromUtf8( ba.data(), ba.size() );
563 QChar *uc = (QChar *)data.unicode(); 722 QChar *uc = (QChar *)data.unicode();
564 int len = data.length(); 723 int len = data.length();
565 724
566 // QTime t; 725 // QTime t;
567 // t.start(); 726 // t.start();
568 QString name; 727 QString name;
569 QString id; 728 QString id;
570 QString app; 729 QString app;
571 int i = 0; 730 int i = 0;
572 while ( (i = data.find( "<Category ", i)) != -1 ) { 731 while ( (i = data.find( "<Category ", i)) != -1 ) {
573 732
574 i += 10; 733 i += 10;
575 name = QString::null; 734 name = QString::null;
576 app = QString::null; 735 app = QString::null;
577 while ( 1 ) { 736 while ( 1 ) {
578 // skip white space 737 // skip white space
579 while ( i < len && 738 while ( i < len &&
580 (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') ) 739 (uc[i] == ' ' || uc[i] == '\n' || uc[i] == '\r') )
581 i++; 740 i++;
582 // if at the end, then done 741 // if at the end, then done
583 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') ) 742 if ( i >= len-2 || (uc[i] == '/' && uc[i+1] == '>') )
584 break; 743 break;
585 // we have another attribute read it. 744 // we have another attribute read it.
586 int j = i; 745 int j = i;
587 while ( j < len && uc[j] != '=' ) 746 while ( j < len && uc[j] != '=' )
588 j++; 747 j++;
589 QString attr = QConstString( uc+i, j-i ).string(); 748 QString attr = QConstString( uc+i, j-i ).string();
590 i = ++j; // skip = 749 i = ++j; // skip =
591 while ( i < len && uc[i] != '"' ) 750 while ( i < len && uc[i] != '"' )
592 i++; 751 i++;
593 j = ++i; 752 j = ++i;
594 while ( j < len && uc[j] != '"' ) 753 while ( j < len && uc[j] != '"' )
595 j++; 754 j++;
596 QString value = Qtopia::plainString( QConstString( uc+i, j-i ).string() ); 755 QString value = Qtopia::plainString( QConstString( uc+i, j-i ).string() );
597 i = j + 1; 756 i = j + 1;
598 757
599 // qDebug("attr='%s' value='%s'", attr.latin1(), value.latin1() ); 758 // qDebug("attr='%s' value='%s'", attr.latin1(), value.latin1() );
600 if ( attr == "id" ) 759 if ( attr == "id" )
601 id = value; 760 id = value;
602 else if ( attr == "app" ) 761 else if ( attr == "app" )
603 app = value; 762 app = value;
604 763
605 else if ( attr == "name" ) 764 else if ( attr == "name" )
606 name = value; 765 name = value;
607 } 766 }
608 767
609 if ( name.isNull() || id.isNull() ) { 768 if ( name.isNull() || id.isNull() ) {
610 qWarning("No name or id in the category"); 769 qWarning("No name or id in the category");
611 continue; 770 continue;
612 } 771 }
613 if ( app.isNull() ) 772 if ( app.isNull() )
614 mGlobalCats.add( id.toInt(), name ); 773 mGlobalCats.add( id.toInt(), name );
615 else 774 else
616 mAppCats[ app ].add( id.toInt(), name ); 775 mAppCats[ app ].add( id.toInt(), name );
617 } 776 }
618 777
619 return TRUE; 778 return TRUE;
620} 779}
621 780
781/*!
782 Clear the categories in memory. Equivelent to creating an empty Categories
783 object.
784*/
622void Categories::clear() 785void Categories::clear()
623{ 786{
624 mGlobalCats.clear(); 787 mGlobalCats.clear();
625 mAppCats.clear(); 788 mAppCats.clear();
626} 789}
627 790
791/*!
792 Dump the contents to standard out. Used for debugging only.
793*/
628void Categories::dump() const 794void Categories::dump() const
629{ 795{
630 qDebug("\tglobal categories = %s", mGlobalCats.labels().join(", ").latin1() ); 796 qDebug("\tglobal categories = %s", mGlobalCats.labels().join(", ").latin1() );
631 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) { 797 for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) {
632 const QString &app = appsIt.key(); 798 const QString &app = appsIt.key();
633 QStringList appcats = (*appsIt).labels(); 799 QStringList appcats = (*appsIt).labels();
634 qDebug("\tapp = %s\tcategories = %s", app.latin1(), 800 qDebug("\tapp = %s\tcategories = %s", app.latin1(),
635 appcats.join(", ").latin1() ); 801 appcats.join(", ").latin1() );
636 802
637 } 803 }
638} 804}
639 805
640QStringList CheckedListView::checked() const 806QStringList CheckedListView::checked() const
641{ 807{
642 QStringList strs; 808 QStringList strs;
643 for ( QCheckListItem *i = (QCheckListItem *) firstChild(); 809 for ( QCheckListItem *i = (QCheckListItem *) firstChild();
644 i; i = (QCheckListItem *)i->nextSibling() ) 810 i; i = (QCheckListItem *)i->nextSibling() )
645 if ( i->isOn() ) 811 if ( i->isOn() )
646 strs += i->text( 0 ); 812 strs += i->text( 0 );
647 return strs; 813 return strs;
648} 814}
649 815
650void CheckedListView::addCheckableList( const QStringList &options ) 816void CheckedListView::addCheckableList( const QStringList &options )
651{ 817{
652 for ( QStringList::ConstIterator it = options.begin(); 818 for ( QStringList::ConstIterator it = options.begin();
653 it != options.end(); ++it ) { 819 it != options.end(); ++it ) {
654 (void) new QCheckListItem( this, *it, 820 (void) new QCheckListItem( this, *it,
655 QCheckListItem::CheckBox ); 821 QCheckListItem::CheckBox );
656 } 822 }
657} 823}
658 824
659void CheckedListView::setChecked( const QStringList &checked ) 825void CheckedListView::setChecked( const QStringList &checked )
660{ 826{
661 // iterate over all items 827 // iterate over all items
662 bool showingChecked = FALSE; 828 bool showingChecked = FALSE;
663 for ( QCheckListItem *i = (QCheckListItem *) firstChild(); 829 for ( QCheckListItem *i = (QCheckListItem *) firstChild();
664 i; i = (QCheckListItem *)i->nextSibling() ) 830 i; i = (QCheckListItem *)i->nextSibling() )
665 // see if the item should be checked by searching the 831 // see if the item should be checked by searching the
666 // checked list 832 // checked list
667 if ( checked.find( i->text( 0 ) ) != checked.end() ) { 833 if ( checked.find( i->text( 0 ) ) != checked.end() ) {
668 i->setOn( TRUE ); 834 i->setOn( TRUE );
669 // make sure it is showing at least one checked item 835 // make sure it is showing at least one checked item
670 if ( !showingChecked ) { 836 if ( !showingChecked ) {
671 ensureItemVisible( i ); 837 ensureItemVisible( i );
672 showingChecked = TRUE; 838 showingChecked = TRUE;
673 } 839 }
674 } 840 }
675 else 841 else
676 i->setOn( FALSE ); 842 i->setOn( FALSE );
677} 843}
844
845/*! \fn Categories &Categories::operator= ( const Categories &c )
846
847 Performs deep copy.
848 */
849
850
851/*! \fn QStringList Categories::labels( const QString & app, const QArray<int> &catids ) const
852
853 Returns list of labels associated with the application and catids
854*/
855
856/*! \fn QStringList Categories::globalCategories() const
857
858 Returns list of all global category labels
859*/
860
861/*! \fn const QMap<QString, CategoryGroup> &Categories::appGroupMap() const
862
863 Returns a map of application names to CategoryGroup. The CategoryGroup
864 class defines a map of ids to category labels and category labels to ids.
865*/
866
867/*! \fn const CategoryGroup &Categories::globalGroup() const
868
869 Returns the global CategoryGroup. The CategoryGroup
870 class defines a map of ids to category labels and category labels to ids.
871*/
872
873/*! \fn void Categories::categoryAdded( const Categories &cats, const QString &appname, int uid)
874
875 Emitted if a category is added.
876
877 \a cats is a const reference to this object
878 \a appname is the CategoryGroup application name that the category was added to or QString::null if it was global
879 \a uid is the unique identifier associated with the added category
880 */
881
882/*! \fn void Categories::categoryRemoved( const Categories &cats, const QString &appname,
883 int uid)
884
885 Emitted if removed category is removed.
886
887 \a cats is a const reference to this object
888 \a appname is the CategoryGroup application name that the category was removed from or QString::null if it was the global CategoryGroup
889 \a uid is the unique identifier associated with the removed category
890*/
891
892
893/*! \fn void Categories::categoryRenamed( const Categories &cats, const QString &appname,
894 int uid)
895
896 Emitted if \a uid in the \a appname CategoryGroup is renamed in \a cats
897 object.
898
899 \a cats is a const reference to this object
900 \a appname is the CategoryGroup application name that the category was renamed in or QString::null if it was the global CategoryGroup
901 \a uid is the unique identifier associated with the renamed category
902*/
903
904/*! \fn Categories::Categories( QObject *parent=0, const char *name = 0 )
905
906 Constructor for an empty Categories object.
907*/
908
909/*! \fn Categories::Categories( const Categories &copyFrom )
910
911 Deep copy constructor
912*/
913
914/*! \fn Categories::~Categories()
915
916 Empty destructor. Call save() before destruction if there are changes
917 that need to be saved.
918*/
919
920/*! \fn CategoryGroup::clear()
921 \internal
922*/
923
924/*! \fn const QMap<int, QString> &CategoryGroup::idMap() const
925
926 Returns a const reference to the id to label QMap
927*/
928
929/*! \fn CategoryGroup::CategoryGroup()
930 \internal
931*/
932
933/*! \fn CategoryGroup::CategoryGroup(const CategoryGroup &c)
934 \internal
935*/
936
diff --git a/library/backend/contact.cpp b/library/backend/contact.cpp
index b10b19a..3f4934a 100644
--- a/library/backend/contact.cpp
+++ b/library/backend/contact.cpp
@@ -1,924 +1,1408 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#define QTOPIA_INTERNAL_CONTACT_MRE 21#define QTOPIA_INTERNAL_CONTACT_MRE
22 22
23#include "contact.h" 23#include "contact.h"
24#include "vobject_p.h" 24#include "vobject_p.h"
25#include "qfiledirect_p.h" 25#include "qfiledirect_p.h"
26 26
27#include <qpe/stringutil.h> 27#include <qpe/stringutil.h>
28#include <qpe/timeconversion.h> 28#include <qpe/timeconversion.h>
29 29
30#include <qobject.h> 30#include <qobject.h>
31#include <qregexp.h> 31#include <qregexp.h>
32#include <qstylesheet.h> 32#include <qstylesheet.h>
33#include <qfileinfo.h> 33#include <qfileinfo.h>
34 34
35#include <stdio.h> 35#include <stdio.h>
36 36
37/*!
38 \class Contact contact.h
39 \brief The Contact class holds the data of an address book entry.
40
41 This data includes information the name of the person, contact
42 information, and business information such as deparment and job title.
43
44 \ingroup qtopiaemb
45 \ingroup qtopiadesktop
46*/
47
37Qtopia::UidGen Contact::sUidGen( Qtopia::UidGen::Qtopia ); 48Qtopia::UidGen Contact::sUidGen( Qtopia::UidGen::Qtopia );
38 49
50/*!
51 Creates a new, empty contact.
52*/
39Contact::Contact() 53Contact::Contact()
40 : Record(), mMap(), d( 0 ) 54 : Record(), mMap(), d( 0 )
41{ 55{
42} 56}
43 57
58/*!
59 \internal
60 Creates a new contact. The properties of the contact are
61 set from \a fromMap.
62*/
44Contact::Contact( const QMap<int, QString> &fromMap ) : 63Contact::Contact( const QMap<int, QString> &fromMap ) :
45 Record(), mMap( fromMap ), d( 0 ) 64 Record(), mMap( fromMap ), d( 0 )
46{ 65{
47 QString cats = mMap[ Qtopia::AddressCategory ]; 66 QString cats = mMap[ Qtopia::AddressCategory ];
48 if ( !cats.isEmpty() ) 67 if ( !cats.isEmpty() )
49 setCategories( idsFromString( cats ) ); 68 setCategories( idsFromString( cats ) );
50 QString uidStr = find( Qtopia::AddressUid ); 69 QString uidStr = find( Qtopia::AddressUid );
70
51 if ( uidStr.isEmpty() ) 71 if ( uidStr.isEmpty() )
52 setUid( uidGen().generate() ); 72 setUid( uidGen().generate() );
53 else 73 else
54 setUid( uidStr.toInt() ); 74 setUid( uidStr.toInt() );
75
76 if ( !uidStr.isEmpty() )
77 setUid( uidStr.toInt() );
55} 78}
56 79
80/*!
81 Destroys a contact.
82*/
57Contact::~Contact() 83Contact::~Contact()
58{ 84{
59} 85}
60 86
87/*! \fn void Contact::setTitle( const QString &str )
88 Sets the title of the contact to \a str.
89*/
90
91/*! \fn void Contact::setFirstName( const QString &str )
92 Sets the first name of the contact to \a str.
93*/
94
95/*! \fn void Contact::setMiddleName( const QString &str )
96 Sets the middle name of the contact to \a str.
97*/
98
99/*! \fn void Contact::setLastName( const QString &str )
100 Sets the last name of the contact to \a str.
101*/
102
103/*! \fn void Contact::setSuffix( const QString &str )
104 Sets the suffix of the contact to \a str.
105*/
106
107/*! \fn void Contact::setFileAs( const QString &str )
108 Sets the contact to filed as \a str.
109*/
110
111/*! \fn void Contact::setDefaultEmail( const QString &str )
112 Sets the default email of the contact to \a str.
113*/
114
115/*! \fn void Contact::setHomeStreet( const QString &str )
116 Sets the home street address of the contact to \a str.
117*/
118
119/*! \fn void Contact::setHomeCity( const QString &str )
120 Sets the home city of the contact to \a str.
121*/
122
123/*! \fn void Contact::setHomeState( const QString &str )
124 Sets the home state of the contact to \a str.
125*/
126
127/*! \fn void Contact::setHomeZip( const QString &str )
128 Sets the home zip code of the contact to \a str.
129*/
130
131/*! \fn void Contact::setHomeCountry( const QString &str )
132 Sets the home country of the contact to \a str.
133*/
134
135/*! \fn void Contact::setHomePhone( const QString &str )
136 Sets the home phone number of the contact to \a str.
137*/
138
139/*! \fn void Contact::setHomeFax( const QString &str )
140 Sets the home fax number of the contact to \a str.
141*/
142
143/*! \fn void Contact::setHomeMobile( const QString &str )
144 Sets the home mobile phone number of the contact to \a str.
145*/
146
147/*! \fn void Contact::setHomeWebpage( const QString &str )
148 Sets the home webpage of the contact to \a str.
149*/
150
151/*! \fn void Contact::setCompany( const QString &str )
152 Sets the company for contact to \a str.
153*/
154
155/*! \fn void Contact::setJobTitle( const QString &str )
156 Sets the job title of the contact to \a str.
157*/
158
159/*! \fn void Contact::setDepartment( const QString &str )
160 Sets the department for contact to \a str.
161*/
162
163/*! \fn void Contact::setOffice( const QString &str )
164 Sets the office for contact to \a str.
165*/
166
167/*! \fn void Contact::setBusinessStreet( const QString &str )
168 Sets the business street address of the contact to \a str.
169*/
170
171/*! \fn void Contact::setBusinessCity( const QString &str )
172 Sets the business city of the contact to \a str.
173*/
174
175/*! \fn void Contact::setBusinessState( const QString &str )
176 Sets the business state of the contact to \a str.
177*/
178
179/*! \fn void Contact::setBusinessZip( const QString &str )
180 Sets the business zip code of the contact to \a str.
181*/
182
183/*! \fn void Contact::setBusinessCountry( const QString &str )
184 Sets the business country of the contact to \a str.
185*/
186
187/*! \fn void Contact::setBusinessPhone( const QString &str )
188 Sets the business phone number of the contact to \a str.
189*/
190
191/*! \fn void Contact::setBusinessFax( const QString &str )
192 Sets the business fax number of the contact to \a str.
193*/
194
195/*! \fn void Contact::setBusinessMobile( const QString &str )
196 Sets the business mobile phone number of the contact to \a str.
197*/
198
199/*! \fn void Contact::setBusinessPager( const QString &str )
200 Sets the business pager number of the contact to \a str.
201*/
202
203/*! \fn void Contact::setBusinessWebpage( const QString &str )
204 Sets the business webpage of the contact to \a str.
205*/
206
207/*! \fn void Contact::setProfession( const QString &str )
208 Sets the profession of the contact to \a str.
209*/
210
211/*! \fn void Contact::setAssistant( const QString &str )
212 Sets the assistant of the contact to \a str.
213*/
214
215/*! \fn void Contact::setManager( const QString &str )
216 Sets the manager of the contact to \a str.
217*/
218
219/*! \fn void Contact::setSpouse( const QString &str )
220 Sets the spouse of the contact to \a str.
221*/
222
223/*! \fn void Contact::setGender( const QString &str )
224 Sets the gender of the contact to \a str.
225*/
226
227/*! \fn void Contact::setBirthday( const QString &str )
228 Sets the birthday for the contact to \a str.
229*/
230
231/*! \fn void Contact::setAnniversary( const QString &str )
232 Sets the anniversary of the contact to \a str.
233*/
234
235/*! \fn void Contact::setNickname( const QString &str )
236 Sets the nickname of the contact to \a str.
237*/
238
239/*! \fn void Contact::setNotes( const QString &str )
240 Sets the notes about the contact to \a str.
241*/
242
243/*! \fn QString Contact::title() const
244 Returns the title of the contact.
245*/
246
247/*! \fn QString Contact::firstName() const
248 Returns the first name of the contact.
249*/
250
251/*! \fn QString Contact::middleName() const
252 Returns the middle name of the contact.
253*/
254
255/*! \fn QString Contact::lastName() const
256 Returns the last name of the contact.
257*/
258
259/*! \fn QString Contact::suffix() const
260 Returns the suffix of the contact.
261*/
262
263/*! \fn QString Contact::fileAs() const
264 Returns the string the contact is filed as.
265*/
266
267/*! \fn QString Contact::defaultEmail() const
268 Returns the default email address of the contact.
269*/
270
271/*! \fn QString Contact::emails() const
272 Returns the list of email address for a contact separated by ';'s in a single
273 string.
274*/
275
276/*! \fn QString Contact::homeStreet() const
277 Returns the home street address of the contact.
278*/
279
280/*! \fn QString Contact::homeCity() const
281 Returns the home city of the contact.
282*/
283
284/*! \fn QString Contact::homeState() const
285 Returns the home state of the contact.
286*/
287
288/*! \fn QString Contact::homeZip() const
289 Returns the home zip of the contact.
290*/
291
292/*! \fn QString Contact::homeCountry() const
293 Returns the home country of the contact.
294*/
295
296/*! \fn QString Contact::homePhone() const
297 Returns the home phone number of the contact.
298*/
299
300/*! \fn QString Contact::homeFax() const
301 Returns the home fax number of the contact.
302*/
303
304/*! \fn QString Contact::homeMobile() const
305 Returns the home mobile number of the contact.
306*/
307
308/*! \fn QString Contact::homeWebpage() const
309 Returns the home webpage of the contact.
310*/
311
312/*! \fn QString Contact::company() const
313 Returns the company for the contact.
314*/
315
316/*! \fn QString Contact::department() const
317 Returns the department for the contact.
318*/
319
320/*! \fn QString Contact::office() const
321 Returns the office for the contact.
322*/
323
324/*! \fn QString Contact::jobTitle() const
325 Returns the job title of the contact.
326*/
327
328/*! \fn QString Contact::profession() const
329 Returns the profession of the contact.
330*/
331
332/*! \fn QString Contact::assistant() const
333 Returns the assistant of the contact.
334*/
335
336/*! \fn QString Contact::manager() const
337 Returns the manager of the contact.
338*/
339
340/*! \fn QString Contact::businessStreet() const
341 Returns the business street address of the contact.
342*/
343
344/*! \fn QString Contact::businessCity() const
345 Returns the business city of the contact.
346*/
347
348/*! \fn QString Contact::businessState() const
349 Returns the business state of the contact.
350*/
351
352/*! \fn QString Contact::businessZip() const
353 Returns the business zip of the contact.
354*/
355
356/*! \fn QString Contact::businessCountry() const
357 Returns the business country of the contact.
358*/
359
360/*! \fn QString Contact::businessPhone() const
361 Returns the business phone number of the contact.
362*/
363
364/*! \fn QString Contact::businessFax() const
365 Returns the business fax number of the contact.
366*/
367
368/*! \fn QString Contact::businessMobile() const
369 Returns the business mobile number of the contact.
370*/
371
372/*! \fn QString Contact::businessPager() const
373 Returns the business pager number of the contact.
374*/
375
376/*! \fn QString Contact::businessWebpage() const
377 Returns the business webpage of the contact.
378*/
379
380/*! \fn QString Contact::spouse() const
381 Returns the spouse of the contact.
382*/
383
384/*! \fn QString Contact::gender() const
385 Returns the gender of the contact.
386*/
387
388/*! \fn QString Contact::birthday() const
389 Returns the birthday of the contact.
390*/
391
392/*! \fn QString Contact::anniversary() const
393 Returns the anniversary of the contact.
394*/
395
396/*! \fn QString Contact::nickname() const
397 Returns the nickname of the contact.
398*/
399
400/*! \fn QString Contact::children() const
401 Returns the children of the contact.
402*/
403
404/*! \fn QString Contact::notes() const
405 Returns the notes relating to the the contact.
406*/
407
408/*! \fn QString Contact::groups() const
409 \internal
410 Returns the groups for the contact.
411*/
412
413/*! \fn QStringList Contact::groupList() const
414 \internal
415*/
416
417/*! \fn QString Contact::field(int) const
418 \internal
419*/
420
421/*! \fn void Contact::saveJournal( journal_action, const QString & = QString::null )
422 \internal
423*/
424
425/*! \fn void Contact::setUid( int id )
426 \internal
427 Sets the uid for this record to \a id.
428*/
429
430/*! \enum Contact::journal_action
431 \internal
432*/
433
434/*!
435 \internal
436*/
61QMap<int, QString> Contact::toMap() const 437QMap<int, QString> Contact::toMap() const
62{ 438{
63 QMap<int, QString> map = mMap; 439 QMap<int, QString> map = mMap;
64 map.insert( Qtopia::AddressCategory, idsToString( categories() )); 440 QString cats = idsToString( categories() );
441 if ( !cats.isEmpty() )
442 map.insert( Qtopia::AddressCategory, cats );
65 return map; 443 return map;
66} 444}
67 445
68/*! 446/*!
69 Returns a rich text formatted QString of the Contact. 447 Returns a rich text formatted QString representing the contents the contact.
70*/ 448*/
71QString Contact::toRichText() const 449QString Contact::toRichText() const
72{ 450{
73 QString text; 451 QString text;
74 QString value, comp, state; 452 QString value, comp, state;
75 453
76 // name, jobtitle and company 454 // name, jobtitle and company
77 if ( !(value = fullName()).isEmpty() ) 455 if ( !(value = fullName()).isEmpty() )
78 text += "<b>" + Qtopia::escapeString(value) + "</b><br>"; 456 text += "<b>" + Qtopia::escapeString(value) + "</b><br>";
79 if ( !(value = jobTitle()).isEmpty() ) 457 if ( !(value = jobTitle()).isEmpty() )
80 text += Qtopia::escapeString(value) + "<br>"; 458 text += Qtopia::escapeString(value) + "<br>";
81 459
82 comp = company(); 460 comp = company();
83 if ( !(value = department()).isEmpty() ) { 461 if ( !(value = department()).isEmpty() ) {
84 text += Qtopia::escapeString(value); 462 text += Qtopia::escapeString(value);
85 if ( comp ) 463 if ( comp )
86 text += ", "; 464 text += ", ";
87 else 465 else
88 text += "<br>"; 466 text += "<br>";
89 } 467 }
90 if ( !comp.isEmpty() ) 468 if ( !comp.isEmpty() )
91 text += Qtopia::escapeString(comp) + "<br>"; 469 text += Qtopia::escapeString(comp) + "<br>";
92 470
93 // business address 471 // business address
94 if ( !businessStreet().isEmpty() || !businessCity().isEmpty() || 472 if ( !businessStreet().isEmpty() || !businessCity().isEmpty() ||
95 !businessZip().isEmpty() || !businessCountry().isEmpty() ) { 473 !businessZip().isEmpty() || !businessCountry().isEmpty() ) {
96 text += "<br>"; 474 text += "<br>";
97 text += QObject::tr( "<b>Work Address:</b>" ); 475 text += QObject::tr( "<b>Work Address:</b>" );
98 text += "<br>"; 476 text += "<br>";
99 } 477 }
100 478
101 if ( !(value = businessStreet()).isEmpty() ) 479 if ( !(value = businessStreet()).isEmpty() )
102 text += Qtopia::escapeString(value) + "<br>"; 480 text += Qtopia::escapeString(value) + "<br>";
103 state = businessState(); 481 state = businessState();
104 if ( !(value = businessCity()).isEmpty() ) { 482 if ( !(value = businessCity()).isEmpty() ) {
105 text += Qtopia::escapeString(value); 483 text += Qtopia::escapeString(value);
106 if ( state ) 484 if ( state )
107 text += ", " + Qtopia::escapeString(state); 485 text += ", " + Qtopia::escapeString(state);
108 text += "<br>"; 486 text += "<br>";
109 } else if ( !state.isEmpty() ) 487 } else if ( !state.isEmpty() )
110 text += Qtopia::escapeString(state) + "<br>"; 488 text += Qtopia::escapeString(state) + "<br>";
111 if ( !(value = businessZip()).isEmpty() ) 489 if ( !(value = businessZip()).isEmpty() )
112 text += Qtopia::escapeString(value) + "<br>"; 490 text += Qtopia::escapeString(value) + "<br>";
113 if ( !(value = businessCountry()).isEmpty() ) 491 if ( !(value = businessCountry()).isEmpty() )
114 text += Qtopia::escapeString(value) + "<br>"; 492 text += Qtopia::escapeString(value) + "<br>";
115 493
116 // home address 494 // home address
117 if ( !homeStreet().isEmpty() || !homeCity().isEmpty() || 495 if ( !homeStreet().isEmpty() || !homeCity().isEmpty() ||
118 !homeZip().isEmpty() || !homeCountry().isEmpty() ) { 496 !homeZip().isEmpty() || !homeCountry().isEmpty() ) {
119 text += "<br>"; 497 text += "<br>";
120 text += QObject::tr( "<b>Home Address:</b>" ); 498 text += QObject::tr( "<b>Home Address:</b>" );
121 text += "<br>"; 499 text += "<br>";
122 } 500 }
123 501
124 if ( !(value = homeStreet()).isEmpty() ) 502 if ( !(value = homeStreet()).isEmpty() )
125 text += Qtopia::escapeString(value) + "<br>"; 503 text += Qtopia::escapeString(value) + "<br>";
126 state = homeState(); 504 state = homeState();
127 if ( !(value = homeCity()).isEmpty() ) { 505 if ( !(value = homeCity()).isEmpty() ) {
128 text += Qtopia::escapeString(value); 506 text += Qtopia::escapeString(value);
129 if ( !state.isEmpty() ) 507 if ( !state.isEmpty() )
130 text += ", " + Qtopia::escapeString(state); 508 text += ", " + Qtopia::escapeString(state);
131 text += "<br>"; 509 text += "<br>";
132 } else if (!state.isEmpty()) 510 } else if (!state.isEmpty())
133 text += Qtopia::escapeString(state) + "<br>"; 511 text += Qtopia::escapeString(state) + "<br>";
134 if ( !(value = homeZip()).isEmpty() ) 512 if ( !(value = homeZip()).isEmpty() )
135 text += Qtopia::escapeString(value) + "<br>"; 513 text += Qtopia::escapeString(value) + "<br>";
136 if ( !(value = homeCountry()).isEmpty() ) 514 if ( !(value = homeCountry()).isEmpty() )
137 text += Qtopia::escapeString(value) + "<br>"; 515 text += Qtopia::escapeString(value) + "<br>";
138 516
139 // the others... 517 // the others...
140 QString str; 518 QString str;
141 str = emails(); 519 str = emails();
142 if ( !str.isEmpty() ) 520 if ( !str.isEmpty() )
143 text += "<b>" + QObject::tr("Email Addresses: ") + "</b>" 521 text += "<b>" + QObject::tr("Email Addresses: ") + "</b>"
144 + Qtopia::escapeString(str) + "<br>"; 522 + Qtopia::escapeString(str) + "<br>";
145 str = homePhone(); 523 str = homePhone();
146 if ( !str.isEmpty() ) 524 if ( !str.isEmpty() )
147 text += "<b>" + QObject::tr("Home Phone: ") + "</b>" 525 text += "<b>" + QObject::tr("Home Phone: ") + "</b>"
148 + Qtopia::escapeString(str) + "<br>"; 526 + Qtopia::escapeString(str) + "<br>";
149 str = homeFax(); 527 str = homeFax();
150 if ( !str.isEmpty() ) 528 if ( !str.isEmpty() )
151 text += "<b>" + QObject::tr("Home Fax: ") + "</b>" 529 text += "<b>" + QObject::tr("Home Fax: ") + "</b>"
152 + Qtopia::escapeString(str) + "<br>"; 530 + Qtopia::escapeString(str) + "<br>";
153 str = homeMobile(); 531 str = homeMobile();
154 if ( !str.isEmpty() ) 532 if ( !str.isEmpty() )
155 text += "<b>" + QObject::tr("Home Mobile: ") + "</b>" 533 text += "<b>" + QObject::tr("Home Mobile: ") + "</b>"
156 + Qtopia::escapeString(str) + "<br>"; 534 + Qtopia::escapeString(str) + "<br>";
157 str = homeWebpage(); 535 str = homeWebpage();
158 if ( !str.isEmpty() ) 536 if ( !str.isEmpty() )
159 text += "<b>" + QObject::tr("Home Web Page: ") + "</b>" 537 text += "<b>" + QObject::tr("Home Web Page: ") + "</b>"
160 + Qtopia::escapeString(str) + "<br>"; 538 + Qtopia::escapeString(str) + "<br>";
161 str = businessWebpage(); 539 str = businessWebpage();
162 if ( !str.isEmpty() ) 540 if ( !str.isEmpty() )
163 text += "<b>" + QObject::tr("Business Web Page: ") + "</b>" 541 text += "<b>" + QObject::tr("Business Web Page: ") + "</b>"
164 + Qtopia::escapeString(str) + "<br>"; 542 + Qtopia::escapeString(str) + "<br>";
165 str = office(); 543 str = office();
166 if ( !str.isEmpty() ) 544 if ( !str.isEmpty() )
167 text += "<b>" + QObject::tr("Office: ") + "</b>" 545 text += "<b>" + QObject::tr("Office: ") + "</b>"
168 + Qtopia::escapeString(str) + "<br>"; 546 + Qtopia::escapeString(str) + "<br>";
169 str = businessPhone(); 547 str = businessPhone();
170 if ( !str.isEmpty() ) 548 if ( !str.isEmpty() )
171 text += "<b>" + QObject::tr("Business Phone: ") + "</b>" 549 text += "<b>" + QObject::tr("Business Phone: ") + "</b>"
172 + Qtopia::escapeString(str) + "<br>"; 550 + Qtopia::escapeString(str) + "<br>";
173 str = businessFax(); 551 str = businessFax();
174 if ( !str.isEmpty() ) 552 if ( !str.isEmpty() )
175 text += "<b>" + QObject::tr("Business Fax: ") + "</b>" 553 text += "<b>" + QObject::tr("Business Fax: ") + "</b>"
176 + Qtopia::escapeString(str) + "<br>"; 554 + Qtopia::escapeString(str) + "<br>";
177 str = businessMobile(); 555 str = businessMobile();
178 if ( !str.isEmpty() ) 556 if ( !str.isEmpty() )
179 text += "<b>" + QObject::tr("Business Mobile: ") + "</b>" 557 text += "<b>" + QObject::tr("Business Mobile: ") + "</b>"
180 + Qtopia::escapeString(str) + "<br>"; 558 + Qtopia::escapeString(str) + "<br>";
181 str = businessPager(); 559 str = businessPager();
182 if ( !str.isEmpty() ) 560 if ( !str.isEmpty() )
183 text += "<b>" + QObject::tr("Business Pager: ") + "</b>" 561 text += "<b>" + QObject::tr("Business Pager: ") + "</b>"
184 + Qtopia::escapeString(str) + "<br>"; 562 + Qtopia::escapeString(str) + "<br>";
185 str = profession(); 563 str = profession();
186 if ( !str.isEmpty() ) 564 if ( !str.isEmpty() )
187 text += "<b>" + QObject::tr("Profession: ") + "</b>" 565 text += "<b>" + QObject::tr("Profession: ") + "</b>"
188 + Qtopia::escapeString(str) + "<br>"; 566 + Qtopia::escapeString(str) + "<br>";
189 str = assistant(); 567 str = assistant();
190 if ( !str.isEmpty() ) 568 if ( !str.isEmpty() )
191 text += "<b>" + QObject::tr("Assistant: ") + "</b>" 569 text += "<b>" + QObject::tr("Assistant: ") + "</b>"
192 + Qtopia::escapeString(str) + "<br>"; 570 + Qtopia::escapeString(str) + "<br>";
193 str = manager(); 571 str = manager();
194 if ( !str.isEmpty() ) 572 if ( !str.isEmpty() )
195 text += "<b>" + QObject::tr("Manager: ") + "</b>" 573 text += "<b>" + QObject::tr("Manager: ") + "</b>"
196 + Qtopia::escapeString(str) + "<br>"; 574 + Qtopia::escapeString(str) + "<br>";
197 str = gender(); 575 str = gender();
198 if ( !str.isEmpty() && str.toInt() != 0 ) { 576 if ( !str.isEmpty() && str.toInt() != 0 ) {
199 if ( str.toInt() == 1 ) 577 if ( str.toInt() == 1 )
200 str = QObject::tr( "Male" ); 578 str = QObject::tr( "Male" );
201 else if ( str.toInt() == 2 ) 579 else if ( str.toInt() == 2 )
202 str = QObject::tr( "Female" ); 580 str = QObject::tr( "Female" );
203 text += "<b>" + QObject::tr("Gender: ") + "</b>" + str + "<br>"; 581 text += "<b>" + QObject::tr("Gender: ") + "</b>" + str + "<br>";
204 } 582 }
205 str = spouse(); 583 str = spouse();
206 if ( !str.isEmpty() ) 584 if ( !str.isEmpty() )
207 text += "<b>" + QObject::tr("Spouse: ") + "</b>" 585 text += "<b>" + QObject::tr("Spouse: ") + "</b>"
208 + Qtopia::escapeString(str) + "<br>"; 586 + Qtopia::escapeString(str) + "<br>";
209 str = birthday(); 587 str = birthday();
210 if ( !str.isEmpty() ) 588 if ( !str.isEmpty() )
211 text += "<b>" + QObject::tr("Birthday: ") + "</b>" 589 text += "<b>" + QObject::tr("Birthday: ") + "</b>"
212 + Qtopia::escapeString(str) + "<br>"; 590 + Qtopia::escapeString(str) + "<br>";
213 str = anniversary(); 591 str = anniversary();
214 if ( !str.isEmpty() ) 592 if ( !str.isEmpty() )
215 text += "<b>" + QObject::tr("Anniversary: ") + "</b>" 593 text += "<b>" + QObject::tr("Anniversary: ") + "</b>"
216 + Qtopia::escapeString(str) + "<br>"; 594 + Qtopia::escapeString(str) + "<br>";
217 str = nickname(); 595 str = nickname();
218 if ( !str.isEmpty() ) 596 if ( !str.isEmpty() )
219 text += "<b>" + QObject::tr("Nickname: ") + "</b>" 597 text += "<b>" + QObject::tr("Nickname: ") + "</b>"
220 + Qtopia::escapeString(str) + "<br>"; 598 + Qtopia::escapeString(str) + "<br>";
221 599
222 // notes last 600 // notes last
223 if ( (value = notes()) ) { 601 if ( (value = notes()) ) {
224 QRegExp reg("\n"); 602 QRegExp reg("\n");
225 603
226 //QString tmp = Qtopia::escapeString(value); 604 //QString tmp = Qtopia::escapeString(value);
227 QString tmp = QStyleSheet::convertFromPlainText(value); 605 QString tmp = QStyleSheet::convertFromPlainText(value);
228 //tmp.replace( reg, "<br>" ); 606 //tmp.replace( reg, "<br>" );
229 text += "<br>" + tmp + "<br>"; 607 text += "<br>" + tmp + "<br>";
230 } 608 }
231 return text; 609 return text;
232} 610}
233 611
612/*!
613 \internal
614*/
234void Contact::insert( int key, const QString &v ) 615void Contact::insert( int key, const QString &v )
235{ 616{
236 QString value = v.stripWhiteSpace(); 617 QString value = v.stripWhiteSpace();
237 if ( value.isEmpty() ) 618 if ( value.isEmpty() )
238 mMap.remove( key ); 619 mMap.remove( key );
239 else 620 else
240 mMap.insert( key, value ); 621 mMap.insert( key, value );
241} 622}
242 623
624/*!
625 \internal
626*/
243void Contact::replace( int key, const QString & v ) 627void Contact::replace( int key, const QString & v )
244{ 628{
245 QString value = v.stripWhiteSpace(); 629 QString value = v.stripWhiteSpace();
246 if ( value.isEmpty() ) 630 if ( value.isEmpty() )
247 mMap.remove( key ); 631 mMap.remove( key );
248 else 632 else
249 mMap.replace( key, value ); 633 mMap.replace( key, value );
250} 634}
251 635
636/*!
637 \internal
638*/
252QString Contact::find( int key ) const 639QString Contact::find( int key ) const
253{ 640{
254 return mMap[key]; 641 return mMap[key];
255} 642}
256 643
644/*!
645 \internal
646*/
257QString Contact::displayAddress( const QString &street, 647QString Contact::displayAddress( const QString &street,
258 const QString &city, 648 const QString &city,
259 const QString &state, 649 const QString &state,
260 const QString &zip, 650 const QString &zip,
261 const QString &country ) const 651 const QString &country ) const
262{ 652{
263 QString s = street; 653 QString s = street;
264 if ( !street.isEmpty() ) 654 if ( !street.isEmpty() )
265 s+= "\n"; 655 s+= "\n";
266 s += city; 656 s += city;
267 if ( !city.isEmpty() && !state.isEmpty() ) 657 if ( !city.isEmpty() && !state.isEmpty() )
268 s += ", "; 658 s += ", ";
269 s += state; 659 s += state;
270 if ( !state.isEmpty() && !zip.isEmpty() ) 660 if ( !state.isEmpty() && !zip.isEmpty() )
271 s += " "; 661 s += " ";
272 s += zip; 662 s += zip;
273 if ( !country.isEmpty() && !s.isEmpty() ) 663 if ( !country.isEmpty() && !s.isEmpty() )
274 s += "\n"; 664 s += "\n";
275 s += country; 665 s += country;
276 return s; 666 return s;
277} 667}
278 668
669/*!
670 \internal
671*/
279QString Contact::displayBusinessAddress() const 672QString Contact::displayBusinessAddress() const
280{ 673{
281 return displayAddress( businessStreet(), businessCity(), 674 return displayAddress( businessStreet(), businessCity(),
282 businessState(), businessZip(), 675 businessState(), businessZip(),
283 businessCountry() ); 676 businessCountry() );
284} 677}
285 678
679/*!
680 \internal
681*/
286QString Contact::displayHomeAddress() const 682QString Contact::displayHomeAddress() const
287{ 683{
288 return displayAddress( homeStreet(), homeCity(), 684 return displayAddress( homeStreet(), homeCity(),
289 homeState(), homeZip(), 685 homeState(), homeZip(),
290 homeCountry() ); 686 homeCountry() );
291} 687}
292 688
689/*!
690 Returns the full name of the contact
691*/
293QString Contact::fullName() const 692QString Contact::fullName() const
294{ 693{
295 QString title = find( Qtopia::Title ); 694 QString title = find( Qtopia::Title );
296 QString firstName = find( Qtopia::FirstName ); 695 QString firstName = find( Qtopia::FirstName );
297 QString middleName = find( Qtopia::MiddleName ); 696 QString middleName = find( Qtopia::MiddleName );
298 QString lastName = find( Qtopia::LastName ); 697 QString lastName = find( Qtopia::LastName );
299 QString suffix = find( Qtopia::Suffix ); 698 QString suffix = find( Qtopia::Suffix );
300 699
301 QString name = title; 700 QString name = title;
302 if ( !firstName.isEmpty() ) { 701 if ( !firstName.isEmpty() ) {
303 if ( !name.isEmpty() ) 702 if ( !name.isEmpty() )
304 name += " "; 703 name += " ";
305 name += firstName; 704 name += firstName;
306 } 705 }
307 if ( !middleName.isEmpty() ) { 706 if ( !middleName.isEmpty() ) {
308 if ( !name.isEmpty() ) 707 if ( !name.isEmpty() )
309 name += " "; 708 name += " ";
310 name += middleName; 709 name += middleName;
311 } 710 }
312 if ( !lastName.isEmpty() ) { 711 if ( !lastName.isEmpty() ) {
313 if ( !name.isEmpty() ) 712 if ( !name.isEmpty() )
314 name += " "; 713 name += " ";
315 name += lastName; 714 name += lastName;
316 } 715 }
317 if ( !suffix.isEmpty() ) { 716 if ( !suffix.isEmpty() ) {
318 if ( !name.isEmpty() ) 717 if ( !name.isEmpty() )
319 name += " "; 718 name += " ";
320 name += suffix; 719 name += suffix;
321 } 720 }
322 return name.simplifyWhiteSpace(); 721 return name.simplifyWhiteSpace();
323} 722}
324 723
724/*!
725 Returns a list of the names of the children of the contact.
726*/
325QStringList Contact::childrenList() const 727QStringList Contact::childrenList() const
326{ 728{
327 return QStringList::split( " ", find( Qtopia::Children ) ); 729 return QStringList::split( " ", find( Qtopia::Children ) );
328} 730}
329 731
732/*! \fn void Contact::insertEmail( const QString &email )
733
734 Insert \a email into the email list. Ensures \a email can only be added
735 once. If there is no default email address set, it sets it to the \a email.
736*/
737
738/*! \fn void Contact::removeEmail( const QString &email )
739
740 Removes the \a email from the email list. If the default email was \a email,
741 then the default email address is assigned to the first email in the
742 email list
743*/
744
745/*! \fn void Contact::clearEmails()
746
747 Clears the email list.
748 */
749
750/*! \fn void Contact::insertEmails( const QStringList &emailList )
751
752 Appends the \a emailList to the exiting email list
753 */
754
755/*!
756 Returns a list of email addresses belonging to the contact, including
757 the default email address.
758*/
330QStringList Contact::emailList() const 759QStringList Contact::emailList() const
331{ 760{
332 return QStringList::split( ";", find( Qtopia::Emails ) ); 761 QString emailStr = emails();
762
763 QStringList r;
764 if ( !emailStr.isEmpty() ) {
765 qDebug(" emailstr ");
766 QStringList l = QStringList::split( emailSeparator(), emailStr );
767 for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
768 r += (*it).simplifyWhiteSpace();
769 }
770
771 return r;
333} 772}
334 773
774/*!
775 \overload
776
777 Generates the string for the contact to be filed as from the first,
778 middle and last name of the contact.
779*/
335void Contact::setFileAs() 780void Contact::setFileAs()
336{ 781{
337 QString lastName, firstName, middleName, fileas; 782 QString lastName, firstName, middleName, fileas;
338 783
339 lastName = find( Qtopia::LastName ); 784 lastName = find( Qtopia::LastName );
340 firstName = find( Qtopia::FirstName ); 785 firstName = find( Qtopia::FirstName );
341 middleName = find( Qtopia::MiddleName ); 786 middleName = find( Qtopia::MiddleName );
342 if ( !lastName.isEmpty() && !firstName.isEmpty() 787 if ( !lastName.isEmpty() && !firstName.isEmpty()
343 && !middleName.isEmpty() ) 788 && !middleName.isEmpty() )
344 fileas = lastName + ", " + firstName + " " + middleName; 789 fileas = lastName + ", " + firstName + " " + middleName;
345 else if ( !lastName.isEmpty() && !firstName.isEmpty() ) 790 else if ( !lastName.isEmpty() && !firstName.isEmpty() )
346 fileas = lastName + ", " + firstName; 791 fileas = lastName + ", " + firstName;
347 else if ( !lastName.isEmpty() || !firstName.isEmpty() || 792 else if ( !lastName.isEmpty() || !firstName.isEmpty() ||
348 !middleName.isEmpty() ) 793 !middleName.isEmpty() )
349 fileas = firstName + ( firstName.isEmpty() ? "" : " " ) 794 fileas = firstName + ( firstName.isEmpty() ? "" : " " )
350 + middleName + ( middleName.isEmpty() ? "" : " " ) 795 + middleName + ( middleName.isEmpty() ? "" : " " )
351 + lastName; 796 + lastName;
352 797
353 replace( Qtopia::FileAs, fileas ); 798 replace( Qtopia::FileAs, fileas );
354} 799}
355 800
801/*!
802 \internal
803 Appends the contact information to \a buf.
804*/
356void Contact::save( QString &buf ) const 805void Contact::save( QString &buf ) const
357{ 806{
358 static const QStringList SLFIELDS = fields(); 807 static const QStringList SLFIELDS = fields();
359 // I'm expecting "<Contact " in front of this... 808 // I'm expecting "<Contact " in front of this...
360 for ( QMap<int, QString>::ConstIterator it = mMap.begin(); 809 for ( QMap<int, QString>::ConstIterator it = mMap.begin();
361 it != mMap.end(); ++it ) { 810 it != mMap.end(); ++it ) {
362 const QString &value = it.data(); 811 const QString &value = it.data();
363 int key = it.key(); 812 int key = it.key();
364 if ( !value.isEmpty() ) { 813 if ( !value.isEmpty() ) {
365 if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid) 814 if ( key == Qtopia::AddressCategory || key == Qtopia::AddressUid)
366 continue; 815 continue;
367 816
368 key -= Qtopia::AddressCategory+1; 817 key -= Qtopia::AddressCategory+1;
369 buf += SLFIELDS[key]; 818 buf += SLFIELDS[key];
370 buf += "=\"" + Qtopia::escapeString(value) + "\" "; 819 buf += "=\"" + Qtopia::escapeString(value) + "\" ";
371 } 820 }
372 } 821 }
373 buf += customToXml(); 822 buf += customToXml();
374 if ( categories().count() > 0 ) 823 if ( categories().count() > 0 )
375 buf += "Categories=\"" + idsToString( categories() ) + "\" "; 824 buf += "Categories=\"" + idsToString( categories() ) + "\" ";
376 buf += "Uid=\"" + QString::number( uid() ) + "\" "; 825 buf += "Uid=\"" + QString::number( uid() ) + "\" ";
377 // You need to close this yourself 826 // You need to close this yourself
378} 827}
379 828
829/*!
830 \internal
831 Returns the list of fields belonging to a contact
832*/
380QStringList Contact::fields() 833QStringList Contact::fields()
381{ 834{
382 QStringList list; 835 QStringList list;
383 836
384 list.append( "Title" ); // Not Used! 837 list.append( "Title" ); // Not Used!
385 list.append( "FirstName" ); 838 list.append( "FirstName" );
386 list.append( "MiddleName" ); 839 list.append( "MiddleName" );
387 list.append( "LastName" ); 840 list.append( "LastName" );
388 list.append( "Suffix" ); 841 list.append( "Suffix" );
389 list.append( "FileAs" ); 842 list.append( "FileAs" );
390 843
391 list.append( "JobTitle" ); 844 list.append( "JobTitle" );
392 list.append( "Department" ); 845 list.append( "Department" );
393 list.append( "Company" ); 846 list.append( "Company" );
394 list.append( "BusinessPhone" ); 847 list.append( "BusinessPhone" );
395 list.append( "BusinessFax" ); 848 list.append( "BusinessFax" );
396 list.append( "BusinessMobile" ); 849 list.append( "BusinessMobile" );
397 850
398 list.append( "DefaultEmail" ); 851 list.append( "DefaultEmail" );
399 list.append( "Emails" ); 852 list.append( "Emails" );
400 853
401 list.append( "HomePhone" ); 854 list.append( "HomePhone" );
402 list.append( "HomeFax" ); 855 list.append( "HomeFax" );
403 list.append( "HomeMobile" ); 856 list.append( "HomeMobile" );
404 857
405 list.append( "BusinessStreet" ); 858 list.append( "BusinessStreet" );
406 list.append( "BusinessCity" ); 859 list.append( "BusinessCity" );
407 list.append( "BusinessState" ); 860 list.append( "BusinessState" );
408 list.append( "BusinessZip" ); 861 list.append( "BusinessZip" );
409 list.append( "BusinessCountry" ); 862 list.append( "BusinessCountry" );
410 list.append( "BusinessPager" ); 863 list.append( "BusinessPager" );
411 list.append( "BusinessWebPage" ); 864 list.append( "BusinessWebPage" );
412 865
413 list.append( "Office" ); 866 list.append( "Office" );
414 list.append( "Profession" ); 867 list.append( "Profession" );
415 list.append( "Assistant" ); 868 list.append( "Assistant" );
416 list.append( "Manager" ); 869 list.append( "Manager" );
417 870
418 list.append( "HomeStreet" ); 871 list.append( "HomeStreet" );
419 list.append( "HomeCity" ); 872 list.append( "HomeCity" );
420 list.append( "HomeState" ); 873 list.append( "HomeState" );
421 list.append( "HomeZip" ); 874 list.append( "HomeZip" );
422 list.append( "HomeCountry" ); 875 list.append( "HomeCountry" );
423 list.append( "HomeWebPage" ); 876 list.append( "HomeWebPage" );
424 877
425 list.append( "Spouse" ); 878 list.append( "Spouse" );
426 list.append( "Gender" ); 879 list.append( "Gender" );
427 list.append( "Birthday" ); 880 list.append( "Birthday" );
428 list.append( "Anniversary" ); 881 list.append( "Anniversary" );
429 list.append( "Nickname" ); 882 list.append( "Nickname" );
430 list.append( "Children" ); 883 list.append( "Children" );
431 884
432 list.append( "Notes" ); 885 list.append( "Notes" );
433 list.append( "Groups" ); 886 list.append( "Groups" );
434 887
435 return list; 888 return list;
436} 889}
437 890
891/*!
892 \internal
893 Returns a translated list of field names for a contact.
894*/
438QStringList Contact::trfields() 895QStringList Contact::trfields()
439{ 896{
440 QStringList list; 897 QStringList list;
441 898
442 list.append( QObject::tr( "Name Title") ); 899 list.append( QObject::tr( "Name Title") );
443 list.append( QObject::tr( "First Name" ) ); 900 list.append( QObject::tr( "First Name" ) );
444 list.append( QObject::tr( "Middle Name" ) ); 901 list.append( QObject::tr( "Middle Name" ) );
445 list.append( QObject::tr( "Last Name" ) ); 902 list.append( QObject::tr( "Last Name" ) );
446 list.append( QObject::tr( "Suffix" ) ); 903 list.append( QObject::tr( "Suffix" ) );
447 list.append( QObject::tr( "File As" ) ); 904 list.append( QObject::tr( "File As" ) );
448 905
449 list.append( QObject::tr( "Job Title" ) ); 906 list.append( QObject::tr( "Job Title" ) );
450 list.append( QObject::tr( "Department" ) ); 907 list.append( QObject::tr( "Department" ) );
451 list.append( QObject::tr( "Company" ) ); 908 list.append( QObject::tr( "Company" ) );
452 list.append( QObject::tr( "Business Phone" ) ); 909 list.append( QObject::tr( "Business Phone" ) );
453 list.append( QObject::tr( "Business Fax" ) ); 910 list.append( QObject::tr( "Business Fax" ) );
454 list.append( QObject::tr( "Business Mobile" ) ); 911 list.append( QObject::tr( "Business Mobile" ) );
455 912
456 list.append( QObject::tr( "Default Email" ) ); 913 list.append( QObject::tr( "Default Email" ) );
457 list.append( QObject::tr( "Emails" ) ); 914 list.append( QObject::tr( "Emails" ) );
458 915
459 list.append( QObject::tr( "Home Phone" ) ); 916 list.append( QObject::tr( "Home Phone" ) );
460 list.append( QObject::tr( "Home Fax" ) ); 917 list.append( QObject::tr( "Home Fax" ) );
461 list.append( QObject::tr( "Home Mobile" ) ); 918 list.append( QObject::tr( "Home Mobile" ) );
462 919
463 list.append( QObject::tr( "Business Street" ) ); 920 list.append( QObject::tr( "Business Street" ) );
464 list.append( QObject::tr( "Business City" ) ); 921 list.append( QObject::tr( "Business City" ) );
465 list.append( QObject::tr( "Business State" ) ); 922 list.append( QObject::tr( "Business State" ) );
466 list.append( QObject::tr( "Business Zip" ) ); 923 list.append( QObject::tr( "Business Zip" ) );
467 list.append( QObject::tr( "Business Country" ) ); 924 list.append( QObject::tr( "Business Country" ) );
468 list.append( QObject::tr( "Business Pager" ) ); 925 list.append( QObject::tr( "Business Pager" ) );
469 list.append( QObject::tr( "Business WebPage" ) ); 926 list.append( QObject::tr( "Business WebPage" ) );
470 927
471 list.append( QObject::tr( "Office" ) ); 928 list.append( QObject::tr( "Office" ) );
472 list.append( QObject::tr( "Profession" ) ); 929 list.append( QObject::tr( "Profession" ) );
473 list.append( QObject::tr( "Assistant" ) ); 930 list.append( QObject::tr( "Assistant" ) );
474 list.append( QObject::tr( "Manager" ) ); 931 list.append( QObject::tr( "Manager" ) );
475 932
476 list.append( QObject::tr( "Home Street" ) ); 933 list.append( QObject::tr( "Home Street" ) );
477 list.append( QObject::tr( "Home City" ) ); 934 list.append( QObject::tr( "Home City" ) );
478 list.append( QObject::tr( "Home State" ) ); 935 list.append( QObject::tr( "Home State" ) );
479 list.append( QObject::tr( "Home Zip" ) ); 936 list.append( QObject::tr( "Home Zip" ) );
480 list.append( QObject::tr( "Home Country" ) ); 937 list.append( QObject::tr( "Home Country" ) );
481 list.append( QObject::tr( "Home Web Page" ) ); 938 list.append( QObject::tr( "Home Web Page" ) );
482 939
483 list.append( QObject::tr( "Spouse" ) ); 940 list.append( QObject::tr( "Spouse" ) );
484 list.append( QObject::tr( "Gender" ) ); 941 list.append( QObject::tr( "Gender" ) );
485 list.append( QObject::tr( "Birthday" ) ); 942 list.append( QObject::tr( "Birthday" ) );
486 list.append( QObject::tr( "Anniversary" ) ); 943 list.append( QObject::tr( "Anniversary" ) );
487 list.append( QObject::tr( "Nickname" ) ); 944 list.append( QObject::tr( "Nickname" ) );
488 list.append( QObject::tr( "Children" ) ); 945 list.append( QObject::tr( "Children" ) );
489 946
490 list.append( QObject::tr( "Notes" ) ); 947 list.append( QObject::tr( "Notes" ) );
491 list.append( QObject::tr( "Groups" ) ); 948 list.append( QObject::tr( "Groups" ) );
492 949
493 return list; 950 return list;
494} 951}
495 952
496void Contact::setEmails( const QString &v ) 953/*!
954 Sets the list of email address for contact to those contained in \a str.
955 Email address should be separated by ';'s.
956*/
957void Contact::setEmails( const QString &str )
497{ 958{
498 replace( Qtopia::Emails, v ); 959 replace( Qtopia::Emails, str );
499 if ( v.isEmpty() ) 960 if ( str.isEmpty() )
500 setDefaultEmail( QString::null ); 961 setDefaultEmail( QString::null );
501} 962}
502 963
503void Contact::setChildren( const QString &v ) 964/*!
965 Sets the list of children for the contact to those contained in \a str.
966*/
967void Contact::setChildren( const QString &str )
504{ 968{
505 replace( Qtopia::Children, v ); 969 replace( Qtopia::Children, str );
506} 970}
507 971
508// vcard conversion code 972// vcard conversion code
973/*!
974 \internal
975*/
509static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value ) 976static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
510{ 977{
511 VObject *ret = 0; 978 VObject *ret = 0;
512 if ( o && !value.isEmpty() ) 979 if ( o && !value.isEmpty() )
513 ret = addPropValue( o, prop, value.latin1() ); 980 ret = addPropValue( o, prop, value.latin1() );
514 return ret; 981 return ret;
515} 982}
516 983
984/*!
985 \internal
986*/
517static inline VObject *safeAddProp( VObject *o, const char *prop) 987static inline VObject *safeAddProp( VObject *o, const char *prop)
518{ 988{
519 VObject *ret = 0; 989 VObject *ret = 0;
520 if ( o ) 990 if ( o )
521 ret = addProp( o, prop ); 991 ret = addProp( o, prop );
522 return ret; 992 return ret;
523} 993}
524 994
995/*!
996 \internal
997*/
525static VObject *createVObject( const Contact &c ) 998static VObject *createVObject( const Contact &c )
526{ 999{
527 VObject *vcard = newVObject( VCCardProp ); 1000 VObject *vcard = newVObject( VCCardProp );
528 safeAddPropValue( vcard, VCVersionProp, "2.1" ); 1001 safeAddPropValue( vcard, VCVersionProp, "2.1" );
529 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) ); 1002 safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
530 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) ); 1003 safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
531 1004
532 // full name 1005 // full name
533 safeAddPropValue( vcard, VCFullNameProp, c.fullName() ); 1006 safeAddPropValue( vcard, VCFullNameProp, c.fullName() );
534 1007
535 // name properties 1008 // name properties
536 VObject *name = safeAddProp( vcard, VCNameProp ); 1009 VObject *name = safeAddProp( vcard, VCNameProp );
537 safeAddPropValue( name, VCFamilyNameProp, c.lastName() ); 1010 safeAddPropValue( name, VCFamilyNameProp, c.lastName() );
538 safeAddPropValue( name, VCGivenNameProp, c.firstName() ); 1011 safeAddPropValue( name, VCGivenNameProp, c.firstName() );
539 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() ); 1012 safeAddPropValue( name, VCAdditionalNamesProp, c.middleName() );
540 safeAddPropValue( name, VCNamePrefixesProp, c.title() ); 1013 safeAddPropValue( name, VCNamePrefixesProp, c.title() );
541 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() ); 1014 safeAddPropValue( name, VCNameSuffixesProp, c.suffix() );
542 1015
543 // home properties 1016 // home properties
544 VObject *home_adr= safeAddProp( vcard, VCAdrProp ); 1017 VObject *home_adr= safeAddProp( vcard, VCAdrProp );
545 safeAddProp( home_adr, VCHomeProp ); 1018 safeAddProp( home_adr, VCHomeProp );
546 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() ); 1019 safeAddPropValue( home_adr, VCStreetAddressProp, c.homeStreet() );
547 safeAddPropValue( home_adr, VCCityProp, c.homeCity() ); 1020 safeAddPropValue( home_adr, VCCityProp, c.homeCity() );
548 safeAddPropValue( home_adr, VCRegionProp, c.homeState() ); 1021 safeAddPropValue( home_adr, VCRegionProp, c.homeState() );
549 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() ); 1022 safeAddPropValue( home_adr, VCPostalCodeProp, c.homeZip() );
550 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() ); 1023 safeAddPropValue( home_adr, VCCountryNameProp, c.homeCountry() );
551 1024
552 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() ); 1025 VObject *home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homePhone() );
553 safeAddProp( home_phone, VCHomeProp ); 1026 safeAddProp( home_phone, VCHomeProp );
554 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() ); 1027 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeMobile() );
555 safeAddProp( home_phone, VCHomeProp ); 1028 safeAddProp( home_phone, VCHomeProp );
556 safeAddProp( home_phone, VCCellularProp ); 1029 safeAddProp( home_phone, VCCellularProp );
557 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() ); 1030 home_phone = safeAddPropValue( vcard, VCTelephoneProp, c.homeFax() );
558 safeAddProp( home_phone, VCHomeProp ); 1031 safeAddProp( home_phone, VCHomeProp );
559 safeAddProp( home_phone, VCFaxProp ); 1032 safeAddProp( home_phone, VCFaxProp );
560 1033
561 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() ); 1034 VObject *url = safeAddPropValue( vcard, VCURLProp, c.homeWebpage() );
562 safeAddProp( url, VCHomeProp ); 1035 safeAddProp( url, VCHomeProp );
563 1036
564 // work properties 1037 // work properties
565 VObject *work_adr= safeAddProp( vcard, VCAdrProp ); 1038 VObject *work_adr= safeAddProp( vcard, VCAdrProp );
566 safeAddProp( work_adr, VCWorkProp ); 1039 safeAddProp( work_adr, VCWorkProp );
567 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() ); 1040 safeAddPropValue( work_adr, VCStreetAddressProp, c.businessStreet() );
568 safeAddPropValue( work_adr, VCCityProp, c.businessCity() ); 1041 safeAddPropValue( work_adr, VCCityProp, c.businessCity() );
569 safeAddPropValue( work_adr, VCRegionProp, c.businessState() ); 1042 safeAddPropValue( work_adr, VCRegionProp, c.businessState() );
570 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() ); 1043 safeAddPropValue( work_adr, VCPostalCodeProp, c.businessZip() );
571 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() ); 1044 safeAddPropValue( work_adr, VCCountryNameProp, c.businessCountry() );
572 1045
573 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() ); 1046 VObject *work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPhone() );
574 safeAddProp( work_phone, VCWorkProp ); 1047 safeAddProp( work_phone, VCWorkProp );
575 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() ); 1048 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessMobile() );
576 safeAddProp( work_phone, VCWorkProp ); 1049 safeAddProp( work_phone, VCWorkProp );
577 safeAddProp( work_phone, VCCellularProp ); 1050 safeAddProp( work_phone, VCCellularProp );
578 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() ); 1051 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessFax() );
579 safeAddProp( work_phone, VCWorkProp ); 1052 safeAddProp( work_phone, VCWorkProp );
580 safeAddProp( work_phone, VCFaxProp ); 1053 safeAddProp( work_phone, VCFaxProp );
581 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() ); 1054 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
582 safeAddProp( work_phone, VCWorkProp ); 1055 safeAddProp( work_phone, VCWorkProp );
583 safeAddProp( work_phone, VCPagerProp ); 1056 safeAddProp( work_phone, VCPagerProp );
584 1057
585 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() ); 1058 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
586 safeAddProp( url, VCWorkProp ); 1059 safeAddProp( url, VCWorkProp );
587 1060
588 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() ); 1061 VObject *title = safeAddPropValue( vcard, VCTitleProp, c.jobTitle() );
589 safeAddProp( title, VCWorkProp ); 1062 safeAddProp( title, VCWorkProp );
590 1063
591 1064
592 QStringList emails = c.emailList(); 1065 QStringList emails = c.emailList();
593 emails.prepend( c.defaultEmail() ); 1066 emails.prepend( c.defaultEmail() );
594 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) { 1067 for( QStringList::Iterator it = emails.begin(); it != emails.end(); ++it ) {
595 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it ); 1068 VObject *email = safeAddPropValue( vcard, VCEmailAddressProp, *it );
596 safeAddProp( email, VCInternetProp ); 1069 safeAddProp( email, VCInternetProp );
597 } 1070 }
598 1071
599 safeAddPropValue( vcard, VCNoteProp, c.notes() ); 1072 safeAddPropValue( vcard, VCNoteProp, c.notes() );
600 1073
601 safeAddPropValue( vcard, VCBirthDateProp, c.birthday() ); 1074 safeAddPropValue( vcard, VCBirthDateProp, c.birthday() );
602 1075
603 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) { 1076 if ( !c.company().isEmpty() || !c.department().isEmpty() || !c.office().isEmpty() ) {
604 VObject *org = safeAddProp( vcard, VCOrgProp ); 1077 VObject *org = safeAddProp( vcard, VCOrgProp );
605 safeAddPropValue( org, VCOrgNameProp, c.company() ); 1078 safeAddPropValue( org, VCOrgNameProp, c.company() );
606 safeAddPropValue( org, VCOrgUnitProp, c.department() ); 1079 safeAddPropValue( org, VCOrgUnitProp, c.department() );
607 safeAddPropValue( org, VCOrgUnit2Prop, c.office() ); 1080 safeAddPropValue( org, VCOrgUnit2Prop, c.office() );
608 } 1081 }
609 1082
610 // some values we have to export as custom fields 1083 // some values we have to export as custom fields
611 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() ); 1084 safeAddPropValue( vcard, "X-Qtopia-Profession", c.profession() );
612 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() ); 1085 safeAddPropValue( vcard, "X-Qtopia-Manager", c.manager() );
613 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() ); 1086 safeAddPropValue( vcard, "X-Qtopia-Assistant", c.assistant() );
614 1087
615 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() ); 1088 safeAddPropValue( vcard, "X-Qtopia-Spouse", c.spouse() );
616 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() ); 1089 safeAddPropValue( vcard, "X-Qtopia-Gender", c.gender() );
617 safeAddPropValue( vcard, "X-Qtopia-Anniversary", c.anniversary() ); 1090 safeAddPropValue( vcard, "X-Qtopia-Anniversary", c.anniversary() );
618 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() ); 1091 safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
619 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() ); 1092 safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
620 1093
621 return vcard; 1094 return vcard;
622} 1095}
623 1096
624 1097
1098/*!
1099 \internal
1100*/
625static Contact parseVObject( VObject *obj ) 1101static Contact parseVObject( VObject *obj )
626{ 1102{
627 Contact c; 1103 Contact c;
628 1104
629 bool haveDefaultEmail = FALSE;
630
631 VObjectIterator it; 1105 VObjectIterator it;
632 initPropIterator( &it, obj ); 1106 initPropIterator( &it, obj );
633 while( moreIteration( &it ) ) { 1107 while( moreIteration( &it ) ) {
634 VObject *o = nextVObject( &it ); 1108 VObject *o = nextVObject( &it );
635 QCString name = vObjectName( o ); 1109 QCString name = vObjectName( o );
636 QCString value = vObjectStringZValue( o ); 1110 QCString value = vObjectStringZValue( o );
637 if ( name == VCNameProp ) { 1111 if ( name == VCNameProp ) {
638 VObjectIterator nit; 1112 VObjectIterator nit;
639 initPropIterator( &nit, o ); 1113 initPropIterator( &nit, o );
640 while( moreIteration( &nit ) ) { 1114 while( moreIteration( &nit ) ) {
641 VObject *o = nextVObject( &nit ); 1115 VObject *o = nextVObject( &nit );
642 QCString name = vObjectTypeInfo( o ); 1116 QCString name = vObjectTypeInfo( o );
643 QString value = vObjectStringZValue( o ); 1117 QString value = vObjectStringZValue( o );
644 if ( name == VCNamePrefixesProp ) 1118 if ( name == VCNamePrefixesProp )
645 c.setTitle( value ); 1119 c.setTitle( value );
646 else if ( name == VCNameSuffixesProp ) 1120 else if ( name == VCNameSuffixesProp )
647 c.setSuffix( value ); 1121 c.setSuffix( value );
648 else if ( name == VCFamilyNameProp ) 1122 else if ( name == VCFamilyNameProp )
649 c.setLastName( value ); 1123 c.setLastName( value );
650 else if ( name == VCGivenNameProp ) 1124 else if ( name == VCGivenNameProp )
651 c.setFirstName( value ); 1125 c.setFirstName( value );
652 else if ( name == VCAdditionalNamesProp ) 1126 else if ( name == VCAdditionalNamesProp )
653 c.setMiddleName( value ); 1127 c.setMiddleName( value );
654 } 1128 }
655 } 1129 }
656 else if ( name == VCAdrProp ) { 1130 else if ( name == VCAdrProp ) {
657 bool work = TRUE; // default address is work address 1131 bool work = TRUE; // default address is work address
658 QString street; 1132 QString street;
659 QString city; 1133 QString city;
660 QString region; 1134 QString region;
661 QString postal; 1135 QString postal;
662 QString country; 1136 QString country;
663 1137
664 VObjectIterator nit; 1138 VObjectIterator nit;
665 initPropIterator( &nit, o ); 1139 initPropIterator( &nit, o );
666 while( moreIteration( &nit ) ) { 1140 while( moreIteration( &nit ) ) {
667 VObject *o = nextVObject( &nit ); 1141 VObject *o = nextVObject( &nit );
668 QCString name = vObjectName( o ); 1142 QCString name = vObjectName( o );
669 QString value = vObjectStringZValue( o ); 1143 QString value = vObjectStringZValue( o );
670 if ( name == VCHomeProp ) 1144 if ( name == VCHomeProp )
671 work = FALSE; 1145 work = FALSE;
672 else if ( name == VCWorkProp ) 1146 else if ( name == VCWorkProp )
673 work = TRUE; 1147 work = TRUE;
674 else if ( name == VCStreetAddressProp ) 1148 else if ( name == VCStreetAddressProp )
675 street = value; 1149 street = value;
676 else if ( name == VCCityProp ) 1150 else if ( name == VCCityProp )
677 city = value; 1151 city = value;
678 else if ( name == VCRegionProp ) 1152 else if ( name == VCRegionProp )
679 region = value; 1153 region = value;
680 else if ( name == VCPostalCodeProp ) 1154 else if ( name == VCPostalCodeProp )
681 postal = value; 1155 postal = value;
682 else if ( name == VCCountryNameProp ) 1156 else if ( name == VCCountryNameProp )
683 country = value; 1157 country = value;
684 } 1158 }
685 if ( work ) { 1159 if ( work ) {
686 c.setBusinessStreet( street ); 1160 c.setBusinessStreet( street );
687 c.setBusinessCity( city ); 1161 c.setBusinessCity( city );
688 c.setBusinessCountry( country ); 1162 c.setBusinessCountry( country );
689 c.setBusinessZip( postal ); 1163 c.setBusinessZip( postal );
690 c.setBusinessState( region ); 1164 c.setBusinessState( region );
691 } else { 1165 } else {
692 c.setHomeStreet( street ); 1166 c.setHomeStreet( street );
693 c.setHomeCity( city ); 1167 c.setHomeCity( city );
694 c.setHomeCountry( country ); 1168 c.setHomeCountry( country );
695 c.setHomeZip( postal ); 1169 c.setHomeZip( postal );
696 c.setHomeState( region ); 1170 c.setHomeState( region );
697 } 1171 }
698 } 1172 }
699 else if ( name == VCTelephoneProp ) { 1173 else if ( name == VCTelephoneProp ) {
700 enum { 1174 enum {
701 HOME = 0x01, 1175 HOME = 0x01,
702 WORK = 0x02, 1176 WORK = 0x02,
703 VOICE = 0x04, 1177 VOICE = 0x04,
704 CELL = 0x08, 1178 CELL = 0x08,
705 FAX = 0x10, 1179 FAX = 0x10,
706 PAGER = 0x20, 1180 PAGER = 0x20,
707 UNKNOWN = 0x80 1181 UNKNOWN = 0x80
708 }; 1182 };
709 int type = 0; 1183 int type = 0;
710 1184
711 VObjectIterator nit; 1185 VObjectIterator nit;
712 initPropIterator( &nit, o ); 1186 initPropIterator( &nit, o );
713 while( moreIteration( &nit ) ) { 1187 while( moreIteration( &nit ) ) {
714 VObject *o = nextVObject( &nit ); 1188 VObject *o = nextVObject( &nit );
715 QCString name = vObjectTypeInfo( o ); 1189 QCString name = vObjectTypeInfo( o );
716 if ( name == VCHomeProp ) 1190 if ( name == VCHomeProp )
717 type |= HOME; 1191 type |= HOME;
718 else if ( name == VCWorkProp ) 1192 else if ( name == VCWorkProp )
719 type |= WORK; 1193 type |= WORK;
720 else if ( name == VCVoiceProp ) 1194 else if ( name == VCVoiceProp )
721 type |= VOICE; 1195 type |= VOICE;
722 else if ( name == VCCellularProp ) 1196 else if ( name == VCCellularProp )
723 type |= CELL; 1197 type |= CELL;
724 else if ( name == VCFaxProp ) 1198 else if ( name == VCFaxProp )
725 type |= FAX; 1199 type |= FAX;
726 else if ( name == VCPagerProp ) 1200 else if ( name == VCPagerProp )
727 type |= PAGER; 1201 type |= PAGER;
728 else if ( name == VCPreferredProp ) 1202 else if ( name == VCPreferredProp )
729 ; 1203 ;
730 else 1204 else
731 type |= UNKNOWN; 1205 type |= UNKNOWN;
732 } 1206 }
733 if ( (type & UNKNOWN) != UNKNOWN ) { 1207 if ( (type & UNKNOWN) != UNKNOWN ) {
734 if ( ( type & (HOME|WORK) ) == 0 ) // default 1208 if ( ( type & (HOME|WORK) ) == 0 ) // default
735 type |= HOME; 1209 type |= HOME;
736 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default 1210 if ( ( type & (VOICE|CELL|FAX|PAGER) ) == 0 ) // default
737 type |= VOICE; 1211 type |= VOICE;
738 1212
739 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) ) 1213 if ( (type & (VOICE|HOME) ) == (VOICE|HOME) )
740 c.setHomePhone( value ); 1214 c.setHomePhone( value );
741 if ( ( type & (FAX|HOME) ) == (FAX|HOME) ) 1215 if ( ( type & (FAX|HOME) ) == (FAX|HOME) )
742 c.setHomeFax( value ); 1216 c.setHomeFax( value );
743 if ( ( type & (CELL|HOME) ) == (CELL|HOME) ) 1217 if ( ( type & (CELL|HOME) ) == (CELL|HOME) )
744 c.setHomeMobile( value ); 1218 c.setHomeMobile( value );
745 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) ) 1219 if ( ( type & (VOICE|WORK) ) == (VOICE|WORK) )
746 c.setBusinessPhone( value ); 1220 c.setBusinessPhone( value );
747 if ( ( type & (FAX|WORK) ) == (FAX|WORK) ) 1221 if ( ( type & (FAX|WORK) ) == (FAX|WORK) )
748 c.setBusinessFax( value ); 1222 c.setBusinessFax( value );
749 if ( ( type & (CELL|WORK) ) == (CELL|WORK) ) 1223 if ( ( type & (CELL|WORK) ) == (CELL|WORK) )
750 c.setBusinessMobile( value ); 1224 c.setBusinessMobile( value );
751 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) ) 1225 if ( ( type & (PAGER|WORK) ) == (PAGER|WORK) )
752 c.setBusinessPager( value ); 1226 c.setBusinessPager( value );
753 } 1227 }
754 } 1228 }
755 else if ( name == VCEmailAddressProp ) { 1229 else if ( name == VCEmailAddressProp ) {
756 QString email = vObjectStringZValue( o ); 1230 QString email = vObjectStringZValue( o );
757 bool valid = TRUE; 1231 bool valid = TRUE;
758 VObjectIterator nit; 1232 VObjectIterator nit;
759 initPropIterator( &nit, o ); 1233 initPropIterator( &nit, o );
760 while( moreIteration( &nit ) ) { 1234 while( moreIteration( &nit ) ) {
761 VObject *o = nextVObject( &nit ); 1235 VObject *o = nextVObject( &nit );
762 QCString name = vObjectTypeInfo( o ); 1236 QCString name = vObjectTypeInfo( o );
763 if ( name != VCInternetProp && name != VCHomeProp && 1237 if ( name != VCInternetProp && name != VCHomeProp &&
764 name != VCWorkProp && 1238 name != VCWorkProp &&
765 name != VCPreferredProp ) 1239 name != VCPreferredProp )
766 // ### preffered should map to default email 1240 // ### preffered should map to default email
767 valid = FALSE; 1241 valid = FALSE;
768 } 1242 }
769 if ( valid ) { 1243 if ( valid ) {
770 if ( haveDefaultEmail ) { 1244 c.insertEmail( email );
771 QString str = c.emails();
772 if ( !str.isEmpty() )
773 str += ","+email;
774 c.setEmails( str );
775 } else {
776 c.setDefaultEmail( email );
777 }
778 } 1245 }
779 } 1246 }
780 else if ( name == VCURLProp ) { 1247 else if ( name == VCURLProp ) {
781 VObjectIterator nit; 1248 VObjectIterator nit;
782 initPropIterator( &nit, o ); 1249 initPropIterator( &nit, o );
783 while( moreIteration( &nit ) ) { 1250 while( moreIteration( &nit ) ) {
784 VObject *o = nextVObject( &nit ); 1251 VObject *o = nextVObject( &nit );
785 QCString name = vObjectTypeInfo( o ); 1252 QCString name = vObjectTypeInfo( o );
786 if ( name == VCHomeProp ) 1253 if ( name == VCHomeProp )
787 c.setHomeWebpage( value ); 1254 c.setHomeWebpage( value );
788 else if ( name == VCWorkProp ) 1255 else if ( name == VCWorkProp )
789 c.setBusinessWebpage( value ); 1256 c.setBusinessWebpage( value );
790 } 1257 }
791 } 1258 }
792 else if ( name == VCOrgProp ) { 1259 else if ( name == VCOrgProp ) {
793 VObjectIterator nit; 1260 VObjectIterator nit;
794 initPropIterator( &nit, o ); 1261 initPropIterator( &nit, o );
795 while( moreIteration( &nit ) ) { 1262 while( moreIteration( &nit ) ) {
796 VObject *o = nextVObject( &nit ); 1263 VObject *o = nextVObject( &nit );
797 QCString name = vObjectName( o ); 1264 QCString name = vObjectName( o );
798 QString value = vObjectStringZValue( o ); 1265 QString value = vObjectStringZValue( o );
799 if ( name == VCOrgNameProp ) 1266 if ( name == VCOrgNameProp )
800 c.setCompany( value ); 1267 c.setCompany( value );
801 else if ( name == VCOrgUnitProp ) 1268 else if ( name == VCOrgUnitProp )
802 c.setDepartment( value ); 1269 c.setDepartment( value );
803 else if ( name == VCOrgUnit2Prop ) 1270 else if ( name == VCOrgUnit2Prop )
804 c.setOffice( value ); 1271 c.setOffice( value );
805 } 1272 }
806 } 1273 }
807 else if ( name == VCTitleProp ) { 1274 else if ( name == VCTitleProp ) {
808 c.setJobTitle( value ); 1275 c.setJobTitle( value );
809 } 1276 }
810 else if ( name == "X-Qtopia-Profession" ) { 1277 else if ( name == "X-Qtopia-Profession" ) {
811 c.setProfession( value ); 1278 c.setProfession( value );
812 } 1279 }
813 else if ( name == "X-Qtopia-Manager" ) { 1280 else if ( name == "X-Qtopia-Manager" ) {
814 c.setManager( value ); 1281 c.setManager( value );
815 } 1282 }
816 else if ( name == "X-Qtopia-Assistant" ) { 1283 else if ( name == "X-Qtopia-Assistant" ) {
817 c.setAssistant( value ); 1284 c.setAssistant( value );
818 } 1285 }
819 else if ( name == "X-Qtopia-Spouse" ) { 1286 else if ( name == "X-Qtopia-Spouse" ) {
820 c.setSpouse( value ); 1287 c.setSpouse( value );
821 } 1288 }
822 else if ( name == "X-Qtopia-Gender" ) { 1289 else if ( name == "X-Qtopia-Gender" ) {
823 c.setGender( value ); 1290 c.setGender( value );
824 } 1291 }
825 else if ( name == "X-Qtopia-Anniversary" ) { 1292 else if ( name == "X-Qtopia-Anniversary" ) {
826 c.setAnniversary( value ); 1293 c.setAnniversary( value );
827 } 1294 }
828 else if ( name == "X-Qtopia-Nickname" ) { 1295 else if ( name == "X-Qtopia-Nickname" ) {
829 c.setNickname( value ); 1296 c.setNickname( value );
830 } 1297 }
831 else if ( name == "X-Qtopia-Children" ) { 1298 else if ( name == "X-Qtopia-Children" ) {
832 c.setChildren( value ); 1299 c.setChildren( value );
833 } 1300 }
834 1301
835 1302
836#if 0 1303#if 0
837 else { 1304 else {
838 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); 1305 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
839 VObjectIterator nit; 1306 VObjectIterator nit;
840 initPropIterator( &nit, o ); 1307 initPropIterator( &nit, o );
841 while( moreIteration( &nit ) ) { 1308 while( moreIteration( &nit ) ) {
842 VObject *o = nextVObject( &nit ); 1309 VObject *o = nextVObject( &nit );
843 QCString name = vObjectName( o ); 1310 QCString name = vObjectName( o );
844 QString value = vObjectStringZValue( o ); 1311 QString value = vObjectStringZValue( o );
845 printf(" subprop: %s = %s\n", name.data(), value.latin1() ); 1312 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
846 } 1313 }
847 } 1314 }
848#endif 1315#endif
849 } 1316 }
850 c.setFileAs(); 1317 c.setFileAs();
851 return c; 1318 return c;
852} 1319}
853 1320
1321/*!
1322 Writes the list of \a contacts as a set of VCards to the file \a filename.
1323*/
854void Contact::writeVCard( const QString &filename, const QValueList<Contact> &contacts) 1324void Contact::writeVCard( const QString &filename, const QValueList<Contact> &contacts)
855{ 1325{
856 QFileDirect f( filename.utf8().data() ); 1326 QFileDirect f( filename.utf8().data() );
857 if ( !f.open( IO_WriteOnly ) ) { 1327 if ( !f.open( IO_WriteOnly ) ) {
858 qWarning("Unable to open vcard write"); 1328 qWarning("Unable to open vcard write");
859 return; 1329 return;
860 } 1330 }
861 1331
862 QValueList<Contact>::ConstIterator it; 1332 QValueList<Contact>::ConstIterator it;
863 for( it = contacts.begin(); it != contacts.end(); ++it ) { 1333 for( it = contacts.begin(); it != contacts.end(); ++it ) {
864 VObject *obj = createVObject( *it ); 1334 VObject *obj = createVObject( *it );
865 writeVObject(f.directHandle() , obj ); 1335 writeVObject(f.directHandle() , obj );
866 cleanVObject( obj ); 1336 cleanVObject( obj );
867 } 1337 }
868 cleanStrTbl(); 1338 cleanStrTbl();
869} 1339}
870 1340
1341/*!
1342 writes \a contact as a VCard to the file \a filename.
1343*/
871void Contact::writeVCard( const QString &filename, const Contact &contact) 1344void Contact::writeVCard( const QString &filename, const Contact &contact)
872{ 1345{
873 QFileDirect f( filename.utf8().data() ); 1346 QFileDirect f( filename.utf8().data() );
874 if ( !f.open( IO_WriteOnly ) ) { 1347 if ( !f.open( IO_WriteOnly ) ) {
875 qWarning("Unable to open vcard write"); 1348 qWarning("Unable to open vcard write");
876 return; 1349 return;
877 } 1350 }
878 1351
879 VObject *obj = createVObject( contact ); 1352 VObject *obj = createVObject( contact );
880 writeVObject( f.directHandle() , obj ); 1353 writeVObject( f.directHandle() , obj );
881 cleanVObject( obj ); 1354 cleanVObject( obj );
882 1355
883 cleanStrTbl(); 1356 cleanStrTbl();
884} 1357}
885 1358
886 1359/*!
1360 Returns the set of contacts read as VCards from the file \a filename.
1361*/
887QValueList<Contact> Contact::readVCard( const QString &filename ) 1362QValueList<Contact> Contact::readVCard( const QString &filename )
888{ 1363{
889 qDebug("trying to open %s, exists=%d", filename.utf8().data(), QFileInfo( filename.utf8().data() ).size() ); 1364 qDebug("trying to open %s, exists=%d", filename.utf8().data(), QFileInfo( filename.utf8().data() ).size() );
890 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() ); 1365 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
891 1366
892 qDebug("vobject = %p", obj ); 1367 qDebug("vobject = %p", obj );
893 1368
894 QValueList<Contact> contacts; 1369 QValueList<Contact> contacts;
895 1370
896 while ( obj ) { 1371 while ( obj ) {
897 contacts.append( parseVObject( obj ) ); 1372 contacts.append( parseVObject( obj ) );
898 1373
899 VObject *t = obj; 1374 VObject *t = obj;
900 obj = nextVObjectInList(obj); 1375 obj = nextVObjectInList(obj);
901 cleanVObject( t ); 1376 cleanVObject( t );
902 } 1377 }
903 1378
904 return contacts; 1379 return contacts;
905} 1380}
906 1381
1382/*!
1383 Returns TRUE if the contact matches the regular expression \a regexp.
1384 Otherwise returns FALSE.
1385*/
907bool Contact::match( const QString &regexp ) const 1386bool Contact::match( const QString &regexp ) const
908{ 1387{
909 return match(QRegExp(regexp)); 1388 return match(QRegExp(regexp));
910} 1389}
911 1390
1391/*!
1392 \overload
1393 Returns TRUE if the contact matches the regular expression \a regexp.
1394 Otherwise returns FALSE.
1395*/
912bool Contact::match( const QRegExp &r ) const 1396bool Contact::match( const QRegExp &r ) const
913{ 1397{
914 bool match; 1398 bool match;
915 match = false; 1399 match = false;
916 QMap<int, QString>::ConstIterator it; 1400 QMap<int, QString>::ConstIterator it;
917 for ( it = mMap.begin(); it != mMap.end(); ++it ) { 1401 for ( it = mMap.begin(); it != mMap.end(); ++it ) {
918 if ( (*it).find( r ) > -1 ) { 1402 if ( (*it).find( r ) > -1 ) {
919 match = true; 1403 match = true;
920 break; 1404 break;
921 } 1405 }
922 } 1406 }
923 return match; 1407 return match;
924} 1408}
diff --git a/library/backend/contact.h b/library/backend/contact.h
index a74cbbe..4999430 100644
--- a/library/backend/contact.h
+++ b/library/backend/contact.h
@@ -1,222 +1,306 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#ifndef __CONTACT_H__ 21#ifndef __CONTACT_H__
22#define __CONTACT_H__ 22#define __CONTACT_H__
23 23
24#include <qpe/palmtoprecord.h> 24#include <qtopia/private/palmtoprecord.h>
25#include <qpe/recordfields.h> 25#include <qtopia/private/recordfields.h>
26 26
27#include <qstringlist.h> 27#include <qstringlist.h>
28 28
29#if defined(QPC_TEMPLATEDLL) 29#if defined(QPC_TEMPLATEDLL)
30// MOC_SKIP_BEGIN 30// MOC_SKIP_BEGIN
31template class QPC_EXPORT QMap<int, QString>; 31QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
32// MOC_SKIP_END 32// MOC_SKIP_END
33#endif 33#endif
34 34
35class ContactPrivate; 35class ContactPrivate;
36class QPC_EXPORT Contact : public Qtopia::Record 36class QPC_EXPORT Contact : public Qtopia::Record
37{ 37{
38 friend class DataSet; 38 friend class DataSet;
39public: 39public:
40 Contact(); 40 Contact();
41 Contact( const QMap<int, QString> &fromMap ); 41 Contact( const QMap<int, QString> &fromMap );
42 virtual ~Contact(); 42 virtual ~Contact();
43 43
44 static void writeVCard( const QString &filename, const QValueList<Contact> &contacts); 44 static void writeVCard( const QString &filename, const QValueList<Contact> &contacts);
45 static void writeVCard( const QString &filename, const Contact &c ); 45 static void writeVCard( const QString &filename, const Contact &c );
46 static QValueList<Contact> readVCard( const QString &filename ); 46 static QValueList<Contact> readVCard( const QString &filename );
47 47
48 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE }; 48 enum journal_action { ACTION_ADD, ACTION_REMOVE, ACTION_REPLACE };
49 49
50 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); } 50 void setTitle( const QString &v ) { replace( Qtopia::Title, v ); }
51 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); } 51 void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
52 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); } 52 void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
53 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); } 53 void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
54 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); } 54 void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
55 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); } 55 void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
56 void setFileAs(); 56 void setFileAs();
57 57
58 // default email address 58 // default email address
59 void setDefaultEmail( const QString &v ) { replace( Qtopia::DefaultEmail, v ); } 59 void setDefaultEmail( const QString &v );
60 // the emails should be seperated by a semicolon 60 // inserts email to list and ensure's doesn't already exist
61 void setEmails( const QString &v ); 61 void insertEmail( const QString &v );
62 void removeEmail( const QString &v );
63 void clearEmails();
64 void insertEmails( const QStringList &v );
62 65
63 // home 66 // home
64 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); } 67 void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
65 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); } 68 void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
66 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); } 69 void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
67 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); } 70 void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
68 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); } 71 void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
69 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); } 72 void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
70 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); } 73 void setHomeFax( const QString &v ) { replace( Qtopia::HomeFax, v ); }
71 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); } 74 void setHomeMobile( const QString &v ) { replace( Qtopia::HomeMobile, v ); }
72 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); } 75 void setHomeWebpage( const QString &v ) { replace( Qtopia::HomeWebPage, v ); }
73 76
74 // business 77 // business
75 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); } 78 void setCompany( const QString &v ) { replace( Qtopia::Company, v ); }
76 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); } 79 void setBusinessStreet( const QString &v ) { replace( Qtopia::BusinessStreet, v ); }
77 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); } 80 void setBusinessCity( const QString &v ) { replace( Qtopia::BusinessCity, v ); }
78 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); } 81 void setBusinessState( const QString &v ) { replace( Qtopia::BusinessState, v ); }
79 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); } 82 void setBusinessZip( const QString &v ) { replace( Qtopia::BusinessZip, v ); }
80 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); } 83 void setBusinessCountry( const QString &v ) { replace( Qtopia::BusinessCountry, v ); }
81 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); } 84 void setBusinessWebpage( const QString &v ) { replace( Qtopia::BusinessWebPage, v ); }
82 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); } 85 void setJobTitle( const QString &v ) { replace( Qtopia::JobTitle, v ); }
83 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); } 86 void setDepartment( const QString &v ) { replace( Qtopia::Department, v ); }
84 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); } 87 void setOffice( const QString &v ) { replace( Qtopia::Office, v ); }
85 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); } 88 void setBusinessPhone( const QString &v ) { replace( Qtopia::BusinessPhone, v ); }
86 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); } 89 void setBusinessFax( const QString &v ) { replace( Qtopia::BusinessFax, v ); }
87 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); } 90 void setBusinessMobile( const QString &v ) { replace( Qtopia::BusinessMobile, v ); }
88 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); } 91 void setBusinessPager( const QString &v ) { replace( Qtopia::BusinessPager, v ); }
89 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); } 92 void setProfession( const QString &v ) { replace( Qtopia::Profession, v ); }
90 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); } 93 void setAssistant( const QString &v ) { replace( Qtopia::Assistant, v ); }
91 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); } 94 void setManager( const QString &v ) { replace( Qtopia::Manager, v ); }
92 95
93 // personal 96 // personal
94 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); } 97 void setSpouse( const QString &v ) { replace( Qtopia::Spouse, v ); }
95 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); } 98 void setGender( const QString &v ) { replace( Qtopia::Gender, v ); }
96 void setBirthday( const QString &v ) { replace( Qtopia::Birthday, v ); } 99 void setBirthday( const QString &v ) { replace( Qtopia::Birthday, v ); }
97 void setAnniversary( const QString &v ) { replace( Qtopia::Anniversary, v ); } 100 void setAnniversary( const QString &v ) { replace( Qtopia::Anniversary, v ); }
98 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); } 101 void setNickname( const QString &v ) { replace( Qtopia::Nickname, v ); }
99 void setChildren( const QString &v ); 102 void setChildren( const QString &v );
100 103
101 // other 104 // other
102 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); } 105 void setNotes( const QString &v ) { replace( Qtopia::Notes, v); }
103 106
104 bool match( const QString &regexp ) const; 107 bool match( const QString &regexp ) const;
105 108
106// DON'T ATTEMPT TO USE THIS 109// DON'T ATTEMPT TO USE THIS
107#ifdef QTOPIA_INTERNAL_CONTACT_MRE 110#ifdef QTOPIA_INTERNAL_CONTACT_MRE
108 bool match( const QRegExp &regexp ) const; 111 bool match( const QRegExp &regexp ) const;
109#endif 112#endif
110 113
111// // custom 114// // custom
112// void setCustomField( const QString &key, const QString &v ) 115// void setCustomField( const QString &key, const QString &v )
113// { replace(Custom- + key, v ); } 116// { replace(Custom- + key, v ); }
114 117
115 // name 118 // name
116 QString fullName() const; 119 QString fullName() const;
117 QString title() const { return find( Qtopia::Title ); } 120 QString title() const { return find( Qtopia::Title ); }
118 QString firstName() const { return find( Qtopia::FirstName ); } 121 QString firstName() const { return find( Qtopia::FirstName ); }
119 QString middleName() const { return find( Qtopia::MiddleName ); } 122 QString middleName() const { return find( Qtopia::MiddleName ); }
120 QString lastName() const { return find( Qtopia::LastName ); } 123 QString lastName() const { return find( Qtopia::LastName ); }
121 QString suffix() const { return find( Qtopia::Suffix ); } 124 QString suffix() const { return find( Qtopia::Suffix ); }
122 QString fileAs() const { return find( Qtopia::FileAs ); } 125 QString fileAs() const { return find( Qtopia::FileAs ); }
123 126
124 // email 127 // email
125 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); } 128 QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
126 QString emails() const { return find( Qtopia::Emails ); }
127 QStringList emailList() const; 129 QStringList emailList() const;
128 130
129 // home 131 // home
130 QString homeStreet() const { return find( Qtopia::HomeStreet ); } 132 QString homeStreet() const { return find( Qtopia::HomeStreet ); }
131 QString homeCity() const { return find( Qtopia::HomeCity ); } 133 QString homeCity() const { return find( Qtopia::HomeCity ); }
132 QString homeState() const { return find( Qtopia::HomeState ); } 134 QString homeState() const { return find( Qtopia::HomeState ); }
133 QString homeZip() const { return find( Qtopia::HomeZip ); } 135 QString homeZip() const { return find( Qtopia::HomeZip ); }
134 QString homeCountry() const { return find( Qtopia::HomeCountry ); } 136 QString homeCountry() const { return find( Qtopia::HomeCountry ); }
135 QString homePhone() const { return find( Qtopia::HomePhone ); } 137 QString homePhone() const { return find( Qtopia::HomePhone ); }
136 QString homeFax() const { return find( Qtopia::HomeFax ); } 138 QString homeFax() const { return find( Qtopia::HomeFax ); }
137 QString homeMobile() const { return find( Qtopia::HomeMobile ); } 139 QString homeMobile() const { return find( Qtopia::HomeMobile ); }
138 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); } 140 QString homeWebpage() const { return find( Qtopia::HomeWebPage ); }
139 /** Multi line string containing all non-empty address info in the form 141 /** Multi line string containing all non-empty address info in the form
140 * Street 142 * Street
141 * City, State Zip 143 * City, State Zip
142 * Country 144 * Country
143 */ 145 */
144 QString displayHomeAddress() const; 146 QString displayHomeAddress() const;
145 147
146 // business 148 // business
147 QString company() const { return find( Qtopia::Company ); } 149 QString company() const { return find( Qtopia::Company ); }
148 QString businessStreet() const { return find( Qtopia::BusinessStreet ); } 150 QString businessStreet() const { return find( Qtopia::BusinessStreet ); }
149 QString businessCity() const { return find( Qtopia::BusinessCity ); } 151 QString businessCity() const { return find( Qtopia::BusinessCity ); }
150 QString businessState() const { return find( Qtopia::BusinessState ); } 152 QString businessState() const { return find( Qtopia::BusinessState ); }
151 QString businessZip() const { return find( Qtopia::BusinessZip ); } 153 QString businessZip() const { return find( Qtopia::BusinessZip ); }
152 QString businessCountry() const { return find( Qtopia::BusinessCountry ); } 154 QString businessCountry() const { return find( Qtopia::BusinessCountry ); }
153 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); } 155 QString businessWebpage() const { return find( Qtopia::BusinessWebPage ); }
154 QString jobTitle() const { return find( Qtopia::JobTitle ); } 156 QString jobTitle() const { return find( Qtopia::JobTitle ); }
155 QString department() const { return find( Qtopia::Department ); } 157 QString department() const { return find( Qtopia::Department ); }
156 QString office() const { return find( Qtopia::Office ); } 158 QString office() const { return find( Qtopia::Office ); }
157 QString businessPhone() const { return find( Qtopia::BusinessPhone ); } 159 QString businessPhone() const { return find( Qtopia::BusinessPhone ); }
158 QString businessFax() const { return find( Qtopia::BusinessFax ); } 160 QString businessFax() const { return find( Qtopia::BusinessFax ); }
159 QString businessMobile() const { return find( Qtopia::BusinessMobile ); } 161 QString businessMobile() const { return find( Qtopia::BusinessMobile ); }
160 QString businessPager() const { return find( Qtopia::BusinessPager ); } 162 QString businessPager() const { return find( Qtopia::BusinessPager ); }
161 QString profession() const { return find( Qtopia::Profession ); } 163 QString profession() const { return find( Qtopia::Profession ); }
162 QString assistant() const { return find( Qtopia::Assistant ); } 164 QString assistant() const { return find( Qtopia::Assistant ); }
163 QString manager() const { return find( Qtopia::Manager ); } 165 QString manager() const { return find( Qtopia::Manager ); }
164 /** Multi line string containing all non-empty address info in the form 166 /** Multi line string containing all non-empty address info in the form
165 * Street 167 * Street
166 * City, State Zip 168 * City, State Zip
167 * Country 169 * Country
168 */ 170 */
169 QString displayBusinessAddress() const; 171 QString displayBusinessAddress() const;
170 172
171 //personal 173 //personal
172 QString spouse() const { return find( Qtopia::Spouse ); } 174 QString spouse() const { return find( Qtopia::Spouse ); }
173 QString gender() const { return find( Qtopia::Gender ); } 175 QString gender() const { return find( Qtopia::Gender ); }
174 QString birthday() const { return find( Qtopia::Birthday ); } 176 QString birthday() const { return find( Qtopia::Birthday ); }
175 QString anniversary() const { return find( Qtopia::Anniversary ); } 177 QString anniversary() const { return find( Qtopia::Anniversary ); }
176 QString nickname() const { return find( Qtopia::Nickname ); } 178 QString nickname() const { return find( Qtopia::Nickname ); }
177 QString children() const { return find( Qtopia::Children ); } 179 QString children() const { return find( Qtopia::Children ); }
178 QStringList childrenList() const; 180 QStringList childrenList() const;
179 181
180 // other 182 // other
181 QString notes() const { return find( Qtopia::Notes ); } 183 QString notes() const { return find( Qtopia::Notes ); }
182 QString groups() const { return find( Qtopia::Groups ); } 184 QString groups() const { return find( Qtopia::Groups ); }
183 QStringList groupList() const; 185 QStringList groupList() const;
184 186
185// // custom 187// // custom
186// const QString &customField( const QString &key ) 188// const QString &customField( const QString &key )
187// { return find( Custom- + key ); } 189// { return find( Custom- + key ); }
188 190
189 static QStringList fields(); 191 static QStringList fields();
190 static QStringList trfields(); 192 static QStringList trfields();
191 193
192 QString toRichText() const; 194 QString toRichText() const;
193 QMap<int, QString> toMap() const; 195 QMap<int, QString> toMap() const;
194 QString field( int key ) const { return find( key ); } 196 QString field( int key ) const { return find( key ); }
195 197
196 198
197 // journaling... 199 // journaling...
198 void saveJournal( journal_action action, const QString &key = QString::null ); 200 void saveJournal( journal_action action, const QString &key = QString::null );
199 void save( QString &buf ) const; 201 void save( QString &buf ) const;
200 202
201 void setUid( int i ) 203 void setUid( int i )
202{ Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); } 204{ Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); }
203 205
204private: 206private:
207 friend class AbEditor;
205 friend class AbTable; 208 friend class AbTable;
209 friend class AddressBookAccessPrivate;
210 friend class XMLIO;
211
212 QString emailSeparator() const { return " "; }
213 // the emails should be seperated by a comma
214 void setEmails( const QString &v );
215 QString emails() const { return find( Qtopia::Emails ); }
216
206 void insert( int key, const QString &value ); 217 void insert( int key, const QString &value );
207 void replace( int key, const QString &value ); 218 void replace( int key, const QString &value );
208 QString find( int key ) const; 219 QString find( int key ) const;
209 220
210 QString displayAddress( const QString &street, 221 QString displayAddress( const QString &street,
211 const QString &city, 222 const QString &city,
212 const QString &state, 223 const QString &state,
213 const QString &zip, 224 const QString &zip,
214 const QString &country ) const; 225 const QString &country ) const;
215 226
216 Qtopia::UidGen &uidGen() { return sUidGen; } 227 Qtopia::UidGen &uidGen() { return sUidGen; }
217 static Qtopia::UidGen sUidGen; 228 static Qtopia::UidGen sUidGen;
218 QMap<int, QString> mMap; 229 QMap<int, QString> mMap;
219 ContactPrivate *d; 230 ContactPrivate *d;
220}; 231};
221 232
233// these methods are inlined to keep binary compatability with Qtopia 1.5
234inline void Contact::insertEmail( const QString &v )
235{
236 //qDebug("insertEmail %s", v.latin1());
237 QString e = v.simplifyWhiteSpace();
238 QString def = defaultEmail();
239
240 // if no default, set it as the default email and don't insert
241 if ( def.isEmpty() ) {
242 setDefaultEmail( e ); // will insert into the list for us
243 return;
244 }
245
246 // otherwise, insert assuming doesn't already exist
247 QString emailsStr = find( Qtopia::Emails );
248 if ( emailsStr.contains( e ))
249 return;
250 if ( !emailsStr.isEmpty() )
251 emailsStr += emailSeparator();
252 emailsStr += e;
253 replace( Qtopia::Emails, emailsStr );
254}
255
256inline void Contact::removeEmail( const QString &v )
257{
258 QString e = v.simplifyWhiteSpace();
259 QString def = defaultEmail();
260 QString emailsStr = find( Qtopia::Emails );
261 QStringList emails = emailList();
262
263 // otherwise, must first contain it
264 if ( !emailsStr.contains( e ) )
265 return;
266
267 // remove it
268 //qDebug(" removing email from list %s", e.latin1());
269 emails.remove( e );
270 // reset the string
271 emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
272 replace( Qtopia::Emails, emailsStr );
273
274 // if default, then replace the default email with the first one
275 if ( def == e ) {
276 //qDebug("removeEmail is default; setting new default");
277 if ( !emails.count() )
278 clearEmails();
279 else // setDefaultEmail will remove e from the list
280 setDefaultEmail( emails.first() );
281 }
282}
283inline void Contact::clearEmails()
284{
285 mMap.remove( Qtopia::DefaultEmail );
286 mMap.remove( Qtopia::Emails );
287}
288inline void Contact::setDefaultEmail( const QString &v )
289{
290 QString e = v.simplifyWhiteSpace();
291
292 //qDebug("Contact::setDefaultEmail %s", e.latin1());
293 replace( Qtopia::DefaultEmail, e );
294
295 if ( !e.isEmpty() )
296 insertEmail( e );
297
298}
299
300inline void Contact::insertEmails( const QStringList &v )
301{
302 for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
303 insertEmail( *it );
304}
305
222#endif 306#endif
diff --git a/library/backend/event.cpp b/library/backend/event.cpp
index 50a663d..7110717 100644
--- a/library/backend/event.cpp
+++ b/library/backend/event.cpp
@@ -1,830 +1,1315 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include "event.h" 21#include "event.h"
22#include "qfiledirect_p.h" 22#include "qfiledirect_p.h"
23#include <qpe/timeconversion.h> 23#include <qtopia/timeconversion.h>
24#include <qpe/stringutil.h> 24#include <qtopia/stringutil.h>
25#include <qpe/recordfields.h> 25#include <qtopia/private/recordfields.h>
26#include <qbuffer.h> 26#include <qbuffer.h>
27#include <time.h> 27#include <time.h>
28#include "vobject_p.h" 28#include "vobject_p.h"
29 29
30#include <stdio.h> 30#include <stdio.h>
31 31
32using namespace Qtopia; 32using namespace Qtopia;
33 33
34static void write( QString& buf, const Event::RepeatPattern &r ) 34static void write( QString& buf, const Event::RepeatPattern &r )
35{ 35{
36 buf += " rtype=\""; 36 buf += " rtype=\"";
37 switch ( r.type ) { 37 switch ( r.type ) {
38 case Event::Daily: 38 case Event::Daily:
39 buf += "Daily"; 39 buf += "Daily";
40 break; 40 break;
41 case Event::Weekly: 41 case Event::Weekly:
42 buf += "Weekly"; 42 buf += "Weekly";
43 break; 43 break;
44 case Event::MonthlyDay: 44 case Event::MonthlyDay:
45 buf += "MonthlyDay"; 45 buf += "MonthlyDay";
46 break; 46 break;
47 case Event::MonthlyDate: 47 case Event::MonthlyDate:
48 buf += "MonthlyDate"; 48 buf += "MonthlyDate";
49 break; 49 break;
50 case Event::Yearly: 50 case Event::Yearly:
51 buf += "Yearly"; 51 buf += "Yearly";
52 break; 52 break;
53 default: 53 default:
54 buf += "NoRepeat"; 54 buf += "NoRepeat";
55 break; 55 break;
56 } 56 }
57 buf += "\""; 57 buf += "\"";
58 if ( r.days > 0 ) 58 if ( r.days > 0 )
59 buf += " rweekdays=\"" + QString::number( static_cast<int>( r.days ) ) + "\""; 59 buf += " rweekdays=\"" + QString::number( static_cast<int>( r.days ) ) + "\"";
60 if ( r.position != 0 ) 60 if ( r.position != 0 )
61 buf += " rposition=\"" + QString::number( r.position ) + "\""; 61 buf += " rposition=\"" + QString::number( r.position ) + "\"";
62 62
63 buf += " rfreq=\"" + QString::number( r.frequency ) + "\""; 63 buf += " rfreq=\"" + QString::number( r.frequency ) + "\"";
64 buf += " rhasenddate=\"" + QString::number( static_cast<int>( r.hasEndDate ) ) + "\""; 64 buf += " rhasenddate=\"" + QString::number( static_cast<int>( r.hasEndDate ) ) + "\"";
65 if ( r.hasEndDate ) 65 if ( r.hasEndDate )
66 buf += " enddt=\"" 66 buf += " enddt=\""
67 + QString::number( r.endDateUTC ? r.endDateUTC : time( 0 ) ) 67 + QString::number( r.endDateUTC ? r.endDateUTC : time( 0 ) )
68 + "\""; 68 + "\"";
69 buf += " created=\"" + QString::number( r.createTime ) + "\""; 69 buf += " created=\"" + QString::number( r.createTime ) + "\"";
70} 70}
71 71
72Qtopia::UidGen Event::sUidGen( Qtopia::UidGen::Qtopia ); 72Qtopia::UidGen Event::sUidGen( Qtopia::UidGen::Qtopia );
73 73
74/*!
75 \class Event event.h
76 \brief The Event class holds the data of a calendar event.
77
78 This data includes descriptive data of the event and schedualing information.
79
80 \ingroup qtopiaemb
81 \ingroup qtopiadesktop
82*/
83
84/*!
85 \class Event::RepeatPattern
86 \class The Event::RepeatPattern class is internal.
87 \internal
88*/
89
90/*!
91 \enum Event::Days
92 \internal
93*/
94
95/*!
96 \enum Event::Type
97 \internal
98*/
99
100/*!
101 \enum Event::SoundTypeChoice
102
103 This enum type defines what kind of sound is made when an alarm occurs
104 for an event. The currently defined types are:
105
106 <ul>
107 <li>\c Silent - No sound is produced.
108 <li>\c Loud - A loud sound is produced.
109 </ul>
110*/
111
112/*!
113 \fn bool Event::operator<( const Event & ) const
114 \internal
115*/
116
117/*!
118 \fn bool Event::operator<=( const Event & ) const
119 \internal
120*/
121
122/*!
123 \fn bool Event::operator!=( const Event & ) const
124 \internal
125*/
126
127/*!
128 \fn bool Event::operator>( const Event & ) const
129 \internal
130*/
131
132/*!
133 \fn bool Event::operator>=( const Event & ) const
134 \internal
135*/
136
137/*!
138 \enum Event::RepeatType
139
140 This enum defines how a event will repeat, if at all.
141
142 <ul>
143 <li>\c NoRepeat - Event does not repeat.
144 <li>\c Daily - Event occurs every n days.
145 <li>\c Weekly - Event occurs every n weeks.
146 <li>\c MonthlyDay - Event occurs every n months. Event will always occur in
147 the same week and same day of week as the first event.
148 <li>\c MonthlyDate - Event occurs every n months. Event will always occur
149 on the same day of the month as the first event.
150 <li>\c Yearly - Event occurs every n years.
151 </ul>
152*/
153
154/*!
155 \fn bool Event::isAllDay() const
156
157 Returns TRUE if the event is an all day event. Otherwise returns FALSE.
158*/
159
160/*!
161 \fn void Event::setAllDay(bool allday)
162
163 If \a allday is TRUE, will set the event to be an all day event.
164 Otherwise sets the event to not be an all day event.
165
166 \warning This function may affect the start and end times of the event.
167*/
168
169/*!
170 \fn QDateTime Event::start() const
171
172 Returns the start date and time of the first occurance of the event.
173*/
174
175/*!
176 \fn QDateTime Event::end() const
177
178 Returns the end date and time of the first occurance of the event.
179*/
180
181/*!
182 \fn time_t Event::startTime() const
183 \internal
184*/
185
186/*!
187 \fn time_t Event::endTime() const
188 \internal
189*/
190
191/*!
192 \fn void Event::setAlarm(int delay, SoundTypeChoice s)
193
194 Sets the alarm delay of the event to \a delay and the sound type of the
195 alarm to \a s.
196*/
197
198/*!
199 \fn void Event::clearAlarm()
200
201 Clears the alarm for the event.
202*/
203
204/*!
205 \fn int Event::alarmDelay() const
206
207 Returns the delay in minutes between the alarm for an event and the
208 start of the event.
209*/
210
211/*!
212 \fn Event::RepeatType Event::repeatType() const
213
214 Returns the repeat pattern type for the event.
215
216 \sa frequency()
217*/
218
219/*!
220 \fn int Event::weekOffset() const
221
222 Returns the number of weeks from the start of the month that this event
223 occurs.
224*/
225
226/*!
227 \fn QDate Event::repeatTill() const
228
229 Returns the date that the event will continue to repeat until. If the event
230 repeats forever the value returned is undefined.
231
232 \sa repeatForever()
233*/
234
235/*!
236 \fn bool Event::repeatForever() const
237
238 Returns FALSE if there is a date set for the event to continue until.
239 Otherwise returns TRUE.
240*/
241
242/*!
243 \fn bool Event::doRepeat() const
244 \internal
245*/
246
247/*!
248 \fn bool Event::repeatOnWeekDay(int day) const
249
250 Returns TRUE if the event has a RepeatType of Weekly and is set to occur on
251 \a day each week. Otherwise returns FALSE.
252
253 \sa QDate::dayName()
254*/
255
256/*!
257 \fn void Event::setRepeatOnWeekDay(int day, bool enable)
258
259 If \a enable is TRUE then sets the event to occur on \a day each week.
260 Otherwise sets the event not to occur on \a day.
261
262 \warning this function is only relavent for a event with RepeatType of
263 Weekly.
264
265 \sa QDate::dayName()
266*/
267
268/*!
269 \fn int Event::frequency() const
270
271 Returns how often the event repeats.
272
273 \sa repeatType()
274*/
275
276/*!
277 \fn void Event::setRepeatType(RepeatType t)
278
279 Sets the repeat pattern type of the event to \a t.
280
281 \sa setFrequency()
282*/
283
284/*!
285 \fn void Event::setFrequency(int n)
286
287 Sets how often the event occurs with in its repeat pattern.
288
289 \sa setRepeatType()
290*/
291
292/*!
293 \fn void Event::setRepeatTill(const QDate &d)
294
295 Sets the event to repeat until \a d.
296*/
297
298/*!
299 \fn void Event::setRepeatForever(bool enable)
300
301 If \a enable is TRUE, sets the event to repeat forever. Otherwise
302 sets the event to stop repeating at some date.
303
304 \warning This function may affect the specific date the event will repeat
305 till.
306*/
307
308/*!
309 \fn bool Event::match(const QRegExp &r) const
310
311 Returns TRUE if the event matches the regular expression \a r.
312 Otherwise returns FALSE.
313*/
314
315/*!
316 \fn char Event::day(int)
317 \internal
318*/
319
320/*!
321 Creates a new, empty event.
322*/
74Event::Event() : Record() 323Event::Event() : Record()
75{ 324{
76 startUTC = endUTC = time( 0 ); 325 startUTC = endUTC = time( 0 );
77 typ = Normal; 326 typ = Normal;
78 hAlarm = FALSE; 327 hAlarm = FALSE;
79 hRepeat = FALSE; 328 hRepeat = FALSE;
80 aMinutes = 0; 329 aMinutes = 0;
81 aSound = Silent; 330 aSound = Silent;
82 pattern.type = NoRepeat; 331 pattern.type = NoRepeat;
83 pattern.frequency = -1; 332 pattern.frequency = -1;
84} 333}
85 334
335/*!
336 \internal
337*/
86Event::Event( const QMap<int, QString> &map ) 338Event::Event( const QMap<int, QString> &map )
87{ 339{
88 setDescription( map[DatebookDescription] ); 340 setDescription( map[DatebookDescription] );
89 setLocation( map[Location] ); 341 setLocation( map[Location] );
90 setCategories( idsFromString( map[DatebookCategory] ) ); 342 setCategories( idsFromString( map[DatebookCategory] ) );
91 setTimeZone( map[TimeZone] ); 343 setTimeZone( map[TimeZone] );
92 setNotes( map[Note] ); 344 setNotes( map[Note] );
93 setStart( TimeConversion::fromUTC( map[StartDateTime].toUInt() ) ); 345 setStart( TimeConversion::fromUTC( map[StartDateTime].toUInt() ) );
94 setEnd( TimeConversion::fromUTC( map[EndDateTime].toUInt() ) ); 346 setEnd( TimeConversion::fromUTC( map[EndDateTime].toUInt() ) );
95 setType( (Event::Type) map[DatebookType].toInt() ); 347 setType( (Event::Type) map[DatebookType].toInt() );
96 setAlarm( ( map[HasAlarm] == "1" ? TRUE : FALSE ), map[AlarmTime].toInt(), (Event::SoundTypeChoice)map[SoundType].toInt() ); 348 setAlarm( ( map[HasAlarm] == "1" ? TRUE : FALSE ), map[AlarmTime].toInt(), (Event::SoundTypeChoice)map[SoundType].toInt() );
97 Event::RepeatPattern p; 349 Event::RepeatPattern p;
98 p.type = (Event::RepeatType) map[ RepeatPatternType ].toInt(); 350 p.type = (Event::RepeatType) map[ RepeatPatternType ].toInt();
99 p.frequency = map[ RepeatPatternFrequency ].toInt(); 351 p.frequency = map[ RepeatPatternFrequency ].toInt();
100 p.position = map[ RepeatPatternPosition ].toInt(); 352 p.position = map[ RepeatPatternPosition ].toInt();
101 p.days = map[ RepeatPatternDays ].toInt(); 353 p.days = map[ RepeatPatternDays ].toInt();
102 p.hasEndDate = map[ RepeatPatternHasEndDate ].toInt(); 354 p.hasEndDate = map[ RepeatPatternHasEndDate ].toInt();
103 p.endDateUTC = map[ RepeatPatternEndDate ].toUInt(); 355 p.endDateUTC = map[ RepeatPatternEndDate ].toUInt();
104 setRepeat( p ); 356 setRepeat( p );
105 357
106 setUid( map[ DatebookUid ].toInt() ); 358 setUid( map[ DatebookUid ].toInt() );
107} 359}
108 360
361/*!
362 Destroys an event.
363*/
109Event::~Event() 364Event::~Event()
110{ 365{
111} 366}
112 367
368/*!
369 \internal
370*/
113int Event::week( const QDate& date ) 371int Event::week( const QDate& date )
114{ 372{
115 // Calculates the week this date is in within that 373 // Calculates the week this date is in within that
116 // month. Equals the "row" is is in in the month view 374 // month. Equals the "row" is is in in the month view
117 int week = 1; 375 int week = 1;
118 QDate tmp( date.year(), date.month(), 1 ); 376 QDate tmp( date.year(), date.month(), 1 );
119 377
120 if ( date.dayOfWeek() < tmp.dayOfWeek() ) 378 if ( date.dayOfWeek() < tmp.dayOfWeek() )
121 ++week; 379 ++week;
122 380
123 week += ( date.day() - 1 ) / 7; 381 week += ( date.day() - 1 ) / 7;
124 return week; 382 return week;
125} 383}
126 384
385/*!
386 \internal
387*/
127int Event::occurrence( const QDate& date ) 388int Event::occurrence( const QDate& date )
128{ 389{
129 // calculates the number of occurrances of this day of the 390 // calculates the number of occurrances of this day of the
130 // week till the given date (e.g 3rd Wednesday of the month) 391 // week till the given date (e.g 3rd Wednesday of the month)
131 return ( date.day() - 1 ) / 7 + 1; 392 return ( date.day() - 1 ) / 7 + 1;
132} 393}
133 394
395/*!
396 \internal
397*/
134int Event::dayOfWeek( char day ) 398int Event::dayOfWeek( char day )
135{ 399{
136 int dayOfWeek = 1; 400 int dayOfWeek = 1;
137 char i = Event::MON; 401 char i = Event::MON;
138 while ( !( i & day ) && i <= Event::SUN ) { 402 while ( !( i & day ) && i <= Event::SUN ) {
139 i <<= 1; 403 i <<= 1;
140 ++dayOfWeek; 404 ++dayOfWeek;
141 } 405 }
142 return dayOfWeek; 406 return dayOfWeek;
143} 407}
144 408
409/*!
410 \internal
411*/
145int Event::monthDiff( const QDate& first, const QDate& second ) 412int Event::monthDiff( const QDate& first, const QDate& second )
146{ 413{
147 return ( second.year() - first.year() ) * 12 + 414 return ( second.year() - first.year() ) * 12 +
148 second.month() - first.month(); 415 second.month() - first.month();
149} 416}
150 417
418/*!
419 \internal
420*/
151QMap<int, QString> Event::toMap() const 421QMap<int, QString> Event::toMap() const
152{ 422{
153 QMap<int, QString> m; 423 QMap<int, QString> m;
154 m.insert( DatebookDescription, description() ); 424
155 m.insert ( Location, location() ); 425 if ( !description().isEmpty() )
156 m.insert ( DatebookCategory, idsToString( categories() ) ); 426 m.insert( DatebookDescription, description() );
157 m.insert ( TimeZone, timeZone() ); 427 if ( !location().isEmpty() )
158 m.insert ( Note, notes() ); 428 m.insert ( Location, location() );
429 if ( categories().count() )
430 m.insert ( DatebookCategory, idsToString( categories() ) );
431 if ( !timeZone().isEmpty() )
432 m.insert ( TimeZone, timeZone() );
433 if ( !notes().isEmpty() )
434 m.insert ( Note, notes() );
435
159 m.insert ( StartDateTime, QString::number( TimeConversion::toUTC( start() ) ) ); 436 m.insert ( StartDateTime, QString::number( TimeConversion::toUTC( start() ) ) );
160 m.insert ( EndDateTime, QString::number( TimeConversion::toUTC( end() ) ) ); 437 m.insert ( EndDateTime, QString::number( TimeConversion::toUTC( end() ) ) );
161 m.insert ( DatebookType, QString::number( (int)type() ) ); 438 m.insert ( DatebookType, QString::number( (int)type() ) );
162 m.insert ( HasAlarm, ( hasAlarm() ? "1" : "0" ) ); 439 m.insert ( HasAlarm, ( hasAlarm() ? "1" : "0" ) );
163 m.insert ( SoundType, QString::number( (int)alarmSound() ) ); 440 m.insert ( SoundType, QString::number( (int)alarmSound() ) );
164 m.insert ( AlarmTime, QString::number( alarmTime() ) ); 441 m.insert ( AlarmTime, QString::number( alarmTime() ) );
165 m.insert ( RepeatPatternType, QString::number( static_cast<int>( repeatPattern().type ) ) ); 442 m.insert ( RepeatPatternType, QString::number( static_cast<int>( repeatPattern().type ) ) );
166 m.insert ( RepeatPatternFrequency, QString::number( repeatPattern().frequency ) ); 443 m.insert ( RepeatPatternFrequency, QString::number( repeatPattern().frequency ) );
167 m.insert ( RepeatPatternPosition, QString::number( repeatPattern().position ) ); 444 m.insert ( RepeatPatternPosition, QString::number( repeatPattern().position ) );
168 m.insert ( RepeatPatternDays, QString::number( repeatPattern().days ) ); 445 m.insert ( RepeatPatternDays, QString::number( repeatPattern().days ) );
169 m.insert ( RepeatPatternHasEndDate, QString::number( static_cast<int>( repeatPattern().hasEndDate ) ) ); 446 m.insert ( RepeatPatternHasEndDate, QString::number( static_cast<int>( repeatPattern().hasEndDate ) ) );
170 m.insert ( RepeatPatternEndDate, QString::number( repeatPattern().endDateUTC ) ); 447 m.insert ( RepeatPatternEndDate, QString::number( repeatPattern().endDateUTC ) );
171 448
172 m.insert( DatebookUid, QString::number( uid()) ); 449 m.insert( DatebookUid, QString::number( uid()) );
173 450
174 return m; 451 return m;
175} 452}
176 453
454/*!
455 \internal
456*/
177void Event::setRepeat( const RepeatPattern &p ) 457void Event::setRepeat( const RepeatPattern &p )
178{ 458{
179 setRepeat( p.type != NoRepeat, p ); 459 setRepeat( p.type != NoRepeat, p );
180} 460}
181 461
462/*!
463 Sets the description of the event to \a s.
464*/
182void Event::setDescription( const QString &s ) 465void Event::setDescription( const QString &s )
183{ 466{
184 descript = s; 467 descript = s;
185} 468}
186 469
470/*!
471 Sets the location of the event to \a s.
472*/
187void Event::setLocation( const QString &s ) 473void Event::setLocation( const QString &s )
188{ 474{
189 locat = s; 475 locat = s;
190} 476}
191 477
192// void Event::setCategory( const QString &s ) 478// void Event::setCategory( const QString &s )
193// { 479// {
194// categ = s; 480// categ = s;
195// } 481// }
196 482
483/*!
484 \internal
485*/
197void Event::setType( Type t ) 486void Event::setType( Type t )
198{ 487{
199 typ = t; 488 typ = t;
200} 489}
201 490
491/*!
492 Sets the start date and time of the first or only occurance of this event
493 to the date and time \a d. \a d should be in local time.
494*/
202void Event::setStart( const QDateTime &d ) 495void Event::setStart( const QDateTime &d )
203{ 496{
204 startUTC = TimeConversion::toUTC( d ); 497 startUTC = TimeConversion::toUTC( d );
205} 498}
206 499
500/*!
501 \internal
502*/
207void Event::setStart( time_t time ) 503void Event::setStart( time_t time )
208{ 504{
209 startUTC = time; 505 startUTC = time;
210} 506}
211 507
508/*!
509 Sets the end date and time of the first or only occurance of this event
510 to the date and time \a d. \a d should be in local time.
511*/
212void Event::setEnd( const QDateTime &d ) 512void Event::setEnd( const QDateTime &d )
213{ 513{
214 endUTC = TimeConversion::toUTC( d ); 514 endUTC = TimeConversion::toUTC( d );
215} 515}
216 516
517/*!
518 \internal
519*/
217void Event::setEnd( time_t time ) 520void Event::setEnd( time_t time )
218{ 521{
219 endUTC = time; 522 endUTC = time;
220} 523}
221 524
525/*!
526 \internal
527*/
222void Event::setTimeZone( const QString &z ) 528void Event::setTimeZone( const QString &z )
223{ 529{
224 tz = z; 530 tz = z;
225} 531}
226 532
533/*!
534 \internal
535*/
227void Event::setAlarm( bool b, int minutes, SoundTypeChoice s ) 536void Event::setAlarm( bool b, int minutes, SoundTypeChoice s )
228{ 537{
229 hAlarm = b; 538 hAlarm = b;
230 aMinutes = minutes; 539 aMinutes = minutes;
231 aSound = s; 540 aSound = s;
232} 541}
233 542
543/*!
544 \internal
545*/
234void Event::setRepeat( bool b, const RepeatPattern &p ) 546void Event::setRepeat( bool b, const RepeatPattern &p )
235{ 547{
236 hRepeat = b; 548 hRepeat = b;
237 pattern = p; 549 pattern = p;
238} 550}
239 551
552/*!
553 Sets the notes for the event to \a n.
554*/
240void Event::setNotes( const QString &n ) 555void Event::setNotes( const QString &n )
241{ 556{
242 note = n; 557 note = n;
243} 558}
244 559
560/*!
561 Returns the description of the event.
562*/
245const QString &Event::description() const 563const QString &Event::description() const
246{ 564{
247 return descript; 565 return descript;
248} 566}
249 567
568/*!
569 Returns the location of the event.
570*/
250const QString &Event::location() const 571const QString &Event::location() const
251{ 572{
252 return locat; 573 return locat;
253} 574}
254 575
255// QString Event::category() const 576// QString Event::category() const
256// { 577// {
257// return categ; 578// return categ;
258// } 579// }
259 580
581/*!
582 \internal
583*/
260Event::Type Event::type() const 584Event::Type Event::type() const
261{ 585{
262 return typ; 586 return typ;
263} 587}
264 588
589/*!
590 \internal
591*/
265QDateTime Event::start( bool actual ) const 592QDateTime Event::start( bool actual ) const
266{ 593{
267 QDateTime dt = (startUTC > 0) ? TimeConversion::fromUTC( startUTC ) : QDateTime::currentDateTime(); 594 QDateTime dt = (startUTC > 0) ? TimeConversion::fromUTC( startUTC ) : QDateTime::currentDateTime();
268 595
269 if ( actual && typ == AllDay ) { 596 if ( actual && typ == AllDay ) {
270 QTime t = dt.time(); 597 QTime t = dt.time();
271 t.setHMS( 0, 0, 0 ); 598 t.setHMS( 0, 0, 0 );
272 dt.setTime( t ); 599 dt.setTime( t );
273 } 600 }
274 return dt; 601 return dt;
275} 602}
276 603
604/*!
605 \internal
606*/
277QDateTime Event::end( bool actual ) const 607QDateTime Event::end( bool actual ) const
278{ 608{
279 QDateTime dt = (endUTC > 0) ? TimeConversion::fromUTC( endUTC ) : QDateTime::currentDateTime(); 609 QDateTime dt = (endUTC > 0) ? TimeConversion::fromUTC( endUTC ) : QDateTime::currentDateTime();
280 610
281 if ( actual && typ == AllDay ) { 611 if ( actual && typ == AllDay ) {
282 QTime t = dt.time(); 612 QTime t = dt.time();
283 t.setHMS( 23, 59, 59 ); 613 t.setHMS( 23, 59, 59 );
284 dt.setTime( t ); 614 dt.setTime( t );
285 } 615 }
286 return dt; 616 return dt;
287} 617}
288 618
619/*!
620 \internal
621*/
289const QString &Event::timeZone() const 622const QString &Event::timeZone() const
290{ 623{
291 return tz; 624 return tz;
292} 625}
293 626
627/*!
628 \internal
629*/
294bool Event::hasAlarm() const 630bool Event::hasAlarm() const
295{ 631{
296 return hAlarm; 632 return hAlarm;
297} 633}
298 634
635/*!
636 \internal
637*/
299int Event::alarmTime() const 638int Event::alarmTime() const
300{ 639{
301 return aMinutes; 640 return aMinutes;
302} 641}
303 642
643/*!
644 Returns the sound type for the alarm of this event.
645*/
304Event::SoundTypeChoice Event::alarmSound() const 646Event::SoundTypeChoice Event::alarmSound() const
305{ 647{
306 return aSound; 648 return aSound;
307} 649}
308 650
651/*!
652 \internal
653*/
309bool Event::hasRepeat() const 654bool Event::hasRepeat() const
310{ 655{
311 return doRepeat(); 656 return doRepeat();
312} 657}
313 658
659/*!
660 \internal
661*/
314const Event::RepeatPattern &Event::repeatPattern() const 662const Event::RepeatPattern &Event::repeatPattern() const
315{ 663{
316 return pattern; 664 return pattern;
317} 665}
318 666
667/*!
668 \internal
669*/
319Event::RepeatPattern &Event::repeatPattern() 670Event::RepeatPattern &Event::repeatPattern()
320{ 671{
321 return pattern; 672 return pattern;
322} 673}
323 674
675/*!
676 Returns the notes for the event.
677*/
324const QString &Event::notes() const 678const QString &Event::notes() const
325{ 679{
326 return note; 680 return note;
327} 681}
328 682
683/*!
684 \internal
685*/
329bool Event::operator==( const Event &e ) const 686bool Event::operator==( const Event &e ) const
330{ 687{
688 if ( uid() && e.uid() == uid() )
689 return TRUE;
331 return ( e.descript == descript && 690 return ( e.descript == descript &&
332 e.locat == locat && 691 e.locat == locat &&
333 e.categ == categ && 692 e.categ == categ &&
334 e.typ == typ && 693 e.typ == typ &&
335 e.startUTC == startUTC && 694 e.startUTC == startUTC &&
336 e.endUTC == endUTC && 695 e.endUTC == endUTC &&
337 e.tz == tz && 696 e.tz == tz &&
338 e.hAlarm == hAlarm && 697 e.hAlarm == hAlarm &&
339 e.aMinutes == aMinutes && 698 e.aMinutes == aMinutes &&
340 e.aSound == aSound && 699 e.aSound == aSound &&
341 e.hRepeat == hRepeat && 700 e.hRepeat == hRepeat &&
342 e.pattern == pattern && 701 e.pattern == pattern &&
343 e.note == note ); 702 e.note == note );
344} 703}
345 704
705/*!
706 \internal
707 Appends the contact information to \a buf.
708*/
346void Event::save( QString& buf ) 709void Event::save( QString& buf )
347{ 710{
348 buf += " description=\"" + Qtopia::escapeString(descript) + "\""; 711 buf += " description=\"" + Qtopia::escapeString(descript) + "\"";
349 if ( !locat.isEmpty() ) 712 if ( !locat.isEmpty() )
350 buf += " location=\"" + Qtopia::escapeString(locat) + "\""; 713 buf += " location=\"" + Qtopia::escapeString(locat) + "\"";
351 // save the categoies differently.... 714 // save the categoies differently....
352 QString strCats = idsToString( categories() ); 715 QString strCats = idsToString( categories() );
353 buf += " categories=\"" + Qtopia::escapeString(strCats) + "\""; 716 buf += " categories=\"" + Qtopia::escapeString(strCats) + "\"";
354 buf += " uid=\"" + QString::number( uid() ) + "\""; 717 buf += " uid=\"" + QString::number( uid() ) + "\"";
355 if ( (Type)typ != Normal ) 718 if ( (Type)typ != Normal )
356 buf += " type=\"AllDay\""; 719 buf += " type=\"AllDay\"";
357 if ( hAlarm ) { 720 if ( hAlarm ) {
358 buf += " alarm=\"" + QString::number( aMinutes ) + "\" sound=\""; 721 buf += " alarm=\"" + QString::number( aMinutes ) + "\" sound=\"";
359 if ( aSound == Event::Loud ) 722 if ( aSound == Event::Loud )
360 buf += "loud"; 723 buf += "loud";
361 else 724 else
362 buf += "silent"; 725 buf += "silent";
363 buf += "\""; 726 buf += "\"";
364 } 727 }
365 if ( hRepeat ) 728 if ( hRepeat )
366 write( buf, pattern ); 729 write( buf, pattern );
367 730
368 buf += " start=\"" 731 buf += " start=\""
369 + QString::number( startUTC ) 732 + QString::number( startUTC )
370 + "\""; 733 + "\"";
371 734
372 buf += " end=\"" 735 buf += " end=\""
373 + QString::number( endUTC ) 736 + QString::number( endUTC )
374 + "\""; 737 + "\"";
375 738
376 if ( !note.isEmpty() ) 739 if ( !note.isEmpty() )
377 buf += " note=\"" + Qtopia::escapeString( note ) + "\""; 740 buf += " note=\"" + Qtopia::escapeString( note ) + "\"";
378 buf += customToXml(); 741 buf += customToXml();
379} 742}
380 743
744/*!
745 \internal
746*/
381bool Event::RepeatPattern::operator==( const Event::RepeatPattern &right ) const 747bool Event::RepeatPattern::operator==( const Event::RepeatPattern &right ) const
382{ 748{
383 // *sigh* 749 // *sigh*
384 return ( type == right.type 750 return ( type == right.type
385 && frequency == right.frequency 751 && frequency == right.frequency
386 && position == right.position 752 && position == right.position
387 && days == right.days 753 && days == right.days
388 && hasEndDate == right.hasEndDate 754 && hasEndDate == right.hasEndDate
389 && endDateUTC == right.endDateUTC 755 && endDateUTC == right.endDateUTC
390 && createTime == right.createTime ); 756 && createTime == right.createTime );
391} 757}
392 758
759/*!
760 \class EffectiveEvent
761 \brief The EffectiveEvent class the data for a single occurance of an event.
762
763 This class describes the event for a single occurance of it. For example if
764 an Event occurs every week, the effective event might represent the third
765 occurance of this Event.
766
767 \ingroup qtopiaemb
768 \ingroup qtopiadesktop
769 \warning This class will be phased out in Qtopia 3.x
770*/
771
772/*!
773 \enum EffectiveEvent::Position
774 \internal
775*/
776
777/*!
778 \fn EffectiveEvent &EffectiveEvent::operator=(const EffectiveEvent &)
779 \internal
780*/
393 781
394class EffectiveEventPrivate 782class EffectiveEventPrivate
395{ 783{
396public: 784public:
397 //currently the existence of the d pointer means multi-day repeating, 785 //currently the existence of the d pointer means multi-day repeating,
398 //msut be changed if we use the d pointer for anything else. 786 //msut be changed if we use the d pointer for anything else.
399 QDate startDate; 787 QDate startDate;
400 QDate endDate; 788 QDate endDate;
401}; 789};
402 790
403 791/*!
792 \internal
793*/
404EffectiveEvent::EffectiveEvent() 794EffectiveEvent::EffectiveEvent()
405{ 795{
406 mDate = QDate::currentDate(); 796 mDate = QDate::currentDate();
407 mStart = mEnd = QTime::currentTime(); 797 mStart = mEnd = QTime::currentTime();
408 d = 0; 798 d = 0;
409} 799}
410 800
801/*!
802 \internal
803*/
411EffectiveEvent::EffectiveEvent( const Event &e, const QDate &date, Position pos ) 804EffectiveEvent::EffectiveEvent( const Event &e, const QDate &date, Position pos )
412{ 805{
413 mEvent = e; 806 mEvent = e;
414 mDate = date; 807 mDate = date;
415 if ( pos & Start ) 808 if ( pos & Start )
416 mStart = e.start( TRUE ).time(); 809 mStart = e.start( TRUE ).time();
417 else 810 else
418 mStart = QTime( 0, 0, 0 ); 811 mStart = QTime( 0, 0, 0 );
419 812
420 if ( pos & End ) 813 if ( pos & End )
421 mEnd = e.end( TRUE ).time(); 814 mEnd = e.end( TRUE ).time();
422 else 815 else
423 mEnd = QTime( 23, 59, 59 ); 816 mEnd = QTime( 23, 59, 59 );
424 d = 0; 817 d = 0;
425} 818}
426 819
820/*!
821 \internal
822*/
427EffectiveEvent::~EffectiveEvent() 823EffectiveEvent::~EffectiveEvent()
428{ 824{
429 delete d; 825 delete d;
430} 826}
431 827
828/*!
829 \internal
830*/
432EffectiveEvent::EffectiveEvent( const EffectiveEvent &e ) 831EffectiveEvent::EffectiveEvent( const EffectiveEvent &e )
433{ 832{
434 d = 0; 833 d = 0;
435 *this = e; 834 *this = e;
436} 835}
437 836
438EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e ) 837EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e )
439{ 838{
440 if ( &e == this ) 839 if ( &e == this )
441 return *this; 840 return *this;
442 delete d; 841 delete d;
443 if ( e.d ) { 842 if ( e.d ) {
444 d = new EffectiveEventPrivate; 843 d = new EffectiveEventPrivate;
445 d->startDate = e.d->startDate; 844 d->startDate = e.d->startDate;
446 d->endDate = e.d->endDate; 845 d->endDate = e.d->endDate;
447 } else { 846 } else {
448 d = 0; 847 d = 0;
449 } 848 }
450 mEvent = e.mEvent; 849 mEvent = e.mEvent;
451 mDate = e.mDate; 850 mDate = e.mDate;
452 mStart = e.mStart; 851 mStart = e.mStart;
453 mEnd = e.mEnd; 852 mEnd = e.mEnd;
454 853
455 return *this; 854 return *this;
456 855
457} 856}
458 857
459// QString EffectiveEvent::category() const 858// QString EffectiveEvent::category() const
460// { 859// {
461// return mEvent.category(); 860// return mEvent.category();
462// } 861// }
463 862
863/*!
864 Returns the description of the event for this effective event.
865*/
464const QString &EffectiveEvent::description( ) const 866const QString &EffectiveEvent::description( ) const
465{ 867{
466 return mEvent.description(); 868 return mEvent.description();
467} 869}
468 870
871/*!
872\internal
873*/
469const QString &EffectiveEvent::location( ) const 874const QString &EffectiveEvent::location( ) const
470{ 875{
471 return mEvent.location(); 876 return mEvent.location();
472} 877}
473 878
879/*!
880\internal
881*/
474const QString &EffectiveEvent::notes() const 882const QString &EffectiveEvent::notes() const
475{ 883{
476 return mEvent.notes(); 884 return mEvent.notes();
477} 885}
478 886
887/*!
888 Returns the event associated with this effective event.
889*/
479const Event &EffectiveEvent::event() const 890const Event &EffectiveEvent::event() const
480{ 891{
481 return mEvent; 892 return mEvent;
482} 893}
483 894
895/*!
896 \internal
897*/
484const QTime &EffectiveEvent::end() const 898const QTime &EffectiveEvent::end() const
485{ 899{
486 return mEnd; 900 return mEnd;
487} 901}
488 902
903/*!
904 \internal
905*/
489const QTime &EffectiveEvent::start() const 906const QTime &EffectiveEvent::start() const
490{ 907{
491 return mStart; 908 return mStart;
492} 909}
493 910
911/*!
912 Returns the date the effective event occurs on.
913*/
494const QDate &EffectiveEvent::date() const 914const QDate &EffectiveEvent::date() const
495{ 915{
496 return mDate; 916 return mDate;
497} 917}
498 918
919/*!
920 \internal
921*/
499int EffectiveEvent::length() const 922int EffectiveEvent::length() const
500{ 923{
501 return (mEnd.hour() * 60 - mStart.hour() * 60) 924 return (mEnd.hour() * 60 - mStart.hour() * 60)
502 + QABS(mStart.minute() - mEnd.minute() ); 925 + QABS(mStart.minute() - mEnd.minute() );
503} 926}
504 927
928/*!
929 \internal
930*/
505void EffectiveEvent::setDate( const QDate &dt ) 931void EffectiveEvent::setDate( const QDate &dt )
506{ 932{
507 mDate = dt; 933 mDate = dt;
508} 934}
509 935
936/*!
937 \internal
938*/
510void EffectiveEvent::setStart( const QTime &start ) 939void EffectiveEvent::setStart( const QTime &start )
511{ 940{
512 mStart = start; 941 mStart = start;
513} 942}
514 943
944/*!
945 \internal
946*/
515void EffectiveEvent::setEnd( const QTime &end ) 947void EffectiveEvent::setEnd( const QTime &end )
516{ 948{
517 mEnd = end; 949 mEnd = end;
518} 950}
519 951
952/*!
953 \internal
954*/
520void EffectiveEvent::setEvent( Event e ) 955void EffectiveEvent::setEvent( Event e )
521{ 956{
522 mEvent = e; 957 mEvent = e;
523} 958}
524 959
960/*!
961 \internal
962*/
525bool EffectiveEvent::operator<( const EffectiveEvent &e ) const 963bool EffectiveEvent::operator<( const EffectiveEvent &e ) const
526{ 964{
527 if ( mDate < e.date() ) 965 if ( mDate < e.date() )
528 return TRUE; 966 return TRUE;
529 if ( mDate == e.date() ) 967 if ( mDate == e.date() )
530 return ( mStart < e.start() ); 968 return ( mStart < e.start() );
531 else 969 else
532 return FALSE; 970 return FALSE;
533} 971}
534 972
973/*!
974 \internal
975*/
535bool EffectiveEvent::operator<=( const EffectiveEvent &e ) const 976bool EffectiveEvent::operator<=( const EffectiveEvent &e ) const
536{ 977{
537 return (mDate <= e.date() ); 978 return (mDate <= e.date() );
538} 979}
539 980
981/*!
982 \internal
983*/
540bool EffectiveEvent::operator==( const EffectiveEvent &e ) const 984bool EffectiveEvent::operator==( const EffectiveEvent &e ) const
541{ 985{
542 return ( mDate == e.date() 986 return ( mDate == e.date()
543 && mStart == e.start() 987 && mStart == e.start()
544 && mEnd == e.end() 988 && mEnd == e.end()
545 && mEvent == e.event() ); 989 && mEvent == e.event() );
546} 990}
547 991
992/*!
993 \internal
994*/
548bool EffectiveEvent::operator!=( const EffectiveEvent &e ) const 995bool EffectiveEvent::operator!=( const EffectiveEvent &e ) const
549{ 996{
550 return !(*this == e); 997 return !(*this == e);
551} 998}
552 999
1000/*!
1001 \internal
1002*/
553bool EffectiveEvent::operator>( const EffectiveEvent &e ) const 1003bool EffectiveEvent::operator>( const EffectiveEvent &e ) const
554{ 1004{
555 return !(*this <= e ); 1005 return !(*this <= e );
556} 1006}
557 1007
1008/*!
1009 \internal
1010*/
558bool EffectiveEvent::operator>=(const EffectiveEvent &e) const 1011bool EffectiveEvent::operator>=(const EffectiveEvent &e) const
559{ 1012{
560 return !(*this < e); 1013 return !(*this < e);
561} 1014}
562 1015
1016/*!
1017 \internal
1018*/
563void EffectiveEvent::setEffectiveDates( const QDate &from, const QDate &to ) 1019void EffectiveEvent::setEffectiveDates( const QDate &from, const QDate &to )
564{ 1020{
565 if ( !from.isValid() ) { 1021 if ( !from.isValid() ) {
566 delete d; 1022 delete d;
567 d = 0; 1023 d = 0;
568 return; 1024 return;
569 } 1025 }
570 if ( !d ) 1026 if ( !d )
571 d = new EffectiveEventPrivate; 1027 d = new EffectiveEventPrivate;
572 d->startDate = from; 1028 d->startDate = from;
573 d->endDate = to; 1029 d->endDate = to;
574} 1030}
575 1031
1032/*!
1033 \internal
1034*/
576QDate EffectiveEvent::startDate() const 1035QDate EffectiveEvent::startDate() const
577{ 1036{
578 if ( d ) 1037 if ( d )
579 return d->startDate; 1038 return d->startDate;
580 else if ( mEvent.hasRepeat() ) 1039 else if ( mEvent.hasRepeat() )
581 return mDate; // single day, since multi-day should have a d pointer 1040 return mDate; // single day, since multi-day should have a d pointer
582 else 1041 else
583 return mEvent.start().date(); 1042 return mEvent.start().date();
584} 1043}
585 1044
1045/*!
1046 \internal
1047*/
586QDate EffectiveEvent::endDate() const 1048QDate EffectiveEvent::endDate() const
587{ 1049{
588 if ( d ) 1050 if ( d )
589 return d->endDate; 1051 return d->endDate;
590 else if ( mEvent.hasRepeat() ) 1052 else if ( mEvent.hasRepeat() )
591 return mDate; // single day, since multi-day should have a d pointer 1053 return mDate; // single day, since multi-day should have a d pointer
592 else 1054 else
593 return mEvent.end().date(); 1055 return mEvent.end().date();
594} 1056}
595 1057
1058/*!
1059 \internal
1060*/
596int EffectiveEvent::size() const 1061int EffectiveEvent::size() const
597{ 1062{
598 return ( mEnd.hour() - mStart.hour() ) * 3600 1063 return ( mEnd.hour() - mStart.hour() ) * 3600
599 + (mEnd.minute() - mStart.minute() * 60 1064 + (mEnd.minute() - mStart.minute() * 60
600 + mEnd.second() - mStart.second() ); 1065 + mEnd.second() - mStart.second() );
601} 1066}
602 1067
603 1068
604// vcal conversion code 1069// vcal conversion code
605static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value ) 1070static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
606{ 1071{
607 VObject *ret = 0; 1072 VObject *ret = 0;
608 if ( o && !value.isEmpty() ) 1073 if ( o && !value.isEmpty() )
609 ret = addPropValue( o, prop, value.latin1() ); 1074 ret = addPropValue( o, prop, value.latin1() );
610 return ret; 1075 return ret;
611} 1076}
612 1077
613static inline VObject *safeAddProp( VObject *o, const char *prop) 1078static inline VObject *safeAddProp( VObject *o, const char *prop)
614{ 1079{
615 VObject *ret = 0; 1080 VObject *ret = 0;
616 if ( o ) 1081 if ( o )
617 ret = addProp( o, prop ); 1082 ret = addProp( o, prop );
618 return ret; 1083 return ret;
619} 1084}
620 1085
621static VObject *createVObject( const Event &e ) 1086static VObject *createVObject( const Event &e )
622{ 1087{
623 VObject *vcal = newVObject( VCCalProp ); 1088 VObject *vcal = newVObject( VCCalProp );
624 safeAddPropValue( vcal, VCVersionProp, "1.0" ); 1089 safeAddPropValue( vcal, VCVersionProp, "1.0" );
625 VObject *event = safeAddProp( vcal, VCEventProp ); 1090 VObject *event = safeAddProp( vcal, VCEventProp );
626 1091
627 safeAddPropValue( event, VCDTstartProp, TimeConversion::toISO8601( e.start() ) ); 1092 safeAddPropValue( event, VCDTstartProp, TimeConversion::toISO8601( e.start() ) );
628 safeAddPropValue( event, VCDTendProp, TimeConversion::toISO8601( e.end() ) ); 1093 safeAddPropValue( event, VCDTendProp, TimeConversion::toISO8601( e.end() ) );
629 safeAddPropValue( event, "X-Qtopia-NOTES", e.description() ); 1094 safeAddPropValue( event, "X-Qtopia-NOTES", e.description() );
630 safeAddPropValue( event, VCDescriptionProp, e.description() ); 1095 safeAddPropValue( event, VCDescriptionProp, e.description() );
631 safeAddPropValue( event, VCLocationProp, e.location() ); 1096 safeAddPropValue( event, VCLocationProp, e.location() );
632 1097
633 if ( e.hasAlarm() ) { 1098 if ( e.hasAlarm() ) {
634 VObject *alarm = safeAddProp( event, VCAAlarmProp ); 1099 VObject *alarm = safeAddProp( event, VCAAlarmProp );
635 QDateTime dt = e.start(); 1100 QDateTime dt = e.start();
636 dt = dt.addSecs( -e.alarmTime()*60 ); 1101 dt = dt.addSecs( -e.alarmTime()*60 );
637 safeAddPropValue( alarm, VCRunTimeProp, TimeConversion::toISO8601( dt ) ); 1102 safeAddPropValue( alarm, VCRunTimeProp, TimeConversion::toISO8601( dt ) );
638 safeAddPropValue( alarm, VCAudioContentProp, 1103 safeAddPropValue( alarm, VCAudioContentProp,
639 (e.alarmSound() == Event::Silent ? "silent" : "alarm" ) ); 1104 (e.alarmSound() == Event::Silent ? "silent" : "alarm" ) );
640 } 1105 }
641 1106
642 safeAddPropValue( event, "X-Qtopia-TIMEZONE", e.timeZone() ); 1107 safeAddPropValue( event, "X-Qtopia-TIMEZONE", e.timeZone() );
643 1108
644 if ( e.type() == Event::AllDay ) 1109 if ( e.type() == Event::AllDay )
645 safeAddPropValue( event, "X-Qtopia-AllDay", e.timeZone() ); 1110 safeAddPropValue( event, "X-Qtopia-AllDay", e.timeZone() );
646 1111
647 // ### repeat missing 1112 // ### repeat missing
648 1113
649 // ### categories missing 1114 // ### categories missing
650 1115
651 return vcal; 1116 return vcal;
652} 1117}
653 1118
654 1119
655static Event parseVObject( VObject *obj ) 1120static Event parseVObject( VObject *obj )
656{ 1121{
657 Event e; 1122 Event e;
658 1123
659 bool haveAlarm = FALSE; 1124 bool haveAlarm = FALSE;
660 bool haveStart = FALSE; 1125 bool haveStart = FALSE;
661 bool haveEnd = FALSE; 1126 bool haveEnd = FALSE;
662 QDateTime alarmTime; 1127 QDateTime alarmTime;
663 Event::SoundTypeChoice soundType = Event::Silent; 1128 Event::SoundTypeChoice soundType = Event::Silent;
664 1129
665 VObjectIterator it; 1130 VObjectIterator it;
666 initPropIterator( &it, obj ); 1131 initPropIterator( &it, obj );
667 while( moreIteration( &it ) ) { 1132 while( moreIteration( &it ) ) {
668 VObject *o = nextVObject( &it ); 1133 VObject *o = nextVObject( &it );
669 QCString name = vObjectName( o ); 1134 QCString name = vObjectName( o );
670 QCString value = vObjectStringZValue( o ); 1135 QCString value = vObjectStringZValue( o );
671 if ( name == VCDTstartProp ) { 1136 if ( name == VCDTstartProp ) {
672 e.setStart( TimeConversion::fromISO8601( value ) ); 1137 e.setStart( TimeConversion::fromISO8601( value ) );
673 haveStart = TRUE; 1138 haveStart = TRUE;
674 } 1139 }
675 else if ( name == VCDTendProp ) { 1140 else if ( name == VCDTendProp ) {
676 e.setEnd( TimeConversion::fromISO8601( value ) ); 1141 e.setEnd( TimeConversion::fromISO8601( value ) );
677 haveEnd = TRUE; 1142 haveEnd = TRUE;
678 } 1143 }
679 else if ( name == "X-Qtopia-NOTES" ) { 1144 else if ( name == "X-Qtopia-NOTES" ) {
680 e.setNotes( value ); 1145 e.setNotes( value );
681 } 1146 }
682 else if ( name == VCDescriptionProp ) { 1147 else if ( name == VCDescriptionProp ) {
683 e.setDescription( value ); 1148 e.setDescription( value );
684 } 1149 }
685 else if ( name == VCLocationProp ) { 1150 else if ( name == VCLocationProp ) {
686 e.setLocation( value ); 1151 e.setLocation( value );
687 } 1152 }
688 else if ( name == VCAudioContentProp ) { 1153 else if ( name == VCAudioContentProp ) {
689 haveAlarm = TRUE; 1154 haveAlarm = TRUE;
690 VObjectIterator nit; 1155 VObjectIterator nit;
691 initPropIterator( &nit, o ); 1156 initPropIterator( &nit, o );
692 while( moreIteration( &nit ) ) { 1157 while( moreIteration( &nit ) ) {
693 VObject *o = nextVObject( &nit ); 1158 VObject *o = nextVObject( &nit );
694 QCString name = vObjectName( o ); 1159 QCString name = vObjectName( o );
695 QCString value = vObjectStringZValue( o ); 1160 QCString value = vObjectStringZValue( o );
696 if ( name == VCRunTimeProp ) 1161 if ( name == VCRunTimeProp )
697 alarmTime = TimeConversion::fromISO8601( value ); 1162 alarmTime = TimeConversion::fromISO8601( value );
698 else if ( name == VCAudioContentProp ) { 1163 else if ( name == VCAudioContentProp ) {
699 if ( value == "silent" ) 1164 if ( value == "silent" )
700 soundType = Event::Silent; 1165 soundType = Event::Silent;
701 else 1166 else
702 soundType = Event::Loud; 1167 soundType = Event::Loud;
703 } 1168 }
704 } 1169 }
705 } 1170 }
706 else if ( name == "X-Qtopia-TIMEZONE") { 1171 else if ( name == "X-Qtopia-TIMEZONE") {
707 e.setTimeZone( value ); 1172 e.setTimeZone( value );
708 } 1173 }
709 else if ( name == "X-Qtopia-AllDay" ) { 1174 else if ( name == "X-Qtopia-AllDay" ) {
710 e.setType( Event::AllDay ); 1175 e.setType( Event::AllDay );
711 } 1176 }
712#if 0 1177#if 0
713 else { 1178 else {
714 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); 1179 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
715 VObjectIterator nit; 1180 VObjectIterator nit;
716 initPropIterator( &nit, o ); 1181 initPropIterator( &nit, o );
717 while( moreIteration( &nit ) ) { 1182 while( moreIteration( &nit ) ) {
718 VObject *o = nextVObject( &nit ); 1183 VObject *o = nextVObject( &nit );
719 QCString name = vObjectName( o ); 1184 QCString name = vObjectName( o );
720 QString value = vObjectStringZValue( o ); 1185 QString value = vObjectStringZValue( o );
721 printf(" subprop: %s = %s\n", name.data(), value.latin1() ); 1186 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
722 } 1187 }
723 } 1188 }
724#endif 1189#endif
725 } 1190 }
726 1191
727 if ( !haveStart && !haveEnd ) 1192 if ( !haveStart && !haveEnd )
728 e.setStart( QDateTime::currentDateTime() ); 1193 e.setStart( QDateTime::currentDateTime() );
729 1194
730 if ( !haveEnd ) { 1195 if ( !haveEnd ) {
731 e.setType( Event::AllDay ); 1196 e.setType( Event::AllDay );
732 e.setEnd( e.start() ); 1197 e.setEnd( e.start() );
733 } 1198 }
734 1199
735 if ( haveAlarm ) { 1200 if ( haveAlarm ) {
736 int minutes = alarmTime.secsTo( e.start() ) / 60; 1201 int minutes = alarmTime.secsTo( e.start() ) / 60;
737 e.setAlarm( TRUE, minutes, soundType ); 1202 e.setAlarm( TRUE, minutes, soundType );
738 } 1203 }
739 return e; 1204 return e;
740} 1205}
741 1206
742 1207
743 1208/*!
1209 Writes the list of \a events as a set of VCards to the file \a filename.
1210*/
744void Event::writeVCalendar( const QString &filename, const QValueList<Event> &events) 1211void Event::writeVCalendar( const QString &filename, const QValueList<Event> &events)
745{ 1212{
746 QFileDirect f( filename.utf8().data() ); 1213
747 if ( !f.open( IO_WriteOnly ) ) { 1214 QFileDirect f( filename.utf8().data() );
748 qWarning("Unable to open vcard write"); 1215
749 return; 1216 if ( !f.open( IO_WriteOnly ) ) {
750 } 1217
1218 qWarning("Unable to open vcard write");
1219
1220 return;
1221
1222 }
1223
751 1224
752 QValueList<Event>::ConstIterator it; 1225 QValueList<Event>::ConstIterator it;
753 for( it = events.begin(); it != events.end(); ++it ) { 1226 for( it = events.begin(); it != events.end(); ++it ) {
754 VObject *obj = createVObject( *it ); 1227 VObject *obj = createVObject( *it );
755 writeVObject( f.directHandle() , obj ); 1228 writeVObject( f.directHandle() , obj );
756 cleanVObject( obj ); 1229 cleanVObject( obj );
757 } 1230 }
1231
758 1232
759 cleanStrTbl(); 1233 cleanStrTbl();
760} 1234}
761 1235
1236/*!
1237 Writes \a event as a VCard to the file \a filename.
1238*/
762void Event::writeVCalendar( const QString &filename, const Event &event) 1239void Event::writeVCalendar( const QString &filename, const Event &event)
763{ 1240{
764 QFileDirect f( filename.utf8().data() ); 1241
765 if ( !f.open( IO_WriteOnly ) ) { 1242 QFileDirect f( filename.utf8().data() );
766 qWarning("Unable to open vcard write"); 1243
767 return; 1244 if ( !f.open( IO_WriteOnly ) ) {
768 } 1245
1246 qWarning("Unable to open vcard write");
1247
1248 return;
1249
1250 }
1251
769 1252
770 VObject *obj = createVObject( event ); 1253 VObject *obj = createVObject( event );
771 writeVObject( f.directHandle() , obj ); 1254 writeVObject( f.directHandle() , obj );
772 cleanVObject( obj ); 1255 cleanVObject( obj );
773 1256
774 cleanStrTbl(); 1257 cleanStrTbl();
775} 1258}
776 1259
777 1260/*!
1261 Returns the set of events read as VCards from the file \a filename.
1262*/
778QValueList<Event> Event::readVCalendar( const QString &filename ) 1263QValueList<Event> Event::readVCalendar( const QString &filename )
779{ 1264{
780 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() ); 1265 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
781 1266
782 QValueList<Event> events; 1267 QValueList<Event> events;
783 1268
784 while ( obj ) { 1269 while ( obj ) {
785 QCString name = vObjectName( obj ); 1270 QCString name = vObjectName( obj );
786 if ( name == VCCalProp ) { 1271 if ( name == VCCalProp ) {
787 VObjectIterator nit; 1272 VObjectIterator nit;
788 initPropIterator( &nit, obj ); 1273 initPropIterator( &nit, obj );
789 while( moreIteration( &nit ) ) { 1274 while( moreIteration( &nit ) ) {
790 VObject *o = nextVObject( &nit ); 1275 VObject *o = nextVObject( &nit );
791 QCString name = vObjectName( o ); 1276 QCString name = vObjectName( o );
792 if ( name == VCEventProp ) 1277 if ( name == VCEventProp )
793 events.append( parseVObject( o ) ); 1278 events.append( parseVObject( o ) );
794 } 1279 }
795 } else if ( name == VCEventProp ) { 1280 } else if ( name == VCEventProp ) {
796 // shouldn't happen, but just to be sure 1281 // shouldn't happen, but just to be sure
797 events.append( parseVObject( obj ) ); 1282 events.append( parseVObject( obj ) );
798 } 1283 }
799 VObject *t = obj; 1284 VObject *t = obj;
800 obj = nextVObjectInList(obj); 1285 obj = nextVObjectInList(obj);
801 cleanVObject( t ); 1286 cleanVObject( t );
802 } 1287 }
803 1288
804 return events; 1289 return events;
805} 1290}
806 1291
807bool Event::match( const QRegExp &r ) const 1292bool Event::match( const QRegExp &r ) const
808{ 1293{
809 bool returnMe; 1294 bool returnMe;
810 returnMe = false; 1295 returnMe = false;
811 1296
812 if ( descript.find( r ) > -1 ) 1297 if ( descript.find( r ) > -1 )
813 returnMe = true; 1298 returnMe = true;
814 else if ( locat.find( r ) > -1 ) 1299 else if ( locat.find( r ) > -1 )
815 returnMe = true; 1300 returnMe = true;
816 else if ( TimeConversion::fromUTC( startUTC ).toString().find( r ) > -1 ) 1301 else if ( TimeConversion::fromUTC( startUTC ).toString().find( r ) > -1 )
817 returnMe = true; 1302 returnMe = true;
818 else if ( TimeConversion::fromUTC( endUTC ).toString().find( r ) > -1 ) 1303 else if ( TimeConversion::fromUTC( endUTC ).toString().find( r ) > -1 )
819 returnMe = true; 1304 returnMe = true;
820 else if ( tz.find( r ) > -1 ) 1305 else if ( tz.find( r ) > -1 )
821 returnMe = true; 1306 returnMe = true;
822 else if ( note.find( r ) > -1 ) 1307 else if ( note.find( r ) > -1 )
823 returnMe = true; 1308 returnMe = true;
824 else if ( doRepeat() ) { 1309 else if ( doRepeat() ) {
825 if ( pattern.hasEndDate ) 1310 if ( pattern.hasEndDate )
826 if ( TimeConversion::fromUTC( pattern.endDateUTC ).toString().find(r) > -1 ) 1311 if ( TimeConversion::fromUTC( pattern.endDateUTC ).toString().find(r) > -1 )
827 returnMe = true; 1312 returnMe = true;
828 } 1313 }
829 return returnMe; 1314 return returnMe;
830} 1315}
diff --git a/library/backend/event.h b/library/backend/event.h
index 277aadd..7fe41a5 100644
--- a/library/backend/event.h
+++ b/library/backend/event.h
@@ -1,234 +1,375 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#ifndef __EVENT_H__ 21#ifndef __EVENT_H__
22#define __EVENT_H__ 22#define __EVENT_H__
23 23
24#include <qdatetime.h> 24#include <qdatetime.h>
25#include <qvaluelist.h> 25#include <qvaluelist.h>
26#include <qcolor.h>
26 27
27#ifdef PALMTOPCENTER 28#ifdef PALMTOPCENTER
28#include <qpc/qsorter.h> 29#include <qpc/qsorter.h>
29#endif 30#endif
30#include <qpe/palmtoprecord.h> 31#include <qtopia/private/palmtoprecord.h>
31 32
32#include <qpe/timeconversion.h> 33#include <qpe/timeconversion.h>
33 34
35static const QColor colorNormal = QColor(255, 0 , 0 );
36static const QColor colorRepeat = QColor(0 , 0 , 255);
37static const QColor colorNormalLight = QColor(255, 220, 220);
38static const QColor colorRepeatLight = QColor(200, 200, 255);
39
34class EventPrivate; 40class EventPrivate;
35class QPC_EXPORT Event : public Qtopia::Record 41class QPC_EXPORT Event : public Qtopia::Record
36{ 42{
37public: 43public:
38 enum RepeatType { NoRepeat = -1, Daily, Weekly, MonthlyDay, 44 enum RepeatType { NoRepeat = -1, Daily, Weekly, MonthlyDay,
39 MonthlyDate, Yearly }; 45 MonthlyDate, Yearly };
46
47 // Don't use this.
40 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, 48 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
41 FRI = 0x10, SAT = 0x20, SUN = 0x40 }; 49 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
50 // Don't use this.
42 struct QPC_EXPORT RepeatPattern 51 struct QPC_EXPORT RepeatPattern
43 { 52 {
44 RepeatPattern() { 53 RepeatPattern() {
45 type = NoRepeat; frequency = -1; days = 0; position = 0; createTime = -1; 54 type = NoRepeat; frequency = -1; days = 0; position = 0; createTime = -1;
46 hasEndDate = FALSE; endDateUTC = 0; } 55 hasEndDate = FALSE; endDateUTC = 0; }
47 bool operator ==( const RepeatPattern &right ) const; 56 bool operator ==( const RepeatPattern &right ) const;
48 57
49 RepeatType type; 58 RepeatType type;
50 int frequency; 59 int frequency;
51 int position;// the posistion in the month (e.g. the first sunday, etc) positive, count from the front negative count from the end... 60 int position;// the posistion in the month (e.g. the first sunday, etc) positive, count from the front negative count from the end...
52 char days; // a mask for days OR in your days! 61 char days; // a mask for days OR in your days!
53 bool hasEndDate; 62 bool hasEndDate;
54 QDate endDate() const { return TimeConversion::fromUTC( endDateUTC ).date(); } 63 QDate endDate() const { return TimeConversion::fromUTC( endDateUTC ).date(); }
55 void setEndDate( const QDate &dt ) { endDateUTC = TimeConversion::toUTC( dt ); } 64 void setEndDate( const QDate &dt ) { endDateUTC = TimeConversion::toUTC( dt ); }
56 time_t endDateUTC; 65 time_t endDateUTC;
57 time_t createTime; 66 time_t createTime;
58 }; 67 };
59 68
60 Event(); 69 Event();
61 Event( const QMap<int, QString > & map ); 70 Event( const QMap<int, QString > & map );
62 virtual ~Event(); 71 virtual ~Event();
63 72
64 QMap<int, QString> toMap() const; 73 QMap<int, QString> toMap() const;
65 74
66 static void writeVCalendar( const QString &filename, const QValueList<Event> &events); 75 static void writeVCalendar( const QString &filename, const QValueList<Event> &events);
67 static void writeVCalendar( const QString &filename, const Event &event); 76 static void writeVCalendar( const QString &filename, const Event &event);
68 static QValueList<Event> readVCalendar( const QString &filename ); 77 static QValueList<Event> readVCalendar( const QString &filename );
69 78
70 enum Type { Normal, AllDay }; 79 enum Type { Normal, AllDay };
71 enum SoundTypeChoice { Silent, Loud }; 80 enum SoundTypeChoice { Silent, Loud };
72 81
82 // Don't use these, there are essentially meaningless.
73 bool operator<( const Event &e1) const { return start() < e1.start(); }; 83 bool operator<( const Event &e1) const { return start() < e1.start(); };
74 bool operator<=( const Event &e1 ) const { return start() <= e1.start(); }; 84 bool operator<=( const Event &e1 ) const { return start() <= e1.start(); };
75 bool operator!=( const Event &e1 ) const { return !( *this == e1 ); }; 85 bool operator!=( const Event &e1 ) const { return !( *this == e1 ); };
76 bool operator>( const Event &e1 ) const { return start() > e1.start(); }; 86 bool operator>( const Event &e1 ) const { return start() > e1.start(); };
77 bool operator>=(const Event &e1 ) const { return start() >= e1.start(); }; 87 bool operator>=(const Event &e1 ) const { return start() >= e1.start(); };
78 bool operator==( const Event &e ) const; 88 bool operator==( const Event &e ) const;
79 89
80 void setDescription( const QString &s ); 90 void setDescription( const QString &s );
81 const QString &description() const; 91 const QString &description() const;
82 92
83 void setLocation( const QString &s ); 93 void setLocation( const QString &s );
84 const QString &location() const; 94 const QString &location() const;
85 95
86 void setType( Type t ); 96 void setNotes( const QString &n );
87 Type type() const; 97 const QString &notes() const;
98
99 void setType( Type t ); // Don't use me.
100 Type type() const; // Don't use me.
101
102 void setAllDay(bool);
103 bool isAllDay() const;
104
88 void setStart( const QDateTime &d ); 105 void setStart( const QDateTime &d );
89 void setStart( time_t time ); 106 void setStart( time_t time ); // don't use me.
90 QDateTime start( bool actual = FALSE ) const; 107 QDateTime start( ) const;
91 time_t startTime() const { return startUTC; } 108 QDateTime start( bool actual ) const; // don't use me.
109 time_t startTime() const { return startUTC; } // don't use me.
92 void setEnd( const QDateTime &e ); 110 void setEnd( const QDateTime &e );
93 void setEnd( time_t time ); 111 void setEnd( time_t time ); // don't use me
94 QDateTime end( bool actual = FALSE ) const; 112 QDateTime end( ) const;
95 time_t endTime() const { return endUTC; } 113 QDateTime end( bool actual ) const; // don't use me.
114 time_t endTime() const { return endUTC; } // don't use me.
96 void setTimeZone( const QString & ); 115 void setTimeZone( const QString & );
97 const QString &timeZone() const; 116 const QString &timeZone() const;
98 void setAlarm( bool b, int minutes, SoundTypeChoice ); 117 void setAlarm( int minutes, SoundTypeChoice );
118 void clearAlarm();
119 void setAlarm( bool b, int minutes, SoundTypeChoice ); // Don't use me.
99 bool hasAlarm() const; 120 bool hasAlarm() const;
100 int alarmTime() const; 121 int alarmDelay() const;
122 int alarmTime() const; // Don't use me.
101 SoundTypeChoice alarmSound() const; 123 SoundTypeChoice alarmSound() const;
124
125 RepeatType repeatType() const;
126 int frequency() const;
127 int weekOffset() const;
128 QDate repeatTill() const;
129 bool repeatForever() const;
130 bool repeatOnWeekDay(int day) const;
131
132 void setRepeatType(RepeatType);
133 void setFrequency(int);
134 void setRepeatTill(const QDate &);
135 void setRepeatForever(bool);
136 void setRepeatOnWeekDay(int day, bool enable);
137
138 // Don't use any of these.
102 void setRepeat( bool b, const RepeatPattern &p ); 139 void setRepeat( bool b, const RepeatPattern &p );
103 void setRepeat( const RepeatPattern &p ); 140 void setRepeat( const RepeatPattern &p );
104 bool hasRepeat() const; 141 bool hasRepeat() const;
105 const RepeatPattern &repeatPattern() const; 142 const RepeatPattern &repeatPattern() const;
106 RepeatPattern &repeatPattern(); 143 RepeatPattern &repeatPattern();
107 void setNotes( const QString &n );
108 const QString &notes() const;
109 bool doRepeat() const { return pattern.type != NoRepeat; } 144 bool doRepeat() const { return pattern.type != NoRepeat; }
110 145
111 void save( QString& buf ); 146 void save( QString& buf );
112 //void load( Node *n ); 147 //void load( Node *n );
113 148
149 bool match( const QRegExp &r ) const;
150
151 // Don't use these either. Functionality will be moved elsewhere.
152
114 // helper function to calculate the week of the given date 153 // helper function to calculate the week of the given date
115 static int week( const QDate& date ); 154 static int week( const QDate& date );
116 // calculates the number of occurrences of the week day of 155 // calculates the number of occurrences of the week day of
117 // the given date from the start of the month 156 // the given date from the start of the month
118 static int occurrence( const QDate& date ); 157 static int occurrence( const QDate& date );
119 // returns a proper days-char for a given dayOfWeek() 158 // returns a proper days-char for a given dayOfWeek()
120 static char day( int dayOfWeek ) { return 1 << ( dayOfWeek - 1 ); } 159 static char day( int dayOfWeek ) { return 1 << ( dayOfWeek - 1 ); }
121 // returns the dayOfWeek for the *first* day it finds (ignores 160 // returns the dayOfWeek for the *first* day it finds (ignores
122 // any further days!). Returns 1 (Monday) if there isn't any day found 161 // any further days!). Returns 1 (Monday) if there isn't any day found
123 static int dayOfWeek( char day ); 162 static int dayOfWeek( char day );
124 // returns the difference of months from first to second. 163 // returns the difference of months from first to second.
125 static int monthDiff( const QDate& first, const QDate& second ); 164 static int monthDiff( const QDate& first, const QDate& second );
126 bool match( const QRegExp &r ) const;
127 165
128private: 166private:
129 Qtopia::UidGen &uidGen() { return sUidGen; } 167 Qtopia::UidGen &uidGen() { return sUidGen; }
130 static Qtopia::UidGen sUidGen; 168 static Qtopia::UidGen sUidGen;
131 169
132 QString descript, locat, categ; 170 QString descript, locat, categ;
133 Type typ : 4; 171 Type typ : 4;
134 bool startTimeDirty : 1; 172 bool startTimeDirty : 1;
135 bool endTimeDirty : 1; 173 bool endTimeDirty : 1;
136 time_t startUTC, endUTC; 174 time_t startUTC, endUTC;
137 QString tz; 175 QString tz;
138 bool hAlarm, hRepeat; 176 bool hAlarm, hRepeat;
139 int aMinutes; 177 int aMinutes;
140 SoundTypeChoice aSound; 178 SoundTypeChoice aSound;
141 RepeatPattern pattern; 179 RepeatPattern pattern;
142 QString note; 180 QString note;
143 // ADDITION 181 // ADDITION
144 int mRid;// Recode ID 182 int mRid;// Recode ID
145 int mRinfo;// Recode Info 183 int mRinfo;// Recode Info
146 // 184 //
147 EventPrivate *d; 185 EventPrivate *d;
148 186
149}; 187};
150 188
151// Since an event spans multiple day, it is better to have this 189// Since an event spans multiple day, it is better to have this
152// class to represent a day instead of creating many 190// class to represent a day instead of creating many
153// dummy events... 191// dummy events...
154 192
155class EffectiveEventPrivate; 193class EffectiveEventPrivate;
156class QPC_EXPORT EffectiveEvent 194class QPC_EXPORT EffectiveEvent
157{ 195{
158public: 196public:
159 // If we calculate the effective event of a multi-day event 197 // If we calculate the effective event of a multi-day event
160 // we have to figure out whether we are at the first day, 198 // we have to figure out whether we are at the first day,
161 // at the end, or anywhere else ("middle"). This is important 199 // at the end, or anywhere else ("middle"). This is important
162 // for the start/end times (00:00/23:59) 200 // for the start/end times (00:00/23:59)
163 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- 201 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
164 // day event 202 // day event
165 // Start: start time -> 23:59 203 // Start: start time -> 23:59
166 // End: 00:00 -> end time 204 // End: 00:00 -> end time
167 // Start | End == StartEnd: for single-day events (default) 205 // Start | End == StartEnd: for single-day events (default)
168 // here we draw start time -> end time 206 // here we draw start time -> end time
169 enum Position { MidWay = 0, Start = 1, End = 2, StartEnd = 3 }; 207 enum Position { MidWay = 0, Start = 1, End = 2, StartEnd = 3 };
170 208
171 EffectiveEvent(); 209 EffectiveEvent();
172 EffectiveEvent( const Event &event, const QDate &startDate, Position pos = StartEnd ); 210 EffectiveEvent( const Event &event, const QDate &startDate, Position pos = StartEnd );
173 EffectiveEvent( const EffectiveEvent & ); 211 EffectiveEvent( const EffectiveEvent & );
174 EffectiveEvent& operator=( const EffectiveEvent & ); 212 EffectiveEvent& operator=( const EffectiveEvent & );
175 ~EffectiveEvent(); 213 ~EffectiveEvent();
176 214
177 215
178 bool operator<( const EffectiveEvent &e ) const; 216 bool operator<( const EffectiveEvent &e ) const;
179 bool operator<=( const EffectiveEvent &e ) const; 217 bool operator<=( const EffectiveEvent &e ) const;
180 bool operator==( const EffectiveEvent &e ) const; 218 bool operator==( const EffectiveEvent &e ) const;
181 bool operator!=( const EffectiveEvent &e ) const; 219 bool operator!=( const EffectiveEvent &e ) const;
182 bool operator>( const EffectiveEvent &e ) const; 220 bool operator>( const EffectiveEvent &e ) const;
183 bool operator>= ( const EffectiveEvent &e ) const; 221 bool operator>= ( const EffectiveEvent &e ) const;
184 222
185 void setStart( const QTime &start ); 223 void setStart( const QTime &start );
186 void setEnd( const QTime &end ); 224 void setEnd( const QTime &end );
187 void setEvent( Event e ); 225 void setEvent( Event e );
188 void setDate( const QDate &date ); 226 void setDate( const QDate &date );
189 void setEffectiveDates( const QDate &from, const QDate &to ); 227 void setEffectiveDates( const QDate &from, const QDate &to );
190 228
191 // QString category() const; 229 // QString category() const;
192 const QString &description() const; 230 const QString &description() const;
193 const QString &location() const; 231 const QString &location() const;
194 const QString &notes() const; 232 const QString &notes() const;
195 const Event &event() const; 233 const Event &event() const;
196 const QTime &start() const; 234 const QTime &start() const;
197 const QTime &end() const; 235 const QTime &end() const;
198 const QDate &date() const; 236 const QDate &date() const;
199 int length() const; 237 int length() const;
200 int size() const; 238 int size() const;
201 239
202 QDate startDate() const; 240 QDate startDate() const;
203 QDate endDate() const; 241 QDate endDate() const;
204 242
205private: 243private:
206 class EffectiveEventPrivate *d; 244 class EffectiveEventPrivate *d;
207 Event mEvent; 245 Event mEvent;
208 QDate mDate; 246 QDate mDate;
209 QTime mStart, 247 QTime mStart,
210 mEnd; 248 mEnd;
211 249
212}; 250};
213 251
252inline void Event::setAlarm( int minutes, SoundTypeChoice s )
253{
254 setAlarm(TRUE, minutes, s);
255}
256
257inline void Event::clearAlarm()
258{
259 setAlarm(FALSE, 0, Silent);
260}
261
262inline int Event::alarmDelay() const
263{
264 return alarmTime();
265}
266
267inline void Event::setAllDay(bool enable)
268{
269 if (enable)
270 setType(AllDay);
271 else
272 setType(Normal);
273};
274
275inline bool Event::isAllDay() const
276{
277 return type() == AllDay;
278}
279
280inline Event::RepeatType Event::repeatType() const
281{
282 return repeatPattern().type;
283}
284
285inline int Event::frequency() const
286{
287 return repeatPattern().frequency;
288}
289
290inline int Event::weekOffset() const
291{
292 if (start().date().day() == 1)
293 return 1;
294 return (start().date().day() - 1) / 7 + 1;
295}
296
297inline QDate Event::repeatTill() const
298{
299 return repeatPattern().endDate();
300}
301
302inline bool Event::repeatForever() const
303{
304 return !repeatPattern().hasEndDate;
305}
306
307inline void Event::setRepeatType(RepeatType t)
308{
309 pattern.type = t;
310}
311
312inline void Event::setFrequency(int f)
313{
314 pattern.frequency = f;
315}
316
317inline void Event::setRepeatTill(const QDate &d)
318{
319 pattern.setEndDate(d);
320 pattern.hasEndDate = TRUE;
321}
322
323inline void Event::setRepeatForever(bool b)
324{
325 if (!b == pattern.hasEndDate)
326 return;
327 if (!b && !pattern.hasEndDate)
328 pattern.setEndDate(end().date());
329 pattern.hasEndDate = !b;
330}
331
332inline bool Event::repeatOnWeekDay(int day) const
333{
334 if (pattern.type != Weekly)
335 return FALSE;
336 return ( (1 << (day - 1)) & pattern.days ) != 0;
337}
338
339inline void Event::setRepeatOnWeekDay(int day, bool enable)
340{
341 if ( repeatOnWeekDay( day ) != enable )
342 pattern.days ^= 1 << (day - 1);
343}
344
345inline QDateTime Event::start( ) const
346{
347 return start(FALSE);
348}
349
350inline QDateTime Event::end( ) const
351{
352 return end(FALSE);
353}
354
214#ifdef PALMTOPCENTER 355#ifdef PALMTOPCENTER
215class QPC_EXPORT EffectiveEventSizeSorter : public QSorter<EffectiveEvent> 356class QPC_EXPORT EffectiveEventSizeSorter : public QSorter<EffectiveEvent>
216{ 357{
217public: 358public:
218 int compare( const EffectiveEvent& a, const EffectiveEvent& b ) const 359 int compare( const EffectiveEvent& a, const EffectiveEvent& b ) const
219 { 360 {
220 return a.size() - b.size(); 361 return a.size() - b.size();
221 } 362 }
222}; 363};
223 364
224class QPC_EXPORT EffectiveEventTimeSorter : public QSorter<EffectiveEvent> 365class QPC_EXPORT EffectiveEventTimeSorter : public QSorter<EffectiveEvent>
225{ 366{
226public: 367public:
227 int compare( const EffectiveEvent& a, const EffectiveEvent& b ) const 368 int compare( const EffectiveEvent& a, const EffectiveEvent& b ) const
228 { 369 {
229 return a.start().secsTo( b.start() ); 370 return a.start().secsTo( b.start() );
230 } 371 }
231}; 372};
232#endif 373#endif
233 374
234#endif 375#endif
diff --git a/library/backend/palmtoprecord.cpp b/library/backend/palmtoprecord.cpp
index 0d57699..3cfa874 100644
--- a/library/backend/palmtoprecord.cpp
+++ b/library/backend/palmtoprecord.cpp
@@ -1,127 +1,141 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free 7** GNU General Public License version 2 as published by the Free Software
8** Software Foundation and appearing in the file LICENSE.GPL included 8** Foundation and appearing in the file LICENSE.GPL included in the
9** in the packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** PARTICULAR PURPOSE.
14** 13**
15** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
16** 15**
17** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you. 17** not clear to you.
19** 18**
20**********************************************************************/ 19**********************************************************************/
21#include "palmtoprecord.h" 20#include <qtopia/private/palmtoprecord.h>
22#include "stringutil.h" 21#include <qtopia/stringutil.h>
23#include <qstringlist.h> 22#include <qstringlist.h>
24 23
24/*! \class Qtopia::PalmtopRecord palmtoprecord.h
25 \brief The Qtopia::PalmtopRecord class is the base class for all PIM records.
26
27 Provides unique id and category support for all PIM records.
28
29 \ingroup qtopiaemb
30 \ingroup qtopiadesktop
31*/
32
33
25namespace Qtopia { 34namespace Qtopia {
26 35
36
37
27Record &Record::operator=( const Record &c ) 38Record &Record::operator=( const Record &c )
28{ 39{
29 mUid = c.mUid; 40 mUid = c.mUid;
30 mCats = c.mCats; 41 mCats = c.mCats;
31 customMap = c.customMap; 42 customMap = c.customMap;
32 return *this; 43 return *this;
33} 44}
34 45
35void Record::setCategories( int single ) 46void Record::setCategories( int single )
36{ 47{
37 if ( single == 0 ) 48 if ( single == 0 )
38 return; 49 return;
39 mCats.resize(1); 50 mCats.resize(1);
40 mCats[0] = single; 51 mCats[0] = single;
41} 52}
42 53
43// convenience methods provided for loading and saving to xml 54// convenience methods provided for loading and saving to xml
44QString Record::idsToString( const QArray<int> &cats ) 55QString Record::idsToString( const QArray<int> &catsUnsorted )
45{ 56{
57 QArray<int> cats = catsUnsorted;
58 cats.sort();
59
46 QString str; 60 QString str;
47 for ( uint i = 0; i < cats.size(); i++ ) 61 for ( uint i = 0; i < cats.size(); i++ )
48 if ( i == 0 ) 62 if ( i == 0 )
49 str = QString::number( cats[int(i)] ); 63 str = QString::number( cats[int(i)] );
50 else 64 else
51 str += ";" + QString::number( cats[int(i)] ); 65 str += ";" + QString::number( cats[int(i)] );
52 66
53 return str; 67 return str;
54} 68}
55 69
56// convenience methods provided for loading and saving to xml 70// convenience methods provided for loading and saving to xml
57QArray<int> Record::idsFromString( const QString &str ) 71QArray<int> Record::idsFromString( const QString &str )
58{ 72{
59 QStringList catStrs = QStringList::split( ";", str ); 73 QStringList catStrs = QStringList::split( ";", str );
60 QArray<int> cats( catStrs.count() ); 74 QArray<int> cats( catStrs.count() );
61 uint i = 0; 75 uint i = 0;
62 for ( QStringList::ConstIterator it = catStrs.begin(); 76 for ( QStringList::ConstIterator it = catStrs.begin();
63 it != catStrs.end(); ++it ) { 77 it != catStrs.end(); ++it ) {
64 cats[int(i)] = (*it).toInt(); 78 cats[int(i)] = (*it).toInt();
65 i++; 79 i++;
66 } 80 }
67 return cats; 81 return cats;
68} 82}
69 83
70/*! 84/*!
71 Returns the string stored for the custom field \a key. 85 Returns the string stored for the custom field \a key.
72 Returns a null string if the field does not exist. 86 Returns a null string if the field does not exist.
73 */ 87 */
74QString Record::customField( const QString &key) const 88QString Record::customField( const QString &key) const
75{ 89{
76 if (customMap.contains(key)) 90 if (customMap.contains(key))
77 return customMap[key]; 91 return customMap[key];
78 92
79 return QString::null; 93 return QString::null;
80} 94}
81 95
82/*! 96/*!
83 Sets the string stored for the custom field \a key to \a value. 97 Sets the string stored for the custom field \a key to \a value.
84 */ 98 */
85void Record::setCustomField( const QString &key, const QString &value) 99void Record::setCustomField( const QString &key, const QString &value)
86{ 100{
87 qWarning("setting custom " + key + " to " + value); 101// qWarning("setting custom " + key + " to " + value);
88 if (customMap.contains(key)) 102 if (customMap.contains(key))
89 customMap.replace(key, value); 103 customMap.replace(key, value);
90 else 104 else
91 customMap.insert(key, value); 105 customMap.insert(key, value);
92 106
93 qWarning(QString("custom size %1").arg(customMap.count())); 107// qWarning(QString("custom size %1").arg(customMap.count()));
94} 108}
95 109
96/*! 110/*!
97 Removes the custom field \a key. 111 Removes the custom field \a key.
98 */ 112 */
99void Record::removeCustomField(const QString &key) 113void Record::removeCustomField(const QString &key)
100{ 114{
101 customMap.remove(key); 115 customMap.remove(key);
102} 116}
103 117
104QString Record::customToXml() const 118QString Record::customToXml() const
105{ 119{
106 //qWarning(QString("writing custom %1").arg(customMap.count())); 120 //qWarning(QString("writing custom %1").arg(customMap.count()));
107 QString buf(" "); 121 QString buf(" ");
108 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin(); 122 for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
109 cit != customMap.end(); ++cit) { 123 cit != customMap.end(); ++cit) {
110 qWarning(".ITEM."); 124 // qWarning(".ITEM.");
111 buf += cit.key(); 125 buf += cit.key();
112 buf += "=\""; 126 buf += "=\"";
113 buf += escapeString(cit.data()); 127 buf += escapeString(cit.data());
114 buf += "\" "; 128 buf += "\" ";
115 } 129 }
116 return buf; 130 return buf;
117} 131}
118 132
119void Record::dump( const QMap<int, QString> &map ) 133void Record::dump( const QMap<int, QString> &map )
120{ 134{
121 QMap<int, QString>::ConstIterator it; 135 QMap<int, QString>::ConstIterator it;
122 for( it = map.begin(); it != map.end(); ++it ) 136 for( it = map.begin(); it != map.end(); ++it )
123 qDebug("%d : %s", it.key(), it.data().local8Bit().data() ); 137 qDebug("%d : %s", it.key(), it.data().local8Bit().data() );
124} 138}
125 139
126} 140}
127 141
diff --git a/library/backend/palmtoprecord.h b/library/backend/palmtoprecord.h
index 0372011..72f7d1c 100644
--- a/library/backend/palmtoprecord.h
+++ b/library/backend/palmtoprecord.h
@@ -1,94 +1,95 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free 7** GNU General Public License version 2 as published by the Free Software
8** Software Foundation and appearing in the file LICENSE.GPL included 8** Foundation and appearing in the file LICENSE.GPL included in the
9** in the packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** PARTICULAR PURPOSE.
14** 13**
15** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
16** 15**
17** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you. 17** not clear to you.
19** 18**
20**********************************************************************/ 19**********************************************************************/
21
22#ifndef QTPALMTOP_RECORD_H 20#ifndef QTPALMTOP_RECORD_H
23#define QTPALMTOP_RECORD_H 21#define QTPALMTOP_RECORD_H
24
25#include <qglobal.h> 22#include <qglobal.h>
26#include "qpcglobal.h" 23#include "qpcglobal.h"
27#include "palmtopuidgen.h" 24#include "palmtopuidgen.h"
28#include <qarray.h> 25#include <qarray.h>
29#include <qmap.h> 26#include <qmap.h>
30 27
31#if defined(QPC_TEMPLATEDLL) 28#if defined(QPC_TEMPLATEDLL)
32// MOC_SKIP_BEGIN 29// MOC_SKIP_BEGIN
33template class QPC_EXPORT QMap<QString, QString>; 30QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<QString, QString>;
34// MOC_SKIP_END 31// MOC_SKIP_END
35#endif 32#endif
36 33
37class QRegExp; 34class QRegExp;
38namespace Qtopia { 35namespace Qtopia {
39 36
40class RecordPrivate; 37class RecordPrivate;
41class QPC_EXPORT Record 38class QPC_EXPORT Record
42{ 39{
43public: 40public:
44 Record() : mUid(0), mCats() { } 41 Record() : mUid(0), mCats() { }
45 Record( const Record &c ) :mUid( c.mUid ), mCats ( c.mCats ), customMap(c.customMap) { } 42 Record( const Record &c ) :mUid( c.mUid ), mCats ( c.mCats ), customMap(c.customMap) { }
46 virtual ~Record() { } 43 virtual ~Record() { }
47 44
48 Record &operator=( const Record &c ); 45 Record &operator=( const Record &c );
49 46
50 virtual bool match( const QRegExp & ) const { return FALSE; } 47 virtual bool match( const QRegExp & ) const { return FALSE; }
51 48
52 void setCategories( const QArray<int> &v ) { mCats = v; } 49 void setCategories( const QArray<int> &v ) { mCats = v; mCats.sort(); }
53 void setCategories( int single ); 50 void setCategories( int single );
54 const QArray<int> &categories() const { return mCats; } 51 const QArray<int> &categories() const { return mCats; }
55 52
53 void reassignCategoryId( int oldId, int newId )
54 {
55 int index = mCats.find( oldId );
56 if ( index >= 0 )
57 mCats[index] = newId;
58 }
59
56 int uid() const { return mUid; }; 60 int uid() const { return mUid; };
57 virtual void setUid( int i ) { mUid = i; uidGen().store( mUid ); } 61 virtual void setUid( int i ) { mUid = i; uidGen().store( mUid ); }
58 bool isValidUid() const { return mUid != 0; } 62 bool isValidUid() const { return mUid != 0; }
59 void assignUid() { setUid( uidGen().generate() ); } 63 void assignUid() { setUid( uidGen().generate() ); }
60 64
61 virtual QString customField(const QString &) const; 65 virtual QString customField(const QString &) const;
62 virtual void setCustomField(const QString &, const QString &); 66 virtual void setCustomField(const QString &, const QString &);
63 virtual void removeCustomField(const QString &); 67 virtual void removeCustomField(const QString &);
64 68
65 virtual bool operator == ( const Record &r ) const 69 virtual bool operator == ( const Record &r ) const
66{ return mUid == r.mUid; } 70{ return mUid == r.mUid; }
67 virtual bool operator != ( const Record &r ) const 71 virtual bool operator != ( const Record &r ) const
68{ return mUid != r.mUid; } 72{ return mUid != r.mUid; }
69 73
70 // convenience methods provided for loading and saving to xml 74 // convenience methods provided for loading and saving to xml
71 static QString idsToString( const QArray<int> &ids ); 75 static QString idsToString( const QArray<int> &ids );
72 // convenience methods provided for loading and saving to xml 76 // convenience methods provided for loading and saving to xml
73 static QArray<int> idsFromString( const QString &str ); 77 static QArray<int> idsFromString( const QString &str );
74 78
75 // for debugging 79 // for debugging
76 static void dump( const QMap<int, QString> &map ); 80 static void dump( const QMap<int, QString> &map );
77 81
78protected: 82protected:
79 virtual UidGen &uidGen() = 0; 83 virtual UidGen &uidGen() = 0;
80
81 virtual QString customToXml() const; 84 virtual QString customToXml() const;
82
83private: 85private:
84 int mUid; 86 int mUid;
85 QArray<int> mCats; 87 QArray<int> mCats;
86
87 QMap<QString, QString> customMap; 88 QMap<QString, QString> customMap;
88
89 RecordPrivate *d; 89 RecordPrivate *d;
90}; 90};
91 91
92} 92}
93 93
94#endif 94#endif
95
diff --git a/library/backend/palmtopuidgen.h b/library/backend/palmtopuidgen.h
index 1a16681..c3fbcb9 100644
--- a/library/backend/palmtopuidgen.h
+++ b/library/backend/palmtopuidgen.h
@@ -1,83 +1,83 @@
1#ifndef QTPALMTOP_UIDGEN_H
2#define QTPALMTOP_UIDGEN_H
3/********************************************************************** 1/**********************************************************************
4** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
5** 3**
6** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
7** 5**
8** Licensees holding valid Qtopia Developer license may use this 6** This file may be distributed and/or modified under the terms of the
9** file in accordance with the Qtopia Developer License Agreement 7** GNU General Public License version 2 as published by the Free Software
10** provided with the Software. 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
11** 10**
12** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14** PURPOSE.
15** 13**
16** email sales@trolltech.com for information about Qtopia License 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
17** Agreements.
18** 15**
19** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
20** not clear to you. 17** not clear to you.
21** 18**
22**********************************************************************/ 19**********************************************************************/
23 20
21#ifndef QTPALMTOP_UIDGEN_H
22#define QTPALMTOP_UIDGEN_H
23
24#include <time.h> 24#include <time.h>
25#include <qmap.h> 25#include <qmap.h>
26#include "qpcglobal.h" 26#include "qpcglobal.h"
27 27
28#if defined(QPC_TEMPLATEDLL) 28#if defined(QPC_TEMPLATEDLL)
29// MOC_SKIP_BEGIN 29// MOC_SKIP_BEGIN
30template class QPC_EXPORT QMap< int, bool >; 30QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap< int, bool >;
31// MOC_SKIP_END 31// MOC_SKIP_END
32#endif 32#endif
33 33
34namespace Qtopia { 34namespace Qtopia {
35 35
36 36
37class QPC_EXPORT UidGen 37class QPC_EXPORT UidGen
38{ 38{
39public: 39public:
40 enum Type { Qtopia, PalmtopCenter }; 40 enum Type { Qtopia, PalmtopCenter };
41 41
42 UidGen() : type( Qtopia ), sign( -1 ), ids() 42 UidGen() : type( Qtopia ), sign( -1 ), ids()
43{ 43{
44#ifdef PALMTOPCENTER 44#ifdef PALMTOPCENTER
45 type = PalmtopCenter; 45 type = PalmtopCenter;
46 sign = 1; 46 sign = 1;
47#endif 47#endif
48} 48}
49 UidGen( Type t ) : type(t), sign(1), ids() 49 UidGen( Type t ) : type(t), sign(1), ids()
50{ 50{
51 if ( t == Qtopia ) 51 if ( t == Qtopia )
52 sign = -1; 52 sign = -1;
53} 53}
54 54
55 virtual ~UidGen() { } 55 virtual ~UidGen() { }
56 56
57 int generate() const 57 int generate() const
58{ 58{
59 int id = sign * (int) ::time(NULL); 59 int id = sign * (int) ::time(NULL);
60 while ( ids.contains( id ) ) { 60 while ( ids.contains( id ) ) {
61 id += sign; 61 id += sign;
62 62
63 // check for overflow cases; if so, wrap back to beginning of 63 // check for overflow cases; if so, wrap back to beginning of
64 // set ( -1 or 1 ) 64 // set ( -1 or 1 )
65 if ( sign == -1 && id > 0 || sign == 1 && id < 0 ) 65 if ( sign == -1 && id > 0 || sign == 1 && id < 0 )
66 id = sign; 66 id = sign;
67 } 67 }
68 return id; 68 return id;
69} 69}
70 70
71 void store(int id) { ids.insert(id, TRUE); } 71 void store(int id) { ids.insert(id, TRUE); }
72 bool isUnique(int id) const { return (!ids.contains(id)); } 72 bool isUnique(int id) const { return (!ids.contains(id)); }
73 73
74private: 74private:
75 Type type; 75 Type type;
76 int sign; 76 int sign;
77 QMap<int, bool> ids; 77 QMap<int, bool> ids;
78 78
79}; 79};
80 80
81} 81}
82 82
83#endif 83#endif
diff --git a/library/backend/qfiledirect_p.h b/library/backend/qfiledirect_p.h
index 3ade622..976c69f 100644
--- a/library/backend/qfiledirect_p.h
+++ b/library/backend/qfiledirect_p.h
@@ -1,37 +1,35 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** Licensees holding valid Qtopia Developer license may use this 6** This file may be distributed and/or modified under the terms of the
7** file in accordance with the Qtopia Developer License Agreement 7** GNU General Public License version 2 as published by the Free Software
8** provided with the Software. 8** Foundation and appearing in the file LICENSE.GPL included in the
9** 9** packaging of this file.
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 10**
11** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** email sales@trolltech.com for information about Qtopia License 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** Agreements. 15**
16** 16** Contact info@trolltech.com if any conditions of this licensing are
17** Contact info@trolltech.com if any conditions of this licensing are 17** not clear to you.
18** not clear to you. 18**
19** 19**********************************************************************/
20**********************************************************************/ 20
21 21#ifndef QFILE_DIRECT_H
22#ifndef QFILE_DIRECT_H 22#define QFILE_DIRECT_H
23#define QFILE_DIRECT_H 23#include <qfile.h>
24#include <qfile.h> 24#include <qtopia/private/qpcglobal.h>
25#include <qpe/qpcglobal.h> 25
26 26class QPC_EXPORT QFileDirect : public QFile
27class QPC_EXPORT QFileDirect : public QFile 27{
28{ 28public:
29public: 29 QFileDirect() : QFile() { }
30 QFileDirect() : QFile() { } 30 QFileDirect( const QString &name ) : QFile(name) { }
31 QFileDirect( const QString &name ) : QFile(name) { } 31
32 32 FILE *directHandle() { return fh; }
33 FILE *directHandle() { return fh; } 33};
34}; 34
35 35#endif
36#endif
37
diff --git a/library/backend/qpcglobal.h b/library/backend/qpcglobal.h
index 0d60272..7b71f06 100644
--- a/library/backend/qpcglobal.h
+++ b/library/backend/qpcglobal.h
@@ -1,50 +1,53 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** Licensees holding valid Qtopia Developer license may use this 6** Licensees holding valid Qtopia Developer license may use this
7** file in accordance with the Qtopia Developer License Agreement 7** file in accordance with the Qtopia Developer License Agreement
8** provided with the Software. 8** provided with the Software.
9** 9**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
11** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 11** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12** PURPOSE. 12** PURPOSE.
13** 13**
14** email sales@trolltech.com for information about Qtopia License 14** email sales@trolltech.com for information about Qtopia License
15** Agreements. 15** Agreements.
16** 16**
17** Contact info@trolltech.com if any conditions of this licensing are 17** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you. 18** not clear to you.
19** 19**
20**********************************************************************/ 20**********************************************************************/
21 21
22#ifndef QPC_GLOBAL_H 22#ifndef QPC_GLOBAL_H
23#define QPC_GLOBAL_H 23#define QPC_GLOBAL_H
24 24
25#if ( defined(Q_OS_WIN32) || defined(Q_OS_WIN64) ) && defined(PALMTOPCENTER)
26#include <qglobal.h> 25#include <qglobal.h>
26
27#if ( defined(Q_OS_WIN32) || defined(Q_OS_WIN64) ) && defined(PALMTOPCENTER)
27// # if defined(QT_NODLL) 28// # if defined(QT_NODLL)
28//# undef QPC_MAKEDLL 29//# undef QPC_MAKEDLL
29//# undef QPC_DLL 30//# undef QPC_DLL
30 # if defined(QPC_MAKEDLL)/* create a Qt DLL library */ 31 # if defined(QPC_MAKEDLL)/* create a Qt DLL library */
31# if defined(QPC_DLL) 32# if defined(QPC_DLL)
32# undef QPC_DLL 33# undef QPC_DLL
33# endif 34# endif
34# define QPC_EXPORT __declspec(dllexport) 35# define QPC_EXPORT __declspec(dllexport)
36# define QPC_TEMPLATEEXTERN
35# define QPC_TEMPLATEDLL 37# define QPC_TEMPLATEDLL
36 # undef QPC_DISABLE_COPY/* avoid unresolved externals */ 38 # undef QPC_DISABLE_COPY/* avoid unresolved externals */
37 # elif defined(QPC_DLL) /* use a Qt DLL library */ 39 # elif defined(QPC_DLL) /* use a Qt DLL library */
38# define QPC_EXPORT __declspec(dllimport) 40# define QPC_EXPORT __declspec(dllimport)
41# define QPC_TEMPLATEEXTERN extern
39# define QPC_TEMPLATEDLL 42# define QPC_TEMPLATEDLL
40 # undef QPC_DISABLE_COPY/* avoid unresolved externals */ 43 # undef QPC_DISABLE_COPY/* avoid unresolved externals */
41# endif 44# endif
42#else 45#else
43 # undef QPC_MAKEDLL /* ignore these for other platforms */ 46 # undef QPC_MAKEDLL /* ignore these for other platforms */
44# undef QPC_DLL 47# undef QPC_DLL
45#endif 48#endif
46#endif 49#endif
47 50
48#ifndef QPC_EXPORT 51#ifndef QPC_EXPORT
49# define QPC_EXPORT 52# define QPC_EXPORT
50#endif 53#endif
diff --git a/library/backend/recordfields.h b/library/backend/recordfields.h
index 4196c8b..1167ed3 100644
--- a/library/backend/recordfields.h
+++ b/library/backend/recordfields.h
@@ -1,149 +1,149 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** Licensees holding valid Qtopia Developer license may use this 6** This file may be distributed and/or modified under the terms of the
7** file in accordance with the Qtopia Developer License Agreement 7** GNU General Public License version 2 as published by the Free Software
8** provided with the Software. 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
9** 10**
10** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12** PURPOSE.
13** 13**
14** email sales@trolltech.com for information about Qtopia License 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** Agreements.
16** 15**
17** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you. 17** not clear to you.
19** 18**
20**********************************************************************/ 19**********************************************************************/
21#ifndef QPC_RECORD_FIELDS_H 20#ifndef QPC_RECORD_FIELDS_H
22#define QPC_RECORD_FIELDS_H 21#define QPC_RECORD_FIELDS_H
23#include "qpcglobal.h" 22#include "qpcglobal.h"
24 23
25// dataset = "addressbook" 24// dataset = "addressbook"
26namespace Qtopia 25namespace Qtopia
27{ 26{
28 static const int UID_ID = 0; 27 static const int UID_ID = 0;
29 static const int CATEGORY_ID = 1; 28 static const int CATEGORY_ID = 1;
30 29
31 enum AddressBookFields { 30 enum AddressBookFields {
32 AddressUid = UID_ID, 31 AddressUid = UID_ID,
33 AddressCategory = CATEGORY_ID, 32 AddressCategory = CATEGORY_ID,
34 33
35 // NOTE: Order of fields dependency in backend/contact.cpp 34 // NOTE: Order of fields dependency in backend/contact.cpp
36 35
37 Title, 36 Title,
38 FirstName, 37 FirstName,
39 MiddleName, 38 MiddleName,
40 LastName, 39 LastName,
41 Suffix, 40 Suffix,
42 FileAs, 41 FileAs,
43 42
44 JobTitle, 43 JobTitle,
45 Department, 44 Department,
46 Company, 45 Company,
47 BusinessPhone, 46 BusinessPhone,
48 BusinessFax, 47 BusinessFax,
49 BusinessMobile, 48 BusinessMobile,
50 49
51 // email 50 // email
52 DefaultEmail, 51 DefaultEmail,
53 Emails, 52 Emails,
54 53
55 HomePhone, 54 HomePhone,
56 HomeFax, 55 HomeFax,
57 HomeMobile, 56 HomeMobile,
58 57
59 // business 58 // business
60 BusinessStreet, 59 BusinessStreet,
61 BusinessCity, 60 BusinessCity,
62 BusinessState, 61 BusinessState,
63 BusinessZip, 62 BusinessZip,
64 BusinessCountry, 63 BusinessCountry,
65 BusinessPager, 64 BusinessPager,
66 BusinessWebPage, 65 BusinessWebPage,
67 66
68 Office, 67 Office,
69 Profession, 68 Profession,
70 Assistant, 69 Assistant,
71 Manager, 70 Manager,
72 71
73 // home 72 // home
74 HomeStreet, 73 HomeStreet,
75 HomeCity, 74 HomeCity,
76 HomeState, 75 HomeState,
77 HomeZip, 76 HomeZip,
78 HomeCountry, 77 HomeCountry,
79 HomeWebPage, 78 HomeWebPage,
80 79
81 //personal 80 //personal
82 Spouse, 81 Spouse,
83 Gender, 82 Gender,
84 Birthday, 83 Birthday,
85 Anniversary, 84 Anniversary,
86 Nickname, 85 Nickname,
87 Children, 86 Children,
88 87
89 // other 88 // other
90 Notes, 89 Notes,
91 Groups
92 90
93 ,rid, 91 // used for internal record keeping, not for end user.
92 Groups,
93 rid,
94 rinfo 94 rinfo
95 }; 95 };
96 96
97 // dataset = "todolist" 97 // dataset = "todolist"
98 enum TaskFields { 98 enum TaskFields {
99 TaskUid = UID_ID, 99 TaskUid = UID_ID,
100 TaskCategory = CATEGORY_ID, 100 TaskCategory = CATEGORY_ID,
101 101
102 HasDate, 102 HasDate,
103 Completed, 103 Completed,
104 TaskDescription, 104 TaskDescription,
105 Priority, 105 Priority,
106 Date, 106 Date,
107 107
108 TaskRid, 108 TaskRid,
109 TaskRinfo 109 TaskRinfo
110 }; 110 };
111 111
112 // dataset = "categories" for todos 112 // dataset = "categories" for todos
113 enum CategoryFields { 113 enum CategoryFields {
114 CatUid = UID_ID, 114 CatUid = UID_ID,
115 CatName, 115 CatName,
116 CatAppGroup 116 CatAppGroup
117 }; 117 };
118 118
119 119
120// dataset = "datebook" 120// dataset = "datebook"
121 enum DatebookFields { 121 enum DatebookFields {
122 DatebookUid = UID_ID, 122 DatebookUid = UID_ID,
123 DatebookCategory = CATEGORY_ID, 123 DatebookCategory = CATEGORY_ID,
124 124
125 DatebookDescription, 125 DatebookDescription,
126 Location, 126 Location,
127 TimeZone, 127 TimeZone,
128 Note, 128 Note,
129 StartDateTime, 129 StartDateTime,
130 EndDateTime, 130 EndDateTime,
131 DatebookType, 131 DatebookType,
132 HasAlarm, 132 HasAlarm,
133 SoundType, 133 SoundType,
134 AlarmTime, 134 AlarmTime,
135 135
136 RepeatPatternType, 136 RepeatPatternType,
137 RepeatPatternFrequency, 137 RepeatPatternFrequency,
138 RepeatPatternPosition, 138 RepeatPatternPosition,
139 RepeatPatternDays, 139 RepeatPatternDays,
140 RepeatPatternHasEndDate, 140 RepeatPatternHasEndDate,
141 RepeatPatternEndDate, 141 RepeatPatternEndDate,
142 142
143 DateBookRid, 143 DateBookRid,
144 DateBookRinfo 144 DateBookRinfo
145 }; 145 };
146}; 146};
147 147
148 148
149#endif 149#endif
diff --git a/library/backend/stringutil.cpp b/library/backend/stringutil.cpp
deleted file mode 100644
index df58f54..0000000
--- a/library/backend/stringutil.cpp
+++ b/dev/null
@@ -1,415 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free
8** Software Foundation and appearing in the file LICENSE.GPL included
9** in the packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
12** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
13** PARTICULAR PURPOSE.
14**
15** See http://www.trolltech.com/gpl/ for GPL licensing information.
16**
17** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you.
19**
20**********************************************************************/
21
22#include "stringutil.h"
23#include <qregexp.h>
24#include <qstringlist.h>
25
26namespace Qtopia
27{
28
29
30
31/*
32 Very, very simple Latin-1 only collation guaranteed to displease anyone
33 who actually uses the non-ASCII characters.
34 */
35
36static const char collationHack[] = {
370x00, //C-@
380x01, //C-A
390x02, //C-B
400x03, //C-C
410x04, //C-D
420x05, //C-E
430x06, //C-F
440x07, //C-G
450x08, //C-H
460x09, //C-I
470x0a, //C-J
480x0b, //C-K
490x0c, //C-L
500x0d, //C-M
510x0e, //C-N
520x0f, //C-O
530x10, //C-P
540x11, //C-Q
550x12, //C-R
560x13, //C-S
570x14, //C-T
580x15, //C-U
590x16, //C-V
600x17, //C-W
610x18, //C-X
620x19, //C-Y
630x1a, //C-Z
640x1b, //C-[
650x1c, //C-\
660x1d, //C-]
670x1e, //C-^
680x1f, //C-_
69' ', //
70'!', //!
71'"', //"
72'#', //#
73'$', //$
74'%', //%
75'&', //&
76'\'', //'
77'(', //(
78')', //)
79'*', //*
80'+', //+
81',', //,
82'-', //-
83'.', //.
84'/', ///
850x80, //0
860x81, //1
870x82, //2
880x83, //3
890x84, //4
900x85, //5
910x86, //6
920x87, //7
930x88, //8
940x89, //9
95':', //:
96';', //;
97'<', //<
98'=', //=
99'>', //>
100'?', //?
101'@', //@
102'A', //A
103'B', //B
104'C', //C
105'D', //D
106'E', //E
107'F', //F
108'G', //G
109'H', //H
110'I', //I
111'J', //J
112'K', //K
113'L', //L
114'M', //M
115'N', //N
116'O', //O
117'P', //P
118'Q', //Q
119'R', //R
120'S', //S
121'T', //T
122'U', //U
123'V', //V
124'W', //W
125'X', //X
126'Y', //Y
127'Z', //Z
128'[', //[
129'\\', //\
130']', //]
131'^', //^
132'_', //_
133'`', //`
134'A', //a
135'B', //b
136'C', //c
137'D', //d
138'E', //e
139'F', //f
140'G', //g
141'H', //h
142'I', //i
143'J', //j
144'K', //k
145'L', //l
146'M', //m
147'N', //n
148'O', //o
149'P', //p
150'Q', //q
151'R', //r
152'S', //s
153'T', //t
154'U', //u
155'V', //v
156'W', //w
157'X', //x
158'Y', //y
159'Z', //z
160'{', //{
161'|', //|
162'}', //}
163'~', //~
164'', //
1650x80, //C-M-@
1660x81, //C-M-A
1670x82, //C-M-B
1680x83, //C-M-C
1690x84, //C-M-D
1700x85, //C-M-E
1710x86, //C-M-F
1720x87, //C-M-G
1730x88, //C-M-H
1740x89, //C-M-I
1750x8a, //C-M-J
1760x8b, //C-M-K
1770x8c, //C-M-L
1780x8d, //C-M-M
1790x8e, //C-M-N
1800x8f, //C-M-O
1810x90, //C-M-P
1820x91, //C-M-Q
1830x92, //C-M-R
1840x93, //C-M-S
1850x94, //C-M-T
1860x95, //C-M-U
1870x96, //C-M-V
1880x97, //C-M-W
1890x98, //C-M-X
1900x99, //C-M-Y
1910x9a, //C-M-Z
1920x9b, //C-M-[
1930x9c, //C-M-\
1940x9d, //C-M-]
1950x9e, //C-M-^
1960x9f, //C-M-_
197' ', // 
198'¡', //¡
199'¢', //¢
200'£', //£
201'¤', //¤
202'¥', //¥
203'¦', //¦
204'§', //§
205'¨', //¨
206'©', //©
207'A', //ª
208'«', //«
209'¬', //¬
210'­', //­
211'®', //®
212'¯', //¯
213'O', //°
214'±', //±
215'²', //²
216'³', //³
217'´', //´
218'µ', //µ
219'P', //¶
220'·', //·
221'¸', //¸
222'¹', //¹
223'O', //º
224'»', //»
225'¼', //¼
226'½', //½
227'¾', //¾
228'¿', //¿
229'A', //À
230'A', //Á
231'A', //Â
232'A', //Ã
233'A', //Ä
234'A', //Å
235'A', //Æ
236'C', //Ç
237'E', //È
238'E', //É
239'E', //Ê
240'E', //Ë
241'I', //Ì
242'I', //Í
243'I', //Î
244'I', //Ï
245'D', //Ð
246'N', //Ñ
247'O', //Ò
248'O', //Ó
249'O', //Ô
250'O', //Õ
251'O', //Ö
252'×', //×
253'O', //Ø
254'U', //Ù
255'U', //Ú
256'U', //Û
257'U', //Ü
258'Y', //Ý
259'T', //Þ
260'S', //ß
261'A', //à
262'A', //á
263'A', //â
264'A', //ã
265'A', //ä
266'A', //å
267'A', //æ
268'C', //ç
269'E', //è
270'E', //é
271'E', //ê
272'E', //ë
273'I', //ì
274'I', //í
275'I', //î
276'I', //ï
277'D', //ð
278'N', //ñ
279'O', //ò
280'O', //ó
281'O', //ô
282'O', //õ
283'O', //ö
284'÷', //÷
285'O', //ø
286'U', //ù
287'U', //ú
288'U', //û
289'U', //ü
290'Y', //ý
291'T', //þ
292'Y', //ÿ
293};
294
295
296
297
298
299static void hackString ( QString &s )
300{
301 int len = s.length();
302 const QChar* uc = s.unicode();
303 for ( int i = 0; i < len; i++ ) {
304 if ( !uc++->row() )
305 s[i] = collationHack[s[i].cell()];
306 }
307}
308
309QString buildSortKey( const QString & s )
310{
311 QString res = s;
312 hackString( res );
313 return res;
314}
315
316QString buildSortKey( const QString & s1, const QString & s2 )
317{
318 QString res = s1 + QChar( '\0' ) + s2;
319 hackString( res );
320 return res;
321}
322
323QString buildSortKey( const QString & s1, const QString & s2,
324 const QString & s3 )
325{
326 QString res = s1 + QChar( '\0' ) + s2 + QChar( '\0' ) + s3;
327 hackString( res );
328 return res;
329}
330
331static inline QChar coll( QChar u )
332{
333 return u.row() ? u : QChar(collationHack[ u.cell() ]);
334}
335
336
337int compare( const QString & s1, const QString & s2 )
338{
339 const QChar* u1 = s1.unicode();
340 const QChar* u2 = s2.unicode();
341
342 if ( u1 == u2 )
343 return 0;
344 if ( u1 == 0 )
345 return 1;
346 if ( u2 == 0 )
347 return -1;
348 int l=QMIN(s1.length(),s2.length());
349 while ( l-- && coll(*u1) == coll(*u2) )
350 u1++,u2++;
351 if ( l==-1 )
352 return ( s1.length()-s2.length() );
353 return u1->unicode() - u2->unicode();
354}
355
356QString simplifyMultiLineSpace( const QString &multiLine )
357{
358 QString result;
359 QStringList lines = QStringList::split("\n", multiLine);
360 for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
361 if ( it != lines.begin() )
362 result += "\n";
363 result += (*it).simplifyWhiteSpace();
364 }
365 return result;
366}
367
368QString escapeString( const QString& plain )
369{
370 QString tmp(plain);
371 int pos = tmp.length();
372 const QChar *uc = plain.unicode();
373 while ( pos-- ) {
374 unsigned char ch = uc[pos].latin1();
375 if ( ch == '&' )
376 tmp.replace( pos, 1, "&amp;" );
377 else if ( ch == '<' )
378 tmp.replace( pos, 1, "&lt;" );
379 else if ( ch == '>' )
380 tmp.replace( pos, 1, "&gt;" );
381 else if ( ch == '\"' )
382 tmp.replace( pos, 1, "&quot;" );
383 }
384 return tmp;
385}
386
387QString plainString( const char* escaped, unsigned int length )
388{
389 return plainString( QString::fromUtf8( escaped, length ) );
390}
391
392QString plainString( const QCString& string )
393{
394 // We first have to pass it through a ::fromUtf8()
395 return plainString( string.data(), string.length() );
396}
397
398QString plainString( const QString& string )
399{
400 QString tmp( string );
401 int pos = -1;
402 while ( (pos = tmp.find( "&", pos +1 ) ) != -1 ) {
403 if ( tmp.find( "&amp;", pos ) == pos )
404 tmp.replace( pos, 5, "&" );
405 else if ( tmp.find( "&lt;", pos ) == pos )
406 tmp.replace( pos, 4, "<" );
407 else if( tmp.find( "&gt;", pos ) == pos )
408 tmp.replace( pos, 4, ">" );
409 else if ( tmp.find( "&quot;", pos ) == pos )
410 tmp.replace( pos, 6, "\"" );
411 }
412 return tmp;
413}
414
415} // namespace QPC
diff --git a/library/backend/stringutil.h b/library/backend/stringutil.h
deleted file mode 100644
index e9daf70..0000000
--- a/library/backend/stringutil.h
+++ b/dev/null
@@ -1,57 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free
8** Software Foundation and appearing in the file LICENSE.GPL included
9** in the packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
12** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
13** PARTICULAR PURPOSE.
14**
15** See http://www.trolltech.com/gpl/ for GPL licensing information.
16**
17** Contact info@trolltech.com if any conditions of this licensing are
18** not clear to you.
19**
20**********************************************************************/
21
22
23#ifndef QTPALMTOP_stringutil_h__
24#define QTPALMTOP_stringutil_h__
25
26#include <qstring.h>
27#include "qpcglobal.h"
28
29namespace Qtopia
30{
31
32// Simplifies white space within each line but keeps the new line characters
33QString QPC_EXPORT simplifyMultiLineSpace( const QString &multiLine );
34
35// Creates a QString which doesn't contain any "dangerous"
36// characters (i.e. <, >, &, ")
37QString QPC_EXPORT escapeString( const QString& plain );
38
39// Takes a UTF-8!! string and removes all the XML thingies (entities?)
40// from the string and also calls fromUtf8() on it... so make sure
41// to pass a QCString/const char* with UTF-8 data only
42QString QPC_EXPORT plainString( const char* escaped, unsigned int length );
43QString QPC_EXPORT plainString( const QCString& string );
44
45QString QPC_EXPORT plainString( const QString& string );
46
47
48// collation functions
49int compare( const QString & s1, const QString & s2 );
50QString buildSortKey( const QString & s );
51QString buildSortKey( const QString & s1, const QString & s2 );
52QString buildSortKey( const QString & s1, const QString & s2,
53 const QString & s3 );
54
55}
56
57#endif
diff --git a/library/backend/task.cpp b/library/backend/task.cpp
index f0a38f1..a00adb3 100644
--- a/library/backend/task.cpp
+++ b/library/backend/task.cpp
@@ -1,272 +1,409 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <qpe/task.h> 21#include "task.h"
22#include <qregexp.h> 22#include "recordfields.h"
23#include <qstring.h>
24#include <qpe/recordfields.h>
25#include "vobject_p.h" 23#include "vobject_p.h"
26#include "timeconversion.h"
27#include "qfiledirect_p.h" 24#include "qfiledirect_p.h"
28 25
26#include <qtopia/timeconversion.h>
27
28#include <qregexp.h>
29#include <qstring.h>
30
29#include <stdio.h> 31#include <stdio.h>
30 32
31using namespace Qtopia; 33using namespace Qtopia;
32UidGen Task::sUidGen( UidGen::Qtopia ); 34UidGen Task::sUidGen( UidGen::Qtopia );
33 35
36/*!
37 \class Task
38 \brief The Task class holds the data of a todo entry.
39
40 This data includes the priority of the task, a description, an optional due
41 date, and whether the task is completed or not.
42
43 \ingroup qtopiaemb
44 \ingroup qtopiadesktop
45*/
46
47/*!
48 Creates a new, empty task.
49*/
34Task::Task() : Record(), mDue( FALSE ), 50Task::Task() : Record(), mDue( FALSE ),
35mDueDate( QDate::currentDate() ), 51mDueDate( QDate::currentDate() ),
36mCompleted( FALSE ), mPriority( 3 ), mDesc() 52mCompleted( FALSE ), mPriority( 3 ), mDesc()
37{ 53{
38} 54}
39 55
56/*!
57 \fn void Task::setPriority( int priority )
58
59 Sets the priority of the task to \a priority.
60*/
61
62/*!
63 \fn int Task::priority() const
64
65 Returns the priority of the task.
66*/
67
68/*!
69 \fn void Task::setDescription( const QString &description )
70
71 Sets the description of the task to \a description.
72 */
73
74/*!
75 \fn const QString &Task::description() const
76
77 Returns the description of the task.
78 */
79
80/*!
81 \fn void Task::setDueDate( const QDate &date, bool hasDue )
82
83 \internal
84 If \a hasDue is TRUE sets the due date of the task to \a date.
85 Otherwise clears the due date of the task.
86*/
87
88/*!
89 \fn void Task::setDueDate( const QDate &date )
90
91 Sets the due date of the task to \a date.
92*/
93
94/*!
95 \fn void Task::clearDueDate( )
96
97 Clears the due date of the task.
98*/
99
100/*!
101 \fn void Task::setCompleted( bool b )
102
103 If \a b is TRUE marks the task as completed. Otherwise marks the task as
104 uncompleted.
105*/
106
107/*!
108 \fn bool Task::isCompleted() const
109
110 Returns TRUE if the task is completed. Otherwise returns FALSE.
111*/
112
113/*!
114 \fn const QDate &Task::dueDate() const
115
116 Returns the due date of the task.
117 */
118
119/*!
120 \fn bool Task::hasDueDate() const
121
122 Returns TRUE if there is a due date set for the task. Otherwise returns
123 FALSE.
124*/
125
126/*!
127 \fn void Task::setHasDueDate( bool b )
128
129 \internal
130 Just don't ask. I really can't justify the function.
131*/
132
133
134/*!
135 \internal
136 Creates a new task. The properties of the task are set from \a m.
137*/
138
40Task::Task( const QMap<int, QString> &m ) : Record(), mDue( FALSE ), 139Task::Task( const QMap<int, QString> &m ) : Record(), mDue( FALSE ),
41mDueDate( QDate::currentDate() ), mCompleted( FALSE ), mPriority( 3 ), mDesc() 140mDueDate( QDate::currentDate() ), mCompleted( FALSE ), mPriority( 3 ), mDesc()
42{ 141{
43 //qDebug("Task::Task fromMap"); 142 //qDebug("Task::Task fromMap");
44 //dump( m ); 143 //dump( m );
45 for ( QMap<int,QString>::ConstIterator it = m.begin(); it != m.end();++it ) 144 for ( QMap<int,QString>::ConstIterator it = m.begin(); it != m.end();++it )
46 switch ( (TaskFields) it.key() ) { 145 switch ( (TaskFields) it.key() ) {
47 case HasDate: if ( *it == "1" ) mDue = TRUE; break; 146 case HasDate: if ( *it == "1" ) mDue = TRUE; break;
48 case Completed: setCompleted( *it == "1" ); break; 147 case Completed: setCompleted( *it == "1" ); break;
49 case TaskCategory: setCategories( idsFromString( *it ) ); break; 148 case TaskCategory: setCategories( idsFromString( *it ) ); break;
50 case TaskDescription: setDescription( *it ); break; 149 case TaskDescription: setDescription( *it ); break;
51 case Priority: setPriority( (*it).toInt() ); break; 150 case Priority: setPriority( (*it).toInt() ); break;
52 case Date: mDueDate = TimeConversion::fromString( (*it) ); break; 151 case Date: mDueDate = TimeConversion::fromString( (*it) ); break;
53 case TaskUid: setUid( (*it).toInt() ); break; 152 case TaskUid: setUid( (*it).toInt() ); break;
54 default: break; 153 case TaskRid:
154 case TaskRinfo:
155 break;
55 } 156 }
56} 157}
57 158
159/*!
160 Destroys a task.
161*/
58Task::~Task() 162Task::~Task()
59{ 163{
60} 164}
61 165
166/*!
167 \internal
168 Returns the task as a map of field ids to property values.
169*/
62QMap<int, QString> Task::toMap() const 170QMap<int, QString> Task::toMap() const
63{ 171{
64 QMap<int, QString> m; 172 QMap<int, QString> m;
65 m.insert( HasDate, hasDueDate() ? "1" : "0" ); 173 m.insert( HasDate, hasDueDate() ? "1" : "0" );
66 m.insert( Completed, isCompleted() ? "1" : "0" ); 174 m.insert( Completed, isCompleted() ? "1" : "0" );
67 m.insert( TaskCategory, idsToString( categories() ) ); 175 if ( categories().count() )
68 m.insert( TaskDescription, description() ); 176 m.insert( TaskCategory, idsToString( categories() ) );
177 if ( !description().isEmpty() )
178 m.insert( TaskDescription, description() );
69 m.insert( Priority, QString::number( priority() ) ); 179 m.insert( Priority, QString::number( priority() ) );
70 m.insert( Date, TimeConversion::toString( dueDate() ) ); 180 if ( hasDueDate() )
181 m.insert( Date, TimeConversion::toString( dueDate() ) );
71 m.insert( TaskUid, QString::number(uid()) ); 182 m.insert( TaskUid, QString::number(uid()) );
72 183
73 //qDebug("Task::toMap"); 184 //qDebug("Task::toMap");
74 //dump( m ); 185 //dump( m );
75 return m; 186 return m;
76} 187}
77 188
189/*!
190 \internal
191 Appends the task information to \a buf.
192*/
78void Task::save( QString& buf ) const 193void Task::save( QString& buf ) const
79{ 194{
80 buf += " Completed=\""; 195 buf += " Completed=\"";
81 // qDebug( "writing %d", complete ); 196 // qDebug( "writing %d", complete );
82 buf += QString::number( (int)mCompleted ); 197 buf += QString::number( (int)mCompleted );
83 buf += "\""; 198 buf += "\"";
84 buf += " HasDate=\""; 199 buf += " HasDate=\"";
85 // qDebug( "writing %d", ); 200 // qDebug( "writing %d", );
86 buf += QString::number( (int)mDue ); 201 buf += QString::number( (int)mDue );
87 buf += "\""; 202 buf += "\"";
88 buf += " Priority=\""; 203 buf += " Priority=\"";
89 // qDebug ("writing %d", prior ); 204 // qDebug ("writing %d", prior );
90 buf += QString::number( mPriority ); 205 buf += QString::number( mPriority );
91 buf += "\""; 206 buf += "\"";
92 buf += " Categories=\""; 207 buf += " Categories=\"";
93 buf += Qtopia::Record::idsToString( categories() ); 208 buf += Qtopia::Record::idsToString( categories() );
94 buf += "\""; 209 buf += "\"";
95 buf += " Description=\""; 210 buf += " Description=\"";
96 // qDebug( "writing note %s", note.latin1() ); 211 // qDebug( "writing note %s", note.latin1() );
97 buf += Qtopia::escapeString( mDesc ); 212 buf += Qtopia::escapeString( mDesc );
98 buf += "\""; 213 buf += "\"";
99 if ( mDue ) { 214 if ( mDue ) {
100 // qDebug("saving ymd %d %d %d", mDueDate.year(), mDueDate.month(), 215 // qDebug("saving ymd %d %d %d", mDueDate.year(), mDueDate.month(),
101 // mDueDate.day() ); 216 // mDueDate.day() );
102 buf += " DateYear=\""; 217 buf += " DateYear=\"";
103 buf += QString::number( mDueDate.year() ); 218 buf += QString::number( mDueDate.year() );
104 buf += "\""; 219 buf += "\"";
105 buf += " DateMonth=\""; 220 buf += " DateMonth=\"";
106 buf += QString::number( mDueDate.month() ); 221 buf += QString::number( mDueDate.month() );
107 buf += "\""; 222 buf += "\"";
108 buf += " DateDay=\""; 223 buf += " DateDay=\"";
109 buf += QString::number( mDueDate.day() ); 224 buf += QString::number( mDueDate.day() );
110 buf += "\""; 225 buf += "\"";
111 } 226 }
112 buf += customToXml(); 227 buf += customToXml();
113 // qDebug ("writing uid %d", uid() ); 228 // qDebug ("writing uid %d", uid() );
114 buf += " Uid=\""; 229 buf += " Uid=\"";
115 buf += QString::number( uid() ); 230 buf += QString::number( uid() );
116 // terminate it in the application... 231 // terminate it in the application...
117 buf += "\""; 232 buf += "\"";
118} 233}
119 234
120bool Task::match ( const QRegExp &r ) const 235/*!
236 Returns TRUE if the task matches the regular expressions \a regexp.
237 Otherwise returns FALSE.
238*/
239bool Task::match ( const QRegExp &regexp ) const
121{ 240{
122 // match on priority, description on due date... 241 // match on priority, description on due date...
123 bool match; 242 bool match;
124 match = false; 243 match = false;
125 if ( QString::number( mPriority ).find( r ) > -1 ) 244 if ( QString::number( mPriority ).find( regexp ) > -1 )
126 match = true; 245 match = true;
127 else if ( mDue && mDueDate.toString().find( r ) > -1 ) 246 else if ( mDue && mDueDate.toString().find( regexp ) > -1 )
128 match = true; 247 match = true;
129 else if ( mDesc.find( r ) > -1 ) 248 else if ( mDesc.find( regexp ) > -1 )
130 match = true; 249 match = true;
131 return match; 250 return match;
132} 251}
133 252
253/*!
254 \internal
255*/
134static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value ) 256static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
135{ 257{
136 VObject *ret = 0; 258 VObject *ret = 0;
137 if ( o && !value.isEmpty() ) 259 if ( o && !value.isEmpty() )
138 ret = addPropValue( o, prop, value.latin1() ); 260 ret = addPropValue( o, prop, value.latin1() );
139 return ret; 261 return ret;
140} 262}
141 263
264/*!
265 \internal
266*/
142static inline VObject *safeAddProp( VObject *o, const char *prop) 267static inline VObject *safeAddProp( VObject *o, const char *prop)
143{ 268{
144 VObject *ret = 0; 269 VObject *ret = 0;
145 if ( o ) 270 if ( o )
146 ret = addProp( o, prop ); 271 ret = addProp( o, prop );
147 return ret; 272 return ret;
148} 273}
149 274
150 275
276/*!
277 \internal
278*/
151static VObject *createVObject( const Task &t ) 279static VObject *createVObject( const Task &t )
152{ 280{
153 VObject *vcal = newVObject( VCCalProp ); 281 VObject *vcal = newVObject( VCCalProp );
154 safeAddPropValue( vcal, VCVersionProp, "1.0" ); 282 safeAddPropValue( vcal, VCVersionProp, "1.0" );
155 VObject *task = safeAddProp( vcal, VCTodoProp ); 283 VObject *task = safeAddProp( vcal, VCTodoProp );
156 284
157 if ( t.hasDueDate() ) 285 if ( t.hasDueDate() )
158 safeAddPropValue( task, VCDueProp, TimeConversion::toISO8601( t.dueDate() ) ); 286 safeAddPropValue( task, VCDueProp, TimeConversion::toISO8601( t.dueDate() ) );
159 safeAddPropValue( task, VCDescriptionProp, t.description() ); 287 safeAddPropValue( task, VCDescriptionProp, t.description() );
160 if ( t.isCompleted() ) 288 if ( t.isCompleted() )
161 safeAddPropValue( task, VCStatusProp, "COMPLETED" ); 289 safeAddPropValue( task, VCStatusProp, "COMPLETED" );
162 safeAddPropValue( task, VCPriorityProp, QString::number( t.priority() ) ); 290 safeAddPropValue( task, VCPriorityProp, QString::number( t.priority() ) );
163 291
164 return vcal; 292 return vcal;
165} 293}
166 294
167 295/*!
296 \internal
297*/
168static Task parseVObject( VObject *obj ) 298static Task parseVObject( VObject *obj )
169{ 299{
170 Task t; 300 Task t;
171 301
172 VObjectIterator it; 302 VObjectIterator it;
173 initPropIterator( &it, obj ); 303 initPropIterator( &it, obj );
174 while( moreIteration( &it ) ) { 304 while( moreIteration( &it ) ) {
175 VObject *o = nextVObject( &it ); 305 VObject *o = nextVObject( &it );
176 QCString name = vObjectName( o ); 306 QCString name = vObjectName( o );
177 QCString value = vObjectStringZValue( o ); 307 QCString value = vObjectStringZValue( o );
178 if ( name == VCDueProp ) { 308 if ( name == VCDueProp ) {
179 t.setDueDate( TimeConversion::fromISO8601( value ).date(), TRUE ); 309 t.setDueDate( TimeConversion::fromISO8601( value ).date(), TRUE );
180 } 310 }
181 else if ( name == VCDescriptionProp ) { 311 else if ( name == VCDescriptionProp ) {
182 t.setDescription( value ); 312 t.setDescription( value );
183 } 313 }
184 else if ( name == VCStatusProp ) { 314 else if ( name == VCStatusProp ) {
185 if ( value == "COMPLETED" ) 315 if ( value == "COMPLETED" )
186 t.setCompleted( TRUE ); 316 t.setCompleted( TRUE );
187 } 317 }
188 else if ( name == VCPriorityProp ) { 318 else if ( name == VCPriorityProp ) {
189 t.setPriority( value.toInt() ); 319 t.setPriority( value.toInt() );
190 } 320 }
191#if 0 321#if 0
192 else { 322 else {
193 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); 323 printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) );
194 VObjectIterator nit; 324 VObjectIterator nit;
195 initPropIterator( &nit, o ); 325 initPropIterator( &nit, o );
196 while( moreIteration( &nit ) ) { 326 while( moreIteration( &nit ) ) {
197 VObject *o = nextVObject( &nit ); 327 VObject *o = nextVObject( &nit );
198 QCString name = vObjectName( o ); 328 QCString name = vObjectName( o );
199 QString value = vObjectStringZValue( o ); 329 QString value = vObjectStringZValue( o );
200 printf(" subprop: %s = %s\n", name.data(), value.latin1() ); 330 printf(" subprop: %s = %s\n", name.data(), value.latin1() );
201 } 331 }
202 } 332 }
203#endif 333#endif
204 } 334 }
205 335
206 return t; 336 return t;
207} 337}
208 338
209 339
210 340/*!
341 Writes the list of \a tasks as a set of VCards to the file \a filename.
342*/
211void Task::writeVCalendar( const QString &filename, const QValueList<Task> &tasks) 343void Task::writeVCalendar( const QString &filename, const QValueList<Task> &tasks)
212{ 344{
213 QFileDirect f( filename.utf8().data() ); 345 QFileDirect f( filename.utf8().data() );
214 if ( !f.open( IO_WriteOnly ) ) { 346 if ( !f.open( IO_WriteOnly ) ) {
215 qWarning("Unable to open vcard write"); 347 qWarning("Unable to open vcard write");
216 return; 348 return;
217 } 349 }
218 350
219 QValueList<Task>::ConstIterator it; 351 QValueList<Task>::ConstIterator it;
220 for( it = tasks.begin(); it != tasks.end(); ++it ) { 352 for( it = tasks.begin(); it != tasks.end(); ++it ) {
221 VObject *obj = createVObject( *it ); 353 VObject *obj = createVObject( *it );
222 writeVObject(f.directHandle() , obj ); 354 writeVObject(f.directHandle() , obj );
223 cleanVObject( obj ); 355 cleanVObject( obj );
224 } 356 }
225 357
226 cleanStrTbl(); 358 cleanStrTbl();
227} 359}
228 360
361/*!
362 Writes \a task as a VCard to the file \a filename.
363*/
229void Task::writeVCalendar( const QString &filename, const Task &task) 364void Task::writeVCalendar( const QString &filename, const Task &task)
230{ 365{
231 QFileDirect f( filename.utf8().data() ); 366 QFileDirect f( filename.utf8().data() );
232 if ( !f.open( IO_WriteOnly ) ) { 367 if ( !f.open( IO_WriteOnly ) ) {
233 qWarning("Unable to open vcard write"); 368 qWarning("Unable to open vcard write");
234 return; 369 return;
235 } 370 }
236 371
237 VObject *obj = createVObject( task ); 372 VObject *obj = createVObject( task );
238 writeVObject(f.directHandle() , obj ); 373 writeVObject(f.directHandle() , obj );
239 cleanVObject( obj ); 374 cleanVObject( obj );
240 375
241 cleanStrTbl(); 376 cleanStrTbl();
242} 377}
243 378
244 379/*!
380 Returns the set of tasks read as VCards from the file \a filename.
381*/
245QValueList<Task> Task::readVCalendar( const QString &filename ) 382QValueList<Task> Task::readVCalendar( const QString &filename )
246{ 383{
247 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() ); 384 VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
248 385
249 QValueList<Task> tasks; 386 QValueList<Task> tasks;
250 387
251 while ( obj ) { 388 while ( obj ) {
252 QCString name = vObjectName( obj ); 389 QCString name = vObjectName( obj );
253 if ( name == VCCalProp ) { 390 if ( name == VCCalProp ) {
254 VObjectIterator nit; 391 VObjectIterator nit;
255 initPropIterator( &nit, obj ); 392 initPropIterator( &nit, obj );
256 while( moreIteration( &nit ) ) { 393 while( moreIteration( &nit ) ) {
257 VObject *o = nextVObject( &nit ); 394 VObject *o = nextVObject( &nit );
258 QCString name = vObjectName( o ); 395 QCString name = vObjectName( o );
259 if ( name == VCTodoProp ) 396 if ( name == VCTodoProp )
260 tasks.append( parseVObject( o ) ); 397 tasks.append( parseVObject( o ) );
261 } 398 }
262 } else if ( name == VCTodoProp ) { 399 } else if ( name == VCTodoProp ) {
263 // shouldn't happen, but just to be sure 400 // shouldn't happen, but just to be sure
264 tasks.append( parseVObject( obj ) ); 401 tasks.append( parseVObject( obj ) );
265 } 402 }
266 VObject *t = obj; 403 VObject *t = obj;
267 obj = nextVObjectInList(obj); 404 obj = nextVObjectInList(obj);
268 cleanVObject( t ); 405 cleanVObject( t );
269 } 406 }
270 407
271 return tasks; 408 return tasks;
272} 409}
diff --git a/library/backend/task.h b/library/backend/task.h
index 6f383b8..091f2e9 100644
--- a/library/backend/task.h
+++ b/library/backend/task.h
@@ -1,81 +1,92 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20#ifndef __TASK_H__ 20#ifndef __TASK_H__
21#define __TASK_H__ 21#define __TASK_H__
22 22
23#include <qpe/palmtoprecord.h> 23#include <qtopia/private/palmtoprecord.h>
24#include <qpe/stringutil.h> 24#include <qtopia/stringutil.h>
25 25
26#include <qvaluelist.h> 26#include <qvaluelist.h>
27#include <qdatetime.h> 27#include <qdatetime.h>
28 28
29class TaskPrivate; 29class TaskPrivate;
30class QPC_EXPORT Task : public Qtopia::Record 30class QPC_EXPORT Task : public Qtopia::Record
31{ 31{
32public: 32public:
33 Task(); 33 Task();
34 Task( const QMap<int, QString> &fromMap ); 34 Task( const QMap<int, QString> &fromMap );
35 ~Task(); 35 ~Task();
36 36
37 QMap<int, QString> toMap() const; 37 QMap<int, QString> toMap() const;
38 38
39 static void writeVCalendar( const QString &filename, const QValueList<Task> &tasks); 39 static void writeVCalendar( const QString &filename, const QValueList<Task> &tasks);
40 static void writeVCalendar( const QString &filename, const Task &task); 40 static void writeVCalendar( const QString &filename, const Task &task);
41 static QValueList<Task> readVCalendar( const QString &filename ); 41 static QValueList<Task> readVCalendar( const QString &filename );
42 42
43 enum PriorityValue { VeryHigh=1, High, Normal, Low, VeryLow };
44
43 void setPriority( int priority ) { mPriority = priority; } 45 void setPriority( int priority ) { mPriority = priority; }
44 int priority() const { return mPriority; } 46 int priority() const { return mPriority; }
45 47
46// void setCategory( const QString& category ) 48// void setCategory( const QString& category )
47// { mCategory = category.stripWhiteSpace(); } 49// { mCategory = category.stripWhiteSpace(); }
48// const QString &category() const { return mCategory; } 50// const QString &category() const { return mCategory; }
49 51
50 void setDescription( const QString& description ) 52 void setDescription( const QString& description )
51 { mDesc = Qtopia::simplifyMultiLineSpace(description); } 53 { mDesc = Qtopia::simplifyMultiLineSpace(description); }
52 const QString &description() const { return mDesc; } 54 const QString &description() const { return mDesc; }
53 55
56 // Use THESE functions
57 void setDueDate( const QDate &date);
58 void clearDueDate();
59
60 // Instead of these functions.
54 void setDueDate( const QDate& date, bool hasDue ) { mDueDate = date; mDue = hasDue; } 61 void setDueDate( const QDate& date, bool hasDue ) { mDueDate = date; mDue = hasDue; }
62 void setHasDueDate( bool b ) { mDue = b; }
63
55 const QDate &dueDate() const { return mDueDate; } 64 const QDate &dueDate() const { return mDueDate; }
56 bool hasDueDate() const { return mDue; } 65 bool hasDueDate() const { return mDue; }
57 void setHasDueDate( bool b ) { mDue = b; }
58 66
59 void setCompleted( bool b ) { mCompleted = b; } 67 void setCompleted( bool b ) { mCompleted = b; }
60 bool isCompleted() const { return mCompleted; } 68 bool isCompleted() const { return mCompleted; }
61 69
62 void save( QString& buf ) const; 70 void save( QString& buf ) const;
63 bool match( const QRegExp &r ) const; 71 bool match( const QRegExp &r ) const;
64 72
65private: 73private:
66 Qtopia::UidGen &uidGen() { return sUidGen; } 74 Qtopia::UidGen &uidGen() { return sUidGen; }
67 static Qtopia::UidGen sUidGen; 75 static Qtopia::UidGen sUidGen;
68 76
69 bool mDue; 77 bool mDue;
70 QDate mDueDate; 78 QDate mDueDate;
71 bool mCompleted; 79 bool mCompleted;
72 int mPriority; 80 int mPriority;
73 QString mDesc; 81 QString mDesc;
74 TaskPrivate *d; 82 TaskPrivate *d;
75 // ADDITION 83 // ADDITION
76 int recordId; 84 int recordId;
77 int recordInfo; 85 int recordInfo;
78 // 86 //
79}; 87};
80 88
89// MUST be inline. (forwards compatability).
90inline void Task::setDueDate( const QDate &date) { setDueDate(date, date.isValid()); }
91inline void Task::clearDueDate() { setHasDueDate( FALSE ); }
81#endif 92#endif
diff --git a/library/backend/timeconversion.cpp b/library/backend/timeconversion.cpp
deleted file mode 100644
index a4a2547..0000000
--- a/library/backend/timeconversion.cpp
+++ b/dev/null
@@ -1,237 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include <qglobal.h>
22#include "timeconversion.h"
23#include <qregexp.h>
24#include <stdlib.h>
25
26QString TimeConversion::toString( const QDate &d )
27{
28 QString r = QString::number( d.day() ) + "." +
29 QString::number( d.month() ) + "." +
30 QString::number( d.year() );
31 //qDebug("TimeConversion::toString %s", r.latin1());
32 return r;
33}
34
35QDate TimeConversion::fromString( const QString &datestr )
36{
37 int monthPos = datestr.find('.');
38 int yearPos = datestr.find('.', monthPos+1 );
39 if ( monthPos == -1 || yearPos == -1 ) {
40 qDebug("fromString didn't find . in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, yearPos );
41 return QDate();
42 }
43 int d = datestr.left( monthPos ).toInt();
44 int m = datestr.mid( monthPos+1, yearPos - monthPos - 1 ).toInt();
45 int y = datestr.mid( yearPos+1 ).toInt();
46 QDate date ( y,m,d );
47 //qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, yearPos);
48 return date;
49}
50
51time_t TimeConversion::toUTC( const QDateTime& dt )
52{
53 time_t tmp;
54 struct tm *lt;
55
56#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
57 _tzset();
58#else
59 tzset();
60#endif
61
62 // get a tm structure from the system to get the correct tz_name
63 tmp = time( 0 );
64 lt = localtime( &tmp );
65
66 lt->tm_sec = dt.time().second();
67 lt->tm_min = dt.time().minute();
68 lt->tm_hour = dt.time().hour();
69 lt->tm_mday = dt.date().day();
70 lt->tm_mon = dt.date().month() - 1; // 0-11 instead of 1-12
71 lt->tm_year = dt.date().year() - 1900; // year - 1900
72 //lt->tm_wday = dt.date().dayOfWeek(); ignored anyway
73 //lt->tm_yday = dt.date().dayOfYear(); ignored anyway
74 lt->tm_wday = -1;
75 lt->tm_yday = -1;
76 // tm_isdst negative -> mktime will find out about DST
77 lt->tm_isdst = -1;
78 // keep tm_zone and tm_gmtoff
79 tmp = mktime( lt );
80 return tmp;
81}
82
83QDateTime TimeConversion::fromUTC( time_t time )
84{
85 struct tm *lt;
86
87#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
88 _tzset();
89#else
90 tzset();
91#endif
92 lt = localtime( &time );
93 QDateTime dt;
94 dt.setDate( QDate( lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday ) );
95 dt.setTime( QTime( lt->tm_hour, lt->tm_min, lt->tm_sec ) );
96 return dt;
97}
98
99
100int TimeConversion::secsTo( const QDateTime &from, const QDateTime &to )
101{
102 return toUTC( to ) - toUTC( from );
103}
104
105QCString TimeConversion::toISO8601( const QDate &d )
106{
107 time_t tmp = toUTC( d );
108 struct tm *utc = gmtime( &tmp );
109
110 QCString str;
111 str.sprintf("%04d%02d%02d", (utc->tm_year + 1900), utc->tm_mon+1, utc->tm_mday );
112 return str;
113}
114
115QCString TimeConversion::toISO8601( const QDateTime &dt )
116{
117 time_t tmp = toUTC( dt );
118 struct tm *utc = gmtime( &tmp );
119
120 QCString str;
121 str.sprintf("%04d%02d%02dT%02d%02d%02dZ",
122 (utc->tm_year + 1900), utc->tm_mon+1, utc->tm_mday,
123 utc->tm_hour, utc->tm_min, utc->tm_sec );
124 return str;
125}
126
127QDateTime TimeConversion::fromISO8601( const QCString &s )
128{
129
130#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
131 _tzset();
132#else
133 tzset();
134#endif
135
136 struct tm *thetime = new tm;
137
138 QCString str = s.copy();
139 str.replace(QRegExp("-"), "" );
140 str.replace(QRegExp(":"), "" );
141 str.stripWhiteSpace();
142 str = str.lower();
143
144 int i = str.find( "t" );
145 QCString date;
146 QCString timestr;
147 if ( i != -1 ) {
148 date = str.left( i );
149 timestr = str.mid( i+1 );
150 } else {
151 date = str;
152 }
153
154// qDebug("--- parsing ISO time---");
155 thetime->tm_year = 100;
156 thetime->tm_mon = 0;
157 thetime->tm_mday = 0;
158 thetime->tm_hour = 0;
159 thetime->tm_min = 0;
160 thetime->tm_sec = 0;
161
162// qDebug("date = %s", date.data() );
163
164 switch( date.length() ) {
165 case 8:
166 thetime->tm_mday = date.right( 2 ).toInt();
167 case 6:
168 thetime->tm_mon = date.mid( 4, 2 ).toInt() - 1;
169 case 4:
170 thetime->tm_year = date.left( 4 ).toInt();
171 thetime->tm_year -= 1900;
172 break;
173 default:
174 break;
175 }
176
177 int tzoff = 0;
178 bool inLocalTime = FALSE;
179 if ( timestr.find( 'z' ) == (int)timestr.length() - 1 )
180 // UTC
181 timestr = timestr.left( timestr.length() -1 );
182 else {
183 int plus = timestr.find( "+" );
184 int minus = timestr.find( "-" );
185 if ( plus != -1 || minus != -1 ) {
186 // have a timezone offset
187 plus = (plus != -1) ? plus : minus;
188 QCString off = timestr.mid( plus );
189 timestr = timestr.left( plus );
190
191 int tzoffhour = 0;
192 int tzoffmin = 0;
193 switch( off.length() ) {
194 case 5:
195 tzoffmin = off.mid(3).toInt();
196 case 3:
197 tzoffhour = off.left(3).toInt();
198 default:
199 break;
200 }
201 tzoff = 60*tzoffhour + tzoffmin;
202 } else
203 inLocalTime = TRUE;
204 }
205
206 // get the time:
207 switch( timestr.length() ) {
208 case 6:
209 thetime->tm_sec = timestr.mid( 4 ).toInt();
210 case 4:
211 thetime->tm_min = timestr.mid( 2, 2 ).toInt();
212 case 2:
213 thetime->tm_hour = timestr.left( 2 ).toInt();
214 default:
215 break;
216 }
217
218 int tzloc = 0;
219 time_t tmp = time( 0 );
220 if ( !inLocalTime ) {
221 // have to get the offset between gmt and local time
222 struct tm *lt = localtime( &tmp );
223 tzloc = mktime( lt );
224 struct tm *ut = gmtime( &tmp );
225 tzloc -= mktime( ut );
226 }
227// qDebug("time: %d %d %d, tzloc=%d, tzoff=%d", thetime->tm_hour, thetime->tm_min, thetime->tm_sec,
228 // tzloc, tzoff );
229
230 tmp = mktime( thetime );
231 tmp += 60*(-tzloc + tzoff);
232
233 delete thetime;
234
235 return fromUTC( tmp );
236}
237
diff --git a/library/backend/timeconversion.h b/library/backend/timeconversion.h
deleted file mode 100644
index 1724812..0000000
--- a/library/backend/timeconversion.h
+++ b/dev/null
@@ -1,45 +0,0 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#ifndef __timeconversion_h__
22#define __timeconversion_h__
23
24#include <time.h>
25#include <sys/types.h>
26#include <qdatetime.h>
27
28#include <qpe/qpcglobal.h>
29
30class QPC_EXPORT TimeConversion
31{
32public:
33 static QString toString( const QDate &d );
34 static QDate fromString( const QString &datestr );
35
36 static time_t toUTC( const QDateTime& dt );
37 static QDateTime fromUTC( time_t time );
38 static int secsTo( const QDateTime &from, const QDateTime &to );
39
40 static QCString toISO8601( const QDate & );
41 static QCString toISO8601( const QDateTime & );
42 static QDateTime fromISO8601( const QCString & );
43};
44
45#endif // __timeconversion_h__
diff --git a/library/backend/vcc.y b/library/backend/vcc.y
index e326a64..5bcf0cb 100644
--- a/library/backend/vcc.y
+++ b/library/backend/vcc.y
@@ -1,1199 +1,1208 @@
1%{ 1%{
2 2
3/*************************************************************************** 3/***************************************************************************
4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 4(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
5Business Machines Corporation and Siemens Rolm Communications Inc. 5Business Machines Corporation and Siemens Rolm Communications Inc.
6 6
7For purposes of this license notice, the term Licensors shall mean, 7For purposes of this license notice, the term Licensors shall mean,
8collectively, Apple Computer, Inc., AT&T Corp., International 8collectively, Apple Computer, Inc., AT&T Corp., International
9Business Machines Corporation and Siemens Rolm Communications Inc. 9Business Machines Corporation and Siemens Rolm Communications Inc.
10The term Licensor shall mean any of the Licensors. 10The term Licensor shall mean any of the Licensors.
11 11
12Subject to acceptance of the following conditions, permission is hereby 12Subject to acceptance of the following conditions, permission is hereby
13granted by Licensors without the need for written agreement and without 13granted by Licensors without the need for written agreement and without
14license or royalty fees, to use, copy, modify and distribute this 14license or royalty fees, to use, copy, modify and distribute this
15software for any purpose. 15software for any purpose.
16 16
17The above copyright notice and the following four paragraphs must be 17The above copyright notice and the following four paragraphs must be
18reproduced in all copies of this software and any software including 18reproduced in all copies of this software and any software including
19this software. 19this software.
20 20
21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 21THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 22ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
23MODIFICATIONS. 23MODIFICATIONS.
24 24
25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 25IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 26INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 27OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28DAMAGE. 28DAMAGE.
29 29
30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 30EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 31INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33PURPOSE. 33PURPOSE.
34 34
35The software is provided with RESTRICTED RIGHTS. Use, duplication, or 35The software is provided with RESTRICTED RIGHTS. Use, duplication, or
36disclosure by the government are subject to restrictions set forth in 36disclosure by the government are subject to restrictions set forth in
37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 37DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
38 38
39***************************************************************************/ 39***************************************************************************/
40 40
41/* 41/*
42 * src: vcc.c 42 * src: vcc.c
43 * doc: Parser for vCard and vCalendar. Note that this code is 43 * doc: Parser for vCard and vCalendar. Note that this code is
44 * generated by a yacc parser generator. Generally it should not 44 * generated by a yacc parser generator. Generally it should not
45 * be edited by hand. The real source is vcc.y. The #line directives 45 * be edited by hand. The real source is vcc.y. The #line directives
46 * can be commented out here to make it easier to trace through 46 * can be commented out here to make it easier to trace through
47 * in a debugger. However, if a bug is found it should 47 * in a debugger. However, if a bug is found it should
48 * be fixed in vcc.y and this file regenerated. 48 * be fixed in vcc.y and this file regenerated.
49 */ 49 */
50 50
51 51
52/* debugging utilities */ 52/* debugging utilities */
53#if __DEBUG 53#if __DEBUG
54#define DBG_(x) printf x 54#define DBG_(x) printf x
55#else 55#else
56#define DBG_(x) 56#define DBG_(x)
57#endif 57#endif
58 58
59/**** External Functions ****/ 59/**** External Functions ****/
60 60
61/* assign local name to parser variables and functions so that 61/* assign local name to parser variables and functions so that
62 we can use more than one yacc based parser. 62 we can use more than one yacc based parser.
63*/ 63*/
64 64
65#if 0 65#if 0
66#define yyparse mime_parse 66#define yyparse mime_parse
67#define yylex mime_lex 67#define yylex mime_lex
68#define yyerror mime_error 68#define yyerror mime_error
69#define yychar mime_char 69#define yychar mime_char
70/* #define p_yyval p_mime_val */ 70/* #define p_yyval p_mime_val */
71#undef yyval 71#undef yyval
72#define yyval mime_yyval 72#define yyval mime_yyval
73/* #define p_yylval p_mime_lval */ 73/* #define p_yylval p_mime_lval */
74#undef yylval 74#undef yylval
75#define yylval mime_yylval 75#define yylval mime_yylval
76#define yydebug mime_debug 76#define yydebug mime_debug
77#define yynerrs mime_nerrs 77#define yynerrs mime_nerrs
78#define yyerrflag mime_errflag 78#define yyerrflag mime_errflag
79#define yyss mime_ss 79#define yyss mime_ss
80#define yyssp mime_ssp 80#define yyssp mime_ssp
81#define yyvs mime_vs 81#define yyvs mime_vs
82#define yyvsp mime_vsp 82#define yyvsp mime_vsp
83#define yylhs mime_lhs 83#define yylhs mime_lhs
84#define yylen mime_len 84#define yylen mime_len
85#define yydefred mime_defred 85#define yydefred mime_defred
86#define yydgoto mime_dgoto 86#define yydgoto mime_dgoto
87#define yysindex mime_sindex 87#define yysindex mime_sindex
88#define yyrindex mime_rindex 88#define yyrindex mime_rindex
89#define yygindex mime_gindex 89#define yygindex mime_gindex
90#define yytable mime_table 90#define yytable mime_table
91#define yycheck mime_check 91#define yycheck mime_check
92#define yyname mime_name 92#define yyname mime_name
93#define yyrule mime_rule 93#define yyrule mime_rule
94#ifdef YYPREFIX 94#ifdef YYPREFIX
95#undef YYPREFIX 95#undef YYPREFIX
96#endif 96#endif
97#define YYPREFIX "mime_" 97#define YYPREFIX "mime_"
98#endif 98#endif
99 99
100 100
101#ifndef _NO_LINE_FOLDING 101#ifndef _NO_LINE_FOLDING
102#define _SUPPORT_LINE_FOLDING 1 102#define _SUPPORT_LINE_FOLDING 1
103#endif 103#endif
104 104
105/* undef below if compile with MFC */ 105/* undef below if compile with MFC */
106/* #define INCLUDEMFC 1 */ 106/* #define INCLUDEMFC 1 */
107 107
108#if defined(WIN32) || defined(_WIN32) 108#if defined(WIN32) || defined(_WIN32)
109#ifdef INCLUDEMFC 109#ifdef INCLUDEMFC
110#include <afx.h> 110#include <afx.h>
111#endif 111#endif
112#endif 112#endif
113 113
114#include <string.h> 114#include <string.h>
115#ifndef __MWERKS__ 115#ifndef __MWERKS__
116#include <stdlib.h> 116#include <stdlib.h>
117#endif 117#endif
118#include <stdio.h> 118#include <stdio.h>
119#include <stdlib.h> 119#include <stdlib.h>
120#include <ctype.h> 120#include <ctype.h>
121 121
122//#ifdef PALMTOPCENTER 122//#ifdef PALMTOPCENTER
123//#include <qpe/vobject_p.h> 123//#include <qpe/vobject_p.h>
124//#else 124//#else
125#include "vobject_p.h" 125#include "vobject_p.h"
126//#endif 126//#endif
127 127
128/**** Types, Constants ****/ 128/**** Types, Constants ****/
129 129
130 #define YYDEBUG 0/* 1 to compile in some debugging code */ 130 #define YYDEBUG 0/* 1 to compile in some debugging code */
131 #define MAXTOKEN 256/* maximum token (line) length */ 131 #define MAXTOKEN 256/* maximum token (line) length */
132 #define YYSTACKSIZE 100// ~unref ? 132 #define YYSTACKSIZE 100// ~unref ?
133 #define MAXLEVEL 10/* max # of nested objects parseable */ 133 #define MAXLEVEL 10/* max # of nested objects parseable */
134 /* (includes outermost) */ 134 /* (includes outermost) */
135 135
136 136
137/**** Global Variables ****/ 137/**** Global Variables ****/
138int mime_lineNum, mime_numErrors; /* yyerror() can use these */ 138int mime_lineNum, mime_numErrors; /* yyerror() can use these */
139static VObject* vObjList; 139static VObject* vObjList;
140static VObject *curProp; 140static VObject *curProp;
141static VObject *curObj; 141static VObject *curObj;
142static VObject* ObjStack[MAXLEVEL]; 142static VObject* ObjStack[MAXLEVEL];
143static int ObjStackTop; 143static int ObjStackTop;
144 144
145 145
146/* A helpful utility for the rest of the app. */ 146/* A helpful utility for the rest of the app. */
147#if __CPLUSPLUS__ 147#if __CPLUSPLUS__
148extern "C" { 148extern "C" {
149#endif 149#endif
150 150
151 extern void yyerror(char *s); 151 extern void yyerror(char *s);
152 152
153#if __CPLUSPLUS__ 153#if __CPLUSPLUS__
154 }; 154 };
155#endif 155#endif
156 156
157int yyparse(); 157int yyparse();
158 158
159enum LexMode { 159enum LexMode {
160 L_NORMAL, 160 L_NORMAL,
161 L_VCARD, 161 L_VCARD,
162 L_VCAL, 162 L_VCAL,
163 L_VEVENT, 163 L_VEVENT,
164 L_VTODO, 164 L_VTODO,
165 L_VALUES, 165 L_VALUES,
166 L_BASE64, 166 L_BASE64,
167 L_QUOTED_PRINTABLE 167 L_QUOTED_PRINTABLE
168 }; 168 };
169 169
170/**** Private Forward Declarations ****/ 170/**** Private Forward Declarations ****/
171static int pushVObject(const char *prop); 171static int pushVObject(const char *prop);
172static VObject* popVObject(); 172static VObject* popVObject();
173static void lexPopMode(int top); 173static void lexPopMode(int top);
174static int lexWithinMode(enum LexMode mode); 174static int lexWithinMode(enum LexMode mode);
175static void lexPushMode(enum LexMode mode); 175static void lexPushMode(enum LexMode mode);
176static void enterProps(const char *s); 176static void enterProps(const char *s);
177static void enterAttr(const char *s1, const char *s2); 177static void enterAttr(const char *s1, const char *s2);
178static void enterValues(const char *value); 178static void enterValues(const char *value);
179#define mime_error yyerror 179#define mime_error yyerror
180void mime_error(char *s); 180void mime_error(char *s);
181void mime_error_(char *s); 181void mime_error_(char *s);
182 182
183%} 183%}
184 184
185/***************************************************************************/ 185/***************************************************************************/
186/*** The grammar ****/ 186/*** The grammar ****/
187/***************************************************************************/ 187/***************************************************************************/
188 188
189%union { 189%union {
190 char *str; 190 char *str;
191 VObject *vobj; 191 VObject *vobj;
192 } 192 }
193 193
194%token 194%token
195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE 195 EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE
196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL 196 BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL
197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO 197 BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO
198 ID 198 ID
199 199
200/* 200/*
201 * NEWLINE is the token that would occur outside a vCard, 201 * NEWLINE is the token that would occur outside a vCard,
202 * while LINESEP is the token that would occur inside a vCard. 202 * while LINESEP is the token that would occur inside a vCard.
203 */ 203 */
204 204
205%token <str> 205%token <str>
206 STRING ID 206 STRING ID
207 207
208%type <str> name value 208%type <str> name value
209 209
210%type <vobj> vcard vcal vobject 210%type <vobj> vcard vcal vobject
211 211
212%start mime 212%start mime
213 213
214%% 214%%
215 215
216 216
217mime: vobjects 217mime: vobjects
218 ; 218 ;
219 219
220vobjects: vobjects vobject 220vobjects: vobjects vobject
221 { addList(&vObjList, $2); curObj = 0; } 221 { addList(&vObjList, $2); curObj = 0; }
222 | vobject 222 | vobject
223 { addList(&vObjList, $1); curObj = 0; } 223 { addList(&vObjList, $1); curObj = 0; }
224 ; 224 ;
225 225
226vobject: vcard 226vobject: vcard
227 | vcal 227 | vcal
228 ; 228 ;
229 229
230vcard: 230vcard:
231 BEGIN_VCARD 231 BEGIN_VCARD
232 { 232 {
233 lexPushMode(L_VCARD); 233 lexPushMode(L_VCARD);
234 if (!pushVObject(VCCardProp)) YYERROR; 234 if (!pushVObject(VCCardProp)) YYERROR;
235 } 235 }
236 items END_VCARD 236 items END_VCARD
237 { 237 {
238 lexPopMode(0); 238 lexPopMode(0);
239 $$ = popVObject(); 239 $$ = popVObject();
240 } 240 }
241 | BEGIN_VCARD 241 | BEGIN_VCARD
242 { 242 {
243 lexPushMode(L_VCARD); 243 lexPushMode(L_VCARD);
244 if (!pushVObject(VCCardProp)) YYERROR; 244 if (!pushVObject(VCCardProp)) YYERROR;
245 } 245 }
246 END_VCARD 246 END_VCARD
247 { 247 {
248 lexPopMode(0); 248 lexPopMode(0);
249 $$ = popVObject(); 249 $$ = popVObject();
250 } 250 }
251 ; 251 ;
252 252
253items: items item 253items: items item
254 | item 254 | item
255 ; 255 ;
256 256
257item: prop COLON 257item: prop COLON
258 { 258 {
259 lexPushMode(L_VALUES); 259 lexPushMode(L_VALUES);
260 } 260 }
261 values LINESEP 261 values LINESEP
262 { 262 {
263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) 263 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
264 lexPopMode(0); 264 lexPopMode(0);
265 lexPopMode(0); 265 lexPopMode(0);
266 } 266 }
267 | error 267 | error
268 ; 268 ;
269 269
270prop: name 270prop: name
271 { 271 {
272 enterProps($1); 272 enterProps($1);
273 } 273 }
274 attr_params 274 attr_params
275 | name 275 | name
276 { 276 {
277 enterProps($1); 277 enterProps($1);
278 } 278 }
279 ; 279 ;
280 280
281attr_params: attr_params attr_param 281attr_params: attr_params attr_param
282 | attr_param 282 | attr_param
283 ; 283 ;
284 284
285attr_param: SEMICOLON attr 285attr_param: SEMICOLON attr
286 ; 286 ;
287 287
288attr: name 288attr: name
289 { 289 {
290 enterAttr($1,0); 290 enterAttr($1,0);
291 } 291 }
292 | name EQ name 292 | name EQ name
293 { 293 {
294 enterAttr($1,$3); 294 enterAttr($1,$3);
295 295
296 } 296 }
297 ; 297 ;
298 298
299name: ID 299name: ID
300 ; 300 ;
301 301
302values: value SEMICOLON { enterValues($1); } values 302values: value SEMICOLON { enterValues($1); } values
303 | value 303 | value
304 { enterValues($1); } 304 { enterValues($1); }
305 ; 305 ;
306 306
307value: STRING 307value: STRING
308 | 308 |
309 { $$ = 0; } 309 { $$ = 0; }
310 ; 310 ;
311 311
312vcal: 312vcal:
313 BEGIN_VCAL 313 BEGIN_VCAL
314 { if (!pushVObject(VCCalProp)) YYERROR; } 314 { if (!pushVObject(VCCalProp)) YYERROR; }
315 calitems 315 calitems
316 END_VCAL 316 END_VCAL
317 { $$ = popVObject(); } 317 { $$ = popVObject(); }
318 | BEGIN_VCAL 318 | BEGIN_VCAL
319 { if (!pushVObject(VCCalProp)) YYERROR; } 319 { if (!pushVObject(VCCalProp)) YYERROR; }
320 END_VCAL 320 END_VCAL
321 { $$ = popVObject(); } 321 { $$ = popVObject(); }
322 ; 322 ;
323 323
324calitems: calitems calitem 324calitems: calitems calitem
325 | calitem 325 | calitem
326 ; 326 ;
327 327
328calitem: 328calitem:
329 eventitem 329 eventitem
330 | todoitem 330 | todoitem
331 | items 331 | items
332 ; 332 ;
333 333
334eventitem: 334eventitem:
335 BEGIN_VEVENT 335 BEGIN_VEVENT
336 { 336 {
337 lexPushMode(L_VEVENT); 337 lexPushMode(L_VEVENT);
338 if (!pushVObject(VCEventProp)) YYERROR; 338 if (!pushVObject(VCEventProp)) YYERROR;
339 } 339 }
340 items 340 items
341 END_VEVENT 341 END_VEVENT
342 { 342 {
343 lexPopMode(0); 343 lexPopMode(0);
344 popVObject(); 344 popVObject();
345 } 345 }
346 | BEGIN_VEVENT 346 | BEGIN_VEVENT
347 { 347 {
348 lexPushMode(L_VEVENT); 348 lexPushMode(L_VEVENT);
349 if (!pushVObject(VCEventProp)) YYERROR; 349 if (!pushVObject(VCEventProp)) YYERROR;
350 } 350 }
351 END_VEVENT 351 END_VEVENT
352 { 352 {
353 lexPopMode(0); 353 lexPopMode(0);
354 popVObject(); 354 popVObject();
355 } 355 }
356 ; 356 ;
357 357
358todoitem: 358todoitem:
359 BEGIN_VTODO 359 BEGIN_VTODO
360 { 360 {
361 lexPushMode(L_VTODO); 361 lexPushMode(L_VTODO);
362 if (!pushVObject(VCTodoProp)) YYERROR; 362 if (!pushVObject(VCTodoProp)) YYERROR;
363 } 363 }
364 items 364 items
365 END_VTODO 365 END_VTODO
366 { 366 {
367 lexPopMode(0); 367 lexPopMode(0);
368 popVObject(); 368 popVObject();
369 } 369 }
370 | BEGIN_VTODO 370 | BEGIN_VTODO
371 { 371 {
372 lexPushMode(L_VTODO); 372 lexPushMode(L_VTODO);
373 if (!pushVObject(VCTodoProp)) YYERROR; 373 if (!pushVObject(VCTodoProp)) YYERROR;
374 } 374 }
375 END_VTODO 375 END_VTODO
376 { 376 {
377 lexPopMode(0); 377 lexPopMode(0);
378 popVObject(); 378 popVObject();
379 } 379 }
380 ; 380 ;
381 381
382%% 382%%
383/*------------------------------------*/ 383/*------------------------------------*/
384static int pushVObject(const char *prop) 384static int pushVObject(const char *prop)
385 { 385 {
386 VObject *newObj; 386 VObject *newObj;
387 if (ObjStackTop == MAXLEVEL) 387 if (ObjStackTop == MAXLEVEL)
388 return FALSE; 388 return FALSE;
389 389
390 ObjStack[++ObjStackTop] = curObj; 390 ObjStack[++ObjStackTop] = curObj;
391 391
392 if (curObj) { 392 if (curObj) {
393 newObj = addProp(curObj,prop); 393 newObj = addProp(curObj,prop);
394 curObj = newObj; 394 curObj = newObj;
395 } 395 }
396 else 396 else
397 curObj = newVObject(prop); 397 curObj = newVObject(prop);
398 398
399 return TRUE; 399 return TRUE;
400 } 400 }
401 401
402 402
403/*---------------------------------------*/ 403/*---------------------------------------*/
404/* This pops the recently built vCard off the stack and returns it. */ 404/* This pops the recently built vCard off the stack and returns it. */
405static VObject* popVObject() 405static VObject* popVObject()
406 { 406 {
407 VObject *oldObj; 407 VObject *oldObj;
408 if (ObjStackTop < 0) { 408 if (ObjStackTop < 0) {
409 yyerror("pop on empty Object Stack\n"); 409 yyerror("pop on empty Object Stack\n");
410 return 0; 410 return 0;
411 } 411 }
412 oldObj = curObj; 412 oldObj = curObj;
413 curObj = ObjStack[ObjStackTop--]; 413 curObj = ObjStack[ObjStackTop--];
414 414
415 return oldObj; 415 return oldObj;
416 } 416 }
417 417
418 418
419static void enterValues(const char *value) 419static void enterValues(const char *value)
420 { 420 {
421 if (fieldedProp && *fieldedProp) { 421 if (fieldedProp && *fieldedProp) {
422 if (value) { 422 if (value) {
423 addPropValue(curProp,*fieldedProp,value); 423 addPropValue(curProp,*fieldedProp,value);
424 } 424 }
425 /* else this field is empty, advance to next field */ 425 /* else this field is empty, advance to next field */
426 fieldedProp++; 426 fieldedProp++;
427 } 427 }
428 else { 428 else {
429 if (value) { 429 if (value) {
430 setVObjectStringZValue_(curProp,strdup( value )); 430 setVObjectStringZValue_(curProp,strdup( value ));
431 } 431 }
432 } 432 }
433 deleteStr(value); 433 deleteStr(value);
434 } 434 }
435 435
436static void enterProps(const char *s) 436static void enterProps(const char *s)
437 { 437 {
438 curProp = addGroup(curObj,s); 438 curProp = addGroup(curObj,s);
439 deleteStr(s); 439 deleteStr(s);
440 } 440 }
441 441
442static void enterAttr(const char *s1, const char *s2) 442static void enterAttr(const char *s1, const char *s2)
443 { 443 {
444 const char *p1, *p2; 444 const char *p1, *p2;
445 p1 = lookupProp_(s1); 445 p1 = lookupProp_(s1);
446 if (s2) { 446 if (s2) {
447 VObject *a; 447 VObject *a;
448 p2 = lookupProp_(s2); 448 p2 = lookupProp_(s2);
449 a = addProp(curProp,p1); 449 a = addProp(curProp,p1);
450 setVObjectStringZValue(a,p2); 450 setVObjectStringZValue(a,p2);
451 } 451 }
452 else 452 else
453 addProp(curProp,p1); 453 addProp(curProp,p1);
454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) 454 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
455 lexPushMode(L_BASE64); 455 lexPushMode(L_BASE64);
456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0 456 else if (qstricmp(p1,VCQuotedPrintableProp) == 0
457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) 457 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
458 lexPushMode(L_QUOTED_PRINTABLE); 458 lexPushMode(L_QUOTED_PRINTABLE);
459 deleteStr(s1); deleteStr(s2); 459 deleteStr(s1); deleteStr(s2);
460 } 460 }
461 461
462 462
463#define MAX_LEX_LOOKAHEAD_0 32 463#define MAX_LEX_LOOKAHEAD_0 32
464#define MAX_LEX_LOOKAHEAD 64 464#define MAX_LEX_LOOKAHEAD 64
465#define MAX_LEX_MODE_STACK_SIZE 10 465#define MAX_LEX_MODE_STACK_SIZE 10
466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) 466#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
467 467
468struct LexBuf { 468struct LexBuf {
469 /* input */ 469 /* input */
470#ifdef INCLUDEMFC 470#ifdef INCLUDEMFC
471 CFile *inputFile; 471 CFile *inputFile;
472#else 472#else
473 FILE *inputFile; 473 FILE *inputFile;
474#endif 474#endif
475 char *inputString; 475 char *inputString;
476 unsigned long curPos; 476 unsigned long curPos;
477 unsigned long inputLen; 477 unsigned long inputLen;
478 /* lookahead buffer */ 478 /* lookahead buffer */
479 /* -- lookahead buffer is short instead of char so that EOF 479 /* -- lookahead buffer is short instead of char so that EOF
480 / can be represented correctly. 480 / can be represented correctly.
481 */ 481 */
482 unsigned long len; 482 unsigned long len;
483 short buf[MAX_LEX_LOOKAHEAD]; 483 short buf[MAX_LEX_LOOKAHEAD];
484 unsigned long getPtr; 484 unsigned long getPtr;
485 /* context stack */ 485 /* context stack */
486 unsigned long lexModeStackTop; 486 unsigned long lexModeStackTop;
487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; 487 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
488 /* token buffer */ 488 /* token buffer */
489 unsigned long maxToken; 489 unsigned long maxToken;
490 char *strs; 490 char *strs;
491 unsigned long strsLen; 491 unsigned long strsLen;
492 } lexBuf; 492 } lexBuf;
493 493
494static void lexPushMode(enum LexMode mode) 494static void lexPushMode(enum LexMode mode)
495 { 495 {
496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) 496 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
497 yyerror("lexical context stack overflow"); 497 yyerror("lexical context stack overflow");
498 else { 498 else {
499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; 499 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
500 } 500 }
501 } 501 }
502 502
503static void lexPopMode(int top) 503static void lexPopMode(int top)
504 { 504 {
505 /* special case of pop for ease of error recovery -- this 505 /* special case of pop for ease of error recovery -- this
506 version will never underflow */ 506 version will never underflow */
507 if (top) 507 if (top)
508 lexBuf.lexModeStackTop = 0; 508 lexBuf.lexModeStackTop = 0;
509 else 509 else
510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; 510 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
511 } 511 }
512 512
513static int lexWithinMode(enum LexMode mode) { 513static int lexWithinMode(enum LexMode mode) {
514 unsigned long i; 514 unsigned long i;
515 for (i=0;i<lexBuf.lexModeStackTop;i++) 515 for (i=0;i<lexBuf.lexModeStackTop;i++)
516 if (mode == lexBuf.lexModeStack[i]) return 1; 516 if (mode == lexBuf.lexModeStack[i]) return 1;
517 return 0; 517 return 0;
518 } 518 }
519 519
520static char lexGetc_() 520static int lexGetc_()
521 { 521 {
522 /* get next char from input, no buffering. */ 522 /* get next char from input, no buffering. */
523 if (lexBuf.curPos == lexBuf.inputLen) 523 if (lexBuf.curPos == lexBuf.inputLen)
524 return EOF; 524 return EOF;
525 else if (lexBuf.inputString) 525 else if (lexBuf.inputString)
526 return *(lexBuf.inputString + lexBuf.curPos++); 526 return *(lexBuf.inputString + lexBuf.curPos++);
527 else { 527 else {
528#ifdef INCLUDEMFC 528#ifdef INCLUDEMFC
529 char result; 529 char result;
530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF; 530 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
531#else 531#else
532 return fgetc(lexBuf.inputFile); 532 return fgetc(lexBuf.inputFile);
533#endif 533#endif
534 } 534 }
535 } 535 }
536 536
537static int lexGeta() 537static int lexGeta()
538 { 538 {
539 ++lexBuf.len; 539 ++lexBuf.len;
540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); 540 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
541 } 541 }
542 542
543static int lexGeta_(int i) 543static int lexGeta_(int i)
544 { 544 {
545 ++lexBuf.len; 545 ++lexBuf.len;
546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); 546 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
547 } 547 }
548 548
549static void lexSkipLookahead() { 549static void lexSkipLookahead() {
550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 550 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
551 /* don't skip EOF. */ 551 /* don't skip EOF. */
552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 552 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
553 lexBuf.len--; 553 lexBuf.len--;
554 } 554 }
555 } 555 }
556 556
557static int lexLookahead() { 557static int lexLookahead() {
558 int c = (lexBuf.len)? 558 int c = (lexBuf.len)?
559 lexBuf.buf[lexBuf.getPtr]: 559 lexBuf.buf[lexBuf.getPtr]:
560 lexGeta(); 560 lexGeta();
561 /* do the \r\n -> \n or \r -> \n translation here */ 561 /* do the \r\n -> \n or \r -> \n translation here */
562 if (c == '\r') { 562 if (c == '\r') {
563 int a = (lexBuf.len>1)? 563 int a = (lexBuf.len>1)?
564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: 564 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
565 lexGeta_(1); 565 lexGeta_(1);
566 if (a == '\n') { 566 if (a == '\n') {
567 lexSkipLookahead(); 567 lexSkipLookahead();
568 } 568 }
569 lexBuf.buf[lexBuf.getPtr] = c = '\n'; 569 lexBuf.buf[lexBuf.getPtr] = c = '\n';
570 } 570 }
571 else if (c == '\n') { 571 else if (c == '\n') {
572 int a = (lexBuf.len>1)? 572 int a = (lexBuf.len>1)?
573 lexBuf.buf[lexBuf.getPtr+1]: 573 lexBuf.buf[lexBuf.getPtr+1]:
574 lexGeta_(1); 574 lexGeta_(1);
575 if (a == '\r') { 575 if (a == '\r') {
576 lexSkipLookahead(); 576 lexSkipLookahead();
577 } 577 }
578 lexBuf.buf[lexBuf.getPtr] = '\n'; 578 lexBuf.buf[lexBuf.getPtr] = '\n';
579 } 579 }
580 return c; 580 return c;
581 } 581 }
582 582
583static int lexGetc() { 583static int lexGetc() {
584 int c = lexLookahead(); 584 int c = lexLookahead();
585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 585 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
586 /* EOF will remain in lookahead buffer */ 586 /* EOF will remain in lookahead buffer */
587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 587 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
588 lexBuf.len--; 588 lexBuf.len--;
589 } 589 }
590 return c; 590 return c;
591 } 591 }
592 592
593static void lexSkipLookaheadWord() { 593static void lexSkipLookaheadWord() {
594 if (lexBuf.strsLen <= lexBuf.len) { 594 if (lexBuf.strsLen <= lexBuf.len) {
595 lexBuf.len -= lexBuf.strsLen; 595 lexBuf.len -= lexBuf.strsLen;
596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; 596 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
597 } 597 }
598 } 598 }
599 599
600static void lexClearToken() 600static void lexClearToken()
601 { 601 {
602 lexBuf.strsLen = 0; 602 lexBuf.strsLen = 0;
603 } 603 }
604 604
605static void lexAppendc(int c) 605static void lexAppendc(int c)
606 { 606 {
607 lexBuf.strs[lexBuf.strsLen] = c; 607 lexBuf.strs[lexBuf.strsLen] = c;
608 /* append up to zero termination */ 608 /* append up to zero termination */
609 if (c == 0) return; 609 if (c == 0) return;
610 lexBuf.strsLen++; 610 lexBuf.strsLen++;
611 if (lexBuf.strsLen > lexBuf.maxToken) { 611 if (lexBuf.strsLen > lexBuf.maxToken) {
612 /* double the token string size */ 612 /* double the token string size */
613 lexBuf.maxToken <<= 1; 613 lexBuf.maxToken <<= 1;
614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); 614 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
615 } 615 }
616 } 616 }
617 617
618static char* lexStr() { 618static char* lexStr() {
619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); 619 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
620 } 620 }
621 621
622static void lexSkipWhite() { 622static void lexSkipWhite() {
623 int c = lexLookahead(); 623 int c = lexLookahead();
624 while (c == ' ' || c == '\t') { 624 while (c == ' ' || c == '\t') {
625 lexSkipLookahead(); 625 lexSkipLookahead();
626 c = lexLookahead(); 626 c = lexLookahead();
627 } 627 }
628 } 628 }
629 629
630static char* lexGetWord() { 630static char* lexGetWord() {
631 int c; 631 int c;
632 lexSkipWhite(); 632 lexSkipWhite();
633 lexClearToken(); 633 lexClearToken();
634 c = lexLookahead(); 634 c = lexLookahead();
635 while (c != EOF && !strchr("\t\n ;:=",c)) { 635 while (c != EOF && !strchr("\t\n ;:=",c)) {
636 lexAppendc(c); 636 lexAppendc(c);
637 lexSkipLookahead(); 637 lexSkipLookahead();
638 c = lexLookahead(); 638 c = lexLookahead();
639 } 639 }
640 lexAppendc(0); 640 lexAppendc(0);
641 return lexStr(); 641 return lexStr();
642 } 642 }
643 643
644static void lexPushLookaheadc(int c) { 644static void lexPushLookaheadc(int c) {
645 int putptr; 645 int putptr;
646 /* can't putback EOF, because it never leaves lookahead buffer */ 646 /* can't putback EOF, because it never leaves lookahead buffer */
647 if (c == EOF) return; 647 if (c == EOF) return;
648 putptr = (int)lexBuf.getPtr - 1; 648 putptr = (int)lexBuf.getPtr - 1;
649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; 649 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
650 lexBuf.getPtr = putptr; 650 lexBuf.getPtr = putptr;
651 lexBuf.buf[putptr] = c; 651 lexBuf.buf[putptr] = c;
652 lexBuf.len += 1; 652 lexBuf.len += 1;
653 } 653 }
654 654
655static char* lexLookaheadWord() { 655static char* lexLookaheadWord() {
656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 656 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
657 / and thing bigger than that will stop the lookahead and return 0; 657 / and thing bigger than that will stop the lookahead and return 0;
658 / leading white spaces are not recoverable. 658 / leading white spaces are not recoverable.
659 */ 659 */
660 int c; 660 int c;
661 int len = 0; 661 int len = 0;
662 int curgetptr = 0; 662 int curgetptr = 0;
663 lexSkipWhite(); 663 lexSkipWhite();
664 lexClearToken(); 664 lexClearToken();
665 curgetptr = (int)lexBuf.getPtr;// remember! 665 curgetptr = (int)lexBuf.getPtr;// remember!
666 while (len < (MAX_LEX_LOOKAHEAD_0)) { 666 while (len < (MAX_LEX_LOOKAHEAD_0)) {
667 c = lexGetc(); 667 c = lexGetc();
668 len++; 668 len++;
669 if (c == EOF || strchr("\t\n ;:=", c)) { 669 if (c == EOF || strchr("\t\n ;:=", c)) {
670 lexAppendc(0); 670 lexAppendc(0);
671 /* restore lookahead buf. */ 671 /* restore lookahead buf. */
672 lexBuf.len += len; 672 lexBuf.len += len;
673 lexBuf.getPtr = curgetptr; 673 lexBuf.getPtr = curgetptr;
674 return lexStr(); 674 return lexStr();
675 } 675 }
676 else 676 else
677 lexAppendc(c); 677 lexAppendc(c);
678 } 678 }
679 lexBuf.len += len;/* char that has been moved to lookahead buffer */ 679 lexBuf.len += len;/* char that has been moved to lookahead buffer */
680 lexBuf.getPtr = curgetptr; 680 lexBuf.getPtr = curgetptr;
681 return 0; 681 return 0;
682 } 682 }
683 683
684#ifdef _SUPPORT_LINE_FOLDING 684#ifdef _SUPPORT_LINE_FOLDING
685static void handleMoreRFC822LineBreak(int c) { 685static void handleMoreRFC822LineBreak(int c) {
686 /* suport RFC 822 line break in cases like 686 /* suport RFC 822 line break in cases like
687 *ADR: foo; 687 *ADR: foo;
688 * morefoo; 688 * morefoo;
689 * more foo; 689 * more foo;
690 */ 690 */
691 if (c == ';') { 691 if (c == ';') {
692 int a; 692 int a;
693 lexSkipLookahead(); 693 lexSkipLookahead();
694 /* skip white spaces */ 694 /* skip white spaces */
695 a = lexLookahead(); 695 a = lexLookahead();
696 while (a == ' ' || a == '\t') { 696 while (a == ' ' || a == '\t') {
697 lexSkipLookahead(); 697 lexSkipLookahead();
698 a = lexLookahead(); 698 a = lexLookahead();
699 } 699 }
700 if (a == '\n') { 700 if (a == '\n') {
701 lexSkipLookahead(); 701 lexSkipLookahead();
702 a = lexLookahead(); 702 a = lexLookahead();
703 if (a == ' ' || a == '\t') { 703 if (a == ' ' || a == '\t') {
704 /* continuation, throw away all the \n and spaces read so 704 /* continuation, throw away all the \n and spaces read so
705 * far 705 * far
706 */ 706 */
707 lexSkipWhite(); 707 lexSkipWhite();
708 lexPushLookaheadc(';'); 708 lexPushLookaheadc(';');
709 } 709 }
710 else { 710 else {
711 lexPushLookaheadc('\n'); 711 lexPushLookaheadc('\n');
712 lexPushLookaheadc(';'); 712 lexPushLookaheadc(';');
713 } 713 }
714 } 714 }
715 else { 715 else {
716 lexPushLookaheadc(';'); 716 lexPushLookaheadc(';');
717 } 717 }
718 } 718 }
719 } 719 }
720 720
721static char* lexGet1Value() { 721static char* lexGet1Value() {
722 int c; 722 int c;
723 lexSkipWhite(); 723 lexSkipWhite();
724 c = lexLookahead(); 724 c = lexLookahead();
725 lexClearToken(); 725 lexClearToken();
726 while (c != EOF && c != ';') { 726 while (c != EOF && c != ';') {
727 if (c == '\\' ) { 727 if (c == '\\' ) {
728 int a; 728 int a;
729 lexSkipLookahead(); 729 lexSkipLookahead();
730 a = lexLookahead(); 730 a = lexLookahead();
731 if ( a != ';' ) { 731 if ( a != ';' ) {
732 lexAppendc('\\'); 732 lexAppendc('\\');
733 } else { 733 } else {
734 lexAppendc( ';' ); 734 lexAppendc( ';' );
735 lexSkipLookahead(); 735 lexSkipLookahead();
736 } 736 }
737 } else if (c == '\n') { 737 } else if (c == '\n') {
738 int a; 738 int a;
739 lexSkipLookahead(); 739 lexSkipLookahead();
740 a = lexLookahead(); 740 a = lexLookahead();
741 if (a == ' ' || a == '\t') { 741 if (a == ' ' || a == '\t') {
742 lexAppendc(' '); 742 lexAppendc(' ');
743 lexSkipLookahead(); 743 lexSkipLookahead();
744 } 744 }
745 else { 745 else {
746 lexPushLookaheadc('\n'); 746 lexPushLookaheadc('\n');
747 break; 747 break;
748 } 748 }
749 } 749 }
750 else { 750 else {
751 lexAppendc(c); 751 lexAppendc(c);
752 lexSkipLookahead(); 752 lexSkipLookahead();
753 } 753 }
754 c = lexLookahead(); 754 c = lexLookahead();
755 } 755 }
756 lexAppendc(0); 756 lexAppendc(0);
757 handleMoreRFC822LineBreak(c); 757 handleMoreRFC822LineBreak(c);
758 return c==EOF?0:lexStr(); 758 return c==EOF?0:lexStr();
759 } 759 }
760#endif 760#endif
761 761
762static int match_begin_name(int end) { 762static int match_begin_name(int end) {
763 char *n = lexLookaheadWord(); 763 char *n = lexLookaheadWord();
764 int token = ID; 764 int token = ID;
765 if (n) { 765 if (n) {
766 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; 766 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
767 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; 767 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
768 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; 768 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
769 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; 769 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
770 deleteStr(n); 770 deleteStr(n);
771 return token; 771 return token;
772 } 772 }
773 return 0; 773 return 0;
774 } 774 }
775 775
776 776
777#ifdef INCLUDEMFC 777#ifdef INCLUDEMFC
778void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile) 778void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
779#else 779#else
780void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) 780void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
781#endif 781#endif
782 { 782 {
783 // initialize lex mode stack 783 // initialize lex mode stack
784 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; 784 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
785 785
786 // iniatialize lex buffer. 786 // iniatialize lex buffer.
787 lexBuf.inputString = (char*) inputstring; 787 lexBuf.inputString = (char*) inputstring;
788 lexBuf.inputLen = inputlen; 788 lexBuf.inputLen = inputlen;
789 lexBuf.curPos = 0; 789 lexBuf.curPos = 0;
790 lexBuf.inputFile = inputfile; 790 lexBuf.inputFile = inputfile;
791 791
792 lexBuf.len = 0; 792 lexBuf.len = 0;
793 lexBuf.getPtr = 0; 793 lexBuf.getPtr = 0;
794 794
795 lexBuf.maxToken = MAXTOKEN; 795 lexBuf.maxToken = MAXTOKEN;
796 lexBuf.strs = (char*)malloc(MAXTOKEN); 796 lexBuf.strs = (char*)malloc(MAXTOKEN);
797 lexBuf.strsLen = 0; 797 lexBuf.strsLen = 0;
798 798
799 } 799 }
800 800
801static void finiLex() { 801static void finiLex() {
802 free(lexBuf.strs); 802 free(lexBuf.strs);
803 } 803 }
804 804
805 805
806/*-----------------------------------*/ 806/*-----------------------------------*/
807/* This parses and converts the base64 format for binary encoding into 807/* This parses and converts the base64 format for binary encoding into
808 * a decoded buffer (allocated with new). See RFC 1521. 808 * a decoded buffer (allocated with new). See RFC 1521.
809 */ 809 */
810static char * lexGetDataFromBase64() 810static char * lexGetDataFromBase64()
811 { 811 {
812 unsigned long bytesLen = 0, bytesMax = 0; 812 unsigned long bytesLen = 0, bytesMax = 0;
813 int quadIx = 0, pad = 0; 813 int quadIx = 0, pad = 0;
814 unsigned long trip = 0; 814 unsigned long trip = 0;
815 unsigned char b; 815 unsigned char b;
816 int c; 816 int c;
817 unsigned char *bytes = NULL; 817 unsigned char *bytes = NULL;
818 unsigned char *oldBytes = NULL; 818 unsigned char *oldBytes = NULL;
819 819
820 DBG_(("db: lexGetDataFromBase64\n")); 820 DBG_(("db: lexGetDataFromBase64\n"));
821 while (1) { 821 while (1) {
822 c = lexGetc(); 822 c = lexGetc();
823 if (c == '\n') { 823 if (c == '\n') {
824 ++mime_lineNum; 824 ++mime_lineNum;
825 if (lexLookahead() == '\n') { 825 if (lexLookahead() == '\n') {
826 /* a '\n' character by itself means end of data */ 826 /* a '\n' character by itself means end of data */
827 break; 827 break;
828 } 828 }
829 else continue; /* ignore '\n' */ 829 else continue; /* ignore '\n' */
830 } 830 }
831 else { 831 else {
832 if ((c >= 'A') && (c <= 'Z')) 832 if ((c >= 'A') && (c <= 'Z'))
833 b = (unsigned char)(c - 'A'); 833 b = (unsigned char)(c - 'A');
834 else if ((c >= 'a') && (c <= 'z')) 834 else if ((c >= 'a') && (c <= 'z'))
835 b = (unsigned char)(c - 'a') + 26; 835 b = (unsigned char)(c - 'a') + 26;
836 else if ((c >= '0') && (c <= '9')) 836 else if ((c >= '0') && (c <= '9'))
837 b = (unsigned char)(c - '0') + 52; 837 b = (unsigned char)(c - '0') + 52;
838 else if (c == '+') 838 else if (c == '+')
839 b = 62; 839 b = 62;
840 else if (c == '/') 840 else if (c == '/')
841 b = 63; 841 b = 63;
842 else if (c == '=') { 842 else if (c == '=') {
843 b = 0; 843 b = 0;
844 pad++; 844 pad++;
845 } else if ((c == ' ') || (c == '\t')) { 845 } else if ((c == ' ') || (c == '\t')) {
846 continue; 846 continue;
847 } else { /* error condition */ 847 } else { /* error condition */
848 if (bytes) free(bytes); 848 if (bytes) free(bytes);
849 else if (oldBytes) free(oldBytes); 849 else if (oldBytes) free(oldBytes);
850 // error recovery: skip until 2 adjacent newlines. 850 // error recovery: skip until 2 adjacent newlines.
851 DBG_(("db: invalid character 0x%x '%c'\n", c,c)); 851 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
852 if (c != EOF) { 852 if (c != EOF) {
853 c = lexGetc(); 853 c = lexGetc();
854 while (c != EOF) { 854 while (c != EOF) {
855 if (c == '\n' && lexLookahead() == '\n') { 855 if (c == '\n' && lexLookahead() == '\n') {
856 ++mime_lineNum; 856 ++mime_lineNum;
857 break; 857 break;
858 } 858 }
859 c = lexGetc(); 859 c = lexGetc();
860 } 860 }
861 } 861 }
862 return NULL; 862 return NULL;
863 } 863 }
864 trip = (trip << 6) | b; 864 trip = (trip << 6) | b;
865 if (++quadIx == 4) { 865 if (++quadIx == 4) {
866 unsigned char outBytes[3]; 866 unsigned char outBytes[3];
867 int numOut; 867 int numOut;
868 int i; 868 int i;
869 for (i = 0; i < 3; i++) { 869 for (i = 0; i < 3; i++) {
870 outBytes[2-i] = (unsigned char)(trip & 0xFF); 870 outBytes[2-i] = (unsigned char)(trip & 0xFF);
871 trip >>= 8; 871 trip >>= 8;
872 } 872 }
873 numOut = 3 - pad; 873 numOut = 3 - pad;
874 if (bytesLen + numOut > bytesMax) { 874 if (bytesLen + numOut > bytesMax) {
875 if (!bytes) { 875 if (!bytes) {
876 bytesMax = 1024; 876 bytesMax = 1024;
877 bytes = (unsigned char*)malloc((size_t)bytesMax); 877 bytes = (unsigned char*)malloc((size_t)bytesMax);
878 } 878 }
879 else { 879 else {
880 bytesMax <<= 2; 880 bytesMax <<= 2;
881 oldBytes = bytes; 881 oldBytes = bytes;
882 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); 882 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
883 } 883 }
884 if (bytes == 0) { 884 if (bytes == 0) {
885 mime_error("out of memory while processing BASE64 data\n"); 885 mime_error("out of memory while processing BASE64 data\n");
886 } 886 }
887 } 887 }
888 if (bytes) { 888 if (bytes) {
889 memcpy(bytes + bytesLen, outBytes, numOut); 889 memcpy(bytes + bytesLen, outBytes, numOut);
890 bytesLen += numOut; 890 bytesLen += numOut;
891 } 891 }
892 trip = 0; 892 trip = 0;
893 quadIx = 0; 893 quadIx = 0;
894 } 894 }
895 } 895 }
896 } /* while */ 896 } /* while */
897 DBG_(("db: bytesLen = %d\n", bytesLen)); 897 DBG_(("db: bytesLen = %d\n", bytesLen));
898 /* kludge: all this won't be necessary if we have tree form 898 /* kludge: all this won't be necessary if we have tree form
899 representation */ 899 representation */
900 if (bytes) { 900 if (bytes) {
901 setValueWithSize(curProp,bytes,(unsigned int)bytesLen); 901 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
902 free(bytes); 902 free(bytes);
903 } 903 }
904 else if (oldBytes) { 904 else if (oldBytes) {
905 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); 905 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
906 free(oldBytes); 906 free(oldBytes);
907 } 907 }
908 return 0; 908 return 0;
909 } 909 }
910 910
911static int match_begin_end_name(int end) { 911static int match_begin_end_name(int end) {
912 int token; 912 int token;
913 lexSkipWhite(); 913 lexSkipWhite();
914 if (lexLookahead() != ':') return ID; 914 if (lexLookahead() != ':') return ID;
915 lexSkipLookahead(); 915 lexSkipLookahead();
916 lexSkipWhite(); 916 lexSkipWhite();
917 token = match_begin_name(end); 917 token = match_begin_name(end);
918 if (token == ID) { 918 if (token == ID) {
919 lexPushLookaheadc(':'); 919 lexPushLookaheadc(':');
920 DBG_(("db: ID '%s'\n", yylval.str)); 920 DBG_(("db: ID '%s'\n", yylval.str));
921 return ID; 921 return ID;
922 } 922 }
923 else if (token != 0) { 923 else if (token != 0) {
924 lexSkipLookaheadWord(); 924 lexSkipLookaheadWord();
925 deleteStr(yylval.str); 925 deleteStr(yylval.str);
926 DBG_(("db: begin/end %d\n", token)); 926 DBG_(("db: begin/end %d\n", token));
927 return token; 927 return token;
928 } 928 }
929 return 0; 929 return 0;
930 } 930 }
931 931
932static char* lexGetQuotedPrintable() 932static char* lexGetQuotedPrintable()
933 { 933{
934 char cur; 934 int c;
935 935 lexSkipWhite();
936 lexClearToken(); 936 c = lexLookahead();
937 do { 937 lexClearToken();
938 cur = lexGetc(); 938
939 switch (cur) { 939 while (c != EOF && c != ';') {
940 case '=': { 940 if (c == '\n') {
941 int c = 0; 941 // break, leave '\n' on remaining chars.
942 int next[2]; 942 break;
943 int i; 943 } else if (c == '=') {
944 for (i = 0; i < 2; i++) { 944 int cur = 0;
945 next[i] = lexGetc(); 945 int next;
946 if (next[i] >= '0' && next[i] <= '9') 946
947 c = c * 16 + next[i] - '0'; 947 lexSkipLookahead(); // skip '='
948 else if (next[i] >= 'A' && next[i] <= 'F') 948 next = lexLookahead();
949 c = c * 16 + next[i] - 'A' + 10; 949
950 else 950 if (next == '\n') {
951 break; 951 // skip and only skip the \n
952 } 952 lexSkipLookahead();
953 if (i == 0) { 953 c = lexLookahead();
954 /* single '=' follow by LINESEP is continuation sign? */ 954 ++mime_lineNum; // aid in error reporting
955 if (next[0] == '\n') { 955 continue;
956 ++mime_lineNum; 956 } else if (next >= '0' && next <= '9') {
957 } 957 cur = next - '0';
958 else { 958 } else if (next >= 'A' && next <= 'F') {
959 lexPushLookaheadc('='); 959 cur = next - 'A' + 10;
960 goto EndString; 960 } else {
961 } 961 // we have been sent buggy stuff. doesn't matter
962 } 962 // what we do so long as we keep going.
963 else if (i == 1) { 963 // should probably spit an error here
964 lexPushLookaheadc(next[1]); 964 c = lexLookahead();
965 lexPushLookaheadc(next[0]); 965 continue;
966 lexAppendc('='); 966 }
967 } else { 967
968 lexAppendc(c); 968 lexSkipLookahead(); // skip A-Z0-9
969 } 969 next = lexLookahead();
970 break; 970
971 } /* '=' */ 971 cur = cur * 16;
972 case '\n': { 972 // this time really just expecting 0-9A-F
973 lexPushLookaheadc('\n'); 973 if (next >= '0' && next <= '9') {
974 goto EndString; 974 cur += next - '0';
975 } 975 } else if (next >= 'A' && next <= 'F') {
976 case (char)EOF: 976 cur += next - 'A' + 10;
977 break; 977 } else {
978 default: 978 // we have been sent buggy stuff. doesn't matter
979 lexAppendc(cur); 979 // what we do so long as we keep going.
980 break; 980 // should probably spit an error here
981 } /* switch */ 981 c = lexLookahead();
982 } while (cur != (char)EOF); 982 continue;
983 983 }
984EndString: 984
985 lexAppendc(0); 985 // got a valid escaped =. append it.
986 return lexStr(); 986 lexSkipLookahead(); // skip second 0-9A-F
987 } /* LexQuotedPrintable */ 987 lexAppendc(cur);
988 988 } else {
989static int yylex() { 989 lexSkipLookahead(); // skip whatever we just read.
990 990 lexAppendc(c); // and append it.
991 int lexmode = LEXMODE(); 991 }
992 if (lexmode == L_VALUES) { 992 c = lexLookahead();
993 int c = lexGetc(); 993 }
994 if (c == ';') { 994 lexAppendc(0);
995 DBG_(("db: SEMICOLON\n")); 995 return c==EOF?0:lexStr();
996 lexPushLookaheadc(c); 996}
997 handleMoreRFC822LineBreak(c); 997
998 lexSkipLookahead(); 998static int yylex() {
999 return SEMICOLON; 999
1000 } 1000 int lexmode = LEXMODE();
1001 else if (strchr("\n",c)) { 1001 if (lexmode == L_VALUES) {
1002 ++mime_lineNum; 1002 int c = lexGetc();
1003 /* consume all line separator(s) adjacent to each other */ 1003 if (c == ';') {
1004 c = lexLookahead(); 1004 DBG_(("db: SEMICOLON\n"));
1005 while (strchr("\n",c)) { 1005 lexPushLookaheadc(c);
1006 lexSkipLookahead(); 1006 handleMoreRFC822LineBreak(c);
1007 c = lexLookahead(); 1007 lexSkipLookahead();
1008 ++mime_lineNum; 1008 return SEMICOLON;
1009 } 1009 }
1010 DBG_(("db: LINESEP\n")); 1010 else if (strchr("\n",c)) {
1011 return LINESEP; 1011 ++mime_lineNum;
1012 } 1012 /* consume all line separator(s) adjacent to each other */
1013 else { 1013 c = lexLookahead();
1014 char *p = 0; 1014 while (strchr("\n",c)) {
1015 lexPushLookaheadc(c); 1015 lexSkipLookahead();
1016 if (lexWithinMode(L_BASE64)) { 1016 c = lexLookahead();
1017 /* get each char and convert to bin on the fly... */ 1017 ++mime_lineNum;
1018 p = lexGetDataFromBase64(); 1018 }
1019 yylval.str = p; 1019 DBG_(("db: LINESEP\n"));
1020 return STRING; 1020 return LINESEP;
1021 } 1021 }
1022 else if (lexWithinMode(L_QUOTED_PRINTABLE)) { 1022 else {
1023 p = lexGetQuotedPrintable(); 1023 char *p = 0;
1024 } 1024 lexPushLookaheadc(c);
1025 else { 1025 if (lexWithinMode(L_BASE64)) {
1026#ifdef _SUPPORT_LINE_FOLDING 1026 /* get each char and convert to bin on the fly... */
1027 p = lexGet1Value(); 1027 p = lexGetDataFromBase64();
1028#else 1028 yylval.str = p;
1029 p = lexGetStrUntil(";\n"); 1029 return STRING;
1030#endif 1030 }
1031 } 1031 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1032 if (p) { 1032 p = lexGetQuotedPrintable();
1033 DBG_(("db: STRING: '%s'\n", p)); 1033 }
1034 yylval.str = p; 1034 else {
1035 return STRING; 1035#ifdef _SUPPORT_LINE_FOLDING
1036 } 1036 p = lexGet1Value();
1037 else return 0; 1037#else
1038 } 1038 p = lexGetStrUntil(";\n");
1039 } 1039#endif
1040 else { 1040 }
1041 /* normal mode */ 1041 if (p) {
1042 while (1) { 1042 DBG_(("db: STRING: '%s'\n", p));
1043 int c = lexGetc(); 1043 yylval.str = p;
1044 switch(c) { 1044 return STRING;
1045 case ':': { 1045 }
1046 /* consume all line separator(s) adjacent to each other */ 1046 else return 0;
1047 /* ignoring linesep immediately after colon. */ 1047 }
1048 c = lexLookahead(); 1048 }
1049 while (strchr("\n",c)) { 1049 else {
1050 lexSkipLookahead(); 1050 /* normal mode */
1051 c = lexLookahead(); 1051 while (1) {
1052 ++mime_lineNum; 1052 int c = lexGetc();
1053 } 1053 switch(c) {
1054 DBG_(("db: COLON\n")); 1054 case ':': {
1055 return COLON; 1055 /* consume all line separator(s) adjacent to each other */
1056 } 1056 /* ignoring linesep immediately after colon. */
1057 case ';': 1057 c = lexLookahead();
1058 DBG_(("db: SEMICOLON\n")); 1058 while (strchr("\n",c)) {
1059 return SEMICOLON; 1059 lexSkipLookahead();
1060 case '=': 1060 c = lexLookahead();
1061 DBG_(("db: EQ\n")); 1061 ++mime_lineNum;
1062 return EQ; 1062 }
1063 /* ignore whitespace in this mode */ 1063 DBG_(("db: COLON\n"));
1064 case '\t': 1064 return COLON;
1065 case ' ': continue; 1065 }
1066 case '\n': { 1066 case ';':
1067 ++mime_lineNum; 1067 DBG_(("db: SEMICOLON\n"));
1068 continue; 1068 return SEMICOLON;
1069 } 1069 case '=':
1070 case EOF: return 0; 1070 DBG_(("db: EQ\n"));
1071 break; 1071 return EQ;
1072 default: { 1072 /* ignore whitespace in this mode */
1073 lexPushLookaheadc(c); 1073 case '\t':
1074 if (isalnum(c)) { 1074 case ' ': continue;
1075 char *t = lexGetWord(); 1075 case '\n': {
1076 yylval.str = t; 1076 ++mime_lineNum;
1077 if (!qstricmp(t, "begin")) { 1077 continue;
1078 return match_begin_end_name(0); 1078 }
1079 } 1079 case EOF: return 0;
1080 else if (!qstricmp(t,"end")) { 1080 break;
1081 return match_begin_end_name(1); 1081 default: {
1082 } 1082 lexPushLookaheadc(c);
1083 else { 1083 if (isalnum(c)) {
1084 DBG_(("db: ID '%s'\n", t)); 1084 char *t = lexGetWord();
1085 return ID; 1085 yylval.str = t;
1086 } 1086 if (!qstricmp(t, "begin")) {
1087 } 1087 return match_begin_end_name(0);
1088 else { 1088 }
1089 /* unknow token */ 1089 else if (!qstricmp(t,"end")) {
1090 return 0; 1090 return match_begin_end_name(1);
1091 } 1091 }
1092 break; 1092 else {
1093 } 1093 DBG_(("db: ID '%s'\n", t));
1094 } 1094 return ID;
1095 } 1095 }
1096 } 1096 }
1097 return 0; 1097 else {
1098 } 1098 /* unknow token */
1099 1099 return 0;
1100 1100 }
1101/***************************************************************************/ 1101 break;
1102 /*** Public Functions ****/ 1102 }
1103/***************************************************************************/ 1103 }
1104 1104 }
1105static VObject* Parse_MIMEHelper() 1105 }
1106 { 1106 return 0;
1107 ObjStackTop = -1; 1107 }
1108 mime_numErrors = 0; 1108
1109 mime_lineNum = 1; 1109
1110 vObjList = 0; 1110/***************************************************************************/
1111 curObj = 0; 1111 /*** Public Functions ****/
1112 1112/***************************************************************************/
1113 if (yyparse() != 0) 1113
1114 return 0; 1114static VObject* Parse_MIMEHelper()
1115 1115 {
1116 finiLex(); 1116 ObjStackTop = -1;
1117 return vObjList; 1117 mime_numErrors = 0;
1118 } 1118 mime_lineNum = 1;
1119 1119 vObjList = 0;
1120/*--------------------------------------------*/ 1120 curObj = 0;
1121DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) 1121
1122 { 1122 if (yyparse() != 0)
1123 initLex(input, len, 0); 1123 return 0;
1124 return Parse_MIMEHelper(); 1124
1125 } 1125 finiLex();
1126 1126 return vObjList;
1127 1127 }
1128#if INCLUDEMFC 1128
1129 1129/*--------------------------------------------*/
1130DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file) 1130DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
1131 { 1131 {
1132 unsigned long startPos; 1132 initLex(input, len, 0);
1133 VObject *result; 1133 return Parse_MIMEHelper();
1134 1134 }
1135 initLex(0,-1,file); 1135
1136 startPos = file->GetPosition(); 1136
1137 if (!(result = Parse_MIMEHelper())) 1137#if INCLUDEMFC
1138 file->Seek(startPos, CFile::begin); 1138
1139 return result; 1139DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
1140 } 1140 {
1141 1141 unsigned long startPos;
1142#else 1142 VObject *result;
1143 1143
1144VObject* Parse_MIME_FromFile(FILE *file) 1144 initLex(0,-1,file);
1145 { 1145 startPos = file->GetPosition();
1146 VObject *result; 1146 if (!(result = Parse_MIMEHelper()))
1147 long startPos; 1147 file->Seek(startPos, CFile::begin);
1148 1148 return result;
1149 initLex(0,(unsigned long)-1,file); 1149 }
1150 startPos = ftell(file); 1150
1151 if (!(result = Parse_MIMEHelper())) { 1151#else
1152 fseek(file,startPos,SEEK_SET); 1152
1153 } 1153VObject* Parse_MIME_FromFile(FILE *file)
1154 return result; 1154 {
1155 } 1155 VObject *result;
1156 1156 long startPos;
1157DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) 1157
1158 { 1158 initLex(0,(unsigned long)-1,file);
1159 FILE *fp = fopen(fname,"r"); 1159 startPos = ftell(file);
1160 if (fp) { 1160 if (!(result = Parse_MIMEHelper())) {
1161 VObject* o = Parse_MIME_FromFile(fp); 1161 fseek(file,startPos,SEEK_SET);
1162 fclose(fp); 1162 }
1163 return o; 1163 return result;
1164 } 1164 }
1165 else { 1165
1166 char msg[80]; 1166DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
1167 sprintf(msg, "can't open file '%s' for reading\n", fname); 1167 {
1168 mime_error_(msg); 1168 FILE *fp = fopen(fname,"r");
1169 return 0; 1169 if (fp) {
1170 } 1170 VObject* o = Parse_MIME_FromFile(fp);
1171 } 1171 fclose(fp);
1172 1172 return o;
1173#endif 1173 }
1174 1174 else {
1175/*-------------------------------------*/ 1175 char msg[80];
1176 1176 sprintf(msg, "can't open file '%s' for reading\n", fname);
1177static MimeErrorHandler mimeErrorHandler; 1177 mime_error_(msg);
1178 1178 return 0;
1179DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) 1179 }
1180 { 1180 }
1181 mimeErrorHandler = me; 1181
1182 } 1182#endif
1183 1183
1184void mime_error(char *s) 1184/*-------------------------------------*/
1185 { 1185
1186 char msg[256]; 1186static MimeErrorHandler mimeErrorHandler;
1187 if (mimeErrorHandler) { 1187
1188 sprintf(msg,"%s at line %d", s, mime_lineNum); 1188DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
1189 mimeErrorHandler(msg); 1189 {
1190 } 1190 mimeErrorHandler = me;
1191 } 1191 }
1192 1192
1193void mime_error_(char *s) 1193void mime_error(char *s)
1194 { 1194 {
1195 if (mimeErrorHandler) { 1195 char msg[256];
1196 mimeErrorHandler(s); 1196 if (mimeErrorHandler) {
1197 } 1197 sprintf(msg,"%s at line %d", s, mime_lineNum);
1198 } 1198 mimeErrorHandler(msg);
1199 1199 }
1200 }
1201
1202void mime_error_(char *s)
1203 {
1204 if (mimeErrorHandler) {
1205 mimeErrorHandler(s);
1206 }
1207 }
1208
diff --git a/library/backend/vcc_yacc.cpp b/library/backend/vcc_yacc.cpp
index cb24631..19a108f 100644
--- a/library/backend/vcc_yacc.cpp
+++ b/library/backend/vcc_yacc.cpp
@@ -1,706 +1,732 @@
1#ifndef lint 1#ifndef lint
2 static char yysccsid[] = "@(#)yaccpar1.9 (Berkeley) 02/21/93"; 2 /*static char yysccsid[] = "from: @(#)yaccpar1.9 (Berkeley) 02/21/93";*/
3static char yyrcsid[] = "$Id$";
3#endif 4#endif
4#define YYBYACC 1 5#define YYBYACC 1
5#define YYMAJOR 1 6#define YYMAJOR 1
6#define YYMINOR 9 7#define YYMINOR 9
7#define yyclearin (yychar=(-1)) 8#define yyclearin (yychar=(-1))
8#define yyerrok (yyerrflag=0) 9#define yyerrok (yyerrflag=0)
9#define YYRECOVERING (yyerrflag!=0) 10#define YYRECOVERING (yyerrflag!=0)
10#define YYPREFIX "yy" 11#define yyparse vccparse
11#line 1 "vcc.y" 12#define yylex vcclex
13#define yyerror vccerror
14#define yychar vccchar
15#define yyval vccval
16#define yylval vcclval
17#define yydebug vccdebug
18#define yynerrs vccnerrs
19#define yyerrflag vccerrflag
20#define yyss vccss
21#define yyssp vccssp
22#define yyvs vccvs
23#define yyvsp vccvsp
24#define yylhs vcclhs
25#define yylen vcclen
26#define yydefred vccdefred
27#define yydgoto vccdgoto
28#define yysindex vccsindex
29#define yyrindex vccrindex
30#define yygindex vccgindex
31#define yytable vcctable
32#define yycheck vcccheck
33#define yyname vccname
34#define yyrule vccrule
35#define YYPREFIX "vcc"
36#line 1 "backend/vcc.y"
12 37
13 38
14/*************************************************************************** 39/***************************************************************************
15(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 40(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
16Business Machines Corporation and Siemens Rolm Communications Inc. 41Business Machines Corporation and Siemens Rolm Communications Inc.
17 42
18For purposes of this license notice, the term Licensors shall mean, 43For purposes of this license notice, the term Licensors shall mean,
19collectively, Apple Computer, Inc., AT&T Corp., International 44collectively, Apple Computer, Inc., AT&T Corp., International
20Business Machines Corporation and Siemens Rolm Communications Inc. 45Business Machines Corporation and Siemens Rolm Communications Inc.
21The term Licensor shall mean any of the Licensors. 46The term Licensor shall mean any of the Licensors.
22 47
23Subject to acceptance of the following conditions, permission is hereby 48Subject to acceptance of the following conditions, permission is hereby
24granted by Licensors without the need for written agreement and without 49granted by Licensors without the need for written agreement and without
25license or royalty fees, to use, copy, modify and distribute this 50license or royalty fees, to use, copy, modify and distribute this
26software for any purpose. 51software for any purpose.
27 52
28The above copyright notice and the following four paragraphs must be 53The above copyright notice and the following four paragraphs must be
29reproduced in all copies of this software and any software including 54reproduced in all copies of this software and any software including
30this software. 55this software.
31 56
32THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 57THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
33ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 58ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
34MODIFICATIONS. 59MODIFICATIONS.
35 60
36IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 61IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
37INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 62INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
38OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 63OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
39DAMAGE. 64DAMAGE.
40 65
41EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 66EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
42INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 67INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
43IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 68IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44PURPOSE. 69PURPOSE.
45 70
46The software is provided with RESTRICTED RIGHTS. Use, duplication, or 71The software is provided with RESTRICTED RIGHTS. Use, duplication, or
47disclosure by the government are subject to restrictions set forth in 72disclosure by the government are subject to restrictions set forth in
48DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 73DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
49 74
50***************************************************************************/ 75***************************************************************************/
51 76
52/* 77/*
53 * src: vcc.c 78 * src: vcc.c
54 * doc: Parser for vCard and vCalendar. Note that this code is 79 * doc: Parser for vCard and vCalendar. Note that this code is
55 * generated by a yacc parser generator. Generally it should not 80 * generated by a yacc parser generator. Generally it should not
56 * be edited by hand. The real source is vcc.y. The #line directives 81 * be edited by hand. The real source is vcc.y. The #line directives
57 * can be commented out here to make it easier to trace through 82 * can be commented out here to make it easier to trace through
58 * in a debugger. However, if a bug is found it should 83 * in a debugger. However, if a bug is found it should
59 * be fixed in vcc.y and this file regenerated. 84 * be fixed in vcc.y and this file regenerated.
60 */ 85 */
61 86
62 87
63/* debugging utilities */ 88/* debugging utilities */
64#if __DEBUG 89#if __DEBUG
65#define DBG_(x) printf x 90#define DBG_(x) printf x
66#else 91#else
67#define DBG_(x) 92#define DBG_(x)
68#endif 93#endif
69 94
70/**** External Functions ****/ 95/**** External Functions ****/
71 96
72/* assign local name to parser variables and functions so that 97/* assign local name to parser variables and functions so that
73 we can use more than one yacc based parser. 98 we can use more than one yacc based parser.
74*/ 99*/
75 100
101#if 0
76#define yyparse mime_parse 102#define yyparse mime_parse
77#define yylex mime_lex 103#define yylex mime_lex
78#define yyerror mime_error 104#define yyerror mime_error
79#define yychar mime_char 105#define yychar mime_char
80/* #define p_yyval p_mime_val */ 106/* #define p_yyval p_mime_val */
81#undef yyval 107#undef yyval
82#define yyval mime_yyval 108#define yyval mime_yyval
83/* #define p_yylval p_mime_lval */ 109/* #define p_yylval p_mime_lval */
84#undef yylval 110#undef yylval
85#define yylval mime_yylval 111#define yylval mime_yylval
86#define yydebug mime_debug 112#define yydebug mime_debug
87#define yynerrs mime_nerrs 113#define yynerrs mime_nerrs
88#define yyerrflag mime_errflag 114#define yyerrflag mime_errflag
89#define yyss mime_ss 115#define yyss mime_ss
90#define yyssp mime_ssp 116#define yyssp mime_ssp
91#define yyvs mime_vs 117#define yyvs mime_vs
92#define yyvsp mime_vsp 118#define yyvsp mime_vsp
93#define yylhs mime_lhs 119#define yylhs mime_lhs
94#define yylen mime_len 120#define yylen mime_len
95#define yydefred mime_defred 121#define yydefred mime_defred
96#define yydgoto mime_dgoto 122#define yydgoto mime_dgoto
97#define yysindex mime_sindex 123#define yysindex mime_sindex
98#define yyrindex mime_rindex 124#define yyrindex mime_rindex
99#define yygindex mime_gindex 125#define yygindex mime_gindex
100#define yytable mime_table 126#define yytable mime_table
101#define yycheck mime_check 127#define yycheck mime_check
102#define yyname mime_name 128#define yyname mime_name
103#define yyrule mime_rule 129#define yyrule mime_rule
104#ifdef YYPREFIX 130#ifdef YYPREFIX
105#undef YYPREFIX 131#undef YYPREFIX
106#endif 132#endif
107#define YYPREFIX "mime_" 133#define YYPREFIX "mime_"
134#endif
108 135
109 136
110#ifndef _NO_LINE_FOLDING 137#ifndef _NO_LINE_FOLDING
111#define _SUPPORT_LINE_FOLDING 1 138#define _SUPPORT_LINE_FOLDING 1
112#endif 139#endif
113 140
114/* undef below if compile with MFC */ 141/* undef below if compile with MFC */
115/* #define INCLUDEMFC 1 */ 142/* #define INCLUDEMFC 1 */
116 143
117#if defined(WIN32) || defined(_WIN32) 144#if defined(WIN32) || defined(_WIN32)
118#ifdef INCLUDEMFC 145#ifdef INCLUDEMFC
119#include <afx.h> 146#include <afx.h>
120#endif 147#endif
121#endif 148#endif
122 149
123#include <string.h> 150#include <string.h>
124#ifndef __MWERKS__ 151#ifndef __MWERKS__
125#include <stdlib.h> 152#include <stdlib.h>
126#endif 153#endif
127#include <stdio.h> 154#include <stdio.h>
128#include <stdlib.h> 155#include <stdlib.h>
129#include <ctype.h> 156#include <ctype.h>
130 157
131#ifdef PALMTOPCENTER 158/*#ifdef PALMTOPCENTER */
132#include <qpe/vobject_p.h> 159/*#include <qpe/vobject_p.h> */
133#include <qpe/qfiledirect_p.h> 160/*#else */
134#else
135#include "vobject_p.h" 161#include "vobject_p.h"
136#include "qfiledirect_p.h" 162/*#endif */
137#endif
138 163
139/**** Types, Constants ****/ 164/**** Types, Constants ****/
140 165
141 #define YYDEBUG 0/* 1 to compile in some debugging code */ 166 #define YYDEBUG 0/* 1 to compile in some debugging code */
142 #define MAXTOKEN 256/* maximum token (line) length */ 167 #define MAXTOKEN 256/* maximum token (line) length */
143 #define YYSTACKSIZE 100/* ~unref ? 168 #define YYSTACKSIZE 100/* ~unref ? */
144*/
145 #define MAXLEVEL 10/* max # of nested objects parseable */ 169 #define MAXLEVEL 10/* max # of nested objects parseable */
146 /* (includes outermost) */ 170 /* (includes outermost) */
147 171
148 172
149/**** Global Variables ****/ 173/**** Global Variables ****/
150int mime_lineNum, mime_numErrors; /* yyerror() can use these */ 174int mime_lineNum, mime_numErrors; /* yyerror() can use these */
151static VObject* vObjList; 175static VObject* vObjList;
152static VObject *curProp; 176static VObject *curProp;
153static VObject *curObj; 177static VObject *curObj;
154static VObject* ObjStack[MAXLEVEL]; 178static VObject* ObjStack[MAXLEVEL];
155static int ObjStackTop; 179static int ObjStackTop;
156 180
157 181
158/* A helpful utility for the rest of the app. */ 182/* A helpful utility for the rest of the app. */
159#if __CPLUSPLUS__ 183#if __CPLUSPLUS__
160extern "C" { 184extern "C" {
161#endif 185#endif
162 186
163 extern void yyerror(char *s); 187 extern void yyerror(char *s);
164 188
165#if __CPLUSPLUS__ 189#if __CPLUSPLUS__
166 }; 190 };
167#endif 191#endif
168 192
169int yyparse(); 193int yyparse();
170 194
171enum LexMode { 195enum LexMode {
172 L_NORMAL, 196 L_NORMAL,
173 L_VCARD, 197 L_VCARD,
174 L_VCAL, 198 L_VCAL,
175 L_VEVENT, 199 L_VEVENT,
176 L_VTODO, 200 L_VTODO,
177 L_VALUES, 201 L_VALUES,
178 L_BASE64, 202 L_BASE64,
179 L_QUOTED_PRINTABLE 203 L_QUOTED_PRINTABLE
180 }; 204 };
181 205
182/**** Private Forward Declarations ****/ 206/**** Private Forward Declarations ****/
183static int pushVObject(const char *prop); 207static int pushVObject(const char *prop);
184static VObject* popVObject(); 208static VObject* popVObject();
185static void lexPopMode(int top); 209static void lexPopMode(int top);
186static int lexWithinMode(enum LexMode mode); 210static int lexWithinMode(enum LexMode mode);
187static void lexPushMode(enum LexMode mode); 211static void lexPushMode(enum LexMode mode);
188static void enterProps(const char *s); 212static void enterProps(const char *s);
189static void enterAttr(const char *s1, const char *s2); 213static void enterAttr(const char *s1, const char *s2);
190static void enterValues(const char *value); 214static void enterValues(const char *value);
215#define mime_error yyerror
216void mime_error(char *s);
191void mime_error_(char *s); 217void mime_error_(char *s);
192 218
193#line 185 "vcc.y" 219#line 189 "backend/vcc.y"
194typedef union { 220typedef union {
195 char *str; 221 char *str;
196 VObject *vobj; 222 VObject *vobj;
197 } YYSTYPE; 223 } YYSTYPE;
198#line 196 "y.tab.c" 224#line 225 "y.tab.c"
199#define EQ 257 225#define EQ 257
200#define COLON 258 226#define COLON 258
201#define DOT 259 227#define DOT 259
202#define SEMICOLON 260 228#define SEMICOLON 260
203#define SPACE 261 229#define SPACE 261
204#define HTAB 262 230#define HTAB 262
205#define LINESEP 263 231#define LINESEP 263
206#define NEWLINE 264 232#define NEWLINE 264
207#define BEGIN_VCARD 265 233#define BEGIN_VCARD 265
208#define END_VCARD 266 234#define END_VCARD 266
209#define BEGIN_VCAL 267 235#define BEGIN_VCAL 267
210#define END_VCAL 268 236#define END_VCAL 268
211#define BEGIN_VEVENT 269 237#define BEGIN_VEVENT 269
212#define END_VEVENT 270 238#define END_VEVENT 270
213#define BEGIN_VTODO 271 239#define BEGIN_VTODO 271
214#define END_VTODO 272 240#define END_VTODO 272
215#define ID 273 241#define ID 273
216#define STRING 274 242#define STRING 274
217#define YYERRCODE 256 243#define YYERRCODE 256
218short yylhs[] = { -1, 244short vcclhs[] = { -1,
219 0, 6, 6, 5, 5, 8, 3, 9, 3, 7, 245 0, 6, 6, 5, 5, 8, 3, 9, 3, 7,
220 7, 13, 10, 10, 15, 11, 11, 14, 14, 16, 246 7, 13, 10, 10, 15, 11, 11, 14, 14, 16,
221 17, 17, 1, 18, 12, 12, 2, 2, 20, 4, 247 17, 17, 1, 18, 12, 12, 2, 2, 20, 4,
222 21, 4, 19, 19, 22, 22, 22, 25, 23, 26, 248 21, 4, 19, 19, 22, 22, 22, 25, 23, 26,
223 23, 27, 24, 28, 24, 249 23, 27, 24, 28, 24,
224}; 250};
225short yylen[] = { 2, 251short vcclen[] = { 2,
226 1, 2, 1, 1, 1, 0, 4, 0, 3, 2, 252 1, 2, 1, 1, 1, 0, 4, 0, 3, 2,
227 1, 0, 5, 1, 0, 3, 1, 2, 1, 2, 253 1, 0, 5, 1, 0, 3, 1, 2, 1, 2,
228 1, 3, 1, 0, 4, 1, 1, 0, 0, 4, 254 1, 3, 1, 0, 4, 1, 1, 0, 0, 4,
229 0, 3, 2, 1, 1, 1, 1, 0, 4, 0, 255 0, 3, 2, 1, 1, 1, 1, 0, 4, 0,
230 3, 0, 4, 0, 3, 256 3, 0, 4, 0, 3,
231}; 257};
232short yydefred[] = { 0, 258short vccdefred[] = { 0,
233 0, 0, 0, 4, 5, 3, 0, 0, 0, 0, 259 0, 0, 0, 4, 5, 3, 0, 0, 0, 0,
234 0, 2, 14, 23, 0, 0, 11, 0, 9, 0, 260 0, 2, 14, 23, 0, 0, 11, 0, 9, 0,
235 0, 0, 0, 34, 35, 36, 32, 0, 7, 10, 261 0, 0, 0, 34, 35, 36, 32, 0, 7, 10,
236 12, 0, 0, 0, 0, 30, 33, 0, 0, 19, 262 12, 0, 0, 0, 0, 30, 33, 0, 0, 19,
237 0, 0, 41, 0, 45, 0, 20, 18, 27, 0, 263 0, 0, 41, 0, 45, 0, 20, 18, 27, 0,
238 0, 39, 43, 0, 24, 13, 22, 0, 25, 264 0, 39, 43, 0, 24, 13, 22, 0, 25,
239}; 265};
240short yydgoto[] = { 3, 266short vccdgoto[] = { 3,
241 15, 50, 4, 5, 6, 7, 22, 8, 9, 17, 267 15, 50, 4, 5, 6, 7, 22, 8, 9, 17,
242 18, 51, 41, 39, 28, 40, 47, 58, 23, 10, 268 18, 51, 41, 39, 28, 40, 47, 58, 23, 10,
243 11, 24, 25, 26, 32, 33, 34, 35, 269 11, 24, 25, 26, 32, 33, 34, 35,
244}; 270};
245short yysindex[] = { -262, 271short vccsindex[] = { -262,
246 0, 0, 0, 0, 0, 0, -262, -252, -219, -249, 272 0, 0, 0, 0, 0, 0, -262, -252, -219, -249,
247 -256, 0, 0, 0, 0, -227, 0, -242, 0, 0, 273 -256, 0, 0, 0, 0, -227, 0, -242, 0, 0,
248 0, -252, -254, 0, 0, 0, 0, -208, 0, 0, 274 0, -252, -254, 0, 0, 0, 0, -208, 0, 0,
249 0, -252, -228, -252, -213, 0, 0, -212, -208, 0, 275 0, -252, -228, -252, -213, 0, 0, -212, -208, 0,
250 -214, -233, 0, -224, 0, -195, 0, 0, 0, -197, 276 -214, -233, 0, -224, 0, -195, 0, 0, 0, -197,
251 -199, 0, 0, -212, 0, 0, 0, -214, 0, 277 -199, 0, 0, -212, 0, 0, 0, -214, 0,
252}; 278};
253short yyrindex[] = { 0, 279short vccrindex[] = { 0,
254 -222, -238, 0, 0, 0, 0, 65, 0, 0, 0, 280 -222, -238, 0, 0, 0, 0, 65, 0, 0, 0,
255 0, 0, 0, 0, -215, 0, 0, 0, 0, -220, 281 0, 0, 0, 0, -215, 0, 0, 0, 0, -220,
256 -218, -260, 0, 0, 0, 0, 0, 0, 0, 0, 282 -218, -260, 0, 0, 0, 0, 0, 0, 0, 0,
257 0, 0, 0, 0, 0, 0, 0, 0, -192, 0, 283 0, 0, 0, 0, 0, 0, 0, 0, -192, 0,
258 -250, 0, 0, 0, 0, -202, 0, 0, 0, -196, 284 -250, 0, 0, 0, 0, -202, 0, 0, 0, -196,
259 0, 0, 0, 0, 0, 0, 0, -250, 0, 285 0, 0, 0, 0, 0, 0, 0, -250, 0,
260}; 286};
261short yygindex[] = { 0, 287short vccgindex[] = { 0,
262 3, 0, 0, 0, 61, 0, -7, 0, 0, -16, 288 3, 0, 0, 0, 61, 0, -7, 0, 0, -16,
263 0, 11, 0, 0, 0, 31, 0, 0, 0, 0, 289 0, 11, 0, 0, 0, 31, 0, 0, 0, 0,
264 0, 48, 0, 0, 0, 0, 0, 0, 290 0, 48, 0, 0, 0, 0, 0, 0,
265}; 291};
266#define YYTABLESIZE 71 292#define YYTABLESIZE 71
267short yytable[] = { 30, 293short vcctable[] = { 30,
268 16, 13, 1, 13, 2, 30, 13, 37, 37, 28, 294 16, 13, 1, 13, 2, 30, 13, 37, 37, 28,
269 37, 27, 28, 36, 20, 31, 21, 29, 14, 20, 295 37, 27, 28, 36, 20, 31, 21, 29, 14, 20,
270 14, 21, 13, 14, 42, 30, 44, 30, 13, 31, 296 14, 21, 13, 14, 42, 30, 44, 30, 13, 31,
271 29, 13, 29, 6, 29, 38, 52, 42, 29, 14, 297 29, 13, 29, 6, 29, 38, 52, 42, 29, 14,
272 46, 43, 17, 8, 15, 14, 19, 53, 14, 40, 298 46, 43, 17, 8, 15, 14, 19, 53, 14, 40,
273 6, 38, 38, 44, 42, 21, 57, 21, 45, 49, 299 6, 38, 38, 44, 42, 21, 57, 21, 45, 49,
274 14, 54, 55, 56, 1, 16, 26, 12, 59, 48, 300 14, 54, 55, 56, 1, 16, 26, 12, 59, 48,
275 37, 301 37,
276}; 302};
277short yycheck[] = { 16, 303short vcccheck[] = { 16,
278 8, 256, 265, 256, 267, 22, 256, 268, 269, 260, 304 8, 256, 265, 256, 267, 22, 256, 268, 269, 260,
279 271, 268, 263, 268, 269, 258, 271, 256, 273, 269, 305 271, 268, 263, 268, 269, 258, 271, 256, 273, 269,
280 273, 271, 256, 273, 32, 42, 34, 44, 256, 268, 306 273, 271, 256, 273, 32, 42, 34, 44, 256, 268,
281 269, 256, 271, 256, 273, 256, 270, 256, 266, 273, 307 269, 256, 271, 256, 273, 256, 270, 256, 266, 273,
282 38, 270, 258, 266, 260, 273, 266, 272, 273, 270, 308 38, 270, 258, 266, 260, 273, 266, 272, 273, 270,
283 273, 260, 273, 272, 273, 258, 54, 260, 272, 274, 309 273, 260, 273, 272, 273, 258, 54, 260, 272, 274,
284 273, 257, 260, 263, 0, 258, 263, 7, 58, 39, 310 273, 257, 260, 263, 0, 258, 263, 7, 58, 39,
285 23, 311 23,
286}; 312};
287#define YYFINAL 3 313#define YYFINAL 3
288#ifndef YYDEBUG 314#ifndef YYDEBUG
289#define YYDEBUG 0 315#define YYDEBUG 0
290#endif 316#endif
291#define YYMAXTOKEN 274 317#define YYMAXTOKEN 274
292#if YYDEBUG 318#if YYDEBUG
293char *yyname[] = { 319char *vccname[] = {
294"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 320"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3210,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2960,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3220,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2970,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3230,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2980,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2990,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3250,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"EQ","COLON","DOT","SEMICOLON", 3260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"EQ","COLON","DOT","SEMICOLON",
301"SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD","BEGIN_VCAL", 327"SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD","BEGIN_VCAL",
302"END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO","ID","STRING", 328"END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO","ID","STRING",
303}; 329};
304char *yyrule[] = { 330char *vccrule[] = {
305"$accept : mime", 331"$accept : mime",
306"mime : vobjects", 332"mime : vobjects",
307"vobjects : vobjects vobject", 333"vobjects : vobjects vobject",
308"vobjects : vobject", 334"vobjects : vobject",
309"vobject : vcard", 335"vobject : vcard",
310"vobject : vcal", 336"vobject : vcal",
311"$$1 :", 337"$$1 :",
312"vcard : BEGIN_VCARD $$1 items END_VCARD", 338"vcard : BEGIN_VCARD $$1 items END_VCARD",
313"$$2 :", 339"$$2 :",
314"vcard : BEGIN_VCARD $$2 END_VCARD", 340"vcard : BEGIN_VCARD $$2 END_VCARD",
315"items : items item", 341"items : items item",
316"items : item", 342"items : item",
317"$$3 :", 343"$$3 :",
318"item : prop COLON $$3 values LINESEP", 344"item : prop COLON $$3 values LINESEP",
319"item : error", 345"item : error",
320"$$4 :", 346"$$4 :",
321"prop : name $$4 attr_params", 347"prop : name $$4 attr_params",
322"prop : name", 348"prop : name",
323"attr_params : attr_params attr_param", 349"attr_params : attr_params attr_param",
324"attr_params : attr_param", 350"attr_params : attr_param",
325"attr_param : SEMICOLON attr", 351"attr_param : SEMICOLON attr",
326"attr : name", 352"attr : name",
327"attr : name EQ name", 353"attr : name EQ name",
328"name : ID", 354"name : ID",
329"$$5 :", 355"$$5 :",
330"values : value SEMICOLON $$5 values", 356"values : value SEMICOLON $$5 values",
331"values : value", 357"values : value",
332"value : STRING", 358"value : STRING",
333"value :", 359"value :",
334"$$6 :", 360"$$6 :",
335"vcal : BEGIN_VCAL $$6 calitems END_VCAL", 361"vcal : BEGIN_VCAL $$6 calitems END_VCAL",
336"$$7 :", 362"$$7 :",
337"vcal : BEGIN_VCAL $$7 END_VCAL", 363"vcal : BEGIN_VCAL $$7 END_VCAL",
338"calitems : calitems calitem", 364"calitems : calitems calitem",
339"calitems : calitem", 365"calitems : calitem",
340"calitem : eventitem", 366"calitem : eventitem",
341"calitem : todoitem", 367"calitem : todoitem",
342"calitem : items", 368"calitem : items",
343"$$8 :", 369"$$8 :",
344"eventitem : BEGIN_VEVENT $$8 items END_VEVENT", 370"eventitem : BEGIN_VEVENT $$8 items END_VEVENT",
345"$$9 :", 371"$$9 :",
346"eventitem : BEGIN_VEVENT $$9 END_VEVENT", 372"eventitem : BEGIN_VEVENT $$9 END_VEVENT",
347"$$10 :", 373"$$10 :",
348"todoitem : BEGIN_VTODO $$10 items END_VTODO", 374"todoitem : BEGIN_VTODO $$10 items END_VTODO",
349"$$11 :", 375"$$11 :",
350"todoitem : BEGIN_VTODO $$11 END_VTODO", 376"todoitem : BEGIN_VTODO $$11 END_VTODO",
351}; 377};
352#endif 378#endif
353#ifdef YYSTACKSIZE 379#ifdef YYSTACKSIZE
354#undef YYMAXDEPTH 380#undef YYMAXDEPTH
355#define YYMAXDEPTH YYSTACKSIZE 381#define YYMAXDEPTH YYSTACKSIZE
356#else 382#else
357#ifdef YYMAXDEPTH 383#ifdef YYMAXDEPTH
358#define YYSTACKSIZE YYMAXDEPTH 384#define YYSTACKSIZE YYMAXDEPTH
359#else 385#else
360#define YYSTACKSIZE 500 386#define YYSTACKSIZE 500
361#define YYMAXDEPTH 500 387#define YYMAXDEPTH 500
362#endif 388#endif
363#endif 389#endif
364int yydebug; 390int yydebug;
365int yynerrs; 391int yynerrs;
366int yyerrflag; 392int yyerrflag;
367int yychar; 393int yychar;
368short *yyssp; 394short *yyssp;
369YYSTYPE *yyvsp; 395YYSTYPE *yyvsp;
370YYSTYPE yyval; 396YYSTYPE yyval;
371YYSTYPE yylval; 397YYSTYPE yylval;
372short yyss[YYSTACKSIZE]; 398short yyss[YYSTACKSIZE];
373YYSTYPE yyvs[YYSTACKSIZE]; 399YYSTYPE yyvs[YYSTACKSIZE];
374#define yystacksize YYSTACKSIZE 400#define yystacksize YYSTACKSIZE
375#line 378 "vcc.y" 401#line 382 "backend/vcc.y"
376 402
377/*------------------------------------*/ 403/*------------------------------------*/
378static int pushVObject(const char *prop) 404static int pushVObject(const char *prop)
379 { 405 {
380 VObject *newObj; 406 VObject *newObj;
381 if (ObjStackTop == MAXLEVEL) 407 if (ObjStackTop == MAXLEVEL)
382 return FALSE; 408 return FALSE;
383 409
384 ObjStack[++ObjStackTop] = curObj; 410 ObjStack[++ObjStackTop] = curObj;
385 411
386 if (curObj) { 412 if (curObj) {
387 newObj = addProp(curObj,prop); 413 newObj = addProp(curObj,prop);
388 curObj = newObj; 414 curObj = newObj;
389 } 415 }
390 else 416 else
391 curObj = newVObject(prop); 417 curObj = newVObject(prop);
392 418
393 return TRUE; 419 return TRUE;
394 } 420 }
395 421
396 422
397/*---------------------------------------*/ 423/*---------------------------------------*/
398/* This pops the recently built vCard off the stack and returns it. */ 424/* This pops the recently built vCard off the stack and returns it. */
399static VObject* popVObject() 425static VObject* popVObject()
400 { 426 {
401 VObject *oldObj; 427 VObject *oldObj;
402 if (ObjStackTop < 0) { 428 if (ObjStackTop < 0) {
403 yyerror("pop on empty Object Stack\n"); 429 yyerror("pop on empty Object Stack\n");
404 return 0; 430 return 0;
405 } 431 }
406 oldObj = curObj; 432 oldObj = curObj;
407 curObj = ObjStack[ObjStackTop--]; 433 curObj = ObjStack[ObjStackTop--];
408 434
409 return oldObj; 435 return oldObj;
410 } 436 }
411 437
412 438
413static void enterValues(const char *value) 439static void enterValues(const char *value)
414 { 440 {
415 if (fieldedProp && *fieldedProp) { 441 if (fieldedProp && *fieldedProp) {
416 if (value) { 442 if (value) {
417 addPropValue(curProp,*fieldedProp,value); 443 addPropValue(curProp,*fieldedProp,value);
418 } 444 }
419 /* else this field is empty, advance to next field */ 445 /* else this field is empty, advance to next field */
420 fieldedProp++; 446 fieldedProp++;
421 } 447 }
422 else { 448 else {
423 if (value) { 449 if (value) {
424 setVObjectStringZValue_(curProp,strdup( value )); 450 setVObjectStringZValue_(curProp,strdup( value ));
425 } 451 }
426 } 452 }
427 deleteStr(value); 453 deleteStr(value);
428 } 454 }
429 455
430static void enterProps(const char *s) 456static void enterProps(const char *s)
431 { 457 {
432 curProp = addGroup(curObj,s); 458 curProp = addGroup(curObj,s);
433 deleteStr(s); 459 deleteStr(s);
434 } 460 }
435 461
436static void enterAttr(const char *s1, const char *s2) 462static void enterAttr(const char *s1, const char *s2)
437 { 463 {
438 const char *p1, *p2; 464 const char *p1, *p2;
439 p1 = lookupProp_(s1); 465 p1 = lookupProp_(s1);
440 if (s2) { 466 if (s2) {
441 VObject *a; 467 VObject *a;
442 p2 = lookupProp_(s2); 468 p2 = lookupProp_(s2);
443 a = addProp(curProp,p1); 469 a = addProp(curProp,p1);
444 setVObjectStringZValue(a,p2); 470 setVObjectStringZValue(a,p2);
445 } 471 }
446 else 472 else
447 addProp(curProp,p1); 473 addProp(curProp,p1);
448 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0)) 474 if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
449 lexPushMode(L_BASE64); 475 lexPushMode(L_BASE64);
450 else if (qstricmp(p1,VCQuotedPrintableProp) == 0 476 else if (qstricmp(p1,VCQuotedPrintableProp) == 0
451 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0)) 477 || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
452 lexPushMode(L_QUOTED_PRINTABLE); 478 lexPushMode(L_QUOTED_PRINTABLE);
453 deleteStr(s1); deleteStr(s2); 479 deleteStr(s1); deleteStr(s2);
454 } 480 }
455 481
456 482
457#define MAX_LEX_LOOKAHEAD_0 32 483#define MAX_LEX_LOOKAHEAD_0 32
458#define MAX_LEX_LOOKAHEAD 64 484#define MAX_LEX_LOOKAHEAD 64
459#define MAX_LEX_MODE_STACK_SIZE 10 485#define MAX_LEX_MODE_STACK_SIZE 10
460#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop]) 486#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
461 487
462struct LexBuf { 488struct LexBuf {
463 /* input */ 489 /* input */
464#ifdef INCLUDEMFC 490#ifdef INCLUDEMFC
465 CFile *inputFile; 491 CFile *inputFile;
466#else 492#else
467 FILE *inputFile; 493 FILE *inputFile;
468#endif 494#endif
469 char *inputString; 495 char *inputString;
470 unsigned long curPos; 496 unsigned long curPos;
471 unsigned long inputLen; 497 unsigned long inputLen;
472 /* lookahead buffer */ 498 /* lookahead buffer */
473 /* -- lookahead buffer is short instead of char so that EOF 499 /* -- lookahead buffer is short instead of char so that EOF
474 / can be represented correctly. 500 / can be represented correctly.
475 */ 501 */
476 unsigned long len; 502 unsigned long len;
477 short buf[MAX_LEX_LOOKAHEAD]; 503 short buf[MAX_LEX_LOOKAHEAD];
478 unsigned long getPtr; 504 unsigned long getPtr;
479 /* context stack */ 505 /* context stack */
480 unsigned long lexModeStackTop; 506 unsigned long lexModeStackTop;
481 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE]; 507 enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
482 /* token buffer */ 508 /* token buffer */
483 unsigned long maxToken; 509 unsigned long maxToken;
484 char *strs; 510 char *strs;
485 unsigned long strsLen; 511 unsigned long strsLen;
486 } lexBuf; 512 } lexBuf;
487 513
488static void lexPushMode(enum LexMode mode) 514static void lexPushMode(enum LexMode mode)
489 { 515 {
490 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1)) 516 if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
491 yyerror("lexical context stack overflow"); 517 yyerror("lexical context stack overflow");
492 else { 518 else {
493 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode; 519 lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
494 } 520 }
495 } 521 }
496 522
497static void lexPopMode(int top) 523static void lexPopMode(int top)
498 { 524 {
499 /* special case of pop for ease of error recovery -- this 525 /* special case of pop for ease of error recovery -- this
500 version will never underflow */ 526 version will never underflow */
501 if (top) 527 if (top)
502 lexBuf.lexModeStackTop = 0; 528 lexBuf.lexModeStackTop = 0;
503 else 529 else
504 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--; 530 if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
505 } 531 }
506 532
507static int lexWithinMode(enum LexMode mode) { 533static int lexWithinMode(enum LexMode mode) {
508 unsigned long i; 534 unsigned long i;
509 for (i=0;i<lexBuf.lexModeStackTop;i++) 535 for (i=0;i<lexBuf.lexModeStackTop;i++)
510 if (mode == lexBuf.lexModeStack[i]) return 1; 536 if (mode == lexBuf.lexModeStack[i]) return 1;
511 return 0; 537 return 0;
512 } 538 }
513 539
514static char lexGetc_() 540static int lexGetc_()
515 { 541 {
516 /* get next char from input, no buffering. */ 542 /* get next char from input, no buffering. */
517 if (lexBuf.curPos == lexBuf.inputLen) 543 if (lexBuf.curPos == lexBuf.inputLen)
518 return EOF; 544 return EOF;
519 else if (lexBuf.inputString) 545 else if (lexBuf.inputString)
520 return *(lexBuf.inputString + lexBuf.curPos++); 546 return *(lexBuf.inputString + lexBuf.curPos++);
521 else { 547 else {
522#ifdef INCLUDEMFC 548#ifdef INCLUDEMFC
523 char result; 549 char result;
524 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF; 550 return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
525#else 551#else
526 return fgetc(lexBuf.inputFile); 552 return fgetc(lexBuf.inputFile);
527#endif 553#endif
528 } 554 }
529 } 555 }
530 556
531static int lexGeta() 557static int lexGeta()
532 { 558 {
533 ++lexBuf.len; 559 ++lexBuf.len;
534 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_()); 560 return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
535 } 561 }
536 562
537static int lexGeta_(int i) 563static int lexGeta_(int i)
538 { 564 {
539 ++lexBuf.len; 565 ++lexBuf.len;
540 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_()); 566 return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
541 } 567 }
542 568
543static void lexSkipLookahead() { 569static void lexSkipLookahead() {
544 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 570 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
545 /* don't skip EOF. */ 571 /* don't skip EOF. */
546 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 572 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
547 lexBuf.len--; 573 lexBuf.len--;
548 } 574 }
549 } 575 }
550 576
551static int lexLookahead() { 577static int lexLookahead() {
552 int c = (lexBuf.len)? 578 int c = (lexBuf.len)?
553 lexBuf.buf[lexBuf.getPtr]: 579 lexBuf.buf[lexBuf.getPtr]:
554 lexGeta(); 580 lexGeta();
555 /* do the \r\n -> \n or \r -> \n translation here */ 581 /* do the \r\n -> \n or \r -> \n translation here */
556 if (c == '\r') { 582 if (c == '\r') {
557 int a = (lexBuf.len>1)? 583 int a = (lexBuf.len>1)?
558 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]: 584 lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
559 lexGeta_(1); 585 lexGeta_(1);
560 if (a == '\n') { 586 if (a == '\n') {
561 lexSkipLookahead(); 587 lexSkipLookahead();
562 } 588 }
563 lexBuf.buf[lexBuf.getPtr] = c = '\n'; 589 lexBuf.buf[lexBuf.getPtr] = c = '\n';
564 } 590 }
565 else if (c == '\n') { 591 else if (c == '\n') {
566 int a = (lexBuf.len>1)? 592 int a = (lexBuf.len>1)?
567 lexBuf.buf[lexBuf.getPtr+1]: 593 lexBuf.buf[lexBuf.getPtr+1]:
568 lexGeta_(1); 594 lexGeta_(1);
569 if (a == '\r') { 595 if (a == '\r') {
570 lexSkipLookahead(); 596 lexSkipLookahead();
571 } 597 }
572 lexBuf.buf[lexBuf.getPtr] = '\n'; 598 lexBuf.buf[lexBuf.getPtr] = '\n';
573 } 599 }
574 return c; 600 return c;
575 } 601 }
576 602
577static int lexGetc() { 603static int lexGetc() {
578 int c = lexLookahead(); 604 int c = lexLookahead();
579 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) { 605 if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
580 /* EOF will remain in lookahead buffer */ 606 /* EOF will remain in lookahead buffer */
581 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD; 607 lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
582 lexBuf.len--; 608 lexBuf.len--;
583 } 609 }
584 return c; 610 return c;
585 } 611 }
586 612
587static void lexSkipLookaheadWord() { 613static void lexSkipLookaheadWord() {
588 if (lexBuf.strsLen <= lexBuf.len) { 614 if (lexBuf.strsLen <= lexBuf.len) {
589 lexBuf.len -= lexBuf.strsLen; 615 lexBuf.len -= lexBuf.strsLen;
590 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD; 616 lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
591 } 617 }
592 } 618 }
593 619
594static void lexClearToken() 620static void lexClearToken()
595 { 621 {
596 lexBuf.strsLen = 0; 622 lexBuf.strsLen = 0;
597 } 623 }
598 624
599static void lexAppendc(int c) 625static void lexAppendc(int c)
600 { 626 {
601 lexBuf.strs[lexBuf.strsLen] = c; 627 lexBuf.strs[lexBuf.strsLen] = c;
602 /* append up to zero termination */ 628 /* append up to zero termination */
603 if (c == 0) return; 629 if (c == 0) return;
604 lexBuf.strsLen++; 630 lexBuf.strsLen++;
605 if (lexBuf.strsLen > lexBuf.maxToken) { 631 if (lexBuf.strsLen > lexBuf.maxToken) {
606 /* double the token string size */ 632 /* double the token string size */
607 lexBuf.maxToken <<= 1; 633 lexBuf.maxToken <<= 1;
608 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken); 634 lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
609 } 635 }
610 } 636 }
611 637
612static char* lexStr() { 638static char* lexStr() {
613 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1); 639 return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
614 } 640 }
615 641
616static void lexSkipWhite() { 642static void lexSkipWhite() {
617 int c = lexLookahead(); 643 int c = lexLookahead();
618 while (c == ' ' || c == '\t') { 644 while (c == ' ' || c == '\t') {
619 lexSkipLookahead(); 645 lexSkipLookahead();
620 c = lexLookahead(); 646 c = lexLookahead();
621 } 647 }
622 } 648 }
623 649
624static char* lexGetWord() { 650static char* lexGetWord() {
625 int c; 651 int c;
626 lexSkipWhite(); 652 lexSkipWhite();
627 lexClearToken(); 653 lexClearToken();
628 c = lexLookahead(); 654 c = lexLookahead();
629 while (c != EOF && !strchr("\t\n ;:=",c)) { 655 while (c != EOF && !strchr("\t\n ;:=",c)) {
630 lexAppendc(c); 656 lexAppendc(c);
631 lexSkipLookahead(); 657 lexSkipLookahead();
632 c = lexLookahead(); 658 c = lexLookahead();
633 } 659 }
634 lexAppendc(0); 660 lexAppendc(0);
635 return lexStr(); 661 return lexStr();
636 } 662 }
637 663
638static void lexPushLookaheadc(int c) { 664static void lexPushLookaheadc(int c) {
639 int putptr; 665 int putptr;
640 /* can't putback EOF, because it never leaves lookahead buffer */ 666 /* can't putback EOF, because it never leaves lookahead buffer */
641 if (c == EOF) return; 667 if (c == EOF) return;
642 putptr = (int)lexBuf.getPtr - 1; 668 putptr = (int)lexBuf.getPtr - 1;
643 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD; 669 if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
644 lexBuf.getPtr = putptr; 670 lexBuf.getPtr = putptr;
645 lexBuf.buf[putptr] = c; 671 lexBuf.buf[putptr] = c;
646 lexBuf.len += 1; 672 lexBuf.len += 1;
647 } 673 }
648 674
649static char* lexLookaheadWord() { 675static char* lexLookaheadWord() {
650 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0 676 /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
651 / and thing bigger than that will stop the lookahead and return 0; 677 / and thing bigger than that will stop the lookahead and return 0;
652 / leading white spaces are not recoverable. 678 / leading white spaces are not recoverable.
653 */ 679 */
654 int c; 680 int c;
655 int len = 0; 681 int len = 0;
656 int curgetptr = 0; 682 int curgetptr = 0;
657 lexSkipWhite(); 683 lexSkipWhite();
658 lexClearToken(); 684 lexClearToken();
659 curgetptr = (int)lexBuf.getPtr;// remember! 685 curgetptr = (int)lexBuf.getPtr;// remember!
660 while (len < (MAX_LEX_LOOKAHEAD_0)) { 686 while (len < (MAX_LEX_LOOKAHEAD_0)) {
661 c = lexGetc(); 687 c = lexGetc();
662 len++; 688 len++;
663 if (c == EOF || strchr("\t\n ;:=", c)) { 689 if (c == EOF || strchr("\t\n ;:=", c)) {
664 lexAppendc(0); 690 lexAppendc(0);
665 /* restore lookahead buf. */ 691 /* restore lookahead buf. */
666 lexBuf.len += len; 692 lexBuf.len += len;
667 lexBuf.getPtr = curgetptr; 693 lexBuf.getPtr = curgetptr;
668 return lexStr(); 694 return lexStr();
669 } 695 }
670 else 696 else
671 lexAppendc(c); 697 lexAppendc(c);
672 } 698 }
673 lexBuf.len += len;/* char that has been moved to lookahead buffer */ 699 lexBuf.len += len;/* char that has been moved to lookahead buffer */
674 lexBuf.getPtr = curgetptr; 700 lexBuf.getPtr = curgetptr;
675 return 0; 701 return 0;
676 } 702 }
677 703
678#ifdef _SUPPORT_LINE_FOLDING 704#ifdef _SUPPORT_LINE_FOLDING
679static void handleMoreRFC822LineBreak(int c) { 705static void handleMoreRFC822LineBreak(int c) {
680 /* suport RFC 822 line break in cases like 706 /* suport RFC 822 line break in cases like
681 *ADR: foo; 707 *ADR: foo;
682 * morefoo; 708 * morefoo;
683 * more foo; 709 * more foo;
684 */ 710 */
685 if (c == ';') { 711 if (c == ';') {
686 int a; 712 int a;
687 lexSkipLookahead(); 713 lexSkipLookahead();
688 /* skip white spaces */ 714 /* skip white spaces */
689 a = lexLookahead(); 715 a = lexLookahead();
690 while (a == ' ' || a == '\t') { 716 while (a == ' ' || a == '\t') {
691 lexSkipLookahead(); 717 lexSkipLookahead();
692 a = lexLookahead(); 718 a = lexLookahead();
693 } 719 }
694 if (a == '\n') { 720 if (a == '\n') {
695 lexSkipLookahead(); 721 lexSkipLookahead();
696 a = lexLookahead(); 722 a = lexLookahead();
697 if (a == ' ' || a == '\t') { 723 if (a == ' ' || a == '\t') {
698 /* continuation, throw away all the \n and spaces read so 724 /* continuation, throw away all the \n and spaces read so
699 * far 725 * far
700 */ 726 */
701 lexSkipWhite(); 727 lexSkipWhite();
702 lexPushLookaheadc(';'); 728 lexPushLookaheadc(';');
703 } 729 }
704 else { 730 else {
705 lexPushLookaheadc('\n'); 731 lexPushLookaheadc('\n');
706 lexPushLookaheadc(';'); 732 lexPushLookaheadc(';');
@@ -736,810 +762,815 @@ static char* lexGet1Value() {
736 lexAppendc(' '); 762 lexAppendc(' ');
737 lexSkipLookahead(); 763 lexSkipLookahead();
738 } 764 }
739 else { 765 else {
740 lexPushLookaheadc('\n'); 766 lexPushLookaheadc('\n');
741 break; 767 break;
742 } 768 }
743 } 769 }
744 else { 770 else {
745 lexAppendc(c); 771 lexAppendc(c);
746 lexSkipLookahead(); 772 lexSkipLookahead();
747 } 773 }
748 c = lexLookahead(); 774 c = lexLookahead();
749 } 775 }
750 lexAppendc(0); 776 lexAppendc(0);
751 handleMoreRFC822LineBreak(c); 777 handleMoreRFC822LineBreak(c);
752 return c==EOF?0:lexStr(); 778 return c==EOF?0:lexStr();
753 } 779 }
754#endif 780#endif
755 781
756static int match_begin_name(int end) { 782static int match_begin_name(int end) {
757 char *n = lexLookaheadWord(); 783 char *n = lexLookaheadWord();
758 int token = ID; 784 int token = ID;
759 if (n) { 785 if (n) {
760 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD; 786 if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
761 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL; 787 else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
762 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT; 788 else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
763 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO; 789 else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
764 deleteStr(n); 790 deleteStr(n);
765 return token; 791 return token;
766 } 792 }
767 return 0; 793 return 0;
768 } 794 }
769 795
770 796
771#ifdef INCLUDEMFC 797#ifdef INCLUDEMFC
772void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile) 798void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
773#else 799#else
774void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile) 800void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
775#endif 801#endif
776 { 802 {
777 // initialize lex mode stack 803 // initialize lex mode stack
778 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL; 804 lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
779 805
780 // iniatialize lex buffer. 806 // iniatialize lex buffer.
781 lexBuf.inputString = (char*) inputstring; 807 lexBuf.inputString = (char*) inputstring;
782 lexBuf.inputLen = inputlen; 808 lexBuf.inputLen = inputlen;
783 lexBuf.curPos = 0; 809 lexBuf.curPos = 0;
784 lexBuf.inputFile = inputfile; 810 lexBuf.inputFile = inputfile;
785 811
786 lexBuf.len = 0; 812 lexBuf.len = 0;
787 lexBuf.getPtr = 0; 813 lexBuf.getPtr = 0;
788 814
789 lexBuf.maxToken = MAXTOKEN; 815 lexBuf.maxToken = MAXTOKEN;
790 lexBuf.strs = (char*)malloc(MAXTOKEN); 816 lexBuf.strs = (char*)malloc(MAXTOKEN);
791 lexBuf.strsLen = 0; 817 lexBuf.strsLen = 0;
792 818
793 } 819 }
794 820
795static void finiLex() { 821static void finiLex() {
796 free(lexBuf.strs); 822 free(lexBuf.strs);
797 } 823 }
798 824
799 825
800/*-----------------------------------*/ 826/*-----------------------------------*/
801/* This parses and converts the base64 format for binary encoding into 827/* This parses and converts the base64 format for binary encoding into
802 * a decoded buffer (allocated with new). See RFC 1521. 828 * a decoded buffer (allocated with new). See RFC 1521.
803 */ 829 */
804static char * lexGetDataFromBase64() 830static char * lexGetDataFromBase64()
805 { 831 {
806 unsigned long bytesLen = 0, bytesMax = 0; 832 unsigned long bytesLen = 0, bytesMax = 0;
807 int quadIx = 0, pad = 0; 833 int quadIx = 0, pad = 0;
808 unsigned long trip = 0; 834 unsigned long trip = 0;
809 unsigned char b; 835 unsigned char b;
810 int c; 836 int c;
811 unsigned char *bytes = NULL; 837 unsigned char *bytes = NULL;
812 unsigned char *oldBytes = NULL; 838 unsigned char *oldBytes = NULL;
813 839
814 DBG_(("db: lexGetDataFromBase64\n")); 840 DBG_(("db: lexGetDataFromBase64\n"));
815 while (1) { 841 while (1) {
816 c = lexGetc(); 842 c = lexGetc();
817 if (c == '\n') { 843 if (c == '\n') {
818 ++mime_lineNum; 844 ++mime_lineNum;
819 if (lexLookahead() == '\n') { 845 if (lexLookahead() == '\n') {
820 /* a '\n' character by itself means end of data */ 846 /* a '\n' character by itself means end of data */
821 break; 847 break;
822 } 848 }
823 else continue; /* ignore '\n' */ 849 else continue; /* ignore '\n' */
824 } 850 }
825 else { 851 else {
826 if ((c >= 'A') && (c <= 'Z')) 852 if ((c >= 'A') && (c <= 'Z'))
827 b = (unsigned char)(c - 'A'); 853 b = (unsigned char)(c - 'A');
828 else if ((c >= 'a') && (c <= 'z')) 854 else if ((c >= 'a') && (c <= 'z'))
829 b = (unsigned char)(c - 'a') + 26; 855 b = (unsigned char)(c - 'a') + 26;
830 else if ((c >= '0') && (c <= '9')) 856 else if ((c >= '0') && (c <= '9'))
831 b = (unsigned char)(c - '0') + 52; 857 b = (unsigned char)(c - '0') + 52;
832 else if (c == '+') 858 else if (c == '+')
833 b = 62; 859 b = 62;
834 else if (c == '/') 860 else if (c == '/')
835 b = 63; 861 b = 63;
836 else if (c == '=') { 862 else if (c == '=') {
837 b = 0; 863 b = 0;
838 pad++; 864 pad++;
839 } else if ((c == ' ') || (c == '\t')) { 865 } else if ((c == ' ') || (c == '\t')) {
840 continue; 866 continue;
841 } else { /* error condition */ 867 } else { /* error condition */
842 if (bytes) free(bytes); 868 if (bytes) free(bytes);
843 else if (oldBytes) free(oldBytes); 869 else if (oldBytes) free(oldBytes);
844 // error recovery: skip until 2 adjacent newlines. 870 // error recovery: skip until 2 adjacent newlines.
845 DBG_(("db: invalid character 0x%x '%c'\n", c,c)); 871 DBG_(("db: invalid character 0x%x '%c'\n", c,c));
846 if (c != EOF) { 872 if (c != EOF) {
847 c = lexGetc(); 873 c = lexGetc();
848 while (c != EOF) { 874 while (c != EOF) {
849 if (c == '\n' && lexLookahead() == '\n') { 875 if (c == '\n' && lexLookahead() == '\n') {
850 ++mime_lineNum; 876 ++mime_lineNum;
851 break; 877 break;
852 } 878 }
853 c = lexGetc(); 879 c = lexGetc();
854 } 880 }
855 } 881 }
856 return NULL; 882 return NULL;
857 } 883 }
858 trip = (trip << 6) | b; 884 trip = (trip << 6) | b;
859 if (++quadIx == 4) { 885 if (++quadIx == 4) {
860 unsigned char outBytes[3]; 886 unsigned char outBytes[3];
861 int numOut; 887 int numOut;
862 int i; 888 int i;
863 for (i = 0; i < 3; i++) { 889 for (i = 0; i < 3; i++) {
864 outBytes[2-i] = (unsigned char)(trip & 0xFF); 890 outBytes[2-i] = (unsigned char)(trip & 0xFF);
865 trip >>= 8; 891 trip >>= 8;
866 } 892 }
867 numOut = 3 - pad; 893 numOut = 3 - pad;
868 if (bytesLen + numOut > bytesMax) { 894 if (bytesLen + numOut > bytesMax) {
869 if (!bytes) { 895 if (!bytes) {
870 bytesMax = 1024; 896 bytesMax = 1024;
871 bytes = (unsigned char*)malloc((size_t)bytesMax); 897 bytes = (unsigned char*)malloc((size_t)bytesMax);
872 } 898 }
873 else { 899 else {
874 bytesMax <<= 2; 900 bytesMax <<= 2;
875 oldBytes = bytes; 901 oldBytes = bytes;
876 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax); 902 bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
877 } 903 }
878 if (bytes == 0) { 904 if (bytes == 0) {
879 mime_error("out of memory while processing BASE64 data\n"); 905 mime_error("out of memory while processing BASE64 data\n");
880 } 906 }
881 } 907 }
882 if (bytes) { 908 if (bytes) {
883 memcpy(bytes + bytesLen, outBytes, numOut); 909 memcpy(bytes + bytesLen, outBytes, numOut);
884 bytesLen += numOut; 910 bytesLen += numOut;
885 } 911 }
886 trip = 0; 912 trip = 0;
887 quadIx = 0; 913 quadIx = 0;
888 } 914 }
889 } 915 }
890 } /* while */ 916 } /* while */
891 DBG_(("db: bytesLen = %d\n", bytesLen)); 917 DBG_(("db: bytesLen = %d\n", bytesLen));
892 /* kludge: all this won't be necessary if we have tree form 918 /* kludge: all this won't be necessary if we have tree form
893 representation */ 919 representation */
894 if (bytes) { 920 if (bytes) {
895 setValueWithSize(curProp,bytes,(unsigned int)bytesLen); 921 setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
896 free(bytes); 922 free(bytes);
897 } 923 }
898 else if (oldBytes) { 924 else if (oldBytes) {
899 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen); 925 setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
900 free(oldBytes); 926 free(oldBytes);
901 } 927 }
902 return 0; 928 return 0;
903 } 929 }
904 930
905static int match_begin_end_name(int end) { 931static int match_begin_end_name(int end) {
906 int token; 932 int token;
907 lexSkipWhite(); 933 lexSkipWhite();
908 if (lexLookahead() != ':') return ID; 934 if (lexLookahead() != ':') return ID;
909 lexSkipLookahead(); 935 lexSkipLookahead();
910 lexSkipWhite(); 936 lexSkipWhite();
911 token = match_begin_name(end); 937 token = match_begin_name(end);
912 if (token == ID) { 938 if (token == ID) {
913 lexPushLookaheadc(':'); 939 lexPushLookaheadc(':');
914 DBG_(("db: ID '%s'\n", yylval.str)); 940 DBG_(("db: ID '%s'\n", yylval.str));
915 return ID; 941 return ID;
916 } 942 }
917 else if (token != 0) { 943 else if (token != 0) {
918 lexSkipLookaheadWord(); 944 lexSkipLookaheadWord();
919 deleteStr(yylval.str); 945 deleteStr(yylval.str);
920 DBG_(("db: begin/end %d\n", token)); 946 DBG_(("db: begin/end %d\n", token));
921 return token; 947 return token;
922 } 948 }
923 return 0; 949 return 0;
924 } 950 }
925 951
926static char* lexGetQuotedPrintable() 952static char* lexGetQuotedPrintable()
927 { 953 {
928 char cur; 954 int cur;
929 955
930 lexClearToken(); 956 lexClearToken();
931 do { 957 do {
932 cur = lexGetc(); 958 cur = lexGetc();
933 switch (cur) { 959 switch (cur) {
934 case '=': { 960 case '=': {
935 int c = 0; 961 int c = 0;
936 int next[2]; 962 int next[2];
937 int i; 963 int i;
938 for (i = 0; i < 2; i++) { 964 for (i = 0; i < 2; i++) {
939 next[i] = lexGetc(); 965 next[i] = lexGetc();
940 if (next[i] >= '0' && next[i] <= '9') 966 if (next[i] >= '0' && next[i] <= '9')
941 c = c * 16 + next[i] - '0'; 967 c = c * 16 + next[i] - '0';
942 else if (next[i] >= 'A' && next[i] <= 'F') 968 else if (next[i] >= 'A' && next[i] <= 'F')
943 c = c * 16 + next[i] - 'A' + 10; 969 c = c * 16 + next[i] - 'A' + 10;
944 else 970 else
945 break; 971 break;
946 } 972 }
947 if (i == 0) { 973 if (i == 0) {
948 /* single '=' follow by LINESEP is continuation sign? */ 974 /* single '=' follow by LINESEP is continuation sign? */
949 if (next[0] == '\n') { 975 if (next[0] == '\n') {
950 ++mime_lineNum; 976 ++mime_lineNum;
951 } 977 }
952 else { 978 else {
953 lexPushLookaheadc('='); 979 lexPushLookaheadc('=');
954 goto EndString; 980 goto EndString;
955 } 981 }
956 } 982 }
957 else if (i == 1) { 983 else if (i == 1) {
958 lexPushLookaheadc(next[1]); 984 lexPushLookaheadc(next[1]);
959 lexPushLookaheadc(next[0]); 985 lexPushLookaheadc(next[0]);
960 lexAppendc('='); 986 lexAppendc('=');
961 } else { 987 } else {
962 lexAppendc(c); 988 lexAppendc(c);
963 } 989 }
964 break; 990 break;
965 } /* '=' */ 991 } /* '=' */
966 case '\n': { 992 case '\n': {
967 lexPushLookaheadc('\n'); 993 lexPushLookaheadc('\n');
968 goto EndString; 994 goto EndString;
969 } 995 }
970 case (char)EOF: 996 case (int)EOF:
971 break; 997 break;
972 default: 998 default:
973 lexAppendc(cur); 999 lexAppendc(cur);
974 break; 1000 break;
975 } /* switch */ 1001 } /* switch */
976 } while (cur != (char)EOF); 1002 } while (cur != (int)EOF);
977 1003
978EndString: 1004EndString:
979 lexAppendc(0); 1005 lexAppendc(0);
980 return lexStr(); 1006 return lexStr();
981 } /* LexQuotedPrintable */ 1007 } /* LexQuotedPrintable */
982 1008
983static int yylex() { 1009static int yylex() {
984 1010
985 int lexmode = LEXMODE(); 1011 int lexmode = LEXMODE();
986 if (lexmode == L_VALUES) { 1012 if (lexmode == L_VALUES) {
987 int c = lexGetc(); 1013 int c = lexGetc();
988 if (c == ';') { 1014 if (c == ';') {
989 DBG_(("db: SEMICOLON\n")); 1015 DBG_(("db: SEMICOLON\n"));
990 lexPushLookaheadc(c); 1016 lexPushLookaheadc(c);
991 handleMoreRFC822LineBreak(c); 1017 handleMoreRFC822LineBreak(c);
992 lexSkipLookahead(); 1018 lexSkipLookahead();
993 return SEMICOLON; 1019 return SEMICOLON;
994 } 1020 }
995 else if (strchr("\n",c)) { 1021 else if (strchr("\n",c)) {
996 ++mime_lineNum; 1022 ++mime_lineNum;
997 /* consume all line separator(s) adjacent to each other */ 1023 /* consume all line separator(s) adjacent to each other */
998 c = lexLookahead(); 1024 c = lexLookahead();
999 while (strchr("\n",c)) { 1025 while (strchr("\n",c)) {
1000 lexSkipLookahead(); 1026 lexSkipLookahead();
1001 c = lexLookahead(); 1027 c = lexLookahead();
1002 ++mime_lineNum; 1028 ++mime_lineNum;
1003 } 1029 }
1004 DBG_(("db: LINESEP\n")); 1030 DBG_(("db: LINESEP\n"));
1005 return LINESEP; 1031 return LINESEP;
1006 } 1032 }
1007 else { 1033 else {
1008 char *p = 0; 1034 char *p = 0;
1009 lexPushLookaheadc(c); 1035 lexPushLookaheadc(c);
1010 if (lexWithinMode(L_BASE64)) { 1036 if (lexWithinMode(L_BASE64)) {
1011 /* get each char and convert to bin on the fly... */ 1037 /* get each char and convert to bin on the fly... */
1012 p = lexGetDataFromBase64(); 1038 p = lexGetDataFromBase64();
1013 yylval.str = p; 1039 yylval.str = p;
1014 return STRING; 1040 return STRING;
1015 } 1041 }
1016 else if (lexWithinMode(L_QUOTED_PRINTABLE)) { 1042 else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
1017 p = lexGetQuotedPrintable(); 1043 p = lexGetQuotedPrintable();
1018 } 1044 }
1019 else { 1045 else {
1020#ifdef _SUPPORT_LINE_FOLDING 1046#ifdef _SUPPORT_LINE_FOLDING
1021 p = lexGet1Value(); 1047 p = lexGet1Value();
1022#else 1048#else
1023 p = lexGetStrUntil(";\n"); 1049 p = lexGetStrUntil(";\n");
1024#endif 1050#endif
1025 } 1051 }
1026 if (p) { 1052 if (p) {
1027 DBG_(("db: STRING: '%s'\n", p)); 1053 DBG_(("db: STRING: '%s'\n", p));
1028 yylval.str = p; 1054 yylval.str = p;
1029 return STRING; 1055 return STRING;
1030 } 1056 }
1031 else return 0; 1057 else return 0;
1032 } 1058 }
1033 } 1059 }
1034 else { 1060 else {
1035 /* normal mode */ 1061 /* normal mode */
1036 while (1) { 1062 while (1) {
1037 int c = lexGetc(); 1063 int c = lexGetc();
1038 switch(c) { 1064 switch(c) {
1039 case ':': { 1065 case ':': {
1040 /* consume all line separator(s) adjacent to each other */ 1066 /* consume all line separator(s) adjacent to each other */
1041 /* ignoring linesep immediately after colon. */ 1067 /* ignoring linesep immediately after colon. */
1042 c = lexLookahead(); 1068 c = lexLookahead();
1043 while (strchr("\n",c)) { 1069 while (strchr("\n",c)) {
1044 lexSkipLookahead(); 1070 lexSkipLookahead();
1045 c = lexLookahead(); 1071 c = lexLookahead();
1046 ++mime_lineNum; 1072 ++mime_lineNum;
1047 } 1073 }
1048 DBG_(("db: COLON\n")); 1074 DBG_(("db: COLON\n"));
1049 return COLON; 1075 return COLON;
1050 } 1076 }
1051 case ';': 1077 case ';':
1052 DBG_(("db: SEMICOLON\n")); 1078 DBG_(("db: SEMICOLON\n"));
1053 return SEMICOLON; 1079 return SEMICOLON;
1054 case '=': 1080 case '=':
1055 DBG_(("db: EQ\n")); 1081 DBG_(("db: EQ\n"));
1056 return EQ; 1082 return EQ;
1057 /* ignore whitespace in this mode */ 1083 /* ignore whitespace in this mode */
1058 case '\t': 1084 case '\t':
1059 case ' ': continue; 1085 case ' ': continue;
1060 case '\n': { 1086 case '\n': {
1061 ++mime_lineNum; 1087 ++mime_lineNum;
1062 continue; 1088 continue;
1063 } 1089 }
1064 case EOF: return 0; 1090 case EOF: return 0;
1065 break; 1091 break;
1066 default: { 1092 default: {
1067 lexPushLookaheadc(c); 1093 lexPushLookaheadc(c);
1068 if (isalnum(c)) { 1094 if (isalnum(c)) {
1069 char *t = lexGetWord(); 1095 char *t = lexGetWord();
1070 yylval.str = t; 1096 yylval.str = t;
1071 if (!qstricmp(t, "begin")) { 1097 if (!qstricmp(t, "begin")) {
1072 return match_begin_end_name(0); 1098 return match_begin_end_name(0);
1073 } 1099 }
1074 else if (!qstricmp(t,"end")) { 1100 else if (!qstricmp(t,"end")) {
1075 return match_begin_end_name(1); 1101 return match_begin_end_name(1);
1076 } 1102 }
1077 else { 1103 else {
1078 DBG_(("db: ID '%s'\n", t)); 1104 DBG_(("db: ID '%s'\n", t));
1079 return ID; 1105 return ID;
1080 } 1106 }
1081 } 1107 }
1082 else { 1108 else {
1083 /* unknow token */ 1109 /* unknow token */
1084 return 0; 1110 return 0;
1085 } 1111 }
1086 break; 1112 break;
1087 } 1113 }
1088 } 1114 }
1089 } 1115 }
1090 } 1116 }
1091 return 0; 1117 return 0;
1092 } 1118 }
1093 1119
1094 1120
1095/***************************************************************************/ 1121/***************************************************************************/
1096 /*** Public Functions ****/ 1122 /*** Public Functions ****/
1097/***************************************************************************/ 1123/***************************************************************************/
1098 1124
1099static VObject* Parse_MIMEHelper() 1125static VObject* Parse_MIMEHelper()
1100 { 1126 {
1101 ObjStackTop = -1; 1127 ObjStackTop = -1;
1102 mime_numErrors = 0; 1128 mime_numErrors = 0;
1103 mime_lineNum = 1; 1129 mime_lineNum = 1;
1104 vObjList = 0; 1130 vObjList = 0;
1105 curObj = 0; 1131 curObj = 0;
1106 1132
1107 if (yyparse() != 0) 1133 if (yyparse() != 0)
1108 return 0; 1134 return 0;
1109 1135
1110 finiLex(); 1136 finiLex();
1111 return vObjList; 1137 return vObjList;
1112 } 1138 }
1113 1139
1114/*--------------------------------------------*/ 1140/*--------------------------------------------*/
1115DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len) 1141DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
1116 { 1142 {
1117 initLex(input, len, 0); 1143 initLex(input, len, 0);
1118 return Parse_MIMEHelper(); 1144 return Parse_MIMEHelper();
1119 } 1145 }
1120 1146
1121 1147
1122#if INCLUDEMFC 1148#if INCLUDEMFC
1123 1149
1124DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file) 1150DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
1125 { 1151 {
1126 unsigned long startPos; 1152 unsigned long startPos;
1127 VObject *result; 1153 VObject *result;
1128 1154
1129 initLex(0,-1,file); 1155 initLex(0,-1,file);
1130 startPos = file->GetPosition(); 1156 startPos = file->GetPosition();
1131 if (!(result = Parse_MIMEHelper())) 1157 if (!(result = Parse_MIMEHelper()))
1132 file->Seek(startPos, CFile::begin); 1158 file->Seek(startPos, CFile::begin);
1133 return result; 1159 return result;
1134 } 1160 }
1135 1161
1136#else 1162#else
1137 1163
1138VObject* Parse_MIME_FromFile(FILE *file) 1164VObject* Parse_MIME_FromFile(FILE *file)
1139 { 1165 {
1140 VObject *result; 1166 VObject *result;
1141 long startPos; 1167 long startPos;
1142 1168
1143 initLex(0,(unsigned long)-1,file); 1169 initLex(0,(unsigned long)-1,file);
1144 startPos = ftell(file); 1170 startPos = ftell(file);
1145 if (!(result = Parse_MIMEHelper())) { 1171 if (!(result = Parse_MIMEHelper())) {
1146 fseek(file,startPos,SEEK_SET); 1172 fseek(file,startPos,SEEK_SET);
1147 } 1173 }
1148 return result; 1174 return result;
1149 } 1175 }
1150 1176
1151DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname) 1177DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
1152 { 1178 {
1153 QFileDirect f( fname ); 1179 FILE *fp = fopen(fname,"r");
1154 if ( !f.open( IO_ReadOnly ) ) { 1180 if (fp) {
1155 qWarning("Unable to open mime for reading %s", fname); 1181 VObject* o = Parse_MIME_FromFile(fp);
1156 return 0; 1182 fclose(fp);
1183 return o;
1184 }
1185 else {
1186 char msg[80];
1187 sprintf(msg, "can't open file '%s' for reading\n", fname);
1188 mime_error_(msg);
1189 return 0;
1157 } 1190 }
1158
1159 return Parse_MIME_FromFile( f.directHandle() );
1160 } 1191 }
1161 1192
1162#endif 1193#endif
1163 1194
1164/*-------------------------------------*/ 1195/*-------------------------------------*/
1165 1196
1166static MimeErrorHandler mimeErrorHandler; 1197static MimeErrorHandler mimeErrorHandler;
1167 1198
1168DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me) 1199DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
1169 { 1200 {
1170 mimeErrorHandler = me; 1201 mimeErrorHandler = me;
1171 } 1202 }
1172 1203
1173void mime_error(char *s) 1204void mime_error(char *s)
1174 { 1205 {
1175 char msg[256]; 1206 char msg[256];
1176 if (mimeErrorHandler) { 1207 if (mimeErrorHandler) {
1177 sprintf(msg,"%s at line %d", s, mime_lineNum); 1208 sprintf(msg,"%s at line %d", s, mime_lineNum);
1178 mimeErrorHandler(msg); 1209 mimeErrorHandler(msg);
1179 } 1210 }
1180 } 1211 }
1181 1212
1182void mime_error_(char *s) 1213void mime_error_(char *s)
1183 { 1214 {
1184 if (mimeErrorHandler) { 1215 if (mimeErrorHandler) {
1185 mimeErrorHandler(s); 1216 mimeErrorHandler(s);
1186 } 1217 }
1187 } 1218 }
1188 1219
1189#line 1192 "y.tab.c" 1220#line 1221 "y.tab.c"
1190#define YYABORT goto yyabort 1221#define YYABORT goto yyabort
1191#define YYREJECT goto yyabort 1222#define YYREJECT goto yyabort
1192#define YYACCEPT goto yyaccept 1223#define YYACCEPT goto yyaccept
1193#define YYERROR goto yyerrlab 1224#define YYERROR goto yyerrlab
1194int 1225int
1226#if defined(__STDC__)
1227yyparse(void)
1228#else
1195yyparse() 1229yyparse()
1230#endif
1196{ 1231{
1197 register int yym, yyn, yystate; 1232 register int yym, yyn, yystate;
1198#if YYDEBUG 1233#if YYDEBUG
1199 register char *yys; 1234 register char *yys;
1200 extern char *getenv(); 1235 extern char *getenv();
1201 1236
1202 if (yys = getenv("YYDEBUG")) 1237 if (yys = getenv("YYDEBUG"))
1203 { 1238 {
1204 yyn = *yys; 1239 yyn = *yys;
1205 if (yyn >= '0' && yyn <= '9') 1240 if (yyn >= '0' && yyn <= '9')
1206 yydebug = yyn - '0'; 1241 yydebug = yyn - '0';
1207 } 1242 }
1208#endif 1243#endif
1209 1244
1210 yynerrs = 0; 1245 yynerrs = 0;
1211 yyerrflag = 0; 1246 yyerrflag = 0;
1212 yychar = (-1); 1247 yychar = (-1);
1213 1248
1214 yyssp = yyss; 1249 yyssp = yyss;
1215 yyvsp = yyvs; 1250 yyvsp = yyvs;
1216 *yyssp = yystate = 0; 1251 *yyssp = yystate = 0;
1217 1252
1218yyloop: 1253yyloop:
1219 if (yyn = yydefred[yystate]) goto yyreduce; 1254 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1220 if (yychar < 0) 1255 if (yychar < 0)
1221 { 1256 {
1222 if ((yychar = yylex()) < 0) yychar = 0; 1257 if ((yychar = yylex()) < 0) yychar = 0;
1223#if YYDEBUG 1258#if YYDEBUG
1224 if (yydebug) 1259 if (yydebug)
1225 { 1260 {
1226 yys = 0; 1261 yys = 0;
1227 if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; 1262 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1228 if (!yys) yys = "illegal-symbol"; 1263 if (!yys) yys = "illegal-symbol";
1229 printf("%sdebug: state %d, reading %d (%s)\n", 1264 printf("%sdebug: state %d, reading %d (%s)\n",
1230 YYPREFIX, yystate, yychar, yys); 1265 YYPREFIX, yystate, yychar, yys);
1231 } 1266 }
1232#endif 1267#endif
1233 } 1268 }
1234 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && 1269 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1235 yyn <= YYTABLESIZE && yycheck[yyn] == yychar) 1270 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1236 { 1271 {
1237#if YYDEBUG 1272#if YYDEBUG
1238 if (yydebug) 1273 if (yydebug)
1239 printf("%sdebug: state %d, shifting to state %d\n", 1274 printf("%sdebug: state %d, shifting to state %d\n",
1240 YYPREFIX, yystate, yytable[yyn]); 1275 YYPREFIX, yystate, yytable[yyn]);
1241#endif 1276#endif
1242 if (yyssp >= yyss + yystacksize - 1) 1277 if (yyssp >= yyss + yystacksize - 1)
1243 { 1278 {
1244 goto yyoverflow; 1279 goto yyoverflow;
1245 } 1280 }
1246 *++yyssp = yystate = yytable[yyn]; 1281 *++yyssp = yystate = yytable[yyn];
1247 *++yyvsp = yylval; 1282 *++yyvsp = yylval;
1248 yychar = (-1); 1283 yychar = (-1);
1249 if (yyerrflag > 0) --yyerrflag; 1284 if (yyerrflag > 0) --yyerrflag;
1250 goto yyloop; 1285 goto yyloop;
1251 } 1286 }
1252 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && 1287 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1253 yyn <= YYTABLESIZE && yycheck[yyn] == yychar) 1288 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1254 { 1289 {
1255 yyn = yytable[yyn]; 1290 yyn = yytable[yyn];
1256 goto yyreduce; 1291 goto yyreduce;
1257 } 1292 }
1258 if (yyerrflag) goto yyinrecovery; 1293 if (yyerrflag) goto yyinrecovery;
1259#ifdef lint
1260 goto yynewerror;
1261#endif
1262yynewerror:
1263 yyerror("syntax error"); 1294 yyerror("syntax error");
1264#ifdef lint 1295#ifdef lint
1265 goto yyerrlab; 1296 goto yyerrlab;
1266#endif 1297#endif
1267yyerrlab: 1298yyerrlab:
1268 ++yynerrs; 1299 ++yynerrs;
1269yyinrecovery: 1300yyinrecovery:
1270 if (yyerrflag < 3) 1301 if (yyerrflag < 3)
1271 { 1302 {
1272 yyerrflag = 3; 1303 yyerrflag = 3;
1273 for (;;) 1304 for (;;)
1274 { 1305 {
1275 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && 1306 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1276 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) 1307 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1277 { 1308 {
1278#if YYDEBUG 1309#if YYDEBUG
1279 if (yydebug) 1310 if (yydebug)
1280 printf("%sdebug: state %d, error recovery shifting\ 1311 printf("%sdebug: state %d, error recovery shifting\
1281 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]); 1312 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1282#endif 1313#endif
1283 if (yyssp >= yyss + yystacksize - 1) 1314 if (yyssp >= yyss + yystacksize - 1)
1284 { 1315 {
1285 goto yyoverflow; 1316 goto yyoverflow;
1286 } 1317 }
1287 *++yyssp = yystate = yytable[yyn]; 1318 *++yyssp = yystate = yytable[yyn];
1288 *++yyvsp = yylval; 1319 *++yyvsp = yylval;
1289 goto yyloop; 1320 goto yyloop;
1290 } 1321 }
1291 else 1322 else
1292 { 1323 {
1293#if YYDEBUG 1324#if YYDEBUG
1294 if (yydebug) 1325 if (yydebug)
1295 printf("%sdebug: error recovery discarding state %d\n", 1326 printf("%sdebug: error recovery discarding state %d\n",
1296 YYPREFIX, *yyssp); 1327 YYPREFIX, *yyssp);
1297#endif 1328#endif
1298 if (yyssp <= yyss) goto yyabort; 1329 if (yyssp <= yyss) goto yyabort;
1299 --yyssp; 1330 --yyssp;
1300 --yyvsp; 1331 --yyvsp;
1301 } 1332 }
1302 } 1333 }
1303 } 1334 }
1304 else 1335 else
1305 { 1336 {
1306 if (yychar == 0) goto yyabort; 1337 if (yychar == 0) goto yyabort;
1307#if YYDEBUG 1338#if YYDEBUG
1308 if (yydebug) 1339 if (yydebug)
1309 { 1340 {
1310 yys = 0; 1341 yys = 0;
1311 if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; 1342 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1312 if (!yys) yys = "illegal-symbol"; 1343 if (!yys) yys = "illegal-symbol";
1313 printf("%sdebug: state %d, error recovery discards token %d (%s)\n", 1344 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1314 YYPREFIX, yystate, yychar, yys); 1345 YYPREFIX, yystate, yychar, yys);
1315 } 1346 }
1316#endif 1347#endif
1317 yychar = (-1); 1348 yychar = (-1);
1318 goto yyloop; 1349 goto yyloop;
1319 } 1350 }
1320yyreduce: 1351yyreduce:
1321#if YYDEBUG 1352#if YYDEBUG
1322 if (yydebug) 1353 if (yydebug)
1323 printf("%sdebug: state %d, reducing by rule %d (%s)\n", 1354 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1324 YYPREFIX, yystate, yyn, yyrule[yyn]); 1355 YYPREFIX, yystate, yyn, yyrule[yyn]);
1325#endif 1356#endif
1326 yym = yylen[yyn]; 1357 yym = yylen[yyn];
1327 yyval = yyvsp[1-yym]; 1358 yyval = yyvsp[1-yym];
1328 switch (yyn) 1359 switch (yyn)
1329 { 1360 {
1330case 2: 1361case 2:
1331#line 217 "vcc.y" 1362#line 221 "backend/vcc.y"
1332{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; } 1363{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
1333break; 1364break;
1334case 3: 1365case 3:
1335#line 219 "vcc.y" 1366#line 223 "backend/vcc.y"
1336{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; } 1367{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
1337break; 1368break;
1338case 6: 1369case 6:
1339#line 228 "vcc.y" 1370#line 232 "backend/vcc.y"
1340{ 1371{
1341 lexPushMode(L_VCARD); 1372 lexPushMode(L_VCARD);
1342 if (!pushVObject(VCCardProp)) YYERROR; 1373 if (!pushVObject(VCCardProp)) YYERROR;
1343 } 1374 }
1344break; 1375break;
1345case 7: 1376case 7:
1346#line 233 "vcc.y" 1377#line 237 "backend/vcc.y"
1347{ 1378{
1348 lexPopMode(0); 1379 lexPopMode(0);
1349 yyval.vobj = popVObject(); 1380 yyval.vobj = popVObject();
1350 } 1381 }
1351break; 1382break;
1352case 8: 1383case 8:
1353#line 238 "vcc.y" 1384#line 242 "backend/vcc.y"
1354{ 1385{
1355 lexPushMode(L_VCARD); 1386 lexPushMode(L_VCARD);
1356 if (!pushVObject(VCCardProp)) YYERROR; 1387 if (!pushVObject(VCCardProp)) YYERROR;
1357 } 1388 }
1358break; 1389break;
1359case 9: 1390case 9:
1360#line 243 "vcc.y" 1391#line 247 "backend/vcc.y"
1361{ 1392{
1362 lexPopMode(0); 1393 lexPopMode(0);
1363 yyval.vobj = popVObject(); 1394 yyval.vobj = popVObject();
1364 } 1395 }
1365break; 1396break;
1366case 12: 1397case 12:
1367#line 254 "vcc.y" 1398#line 258 "backend/vcc.y"
1368{ 1399{
1369 lexPushMode(L_VALUES); 1400 lexPushMode(L_VALUES);
1370 } 1401 }
1371break; 1402break;
1372case 13: 1403case 13:
1373#line 258 "vcc.y" 1404#line 262 "backend/vcc.y"
1374{ 1405{
1375 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE)) 1406 if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
1376 lexPopMode(0); 1407 lexPopMode(0);
1377 lexPopMode(0); 1408 lexPopMode(0);
1378 } 1409 }
1379break; 1410break;
1380case 15: 1411case 15:
1381#line 267 "vcc.y" 1412#line 271 "backend/vcc.y"
1382{ 1413{
1383 enterProps(yyvsp[0].str); 1414 enterProps(yyvsp[0].str);
1384 } 1415 }
1385break; 1416break;
1386case 17: 1417case 17:
1387#line 272 "vcc.y" 1418#line 276 "backend/vcc.y"
1388{ 1419{
1389 enterProps(yyvsp[0].str); 1420 enterProps(yyvsp[0].str);
1390 } 1421 }
1391break; 1422break;
1392case 21: 1423case 21:
1393#line 285 "vcc.y" 1424#line 289 "backend/vcc.y"
1394{ 1425{
1395 enterAttr(yyvsp[0].str,0); 1426 enterAttr(yyvsp[0].str,0);
1396 } 1427 }
1397break; 1428break;
1398case 22: 1429case 22:
1399#line 289 "vcc.y" 1430#line 293 "backend/vcc.y"
1400{ 1431{
1401 enterAttr(yyvsp[-2].str,yyvsp[0].str); 1432 enterAttr(yyvsp[-2].str,yyvsp[0].str);
1402 1433
1403 } 1434 }
1404break; 1435break;
1405case 24: 1436case 24:
1406#line 298 "vcc.y" 1437#line 302 "backend/vcc.y"
1407{ enterValues(yyvsp[-1].str); } 1438{ enterValues(yyvsp[-1].str); }
1408break; 1439break;
1409case 26: 1440case 26:
1410#line 300 "vcc.y" 1441#line 304 "backend/vcc.y"
1411{ enterValues(yyvsp[0].str); } 1442{ enterValues(yyvsp[0].str); }
1412break; 1443break;
1413case 28: 1444case 28:
1414#line 305 "vcc.y" 1445#line 309 "backend/vcc.y"
1415{ yyval.str = 0; } 1446{ yyval.str = 0; }
1416break; 1447break;
1417case 29: 1448case 29:
1418#line 310 "vcc.y" 1449#line 314 "backend/vcc.y"
1419{ if (!pushVObject(VCCalProp)) YYERROR; } 1450{ if (!pushVObject(VCCalProp)) YYERROR; }
1420break; 1451break;
1421case 30: 1452case 30:
1422#line 313 "vcc.y" 1453#line 317 "backend/vcc.y"
1423{ yyval.vobj = popVObject(); } 1454{ yyval.vobj = popVObject(); }
1424break; 1455break;
1425case 31: 1456case 31:
1426#line 315 "vcc.y" 1457#line 319 "backend/vcc.y"
1427{ if (!pushVObject(VCCalProp)) YYERROR; } 1458{ if (!pushVObject(VCCalProp)) YYERROR; }
1428break; 1459break;
1429case 32: 1460case 32:
1430#line 317 "vcc.y" 1461#line 321 "backend/vcc.y"
1431{ yyval.vobj = popVObject(); } 1462{ yyval.vobj = popVObject(); }
1432break; 1463break;
1433case 38: 1464case 38:
1434#line 332 "vcc.y" 1465#line 336 "backend/vcc.y"
1435{ 1466{
1436 lexPushMode(L_VEVENT); 1467 lexPushMode(L_VEVENT);
1437 if (!pushVObject(VCEventProp)) YYERROR; 1468 if (!pushVObject(VCEventProp)) YYERROR;
1438 } 1469 }
1439break; 1470break;
1440case 39: 1471case 39:
1441#line 338 "vcc.y" 1472#line 342 "backend/vcc.y"
1442{ 1473{
1443 lexPopMode(0); 1474 lexPopMode(0);
1444 popVObject(); 1475 popVObject();
1445 } 1476 }
1446break; 1477break;
1447case 40: 1478case 40:
1448#line 343 "vcc.y" 1479#line 347 "backend/vcc.y"
1449{ 1480{
1450 lexPushMode(L_VEVENT); 1481 lexPushMode(L_VEVENT);
1451 if (!pushVObject(VCEventProp)) YYERROR; 1482 if (!pushVObject(VCEventProp)) YYERROR;
1452 } 1483 }
1453break; 1484break;
1454case 41: 1485case 41:
1455#line 348 "vcc.y" 1486#line 352 "backend/vcc.y"
1456{ 1487{
1457 lexPopMode(0); 1488 lexPopMode(0);
1458 popVObject(); 1489 popVObject();
1459 } 1490 }
1460break; 1491break;
1461case 42: 1492case 42:
1462#line 356 "vcc.y" 1493#line 360 "backend/vcc.y"
1463{ 1494{
1464 lexPushMode(L_VTODO); 1495 lexPushMode(L_VTODO);
1465 if (!pushVObject(VCTodoProp)) YYERROR; 1496 if (!pushVObject(VCTodoProp)) YYERROR;
1466 } 1497 }
1467break; 1498break;
1468case 43: 1499case 43:
1469#line 362 "vcc.y" 1500#line 366 "backend/vcc.y"
1470{ 1501{
1471 lexPopMode(0); 1502 lexPopMode(0);
1472 popVObject(); 1503 popVObject();
1473 } 1504 }
1474break; 1505break;
1475case 44: 1506case 44:
1476#line 367 "vcc.y" 1507#line 371 "backend/vcc.y"
1477{ 1508{
1478 lexPushMode(L_VTODO); 1509 lexPushMode(L_VTODO);
1479 if (!pushVObject(VCTodoProp)) YYERROR; 1510 if (!pushVObject(VCTodoProp)) YYERROR;
1480 } 1511 }
1481break; 1512break;
1482case 45: 1513case 45:
1483#line 372 "vcc.y" 1514#line 376 "backend/vcc.y"
1484{ 1515{
1485 lexPopMode(0); 1516 lexPopMode(0);
1486 popVObject(); 1517 popVObject();
1487 } 1518 }
1488break; 1519break;
1489#line 1492 "y.tab.c" 1520#line 1521 "y.tab.c"
1490 } 1521 }
1491 yyssp -= yym; 1522 yyssp -= yym;
1492 yystate = *yyssp; 1523 yystate = *yyssp;
1493 yyvsp -= yym; 1524 yyvsp -= yym;
1494 yym = yylhs[yyn]; 1525 yym = yylhs[yyn];
1495 if (yystate == 0 && yym == 0) 1526 if (yystate == 0 && yym == 0)
1496 { 1527 {
1497#if YYDEBUG 1528#if YYDEBUG
1498 if (yydebug) 1529 if (yydebug)
1499 printf("%sdebug: after reduction, shifting from state 0 to\ 1530 printf("%sdebug: after reduction, shifting from state 0 to\
1500 state %d\n", YYPREFIX, YYFINAL); 1531 state %d\n", YYPREFIX, YYFINAL);
1501#endif 1532#endif
1502 yystate = YYFINAL; 1533 yystate = YYFINAL;
1503 *++yyssp = YYFINAL; 1534 *++yyssp = YYFINAL;
1504 *++yyvsp = yyval; 1535 *++yyvsp = yyval;
1505 if (yychar < 0) 1536 if (yychar < 0)
1506 { 1537 {
1507 if ((yychar = yylex()) < 0) yychar = 0; 1538 if ((yychar = yylex()) < 0) yychar = 0;
1508#if YYDEBUG 1539#if YYDEBUG
1509 if (yydebug) 1540 if (yydebug)
1510 { 1541 {
1511 yys = 0; 1542 yys = 0;
1512 if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; 1543 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1513 if (!yys) yys = "illegal-symbol"; 1544 if (!yys) yys = "illegal-symbol";
1514 printf("%sdebug: state %d, reading %d (%s)\n", 1545 printf("%sdebug: state %d, reading %d (%s)\n",
1515 YYPREFIX, YYFINAL, yychar, yys); 1546 YYPREFIX, YYFINAL, yychar, yys);
1516 } 1547 }
1517#endif 1548#endif
1518 } 1549 }
1519 if (yychar == 0) goto yyaccept; 1550 if (yychar == 0) goto yyaccept;
1520 goto yyloop; 1551 goto yyloop;
1521 } 1552 }
1522 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && 1553 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1523 yyn <= YYTABLESIZE && yycheck[yyn] == yystate) 1554 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1524 yystate = yytable[yyn]; 1555 yystate = yytable[yyn];
1525 else 1556 else
1526 yystate = yydgoto[yym]; 1557 yystate = yydgoto[yym];
1527#if YYDEBUG 1558#if YYDEBUG
1528 if (yydebug) 1559 if (yydebug)
1529 printf("%sdebug: after reduction, shifting from state %d \ 1560 printf("%sdebug: after reduction, shifting from state %d \
1530to state %d\n", YYPREFIX, *yyssp, yystate); 1561to state %d\n", YYPREFIX, *yyssp, yystate);
1531#endif 1562#endif
1532 if (yyssp >= yyss + yystacksize - 1) 1563 if (yyssp >= yyss + yystacksize - 1)
1533 { 1564 {
1534 goto yyoverflow; 1565 goto yyoverflow;
1535 } 1566 }
1536 *++yyssp = yystate; 1567 *++yyssp = yystate;
1537 *++yyvsp = yyval; 1568 *++yyvsp = yyval;
1538 goto yyloop; 1569 goto yyloop;
1539yyoverflow: 1570yyoverflow:
1540 yyerror("yacc stack overflow"); 1571 yyerror("yacc stack overflow");
1541yyabort: 1572yyabort:
1542 return (1); 1573 return (1);
1543yyaccept: 1574yyaccept:
1544 return (0); 1575 return (0);
1545} 1576}
diff --git a/library/backend/vobject.cpp b/library/backend/vobject.cpp
index 9c2ba3b..e6f6b78 100644
--- a/library/backend/vobject.cpp
+++ b/library/backend/vobject.cpp
@@ -1,1219 +1,1315 @@
1/*************************************************************************** 1/***************************************************************************
2(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 2(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
3Business Machines Corporation and Siemens Rolm Communications Inc. 3Business Machines Corporation and Siemens Rolm Communications Inc.
4 4
5For purposes of this license notice, the term Licensors shall mean, 5For purposes of this license notice, the term Licensors shall mean,
6collectively, Apple Computer, Inc., AT&T Corp., International 6collectively, Apple Computer, Inc., AT&T Corp., International
7Business Machines Corporation and Siemens Rolm Communications Inc. 7Business Machines Corporation and Siemens Rolm Communications Inc.
8The term Licensor shall mean any of the Licensors. 8The term Licensor shall mean any of the Licensors.
9 9
10Subject to acceptance of the following conditions, permission is hereby 10Subject to acceptance of the following conditions, permission is hereby
11granted by Licensors without the need for written agreement and without 11granted by Licensors without the need for written agreement and without
12license or royalty fees, to use, copy, modify and distribute this 12license or royalty fees, to use, copy, modify and distribute this
13software for any purpose. 13software for any purpose.
14 14
15The above copyright notice and the following four paragraphs must be 15The above copyright notice and the following four paragraphs must be
16reproduced in all copies of this software and any software including 16reproduced in all copies of this software and any software including
17this software. 17this software.
18 18
19THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 19THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
20ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 20ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
21MODIFICATIONS. 21MODIFICATIONS.
22 22
23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE. 26DAMAGE.
27 27
28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31PURPOSE. 31PURPOSE.
32 32
33The software is provided with RESTRICTED RIGHTS. Use, duplication, or 33The software is provided with RESTRICTED RIGHTS. Use, duplication, or
34disclosure by the government are subject to restrictions set forth in 34disclosure by the government are subject to restrictions set forth in
35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
36 36
37***************************************************************************/ 37***************************************************************************/
38 38
39/* 39/*
40 * src: vobject.c 40 * src: vobject.c
41 * doc: vobject and APIs to construct vobject, APIs pretty print 41 * doc: vobject and APIs to construct vobject, APIs pretty print
42 * vobject, and convert a vobject into its textual representation. 42 * vobject, and convert a vobject into its textual representation.
43 */ 43 */
44 44
45 #ifndef MWERKS 45 #ifndef MWERKS
46#include <malloc.h> 46#include <malloc.h>
47#endif 47#endif
48 48
49#include "vobject_p.h" 49#include "vobject_p.h"
50#include "qfiledirect_p.h" 50#include "qfiledirect_p.h"
51#include <string.h> 51#include <string.h>
52#include <stdio.h> 52#include <stdio.h>
53#include <fcntl.h> 53#include <fcntl.h>
54//#include <io.h> 54//#include <io.h>
55 55
56 56
57 #define NAME_OF(o) o->id 57 #define NAME_OF(o) o->id
58 #define VALUE_TYPE(o) o->valType 58 #define VALUE_TYPE(o) o->valType
59 #define STRINGZ_VALUE_OF(o) o->val.strs 59 #define STRINGZ_VALUE_OF(o) o->val.strs
60 #define INTEGER_VALUE_OF(o) o->val.i 60 #define INTEGER_VALUE_OF(o) o->val.i
61 #define LONG_VALUE_OF(o) o->val.l 61 #define LONG_VALUE_OF(o) o->val.l
62 #define ANY_VALUE_OF(o) o->val.any 62 #define ANY_VALUE_OF(o) o->val.any
63 #define VOBJECT_VALUE_OF(o) o->val.vobj 63 #define VOBJECT_VALUE_OF(o) o->val.vobj
64 64
65typedef union ValueItem { 65typedef union ValueItem {
66 const char *strs; 66 const char *strs;
67 unsigned int i; 67 unsigned int i;
68 unsigned long l; 68 unsigned long l;
69 void *any; 69 void *any;
70 VObject *vobj; 70 VObject *vobj;
71 } ValueItem; 71 } ValueItem;
72 72
73struct VObject { 73struct VObject {
74 VObject *next; 74 VObject *next;
75 const char *id; 75 const char *id;
76 VObject *prop; 76 VObject *prop;
77 unsigned short valType; 77 unsigned short valType;
78 ValueItem val; 78 ValueItem val;
79 }; 79 };
80 80
81typedef struct StrItem StrItem; 81typedef struct StrItem StrItem;
82 82
83struct StrItem { 83struct StrItem {
84 StrItem *next; 84 StrItem *next;
85 const char *s; 85 const char *s;
86 unsigned int refCnt; 86 unsigned int refCnt;
87 }; 87 };
88 88
89const char** fieldedProp; 89const char** fieldedProp;
90 90
91 91
92 92
93/*---------------------------------------------------------------------- 93/*----------------------------------------------------------------------
94 The following functions involve with memory allocation: 94 The following functions involve with memory allocation:
95 newVObject 95 newVObject
96 deleteVObject 96 deleteVObject
97 dupStr 97 dupStr
98 deleteStr 98 deleteStr
99 newStrItem 99 newStrItem
100 deleteStrItem 100 deleteStrItem
101 ----------------------------------------------------------------------*/ 101 ----------------------------------------------------------------------*/
102 102
103DLLEXPORT(VObject*) newVObject_(const char *id) 103DLLEXPORT(VObject*) newVObject_(const char *id)
104{ 104{
105 VObject *p = (VObject*)malloc(sizeof(VObject)); 105 VObject *p = (VObject*)malloc(sizeof(VObject));
106 p->next = 0; 106 p->next = 0;
107 p->id = id; 107 p->id = id;
108 p->prop = 0; 108 p->prop = 0;
109 VALUE_TYPE(p) = 0; 109 VALUE_TYPE(p) = 0;
110 ANY_VALUE_OF(p) = 0; 110 ANY_VALUE_OF(p) = 0;
111 return p; 111 return p;
112} 112}
113 113
114DLLEXPORT(VObject*) newVObject(const char *id) 114DLLEXPORT(VObject*) newVObject(const char *id)
115{ 115{
116 return newVObject_(lookupStr(id)); 116 return newVObject_(lookupStr(id));
117} 117}
118 118
119DLLEXPORT(void) deleteVObject(VObject *p) 119DLLEXPORT(void) deleteVObject(VObject *p)
120{ 120{
121 unUseStr(p->id); 121 unUseStr(p->id);
122 free(p); 122 free(p);
123} 123}
124 124
125DLLEXPORT(char*) dupStr(const char *s, unsigned int size) 125DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
126{ 126{
127 char *t; 127 char *t;
128 if (size == 0) { 128 if (size == 0) {
129 size = strlen(s); 129 size = strlen(s);
130 } 130 }
131 t = (char*)malloc(size+1); 131 t = (char*)malloc(size+1);
132 if (t) { 132 if (t) {
133 memcpy(t,s,size); 133 memcpy(t,s,size);
134 t[size] = 0; 134 t[size] = 0;
135 return t; 135 return t;
136 } 136 }
137 else { 137 else {
138 return (char*)0; 138 return (char*)0;
139 } 139 }
140} 140}
141 141
142DLLEXPORT(void) deleteStr(const char *p) 142DLLEXPORT(void) deleteStr(const char *p)
143{ 143{
144 if (p) free((void*)p); 144 if (p) free((void*)p);
145} 145}
146 146
147 147
148static StrItem* newStrItem(const char *s, StrItem *next) 148static StrItem* newStrItem(const char *s, StrItem *next)
149{ 149{
150 StrItem *p = (StrItem*)malloc(sizeof(StrItem)); 150 StrItem *p = (StrItem*)malloc(sizeof(StrItem));
151 p->next = next; 151 p->next = next;
152 p->s = s; 152 p->s = s;
153 p->refCnt = 1; 153 p->refCnt = 1;
154 return p; 154 return p;
155} 155}
156 156
157static void deleteStrItem(StrItem *p) 157static void deleteStrItem(StrItem *p)
158{ 158{
159 free((void*)p); 159 free((void*)p);
160} 160}
161 161
162 162
163/*---------------------------------------------------------------------- 163/*----------------------------------------------------------------------
164 The following function provide accesses to VObject's value. 164 The following function provide accesses to VObject's value.
165 ----------------------------------------------------------------------*/ 165 ----------------------------------------------------------------------*/
166 166
167DLLEXPORT(const char*) vObjectName(VObject *o) 167DLLEXPORT(const char*) vObjectName(VObject *o)
168{ 168{
169 return NAME_OF(o); 169 return NAME_OF(o);
170} 170}
171 171
172DLLEXPORT(void) setVObjectName(VObject *o, const char* id) 172DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
173{ 173{
174 NAME_OF(o) = id; 174 NAME_OF(o) = id;
175} 175}
176 176
177DLLEXPORT(const char*) vObjectStringZValue(VObject *o) 177DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
178{ 178{
179 return STRINGZ_VALUE_OF(o); 179 return STRINGZ_VALUE_OF(o);
180} 180}
181 181
182DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s) 182DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
183{ 183{
184 STRINGZ_VALUE_OF(o) = dupStr(s,0); 184 STRINGZ_VALUE_OF(o) = dupStr(s,0);
185 VALUE_TYPE(o) = VCVT_STRINGZ; 185 VALUE_TYPE(o) = VCVT_STRINGZ;
186} 186}
187 187
188DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s) 188DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
189{ 189{
190 STRINGZ_VALUE_OF(o) = s; 190 STRINGZ_VALUE_OF(o) = s;
191 VALUE_TYPE(o) = VCVT_STRINGZ; 191 VALUE_TYPE(o) = VCVT_STRINGZ;
192} 192}
193 193
194DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o) 194DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
195{ 195{
196 return INTEGER_VALUE_OF(o); 196 return INTEGER_VALUE_OF(o);
197} 197}
198 198
199DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i) 199DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
200{ 200{
201 INTEGER_VALUE_OF(o) = i; 201 INTEGER_VALUE_OF(o) = i;
202 VALUE_TYPE(o) = VCVT_UINT; 202 VALUE_TYPE(o) = VCVT_UINT;
203} 203}
204 204
205DLLEXPORT(unsigned long) vObjectLongValue(VObject *o) 205DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
206{ 206{
207 return LONG_VALUE_OF(o); 207 return LONG_VALUE_OF(o);
208} 208}
209 209
210DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l) 210DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
211{ 211{
212 LONG_VALUE_OF(o) = l; 212 LONG_VALUE_OF(o) = l;
213 VALUE_TYPE(o) = VCVT_ULONG; 213 VALUE_TYPE(o) = VCVT_ULONG;
214} 214}
215 215
216DLLEXPORT(void*) vObjectAnyValue(VObject *o) 216DLLEXPORT(void*) vObjectAnyValue(VObject *o)
217{ 217{
218 return ANY_VALUE_OF(o); 218 return ANY_VALUE_OF(o);
219} 219}
220 220
221DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t) 221DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
222{ 222{
223 ANY_VALUE_OF(o) = t; 223 ANY_VALUE_OF(o) = t;
224 VALUE_TYPE(o) = VCVT_RAW; 224 VALUE_TYPE(o) = VCVT_RAW;
225} 225}
226 226
227DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o) 227DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
228{ 228{
229 return VOBJECT_VALUE_OF(o); 229 return VOBJECT_VALUE_OF(o);
230} 230}
231 231
232DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p) 232DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
233{ 233{
234 VOBJECT_VALUE_OF(o) = p; 234 VOBJECT_VALUE_OF(o) = p;
235 VALUE_TYPE(o) = VCVT_VOBJECT; 235 VALUE_TYPE(o) = VCVT_VOBJECT;
236} 236}
237 237
238DLLEXPORT(int) vObjectValueType(VObject *o) 238DLLEXPORT(int) vObjectValueType(VObject *o)
239{ 239{
240 return VALUE_TYPE(o); 240 return VALUE_TYPE(o);
241} 241}
242 242
243 243
244/*---------------------------------------------------------------------- 244/*----------------------------------------------------------------------
245 The following functions can be used to build VObject. 245 The following functions can be used to build VObject.
246 ----------------------------------------------------------------------*/ 246 ----------------------------------------------------------------------*/
247 247
248DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p) 248DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
249{ 249{
250 /* circular link list pointed to tail */ 250 /* circular link list pointed to tail */
251 /* 251 /*
252 o {next,id,prop,val} 252 o {next,id,prop,val}
253 V 253 V
254 pn {next,id,prop,val} 254 pn {next,id,prop,val}
255 V 255 V
256 ... 256 ...
257 p1 {next,id,prop,val} 257 p1 {next,id,prop,val}
258 V 258 V
259 pn 259 pn
260 --> 260 -->
261 o {next,id,prop,val} 261 o {next,id,prop,val}
262 V 262 V
263 pn {next,id,prop,val} 263 pn {next,id,prop,val}
264 V 264 V
265 p {next,id,prop,val} 265 p {next,id,prop,val}
266 ... 266 ...
267 p1 {next,id,prop,val} 267 p1 {next,id,prop,val}
268 V 268 V
269 pn 269 pn
270 */ 270 */
271 271
272 VObject *tail = o->prop; 272 VObject *tail = o->prop;
273 if (tail) { 273 if (tail) {
274 p->next = tail->next; 274 p->next = tail->next;
275 o->prop = tail->next = p; 275 o->prop = tail->next = p;
276 } 276 }
277 else { 277 else {
278 o->prop = p->next = p; 278 o->prop = p->next = p;
279 } 279 }
280 return p; 280 return p;
281} 281}
282 282
283DLLEXPORT(VObject*) addProp(VObject *o, const char *id) 283DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
284{ 284{
285 return addVObjectProp(o,newVObject(id)); 285 return addVObjectProp(o,newVObject(id));
286} 286}
287 287
288DLLEXPORT(VObject*) addProp_(VObject *o, const char *id) 288DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
289{ 289{
290 return addVObjectProp(o,newVObject_(id)); 290 return addVObjectProp(o,newVObject_(id));
291} 291}
292 292
293DLLEXPORT(void) addList(VObject **o, VObject *p) 293DLLEXPORT(void) addList(VObject **o, VObject *p)
294{ 294{
295 p->next = 0; 295 p->next = 0;
296 if (*o == 0) { 296 if (*o == 0) {
297 *o = p; 297 *o = p;
298 } 298 }
299 else { 299 else {
300 VObject *t = *o; 300 VObject *t = *o;
301 while (t->next) { 301 while (t->next) {
302 t = t->next; 302 t = t->next;
303 } 303 }
304 t->next = p; 304 t->next = p;
305 } 305 }
306} 306}
307 307
308DLLEXPORT(VObject*) nextVObjectInList(VObject *o) 308DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
309{ 309{
310 return o->next; 310 return o->next;
311} 311}
312 312
313DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size) 313DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
314{ 314{
315 VObject *sizeProp; 315 VObject *sizeProp;
316 setVObjectAnyValue(prop, val); 316 setVObjectAnyValue(prop, val);
317 sizeProp = addProp(prop,VCDataSizeProp); 317 sizeProp = addProp(prop,VCDataSizeProp);
318 setVObjectLongValue(sizeProp, size); 318 setVObjectLongValue(sizeProp, size);
319 return prop; 319 return prop;
320} 320}
321 321
322DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size) 322DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
323{ 323{
324 void *p = dupStr((const char *)val,size); 324 void *p = dupStr((const char *)val,size);
325 return setValueWithSize_(prop,p,p?size:0); 325 return setValueWithSize_(prop,p,p?size:0);
326} 326}
327 327
328DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o) 328DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
329{ 329{
330 i->start = o->prop; 330 i->start = o->prop;
331 i->next = 0; 331 i->next = 0;
332} 332}
333 333
334DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o) 334DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
335{ 335{
336 i->start = o->next; 336 i->start = o->next;
337 i->next = 0; 337 i->next = 0;
338} 338}
339 339
340DLLEXPORT(int) moreIteration(VObjectIterator *i) 340DLLEXPORT(int) moreIteration(VObjectIterator *i)
341{ 341{
342 return (i->start && (i->next==0 || i->next!=i->start)); 342 return (i->start && (i->next==0 || i->next!=i->start));
343} 343}
344 344
345DLLEXPORT(VObject*) nextVObject(VObjectIterator *i) 345DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
346{ 346{
347 if (i->start && i->next != i->start) { 347 if (i->start && i->next != i->start) {
348 if (i->next == 0) { 348 if (i->next == 0) {
349 i->next = i->start->next; 349 i->next = i->start->next;
350 return i->next; 350 return i->next;
351 } 351 }
352 else { 352 else {
353 i->next = i->next->next; 353 i->next = i->next->next;
354 return i->next; 354 return i->next;
355 } 355 }
356 } 356 }
357 else return (VObject*)0; 357 else return (VObject*)0;
358} 358}
359 359
360DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id) 360DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
361{ 361{
362 VObjectIterator i; 362 VObjectIterator i;
363 initPropIterator(&i,o); 363 initPropIterator(&i,o);
364 while (moreIteration(&i)) { 364 while (moreIteration(&i)) {
365 VObject *each = nextVObject(&i); 365 VObject *each = nextVObject(&i);
366 if (!qstricmp(id,each->id)) 366 if (!qstricmp(id,each->id))
367 return each; 367 return each;
368 } 368 }
369 return (VObject*)0; 369 return (VObject*)0;
370} 370}
371 371
372DLLEXPORT(VObject*) addGroup(VObject *o, const char *g) 372DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
373{ 373{
374 /* 374 /*
375 a.b.c 375 a.b.c
376 --> 376 -->
377 prop(c) 377 prop(c)
378 prop(VCGrouping=b) 378 prop(VCGrouping=b)
379 prop(VCGrouping=a) 379 prop(VCGrouping=a)
380 */ 380 */
381 char *dot = strrchr(g,'.'); 381 char *dot = strrchr(g,'.');
382 if (dot) { 382 if (dot) {
383 VObject *p, *t; 383 VObject *p, *t;
384 char *gs, *n = dot+1; 384 char *gs, *n = dot+1;
385 gs = dupStr(g,0);/* so we can write to it. */ 385 gs = dupStr(g,0);/* so we can write to it. */
386 /* used to be 386 /* used to be
387 * t = p = addProp_(o,lookupProp_(n)); 387 * t = p = addProp_(o,lookupProp_(n));
388 */ 388 */
389 t = p = addProp_(o,lookupProp(n)); 389 t = p = addProp_(o,lookupProp(n));
390 dot = strrchr(gs,'.'); 390 dot = strrchr(gs,'.');
391 *dot = 0; 391 *dot = 0;
392 do { 392 do {
393 dot = strrchr(gs,'.'); 393 dot = strrchr(gs,'.');
394 if (dot) { 394 if (dot) {
395 n = dot+1; 395 n = dot+1;
396 *dot=0; 396 *dot=0;
397 } 397 }
398 else 398 else
399 n = gs; 399 n = gs;
400 /* property(VCGroupingProp=n); 400 /* property(VCGroupingProp=n);
401 *and the value may have VCGrouping property 401 *and the value may have VCGrouping property
402 */ 402 */
403 t = addProp(t,VCGroupingProp); 403 t = addProp(t,VCGroupingProp);
404 setVObjectStringZValue(t,lookupProp_(n)); 404 setVObjectStringZValue(t,lookupProp_(n));
405 } while (n != gs); 405 } while (n != gs);
406 deleteStr(gs); 406 deleteStr(gs);
407 return p; 407 return p;
408 } 408 }
409 else 409 else
410 return addProp_(o,lookupProp(g)); 410 return addProp_(o,lookupProp(g));
411} 411}
412 412
413DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v) 413DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
414{ 414{
415 VObject *prop; 415 VObject *prop;
416 prop = addProp(o,p); 416 prop = addProp(o,p);
417 setVObjectStringZValue_(prop, strdup( v ) ); 417 setVObjectStringZValue_(prop, strdup( v ) );
418 return prop; 418 return prop;
419} 419}
420 420
421DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, 421DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
422 unsigned int size) 422 unsigned int size)
423{ 423{
424 VObject *prop; 424 VObject *prop;
425 prop = addProp(o,p); 425 prop = addProp(o,p);
426 setValueWithSize_(prop, (void*)v, size); 426 setValueWithSize_(prop, (void*)v, size);
427 return prop; 427 return prop;
428} 428}
429 429
430DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, 430DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
431 unsigned int size) 431 unsigned int size)
432{ 432{
433 return addPropSizedValue_(o,p,dupStr(v,size),size); 433 return addPropSizedValue_(o,p,dupStr(v,size),size);
434} 434}
435 435
436 436
437DLLEXPORT(void) cleanVObject(VObject *o) 437DLLEXPORT(void) cleanVObject(VObject *o)
438{ 438{
439 if (o == 0) return; 439 if (o == 0) return;
440 if (o->prop) { 440 if (o->prop) {
441 /* destroy time: cannot use the iterator here. 441 /* destroy time: cannot use the iterator here.
442 Have to break the cycle in the circular link 442 Have to break the cycle in the circular link
443 list and turns it into regular NULL-terminated 443 list and turns it into regular NULL-terminated
444 list -- since at some point of destruction, 444 list -- since at some point of destruction,
445 the reference entry for the iterator to work 445 the reference entry for the iterator to work
446 will not longer be valid. 446 will not longer be valid.
447 */ 447 */
448 VObject *p; 448 VObject *p;
449 p = o->prop->next; 449 p = o->prop->next;
450 o->prop->next = 0; 450 o->prop->next = 0;
451 do { 451 do {
452 VObject *t = p->next; 452 VObject *t = p->next;
453 cleanVObject(p); 453 cleanVObject(p);
454 p = t; 454 p = t;
455 } while (p); 455 } while (p);
456 } 456 }
457 switch (VALUE_TYPE(o)) { 457 switch (VALUE_TYPE(o)) {
458 case VCVT_STRINGZ: 458 case VCVT_STRINGZ:
459 case VCVT_RAW: 459 case VCVT_RAW:
460 // assume they are all allocated by malloc. 460 // assume they are all allocated by malloc.
461 free((char*)STRINGZ_VALUE_OF(o)); 461 free((char*)STRINGZ_VALUE_OF(o));
462 break; 462 break;
463 case VCVT_VOBJECT: 463 case VCVT_VOBJECT:
464 cleanVObject(VOBJECT_VALUE_OF(o)); 464 cleanVObject(VOBJECT_VALUE_OF(o));
465 break; 465 break;
466 } 466 }
467 deleteVObject(o); 467 deleteVObject(o);
468} 468}
469 469
470DLLEXPORT(void) cleanVObjects(VObject *list) 470DLLEXPORT(void) cleanVObjects(VObject *list)
471{ 471{
472 while (list) { 472 while (list) {
473 VObject *t = list; 473 VObject *t = list;
474 list = nextVObjectInList(list); 474 list = nextVObjectInList(list);
475 cleanVObject(t); 475 cleanVObject(t);
476 } 476 }
477} 477}
478 478
479/*---------------------------------------------------------------------- 479/*----------------------------------------------------------------------
480 The following is a String Table Facilities. 480 The following is a String Table Facilities.
481 ----------------------------------------------------------------------*/ 481 ----------------------------------------------------------------------*/
482 482
483#define STRTBLSIZE 255 483#define STRTBLSIZE 255
484 484
485static StrItem *strTbl[STRTBLSIZE]; 485static StrItem *strTbl[STRTBLSIZE];
486 486
487static unsigned int hashStr(const char *s) 487static unsigned int hashStr(const char *s)
488{ 488{
489 unsigned int h = 0; 489 unsigned int h = 0;
490 int i; 490 int i;
491 for (i=0;s[i];i++) { 491 for (i=0;s[i];i++) {
492 h += s[i]*i; 492 h += s[i]*i;
493 } 493 }
494 return h % STRTBLSIZE; 494 return h % STRTBLSIZE;
495} 495}
496 496
497DLLEXPORT(const char*) lookupStr(const char *s) 497DLLEXPORT(const char*) lookupStr(const char *s)
498{ 498{
499 StrItem *t; 499 StrItem *t;
500 unsigned int h = hashStr(s); 500 unsigned int h = hashStr(s);
501 if ((t = strTbl[h]) != 0) { 501 if ((t = strTbl[h]) != 0) {
502 do { 502 do {
503 if (qstricmp(t->s,s) == 0) { 503 if (qstricmp(t->s,s) == 0) {
504 t->refCnt++; 504 t->refCnt++;
505 return t->s; 505 return t->s;
506 } 506 }
507 t = t->next; 507 t = t->next;
508 } while (t); 508 } while (t);
509 } 509 }
510 s = dupStr(s,0); 510 s = dupStr(s,0);
511 strTbl[h] = newStrItem(s,strTbl[h]); 511 strTbl[h] = newStrItem(s,strTbl[h]);
512 return s; 512 return s;
513} 513}
514 514
515DLLEXPORT(void) unUseStr(const char *s) 515DLLEXPORT(void) unUseStr(const char *s)
516{ 516{
517 StrItem *t, *p; 517 StrItem *t, *p;
518 unsigned int h = hashStr(s); 518 unsigned int h = hashStr(s);
519 if ((t = strTbl[h]) != 0) { 519 if ((t = strTbl[h]) != 0) {
520 p = t; 520 p = t;
521 do { 521 do {
522 if (qstricmp(t->s,s) == 0) { 522 if (qstricmp(t->s,s) == 0) {
523 t->refCnt--; 523 t->refCnt--;
524 if (t->refCnt == 0) { 524 if (t->refCnt == 0) {
525 if (p == strTbl[h]) { 525 if (p == strTbl[h]) {
526 strTbl[h] = t->next; 526 strTbl[h] = t->next;
527 } 527 }
528 else { 528 else {
529 p->next = t->next; 529 p->next = t->next;
530 } 530 }
531 deleteStr(t->s); 531 deleteStr(t->s);
532 deleteStrItem(t); 532 deleteStrItem(t);
533 return; 533 return;
534 } 534 }
535 } 535 }
536 p = t; 536 p = t;
537 t = t->next; 537 t = t->next;
538 } while (t); 538 } while (t);
539 } 539 }
540} 540}
541 541
542DLLEXPORT(void) cleanStrTbl() 542DLLEXPORT(void) cleanStrTbl()
543{ 543{
544 int i; 544 int i;
545 for (i=0; i<STRTBLSIZE;i++) { 545 for (i=0; i<STRTBLSIZE;i++) {
546 StrItem *t = strTbl[i]; 546 StrItem *t = strTbl[i];
547 while (t) { 547 while (t) {
548 StrItem *p; 548 StrItem *p;
549 deleteStr(t->s); 549 deleteStr(t->s);
550 p = t; 550 p = t;
551 t = t->next; 551 t = t->next;
552 deleteStrItem(p); 552 deleteStrItem(p);
553 } while (t); 553 } while (t);
554 strTbl[i] = 0; 554 strTbl[i] = 0;
555 } 555 }
556} 556}
557 557
558 558
559struct PreDefProp { 559struct PreDefProp {
560 const char *name; 560 const char *name;
561 const char *alias; 561 const char *alias;
562 const char** fields; 562 const char** fields;
563 unsigned int flags; 563 unsigned int flags;
564 }; 564 };
565 565
566/* flags in PreDefProp */ 566/* flags in PreDefProp */
567 #define PD_BEGIN0x1 567 #define PD_BEGIN0x1
568 #define PD_INTERNAL0x2 568 #define PD_INTERNAL0x2
569 569
570static const char *adrFields[] = { 570static const char *adrFields[] = {
571 VCPostalBoxProp, 571 VCPostalBoxProp,
572 VCExtAddressProp, 572 VCExtAddressProp,
573 VCStreetAddressProp, 573 VCStreetAddressProp,
574 VCCityProp, 574 VCCityProp,
575 VCRegionProp, 575 VCRegionProp,
576 VCPostalCodeProp, 576 VCPostalCodeProp,
577 VCCountryNameProp, 577 VCCountryNameProp,
578 0 578 0
579}; 579};
580 580
581static const char *nameFields[] = { 581static const char *nameFields[] = {
582 VCFamilyNameProp, 582 VCFamilyNameProp,
583 VCGivenNameProp, 583 VCGivenNameProp,
584 VCAdditionalNamesProp, 584 VCAdditionalNamesProp,
585 VCNamePrefixesProp, 585 VCNamePrefixesProp,
586 VCNameSuffixesProp, 586 VCNameSuffixesProp,
587 NULL 587 NULL
588 }; 588 };
589 589
590static const char *orgFields[] = { 590static const char *orgFields[] = {
591 VCOrgNameProp, 591 VCOrgNameProp,
592 VCOrgUnitProp, 592 VCOrgUnitProp,
593 VCOrgUnit2Prop, 593 VCOrgUnit2Prop,
594 VCOrgUnit3Prop, 594 VCOrgUnit3Prop,
595 VCOrgUnit4Prop, 595 VCOrgUnit4Prop,
596 NULL 596 NULL
597 }; 597 };
598 598
599static const char *AAlarmFields[] = { 599static const char *AAlarmFields[] = {
600 VCRunTimeProp, 600 VCRunTimeProp,
601 VCSnoozeTimeProp, 601 VCSnoozeTimeProp,
602 VCRepeatCountProp, 602 VCRepeatCountProp,
603 VCAudioContentProp, 603 VCAudioContentProp,
604 0 604 0
605 }; 605 };
606 606
607/* ExDate -- has unamed fields */ 607/* ExDate -- has unamed fields */
608/* RDate -- has unamed fields */ 608/* RDate -- has unamed fields */
609 609
610static const char *DAlarmFields[] = { 610static const char *DAlarmFields[] = {
611 VCRunTimeProp, 611 VCRunTimeProp,
612 VCSnoozeTimeProp, 612 VCSnoozeTimeProp,
613 VCRepeatCountProp, 613 VCRepeatCountProp,
614 VCDisplayStringProp, 614 VCDisplayStringProp,
615 0 615 0
616 }; 616 };
617 617
618static const char *MAlarmFields[] = { 618static const char *MAlarmFields[] = {
619 VCRunTimeProp, 619 VCRunTimeProp,
620 VCSnoozeTimeProp, 620 VCSnoozeTimeProp,
621 VCRepeatCountProp, 621 VCRepeatCountProp,
622 VCEmailAddressProp, 622 VCEmailAddressProp,
623 VCNoteProp, 623 VCNoteProp,
624 0 624 0
625 }; 625 };
626 626
627static const char *PAlarmFields[] = { 627static const char *PAlarmFields[] = {
628 VCRunTimeProp, 628 VCRunTimeProp,
629 VCSnoozeTimeProp, 629 VCSnoozeTimeProp,
630 VCRepeatCountProp, 630 VCRepeatCountProp,
631 VCProcedureNameProp, 631 VCProcedureNameProp,
632 0 632 0
633 }; 633 };
634 634
635static struct PreDefProp propNames[] = { 635static struct PreDefProp propNames[] = {
636 { VC7bitProp, 0, 0, 0 }, 636 { VC7bitProp, 0, 0, 0 },
637 { VC8bitProp, 0, 0, 0 }, 637 { VC8bitProp, 0, 0, 0 },
638 { VCAAlarmProp, 0, AAlarmFields, 0 }, 638 { VCAAlarmProp, 0, AAlarmFields, 0 },
639 { VCAdditionalNamesProp, 0, 0, 0 }, 639 { VCAdditionalNamesProp, 0, 0, 0 },
640 { VCAdrProp, 0, adrFields, 0 }, 640 { VCAdrProp, 0, adrFields, 0 },
641 { VCAgentProp, 0, 0, 0 }, 641 { VCAgentProp, 0, 0, 0 },
642 { VCAIFFProp, 0, 0, 0 }, 642 { VCAIFFProp, 0, 0, 0 },
643 { VCAOLProp, 0, 0, 0 }, 643 { VCAOLProp, 0, 0, 0 },
644 { VCAppleLinkProp, 0, 0, 0 }, 644 { VCAppleLinkProp, 0, 0, 0 },
645 { VCAttachProp, 0, 0, 0 }, 645 { VCAttachProp, 0, 0, 0 },
646 { VCAttendeeProp, 0, 0, 0 }, 646 { VCAttendeeProp, 0, 0, 0 },
647 { VCATTMailProp, 0, 0, 0 }, 647 { VCATTMailProp, 0, 0, 0 },
648 { VCAudioContentProp, 0, 0, 0 }, 648 { VCAudioContentProp, 0, 0, 0 },
649 { VCAVIProp, 0, 0, 0 }, 649 { VCAVIProp, 0, 0, 0 },
650 { VCBase64Prop, 0, 0, 0 }, 650 { VCBase64Prop, 0, 0, 0 },
651 { VCBBSProp, 0, 0, 0 }, 651 { VCBBSProp, 0, 0, 0 },
652 { VCBirthDateProp, 0, 0, 0 }, 652 { VCBirthDateProp, 0, 0, 0 },
653 { VCBMPProp, 0, 0, 0 }, 653 { VCBMPProp, 0, 0, 0 },
654 { VCBodyProp, 0, 0, 0 }, 654 { VCBodyProp, 0, 0, 0 },
655 { VCBusinessRoleProp, 0, 0, 0 }, 655 { VCBusinessRoleProp, 0, 0, 0 },
656 { VCCalProp, 0, 0, PD_BEGIN }, 656 { VCCalProp, 0, 0, PD_BEGIN },
657 { VCCaptionProp, 0, 0, 0 }, 657 { VCCaptionProp, 0, 0, 0 },
658 { VCCardProp, 0, 0, PD_BEGIN }, 658 { VCCardProp, 0, 0, PD_BEGIN },
659 { VCCarProp, 0, 0, 0 }, 659 { VCCarProp, 0, 0, 0 },
660 { VCCategoriesProp, 0, 0, 0 }, 660 { VCCategoriesProp, 0, 0, 0 },
661 { VCCellularProp, 0, 0, 0 }, 661 { VCCellularProp, 0, 0, 0 },
662 { VCCGMProp, 0, 0, 0 }, 662 { VCCGMProp, 0, 0, 0 },
663 { VCCharSetProp, 0, 0, 0 }, 663 { VCCharSetProp, 0, 0, 0 },
664 { VCCIDProp, VCContentIDProp, 0, 0 }, 664 { VCCIDProp, VCContentIDProp, 0, 0 },
665 { VCCISProp, 0, 0, 0 }, 665 { VCCISProp, 0, 0, 0 },
666 { VCCityProp, 0, 0, 0 }, 666 { VCCityProp, 0, 0, 0 },
667 { VCClassProp, 0, 0, 0 }, 667 { VCClassProp, 0, 0, 0 },
668 { VCCommentProp, 0, 0, 0 }, 668 { VCCommentProp, 0, 0, 0 },
669 { VCCompletedProp, 0, 0, 0 }, 669 { VCCompletedProp, 0, 0, 0 },
670 { VCContentIDProp, 0, 0, 0 }, 670 { VCContentIDProp, 0, 0, 0 },
671 { VCCountryNameProp, 0, 0, 0 }, 671 { VCCountryNameProp, 0, 0, 0 },
672 { VCDAlarmProp, 0, DAlarmFields, 0 }, 672 { VCDAlarmProp, 0, DAlarmFields, 0 },
673 { VCDataSizeProp, 0, 0, PD_INTERNAL }, 673 { VCDataSizeProp, 0, 0, PD_INTERNAL },
674 { VCDayLightProp, 0, 0, 0 }, 674 { VCDayLightProp, 0, 0, 0 },
675 { VCDCreatedProp, 0, 0, 0 }, 675 { VCDCreatedProp, 0, 0, 0 },
676 { VCDeliveryLabelProp, 0, 0, 0 }, 676 { VCDeliveryLabelProp, 0, 0, 0 },
677 { VCDescriptionProp, 0, 0, 0 }, 677 { VCDescriptionProp, 0, 0, 0 },
678 { VCDIBProp, 0, 0, 0 }, 678 { VCDIBProp, 0, 0, 0 },
679 { VCDisplayStringProp, 0, 0, 0 }, 679 { VCDisplayStringProp, 0, 0, 0 },
680 { VCDomesticProp, 0, 0, 0 }, 680 { VCDomesticProp, 0, 0, 0 },
681 { VCDTendProp, 0, 0, 0 }, 681 { VCDTendProp, 0, 0, 0 },
682 { VCDTstartProp, 0, 0, 0 }, 682 { VCDTstartProp, 0, 0, 0 },
683 { VCDueProp, 0, 0, 0 }, 683 { VCDueProp, 0, 0, 0 },
684 { VCEmailAddressProp, 0, 0, 0 }, 684 { VCEmailAddressProp, 0, 0, 0 },
685 { VCEncodingProp, 0, 0, 0 }, 685 { VCEncodingProp, 0, 0, 0 },
686 { VCEndProp, 0, 0, 0 }, 686 { VCEndProp, 0, 0, 0 },
687 { VCEventProp, 0, 0, PD_BEGIN }, 687 { VCEventProp, 0, 0, PD_BEGIN },
688 { VCEWorldProp, 0, 0, 0 }, 688 { VCEWorldProp, 0, 0, 0 },
689 { VCExNumProp, 0, 0, 0 }, 689 { VCExNumProp, 0, 0, 0 },
690 { VCExpDateProp, 0, 0, 0 }, 690 { VCExpDateProp, 0, 0, 0 },
691 { VCExpectProp, 0, 0, 0 }, 691 { VCExpectProp, 0, 0, 0 },
692 { VCExtAddressProp, 0, 0, 0 }, 692 { VCExtAddressProp, 0, 0, 0 },
693 { VCFamilyNameProp, 0, 0, 0 }, 693 { VCFamilyNameProp, 0, 0, 0 },
694 { VCFaxProp, 0, 0, 0 }, 694 { VCFaxProp, 0, 0, 0 },
695 { VCFullNameProp, 0, 0, 0 }, 695 { VCFullNameProp, 0, 0, 0 },
696 { VCGeoLocationProp, 0, 0, 0 }, 696 { VCGeoLocationProp, 0, 0, 0 },
697 { VCGeoProp, 0, 0, 0 }, 697 { VCGeoProp, 0, 0, 0 },
698 { VCGIFProp, 0, 0, 0 }, 698 { VCGIFProp, 0, 0, 0 },
699 { VCGivenNameProp, 0, 0, 0 }, 699 { VCGivenNameProp, 0, 0, 0 },
700 { VCGroupingProp, 0, 0, 0 }, 700 { VCGroupingProp, 0, 0, 0 },
701 { VCHomeProp, 0, 0, 0 }, 701 { VCHomeProp, 0, 0, 0 },
702 { VCIBMMailProp, 0, 0, 0 }, 702 { VCIBMMailProp, 0, 0, 0 },
703 { VCInlineProp, 0, 0, 0 }, 703 { VCInlineProp, 0, 0, 0 },
704 { VCInternationalProp, 0, 0, 0 }, 704 { VCInternationalProp, 0, 0, 0 },
705 { VCInternetProp, 0, 0, 0 }, 705 { VCInternetProp, 0, 0, 0 },
706 { VCISDNProp, 0, 0, 0 }, 706 { VCISDNProp, 0, 0, 0 },
707 { VCJPEGProp, 0, 0, 0 }, 707 { VCJPEGProp, 0, 0, 0 },
708 { VCLanguageProp, 0, 0, 0 }, 708 { VCLanguageProp, 0, 0, 0 },
709 { VCLastModifiedProp, 0, 0, 0 }, 709 { VCLastModifiedProp, 0, 0, 0 },
710 { VCLastRevisedProp, 0, 0, 0 }, 710 { VCLastRevisedProp, 0, 0, 0 },
711 { VCLocationProp, 0, 0, 0 }, 711 { VCLocationProp, 0, 0, 0 },
712 { VCLogoProp, 0, 0, 0 }, 712 { VCLogoProp, 0, 0, 0 },
713 { VCMailerProp, 0, 0, 0 }, 713 { VCMailerProp, 0, 0, 0 },
714 { VCMAlarmProp, 0, MAlarmFields, 0 }, 714 { VCMAlarmProp, 0, MAlarmFields, 0 },
715 { VCMCIMailProp, 0, 0, 0 }, 715 { VCMCIMailProp, 0, 0, 0 },
716 { VCMessageProp, 0, 0, 0 }, 716 { VCMessageProp, 0, 0, 0 },
717 { VCMETProp, 0, 0, 0 }, 717 { VCMETProp, 0, 0, 0 },
718 { VCModemProp, 0, 0, 0 }, 718 { VCModemProp, 0, 0, 0 },
719 { VCMPEG2Prop, 0, 0, 0 }, 719 { VCMPEG2Prop, 0, 0, 0 },
720 { VCMPEGProp, 0, 0, 0 }, 720 { VCMPEGProp, 0, 0, 0 },
721 { VCMSNProp, 0, 0, 0 }, 721 { VCMSNProp, 0, 0, 0 },
722 { VCNamePrefixesProp, 0, 0, 0 }, 722 { VCNamePrefixesProp, 0, 0, 0 },
723 { VCNameProp, 0, nameFields, 0 }, 723 { VCNameProp, 0, nameFields, 0 },
724 { VCNameSuffixesProp, 0, 0, 0 }, 724 { VCNameSuffixesProp, 0, 0, 0 },
725 { VCNoteProp, 0, 0, 0 }, 725 { VCNoteProp, 0, 0, 0 },
726 { VCOrgNameProp, 0, 0, 0 }, 726 { VCOrgNameProp, 0, 0, 0 },
727 { VCOrgProp, 0, orgFields, 0 }, 727 { VCOrgProp, 0, orgFields, 0 },
728 { VCOrgUnit2Prop, 0, 0, 0 }, 728 { VCOrgUnit2Prop, 0, 0, 0 },
729 { VCOrgUnit3Prop, 0, 0, 0 }, 729 { VCOrgUnit3Prop, 0, 0, 0 },
730 { VCOrgUnit4Prop, 0, 0, 0 }, 730 { VCOrgUnit4Prop, 0, 0, 0 },
731 { VCOrgUnitProp, 0, 0, 0 }, 731 { VCOrgUnitProp, 0, 0, 0 },
732 { VCPagerProp, 0, 0, 0 }, 732 { VCPagerProp, 0, 0, 0 },
733 { VCPAlarmProp, 0, PAlarmFields, 0 }, 733 { VCPAlarmProp, 0, PAlarmFields, 0 },
734 { VCParcelProp, 0, 0, 0 }, 734 { VCParcelProp, 0, 0, 0 },
735 { VCPartProp, 0, 0, 0 }, 735 { VCPartProp, 0, 0, 0 },
736 { VCPCMProp, 0, 0, 0 }, 736 { VCPCMProp, 0, 0, 0 },
737 { VCPDFProp, 0, 0, 0 }, 737 { VCPDFProp, 0, 0, 0 },
738 { VCPGPProp, 0, 0, 0 }, 738 { VCPGPProp, 0, 0, 0 },
739 { VCPhotoProp, 0, 0, 0 }, 739 { VCPhotoProp, 0, 0, 0 },
740 { VCPICTProp, 0, 0, 0 }, 740 { VCPICTProp, 0, 0, 0 },
741 { VCPMBProp, 0, 0, 0 }, 741 { VCPMBProp, 0, 0, 0 },
742 { VCPostalBoxProp, 0, 0, 0 }, 742 { VCPostalBoxProp, 0, 0, 0 },
743 { VCPostalCodeProp, 0, 0, 0 }, 743 { VCPostalCodeProp, 0, 0, 0 },
744 { VCPostalProp, 0, 0, 0 }, 744 { VCPostalProp, 0, 0, 0 },
745 { VCPowerShareProp, 0, 0, 0 }, 745 { VCPowerShareProp, 0, 0, 0 },
746 { VCPreferredProp, 0, 0, 0 }, 746 { VCPreferredProp, 0, 0, 0 },
747 { VCPriorityProp, 0, 0, 0 }, 747 { VCPriorityProp, 0, 0, 0 },
748 { VCProcedureNameProp, 0, 0, 0 }, 748 { VCProcedureNameProp, 0, 0, 0 },
749 { VCProdIdProp, 0, 0, 0 }, 749 { VCProdIdProp, 0, 0, 0 },
750 { VCProdigyProp, 0, 0, 0 }, 750 { VCProdigyProp, 0, 0, 0 },
751 { VCPronunciationProp, 0, 0, 0 }, 751 { VCPronunciationProp, 0, 0, 0 },
752 { VCPSProp, 0, 0, 0 }, 752 { VCPSProp, 0, 0, 0 },
753 { VCPublicKeyProp, 0, 0, 0 }, 753 { VCPublicKeyProp, 0, 0, 0 },
754 { VCQPProp, VCQuotedPrintableProp, 0, 0 }, 754 { VCQPProp, VCQuotedPrintableProp, 0, 0 },
755 { VCQuickTimeProp, 0, 0, 0 }, 755 { VCQuickTimeProp, 0, 0, 0 },
756 { VCQuotedPrintableProp, 0, 0, 0 }, 756 { VCQuotedPrintableProp, 0, 0, 0 },
757 { VCRDateProp, 0, 0, 0 }, 757 { VCRDateProp, 0, 0, 0 },
758 { VCRegionProp, 0, 0, 0 }, 758 { VCRegionProp, 0, 0, 0 },
759 { VCRelatedToProp, 0, 0, 0 }, 759 { VCRelatedToProp, 0, 0, 0 },
760 { VCRepeatCountProp, 0, 0, 0 }, 760 { VCRepeatCountProp, 0, 0, 0 },
761 { VCResourcesProp, 0, 0, 0 }, 761 { VCResourcesProp, 0, 0, 0 },
762 { VCRNumProp, 0, 0, 0 }, 762 { VCRNumProp, 0, 0, 0 },
763 { VCRoleProp, 0, 0, 0 }, 763 { VCRoleProp, 0, 0, 0 },
764 { VCRRuleProp, 0, 0, 0 }, 764 { VCRRuleProp, 0, 0, 0 },
765 { VCRSVPProp, 0, 0, 0 }, 765 { VCRSVPProp, 0, 0, 0 },
766 { VCRunTimeProp, 0, 0, 0 }, 766 { VCRunTimeProp, 0, 0, 0 },
767 { VCSequenceProp, 0, 0, 0 }, 767 { VCSequenceProp, 0, 0, 0 },
768 { VCSnoozeTimeProp, 0, 0, 0 }, 768 { VCSnoozeTimeProp, 0, 0, 0 },
769 { VCStartProp, 0, 0, 0 }, 769 { VCStartProp, 0, 0, 0 },
770 { VCStatusProp, 0, 0, 0 }, 770 { VCStatusProp, 0, 0, 0 },
771 { VCStreetAddressProp, 0, 0, 0 }, 771 { VCStreetAddressProp, 0, 0, 0 },
772 { VCSubTypeProp, 0, 0, 0 }, 772 { VCSubTypeProp, 0, 0, 0 },
773 { VCSummaryProp, 0, 0, 0 }, 773 { VCSummaryProp, 0, 0, 0 },
774 { VCTelephoneProp, 0, 0, 0 }, 774 { VCTelephoneProp, 0, 0, 0 },
775 { VCTIFFProp, 0, 0, 0 }, 775 { VCTIFFProp, 0, 0, 0 },
776 { VCTimeZoneProp, 0, 0, 0 }, 776 { VCTimeZoneProp, 0, 0, 0 },
777 { VCTitleProp, 0, 0, 0 }, 777 { VCTitleProp, 0, 0, 0 },
778 { VCTLXProp, 0, 0, 0 }, 778 { VCTLXProp, 0, 0, 0 },
779 { VCTodoProp, 0, 0, PD_BEGIN }, 779 { VCTodoProp, 0, 0, PD_BEGIN },
780 { VCTranspProp, 0, 0, 0 }, 780 { VCTranspProp, 0, 0, 0 },
781 { VCUniqueStringProp, 0, 0, 0 }, 781 { VCUniqueStringProp, 0, 0, 0 },
782 { VCURLProp, 0, 0, 0 }, 782 { VCURLProp, 0, 0, 0 },
783 { VCURLValueProp, 0, 0, 0 }, 783 { VCURLValueProp, 0, 0, 0 },
784 { VCValueProp, 0, 0, 0 }, 784 { VCValueProp, 0, 0, 0 },
785 { VCVersionProp, 0, 0, 0 }, 785 { VCVersionProp, 0, 0, 0 },
786 { VCVideoProp, 0, 0, 0 }, 786 { VCVideoProp, 0, 0, 0 },
787 { VCVoiceProp, 0, 0, 0 }, 787 { VCVoiceProp, 0, 0, 0 },
788 { VCWAVEProp, 0, 0, 0 }, 788 { VCWAVEProp, 0, 0, 0 },
789 { VCWMFProp, 0, 0, 0 }, 789 { VCWMFProp, 0, 0, 0 },
790 { VCWorkProp, 0, 0, 0 }, 790 { VCWorkProp, 0, 0, 0 },
791 { VCX400Prop, 0, 0, 0 }, 791 { VCX400Prop, 0, 0, 0 },
792 { VCX509Prop, 0, 0, 0 }, 792 { VCX509Prop, 0, 0, 0 },
793 { VCXRuleProp, 0, 0, 0 }, 793 { VCXRuleProp, 0, 0, 0 },
794 { 0,0,0,0 } 794 { 0,0,0,0 }
795 }; 795 };
796 796
797 797
798static struct PreDefProp* lookupPropInfo(const char* str) 798static struct PreDefProp* lookupPropInfo(const char* str)
799{ 799{
800 /* brute force for now, could use a hash table here. */ 800 /* brute force for now, could use a hash table here. */
801 int i; 801 int i;
802 802
803 for (i = 0; propNames[i].name; i++) 803 for (i = 0; propNames[i].name; i++)
804 if (qstricmp(str, propNames[i].name) == 0) { 804 if (qstricmp(str, propNames[i].name) == 0) {
805 return &propNames[i]; 805 return &propNames[i];
806 } 806 }
807 807
808 return 0; 808 return 0;
809} 809}
810 810
811 811
812DLLEXPORT(const char*) lookupProp_(const char* str) 812DLLEXPORT(const char*) lookupProp_(const char* str)
813{ 813{
814 int i; 814 int i;
815 815
816 for (i = 0; propNames[i].name; i++) 816 for (i = 0; propNames[i].name; i++)
817 if (qstricmp(str, propNames[i].name) == 0) { 817 if (qstricmp(str, propNames[i].name) == 0) {
818 const char* s; 818 const char* s;
819 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 819 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
820 return lookupStr(s); 820 return lookupStr(s);
821 } 821 }
822 return lookupStr(str); 822 return lookupStr(str);
823} 823}
824 824
825 825
826DLLEXPORT(const char*) lookupProp(const char* str) 826DLLEXPORT(const char*) lookupProp(const char* str)
827{ 827{
828 int i; 828 int i;
829 829
830 for (i = 0; propNames[i].name; i++) 830 for (i = 0; propNames[i].name; i++)
831 if (qstricmp(str, propNames[i].name) == 0) { 831 if (qstricmp(str, propNames[i].name) == 0) {
832 const char *s; 832 const char *s;
833 fieldedProp = propNames[i].fields; 833 fieldedProp = propNames[i].fields;
834 s = propNames[i].alias?propNames[i].alias:propNames[i].name; 834 s = propNames[i].alias?propNames[i].alias:propNames[i].name;
835 return lookupStr(s); 835 return lookupStr(s);
836 } 836 }
837 fieldedProp = 0; 837 fieldedProp = 0;
838 return lookupStr(str); 838 return lookupStr(str);
839} 839}
840 840
841 841
842/*---------------------------------------------------------------------- 842/*----------------------------------------------------------------------
843 APIs to Output text form. 843 APIs to Output text form.
844 ----------------------------------------------------------------------*/ 844 ----------------------------------------------------------------------*/
845#define OFILE_REALLOC_SIZE 256 845#define OFILE_REALLOC_SIZE 256
846typedef struct OFile { 846typedef struct OFile {
847 FILE *fp; 847 FILE *fp;
848 char *s; 848 char *s;
849 int len; 849 int len;
850 int limit; 850 int limit;
851 int alloc:1; 851 int alloc:1;
852 int fail:1; 852 int fail:1;
853 } OFile; 853 } OFile;
854 854
855#if 0 855#if 0
856static void appendsOFile(OFile *fp, const char *s) 856static void appendsOFile(OFile *fp, const char *s)
857{ 857{
858 int slen; 858 int slen;
859 if (fp->fail) return; 859 if (fp->fail) return;
860 slen = strlen(s); 860 slen = strlen(s);
861 if (fp->fp) { 861 if (fp->fp) {
862 fwrite(s,1,slen,fp->fp); 862 fwrite(s,1,slen,fp->fp);
863 } 863 }
864 else { 864 else {
865stuff: 865stuff:
866 if (fp->len + slen < fp->limit) { 866 if (fp->len + slen < fp->limit) {
867 memcpy(fp->s+fp->len,s,slen); 867 memcpy(fp->s+fp->len,s,slen);
868 fp->len += slen; 868 fp->len += slen;
869 return; 869 return;
870 } 870 }
871 else if (fp->alloc) { 871 else if (fp->alloc) {
872 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 872 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
873 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen; 873 if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
874 fp->s = (char *) realloc(fp->s,fp->limit); 874 fp->s = (char *) realloc(fp->s,fp->limit);
875 if (fp->s) goto stuff; 875 if (fp->s) goto stuff;
876 } 876 }
877 if (fp->alloc) 877 if (fp->alloc)
878 free(fp->s); 878 free(fp->s);
879 fp->s = 0; 879 fp->s = 0;
880 fp->fail = 1; 880 fp->fail = 1;
881 } 881 }
882} 882}
883 883
884static void appendcOFile(OFile *fp, char c) 884static void appendcOFile(OFile *fp, char c)
885{ 885{
886 if (fp->fail) return; 886 if (fp->fail) return;
887 if (fp->fp) { 887 if (fp->fp) {
888 fputc(c,fp->fp); 888 fputc(c,fp->fp);
889 } 889 }
890 else { 890 else {
891stuff: 891stuff:
892 if (fp->len+1 < fp->limit) { 892 if (fp->len+1 < fp->limit) {
893 fp->s[fp->len] = c; 893 fp->s[fp->len] = c;
894 fp->len++; 894 fp->len++;
895 return; 895 return;
896 } 896 }
897 else if (fp->alloc) { 897 else if (fp->alloc) {
898 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 898 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
899 fp->s = (char *) realloc(fp->s,fp->limit); 899 fp->s = (char *) realloc(fp->s,fp->limit);
900 if (fp->s) goto stuff; 900 if (fp->s) goto stuff;
901 } 901 }
902 if (fp->alloc) 902 if (fp->alloc)
903 free(fp->s); 903 free(fp->s);
904 fp->s = 0; 904 fp->s = 0;
905 fp->fail = 1; 905 fp->fail = 1;
906 } 906 }
907} 907}
908#else 908#else
909static void appendcOFile_(OFile *fp, char c) 909static void appendcOFile_(OFile *fp, char c)
910{ 910{
911 if (fp->fail) return; 911 if (fp->fail) return;
912 if (fp->fp) { 912 if (fp->fp) {
913 fputc(c,fp->fp); 913 fputc(c,fp->fp);
914 } 914 }
915 else { 915 else {
916stuff: 916stuff:
917 if (fp->len+1 < fp->limit) { 917 if (fp->len+1 < fp->limit) {
918 fp->s[fp->len] = c; 918 fp->s[fp->len] = c;
919 fp->len++; 919 fp->len++;
920 return; 920 return;
921 } 921 }
922 else if (fp->alloc) { 922 else if (fp->alloc) {
923 fp->limit = fp->limit + OFILE_REALLOC_SIZE; 923 fp->limit = fp->limit + OFILE_REALLOC_SIZE;
924 fp->s = (char *)realloc(fp->s,fp->limit); 924 fp->s = (char *)realloc(fp->s,fp->limit);
925 if (fp->s) goto stuff; 925 if (fp->s) goto stuff;
926 } 926 }
927 if (fp->alloc) 927 if (fp->alloc)
928 free(fp->s); 928 free(fp->s);
929 fp->s = 0; 929 fp->s = 0;
930 fp->fail = 1; 930 fp->fail = 1;
931 } 931 }
932} 932}
933 933
934static void appendcOFile(OFile *fp, char c) 934static void appendcOFile(OFile *fp, char c)
935{ 935{
936 if (c == '\n') { 936 if (c == '\n') {
937 /* write out as <CR><LF> */ 937 /* write out as <CR><LF> */
938 appendcOFile_(fp,0xd); 938 appendcOFile_(fp,0xd);
939 appendcOFile_(fp,0xa); 939 appendcOFile_(fp,0xa);
940 } 940 }
941 else 941 else
942 appendcOFile_(fp,c); 942 appendcOFile_(fp,c);
943} 943}
944 944
945static void appendsOFile(OFile *fp, const char *s) 945static void appendsOFile(OFile *fp, const char *s)
946{ 946{
947 int i, slen; 947 int i, slen;
948 slen = strlen(s); 948 slen = strlen(s);
949 for (i=0; i<slen; i++) { 949 for (i=0; i<slen; i++) {
950 appendcOFile(fp,s[i]); 950 appendcOFile(fp,s[i]);
951 } 951 }
952} 952}
953 953
954#endif 954#endif
955 955
956static void initOFile(OFile *fp, FILE *ofp) 956static void initOFile(OFile *fp, FILE *ofp)
957{ 957{
958 fp->fp = ofp; 958 fp->fp = ofp;
959 fp->s = 0; 959 fp->s = 0;
960 fp->len = 0; 960 fp->len = 0;
961 fp->limit = 0; 961 fp->limit = 0;
962 fp->alloc = 0; 962 fp->alloc = 0;
963 fp->fail = 0; 963 fp->fail = 0;
964} 964}
965 965
966static int writeBase64(OFile *fp, unsigned char *s, long len) 966static int writeBase64(OFile *fp, unsigned char *s, long len)
967{ 967{
968 long cur = 0; 968 long cur = 0;
969 int i, numQuads = 0; 969 int i, numQuads = 0;
970 unsigned long trip; 970 unsigned long trip;
971 unsigned char b; 971 unsigned char b;
972 char quad[5]; 972 char quad[5];
973#define MAXQUADS 16 973#define MAXQUADS 16
974 974
975 quad[4] = 0; 975 quad[4] = 0;
976 976
977 while (cur < len) { 977 while (cur < len) {
978 // collect the triplet of bytes into 'trip' 978 // collect the triplet of bytes into 'trip'
979 trip = 0; 979 trip = 0;
980 for (i = 0; i < 3; i++) { 980 for (i = 0; i < 3; i++) {
981 b = (cur < len) ? *(s + cur) : 0; 981 b = (cur < len) ? *(s + cur) : 0;
982 cur++; 982 cur++;
983 trip = trip << 8 | b; 983 trip = trip << 8 | b;
984 } 984 }
985 // fill in 'quad' with the appropriate four characters 985 // fill in 'quad' with the appropriate four characters
986 for (i = 3; i >= 0; i--) { 986 for (i = 3; i >= 0; i--) {
987 b = (unsigned char)(trip & 0x3F); 987 b = (unsigned char)(trip & 0x3F);
988 trip = trip >> 6; 988 trip = trip >> 6;
989 if ((3 - i) < (cur - len)) 989 if ((3 - i) < (cur - len))
990 quad[i] = '='; // pad char 990 quad[i] = '='; // pad char
991 else if (b < 26) quad[i] = (char)b + 'A'; 991 else if (b < 26) quad[i] = (char)b + 'A';
992 else if (b < 52) quad[i] = (char)(b - 26) + 'a'; 992 else if (b < 52) quad[i] = (char)(b - 26) + 'a';
993 else if (b < 62) quad[i] = (char)(b - 52) + '0'; 993 else if (b < 62) quad[i] = (char)(b - 52) + '0';
994 else if (b == 62) quad[i] = '+'; 994 else if (b == 62) quad[i] = '+';
995 else quad[i] = '/'; 995 else quad[i] = '/';
996 } 996 }
997 // now output 'quad' with appropriate whitespace and line ending 997 // now output 'quad' with appropriate whitespace and line ending
998 appendsOFile(fp, (numQuads == 0 ? " " : "")); 998 appendsOFile(fp, (numQuads == 0 ? " " : ""));
999 appendsOFile(fp, quad); 999 appendsOFile(fp, quad);
1000 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : ""))); 1000 appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
1001 numQuads = (numQuads + 1) % MAXQUADS; 1001 numQuads = (numQuads + 1) % MAXQUADS;
1002 } 1002 }
1003 appendcOFile(fp,'\n'); 1003 appendcOFile(fp,'\n');
1004 1004
1005 return 1; 1005 return 1;
1006} 1006}
1007 1007
1008static void writeQPString(OFile *fp, const char *s) 1008static const char *replaceChar(unsigned char c)
1009{ 1009{
1010 const char *p = s; 1010 if (c == '\n') {
1011 while (*p) { 1011 return "=0A=\n";
1012 if (*p == '\n') { 1012 } else if (
1013 if (p[1]) appendsOFile(fp,"=0A="); 1013 (c >= 'A' && c <= 'Z')
1014 } 1014 ||
1015 appendcOFile(fp,*p); 1015 (c >= 'a' && c <= 'z')
1016 p++; 1016 ||
1017 } 1017 (c >= '0' && c <= '9')
1018} 1018 ||
1019 1019 (c >= '\'' && c <= ')')
1020 1020 ||
1021 1021 (c >= '+' && c <= '-')
1022static void writeVObject_(OFile *fp, VObject *o); 1022 ||
1023 1023 (c == '/')
1024static void writeValue(OFile *fp, VObject *o, unsigned long size) 1024 ||
1025{ 1025 (c == '?')
1026 if (o == 0) return; 1026 ||
1027 switch (VALUE_TYPE(o)) { 1027 (c == ' '))
1028 case VCVT_STRINGZ: { 1028 {
1029 writeQPString(fp, STRINGZ_VALUE_OF(o)); 1029 return 0;
1030 break; 1030 }
1031 } 1031
1032 case VCVT_UINT: { 1032 static char trans[4];
1033 char buf[16]; 1033 trans[0] = '=';
1034 sprintf(buf,"%u", INTEGER_VALUE_OF(o)); 1034 trans[3] = '\0';
1035 appendsOFile(fp,buf); 1035 int rem = c % 16;
1036 break; 1036 int div = c / 16;
1037 } 1037
1038 case VCVT_ULONG: { 1038 if (div < 10)
1039 char buf[16]; 1039 trans[1] = '0' + div;
1040 sprintf(buf,"%lu", LONG_VALUE_OF(o)); 1040 else
1041 appendsOFile(fp,buf); 1041 trans[1] = 'A' + (div - 10);
1042 break; 1042
1043 } 1043 if (rem < 10)
1044 case VCVT_RAW: { 1044 trans[2] = '0' + rem;
1045 appendcOFile(fp,'\n'); 1045 else
1046 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size); 1046 trans[2] = 'A' + (rem - 10);
1047 break; 1047
1048 } 1048 return trans;
1049 case VCVT_VOBJECT: 1049}
1050 appendcOFile(fp,'\n'); 1050
1051 writeVObject_(fp,VOBJECT_VALUE_OF(o)); 1051static void writeQPString(OFile *fp, const char *s)
1052 break; 1052{
1053 } 1053 /*
1054} 1054 only A-Z, 0-9 and
1055 1055 "'" (ASCII code 39)
1056static void writeAttrValue(OFile *fp, VObject *o) 1056 "(" (ASCII code 40)
1057{ 1057 ")" (ASCII code 41)
1058 if (NAME_OF(o)) { 1058 "+" (ASCII code 43)
1059 struct PreDefProp *pi; 1059 "," (ASCII code 44)
1060 pi = lookupPropInfo(NAME_OF(o)); 1060 "-" (ASCII code 45)
1061 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return; 1061 "/" (ASCII code 47)
1062 appendcOFile(fp,';'); 1062 "?" (ASCII code 63)
1063 appendsOFile(fp,NAME_OF(o)); 1063
1064 } 1064 should remain un-encoded.
1065 else 1065 '=' needs to be encoded as it is the escape character.
1066 appendcOFile(fp,';'); 1066 ';' needs to be as it is a field separator.
1067 if (VALUE_TYPE(o)) { 1067
1068 appendcOFile(fp,'='); 1068 */
1069 writeValue(fp,o,0); 1069 const char *p = s;
1070 } 1070 while (*p) {
1071} 1071 const char *rep = replaceChar(*p);
1072 1072 if (rep)
1073static void writeGroup(OFile *fp, VObject *o) 1073 appendsOFile(fp, rep);
1074{ 1074 else
1075 char buf1[256]; 1075 appendcOFile(fp, *p);
1076 char buf2[256]; 1076 p++;
1077 strcpy(buf1,NAME_OF(o)); 1077 }
1078 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) { 1078}
1079 strcpy(buf2,STRINGZ_VALUE_OF(o)); 1079
1080 strcat(buf2,"."); 1080static bool includesUnprintable(VObject *o)
1081 strcat(buf2,buf1); 1081{
1082 strcpy(buf1,buf2); 1082 if (o) {
1083 } 1083 if (VALUE_TYPE(o) == VCVT_STRINGZ) {
1084 appendsOFile(fp,buf1); 1084 const char *p = STRINGZ_VALUE_OF(o);
1085} 1085 if (p) {
1086 1086 while (*p) {
1087static int inList(const char **list, const char *s) 1087 if (replaceChar(*p))
1088{ 1088 return TRUE;
1089 if (list == 0) return 0; 1089 p++;
1090 while (*list) { 1090 }
1091 if (qstricmp(*list,s) == 0) return 1; 1091 }
1092 list++; 1092 }
1093 } 1093 }
1094 return 0; 1094 return FALSE;
1095} 1095}
1096 1096
1097static void writeProp(OFile *fp, VObject *o) 1097static void writeVObject_(OFile *fp, VObject *o);
1098{ 1098
1099 if (NAME_OF(o)) { 1099static void writeValue(OFile *fp, VObject *o, unsigned long size)
1100 struct PreDefProp *pi; 1100{
1101 VObjectIterator t; 1101 if (o == 0) return;
1102 const char **fields_ = 0; 1102 switch (VALUE_TYPE(o)) {
1103 pi = lookupPropInfo(NAME_OF(o)); 1103 case VCVT_STRINGZ: {
1104 if (pi && ((pi->flags & PD_BEGIN) != 0)) { 1104 writeQPString(fp, STRINGZ_VALUE_OF(o));
1105 writeVObject_(fp,o); 1105 break;
1106 return; 1106 }
1107 } 1107 case VCVT_UINT: {
1108 if (isAPropertyOf(o,VCGroupingProp)) 1108 char buf[16];
1109 writeGroup(fp,o); 1109 sprintf(buf,"%u", INTEGER_VALUE_OF(o));
1110 else 1110 appendsOFile(fp,buf);
1111 appendsOFile(fp,NAME_OF(o)); 1111 break;
1112 if (pi) fields_ = pi->fields; 1112 }
1113 initPropIterator(&t,o); 1113 case VCVT_ULONG: {
1114 while (moreIteration(&t)) { 1114 char buf[16];
1115 const char *s; 1115 sprintf(buf,"%lu", LONG_VALUE_OF(o));
1116 VObject *eachProp = nextVObject(&t); 1116 appendsOFile(fp,buf);
1117 s = NAME_OF(eachProp); 1117 break;
1118 if (qstricmp(VCGroupingProp,s) && !inList(fields_,s)) 1118 }
1119 writeAttrValue(fp,eachProp); 1119 case VCVT_RAW: {
1120 } 1120 appendcOFile(fp,'\n');
1121 if (fields_) { 1121 writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
1122 int i = 0, n = 0; 1122 break;
1123 const char** fields = fields_; 1123 }
1124 /* output prop as fields */ 1124 case VCVT_VOBJECT:
1125 appendcOFile(fp,':'); 1125 appendcOFile(fp,'\n');
1126 while (*fields) { 1126 writeVObject_(fp,VOBJECT_VALUE_OF(o));
1127 VObject *t = isAPropertyOf(o,*fields); 1127 break;
1128 i++; 1128 }
1129 if (t) n = i; 1129}
1130 fields++; 1130
1131 } 1131static void writeAttrValue(OFile *fp, VObject *o)
1132 fields = fields_; 1132{
1133 for (i=0;i<n;i++) { 1133 if (NAME_OF(o)) {
1134 writeValue(fp,isAPropertyOf(o,*fields),0); 1134 struct PreDefProp *pi;
1135 fields++; 1135 pi = lookupPropInfo(NAME_OF(o));
1136 if (i<(n-1)) appendcOFile(fp,';'); 1136 if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
1137 } 1137 if ( includesUnprintable(o) ) {
1138 } 1138 appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
1139 } 1139 appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
1140 1140 }
1141 if (VALUE_TYPE(o)) { 1141 appendcOFile(fp,';');
1142 unsigned long size = 0; 1142 appendsOFile(fp,NAME_OF(o));
1143 VObject *p = isAPropertyOf(o,VCDataSizeProp); 1143 }
1144 if (p) size = LONG_VALUE_OF(p); 1144 else
1145 appendcOFile(fp,':'); 1145 appendcOFile(fp,';');
1146 writeValue(fp,o,size); 1146 if (VALUE_TYPE(o)) {
1147 } 1147 appendcOFile(fp,'=');
1148 1148 writeValue(fp,o,0);
1149 appendcOFile(fp,'\n'); 1149 }
1150} 1150}
1151 1151
1152static void writeVObject_(OFile *fp, VObject *o) 1152static void writeGroup(OFile *fp, VObject *o)
1153{ 1153{
1154 if (NAME_OF(o)) { 1154 char buf1[256];
1155 struct PreDefProp *pi; 1155 char buf2[256];
1156 pi = lookupPropInfo(NAME_OF(o)); 1156 strcpy(buf1,NAME_OF(o));
1157 1157 while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
1158 if (pi && ((pi->flags & PD_BEGIN) != 0)) { 1158 strcpy(buf2,STRINGZ_VALUE_OF(o));
1159 VObjectIterator t; 1159 strcat(buf2,".");
1160 const char *begin = NAME_OF(o); 1160 strcat(buf2,buf1);
1161 appendsOFile(fp,"BEGIN:"); 1161 strcpy(buf1,buf2);
1162 appendsOFile(fp,begin); 1162 }
1163 appendcOFile(fp,'\n'); 1163 appendsOFile(fp,buf1);
1164 initPropIterator(&t,o); 1164}
1165 while (moreIteration(&t)) { 1165
1166 VObject *eachProp = nextVObject(&t); 1166static int inList(const char **list, const char *s)
1167 writeProp(fp, eachProp); 1167{
1168 } 1168 if (list == 0) return 0;
1169 appendsOFile(fp,"END:"); 1169 while (*list) {
1170 appendsOFile(fp,begin); 1170 if (qstricmp(*list,s) == 0) return 1;
1171 appendsOFile(fp,"\n\n"); 1171 list++;
1172 } 1172 }
1173 } 1173 return 0;
1174} 1174}
1175 1175
1176void writeVObject(FILE *fp, VObject *o) 1176static void writeProp(OFile *fp, VObject *o)
1177{ 1177{
1178 OFile ofp; 1178 if (NAME_OF(o)) {
1179 // ##### 1179 struct PreDefProp *pi;
1180 //_setmode(_fileno(fp), _O_BINARY); 1180 VObjectIterator t;
1181 initOFile(&ofp,fp); 1181 const char **fields_ = 0;
1182 writeVObject_(&ofp,o); 1182 pi = lookupPropInfo(NAME_OF(o));
1183} 1183 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1184 1184 writeVObject_(fp,o);
1185DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o) 1185 return;
1186{ 1186 }
1187 QFileDirect f( fname); 1187 if (isAPropertyOf(o,VCGroupingProp))
1188 if ( !f.open( IO_WriteOnly ) ) { 1188 writeGroup(fp,o);
1189 qWarning("Unable to open vobject write %s", fname); 1189 else
1190 return; 1190 appendsOFile(fp,NAME_OF(o));
1191 } 1191 if (pi) fields_ = pi->fields;
1192 1192 initPropIterator(&t,o);
1193 writeVObject( f.directHandle(),o ); 1193 while (moreIteration(&t)) {
1194} 1194 const char *s;
1195 1195 VObject *eachProp = nextVObject(&t);
1196DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list) 1196 s = NAME_OF(eachProp);
1197{ 1197 if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
1198 QFileDirect f( fname); 1198 writeAttrValue(fp,eachProp);
1199 if ( !f.open( IO_WriteOnly ) ) { 1199 }
1200 qWarning("Unable to open vobject write %s", fname); 1200 if (fields_) {
1201 return; 1201 int i = 0, n = 0;
1202 } 1202 const char** fields = fields_;
1203 1203 /* output prop as fields */
1204 while (list) { 1204 bool printable = TRUE;
1205 writeVObject(f.directHandle(),list); 1205 while (*fields && printable) {
1206 list = nextVObjectInList(list); 1206 VObject *t = isAPropertyOf(o,*fields);
1207 } 1207 if (includesUnprintable(t))
1208} 1208 printable = FALSE;
1209 1209 fields++;
1210DLLEXPORT(const char *) vObjectTypeInfo(VObject *o) 1210 }
1211{ 1211 fields = fields_;
1212 const char *type = vObjectName( o ); 1212 if (!printable) {
1213 if ( strcmp( type, "TYPE" ) == 0 ) 1213 appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
1214 type = vObjectStringZValue( o ); 1214 appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
1215 return type; 1215 }
1216} 1216 appendcOFile(fp,':');
1217 1217 while (*fields) {
1218 1218 VObject *t = isAPropertyOf(o,*fields);
1219// end of source file vobject.c 1219 i++;
1220 if (t) n = i;
1221 fields++;
1222 }
1223 fields = fields_;
1224 for (i=0;i<n;i++) {
1225 writeValue(fp,isAPropertyOf(o,*fields),0);
1226 fields++;
1227 if (i<(n-1)) appendcOFile(fp,';');
1228 }
1229 }
1230 }
1231
1232
1233 if (VALUE_TYPE(o)) {
1234 if ( includesUnprintable(o) ) {
1235 appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
1236 appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
1237 }
1238 unsigned long size = 0;
1239 VObject *p = isAPropertyOf(o,VCDataSizeProp);
1240 if (p) size = LONG_VALUE_OF(p);
1241 appendcOFile(fp,':');
1242 writeValue(fp,o,size);
1243 }
1244
1245 appendcOFile(fp,'\n');
1246}
1247
1248static void writeVObject_(OFile *fp, VObject *o)
1249{
1250 if (NAME_OF(o)) {
1251 struct PreDefProp *pi;
1252 pi = lookupPropInfo(NAME_OF(o));
1253
1254 if (pi && ((pi->flags & PD_BEGIN) != 0)) {
1255 VObjectIterator t;
1256 const char *begin = NAME_OF(o);
1257 appendsOFile(fp,"BEGIN:");
1258 appendsOFile(fp,begin);
1259 appendcOFile(fp,'\n');
1260 initPropIterator(&t,o);
1261 while (moreIteration(&t)) {
1262 VObject *eachProp = nextVObject(&t);
1263 writeProp(fp, eachProp);
1264 }
1265 appendsOFile(fp,"END:");
1266 appendsOFile(fp,begin);
1267 appendsOFile(fp,"\n\n");
1268 }
1269 }
1270}
1271
1272void writeVObject(FILE *fp, VObject *o)
1273{
1274 OFile ofp;
1275 // #####
1276 //_setmode(_fileno(fp), _O_BINARY);
1277 initOFile(&ofp,fp);
1278 writeVObject_(&ofp,o);
1279}
1280
1281DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
1282{
1283 QFileDirect f( fname);
1284 if ( !f.open( IO_WriteOnly ) ) {
1285 qWarning("Unable to open vobject write %s", fname);
1286 return;
1287 }
1288
1289 writeVObject( f.directHandle(),o );
1290}
1291
1292DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
1293{
1294 QFileDirect f( fname);
1295 if ( !f.open( IO_WriteOnly ) ) {
1296 qWarning("Unable to open vobject write %s", fname);
1297 return;
1298 }
1299
1300 while (list) {
1301 writeVObject(f.directHandle(),list);
1302 list = nextVObjectInList(list);
1303 }
1304}
1305
1306DLLEXPORT(const char *) vObjectTypeInfo(VObject *o)
1307{
1308 const char *type = vObjectName( o );
1309 if ( strcmp( type, "TYPE" ) == 0 )
1310 type = vObjectStringZValue( o );
1311 return type;
1312}
1313
1314
1315// end of source file vobject.c
diff --git a/library/backend/vobject_p.h b/library/backend/vobject_p.h
index a0d921e..0d0a2a8 100644
--- a/library/backend/vobject_p.h
+++ b/library/backend/vobject_p.h
@@ -1,404 +1,406 @@
1/*************************************************************************** 1/***************************************************************************
2(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International 2(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
3Business Machines Corporation and Siemens Rolm Communications Inc. 3Business Machines Corporation and Siemens Rolm Communications Inc.
4 4
5For purposes of this license notice, the term Licensors shall mean, 5For purposes of this license notice, the term Licensors shall mean,
6collectively, Apple Computer, Inc., AT&T Corp., International 6collectively, Apple Computer, Inc., AT&T Corp., International
7Business Machines Corporation and Siemens Rolm Communications Inc. 7Business Machines Corporation and Siemens Rolm Communications Inc.
8The term Licensor shall mean any of the Licensors. 8The term Licensor shall mean any of the Licensors.
9 9
10Subject to acceptance of the following conditions, permission is hereby 10Subject to acceptance of the following conditions, permission is hereby
11granted by Licensors without the need for written agreement and without 11granted by Licensors without the need for written agreement and without
12license or royalty fees, to use, copy, modify and distribute this 12license or royalty fees, to use, copy, modify and distribute this
13software for any purpose. 13software for any purpose.
14 14
15The above copyright notice and the following four paragraphs must be 15The above copyright notice and the following four paragraphs must be
16reproduced in all copies of this software and any software including 16reproduced in all copies of this software and any software including
17this software. 17this software.
18 18
19THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE 19THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
20ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR 20ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
21MODIFICATIONS. 21MODIFICATIONS.
22 22
23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT, 23IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 24INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 25OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE. 26DAMAGE.
27 27
28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, 28EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE 29INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31PURPOSE. 31PURPOSE.
32 32
33The software is provided with RESTRICTED RIGHTS. Use, duplication, or 33The software is provided with RESTRICTED RIGHTS. Use, duplication, or
34disclosure by the government are subject to restrictions set forth in 34disclosure by the government are subject to restrictions set forth in
35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable. 35DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
36 36
37***************************************************************************/ 37***************************************************************************/
38 38
39/* 39/*
40 40
41The vCard/vCalendar C interface is implemented in the set 41The vCard/vCalendar C interface is implemented in the set
42of files as follows: 42of files as follows:
43 43
44vcc.y, yacc source, and vcc.c, the yacc output you will use 44vcc.y, yacc source, and vcc.c, the yacc output you will use
45implements the core parser 45implements the core parser
46 46
47vobject.c implements an API that insulates the caller from 47vobject.c implements an API that insulates the caller from
48the parser and changes in the vCard/vCalendar BNF 48the parser and changes in the vCard/vCalendar BNF
49 49
50port.h defines compilation environment dependent stuff 50port.h defines compilation environment dependent stuff
51 51
52vcc.h and vobject.h are header files for their .c counterparts 52vcc.h and vobject.h are header files for their .c counterparts
53 53
54vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions 54vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
55which you may find useful. 55which you may find useful.
56 56
57test.c is a standalone test driver that exercises some of 57test.c is a standalone test driver that exercises some of
58the features of the APIs provided. Invoke test.exe on a 58the features of the APIs provided. Invoke test.exe on a
59VCARD/VCALENDAR input text file and you will see the pretty 59VCARD/VCALENDAR input text file and you will see the pretty
60print output of the internal representation (this pretty print 60print output of the internal representation (this pretty print
61output should give you a good idea of how the internal 61output should give you a good idea of how the internal
62representation looks like -- there is one such output in the 62representation looks like -- there is one such output in the
63following too). Also, a file with the .out suffix is generated 63following too). Also, a file with the .out suffix is generated
64to show that the internal representation can be written back 64to show that the internal representation can be written back
65in the original text format. 65in the original text format.
66 66
67For more information on this API see the readme.txt file 67For more information on this API see the readme.txt file
68which accompanied this distribution. 68which accompanied this distribution.
69 69
70 Also visit: 70 Also visit:
71 71
72 http://www.versit.com 72 http://www.versit.com
73 http://www.ralden.com 73 http://www.ralden.com
74 74
75*/ 75*/
76 76
77 77// No tr() anywhere in this file
78#ifndef __VOBJECT_H__ 78
79#define __VOBJECT_H__ 1 79
80 80#ifndef __VOBJECT_H__
81#include <qstring.h> 81#define __VOBJECT_H__ 1
82 82
83 #define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard" 83#include <qstring.h>
84 #define vCalendarClipboardFormat"+//ISBN 1-887687-00-9::versit::PDI//vCalendar" 84
85 85 #define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
86/* The above strings vCardClipboardFormat and vCalendarClipboardFormat 86 #define vCalendarClipboardFormat"+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
87are globally unique IDs which can be used to generate clipboard format 87
88ID's as per the requirements of a specific platform. For example, in 88/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
89Windows they are used as the parameter in a call to RegisterClipboardFormat. 89are globally unique IDs which can be used to generate clipboard format
90For example: 90ID's as per the requirements of a specific platform. For example, in
91 91Windows they are used as the parameter in a call to RegisterClipboardFormat.
92 CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat); 92For example:
93 93
94*/ 94 CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
95 95
96 #define vCardMimeType "text/x-vCard" 96*/
97 #define vCalendarMimeType"text/x-vCalendar" 97
98 98 #define vCardMimeType "text/x-vCard"
99#undef DLLEXPORT 99 #define vCalendarMimeType"text/x-vCalendar"
100#include <qglobal.h> 100
101#if defined(Q_WS_WIN) 101#undef DLLEXPORT
102#define DLLEXPORT(t) __declspec(dllexport) t 102#include <qglobal.h>
103#else 103#if defined(Q_WS_WIN)
104#define DLLEXPORT(t) t 104#define DLLEXPORT(t) __declspec(dllexport) t
105#endif 105#else
106 106#define DLLEXPORT(t) t
107#ifndef FALSE 107#endif
108 #define FALSE0 108
109#endif 109#ifndef FALSE
110#ifndef TRUE 110 #define FALSE0
111 #define TRUE1 111#endif
112#endif 112#ifndef TRUE
113 113 #define TRUE1
114#include <stdlib.h> 114#endif
115#include <stdio.h> 115
116 116#include <stdlib.h>
117 117#include <stdio.h>
118 #define VC7bitProp "7BIT" 118
119 #define VC8bitProp "8BIT" 119
120 #define VCAAlarmProp "AALARM" 120 #define VC7bitProp "7BIT"
121 #define VCAdditionalNamesProp"ADDN" 121 #define VC8bitProp "8BIT"
122 #define VCAdrProp "ADR" 122 #define VCAAlarmProp "AALARM"
123 #define VCAgentProp "AGENT" 123 #define VCAdditionalNamesProp"ADDN"
124 #define VCAIFFProp "AIFF" 124 #define VCAdrProp "ADR"
125 #define VCAOLProp "AOL" 125 #define VCAgentProp "AGENT"
126 #define VCAppleLinkProp "APPLELINK" 126 #define VCAIFFProp "AIFF"
127 #define VCAttachProp "ATTACH" 127 #define VCAOLProp "AOL"
128 #define VCAttendeeProp "ATTENDEE" 128 #define VCAppleLinkProp "APPLELINK"
129 #define VCATTMailProp "ATTMAIL" 129 #define VCAttachProp "ATTACH"
130 #define VCAudioContentProp "AUDIOCONTENT" 130 #define VCAttendeeProp "ATTENDEE"
131 #define VCAVIProp "AVI" 131 #define VCATTMailProp "ATTMAIL"
132 #define VCBase64Prop "BASE64" 132 #define VCAudioContentProp "AUDIOCONTENT"
133 #define VCBBSProp "BBS" 133 #define VCAVIProp "AVI"
134 #define VCBirthDateProp "BDAY" 134 #define VCBase64Prop "BASE64"
135 #define VCBMPProp "BMP" 135 #define VCBBSProp "BBS"
136 #define VCBodyProp "BODY" 136 #define VCBirthDateProp "BDAY"
137 #define VCBusinessRoleProp "ROLE" 137 #define VCBMPProp "BMP"
138 #define VCCalProp "VCALENDAR" 138 #define VCBodyProp "BODY"
139 #define VCCaptionProp "CAP" 139 #define VCBusinessRoleProp "ROLE"
140 #define VCCardProp "VCARD" 140 #define VCCalProp "VCALENDAR"
141 #define VCCarProp "CAR" 141 #define VCCaptionProp "CAP"
142 #define VCCategoriesProp "CATEGORIES" 142 #define VCCardProp "VCARD"
143 #define VCCellularProp "CELL" 143 #define VCCarProp "CAR"
144 #define VCCGMProp "CGM" 144 #define VCCategoriesProp "CATEGORIES"
145 #define VCCharSetProp "CS" 145 #define VCCellularProp "CELL"
146 #define VCCIDProp "CID" 146 #define VCCGMProp "CGM"
147 #define VCCISProp "CIS" 147 #define VCCharSetProp "CHARSET"
148 #define VCCityProp "L" 148 #define VCCIDProp "CID"
149 #define VCClassProp "CLASS" 149 #define VCCISProp "CIS"
150 #define VCCommentProp "NOTE" 150 #define VCCityProp "L"
151 #define VCCompletedProp "COMPLETED" 151 #define VCClassProp "CLASS"
152 #define VCContentIDProp "CONTENT-ID" 152 #define VCCommentProp "NOTE"
153 #define VCCountryNameProp "C" 153 #define VCCompletedProp "COMPLETED"
154 #define VCDAlarmProp "DALARM" 154 #define VCContentIDProp "CONTENT-ID"
155 #define VCDataSizeProp "DATASIZE" 155 #define VCCountryNameProp "C"
156 #define VCDayLightProp "DAYLIGHT" 156 #define VCDAlarmProp "DALARM"
157 #define VCDCreatedProp "DCREATED" 157 #define VCDataSizeProp "DATASIZE"
158#define VCDeliveryLabelProp "LABEL" 158 #define VCDayLightProp "DAYLIGHT"
159 #define VCDescriptionProp "DESCRIPTION" 159 #define VCDCreatedProp "DCREATED"
160 #define VCDIBProp "DIB" 160#define VCDeliveryLabelProp "LABEL"
161 #define VCDisplayStringProp "DISPLAYSTRING" 161 #define VCDescriptionProp "DESCRIPTION"
162 #define VCDomesticProp "DOM" 162 #define VCDIBProp "DIB"
163 #define VCDTendProp "DTEND" 163 #define VCDisplayStringProp "DISPLAYSTRING"
164 #define VCDTstartProp "DTSTART" 164 #define VCDomesticProp "DOM"
165 #define VCDueProp "DUE" 165 #define VCDTendProp "DTEND"
166 #define VCEmailAddressProp "EMAIL" 166 #define VCDTstartProp "DTSTART"
167 #define VCEncodingProp "ENCODING" 167 #define VCDueProp "DUE"
168 #define VCEndProp "END" 168 #define VCEmailAddressProp "EMAIL"
169 #define VCEventProp "VEVENT" 169 #define VCEncodingProp "ENCODING"
170 #define VCEWorldProp "EWORLD" 170 #define VCEndProp "END"
171 #define VCExNumProp "EXNUM" 171 #define VCEventProp "VEVENT"
172 #define VCExpDateProp "EXDATE" 172 #define VCEWorldProp "EWORLD"
173 #define VCExpectProp "EXPECT" 173 #define VCExNumProp "EXNUM"
174 #define VCExtAddressProp "EXT ADD" 174 #define VCExpDateProp "EXDATE"
175 #define VCFamilyNameProp "F" 175 #define VCExpectProp "EXPECT"
176 #define VCFaxProp "FAX" 176 #define VCExtAddressProp "EXT ADD"
177 #define VCFullNameProp "FN" 177 #define VCFamilyNameProp "F"
178 #define VCGeoProp "GEO" 178 #define VCFaxProp "FAX"
179 #define VCGeoLocationProp "GEO" 179 #define VCFullNameProp "FN"
180 #define VCGIFProp "GIF" 180 #define VCGeoProp "GEO"
181 #define VCGivenNameProp "G" 181 #define VCGeoLocationProp "GEO"
182 #define VCGroupingProp "Grouping" 182 #define VCGIFProp "GIF"
183 #define VCHomeProp "HOME" 183 #define VCGivenNameProp "G"
184 #define VCIBMMailProp "IBMMail" 184 #define VCGroupingProp "Grouping"
185 #define VCInlineProp "INLINE" 185 #define VCHomeProp "HOME"
186 #define VCInternationalProp "INTL" 186 #define VCIBMMailProp "IBMMail"
187 #define VCInternetProp "INTERNET" 187 #define VCInlineProp "INLINE"
188 #define VCISDNProp "ISDN" 188 #define VCInternationalProp "INTL"
189 #define VCJPEGProp "JPEG" 189 #define VCInternetProp "INTERNET"
190 #define VCLanguageProp "LANG" 190 #define VCISDNProp "ISDN"
191 #define VCLastModifiedProp "LAST-MODIFIED" 191 #define VCJPEGProp "JPEG"
192 #define VCLastRevisedProp "REV" 192 #define VCLanguageProp "LANG"
193 #define VCLocationProp "LOCATION" 193 #define VCLastModifiedProp "LAST-MODIFIED"
194 #define VCLogoProp "LOGO" 194 #define VCLastRevisedProp "REV"
195 #define VCMailerProp "MAILER" 195 #define VCLocationProp "LOCATION"
196 #define VCMAlarmProp "MALARM" 196 #define VCLogoProp "LOGO"
197 #define VCMCIMailProp "MCIMAIL" 197 #define VCMailerProp "MAILER"
198 #define VCMessageProp "MSG" 198 #define VCMAlarmProp "MALARM"
199 #define VCMETProp "MET" 199 #define VCMCIMailProp "MCIMAIL"
200 #define VCModemProp "MODEM" 200 #define VCMessageProp "MSG"
201 #define VCMPEG2Prop "MPEG2" 201 #define VCMETProp "MET"
202 #define VCMPEGProp "MPEG" 202 #define VCModemProp "MODEM"
203 #define VCMSNProp "MSN" 203 #define VCMPEG2Prop "MPEG2"
204 #define VCNamePrefixesProp "NPRE" 204 #define VCMPEGProp "MPEG"
205 #define VCNameProp "N" 205 #define VCMSNProp "MSN"
206 #define VCNameSuffixesProp "NSUF" 206 #define VCNamePrefixesProp "NPRE"
207 #define VCNoteProp "NOTE" 207 #define VCNameProp "N"
208 #define VCOrgNameProp "ORGNAME" 208 #define VCNameSuffixesProp "NSUF"
209 #define VCOrgProp "ORG" 209 #define VCNoteProp "NOTE"
210 #define VCOrgUnit2Prop "OUN2" 210 #define VCOrgNameProp "ORGNAME"
211 #define VCOrgUnit3Prop "OUN3" 211 #define VCOrgProp "ORG"
212 #define VCOrgUnit4Prop "OUN4" 212 #define VCOrgUnit2Prop "OUN2"
213 #define VCOrgUnitProp "OUN" 213 #define VCOrgUnit3Prop "OUN3"
214 #define VCPagerProp "PAGER" 214 #define VCOrgUnit4Prop "OUN4"
215 #define VCPAlarmProp "PALARM" 215 #define VCOrgUnitProp "OUN"
216 #define VCParcelProp "PARCEL" 216 #define VCPagerProp "PAGER"
217 #define VCPartProp "PART" 217 #define VCPAlarmProp "PALARM"
218 #define VCPCMProp "PCM" 218 #define VCParcelProp "PARCEL"
219 #define VCPDFProp "PDF" 219 #define VCPartProp "PART"
220 #define VCPGPProp "PGP" 220 #define VCPCMProp "PCM"
221 #define VCPhotoProp "PHOTO" 221 #define VCPDFProp "PDF"
222 #define VCPICTProp "PICT" 222 #define VCPGPProp "PGP"
223 #define VCPMBProp "PMB" 223 #define VCPhotoProp "PHOTO"
224 #define VCPostalBoxProp "BOX" 224 #define VCPICTProp "PICT"
225 #define VCPostalCodeProp "PC" 225 #define VCPMBProp "PMB"
226 #define VCPostalProp "POSTAL" 226 #define VCPostalBoxProp "BOX"
227 #define VCPowerShareProp "POWERSHARE" 227 #define VCPostalCodeProp "PC"
228 #define VCPreferredProp "PREF" 228 #define VCPostalProp "POSTAL"
229 #define VCPriorityProp "PRIORITY" 229 #define VCPowerShareProp "POWERSHARE"
230 #define VCProcedureNameProp "PROCEDURENAME" 230 #define VCPreferredProp "PREF"
231 #define VCProdIdProp "PRODID" 231 #define VCPriorityProp "PRIORITY"
232 #define VCProdigyProp "PRODIGY" 232 #define VCProcedureNameProp "PROCEDURENAME"
233 #define VCPronunciationProp "SOUND" 233 #define VCProdIdProp "PRODID"
234 #define VCPSProp "PS" 234 #define VCProdigyProp "PRODIGY"
235 #define VCPublicKeyProp "KEY" 235 #define VCPronunciationProp "SOUND"
236 #define VCQPProp "QP" 236 #define VCPSProp "PS"
237 #define VCQuickTimeProp "QTIME" 237 #define VCPublicKeyProp "KEY"
238 #define VCQuotedPrintableProp"QUOTED-PRINTABLE" 238 #define VCQPProp "QP"
239 #define VCRDateProp "RDATE" 239 #define VCQuickTimeProp "QTIME"
240 #define VCRegionProp "R" 240 #define VCQuotedPrintableProp"QUOTED-PRINTABLE"
241 #define VCRelatedToProp "RELATED-TO" 241 #define VCRDateProp "RDATE"
242 #define VCRepeatCountProp "REPEATCOUNT" 242 #define VCRegionProp "R"
243 #define VCResourcesProp "RESOURCES" 243 #define VCRelatedToProp "RELATED-TO"
244 #define VCRNumProp "RNUM" 244 #define VCRepeatCountProp "REPEATCOUNT"
245 #define VCRoleProp "ROLE" 245 #define VCResourcesProp "RESOURCES"
246 #define VCRRuleProp "RRULE" 246 #define VCRNumProp "RNUM"
247 #define VCRSVPProp "RSVP" 247 #define VCRoleProp "ROLE"
248 #define VCRunTimeProp "RUNTIME" 248 #define VCRRuleProp "RRULE"
249 #define VCSequenceProp "SEQUENCE" 249 #define VCRSVPProp "RSVP"
250 #define VCSnoozeTimeProp "SNOOZETIME" 250 #define VCRunTimeProp "RUNTIME"
251 #define VCStartProp "START" 251 #define VCSequenceProp "SEQUENCE"
252 #define VCStatusProp "STATUS" 252 #define VCSnoozeTimeProp "SNOOZETIME"
253 #define VCStreetAddressProp "STREET" 253 #define VCStartProp "START"
254 #define VCSubTypeProp "SUBTYPE" 254 #define VCStatusProp "STATUS"
255 #define VCSummaryProp "SUMMARY" 255 #define VCStreetAddressProp "STREET"
256 #define VCTelephoneProp "TEL" 256 #define VCSubTypeProp "SUBTYPE"
257 #define VCTIFFProp "TIFF" 257 #define VCSummaryProp "SUMMARY"
258 #define VCTimeZoneProp "TZ" 258 #define VCTelephoneProp "TEL"
259 #define VCTitleProp "TITLE" 259 #define VCTIFFProp "TIFF"
260 #define VCTLXProp "TLX" 260 #define VCTimeZoneProp "TZ"
261 #define VCTodoProp "VTODO" 261 #define VCTitleProp "TITLE"
262 #define VCTranspProp "TRANSP" 262 #define VCTLXProp "TLX"
263 #define VCUniqueStringProp "UID" 263 #define VCTodoProp "VTODO"
264 #define VCURLProp "URL" 264 #define VCTranspProp "TRANSP"
265 #define VCURLValueProp "URLVAL" 265 #define VCUniqueStringProp "UID"
266 #define VCValueProp "VALUE" 266 #define VCURLProp "URL"
267 #define VCVersionProp "VERSION" 267 #define VCURLValueProp "URLVAL"
268 #define VCVideoProp "VIDEO" 268 #define VCValueProp "VALUE"
269 #define VCVoiceProp "VOICE" 269 #define VCVersionProp "VERSION"
270 #define VCWAVEProp "WAVE" 270 #define VCVideoProp "VIDEO"
271 #define VCWMFProp "WMF" 271 #define VCVoiceProp "VOICE"
272 #define VCWorkProp "WORK" 272 #define VCWAVEProp "WAVE"
273 #define VCX400Prop "X400" 273 #define VCWMFProp "WMF"
274 #define VCX509Prop "X509" 274 #define VCWorkProp "WORK"
275 #define VCXRuleProp "XRULE" 275 #define VCX400Prop "X400"
276 276 #define VCX509Prop "X509"
277 277 #define VCXRuleProp "XRULE"
278typedef struct VObject VObject; 278
279 279
280typedef struct VObjectIterator { 280typedef struct VObject VObject;
281 VObject* start; 281
282 VObject* next; 282typedef struct VObjectIterator {
283 } VObjectIterator; 283 VObject* start;
284 284 VObject* next;
285extern DLLEXPORT(VObject*) newVObject(const char *id); 285 } VObjectIterator;
286extern DLLEXPORT(void) deleteVObject(VObject *p); 286
287extern DLLEXPORT(char*) dupStr(const char *s, unsigned int size); 287extern DLLEXPORT(VObject*) newVObject(const char *id);
288extern DLLEXPORT(void) deleteStr(const char *p); 288extern DLLEXPORT(void) deleteVObject(VObject *p);
289extern DLLEXPORT(void) unUseStr(const char *s); 289extern DLLEXPORT(char*) dupStr(const char *s, unsigned int size);
290 290extern DLLEXPORT(void) deleteStr(const char *p);
291extern DLLEXPORT(void) setVObjectName(VObject *o, const char* id); 291extern DLLEXPORT(void) unUseStr(const char *s);
292extern DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s); 292
293extern DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s); 293extern DLLEXPORT(void) setVObjectName(VObject *o, const char* id);
294extern DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i); 294extern DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s);
295extern DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l); 295extern DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s);
296extern DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t); 296extern DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i);
297extern DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size); 297extern DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l);
298extern DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size); 298extern DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t);
299 299extern DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size);
300extern DLLEXPORT(const char*) vObjectName(VObject *o); 300extern DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size);
301extern DLLEXPORT(const char*) vObjectStringZValue(VObject *o); 301
302extern DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o); 302extern DLLEXPORT(const char*) vObjectName(VObject *o);
303extern DLLEXPORT(unsigned long) vObjectLongValue(VObject *o); 303extern DLLEXPORT(const char*) vObjectStringZValue(VObject *o);
304extern DLLEXPORT(void*) vObjectAnyValue(VObject *o); 304extern DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o);
305extern DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o); 305extern DLLEXPORT(unsigned long) vObjectLongValue(VObject *o);
306extern DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p); 306extern DLLEXPORT(void*) vObjectAnyValue(VObject *o);
307 307extern DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o);
308extern DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p); 308extern DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p);
309extern DLLEXPORT(VObject*) addProp(VObject *o, const char *id); 309
310extern DLLEXPORT(VObject*) addProp_(VObject *o, const char *id); 310extern DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p);
311extern DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v); 311extern DLLEXPORT(VObject*) addProp(VObject *o, const char *id);
312extern DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size); 312extern DLLEXPORT(VObject*) addProp_(VObject *o, const char *id);
313extern DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size); 313extern DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v);
314extern DLLEXPORT(VObject*) addGroup(VObject *o, const char *g); 314extern DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
315extern DLLEXPORT(void) addList(VObject **o, VObject *p); 315extern DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
316 316extern DLLEXPORT(VObject*) addGroup(VObject *o, const char *g);
317extern DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id); 317extern DLLEXPORT(void) addList(VObject **o, VObject *p);
318 318
319extern DLLEXPORT(VObject*) nextVObjectInList(VObject *o); 319extern DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id);
320extern DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o); 320
321extern DLLEXPORT(int) moreIteration(VObjectIterator *i); 321extern DLLEXPORT(VObject*) nextVObjectInList(VObject *o);
322extern DLLEXPORT(VObject*) nextVObject(VObjectIterator *i); 322extern DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o);
323 323extern DLLEXPORT(int) moreIteration(VObjectIterator *i);
324extern DLLEXPORT(const char*) lookupStr(const char *s); 324extern DLLEXPORT(VObject*) nextVObject(VObjectIterator *i);
325extern DLLEXPORT(void) cleanStrTbl(); 325
326 326extern DLLEXPORT(const char*) lookupStr(const char *s);
327extern DLLEXPORT(void) cleanVObject(VObject *o); 327extern DLLEXPORT(void) cleanStrTbl();
328extern DLLEXPORT(void) cleanVObjects(VObject *list); 328
329 329extern DLLEXPORT(void) cleanVObject(VObject *o);
330extern DLLEXPORT(const char*) lookupProp(const char* str); 330extern DLLEXPORT(void) cleanVObjects(VObject *list);
331extern DLLEXPORT(const char*) lookupProp_(const char* str); 331
332 332extern DLLEXPORT(const char*) lookupProp(const char* str);
333extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o); 333extern DLLEXPORT(const char*) lookupProp_(const char* str);
334extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list); 334
335 335extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o);
336extern DLLEXPORT(int) vObjectValueType(VObject *o); 336extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list);
337 337
338/* return type of vObjectValueType: */ 338extern DLLEXPORT(int) vObjectValueType(VObject *o);
339 #define VCVT_NOVALUE0 339
340 /* if the VObject has no value associated with it. */ 340/* return type of vObjectValueType: */
341 #define VCVT_STRINGZ1 341 #define VCVT_NOVALUE0
342 /* if the VObject has value set by setVObjectStringZValue. */ 342 /* if the VObject has no value associated with it. */
343 #define VCVT_UINT 2 343 #define VCVT_STRINGZ1
344 /* if the VObject has value set by setVObjectIntegerValue. */ 344 /* if the VObject has value set by setVObjectStringZValue. */
345 #define VCVT_ULONG 3 345 #define VCVT_UINT 2
346 /* if the VObject has value set by setVObjectLongValue. */ 346 /* if the VObject has value set by setVObjectIntegerValue. */
347 #define VCVT_RAW 4 347 #define VCVT_ULONG 3
348 /* if the VObject has value set by setVObjectAnyValue. */ 348 /* if the VObject has value set by setVObjectLongValue. */
349 #define VCVT_VOBJECT5 349 #define VCVT_RAW 4
350 /* if the VObject has value set by setVObjectVObjectValue. */ 350 /* if the VObject has value set by setVObjectAnyValue. */
351 351 #define VCVT_VOBJECT5
352extern const char** fieldedProp; 352 /* if the VObject has value set by setVObjectVObjectValue. */
353 353
354/*************************************************** 354extern const char** fieldedProp;
355 * The methods below are implemented in vcc.c (generated from vcc.y ) 355
356 ***************************************************/ 356/***************************************************
357 357 * The methods below are implemented in vcc.c (generated from vcc.y )
358/* NOTE regarding printVObject and writeVObject 358 ***************************************************/
359 359
360The functions below are not exported from the DLL because they 360/* NOTE regarding printVObject and writeVObject
361take a FILE* as a parameter, which cannot be passed across a DLL 361
362interface (at least that is my experience). Instead you can use 362The functions below are not exported from the DLL because they
363their companion functions which take file names or pointers 363take a FILE* as a parameter, which cannot be passed across a DLL
364to memory. However, if you are linking this code into 364interface (at least that is my experience). Instead you can use
365your build directly then you may find them a more convenient API 365their companion functions which take file names or pointers
366and you can go ahead and use them. If you try to use them with 366to memory. However, if you are linking this code into
367the DLL LIB you will get a link error. 367your build directly then you may find them a more convenient API
368*/ 368and you can go ahead and use them. If you try to use them with
369extern void writeVObject(FILE *fp, VObject *o); 369the DLL LIB you will get a link error.
370 370*/
371 371extern void writeVObject(FILE *fp, VObject *o);
372 372
373typedef void (*MimeErrorHandler)(char *); 373
374 374
375extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler); 375typedef void (*MimeErrorHandler)(char *);
376 376
377extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len); 377extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler);
378extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname); 378
379 379extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len);
380 380extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname);
381/* NOTE regarding Parse_MIME_FromFile 381
382The function above, Parse_MIME_FromFile, comes in two flavors, 382
383neither of which is exported from the DLL. Each version takes 383/* NOTE regarding Parse_MIME_FromFile
384a CFile or FILE* as a parameter, neither of which can be 384The function above, Parse_MIME_FromFile, comes in two flavors,
385passed across a DLL interface (at least that is my experience). 385neither of which is exported from the DLL. Each version takes
386If you are linking this code into your build directly then 386a CFile or FILE* as a parameter, neither of which can be
387you may find them a more convenient API that the other flavors 387passed across a DLL interface (at least that is my experience).
388that take a file name. If you use them with the DLL LIB you 388If you are linking this code into your build directly then
389will get a link error. 389you may find them a more convenient API that the other flavors
390*/ 390that take a file name. If you use them with the DLL LIB you
391 391will get a link error.
392 392*/
393#if INCLUDEMFC 393
394extern VObject* Parse_MIME_FromFile(CFile *file); 394
395#else 395#if INCLUDEMFC
396extern VObject* Parse_MIME_FromFile(FILE *file); 396extern VObject* Parse_MIME_FromFile(CFile *file);
397#endif 397#else
398 398extern VObject* Parse_MIME_FromFile(FILE *file);
399extern DLLEXPORT(const char *) vObjectTypeInfo(VObject *o); 399#endif
400 400
401 401extern DLLEXPORT(const char *) vObjectTypeInfo(VObject *o);
402#endif /* __VOBJECT_H__ */ 402
403 403
404 404#endif /* __VOBJECT_H__ */
405
406