summaryrefslogtreecommitdiff
path: root/library/backend
authorzecke <zecke>2002-09-10 12:09:49 (UTC)
committer zecke <zecke>2002-09-10 12:09:49 (UTC)
commit6b77a1cdb9536b1c135eb86d53a6b2c22c19b0a4 (patch) (side-by-side diff)
tree6ebc93c6432f4ed9d00ef1448b6a047ef522a79a /library/backend
parentd10cddb3c9ce75bc90b14add14bc133737fe35aa (diff)
downloadopie-6b77a1cdb9536b1c135eb86d53a6b2c22c19b0a4.zip
opie-6b77a1cdb9536b1c135eb86d53a6b2c22c19b0a4.tar.gz
opie-6b77a1cdb9536b1c135eb86d53a6b2c22c19b0a4.tar.bz2
Qtopia1-6 merge
still to test bic changes to be resolved more changes to be made?
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,48 +1,65 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included
-** in the packaging of this file.
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-** PARTICULAR PURPOSE.
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-#include "categories.h"
+#include <qtopia/categories.h>
+#include <qtopia/stringutil.h>
#include <qfile.h>
#include <qcstring.h>
#include <qtextstream.h>
-#include "stringutil.h"
using namespace Qtopia;
/***********************************************************
*
* CategoryGroup
*
**********************************************************/
#ifdef PALMTOPCENTER
UidGen CategoryGroup::sUidGen( UidGen::PalmtopCenter );
#else
UidGen CategoryGroup::sUidGen( UidGen::Qtopia );
#endif
+/*! \class CategoryGroup categories.h
+ \brief Helper class that is used by Categories
+
+ CategoryGroup is a group of categories that is associated with an
+ application or global set. Mainly it defines a map of ids to
+ category labels and category labels to ids. Lookups can be done with
+ labels or unique idenifiers.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+ \warning Categories API will likely change between Qtopia 1.5 and Qtopia 3
+ \sa Categories::appGroupMap(), Categories::globalGroup()
+ */
+
+/*! Add \a label and return the UID. If failure, then 0 is returned. Note
+ that All and Unfiled are reserved labels.
+ \internal
+*/
int CategoryGroup::add( const QString &label )
{
if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
return 0;
QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
if ( findIt != mLabelIdMap.end() )
return 0;
@@ -53,117 +70,133 @@ int CategoryGroup::add( const QString &label )
void CategoryGroup::insert( int uid, const QString &label )
{
uidGen().store( uid );
mIdLabelMap[uid] = label;
mLabelIdMap[label] = uid;
}
+/*! \internal
+ */
bool CategoryGroup::add( int uid, const QString &label )
{
if ( label == QObject::tr("All") || label == QObject::tr("Unfiled") )
return FALSE;
QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
if ( labelIt != mLabelIdMap.end() )
return FALSE;
QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
if ( idIt != mIdLabelMap.end() )
return FALSE;
insert( uid, label );
return TRUE;
}
+/*! Returns TRUE if \a label was removed from the group, FALSE if not.
+ \internal
+ */
bool CategoryGroup::remove( const QString &label )
{
QMap<QString,int>::Iterator findIt = mLabelIdMap.find( label );
if ( findIt == mLabelIdMap.end() )
return FALSE;
mIdLabelMap.remove( *findIt );
mLabelIdMap.remove( findIt );
return TRUE;
}
+/*! Returns TRUE if \a uid was removed from the group, FALSE if not.
+ \internal
+ */
bool CategoryGroup::remove( int uid )
{
QMap<int,QString>::Iterator idIt = mIdLabelMap.find( uid );
if ( idIt == mIdLabelMap.end() )
return FALSE;
mLabelIdMap.remove( *idIt );
mIdLabelMap.remove( idIt );
return TRUE;
}
+/*! \internal
+ */
bool CategoryGroup::rename( int uid, const QString &newLabel )
{
if ( newLabel == QObject::tr("All") || newLabel == QObject::tr("Unfiled") )
return FALSE;
QMap<int, QString>::Iterator idIt = mIdLabelMap.find( uid );
if ( idIt == mIdLabelMap.end() )
return FALSE;
mLabelIdMap.remove( *idIt );
mLabelIdMap[newLabel] = uid;
*idIt = newLabel;
return TRUE;
}
+/*! \internal
+ */
bool CategoryGroup::rename( const QString &oldLabel, const QString &newLabel )
{
return rename( id(oldLabel), newLabel );
}
+/*! Returns TRUE if \a uid is stored in this group, FALSE if not. */
bool CategoryGroup::contains(int uid) const
{
return ( mIdLabelMap.find( uid ) != mIdLabelMap.end() );
}
+/*! Returns TRUE if \a label is stored in this group, FALSE if not. */
bool CategoryGroup::contains(const QString &label) const
{
return ( mLabelIdMap.find( label ) != mLabelIdMap.end() );
}
-/** Returns label associated with the uid or QString::null if
- * not found
+/*! Returns label associated with the \a uid or QString::null if
+ not found
*/
const QString &CategoryGroup::label(int uid) const
{
QMap<int,QString>::ConstIterator idIt = mIdLabelMap.find( uid );
if ( idIt == mIdLabelMap.end() )
return QString::null;
return *idIt;
}
-/** Returns the uid associated with label or 0 if not found */
+/*! Returns the uid associated with \a label or 0 if not found */
int CategoryGroup::id(const QString &label) const
{
QMap<QString,int>::ConstIterator labelIt = mLabelIdMap.find( label );
if ( labelIt == mLabelIdMap.end() )
return 0;
return *labelIt;
}
+/*! Returns a list of all labels stored in this group. */
QStringList CategoryGroup::labels() const
{
QStringList labels;
for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
it != mIdLabelMap.end(); ++it )
labels += *it;
// ### I don't think this is the place for this...
// labels.sort();
return labels;
}
+/*! Returns a list of all labels associated with the \a catids */
QStringList CategoryGroup::labels(const QArray<int> &catids ) const
{
QStringList labels;
if ( catids.count() == 0 )
return labels;
for ( QMap<int, QString>::ConstIterator it = mIdLabelMap.begin();
it != mIdLabelMap.end(); ++it )
if ( catids.find( it.key() ) != -1 )
@@ -172,19 +205,59 @@ QStringList CategoryGroup::labels(const QArray<int> &catids ) const
}
/***********************************************************
*
* Categories
*
**********************************************************/
-/** Add the category name as long as it doesn't already exist locally
- * or globally. Return TRUE if added, FALSE if conflicts.
- */
+/*!
+ \class Categories categories.h
+ \brief The Categories class is a database that groups categories and maps ids to names.
+
+ The Categories class is the low level Categories accessor class. To
+ add a category menu and filter for your application, see CategoryMenu.
+
+ The Categories class allows the developer to add, remove, and rename
+ categories. Categories can be created for an individual application
+ such as Todo List or to be used for all applications. Categories
+ that can be used by all applications are called global
+ categories. Each PalmtopRecord subclass stores categories as an
+ QArray<int> using PalmtopRecord::setCategories() and
+ PalmtopRecord::categories(). This allows each record to be assigned
+ to multiple categories. This also allows the user to rename a
+ category and for it to update automatically in all records.
+
+ This class provides several methods to convert between a category id
+ and it's associated string such as id(), ids(), label() and labels(). A
+ helper class called CategoryGroup is used to access categories of a
+ single application group, such as Todo List. Global categories can
+ also be accessed via CategoryGroup objects. See appGroupMap() and
+ globalGroup() for the appropriate accessor methods.
+
+ Categories are stored in an xml file in the Settings directory
+ (Categories.xml). A global function called categoryFileName() will
+ return to appropriate QString file location to be passed to load()
+ and save() for the master categories database.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+ \warning Categories API will likely change between Qtopia 1.5 and Qtopia 3
+ \sa CategoryGroup, CategoryMenu
+*/
+
+
+/*!
+ Add the category name as long as it doesn't already exist locally or
+ globally. The \a uid is assigned to the category if successfully
+ added. Return \a uid if added, 0 if conflicts (error).
+
+ \internal
+*/
int Categories::addCategory( const QString &appname,
const QString &catname,
int uid )
{
if ( mGlobalCats.contains(catname) )
return 0;
QMap< QString, CategoryGroup >::Iterator
@@ -199,16 +272,21 @@ int Categories::addCategory( const QString &appname,
}
CategoryGroup &cats = *appIt;
cats.add( uid, catname );
emit categoryAdded( *this, appname, uid );
return uid;
}
+/*!
+ Add the category name as long as it doesn't already exist locally or
+ globally. Return UID if added, 0 if conflicts (error).
+*/
+
int Categories::addCategory( const QString &appname,
const QString &catname )
{
if ( mGlobalCats.contains(catname) )
return 0;
QMap< QString, CategoryGroup >::Iterator
appIt = mAppCats.find( appname );
@@ -224,36 +302,47 @@ int Categories::addCategory( const QString &appname,
CategoryGroup &cats = *appIt;
int uid = cats.add( catname );
if ( !uid )
return 0;
emit categoryAdded( *this, appname, uid );
return uid;
}
+/*!
+ \internal
+*/
int Categories::addGlobalCategory( const QString &catname, int uid )
{
mGlobalCats.add( uid, catname );
emit categoryAdded( *this, QString::null, uid );
return uid;
}
+/*!
+ Add the global category \a catname while checking that it doesn't
+ already exist globally. Return UID if added, 0 if conflicts.
+
+ \sa addCategory()
+ */
int Categories::addGlobalCategory( const QString &catname )
{
int uid = mGlobalCats.add( catname );
if ( !uid )
return 0;
emit categoryAdded( *this, QString::null, uid );
return uid;
}
-/** Removes the category from the application; if it is not found
- * in the application, then it attempts to remove it from
- * the global list
- */
+/*!
+
+ Removes the \a catname from the application group. If it is not
+ found in the application group and \a checkGlobal is TRUE, then it
+ attempts to remove it from the global list
+*/
bool Categories::removeCategory( const QString &appname,
const QString &catname,
bool checkGlobal )
{
QMap< QString, CategoryGroup >::Iterator
appIt = mAppCats.find( appname );
if ( appIt != mAppCats.end() ) {
CategoryGroup &cats = *appIt;
@@ -263,65 +352,78 @@ bool Categories::removeCategory( const QString &appname,
return TRUE;
}
}
if ( !checkGlobal )
return FALSE;
return removeGlobalCategory( catname );
}
+
+/*!
+ Removes the \a uid from the application group \a appname. Returns TRUE
+ if success, FALSE if not found.
+*/
bool Categories::removeCategory( const QString &appname, int uid )
{
QMap< QString, CategoryGroup >::Iterator
appIt = mAppCats.find( appname );
if ( appIt != mAppCats.end() ) {
CategoryGroup &cats = *appIt;
if ( cats.remove( uid ) ) {
emit categoryRemoved( *this, appname, uid );
return TRUE;
}
}
return FALSE;
}
+/*!
+ Removes the global category \a catname. Returns TRUE
+ if success, FALSE if not found.
+*/
bool Categories::removeGlobalCategory( const QString &catname )
{
int uid = mGlobalCats.id( catname );
if ( mGlobalCats.remove( uid ) ) {
emit categoryRemoved( *this, QString::null, uid );
return TRUE;
}
return FALSE;
}
-
+/*!
+ Removes the global category \a uid. Returns TRUE
+ if success, FALSE if not found.
+*/
bool Categories::removeGlobalCategory( int uid )
{
if ( mGlobalCats.remove( uid ) ) {
emit categoryRemoved( *this, QString::null, uid );
return TRUE;
}
return FALSE;
}
-/** Returns the sorted list of all categories that are associated with
- * the app. If includeGlobal parameter is TRUE then the returned
- * categories will include the global category items.
+/*!
+ Returns the sorted list of all categories that are associated with
+ the \a app. If \a includeGlobal is TRUE then the returned
+ categories will include the global category items.
*/
QStringList Categories::labels( const QString &app,
bool includeGlobal,
ExtraLabels extra ) const
{
QMap< QString, CategoryGroup >::ConstIterator
appIt = mAppCats.find( app );
QStringList cats;
if ( appIt != mAppCats.end() )
cats += (*appIt).labels();
- else qDebug("Categories::labels didn't find app %s", app.latin1() );
+ //else qDebug("Categories::labels didn't find app %s", app.latin1() );
if ( includeGlobal )
cats += mGlobalCats.labels();
cats.sort();
switch ( extra ) {
case NoExtra: break;
case AllUnfiled:
cats.append( tr("All") );
@@ -333,32 +435,41 @@ QStringList Categories::labels( const QString &app,
case UnfiledLabel:
cats.append( tr("Unfiled") );
break;
}
return cats;
}
+/*!
+ Returns the label associated with the id
+*/
QString Categories::label( const QString &app, int id ) const
{
if ( mGlobalCats.contains( id ) )
return mGlobalCats.label( id );
QMap< QString, CategoryGroup >::ConstIterator
appIt = mAppCats.find( app );
if ( appIt == mAppCats.end() )
return QString::null;
return (*appIt).label( id );
}
-/** Returns a single string associated with the cat ids for display in
- * a combobox or any area that requires one string. If catids are empty
- * then "Unfiled" will be returned. If multiple categories are assigned
- * the first cat id is shown with " (multi)" appended to the string.
- */
+/*!
+ Returns a single string associated with \a catids for display in a
+ combobox or any area that requires one string. If \a catids are empty
+ then "Unfiled" will be returned. If multiple categories are
+ assigned then the behavior depends on the DisplaySingle type.
+
+ If \a display is set to ShowMulti then " (multi)" appended to the
+ first string. If \a display is set to ShowAll, then a space
+ seperated string is returned with all categories. If ShowFirst is
+ set, the just the first string is returned.
+*/
QString Categories::displaySingle( const QString &app,
const QArray<int> &catids,
DisplaySingle display ) const
{
QStringList strs = labels( app, catids );
if ( !strs.count() )
return tr("Unfiled");
strs.sort();
@@ -375,46 +486,61 @@ QString Categories::displaySingle( const QString &app,
r = strs.join(" ");
break;
}
}
else r = strs.first();
return r;
}
+/*!
+
+ Returns all ids associated with the application CategoryGroup \a app
+ and the passed in \a labels in that group.
+*/
QArray<int> Categories::ids( const QString &app, const QStringList &labels) const
{
QArray<int> results;
QStringList::ConstIterator it;
int i;
-
+
for ( i=0, it=labels.begin(); it!=labels.end(); i++, ++it ) {
int value = id( app, *it );
if ( value != 0 ) {
int tmp = results.size();
results.resize( tmp + 1 );
results[ tmp ] = value;
}
}
return results;
}
+/*!
+ Returns the id associated with the app. If the id is not found in the
+ application CategoryGroup, then it searches the global CategoryGroup.
+ If it is not found it either, 0 is returned.
+*/
int Categories::id( const QString &app, const QString &cat ) const
{
if ( cat == tr("Unfiled") || cat.contains( tr(" (multi.)") ) )
return 0;
int uid = mGlobalCats.id( cat );
if ( uid != 0 )
return uid;
return mAppCats[app].id( cat );
}
-/** Return TRUE if renaming succeeded; FALSE if app name not found,
- * or if there was a name conflict
+/*!
+ Return TRUE if renaming succeeded; FALSE if \a appname or \a oldName
+ is not found, or if \a newName conflicts with an existing category
+ in the CategoryGroup.
+
+ It will first search the CategoryGroup associated with \a appname
+ and if not found it will try to replace in global CategoryGroup.
*/
bool Categories::renameCategory( const QString &appname,
const QString &oldName,
const QString &newName )
{
QMap< QString, CategoryGroup >::Iterator
appIt = mAppCats.find( appname );
@@ -424,27 +550,37 @@ bool Categories::renameCategory( const QString &appname,
if ( id != 0 && cats.rename( id, newName ) ) {
emit categoryRenamed( *this, appname, id );
return TRUE;
}
}
return renameGlobalCategory( oldName, newName );
}
+/*!
+ Return TRUE if renaming succeeded; FALSE if \a appname or \a oldName
+ is not found, or if \a newName conflicts with an existing category
+ in the CategoryGroup. This function will only rename categories found
+ in the global CategoryGroup.
+ */
bool Categories::renameGlobalCategory( const QString &oldName,
const QString &newName )
{
int uid = mGlobalCats.id( oldName );
if ( uid != 0 && mGlobalCats.rename( uid, newName ) ) {
emit categoryRenamed( *this, QString::null, uid );
return TRUE;
}
return FALSE;
}
+/*!
+ Changes the grouping of a category. If a category was global and \a global
+ is set to TRUE, then the \a catname will be moved to the \a appname group.
+*/
void Categories::setGlobal( const QString &appname,
const QString &catname,
bool global )
{
// if in global and should be in app; then move it
if ( mGlobalCats.contains( catname ) && !global ) {
mGlobalCats.remove( catname );
addCategory( appname, catname );
@@ -453,49 +589,63 @@ void Categories::setGlobal( const QString &appname,
// if in app and should be in global, then move it
if ( !global )
return;
if ( removeCategory( appname, catname, FALSE ) )
addGlobalCategory( catname );
}
+/*!
+ Returns TRUE if the \a catname is in the global CategoryGroup, FALSE if not.
+*/
bool Categories::isGlobal( const QString &catname ) const
{
return mGlobalCats.contains( catname );
}
-/** Returns true if the catname is associated with any application
+/*!
+ Returns true if the \a catname is associated with any CategoryGroup,
+ including global.
*/
bool Categories::exists( const QString &catname ) const
{
if ( isGlobal(catname) )
return TRUE;
for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt )
if ( exists( appsIt.key(), catname ) )
return TRUE;
return FALSE;
}
+/*!
+ Returns TRUE if the \a catname is associated with the \a appname
+ CategoryGroup, FALSE if not found.
+ */
bool Categories::exists( const QString &appname,
const QString &catname) const
{
QMap< QString, CategoryGroup >::ConstIterator
appIt = mAppCats.find( appname );
if ( appIt == mAppCats.end() )
return FALSE;
return (*appIt).contains( catname );
}
+/*!
+ Saves the Categories database to the \a fname. See categoryFileName()
+ for the default file name string used for the shared category database.
+ Returns FALSE if there is error writing the file or TRUE on success.
+ */
bool Categories::save( const QString &fname ) const
{
QString strNewFile = fname + ".new";
QFile f( strNewFile );
QString out;
int total_written;
if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
@@ -529,26 +679,35 @@ bool Categories::save( const QString &fname ) const
total_written = f.writeBlock( cstr.data(), cstr.length() );
if ( total_written != int(cstr.length()) ) {
f.close();
QFile::remove( strNewFile );
return FALSE;
}
f.close();
+#ifdef Q_OS_WIN32
+ QFile::remove( fname );
+#endif
if ( ::rename( strNewFile.latin1(), fname.latin1() ) < 0 ) {
qWarning( "problem renaming file %s to %s",
strNewFile.latin1(), fname.latin1());
// remove the tmp file...
QFile::remove( strNewFile );
}
return TRUE;
}
+/*!
+ Loads the Categories database using \a fname. See categoryFileName()
+ for the default file name string used for the shared category database.
+
+ Returns FALSE if there is error reading the file or TRUE on success.
+ */
bool Categories::load( const QString &fname )
{
QFile file( fname );
if ( !file.open( IO_ReadOnly ) ) {
qWarning("Unable to open %s", fname.latin1());
addGlobalCategory(tr("Business"));
addGlobalCategory(tr("Personal"));
@@ -614,22 +773,29 @@ bool Categories::load( const QString &fname )
mGlobalCats.add( id.toInt(), name );
else
mAppCats[ app ].add( id.toInt(), name );
}
return TRUE;
}
+/*!
+ Clear the categories in memory. Equivelent to creating an empty Categories
+ object.
+*/
void Categories::clear()
{
mGlobalCats.clear();
mAppCats.clear();
}
+/*!
+ Dump the contents to standard out. Used for debugging only.
+*/
void Categories::dump() const
{
qDebug("\tglobal categories = %s", mGlobalCats.labels().join(", ").latin1() );
for ( QMap<QString, CategoryGroup>::ConstIterator appsIt = mAppCats.begin(); appsIt != mAppCats.end(); ++appsIt ) {
const QString &app = appsIt.key();
QStringList appcats = (*appsIt).labels();
qDebug("\tapp = %s\tcategories = %s", app.latin1(),
appcats.join(", ").latin1() );
@@ -670,8 +836,101 @@ void CheckedListView::setChecked( const QStringList &checked )
if ( !showingChecked ) {
ensureItemVisible( i );
showingChecked = TRUE;
}
}
else
i->setOn( FALSE );
}
+
+/*! \fn Categories &Categories::operator= ( const Categories &c )
+
+ Performs deep copy.
+ */
+
+
+/*! \fn QStringList Categories::labels( const QString & app, const QArray<int> &catids ) const
+
+ Returns list of labels associated with the application and catids
+*/
+
+/*! \fn QStringList Categories::globalCategories() const
+
+ Returns list of all global category labels
+*/
+
+/*! \fn const QMap<QString, CategoryGroup> &Categories::appGroupMap() const
+
+ Returns a map of application names to CategoryGroup. The CategoryGroup
+ class defines a map of ids to category labels and category labels to ids.
+*/
+
+/*! \fn const CategoryGroup &Categories::globalGroup() const
+
+ Returns the global CategoryGroup. The CategoryGroup
+ class defines a map of ids to category labels and category labels to ids.
+*/
+
+/*! \fn void Categories::categoryAdded( const Categories &cats, const QString &appname, int uid)
+
+ Emitted if a category is added.
+
+ \a cats is a const reference to this object
+ \a appname is the CategoryGroup application name that the category was added to or QString::null if it was global
+ \a uid is the unique identifier associated with the added category
+*/
+
+/*! \fn void Categories::categoryRemoved( const Categories &cats, const QString &appname,
+ int uid)
+
+ Emitted if removed category is removed.
+
+ \a cats is a const reference to this object
+ \a appname is the CategoryGroup application name that the category was removed from or QString::null if it was the global CategoryGroup
+ \a uid is the unique identifier associated with the removed category
+*/
+
+
+/*! \fn void Categories::categoryRenamed( const Categories &cats, const QString &appname,
+ int uid)
+
+ Emitted if \a uid in the \a appname CategoryGroup is renamed in \a cats
+ object.
+
+ \a cats is a const reference to this object
+ \a appname is the CategoryGroup application name that the category was renamed in or QString::null if it was the global CategoryGroup
+ \a uid is the unique identifier associated with the renamed category
+*/
+
+/*! \fn Categories::Categories( QObject *parent=0, const char *name = 0 )
+
+ Constructor for an empty Categories object.
+*/
+
+/*! \fn Categories::Categories( const Categories &copyFrom )
+
+ Deep copy constructor
+*/
+
+/*! \fn Categories::~Categories()
+
+ Empty destructor. Call save() before destruction if there are changes
+ that need to be saved.
+*/
+
+/*! \fn CategoryGroup::clear()
+ \internal
+*/
+
+/*! \fn const QMap<int, QString> &CategoryGroup::idMap() const
+
+ Returns a const reference to the id to label QMap
+*/
+
+/*! \fn CategoryGroup::CategoryGroup()
+ \internal
+*/
+
+/*! \fn CategoryGroup::CategoryGroup(const CategoryGroup &c)
+ \internal
+*/
+
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,12 +1,12 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
@@ -29,49 +29,427 @@
#include <qobject.h>
#include <qregexp.h>
#include <qstylesheet.h>
#include <qfileinfo.h>
#include <stdio.h>
+/*!
+ \class Contact contact.h
+ \brief The Contact class holds the data of an address book entry.
+
+ This data includes information the name of the person, contact
+ information, and business information such as deparment and job title.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
Qtopia::UidGen Contact::sUidGen( Qtopia::UidGen::Qtopia );
+/*!
+ Creates a new, empty contact.
+*/
Contact::Contact()
: Record(), mMap(), d( 0 )
{
}
+/*!
+ \internal
+ Creates a new contact. The properties of the contact are
+ set from \a fromMap.
+*/
Contact::Contact( const QMap<int, QString> &fromMap ) :
Record(), mMap( fromMap ), d( 0 )
{
QString cats = mMap[ Qtopia::AddressCategory ];
if ( !cats.isEmpty() )
setCategories( idsFromString( cats ) );
QString uidStr = find( Qtopia::AddressUid );
+
if ( uidStr.isEmpty() )
setUid( uidGen().generate() );
else
setUid( uidStr.toInt() );
+
+ if ( !uidStr.isEmpty() )
+ setUid( uidStr.toInt() );
}
+/*!
+ Destroys a contact.
+*/
Contact::~Contact()
{
}
+/*! \fn void Contact::setTitle( const QString &str )
+ Sets the title of the contact to \a str.
+*/
+
+/*! \fn void Contact::setFirstName( const QString &str )
+ Sets the first name of the contact to \a str.
+*/
+
+/*! \fn void Contact::setMiddleName( const QString &str )
+ Sets the middle name of the contact to \a str.
+*/
+
+/*! \fn void Contact::setLastName( const QString &str )
+ Sets the last name of the contact to \a str.
+*/
+
+/*! \fn void Contact::setSuffix( const QString &str )
+ Sets the suffix of the contact to \a str.
+*/
+
+/*! \fn void Contact::setFileAs( const QString &str )
+ Sets the contact to filed as \a str.
+*/
+
+/*! \fn void Contact::setDefaultEmail( const QString &str )
+ Sets the default email of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeStreet( const QString &str )
+ Sets the home street address of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeCity( const QString &str )
+ Sets the home city of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeState( const QString &str )
+ Sets the home state of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeZip( const QString &str )
+ Sets the home zip code of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeCountry( const QString &str )
+ Sets the home country of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomePhone( const QString &str )
+ Sets the home phone number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeFax( const QString &str )
+ Sets the home fax number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeMobile( const QString &str )
+ Sets the home mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setHomeWebpage( const QString &str )
+ Sets the home webpage of the contact to \a str.
+*/
+
+/*! \fn void Contact::setCompany( const QString &str )
+ Sets the company for contact to \a str.
+*/
+
+/*! \fn void Contact::setJobTitle( const QString &str )
+ Sets the job title of the contact to \a str.
+*/
+
+/*! \fn void Contact::setDepartment( const QString &str )
+ Sets the department for contact to \a str.
+*/
+
+/*! \fn void Contact::setOffice( const QString &str )
+ Sets the office for contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessStreet( const QString &str )
+ Sets the business street address of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessCity( const QString &str )
+ Sets the business city of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessState( const QString &str )
+ Sets the business state of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessZip( const QString &str )
+ Sets the business zip code of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessCountry( const QString &str )
+ Sets the business country of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessPhone( const QString &str )
+ Sets the business phone number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessFax( const QString &str )
+ Sets the business fax number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessMobile( const QString &str )
+ Sets the business mobile phone number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessPager( const QString &str )
+ Sets the business pager number of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBusinessWebpage( const QString &str )
+ Sets the business webpage of the contact to \a str.
+*/
+
+/*! \fn void Contact::setProfession( const QString &str )
+ Sets the profession of the contact to \a str.
+*/
+
+/*! \fn void Contact::setAssistant( const QString &str )
+ Sets the assistant of the contact to \a str.
+*/
+
+/*! \fn void Contact::setManager( const QString &str )
+ Sets the manager of the contact to \a str.
+*/
+
+/*! \fn void Contact::setSpouse( const QString &str )
+ Sets the spouse of the contact to \a str.
+*/
+
+/*! \fn void Contact::setGender( const QString &str )
+ Sets the gender of the contact to \a str.
+*/
+
+/*! \fn void Contact::setBirthday( const QString &str )
+ Sets the birthday for the contact to \a str.
+*/
+
+/*! \fn void Contact::setAnniversary( const QString &str )
+ Sets the anniversary of the contact to \a str.
+*/
+
+/*! \fn void Contact::setNickname( const QString &str )
+ Sets the nickname of the contact to \a str.
+*/
+
+/*! \fn void Contact::setNotes( const QString &str )
+ Sets the notes about the contact to \a str.
+*/
+
+/*! \fn QString Contact::title() const
+ Returns the title of the contact.
+*/
+
+/*! \fn QString Contact::firstName() const
+ Returns the first name of the contact.
+*/
+
+/*! \fn QString Contact::middleName() const
+ Returns the middle name of the contact.
+*/
+
+/*! \fn QString Contact::lastName() const
+ Returns the last name of the contact.
+*/
+
+/*! \fn QString Contact::suffix() const
+ Returns the suffix of the contact.
+*/
+
+/*! \fn QString Contact::fileAs() const
+ Returns the string the contact is filed as.
+*/
+
+/*! \fn QString Contact::defaultEmail() const
+ Returns the default email address of the contact.
+*/
+
+/*! \fn QString Contact::emails() const
+ Returns the list of email address for a contact separated by ';'s in a single
+ string.
+*/
+
+/*! \fn QString Contact::homeStreet() const
+ Returns the home street address of the contact.
+*/
+
+/*! \fn QString Contact::homeCity() const
+ Returns the home city of the contact.
+*/
+
+/*! \fn QString Contact::homeState() const
+ Returns the home state of the contact.
+*/
+
+/*! \fn QString Contact::homeZip() const
+ Returns the home zip of the contact.
+*/
+
+/*! \fn QString Contact::homeCountry() const
+ Returns the home country of the contact.
+*/
+
+/*! \fn QString Contact::homePhone() const
+ Returns the home phone number of the contact.
+*/
+
+/*! \fn QString Contact::homeFax() const
+ Returns the home fax number of the contact.
+*/
+
+/*! \fn QString Contact::homeMobile() const
+ Returns the home mobile number of the contact.
+*/
+
+/*! \fn QString Contact::homeWebpage() const
+ Returns the home webpage of the contact.
+*/
+
+/*! \fn QString Contact::company() const
+ Returns the company for the contact.
+*/
+
+/*! \fn QString Contact::department() const
+ Returns the department for the contact.
+*/
+
+/*! \fn QString Contact::office() const
+ Returns the office for the contact.
+*/
+
+/*! \fn QString Contact::jobTitle() const
+ Returns the job title of the contact.
+*/
+
+/*! \fn QString Contact::profession() const
+ Returns the profession of the contact.
+*/
+
+/*! \fn QString Contact::assistant() const
+ Returns the assistant of the contact.
+*/
+
+/*! \fn QString Contact::manager() const
+ Returns the manager of the contact.
+*/
+
+/*! \fn QString Contact::businessStreet() const
+ Returns the business street address of the contact.
+*/
+
+/*! \fn QString Contact::businessCity() const
+ Returns the business city of the contact.
+*/
+
+/*! \fn QString Contact::businessState() const
+ Returns the business state of the contact.
+*/
+
+/*! \fn QString Contact::businessZip() const
+ Returns the business zip of the contact.
+*/
+
+/*! \fn QString Contact::businessCountry() const
+ Returns the business country of the contact.
+*/
+
+/*! \fn QString Contact::businessPhone() const
+ Returns the business phone number of the contact.
+*/
+
+/*! \fn QString Contact::businessFax() const
+ Returns the business fax number of the contact.
+*/
+
+/*! \fn QString Contact::businessMobile() const
+ Returns the business mobile number of the contact.
+*/
+
+/*! \fn QString Contact::businessPager() const
+ Returns the business pager number of the contact.
+*/
+
+/*! \fn QString Contact::businessWebpage() const
+ Returns the business webpage of the contact.
+*/
+
+/*! \fn QString Contact::spouse() const
+ Returns the spouse of the contact.
+*/
+
+/*! \fn QString Contact::gender() const
+ Returns the gender of the contact.
+*/
+
+/*! \fn QString Contact::birthday() const
+ Returns the birthday of the contact.
+*/
+
+/*! \fn QString Contact::anniversary() const
+ Returns the anniversary of the contact.
+*/
+
+/*! \fn QString Contact::nickname() const
+ Returns the nickname of the contact.
+*/
+
+/*! \fn QString Contact::children() const
+ Returns the children of the contact.
+*/
+
+/*! \fn QString Contact::notes() const
+ Returns the notes relating to the the contact.
+*/
+
+/*! \fn QString Contact::groups() const
+ \internal
+ Returns the groups for the contact.
+*/
+
+/*! \fn QStringList Contact::groupList() const
+ \internal
+*/
+
+/*! \fn QString Contact::field(int) const
+ \internal
+*/
+
+/*! \fn void Contact::saveJournal( journal_action, const QString & = QString::null )
+ \internal
+*/
+
+/*! \fn void Contact::setUid( int id )
+ \internal
+ Sets the uid for this record to \a id.
+*/
+
+/*! \enum Contact::journal_action
+ \internal
+*/
+
+/*!
+ \internal
+*/
QMap<int, QString> Contact::toMap() const
{
QMap<int, QString> map = mMap;
- map.insert( Qtopia::AddressCategory, idsToString( categories() ));
+ QString cats = idsToString( categories() );
+ if ( !cats.isEmpty() )
+ map.insert( Qtopia::AddressCategory, cats );
return map;
}
/*!
- Returns a rich text formatted QString of the Contact.
+ Returns a rich text formatted QString representing the contents the contact.
*/
QString Contact::toRichText() const
{
QString text;
QString value, comp, state;
// name, jobtitle and company
if ( !(value = fullName()).isEmpty() )
@@ -226,39 +604,51 @@ QString Contact::toRichText() const
//QString tmp = Qtopia::escapeString(value);
QString tmp = QStyleSheet::convertFromPlainText(value);
//tmp.replace( reg, "<br>" );
text += "<br>" + tmp + "<br>";
}
return text;
}
+/*!
+ \internal
+*/
void Contact::insert( int key, const QString &v )
{
QString value = v.stripWhiteSpace();
if ( value.isEmpty() )
mMap.remove( key );
else
mMap.insert( key, value );
}
+/*!
+ \internal
+*/
void Contact::replace( int key, const QString & v )
{
QString value = v.stripWhiteSpace();
if ( value.isEmpty() )
mMap.remove( key );
else
mMap.replace( key, value );
}
+/*!
+ \internal
+*/
QString Contact::find( int key ) const
{
return mMap[key];
}
+/*!
+ \internal
+*/
QString Contact::displayAddress( const QString &street,
const QString &city,
const QString &state,
const QString &zip,
const QString &country ) const
{
QString s = street;
if ( !street.isEmpty() )
@@ -271,30 +661,39 @@ QString Contact::displayAddress( const QString &street,
s += " ";
s += zip;
if ( !country.isEmpty() && !s.isEmpty() )
s += "\n";
s += country;
return s;
}
+/*!
+ \internal
+*/
QString Contact::displayBusinessAddress() const
{
return displayAddress( businessStreet(), businessCity(),
businessState(), businessZip(),
businessCountry() );
}
+/*!
+ \internal
+*/
QString Contact::displayHomeAddress() const
{
return displayAddress( homeStreet(), homeCity(),
homeState(), homeZip(),
homeCountry() );
}
+/*!
+ Returns the full name of the contact
+*/
QString Contact::fullName() const
{
QString title = find( Qtopia::Title );
QString firstName = find( Qtopia::FirstName );
QString middleName = find( Qtopia::MiddleName );
QString lastName = find( Qtopia::LastName );
QString suffix = find( Qtopia::Suffix );
@@ -317,26 +716,72 @@ QString Contact::fullName() const
if ( !suffix.isEmpty() ) {
if ( !name.isEmpty() )
name += " ";
name += suffix;
}
return name.simplifyWhiteSpace();
}
+/*!
+ Returns a list of the names of the children of the contact.
+*/
QStringList Contact::childrenList() const
{
return QStringList::split( " ", find( Qtopia::Children ) );
}
+/*! \fn void Contact::insertEmail( const QString &email )
+
+ Insert \a email into the email list. Ensures \a email can only be added
+ once. If there is no default email address set, it sets it to the \a email.
+*/
+
+/*! \fn void Contact::removeEmail( const QString &email )
+
+ Removes the \a email from the email list. If the default email was \a email,
+ then the default email address is assigned to the first email in the
+ email list
+*/
+
+/*! \fn void Contact::clearEmails()
+
+ Clears the email list.
+ */
+
+/*! \fn void Contact::insertEmails( const QStringList &emailList )
+
+ Appends the \a emailList to the exiting email list
+ */
+
+/*!
+ Returns a list of email addresses belonging to the contact, including
+ the default email address.
+*/
QStringList Contact::emailList() const
{
- return QStringList::split( ";", find( Qtopia::Emails ) );
+ QString emailStr = emails();
+
+ QStringList r;
+ if ( !emailStr.isEmpty() ) {
+ qDebug(" emailstr ");
+ QStringList l = QStringList::split( emailSeparator(), emailStr );
+ for ( QStringList::ConstIterator it = l.begin();it != l.end();++it )
+ r += (*it).simplifyWhiteSpace();
+ }
+
+ return r;
}
+/*!
+ \overload
+
+ Generates the string for the contact to be filed as from the first,
+ middle and last name of the contact.
+*/
void Contact::setFileAs()
{
QString lastName, firstName, middleName, fileas;
lastName = find( Qtopia::LastName );
firstName = find( Qtopia::FirstName );
middleName = find( Qtopia::MiddleName );
if ( !lastName.isEmpty() && !firstName.isEmpty()
@@ -348,16 +793,20 @@ void Contact::setFileAs()
!middleName.isEmpty() )
fileas = firstName + ( firstName.isEmpty() ? "" : " " )
+ middleName + ( middleName.isEmpty() ? "" : " " )
+ lastName;
replace( Qtopia::FileAs, fileas );
}
+/*!
+ \internal
+ Appends the contact information to \a buf.
+*/
void Contact::save( QString &buf ) const
{
static const QStringList SLFIELDS = fields();
// I'm expecting "<Contact " in front of this...
for ( QMap<int, QString>::ConstIterator it = mMap.begin();
it != mMap.end(); ++it ) {
const QString &value = it.data();
int key = it.key();
@@ -372,16 +821,20 @@ void Contact::save( QString &buf ) const
}
buf += customToXml();
if ( categories().count() > 0 )
buf += "Categories=\"" + idsToString( categories() ) + "\" ";
buf += "Uid=\"" + QString::number( uid() ) + "\" ";
// You need to close this yourself
}
+/*!
+ \internal
+ Returns the list of fields belonging to a contact
+*/
QStringList Contact::fields()
{
QStringList list;
list.append( "Title" ); // Not Used!
list.append( "FirstName" );
list.append( "MiddleName" );
list.append( "LastName" );
@@ -430,16 +883,20 @@ QStringList Contact::fields()
list.append( "Children" );
list.append( "Notes" );
list.append( "Groups" );
return list;
}
+/*!
+ \internal
+ Returns a translated list of field names for a contact.
+*/
QStringList Contact::trfields()
{
QStringList list;
list.append( QObject::tr( "Name Title") );
list.append( QObject::tr( "First Name" ) );
list.append( QObject::tr( "Middle Name" ) );
list.append( QObject::tr( "Last Name" ) );
@@ -488,45 +945,61 @@ QStringList Contact::trfields()
list.append( QObject::tr( "Children" ) );
list.append( QObject::tr( "Notes" ) );
list.append( QObject::tr( "Groups" ) );
return list;
}
-void Contact::setEmails( const QString &v )
+/*!
+ Sets the list of email address for contact to those contained in \a str.
+ Email address should be separated by ';'s.
+*/
+void Contact::setEmails( const QString &str )
{
- replace( Qtopia::Emails, v );
- if ( v.isEmpty() )
+ replace( Qtopia::Emails, str );
+ if ( str.isEmpty() )
setDefaultEmail( QString::null );
}
-void Contact::setChildren( const QString &v )
+/*!
+ Sets the list of children for the contact to those contained in \a str.
+*/
+void Contact::setChildren( const QString &str )
{
- replace( Qtopia::Children, v );
+ replace( Qtopia::Children, str );
}
// vcard conversion code
+/*!
+ \internal
+*/
static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
{
VObject *ret = 0;
if ( o && !value.isEmpty() )
ret = addPropValue( o, prop, value.latin1() );
return ret;
}
+/*!
+ \internal
+*/
static inline VObject *safeAddProp( VObject *o, const char *prop)
{
VObject *ret = 0;
if ( o )
ret = addProp( o, prop );
return ret;
}
+/*!
+ \internal
+*/
static VObject *createVObject( const Contact &c )
{
VObject *vcard = newVObject( VCCardProp );
safeAddPropValue( vcard, VCVersionProp, "2.1" );
safeAddPropValue( vcard, VCLastRevisedProp, TimeConversion::toISO8601( QDateTime::currentDateTime() ) );
safeAddPropValue( vcard, VCUniqueStringProp, QString::number(c.uid()) );
// full name
@@ -617,22 +1090,23 @@ static VObject *createVObject( const Contact &c )
safeAddPropValue( vcard, "X-Qtopia-Anniversary", c.anniversary() );
safeAddPropValue( vcard, "X-Qtopia-Nickname", c.nickname() );
safeAddPropValue( vcard, "X-Qtopia-Children", c.children() );
return vcard;
}
+/*!
+ \internal
+*/
static Contact parseVObject( VObject *obj )
{
Contact c;
- bool haveDefaultEmail = FALSE;
-
VObjectIterator it;
initPropIterator( &it, obj );
while( moreIteration( &it ) ) {
VObject *o = nextVObject( &it );
QCString name = vObjectName( o );
QCString value = vObjectStringZValue( o );
if ( name == VCNameProp ) {
VObjectIterator nit;
@@ -762,24 +1236,17 @@ static Contact parseVObject( VObject *obj )
QCString name = vObjectTypeInfo( o );
if ( name != VCInternetProp && name != VCHomeProp &&
name != VCWorkProp &&
name != VCPreferredProp )
// ### preffered should map to default email
valid = FALSE;
}
if ( valid ) {
- if ( haveDefaultEmail ) {
- QString str = c.emails();
- if ( !str.isEmpty() )
- str += ","+email;
- c.setEmails( str );
- } else {
- c.setDefaultEmail( email );
- }
+ c.insertEmail( email );
}
}
else if ( name == VCURLProp ) {
VObjectIterator nit;
initPropIterator( &nit, o );
while( moreIteration( &nit ) ) {
VObject *o = nextVObject( &nit );
QCString name = vObjectTypeInfo( o );
@@ -846,16 +1313,19 @@ static Contact parseVObject( VObject *obj )
}
}
#endif
}
c.setFileAs();
return c;
}
+/*!
+ Writes the list of \a contacts as a set of VCards to the file \a filename.
+*/
void Contact::writeVCard( const QString &filename, const QValueList<Contact> &contacts)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
@@ -863,32 +1333,37 @@ void Contact::writeVCard( const QString &filename, const QValueList<Contact> &co
for( it = contacts.begin(); it != contacts.end(); ++it ) {
VObject *obj = createVObject( *it );
writeVObject(f.directHandle() , obj );
cleanVObject( obj );
}
cleanStrTbl();
}
+/*!
+ writes \a contact as a VCard to the file \a filename.
+*/
void Contact::writeVCard( const QString &filename, const Contact &contact)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
VObject *obj = createVObject( contact );
writeVObject( f.directHandle() , obj );
cleanVObject( obj );
cleanStrTbl();
}
-
+/*!
+ Returns the set of contacts read as VCards from the file \a filename.
+*/
QValueList<Contact> Contact::readVCard( const QString &filename )
{
qDebug("trying to open %s, exists=%d", filename.utf8().data(), QFileInfo( filename.utf8().data() ).size() );
VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
qDebug("vobject = %p", obj );
QValueList<Contact> contacts;
@@ -899,21 +1374,30 @@ QValueList<Contact> Contact::readVCard( const QString &filename )
VObject *t = obj;
obj = nextVObjectInList(obj);
cleanVObject( t );
}
return contacts;
}
+/*!
+ Returns TRUE if the contact matches the regular expression \a regexp.
+ Otherwise returns FALSE.
+*/
bool Contact::match( const QString &regexp ) const
{
return match(QRegExp(regexp));
}
+/*!
+ \overload
+ Returns TRUE if the contact matches the regular expression \a regexp.
+ Otherwise returns FALSE.
+*/
bool Contact::match( const QRegExp &r ) const
{
bool match;
match = false;
QMap<int, QString>::ConstIterator it;
for ( it = mMap.begin(); it != mMap.end(); ++it ) {
if ( (*it).find( r ) > -1 ) {
match = true;
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,12 +1,12 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
@@ -16,24 +16,24 @@
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef __CONTACT_H__
#define __CONTACT_H__
-#include <qpe/palmtoprecord.h>
-#include <qpe/recordfields.h>
+#include <qtopia/private/palmtoprecord.h>
+#include <qtopia/private/recordfields.h>
#include <qstringlist.h>
#if defined(QPC_TEMPLATEDLL)
// MOC_SKIP_BEGIN
-template class QPC_EXPORT QMap<int, QString>;
+QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<int, QString>;
// MOC_SKIP_END
#endif
class ContactPrivate;
class QPC_EXPORT Contact : public Qtopia::Record
{
friend class DataSet;
public:
@@ -51,19 +51,22 @@ public:
void setFirstName( const QString &v ) { replace( Qtopia::FirstName, v ); }
void setMiddleName( const QString &v ) { replace( Qtopia::MiddleName, v ); }
void setLastName( const QString &v ) { replace( Qtopia::LastName, v ); }
void setSuffix( const QString &v ) { replace( Qtopia::Suffix, v ); }
void setFileAs( const QString &v ) { replace( Qtopia::FileAs, v ); }
void setFileAs();
// default email address
- void setDefaultEmail( const QString &v ) { replace( Qtopia::DefaultEmail, v ); }
- // the emails should be seperated by a semicolon
- void setEmails( const QString &v );
+ void setDefaultEmail( const QString &v );
+ // inserts email to list and ensure's doesn't already exist
+ void insertEmail( const QString &v );
+ void removeEmail( const QString &v );
+ void clearEmails();
+ void insertEmails( const QStringList &v );
// home
void setHomeStreet( const QString &v ) { replace( Qtopia::HomeStreet, v ); }
void setHomeCity( const QString &v ) { replace( Qtopia::HomeCity, v ); }
void setHomeState( const QString &v ) { replace( Qtopia::HomeState, v ); }
void setHomeZip( const QString &v ) { replace( Qtopia::HomeZip, v ); }
void setHomeCountry( const QString &v ) { replace( Qtopia::HomeCountry, v ); }
void setHomePhone( const QString &v ) { replace( Qtopia::HomePhone, v ); }
@@ -118,17 +121,16 @@ public:
QString firstName() const { return find( Qtopia::FirstName ); }
QString middleName() const { return find( Qtopia::MiddleName ); }
QString lastName() const { return find( Qtopia::LastName ); }
QString suffix() const { return find( Qtopia::Suffix ); }
QString fileAs() const { return find( Qtopia::FileAs ); }
// email
QString defaultEmail() const { return find( Qtopia::DefaultEmail ); }
- QString emails() const { return find( Qtopia::Emails ); }
QStringList emailList() const;
// home
QString homeStreet() const { return find( Qtopia::HomeStreet ); }
QString homeCity() const { return find( Qtopia::HomeCity ); }
QString homeState() const { return find( Qtopia::HomeState ); }
QString homeZip() const { return find( Qtopia::HomeZip ); }
QString homeCountry() const { return find( Qtopia::HomeCountry ); }
@@ -197,26 +199,108 @@ public:
// journaling...
void saveJournal( journal_action action, const QString &key = QString::null );
void save( QString &buf ) const;
void setUid( int i )
{ Record::setUid(i); replace( Qtopia::AddressUid , QString::number(i)); }
private:
+ friend class AbEditor;
friend class AbTable;
+ friend class AddressBookAccessPrivate;
+ friend class XMLIO;
+
+ QString emailSeparator() const { return " "; }
+ // the emails should be seperated by a comma
+ void setEmails( const QString &v );
+ QString emails() const { return find( Qtopia::Emails ); }
+
void insert( int key, const QString &value );
void replace( int key, const QString &value );
QString find( int key ) const;
QString displayAddress( const QString &street,
const QString &city,
const QString &state,
const QString &zip,
const QString &country ) const;
Qtopia::UidGen &uidGen() { return sUidGen; }
static Qtopia::UidGen sUidGen;
QMap<int, QString> mMap;
ContactPrivate *d;
};
+// these methods are inlined to keep binary compatability with Qtopia 1.5
+inline void Contact::insertEmail( const QString &v )
+{
+ //qDebug("insertEmail %s", v.latin1());
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+
+ // if no default, set it as the default email and don't insert
+ if ( def.isEmpty() ) {
+ setDefaultEmail( e ); // will insert into the list for us
+ return;
+ }
+
+ // otherwise, insert assuming doesn't already exist
+ QString emailsStr = find( Qtopia::Emails );
+ if ( emailsStr.contains( e ))
+ return;
+ if ( !emailsStr.isEmpty() )
+ emailsStr += emailSeparator();
+ emailsStr += e;
+ replace( Qtopia::Emails, emailsStr );
+}
+
+inline void Contact::removeEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+ QString def = defaultEmail();
+ QString emailsStr = find( Qtopia::Emails );
+ QStringList emails = emailList();
+
+ // otherwise, must first contain it
+ if ( !emailsStr.contains( e ) )
+ return;
+
+ // remove it
+ //qDebug(" removing email from list %s", e.latin1());
+ emails.remove( e );
+ // reset the string
+ emailsStr = emails.join(emailSeparator()); // Sharp's brain dead separator
+ replace( Qtopia::Emails, emailsStr );
+
+ // if default, then replace the default email with the first one
+ if ( def == e ) {
+ //qDebug("removeEmail is default; setting new default");
+ if ( !emails.count() )
+ clearEmails();
+ else // setDefaultEmail will remove e from the list
+ setDefaultEmail( emails.first() );
+ }
+}
+inline void Contact::clearEmails()
+{
+ mMap.remove( Qtopia::DefaultEmail );
+ mMap.remove( Qtopia::Emails );
+}
+inline void Contact::setDefaultEmail( const QString &v )
+{
+ QString e = v.simplifyWhiteSpace();
+
+ //qDebug("Contact::setDefaultEmail %s", e.latin1());
+ replace( Qtopia::DefaultEmail, e );
+
+ if ( !e.isEmpty() )
+ insertEmail( e );
+
+}
+
+inline void Contact::insertEmails( const QStringList &v )
+{
+ for ( QStringList::ConstIterator it = v.begin(); it != v.end(); ++it )
+ insertEmail( *it );
+}
+
#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,33 +1,33 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-#include "event.h"
+#include "event.h"
#include "qfiledirect_p.h"
-#include <qpe/timeconversion.h>
-#include <qpe/stringutil.h>
-#include <qpe/recordfields.h>
+#include <qtopia/timeconversion.h>
+#include <qtopia/stringutil.h>
+#include <qtopia/private/recordfields.h>
#include <qbuffer.h>
#include <time.h>
#include "vobject_p.h"
#include <stdio.h>
using namespace Qtopia;
@@ -66,28 +66,280 @@ static void write( QString& buf, const Event::RepeatPattern &r )
buf += " enddt=\""
+ QString::number( r.endDateUTC ? r.endDateUTC : time( 0 ) )
+ "\"";
buf += " created=\"" + QString::number( r.createTime ) + "\"";
}
Qtopia::UidGen Event::sUidGen( Qtopia::UidGen::Qtopia );
+/*!
+ \class Event event.h
+ \brief The Event class holds the data of a calendar event.
+
+ This data includes descriptive data of the event and schedualing information.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
+/*!
+ \class Event::RepeatPattern
+ \class The Event::RepeatPattern class is internal.
+ \internal
+*/
+
+/*!
+ \enum Event::Days
+ \internal
+*/
+
+/*!
+ \enum Event::Type
+ \internal
+*/
+
+/*!
+ \enum Event::SoundTypeChoice
+
+ This enum type defines what kind of sound is made when an alarm occurs
+ for an event. The currently defined types are:
+
+ <ul>
+ <li>\c Silent - No sound is produced.
+ <li>\c Loud - A loud sound is produced.
+ </ul>
+*/
+
+/*!
+ \fn bool Event::operator<( const Event & ) const
+ \internal
+*/
+
+/*!
+ \fn bool Event::operator<=( const Event & ) const
+ \internal
+*/
+
+/*!
+ \fn bool Event::operator!=( const Event & ) const
+ \internal
+*/
+
+/*!
+ \fn bool Event::operator>( const Event & ) const
+ \internal
+*/
+
+/*!
+ \fn bool Event::operator>=( const Event & ) const
+ \internal
+*/
+
+/*!
+ \enum Event::RepeatType
+
+ This enum defines how a event will repeat, if at all.
+
+ <ul>
+ <li>\c NoRepeat - Event does not repeat.
+ <li>\c Daily - Event occurs every n days.
+ <li>\c Weekly - Event occurs every n weeks.
+ <li>\c MonthlyDay - Event occurs every n months. Event will always occur in
+ the same week and same day of week as the first event.
+ <li>\c MonthlyDate - Event occurs every n months. Event will always occur
+ on the same day of the month as the first event.
+ <li>\c Yearly - Event occurs every n years.
+ </ul>
+*/
+
+/*!
+ \fn bool Event::isAllDay() const
+
+ Returns TRUE if the event is an all day event. Otherwise returns FALSE.
+*/
+
+/*!
+ \fn void Event::setAllDay(bool allday)
+
+ If \a allday is TRUE, will set the event to be an all day event.
+ Otherwise sets the event to not be an all day event.
+
+ \warning This function may affect the start and end times of the event.
+*/
+
+/*!
+ \fn QDateTime Event::start() const
+
+ Returns the start date and time of the first occurance of the event.
+*/
+
+/*!
+ \fn QDateTime Event::end() const
+
+ Returns the end date and time of the first occurance of the event.
+*/
+
+/*!
+ \fn time_t Event::startTime() const
+ \internal
+*/
+
+/*!
+ \fn time_t Event::endTime() const
+ \internal
+*/
+
+/*!
+ \fn void Event::setAlarm(int delay, SoundTypeChoice s)
+
+ Sets the alarm delay of the event to \a delay and the sound type of the
+ alarm to \a s.
+*/
+
+/*!
+ \fn void Event::clearAlarm()
+
+ Clears the alarm for the event.
+*/
+
+/*!
+ \fn int Event::alarmDelay() const
+
+ Returns the delay in minutes between the alarm for an event and the
+ start of the event.
+*/
+
+/*!
+ \fn Event::RepeatType Event::repeatType() const
+
+ Returns the repeat pattern type for the event.
+
+ \sa frequency()
+*/
+
+/*!
+ \fn int Event::weekOffset() const
+
+ Returns the number of weeks from the start of the month that this event
+ occurs.
+*/
+
+/*!
+ \fn QDate Event::repeatTill() const
+
+ Returns the date that the event will continue to repeat until. If the event
+ repeats forever the value returned is undefined.
+
+ \sa repeatForever()
+*/
+
+/*!
+ \fn bool Event::repeatForever() const
+
+ Returns FALSE if there is a date set for the event to continue until.
+ Otherwise returns TRUE.
+*/
+
+/*!
+ \fn bool Event::doRepeat() const
+ \internal
+*/
+
+/*!
+ \fn bool Event::repeatOnWeekDay(int day) const
+
+ Returns TRUE if the event has a RepeatType of Weekly and is set to occur on
+ \a day each week. Otherwise returns FALSE.
+
+ \sa QDate::dayName()
+*/
+
+/*!
+ \fn void Event::setRepeatOnWeekDay(int day, bool enable)
+
+ If \a enable is TRUE then sets the event to occur on \a day each week.
+ Otherwise sets the event not to occur on \a day.
+
+ \warning this function is only relavent for a event with RepeatType of
+ Weekly.
+
+ \sa QDate::dayName()
+*/
+
+/*!
+ \fn int Event::frequency() const
+
+ Returns how often the event repeats.
+
+ \sa repeatType()
+*/
+
+/*!
+ \fn void Event::setRepeatType(RepeatType t)
+
+ Sets the repeat pattern type of the event to \a t.
+
+ \sa setFrequency()
+*/
+
+/*!
+ \fn void Event::setFrequency(int n)
+
+ Sets how often the event occurs with in its repeat pattern.
+
+ \sa setRepeatType()
+*/
+
+/*!
+ \fn void Event::setRepeatTill(const QDate &d)
+
+ Sets the event to repeat until \a d.
+*/
+
+/*!
+ \fn void Event::setRepeatForever(bool enable)
+
+ If \a enable is TRUE, sets the event to repeat forever. Otherwise
+ sets the event to stop repeating at some date.
+
+ \warning This function may affect the specific date the event will repeat
+ till.
+*/
+
+/*!
+ \fn bool Event::match(const QRegExp &r) const
+
+ Returns TRUE if the event matches the regular expression \a r.
+ Otherwise returns FALSE.
+*/
+
+/*!
+ \fn char Event::day(int)
+ \internal
+*/
+
+/*!
+ Creates a new, empty event.
+*/
Event::Event() : Record()
{
startUTC = endUTC = time( 0 );
typ = Normal;
hAlarm = FALSE;
hRepeat = FALSE;
aMinutes = 0;
aSound = Silent;
pattern.type = NoRepeat;
pattern.frequency = -1;
}
+/*!
+ \internal
+*/
Event::Event( const QMap<int, QString> &map )
{
setDescription( map[DatebookDescription] );
setLocation( map[Location] );
setCategories( idsFromString( map[DatebookCategory] ) );
setTimeZone( map[TimeZone] );
setNotes( map[Note] );
setStart( TimeConversion::fromUTC( map[StartDateTime].toUInt() ) );
@@ -101,66 +353,91 @@ Event::Event( const QMap<int, QString> &map )
p.days = map[ RepeatPatternDays ].toInt();
p.hasEndDate = map[ RepeatPatternHasEndDate ].toInt();
p.endDateUTC = map[ RepeatPatternEndDate ].toUInt();
setRepeat( p );
setUid( map[ DatebookUid ].toInt() );
}
+/*!
+ Destroys an event.
+*/
Event::~Event()
{
}
+/*!
+ \internal
+*/
int Event::week( const QDate& date )
{
// Calculates the week this date is in within that
// month. Equals the "row" is is in in the month view
int week = 1;
QDate tmp( date.year(), date.month(), 1 );
if ( date.dayOfWeek() < tmp.dayOfWeek() )
++week;
week += ( date.day() - 1 ) / 7;
return week;
}
+/*!
+ \internal
+*/
int Event::occurrence( const QDate& date )
{
// calculates the number of occurrances of this day of the
// week till the given date (e.g 3rd Wednesday of the month)
return ( date.day() - 1 ) / 7 + 1;
}
+/*!
+ \internal
+*/
int Event::dayOfWeek( char day )
{
int dayOfWeek = 1;
char i = Event::MON;
while ( !( i & day ) && i <= Event::SUN ) {
i <<= 1;
++dayOfWeek;
}
return dayOfWeek;
}
+/*!
+ \internal
+*/
int Event::monthDiff( const QDate& first, const QDate& second )
{
return ( second.year() - first.year() ) * 12 +
second.month() - first.month();
}
+/*!
+ \internal
+*/
QMap<int, QString> Event::toMap() const
{
QMap<int, QString> m;
- m.insert( DatebookDescription, description() );
- m.insert ( Location, location() );
- m.insert ( DatebookCategory, idsToString( categories() ) );
- m.insert ( TimeZone, timeZone() );
- m.insert ( Note, notes() );
+
+ if ( !description().isEmpty() )
+ m.insert( DatebookDescription, description() );
+ if ( !location().isEmpty() )
+ m.insert ( Location, location() );
+ if ( categories().count() )
+ m.insert ( DatebookCategory, idsToString( categories() ) );
+ if ( !timeZone().isEmpty() )
+ m.insert ( TimeZone, timeZone() );
+ if ( !notes().isEmpty() )
+ m.insert ( Note, notes() );
+
m.insert ( StartDateTime, QString::number( TimeConversion::toUTC( start() ) ) );
m.insert ( EndDateTime, QString::number( TimeConversion::toUTC( end() ) ) );
m.insert ( DatebookType, QString::number( (int)type() ) );
m.insert ( HasAlarm, ( hasAlarm() ? "1" : "0" ) );
m.insert ( SoundType, QString::number( (int)alarmSound() ) );
m.insert ( AlarmTime, QString::number( alarmTime() ) );
m.insert ( RepeatPatternType, QString::number( static_cast<int>( repeatPattern().type ) ) );
m.insert ( RepeatPatternFrequency, QString::number( repeatPattern().frequency ) );
@@ -169,185 +446,271 @@ QMap<int, QString> Event::toMap() const
m.insert ( RepeatPatternHasEndDate, QString::number( static_cast<int>( repeatPattern().hasEndDate ) ) );
m.insert ( RepeatPatternEndDate, QString::number( repeatPattern().endDateUTC ) );
m.insert( DatebookUid, QString::number( uid()) );
return m;
}
+/*!
+ \internal
+*/
void Event::setRepeat( const RepeatPattern &p )
{
setRepeat( p.type != NoRepeat, p );
}
+/*!
+ Sets the description of the event to \a s.
+*/
void Event::setDescription( const QString &s )
{
descript = s;
}
+/*!
+ Sets the location of the event to \a s.
+*/
void Event::setLocation( const QString &s )
{
locat = s;
}
// void Event::setCategory( const QString &s )
// {
// categ = s;
// }
+/*!
+ \internal
+*/
void Event::setType( Type t )
{
typ = t;
}
+/*!
+ Sets the start date and time of the first or only occurance of this event
+ to the date and time \a d. \a d should be in local time.
+*/
void Event::setStart( const QDateTime &d )
{
startUTC = TimeConversion::toUTC( d );
}
+/*!
+ \internal
+*/
void Event::setStart( time_t time )
{
startUTC = time;
}
+/*!
+ Sets the end date and time of the first or only occurance of this event
+ to the date and time \a d. \a d should be in local time.
+*/
void Event::setEnd( const QDateTime &d )
{
endUTC = TimeConversion::toUTC( d );
}
+/*!
+ \internal
+*/
void Event::setEnd( time_t time )
{
endUTC = time;
}
+/*!
+ \internal
+*/
void Event::setTimeZone( const QString &z )
{
tz = z;
}
+/*!
+ \internal
+*/
void Event::setAlarm( bool b, int minutes, SoundTypeChoice s )
{
hAlarm = b;
aMinutes = minutes;
aSound = s;
}
+/*!
+ \internal
+*/
void Event::setRepeat( bool b, const RepeatPattern &p )
{
hRepeat = b;
pattern = p;
}
+/*!
+ Sets the notes for the event to \a n.
+*/
void Event::setNotes( const QString &n )
{
note = n;
}
+/*!
+ Returns the description of the event.
+*/
const QString &Event::description() const
{
return descript;
}
+/*!
+ Returns the location of the event.
+*/
const QString &Event::location() const
{
return locat;
}
// QString Event::category() const
// {
// return categ;
// }
+/*!
+ \internal
+*/
Event::Type Event::type() const
{
return typ;
}
+/*!
+ \internal
+*/
QDateTime Event::start( bool actual ) const
{
QDateTime dt = (startUTC > 0) ? TimeConversion::fromUTC( startUTC ) : QDateTime::currentDateTime();
if ( actual && typ == AllDay ) {
QTime t = dt.time();
t.setHMS( 0, 0, 0 );
dt.setTime( t );
}
return dt;
}
+/*!
+ \internal
+*/
QDateTime Event::end( bool actual ) const
{
QDateTime dt = (endUTC > 0) ? TimeConversion::fromUTC( endUTC ) : QDateTime::currentDateTime();
if ( actual && typ == AllDay ) {
QTime t = dt.time();
t.setHMS( 23, 59, 59 );
dt.setTime( t );
}
return dt;
}
+/*!
+ \internal
+*/
const QString &Event::timeZone() const
{
return tz;
}
+/*!
+ \internal
+*/
bool Event::hasAlarm() const
{
return hAlarm;
}
+/*!
+ \internal
+*/
int Event::alarmTime() const
{
return aMinutes;
}
+/*!
+ Returns the sound type for the alarm of this event.
+*/
Event::SoundTypeChoice Event::alarmSound() const
{
return aSound;
}
+/*!
+ \internal
+*/
bool Event::hasRepeat() const
{
return doRepeat();
}
+/*!
+ \internal
+*/
const Event::RepeatPattern &Event::repeatPattern() const
{
return pattern;
}
+/*!
+ \internal
+*/
Event::RepeatPattern &Event::repeatPattern()
{
return pattern;
}
+/*!
+ Returns the notes for the event.
+*/
const QString &Event::notes() const
{
return note;
}
+/*!
+ \internal
+*/
bool Event::operator==( const Event &e ) const
{
+ if ( uid() && e.uid() == uid() )
+ return TRUE;
return ( e.descript == descript &&
e.locat == locat &&
e.categ == categ &&
e.typ == typ &&
e.startUTC == startUTC &&
e.endUTC == endUTC &&
e.tz == tz &&
e.hAlarm == hAlarm &&
e.aMinutes == aMinutes &&
e.aSound == aSound &&
e.hRepeat == hRepeat &&
e.pattern == pattern &&
e.note == note );
}
+/*!
+ \internal
+ Appends the contact information to \a buf.
+*/
void Event::save( QString& buf )
{
buf += " description=\"" + Qtopia::escapeString(descript) + "\"";
if ( !locat.isEmpty() )
buf += " location=\"" + Qtopia::escapeString(locat) + "\"";
// save the categoies differently....
QString strCats = idsToString( categories() );
buf += " categories=\"" + Qtopia::escapeString(strCats) + "\"";
@@ -373,67 +736,103 @@ void Event::save( QString& buf )
+ QString::number( endUTC )
+ "\"";
if ( !note.isEmpty() )
buf += " note=\"" + Qtopia::escapeString( note ) + "\"";
buf += customToXml();
}
+/*!
+ \internal
+*/
bool Event::RepeatPattern::operator==( const Event::RepeatPattern &right ) const
{
// *sigh*
return ( type == right.type
&& frequency == right.frequency
&& position == right.position
&& days == right.days
&& hasEndDate == right.hasEndDate
&& endDateUTC == right.endDateUTC
&& createTime == right.createTime );
}
+/*!
+ \class EffectiveEvent
+ \brief The EffectiveEvent class the data for a single occurance of an event.
+
+ This class describes the event for a single occurance of it. For example if
+ an Event occurs every week, the effective event might represent the third
+ occurance of this Event.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+ \warning This class will be phased out in Qtopia 3.x
+*/
+
+/*!
+ \enum EffectiveEvent::Position
+ \internal
+*/
+
+/*!
+ \fn EffectiveEvent &EffectiveEvent::operator=(const EffectiveEvent &)
+ \internal
+*/
class EffectiveEventPrivate
{
public:
//currently the existence of the d pointer means multi-day repeating,
//msut be changed if we use the d pointer for anything else.
QDate startDate;
QDate endDate;
};
-
+/*!
+ \internal
+*/
EffectiveEvent::EffectiveEvent()
{
mDate = QDate::currentDate();
mStart = mEnd = QTime::currentTime();
d = 0;
}
+/*!
+ \internal
+*/
EffectiveEvent::EffectiveEvent( const Event &e, const QDate &date, Position pos )
{
mEvent = e;
mDate = date;
if ( pos & Start )
mStart = e.start( TRUE ).time();
else
mStart = QTime( 0, 0, 0 );
if ( pos & End )
mEnd = e.end( TRUE ).time();
else
mEnd = QTime( 23, 59, 59 );
d = 0;
}
+/*!
+ \internal
+*/
EffectiveEvent::~EffectiveEvent()
{
delete d;
}
+/*!
+ \internal
+*/
EffectiveEvent::EffectiveEvent( const EffectiveEvent &e )
{
d = 0;
*this = e;
}
EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e )
{
@@ -456,148 +855,214 @@ EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e )
}
// QString EffectiveEvent::category() const
// {
// return mEvent.category();
// }
+/*!
+ Returns the description of the event for this effective event.
+*/
const QString &EffectiveEvent::description( ) const
{
return mEvent.description();
}
+/*!
+\internal
+*/
const QString &EffectiveEvent::location( ) const
{
return mEvent.location();
}
+/*!
+\internal
+*/
const QString &EffectiveEvent::notes() const
{
return mEvent.notes();
}
+/*!
+ Returns the event associated with this effective event.
+*/
const Event &EffectiveEvent::event() const
{
return mEvent;
}
+/*!
+ \internal
+*/
const QTime &EffectiveEvent::end() const
{
return mEnd;
}
+/*!
+ \internal
+*/
const QTime &EffectiveEvent::start() const
{
return mStart;
}
+/*!
+ Returns the date the effective event occurs on.
+*/
const QDate &EffectiveEvent::date() const
{
return mDate;
}
+/*!
+ \internal
+*/
int EffectiveEvent::length() const
{
return (mEnd.hour() * 60 - mStart.hour() * 60)
+ QABS(mStart.minute() - mEnd.minute() );
}
+/*!
+ \internal
+*/
void EffectiveEvent::setDate( const QDate &dt )
{
mDate = dt;
}
+/*!
+ \internal
+*/
void EffectiveEvent::setStart( const QTime &start )
{
mStart = start;
}
+/*!
+ \internal
+*/
void EffectiveEvent::setEnd( const QTime &end )
{
mEnd = end;
}
+/*!
+ \internal
+*/
void EffectiveEvent::setEvent( Event e )
{
mEvent = e;
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator<( const EffectiveEvent &e ) const
{
if ( mDate < e.date() )
return TRUE;
if ( mDate == e.date() )
return ( mStart < e.start() );
else
return FALSE;
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator<=( const EffectiveEvent &e ) const
{
return (mDate <= e.date() );
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator==( const EffectiveEvent &e ) const
{
return ( mDate == e.date()
&& mStart == e.start()
&& mEnd == e.end()
&& mEvent == e.event() );
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator!=( const EffectiveEvent &e ) const
{
return !(*this == e);
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator>( const EffectiveEvent &e ) const
{
return !(*this <= e );
}
+/*!
+ \internal
+*/
bool EffectiveEvent::operator>=(const EffectiveEvent &e) const
{
return !(*this < e);
}
+/*!
+ \internal
+*/
void EffectiveEvent::setEffectiveDates( const QDate &from, const QDate &to )
{
if ( !from.isValid() ) {
delete d;
d = 0;
return;
}
if ( !d )
d = new EffectiveEventPrivate;
d->startDate = from;
d->endDate = to;
}
+/*!
+ \internal
+*/
QDate EffectiveEvent::startDate() const
{
if ( d )
return d->startDate;
else if ( mEvent.hasRepeat() )
return mDate; // single day, since multi-day should have a d pointer
else
return mEvent.start().date();
}
+/*!
+ \internal
+*/
QDate EffectiveEvent::endDate() const
{
if ( d )
return d->endDate;
else if ( mEvent.hasRepeat() )
return mDate; // single day, since multi-day should have a d pointer
else
return mEvent.end().date();
}
+/*!
+ \internal
+*/
int EffectiveEvent::size() const
{
return ( mEnd.hour() - mStart.hour() ) * 3600
+ (mEnd.minute() - mStart.minute() * 60
+ mEnd.second() - mStart.second() );
}
@@ -735,51 +1200,71 @@ static Event parseVObject( VObject *obj )
if ( haveAlarm ) {
int minutes = alarmTime.secsTo( e.start() ) / 60;
e.setAlarm( TRUE, minutes, soundType );
}
return e;
}
-
+/*!
+ Writes the list of \a events as a set of VCards to the file \a filename.
+*/
void Event::writeVCalendar( const QString &filename, const QValueList<Event> &events)
-{
- QFileDirect f( filename.utf8().data() );
- if ( !f.open( IO_WriteOnly ) ) {
- qWarning("Unable to open vcard write");
- return;
- }
+{
+
+ QFileDirect f( filename.utf8().data() );
+
+ if ( !f.open( IO_WriteOnly ) ) {
+
+ qWarning("Unable to open vcard write");
+
+ return;
+
+ }
+
QValueList<Event>::ConstIterator it;
for( it = events.begin(); it != events.end(); ++it ) {
VObject *obj = createVObject( *it );
writeVObject( f.directHandle() , obj );
cleanVObject( obj );
- }
+ }
+
cleanStrTbl();
}
+/*!
+ Writes \a event as a VCard to the file \a filename.
+*/
void Event::writeVCalendar( const QString &filename, const Event &event)
-{
- QFileDirect f( filename.utf8().data() );
- if ( !f.open( IO_WriteOnly ) ) {
- qWarning("Unable to open vcard write");
- return;
- }
+{
+
+ QFileDirect f( filename.utf8().data() );
+
+ if ( !f.open( IO_WriteOnly ) ) {
+
+ qWarning("Unable to open vcard write");
+
+ return;
+
+ }
+
VObject *obj = createVObject( event );
writeVObject( f.directHandle() , obj );
cleanVObject( obj );
cleanStrTbl();
}
-
+/*!
+ Returns the set of events read as VCards from the file \a filename.
+*/
QValueList<Event> Event::readVCalendar( const QString &filename )
{
VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
QValueList<Event> events;
while ( obj ) {
QCString name = vObjectName( obj );
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,12 +1,12 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
@@ -18,32 +18,41 @@
**
**********************************************************************/
#ifndef __EVENT_H__
#define __EVENT_H__
#include <qdatetime.h>
#include <qvaluelist.h>
+#include <qcolor.h>
#ifdef PALMTOPCENTER
#include <qpc/qsorter.h>
#endif
-#include <qpe/palmtoprecord.h>
+#include <qtopia/private/palmtoprecord.h>
#include <qpe/timeconversion.h>
+static const QColor colorNormal = QColor(255, 0 , 0 );
+static const QColor colorRepeat = QColor(0 , 0 , 255);
+static const QColor colorNormalLight = QColor(255, 220, 220);
+static const QColor colorRepeatLight = QColor(200, 200, 255);
+
class EventPrivate;
class QPC_EXPORT Event : public Qtopia::Record
{
public:
enum RepeatType { NoRepeat = -1, Daily, Weekly, MonthlyDay,
MonthlyDate, Yearly };
+
+ // Don't use this.
enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
FRI = 0x10, SAT = 0x20, SUN = 0x40 };
+ // Don't use this.
struct QPC_EXPORT RepeatPattern
{
RepeatPattern() {
type = NoRepeat; frequency = -1; days = 0; position = 0; createTime = -1;
hasEndDate = FALSE; endDateUTC = 0; }
bool operator ==( const RepeatPattern &right ) const;
RepeatType type;
@@ -65,70 +74,99 @@ public:
static void writeVCalendar( const QString &filename, const QValueList<Event> &events);
static void writeVCalendar( const QString &filename, const Event &event);
static QValueList<Event> readVCalendar( const QString &filename );
enum Type { Normal, AllDay };
enum SoundTypeChoice { Silent, Loud };
+ // Don't use these, there are essentially meaningless.
bool operator<( const Event &e1) const { return start() < e1.start(); };
bool operator<=( const Event &e1 ) const { return start() <= e1.start(); };
bool operator!=( const Event &e1 ) const { return !( *this == e1 ); };
bool operator>( const Event &e1 ) const { return start() > e1.start(); };
bool operator>=(const Event &e1 ) const { return start() >= e1.start(); };
bool operator==( const Event &e ) const;
void setDescription( const QString &s );
const QString &description() const;
void setLocation( const QString &s );
const QString &location() const;
- void setType( Type t );
- Type type() const;
+ void setNotes( const QString &n );
+ const QString &notes() const;
+
+ void setType( Type t ); // Don't use me.
+ Type type() const; // Don't use me.
+
+ void setAllDay(bool);
+ bool isAllDay() const;
+
void setStart( const QDateTime &d );
- void setStart( time_t time );
- QDateTime start( bool actual = FALSE ) const;
- time_t startTime() const { return startUTC; }
+ void setStart( time_t time ); // don't use me.
+ QDateTime start( ) const;
+ QDateTime start( bool actual ) const; // don't use me.
+ time_t startTime() const { return startUTC; } // don't use me.
void setEnd( const QDateTime &e );
- void setEnd( time_t time );
- QDateTime end( bool actual = FALSE ) const;
- time_t endTime() const { return endUTC; }
+ void setEnd( time_t time ); // don't use me
+ QDateTime end( ) const;
+ QDateTime end( bool actual ) const; // don't use me.
+ time_t endTime() const { return endUTC; } // don't use me.
void setTimeZone( const QString & );
const QString &timeZone() const;
- void setAlarm( bool b, int minutes, SoundTypeChoice );
+ void setAlarm( int minutes, SoundTypeChoice );
+ void clearAlarm();
+ void setAlarm( bool b, int minutes, SoundTypeChoice ); // Don't use me.
bool hasAlarm() const;
- int alarmTime() const;
+ int alarmDelay() const;
+ int alarmTime() const; // Don't use me.
SoundTypeChoice alarmSound() const;
+
+ RepeatType repeatType() const;
+ int frequency() const;
+ int weekOffset() const;
+ QDate repeatTill() const;
+ bool repeatForever() const;
+ bool repeatOnWeekDay(int day) const;
+
+ void setRepeatType(RepeatType);
+ void setFrequency(int);
+ void setRepeatTill(const QDate &);
+ void setRepeatForever(bool);
+ void setRepeatOnWeekDay(int day, bool enable);
+
+ // Don't use any of these.
void setRepeat( bool b, const RepeatPattern &p );
void setRepeat( const RepeatPattern &p );
bool hasRepeat() const;
const RepeatPattern &repeatPattern() const;
RepeatPattern &repeatPattern();
- void setNotes( const QString &n );
- const QString &notes() const;
bool doRepeat() const { return pattern.type != NoRepeat; }
void save( QString& buf );
//void load( Node *n );
+ bool match( const QRegExp &r ) const;
+
+ // Don't use these either. Functionality will be moved elsewhere.
+
// helper function to calculate the week of the given date
static int week( const QDate& date );
// calculates the number of occurrences of the week day of
// the given date from the start of the month
static int occurrence( const QDate& date );
// returns a proper days-char for a given dayOfWeek()
static char day( int dayOfWeek ) { return 1 << ( dayOfWeek - 1 ); }
// returns the dayOfWeek for the *first* day it finds (ignores
// any further days!). Returns 1 (Monday) if there isn't any day found
static int dayOfWeek( char day );
// returns the difference of months from first to second.
static int monthDiff( const QDate& first, const QDate& second );
- bool match( const QRegExp &r ) const;
private:
Qtopia::UidGen &uidGen() { return sUidGen; }
static Qtopia::UidGen sUidGen;
QString descript, locat, categ;
Type typ : 4;
bool startTimeDirty : 1;
@@ -206,16 +244,119 @@ private:
class EffectiveEventPrivate *d;
Event mEvent;
QDate mDate;
QTime mStart,
mEnd;
};
+inline void Event::setAlarm( int minutes, SoundTypeChoice s )
+{
+ setAlarm(TRUE, minutes, s);
+}
+
+inline void Event::clearAlarm()
+{
+ setAlarm(FALSE, 0, Silent);
+}
+
+inline int Event::alarmDelay() const
+{
+ return alarmTime();
+}
+
+inline void Event::setAllDay(bool enable)
+{
+ if (enable)
+ setType(AllDay);
+ else
+ setType(Normal);
+};
+
+inline bool Event::isAllDay() const
+{
+ return type() == AllDay;
+}
+
+inline Event::RepeatType Event::repeatType() const
+{
+ return repeatPattern().type;
+}
+
+inline int Event::frequency() const
+{
+ return repeatPattern().frequency;
+}
+
+inline int Event::weekOffset() const
+{
+ if (start().date().day() == 1)
+ return 1;
+ return (start().date().day() - 1) / 7 + 1;
+}
+
+inline QDate Event::repeatTill() const
+{
+ return repeatPattern().endDate();
+}
+
+inline bool Event::repeatForever() const
+{
+ return !repeatPattern().hasEndDate;
+}
+
+inline void Event::setRepeatType(RepeatType t)
+{
+ pattern.type = t;
+}
+
+inline void Event::setFrequency(int f)
+{
+ pattern.frequency = f;
+}
+
+inline void Event::setRepeatTill(const QDate &d)
+{
+ pattern.setEndDate(d);
+ pattern.hasEndDate = TRUE;
+}
+
+inline void Event::setRepeatForever(bool b)
+{
+ if (!b == pattern.hasEndDate)
+ return;
+ if (!b && !pattern.hasEndDate)
+ pattern.setEndDate(end().date());
+ pattern.hasEndDate = !b;
+}
+
+inline bool Event::repeatOnWeekDay(int day) const
+{
+ if (pattern.type != Weekly)
+ return FALSE;
+ return ( (1 << (day - 1)) & pattern.days ) != 0;
+}
+
+inline void Event::setRepeatOnWeekDay(int day, bool enable)
+{
+ if ( repeatOnWeekDay( day ) != enable )
+ pattern.days ^= 1 << (day - 1);
+}
+
+inline QDateTime Event::start( ) const
+{
+ return start(FALSE);
+}
+
+inline QDateTime Event::end( ) const
+{
+ return end(FALSE);
+}
+
#ifdef PALMTOPCENTER
class QPC_EXPORT EffectiveEventSizeSorter : public QSorter<EffectiveEvent>
{
public:
int compare( const EffectiveEvent& a, const EffectiveEvent& b ) const
{
return a.size() - b.size();
}
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,34 +1,45 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included
-** in the packaging of this file.
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-** PARTICULAR PURPOSE.
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-#include "palmtoprecord.h"
-#include "stringutil.h"
+#include <qtopia/private/palmtoprecord.h>
+#include <qtopia/stringutil.h>
#include <qstringlist.h>
+/*! \class Qtopia::PalmtopRecord palmtoprecord.h
+ \brief The Qtopia::PalmtopRecord class is the base class for all PIM records.
+
+ Provides unique id and category support for all PIM records.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
+
namespace Qtopia {
+
+
Record &Record::operator=( const Record &c )
{
mUid = c.mUid;
mCats = c.mCats;
customMap = c.customMap;
return *this;
}
@@ -36,18 +47,21 @@ void Record::setCategories( int single )
{
if ( single == 0 )
return;
mCats.resize(1);
mCats[0] = single;
}
// convenience methods provided for loading and saving to xml
-QString Record::idsToString( const QArray<int> &cats )
+QString Record::idsToString( const QArray<int> &catsUnsorted )
{
+ QArray<int> cats = catsUnsorted;
+ cats.sort();
+
QString str;
for ( uint i = 0; i < cats.size(); i++ )
if ( i == 0 )
str = QString::number( cats[int(i)] );
else
str += ";" + QString::number( cats[int(i)] );
return str;
@@ -79,40 +93,40 @@ QString Record::customField( const QString &key) const
return QString::null;
}
/*!
Sets the string stored for the custom field \a key to \a value.
*/
void Record::setCustomField( const QString &key, const QString &value)
{
- qWarning("setting custom " + key + " to " + value);
+// qWarning("setting custom " + key + " to " + value);
if (customMap.contains(key))
customMap.replace(key, value);
else
customMap.insert(key, value);
- qWarning(QString("custom size %1").arg(customMap.count()));
+// qWarning(QString("custom size %1").arg(customMap.count()));
}
/*!
Removes the custom field \a key.
*/
void Record::removeCustomField(const QString &key)
{
customMap.remove(key);
}
QString Record::customToXml() const
{
//qWarning(QString("writing custom %1").arg(customMap.count()));
QString buf(" ");
for ( QMap<QString, QString>::ConstIterator cit = customMap.begin();
cit != customMap.end(); ++cit) {
- qWarning(".ITEM.");
+// qWarning(".ITEM.");
buf += cit.key();
buf += "=\"";
buf += escapeString(cit.data());
buf += "\" ";
}
return buf;
}
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,41 +1,38 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included
-** in the packaging of this file.
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-** PARTICULAR PURPOSE.
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-
#ifndef QTPALMTOP_RECORD_H
#define QTPALMTOP_RECORD_H
-
#include <qglobal.h>
#include "qpcglobal.h"
#include "palmtopuidgen.h"
#include <qarray.h>
#include <qmap.h>
#if defined(QPC_TEMPLATEDLL)
// MOC_SKIP_BEGIN
-template class QPC_EXPORT QMap<QString, QString>;
+QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap<QString, QString>;
// MOC_SKIP_END
#endif
class QRegExp;
namespace Qtopia {
class RecordPrivate;
class QPC_EXPORT Record
@@ -44,20 +41,27 @@ public:
Record() : mUid(0), mCats() { }
Record( const Record &c ) : mUid( c.mUid ), mCats ( c.mCats ), customMap(c.customMap) { }
virtual ~Record() { }
Record &operator=( const Record &c );
virtual bool match( const QRegExp & ) const { return FALSE; }
- void setCategories( const QArray<int> &v ) { mCats = v; }
+ void setCategories( const QArray<int> &v ) { mCats = v; mCats.sort(); }
void setCategories( int single );
const QArray<int> &categories() const { return mCats; }
+ void reassignCategoryId( int oldId, int newId )
+ {
+ int index = mCats.find( oldId );
+ if ( index >= 0 )
+ mCats[index] = newId;
+ }
+
int uid() const { return mUid; };
virtual void setUid( int i ) { mUid = i; uidGen().store( mUid ); }
bool isValidUid() const { return mUid != 0; }
void assignUid() { setUid( uidGen().generate() ); }
virtual QString customField(const QString &) const;
virtual void setCustomField(const QString &, const QString &);
virtual void removeCustomField(const QString &);
@@ -72,23 +76,20 @@ public:
// convenience methods provided for loading and saving to xml
static QArray<int> idsFromString( const QString &str );
// for debugging
static void dump( const QMap<int, QString> &map );
protected:
virtual UidGen &uidGen() = 0;
-
virtual QString customToXml() const;
-
private:
int mUid;
QArray<int> mCats;
-
QMap<QString, QString> customMap;
-
RecordPrivate *d;
};
}
#endif
+
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,38 +1,38 @@
-#ifndef QTPALMTOP_UIDGEN_H
-#define QTPALMTOP_UIDGEN_H
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
-** Licensees holding valid Qtopia Developer license may use this
-** file in accordance with the Qtopia Developer License Agreement
-** provided with the Software.
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-** PURPOSE.
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
-** email sales@trolltech.com for information about Qtopia License
-** Agreements.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
+#ifndef QTPALMTOP_UIDGEN_H
+#define QTPALMTOP_UIDGEN_H
+
#include <time.h>
#include <qmap.h>
#include "qpcglobal.h"
#if defined(QPC_TEMPLATEDLL)
// MOC_SKIP_BEGIN
-template class QPC_EXPORT QMap< int, bool >;
+QPC_TEMPLATEEXTERN template class QPC_EXPORT QMap< int, bool >;
// MOC_SKIP_END
#endif
namespace Qtopia {
class QPC_EXPORT UidGen
{
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 @@
-/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
-**
-** This file is part of the Qtopia Environment.
-**
-** Licensees holding valid Qtopia Developer license may use this
-** file in accordance with the Qtopia Developer License Agreement
-** provided with the Software.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-** PURPOSE.
-**
-** email sales@trolltech.com for information about Qtopia License
-** Agreements.
-**
-** Contact info@trolltech.com if any conditions of this licensing are
-** not clear to you.
-**
-**********************************************************************/
-
-#ifndef QFILE_DIRECT_H
-#define QFILE_DIRECT_H
-#include <qfile.h>
-#include <qpe/qpcglobal.h>
-
-class QPC_EXPORT QFileDirect : public QFile
-{
-public:
- QFileDirect() : QFile() { }
- QFileDirect( const QString &name ) : QFile(name) { }
-
- FILE *directHandle() { return fh; }
-};
-
-#endif
-
+/**********************************************************************
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
+**
+** This file is part of the Qtopia Environment.
+**
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
+**
+** Contact info@trolltech.com if any conditions of this licensing are
+** not clear to you.
+**
+**********************************************************************/
+
+#ifndef QFILE_DIRECT_H
+#define QFILE_DIRECT_H
+#include <qfile.h>
+#include <qtopia/private/qpcglobal.h>
+
+class QPC_EXPORT QFileDirect : public QFile
+{
+public:
+ QFileDirect() : QFile() { }
+ QFileDirect( const QString &name ) : QFile(name) { }
+
+ FILE *directHandle() { return fh; }
+};
+
+#endif
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,12 +1,12 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** Licensees holding valid Qtopia Developer license may use this
** file in accordance with the Qtopia Developer License Agreement
** provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE.
@@ -17,30 +17,33 @@
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef QPC_GLOBAL_H
#define QPC_GLOBAL_H
-#if ( defined(Q_OS_WIN32) || defined(Q_OS_WIN64) ) && defined(PALMTOPCENTER)
#include <qglobal.h>
+
+#if ( defined(Q_OS_WIN32) || defined(Q_OS_WIN64) ) && defined(PALMTOPCENTER)
// # if defined(QT_NODLL)
//# undef QPC_MAKEDLL
//# undef QPC_DLL
# if defined(QPC_MAKEDLL) /* create a Qt DLL library */
# if defined(QPC_DLL)
# undef QPC_DLL
# endif
# define QPC_EXPORT __declspec(dllexport)
+# define QPC_TEMPLATEEXTERN
# define QPC_TEMPLATEDLL
# undef QPC_DISABLE_COPY /* avoid unresolved externals */
# elif defined(QPC_DLL) /* use a Qt DLL library */
# define QPC_EXPORT __declspec(dllimport)
+# define QPC_TEMPLATEEXTERN extern
# define QPC_TEMPLATEDLL
# undef QPC_DISABLE_COPY /* avoid unresolved externals */
# endif
#else
# undef QPC_MAKEDLL /* ignore these for other platforms */
# undef QPC_DLL
#endif
#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,23 +1,22 @@
/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
-** Licensees holding valid Qtopia Developer license may use this
-** file in accordance with the Qtopia Developer License Agreement
-** provided with the Software.
+** This file may be distributed and/or modified under the terms of the
+** GNU General Public License version 2 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.
**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-** PURPOSE.
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
-** email sales@trolltech.com for information about Qtopia License
-** Agreements.
+** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef QPC_RECORD_FIELDS_H
#define QPC_RECORD_FIELDS_H
#include "qpcglobal.h"
@@ -83,19 +82,20 @@ namespace Qtopia
Gender,
Birthday,
Anniversary,
Nickname,
Children,
// other
Notes,
- Groups
- ,rid,
+ // used for internal record keeping, not for end user.
+ Groups,
+ rid,
rinfo
};
// dataset = "todolist"
enum TaskFields {
TaskUid = UID_ID,
TaskCategory = CATEGORY_ID,
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 @@
-/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
-**
-** This file is part of Qtopia Environment.
-**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included
-** in the packaging of this file.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-** PARTICULAR PURPOSE.
-**
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-** Contact info@trolltech.com if any conditions of this licensing are
-** not clear to you.
-**
-**********************************************************************/
-
-#include "stringutil.h"
-#include <qregexp.h>
-#include <qstringlist.h>
-
-namespace Qtopia
-{
-
-
-
-/*
- Very, very simple Latin-1 only collation guaranteed to displease anyone
- who actually uses the non-ASCII characters.
- */
-
-static const char collationHack[] = {
-0x00, //C-@
-0x01, //C-A
-0x02, //C-B
-0x03, //C-C
-0x04, //C-D
-0x05, //C-E
-0x06, //C-F
-0x07, //C-G
-0x08, //C-H
-0x09, //C-I
-0x0a, //C-J
-0x0b, //C-K
-0x0c, //C-L
-0x0d, //C-M
-0x0e, //C-N
-0x0f, //C-O
-0x10, //C-P
-0x11, //C-Q
-0x12, //C-R
-0x13, //C-S
-0x14, //C-T
-0x15, //C-U
-0x16, //C-V
-0x17, //C-W
-0x18, //C-X
-0x19, //C-Y
-0x1a, //C-Z
-0x1b, //C-[
-0x1c, //C-\
-0x1d, //C-]
-0x1e, //C-^
-0x1f, //C-_
-' ', //
-'!', //!
-'"', //"
-'#', //#
-'$', //$
-'%', //%
-'&', //&
-'\'', //'
-'(', //(
-')', //)
-'*', //*
-'+', //+
-',', //,
-'-', //-
-'.', //.
-'/', ///
-0x80, //0
-0x81, //1
-0x82, //2
-0x83, //3
-0x84, //4
-0x85, //5
-0x86, //6
-0x87, //7
-0x88, //8
-0x89, //9
-':', //:
-';', //;
-'<', //<
-'=', //=
-'>', //>
-'?', //?
-'@', //@
-'A', //A
-'B', //B
-'C', //C
-'D', //D
-'E', //E
-'F', //F
-'G', //G
-'H', //H
-'I', //I
-'J', //J
-'K', //K
-'L', //L
-'M', //M
-'N', //N
-'O', //O
-'P', //P
-'Q', //Q
-'R', //R
-'S', //S
-'T', //T
-'U', //U
-'V', //V
-'W', //W
-'X', //X
-'Y', //Y
-'Z', //Z
-'[', //[
-'\\', //\
-']', //]
-'^', //^
-'_', //_
-'`', //`
-'A', //a
-'B', //b
-'C', //c
-'D', //d
-'E', //e
-'F', //f
-'G', //g
-'H', //h
-'I', //i
-'J', //j
-'K', //k
-'L', //l
-'M', //m
-'N', //n
-'O', //o
-'P', //p
-'Q', //q
-'R', //r
-'S', //s
-'T', //t
-'U', //u
-'V', //v
-'W', //w
-'X', //x
-'Y', //y
-'Z', //z
-'{', //{
-'|', //|
-'}', //}
-'~', //~
-'', //
-0x80, //C-M-@
-0x81, //C-M-A
-0x82, //C-M-B
-0x83, //C-M-C
-0x84, //C-M-D
-0x85, //C-M-E
-0x86, //C-M-F
-0x87, //C-M-G
-0x88, //C-M-H
-0x89, //C-M-I
-0x8a, //C-M-J
-0x8b, //C-M-K
-0x8c, //C-M-L
-0x8d, //C-M-M
-0x8e, //C-M-N
-0x8f, //C-M-O
-0x90, //C-M-P
-0x91, //C-M-Q
-0x92, //C-M-R
-0x93, //C-M-S
-0x94, //C-M-T
-0x95, //C-M-U
-0x96, //C-M-V
-0x97, //C-M-W
-0x98, //C-M-X
-0x99, //C-M-Y
-0x9a, //C-M-Z
-0x9b, //C-M-[
-0x9c, //C-M-\
-0x9d, //C-M-]
-0x9e, //C-M-^
-0x9f, //C-M-_
-' ', // 
-'¡', //¡
-'¢', //¢
-'£', //£
-'¤', //¤
-'¥', //¥
-'¦', //¦
-'§', //§
-'¨', //¨
-'©', //©
-'A', //ª
-'«', //«
-'¬', //¬
-'­', //­
-'®', //®
-'¯', //¯
-'O', //°
-'±', //±
-'²', //²
-'³', //³
-'´', //´
-'µ', //µ
-'P', //¶
-'·', //·
-'¸', //¸
-'¹', //¹
-'O', //º
-'»', //»
-'¼', //¼
-'½', //½
-'¾', //¾
-'¿', //¿
-'A', //À
-'A', //Á
-'A', //Â
-'A', //Ã
-'A', //Ä
-'A', //Å
-'A', //Æ
-'C', //Ç
-'E', //È
-'E', //É
-'E', //Ê
-'E', //Ë
-'I', //Ì
-'I', //Í
-'I', //Î
-'I', //Ï
-'D', //Ð
-'N', //Ñ
-'O', //Ò
-'O', //Ó
-'O', //Ô
-'O', //Õ
-'O', //Ö
-'×', //×
-'O', //Ø
-'U', //Ù
-'U', //Ú
-'U', //Û
-'U', //Ü
-'Y', //Ý
-'T', //Þ
-'S', //ß
-'A', //à
-'A', //á
-'A', //â
-'A', //ã
-'A', //ä
-'A', //å
-'A', //æ
-'C', //ç
-'E', //è
-'E', //é
-'E', //ê
-'E', //ë
-'I', //ì
-'I', //í
-'I', //î
-'I', //ï
-'D', //ð
-'N', //ñ
-'O', //ò
-'O', //ó
-'O', //ô
-'O', //õ
-'O', //ö
-'÷', //÷
-'O', //ø
-'U', //ù
-'U', //ú
-'U', //û
-'U', //ü
-'Y', //ý
-'T', //þ
-'Y', //ÿ
-};
-
-
-
-
-
-static void hackString ( QString &s )
-{
- int len = s.length();
- const QChar* uc = s.unicode();
- for ( int i = 0; i < len; i++ ) {
- if ( !uc++->row() )
- s[i] = collationHack[s[i].cell()];
- }
-}
-
-QString buildSortKey( const QString & s )
-{
- QString res = s;
- hackString( res );
- return res;
-}
-
-QString buildSortKey( const QString & s1, const QString & s2 )
-{
- QString res = s1 + QChar( '\0' ) + s2;
- hackString( res );
- return res;
-}
-
-QString buildSortKey( const QString & s1, const QString & s2,
- const QString & s3 )
-{
- QString res = s1 + QChar( '\0' ) + s2 + QChar( '\0' ) + s3;
- hackString( res );
- return res;
-}
-
-static inline QChar coll( QChar u )
-{
- return u.row() ? u : QChar(collationHack[ u.cell() ]);
-}
-
-
-int compare( const QString & s1, const QString & s2 )
-{
- const QChar* u1 = s1.unicode();
- const QChar* u2 = s2.unicode();
-
- if ( u1 == u2 )
- return 0;
- if ( u1 == 0 )
- return 1;
- if ( u2 == 0 )
- return -1;
- int l=QMIN(s1.length(),s2.length());
- while ( l-- && coll(*u1) == coll(*u2) )
- u1++,u2++;
- if ( l==-1 )
- return ( s1.length()-s2.length() );
- return u1->unicode() - u2->unicode();
-}
-
-QString simplifyMultiLineSpace( const QString &multiLine )
-{
- QString result;
- QStringList lines = QStringList::split("\n", multiLine);
- for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
- if ( it != lines.begin() )
- result += "\n";
- result += (*it).simplifyWhiteSpace();
- }
- return result;
-}
-
-QString escapeString( const QString& plain )
-{
- QString tmp(plain);
- int pos = tmp.length();
- const QChar *uc = plain.unicode();
- while ( pos-- ) {
- unsigned char ch = uc[pos].latin1();
- if ( ch == '&' )
- tmp.replace( pos, 1, "&amp;" );
- else if ( ch == '<' )
- tmp.replace( pos, 1, "&lt;" );
- else if ( ch == '>' )
- tmp.replace( pos, 1, "&gt;" );
- else if ( ch == '\"' )
- tmp.replace( pos, 1, "&quot;" );
- }
- return tmp;
-}
-
-QString plainString( const char* escaped, unsigned int length )
-{
- return plainString( QString::fromUtf8( escaped, length ) );
-}
-
-QString plainString( const QCString& string )
-{
- // We first have to pass it through a ::fromUtf8()
- return plainString( string.data(), string.length() );
-}
-
-QString plainString( const QString& string )
-{
- QString tmp( string );
- int pos = -1;
- while ( (pos = tmp.find( "&", pos +1 ) ) != -1 ) {
- if ( tmp.find( "&amp;", pos ) == pos )
- tmp.replace( pos, 5, "&" );
- else if ( tmp.find( "&lt;", pos ) == pos )
- tmp.replace( pos, 4, "<" );
- else if( tmp.find( "&gt;", pos ) == pos )
- tmp.replace( pos, 4, ">" );
- else if ( tmp.find( "&quot;", pos ) == pos )
- tmp.replace( pos, 6, "\"" );
- }
- return tmp;
-}
-
-} // 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 @@
-/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
-**
-** This file is part of Qtopia Environment.
-**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included
-** in the packaging of this file.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
-** THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
-** PARTICULAR PURPOSE.
-**
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-** Contact info@trolltech.com if any conditions of this licensing are
-** not clear to you.
-**
-**********************************************************************/
-
-
-#ifndef QTPALMTOP_stringutil_h__
-#define QTPALMTOP_stringutil_h__
-
-#include <qstring.h>
-#include "qpcglobal.h"
-
-namespace Qtopia
-{
-
-// Simplifies white space within each line but keeps the new line characters
-QString QPC_EXPORT simplifyMultiLineSpace( const QString &multiLine );
-
-// Creates a QString which doesn't contain any "dangerous"
-// characters (i.e. <, >, &, ")
-QString QPC_EXPORT escapeString( const QString& plain );
-
-// Takes a UTF-8!! string and removes all the XML thingies (entities?)
-// from the string and also calls fromUtf8() on it... so make sure
-// to pass a QCString/const char* with UTF-8 data only
-QString QPC_EXPORT plainString( const char* escaped, unsigned int length );
-QString QPC_EXPORT plainString( const QCString& string );
-
-QString QPC_EXPORT plainString( const QString& string );
-
-
-// collation functions
-int compare( const QString & s1, const QString & s2 );
-QString buildSortKey( const QString & s );
-QString buildSortKey( const QString & s1, const QString & s2 );
-QString buildSortKey( const QString & s1, const QString & s2,
- const QString & s3 );
-
-}
-
-#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,85 +1,200 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
-#include <qpe/task.h>
-#include <qregexp.h>
-#include <qstring.h>
-#include <qpe/recordfields.h>
+#include "task.h"
+#include "recordfields.h"
#include "vobject_p.h"
-#include "timeconversion.h"
#include "qfiledirect_p.h"
+#include <qtopia/timeconversion.h>
+
+#include <qregexp.h>
+#include <qstring.h>
+
#include <stdio.h>
using namespace Qtopia;
UidGen Task::sUidGen( UidGen::Qtopia );
+/*!
+ \class Task
+ \brief The Task class holds the data of a todo entry.
+
+ This data includes the priority of the task, a description, an optional due
+ date, and whether the task is completed or not.
+
+ \ingroup qtopiaemb
+ \ingroup qtopiadesktop
+*/
+
+/*!
+ Creates a new, empty task.
+*/
Task::Task() : Record(), mDue( FALSE ),
mDueDate( QDate::currentDate() ),
mCompleted( FALSE ), mPriority( 3 ), mDesc()
{
}
+/*!
+ \fn void Task::setPriority( int priority )
+
+ Sets the priority of the task to \a priority.
+*/
+
+/*!
+ \fn int Task::priority() const
+
+ Returns the priority of the task.
+*/
+
+/*!
+ \fn void Task::setDescription( const QString &description )
+
+ Sets the description of the task to \a description.
+ */
+
+/*!
+ \fn const QString &Task::description() const
+
+ Returns the description of the task.
+ */
+
+/*!
+ \fn void Task::setDueDate( const QDate &date, bool hasDue )
+
+ \internal
+ If \a hasDue is TRUE sets the due date of the task to \a date.
+ Otherwise clears the due date of the task.
+*/
+
+/*!
+ \fn void Task::setDueDate( const QDate &date )
+
+ Sets the due date of the task to \a date.
+*/
+
+/*!
+ \fn void Task::clearDueDate( )
+
+ Clears the due date of the task.
+*/
+
+/*!
+ \fn void Task::setCompleted( bool b )
+
+ If \a b is TRUE marks the task as completed. Otherwise marks the task as
+ uncompleted.
+*/
+
+/*!
+ \fn bool Task::isCompleted() const
+
+ Returns TRUE if the task is completed. Otherwise returns FALSE.
+*/
+
+/*!
+ \fn const QDate &Task::dueDate() const
+
+ Returns the due date of the task.
+ */
+
+/*!
+ \fn bool Task::hasDueDate() const
+
+ Returns TRUE if there is a due date set for the task. Otherwise returns
+ FALSE.
+*/
+
+/*!
+ \fn void Task::setHasDueDate( bool b )
+
+ \internal
+ Just don't ask. I really can't justify the function.
+*/
+
+
+/*!
+ \internal
+ Creates a new task. The properties of the task are set from \a m.
+*/
+
Task::Task( const QMap<int, QString> &m ) : Record(), mDue( FALSE ),
mDueDate( QDate::currentDate() ), mCompleted( FALSE ), mPriority( 3 ), mDesc()
{
//qDebug("Task::Task fromMap");
//dump( m );
for ( QMap<int,QString>::ConstIterator it = m.begin(); it != m.end();++it )
switch ( (TaskFields) it.key() ) {
case HasDate: if ( *it == "1" ) mDue = TRUE; break;
case Completed: setCompleted( *it == "1" ); break;
case TaskCategory: setCategories( idsFromString( *it ) ); break;
case TaskDescription: setDescription( *it ); break;
case Priority: setPriority( (*it).toInt() ); break;
case Date: mDueDate = TimeConversion::fromString( (*it) ); break;
case TaskUid: setUid( (*it).toInt() ); break;
- default: break;
+ case TaskRid:
+ case TaskRinfo:
+ break;
}
}
+/*!
+ Destroys a task.
+*/
Task::~Task()
{
}
+/*!
+ \internal
+ Returns the task as a map of field ids to property values.
+*/
QMap<int, QString> Task::toMap() const
{
QMap<int, QString> m;
m.insert( HasDate, hasDueDate() ? "1" : "0" );
m.insert( Completed, isCompleted() ? "1" : "0" );
- m.insert( TaskCategory, idsToString( categories() ) );
- m.insert( TaskDescription, description() );
+ if ( categories().count() )
+ m.insert( TaskCategory, idsToString( categories() ) );
+ if ( !description().isEmpty() )
+ m.insert( TaskDescription, description() );
m.insert( Priority, QString::number( priority() ) );
- m.insert( Date, TimeConversion::toString( dueDate() ) );
+ if ( hasDueDate() )
+ m.insert( Date, TimeConversion::toString( dueDate() ) );
m.insert( TaskUid, QString::number(uid()) );
//qDebug("Task::toMap");
//dump( m );
return m;
}
+/*!
+ \internal
+ Appends the task information to \a buf.
+*/
void Task::save( QString& buf ) const
{
buf += " Completed=\"";
// qDebug( "writing %d", complete );
buf += QString::number( (int)mCompleted );
buf += "\"";
buf += " HasDate=\"";
// qDebug( "writing %d", );
@@ -112,64 +227,79 @@ void Task::save( QString& buf ) const
buf += customToXml();
// qDebug ("writing uid %d", uid() );
buf += " Uid=\"";
buf += QString::number( uid() );
// terminate it in the application...
buf += "\"";
}
-bool Task::match ( const QRegExp &r ) const
+/*!
+ Returns TRUE if the task matches the regular expressions \a regexp.
+ Otherwise returns FALSE.
+*/
+bool Task::match ( const QRegExp &regexp ) const
{
// match on priority, description on due date...
bool match;
match = false;
- if ( QString::number( mPriority ).find( r ) > -1 )
+ if ( QString::number( mPriority ).find( regexp ) > -1 )
match = true;
- else if ( mDue && mDueDate.toString().find( r ) > -1 )
+ else if ( mDue && mDueDate.toString().find( regexp ) > -1 )
match = true;
- else if ( mDesc.find( r ) > -1 )
+ else if ( mDesc.find( regexp ) > -1 )
match = true;
return match;
}
+/*!
+ \internal
+*/
static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value )
{
VObject *ret = 0;
if ( o && !value.isEmpty() )
ret = addPropValue( o, prop, value.latin1() );
return ret;
}
+/*!
+ \internal
+*/
static inline VObject *safeAddProp( VObject *o, const char *prop)
{
VObject *ret = 0;
if ( o )
ret = addProp( o, prop );
return ret;
}
+/*!
+ \internal
+*/
static VObject *createVObject( const Task &t )
{
VObject *vcal = newVObject( VCCalProp );
safeAddPropValue( vcal, VCVersionProp, "1.0" );
VObject *task = safeAddProp( vcal, VCTodoProp );
if ( t.hasDueDate() )
safeAddPropValue( task, VCDueProp, TimeConversion::toISO8601( t.dueDate() ) );
safeAddPropValue( task, VCDescriptionProp, t.description() );
if ( t.isCompleted() )
safeAddPropValue( task, VCStatusProp, "COMPLETED" );
safeAddPropValue( task, VCPriorityProp, QString::number( t.priority() ) );
return vcal;
}
-
+/*!
+ \internal
+*/
static Task parseVObject( VObject *obj )
{
Task t;
VObjectIterator it;
initPropIterator( &it, obj );
while( moreIteration( &it ) ) {
VObject *o = nextVObject( &it );
@@ -202,17 +332,19 @@ static Task parseVObject( VObject *obj )
}
#endif
}
return t;
}
-
+/*!
+ Writes the list of \a tasks as a set of VCards to the file \a filename.
+*/
void Task::writeVCalendar( const QString &filename, const QValueList<Task> &tasks)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
@@ -221,32 +353,37 @@ void Task::writeVCalendar( const QString &filename, const QValueList<Task> &task
VObject *obj = createVObject( *it );
writeVObject(f.directHandle() , obj );
cleanVObject( obj );
}
cleanStrTbl();
}
+/*!
+ Writes \a task as a VCard to the file \a filename.
+*/
void Task::writeVCalendar( const QString &filename, const Task &task)
{
QFileDirect f( filename.utf8().data() );
if ( !f.open( IO_WriteOnly ) ) {
qWarning("Unable to open vcard write");
return;
}
VObject *obj = createVObject( task );
writeVObject(f.directHandle() , obj );
cleanVObject( obj );
cleanStrTbl();
}
-
+/*!
+ Returns the set of tasks read as VCards from the file \a filename.
+*/
QValueList<Task> Task::readVCalendar( const QString &filename )
{
VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() );
QValueList<Task> tasks;
while ( obj ) {
QCString name = vObjectName( obj );
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,12 +1,12 @@
/**********************************************************************
-** Copyright (C) 2001 Trolltech AS. All rights reserved.
+** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
-** This file is part of Qtopia Environment.
+** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
@@ -15,18 +15,18 @@
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef __TASK_H__
#define __TASK_H__
-#include <qpe/palmtoprecord.h>
-#include <qpe/stringutil.h>
+#include <qtopia/private/palmtoprecord.h>
+#include <qtopia/stringutil.h>
#include <qvaluelist.h>
#include <qdatetime.h>
class TaskPrivate;
class QPC_EXPORT Task : public Qtopia::Record
{
public:
@@ -35,31 +35,39 @@ public:
~Task();
QMap<int, QString> toMap() const;
static void writeVCalendar( const QString &filename, const QValueList<Task> &tasks);
static void writeVCalendar( const QString &filename, const Task &task);
static QValueList<Task> readVCalendar( const QString &filename );
+ enum PriorityValue { VeryHigh=1, High, Normal, Low, VeryLow };
+
void setPriority( int priority ) { mPriority = priority; }
int priority() const { return mPriority; }
// void setCategory( const QString& category )
// { mCategory = category.stripWhiteSpace(); }
// const QString &category() const { return mCategory; }
void setDescription( const QString& description )
{ mDesc = Qtopia::simplifyMultiLineSpace(description); }
const QString &description() const { return mDesc; }
+ // Use THESE functions
+ void setDueDate( const QDate &date);
+ void clearDueDate();
+
+ // Instead of these functions.
void setDueDate( const QDate& date, bool hasDue ) { mDueDate = date; mDue = hasDue; }
+ void setHasDueDate( bool b ) { mDue = b; }
+
const QDate &dueDate() const { return mDueDate; }
bool hasDueDate() const { return mDue; }
- void setHasDueDate( bool b ) { mDue = b; }
void setCompleted( bool b ) { mCompleted = b; }
bool isCompleted() const { return mCompleted; }
void save( QString& buf ) const;
bool match( const QRegExp &r ) const;
private:
@@ -73,9 +81,12 @@ private:
QString mDesc;
TaskPrivate *d;
// ADDITION
int recordId;
int recordInfo;
//
};
+// MUST be inline. (forwards compatability).
+inline void Task::setDueDate( const QDate &date) { setDueDate(date, date.isValid()); }
+inline void Task::clearDueDate() { setHasDueDate( FALSE ); }
#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 @@
-/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
-**
-** This file is part of Qtopia Environment.
-**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
-** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-**
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-** Contact info@trolltech.com if any conditions of this licensing are
-** not clear to you.
-**
-**********************************************************************/
-
-#include <qglobal.h>
-#include "timeconversion.h"
-#include <qregexp.h>
-#include <stdlib.h>
-
-QString TimeConversion::toString( const QDate &d )
-{
- QString r = QString::number( d.day() ) + "." +
- QString::number( d.month() ) + "." +
- QString::number( d.year() );
- //qDebug("TimeConversion::toString %s", r.latin1());
- return r;
-}
-
-QDate TimeConversion::fromString( const QString &datestr )
-{
- int monthPos = datestr.find('.');
- int yearPos = datestr.find('.', monthPos+1 );
- if ( monthPos == -1 || yearPos == -1 ) {
- qDebug("fromString didn't find . in str = %s; mpos = %d ypos = %d", datestr.latin1(), monthPos, yearPos );
- return QDate();
- }
- int d = datestr.left( monthPos ).toInt();
- int m = datestr.mid( monthPos+1, yearPos - monthPos - 1 ).toInt();
- int y = datestr.mid( yearPos+1 ).toInt();
- QDate date ( y,m,d );
- //qDebug("TimeConversion::fromString ymd = %s => %d %d %d; mpos = %d ypos = %d", datestr.latin1(), y, m, d, monthPos, yearPos);
- return date;
-}
-
-time_t TimeConversion::toUTC( const QDateTime& dt )
-{
- time_t tmp;
- struct tm *lt;
-
-#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
- _tzset();
-#else
- tzset();
-#endif
-
- // get a tm structure from the system to get the correct tz_name
- tmp = time( 0 );
- lt = localtime( &tmp );
-
- lt->tm_sec = dt.time().second();
- lt->tm_min = dt.time().minute();
- lt->tm_hour = dt.time().hour();
- lt->tm_mday = dt.date().day();
- lt->tm_mon = dt.date().month() - 1; // 0-11 instead of 1-12
- lt->tm_year = dt.date().year() - 1900; // year - 1900
- //lt->tm_wday = dt.date().dayOfWeek(); ignored anyway
- //lt->tm_yday = dt.date().dayOfYear(); ignored anyway
- lt->tm_wday = -1;
- lt->tm_yday = -1;
- // tm_isdst negative -> mktime will find out about DST
- lt->tm_isdst = -1;
- // keep tm_zone and tm_gmtoff
- tmp = mktime( lt );
- return tmp;
-}
-
-QDateTime TimeConversion::fromUTC( time_t time )
-{
- struct tm *lt;
-
-#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
- _tzset();
-#else
- tzset();
-#endif
- lt = localtime( &time );
- QDateTime dt;
- dt.setDate( QDate( lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday ) );
- dt.setTime( QTime( lt->tm_hour, lt->tm_min, lt->tm_sec ) );
- return dt;
-}
-
-
-int TimeConversion::secsTo( const QDateTime &from, const QDateTime &to )
-{
- return toUTC( to ) - toUTC( from );
-}
-
-QCString TimeConversion::toISO8601( const QDate &d )
-{
- time_t tmp = toUTC( d );
- struct tm *utc = gmtime( &tmp );
-
- QCString str;
- str.sprintf("%04d%02d%02d", (utc->tm_year + 1900), utc->tm_mon+1, utc->tm_mday );
- return str;
-}
-
-QCString TimeConversion::toISO8601( const QDateTime &dt )
-{
- time_t tmp = toUTC( dt );
- struct tm *utc = gmtime( &tmp );
-
- QCString str;
- str.sprintf("%04d%02d%02dT%02d%02d%02dZ",
- (utc->tm_year + 1900), utc->tm_mon+1, utc->tm_mday,
- utc->tm_hour, utc->tm_min, utc->tm_sec );
- return str;
-}
-
-QDateTime TimeConversion::fromISO8601( const QCString &s )
-{
-
-#if defined(_OS_WIN32) || defined (Q_OS_WIN32) || defined (Q_OS_WIN64)
- _tzset();
-#else
- tzset();
-#endif
-
- struct tm *thetime = new tm;
-
- QCString str = s.copy();
- str.replace(QRegExp("-"), "" );
- str.replace(QRegExp(":"), "" );
- str.stripWhiteSpace();
- str = str.lower();
-
- int i = str.find( "t" );
- QCString date;
- QCString timestr;
- if ( i != -1 ) {
- date = str.left( i );
- timestr = str.mid( i+1 );
- } else {
- date = str;
- }
-
-// qDebug("--- parsing ISO time---");
- thetime->tm_year = 100;
- thetime->tm_mon = 0;
- thetime->tm_mday = 0;
- thetime->tm_hour = 0;
- thetime->tm_min = 0;
- thetime->tm_sec = 0;
-
-// qDebug("date = %s", date.data() );
-
- switch( date.length() ) {
- case 8:
- thetime->tm_mday = date.right( 2 ).toInt();
- case 6:
- thetime->tm_mon = date.mid( 4, 2 ).toInt() - 1;
- case 4:
- thetime->tm_year = date.left( 4 ).toInt();
- thetime->tm_year -= 1900;
- break;
- default:
- break;
- }
-
- int tzoff = 0;
- bool inLocalTime = FALSE;
- if ( timestr.find( 'z' ) == (int)timestr.length() - 1 )
- // UTC
- timestr = timestr.left( timestr.length() -1 );
- else {
- int plus = timestr.find( "+" );
- int minus = timestr.find( "-" );
- if ( plus != -1 || minus != -1 ) {
- // have a timezone offset
- plus = (plus != -1) ? plus : minus;
- QCString off = timestr.mid( plus );
- timestr = timestr.left( plus );
-
- int tzoffhour = 0;
- int tzoffmin = 0;
- switch( off.length() ) {
- case 5:
- tzoffmin = off.mid(3).toInt();
- case 3:
- tzoffhour = off.left(3).toInt();
- default:
- break;
- }
- tzoff = 60*tzoffhour + tzoffmin;
- } else
- inLocalTime = TRUE;
- }
-
- // get the time:
- switch( timestr.length() ) {
- case 6:
- thetime->tm_sec = timestr.mid( 4 ).toInt();
- case 4:
- thetime->tm_min = timestr.mid( 2, 2 ).toInt();
- case 2:
- thetime->tm_hour = timestr.left( 2 ).toInt();
- default:
- break;
- }
-
- int tzloc = 0;
- time_t tmp = time( 0 );
- if ( !inLocalTime ) {
- // have to get the offset between gmt and local time
- struct tm *lt = localtime( &tmp );
- tzloc = mktime( lt );
- struct tm *ut = gmtime( &tmp );
- tzloc -= mktime( ut );
- }
-// qDebug("time: %d %d %d, tzloc=%d, tzoff=%d", thetime->tm_hour, thetime->tm_min, thetime->tm_sec,
-// tzloc, tzoff );
-
- tmp = mktime( thetime );
- tmp += 60*(-tzloc + tzoff);
-
- delete thetime;
-
- return fromUTC( tmp );
-}
-
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 @@
-/**********************************************************************
-** Copyright (C) 2000 Trolltech AS. All rights reserved.
-**
-** This file is part of Qtopia Environment.
-**
-** This file may be distributed and/or modified under the terms of the
-** GNU General Public License version 2 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file.
-**
-** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
-** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-**
-** See http://www.trolltech.com/gpl/ for GPL licensing information.
-**
-** Contact info@trolltech.com if any conditions of this licensing are
-** not clear to you.
-**
-**********************************************************************/
-
-#ifndef __timeconversion_h__
-#define __timeconversion_h__
-
-#include <time.h>
-#include <sys/types.h>
-#include <qdatetime.h>
-
-#include <qpe/qpcglobal.h>
-
-class QPC_EXPORT TimeConversion
-{
-public:
- static QString toString( const QDate &d );
- static QDate fromString( const QString &datestr );
-
- static time_t toUTC( const QDateTime& dt );
- static QDateTime fromUTC( time_t time );
- static int secsTo( const QDateTime &from, const QDateTime &to );
-
- static QCString toISO8601( const QDate & );
- static QCString toISO8601( const QDateTime & );
- static QDateTime fromISO8601( const QCString & );
-};
-
-#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 @@
-%{
-
-/***************************************************************************
-(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-
-For purposes of this license notice, the term Licensors shall mean,
-collectively, Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-The term Licensor shall mean any of the Licensors.
-
-Subject to acceptance of the following conditions, permission is hereby
-granted by Licensors without the need for written agreement and without
-license or royalty fees, to use, copy, modify and distribute this
-software for any purpose.
-
-The above copyright notice and the following four paragraphs must be
-reproduced in all copies of this software and any software including
-this software.
-
-THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
-ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
-MODIFICATIONS.
-
-IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
-INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
-OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.
-
-The software is provided with RESTRICTED RIGHTS. Use, duplication, or
-disclosure by the government are subject to restrictions set forth in
-DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
-
-***************************************************************************/
-
-/*
- * src: vcc.c
- * doc: Parser for vCard and vCalendar. Note that this code is
- * generated by a yacc parser generator. Generally it should not
- * be edited by hand. The real source is vcc.y. The #line directives
- * can be commented out here to make it easier to trace through
- * in a debugger. However, if a bug is found it should
- * be fixed in vcc.y and this file regenerated.
- */
-
-
-/* debugging utilities */
-#if __DEBUG
-#define DBG_(x) printf x
-#else
-#define DBG_(x)
-#endif
-
-/**** External Functions ****/
-
-/* assign local name to parser variables and functions so that
- we can use more than one yacc based parser.
-*/
-
-#if 0
-#define yyparse mime_parse
-#define yylex mime_lex
-#define yyerror mime_error
-#define yychar mime_char
-/* #define p_yyval p_mime_val */
-#undef yyval
-#define yyval mime_yyval
-/* #define p_yylval p_mime_lval */
-#undef yylval
-#define yylval mime_yylval
-#define yydebug mime_debug
-#define yynerrs mime_nerrs
-#define yyerrflag mime_errflag
-#define yyss mime_ss
-#define yyssp mime_ssp
-#define yyvs mime_vs
-#define yyvsp mime_vsp
-#define yylhs mime_lhs
-#define yylen mime_len
-#define yydefred mime_defred
-#define yydgoto mime_dgoto
-#define yysindex mime_sindex
-#define yyrindex mime_rindex
-#define yygindex mime_gindex
-#define yytable mime_table
-#define yycheck mime_check
-#define yyname mime_name
-#define yyrule mime_rule
-#ifdef YYPREFIX
-#undef YYPREFIX
-#endif
-#define YYPREFIX "mime_"
-#endif
-
-
-#ifndef _NO_LINE_FOLDING
-#define _SUPPORT_LINE_FOLDING 1
-#endif
-
-/* undef below if compile with MFC */
-/* #define INCLUDEMFC 1 */
-
-#if defined(WIN32) || defined(_WIN32)
-#ifdef INCLUDEMFC
-#include <afx.h>
-#endif
-#endif
-
-#include <string.h>
-#ifndef __MWERKS__
-#include <stdlib.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-//#ifdef PALMTOPCENTER
-//#include <qpe/vobject_p.h>
-//#else
-#include "vobject_p.h"
-//#endif
-
-/**** Types, Constants ****/
-
-#define YYDEBUG 0 /* 1 to compile in some debugging code */
-#define MAXTOKEN 256 /* maximum token (line) length */
-#define YYSTACKSIZE 100 // ~unref ?
-#define MAXLEVEL 10 /* max # of nested objects parseable */
- /* (includes outermost) */
-
-
-/**** Global Variables ****/
-int mime_lineNum, mime_numErrors; /* yyerror() can use these */
-static VObject* vObjList;
-static VObject *curProp;
-static VObject *curObj;
-static VObject* ObjStack[MAXLEVEL];
-static int ObjStackTop;
-
-
-/* A helpful utility for the rest of the app. */
-#if __CPLUSPLUS__
-extern "C" {
-#endif
-
- extern void yyerror(char *s);
-
-#if __CPLUSPLUS__
- };
-#endif
-
-int yyparse();
-
-enum LexMode {
- L_NORMAL,
- L_VCARD,
- L_VCAL,
- L_VEVENT,
- L_VTODO,
- L_VALUES,
- L_BASE64,
- L_QUOTED_PRINTABLE
- };
-
-/**** Private Forward Declarations ****/
-static int pushVObject(const char *prop);
-static VObject* popVObject();
-static void lexPopMode(int top);
-static int lexWithinMode(enum LexMode mode);
-static void lexPushMode(enum LexMode mode);
-static void enterProps(const char *s);
-static void enterAttr(const char *s1, const char *s2);
-static void enterValues(const char *value);
-#define mime_error yyerror
-void mime_error(char *s);
-void mime_error_(char *s);
-
-%}
-
-/***************************************************************************/
-/*** The grammar ****/
-/***************************************************************************/
-
-%union {
- char *str;
- VObject *vobj;
- }
-
-%token
- EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE
- BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL
- BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO
- ID
-
-/*
- * NEWLINE is the token that would occur outside a vCard,
- * while LINESEP is the token that would occur inside a vCard.
- */
-
-%token <str>
- STRING ID
-
-%type <str> name value
-
-%type <vobj> vcard vcal vobject
-
-%start mime
-
-%%
-
-
-mime: vobjects
- ;
-
-vobjects: vobjects vobject
- { addList(&vObjList, $2); curObj = 0; }
- | vobject
- { addList(&vObjList, $1); curObj = 0; }
- ;
-
-vobject: vcard
- | vcal
- ;
-
-vcard:
- BEGIN_VCARD
- {
- lexPushMode(L_VCARD);
- if (!pushVObject(VCCardProp)) YYERROR;
- }
- items END_VCARD
- {
- lexPopMode(0);
- $$ = popVObject();
- }
- | BEGIN_VCARD
- {
- lexPushMode(L_VCARD);
- if (!pushVObject(VCCardProp)) YYERROR;
- }
- END_VCARD
- {
- lexPopMode(0);
- $$ = popVObject();
- }
- ;
-
-items: items item
- | item
- ;
-
-item: prop COLON
- {
- lexPushMode(L_VALUES);
- }
- values LINESEP
- {
- if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
- lexPopMode(0);
- lexPopMode(0);
- }
- | error
- ;
-
-prop: name
- {
- enterProps($1);
- }
- attr_params
- | name
- {
- enterProps($1);
- }
- ;
-
-attr_params: attr_params attr_param
- | attr_param
- ;
-
-attr_param: SEMICOLON attr
- ;
-
-attr: name
- {
- enterAttr($1,0);
- }
- | name EQ name
- {
- enterAttr($1,$3);
-
- }
- ;
-
-name: ID
- ;
-
-values: value SEMICOLON { enterValues($1); } values
- | value
- { enterValues($1); }
- ;
-
-value: STRING
- |
- { $$ = 0; }
- ;
-
-vcal:
- BEGIN_VCAL
- { if (!pushVObject(VCCalProp)) YYERROR; }
- calitems
- END_VCAL
- { $$ = popVObject(); }
- | BEGIN_VCAL
- { if (!pushVObject(VCCalProp)) YYERROR; }
- END_VCAL
- { $$ = popVObject(); }
- ;
-
-calitems: calitems calitem
- | calitem
- ;
-
-calitem:
- eventitem
- | todoitem
- | items
- ;
-
-eventitem:
- BEGIN_VEVENT
- {
- lexPushMode(L_VEVENT);
- if (!pushVObject(VCEventProp)) YYERROR;
- }
- items
- END_VEVENT
- {
- lexPopMode(0);
- popVObject();
- }
- | BEGIN_VEVENT
- {
- lexPushMode(L_VEVENT);
- if (!pushVObject(VCEventProp)) YYERROR;
- }
- END_VEVENT
- {
- lexPopMode(0);
- popVObject();
- }
- ;
-
-todoitem:
- BEGIN_VTODO
- {
- lexPushMode(L_VTODO);
- if (!pushVObject(VCTodoProp)) YYERROR;
- }
- items
- END_VTODO
- {
- lexPopMode(0);
- popVObject();
- }
- | BEGIN_VTODO
- {
- lexPushMode(L_VTODO);
- if (!pushVObject(VCTodoProp)) YYERROR;
- }
- END_VTODO
- {
- lexPopMode(0);
- popVObject();
- }
- ;
-
-%%
-/*------------------------------------*/
-static int pushVObject(const char *prop)
- {
- VObject *newObj;
- if (ObjStackTop == MAXLEVEL)
- return FALSE;
-
- ObjStack[++ObjStackTop] = curObj;
-
- if (curObj) {
- newObj = addProp(curObj,prop);
- curObj = newObj;
- }
- else
- curObj = newVObject(prop);
-
- return TRUE;
- }
-
-
-/*---------------------------------------*/
-/* This pops the recently built vCard off the stack and returns it. */
-static VObject* popVObject()
- {
- VObject *oldObj;
- if (ObjStackTop < 0) {
- yyerror("pop on empty Object Stack\n");
- return 0;
- }
- oldObj = curObj;
- curObj = ObjStack[ObjStackTop--];
-
- return oldObj;
- }
-
-
-static void enterValues(const char *value)
- {
- if (fieldedProp && *fieldedProp) {
- if (value) {
- addPropValue(curProp,*fieldedProp,value);
- }
- /* else this field is empty, advance to next field */
- fieldedProp++;
- }
- else {
- if (value) {
- setVObjectStringZValue_(curProp,strdup( value ));
- }
- }
- deleteStr(value);
- }
-
-static void enterProps(const char *s)
- {
- curProp = addGroup(curObj,s);
- deleteStr(s);
- }
-
-static void enterAttr(const char *s1, const char *s2)
- {
- const char *p1, *p2;
- p1 = lookupProp_(s1);
- if (s2) {
- VObject *a;
- p2 = lookupProp_(s2);
- a = addProp(curProp,p1);
- setVObjectStringZValue(a,p2);
- }
- else
- addProp(curProp,p1);
- if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
- lexPushMode(L_BASE64);
- else if (qstricmp(p1,VCQuotedPrintableProp) == 0
- || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
- lexPushMode(L_QUOTED_PRINTABLE);
- deleteStr(s1); deleteStr(s2);
- }
-
-
-#define MAX_LEX_LOOKAHEAD_0 32
-#define MAX_LEX_LOOKAHEAD 64
-#define MAX_LEX_MODE_STACK_SIZE 10
-#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
-
-struct LexBuf {
- /* input */
-#ifdef INCLUDEMFC
- CFile *inputFile;
-#else
- FILE *inputFile;
-#endif
- char *inputString;
- unsigned long curPos;
- unsigned long inputLen;
- /* lookahead buffer */
- /* -- lookahead buffer is short instead of char so that EOF
- / can be represented correctly.
- */
- unsigned long len;
- short buf[MAX_LEX_LOOKAHEAD];
- unsigned long getPtr;
- /* context stack */
- unsigned long lexModeStackTop;
- enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
- /* token buffer */
- unsigned long maxToken;
- char *strs;
- unsigned long strsLen;
- } lexBuf;
-
-static void lexPushMode(enum LexMode mode)
- {
- if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
- yyerror("lexical context stack overflow");
- else {
- lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
- }
- }
-
-static void lexPopMode(int top)
- {
- /* special case of pop for ease of error recovery -- this
- version will never underflow */
- if (top)
- lexBuf.lexModeStackTop = 0;
- else
- if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
- }
-
-static int lexWithinMode(enum LexMode mode) {
- unsigned long i;
- for (i=0;i<lexBuf.lexModeStackTop;i++)
- if (mode == lexBuf.lexModeStack[i]) return 1;
- return 0;
- }
-
-static char lexGetc_()
- {
- /* get next char from input, no buffering. */
- if (lexBuf.curPos == lexBuf.inputLen)
- return EOF;
- else if (lexBuf.inputString)
- return *(lexBuf.inputString + lexBuf.curPos++);
- else {
-#ifdef INCLUDEMFC
- char result;
- return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
-#else
- return fgetc(lexBuf.inputFile);
-#endif
- }
- }
-
-static int lexGeta()
- {
- ++lexBuf.len;
- return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
- }
-
-static int lexGeta_(int i)
- {
- ++lexBuf.len;
- return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
- }
-
-static void lexSkipLookahead() {
- if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
- /* don't skip EOF. */
- lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
- lexBuf.len--;
- }
- }
-
-static int lexLookahead() {
- int c = (lexBuf.len)?
- lexBuf.buf[lexBuf.getPtr]:
- lexGeta();
- /* do the \r\n -> \n or \r -> \n translation here */
- if (c == '\r') {
- int a = (lexBuf.len>1)?
- lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
- lexGeta_(1);
- if (a == '\n') {
- lexSkipLookahead();
- }
- lexBuf.buf[lexBuf.getPtr] = c = '\n';
- }
- else if (c == '\n') {
- int a = (lexBuf.len>1)?
- lexBuf.buf[lexBuf.getPtr+1]:
- lexGeta_(1);
- if (a == '\r') {
- lexSkipLookahead();
- }
- lexBuf.buf[lexBuf.getPtr] = '\n';
- }
- return c;
- }
-
-static int lexGetc() {
- int c = lexLookahead();
- if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
- /* EOF will remain in lookahead buffer */
- lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
- lexBuf.len--;
- }
- return c;
- }
-
-static void lexSkipLookaheadWord() {
- if (lexBuf.strsLen <= lexBuf.len) {
- lexBuf.len -= lexBuf.strsLen;
- lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
- }
- }
-
-static void lexClearToken()
- {
- lexBuf.strsLen = 0;
- }
-
-static void lexAppendc(int c)
- {
- lexBuf.strs[lexBuf.strsLen] = c;
- /* append up to zero termination */
- if (c == 0) return;
- lexBuf.strsLen++;
- if (lexBuf.strsLen > lexBuf.maxToken) {
- /* double the token string size */
- lexBuf.maxToken <<= 1;
- lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
- }
- }
-
-static char* lexStr() {
- return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
- }
-
-static void lexSkipWhite() {
- int c = lexLookahead();
- while (c == ' ' || c == '\t') {
- lexSkipLookahead();
- c = lexLookahead();
- }
- }
-
-static char* lexGetWord() {
- int c;
- lexSkipWhite();
- lexClearToken();
- c = lexLookahead();
- while (c != EOF && !strchr("\t\n ;:=",c)) {
- lexAppendc(c);
- lexSkipLookahead();
- c = lexLookahead();
- }
- lexAppendc(0);
- return lexStr();
- }
-
-static void lexPushLookaheadc(int c) {
- int putptr;
- /* can't putback EOF, because it never leaves lookahead buffer */
- if (c == EOF) return;
- putptr = (int)lexBuf.getPtr - 1;
- if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
- lexBuf.getPtr = putptr;
- lexBuf.buf[putptr] = c;
- lexBuf.len += 1;
- }
-
-static char* lexLookaheadWord() {
- /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
- / and thing bigger than that will stop the lookahead and return 0;
- / leading white spaces are not recoverable.
- */
- int c;
- int len = 0;
- int curgetptr = 0;
- lexSkipWhite();
- lexClearToken();
- curgetptr = (int)lexBuf.getPtr; // remember!
- while (len < (MAX_LEX_LOOKAHEAD_0)) {
- c = lexGetc();
- len++;
- if (c == EOF || strchr("\t\n ;:=", c)) {
- lexAppendc(0);
- /* restore lookahead buf. */
- lexBuf.len += len;
- lexBuf.getPtr = curgetptr;
- return lexStr();
- }
- else
- lexAppendc(c);
- }
- lexBuf.len += len; /* char that has been moved to lookahead buffer */
- lexBuf.getPtr = curgetptr;
- return 0;
- }
-
-#ifdef _SUPPORT_LINE_FOLDING
-static void handleMoreRFC822LineBreak(int c) {
- /* suport RFC 822 line break in cases like
- * ADR: foo;
- * morefoo;
- * more foo;
- */
- if (c == ';') {
- int a;
- lexSkipLookahead();
- /* skip white spaces */
- a = lexLookahead();
- while (a == ' ' || a == '\t') {
- lexSkipLookahead();
- a = lexLookahead();
- }
- if (a == '\n') {
- lexSkipLookahead();
- a = lexLookahead();
- if (a == ' ' || a == '\t') {
- /* continuation, throw away all the \n and spaces read so
- * far
- */
- lexSkipWhite();
- lexPushLookaheadc(';');
- }
- else {
- lexPushLookaheadc('\n');
- lexPushLookaheadc(';');
- }
- }
- else {
- lexPushLookaheadc(';');
- }
- }
- }
-
-static char* lexGet1Value() {
- int c;
- lexSkipWhite();
- c = lexLookahead();
- lexClearToken();
- while (c != EOF && c != ';') {
- if (c == '\\' ) {
- int a;
- lexSkipLookahead();
- a = lexLookahead();
- if ( a != ';' ) {
- lexAppendc('\\');
- } else {
- lexAppendc( ';' );
- lexSkipLookahead();
- }
- } else if (c == '\n') {
- int a;
- lexSkipLookahead();
- a = lexLookahead();
- if (a == ' ' || a == '\t') {
- lexAppendc(' ');
- lexSkipLookahead();
- }
- else {
- lexPushLookaheadc('\n');
- break;
- }
- }
- else {
- lexAppendc(c);
- lexSkipLookahead();
- }
- c = lexLookahead();
- }
- lexAppendc(0);
- handleMoreRFC822LineBreak(c);
- return c==EOF?0:lexStr();
- }
-#endif
-
-static int match_begin_name(int end) {
- char *n = lexLookaheadWord();
- int token = ID;
- if (n) {
- if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
- else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
- else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
- else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
- deleteStr(n);
- return token;
- }
- return 0;
- }
-
-
-#ifdef INCLUDEMFC
-void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
-#else
-void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
-#endif
- {
- // initialize lex mode stack
- lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
-
- // iniatialize lex buffer.
- lexBuf.inputString = (char*) inputstring;
- lexBuf.inputLen = inputlen;
- lexBuf.curPos = 0;
- lexBuf.inputFile = inputfile;
-
- lexBuf.len = 0;
- lexBuf.getPtr = 0;
-
- lexBuf.maxToken = MAXTOKEN;
- lexBuf.strs = (char*)malloc(MAXTOKEN);
- lexBuf.strsLen = 0;
-
- }
-
-static void finiLex() {
- free(lexBuf.strs);
- }
-
-
-/*-----------------------------------*/
-/* This parses and converts the base64 format for binary encoding into
- * a decoded buffer (allocated with new). See RFC 1521.
- */
-static char * lexGetDataFromBase64()
- {
- unsigned long bytesLen = 0, bytesMax = 0;
- int quadIx = 0, pad = 0;
- unsigned long trip = 0;
- unsigned char b;
- int c;
- unsigned char *bytes = NULL;
- unsigned char *oldBytes = NULL;
-
- DBG_(("db: lexGetDataFromBase64\n"));
- while (1) {
- c = lexGetc();
- if (c == '\n') {
- ++mime_lineNum;
- if (lexLookahead() == '\n') {
- /* a '\n' character by itself means end of data */
- break;
- }
- else continue; /* ignore '\n' */
- }
- else {
- if ((c >= 'A') && (c <= 'Z'))
- b = (unsigned char)(c - 'A');
- else if ((c >= 'a') && (c <= 'z'))
- b = (unsigned char)(c - 'a') + 26;
- else if ((c >= '0') && (c <= '9'))
- b = (unsigned char)(c - '0') + 52;
- else if (c == '+')
- b = 62;
- else if (c == '/')
- b = 63;
- else if (c == '=') {
- b = 0;
- pad++;
- } else if ((c == ' ') || (c == '\t')) {
- continue;
- } else { /* error condition */
- if (bytes) free(bytes);
- else if (oldBytes) free(oldBytes);
- // error recovery: skip until 2 adjacent newlines.
- DBG_(("db: invalid character 0x%x '%c'\n", c,c));
- if (c != EOF) {
- c = lexGetc();
- while (c != EOF) {
- if (c == '\n' && lexLookahead() == '\n') {
- ++mime_lineNum;
- break;
- }
- c = lexGetc();
- }
- }
- return NULL;
- }
- trip = (trip << 6) | b;
- if (++quadIx == 4) {
- unsigned char outBytes[3];
- int numOut;
- int i;
- for (i = 0; i < 3; i++) {
- outBytes[2-i] = (unsigned char)(trip & 0xFF);
- trip >>= 8;
- }
- numOut = 3 - pad;
- if (bytesLen + numOut > bytesMax) {
- if (!bytes) {
- bytesMax = 1024;
- bytes = (unsigned char*)malloc((size_t)bytesMax);
- }
- else {
- bytesMax <<= 2;
- oldBytes = bytes;
- bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
- }
- if (bytes == 0) {
- mime_error("out of memory while processing BASE64 data\n");
- }
- }
- if (bytes) {
- memcpy(bytes + bytesLen, outBytes, numOut);
- bytesLen += numOut;
- }
- trip = 0;
- quadIx = 0;
- }
- }
- } /* while */
- DBG_(("db: bytesLen = %d\n", bytesLen));
- /* kludge: all this won't be necessary if we have tree form
- representation */
- if (bytes) {
- setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
- free(bytes);
- }
- else if (oldBytes) {
- setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
- free(oldBytes);
- }
- return 0;
- }
-
-static int match_begin_end_name(int end) {
- int token;
- lexSkipWhite();
- if (lexLookahead() != ':') return ID;
- lexSkipLookahead();
- lexSkipWhite();
- token = match_begin_name(end);
- if (token == ID) {
- lexPushLookaheadc(':');
- DBG_(("db: ID '%s'\n", yylval.str));
- return ID;
- }
- else if (token != 0) {
- lexSkipLookaheadWord();
- deleteStr(yylval.str);
- DBG_(("db: begin/end %d\n", token));
- return token;
- }
- return 0;
- }
-
-static char* lexGetQuotedPrintable()
- {
- char cur;
-
- lexClearToken();
- do {
- cur = lexGetc();
- switch (cur) {
- case '=': {
- int c = 0;
- int next[2];
- int i;
- for (i = 0; i < 2; i++) {
- next[i] = lexGetc();
- if (next[i] >= '0' && next[i] <= '9')
- c = c * 16 + next[i] - '0';
- else if (next[i] >= 'A' && next[i] <= 'F')
- c = c * 16 + next[i] - 'A' + 10;
- else
- break;
- }
- if (i == 0) {
- /* single '=' follow by LINESEP is continuation sign? */
- if (next[0] == '\n') {
- ++mime_lineNum;
- }
- else {
- lexPushLookaheadc('=');
- goto EndString;
- }
- }
- else if (i == 1) {
- lexPushLookaheadc(next[1]);
- lexPushLookaheadc(next[0]);
- lexAppendc('=');
- } else {
- lexAppendc(c);
- }
- break;
- } /* '=' */
- case '\n': {
- lexPushLookaheadc('\n');
- goto EndString;
- }
- case (char)EOF:
- break;
- default:
- lexAppendc(cur);
- break;
- } /* switch */
- } while (cur != (char)EOF);
-
-EndString:
- lexAppendc(0);
- return lexStr();
- } /* LexQuotedPrintable */
-
-static int yylex() {
-
- int lexmode = LEXMODE();
- if (lexmode == L_VALUES) {
- int c = lexGetc();
- if (c == ';') {
- DBG_(("db: SEMICOLON\n"));
- lexPushLookaheadc(c);
- handleMoreRFC822LineBreak(c);
- lexSkipLookahead();
- return SEMICOLON;
- }
- else if (strchr("\n",c)) {
- ++mime_lineNum;
- /* consume all line separator(s) adjacent to each other */
- c = lexLookahead();
- while (strchr("\n",c)) {
- lexSkipLookahead();
- c = lexLookahead();
- ++mime_lineNum;
- }
- DBG_(("db: LINESEP\n"));
- return LINESEP;
- }
- else {
- char *p = 0;
- lexPushLookaheadc(c);
- if (lexWithinMode(L_BASE64)) {
- /* get each char and convert to bin on the fly... */
- p = lexGetDataFromBase64();
- yylval.str = p;
- return STRING;
- }
- else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
- p = lexGetQuotedPrintable();
- }
- else {
-#ifdef _SUPPORT_LINE_FOLDING
- p = lexGet1Value();
-#else
- p = lexGetStrUntil(";\n");
-#endif
- }
- if (p) {
- DBG_(("db: STRING: '%s'\n", p));
- yylval.str = p;
- return STRING;
- }
- else return 0;
- }
- }
- else {
- /* normal mode */
- while (1) {
- int c = lexGetc();
- switch(c) {
- case ':': {
- /* consume all line separator(s) adjacent to each other */
- /* ignoring linesep immediately after colon. */
- c = lexLookahead();
- while (strchr("\n",c)) {
- lexSkipLookahead();
- c = lexLookahead();
- ++mime_lineNum;
- }
- DBG_(("db: COLON\n"));
- return COLON;
- }
- case ';':
- DBG_(("db: SEMICOLON\n"));
- return SEMICOLON;
- case '=':
- DBG_(("db: EQ\n"));
- return EQ;
- /* ignore whitespace in this mode */
- case '\t':
- case ' ': continue;
- case '\n': {
- ++mime_lineNum;
- continue;
- }
- case EOF: return 0;
- break;
- default: {
- lexPushLookaheadc(c);
- if (isalnum(c)) {
- char *t = lexGetWord();
- yylval.str = t;
- if (!qstricmp(t, "begin")) {
- return match_begin_end_name(0);
- }
- else if (!qstricmp(t,"end")) {
- return match_begin_end_name(1);
- }
- else {
- DBG_(("db: ID '%s'\n", t));
- return ID;
- }
- }
- else {
- /* unknow token */
- return 0;
- }
- break;
- }
- }
- }
- }
- return 0;
- }
-
-
-/***************************************************************************/
-/*** Public Functions ****/
-/***************************************************************************/
-
-static VObject* Parse_MIMEHelper()
- {
- ObjStackTop = -1;
- mime_numErrors = 0;
- mime_lineNum = 1;
- vObjList = 0;
- curObj = 0;
-
- if (yyparse() != 0)
- return 0;
-
- finiLex();
- return vObjList;
- }
-
-/*--------------------------------------------*/
-DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
- {
- initLex(input, len, 0);
- return Parse_MIMEHelper();
- }
-
-
-#if INCLUDEMFC
-
-DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
- {
- unsigned long startPos;
- VObject *result;
-
- initLex(0,-1,file);
- startPos = file->GetPosition();
- if (!(result = Parse_MIMEHelper()))
- file->Seek(startPos, CFile::begin);
- return result;
- }
-
-#else
-
-VObject* Parse_MIME_FromFile(FILE *file)
- {
- VObject *result;
- long startPos;
-
- initLex(0,(unsigned long)-1,file);
- startPos = ftell(file);
- if (!(result = Parse_MIMEHelper())) {
- fseek(file,startPos,SEEK_SET);
- }
- return result;
- }
-
-DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
- {
- FILE *fp = fopen(fname,"r");
- if (fp) {
- VObject* o = Parse_MIME_FromFile(fp);
- fclose(fp);
- return o;
- }
- else {
- char msg[80];
- sprintf(msg, "can't open file '%s' for reading\n", fname);
- mime_error_(msg);
- return 0;
- }
- }
-
-#endif
-
-/*-------------------------------------*/
-
-static MimeErrorHandler mimeErrorHandler;
-
-DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
- {
- mimeErrorHandler = me;
- }
-
-void mime_error(char *s)
- {
- char msg[256];
- if (mimeErrorHandler) {
- sprintf(msg,"%s at line %d", s, mime_lineNum);
- mimeErrorHandler(msg);
- }
- }
-
-void mime_error_(char *s)
- {
- if (mimeErrorHandler) {
- mimeErrorHandler(s);
- }
- }
-
+%{
+
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+ * src: vcc.c
+ * doc: Parser for vCard and vCalendar. Note that this code is
+ * generated by a yacc parser generator. Generally it should not
+ * be edited by hand. The real source is vcc.y. The #line directives
+ * can be commented out here to make it easier to trace through
+ * in a debugger. However, if a bug is found it should
+ * be fixed in vcc.y and this file regenerated.
+ */
+
+
+/* debugging utilities */
+#if __DEBUG
+#define DBG_(x) printf x
+#else
+#define DBG_(x)
+#endif
+
+/**** External Functions ****/
+
+/* assign local name to parser variables and functions so that
+ we can use more than one yacc based parser.
+*/
+
+#if 0
+#define yyparse mime_parse
+#define yylex mime_lex
+#define yyerror mime_error
+#define yychar mime_char
+/* #define p_yyval p_mime_val */
+#undef yyval
+#define yyval mime_yyval
+/* #define p_yylval p_mime_lval */
+#undef yylval
+#define yylval mime_yylval
+#define yydebug mime_debug
+#define yynerrs mime_nerrs
+#define yyerrflag mime_errflag
+#define yyss mime_ss
+#define yyssp mime_ssp
+#define yyvs mime_vs
+#define yyvsp mime_vsp
+#define yylhs mime_lhs
+#define yylen mime_len
+#define yydefred mime_defred
+#define yydgoto mime_dgoto
+#define yysindex mime_sindex
+#define yyrindex mime_rindex
+#define yygindex mime_gindex
+#define yytable mime_table
+#define yycheck mime_check
+#define yyname mime_name
+#define yyrule mime_rule
+#ifdef YYPREFIX
+#undef YYPREFIX
+#endif
+#define YYPREFIX "mime_"
+#endif
+
+
+#ifndef _NO_LINE_FOLDING
+#define _SUPPORT_LINE_FOLDING 1
+#endif
+
+/* undef below if compile with MFC */
+/* #define INCLUDEMFC 1 */
+
+#if defined(WIN32) || defined(_WIN32)
+#ifdef INCLUDEMFC
+#include <afx.h>
+#endif
+#endif
+
+#include <string.h>
+#ifndef __MWERKS__
+#include <stdlib.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+//#ifdef PALMTOPCENTER
+//#include <qpe/vobject_p.h>
+//#else
+#include "vobject_p.h"
+//#endif
+
+/**** Types, Constants ****/
+
+#define YYDEBUG 0 /* 1 to compile in some debugging code */
+#define MAXTOKEN 256 /* maximum token (line) length */
+#define YYSTACKSIZE 100 // ~unref ?
+#define MAXLEVEL 10 /* max # of nested objects parseable */
+ /* (includes outermost) */
+
+
+/**** Global Variables ****/
+int mime_lineNum, mime_numErrors; /* yyerror() can use these */
+static VObject* vObjList;
+static VObject *curProp;
+static VObject *curObj;
+static VObject* ObjStack[MAXLEVEL];
+static int ObjStackTop;
+
+
+/* A helpful utility for the rest of the app. */
+#if __CPLUSPLUS__
+extern "C" {
+#endif
+
+ extern void yyerror(char *s);
+
+#if __CPLUSPLUS__
+ };
+#endif
+
+int yyparse();
+
+enum LexMode {
+ L_NORMAL,
+ L_VCARD,
+ L_VCAL,
+ L_VEVENT,
+ L_VTODO,
+ L_VALUES,
+ L_BASE64,
+ L_QUOTED_PRINTABLE
+ };
+
+/**** Private Forward Declarations ****/
+static int pushVObject(const char *prop);
+static VObject* popVObject();
+static void lexPopMode(int top);
+static int lexWithinMode(enum LexMode mode);
+static void lexPushMode(enum LexMode mode);
+static void enterProps(const char *s);
+static void enterAttr(const char *s1, const char *s2);
+static void enterValues(const char *value);
+#define mime_error yyerror
+void mime_error(char *s);
+void mime_error_(char *s);
+
+%}
+
+/***************************************************************************/
+/*** The grammar ****/
+/***************************************************************************/
+
+%union {
+ char *str;
+ VObject *vobj;
+ }
+
+%token
+ EQ COLON DOT SEMICOLON SPACE HTAB LINESEP NEWLINE
+ BEGIN_VCARD END_VCARD BEGIN_VCAL END_VCAL
+ BEGIN_VEVENT END_VEVENT BEGIN_VTODO END_VTODO
+ ID
+
+/*
+ * NEWLINE is the token that would occur outside a vCard,
+ * while LINESEP is the token that would occur inside a vCard.
+ */
+
+%token <str>
+ STRING ID
+
+%type <str> name value
+
+%type <vobj> vcard vcal vobject
+
+%start mime
+
+%%
+
+
+mime: vobjects
+ ;
+
+vobjects: vobjects vobject
+ { addList(&vObjList, $2); curObj = 0; }
+ | vobject
+ { addList(&vObjList, $1); curObj = 0; }
+ ;
+
+vobject: vcard
+ | vcal
+ ;
+
+vcard:
+ BEGIN_VCARD
+ {
+ lexPushMode(L_VCARD);
+ if (!pushVObject(VCCardProp)) YYERROR;
+ }
+ items END_VCARD
+ {
+ lexPopMode(0);
+ $$ = popVObject();
+ }
+ | BEGIN_VCARD
+ {
+ lexPushMode(L_VCARD);
+ if (!pushVObject(VCCardProp)) YYERROR;
+ }
+ END_VCARD
+ {
+ lexPopMode(0);
+ $$ = popVObject();
+ }
+ ;
+
+items: items item
+ | item
+ ;
+
+item: prop COLON
+ {
+ lexPushMode(L_VALUES);
+ }
+ values LINESEP
+ {
+ if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
+ lexPopMode(0);
+ lexPopMode(0);
+ }
+ | error
+ ;
+
+prop: name
+ {
+ enterProps($1);
+ }
+ attr_params
+ | name
+ {
+ enterProps($1);
+ }
+ ;
+
+attr_params: attr_params attr_param
+ | attr_param
+ ;
+
+attr_param: SEMICOLON attr
+ ;
+
+attr: name
+ {
+ enterAttr($1,0);
+ }
+ | name EQ name
+ {
+ enterAttr($1,$3);
+
+ }
+ ;
+
+name: ID
+ ;
+
+values: value SEMICOLON { enterValues($1); } values
+ | value
+ { enterValues($1); }
+ ;
+
+value: STRING
+ |
+ { $$ = 0; }
+ ;
+
+vcal:
+ BEGIN_VCAL
+ { if (!pushVObject(VCCalProp)) YYERROR; }
+ calitems
+ END_VCAL
+ { $$ = popVObject(); }
+ | BEGIN_VCAL
+ { if (!pushVObject(VCCalProp)) YYERROR; }
+ END_VCAL
+ { $$ = popVObject(); }
+ ;
+
+calitems: calitems calitem
+ | calitem
+ ;
+
+calitem:
+ eventitem
+ | todoitem
+ | items
+ ;
+
+eventitem:
+ BEGIN_VEVENT
+ {
+ lexPushMode(L_VEVENT);
+ if (!pushVObject(VCEventProp)) YYERROR;
+ }
+ items
+ END_VEVENT
+ {
+ lexPopMode(0);
+ popVObject();
+ }
+ | BEGIN_VEVENT
+ {
+ lexPushMode(L_VEVENT);
+ if (!pushVObject(VCEventProp)) YYERROR;
+ }
+ END_VEVENT
+ {
+ lexPopMode(0);
+ popVObject();
+ }
+ ;
+
+todoitem:
+ BEGIN_VTODO
+ {
+ lexPushMode(L_VTODO);
+ if (!pushVObject(VCTodoProp)) YYERROR;
+ }
+ items
+ END_VTODO
+ {
+ lexPopMode(0);
+ popVObject();
+ }
+ | BEGIN_VTODO
+ {
+ lexPushMode(L_VTODO);
+ if (!pushVObject(VCTodoProp)) YYERROR;
+ }
+ END_VTODO
+ {
+ lexPopMode(0);
+ popVObject();
+ }
+ ;
+
+%%
+/*------------------------------------*/
+static int pushVObject(const char *prop)
+ {
+ VObject *newObj;
+ if (ObjStackTop == MAXLEVEL)
+ return FALSE;
+
+ ObjStack[++ObjStackTop] = curObj;
+
+ if (curObj) {
+ newObj = addProp(curObj,prop);
+ curObj = newObj;
+ }
+ else
+ curObj = newVObject(prop);
+
+ return TRUE;
+ }
+
+
+/*---------------------------------------*/
+/* This pops the recently built vCard off the stack and returns it. */
+static VObject* popVObject()
+ {
+ VObject *oldObj;
+ if (ObjStackTop < 0) {
+ yyerror("pop on empty Object Stack\n");
+ return 0;
+ }
+ oldObj = curObj;
+ curObj = ObjStack[ObjStackTop--];
+
+ return oldObj;
+ }
+
+
+static void enterValues(const char *value)
+ {
+ if (fieldedProp && *fieldedProp) {
+ if (value) {
+ addPropValue(curProp,*fieldedProp,value);
+ }
+ /* else this field is empty, advance to next field */
+ fieldedProp++;
+ }
+ else {
+ if (value) {
+ setVObjectStringZValue_(curProp,strdup( value ));
+ }
+ }
+ deleteStr(value);
+ }
+
+static void enterProps(const char *s)
+ {
+ curProp = addGroup(curObj,s);
+ deleteStr(s);
+ }
+
+static void enterAttr(const char *s1, const char *s2)
+ {
+ const char *p1, *p2;
+ p1 = lookupProp_(s1);
+ if (s2) {
+ VObject *a;
+ p2 = lookupProp_(s2);
+ a = addProp(curProp,p1);
+ setVObjectStringZValue(a,p2);
+ }
+ else
+ addProp(curProp,p1);
+ if (qstricmp(p1,VCBase64Prop) == 0 || (s2 && qstricmp(p2,VCBase64Prop)==0))
+ lexPushMode(L_BASE64);
+ else if (qstricmp(p1,VCQuotedPrintableProp) == 0
+ || (s2 && qstricmp(p2,VCQuotedPrintableProp)==0))
+ lexPushMode(L_QUOTED_PRINTABLE);
+ deleteStr(s1); deleteStr(s2);
+ }
+
+
+#define MAX_LEX_LOOKAHEAD_0 32
+#define MAX_LEX_LOOKAHEAD 64
+#define MAX_LEX_MODE_STACK_SIZE 10
+#define LEXMODE() (lexBuf.lexModeStack[lexBuf.lexModeStackTop])
+
+struct LexBuf {
+ /* input */
+#ifdef INCLUDEMFC
+ CFile *inputFile;
+#else
+ FILE *inputFile;
+#endif
+ char *inputString;
+ unsigned long curPos;
+ unsigned long inputLen;
+ /* lookahead buffer */
+ /* -- lookahead buffer is short instead of char so that EOF
+ / can be represented correctly.
+ */
+ unsigned long len;
+ short buf[MAX_LEX_LOOKAHEAD];
+ unsigned long getPtr;
+ /* context stack */
+ unsigned long lexModeStackTop;
+ enum LexMode lexModeStack[MAX_LEX_MODE_STACK_SIZE];
+ /* token buffer */
+ unsigned long maxToken;
+ char *strs;
+ unsigned long strsLen;
+ } lexBuf;
+
+static void lexPushMode(enum LexMode mode)
+ {
+ if (lexBuf.lexModeStackTop == (MAX_LEX_MODE_STACK_SIZE-1))
+ yyerror("lexical context stack overflow");
+ else {
+ lexBuf.lexModeStack[++lexBuf.lexModeStackTop] = mode;
+ }
+ }
+
+static void lexPopMode(int top)
+ {
+ /* special case of pop for ease of error recovery -- this
+ version will never underflow */
+ if (top)
+ lexBuf.lexModeStackTop = 0;
+ else
+ if (lexBuf.lexModeStackTop > 0) lexBuf.lexModeStackTop--;
+ }
+
+static int lexWithinMode(enum LexMode mode) {
+ unsigned long i;
+ for (i=0;i<lexBuf.lexModeStackTop;i++)
+ if (mode == lexBuf.lexModeStack[i]) return 1;
+ return 0;
+ }
+
+static int lexGetc_()
+ {
+ /* get next char from input, no buffering. */
+ if (lexBuf.curPos == lexBuf.inputLen)
+ return EOF;
+ else if (lexBuf.inputString)
+ return *(lexBuf.inputString + lexBuf.curPos++);
+ else {
+#ifdef INCLUDEMFC
+ char result;
+ return lexBuf.inputFile->Read(&result, 1) == 1 ? result : EOF;
+#else
+ return fgetc(lexBuf.inputFile);
+#endif
+ }
+ }
+
+static int lexGeta()
+ {
+ ++lexBuf.len;
+ return (lexBuf.buf[lexBuf.getPtr] = lexGetc_());
+ }
+
+static int lexGeta_(int i)
+ {
+ ++lexBuf.len;
+ return (lexBuf.buf[(lexBuf.getPtr+i)%MAX_LEX_LOOKAHEAD] = lexGetc_());
+ }
+
+static void lexSkipLookahead() {
+ if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
+ /* don't skip EOF. */
+ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
+ lexBuf.len--;
+ }
+ }
+
+static int lexLookahead() {
+ int c = (lexBuf.len)?
+ lexBuf.buf[lexBuf.getPtr]:
+ lexGeta();
+ /* do the \r\n -> \n or \r -> \n translation here */
+ if (c == '\r') {
+ int a = (lexBuf.len>1)?
+ lexBuf.buf[(lexBuf.getPtr+1)%MAX_LEX_LOOKAHEAD]:
+ lexGeta_(1);
+ if (a == '\n') {
+ lexSkipLookahead();
+ }
+ lexBuf.buf[lexBuf.getPtr] = c = '\n';
+ }
+ else if (c == '\n') {
+ int a = (lexBuf.len>1)?
+ lexBuf.buf[lexBuf.getPtr+1]:
+ lexGeta_(1);
+ if (a == '\r') {
+ lexSkipLookahead();
+ }
+ lexBuf.buf[lexBuf.getPtr] = '\n';
+ }
+ return c;
+ }
+
+static int lexGetc() {
+ int c = lexLookahead();
+ if (lexBuf.len > 0 && lexBuf.buf[lexBuf.getPtr]!=EOF) {
+ /* EOF will remain in lookahead buffer */
+ lexBuf.getPtr = (lexBuf.getPtr + 1) % MAX_LEX_LOOKAHEAD;
+ lexBuf.len--;
+ }
+ return c;
+ }
+
+static void lexSkipLookaheadWord() {
+ if (lexBuf.strsLen <= lexBuf.len) {
+ lexBuf.len -= lexBuf.strsLen;
+ lexBuf.getPtr = (lexBuf.getPtr + lexBuf.strsLen) % MAX_LEX_LOOKAHEAD;
+ }
+ }
+
+static void lexClearToken()
+ {
+ lexBuf.strsLen = 0;
+ }
+
+static void lexAppendc(int c)
+ {
+ lexBuf.strs[lexBuf.strsLen] = c;
+ /* append up to zero termination */
+ if (c == 0) return;
+ lexBuf.strsLen++;
+ if (lexBuf.strsLen > lexBuf.maxToken) {
+ /* double the token string size */
+ lexBuf.maxToken <<= 1;
+ lexBuf.strs = (char*) realloc(lexBuf.strs,(size_t)lexBuf.maxToken);
+ }
+ }
+
+static char* lexStr() {
+ return dupStr(lexBuf.strs,(size_t)lexBuf.strsLen+1);
+ }
+
+static void lexSkipWhite() {
+ int c = lexLookahead();
+ while (c == ' ' || c == '\t') {
+ lexSkipLookahead();
+ c = lexLookahead();
+ }
+ }
+
+static char* lexGetWord() {
+ int c;
+ lexSkipWhite();
+ lexClearToken();
+ c = lexLookahead();
+ while (c != EOF && !strchr("\t\n ;:=",c)) {
+ lexAppendc(c);
+ lexSkipLookahead();
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ return lexStr();
+ }
+
+static void lexPushLookaheadc(int c) {
+ int putptr;
+ /* can't putback EOF, because it never leaves lookahead buffer */
+ if (c == EOF) return;
+ putptr = (int)lexBuf.getPtr - 1;
+ if (putptr < 0) putptr += MAX_LEX_LOOKAHEAD;
+ lexBuf.getPtr = putptr;
+ lexBuf.buf[putptr] = c;
+ lexBuf.len += 1;
+ }
+
+static char* lexLookaheadWord() {
+ /* this function can lookahead word with max size of MAX_LEX_LOOKAHEAD_0
+ / and thing bigger than that will stop the lookahead and return 0;
+ / leading white spaces are not recoverable.
+ */
+ int c;
+ int len = 0;
+ int curgetptr = 0;
+ lexSkipWhite();
+ lexClearToken();
+ curgetptr = (int)lexBuf.getPtr; // remember!
+ while (len < (MAX_LEX_LOOKAHEAD_0)) {
+ c = lexGetc();
+ len++;
+ if (c == EOF || strchr("\t\n ;:=", c)) {
+ lexAppendc(0);
+ /* restore lookahead buf. */
+ lexBuf.len += len;
+ lexBuf.getPtr = curgetptr;
+ return lexStr();
+ }
+ else
+ lexAppendc(c);
+ }
+ lexBuf.len += len; /* char that has been moved to lookahead buffer */
+ lexBuf.getPtr = curgetptr;
+ return 0;
+ }
+
+#ifdef _SUPPORT_LINE_FOLDING
+static void handleMoreRFC822LineBreak(int c) {
+ /* suport RFC 822 line break in cases like
+ * ADR: foo;
+ * morefoo;
+ * more foo;
+ */
+ if (c == ';') {
+ int a;
+ lexSkipLookahead();
+ /* skip white spaces */
+ a = lexLookahead();
+ while (a == ' ' || a == '\t') {
+ lexSkipLookahead();
+ a = lexLookahead();
+ }
+ if (a == '\n') {
+ lexSkipLookahead();
+ a = lexLookahead();
+ if (a == ' ' || a == '\t') {
+ /* continuation, throw away all the \n and spaces read so
+ * far
+ */
+ lexSkipWhite();
+ lexPushLookaheadc(';');
+ }
+ else {
+ lexPushLookaheadc('\n');
+ lexPushLookaheadc(';');
+ }
+ }
+ else {
+ lexPushLookaheadc(';');
+ }
+ }
+ }
+
+static char* lexGet1Value() {
+ int c;
+ lexSkipWhite();
+ c = lexLookahead();
+ lexClearToken();
+ while (c != EOF && c != ';') {
+ if (c == '\\' ) {
+ int a;
+ lexSkipLookahead();
+ a = lexLookahead();
+ if ( a != ';' ) {
+ lexAppendc('\\');
+ } else {
+ lexAppendc( ';' );
+ lexSkipLookahead();
+ }
+ } else if (c == '\n') {
+ int a;
+ lexSkipLookahead();
+ a = lexLookahead();
+ if (a == ' ' || a == '\t') {
+ lexAppendc(' ');
+ lexSkipLookahead();
+ }
+ else {
+ lexPushLookaheadc('\n');
+ break;
+ }
+ }
+ else {
+ lexAppendc(c);
+ lexSkipLookahead();
+ }
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ handleMoreRFC822LineBreak(c);
+ return c==EOF?0:lexStr();
+ }
+#endif
+
+static int match_begin_name(int end) {
+ char *n = lexLookaheadWord();
+ int token = ID;
+ if (n) {
+ if (!qstricmp(n,"vcard")) token = end?END_VCARD:BEGIN_VCARD;
+ else if (!qstricmp(n,"vcalendar")) token = end?END_VCAL:BEGIN_VCAL;
+ else if (!qstricmp(n,"vevent")) token = end?END_VEVENT:BEGIN_VEVENT;
+ else if (!qstricmp(n,"vtodo")) token = end?END_VTODO:BEGIN_VTODO;
+ deleteStr(n);
+ return token;
+ }
+ return 0;
+ }
+
+
+#ifdef INCLUDEMFC
+void initLex(const char *inputstring, unsigned long inputlen, CFile *inputfile)
+#else
+void initLex(const char *inputstring, unsigned long inputlen, FILE *inputfile)
+#endif
+ {
+ // initialize lex mode stack
+ lexBuf.lexModeStack[lexBuf.lexModeStackTop=0] = L_NORMAL;
+
+ // iniatialize lex buffer.
+ lexBuf.inputString = (char*) inputstring;
+ lexBuf.inputLen = inputlen;
+ lexBuf.curPos = 0;
+ lexBuf.inputFile = inputfile;
+
+ lexBuf.len = 0;
+ lexBuf.getPtr = 0;
+
+ lexBuf.maxToken = MAXTOKEN;
+ lexBuf.strs = (char*)malloc(MAXTOKEN);
+ lexBuf.strsLen = 0;
+
+ }
+
+static void finiLex() {
+ free(lexBuf.strs);
+ }
+
+
+/*-----------------------------------*/
+/* This parses and converts the base64 format for binary encoding into
+ * a decoded buffer (allocated with new). See RFC 1521.
+ */
+static char * lexGetDataFromBase64()
+ {
+ unsigned long bytesLen = 0, bytesMax = 0;
+ int quadIx = 0, pad = 0;
+ unsigned long trip = 0;
+ unsigned char b;
+ int c;
+ unsigned char *bytes = NULL;
+ unsigned char *oldBytes = NULL;
+
+ DBG_(("db: lexGetDataFromBase64\n"));
+ while (1) {
+ c = lexGetc();
+ if (c == '\n') {
+ ++mime_lineNum;
+ if (lexLookahead() == '\n') {
+ /* a '\n' character by itself means end of data */
+ break;
+ }
+ else continue; /* ignore '\n' */
+ }
+ else {
+ if ((c >= 'A') && (c <= 'Z'))
+ b = (unsigned char)(c - 'A');
+ else if ((c >= 'a') && (c <= 'z'))
+ b = (unsigned char)(c - 'a') + 26;
+ else if ((c >= '0') && (c <= '9'))
+ b = (unsigned char)(c - '0') + 52;
+ else if (c == '+')
+ b = 62;
+ else if (c == '/')
+ b = 63;
+ else if (c == '=') {
+ b = 0;
+ pad++;
+ } else if ((c == ' ') || (c == '\t')) {
+ continue;
+ } else { /* error condition */
+ if (bytes) free(bytes);
+ else if (oldBytes) free(oldBytes);
+ // error recovery: skip until 2 adjacent newlines.
+ DBG_(("db: invalid character 0x%x '%c'\n", c,c));
+ if (c != EOF) {
+ c = lexGetc();
+ while (c != EOF) {
+ if (c == '\n' && lexLookahead() == '\n') {
+ ++mime_lineNum;
+ break;
+ }
+ c = lexGetc();
+ }
+ }
+ return NULL;
+ }
+ trip = (trip << 6) | b;
+ if (++quadIx == 4) {
+ unsigned char outBytes[3];
+ int numOut;
+ int i;
+ for (i = 0; i < 3; i++) {
+ outBytes[2-i] = (unsigned char)(trip & 0xFF);
+ trip >>= 8;
+ }
+ numOut = 3 - pad;
+ if (bytesLen + numOut > bytesMax) {
+ if (!bytes) {
+ bytesMax = 1024;
+ bytes = (unsigned char*)malloc((size_t)bytesMax);
+ }
+ else {
+ bytesMax <<= 2;
+ oldBytes = bytes;
+ bytes = (unsigned char*)realloc(bytes,(size_t)bytesMax);
+ }
+ if (bytes == 0) {
+ mime_error("out of memory while processing BASE64 data\n");
+ }
+ }
+ if (bytes) {
+ memcpy(bytes + bytesLen, outBytes, numOut);
+ bytesLen += numOut;
+ }
+ trip = 0;
+ quadIx = 0;
+ }
+ }
+ } /* while */
+ DBG_(("db: bytesLen = %d\n", bytesLen));
+ /* kludge: all this won't be necessary if we have tree form
+ representation */
+ if (bytes) {
+ setValueWithSize(curProp,bytes,(unsigned int)bytesLen);
+ free(bytes);
+ }
+ else if (oldBytes) {
+ setValueWithSize(curProp,oldBytes,(unsigned int)bytesLen);
+ free(oldBytes);
+ }
+ return 0;
+ }
+
+static int match_begin_end_name(int end) {
+ int token;
+ lexSkipWhite();
+ if (lexLookahead() != ':') return ID;
+ lexSkipLookahead();
+ lexSkipWhite();
+ token = match_begin_name(end);
+ if (token == ID) {
+ lexPushLookaheadc(':');
+ DBG_(("db: ID '%s'\n", yylval.str));
+ return ID;
+ }
+ else if (token != 0) {
+ lexSkipLookaheadWord();
+ deleteStr(yylval.str);
+ DBG_(("db: begin/end %d\n", token));
+ return token;
+ }
+ return 0;
+ }
+
+static char* lexGetQuotedPrintable()
+{
+ int c;
+ lexSkipWhite();
+ c = lexLookahead();
+ lexClearToken();
+
+ while (c != EOF && c != ';') {
+ if (c == '\n') {
+ // break, leave '\n' on remaining chars.
+ break;
+ } else if (c == '=') {
+ int cur = 0;
+ int next;
+
+ lexSkipLookahead(); // skip '='
+ next = lexLookahead();
+
+ if (next == '\n') {
+ // skip and only skip the \n
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum; // aid in error reporting
+ continue;
+ } else if (next >= '0' && next <= '9') {
+ cur = next - '0';
+ } else if (next >= 'A' && next <= 'F') {
+ cur = next - 'A' + 10;
+ } else {
+ // we have been sent buggy stuff. doesn't matter
+ // what we do so long as we keep going.
+ // should probably spit an error here
+ c = lexLookahead();
+ continue;
+ }
+
+ lexSkipLookahead(); // skip A-Z0-9
+ next = lexLookahead();
+
+ cur = cur * 16;
+ // this time really just expecting 0-9A-F
+ if (next >= '0' && next <= '9') {
+ cur += next - '0';
+ } else if (next >= 'A' && next <= 'F') {
+ cur += next - 'A' + 10;
+ } else {
+ // we have been sent buggy stuff. doesn't matter
+ // what we do so long as we keep going.
+ // should probably spit an error here
+ c = lexLookahead();
+ continue;
+ }
+
+ // got a valid escaped =. append it.
+ lexSkipLookahead(); // skip second 0-9A-F
+ lexAppendc(cur);
+ } else {
+ lexSkipLookahead(); // skip whatever we just read.
+ lexAppendc(c); // and append it.
+ }
+ c = lexLookahead();
+ }
+ lexAppendc(0);
+ return c==EOF?0:lexStr();
+}
+
+static int yylex() {
+
+ int lexmode = LEXMODE();
+ if (lexmode == L_VALUES) {
+ int c = lexGetc();
+ if (c == ';') {
+ DBG_(("db: SEMICOLON\n"));
+ lexPushLookaheadc(c);
+ handleMoreRFC822LineBreak(c);
+ lexSkipLookahead();
+ return SEMICOLON;
+ }
+ else if (strchr("\n",c)) {
+ ++mime_lineNum;
+ /* consume all line separator(s) adjacent to each other */
+ c = lexLookahead();
+ while (strchr("\n",c)) {
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum;
+ }
+ DBG_(("db: LINESEP\n"));
+ return LINESEP;
+ }
+ else {
+ char *p = 0;
+ lexPushLookaheadc(c);
+ if (lexWithinMode(L_BASE64)) {
+ /* get each char and convert to bin on the fly... */
+ p = lexGetDataFromBase64();
+ yylval.str = p;
+ return STRING;
+ }
+ else if (lexWithinMode(L_QUOTED_PRINTABLE)) {
+ p = lexGetQuotedPrintable();
+ }
+ else {
+#ifdef _SUPPORT_LINE_FOLDING
+ p = lexGet1Value();
+#else
+ p = lexGetStrUntil(";\n");
+#endif
+ }
+ if (p) {
+ DBG_(("db: STRING: '%s'\n", p));
+ yylval.str = p;
+ return STRING;
+ }
+ else return 0;
+ }
+ }
+ else {
+ /* normal mode */
+ while (1) {
+ int c = lexGetc();
+ switch(c) {
+ case ':': {
+ /* consume all line separator(s) adjacent to each other */
+ /* ignoring linesep immediately after colon. */
+ c = lexLookahead();
+ while (strchr("\n",c)) {
+ lexSkipLookahead();
+ c = lexLookahead();
+ ++mime_lineNum;
+ }
+ DBG_(("db: COLON\n"));
+ return COLON;
+ }
+ case ';':
+ DBG_(("db: SEMICOLON\n"));
+ return SEMICOLON;
+ case '=':
+ DBG_(("db: EQ\n"));
+ return EQ;
+ /* ignore whitespace in this mode */
+ case '\t':
+ case ' ': continue;
+ case '\n': {
+ ++mime_lineNum;
+ continue;
+ }
+ case EOF: return 0;
+ break;
+ default: {
+ lexPushLookaheadc(c);
+ if (isalnum(c)) {
+ char *t = lexGetWord();
+ yylval.str = t;
+ if (!qstricmp(t, "begin")) {
+ return match_begin_end_name(0);
+ }
+ else if (!qstricmp(t,"end")) {
+ return match_begin_end_name(1);
+ }
+ else {
+ DBG_(("db: ID '%s'\n", t));
+ return ID;
+ }
+ }
+ else {
+ /* unknow token */
+ return 0;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+
+
+/***************************************************************************/
+/*** Public Functions ****/
+/***************************************************************************/
+
+static VObject* Parse_MIMEHelper()
+ {
+ ObjStackTop = -1;
+ mime_numErrors = 0;
+ mime_lineNum = 1;
+ vObjList = 0;
+ curObj = 0;
+
+ if (yyparse() != 0)
+ return 0;
+
+ finiLex();
+ return vObjList;
+ }
+
+/*--------------------------------------------*/
+DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len)
+ {
+ initLex(input, len, 0);
+ return Parse_MIMEHelper();
+ }
+
+
+#if INCLUDEMFC
+
+DLLEXPORT(VObject*) Parse_MIME_FromFile(CFile *file)
+ {
+ unsigned long startPos;
+ VObject *result;
+
+ initLex(0,-1,file);
+ startPos = file->GetPosition();
+ if (!(result = Parse_MIMEHelper()))
+ file->Seek(startPos, CFile::begin);
+ return result;
+ }
+
+#else
+
+VObject* Parse_MIME_FromFile(FILE *file)
+ {
+ VObject *result;
+ long startPos;
+
+ initLex(0,(unsigned long)-1,file);
+ startPos = ftell(file);
+ if (!(result = Parse_MIMEHelper())) {
+ fseek(file,startPos,SEEK_SET);
+ }
+ return result;
+ }
+
+DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
+ {
+ FILE *fp = fopen(fname,"r");
+ if (fp) {
+ VObject* o = Parse_MIME_FromFile(fp);
+ fclose(fp);
+ return o;
+ }
+ else {
+ char msg[80];
+ sprintf(msg, "can't open file '%s' for reading\n", fname);
+ mime_error_(msg);
+ return 0;
+ }
+ }
+
+#endif
+
+/*-------------------------------------*/
+
+static MimeErrorHandler mimeErrorHandler;
+
+DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler me)
+ {
+ mimeErrorHandler = me;
+ }
+
+void mime_error(char *s)
+ {
+ char msg[256];
+ if (mimeErrorHandler) {
+ sprintf(msg,"%s at line %d", s, mime_lineNum);
+ mimeErrorHandler(msg);
+ }
+ }
+
+void mime_error_(char *s)
+ {
+ if (mimeErrorHandler) {
+ mimeErrorHandler(s);
+ }
+ }
+
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,19 +1,44 @@
#ifndef lint
-static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
+/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[] = "$Id$";
#endif
#define YYBYACC 1
#define YYMAJOR 1
#define YYMINOR 9
#define yyclearin (yychar=(-1))
#define yyerrok (yyerrflag=0)
#define YYRECOVERING (yyerrflag!=0)
-#define YYPREFIX "yy"
-#line 1 "vcc.y"
+#define yyparse vccparse
+#define yylex vcclex
+#define yyerror vccerror
+#define yychar vccchar
+#define yyval vccval
+#define yylval vcclval
+#define yydebug vccdebug
+#define yynerrs vccnerrs
+#define yyerrflag vccerrflag
+#define yyss vccss
+#define yyssp vccssp
+#define yyvs vccvs
+#define yyvsp vccvsp
+#define yylhs vcclhs
+#define yylen vcclen
+#define yydefred vccdefred
+#define yydgoto vccdgoto
+#define yysindex vccsindex
+#define yyrindex vccrindex
+#define yygindex vccgindex
+#define yytable vcctable
+#define yycheck vcccheck
+#define yyname vccname
+#define yyrule vccrule
+#define YYPREFIX "vcc"
+#line 1 "backend/vcc.y"
/***************************************************************************
(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
Business Machines Corporation and Siemens Rolm Communications Inc.
For purposes of this license notice, the term Licensors shall mean,
collectively, Apple Computer, Inc., AT&T Corp., International
@@ -68,16 +93,17 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
#endif
/**** External Functions ****/
/* assign local name to parser variables and functions so that
we can use more than one yacc based parser.
*/
+#if 0
#define yyparse mime_parse
#define yylex mime_lex
#define yyerror mime_error
#define yychar mime_char
/* #define p_yyval p_mime_val */
#undef yyval
#define yyval mime_yyval
/* #define p_yylval p_mime_lval */
@@ -100,16 +126,17 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
#define yytable mime_table
#define yycheck mime_check
#define yyname mime_name
#define yyrule mime_rule
#ifdef YYPREFIX
#undef YYPREFIX
#endif
#define YYPREFIX "mime_"
+#endif
#ifndef _NO_LINE_FOLDING
#define _SUPPORT_LINE_FOLDING 1
#endif
/* undef below if compile with MFC */
/* #define INCLUDEMFC 1 */
@@ -123,30 +150,27 @@ DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
#include <string.h>
#ifndef __MWERKS__
#include <stdlib.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
-#ifdef PALMTOPCENTER
-#include <qpe/vobject_p.h>
-#include <qpe/qfiledirect_p.h>
-#else
+/*#ifdef PALMTOPCENTER */
+/*#include <qpe/vobject_p.h> */
+/*#else */
#include "vobject_p.h"
-#include "qfiledirect_p.h"
-#endif
+/*#endif */
/**** Types, Constants ****/
#define YYDEBUG 0 /* 1 to compile in some debugging code */
#define MAXTOKEN 256 /* maximum token (line) length */
-#define YYSTACKSIZE 100 /* ~unref ?
-*/
+#define YYSTACKSIZE 100 /* ~unref ? */
#define MAXLEVEL 10 /* max # of nested objects parseable */
/* (includes outermost) */
/**** Global Variables ****/
int mime_lineNum, mime_numErrors; /* yyerror() can use these */
static VObject* vObjList;
static VObject *curProp;
@@ -183,24 +207,26 @@ enum LexMode {
static int pushVObject(const char *prop);
static VObject* popVObject();
static void lexPopMode(int top);
static int lexWithinMode(enum LexMode mode);
static void lexPushMode(enum LexMode mode);
static void enterProps(const char *s);
static void enterAttr(const char *s1, const char *s2);
static void enterValues(const char *value);
+#define mime_error yyerror
+void mime_error(char *s);
void mime_error_(char *s);
-#line 185 "vcc.y"
+#line 189 "backend/vcc.y"
typedef union {
char *str;
VObject *vobj;
} YYSTYPE;
-#line 196 "y.tab.c"
+#line 225 "y.tab.c"
#define EQ 257
#define COLON 258
#define DOT 259
#define SEMICOLON 260
#define SPACE 261
#define HTAB 262
#define LINESEP 263
#define NEWLINE 264
@@ -210,103 +236,103 @@ typedef union {
#define END_VCAL 268
#define BEGIN_VEVENT 269
#define END_VEVENT 270
#define BEGIN_VTODO 271
#define END_VTODO 272
#define ID 273
#define STRING 274
#define YYERRCODE 256
-short yylhs[] = { -1,
+short vcclhs[] = { -1,
0, 6, 6, 5, 5, 8, 3, 9, 3, 7,
7, 13, 10, 10, 15, 11, 11, 14, 14, 16,
17, 17, 1, 18, 12, 12, 2, 2, 20, 4,
21, 4, 19, 19, 22, 22, 22, 25, 23, 26,
23, 27, 24, 28, 24,
};
-short yylen[] = { 2,
+short vcclen[] = { 2,
1, 2, 1, 1, 1, 0, 4, 0, 3, 2,
1, 0, 5, 1, 0, 3, 1, 2, 1, 2,
1, 3, 1, 0, 4, 1, 1, 0, 0, 4,
0, 3, 2, 1, 1, 1, 1, 0, 4, 0,
3, 0, 4, 0, 3,
};
-short yydefred[] = { 0,
+short vccdefred[] = { 0,
0, 0, 0, 4, 5, 3, 0, 0, 0, 0,
0, 2, 14, 23, 0, 0, 11, 0, 9, 0,
0, 0, 0, 34, 35, 36, 32, 0, 7, 10,
12, 0, 0, 0, 0, 30, 33, 0, 0, 19,
0, 0, 41, 0, 45, 0, 20, 18, 27, 0,
0, 39, 43, 0, 24, 13, 22, 0, 25,
};
-short yydgoto[] = { 3,
+short vccdgoto[] = { 3,
15, 50, 4, 5, 6, 7, 22, 8, 9, 17,
18, 51, 41, 39, 28, 40, 47, 58, 23, 10,
11, 24, 25, 26, 32, 33, 34, 35,
};
-short yysindex[] = { -262,
+short vccsindex[] = { -262,
0, 0, 0, 0, 0, 0, -262, -252, -219, -249,
-256, 0, 0, 0, 0, -227, 0, -242, 0, 0,
0, -252, -254, 0, 0, 0, 0, -208, 0, 0,
0, -252, -228, -252, -213, 0, 0, -212, -208, 0,
-214, -233, 0, -224, 0, -195, 0, 0, 0, -197,
-199, 0, 0, -212, 0, 0, 0, -214, 0,
};
-short yyrindex[] = { 0,
+short vccrindex[] = { 0,
-222, -238, 0, 0, 0, 0, 65, 0, 0, 0,
0, 0, 0, 0, -215, 0, 0, 0, 0, -220,
-218, -260, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, -192, 0,
-250, 0, 0, 0, 0, -202, 0, 0, 0, -196,
0, 0, 0, 0, 0, 0, 0, -250, 0,
};
-short yygindex[] = { 0,
+short vccgindex[] = { 0,
3, 0, 0, 0, 61, 0, -7, 0, 0, -16,
0, 11, 0, 0, 0, 31, 0, 0, 0, 0,
0, 48, 0, 0, 0, 0, 0, 0,
};
#define YYTABLESIZE 71
-short yytable[] = { 30,
+short vcctable[] = { 30,
16, 13, 1, 13, 2, 30, 13, 37, 37, 28,
37, 27, 28, 36, 20, 31, 21, 29, 14, 20,
14, 21, 13, 14, 42, 30, 44, 30, 13, 31,
29, 13, 29, 6, 29, 38, 52, 42, 29, 14,
46, 43, 17, 8, 15, 14, 19, 53, 14, 40,
6, 38, 38, 44, 42, 21, 57, 21, 45, 49,
14, 54, 55, 56, 1, 16, 26, 12, 59, 48,
37,
};
-short yycheck[] = { 16,
+short vcccheck[] = { 16,
8, 256, 265, 256, 267, 22, 256, 268, 269, 260,
271, 268, 263, 268, 269, 258, 271, 256, 273, 269,
273, 271, 256, 273, 32, 42, 34, 44, 256, 268,
269, 256, 271, 256, 273, 256, 270, 256, 266, 273,
38, 270, 258, 266, 260, 273, 266, 272, 273, 270,
273, 260, 273, 272, 273, 258, 54, 260, 272, 274,
273, 257, 260, 263, 0, 258, 263, 7, 58, 39,
23,
};
#define YYFINAL 3
#ifndef YYDEBUG
#define YYDEBUG 0
#endif
#define YYMAXTOKEN 274
#if YYDEBUG
-char *yyname[] = {
+char *vccname[] = {
"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,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"EQ","COLON","DOT","SEMICOLON",
"SPACE","HTAB","LINESEP","NEWLINE","BEGIN_VCARD","END_VCARD","BEGIN_VCAL",
"END_VCAL","BEGIN_VEVENT","END_VEVENT","BEGIN_VTODO","END_VTODO","ID","STRING",
};
-char *yyrule[] = {
+char *vccrule[] = {
"$accept : mime",
"mime : vobjects",
"vobjects : vobjects vobject",
"vobjects : vobject",
"vobject : vcard",
"vobject : vcal",
"$$1 :",
"vcard : BEGIN_VCARD $$1 items END_VCARD",
@@ -367,17 +393,17 @@ int yyerrflag;
int yychar;
short *yyssp;
YYSTYPE *yyvsp;
YYSTYPE yyval;
YYSTYPE yylval;
short yyss[YYSTACKSIZE];
YYSTYPE yyvs[YYSTACKSIZE];
#define yystacksize YYSTACKSIZE
-#line 378 "vcc.y"
+#line 382 "backend/vcc.y"
/*------------------------------------*/
static int pushVObject(const char *prop)
{
VObject *newObj;
if (ObjStackTop == MAXLEVEL)
return FALSE;
@@ -506,17 +532,17 @@ static void lexPopMode(int top)
static int lexWithinMode(enum LexMode mode) {
unsigned long i;
for (i=0;i<lexBuf.lexModeStackTop;i++)
if (mode == lexBuf.lexModeStack[i]) return 1;
return 0;
}
-static char lexGetc_()
+static int lexGetc_()
{
/* get next char from input, no buffering. */
if (lexBuf.curPos == lexBuf.inputLen)
return EOF;
else if (lexBuf.inputString)
return *(lexBuf.inputString + lexBuf.curPos++);
else {
#ifdef INCLUDEMFC
@@ -920,17 +946,17 @@ static int match_begin_end_name(int end) {
DBG_(("db: begin/end %d\n", token));
return token;
}
return 0;
}
static char* lexGetQuotedPrintable()
{
- char cur;
+ int cur;
lexClearToken();
do {
cur = lexGetc();
switch (cur) {
case '=': {
int c = 0;
int next[2];
@@ -962,23 +988,23 @@ static char* lexGetQuotedPrintable()
lexAppendc(c);
}
break;
} /* '=' */
case '\n': {
lexPushLookaheadc('\n');
goto EndString;
}
- case (char)EOF:
+ case (int)EOF:
break;
default:
lexAppendc(cur);
break;
} /* switch */
- } while (cur != (char)EOF);
+ } while (cur != (int)EOF);
EndString:
lexAppendc(0);
return lexStr();
} /* LexQuotedPrintable */
static int yylex() {
@@ -1145,23 +1171,28 @@ VObject* Parse_MIME_FromFile(FILE *file)
if (!(result = Parse_MIMEHelper())) {
fseek(file,startPos,SEEK_SET);
}
return result;
}
DLLEXPORT(VObject*) Parse_MIME_FromFileName(char *fname)
{
- QFileDirect f( fname );
- if ( !f.open( IO_ReadOnly ) ) {
- qWarning("Unable to open mime for reading %s", fname);
- return 0;
+ FILE *fp = fopen(fname,"r");
+ if (fp) {
+ VObject* o = Parse_MIME_FromFile(fp);
+ fclose(fp);
+ return o;
+ }
+ else {
+ char msg[80];
+ sprintf(msg, "can't open file '%s' for reading\n", fname);
+ mime_error_(msg);
+ return 0;
}
-
- return Parse_MIME_FromFile( f.directHandle() );
}
#endif
/*-------------------------------------*/
static MimeErrorHandler mimeErrorHandler;
@@ -1181,23 +1212,27 @@ void mime_error(char *s)
void mime_error_(char *s)
{
if (mimeErrorHandler) {
mimeErrorHandler(s);
}
}
-#line 1192 "y.tab.c"
+#line 1221 "y.tab.c"
#define YYABORT goto yyabort
#define YYREJECT goto yyabort
#define YYACCEPT goto yyaccept
#define YYERROR goto yyerrlab
int
+#if defined(__STDC__)
+yyparse(void)
+#else
yyparse()
+#endif
{
register int yym, yyn, yystate;
#if YYDEBUG
register char *yys;
extern char *getenv();
if (yys = getenv("YYDEBUG"))
{
@@ -1211,17 +1246,17 @@ yyparse()
yyerrflag = 0;
yychar = (-1);
yyssp = yyss;
yyvsp = yyvs;
*yyssp = yystate = 0;
yyloop:
- if (yyn = yydefred[yystate]) goto yyreduce;
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
if (yychar < 0)
{
if ((yychar = yylex()) < 0) yychar = 0;
#if YYDEBUG
if (yydebug)
{
yys = 0;
if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
@@ -1251,20 +1286,16 @@ yyloop:
}
if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
{
yyn = yytable[yyn];
goto yyreduce;
}
if (yyerrflag) goto yyinrecovery;
-#ifdef lint
- goto yynewerror;
-#endif
-yynewerror:
yyerror("syntax error");
#ifdef lint
goto yyerrlab;
#endif
yyerrlab:
++yynerrs;
yyinrecovery:
if (yyerrflag < 3)
@@ -1323,175 +1354,175 @@ yyreduce:
printf("%sdebug: state %d, reducing by rule %d (%s)\n",
YYPREFIX, yystate, yyn, yyrule[yyn]);
#endif
yym = yylen[yyn];
yyval = yyvsp[1-yym];
switch (yyn)
{
case 2:
-#line 217 "vcc.y"
+#line 221 "backend/vcc.y"
{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
break;
case 3:
-#line 219 "vcc.y"
+#line 223 "backend/vcc.y"
{ addList(&vObjList, yyvsp[0].vobj); curObj = 0; }
break;
case 6:
-#line 228 "vcc.y"
+#line 232 "backend/vcc.y"
{
lexPushMode(L_VCARD);
if (!pushVObject(VCCardProp)) YYERROR;
}
break;
case 7:
-#line 233 "vcc.y"
+#line 237 "backend/vcc.y"
{
lexPopMode(0);
yyval.vobj = popVObject();
}
break;
case 8:
-#line 238 "vcc.y"
+#line 242 "backend/vcc.y"
{
lexPushMode(L_VCARD);
if (!pushVObject(VCCardProp)) YYERROR;
}
break;
case 9:
-#line 243 "vcc.y"
+#line 247 "backend/vcc.y"
{
lexPopMode(0);
yyval.vobj = popVObject();
}
break;
case 12:
-#line 254 "vcc.y"
+#line 258 "backend/vcc.y"
{
lexPushMode(L_VALUES);
}
break;
case 13:
-#line 258 "vcc.y"
+#line 262 "backend/vcc.y"
{
if (lexWithinMode(L_BASE64) || lexWithinMode(L_QUOTED_PRINTABLE))
lexPopMode(0);
lexPopMode(0);
}
break;
case 15:
-#line 267 "vcc.y"
+#line 271 "backend/vcc.y"
{
enterProps(yyvsp[0].str);
}
break;
case 17:
-#line 272 "vcc.y"
+#line 276 "backend/vcc.y"
{
enterProps(yyvsp[0].str);
}
break;
case 21:
-#line 285 "vcc.y"
+#line 289 "backend/vcc.y"
{
enterAttr(yyvsp[0].str,0);
}
break;
case 22:
-#line 289 "vcc.y"
+#line 293 "backend/vcc.y"
{
enterAttr(yyvsp[-2].str,yyvsp[0].str);
}
break;
case 24:
-#line 298 "vcc.y"
+#line 302 "backend/vcc.y"
{ enterValues(yyvsp[-1].str); }
break;
case 26:
-#line 300 "vcc.y"
+#line 304 "backend/vcc.y"
{ enterValues(yyvsp[0].str); }
break;
case 28:
-#line 305 "vcc.y"
+#line 309 "backend/vcc.y"
{ yyval.str = 0; }
break;
case 29:
-#line 310 "vcc.y"
+#line 314 "backend/vcc.y"
{ if (!pushVObject(VCCalProp)) YYERROR; }
break;
case 30:
-#line 313 "vcc.y"
+#line 317 "backend/vcc.y"
{ yyval.vobj = popVObject(); }
break;
case 31:
-#line 315 "vcc.y"
+#line 319 "backend/vcc.y"
{ if (!pushVObject(VCCalProp)) YYERROR; }
break;
case 32:
-#line 317 "vcc.y"
+#line 321 "backend/vcc.y"
{ yyval.vobj = popVObject(); }
break;
case 38:
-#line 332 "vcc.y"
+#line 336 "backend/vcc.y"
{
lexPushMode(L_VEVENT);
if (!pushVObject(VCEventProp)) YYERROR;
}
break;
case 39:
-#line 338 "vcc.y"
+#line 342 "backend/vcc.y"
{
lexPopMode(0);
popVObject();
}
break;
case 40:
-#line 343 "vcc.y"
+#line 347 "backend/vcc.y"
{
lexPushMode(L_VEVENT);
if (!pushVObject(VCEventProp)) YYERROR;
}
break;
case 41:
-#line 348 "vcc.y"
+#line 352 "backend/vcc.y"
{
lexPopMode(0);
popVObject();
}
break;
case 42:
-#line 356 "vcc.y"
+#line 360 "backend/vcc.y"
{
lexPushMode(L_VTODO);
if (!pushVObject(VCTodoProp)) YYERROR;
}
break;
case 43:
-#line 362 "vcc.y"
+#line 366 "backend/vcc.y"
{
lexPopMode(0);
popVObject();
}
break;
case 44:
-#line 367 "vcc.y"
+#line 371 "backend/vcc.y"
{
lexPushMode(L_VTODO);
if (!pushVObject(VCTodoProp)) YYERROR;
}
break;
case 45:
-#line 372 "vcc.y"
+#line 376 "backend/vcc.y"
{
lexPopMode(0);
popVObject();
}
break;
-#line 1492 "y.tab.c"
+#line 1521 "y.tab.c"
}
yyssp -= yym;
yystate = *yyssp;
yyvsp -= yym;
yym = yylhs[yyn];
if (yystate == 0 && yym == 0)
{
#if YYDEBUG
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 @@
-/***************************************************************************
-(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-
-For purposes of this license notice, the term Licensors shall mean,
-collectively, Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-The term Licensor shall mean any of the Licensors.
-
-Subject to acceptance of the following conditions, permission is hereby
-granted by Licensors without the need for written agreement and without
-license or royalty fees, to use, copy, modify and distribute this
-software for any purpose.
-
-The above copyright notice and the following four paragraphs must be
-reproduced in all copies of this software and any software including
-this software.
-
-THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
-ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
-MODIFICATIONS.
-
-IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
-INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
-OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.
-
-The software is provided with RESTRICTED RIGHTS. Use, duplication, or
-disclosure by the government are subject to restrictions set forth in
-DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
-
-***************************************************************************/
-
-/*
- * src: vobject.c
- * doc: vobject and APIs to construct vobject, APIs pretty print
- * vobject, and convert a vobject into its textual representation.
- */
-
-#ifndef MWERKS
-#include <malloc.h>
-#endif
-
-#include "vobject_p.h"
-#include "qfiledirect_p.h"
-#include <string.h>
-#include <stdio.h>
-#include <fcntl.h>
-//#include <io.h>
-
-
-#define NAME_OF(o) o->id
-#define VALUE_TYPE(o) o->valType
-#define STRINGZ_VALUE_OF(o) o->val.strs
-#define INTEGER_VALUE_OF(o) o->val.i
-#define LONG_VALUE_OF(o) o->val.l
-#define ANY_VALUE_OF(o) o->val.any
-#define VOBJECT_VALUE_OF(o) o->val.vobj
-
-typedef union ValueItem {
- const char *strs;
- unsigned int i;
- unsigned long l;
- void *any;
- VObject *vobj;
- } ValueItem;
-
-struct VObject {
- VObject *next;
- const char *id;
- VObject *prop;
- unsigned short valType;
- ValueItem val;
- };
-
-typedef struct StrItem StrItem;
-
-struct StrItem {
- StrItem *next;
- const char *s;
- unsigned int refCnt;
- };
-
-const char** fieldedProp;
-
-
-
-/*----------------------------------------------------------------------
- The following functions involve with memory allocation:
- newVObject
- deleteVObject
- dupStr
- deleteStr
- newStrItem
- deleteStrItem
- ----------------------------------------------------------------------*/
-
-DLLEXPORT(VObject*) newVObject_(const char *id)
-{
- VObject *p = (VObject*)malloc(sizeof(VObject));
- p->next = 0;
- p->id = id;
- p->prop = 0;
- VALUE_TYPE(p) = 0;
- ANY_VALUE_OF(p) = 0;
- return p;
-}
-
-DLLEXPORT(VObject*) newVObject(const char *id)
-{
- return newVObject_(lookupStr(id));
-}
-
-DLLEXPORT(void) deleteVObject(VObject *p)
-{
- unUseStr(p->id);
- free(p);
-}
-
-DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
-{
- char *t;
- if (size == 0) {
- size = strlen(s);
- }
- t = (char*)malloc(size+1);
- if (t) {
- memcpy(t,s,size);
- t[size] = 0;
- return t;
- }
- else {
- return (char*)0;
- }
-}
-
-DLLEXPORT(void) deleteStr(const char *p)
-{
- if (p) free((void*)p);
-}
-
-
-static StrItem* newStrItem(const char *s, StrItem *next)
-{
- StrItem *p = (StrItem*)malloc(sizeof(StrItem));
- p->next = next;
- p->s = s;
- p->refCnt = 1;
- return p;
-}
-
-static void deleteStrItem(StrItem *p)
-{
- free((void*)p);
-}
-
-
-/*----------------------------------------------------------------------
- The following function provide accesses to VObject's value.
- ----------------------------------------------------------------------*/
-
-DLLEXPORT(const char*) vObjectName(VObject *o)
-{
- return NAME_OF(o);
-}
-
-DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
-{
- NAME_OF(o) = id;
-}
-
-DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
-{
- return STRINGZ_VALUE_OF(o);
-}
-
-DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
-{
- STRINGZ_VALUE_OF(o) = dupStr(s,0);
- VALUE_TYPE(o) = VCVT_STRINGZ;
-}
-
-DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
-{
- STRINGZ_VALUE_OF(o) = s;
- VALUE_TYPE(o) = VCVT_STRINGZ;
-}
-
-DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
-{
- return INTEGER_VALUE_OF(o);
-}
-
-DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
-{
- INTEGER_VALUE_OF(o) = i;
- VALUE_TYPE(o) = VCVT_UINT;
-}
-
-DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
-{
- return LONG_VALUE_OF(o);
-}
-
-DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
-{
- LONG_VALUE_OF(o) = l;
- VALUE_TYPE(o) = VCVT_ULONG;
-}
-
-DLLEXPORT(void*) vObjectAnyValue(VObject *o)
-{
- return ANY_VALUE_OF(o);
-}
-
-DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
-{
- ANY_VALUE_OF(o) = t;
- VALUE_TYPE(o) = VCVT_RAW;
-}
-
-DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
-{
- return VOBJECT_VALUE_OF(o);
-}
-
-DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
-{
- VOBJECT_VALUE_OF(o) = p;
- VALUE_TYPE(o) = VCVT_VOBJECT;
-}
-
-DLLEXPORT(int) vObjectValueType(VObject *o)
-{
- return VALUE_TYPE(o);
-}
-
-
-/*----------------------------------------------------------------------
- The following functions can be used to build VObject.
- ----------------------------------------------------------------------*/
-
-DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
-{
- /* circular link list pointed to tail */
- /*
- o {next,id,prop,val}
- V
- pn {next,id,prop,val}
- V
- ...
- p1 {next,id,prop,val}
- V
- pn
- -->
- o {next,id,prop,val}
- V
- pn {next,id,prop,val}
- V
- p {next,id,prop,val}
- ...
- p1 {next,id,prop,val}
- V
- pn
- */
-
- VObject *tail = o->prop;
- if (tail) {
- p->next = tail->next;
- o->prop = tail->next = p;
- }
- else {
- o->prop = p->next = p;
- }
- return p;
-}
-
-DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
-{
- return addVObjectProp(o,newVObject(id));
-}
-
-DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
-{
- return addVObjectProp(o,newVObject_(id));
-}
-
-DLLEXPORT(void) addList(VObject **o, VObject *p)
-{
- p->next = 0;
- if (*o == 0) {
- *o = p;
- }
- else {
- VObject *t = *o;
- while (t->next) {
- t = t->next;
- }
- t->next = p;
- }
-}
-
-DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
-{
- return o->next;
-}
-
-DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
-{
- VObject *sizeProp;
- setVObjectAnyValue(prop, val);
- sizeProp = addProp(prop,VCDataSizeProp);
- setVObjectLongValue(sizeProp, size);
- return prop;
-}
-
-DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
-{
- void *p = dupStr((const char *)val,size);
- return setValueWithSize_(prop,p,p?size:0);
-}
-
-DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
-{
- i->start = o->prop;
- i->next = 0;
-}
-
-DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
-{
- i->start = o->next;
- i->next = 0;
-}
-
-DLLEXPORT(int) moreIteration(VObjectIterator *i)
-{
- return (i->start && (i->next==0 || i->next!=i->start));
-}
-
-DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
-{
- if (i->start && i->next != i->start) {
- if (i->next == 0) {
- i->next = i->start->next;
- return i->next;
- }
- else {
- i->next = i->next->next;
- return i->next;
- }
- }
- else return (VObject*)0;
-}
-
-DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
-{
- VObjectIterator i;
- initPropIterator(&i,o);
- while (moreIteration(&i)) {
- VObject *each = nextVObject(&i);
- if (!qstricmp(id,each->id))
- return each;
- }
- return (VObject*)0;
-}
-
-DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
-{
- /*
- a.b.c
- -->
- prop(c)
- prop(VCGrouping=b)
- prop(VCGrouping=a)
- */
- char *dot = strrchr(g,'.');
- if (dot) {
- VObject *p, *t;
- char *gs, *n = dot+1;
- gs = dupStr(g,0); /* so we can write to it. */
- /* used to be
- * t = p = addProp_(o,lookupProp_(n));
- */
- t = p = addProp_(o,lookupProp(n));
- dot = strrchr(gs,'.');
- *dot = 0;
- do {
- dot = strrchr(gs,'.');
- if (dot) {
- n = dot+1;
- *dot=0;
- }
- else
- n = gs;
- /* property(VCGroupingProp=n);
- * and the value may have VCGrouping property
- */
- t = addProp(t,VCGroupingProp);
- setVObjectStringZValue(t,lookupProp_(n));
- } while (n != gs);
- deleteStr(gs);
- return p;
- }
- else
- return addProp_(o,lookupProp(g));
-}
-
-DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
-{
- VObject *prop;
- prop = addProp(o,p);
- setVObjectStringZValue_(prop, strdup( v ) );
- return prop;
-}
-
-DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
- unsigned int size)
-{
- VObject *prop;
- prop = addProp(o,p);
- setValueWithSize_(prop, (void*)v, size);
- return prop;
-}
-
-DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
- unsigned int size)
-{
- return addPropSizedValue_(o,p,dupStr(v,size),size);
-}
-
-
-DLLEXPORT(void) cleanVObject(VObject *o)
-{
- if (o == 0) return;
- if (o->prop) {
- /* destroy time: cannot use the iterator here.
- Have to break the cycle in the circular link
- list and turns it into regular NULL-terminated
- list -- since at some point of destruction,
- the reference entry for the iterator to work
- will not longer be valid.
- */
- VObject *p;
- p = o->prop->next;
- o->prop->next = 0;
- do {
- VObject *t = p->next;
- cleanVObject(p);
- p = t;
- } while (p);
- }
- switch (VALUE_TYPE(o)) {
- case VCVT_STRINGZ:
- case VCVT_RAW:
- // assume they are all allocated by malloc.
- free((char*)STRINGZ_VALUE_OF(o));
- break;
- case VCVT_VOBJECT:
- cleanVObject(VOBJECT_VALUE_OF(o));
- break;
- }
- deleteVObject(o);
-}
-
-DLLEXPORT(void) cleanVObjects(VObject *list)
-{
- while (list) {
- VObject *t = list;
- list = nextVObjectInList(list);
- cleanVObject(t);
- }
-}
-
-/*----------------------------------------------------------------------
- The following is a String Table Facilities.
- ----------------------------------------------------------------------*/
-
-#define STRTBLSIZE 255
-
-static StrItem *strTbl[STRTBLSIZE];
-
-static unsigned int hashStr(const char *s)
-{
- unsigned int h = 0;
- int i;
- for (i=0;s[i];i++) {
- h += s[i]*i;
- }
- return h % STRTBLSIZE;
-}
-
-DLLEXPORT(const char*) lookupStr(const char *s)
-{
- StrItem *t;
- unsigned int h = hashStr(s);
- if ((t = strTbl[h]) != 0) {
- do {
- if (qstricmp(t->s,s) == 0) {
- t->refCnt++;
- return t->s;
- }
- t = t->next;
- } while (t);
- }
- s = dupStr(s,0);
- strTbl[h] = newStrItem(s,strTbl[h]);
- return s;
-}
-
-DLLEXPORT(void) unUseStr(const char *s)
-{
- StrItem *t, *p;
- unsigned int h = hashStr(s);
- if ((t = strTbl[h]) != 0) {
- p = t;
- do {
- if (qstricmp(t->s,s) == 0) {
- t->refCnt--;
- if (t->refCnt == 0) {
- if (p == strTbl[h]) {
- strTbl[h] = t->next;
- }
- else {
- p->next = t->next;
- }
- deleteStr(t->s);
- deleteStrItem(t);
- return;
- }
- }
- p = t;
- t = t->next;
- } while (t);
- }
-}
-
-DLLEXPORT(void) cleanStrTbl()
-{
- int i;
- for (i=0; i<STRTBLSIZE;i++) {
- StrItem *t = strTbl[i];
- while (t) {
- StrItem *p;
- deleteStr(t->s);
- p = t;
- t = t->next;
- deleteStrItem(p);
- } while (t);
- strTbl[i] = 0;
- }
-}
-
-
-struct PreDefProp {
- const char *name;
- const char *alias;
- const char** fields;
- unsigned int flags;
- };
-
-/* flags in PreDefProp */
-#define PD_BEGIN 0x1
-#define PD_INTERNAL 0x2
-
-static const char *adrFields[] = {
- VCPostalBoxProp,
- VCExtAddressProp,
- VCStreetAddressProp,
- VCCityProp,
- VCRegionProp,
- VCPostalCodeProp,
- VCCountryNameProp,
- 0
-};
-
-static const char *nameFields[] = {
- VCFamilyNameProp,
- VCGivenNameProp,
- VCAdditionalNamesProp,
- VCNamePrefixesProp,
- VCNameSuffixesProp,
- NULL
- };
-
-static const char *orgFields[] = {
- VCOrgNameProp,
- VCOrgUnitProp,
- VCOrgUnit2Prop,
- VCOrgUnit3Prop,
- VCOrgUnit4Prop,
- NULL
- };
-
-static const char *AAlarmFields[] = {
- VCRunTimeProp,
- VCSnoozeTimeProp,
- VCRepeatCountProp,
- VCAudioContentProp,
- 0
- };
-
-/* ExDate -- has unamed fields */
-/* RDate -- has unamed fields */
-
-static const char *DAlarmFields[] = {
- VCRunTimeProp,
- VCSnoozeTimeProp,
- VCRepeatCountProp,
- VCDisplayStringProp,
- 0
- };
-
-static const char *MAlarmFields[] = {
- VCRunTimeProp,
- VCSnoozeTimeProp,
- VCRepeatCountProp,
- VCEmailAddressProp,
- VCNoteProp,
- 0
- };
-
-static const char *PAlarmFields[] = {
- VCRunTimeProp,
- VCSnoozeTimeProp,
- VCRepeatCountProp,
- VCProcedureNameProp,
- 0
- };
-
-static struct PreDefProp propNames[] = {
- { VC7bitProp, 0, 0, 0 },
- { VC8bitProp, 0, 0, 0 },
- { VCAAlarmProp, 0, AAlarmFields, 0 },
- { VCAdditionalNamesProp, 0, 0, 0 },
- { VCAdrProp, 0, adrFields, 0 },
- { VCAgentProp, 0, 0, 0 },
- { VCAIFFProp, 0, 0, 0 },
- { VCAOLProp, 0, 0, 0 },
- { VCAppleLinkProp, 0, 0, 0 },
- { VCAttachProp, 0, 0, 0 },
- { VCAttendeeProp, 0, 0, 0 },
- { VCATTMailProp, 0, 0, 0 },
- { VCAudioContentProp, 0, 0, 0 },
- { VCAVIProp, 0, 0, 0 },
- { VCBase64Prop, 0, 0, 0 },
- { VCBBSProp, 0, 0, 0 },
- { VCBirthDateProp, 0, 0, 0 },
- { VCBMPProp, 0, 0, 0 },
- { VCBodyProp, 0, 0, 0 },
- { VCBusinessRoleProp, 0, 0, 0 },
- { VCCalProp, 0, 0, PD_BEGIN },
- { VCCaptionProp, 0, 0, 0 },
- { VCCardProp, 0, 0, PD_BEGIN },
- { VCCarProp, 0, 0, 0 },
- { VCCategoriesProp, 0, 0, 0 },
- { VCCellularProp, 0, 0, 0 },
- { VCCGMProp, 0, 0, 0 },
- { VCCharSetProp, 0, 0, 0 },
- { VCCIDProp, VCContentIDProp, 0, 0 },
- { VCCISProp, 0, 0, 0 },
- { VCCityProp, 0, 0, 0 },
- { VCClassProp, 0, 0, 0 },
- { VCCommentProp, 0, 0, 0 },
- { VCCompletedProp, 0, 0, 0 },
- { VCContentIDProp, 0, 0, 0 },
- { VCCountryNameProp, 0, 0, 0 },
- { VCDAlarmProp, 0, DAlarmFields, 0 },
- { VCDataSizeProp, 0, 0, PD_INTERNAL },
- { VCDayLightProp, 0, 0, 0 },
- { VCDCreatedProp, 0, 0, 0 },
- { VCDeliveryLabelProp, 0, 0, 0 },
- { VCDescriptionProp, 0, 0, 0 },
- { VCDIBProp, 0, 0, 0 },
- { VCDisplayStringProp, 0, 0, 0 },
- { VCDomesticProp, 0, 0, 0 },
- { VCDTendProp, 0, 0, 0 },
- { VCDTstartProp, 0, 0, 0 },
- { VCDueProp, 0, 0, 0 },
- { VCEmailAddressProp, 0, 0, 0 },
- { VCEncodingProp, 0, 0, 0 },
- { VCEndProp, 0, 0, 0 },
- { VCEventProp, 0, 0, PD_BEGIN },
- { VCEWorldProp, 0, 0, 0 },
- { VCExNumProp, 0, 0, 0 },
- { VCExpDateProp, 0, 0, 0 },
- { VCExpectProp, 0, 0, 0 },
- { VCExtAddressProp, 0, 0, 0 },
- { VCFamilyNameProp, 0, 0, 0 },
- { VCFaxProp, 0, 0, 0 },
- { VCFullNameProp, 0, 0, 0 },
- { VCGeoLocationProp, 0, 0, 0 },
- { VCGeoProp, 0, 0, 0 },
- { VCGIFProp, 0, 0, 0 },
- { VCGivenNameProp, 0, 0, 0 },
- { VCGroupingProp, 0, 0, 0 },
- { VCHomeProp, 0, 0, 0 },
- { VCIBMMailProp, 0, 0, 0 },
- { VCInlineProp, 0, 0, 0 },
- { VCInternationalProp, 0, 0, 0 },
- { VCInternetProp, 0, 0, 0 },
- { VCISDNProp, 0, 0, 0 },
- { VCJPEGProp, 0, 0, 0 },
- { VCLanguageProp, 0, 0, 0 },
- { VCLastModifiedProp, 0, 0, 0 },
- { VCLastRevisedProp, 0, 0, 0 },
- { VCLocationProp, 0, 0, 0 },
- { VCLogoProp, 0, 0, 0 },
- { VCMailerProp, 0, 0, 0 },
- { VCMAlarmProp, 0, MAlarmFields, 0 },
- { VCMCIMailProp, 0, 0, 0 },
- { VCMessageProp, 0, 0, 0 },
- { VCMETProp, 0, 0, 0 },
- { VCModemProp, 0, 0, 0 },
- { VCMPEG2Prop, 0, 0, 0 },
- { VCMPEGProp, 0, 0, 0 },
- { VCMSNProp, 0, 0, 0 },
- { VCNamePrefixesProp, 0, 0, 0 },
- { VCNameProp, 0, nameFields, 0 },
- { VCNameSuffixesProp, 0, 0, 0 },
- { VCNoteProp, 0, 0, 0 },
- { VCOrgNameProp, 0, 0, 0 },
- { VCOrgProp, 0, orgFields, 0 },
- { VCOrgUnit2Prop, 0, 0, 0 },
- { VCOrgUnit3Prop, 0, 0, 0 },
- { VCOrgUnit4Prop, 0, 0, 0 },
- { VCOrgUnitProp, 0, 0, 0 },
- { VCPagerProp, 0, 0, 0 },
- { VCPAlarmProp, 0, PAlarmFields, 0 },
- { VCParcelProp, 0, 0, 0 },
- { VCPartProp, 0, 0, 0 },
- { VCPCMProp, 0, 0, 0 },
- { VCPDFProp, 0, 0, 0 },
- { VCPGPProp, 0, 0, 0 },
- { VCPhotoProp, 0, 0, 0 },
- { VCPICTProp, 0, 0, 0 },
- { VCPMBProp, 0, 0, 0 },
- { VCPostalBoxProp, 0, 0, 0 },
- { VCPostalCodeProp, 0, 0, 0 },
- { VCPostalProp, 0, 0, 0 },
- { VCPowerShareProp, 0, 0, 0 },
- { VCPreferredProp, 0, 0, 0 },
- { VCPriorityProp, 0, 0, 0 },
- { VCProcedureNameProp, 0, 0, 0 },
- { VCProdIdProp, 0, 0, 0 },
- { VCProdigyProp, 0, 0, 0 },
- { VCPronunciationProp, 0, 0, 0 },
- { VCPSProp, 0, 0, 0 },
- { VCPublicKeyProp, 0, 0, 0 },
- { VCQPProp, VCQuotedPrintableProp, 0, 0 },
- { VCQuickTimeProp, 0, 0, 0 },
- { VCQuotedPrintableProp, 0, 0, 0 },
- { VCRDateProp, 0, 0, 0 },
- { VCRegionProp, 0, 0, 0 },
- { VCRelatedToProp, 0, 0, 0 },
- { VCRepeatCountProp, 0, 0, 0 },
- { VCResourcesProp, 0, 0, 0 },
- { VCRNumProp, 0, 0, 0 },
- { VCRoleProp, 0, 0, 0 },
- { VCRRuleProp, 0, 0, 0 },
- { VCRSVPProp, 0, 0, 0 },
- { VCRunTimeProp, 0, 0, 0 },
- { VCSequenceProp, 0, 0, 0 },
- { VCSnoozeTimeProp, 0, 0, 0 },
- { VCStartProp, 0, 0, 0 },
- { VCStatusProp, 0, 0, 0 },
- { VCStreetAddressProp, 0, 0, 0 },
- { VCSubTypeProp, 0, 0, 0 },
- { VCSummaryProp, 0, 0, 0 },
- { VCTelephoneProp, 0, 0, 0 },
- { VCTIFFProp, 0, 0, 0 },
- { VCTimeZoneProp, 0, 0, 0 },
- { VCTitleProp, 0, 0, 0 },
- { VCTLXProp, 0, 0, 0 },
- { VCTodoProp, 0, 0, PD_BEGIN },
- { VCTranspProp, 0, 0, 0 },
- { VCUniqueStringProp, 0, 0, 0 },
- { VCURLProp, 0, 0, 0 },
- { VCURLValueProp, 0, 0, 0 },
- { VCValueProp, 0, 0, 0 },
- { VCVersionProp, 0, 0, 0 },
- { VCVideoProp, 0, 0, 0 },
- { VCVoiceProp, 0, 0, 0 },
- { VCWAVEProp, 0, 0, 0 },
- { VCWMFProp, 0, 0, 0 },
- { VCWorkProp, 0, 0, 0 },
- { VCX400Prop, 0, 0, 0 },
- { VCX509Prop, 0, 0, 0 },
- { VCXRuleProp, 0, 0, 0 },
- { 0,0,0,0 }
- };
-
-
-static struct PreDefProp* lookupPropInfo(const char* str)
-{
- /* brute force for now, could use a hash table here. */
- int i;
-
- for (i = 0; propNames[i].name; i++)
- if (qstricmp(str, propNames[i].name) == 0) {
- return &propNames[i];
- }
-
- return 0;
-}
-
-
-DLLEXPORT(const char*) lookupProp_(const char* str)
-{
- int i;
-
- for (i = 0; propNames[i].name; i++)
- if (qstricmp(str, propNames[i].name) == 0) {
- const char* s;
- s = propNames[i].alias?propNames[i].alias:propNames[i].name;
- return lookupStr(s);
- }
- return lookupStr(str);
-}
-
-
-DLLEXPORT(const char*) lookupProp(const char* str)
-{
- int i;
-
- for (i = 0; propNames[i].name; i++)
- if (qstricmp(str, propNames[i].name) == 0) {
- const char *s;
- fieldedProp = propNames[i].fields;
- s = propNames[i].alias?propNames[i].alias:propNames[i].name;
- return lookupStr(s);
- }
- fieldedProp = 0;
- return lookupStr(str);
-}
-
-
-/*----------------------------------------------------------------------
- APIs to Output text form.
- ----------------------------------------------------------------------*/
-#define OFILE_REALLOC_SIZE 256
-typedef struct OFile {
- FILE *fp;
- char *s;
- int len;
- int limit;
- int alloc:1;
- int fail:1;
- } OFile;
-
-#if 0
-static void appendsOFile(OFile *fp, const char *s)
-{
- int slen;
- if (fp->fail) return;
- slen = strlen(s);
- if (fp->fp) {
- fwrite(s,1,slen,fp->fp);
- }
- else {
-stuff:
- if (fp->len + slen < fp->limit) {
- memcpy(fp->s+fp->len,s,slen);
- fp->len += slen;
- return;
- }
- else if (fp->alloc) {
- fp->limit = fp->limit + OFILE_REALLOC_SIZE;
- if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
- fp->s = (char *) realloc(fp->s,fp->limit);
- if (fp->s) goto stuff;
- }
- if (fp->alloc)
- free(fp->s);
- fp->s = 0;
- fp->fail = 1;
- }
-}
-
-static void appendcOFile(OFile *fp, char c)
-{
- if (fp->fail) return;
- if (fp->fp) {
- fputc(c,fp->fp);
- }
- else {
-stuff:
- if (fp->len+1 < fp->limit) {
- fp->s[fp->len] = c;
- fp->len++;
- return;
- }
- else if (fp->alloc) {
- fp->limit = fp->limit + OFILE_REALLOC_SIZE;
- fp->s = (char *) realloc(fp->s,fp->limit);
- if (fp->s) goto stuff;
- }
- if (fp->alloc)
- free(fp->s);
- fp->s = 0;
- fp->fail = 1;
- }
-}
-#else
-static void appendcOFile_(OFile *fp, char c)
-{
- if (fp->fail) return;
- if (fp->fp) {
- fputc(c,fp->fp);
- }
- else {
-stuff:
- if (fp->len+1 < fp->limit) {
- fp->s[fp->len] = c;
- fp->len++;
- return;
- }
- else if (fp->alloc) {
- fp->limit = fp->limit + OFILE_REALLOC_SIZE;
- fp->s = (char *)realloc(fp->s,fp->limit);
- if (fp->s) goto stuff;
- }
- if (fp->alloc)
- free(fp->s);
- fp->s = 0;
- fp->fail = 1;
- }
-}
-
-static void appendcOFile(OFile *fp, char c)
-{
- if (c == '\n') {
- /* write out as <CR><LF> */
- appendcOFile_(fp,0xd);
- appendcOFile_(fp,0xa);
- }
- else
- appendcOFile_(fp,c);
-}
-
-static void appendsOFile(OFile *fp, const char *s)
-{
- int i, slen;
- slen = strlen(s);
- for (i=0; i<slen; i++) {
- appendcOFile(fp,s[i]);
- }
-}
-
-#endif
-
-static void initOFile(OFile *fp, FILE *ofp)
-{
- fp->fp = ofp;
- fp->s = 0;
- fp->len = 0;
- fp->limit = 0;
- fp->alloc = 0;
- fp->fail = 0;
-}
-
-static int writeBase64(OFile *fp, unsigned char *s, long len)
-{
- long cur = 0;
- int i, numQuads = 0;
- unsigned long trip;
- unsigned char b;
- char quad[5];
-#define MAXQUADS 16
-
- quad[4] = 0;
-
- while (cur < len) {
- // collect the triplet of bytes into 'trip'
- trip = 0;
- for (i = 0; i < 3; i++) {
- b = (cur < len) ? *(s + cur) : 0;
- cur++;
- trip = trip << 8 | b;
- }
- // fill in 'quad' with the appropriate four characters
- for (i = 3; i >= 0; i--) {
- b = (unsigned char)(trip & 0x3F);
- trip = trip >> 6;
- if ((3 - i) < (cur - len))
- quad[i] = '='; // pad char
- else if (b < 26) quad[i] = (char)b + 'A';
- else if (b < 52) quad[i] = (char)(b - 26) + 'a';
- else if (b < 62) quad[i] = (char)(b - 52) + '0';
- else if (b == 62) quad[i] = '+';
- else quad[i] = '/';
- }
- // now output 'quad' with appropriate whitespace and line ending
- appendsOFile(fp, (numQuads == 0 ? " " : ""));
- appendsOFile(fp, quad);
- appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
- numQuads = (numQuads + 1) % MAXQUADS;
- }
- appendcOFile(fp,'\n');
-
- return 1;
-}
-
-static void writeQPString(OFile *fp, const char *s)
-{
- const char *p = s;
- while (*p) {
- if (*p == '\n') {
- if (p[1]) appendsOFile(fp,"=0A=");
- }
- appendcOFile(fp,*p);
- p++;
- }
-}
-
-
-
-static void writeVObject_(OFile *fp, VObject *o);
-
-static void writeValue(OFile *fp, VObject *o, unsigned long size)
-{
- if (o == 0) return;
- switch (VALUE_TYPE(o)) {
- case VCVT_STRINGZ: {
- writeQPString(fp, STRINGZ_VALUE_OF(o));
- break;
- }
- case VCVT_UINT: {
- char buf[16];
- sprintf(buf,"%u", INTEGER_VALUE_OF(o));
- appendsOFile(fp,buf);
- break;
- }
- case VCVT_ULONG: {
- char buf[16];
- sprintf(buf,"%lu", LONG_VALUE_OF(o));
- appendsOFile(fp,buf);
- break;
- }
- case VCVT_RAW: {
- appendcOFile(fp,'\n');
- writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
- break;
- }
- case VCVT_VOBJECT:
- appendcOFile(fp,'\n');
- writeVObject_(fp,VOBJECT_VALUE_OF(o));
- break;
- }
-}
-
-static void writeAttrValue(OFile *fp, VObject *o)
-{
- if (NAME_OF(o)) {
- struct PreDefProp *pi;
- pi = lookupPropInfo(NAME_OF(o));
- if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
- appendcOFile(fp,';');
- appendsOFile(fp,NAME_OF(o));
- }
- else
- appendcOFile(fp,';');
- if (VALUE_TYPE(o)) {
- appendcOFile(fp,'=');
- writeValue(fp,o,0);
- }
-}
-
-static void writeGroup(OFile *fp, VObject *o)
-{
- char buf1[256];
- char buf2[256];
- strcpy(buf1,NAME_OF(o));
- while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
- strcpy(buf2,STRINGZ_VALUE_OF(o));
- strcat(buf2,".");
- strcat(buf2,buf1);
- strcpy(buf1,buf2);
- }
- appendsOFile(fp,buf1);
-}
-
-static int inList(const char **list, const char *s)
-{
- if (list == 0) return 0;
- while (*list) {
- if (qstricmp(*list,s) == 0) return 1;
- list++;
- }
- return 0;
-}
-
-static void writeProp(OFile *fp, VObject *o)
-{
- if (NAME_OF(o)) {
- struct PreDefProp *pi;
- VObjectIterator t;
- const char **fields_ = 0;
- pi = lookupPropInfo(NAME_OF(o));
- if (pi && ((pi->flags & PD_BEGIN) != 0)) {
- writeVObject_(fp,o);
- return;
- }
- if (isAPropertyOf(o,VCGroupingProp))
- writeGroup(fp,o);
- else
- appendsOFile(fp,NAME_OF(o));
- if (pi) fields_ = pi->fields;
- initPropIterator(&t,o);
- while (moreIteration(&t)) {
- const char *s;
- VObject *eachProp = nextVObject(&t);
- s = NAME_OF(eachProp);
- if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
- writeAttrValue(fp,eachProp);
- }
- if (fields_) {
- int i = 0, n = 0;
- const char** fields = fields_;
- /* output prop as fields */
- appendcOFile(fp,':');
- while (*fields) {
- VObject *t = isAPropertyOf(o,*fields);
- i++;
- if (t) n = i;
- fields++;
- }
- fields = fields_;
- for (i=0;i<n;i++) {
- writeValue(fp,isAPropertyOf(o,*fields),0);
- fields++;
- if (i<(n-1)) appendcOFile(fp,';');
- }
- }
- }
-
- if (VALUE_TYPE(o)) {
- unsigned long size = 0;
- VObject *p = isAPropertyOf(o,VCDataSizeProp);
- if (p) size = LONG_VALUE_OF(p);
- appendcOFile(fp,':');
- writeValue(fp,o,size);
- }
-
- appendcOFile(fp,'\n');
-}
-
-static void writeVObject_(OFile *fp, VObject *o)
-{
- if (NAME_OF(o)) {
- struct PreDefProp *pi;
- pi = lookupPropInfo(NAME_OF(o));
-
- if (pi && ((pi->flags & PD_BEGIN) != 0)) {
- VObjectIterator t;
- const char *begin = NAME_OF(o);
- appendsOFile(fp,"BEGIN:");
- appendsOFile(fp,begin);
- appendcOFile(fp,'\n');
- initPropIterator(&t,o);
- while (moreIteration(&t)) {
- VObject *eachProp = nextVObject(&t);
- writeProp(fp, eachProp);
- }
- appendsOFile(fp,"END:");
- appendsOFile(fp,begin);
- appendsOFile(fp,"\n\n");
- }
- }
-}
-
-void writeVObject(FILE *fp, VObject *o)
-{
- OFile ofp;
- // #####
- //_setmode(_fileno(fp), _O_BINARY);
- initOFile(&ofp,fp);
- writeVObject_(&ofp,o);
-}
-
-DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
-{
- QFileDirect f( fname);
- if ( !f.open( IO_WriteOnly ) ) {
- qWarning("Unable to open vobject write %s", fname);
- return;
- }
-
- writeVObject( f.directHandle(),o );
-}
-
-DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
-{
- QFileDirect f( fname);
- if ( !f.open( IO_WriteOnly ) ) {
- qWarning("Unable to open vobject write %s", fname);
- return;
- }
-
- while (list) {
- writeVObject(f.directHandle(),list);
- list = nextVObjectInList(list);
- }
-}
-
-DLLEXPORT(const char *) vObjectTypeInfo(VObject *o)
-{
- const char *type = vObjectName( o );
- if ( strcmp( type, "TYPE" ) == 0 )
- type = vObjectStringZValue( o );
- return type;
-}
-
-
-// end of source file vobject.c
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+ * src: vobject.c
+ * doc: vobject and APIs to construct vobject, APIs pretty print
+ * vobject, and convert a vobject into its textual representation.
+ */
+
+#ifndef MWERKS
+#include <malloc.h>
+#endif
+
+#include "vobject_p.h"
+#include "qfiledirect_p.h"
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+//#include <io.h>
+
+
+#define NAME_OF(o) o->id
+#define VALUE_TYPE(o) o->valType
+#define STRINGZ_VALUE_OF(o) o->val.strs
+#define INTEGER_VALUE_OF(o) o->val.i
+#define LONG_VALUE_OF(o) o->val.l
+#define ANY_VALUE_OF(o) o->val.any
+#define VOBJECT_VALUE_OF(o) o->val.vobj
+
+typedef union ValueItem {
+ const char *strs;
+ unsigned int i;
+ unsigned long l;
+ void *any;
+ VObject *vobj;
+ } ValueItem;
+
+struct VObject {
+ VObject *next;
+ const char *id;
+ VObject *prop;
+ unsigned short valType;
+ ValueItem val;
+ };
+
+typedef struct StrItem StrItem;
+
+struct StrItem {
+ StrItem *next;
+ const char *s;
+ unsigned int refCnt;
+ };
+
+const char** fieldedProp;
+
+
+
+/*----------------------------------------------------------------------
+ The following functions involve with memory allocation:
+ newVObject
+ deleteVObject
+ dupStr
+ deleteStr
+ newStrItem
+ deleteStrItem
+ ----------------------------------------------------------------------*/
+
+DLLEXPORT(VObject*) newVObject_(const char *id)
+{
+ VObject *p = (VObject*)malloc(sizeof(VObject));
+ p->next = 0;
+ p->id = id;
+ p->prop = 0;
+ VALUE_TYPE(p) = 0;
+ ANY_VALUE_OF(p) = 0;
+ return p;
+}
+
+DLLEXPORT(VObject*) newVObject(const char *id)
+{
+ return newVObject_(lookupStr(id));
+}
+
+DLLEXPORT(void) deleteVObject(VObject *p)
+{
+ unUseStr(p->id);
+ free(p);
+}
+
+DLLEXPORT(char*) dupStr(const char *s, unsigned int size)
+{
+ char *t;
+ if (size == 0) {
+ size = strlen(s);
+ }
+ t = (char*)malloc(size+1);
+ if (t) {
+ memcpy(t,s,size);
+ t[size] = 0;
+ return t;
+ }
+ else {
+ return (char*)0;
+ }
+}
+
+DLLEXPORT(void) deleteStr(const char *p)
+{
+ if (p) free((void*)p);
+}
+
+
+static StrItem* newStrItem(const char *s, StrItem *next)
+{
+ StrItem *p = (StrItem*)malloc(sizeof(StrItem));
+ p->next = next;
+ p->s = s;
+ p->refCnt = 1;
+ return p;
+}
+
+static void deleteStrItem(StrItem *p)
+{
+ free((void*)p);
+}
+
+
+/*----------------------------------------------------------------------
+ The following function provide accesses to VObject's value.
+ ----------------------------------------------------------------------*/
+
+DLLEXPORT(const char*) vObjectName(VObject *o)
+{
+ return NAME_OF(o);
+}
+
+DLLEXPORT(void) setVObjectName(VObject *o, const char* id)
+{
+ NAME_OF(o) = id;
+}
+
+DLLEXPORT(const char*) vObjectStringZValue(VObject *o)
+{
+ return STRINGZ_VALUE_OF(o);
+}
+
+DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s)
+{
+ STRINGZ_VALUE_OF(o) = dupStr(s,0);
+ VALUE_TYPE(o) = VCVT_STRINGZ;
+}
+
+DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s)
+{
+ STRINGZ_VALUE_OF(o) = s;
+ VALUE_TYPE(o) = VCVT_STRINGZ;
+}
+
+DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o)
+{
+ return INTEGER_VALUE_OF(o);
+}
+
+DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i)
+{
+ INTEGER_VALUE_OF(o) = i;
+ VALUE_TYPE(o) = VCVT_UINT;
+}
+
+DLLEXPORT(unsigned long) vObjectLongValue(VObject *o)
+{
+ return LONG_VALUE_OF(o);
+}
+
+DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l)
+{
+ LONG_VALUE_OF(o) = l;
+ VALUE_TYPE(o) = VCVT_ULONG;
+}
+
+DLLEXPORT(void*) vObjectAnyValue(VObject *o)
+{
+ return ANY_VALUE_OF(o);
+}
+
+DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t)
+{
+ ANY_VALUE_OF(o) = t;
+ VALUE_TYPE(o) = VCVT_RAW;
+}
+
+DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o)
+{
+ return VOBJECT_VALUE_OF(o);
+}
+
+DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p)
+{
+ VOBJECT_VALUE_OF(o) = p;
+ VALUE_TYPE(o) = VCVT_VOBJECT;
+}
+
+DLLEXPORT(int) vObjectValueType(VObject *o)
+{
+ return VALUE_TYPE(o);
+}
+
+
+/*----------------------------------------------------------------------
+ The following functions can be used to build VObject.
+ ----------------------------------------------------------------------*/
+
+DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p)
+{
+ /* circular link list pointed to tail */
+ /*
+ o {next,id,prop,val}
+ V
+ pn {next,id,prop,val}
+ V
+ ...
+ p1 {next,id,prop,val}
+ V
+ pn
+ -->
+ o {next,id,prop,val}
+ V
+ pn {next,id,prop,val}
+ V
+ p {next,id,prop,val}
+ ...
+ p1 {next,id,prop,val}
+ V
+ pn
+ */
+
+ VObject *tail = o->prop;
+ if (tail) {
+ p->next = tail->next;
+ o->prop = tail->next = p;
+ }
+ else {
+ o->prop = p->next = p;
+ }
+ return p;
+}
+
+DLLEXPORT(VObject*) addProp(VObject *o, const char *id)
+{
+ return addVObjectProp(o,newVObject(id));
+}
+
+DLLEXPORT(VObject*) addProp_(VObject *o, const char *id)
+{
+ return addVObjectProp(o,newVObject_(id));
+}
+
+DLLEXPORT(void) addList(VObject **o, VObject *p)
+{
+ p->next = 0;
+ if (*o == 0) {
+ *o = p;
+ }
+ else {
+ VObject *t = *o;
+ while (t->next) {
+ t = t->next;
+ }
+ t->next = p;
+ }
+}
+
+DLLEXPORT(VObject*) nextVObjectInList(VObject *o)
+{
+ return o->next;
+}
+
+DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size)
+{
+ VObject *sizeProp;
+ setVObjectAnyValue(prop, val);
+ sizeProp = addProp(prop,VCDataSizeProp);
+ setVObjectLongValue(sizeProp, size);
+ return prop;
+}
+
+DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size)
+{
+ void *p = dupStr((const char *)val,size);
+ return setValueWithSize_(prop,p,p?size:0);
+}
+
+DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o)
+{
+ i->start = o->prop;
+ i->next = 0;
+}
+
+DLLEXPORT(void) initVObjectIterator(VObjectIterator *i, VObject *o)
+{
+ i->start = o->next;
+ i->next = 0;
+}
+
+DLLEXPORT(int) moreIteration(VObjectIterator *i)
+{
+ return (i->start && (i->next==0 || i->next!=i->start));
+}
+
+DLLEXPORT(VObject*) nextVObject(VObjectIterator *i)
+{
+ if (i->start && i->next != i->start) {
+ if (i->next == 0) {
+ i->next = i->start->next;
+ return i->next;
+ }
+ else {
+ i->next = i->next->next;
+ return i->next;
+ }
+ }
+ else return (VObject*)0;
+}
+
+DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id)
+{
+ VObjectIterator i;
+ initPropIterator(&i,o);
+ while (moreIteration(&i)) {
+ VObject *each = nextVObject(&i);
+ if (!qstricmp(id,each->id))
+ return each;
+ }
+ return (VObject*)0;
+}
+
+DLLEXPORT(VObject*) addGroup(VObject *o, const char *g)
+{
+ /*
+ a.b.c
+ -->
+ prop(c)
+ prop(VCGrouping=b)
+ prop(VCGrouping=a)
+ */
+ char *dot = strrchr(g,'.');
+ if (dot) {
+ VObject *p, *t;
+ char *gs, *n = dot+1;
+ gs = dupStr(g,0); /* so we can write to it. */
+ /* used to be
+ * t = p = addProp_(o,lookupProp_(n));
+ */
+ t = p = addProp_(o,lookupProp(n));
+ dot = strrchr(gs,'.');
+ *dot = 0;
+ do {
+ dot = strrchr(gs,'.');
+ if (dot) {
+ n = dot+1;
+ *dot=0;
+ }
+ else
+ n = gs;
+ /* property(VCGroupingProp=n);
+ * and the value may have VCGrouping property
+ */
+ t = addProp(t,VCGroupingProp);
+ setVObjectStringZValue(t,lookupProp_(n));
+ } while (n != gs);
+ deleteStr(gs);
+ return p;
+ }
+ else
+ return addProp_(o,lookupProp(g));
+}
+
+DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v)
+{
+ VObject *prop;
+ prop = addProp(o,p);
+ setVObjectStringZValue_(prop, strdup( v ) );
+ return prop;
+}
+
+DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v,
+ unsigned int size)
+{
+ VObject *prop;
+ prop = addProp(o,p);
+ setValueWithSize_(prop, (void*)v, size);
+ return prop;
+}
+
+DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v,
+ unsigned int size)
+{
+ return addPropSizedValue_(o,p,dupStr(v,size),size);
+}
+
+
+DLLEXPORT(void) cleanVObject(VObject *o)
+{
+ if (o == 0) return;
+ if (o->prop) {
+ /* destroy time: cannot use the iterator here.
+ Have to break the cycle in the circular link
+ list and turns it into regular NULL-terminated
+ list -- since at some point of destruction,
+ the reference entry for the iterator to work
+ will not longer be valid.
+ */
+ VObject *p;
+ p = o->prop->next;
+ o->prop->next = 0;
+ do {
+ VObject *t = p->next;
+ cleanVObject(p);
+ p = t;
+ } while (p);
+ }
+ switch (VALUE_TYPE(o)) {
+ case VCVT_STRINGZ:
+ case VCVT_RAW:
+ // assume they are all allocated by malloc.
+ free((char*)STRINGZ_VALUE_OF(o));
+ break;
+ case VCVT_VOBJECT:
+ cleanVObject(VOBJECT_VALUE_OF(o));
+ break;
+ }
+ deleteVObject(o);
+}
+
+DLLEXPORT(void) cleanVObjects(VObject *list)
+{
+ while (list) {
+ VObject *t = list;
+ list = nextVObjectInList(list);
+ cleanVObject(t);
+ }
+}
+
+/*----------------------------------------------------------------------
+ The following is a String Table Facilities.
+ ----------------------------------------------------------------------*/
+
+#define STRTBLSIZE 255
+
+static StrItem *strTbl[STRTBLSIZE];
+
+static unsigned int hashStr(const char *s)
+{
+ unsigned int h = 0;
+ int i;
+ for (i=0;s[i];i++) {
+ h += s[i]*i;
+ }
+ return h % STRTBLSIZE;
+}
+
+DLLEXPORT(const char*) lookupStr(const char *s)
+{
+ StrItem *t;
+ unsigned int h = hashStr(s);
+ if ((t = strTbl[h]) != 0) {
+ do {
+ if (qstricmp(t->s,s) == 0) {
+ t->refCnt++;
+ return t->s;
+ }
+ t = t->next;
+ } while (t);
+ }
+ s = dupStr(s,0);
+ strTbl[h] = newStrItem(s,strTbl[h]);
+ return s;
+}
+
+DLLEXPORT(void) unUseStr(const char *s)
+{
+ StrItem *t, *p;
+ unsigned int h = hashStr(s);
+ if ((t = strTbl[h]) != 0) {
+ p = t;
+ do {
+ if (qstricmp(t->s,s) == 0) {
+ t->refCnt--;
+ if (t->refCnt == 0) {
+ if (p == strTbl[h]) {
+ strTbl[h] = t->next;
+ }
+ else {
+ p->next = t->next;
+ }
+ deleteStr(t->s);
+ deleteStrItem(t);
+ return;
+ }
+ }
+ p = t;
+ t = t->next;
+ } while (t);
+ }
+}
+
+DLLEXPORT(void) cleanStrTbl()
+{
+ int i;
+ for (i=0; i<STRTBLSIZE;i++) {
+ StrItem *t = strTbl[i];
+ while (t) {
+ StrItem *p;
+ deleteStr(t->s);
+ p = t;
+ t = t->next;
+ deleteStrItem(p);
+ } while (t);
+ strTbl[i] = 0;
+ }
+}
+
+
+struct PreDefProp {
+ const char *name;
+ const char *alias;
+ const char** fields;
+ unsigned int flags;
+ };
+
+/* flags in PreDefProp */
+#define PD_BEGIN 0x1
+#define PD_INTERNAL 0x2
+
+static const char *adrFields[] = {
+ VCPostalBoxProp,
+ VCExtAddressProp,
+ VCStreetAddressProp,
+ VCCityProp,
+ VCRegionProp,
+ VCPostalCodeProp,
+ VCCountryNameProp,
+ 0
+};
+
+static const char *nameFields[] = {
+ VCFamilyNameProp,
+ VCGivenNameProp,
+ VCAdditionalNamesProp,
+ VCNamePrefixesProp,
+ VCNameSuffixesProp,
+ NULL
+ };
+
+static const char *orgFields[] = {
+ VCOrgNameProp,
+ VCOrgUnitProp,
+ VCOrgUnit2Prop,
+ VCOrgUnit3Prop,
+ VCOrgUnit4Prop,
+ NULL
+ };
+
+static const char *AAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCAudioContentProp,
+ 0
+ };
+
+/* ExDate -- has unamed fields */
+/* RDate -- has unamed fields */
+
+static const char *DAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCDisplayStringProp,
+ 0
+ };
+
+static const char *MAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCEmailAddressProp,
+ VCNoteProp,
+ 0
+ };
+
+static const char *PAlarmFields[] = {
+ VCRunTimeProp,
+ VCSnoozeTimeProp,
+ VCRepeatCountProp,
+ VCProcedureNameProp,
+ 0
+ };
+
+static struct PreDefProp propNames[] = {
+ { VC7bitProp, 0, 0, 0 },
+ { VC8bitProp, 0, 0, 0 },
+ { VCAAlarmProp, 0, AAlarmFields, 0 },
+ { VCAdditionalNamesProp, 0, 0, 0 },
+ { VCAdrProp, 0, adrFields, 0 },
+ { VCAgentProp, 0, 0, 0 },
+ { VCAIFFProp, 0, 0, 0 },
+ { VCAOLProp, 0, 0, 0 },
+ { VCAppleLinkProp, 0, 0, 0 },
+ { VCAttachProp, 0, 0, 0 },
+ { VCAttendeeProp, 0, 0, 0 },
+ { VCATTMailProp, 0, 0, 0 },
+ { VCAudioContentProp, 0, 0, 0 },
+ { VCAVIProp, 0, 0, 0 },
+ { VCBase64Prop, 0, 0, 0 },
+ { VCBBSProp, 0, 0, 0 },
+ { VCBirthDateProp, 0, 0, 0 },
+ { VCBMPProp, 0, 0, 0 },
+ { VCBodyProp, 0, 0, 0 },
+ { VCBusinessRoleProp, 0, 0, 0 },
+ { VCCalProp, 0, 0, PD_BEGIN },
+ { VCCaptionProp, 0, 0, 0 },
+ { VCCardProp, 0, 0, PD_BEGIN },
+ { VCCarProp, 0, 0, 0 },
+ { VCCategoriesProp, 0, 0, 0 },
+ { VCCellularProp, 0, 0, 0 },
+ { VCCGMProp, 0, 0, 0 },
+ { VCCharSetProp, 0, 0, 0 },
+ { VCCIDProp, VCContentIDProp, 0, 0 },
+ { VCCISProp, 0, 0, 0 },
+ { VCCityProp, 0, 0, 0 },
+ { VCClassProp, 0, 0, 0 },
+ { VCCommentProp, 0, 0, 0 },
+ { VCCompletedProp, 0, 0, 0 },
+ { VCContentIDProp, 0, 0, 0 },
+ { VCCountryNameProp, 0, 0, 0 },
+ { VCDAlarmProp, 0, DAlarmFields, 0 },
+ { VCDataSizeProp, 0, 0, PD_INTERNAL },
+ { VCDayLightProp, 0, 0, 0 },
+ { VCDCreatedProp, 0, 0, 0 },
+ { VCDeliveryLabelProp, 0, 0, 0 },
+ { VCDescriptionProp, 0, 0, 0 },
+ { VCDIBProp, 0, 0, 0 },
+ { VCDisplayStringProp, 0, 0, 0 },
+ { VCDomesticProp, 0, 0, 0 },
+ { VCDTendProp, 0, 0, 0 },
+ { VCDTstartProp, 0, 0, 0 },
+ { VCDueProp, 0, 0, 0 },
+ { VCEmailAddressProp, 0, 0, 0 },
+ { VCEncodingProp, 0, 0, 0 },
+ { VCEndProp, 0, 0, 0 },
+ { VCEventProp, 0, 0, PD_BEGIN },
+ { VCEWorldProp, 0, 0, 0 },
+ { VCExNumProp, 0, 0, 0 },
+ { VCExpDateProp, 0, 0, 0 },
+ { VCExpectProp, 0, 0, 0 },
+ { VCExtAddressProp, 0, 0, 0 },
+ { VCFamilyNameProp, 0, 0, 0 },
+ { VCFaxProp, 0, 0, 0 },
+ { VCFullNameProp, 0, 0, 0 },
+ { VCGeoLocationProp, 0, 0, 0 },
+ { VCGeoProp, 0, 0, 0 },
+ { VCGIFProp, 0, 0, 0 },
+ { VCGivenNameProp, 0, 0, 0 },
+ { VCGroupingProp, 0, 0, 0 },
+ { VCHomeProp, 0, 0, 0 },
+ { VCIBMMailProp, 0, 0, 0 },
+ { VCInlineProp, 0, 0, 0 },
+ { VCInternationalProp, 0, 0, 0 },
+ { VCInternetProp, 0, 0, 0 },
+ { VCISDNProp, 0, 0, 0 },
+ { VCJPEGProp, 0, 0, 0 },
+ { VCLanguageProp, 0, 0, 0 },
+ { VCLastModifiedProp, 0, 0, 0 },
+ { VCLastRevisedProp, 0, 0, 0 },
+ { VCLocationProp, 0, 0, 0 },
+ { VCLogoProp, 0, 0, 0 },
+ { VCMailerProp, 0, 0, 0 },
+ { VCMAlarmProp, 0, MAlarmFields, 0 },
+ { VCMCIMailProp, 0, 0, 0 },
+ { VCMessageProp, 0, 0, 0 },
+ { VCMETProp, 0, 0, 0 },
+ { VCModemProp, 0, 0, 0 },
+ { VCMPEG2Prop, 0, 0, 0 },
+ { VCMPEGProp, 0, 0, 0 },
+ { VCMSNProp, 0, 0, 0 },
+ { VCNamePrefixesProp, 0, 0, 0 },
+ { VCNameProp, 0, nameFields, 0 },
+ { VCNameSuffixesProp, 0, 0, 0 },
+ { VCNoteProp, 0, 0, 0 },
+ { VCOrgNameProp, 0, 0, 0 },
+ { VCOrgProp, 0, orgFields, 0 },
+ { VCOrgUnit2Prop, 0, 0, 0 },
+ { VCOrgUnit3Prop, 0, 0, 0 },
+ { VCOrgUnit4Prop, 0, 0, 0 },
+ { VCOrgUnitProp, 0, 0, 0 },
+ { VCPagerProp, 0, 0, 0 },
+ { VCPAlarmProp, 0, PAlarmFields, 0 },
+ { VCParcelProp, 0, 0, 0 },
+ { VCPartProp, 0, 0, 0 },
+ { VCPCMProp, 0, 0, 0 },
+ { VCPDFProp, 0, 0, 0 },
+ { VCPGPProp, 0, 0, 0 },
+ { VCPhotoProp, 0, 0, 0 },
+ { VCPICTProp, 0, 0, 0 },
+ { VCPMBProp, 0, 0, 0 },
+ { VCPostalBoxProp, 0, 0, 0 },
+ { VCPostalCodeProp, 0, 0, 0 },
+ { VCPostalProp, 0, 0, 0 },
+ { VCPowerShareProp, 0, 0, 0 },
+ { VCPreferredProp, 0, 0, 0 },
+ { VCPriorityProp, 0, 0, 0 },
+ { VCProcedureNameProp, 0, 0, 0 },
+ { VCProdIdProp, 0, 0, 0 },
+ { VCProdigyProp, 0, 0, 0 },
+ { VCPronunciationProp, 0, 0, 0 },
+ { VCPSProp, 0, 0, 0 },
+ { VCPublicKeyProp, 0, 0, 0 },
+ { VCQPProp, VCQuotedPrintableProp, 0, 0 },
+ { VCQuickTimeProp, 0, 0, 0 },
+ { VCQuotedPrintableProp, 0, 0, 0 },
+ { VCRDateProp, 0, 0, 0 },
+ { VCRegionProp, 0, 0, 0 },
+ { VCRelatedToProp, 0, 0, 0 },
+ { VCRepeatCountProp, 0, 0, 0 },
+ { VCResourcesProp, 0, 0, 0 },
+ { VCRNumProp, 0, 0, 0 },
+ { VCRoleProp, 0, 0, 0 },
+ { VCRRuleProp, 0, 0, 0 },
+ { VCRSVPProp, 0, 0, 0 },
+ { VCRunTimeProp, 0, 0, 0 },
+ { VCSequenceProp, 0, 0, 0 },
+ { VCSnoozeTimeProp, 0, 0, 0 },
+ { VCStartProp, 0, 0, 0 },
+ { VCStatusProp, 0, 0, 0 },
+ { VCStreetAddressProp, 0, 0, 0 },
+ { VCSubTypeProp, 0, 0, 0 },
+ { VCSummaryProp, 0, 0, 0 },
+ { VCTelephoneProp, 0, 0, 0 },
+ { VCTIFFProp, 0, 0, 0 },
+ { VCTimeZoneProp, 0, 0, 0 },
+ { VCTitleProp, 0, 0, 0 },
+ { VCTLXProp, 0, 0, 0 },
+ { VCTodoProp, 0, 0, PD_BEGIN },
+ { VCTranspProp, 0, 0, 0 },
+ { VCUniqueStringProp, 0, 0, 0 },
+ { VCURLProp, 0, 0, 0 },
+ { VCURLValueProp, 0, 0, 0 },
+ { VCValueProp, 0, 0, 0 },
+ { VCVersionProp, 0, 0, 0 },
+ { VCVideoProp, 0, 0, 0 },
+ { VCVoiceProp, 0, 0, 0 },
+ { VCWAVEProp, 0, 0, 0 },
+ { VCWMFProp, 0, 0, 0 },
+ { VCWorkProp, 0, 0, 0 },
+ { VCX400Prop, 0, 0, 0 },
+ { VCX509Prop, 0, 0, 0 },
+ { VCXRuleProp, 0, 0, 0 },
+ { 0,0,0,0 }
+ };
+
+
+static struct PreDefProp* lookupPropInfo(const char* str)
+{
+ /* brute force for now, could use a hash table here. */
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (qstricmp(str, propNames[i].name) == 0) {
+ return &propNames[i];
+ }
+
+ return 0;
+}
+
+
+DLLEXPORT(const char*) lookupProp_(const char* str)
+{
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (qstricmp(str, propNames[i].name) == 0) {
+ const char* s;
+ s = propNames[i].alias?propNames[i].alias:propNames[i].name;
+ return lookupStr(s);
+ }
+ return lookupStr(str);
+}
+
+
+DLLEXPORT(const char*) lookupProp(const char* str)
+{
+ int i;
+
+ for (i = 0; propNames[i].name; i++)
+ if (qstricmp(str, propNames[i].name) == 0) {
+ const char *s;
+ fieldedProp = propNames[i].fields;
+ s = propNames[i].alias?propNames[i].alias:propNames[i].name;
+ return lookupStr(s);
+ }
+ fieldedProp = 0;
+ return lookupStr(str);
+}
+
+
+/*----------------------------------------------------------------------
+ APIs to Output text form.
+ ----------------------------------------------------------------------*/
+#define OFILE_REALLOC_SIZE 256
+typedef struct OFile {
+ FILE *fp;
+ char *s;
+ int len;
+ int limit;
+ int alloc:1;
+ int fail:1;
+ } OFile;
+
+#if 0
+static void appendsOFile(OFile *fp, const char *s)
+{
+ int slen;
+ if (fp->fail) return;
+ slen = strlen(s);
+ if (fp->fp) {
+ fwrite(s,1,slen,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len + slen < fp->limit) {
+ memcpy(fp->s+fp->len,s,slen);
+ fp->len += slen;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ if (OFILE_REALLOC_SIZE <= slen) fp->limit += slen;
+ fp->s = (char *) realloc(fp->s,fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+
+static void appendcOFile(OFile *fp, char c)
+{
+ if (fp->fail) return;
+ if (fp->fp) {
+ fputc(c,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len+1 < fp->limit) {
+ fp->s[fp->len] = c;
+ fp->len++;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ fp->s = (char *) realloc(fp->s,fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+#else
+static void appendcOFile_(OFile *fp, char c)
+{
+ if (fp->fail) return;
+ if (fp->fp) {
+ fputc(c,fp->fp);
+ }
+ else {
+stuff:
+ if (fp->len+1 < fp->limit) {
+ fp->s[fp->len] = c;
+ fp->len++;
+ return;
+ }
+ else if (fp->alloc) {
+ fp->limit = fp->limit + OFILE_REALLOC_SIZE;
+ fp->s = (char *)realloc(fp->s,fp->limit);
+ if (fp->s) goto stuff;
+ }
+ if (fp->alloc)
+ free(fp->s);
+ fp->s = 0;
+ fp->fail = 1;
+ }
+}
+
+static void appendcOFile(OFile *fp, char c)
+{
+ if (c == '\n') {
+ /* write out as <CR><LF> */
+ appendcOFile_(fp,0xd);
+ appendcOFile_(fp,0xa);
+ }
+ else
+ appendcOFile_(fp,c);
+}
+
+static void appendsOFile(OFile *fp, const char *s)
+{
+ int i, slen;
+ slen = strlen(s);
+ for (i=0; i<slen; i++) {
+ appendcOFile(fp,s[i]);
+ }
+}
+
+#endif
+
+static void initOFile(OFile *fp, FILE *ofp)
+{
+ fp->fp = ofp;
+ fp->s = 0;
+ fp->len = 0;
+ fp->limit = 0;
+ fp->alloc = 0;
+ fp->fail = 0;
+}
+
+static int writeBase64(OFile *fp, unsigned char *s, long len)
+{
+ long cur = 0;
+ int i, numQuads = 0;
+ unsigned long trip;
+ unsigned char b;
+ char quad[5];
+#define MAXQUADS 16
+
+ quad[4] = 0;
+
+ while (cur < len) {
+ // collect the triplet of bytes into 'trip'
+ trip = 0;
+ for (i = 0; i < 3; i++) {
+ b = (cur < len) ? *(s + cur) : 0;
+ cur++;
+ trip = trip << 8 | b;
+ }
+ // fill in 'quad' with the appropriate four characters
+ for (i = 3; i >= 0; i--) {
+ b = (unsigned char)(trip & 0x3F);
+ trip = trip >> 6;
+ if ((3 - i) < (cur - len))
+ quad[i] = '='; // pad char
+ else if (b < 26) quad[i] = (char)b + 'A';
+ else if (b < 52) quad[i] = (char)(b - 26) + 'a';
+ else if (b < 62) quad[i] = (char)(b - 52) + '0';
+ else if (b == 62) quad[i] = '+';
+ else quad[i] = '/';
+ }
+ // now output 'quad' with appropriate whitespace and line ending
+ appendsOFile(fp, (numQuads == 0 ? " " : ""));
+ appendsOFile(fp, quad);
+ appendsOFile(fp, ((cur >= len)?"\n" :(numQuads==MAXQUADS-1?"\n" : "")));
+ numQuads = (numQuads + 1) % MAXQUADS;
+ }
+ appendcOFile(fp,'\n');
+
+ return 1;
+}
+
+static const char *replaceChar(unsigned char c)
+{
+ if (c == '\n') {
+ return "=0A=\n";
+ } else if (
+ (c >= 'A' && c <= 'Z')
+ ||
+ (c >= 'a' && c <= 'z')
+ ||
+ (c >= '0' && c <= '9')
+ ||
+ (c >= '\'' && c <= ')')
+ ||
+ (c >= '+' && c <= '-')
+ ||
+ (c == '/')
+ ||
+ (c == '?')
+ ||
+ (c == ' '))
+ {
+ return 0;
+ }
+
+ static char trans[4];
+ trans[0] = '=';
+ trans[3] = '\0';
+ int rem = c % 16;
+ int div = c / 16;
+
+ if (div < 10)
+ trans[1] = '0' + div;
+ else
+ trans[1] = 'A' + (div - 10);
+
+ if (rem < 10)
+ trans[2] = '0' + rem;
+ else
+ trans[2] = 'A' + (rem - 10);
+
+ return trans;
+}
+
+static void writeQPString(OFile *fp, const char *s)
+{
+ /*
+ only A-Z, 0-9 and
+ "'" (ASCII code 39)
+ "(" (ASCII code 40)
+ ")" (ASCII code 41)
+ "+" (ASCII code 43)
+ "," (ASCII code 44)
+ "-" (ASCII code 45)
+ "/" (ASCII code 47)
+ "?" (ASCII code 63)
+
+ should remain un-encoded.
+ '=' needs to be encoded as it is the escape character.
+ ';' needs to be as it is a field separator.
+
+ */
+ const char *p = s;
+ while (*p) {
+ const char *rep = replaceChar(*p);
+ if (rep)
+ appendsOFile(fp, rep);
+ else
+ appendcOFile(fp, *p);
+ p++;
+ }
+}
+
+static bool includesUnprintable(VObject *o)
+{
+ if (o) {
+ if (VALUE_TYPE(o) == VCVT_STRINGZ) {
+ const char *p = STRINGZ_VALUE_OF(o);
+ if (p) {
+ while (*p) {
+ if (replaceChar(*p))
+ return TRUE;
+ p++;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
+static void writeVObject_(OFile *fp, VObject *o);
+
+static void writeValue(OFile *fp, VObject *o, unsigned long size)
+{
+ if (o == 0) return;
+ switch (VALUE_TYPE(o)) {
+ case VCVT_STRINGZ: {
+ writeQPString(fp, STRINGZ_VALUE_OF(o));
+ break;
+ }
+ case VCVT_UINT: {
+ char buf[16];
+ sprintf(buf,"%u", INTEGER_VALUE_OF(o));
+ appendsOFile(fp,buf);
+ break;
+ }
+ case VCVT_ULONG: {
+ char buf[16];
+ sprintf(buf,"%lu", LONG_VALUE_OF(o));
+ appendsOFile(fp,buf);
+ break;
+ }
+ case VCVT_RAW: {
+ appendcOFile(fp,'\n');
+ writeBase64(fp,(unsigned char*)(ANY_VALUE_OF(o)),size);
+ break;
+ }
+ case VCVT_VOBJECT:
+ appendcOFile(fp,'\n');
+ writeVObject_(fp,VOBJECT_VALUE_OF(o));
+ break;
+ }
+}
+
+static void writeAttrValue(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ pi = lookupPropInfo(NAME_OF(o));
+ if (pi && ((pi->flags & PD_INTERNAL) != 0)) return;
+ if ( includesUnprintable(o) ) {
+ appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
+ appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
+ }
+ appendcOFile(fp,';');
+ appendsOFile(fp,NAME_OF(o));
+ }
+ else
+ appendcOFile(fp,';');
+ if (VALUE_TYPE(o)) {
+ appendcOFile(fp,'=');
+ writeValue(fp,o,0);
+ }
+}
+
+static void writeGroup(OFile *fp, VObject *o)
+{
+ char buf1[256];
+ char buf2[256];
+ strcpy(buf1,NAME_OF(o));
+ while ((o=isAPropertyOf(o,VCGroupingProp)) != 0) {
+ strcpy(buf2,STRINGZ_VALUE_OF(o));
+ strcat(buf2,".");
+ strcat(buf2,buf1);
+ strcpy(buf1,buf2);
+ }
+ appendsOFile(fp,buf1);
+}
+
+static int inList(const char **list, const char *s)
+{
+ if (list == 0) return 0;
+ while (*list) {
+ if (qstricmp(*list,s) == 0) return 1;
+ list++;
+ }
+ return 0;
+}
+
+static void writeProp(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ VObjectIterator t;
+ const char **fields_ = 0;
+ pi = lookupPropInfo(NAME_OF(o));
+ if (pi && ((pi->flags & PD_BEGIN) != 0)) {
+ writeVObject_(fp,o);
+ return;
+ }
+ if (isAPropertyOf(o,VCGroupingProp))
+ writeGroup(fp,o);
+ else
+ appendsOFile(fp,NAME_OF(o));
+ if (pi) fields_ = pi->fields;
+ initPropIterator(&t,o);
+ while (moreIteration(&t)) {
+ const char *s;
+ VObject *eachProp = nextVObject(&t);
+ s = NAME_OF(eachProp);
+ if (qstricmp(VCGroupingProp,s) && !inList(fields_,s))
+ writeAttrValue(fp,eachProp);
+ }
+ if (fields_) {
+ int i = 0, n = 0;
+ const char** fields = fields_;
+ /* output prop as fields */
+ bool printable = TRUE;
+ while (*fields && printable) {
+ VObject *t = isAPropertyOf(o,*fields);
+ if (includesUnprintable(t))
+ printable = FALSE;
+ fields++;
+ }
+ fields = fields_;
+ if (!printable) {
+ appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
+ appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
+ }
+ appendcOFile(fp,':');
+ while (*fields) {
+ VObject *t = isAPropertyOf(o,*fields);
+ i++;
+ if (t) n = i;
+ fields++;
+ }
+ fields = fields_;
+ for (i=0;i<n;i++) {
+ writeValue(fp,isAPropertyOf(o,*fields),0);
+ fields++;
+ if (i<(n-1)) appendcOFile(fp,';');
+ }
+ }
+ }
+
+
+ if (VALUE_TYPE(o)) {
+ if ( includesUnprintable(o) ) {
+ appendsOFile(fp, ";" VCEncodingProp "=" VCQuotedPrintableProp);
+ appendsOFile(fp, ";" VCCharSetProp "=" "UTF-8");
+ }
+ unsigned long size = 0;
+ VObject *p = isAPropertyOf(o,VCDataSizeProp);
+ if (p) size = LONG_VALUE_OF(p);
+ appendcOFile(fp,':');
+ writeValue(fp,o,size);
+ }
+
+ appendcOFile(fp,'\n');
+}
+
+static void writeVObject_(OFile *fp, VObject *o)
+{
+ if (NAME_OF(o)) {
+ struct PreDefProp *pi;
+ pi = lookupPropInfo(NAME_OF(o));
+
+ if (pi && ((pi->flags & PD_BEGIN) != 0)) {
+ VObjectIterator t;
+ const char *begin = NAME_OF(o);
+ appendsOFile(fp,"BEGIN:");
+ appendsOFile(fp,begin);
+ appendcOFile(fp,'\n');
+ initPropIterator(&t,o);
+ while (moreIteration(&t)) {
+ VObject *eachProp = nextVObject(&t);
+ writeProp(fp, eachProp);
+ }
+ appendsOFile(fp,"END:");
+ appendsOFile(fp,begin);
+ appendsOFile(fp,"\n\n");
+ }
+ }
+}
+
+void writeVObject(FILE *fp, VObject *o)
+{
+ OFile ofp;
+ // #####
+ //_setmode(_fileno(fp), _O_BINARY);
+ initOFile(&ofp,fp);
+ writeVObject_(&ofp,o);
+}
+
+DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o)
+{
+ QFileDirect f( fname);
+ if ( !f.open( IO_WriteOnly ) ) {
+ qWarning("Unable to open vobject write %s", fname);
+ return;
+ }
+
+ writeVObject( f.directHandle(),o );
+}
+
+DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list)
+{
+ QFileDirect f( fname);
+ if ( !f.open( IO_WriteOnly ) ) {
+ qWarning("Unable to open vobject write %s", fname);
+ return;
+ }
+
+ while (list) {
+ writeVObject(f.directHandle(),list);
+ list = nextVObjectInList(list);
+ }
+}
+
+DLLEXPORT(const char *) vObjectTypeInfo(VObject *o)
+{
+ const char *type = vObjectName( o );
+ if ( strcmp( type, "TYPE" ) == 0 )
+ type = vObjectStringZValue( o );
+ return type;
+}
+
+
+// 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 @@
-/***************************************************************************
-(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-
-For purposes of this license notice, the term Licensors shall mean,
-collectively, Apple Computer, Inc., AT&T Corp., International
-Business Machines Corporation and Siemens Rolm Communications Inc.
-The term Licensor shall mean any of the Licensors.
-
-Subject to acceptance of the following conditions, permission is hereby
-granted by Licensors without the need for written agreement and without
-license or royalty fees, to use, copy, modify and distribute this
-software for any purpose.
-
-The above copyright notice and the following four paragraphs must be
-reproduced in all copies of this software and any software including
-this software.
-
-THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
-ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
-MODIFICATIONS.
-
-IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
-INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
-OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGE.
-
-EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.
-
-The software is provided with RESTRICTED RIGHTS. Use, duplication, or
-disclosure by the government are subject to restrictions set forth in
-DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
-
-***************************************************************************/
-
-/*
-
-The vCard/vCalendar C interface is implemented in the set
-of files as follows:
-
-vcc.y, yacc source, and vcc.c, the yacc output you will use
-implements the core parser
-
-vobject.c implements an API that insulates the caller from
-the parser and changes in the vCard/vCalendar BNF
-
-port.h defines compilation environment dependent stuff
-
-vcc.h and vobject.h are header files for their .c counterparts
-
-vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
-which you may find useful.
-
-test.c is a standalone test driver that exercises some of
-the features of the APIs provided. Invoke test.exe on a
-VCARD/VCALENDAR input text file and you will see the pretty
-print output of the internal representation (this pretty print
-output should give you a good idea of how the internal
-representation looks like -- there is one such output in the
-following too). Also, a file with the .out suffix is generated
-to show that the internal representation can be written back
-in the original text format.
-
-For more information on this API see the readme.txt file
-which accompanied this distribution.
-
- Also visit:
-
- http://www.versit.com
- http://www.ralden.com
-
-*/
-
-
-#ifndef __VOBJECT_H__
-#define __VOBJECT_H__ 1
-
-#include <qstring.h>
-
-#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
-#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
-
-/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
-are globally unique IDs which can be used to generate clipboard format
-ID's as per the requirements of a specific platform. For example, in
-Windows they are used as the parameter in a call to RegisterClipboardFormat.
-For example:
-
- CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
-
-*/
-
-#define vCardMimeType "text/x-vCard"
-#define vCalendarMimeType "text/x-vCalendar"
-
-#undef DLLEXPORT
-#include <qglobal.h>
-#if defined(Q_WS_WIN)
-#define DLLEXPORT(t) __declspec(dllexport) t
-#else
-#define DLLEXPORT(t) t
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-
-#define VC7bitProp "7BIT"
-#define VC8bitProp "8BIT"
-#define VCAAlarmProp "AALARM"
-#define VCAdditionalNamesProp "ADDN"
-#define VCAdrProp "ADR"
-#define VCAgentProp "AGENT"
-#define VCAIFFProp "AIFF"
-#define VCAOLProp "AOL"
-#define VCAppleLinkProp "APPLELINK"
-#define VCAttachProp "ATTACH"
-#define VCAttendeeProp "ATTENDEE"
-#define VCATTMailProp "ATTMAIL"
-#define VCAudioContentProp "AUDIOCONTENT"
-#define VCAVIProp "AVI"
-#define VCBase64Prop "BASE64"
-#define VCBBSProp "BBS"
-#define VCBirthDateProp "BDAY"
-#define VCBMPProp "BMP"
-#define VCBodyProp "BODY"
-#define VCBusinessRoleProp "ROLE"
-#define VCCalProp "VCALENDAR"
-#define VCCaptionProp "CAP"
-#define VCCardProp "VCARD"
-#define VCCarProp "CAR"
-#define VCCategoriesProp "CATEGORIES"
-#define VCCellularProp "CELL"
-#define VCCGMProp "CGM"
-#define VCCharSetProp "CS"
-#define VCCIDProp "CID"
-#define VCCISProp "CIS"
-#define VCCityProp "L"
-#define VCClassProp "CLASS"
-#define VCCommentProp "NOTE"
-#define VCCompletedProp "COMPLETED"
-#define VCContentIDProp "CONTENT-ID"
-#define VCCountryNameProp "C"
-#define VCDAlarmProp "DALARM"
-#define VCDataSizeProp "DATASIZE"
-#define VCDayLightProp "DAYLIGHT"
-#define VCDCreatedProp "DCREATED"
-#define VCDeliveryLabelProp "LABEL"
-#define VCDescriptionProp "DESCRIPTION"
-#define VCDIBProp "DIB"
-#define VCDisplayStringProp "DISPLAYSTRING"
-#define VCDomesticProp "DOM"
-#define VCDTendProp "DTEND"
-#define VCDTstartProp "DTSTART"
-#define VCDueProp "DUE"
-#define VCEmailAddressProp "EMAIL"
-#define VCEncodingProp "ENCODING"
-#define VCEndProp "END"
-#define VCEventProp "VEVENT"
-#define VCEWorldProp "EWORLD"
-#define VCExNumProp "EXNUM"
-#define VCExpDateProp "EXDATE"
-#define VCExpectProp "EXPECT"
-#define VCExtAddressProp "EXT ADD"
-#define VCFamilyNameProp "F"
-#define VCFaxProp "FAX"
-#define VCFullNameProp "FN"
-#define VCGeoProp "GEO"
-#define VCGeoLocationProp "GEO"
-#define VCGIFProp "GIF"
-#define VCGivenNameProp "G"
-#define VCGroupingProp "Grouping"
-#define VCHomeProp "HOME"
-#define VCIBMMailProp "IBMMail"
-#define VCInlineProp "INLINE"
-#define VCInternationalProp "INTL"
-#define VCInternetProp "INTERNET"
-#define VCISDNProp "ISDN"
-#define VCJPEGProp "JPEG"
-#define VCLanguageProp "LANG"
-#define VCLastModifiedProp "LAST-MODIFIED"
-#define VCLastRevisedProp "REV"
-#define VCLocationProp "LOCATION"
-#define VCLogoProp "LOGO"
-#define VCMailerProp "MAILER"
-#define VCMAlarmProp "MALARM"
-#define VCMCIMailProp "MCIMAIL"
-#define VCMessageProp "MSG"
-#define VCMETProp "MET"
-#define VCModemProp "MODEM"
-#define VCMPEG2Prop "MPEG2"
-#define VCMPEGProp "MPEG"
-#define VCMSNProp "MSN"
-#define VCNamePrefixesProp "NPRE"
-#define VCNameProp "N"
-#define VCNameSuffixesProp "NSUF"
-#define VCNoteProp "NOTE"
-#define VCOrgNameProp "ORGNAME"
-#define VCOrgProp "ORG"
-#define VCOrgUnit2Prop "OUN2"
-#define VCOrgUnit3Prop "OUN3"
-#define VCOrgUnit4Prop "OUN4"
-#define VCOrgUnitProp "OUN"
-#define VCPagerProp "PAGER"
-#define VCPAlarmProp "PALARM"
-#define VCParcelProp "PARCEL"
-#define VCPartProp "PART"
-#define VCPCMProp "PCM"
-#define VCPDFProp "PDF"
-#define VCPGPProp "PGP"
-#define VCPhotoProp "PHOTO"
-#define VCPICTProp "PICT"
-#define VCPMBProp "PMB"
-#define VCPostalBoxProp "BOX"
-#define VCPostalCodeProp "PC"
-#define VCPostalProp "POSTAL"
-#define VCPowerShareProp "POWERSHARE"
-#define VCPreferredProp "PREF"
-#define VCPriorityProp "PRIORITY"
-#define VCProcedureNameProp "PROCEDURENAME"
-#define VCProdIdProp "PRODID"
-#define VCProdigyProp "PRODIGY"
-#define VCPronunciationProp "SOUND"
-#define VCPSProp "PS"
-#define VCPublicKeyProp "KEY"
-#define VCQPProp "QP"
-#define VCQuickTimeProp "QTIME"
-#define VCQuotedPrintableProp "QUOTED-PRINTABLE"
-#define VCRDateProp "RDATE"
-#define VCRegionProp "R"
-#define VCRelatedToProp "RELATED-TO"
-#define VCRepeatCountProp "REPEATCOUNT"
-#define VCResourcesProp "RESOURCES"
-#define VCRNumProp "RNUM"
-#define VCRoleProp "ROLE"
-#define VCRRuleProp "RRULE"
-#define VCRSVPProp "RSVP"
-#define VCRunTimeProp "RUNTIME"
-#define VCSequenceProp "SEQUENCE"
-#define VCSnoozeTimeProp "SNOOZETIME"
-#define VCStartProp "START"
-#define VCStatusProp "STATUS"
-#define VCStreetAddressProp "STREET"
-#define VCSubTypeProp "SUBTYPE"
-#define VCSummaryProp "SUMMARY"
-#define VCTelephoneProp "TEL"
-#define VCTIFFProp "TIFF"
-#define VCTimeZoneProp "TZ"
-#define VCTitleProp "TITLE"
-#define VCTLXProp "TLX"
-#define VCTodoProp "VTODO"
-#define VCTranspProp "TRANSP"
-#define VCUniqueStringProp "UID"
-#define VCURLProp "URL"
-#define VCURLValueProp "URLVAL"
-#define VCValueProp "VALUE"
-#define VCVersionProp "VERSION"
-#define VCVideoProp "VIDEO"
-#define VCVoiceProp "VOICE"
-#define VCWAVEProp "WAVE"
-#define VCWMFProp "WMF"
-#define VCWorkProp "WORK"
-#define VCX400Prop "X400"
-#define VCX509Prop "X509"
-#define VCXRuleProp "XRULE"
-
-
-typedef struct VObject VObject;
-
-typedef struct VObjectIterator {
- VObject* start;
- VObject* next;
- } VObjectIterator;
-
-extern DLLEXPORT(VObject*) newVObject(const char *id);
-extern DLLEXPORT(void) deleteVObject(VObject *p);
-extern DLLEXPORT(char*) dupStr(const char *s, unsigned int size);
-extern DLLEXPORT(void) deleteStr(const char *p);
-extern DLLEXPORT(void) unUseStr(const char *s);
-
-extern DLLEXPORT(void) setVObjectName(VObject *o, const char* id);
-extern DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s);
-extern DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s);
-extern DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i);
-extern DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l);
-extern DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t);
-extern DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size);
-extern DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size);
-
-extern DLLEXPORT(const char*) vObjectName(VObject *o);
-extern DLLEXPORT(const char*) vObjectStringZValue(VObject *o);
-extern DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o);
-extern DLLEXPORT(unsigned long) vObjectLongValue(VObject *o);
-extern DLLEXPORT(void*) vObjectAnyValue(VObject *o);
-extern DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o);
-extern DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p);
-
-extern DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p);
-extern DLLEXPORT(VObject*) addProp(VObject *o, const char *id);
-extern DLLEXPORT(VObject*) addProp_(VObject *o, const char *id);
-extern DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v);
-extern DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
-extern DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
-extern DLLEXPORT(VObject*) addGroup(VObject *o, const char *g);
-extern DLLEXPORT(void) addList(VObject **o, VObject *p);
-
-extern DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id);
-
-extern DLLEXPORT(VObject*) nextVObjectInList(VObject *o);
-extern DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o);
-extern DLLEXPORT(int) moreIteration(VObjectIterator *i);
-extern DLLEXPORT(VObject*) nextVObject(VObjectIterator *i);
-
-extern DLLEXPORT(const char*) lookupStr(const char *s);
-extern DLLEXPORT(void) cleanStrTbl();
-
-extern DLLEXPORT(void) cleanVObject(VObject *o);
-extern DLLEXPORT(void) cleanVObjects(VObject *list);
-
-extern DLLEXPORT(const char*) lookupProp(const char* str);
-extern DLLEXPORT(const char*) lookupProp_(const char* str);
-
-extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o);
-extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list);
-
-extern DLLEXPORT(int) vObjectValueType(VObject *o);
-
-/* return type of vObjectValueType: */
-#define VCVT_NOVALUE 0
- /* if the VObject has no value associated with it. */
-#define VCVT_STRINGZ 1
- /* if the VObject has value set by setVObjectStringZValue. */
-#define VCVT_UINT 2
- /* if the VObject has value set by setVObjectIntegerValue. */
-#define VCVT_ULONG 3
- /* if the VObject has value set by setVObjectLongValue. */
-#define VCVT_RAW 4
- /* if the VObject has value set by setVObjectAnyValue. */
-#define VCVT_VOBJECT 5
- /* if the VObject has value set by setVObjectVObjectValue. */
-
-extern const char** fieldedProp;
-
-/***************************************************
- * The methods below are implemented in vcc.c (generated from vcc.y )
- ***************************************************/
-
-/* NOTE regarding printVObject and writeVObject
-
-The functions below are not exported from the DLL because they
-take a FILE* as a parameter, which cannot be passed across a DLL
-interface (at least that is my experience). Instead you can use
-their companion functions which take file names or pointers
-to memory. However, if you are linking this code into
-your build directly then you may find them a more convenient API
-and you can go ahead and use them. If you try to use them with
-the DLL LIB you will get a link error.
-*/
-extern void writeVObject(FILE *fp, VObject *o);
-
-
-
-typedef void (*MimeErrorHandler)(char *);
-
-extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler);
-
-extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len);
-extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname);
-
-
-/* NOTE regarding Parse_MIME_FromFile
-The function above, Parse_MIME_FromFile, comes in two flavors,
-neither of which is exported from the DLL. Each version takes
-a CFile or FILE* as a parameter, neither of which can be
-passed across a DLL interface (at least that is my experience).
-If you are linking this code into your build directly then
-you may find them a more convenient API that the other flavors
-that take a file name. If you use them with the DLL LIB you
-will get a link error.
-*/
-
-
-#if INCLUDEMFC
-extern VObject* Parse_MIME_FromFile(CFile *file);
-#else
-extern VObject* Parse_MIME_FromFile(FILE *file);
-#endif
-
-extern DLLEXPORT(const char *) vObjectTypeInfo(VObject *o);
-
-
-#endif /* __VOBJECT_H__ */
-
-
+/***************************************************************************
+(C) Copyright 1996 Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+
+For purposes of this license notice, the term Licensors shall mean,
+collectively, Apple Computer, Inc., AT&T Corp., International
+Business Machines Corporation and Siemens Rolm Communications Inc.
+The term Licensor shall mean any of the Licensors.
+
+Subject to acceptance of the following conditions, permission is hereby
+granted by Licensors without the need for written agreement and without
+license or royalty fees, to use, copy, modify and distribute this
+software for any purpose.
+
+The above copyright notice and the following four paragraphs must be
+reproduced in all copies of this software and any software including
+this software.
+
+THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS AND NO LICENSOR SHALL HAVE
+ANY OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR
+MODIFICATIONS.
+
+IN NO EVENT SHALL ANY LICENSOR BE LIABLE TO ANY PARTY FOR DIRECT,
+INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT
+OF THE USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+EACH LICENSOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTY OF NONINFRINGEMENT OR THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+
+The software is provided with RESTRICTED RIGHTS. Use, duplication, or
+disclosure by the government are subject to restrictions set forth in
+DFARS 252.227-7013 or 48 CFR 52.227-19, as applicable.
+
+***************************************************************************/
+
+/*
+
+The vCard/vCalendar C interface is implemented in the set
+of files as follows:
+
+vcc.y, yacc source, and vcc.c, the yacc output you will use
+implements the core parser
+
+vobject.c implements an API that insulates the caller from
+the parser and changes in the vCard/vCalendar BNF
+
+port.h defines compilation environment dependent stuff
+
+vcc.h and vobject.h are header files for their .c counterparts
+
+vcaltmp.h and vcaltmp.c implement vCalendar "macro" functions
+which you may find useful.
+
+test.c is a standalone test driver that exercises some of
+the features of the APIs provided. Invoke test.exe on a
+VCARD/VCALENDAR input text file and you will see the pretty
+print output of the internal representation (this pretty print
+output should give you a good idea of how the internal
+representation looks like -- there is one such output in the
+following too). Also, a file with the .out suffix is generated
+to show that the internal representation can be written back
+in the original text format.
+
+For more information on this API see the readme.txt file
+which accompanied this distribution.
+
+ Also visit:
+
+ http://www.versit.com
+ http://www.ralden.com
+
+*/
+
+// No tr() anywhere in this file
+
+
+#ifndef __VOBJECT_H__
+#define __VOBJECT_H__ 1
+
+#include <qstring.h>
+
+#define vCardClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCard"
+#define vCalendarClipboardFormat "+//ISBN 1-887687-00-9::versit::PDI//vCalendar"
+
+/* The above strings vCardClipboardFormat and vCalendarClipboardFormat
+are globally unique IDs which can be used to generate clipboard format
+ID's as per the requirements of a specific platform. For example, in
+Windows they are used as the parameter in a call to RegisterClipboardFormat.
+For example:
+
+ CLIPFORMAT foo = RegisterClipboardFormat(vCardClipboardFormat);
+
+*/
+
+#define vCardMimeType "text/x-vCard"
+#define vCalendarMimeType "text/x-vCalendar"
+
+#undef DLLEXPORT
+#include <qglobal.h>
+#if defined(Q_WS_WIN)
+#define DLLEXPORT(t) __declspec(dllexport) t
+#else
+#define DLLEXPORT(t) t
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define VC7bitProp "7BIT"
+#define VC8bitProp "8BIT"
+#define VCAAlarmProp "AALARM"
+#define VCAdditionalNamesProp "ADDN"
+#define VCAdrProp "ADR"
+#define VCAgentProp "AGENT"
+#define VCAIFFProp "AIFF"
+#define VCAOLProp "AOL"
+#define VCAppleLinkProp "APPLELINK"
+#define VCAttachProp "ATTACH"
+#define VCAttendeeProp "ATTENDEE"
+#define VCATTMailProp "ATTMAIL"
+#define VCAudioContentProp "AUDIOCONTENT"
+#define VCAVIProp "AVI"
+#define VCBase64Prop "BASE64"
+#define VCBBSProp "BBS"
+#define VCBirthDateProp "BDAY"
+#define VCBMPProp "BMP"
+#define VCBodyProp "BODY"
+#define VCBusinessRoleProp "ROLE"
+#define VCCalProp "VCALENDAR"
+#define VCCaptionProp "CAP"
+#define VCCardProp "VCARD"
+#define VCCarProp "CAR"
+#define VCCategoriesProp "CATEGORIES"
+#define VCCellularProp "CELL"
+#define VCCGMProp "CGM"
+#define VCCharSetProp "CHARSET"
+#define VCCIDProp "CID"
+#define VCCISProp "CIS"
+#define VCCityProp "L"
+#define VCClassProp "CLASS"
+#define VCCommentProp "NOTE"
+#define VCCompletedProp "COMPLETED"
+#define VCContentIDProp "CONTENT-ID"
+#define VCCountryNameProp "C"
+#define VCDAlarmProp "DALARM"
+#define VCDataSizeProp "DATASIZE"
+#define VCDayLightProp "DAYLIGHT"
+#define VCDCreatedProp "DCREATED"
+#define VCDeliveryLabelProp "LABEL"
+#define VCDescriptionProp "DESCRIPTION"
+#define VCDIBProp "DIB"
+#define VCDisplayStringProp "DISPLAYSTRING"
+#define VCDomesticProp "DOM"
+#define VCDTendProp "DTEND"
+#define VCDTstartProp "DTSTART"
+#define VCDueProp "DUE"
+#define VCEmailAddressProp "EMAIL"
+#define VCEncodingProp "ENCODING"
+#define VCEndProp "END"
+#define VCEventProp "VEVENT"
+#define VCEWorldProp "EWORLD"
+#define VCExNumProp "EXNUM"
+#define VCExpDateProp "EXDATE"
+#define VCExpectProp "EXPECT"
+#define VCExtAddressProp "EXT ADD"
+#define VCFamilyNameProp "F"
+#define VCFaxProp "FAX"
+#define VCFullNameProp "FN"
+#define VCGeoProp "GEO"
+#define VCGeoLocationProp "GEO"
+#define VCGIFProp "GIF"
+#define VCGivenNameProp "G"
+#define VCGroupingProp "Grouping"
+#define VCHomeProp "HOME"
+#define VCIBMMailProp "IBMMail"
+#define VCInlineProp "INLINE"
+#define VCInternationalProp "INTL"
+#define VCInternetProp "INTERNET"
+#define VCISDNProp "ISDN"
+#define VCJPEGProp "JPEG"
+#define VCLanguageProp "LANG"
+#define VCLastModifiedProp "LAST-MODIFIED"
+#define VCLastRevisedProp "REV"
+#define VCLocationProp "LOCATION"
+#define VCLogoProp "LOGO"
+#define VCMailerProp "MAILER"
+#define VCMAlarmProp "MALARM"
+#define VCMCIMailProp "MCIMAIL"
+#define VCMessageProp "MSG"
+#define VCMETProp "MET"
+#define VCModemProp "MODEM"
+#define VCMPEG2Prop "MPEG2"
+#define VCMPEGProp "MPEG"
+#define VCMSNProp "MSN"
+#define VCNamePrefixesProp "NPRE"
+#define VCNameProp "N"
+#define VCNameSuffixesProp "NSUF"
+#define VCNoteProp "NOTE"
+#define VCOrgNameProp "ORGNAME"
+#define VCOrgProp "ORG"
+#define VCOrgUnit2Prop "OUN2"
+#define VCOrgUnit3Prop "OUN3"
+#define VCOrgUnit4Prop "OUN4"
+#define VCOrgUnitProp "OUN"
+#define VCPagerProp "PAGER"
+#define VCPAlarmProp "PALARM"
+#define VCParcelProp "PARCEL"
+#define VCPartProp "PART"
+#define VCPCMProp "PCM"
+#define VCPDFProp "PDF"
+#define VCPGPProp "PGP"
+#define VCPhotoProp "PHOTO"
+#define VCPICTProp "PICT"
+#define VCPMBProp "PMB"
+#define VCPostalBoxProp "BOX"
+#define VCPostalCodeProp "PC"
+#define VCPostalProp "POSTAL"
+#define VCPowerShareProp "POWERSHARE"
+#define VCPreferredProp "PREF"
+#define VCPriorityProp "PRIORITY"
+#define VCProcedureNameProp "PROCEDURENAME"
+#define VCProdIdProp "PRODID"
+#define VCProdigyProp "PRODIGY"
+#define VCPronunciationProp "SOUND"
+#define VCPSProp "PS"
+#define VCPublicKeyProp "KEY"
+#define VCQPProp "QP"
+#define VCQuickTimeProp "QTIME"
+#define VCQuotedPrintableProp "QUOTED-PRINTABLE"
+#define VCRDateProp "RDATE"
+#define VCRegionProp "R"
+#define VCRelatedToProp "RELATED-TO"
+#define VCRepeatCountProp "REPEATCOUNT"
+#define VCResourcesProp "RESOURCES"
+#define VCRNumProp "RNUM"
+#define VCRoleProp "ROLE"
+#define VCRRuleProp "RRULE"
+#define VCRSVPProp "RSVP"
+#define VCRunTimeProp "RUNTIME"
+#define VCSequenceProp "SEQUENCE"
+#define VCSnoozeTimeProp "SNOOZETIME"
+#define VCStartProp "START"
+#define VCStatusProp "STATUS"
+#define VCStreetAddressProp "STREET"
+#define VCSubTypeProp "SUBTYPE"
+#define VCSummaryProp "SUMMARY"
+#define VCTelephoneProp "TEL"
+#define VCTIFFProp "TIFF"
+#define VCTimeZoneProp "TZ"
+#define VCTitleProp "TITLE"
+#define VCTLXProp "TLX"
+#define VCTodoProp "VTODO"
+#define VCTranspProp "TRANSP"
+#define VCUniqueStringProp "UID"
+#define VCURLProp "URL"
+#define VCURLValueProp "URLVAL"
+#define VCValueProp "VALUE"
+#define VCVersionProp "VERSION"
+#define VCVideoProp "VIDEO"
+#define VCVoiceProp "VOICE"
+#define VCWAVEProp "WAVE"
+#define VCWMFProp "WMF"
+#define VCWorkProp "WORK"
+#define VCX400Prop "X400"
+#define VCX509Prop "X509"
+#define VCXRuleProp "XRULE"
+
+
+typedef struct VObject VObject;
+
+typedef struct VObjectIterator {
+ VObject* start;
+ VObject* next;
+ } VObjectIterator;
+
+extern DLLEXPORT(VObject*) newVObject(const char *id);
+extern DLLEXPORT(void) deleteVObject(VObject *p);
+extern DLLEXPORT(char*) dupStr(const char *s, unsigned int size);
+extern DLLEXPORT(void) deleteStr(const char *p);
+extern DLLEXPORT(void) unUseStr(const char *s);
+
+extern DLLEXPORT(void) setVObjectName(VObject *o, const char* id);
+extern DLLEXPORT(void) setVObjectStringZValue(VObject *o, const char *s);
+extern DLLEXPORT(void) setVObjectStringZValue_(VObject *o, const char *s);
+extern DLLEXPORT(void) setVObjectIntegerValue(VObject *o, unsigned int i);
+extern DLLEXPORT(void) setVObjectLongValue(VObject *o, unsigned long l);
+extern DLLEXPORT(void) setVObjectAnyValue(VObject *o, void *t);
+extern DLLEXPORT(VObject*) setValueWithSize(VObject *prop, void *val, unsigned int size);
+extern DLLEXPORT(VObject*) setValueWithSize_(VObject *prop, void *val, unsigned int size);
+
+extern DLLEXPORT(const char*) vObjectName(VObject *o);
+extern DLLEXPORT(const char*) vObjectStringZValue(VObject *o);
+extern DLLEXPORT(unsigned int) vObjectIntegerValue(VObject *o);
+extern DLLEXPORT(unsigned long) vObjectLongValue(VObject *o);
+extern DLLEXPORT(void*) vObjectAnyValue(VObject *o);
+extern DLLEXPORT(VObject*) vObjectVObjectValue(VObject *o);
+extern DLLEXPORT(void) setVObjectVObjectValue(VObject *o, VObject *p);
+
+extern DLLEXPORT(VObject*) addVObjectProp(VObject *o, VObject *p);
+extern DLLEXPORT(VObject*) addProp(VObject *o, const char *id);
+extern DLLEXPORT(VObject*) addProp_(VObject *o, const char *id);
+extern DLLEXPORT(VObject*) addPropValue(VObject *o, const char *p, const char *v);
+extern DLLEXPORT(VObject*) addPropSizedValue_(VObject *o, const char *p, const char *v, unsigned int size);
+extern DLLEXPORT(VObject*) addPropSizedValue(VObject *o, const char *p, const char *v, unsigned int size);
+extern DLLEXPORT(VObject*) addGroup(VObject *o, const char *g);
+extern DLLEXPORT(void) addList(VObject **o, VObject *p);
+
+extern DLLEXPORT(VObject*) isAPropertyOf(VObject *o, const char *id);
+
+extern DLLEXPORT(VObject*) nextVObjectInList(VObject *o);
+extern DLLEXPORT(void) initPropIterator(VObjectIterator *i, VObject *o);
+extern DLLEXPORT(int) moreIteration(VObjectIterator *i);
+extern DLLEXPORT(VObject*) nextVObject(VObjectIterator *i);
+
+extern DLLEXPORT(const char*) lookupStr(const char *s);
+extern DLLEXPORT(void) cleanStrTbl();
+
+extern DLLEXPORT(void) cleanVObject(VObject *o);
+extern DLLEXPORT(void) cleanVObjects(VObject *list);
+
+extern DLLEXPORT(const char*) lookupProp(const char* str);
+extern DLLEXPORT(const char*) lookupProp_(const char* str);
+
+extern DLLEXPORT(void) writeVObjectToFile(char *fname, VObject *o);
+extern DLLEXPORT(void) writeVObjectsToFile(char *fname, VObject *list);
+
+extern DLLEXPORT(int) vObjectValueType(VObject *o);
+
+/* return type of vObjectValueType: */
+#define VCVT_NOVALUE 0
+ /* if the VObject has no value associated with it. */
+#define VCVT_STRINGZ 1
+ /* if the VObject has value set by setVObjectStringZValue. */
+#define VCVT_UINT 2
+ /* if the VObject has value set by setVObjectIntegerValue. */
+#define VCVT_ULONG 3
+ /* if the VObject has value set by setVObjectLongValue. */
+#define VCVT_RAW 4
+ /* if the VObject has value set by setVObjectAnyValue. */
+#define VCVT_VOBJECT 5
+ /* if the VObject has value set by setVObjectVObjectValue. */
+
+extern const char** fieldedProp;
+
+/***************************************************
+ * The methods below are implemented in vcc.c (generated from vcc.y )
+ ***************************************************/
+
+/* NOTE regarding printVObject and writeVObject
+
+The functions below are not exported from the DLL because they
+take a FILE* as a parameter, which cannot be passed across a DLL
+interface (at least that is my experience). Instead you can use
+their companion functions which take file names or pointers
+to memory. However, if you are linking this code into
+your build directly then you may find them a more convenient API
+and you can go ahead and use them. If you try to use them with
+the DLL LIB you will get a link error.
+*/
+extern void writeVObject(FILE *fp, VObject *o);
+
+
+
+typedef void (*MimeErrorHandler)(char *);
+
+extern DLLEXPORT(void) registerMimeErrorHandler(MimeErrorHandler);
+
+extern DLLEXPORT(VObject*) Parse_MIME(const char *input, unsigned long len);
+extern DLLEXPORT(VObject*) Parse_MIME_FromFileName(char* fname);
+
+
+/* NOTE regarding Parse_MIME_FromFile
+The function above, Parse_MIME_FromFile, comes in two flavors,
+neither of which is exported from the DLL. Each version takes
+a CFile or FILE* as a parameter, neither of which can be
+passed across a DLL interface (at least that is my experience).
+If you are linking this code into your build directly then
+you may find them a more convenient API that the other flavors
+that take a file name. If you use them with the DLL LIB you
+will get a link error.
+*/
+
+
+#if INCLUDEMFC
+extern VObject* Parse_MIME_FromFile(CFile *file);
+#else
+extern VObject* Parse_MIME_FromFile(FILE *file);
+#endif
+
+extern DLLEXPORT(const char *) vObjectTypeInfo(VObject *o);
+
+
+#endif /* __VOBJECT_H__ */
+
+