summaryrefslogtreecommitdiffstats
path: root/kpilot/lib/pilot.h
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/lib/pilot.h')
-rw-r--r--kpilot/lib/pilot.h410
1 files changed, 410 insertions, 0 deletions
diff --git a/kpilot/lib/pilot.h b/kpilot/lib/pilot.h
new file mode 100644
index 000000000..d4fec82b2
--- /dev/null
+++ b/kpilot/lib/pilot.h
@@ -0,0 +1,410 @@
+#ifndef _KPILOT_PILOT_H
+#define _KPILOT_PILOT_H
+/* KPilot
+**
+** Copyright (C) 1998-2001 by Dan Pilone
+** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+** Copyright (C) 2003-2006 Adriaan de Groot <groot@kde.org>
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published by
+** the Free Software Foundation; either version 2.1 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU Lesser General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include <sys/types.h>
+
+#include <pi-appinfo.h>
+#include <pi-buffer.h>
+#include <pi-dlp.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qvaluelist.h>
+
+#include "pilotLinkVersion.h"
+
+
+/** @file
+* These are some base structures that reside on the
+* handheld device -- strings and binary data.
+*/
+
+class PilotDatabase; // A database
+class PilotRecord; // ... has records
+class PilotCategoryInfo; // ... and category information
+
+#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+
+/**
+* The Pilot namespace holds constants that are global for
+* the handheld data structures. Also contains some global
+* functions that deal with pilot-link structures as well
+* as mapping user-visible strings from UTF8 (KDE side) to
+* the encoding used on the handheld.
+*/
+namespace Pilot
+{
+ /** Maximum size of an AppInfo block, taken roughly from the pilot-link source. */
+ static const int MAX_APPINFO_SIZE=8192;
+
+ /** Maximum number of categories the handheld has */
+ static const unsigned int CATEGORY_COUNT=16;
+
+ /** Maximum size of a category label */
+ static const unsigned int CATEGORY_SIZE=16;
+
+ /** Category number for unfiled records */
+ static const int Unfiled = 0;
+
+ /** Maximum size (in bytes) of a record's data */
+ static const int MAX_RECORD_SIZE = 65535;
+
+ typedef QValueList<recordid_t> RecordIDList;
+
+ /** Static translation function that maps handheld native (8 bit,
+ * usually latin1 but sometimes someting else) encoded data to
+ * a Unicode string. Converts the @p len characters in @p c
+ * to a Unicode string.
+ */
+ QString fromPilot( const char *c, int len );
+
+ /** Static translation function mapping a NUL-terminated
+ * string from the handheld's encoding to UTF-8.
+ * @param c the NUL-terminated string to decode
+ * @return QString (UTF-8) value of @p c
+ * @note NUL-terminated strings are rare on the handheld.
+ */
+ QString fromPilot( const char *c );
+
+ /** Static translation function that maps a QString onto the
+ * native 8 bit encoding of the handheld. Writes the result into
+ * the buffer @p buf which has size @p len. Returns the length
+ * of the result. Zero-fills the buffer as needed.
+ */
+ int toPilot( const QString &s, char *buf, int len);
+ int toPilot( const QString &s, unsigned char *buf, int len);
+
+ /** Static translation function that maps a QString onto the
+ * native 8 bit encoding of the handheld.
+ *
+ * @param s String to encode
+ * @return Encoded string in a QCString
+ */
+ QCString toPilot( const QString &s );
+
+ /** Create a codec for translating handheld native 8 bit to Unicode,
+ * using the given codec @p name -- this will often be latin1, but
+ * might be something else for, say, Russian-language Pilots.
+ * If @p name is empty, use latin1.
+ *
+ * @return @c true on success, @c false otherwise
+ */
+ bool setupPilotCodec(const QString &name);
+
+ /** Returns the name of the codec being used. */
+ QString codecName();
+
+ /** For debugging, display category names for the given AppInfo
+ * structure. Called by dump(). You must pass a valid reference.
+ */
+ void dumpCategories(const struct CategoryAppInfo *info);
+
+ /** Check that a given category number is valid. This
+ * restricts the range of integers to [0..CATEGORY_COUNT-1]
+ * (i.e. [0..15]) which is what the handheld supports.
+ */
+ inline bool validCategory(int c)
+ {
+ if (c<0)
+ {
+ return false;
+ }
+ return ((unsigned int)c<CATEGORY_COUNT);
+ }
+
+ /** Returns the QString for the requested category @p i
+ * in the category structure @p info. Returns @c QString::null
+ * on error (bad pointer or bad category number). May also
+ * return @c QString::null if the category name is empty.
+ */
+ inline QString categoryName(const struct CategoryAppInfo *info, unsigned int i)
+ {
+ if ( ( i < CATEGORY_COUNT ) && ( info->name[i][0] ) )
+ {
+ /*
+ * Seems to be important that we try to pass the real length here
+ * to the codec.
+ */
+ return fromPilot( info->name[i], MIN(strlen(info->name[i]),CATEGORY_SIZE) );
+ }
+ else
+ {
+ return QString::null;
+ }
+ }
+
+ /** Returns a list of all the category names available on the
+ * handheld. This list is neither ordered nor does it contain
+ * all sixteen categories -- empty category names on the
+ * handheld are skipped.
+ */
+ inline QStringList categoryNames(const struct CategoryAppInfo *info)
+ {
+ QStringList l;
+ if (!info)
+ {
+ return l;
+ }
+ for (unsigned int i=0; i<CATEGORY_COUNT; ++i)
+ {
+ QString s = categoryName(info,i);
+ if (!s.isEmpty())
+ {
+ l.append(s);
+ }
+ }
+ return l;
+ }
+
+ /** Search for the given category @p name in the list
+ * of categories; returns the category number. If @p unknownIsUnfiled
+ * is true, then map unknown categories to Unfiled instead of returning
+ * an error number.
+ *
+ * @return >=0 is a specific category based on the text-to-
+ * category number mapping defined by the Pilot,
+ * where 0 is always the 'unfiled' category.
+ * @return -1 means unknown category selected when
+ * @p unknownIsUnfiled is false.
+ * @return 0 == Unfiled means unknown category selected when
+ * @p unknownIsUnfiled is true.
+ *
+ */
+ int findCategory(const struct CategoryAppInfo *info, const QString &name, bool unknownIsUnfiled);
+
+ /** Search for the given category @p name in the list
+ * of categories; returns the category number. If @p unknownIsUnfiled
+ * is @c true, then map unknown categories to Unfiled.
+ * If @p unknownIsUnfiled is @c false, insert a @em new
+ * category into the structure and return the category
+ * number of the new category. Return -1 if (and only if)
+ * @p unknownIsUnfiled is false and the category structure
+ * is already full.
+ *
+ * @return >=0 is a specific category based on the text-to-
+ * category number mapping defined by the Pilot,
+ * where 0 is always the 'unfiled' category.
+ * @return 0 Unknown category and @p unknownIsUnfiled is @c true
+ * @return -1 means unknown category selected when
+ * @p unknownIsUnfiled is false and categories
+ * are all full.
+ *
+ */
+ int insertCategory(struct CategoryAppInfo *info, const QString &label, bool unknownIsUnfiled);
+
+ /** The handheld also holds data about each database
+ * in a DBInfo structure; check if the database described
+ * by this structure is a resource database.
+ */
+ static inline bool isResource(struct DBInfo *info)
+ {
+ return (info->flags & dlpDBFlagResource);
+ }
+
+
+/** @section Binary blob handling
+*
+* For reading and writing binary blobs -- which has to happen to
+* pack data into the format that the handheld needs -- it is important
+* to remember that the handheld has only four data types (as far
+* as I can tell: byte, short (a 2 byte integer), long (a 4 byte integer)
+* and string (NUL terminated). The sizes of the types on the handheld
+* do not necessarily correspond to the sizes of the same-named types
+* on the desktop. This means that 'reading a long' from a binary
+* blob must always be 4 bytes -- not sizeof(long).
+*
+* The following templates help out in manipulating the blobs.
+* Instantiate them with the type @em name you need (char, short, long or
+* char *) and you get a ::size enum specifying the number of bytes
+* (where applicable) and ::append and ::read methods for appending
+* a value of the given type to a pi_buffer_t or reading one from
+* the buffer, respectively.
+*
+* The usage of ::read and ::append is straightforward:
+*
+* append(pi_buffer_t *b, TYPE_VALUE v) Appends the type value @p v to the
+* buffer @p b , extending the buffer as needed.
+*
+* TYPE_VALUE read(pi_buffer_t *b, unsigned int &offset) Read a value from
+* the buffer @p b at position @p offset and return it. The offset value
+* is increased by the number of bytes read from the buffer.
+*
+* To write a binary blob, a sequence of ::append calls constructs the
+* blob. To read the same blob, a sequence of ::read calls with the
+* @em same type parameters is sufficient.
+*
+* The calls may vary a little: the exact interface differs depending
+* on the needs of the type of data to be written to the blob.
+*/
+template<typename t> struct dlp { } ;
+
+template<> struct dlp<char>
+{
+ enum { size = 1 };
+
+ static void append(pi_buffer_t *b, char v)
+ {
+ pi_buffer_append(b,&v,size);
+ }
+
+ /**
+ * Returns next byte from buffer or 0 on error (0 is also a
+ * valid return value, though).
+ */
+ static char read(const pi_buffer_t *b, unsigned int &offset)
+ {
+ if (offset+size > b->used)
+ {
+ return 0;
+ }
+ char c = b->data[offset];
+ offset+=size;
+ return c;
+ }
+} ;
+
+template<> struct dlp<short>
+{
+ enum { size = 2 };
+
+ static void append(pi_buffer_t *b, short v)
+ {
+ char buf[size];
+ set_short(buf,v);
+ pi_buffer_append(b,buf,size);
+ }
+
+ /**
+ * Returns the next short (2 byte) value from the buffer, or
+ * -1 on error (which is also a valid return value).
+ */
+ static int read(const pi_buffer_t *b, unsigned int &offset)
+ {
+ if (offset+size > b->used)
+ {
+ return -1;
+ }
+ else
+ {
+ int r = get_short(b->data + offset);
+ offset+=size;
+ return r;
+ }
+ }
+
+ /**
+ * Overload to read from a data buffer instead of a real pi_buffer;
+ * does no bounds checking.
+ */
+ static int read(const unsigned char *b, unsigned int &offset)
+ {
+ int r = get_short(b+offset);
+ offset+=size;
+ return r;
+ }
+} ;
+
+template<> struct dlp<long>
+{
+ enum { size = 4 };
+
+ static void append(pi_buffer_t *b, int v)
+ {
+ char buf[size];
+ set_long(buf,v);
+ pi_buffer_append(b,buf,size);
+ }
+
+ /**
+ * Returns the next long (4 byte) value from the buffer or
+ * -1 on error (which is also a valid value).
+ */
+ static int read(const pi_buffer_t *b, unsigned int &offset)
+ {
+ if (offset+size > b->used)
+ {
+ return -1;
+ }
+ else
+ {
+ int r = get_long(b->data + offset);
+ offset+=size;
+ return r;
+ }
+ }
+
+ /**
+ * Overload to read a long value from a data buffer; does
+ * no bounds checking.
+ */
+ static int read(const unsigned char *b, unsigned int &offset)
+ {
+ int r = get_long(b+offset);
+ offset+=size;
+ return r;
+ }
+} ;
+
+template<> struct dlp<char *>
+{
+ // No size enum, doesn't make sense
+ // No append, use pi_buffer_append
+ /**
+ * Read a fixed-length string from the buffer @p b into data buffer
+ * @p v which has size (including terminating NUL) of @p s.
+ * Returns the number of bytes read (which will normally be @p s
+ * but will be less than @p s on error).
+ */
+ static int read(const pi_buffer_t *b,
+ unsigned int &offset,
+ unsigned char *v,
+ size_t s)
+ {
+ if ( s+offset > b->used )
+ {
+ s = b->allocated - offset;
+ }
+ memcpy(v, b->data + offset, s);
+ offset+=s;
+ return s;
+ }
+
+ /** Overload for signed char. */
+ inline static int read(const pi_buffer_t *b, unsigned int &offset, char *v, size_t s)
+ {
+ return read(b,offset,(unsigned char *)v,s);
+ }
+} ;
+
+}
+
+#endif
+