diff options
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | camel/camel-data-wrapper.c | 2 | ||||
-rw-r--r-- | camel/camel-folder.c | 13 | ||||
-rw-r--r-- | camel/camel-log.c | 2 | ||||
-rw-r--r-- | camel/camel-mime-message.c | 6 | ||||
-rw-r--r-- | camel/camel-mime-message.h | 91 | ||||
-rw-r--r-- | camel/camel-mime-part.c | 2 | ||||
-rw-r--r-- | camel/camel-mime-part.h | 44 | ||||
-rw-r--r-- | camel/camel-service.c | 2 | ||||
-rw-r--r-- | camel/camel-session.c | 2 | ||||
-rw-r--r-- | camel/camel-simple-data-wrapper.c | 2 | ||||
-rw-r--r-- | camel/camel-store.c | 2 | ||||
-rw-r--r-- | camel/camel-stream-fs.c | 22 | ||||
-rw-r--r-- | camel/camel-stream-fs.h | 1 | ||||
-rw-r--r-- | camel/camel-stream.c | 142 | ||||
-rw-r--r-- | camel/camel-stream.h | 22 | ||||
-rw-r--r-- | camel/gmime-content-field.c | 4 | ||||
-rw-r--r-- | camel/gmime-utils.c | 11 | ||||
-rw-r--r-- | camel/gstring-util.c | 59 | ||||
-rw-r--r-- | camel/gstring-util.h | 42 | ||||
-rw-r--r-- | camel/url-util.c | 2 | ||||
-rw-r--r-- | devel-docs/query/virtual-folder-in-depth.sgml | 772 |
22 files changed, 680 insertions, 598 deletions
@@ -1,3 +1,36 @@ +1999-07-13 Miguel de Icaza <miguel@gnu.org> + + * camel/gmime-base64.c (gmime_encode_base64): Implemented base64 + encoder based on CamelStreams. Should the encoder/decoder be a + Stream itself? + + * camel/gmime-utils.c: include config.h here. + * camel/url-util.c: ditto. + * camel/gstring-util.c: ditto. + * camel/gmime-content-field.c: ditto. + * camel/camel-stream.c: ditto. + * camel/camel-stream-fs.c: ditto. + * camel/camel-store.c: ditto. + * camel/camel-simple-data-wrapper.c: ditto. + * camel/camel-session.c: ditto. + * camel/camel-service.c: ditto. + * camel/camel-mime-part.c: ditto. + * camel/camel-mime-message.c: ditto. + * camel/camel-log.c: ditto. + * camel/camel-data-wrapper.c: ditto + * camel/camel-folder.c: ditto. + + * camel/camel-stream.c (camel_stream_write): Moved api + documentation to the places that they document. + (camel_stream_class_init): Virtual classes do not need to have a + default implementation. So null them all. + (camel_stream_write): Return value from write. + (camel_stream_available): implement. + (camel_stream_write_strings): documented. + + * devel-docs/query/virtual-folder-in-depth.sgml: Small + reformatting + 1999-06-28 bertrand <Bertrand.Guiheneuf@inria.fr> * tests/test2.c (main): now use diff --git a/camel/camel-data-wrapper.c b/camel/camel-data-wrapper.c index 05d97d415d..b4ef2f9c36 100644 --- a/camel/camel-data-wrapper.c +++ b/camel/camel-data-wrapper.c @@ -23,7 +23,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-data-wrapper.h" static GtkObjectClass *parent_class=NULL; diff --git a/camel/camel-folder.c b/camel/camel-folder.c index d7b54075be..63881d1422 100644 --- a/camel/camel-folder.c +++ b/camel/camel-folder.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-folder.h" #include "gstring-util.h" @@ -362,12 +362,17 @@ _create(CamelFolder *folder) g_assert(folder->parent_store); g_assert(folder->name); - if ( CF_CLASS(folder)->exists(folder) ) return TRUE; + if (CF_CLASS(folder)->exists(folder)) + return TRUE; + sep = camel_store_get_separator(folder->parent_store); - if (folder->parent_folder) camel_folder_create(folder->parent_folder); + if (folder->parent_folder) + camel_folder_create(folder->parent_folder); else { if (folder->full_name) { - dich_result = g_string_dichotomy(folder->full_name, sep, &prefix, NULL, DICHOTOMY_STRIP_TRAILING | DICHOTOMY_RIGHT_DIR); + dich_result = g_string_dichotomy( + folder->full_name, sep, &prefix, NULL, + GSTRING_DICHOTOMY_STRIP_TRAILING | GSTRING_DICHOTOMY_RIGHT_DIR); if (dich_result!='o') { g_warning("I have to handle the case where the path is not OK\n"); return FALSE; diff --git a/camel/camel-log.c b/camel/camel-log.c index 59ce5573b2..a0dd8007b7 100644 --- a/camel/camel-log.c +++ b/camel/camel-log.c @@ -20,7 +20,7 @@ * USA */ - +#include <config.h> #include "camel-log.h" int camel_debug_level = 10; diff --git a/camel/camel-mime-message.c b/camel/camel-mime-message.c index df65c127f6..61a4ca4c8d 100644 --- a/camel/camel-mime-message.c +++ b/camel/camel-mime-message.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-mime-message.h" #include <stdio.h> #include "gmime-content-field.h" @@ -564,7 +564,9 @@ _set_recipient_list_from_string (CamelMimeMessage *message, GString *recipient_t { GList *recipients_list; CAMEL_LOG (FULL_DEBUG,"CamelMimeMessage::_set_recipient_list_from_string parsing ##%s##\n", recipients_string->str); - recipients_list = g_string_split (recipients_string, ',', "\t ", TRIM_STRIP_TRAILING | TRIM_STRIP_LEADING); + recipients_list = g_string_split ( + recipients_string, ',', "\t ", + GSTRING_TRIM_STRIP_TRAILING | GSTRING_TRIM_STRIP_LEADING); g_hash_table_insert (message->recipients, recipient_type, recipients_list); } diff --git a/camel/camel-mime-message.h b/camel/camel-mime-message.h index 73d1cb9388..321f3fdade 100644 --- a/camel/camel-mime-message.h +++ b/camel/camel-mime-message.h @@ -81,24 +81,35 @@ typedef struct { CamelMimePartClass parent_class; /* Virtual methods */ - void (*set_received_date) (CamelMimeMessage *mime_message, GString *received_date); + void (*set_received_date) (CamelMimeMessage *mime_message, + GString *received_date); GString * (*get_received_date) (CamelMimeMessage *mime_message); - GString * (*get_sent_date) (CamelMimeMessage *mime_message); - void (*set_reply_to) (CamelMimeMessage *mime_message, GString *reply_to); - GString * (*get_reply_to) (CamelMimeMessage *mime_message); - void (*set_subject) (CamelMimeMessage *mime_message, GString *subject); - GString * (*get_subject) (CamelMimeMessage *mime_message); - void (*set_from) (CamelMimeMessage *mime_message, GString *from); - GString * (*get_from) (CamelMimeMessage *mime_message); - void (*add_recipient) (CamelMimeMessage *mime_message, GString *recipient_type, GString *recipient); - void (*remove_recipient) (CamelMimeMessage *mime_message, GString *recipient_type, GString *recipient); - GList * (*get_recipients) (CamelMimeMessage *mime_message, GString *recipient_type); - void (*set_flag) (CamelMimeMessage *mime_message, GString *flag, gboolean value); - gboolean (*get_flag) (CamelMimeMessage *mime_message, GString *flag); - - void (*set_message_number) (CamelMimeMessage *mime_message, guint number); - guint (*get_message_number) (CamelMimeMessage *mime_message); - + GString * (*get_sent_date) (CamelMimeMessage *mime_message); + void (*set_reply_to) (CamelMimeMessage *mime_message, + GString *reply_to); + GString * (*get_reply_to) (CamelMimeMessage *mime_message); + void (*set_subject) (CamelMimeMessage *mime_message, + GString *subject); + GString * (*get_subject) (CamelMimeMessage *mime_message); + void (*set_from) (CamelMimeMessage *mime_message, + GString *from); + GString * (*get_from) (CamelMimeMessage *mime_message); + void (*add_recipient) (CamelMimeMessage *mime_message, + GString *recipient_type, + GString *recipient); + void (*remove_recipient) (CamelMimeMessage *mime_message, + GString *recipient_type, + GString *recipient); + GList * (*get_recipients) (CamelMimeMessage *mime_message, + GString *recipient_type); + void (*set_flag) (CamelMimeMessage *mime_message, + GString *flag, gboolean value); + gboolean (*get_flag) (CamelMimeMessage *mime_message, + GString *flag); + + void (*set_message_number)(CamelMimeMessage *mime_message, + guint number); + guint (*get_message_number)(CamelMimeMessage *mime_message); } CamelMimeMessageClass; @@ -111,24 +122,34 @@ GtkType camel_mime_message_get_type (void); CamelMimeMessage *camel_mime_message_new_with_session (CamelSession *session); -void camel_mime_message_set_received_date (CamelMimeMessage *mime_message, GString *received_date); -GString *camel_mime_message_get_received_date (CamelMimeMessage *mime_message); -GString *camel_mime_message_get_sent_date (CamelMimeMessage *mime_message); -void camel_mime_message_set_reply_to (CamelMimeMessage *mime_message, GString *reply_to); -GString *camel_mime_message_get_reply_to (CamelMimeMessage *mime_message); -void camel_mime_message_set_subject (CamelMimeMessage *mime_message, GString *subject); -GString *camel_mime_message_get_subject (CamelMimeMessage *mime_message); -void camel_mime_message_set_from (CamelMimeMessage *mime_message, GString *from); -GString *camel_mime_message_get_from (CamelMimeMessage *mime_message); - -void camel_mime_message_add_recipient (CamelMimeMessage *mime_message, GString *recipient_type, GString *recipient); -void camel_mime_message_remove_recipient (CamelMimeMessage *mime_message, GString *recipient_type, GString *recipient); -GList *camel_mime_message_get_recipients (CamelMimeMessage *mime_message, GString *recipient_type); - -void camel_mime_message_set_flag (CamelMimeMessage *mime_message, GString *flag, gboolean value); -gboolean camel_mime_message_get_flag (CamelMimeMessage *mime_message, GString *flag); - -guint camel_mime_message_get_message_number (CamelMimeMessage *mime_message); +void camel_mime_message_set_received_date (CamelMimeMessage *mime_message, + GString *received_date); +GString *camel_mime_message_get_received_date (CamelMimeMessage *mime_message); +GString *camel_mime_message_get_sent_date (CamelMimeMessage *mime_message); +void camel_mime_message_set_reply_to (CamelMimeMessage *mime_message, + GString *reply_to); +GString *camel_mime_message_get_reply_to (CamelMimeMessage *mime_message); +void camel_mime_message_set_subject (CamelMimeMessage *mime_message, + GString *subject); +GString *camel_mime_message_get_subject (CamelMimeMessage *mime_message); +void camel_mime_message_set_from (CamelMimeMessage *mime_message, GString *from); +GString *camel_mime_message_get_from (CamelMimeMessage *mime_message); + +void camel_mime_message_add_recipient (CamelMimeMessage *mime_message, + GString *recipient_type, + GString *recipient); +void camel_mime_message_remove_recipient (CamelMimeMessage *mime_message, + GString *recipient_type, + GString *recipient); +GList *camel_mime_message_get_recipients (CamelMimeMessage *mime_message, + GString *recipient_type); + +void camel_mime_message_set_flag (CamelMimeMessage *mime_message, + GString *flag, gboolean value); +gboolean camel_mime_message_get_flag (CamelMimeMessage *mime_message, + GString *flag); + +guint camel_mime_message_get_message_number (CamelMimeMessage *mime_message); #ifdef __cplusplus } diff --git a/camel/camel-mime-part.c b/camel/camel-mime-part.c index 0fdf749d38..aa40144acf 100644 --- a/camel/camel-mime-part.c +++ b/camel/camel-mime-part.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-mime-part.h" #include <stdio.h> #include "gmime-content-field.h" diff --git a/camel/camel-mime-part.h b/camel/camel-mime-part.h index ad3ce17d2f..9f364c427c 100644 --- a/camel/camel-mime-part.h +++ b/camel/camel-mime-part.h @@ -104,23 +104,33 @@ GtkType camel_mime_part_get_type (void); /* public methods */ -void camel_mime_part_add_header (CamelMimePart *mime_part, GString *header_name, GString *header_value); -void camel_mime_part_remove_header (CamelMimePart *mime_part, GString *header_name); -GString *camel_mime_part_get_header (CamelMimePart *mime_part, GString *header_name); -void camel_mime_part_set_description (CamelMimePart *mime_part, GString *description); -GString *camel_mime_part_get_description (CamelMimePart *mime_part); -void camel_mime_part_set_disposition (CamelMimePart *mime_part, GString *disposition); -GString *camel_mime_part_get_disposition (CamelMimePart *mime_part); -void camel_mime_part_set_filename (CamelMimePart *mime_part, GString *filename); -GString *camel_mime_part_get_filename (CamelMimePart *mime_part); -GString *camel_mime_part_get_content_id (CamelMimePart *mime_part); -GString *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part); -void camel_mime_part_set_encoding (CamelMimePart *mime_part, GString *encoding); -GString *camel_mime_part_get_encoding (CamelMimePart *mime_part); -void camel_mime_part_set_content_languages (CamelMimePart *mime_part, GList *content_languages); -GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part); -void camel_mime_part_set_header_lines (CamelMimePart *mime_part, GList *header_lines); -GList *camel_mime_part_get_header_lines (CamelMimePart *mime_part); +void camel_mime_part_add_header (CamelMimePart *mime_part, + GString *header_name, + GString *header_value); +void camel_mime_part_remove_header (CamelMimePart *mime_part, + GString *header_name); +GString *camel_mime_part_get_header (CamelMimePart *mime_part, + GString *header_name); +void camel_mime_part_set_description (CamelMimePart *mime_part, + GString *description); +GString *camel_mime_part_get_description (CamelMimePart *mime_part); +void camel_mime_part_set_disposition (CamelMimePart *mime_part, + GString *disposition); +GString *camel_mime_part_get_disposition (CamelMimePart *mime_part); +void camel_mime_part_set_filename (CamelMimePart *mime_part, + GString *filename); +GString *camel_mime_part_get_filename (CamelMimePart *mime_part); +GString *camel_mime_part_get_content_id (CamelMimePart *mime_part); +GString *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part); +void camel_mime_part_set_encoding (CamelMimePart *mime_part, + GString *encoding); +GString *camel_mime_part_get_encoding (CamelMimePart *mime_part); +void camel_mime_part_set_content_languages (CamelMimePart *mime_part, + GList *content_languages); +GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part); +void camel_mime_part_set_header_lines (CamelMimePart *mime_part, + GList *header_lines); +GList *camel_mime_part_get_header_lines (CamelMimePart *mime_part); #ifdef __cplusplus } diff --git a/camel/camel-service.c b/camel/camel-service.c index 2ca3d6f352..645eaf3f09 100644 --- a/camel/camel-service.c +++ b/camel/camel-service.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-service.h" static GtkObjectClass *parent_class=NULL; diff --git a/camel/camel-session.c b/camel/camel-session.c index 42f681f626..5238b8d5eb 100644 --- a/camel/camel-session.c +++ b/camel/camel-session.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-session.h" #include "gstring-util.h" diff --git a/camel/camel-simple-data-wrapper.c b/camel/camel-simple-data-wrapper.c index 2d81fa62a9..775cf5ca58 100644 --- a/camel/camel-simple-data-wrapper.c +++ b/camel/camel-simple-data-wrapper.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-simple-data-wrapper.h" static CamelDataWrapperClass *parent_class=NULL; diff --git a/camel/camel-store.c b/camel/camel-store.c index 61c5216780..cedd452c44 100644 --- a/camel/camel-store.c +++ b/camel/camel-store.c @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-store.h" static GtkObjectClass *parent_class=NULL; diff --git a/camel/camel-stream-fs.c b/camel/camel-stream-fs.c index 09b193b229..0b70802943 100644 --- a/camel/camel-stream-fs.c +++ b/camel/camel-stream-fs.c @@ -21,7 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-stream-fs.h" #include <sys/types.h> #include <sys/stat.h> @@ -32,7 +32,7 @@ static CamelStreamClass *parent_class=NULL; -/* Returns the class for a CamelMimeMessage */ +/* Returns the class for a CamelStreamFS */ #define CS_CLASS(so) CAMEL_STREAM_FS_CLASS (GTK_OBJECT(so)->klass) static gint _read (CamelStream *stream, gchar *buffer, gint n); @@ -101,13 +101,17 @@ camel_stream_fs_new_with_name (GString *name, CamelStreamFsMode mode) CAMEL_LOG (FULL_DEBUG, "Entering CamelStream::new_with_name, name=\"%s\", mode=%d\n", name->str, mode); v = stat (name->str, &s); - if (mode & CAMEL_STREAM_FS_READ) - if (mode & CAMEL_STREAM_FS_WRITE) flags = O_RDWR | O_CREAT; - else flags = O_RDONLY; - else - if (mode & CAMEL_STREAM_FS_WRITE) flags = O_WRONLY | O_CREAT; - else return NULL; - + if (mode & CAMEL_STREAM_FS_READ){ + if (mode & CAMEL_STREAM_FS_WRITE) + flags = O_RDWR | O_CREAT; + else + flags = O_RDONLY; + } else { + if (mode & CAMEL_STREAM_FS_WRITE) + flags = O_WRONLY | O_CREAT; + else + return NULL; + } if ( (mode & CAMEL_STREAM_FS_READ) && !(mode & CAMEL_STREAM_FS_WRITE) ) if (v == -1) return NULL; diff --git a/camel/camel-stream-fs.h b/camel/camel-stream-fs.h index 046e90d26c..3570e8a9f9 100644 --- a/camel/camel-stream-fs.h +++ b/camel/camel-stream-fs.h @@ -52,7 +52,6 @@ typedef struct CamelStream parent_object; GString *name; int fd; - } CamelStreamFs; diff --git a/camel/camel-stream.c b/camel/camel-stream.c index 9f9e912bd8..5554b8fe38 100644 --- a/camel/camel-stream.c +++ b/camel/camel-stream.c @@ -21,22 +21,26 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ - +#include <config.h> #include "camel-stream.h" -static CamelStreamClass *parent_class=NULL; +static CamelStreamClass *parent_class = NULL; /* Returns the class for a CamelMimeMessage */ #define CS_CLASS(so) CAMEL_STREAM_CLASS (GTK_OBJECT(so)->klass) -static gint _read (CamelStream *stream, gchar *buffer, gint n); -static gint _write (CamelStream *stream, gchar *buffer, gint n); -static void _flush (CamelStream *stream); -static gint _available (CamelStream *stream); -static gboolean _eos (CamelStream *stream); -static void _close (CamelStream *stream); +static void +default_camel_flush (CamelStream *stream) +{ + /* nothing */ +} +static void +default_camel_close (CamelStream *stream) +{ + /* nothing */ +} static void camel_stream_class_init (CamelStreamClass *camel_stream_class) @@ -45,19 +49,16 @@ camel_stream_class_init (CamelStreamClass *camel_stream_class) parent_class = gtk_type_class (gtk_object_get_type ()); /* virtual method definition */ - camel_stream_class->read = _read; - camel_stream_class->write = _write; - camel_stream_class->flush = _flush; - camel_stream_class->available = _available; - camel_stream_class->eos = _eos; - camel_stream_class->close = _close; + camel_stream_class->read = NULL; + camel_stream_class->write = NULL; + camel_stream_class->flush = default_camel_flush; + camel_stream_class->available = NULL; + camel_stream_class->eos = NULL; + camel_stream_class->close = default_camel_close; /* virtual method overload */ - } - - GtkType camel_stream_get_type (void) { @@ -82,24 +83,17 @@ camel_stream_get_type (void) return camel_stream_type; } - - /** - * _read: read bytes from a stream - * @stream: stream - * @buffer: buffer where bytes are stored - * @n: max number of bytes to read - * + * camel_stream_read: + * @stream: a CamelStream. + * @buffer: buffer where bytes pulled from the stream are stored. + * @n: max number of bytes to read. * + * Read at most @n bytes from the @stream object and stores them + * in the buffer pointed at by @buffer. * * Return value: number of bytes actually read. **/ -static gint -_read (CamelStream *stream, gchar *buffer, gint n) -{ - -} - gint camel_stream_read (CamelStream *stream, gchar *buffer, gint n) { @@ -107,98 +101,84 @@ camel_stream_read (CamelStream *stream, gchar *buffer, gint n) } /** - * _write: read bytes to a stream - * @stream: the stream - * @buffer: byte buffer + * camel_stream_write: + * @stream: a CamelStream object. + * @buffer: buffer to write. * @n: number of bytes to write - * - * - * + * + * Write @n bytes from the buffer pointed at by @buffer into @stream. + * * Return value: the number of bytes actually written * in the stream. **/ -static gint -_write (CamelStream *stream, gchar *buffer, gint n) -{ - -} - gint camel_stream_write (CamelStream *stream, gchar *buffer, gint n) { - CS_CLASS (stream)->write (stream, buffer, n); + return CS_CLASS (stream)->write (stream, buffer, n); } - - /** - * _flush: flush pending changes - * @stream: the stream - * + * camel_stream_flush: + * @stream: a CamelStream object * + * Flushes the contents of the stream to its backing store. **/ -static void -_flush (CamelStream *stream) +void +camel_stream_flush (CamelStream *stream) { - + return CS_CLASS (stream)->flush (stream); } - - /** - * _available: return the number of bytes available for reading - * @stream: the stream - * - * Return the number of bytes available without blocking. + * camel_stream_available: + * @stream: a CamelStream object * - * Return value: the number of bytes available + * Return value: the number of bytes available. **/ static gint -_available (CamelStream *stream) +camel_stream_available (CamelStream *stream) { - + return CS_CLASS (stream)->available (stream); } - /** - * _eos: test if there are bytes left to read - * @stream: the stream - * + * camle_stream_eos: + * @stream: a CamelStream object * + * Test if there are bytes left to read on the @stream object. * - * Return value: true if all stream has been read + * Return value: %TRUE if all the contents on the stream has been read, or + * %FALSE if information is still available. **/ static gboolean -_eos (CamelStream *stream) +camel_stream_eos (CamelStream *stream) { - + return CS_CLASS (stream)->eos (stream); } /** - * _close: close a stream - * @stream: the stream - * + * camel_stram_close: + * @stream: a CamelStream object. * + * Close the @stream object. **/ -static void -_close (CamelStream *stream) -{ - -} - void camel_stream_close (CamelStream *stream) { CS_CLASS (stream)->close (stream); } - - - - /***************** Utility functions ********************/ +/** + * came_stream_write_strings: + * @stream: a CamelStream object. + * @...: A %NULL terminated list of strings. + * + * This is a utility function that writes the list of + * strings into the @stream object. + */ void camel_stream_write_strings (CamelStream *stream, ... ) { @@ -209,7 +189,7 @@ camel_stream_write_strings (CamelStream *stream, ... ) string = va_arg (args, char *); while (string) { - camel_stream_write_string(stream, string); + camel_stream_write_string (stream, string); string = va_arg (args, char *); } va_end (args); diff --git a/camel/camel-stream.h b/camel/camel-stream.h index 5fff22a24a..8434002757 100644 --- a/camel/camel-stream.h +++ b/camel/camel-stream.h @@ -52,13 +52,12 @@ typedef struct { GtkObjectClass parent_class; /* Virtual methods */ -gint (*read) (CamelStream *stream, gchar *buffer, gint n); -gint (*write) (CamelStream *stream, gchar *buffer, gint n); -void (*flush) (CamelStream *stream); -gint (*available) (CamelStream *stream); -gboolean (*eos) (CamelStream *stream); -void (*close) (CamelStream *stream); - + gint (*read) (CamelStream *stream, gchar *buffer, gint n); + gint (*write) (CamelStream *stream, gchar *buffer, gint n); + void (*flush) (CamelStream *stream); + gint (*available) (CamelStream *stream); + gboolean (*eos) (CamelStream *stream); + void (*close) (CamelStream *stream); } CamelStreamClass; @@ -68,9 +67,12 @@ GtkType camel_stream_get_type (void); /* public methods */ -gint camel_stream_read (CamelStream *stream, gchar *buffer, gint n); -gint camel_stream_write (CamelStream *stream, gchar *buffer, gint n); -void camel_stream_close (CamelStream *stream); +gint camel_stream_read (CamelStream *stream, gchar *buffer, gint n); +gint camel_stream_write (CamelStream *stream, gchar *buffer, gint n); +void camel_stream_flush (CamelStream *stream); +gint camel_stream_available (CamelStream *stream); +gboolean camel_stream_eos (CamelStream *stream); +void camel_stream_close (CamelStream *stream); /* utility macros and funcs */ #define camel_stream_write_string(stream, string) camel_stream_write ((stream), (string), strlen (string)) diff --git a/camel/gmime-content-field.c b/camel/gmime-content-field.c index 06e4384437..a86c7047ad 100644 --- a/camel/gmime-content-field.c +++ b/camel/gmime-content-field.c @@ -21,9 +21,7 @@ * USA */ - - - +#include <config.h> #include "gmime-content-field.h" #include "gstring-util.h" #include "camel-log.h" diff --git a/camel/gmime-utils.c b/camel/gmime-utils.c index 1555d27e7b..8c3db96cd4 100644 --- a/camel/gmime-utils.c +++ b/camel/gmime-utils.c @@ -21,8 +21,7 @@ * USA */ - - +#include <config.h> #include "gmime-utils.h" #include "gstring-util.h" #include "camel-log.h" @@ -112,14 +111,18 @@ _store_header_pair_from_gstring (GHashTable *header_table, GString *header_line) g_assert (header_table); if ( (header_line) && (header_line->str) ) { - dich_result = g_string_dichotomy(header_line, ':', &header_name, &header_value, DICHOTOMY_NONE); + dich_result = g_string_dichotomy ( + header_line, ':', &header_name, &header_value, + GSTRING_DICHOTOMY_NONE); if (dich_result != 'o') camel_log(WARNING, "store_header_pair_from_gstring : dichotomy result is %c" "header line is :\n--\n%s\n--\n"); else { - g_string_trim (header_value, " \t", TRIM_STRIP_LEADING | TRIM_STRIP_TRAILING); + g_string_trim ( + header_value, " \t", + GSTRING_TRIM_STRIP_LEADING | GSTRING_TRIM_STRIP_TRAILING); g_hash_table_insert (header_table, header_name, header_value); } } diff --git a/camel/gstring-util.c b/camel/gstring-util.c index c48a98d410..89cd263e85 100644 --- a/camel/gstring-util.c +++ b/camel/gstring-util.c @@ -23,7 +23,7 @@ - +#include <config.h> #include "gstring-util.h" #include "camel-log.h" @@ -64,7 +64,14 @@ g_string_clone(GString *string) /** - * g_string_dichotomy : return the strings before and/or after + * g_string_dichotomy: + * @sep : separator + * @prefix: pointer to be field by the prefix object + * the prefix is not returned when the given pointer is NULL + * @suffix: pointer to be field by the suffix object + * the suffix is not returned when the given pointer is NULL + * + * Return the strings before and/or after * the last occurence of the specified separator * * This routine returns the string before and/or after @@ -75,17 +82,12 @@ g_string_clone(GString *string) * suffix is set to NULL and result is set to 'n' * When the operation succedeed, the return value is 'o' * - * @sep : separator - * @prefix: pointer to be field by the prefix object - * the prefix is not returned when the given pointer is NULL - * @suffix: pointer to be field by the suffix object - * the suffix is not returned when the given pointer is NULL - * * @Return Value : result of the operation ('o', 'l' or 'n') * **/ gchar -g_string_dichotomy (GString *string, gchar sep, GString **prefix, GString **suffix, DichotomyOption options) +g_string_dichotomy (GString *string, gchar sep, GString **prefix, GString **suffix, + GStringDichotomyOption options) { gchar *str, *tmp; gint pos, len, first; @@ -96,17 +98,19 @@ g_string_dichotomy (GString *string, gchar sep, GString **prefix, GString **suff g_assert( tmp=string->str ); len = strlen(tmp); if (!len) { - if (prefix) *prefix=NULL; - if (suffix) *suffix=NULL; + if (prefix) + *prefix=NULL; + if (suffix) + *suffix=NULL; CAMEL_LOG(FULL_DEBUG,"string_dichotomy: string is empty\n"); return 'n'; } first = 0; - if ( (options & DICHOTOMY_STRIP_LEADING ) && (tmp[first] == sep) ) + if ( (options & GSTRING_DICHOTOMY_STRIP_LEADING ) && (tmp[first] == sep) ) do {first++;} while ( (first<len) && (tmp[first] == sep) ); - if (options & DICHOTOMY_STRIP_TRAILING ) + if (options & GSTRING_DICHOTOMY_STRIP_TRAILING ) while (tmp[len-1] == sep) len--; @@ -117,7 +121,7 @@ g_string_dichotomy (GString *string, gchar sep, GString **prefix, GString **suff return 'n'; } - if (options & DICHOTOMY_RIGHT_DIR) { + if (options & GSTRING_DICHOTOMY_RIGHT_DIR) { pos = len; do { @@ -253,7 +257,7 @@ g_string_list_free (GList *string_list) GList * -g_string_split (GString *string, char sep, gchar *trim_chars, TrimOption trim_options) +g_string_split (GString *string, char sep, gchar *trim_chars, GStringTrimOption trim_options) { GList *result = NULL; gint first, last, pos; @@ -296,10 +300,8 @@ g_string_split (GString *string, char sep, gchar *trim_chars, TrimOption trim_op } - - void -g_string_trim (GString *string, gchar *chars, TrimOption options) +g_string_trim (GString *string, gchar *chars, GStringTrimOption options) { gint first_ok; gint last_ok; @@ -308,24 +310,31 @@ g_string_trim (GString *string, gchar *chars, TrimOption options) CAMEL_LOG(FULL_DEBUG,"**\nentering g_string_trim::\n"); - if ((!string) || (!string->str)) return; + if ((!string) || (!string->str)) + return; str = string->str; length = strlen (str); - if (!length) return; + if (!length) + return; first_ok = 0; last_ok = length - 1; CAMEL_LOG (FULL_DEBUG,"g_string_trim:: trim_options:%d\n", options); - if (options & TRIM_STRIP_LEADING) + if (options & GSTRING_TRIM_STRIP_LEADING) while ( (first_ok <= last_ok) && (strchr (chars, str[first_ok])) ) first_ok++; - if (options & TRIM_STRIP_TRAILING) + if (options & GSTRING_TRIM_STRIP_TRAILING) while ( (first_ok <= last_ok) && (strchr (chars, str[last_ok])) ) last_ok++; - CAMEL_LOG (FULL_DEBUG,"g_string_trim::\n\t\"%s\":first ok:%d last_ok:%d\n", string->str, first_ok, last_ok); - if (first_ok>0) g_string_erase (string, 0, first_ok); - if (last_ok<length-1) g_string_truncate (string, last_ok - first_ok +1); + CAMEL_LOG (FULL_DEBUG,"g_string_trim::\n\t\"%s\":first ok:%d last_ok:%d\n", + string->str, first_ok, last_ok); + + if (first_ok > 0) + g_string_erase (string, 0, first_ok); + + if (last_ok < length-1) + g_string_truncate (string, last_ok - first_ok +1); } diff --git a/camel/gstring-util.h b/camel/gstring-util.h index 419895831c..7a82f9ab01 100644 --- a/camel/gstring-util.h +++ b/camel/gstring-util.h @@ -35,33 +35,37 @@ extern "C" { #include <glib.h> typedef enum { - DICHOTOMY_NONE = 0, - DICHOTOMY_RIGHT_DIR = 1, - DICHOTOMY_STRIP_TRAILING = 2, - DICHOTOMY_STRIP_LEADING = 4, + GSTRING_DICHOTOMY_NONE = 0, + GSTRING_DICHOTOMY_RIGHT_DIR = 1, + GSTRING_DICHOTOMY_STRIP_TRAILING = 2, + GSTRING_DICHOTOMY_STRIP_LEADING = 4, -} DichotomyOption; +} GStringDichotomyOption; typedef enum { - TRIM_NONE = 0, - TRIM_STRIP_TRAILING = 1, - TRIM_STRIP_LEADING = 2, - -} TrimOption; + GSTRING_TRIM_NONE = 0, + GSTRING_TRIM_STRIP_TRAILING = 1, + GSTRING_TRIM_STRIP_LEADING = 2, +} GStringTrimOption; -gboolean g_string_equals(GString *string1, GString *string2); -GString *g_string_clone(GString *string); -gchar g_string_dichotomy( GString *string, gchar sep, GString **prefix, GString **suffix, DichotomyOption options); -void g_string_append_g_string(GString *dest_string, GString *other_string); +gboolean g_string_equals (GString *string1, GString *string2); +GString *g_string_clone (GString *string); +gchar g_string_dichotomy (GString *string, gchar sep, + GString **prefix, GString **suffix, + GStringDichotomyOption options); +void g_string_append_g_string (GString *dest_string, + GString *other_string); -gboolean g_string_equal_for_hash (gconstpointer v, gconstpointer v2); +gboolean g_string_equal_for_hash (gconstpointer v, gconstpointer v2); gboolean g_string_equal_for_glist (gconstpointer v, gconstpointer v2); -guint g_string_hash (gconstpointer v); -void g_string_list_free (GList *string_list); +guint g_string_hash (gconstpointer v); +void g_string_list_free (GList *string_list); -GList *g_string_split (GString *string, char sep, gchar *trim_chars, TrimOption trim_options); -void g_string_trim (GString *string, gchar *chars, TrimOption options); +GList *g_string_split (GString *string, char sep, + gchar *trim_chars, GStringTrimOption trim_options); +void g_string_trim (GString *string, gchar *chars, + GStringTrimOption options); #ifdef __cplusplus } diff --git a/camel/url-util.c b/camel/url-util.c index 1b784385f5..b9ee4c653b 100644 --- a/camel/url-util.c +++ b/camel/url-util.c @@ -34,7 +34,7 @@ /* XXX TODO: recover the words between #'s or ?'s after the path */ - +#include <config.h> #include "url-util.h" /* general item finder */ diff --git a/devel-docs/query/virtual-folder-in-depth.sgml b/devel-docs/query/virtual-folder-in-depth.sgml index fc85132673..e6ba7ecf18 100644 --- a/devel-docs/query/virtual-folder-in-depth.sgml +++ b/devel-docs/query/virtual-folder-in-depth.sgml @@ -3,393 +3,405 @@ <!-- SGMLized by Bertrand <Bertrand.Guiheneuf@inria.fr> --> <article id="index"> - <artheader> - <authorgroup> - <author> - <firstname>Giao</firstname> - <surname>Nguyen</surname> - </author> - </authorgroup> - <title>An in-depth look at the virtual folder mechanism</title> - <abstract> - <para> - This document describes a different way of approaching mail - organization and how all things are possible in this brave new - world. This document does not describe physical storage issues nor - interface issues. - </para> - <para> - Historically mail has been organized into folders. These folders - usually mapped to a single storage medium. The relationship between - mail organization and storage medium was one to one. There was one - mail organization for every storage medium. This scheme had its - limitations. - </para> - <para> - Efforts at categorizations are only meaningful at the instance that - one categorized. To find any piece of data, regardless of how well - it was categorized, required some amount of searching. Therefore, any - attempts to nullify searching is doomed to fail. It's time to embrace - searching as a way of life. - </para> - <para> - These are the terms and their definitions. The example rules used are - based on the syntax for VM (http://www.wonderworks.com/vm/) by Kyle - Jones whose ideas form the basis for this. I'm only adding the - existence of summary files to aid in scaling. I currently use VM and - it's virtual-folder rules for my daily mail purposes. To date, my only - complaints are speed (it has no caches) and for the unitiated, it's - not very user-friendly. - </para> - <para> - Comments, questions, rants, etc. should be directed at Giao Nguyen - (grail@cafebabe.org) who will try to address issues in a timely - manner. - </para> - </abstract> -</artheader> - <sect1 id="definitions"> - <title>Definitions</title> - <sect2> - <title>Store</title> - <para> - A location where mail can be found. This may be a file (Berkeley - mbox), directory (MH), IMAP server, POP3 server, Exchange server, - Lotus Notes server, a stack of Post-Its by your monitor fed through - some OCR system. - </para> - </sect2> - <sect2> - <title>Message</title> - <para> - An individual mail message. - </para> - </sect2> - <sect2> - <title>Vfolder</title> - <para> - A group of messages sharing some commonality. This is the result of a - query. The vfolder maybe contained in a store, but it is not necessary - that a store holds only one vfolder. There is always an implicit - vfolder rule which matches all messages. A store contains the vfolder - which is the result of the query (any). It's short for virtual folder - or maybe view folder. I dunno. - </para> - </sect2> - <sect2> - <title>Default-vfolder</title> - <para> - The vfolder defined by (any) applied to the store. This is not the - inbox. The inbox could easily be defined by a query. A default rule - for the inbox could be (new) but it doesn't have to be. Mine happens - to be (or (unread) (new)). - </para> - </sect2> - <sect2> - <title>Folder</title> - <para> - The classical mail folder approach: one message organization per - store. - </para> - </sect2> - <sect2> - <title>Query</title> - <para> - A search for messages. The result of this is a vfolder. There are two - kinds of queries: named queries and lambda queries. More on this - later. - </para> - </sect2> - <sect2> - <title>Summary file </title> - <para> - An external file that contains pointers to messages which are matches - for a named query. In addition to pointers, the summary file should - also contain signatures of the store for sanity checks. When the term - "index" is used as a verb, it means to build a summary file for a - given name-value pair. - </para> - </sect2> - </sect1> + <artheader> + <authorgroup> + <author> + <firstname>Giao</firstname> + <surname>Nguyen</surname> + </author> + </authorgroup> - <sect1> - <title>Queries</title> - <para> - Named queries are analogous to classical mail folders. Because named - queries maybe reused, summary files are kept as caches to reduce - the overall cost of viewing a vfolder. Summary files are superior to - folders in that they allow for the same messages to appear in multiple - vfolders without message duplications. Duplications of messages - defeats attempts at tagging a message with additional user information - like annotations. Named queries will define folders. - </para> - <para> - Lambda queries are similar to named queries except that they have no - name. These are created on the fly by the user to filter out or - include certain messages. - </para> - <para> - All queries can be layered on top of each other. A lambda query can be - layered on a named query and a named query can be layered on a lambda - query. The possibilities are endless. - </para> - <para> - The layerings can be done as boolean operations (and, or, not). Short - circuiting should be used. - </para> - <para> - Examples: - <programlisting> - (and (author "Giao") - (unread)) - </programlisting> - The (unread) query should only be evaluated on the results of (author - "Giao"). - <programlisting> - (or (author "Giao") - (unread)) - </programlisting> - Both of these queries should be evaluated. Any matches are added to the - resulting vfolder. - </para> - </sect1> - - <sect1> - <title>Summary files</title> - <para> - Summary files are only meaningful when applied to the context of the - default-vfolder of a store. - </para> - <para> - Summary files should be generated for queries of the form: - <programlisting> - (function "constant value") - </programlisting> - Summary files should never be generated for queries of the form: - <programlisting> - (function (function1)) - - (and (function "value") - (another-function "another value")) - </programlisting> - Given a query of the form: - <programlisting> - (and (function "value") - (another-function "another value")) - </programlisting> - The system should use one summary file for (function "value") and - another summary file for (another-function "another value"). I will - call the prior form the "plain form". - </para> - <para> - It should be noted that the signature of the store should be based on - the assumption that new data may have been added to the store since - the application generated the summary file. Signatures generated on - the entirety of the store will most likely be meaningless for things - like POP/IMAP servers. - </para> - </sect1> + <title>An in-depth look at the virtual folder mechanism</title> + <abstract> + <para> + This document describes a different way of approaching mail + organization and how all things are possible in this brave new + world. This document does not describe physical storage issues + nor interface issues. + </para> + <para> + Historically mail has been organized into folders. These + folders usually mapped to a single storage medium. The + relationship between mail organization and storage medium was + one to one. There was one mail organization for every storage + medium. This scheme had its limitations. + </para> + <para> + Efforts at categorizations are only meaningful at the instance that + one categorized. To find any piece of data, regardless of how well + it was categorized, required some amount of searching. Therefore, any + attempts to nullify searching is doomed to fail. It's time to embrace + searching as a way of life. + </para> + <para> + These are the terms and their definitions. The example rules used are + based on the syntax for VM (http://www.wonderworks.com/vm/) by Kyle + Jones whose ideas form the basis for this. I'm only adding the + existence of summary files to aid in scaling. I currently use VM and + it's virtual-folder rules for my daily mail purposes. To date, my only + complaints are speed (it has no caches) and for the unitiated, it's + not very user-friendly. + </para> + <para> + Comments, questions, rants, etc. should be directed at Giao Nguyen + (grail@cafebabe.org) who will try to address issues in a timely + manner. + </para> + </abstract> + </artheader> - <sect1> - <title>Incremental indexing</title> - <para> - When new messages are detected, all known queries should be evaluated - on the new messages. vfolders should be notified of new messages that - are positive matches for their queries. The indexes generated by this - process should be merged into the current indexes for the vfolder. - </para> - </sect1> + <!-- Definitions --> + <sect1 id="definitions"> + <title>Definitions</title> + <sect2> + <title>Store</title> + <para> + A location where mail can be found. This may be a file (Berkeley + mbox), directory (MH), IMAP server, POP3 server, Exchange server, + Lotus Notes server, a stack of Post-Its by your monitor fed through + some OCR system. + </para> + </sect2> - <sect1> - <title>Can I have multiple stores?</title> - <para> - I don't see why not. Again, the inbox is a vfolder so you can get a - unified inbox consisting of all new mail sent to all your stores or - your can get inboxes for each store or any combination your heart - desire. You get your cake, eat it, and someone else cleans the dishes! - </para> - </sect1> + <sect2> + <title>Message</title> + <para> + An individual mail message. + </para> + </sect2> + <sect2> + <title>Vfolder</title> + <para> + A group of messages sharing some commonality. This is the result of a + query. The vfolder maybe contained in a store, but it is not necessary + that a store holds only one vfolder. There is always an implicit + vfolder rule which matches all messages. A store contains the vfolder + which is the result of the query (any). It's short for virtual folder + or maybe view folder. I dunno. + </para> + </sect2> + <sect2> + <title>Default-vfolder</title> + <para> + The vfolder defined by (any) applied to the store. This is not the + inbox. The inbox could easily be defined by a query. A default rule + for the inbox could be (new) but it doesn't have to be. Mine happens + to be (or (unread) (new)). + </para> + </sect2> + <sect2> + <title>Folder</title> + <para> + The classical mail folder approach: one message organization per + store. + </para> + </sect2> + <sect2> + <title>Query</title> + <para> + A search for messages. The result of this is a vfolder. There are two + kinds of queries: named queries and lambda queries. More on this + later. + </para> + </sect2> + <sect2> + <title>Summary file </title> + <para> + An external file that contains pointers to messages which are matches + for a named query. In addition to pointers, the summary file should + also contain signatures of the store for sanity checks. When the term + "index" is used as a verb, it means to build a summary file for a + given name-value pair. + </para> + </sect2> + </sect1> - <sect1> - <title>Why all this?</title> - <para> - Consider the dynamic nature of the following query: - <programlisting> - (and (author "Giao") - (sent-after (today-midnight))) - </programlisting> - today-midnight would be a function that is evaluated at run-time to - calculate the appropriate object. - </para> - </sect1> + <!-- Queries --> + <sect1> + <title>Queries</title> + <para> + Named queries are analogous to classical mail folders. Because named + queries maybe reused, summary files are kept as caches to reduce + the overall cost of viewing a vfolder. Summary files are superior to + folders in that they allow for the same messages to appear in multiple + vfolders without message duplications. Duplications of messages + defeats attempts at tagging a message with additional user information + like annotations. Named queries will define folders. + </para> + <para> + Lambda queries are similar to named queries except that they have no + name. These are created on the fly by the user to filter out or + include certain messages. + </para> + <para> + All queries can be layered on top of each other. A lambda query can be + layered on a named query and a named query can be layered on a lambda + query. The possibilities are endless. + </para> + <para> + The layerings can be done as boolean operations (and, or, not). Short + circuiting should be used. + </para> + <para> + Examples: + <programlisting> +(and (author "Giao") + (unread)) + </programlisting> + The (unread) query should only be evaluated on the results of (author + "Giao"). + <programlisting> +(or (author "Giao") + (unread)) + </programlisting> + Both of these queries should be evaluated. Any matches are added to the + resulting vfolder. + </para> + </sect1> - <sect1> - <title>Scenarios of usage and their solutions</title> - <sect2> - <title>Mesage alterations</title> - <para> - This is a fuzzy area that should be left to the UI to handle. Messages - are altered. Read status are altered when a new message is read for - example. How do we handle this if our query is for unread messages? - Upon viewing the state would change. - </para> - <para> - One idea is to not evaluate the queries unless we're changing between - vfolder views. This assumes that one can only view a particular - vfolder at a time. For multi-vfolder viewing, a message change should - propagate through the vfolder system. Certain effects (as in our - example) would not be intuitive. - </para> - <para> - It would not be a clean solution to make special cases but they may be - necessary where certain defined fields are ignored when they are - changed. Some combination of the above rules can be used. I don't - think it's an easy solution. - </para> - </sect2> - <sect2> - <title>Message inclusion and exclusion</title> - <para> - Messages are included and excluded also with queries. The final query - will have the form of: - <programlisting> - (and (author "Giao") - (criteria value) - (not (criteria other-value))) - </programlisting> - Userland criterias may be a label of some sort. These may be userland - labels or Message-IDs. What are the performance issues involved in - this? With short circuiting, it's not a major problem. - </para> - <para> - The criterias and values are determined by the UI. The vfolder - mechanism isn't concerned with such issues. - </para> - <para> - Messages can be included and excluded at will. The idea is often - called "arbitrary inclusion/exclusion". This can be done by - Message-IDs or other fields. It's been noted that Message-IDs are not - unique. - </para> - <para> - I propose that any given vfolder is allocated an inclusion label and an - exclusion label. These should be randomly generated. This should be - part of the vfolder description. It should be noted that the vfolder - description has not been drafted yet. - </para> - <para> - The result is such that the rules for a given named query is: - <programlisting> - (and (user-query) - (label inclusion-label) - (not exclusion-label)) - </programlisting> - </para> - </sect2> - <sect2> - <title>Query scheduling</title> - <para> - Consider the following extremely dynamic queries: - <programlisting> - A: - (and (author "Giao") - (sent-after (today-midnight))) - - B: - (and (sent-after (today-midnight)) - (author "Giao")) - - C: - (or (author "Giao") - (sent-after (today-midnight))) - </programlisting> - Query A would be significantly faster because (author "Giao") is not - dynamic. A summary file could be generated for this query. Query B is - slow and can be optimized if there was a query compiler of some - sort. Query C demonstrates a query in which there is no good - optimization which can be applied. These come with a certain amount of - baggage. - </para> - <para> - It seems then that for boolean 'and' operations, plain forms should be - moved forward and other queries should be moved such that they are - evaluated later. I would expect that the majority of queries would be - of the plain form. - </para> - <para> - First is that the summary file is tied to the query and the store - where the query originates from. Second, a hashing function for - strings needs to be calculated for the query so that the query and the - summary file can be associated. This hashing function could be similar - to the hashing function described in Rob Pike's "The Practice of - Programming". (FIXME: Stick page number here) - </para> - </sect2> - <sect2> - <title>Archives</title> - <para> - Many people are concerned that archives won't be preserved, archives - aren't supported, and many other archive related issues. This is the - short version. - </para> - <para> - Archives are just that, archives. Archives are stores. Take your - vfolder, export it to a store. You are done. If you load up the store - again, then the default-vfolder of that store is the view of the - vfolder, except the query is different. - </para> - <para> - The point to vfolder is not to do away with classical folder - representation but to move the queries to the front where it would - make data management easier for people who don't think in terms of - files but in terms of queries because ordinary people don't think in - terms of files. - </para> - </sect2> - </sect1> + <!-- Summary files --> + <sect1> + <title>Summary files</title> + <para> + Summary files are only meaningful when applied to the context of the + default-vfolder of a store. + </para> + <para> + Summary files should be generated for queries of the form: + <programlisting> +(function "constant value") + </programlisting> + Summary files should never be generated for queries of the form: + <programlisting> + (function (function1)) + + (and (function "value") + (another-function "another value")) + </programlisting> + Given a query of the form: + <programlisting> + (and (function "value") + (another-function "another value")) + </programlisting> + The system should use one summary file for (function "value") and + another summary file for (another-function "another value"). I will + call the prior form the "plain form". + </para> + <para> + It should be noted that the signature of the store should be based on + the assumption that new data may have been added to the store since + the application generated the summary file. Signatures generated on + the entirety of the store will most likely be meaningless for things + like POP/IMAP servers. + </para> + </sect1> - <sect1> - <title>Miscellany</title> - <sect2> - <title>Annotations</title> - <para> - There should be a scheme to add annotations to messages. Common mail - user agents have used a tag in the message header to mark messages as - read/unread for example. Extending on this we have the ability to add - our own data to a message to add meaning to it. If we have a good - scheme for doing this, new possibilities are opened. - </para> - <sect3> - <title>Keywords</title> + <!-- Incremental Indexing --> + <sect1> + <title>Incremental indexing</title> <para> - When sending a message, a message could have certain keywords attached - to it. While this can be done with the subject line, the subject line - has a tendency to be munged by other mail applications. One popular - example is the "[rR]e:" prefix. Using the subject line also breaks the - "contract" with other mail user agents. Using keywords in another - field in the message header allows the sender to assist the recipient - in organizing data automatically. Note that the sender can only - provide hints as the sender is unlikely to know the organization - schemes of the recipient. + When new messages are detected, all known queries should be evaluated + on the new messages. vfolders should be notified of new messages that + are positive matches for their queries. The indexes generated by this + process should be merged into the current indexes for the vfolder. </para> - </sect3> - </sect2> - <sect2> - <title>Scope</title> - <para> - Let us assume that we have multiple stores. Does a query work on a - given store? Or does it work on all stores? Or is it configurable such - that a query can work on a user-selected list of stores? - </para> - </sect2> - </sect1> + </sect1> - <sect1> - <title>Alternatives to the above</title> - <para> - Jim Meyer (purp@selequa.com) is putting some notes on where - annotations needs to be located. They'll be located here as well as - any contributions I may have to them. - </para> - </sect1> + <!-- Can I have multiple stores --> + <sect1> + <title>Can I have multiple stores?</title> + <para> + I don't see why not. Again, the inbox is a vfolder so you can get a + unified inbox consisting of all new mail sent to all your stores or + your can get inboxes for each store or any combination your heart + desire. You get your cake, eat it, and someone else cleans the dishes! + </para> + </sect1> + + <!-- Why all this? --> + <sect1> + <title>Why all this?</title> + <para> + Consider the dynamic nature of the following query: + <programlisting> +(and (author "Giao") + (sent-after (today-midnight))) + </programlisting> + today-midnight would be a function that is evaluated at run-time to + calculate the appropriate object. + </para> + </sect1> + + <!-- Scenarios of usage and their solutions --> + <sect1> + <title>Scenarios of usage and their solutions</title> + <sect2> + <title>Mesage alterations</title> + <para> + This is a fuzzy area that should be left to the UI to handle. Messages + are altered. Read status are altered when a new message is read for + example. How do we handle this if our query is for unread messages? + Upon viewing the state would change. + </para> + <para> + One idea is to not evaluate the queries unless we're changing between + vfolder views. This assumes that one can only view a particular + vfolder at a time. For multi-vfolder viewing, a message change should + propagate through the vfolder system. Certain effects (as in our + example) would not be intuitive. + </para> + <para> + It would not be a clean solution to make special cases but they may be + necessary where certain defined fields are ignored when they are + changed. Some combination of the above rules can be used. I don't + think it's an easy solution. + </para> + </sect2> + <sect2> + <title>Message inclusion and exclusion</title> + <para> + Messages are included and excluded also with queries. The final query + will have the form of: + <programlisting> + (and (author "Giao") + (criteria value) + (not (criteria other-value))) + </programlisting> + Userland criterias may be a label of some sort. These may be userland + labels or Message-IDs. What are the performance issues involved in + this? With short circuiting, it's not a major problem. + </para> + <para> + The criterias and values are determined by the UI. The vfolder + mechanism isn't concerned with such issues. + </para> + <para> + Messages can be included and excluded at will. The idea is often + called "arbitrary inclusion/exclusion". This can be done by + Message-IDs or other fields. It's been noted that Message-IDs are not + unique. + </para> + <para> + I propose that any given vfolder is allocated an inclusion label and an + exclusion label. These should be randomly generated. This should be + part of the vfolder description. It should be noted that the vfolder + description has not been drafted yet. + </para> + <para> + The result is such that the rules for a given named query is: + <programlisting> + (and (user-query) + (label inclusion-label) + (not exclusion-label)) + </programlisting> + </para> + </sect2> + <sect2> + <title>Query scheduling</title> + <para> + Consider the following extremely dynamic queries: + <programlisting> + A: + (and (author "Giao") + (sent-after (today-midnight))) + + B: + (and (sent-after (today-midnight)) + (author "Giao")) + + C: + (or (author "Giao") + (sent-after (today-midnight))) + </programlisting> + Query A would be significantly faster because (author "Giao") is not + dynamic. A summary file could be generated for this query. Query B is + slow and can be optimized if there was a query compiler of some + sort. Query C demonstrates a query in which there is no good + optimization which can be applied. These come with a certain amount of + baggage. + </para> + <para> + It seems then that for boolean 'and' operations, plain forms should be + moved forward and other queries should be moved such that they are + evaluated later. I would expect that the majority of queries would be + of the plain form. + </para> + <para> + First is that the summary file is tied to the query and the store + where the query originates from. Second, a hashing function for + strings needs to be calculated for the query so that the query and the + summary file can be associated. This hashing function could be similar + to the hashing function described in Rob Pike's "The Practice of + Programming". (FIXME: Stick page number here) + </para> + </sect2> + <sect2> + <title>Archives</title> + <para> + Many people are concerned that archives won't be preserved, archives + aren't supported, and many other archive related issues. This is the + short version. + </para> + <para> + Archives are just that, archives. Archives are stores. Take your + vfolder, export it to a store. You are done. If you load up the store + again, then the default-vfolder of that store is the view of the + vfolder, except the query is different. + </para> + <para> + The point to vfolder is not to do away with classical folder + representation but to move the queries to the front where it would + make data management easier for people who don't think in terms of + files but in terms of queries because ordinary people don't think in + terms of files. + </para> + </sect2> + </sect1> + + <!-- Miscellany --> + <sect1> + <title>Miscellany</title> + <sect2> + <title>Annotations</title> + <para> + There should be a scheme to add annotations to messages. Common mail + user agents have used a tag in the message header to mark messages as + read/unread for example. Extending on this we have the ability to add + our own data to a message to add meaning to it. If we have a good + scheme for doing this, new possibilities are opened. + </para> + <sect3> + <title>Keywords</title> + <para> + When sending a message, a message could have certain keywords attached + to it. While this can be done with the subject line, the subject line + has a tendency to be munged by other mail applications. One popular + example is the "[rR]e:" prefix. Using the subject line also breaks the + "contract" with other mail user agents. Using keywords in another + field in the message header allows the sender to assist the recipient + in organizing data automatically. Note that the sender can only + provide hints as the sender is unlikely to know the organization + schemes of the recipient. + </para> + </sect3> + </sect2> + <sect2> + <title>Scope</title> + <para> + Let us assume that we have multiple stores. Does a query work on a + given store? Or does it work on all stores? Or is it configurable such + that a query can work on a user-selected list of stores? + </para> + </sect2> + </sect1> + + <!-- Alternatives to the above --> + <sect1> + <title>Alternatives to the above</title> + <para> + Jim Meyer (purp@selequa.com) is putting some notes on where + annotations needs to be located. They'll be located here as well as + any contributions I may have to them. + </para> + </sect1> </article> |