Check for LOGIN xxxx as well if debug is on, so we dont print passwords to
authorNot Zed <NotZed@Ximian.com>
Tue, 7 May 2002 07:31:26 +0000 (07:31 +0000)
committerMichael Zucci <zucchi@src.gnome.org>
Tue, 7 May 2002 07:31:26 +0000 (07:31 +0000)
2002-05-07  Not Zed  <NotZed@Ximian.com>

        * camel-remote-store.c (remote_send_string): Check for LOGIN xxxx
        as well if debug is on, so we dont print passwords to evolution
        logs.

        * providers/imap/camel-imap-utils.c (imap_is_atom_char): This was
        really broken.  1. isprint() is locale dependent, and 2. it looked
        up an 8 bit value in a 7 bit table without truncating it.  I've
        removed the isprint() stuff and just put it directly into the
        special table, which i've expanded to the right size too.

        * providers/imap/*: Applied patch from Preston Elder
        <prez@magick.tm> to make camel only use literals if it needs to
        for simple strings.  Changed slightly to use imap_is_atom() and
        more consistent formatting.
        providers/imap/camel-imap-utils.c (imap_is_atom): Chagned from
        imap_needs_quoting().

        ** Merged in camel-object2 branch.  Simpler camelobject
        implementation + object args interface.

        * camel.c (camel_init): Call camel_object_get_type() to make sure
        camel_object_type is initialised.

        * camel-object.h (CAMEL_OBJECT_TYPE): Changed to return global
        camel_object_type pointer, not call camel_object_get_type.

49 files changed:
camel/ChangeLog
camel/Makefile.am
camel/camel-arg.c [new file with mode: 0644]
camel/camel-arg.h [new file with mode: 0644]
camel/camel-block-file.c
camel/camel-folder-search.c
camel/camel-folder-search.h
camel/camel-folder-summary.h
camel/camel-folder.c
camel/camel-html-parser.h
camel/camel-index.c
camel/camel-index.h
camel/camel-mime-filter-basic.h
camel/camel-mime-filter-bestenc.h
camel/camel-mime-filter-charset.h
camel/camel-mime-filter-from.h
camel/camel-mime-filter-html.h
camel/camel-mime-filter-index.h
camel/camel-mime-parser.h
camel/camel-news-address.h
camel/camel-object.c
camel/camel-object.h
camel/camel-partition-table.h
camel/camel-remote-store.c
camel/camel-store-summary.h
camel/camel-store.c
camel/camel-stream-filter.h
camel/camel-stream-null.h
camel/camel-text-index.h
camel/camel-vee-folder.c
camel/camel-vee-folder.h
camel/camel-vee-store.c
camel/camel-vee-store.h
camel/camel.c
camel/providers/imap/camel-imap-command.c
camel/providers/imap/camel-imap-search.h
camel/providers/imap/camel-imap-store.c
camel/providers/imap/camel-imap-summary.c
camel/providers/imap/camel-imap-summary.h
camel/providers/imap/camel-imap-utils.c
camel/providers/imap/camel-imap-utils.h
camel/providers/local/camel-local-store.c
camel/providers/local/camel-local-summary.h
camel/providers/local/camel-mbox-summary.h
camel/providers/local/camel-spool-summary.h
camel/providers/nntp/camel-nntp-stream.h
camel/providers/nntp/camel-nntp-summary.h
camel/providers/pop3/camel-pop3-engine.h
camel/providers/pop3/camel-pop3-stream.h

index 2e85fa9..4bd0a93 100644 (file)
@@ -1,3 +1,31 @@
+2002-05-07  Not Zed  <NotZed@Ximian.com>
+
+       * camel-remote-store.c (remote_send_string): Check for LOGIN xxxx
+       as well if debug is on, so we dont print passwords to evolution
+       logs.
+
+       * providers/imap/camel-imap-utils.c (imap_is_atom_char): This was
+       really broken.  1. isprint() is locale dependent, and 2. it looked
+       up an 8 bit value in a 7 bit table without truncating it.  I've
+       removed the isprint() stuff and just put it directly into the
+       special table, which i've expanded to the right size too.
+
+       * providers/imap/*: Applied patch from Preston Elder
+       <prez@magick.tm> to make camel only use literals if it needs to
+       for simple strings.  Changed slightly to use imap_is_atom() and
+       more consistent formatting.
+       providers/imap/camel-imap-utils.c (imap_is_atom): Chagned from
+       imap_needs_quoting().
+
+       ** Merged in camel-object2 branch.  Simpler camelobject
+       implementation + object args interface.
+
+       * camel.c (camel_init): Call camel_object_get_type() to make sure
+       camel_object_type is initialised.
+
+       * camel-object.h (CAMEL_OBJECT_TYPE): Changed to return global
+       camel_object_type pointer, not call camel_object_get_type.
+       
 2002-05-06  Jeffrey Stedfast  <fejj@ximian.com>
 
        * providers/pop3/camel-pop3-store.c (pop3_try_authenticate): If
        used the full names.
        (MONTH_CHARS): Same as above but for months.
 
+2002-04-15  Not Zed  <NotZed@Ximian.com>
+
+       * *.c: Fix callers for api changes to camel-object, mainly
+       declare_event->add_event, and classfuncs->klass, and a couple
+        of missing #include <config.h>'s
+
+       * camel-arg.[ch], Makefile.am: New support code for
+       camel_object_get/set arg.
+
+       * *.h: Fixed all uses of get_type to return a CamelType rather
+       than a guint (now a pointer).
+
+       * camel-object.[ch]: Major cleanup of object implementation.  Also
+       added a get/set interface, and some debugging options.
+
 2002-04-11  Not Zed  <NotZed@Ximian.com>
 
        * providers/local/camel-spool-summary.c (spool_summary_sync_full):
index d38787c..7937c7a 100644 (file)
@@ -20,6 +20,7 @@ INCLUDES = -I.. -I$(srcdir)/..                                \
 libcamel_la_SOURCES =                          \
        broken-date-parser.c                    \
        camel-address.c                         \
+       camel-arg.c                             \
        camel-block-file.c                      \
        camel-cipher-context.c                  \
        camel-cms-context.c                     \
@@ -115,6 +116,7 @@ libcamel_la_SOURCES =                               \
 libcamelinclude_HEADERS =                      \
        broken-date-parser.h                    \
        camel-address.h                         \
+       camel-arg.h                             \
        camel-block-file.h                      \
        camel-charset-map.h                     \
        camel-cipher-context.h                  \
diff --git a/camel/camel-arg.c b/camel/camel-arg.c
new file mode 100644 (file)
index 0000000..bc6ecec
--- /dev/null
@@ -0,0 +1,124 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
+ * Author:
+ *  Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "camel-arg.h"
+
+int camel_argv_build(CamelArgV *tv)
+{
+       register guint32 tag;
+       register int i;
+       register CamelArg *a;
+       int more = TRUE;
+
+       for (i=0;i<CAMEL_ARGV_MAX;i++) {
+               a = &tv->argv[i];
+
+               if ( (tag = va_arg(tv->ap, guint32)) == 0) {
+                       more = FALSE;
+                       break;
+               }
+
+               a->tag = tag;
+
+               switch((tag & CAMEL_ARG_TYPE)) {
+               case CAMEL_ARG_OBJ:
+                       a->ca_object = va_arg(tv->ap, void *);
+                       break;
+               case CAMEL_ARG_INT:
+                       a->ca_int = va_arg(tv->ap, int);
+                       break;
+               case CAMEL_ARG_DBL:
+                       a->ca_double = va_arg(tv->ap, double);
+                       break;
+               case CAMEL_ARG_STR:
+                       a->ca_str = va_arg(tv->ap, char *);
+                       break;
+               case CAMEL_ARG_PTR:
+                       a->ca_ptr = va_arg(tv->ap, void *);
+                       break;
+               default:
+                       printf("Error, unknown type, truncating result\n");
+                       more = FALSE;
+                       goto fail;
+               }
+
+       }
+fail:
+       tv->argc = i;
+
+       return more;
+}
+
+int camel_arggetv_build(CamelArgGetV *tv)
+{
+       register guint32 tag;
+       register int i;
+       register CamelArgGet *a;
+       int more = TRUE;
+
+       for (i=0;i<CAMEL_ARGV_MAX;i++) {
+               a = &tv->argv[i];
+
+               if ( (tag = va_arg(tv->ap, guint32)) == 0) {
+                       more = FALSE;
+                       break;
+               }
+
+               a->tag = tag;
+
+               switch((tag & CAMEL_ARG_TYPE)) {
+               case CAMEL_ARG_OBJ:
+                       a->ca_object = va_arg(tv->ap, void **);
+                       *a->ca_object = NULL;
+                       break;
+               case CAMEL_ARG_INT:
+                       a->ca_int = va_arg(tv->ap, int *);
+                       *a->ca_int = 0;
+                       break;
+               case CAMEL_ARG_DBL:
+                       a->ca_double = va_arg(tv->ap, double *);
+                       *a->ca_double = 0.0;
+                       break;
+               case CAMEL_ARG_STR:
+                       a->ca_str = va_arg(tv->ap, char **);
+                       *a->ca_str = NULL;
+                       break;
+               case CAMEL_ARG_PTR:
+                       a->ca_ptr = va_arg(tv->ap, void **);
+                       *a->ca_ptr = NULL;
+                       break;
+               default:
+                       printf("Error, unknown type, truncating result\n");
+                       more = FALSE;
+                       goto fail;
+               }
+
+       }
+fail:
+       tv->argc = i;
+
+       return more;
+}
diff --git a/camel/camel-arg.h b/camel/camel-arg.h
new file mode 100644 (file)
index 0000000..7846018
--- /dev/null
@@ -0,0 +1,109 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Author:
+ *  Michael Zucchi <notzed@ximian.com>
+ *
+ * Copyright 2002 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#ifndef CAMEL_ARG_H
+#define CAMEL_ARG_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif                         /* __cplusplus } */
+
+#include <glib.h>
+#include <stdarg.h>
+
+enum camel_arg_t {
+       CAMEL_ARG_END = 0,
+       CAMEL_ARG_IGNORE = 1,   /* override/ignore an arg in-place */
+
+       CAMEL_ARG_FIRST = 1024, /* 1024 args reserved for arg system */
+
+       CAMEL_ARG_TYPE = 0xf0000000, /* type field for tags */
+       CAMEL_ARG_TAG = 0x0fffffff, /* tag field for args */
+
+       CAMEL_ARG_OBJ = 0x00000000, /* object */
+       CAMEL_ARG_INT = 0x10000000, /* int */
+       CAMEL_ARG_DBL = 0x20000000, /* double */
+       CAMEL_ARG_STR = 0x30000000, /* c string */
+       CAMEL_ARG_PTR = 0x40000000, /* ptr */
+};
+
+typedef struct _CamelArg CamelArg;
+typedef struct _CamelArgV CamelArgV;
+
+typedef struct _CamelArgGet CamelArgGet;
+typedef struct _CamelArgGetV CamelArgGetV;
+
+struct _CamelArg {
+       guint32 tag;
+       union {
+               void *ca_object;
+               int ca_int;
+               double ca_double;
+               char *ca_str;
+               void *ca_ptr;
+       } u;
+};
+struct _CamelArgGet {
+       guint32 tag;
+       union {
+               void **ca_object;
+               int *ca_int;
+               double *ca_double;
+               char **ca_str;
+               void **ca_ptr;
+       } u;
+};
+#define ca_object u.ca_object
+#define ca_int u.ca_int
+#define ca_double u.ca_double
+#define ca_str u.ca_str
+#define ca_ptr u.ca_ptr
+
+/* maximum no of args processed at any one time, not the max of all args */
+#define CAMEL_ARGV_MAX (20)
+
+struct _CamelArgV {
+       va_list ap;
+       int argc;
+       CamelArg argv[CAMEL_ARGV_MAX];
+};
+
+struct _CamelArgGetV {
+       va_list ap;
+       int argc;
+       CamelArgGet argv[CAMEL_ARGV_MAX];
+};
+
+#define camel_argv_start(tv, last) (va_start((tv)->ap, last))
+#define camel_argv_end(tv) (va_end((tv)->ap))
+int camel_argv_build(CamelArgV *tv);
+int camel_arggetv_build(CamelArgGetV *tv);
+
+/* set an arg ignored */
+#define camel_argv_ignore(tv, i) ((tv)->argv[i].tag = ((tv)->argv[i].tag & CAMEL_ARG_TYPE) | CAMEL_ARG_IGNORE)
+
+#ifdef __cplusplus
+}
+#endif                         /* __cplusplus */
+
+#endif                         /* CAMEL_ARG_H */
index be30ad6..1ec1f74 100644 (file)
@@ -83,7 +83,7 @@ static EDList block_file_active_list = E_DLIST_INITIALISER(block_file_active_lis
 static int block_file_count = 0;
 static int block_file_threshhold = 10;
 
-#define CBF_CLASS(o) ((CamelBlockFileClass *)(((CamelObject *)o)->classfuncs))
+#define CBF_CLASS(o) ((CamelBlockFileClass *)(((CamelObject *)o)->klass))
 
 static int sync_nolock(CamelBlockFile *bs);
 static int sync_block_nolock(CamelBlockFile *bs, CamelBlock *bl);
index d970270..92b73e6 100644 (file)
@@ -213,7 +213,7 @@ camel_folder_search_construct (CamelFolderSearch *search)
                /* c is sure messy sometimes */
                func = *((void **)(((char *)klass)+builtins[i].offset));
                if (func == NULL && builtins[i].flags&1) {
-                       g_warning("Search class doesn't implement '%s' method: %s", builtins[i].name, camel_type_to_name(CAMEL_OBJECT_GET_CLASS(search)->s.type));
+                       g_warning("Search class doesn't implement '%s' method: %s", builtins[i].name, camel_type_to_name(CAMEL_OBJECT_GET_CLASS(search)));
                        func = (void *)search_dummy;
                }
                if (func != NULL) {
index 3f29567..701178b 100644 (file)
@@ -112,7 +112,7 @@ struct _CamelFolderSearchClass {
        ESExpResult * (*uid)(struct _ESExp *f, int argc, struct _ESExpResult **argv, CamelFolderSearch *s);
 };
 
-guint          camel_folder_search_get_type    (void);
+CamelType              camel_folder_search_get_type    (void);
 CamelFolderSearch      *camel_folder_search_new        (void);
 void camel_folder_search_construct (CamelFolderSearch *search);
 
index 3ba0348..e94ffe2 100644 (file)
@@ -209,7 +209,7 @@ struct _CamelFolderSummaryClass {
        char *(*next_uid_string)(CamelFolderSummary *);
 };
 
-guint                   camel_folder_summary_get_type  (void);
+CamelType                       camel_folder_summary_get_type  (void);
 CamelFolderSummary      *camel_folder_summary_new      (void);
 
 void camel_folder_summary_set_filename(CamelFolderSummary *, const char *);
index b29a845..e4edebf 100644 (file)
@@ -45,7 +45,7 @@
 static CamelObjectClass *parent_class = NULL;
 
 /* Returns the class for a CamelFolder */
-#define CF_CLASS(so) ((CamelFolderClass *)((CamelObject *)(so))->classfuncs)
+#define CF_CLASS(so) ((CamelFolderClass *)((CamelObject *)(so))->klass)
 
 static void camel_folder_finalize (CamelObject *object);
 
@@ -156,12 +156,10 @@ camel_folder_class_init (CamelFolderClass *camel_folder_class)
        camel_folder_class->is_frozen = is_frozen;
 
        /* virtual method overload */
-       camel_object_class_declare_event (camel_object_class,
-                                         "folder_changed", folder_changed);
-       camel_object_class_declare_event (camel_object_class,
-                                         "message_changed", message_changed);
-       camel_object_class_declare_event (camel_object_class, "deleted", NULL);
-       camel_object_class_declare_event (camel_object_class, "renamed", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_changed", folder_changed);
+       camel_object_class_add_event(camel_object_class, "message_changed", message_changed);
+       camel_object_class_add_event(camel_object_class, "deleted", NULL);
+       camel_object_class_add_event(camel_object_class, "renamed", NULL);
 }
 
 static void
index 973ce29..2e68e3b 100644 (file)
@@ -65,7 +65,7 @@ struct _CamelHTMLParserClass {
        CamelObjectClass parent_class;
 };
 
-guint          camel_html_parser_get_type      (void);
+CamelType              camel_html_parser_get_type      (void);
 CamelHTMLParser      *camel_html_parser_new    (void);
 
 void camel_html_parser_set_data(CamelHTMLParser *hp, const char *start, int len, int last);
index cb8ebd1..eb476b4 100644 (file)
@@ -46,7 +46,7 @@ struct _CamelIndexPrivate {
 
 #define _PRIVATE(o) (((CamelIndex *)(o))->priv)
 
-#define CI_CLASS(o) ((CamelIndexClass *)(((CamelObject *)o)->classfuncs))
+#define CI_CLASS(o) ((CamelIndexClass *)(((CamelObject *)o)->klass))
 
 /* ********************************************************************** */
 /* CamelIndex */
@@ -203,7 +203,7 @@ camel_index_names(CamelIndex *idx)
 
 static CamelObjectClass *camel_index_name_parent;
 
-#define CIN_CLASS(o) ((CamelIndexNameClass *)(((CamelObject *)o)->classfuncs))
+#define CIN_CLASS(o) ((CamelIndexNameClass *)(((CamelObject *)o)->klass))
 
 static void
 camel_index_name_class_init(CamelIndexNameClass *klass)
@@ -278,7 +278,7 @@ camel_index_name_add_buffer(CamelIndexName *idn, const char *buffer, size_t len)
 
 static CamelObjectClass *camel_index_cursor_parent;
 
-#define CIC_CLASS(o) ((CamelIndexCursorClass *)(((CamelObject *)o)->classfuncs))
+#define CIC_CLASS(o) ((CamelIndexCursorClass *)(((CamelObject *)o)->klass))
 
 static void
 camel_index_cursor_class_init(CamelIndexCursorClass *klass)
index eba57a4..81b84c3 100644 (file)
@@ -64,7 +64,7 @@ struct _CamelIndexCursorClass {
        void         (*reset) (CamelIndexCursor *idc);
 };
 
-guint             camel_index_cursor_get_type(void);
+CamelType                 camel_index_cursor_get_type(void);
 
 CamelIndexCursor  *camel_index_cursor_new(CamelIndex *idx, const char *name);
 
@@ -94,7 +94,7 @@ struct _CamelIndexNameClass {
        size_t (*add_buffer)(CamelIndexName *name, const char *buffer, size_t len);
 };
 
-guint             camel_index_name_get_type    (void);
+CamelType                 camel_index_name_get_type    (void);
 
 CamelIndexName    *camel_index_name_new(CamelIndex *idx, const char *name);
 
@@ -135,7 +135,7 @@ struct _CamelIndexClass {
        CamelIndexCursor *      (*names)(CamelIndex *idx);
 };
 
-guint             camel_index_get_type (void);
+CamelType                 camel_index_get_type (void);
 
 CamelIndex        *camel_index_new(const char *path, int flags);
 void               camel_index_construct(CamelIndex *, const char *path, int flags);
index 196f0bd..d07edee 100644 (file)
@@ -60,7 +60,7 @@ struct _CamelMimeFilterBasicClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_basic_get_type        (void);
+CamelType              camel_mime_filter_basic_get_type        (void);
 CamelMimeFilterBasic      *camel_mime_filter_basic_new (void);
 CamelMimeFilterBasic      *camel_mime_filter_basic_new_type    (CamelMimeFilterBasicType type);
 
index 8950a95..3d2e79f 100644 (file)
@@ -83,7 +83,7 @@ struct _CamelMimeFilterBestencClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_bestenc_get_type      (void);
+CamelType              camel_mime_filter_bestenc_get_type      (void);
 CamelMimeFilterBestenc      *camel_mime_filter_bestenc_new     (unsigned int flags);
 
 
index 80cf7d6..ddc3025 100644 (file)
@@ -50,7 +50,7 @@ struct _CamelMimeFilterCharsetClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_charset_get_type      (void);
+CamelType              camel_mime_filter_charset_get_type      (void);
 CamelMimeFilterCharset      *camel_mime_filter_charset_new     (void);
 
 CamelMimeFilterCharset      *camel_mime_filter_charset_new_convert     (const char *from_charset, const char *to_charset);
index 2176dfc..cbc2e70 100644 (file)
@@ -49,7 +49,7 @@ struct _CamelMimeFilterFromClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_from_get_type (void);
+CamelType              camel_mime_filter_from_get_type (void);
 CamelMimeFilterFrom      *camel_mime_filter_from_new   (void);
 
 #ifdef __cplusplus
index f572e3b..bb9b6aa 100644 (file)
@@ -47,7 +47,7 @@ struct _CamelMimeFilterHTMLClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_html_get_type (void);
+CamelType              camel_mime_filter_html_get_type (void);
 CamelMimeFilterHTML      *camel_mime_filter_html_new   (void);
 
 #ifdef __cplusplus
index fa1f49e..3bb1bd5 100644 (file)
@@ -49,7 +49,7 @@ struct _CamelMimeFilterIndexClass {
        CamelMimeFilterClass parent_class;
 };
 
-guint          camel_mime_filter_index_get_type        (void);
+CamelType              camel_mime_filter_index_get_type        (void);
 CamelMimeFilterIndex      *camel_mime_filter_index_new (void);
 
 CamelMimeFilterIndex      *camel_mime_filter_index_new_index(struct _CamelIndex *);
index 81c2e0d..7f784a1 100644 (file)
@@ -80,7 +80,7 @@ struct _CamelMimeParserClass {
        void (*content)(CamelMimeParser *);
 };
 
-guint          camel_mime_parser_get_type      (void);
+CamelType              camel_mime_parser_get_type      (void);
 CamelMimeParser      *camel_mime_parser_new    (void);
 
 /* quick-fix for parser not erroring, we can find out if it had an error afterwards */
index 444dfb4..ca1505e 100644 (file)
@@ -46,7 +46,7 @@ struct _CamelNewsAddressClass {
        CamelAddressClass parent_class;
 };
 
-guint          camel_news_address_get_type     (void);
+CamelType              camel_news_address_get_type     (void);
 CamelNewsAddress      *camel_news_address_new  (void);
 
 #ifdef __cplusplus
index b10edf8..cb21b58 100644 (file)
@@ -1,9 +1,8 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camel-object.c: Base class for Camel */
-
-/*
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- *
+ *
  * Author:
  *  Dan Winship <danw@ximian.com>
+ *  Michael Zucchi <notzed@ximian.com>
  *
  * Copyright 2000 Ximian, Inc. (www.ximian.com)
  *
 #include <config.h>
 #endif
 
+#include <stdio.h>
 #include <string.h>
 #include "camel-object.h"
 
+#include <e-util/e-memory.h>
+
 #ifdef ENABLE_THREADS
 #include <pthread.h>
 #include <e-util/e-msgport.h>
 #endif
 
 /* I just mashed the keyboard for these... */
-#define CAMEL_OBJECT_MAGIC_VALUE           0x77A344EF
-#define CAMEL_OBJECT_CLASS_MAGIC_VALUE     0xEE26A990
-#define CAMEL_OBJECT_FINALIZED_VALUE       0x84AC3656
-#define CAMEL_OBJECT_CLASS_FINALIZED_VALUE 0x7621ABCD
-
-#define DEFAULT_PREALLOCS 8
-
-#define BAST_CASTARD 1         /* Define to return NULL when casts fail */
-
-#define NULL_PREP_VALUE ((gpointer)make_global_classfuncs)     /* See camel_object_class_declare_event */
+#define CAMEL_OBJECT_MAGIC              0x77A344ED
+#define CAMEL_OBJECT_CLASS_MAGIC        0xEE26A997
+#define CAMEL_OBJECT_FINALISED_MAGIC       0x84AC365F
+#define CAMEL_OBJECT_CLASS_FINALISED_MAGIC 0x7621ABCD
 
 /* ** Quickie type system ************************************************* */
 
-typedef struct _CamelTypeInfo
-{
-       CamelType self;
-       CamelType parent;
-       const gchar *name;
-
-       size_t instance_size;
-       GMemChunk *instance_chunk;
-       CamelObjectInitFunc instance_init;
-       CamelObjectFinalizeFunc instance_finalize;
-       GList *free_instances;
-
-       size_t classfuncs_size;
-       CamelObjectClassInitFunc class_init;
-       CamelObjectClassFinalizeFunc class_finalize;
-       CamelObjectClass *global_classfuncs;
-}
-CamelTypeInfo;
-
 /* A 'locked' hooklist, that is only allocated on demand */
 typedef struct _CamelHookList {
        EMutex *lock;
@@ -90,642 +67,536 @@ typedef struct _CamelHookPair
 {
        struct _CamelHookPair *next; /* next MUST be the first member */
 
-       unsigned int flags;     /* removed, etc */
+       unsigned int id:30;
+       unsigned int flags:2;   /* removed, etc */
 
        const char *name;       /* points to the key field in the classes preplist, static memory */
-       CamelObjectEventHookFunc func;
+       union {
+               CamelObjectEventHookFunc event;
+               CamelObjectEventPrepFunc prep;
+       } func;
        void *data;
 } CamelHookPair;
 
-/* ************************************************************************ */
+/* ********************************************************************** */
 
-static void camel_type_lock_up (void);
-static void camel_type_lock_down (void);
+static void camel_object_free_hooks(CamelObject *o);
 
-static void obj_init (CamelObject * obj);
-static void obj_finalize (CamelObject * obj);
-static void obj_class_init (CamelObjectClass * class);
-static void obj_class_finalize (CamelObjectClass * class);
+/* ********************************************************************** */
 
-static gboolean shared_is_of_type (CamelObjectShared * sh, CamelType ctype,
-                                  gboolean is_obj);
-static void make_global_classfuncs (CamelTypeInfo * type_info);
+static pthread_mutex_t chunks_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static void camel_object_free_hooks(CamelObject *o);
+static EMemChunk *pair_chunks;
+static EMemChunk *hook_chunks;
+static unsigned int pair_id = 1;
 
-/* ************************************************************************ */
+static EMutex *type_lock;
 
-G_LOCK_DEFINE_STATIC (type_system);
-G_LOCK_DEFINE_STATIC (type_system_level);
-static GPrivate *type_system_locklevel = NULL;
+static GHashTable *type_table;
+static EMemChunk *type_chunks;
 
-G_LOCK_DEFINE_STATIC (refcount);
+CamelType camel_object_type;
 
-static gboolean type_system_initialized = FALSE;
-static GHashTable *ctype_to_typeinfo = NULL;
-static GHashTable *name_to_typeinfo = NULL;
-static const CamelType camel_object_type = 1;
-static CamelType cur_max_type = CAMEL_INVALID_TYPE;
+#ifdef ENABLE_THREADS
+#define P_LOCK(l) (pthread_mutex_lock(&l))
+#define P_UNLOCK(l) (pthread_mutex_unlock(&l))
+#define E_LOCK(l) (e_mutex_lock(l))
+#define E_UNLOCK(l) (e_mutex_unlock(l))
+#define CLASS_LOCK(k) (g_mutex_lock((((CamelObjectClass *)k)->lock)))
+#define CLASS_UNLOCK(k) (g_mutex_unlock((((CamelObjectClass *)k)->lock)))
+#else
+#define P_LOCK(l)
+#define P_UNLOCK(l)
+#define E_LOCK(l)
+#define E_UNLOCK(l)
+#define CLASS_LOCK(k)
+#define CLASS_UNLOCK(k)
+#endif
 
-/* ************************************************************************ */
+static struct _CamelHookPair *
+pair_alloc(void)
+{
+       CamelHookPair *pair;
 
-#define LOCK_VAL (GPOINTER_TO_INT (g_private_get (type_system_locklevel)))
-#define LOCK_SET( val ) g_private_set (type_system_locklevel, GINT_TO_POINTER (val))
+       P_LOCK(chunks_lock);
+       pair = e_memchunk_alloc(pair_chunks);
+       pair->id = pair_id++;
+       if (pair_id == 0)
+               pair_id = 1;
+       P_UNLOCK(chunks_lock);
+
+       return pair;
+}
 
 static void
-camel_type_lock_up (void)
+pair_free(CamelHookPair *pair)
 {
-       G_LOCK (type_system_level);
+       g_assert(pair_chunks != NULL);
 
-       if (type_system_locklevel == NULL)
-               type_system_locklevel = g_private_new (GINT_TO_POINTER (0));
+       P_LOCK(chunks_lock);
+       e_memchunk_free(pair_chunks, pair);
+       P_UNLOCK(chunks_lock);
+}
 
-       if (LOCK_VAL == 0) {
-               G_UNLOCK (type_system_level);
-               G_LOCK (type_system);
-               G_LOCK (type_system_level);
-       }
+static struct _CamelHookList *
+hooks_alloc(void)
+{
+       CamelHookList *hooks;
 
-       LOCK_SET (LOCK_VAL + 1);
+       P_LOCK(chunks_lock);
+       hooks = e_memchunk_alloc(hook_chunks);
+       P_UNLOCK(chunks_lock);
 
-       G_UNLOCK (type_system_level);
+       return hooks;
 }
 
 static void
-camel_type_lock_down (void)
+hooks_free(CamelHookList *hooks)
 {
-       G_LOCK (type_system_level);
+       g_assert(hook_chunks != NULL);
 
-       if (type_system_locklevel == NULL) {
-               g_warning
-                       ("camel_type_lock_down: lock down before a lock up?");
-               type_system_locklevel = g_private_new (GINT_TO_POINTER (0));
-               G_UNLOCK (type_system_level);
-               return;
-       }
-
-       LOCK_SET (LOCK_VAL - 1);
-
-       if (LOCK_VAL == 0)
-               G_UNLOCK (type_system);
-
-       G_UNLOCK (type_system_level);
+       P_LOCK(chunks_lock);
+       e_memchunk_free(hook_chunks, hooks);
+       P_UNLOCK(chunks_lock);
 }
 
+/* not checked locked, who cares, only required for people that want to redefine root objects */
 void
-camel_type_init (void)
+camel_type_init(void)
 {
-       CamelTypeInfo *obj_info;
+       static int init = FALSE;
 
-       camel_type_lock_up ();
-
-       if (type_system_initialized) {
-               g_warning ("camel_type_init: type system already initialized.");
-               camel_type_lock_down ();
+       if (init)
                return;
-       }
 
-       type_system_initialized = TRUE;
-       ctype_to_typeinfo = g_hash_table_new (g_direct_hash, g_direct_equal);
-       name_to_typeinfo = g_hash_table_new (g_str_hash, g_str_equal);
-       
-       obj_info = g_new (CamelTypeInfo, 1);
-       obj_info->self = camel_object_type;
-       obj_info->parent = CAMEL_INVALID_TYPE;
-       obj_info->name = "CamelObject";
-
-       obj_info->instance_size = sizeof (CamelObject);
-       obj_info->instance_chunk =
-               g_mem_chunk_create (CamelObject, DEFAULT_PREALLOCS,
-                                   G_ALLOC_ONLY);
-       obj_info->instance_init = obj_init;
-       obj_info->instance_finalize = obj_finalize;
-       obj_info->free_instances = NULL;
-
-       obj_info->classfuncs_size = sizeof (CamelObjectClass);
-       obj_info->class_init = obj_class_init;
-       obj_info->class_finalize = obj_class_finalize;
-
-       g_hash_table_insert (ctype_to_typeinfo,
-                            GINT_TO_POINTER (CAMEL_INVALID_TYPE), NULL);
-       g_hash_table_insert (ctype_to_typeinfo,
-                            GINT_TO_POINTER (camel_object_type), obj_info);
-       g_hash_table_insert (name_to_typeinfo, (gpointer) obj_info->name, obj_info);
-       
-       /* Sigh. Ugly */
-       make_global_classfuncs (obj_info);
-
-       cur_max_type = camel_object_type;
-
-       camel_type_lock_down ();
+       init = TRUE;
+       pair_chunks = e_memchunk_new(16, sizeof(CamelHookPair));
+       hook_chunks = e_memchunk_new(16, sizeof(CamelHookList));
+       type_lock = e_mutex_new(E_MUTEX_REC);
+       type_chunks = e_memchunk_new(32, sizeof(CamelType));
+       type_table = g_hash_table_new(NULL, NULL);
 }
 
-CamelType
-camel_type_register (CamelType parent, const gchar * name,
-                    size_t instance_size, size_t classfuncs_size,
-                    CamelObjectClassInitFunc class_init,
-                    CamelObjectClassFinalizeFunc class_finalize,
-                    CamelObjectInitFunc instance_init,
-                    CamelObjectFinalizeFunc instance_finalize)
-{
-       CamelTypeInfo *parent_info;
-       CamelTypeInfo *obj_info;
-       gchar *chunkname;
-
-       g_return_val_if_fail (parent != CAMEL_INVALID_TYPE,
-                             CAMEL_INVALID_TYPE);
-       g_return_val_if_fail (name, CAMEL_INVALID_TYPE);
-       g_return_val_if_fail (instance_size, CAMEL_INVALID_TYPE);
-       g_return_val_if_fail (classfuncs_size, CAMEL_INVALID_TYPE);
-
-       camel_type_lock_up ();
-
-       if (type_system_initialized == FALSE) {
-               G_UNLOCK (type_system);
-               camel_type_init ();
-               G_LOCK (type_system);
-       }
-       
-       obj_info = g_hash_table_lookup (name_to_typeinfo, name);
-       if (obj_info != NULL) {
-               /* looks like we've already registered this type... */
-               camel_type_lock_down ();
-               return obj_info->self;
-       }
-       
-       parent_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (parent));
-
-       if (parent_info == NULL) {
-               g_warning
-                       ("camel_type_register: no such parent type %d of class `%s'",
-                        parent, name);
-               camel_type_lock_down ();
-               return CAMEL_INVALID_TYPE;
-       }
-
-       if (parent_info->instance_size > instance_size) {
-               g_warning
-                       ("camel_type_register: instance of class `%s' would be smaller than parent `%s'",
-                        name, parent_info->name);
-               camel_type_lock_down ();
-               return CAMEL_INVALID_TYPE;
-       }
-
-       if (parent_info->classfuncs_size > classfuncs_size) {
-               g_warning
-                       ("camel_type_register: classfuncs of class `%s' would be smaller than parent `%s'",
-                        name, parent_info->name);
-               camel_type_lock_down ();
-               return CAMEL_INVALID_TYPE;
-       }
+/* ************************************************************************ */
 
-       cur_max_type++;
-
-       obj_info = g_new (CamelTypeInfo, 1);
-       obj_info->self = cur_max_type;
-       obj_info->parent = parent;
-       obj_info->name = name;
-
-       obj_info->instance_size = instance_size;
-       chunkname =
-               g_strdup_printf ("chunk for instances of Camel type `%s'",
-                                name);
-       obj_info->instance_chunk =
-               g_mem_chunk_new (chunkname, instance_size,
-                                instance_size * DEFAULT_PREALLOCS,
-                                G_ALLOC_ONLY);
-       g_free (chunkname);
-       obj_info->instance_init = instance_init;
-       obj_info->instance_finalize = instance_finalize;
-       obj_info->free_instances = NULL;
-
-       obj_info->classfuncs_size = classfuncs_size;
-       obj_info->class_init = class_init;
-       obj_info->class_finalize = class_finalize;
-
-       g_hash_table_insert (ctype_to_typeinfo,
-                            GINT_TO_POINTER (obj_info->self), obj_info);
-       g_hash_table_insert (name_to_typeinfo, (gpointer) obj_info->name, obj_info);
-
-       /* Sigh. Ugly. */
-       make_global_classfuncs (obj_info);
-
-       camel_type_lock_down ();
-       return obj_info->self;
+/* Should this return the object to the caller? */
+static void
+cobject_init (CamelObject *o, CamelObjectClass *klass)
+{
+       o->klass = klass;
+       o->magic = CAMEL_OBJECT_MAGIC;
+       o->ref_count = 1;
+       o->flags = 0;
 }
 
-CamelObjectClass *
-camel_type_get_global_classfuncs (CamelType type)
+static void
+cobject_finalise(CamelObject *o)
 {
-       CamelTypeInfo *type_info;
-
-       g_return_val_if_fail (type != CAMEL_INVALID_TYPE, NULL);
-
-       camel_type_lock_up ();
-       type_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (type));
-       camel_type_lock_down ();
+       g_assert(o->ref_count == 0);
 
-       g_return_val_if_fail (type_info != NULL, NULL);
+       camel_object_free_hooks(o);
 
-       return type_info->global_classfuncs;
+       o->magic = CAMEL_OBJECT_FINALISED_MAGIC;
+       o->klass = NULL;
 }
 
-const gchar *
-camel_type_to_name (CamelType type)
+static int
+cobject_getv(CamelObject *o, CamelException *ex, CamelArgGetV *args)
 {
-       CamelTypeInfo *type_info;
-
-       g_return_val_if_fail (type != CAMEL_INVALID_TYPE,
-                             "(the invalid type)");
-
-       camel_type_lock_up ();
-       type_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (type));
-       camel_type_lock_down ();
-
-       g_return_val_if_fail (type_info != NULL,
-                             "(a bad type parameter was specified)");
-
-       return type_info->name;
+       /* could have flags or stuff here? */
+       return 0;
 }
 
-/* ** The CamelObject ***************************************************** */
-
-static void
-obj_init (CamelObject * obj)
+static int
+cobject_setv(CamelObject *o, CamelException *ex, CamelArgV *args)
 {
-       obj->s.magic = CAMEL_OBJECT_MAGIC_VALUE;
-       obj->ref_count = 1;
-       obj->hooks = NULL;
-       obj->in_event = 0;
-       obj->destroying = 0;
+       /* could have flags or stuff here? */
+       return 0;
 }
 
 static void
-obj_finalize (CamelObject * obj)
+cobject_class_init(CamelObjectClass *klass)
 {
-       g_return_if_fail (obj->s.magic == CAMEL_OBJECT_MAGIC_VALUE);
-       g_return_if_fail (obj->ref_count == 0);
-       g_return_if_fail (obj->in_event == 0);
+       klass->magic = CAMEL_OBJECT_CLASS_MAGIC;
 
-       obj->s.magic = CAMEL_OBJECT_FINALIZED_VALUE;
+       klass->getv = cobject_getv;
+       klass->setv = cobject_setv;
 
-       camel_object_free_hooks(obj);
+       camel_object_class_add_event(klass, "finalize", NULL);
 }
 
 static void
-obj_class_init (CamelObjectClass * class)
+cobject_class_finalise(CamelObjectClass * klass)
 {
-       class->s.magic = CAMEL_OBJECT_CLASS_MAGIC_VALUE;
+       klass->magic = CAMEL_OBJECT_CLASS_FINALISED_MAGIC;
 
-       camel_object_class_declare_event (class, "finalize", NULL);
-}
-
-static void
-obj_class_finalize (CamelObjectClass * class)
-{
-       g_return_if_fail (class->s.magic == CAMEL_OBJECT_CLASS_MAGIC_VALUE);
-
-       class->s.magic = CAMEL_OBJECT_CLASS_FINALIZED_VALUE;
-
-       if (class->event_to_preplist) {
-               /* FIXME: This leaks the preplist slist entries */
-               g_hash_table_foreach (class->event_to_preplist,
-                                     (GHFunc) g_free, NULL);
-               g_hash_table_destroy (class->event_to_preplist);
-               class->event_to_preplist = NULL;
-       }
+       g_free(klass);
 }
 
 CamelType
 camel_object_get_type (void)
 {
-       if (type_system_initialized == FALSE)
-               camel_type_init ();
+       if (camel_object_type == CAMEL_INVALID_TYPE) {
+               camel_type_init();
+
+               camel_object_type = camel_type_register(NULL, "CamelObject", /*, 0, 0*/
+                                                       sizeof(CamelObject), sizeof(CamelObjectClass),
+                                                       cobject_class_init, cobject_class_finalise,
+                                                       cobject_init, cobject_finalise);
+       }
 
        return camel_object_type;
 }
 
-CamelObject *
-camel_object_new (CamelType type)
+static void
+camel_type_class_init(CamelObjectClass *klass, CamelObjectClass *type)
 {
-       CamelTypeInfo *type_info;
-       GSList *parents = NULL;
-       GSList *head = NULL;
-       CamelObject *instance;
-
-       g_return_val_if_fail (type != CAMEL_INVALID_TYPE, NULL);
+       if (type->parent)
+               camel_type_class_init(klass, type->parent);
 
-       /* Look up the type */
-
-       camel_type_lock_up ();
+       if (type->klass_init)
+               type->klass_init(klass);
+}
 
-       type_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (type));
+CamelType
+camel_type_register (CamelType parent, const char * name,
+                    /*unsigned int ver, unsigned int rev,*/
+                    size_t object_size, size_t klass_size,
+                    CamelObjectClassInitFunc class_init,
+                    CamelObjectClassFinalizeFunc class_finalise,
+                    CamelObjectInitFunc object_init,
+                    CamelObjectFinalizeFunc object_finalise)
+{
+       CamelObjectClass *klass;
+       /*int offset;
+         size_t size;*/
 
-       if (type_info == NULL) {
-               g_warning
-                       ("camel_object_new: trying to create object of invalid type %d",
-                        type);
-               camel_type_lock_down ();
+       if (parent != NULL && parent->magic != CAMEL_OBJECT_CLASS_MAGIC) {
+               g_warning("camel_type_register: invalid junk parent class for '%s'", name);
                return NULL;
        }
 
-       /* Grab an instance out of the freed ones if possible, alloc otherwise */
-
-       if (type_info->free_instances) {
-               GList *first;
+       E_LOCK(type_lock);
 
-               first = g_list_first (type_info->free_instances);
-               instance = first->data;
-               type_info->free_instances =
-                       g_list_remove_link (type_info->free_instances, first);
-               g_list_free_1 (first);
-               memset (instance, 0, type_info->instance_size);
-       } else {
-               instance = g_mem_chunk_alloc0 (type_info->instance_chunk);
+       /* Have to check creation, it might've happened in another thread before we got here */
+       klass = g_hash_table_lookup(type_table, name);
+       if (klass != NULL) {
+               if (klass->klass_size != klass_size || klass->object_size != object_size
+                   || klass->klass_init != class_init || klass->klass_finalise != class_finalise
+                   || klass->init != object_init || klass->finalise != object_finalise) {
+                       g_warning("camel_type_register: Trying to re-register class '%s'", name);
+                       klass = NULL;
+               }
+               E_UNLOCK(type_lock);
+               return klass;
        }
 
-       /* Init the instance and classfuncs a bit */
-
-       instance->s.type = type;
-       instance->classfuncs = type_info->global_classfuncs;
+       /* this is for objects with no parent as part of their struct ('interfaces'?) */
+       /*offset = parent?parent->klass_size:0;
+       offset = (offset + 3) & (~3);
 
-       /* Loop through the parents in simplest -> most complex order, initing the class and instance.
+       size = offset + klass_size;
 
-        * When parent = CAMEL_INVALID_TYPE and we're at the end of the line, _lookup returns NULL
-        * because we inserted it as corresponding to CAMEL_INVALID_TYPE. Clever, eh?
-        */
+       klass = g_malloc0(size);
 
-       while (type_info) {
-               parents = g_slist_prepend (parents, type_info);
-               type_info =
-                       g_hash_table_lookup (ctype_to_typeinfo,
-                                            GINT_TO_POINTER (type_info->
-                                                             parent));
-       }
+       klass->klass_size = size;
+       klass->klass_data = offset;
 
-       head = parents;
+       offset = parent?parent->object_size:0;
+       offset = (offset + 3) & (~3);
 
-       for (; parents && parents->data; parents = parents->next) {
-               CamelTypeInfo *thisinfo;
+       klass->object_size = offset + object_size;
+       klass->object_data = offset;*/
 
-               thisinfo = parents->data;
-               if (thisinfo->instance_init)
-                       (thisinfo->instance_init) (instance);
+       if (parent
+           && klass_size < parent->klass_size) {
+               g_warning("camel_type_register: '%s' has smaller class size than parent '%s'", name, parent->name);
+               E_UNLOCK(type_lock);
+               return NULL;
        }
 
-       g_slist_free (head);
+       klass = g_malloc0(klass_size);
+       klass->klass_size = klass_size;
+       klass->object_size = object_size;       
+#ifdef ENABLE_THREADS
+       klass->lock = g_mutex_new();
+#endif
+       klass->instance_chunks = e_memchunk_new(8, object_size);
 
-       camel_type_lock_down ();
-       return instance;
-}
+       klass->parent = parent;
+       if (parent) {
+               klass->next = parent->child;
+               parent->child = klass;
+       }
+       klass->name = name;
 
-#ifdef camel_object_ref
-#undef camel_object_ref
-#endif
+       /*klass->version = ver;
+         klass->revision = rev;*/
 
-void
-camel_object_ref (CamelObject * obj)
-{
-       g_return_if_fail (CAMEL_IS_OBJECT (obj));
+       klass->klass_init = class_init;
+       klass->klass_finalise = class_finalise;
 
-       G_LOCK (refcount);
-       obj->ref_count++;
-       G_UNLOCK (refcount);
-}
+       klass->init = object_init;
+       klass->finalise = object_finalise;
 
-#ifdef camel_object_unref
-#undef camel_object_unref
-#endif
+       /* setup before class init, incase class init func uses the type or looks it up ? */
+       g_hash_table_insert(type_table, (void *)name, klass);
 
-void
-camel_object_unref (CamelObject * obj)
-{
-       CamelTypeInfo *type_info;
-       CamelTypeInfo *iter;
-       GSList *parents = NULL;
-       GSList *head = NULL;
+       camel_type_class_init(klass, klass);
 
-       g_return_if_fail (CAMEL_IS_OBJECT (obj));
+       E_UNLOCK(type_lock);
 
-       G_LOCK (refcount);
-       obj->ref_count--;
+       return klass;
+}
 
-       if (obj->ref_count > 0) {
-               G_UNLOCK (refcount);
-               return;
-       }
+static void
+camel_object_init(CamelObject *o, CamelObjectClass *klass, CamelType type)
+{
+       if (type->parent)
+               camel_object_init(o, klass, type->parent);
 
-       G_UNLOCK (refcount);
+       if (type->init)
+               type->init(o, klass);
+}
 
-       /* If the object already had its last unref, do not begin the
-        * destruction process again. This can happen if, for example,
-        * the object sends an event in its finalize handler (vfolders
-        * do this).
-        */
+CamelObject *
+camel_object_new(CamelType type)
+{
+       CamelObject *o;
 
-       if (obj->destroying)
-               return;
-       
-       obj->destroying = 1;
+       if (type == NULL)
+               return NULL;
 
-       /* Send the finalize event */
+       if (type->magic != CAMEL_OBJECT_CLASS_MAGIC)
+               return NULL;
 
-       camel_object_trigger_event (obj, "finalize", NULL);
+       CLASS_LOCK(type);
+       o = e_memchunk_alloc0(type->instance_chunks);
 
-       /* Destroy it! hahaha! */
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+       if (type->instances)
+               type->instances->prev = o;
+       o->next = type->instances;
+       o->prev = NULL;
+       type->instances = o;
+#endif
 
-       camel_type_lock_up ();
+       CLASS_UNLOCK(type);
+       camel_object_init(o, type, type);
 
-       type_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (obj->s.type));
+       return o;
+}
 
-       if (type_info == NULL) {
-               g_warning
-                       ("camel_object_unref: seemingly valid object has a bad type %d",
-                        obj->s.type);
-               camel_type_lock_down ();
-               return;
-       }
+void
+camel_object_ref(CamelObject *o)
+{
+       CLASS_LOCK(o->klass);
+       o->ref_count++;
+       CLASS_UNLOCK(o->klass);
+}
 
-       /* Loop through the parents in most complex -> simplest order, finalizing the class 
-        * and instance.
-        *
-        * When parent = CAMEL_INVALID_TYPE and we're at the end of the line, _lookup returns NULL
-        * because we inserted it as corresponding to CAMEL_INVALID_TYPE. Clever, eh?
-        *
-        * Use iter to preserve type_info for free_{instance,classfunc}s
-        */
-
-       iter = type_info;
-
-       while (iter) {
-               parents = g_slist_prepend (parents, iter);
-               iter =
-                       g_hash_table_lookup (ctype_to_typeinfo,
-                                            GINT_TO_POINTER (iter->parent));
+void
+camel_object_unref(CamelObject *o)
+{
+       register CamelObjectClass *klass = o->klass, *k;
+       
+       CLASS_LOCK(klass);
+       o->ref_count--;
+       if (o->ref_count > 0
+           || (o->flags & CAMEL_OBJECT_DESTROY)) {
+               CLASS_UNLOCK(klass);
+               return;
        }
 
-       /* ok, done with the type stuff, and our data pointers
-        * won't go bad. */
-       camel_type_lock_down ();
+       o->flags |= CAMEL_OBJECT_DESTROY;
 
-       parents = g_slist_reverse (parents);
-       head = parents;
+       CLASS_UNLOCK(klass);
 
-       for (; parents && parents->data; parents = parents->next) {
-               CamelTypeInfo *thisinfo;
+       camel_object_trigger_event(o, "finalize", NULL);
 
-               thisinfo = parents->data;
-               if (thisinfo->instance_finalize)
-                       (thisinfo->instance_finalize) (obj);
+       k = klass;
+       while (k) {
+               if (k->finalise)
+                       k->finalise(o);
+               k = k->parent;
        }
 
-       g_slist_free (head);
+       o->magic = CAMEL_OBJECT_FINALISED_MAGIC;
 
-       /* Sanity check */
+       CLASS_LOCK(klass);
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+       if (o->prev)
+               o->prev->next = o->next;
+       else
+               klass->instances = o->next;
+       if (o->next)
+               o->next->prev = o->prev;
+#endif
+       e_memchunk_free(klass->instance_chunks, o);
+       CLASS_UNLOCK(klass);
+}
 
-       if (obj->ref_count != 0)
-               g_warning ("camel_object_unref: destroyed object %s at %p somehow got"
-                          " referenced in destruction chain.",
-                          camel_type_to_name (obj->s.type),
-                          obj);
+const char *
+camel_type_to_name (CamelType type)
+{
+       if (type == NULL)
+               return "(NULL class)";
 
-       /* A little bit of cleaning up.
+       if (type->magic == CAMEL_OBJECT_CLASS_MAGIC)
+               return type->name;
 
-        * Don't erase the type, so we can peek at it if a finalized object
-        * is check_cast'ed somewhere.  Fill it with gunk to help detect
-        * other invalid ref's of it.
-        */
+       return "(Junk class)";
+}
 
-       memset (obj, 0xEB, type_info->instance_size);
-       obj->s.type = type_info->self;
-       obj->s.magic = CAMEL_OBJECT_FINALIZED_VALUE;
+CamelType camel_name_to_type(const char *name)
+{
+       /* TODO: Load a class off disk (!) */
 
-       /* Tuck away the pointer for use in a new object */
+       return g_hash_table_lookup(type_table, name);
+}
 
-       camel_type_lock_up ();
+static char *
+desc_data(CamelObject *o, int ok)
+{
+       char *what;
+
+       if (o == NULL)
+               what = g_strdup("NULL OBJECT");
+       else if (o->magic == ok)
+               what = NULL;
+       else if (o->magic == CAMEL_OBJECT_MAGIC)
+               what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name);
+       else if (o->magic == CAMEL_OBJECT_CLASS_MAGIC)
+               what = g_strdup_printf("CLASS '%s'", ((CamelObjectClass *)o)->name);
+       else if (o->magic == CAMEL_OBJECT_FINALISED_MAGIC)
+               what = g_strdup_printf("finalised OBJECT");
+       else if (o->magic == CAMEL_OBJECT_CLASS_FINALISED_MAGIC)
+               what = g_strdup_printf("finalised CLASS");
+       else 
+               what = g_strdup_printf("junk data");
+
+       return what;
+}
 
-       type_info->free_instances =
-               g_list_prepend (type_info->free_instances, obj);
+static gboolean
+check_magic(void *o, CamelType ctype, int isob)
+{
+       char *what, *to;
+
+       what = desc_data(o, isob?CAMEL_OBJECT_MAGIC:CAMEL_OBJECT_CLASS_MAGIC);
+       to = desc_data((CamelObject *)ctype, CAMEL_OBJECT_CLASS_MAGIC);
+
+       if (what || to) {
+               if (what == NULL) {
+                       if (isob)
+                               what = g_strdup_printf("OBJECT '%s'", ((CamelObject *)o)->klass->name);
+                       else
+                               what = g_strdup_printf("OBJECT '%s'", ((CamelObjectClass *)o)->name);
+               }               
+               if (to == NULL)
+                       to = g_strdup_printf("OBJECT '%s'", ctype->name);
+               g_warning("Trying to check %s is %s", what, to);
+               g_free(what);
+               g_free(to);
 
-       camel_type_lock_down ();
+               return FALSE;
+       }
+
+       return TRUE;
 }
 
 gboolean
-camel_object_is_of_type (CamelObject * obj, CamelType ctype)
+camel_object_is (CamelObject *o, CamelType ctype)
 {
-       return shared_is_of_type ((CamelObjectShared *) obj, ctype, TRUE);
+       CamelObjectClass *k;
+
+       g_return_val_if_fail(check_magic(o, ctype, TRUE), FALSE);
+
+       k = o->klass;
+       while (k) {
+               if (k == ctype)
+                       return TRUE;
+               k = k->parent;
+       }
+
+       return FALSE;
 }
 
 gboolean
-camel_object_class_is_of_type (CamelObjectClass * class, CamelType ctype)
+camel_object_class_is (CamelObjectClass *k, CamelType ctype)
 {
-       return shared_is_of_type ((CamelObjectShared *) class, ctype, FALSE);
-}
+       g_return_val_if_fail(check_magic(k, ctype, FALSE), FALSE);
 
-#ifdef BAST_CASTARD
-#define ERRVAL NULL
-#else
-#define ERRVAL obj
-#endif
+       while (k) {
+               if (k == ctype)
+                       return TRUE;
+               k = k->parent;
+       }
+
+       return FALSE;
+}
 
 CamelObject *
-camel_object_check_cast (CamelObject * obj, CamelType ctype)
+camel_object_cast(CamelObject *o, CamelType ctype)
 {
-       if (shared_is_of_type ((CamelObjectShared *) obj, ctype, TRUE))
-               return obj;
-       return ERRVAL;
+       CamelObjectClass *k;
+
+       g_return_val_if_fail(check_magic(o, ctype, TRUE), NULL);
+
+       k = o->klass;
+       while (k) {
+               if (k == ctype)
+                       return o;
+               k = k->parent;
+       }
+
+       g_warning("Object %p (class '%s') doesn't have '%s' in its heirachy", o, o->klass->name, ctype->name);
+
+       return NULL;
 }
 
 CamelObjectClass *
-camel_object_class_check_cast (CamelObjectClass * class, CamelType ctype)
+camel_object_class_cast(CamelObjectClass *k, CamelType ctype)
 {
-       if (shared_is_of_type ((CamelObjectShared *) class, ctype, FALSE))
-               return class;
-       return ERRVAL;
-}
+       CamelObjectClass *r = k;
 
-#undef ERRVAL
+       g_return_val_if_fail(check_magic(k, ctype, FALSE), NULL);
 
-gchar *
-camel_object_describe (CamelObject * obj)
-{
-       if (obj == NULL)
-               return g_strdup ("a NULL pointer");
-
-       if (obj->s.magic == CAMEL_OBJECT_MAGIC_VALUE) {
-               return g_strdup_printf ("an instance of `%s' at %p",
-                                       camel_type_to_name (obj->s.type),
-                                       obj);
-       } else if (obj->s.magic == CAMEL_OBJECT_FINALIZED_VALUE) {
-               return g_strdup_printf ("a finalized instance of `%s' at %p",
-                                       camel_type_to_name (obj->s.type),
-                                       obj);
-       } else if (obj->s.magic == CAMEL_OBJECT_CLASS_MAGIC_VALUE) {
-               return g_strdup_printf ("the classfuncs of `%s' at %p",
-                                       camel_type_to_name (obj->s.type),
-                                       obj);
-       } else if (obj->s.magic == CAMEL_OBJECT_CLASS_FINALIZED_VALUE) {
-               return
-                       g_strdup_printf
-                       ("the finalized classfuncs of `%s' at %p",
-                        camel_type_to_name (obj->s.type), obj);
+       while (k) {
+               if (k == ctype)
+                       return r;
+               k = k->parent;
        }
 
-       return g_strdup ("not a CamelObject");
+       g_warning("Class '%s' doesn't have '%s' in its heirarchy", k->name, ctype->name);
+
+       return NULL;
 }
 
-/* This is likely to be called in the class_init callback,
- * and the type will likely be somewhat uninitialized. 
- * Is this a problem? We'll see....
- */
 void
-camel_object_class_declare_event (CamelObjectClass * class,
-                                 const gchar * name,
-                                 CamelObjectEventPrepFunc prep)
+camel_object_class_add_event(CamelObjectClass *klass, const char *name, CamelObjectEventPrepFunc prep)
 {
-       g_return_if_fail (CAMEL_IS_OBJECT_CLASS (class));
+       CamelHookPair *pair;
+
        g_return_if_fail (name);
 
-       if (class->event_to_preplist == NULL)
-               class->event_to_preplist =
-                       g_hash_table_new (g_str_hash, g_str_equal);
-       else if (g_hash_table_lookup (class->event_to_preplist, name) != NULL) {
-               g_warning
-                       ("camel_object_class_declare_event: event `%s' already declared for `%s'",
-                        name, camel_type_to_name (class->s.type));
-               return;
+       pair = klass->hooks;
+       while (pair) {
+               if (strcmp(pair->name, name) == 0) {
+                       g_warning("camel_object_class_add_event: `%s' is already declared for '%s'\n",
+                                 name, klass->name);
+                       return;
+               }
+               pair = pair->next;
        }
 
-       /* AIEEEEEEEEEEEEEEEEEEEEEE
-
-        * I feel so naughty. Since it's valid to declare an event and not
-        * provide a hook, it should be valid to insert a NULL value into
-        * the table. However, then our lookup in trigger_event would be
-        * ambiguous, not telling us whether the event is undefined or whether
-        * it merely has no hook.
-        *
-        * So we create an 'NULL prep' value that != NULL... specifically, it
-        * equals the address of one of our static functions , because that
-        * can't possibly be your hook.
-        *
-        * Just don't forget to check for the 'evil value' and it'll work,
-        * I promise.
-        */
-
-       if (prep == NULL)
-               prep = NULL_PREP_VALUE;
-
-       g_hash_table_insert (class->event_to_preplist, g_strdup (name), prep);
+       pair = pair_alloc();
+       pair->name = name;
+       pair->func.prep = prep;
+       pair->flags = 0;
+
+       pair->next = klass->hooks;
+       klass->hooks = pair;
 }
 
 /* free hook data */
@@ -734,18 +605,17 @@ static void camel_object_free_hooks(CamelObject *o)
        CamelHookPair *pair, *next;
 
        if (o->hooks) {
-
                g_assert(o->hooks->depth == 0);
                g_assert((o->hooks->flags & CAMEL_HOOK_PAIR_REMOVED) == 0);
 
                pair = o->hooks->list;
                while (pair) {
                        next = pair->next;
-                       g_free(pair);
+                       pair_free(pair);
                        pair = next;
                }
                e_mutex_destroy(o->hooks->lock);
-               g_free(o->hooks);
+               hooks_free(o->hooks);
                o->hooks = NULL;
        }
 }
@@ -765,7 +635,7 @@ static CamelHookList *camel_object_get_hooks(CamelObject *o)
                pthread_mutex_lock(&lock);
 #endif
                if (o->hooks == NULL) {
-                       hooks = g_malloc(sizeof(*o->hooks));
+                       hooks = hooks_alloc();
 #ifdef ENABLE_THREADS
                        hooks->lock = e_mutex_new(E_MUTEX_REC);
 #endif
@@ -793,34 +663,37 @@ static CamelHookList *camel_object_get_hooks(CamelObject *o)
 #define camel_object_unget_hooks(o)
 #endif
 
-void
-camel_object_hook_event (CamelObject * obj, const char * name,
-                        CamelObjectEventHookFunc func, void *data)
+unsigned int
+camel_object_hook_event(CamelObject * obj, const char * name, CamelObjectEventHookFunc func, void *data)
 {
-       CamelHookPair *pair;
-       const char *prepname;
-       CamelObjectEventPrepFunc prep;
+       CamelHookPair *pair, *hook;
        CamelHookList *hooks;
+       int id;
 
-       g_return_if_fail (CAMEL_IS_OBJECT (obj));
-       g_return_if_fail (name != NULL);
-       g_return_if_fail (func != NULL);
+       g_return_val_if_fail (CAMEL_IS_OBJECT (obj), 0);
+       g_return_val_if_fail (name != NULL, 0);
+       g_return_val_if_fail (func != NULL, 0);
 
-       /* first, does this event exist? */
-       if (obj->classfuncs->event_to_preplist == NULL
-           || !g_hash_table_lookup_extended(obj->classfuncs->event_to_preplist, name,
-                                            (void **)&prepname, (void **)&prep)) {
-               g_warning("camel_object_hook_event: trying to hook event `%s' in class `%s' with no defined events.",
-                         name, camel_type_to_name (obj->s.type));
-               return;
+       hook = obj->klass->hooks;
+       while (hook) {
+               if (strcmp(hook->name, name) == 0)
+                       goto setup;
+               hook = hook->next;
        }
 
+       g_warning("camel_object_hook_event: trying to hook event `%s' in class `%s' with no defined events.",
+                 name, obj->klass->name);
+
+       return 0;
+
+setup:
        /* setup hook pair */
-       pair = g_malloc(sizeof(*pair));
-       pair->name = prepname;  /* effectively static! */
-       pair->func = func;
+       pair = pair_alloc();
+       pair->name = hook->name;        /* effectively static! */
+       pair->func.event = func;
        pair->data = data;
        pair->flags = 0;
+       id = pair->id;
 
        /* get the hook list object, locked, link in new event hook, unlock */
        hooks = camel_object_get_hooks(obj);
@@ -828,33 +701,65 @@ camel_object_hook_event (CamelObject * obj, const char * name,
        hooks->list = pair;
        hooks->list_length++;
        camel_object_unget_hooks(obj);
+
+       return id;
 }
 
 void
-camel_object_unhook_event (CamelObject * obj, const char * name,
-                          CamelObjectEventHookFunc func, void *data)
+camel_object_remove_event(CamelObject * obj, unsigned int id)
 {
-       char *prepname;
-       CamelObjectEventPrepFunc prep;
        CamelHookList *hooks;
        CamelHookPair *pair, *parent;
 
        g_return_if_fail (CAMEL_IS_OBJECT (obj));
-       g_return_if_fail (name != NULL);
-       g_return_if_fail (func != NULL);
+       g_return_if_fail (id != 0);
 
        if (obj->hooks == NULL) {
-               g_warning("camel_object_unhook_event: trying to unhook `%s` from an instance of `%s' with no hooks",
-                         name, camel_type_to_name(obj->s.type));
+               g_warning("camel_object_unhook_event: trying to unhook `%d` from an instance of `%s' with no hooks",
+                         id, obj->klass->name);
                return;
        }
 
-       /* get event name static pointer */
-       if (obj->classfuncs->event_to_preplist == NULL
-           || !g_hash_table_lookup_extended(obj->classfuncs->event_to_preplist, name,
-                                            (void **)&prepname, (void **)&prep)) {
-               g_warning("camel_object_hook_event: trying to hook event `%s' in class `%s' with no defined events.",
-                         name, camel_type_to_name (obj->s.type));
+       /* scan hooks for this event, remove it, or flag it if we're busy */
+       hooks = camel_object_get_hooks(obj);
+       parent = (CamelHookPair *)&hooks->list;
+       pair = parent->next;
+       while (pair) {
+               if (pair->id == id
+                   && (pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0) {
+                       if (hooks->depth > 0) {
+                               pair->flags |= CAMEL_HOOK_PAIR_REMOVED;
+                               hooks->flags |= CAMEL_HOOK_PAIR_REMOVED;
+                       } else {
+                               parent->next = pair->next;
+                               pair_free(pair);
+                               hooks->list_length--;
+                       }
+                       camel_object_unget_hooks(obj);
+                       return;
+               }
+               parent = pair;
+               pair = pair->next;
+       }
+       camel_object_unget_hooks(obj);
+
+       g_warning("camel_object_unhook_event: cannot find hook id %d in instance of `%s'",
+                 id, obj->klass->name);
+}
+
+void
+camel_object_unhook_event(CamelObject * obj, const char * name, CamelObjectEventHookFunc func, void *data)
+{
+       CamelHookList *hooks;
+       CamelHookPair *pair, *parent;
+
+       g_return_if_fail (CAMEL_IS_OBJECT (obj));
+       g_return_if_fail (name != NULL);
+       g_return_if_fail (func != NULL);
+
+       if (obj->hooks == NULL) {
+               g_warning("camel_object_unhook_event: trying to unhook `%s` from an instance of `%s' with no hooks",
+                         name, obj->klass->name);
                return;
        }
 
@@ -863,16 +768,16 @@ camel_object_unhook_event (CamelObject * obj, const char * name,
        parent = (CamelHookPair *)&hooks->list;
        pair = parent->next;
        while (pair) {
-               if (pair->name == prepname
-                   && pair->func == func
+               if (pair->func.event == func
                    && pair->data == data
+                   && strcmp(pair->name, name) == 0
                    && (pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0) {
                        if (hooks->depth > 0) {
                                pair->flags |= CAMEL_HOOK_PAIR_REMOVED;
                                hooks->flags |= CAMEL_HOOK_PAIR_REMOVED;
                        } else {
                                parent->next = pair->next;
-                               g_free(pair);
+                               pair_free(pair);
                                hooks->list_length--;
                        }
                        camel_object_unget_hooks(obj);
@@ -884,32 +789,35 @@ camel_object_unhook_event (CamelObject * obj, const char * name,
        camel_object_unget_hooks(obj);
 
        g_warning("camel_object_unhook_event: cannot find hook/data pair %p/%p in an instance of `%s' attached to `%s'",
-                 func, data, camel_type_to_name (obj->s.type), name);
+                 func, data, obj->klass->name, name);
 }
 
 void
 camel_object_trigger_event (CamelObject * obj, const char * name, void *event_data)
 {
-       CamelObjectEventPrepFunc prep;
-       const char *prepname;
        CamelHookList *hooks;
-       CamelHookPair *pair, **pairs, *parent;
+       CamelHookPair *pair, **pairs, *parent, *hook;
        int i, size;
+       const char *prepname;
 
        g_return_if_fail (CAMEL_IS_OBJECT (obj));
        g_return_if_fail (name);
 
-       /* get event name static pointer/prep func */
-       if (obj->classfuncs->event_to_preplist == NULL
-           || !g_hash_table_lookup_extended(obj->classfuncs->event_to_preplist, name,
-                                            (void **)&prepname, (void **)&prep)) {
-               g_warning("camel_object_hook_event: trying to hook event `%s' in class `%s' with no defined events.",
-                         name, camel_type_to_name (obj->s.type));
-               return;
+       hook = obj->klass->hooks;
+       while (hook) {
+               if (strcmp(hook->name, name) == 0)
+                       goto trigger;
+               hook = hook->next;
        }
 
+       g_warning("camel_object_trigger_event: trying to trigger unknown event `%s' in class `%s'",
+                 name, obj->klass->name);
+
+       return;
+
+trigger:
        /* try prep function, if false, then quit */
-       if (prep != NULL_PREP_VALUE && !prep(obj, event_data))
+       if (hook->func.prep != NULL && !hook->func.prep(obj, event_data))
                return;
 
        /* also, no hooks, dont bother going further */
@@ -919,13 +827,14 @@ camel_object_trigger_event (CamelObject * obj, const char * name, void *event_da
        /* lock the object for hook emission */
        camel_object_ref(obj);
        hooks = camel_object_get_hooks(obj);
-
+       
        if (hooks->list) {
                /* first, copy the items in the list, and say we're in an event */
                hooks->depth++;
                pair = hooks->list;
                size = 0;
                pairs = alloca(sizeof(pairs[0]) * hooks->list_length);
+               prepname = hook->name;
                while (pair) {
                        if (pair->name == prepname)
                                pairs[size++] = pair;
@@ -936,7 +845,7 @@ camel_object_trigger_event (CamelObject * obj, const char * name, void *event_da
                for (i=0;i<size;i++) {
                        pair = pairs[i];
                        if ((pair->flags & CAMEL_HOOK_PAIR_REMOVED) == 0)
-                               (pair->func) (obj, event_data, pair->data);
+                               (pair->func.event) (obj, event_data, pair->data);
                }
                hooks->depth--;
 
@@ -947,7 +856,7 @@ camel_object_trigger_event (CamelObject * obj, const char * name, void *event_da
                        while (pair) {
                                if (pair->flags & CAMEL_HOOK_PAIR_REMOVED) {
                                        parent->next = pair->next;
-                                       g_free(pair);
+                                       pair_free(pair);
                                        hooks->list_length--;
                                } else {
                                        parent = pair;
@@ -962,154 +871,114 @@ camel_object_trigger_event (CamelObject * obj, const char * name, void *event_da
        camel_object_unref(obj);
 }
 
-/* ** Static helpers ****************************************************** */
-
-static gboolean
-shared_is_of_type (CamelObjectShared * sh, CamelType ctype, gboolean is_obj)
+/* get/set arg methods */
+int camel_object_set(CamelObject *o, CamelException *ex, ...)
 {
-       CamelTypeInfo *type_info;
-       gchar *targtype;
+       CamelArgV args;
+       CamelObjectClass *klass = o->klass;
+       int ret = 0;
 
-       if (is_obj)
-               targtype = "instance";
-       else
-               targtype = "classdata";
+       g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1);
 
-       if (ctype == CAMEL_INVALID_TYPE) {
-               g_warning
-                       ("shared_is_of_type: trying to cast to CAMEL_INVALID_TYPE");
-               return FALSE;
-       }
+       camel_argv_start(&args, ex);
 
-       if (sh == NULL) {
-               g_warning
-                       ("shared_is_of_type: trying to cast NULL to %s of `%s'",
-                        targtype, camel_type_to_name (ctype));
-               return FALSE;
-       }
+       while (camel_argv_build(&args) && ret == 0)
+               ret = klass->setv(o, ex, &args);
+       if (ret == 0)
+               ret = klass->setv(o, ex, &args);
 
-       if (sh->magic == CAMEL_OBJECT_FINALIZED_VALUE) {
-               g_warning
-                       ("shared_is_of_type: trying to cast finalized instance "
-                        "of `%s' into %s of `%s'",
-                        camel_type_to_name (sh->type), targtype,
-                        camel_type_to_name (ctype));
-               return FALSE;
-       }
+       camel_argv_end(&args);
 
-       if (sh->magic == CAMEL_OBJECT_CLASS_FINALIZED_VALUE) {
-               g_warning
-                       ("shared_is_of_type: trying to cast finalized classdata "
-                        "of `%s' into %s of `%s'",
-                        camel_type_to_name (sh->type), targtype,
-                        camel_type_to_name (ctype));
-               return FALSE;
-       }
+       return ret;
+}
 
-       if (is_obj) {
-               if (sh->magic == CAMEL_OBJECT_CLASS_MAGIC_VALUE) {
-                       g_warning
-                               ("shared_is_of_type: trying to cast classdata "
-                                "of `%s' into instance of `%s'",
-                                camel_type_to_name (sh->type),
-                                camel_type_to_name (ctype));
-                       return FALSE;
-               }
+int camel_object_setv(CamelObject *o, CamelException *ex, CamelArgV *args)
+{
+       g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1);
 
-               if (sh->magic != CAMEL_OBJECT_MAGIC_VALUE) {
-                       g_warning
-                               ("shared_is_of_type: trying to cast junk data "
-                                "into instance of `%s'",
-                                camel_type_to_name (ctype));
-                       return FALSE;
-               }
-       } else {
-               if (sh->magic == CAMEL_OBJECT_MAGIC_VALUE) {
-                       g_warning
-                               ("shared_is_of_type: trying to cast instance "
-                                "of `%s' into classdata of `%s'",
-                                camel_type_to_name (sh->type),
-                                camel_type_to_name (ctype));
-                       return FALSE;
-               }
+       return o->klass->setv(o, ex, args);
+}
 
-               if (sh->magic != CAMEL_OBJECT_CLASS_MAGIC_VALUE) {
-                       g_warning
-                               ("shared_is_of_type: trying to cast junk data "
-                                "into classdata of `%s'",
-                                camel_type_to_name (ctype));
-                       return FALSE;
-               }
-       }
+int camel_object_get(CamelObject *o, CamelException *ex, ...)
+{
+       CamelArgGetV args;
+       CamelObjectClass *klass = o->klass;
+       int ret = 0;
 
-       camel_type_lock_up ();
+       g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1);
 
-       type_info =
-               g_hash_table_lookup (ctype_to_typeinfo,
-                                    GINT_TO_POINTER (sh->type));
+       camel_argv_start(&args, ex);
 
-       if (type_info == NULL) {
-               g_warning ("shared_is_of_type: seemingly valid %s has "
-                          "bad type %d.", targtype, sh->type);
-               camel_type_lock_down ();
-               return FALSE;
-       }
+       while (camel_arggetv_build(&args) && ret == 0)
+               ret = klass->getv(o, ex, &args);
+       if (ret == 0)
+               ret = klass->getv(o, ex, &args);
 
-       while (type_info) {
-               if (type_info->self == ctype) {
-                       camel_type_lock_down ();
-                       return TRUE;
-               }
+       camel_argv_end(&args);
 
-               type_info =
-                       g_hash_table_lookup (ctype_to_typeinfo,
-                                            GINT_TO_POINTER (type_info->
-                                                             parent));
-       }
+       return ret;
+}
 
-       /* this isn't an error, e.g. CAMEL_IS_FOLDER(folder), its upto  the
-          caller to handle the false case */
-       /*g_warning
-               ("shared_is_of_type: %s of `%s' (@%p) is not also %s of `%s'",
-                targtype, camel_type_to_name (sh->type), sh, targtype,
-                camel_type_to_name (ctype));*/
+int camel_object_getv(CamelObject *o, CamelException *ex, CamelArgGetV *args)
+{
+       CamelObjectClass *klass = o->klass;
 
-       camel_type_lock_down ();
-       return FALSE;
+       g_return_val_if_fail(CAMEL_IS_OBJECT(o), -1);
+
+       return klass->getv(o, ex, args);
 }
 
 static void
-make_global_classfuncs (CamelTypeInfo * type_info)
+object_class_dump_tree_rec(CamelType root, int depth)
 {
-       CamelObjectClass *funcs;
-       GSList *parents;
-       GSList *head;
-
-       g_assert (type_info);
-
-       funcs = g_malloc0 (type_info->classfuncs_size);
-       funcs->s.type = type_info->self;
+       char *p;
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+       struct _CamelObject *o;
+#endif
 
-       type_info->global_classfuncs = funcs;
+       p = alloca(depth*2+1);
+       memset(p, ' ', depth*2);
+       p[depth*2] = 0;
 
-       parents = NULL;
-       while (type_info) {
-               parents = g_slist_prepend (parents, type_info);
-               type_info =
-                       g_hash_table_lookup (ctype_to_typeinfo,
-                                            GINT_TO_POINTER (type_info->
-                                                             parent));
-       }
+       while (root) {
+               CLASS_LOCK(root);
+               printf("%sClass: %s\n", p, root->name);
+               /*printf("%sVersion: %u.%u\n", p, root->version, root->revision);*/
+               if (root->hooks) {
+                       CamelHookPair *pair = root->hooks;
 
-       head = parents;
+                       while (pair) {
+                               printf("%s  event '%s' prep %p\n", p, pair->name, pair->func.prep);
+                               pair = pair->next;
+                       }
+               }
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+               o = root->instances;
+               while (o) {
+                       printf("%s instance %p [%d]\n", p, o, o->ref_count);
+                       /* todo: should lock hooks while it scans them */
+                       if (o->hooks) {
+                               CamelHookPair *pair = o->hooks->list;
+
+                               while (pair) {
+                                       printf("%s  hook '%s' func %p data %p\n", p, pair->name, pair->func.event, pair->data);
+                                       pair = pair->next;
+                               }
+                       }
+                       o = o->next;
+               }
+#endif
+               CLASS_UNLOCK(root);
 
-       for (; parents && parents->data; parents = parents->next) {
-               CamelTypeInfo *thisinfo;
+               if (root->child)
+                       object_class_dump_tree_rec(root->child, depth+1);
 
-               thisinfo = parents->data;
-               if (thisinfo->class_init)
-                       (thisinfo->class_init) (funcs);
+               root = root->next;
        }
+}
 
-       g_slist_free (head);
+void
+camel_object_class_dump_tree(CamelType root)
+{
+       object_class_dump_tree_rec(root, 0);
 }
index 27e30a7..0578db7 100644 (file)
@@ -4,6 +4,7 @@
 /*
  * Author:
  *  Dan Winship <danw@ximian.com>
+ *  Michael Zucchi <notzed@ximian.com>
  *
  * Copyright 2000 Ximian, Inc. (www.ximian.com)
  *
@@ -32,89 +33,152 @@ extern "C" {
 
 #include <stdlib.h>            /* size_t */
 #include <glib.h>
+#include <stdarg.h>
+#include <camel/camel-arg.h>
+#include <camel/camel-types.h> /* this is a @##$@#SF stupid header */
+
+/* this crap shouldn't be here */
 #include <libgnome/gnome-defs.h>
 #include <libgnome/gnome-i18n.h>
-#include <camel/camel-types.h>
+
+#ifdef ENABLE_THREADS
+#include <pthread.h>
+#endif
+
+/* turn on so that camel_object_class_dump_tree() dumps object instances as well */
+/*#define CAMEL_OBJECT_TRACK_INSTANCES*/
+
+typedef struct _CamelObjectClass *CamelType;
 
 #ifdef G_DISABLE_CHECKS
 #define CAMEL_CHECK_CAST( obj, ctype, ptype )         ((ptype *) obj)
-#define CAMEL_CHECK_CLASS_CAST( klass, ctype, ptype ) ((ptype *) klass)
-#define CAMEL_CHECK_TYPE( obj, ctype )                (TRUE)
-#define CAMEL_CHECK_CLASS_TYPE( klass, ctype )        (TRUE)
+#define CAMEL_CHECK_CLASS_CAST( class, ctype, ptype ) ((ptype *) class)
 #else
-#define CAMEL_CHECK_CAST( obj, ctype, ptype )         ((ptype *) camel_object_check_cast( (CamelObject *)(obj), (CamelType)(ctype) ))
-#define CAMEL_CHECK_CLASS_CAST( klass, ctype, ptype ) ((ptype *) camel_object_class_check_cast( (CamelObjectClass *)(klass), (CamelType)(ctype) ))
-#define CAMEL_CHECK_TYPE( obj, ctype )                (camel_object_is_of_type( (CamelObject *)(obj), (CamelType)(ctype) ))
-#define CAMEL_CHECK_CLASS_TYPE( klass, ctype )        (camel_object_class_is_of_type( (CamelObjectClass *)(klass), (CamelType)(ctype) ))
+#define CAMEL_CHECK_CAST( obj, ctype, ptype )         ((ptype *) camel_object_cast( (CamelObject *)(obj), (CamelType)(ctype) ))
+#define CAMEL_CHECK_CLASS_CAST( class, ctype, ptype ) ((ptype *) camel_object_class_cast( (CamelObjectClass *)(class), (CamelType)(ctype) ))
 #endif
+#define CAMEL_CHECK_TYPE( obj, ctype )                (camel_object_is( (CamelObject *)(obj), (CamelType)(ctype) ))
+#define CAMEL_CHECK_CLASS_TYPE( class, ctype )        (camel_object_class_is( (CamelObjectClass *)(class), (CamelType)(ctype) ))
 
-#define CAMEL_INVALID_TYPE ((CamelType)0)
+extern CamelType camel_object_type;
 
-#define CAMEL_OBJECT_TYPE        (camel_object_get_type ())
+#define CAMEL_OBJECT_TYPE        (camel_object_type)
 
-#define CAMEL_OBJECT(obj)        (CAMEL_CHECK_CAST((obj), CAMEL_OBJECT_TYPE, CamelObject))
-#define CAMEL_OBJECT_CLASS(k)    (CAMEL_CHECK_CLASS_CAST ((k), CAMEL_OBJECT_TYPE, CamelObjectClass))
-#define CAMEL_IS_OBJECT(o)       (CAMEL_CHECK_TYPE((o), CAMEL_OBJECT_TYPE))
-#define CAMEL_IS_OBJECT_CLASS(k) (CAMEL_CHECK_CLASS_TYPE((k), CAMEL_OBJECT_TYPE))
+/* we can't check casts till we've got the type, use the global type variable because its cheaper */
+#define CAMEL_OBJECT(obj)        (CAMEL_CHECK_CAST((obj), camel_object_type, CamelObject))
+#define CAMEL_OBJECT_CLASS(k)    (CAMEL_CHECK_CLASS_CAST ((k), camel_object_type, CamelObjectClass))
+#define CAMEL_IS_OBJECT(o)       (CAMEL_CHECK_TYPE((o), camel_object_type))
+#define CAMEL_IS_OBJECT_CLASS(k) (CAMEL_CHECK_CLASS_TYPE((k), camel_object_type))
 
-#define CAMEL_OBJECT_GET_CLASS(o) ((CamelObjectClass *)(CAMEL_OBJECT(o))->classfuncs)
-#define CAMEL_OBJECT_GET_TYPE(o)  ((CamelType)(CAMEL_OBJECT(o))->s.type)
+#define CAMEL_OBJECT_GET_CLASS(o) ((CamelObjectClass *)(CAMEL_OBJECT(o))->klass)
+#define CAMEL_OBJECT_GET_TYPE(o)  ((CamelType)(CAMEL_OBJECT(o))->klass)
 
-typedef guint32 CamelType;
+typedef struct _CamelObjectClass CamelObjectClass;
+typedef struct _CamelObject CamelObject;
+typedef unsigned int CamelObjectHookID;
 
-typedef struct _CamelObjectShared
-{
-       guint32 magic;
-       CamelType type;
-}
-CamelObjectShared;
+typedef void (*CamelObjectClassInitFunc) (CamelObjectClass *);
+typedef void (*CamelObjectClassFinalizeFunc) (CamelObjectClass *);
+typedef void (*CamelObjectInitFunc) (CamelObject *, CamelObjectClass *);
+typedef void (*CamelObjectFinalizeFunc) (CamelObject *);
 
-typedef struct _CamelObjectClass
-{
-       CamelObjectShared s;
-       
-       GHashTable *event_to_preplist;
-}
-CamelObjectClass;
+typedef gboolean (*CamelObjectEventPrepFunc) (CamelObject *, gpointer);
+typedef void (*CamelObjectEventHookFunc) (CamelObject *, gpointer, gpointer);
 
-typedef struct _CamelObject
-{
-       CamelObjectShared s;
-       CamelObjectClass *classfuncs;
+#define CAMEL_INVALID_TYPE (NULL)
+
+enum _CamelObjectFlags {
+       CAMEL_OBJECT_DESTROY = (1<<0),
+};
+
+/* TODO: create a simpleobject which has no events on it, or an interface for events */
+struct _CamelObject {
+       struct _CamelObjectClass *klass;
+
+       guint32 magic;          /* only really needed for debugging ... */
+
+       /* current hooks on this object */
        struct _CamelHookList *hooks;
-       guint32 ref_count:30;
-       guint32 in_event:1;
-       guint32 destroying:1;
-}
-CamelObject;
 
-typedef void (*CamelObjectClassInitFunc) (CamelObjectClass *);
-typedef void (*CamelObjectClassFinalizeFunc) (CamelObjectClass *);
-typedef void (*CamelObjectInitFunc) (CamelObject *);
-typedef void (*CamelObjectFinalizeFunc) (CamelObject *);
+       guint32 ref_count:24;
+       guint32 flags:8;
 
-typedef gboolean (*CamelObjectEventPrepFunc) (CamelObject *,
-                                             gpointer);
-typedef void (*CamelObjectEventHookFunc) (CamelObject *, gpointer,
-                                         gpointer);
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+       struct _CamelObject *next, *prev;
+#endif
+};
 
-/* The type system .... it's pretty simple..... */
+struct _CamelObjectClass
+{
+       struct _CamelObjectClass *parent;
+
+       guint32 magic;          /* in same spot for validation */
+
+       struct _CamelObjectClass *next, *child; /* maintain heirarchy, just for kicks */
+
+       const char *name;
+
+       void *lock;             /* lock when used in threading, else just pads struct */
+
+       /*unsigned short version, revision;*/
+
+       /* if the object's bigger than 64K, it could use redesigning */
+       unsigned short object_size/*, object_data*/;
+       unsigned short klass_size/*, klass_data*/;
+
+       /* available hooks for this class */
+       struct _CamelHookPair *hooks;
+
+       /* memchunks for this type */
+       struct _EMemChunk *instance_chunks;
+#ifdef CAMEL_OBJECT_TRACK_INSTANCES
+       struct _CamelObject *instances;
+#endif
 
+       /* init class */
+       void (*klass_init)(struct _CamelObjectClass *);
+       void (*klass_finalise)(struct _CamelObjectClass *);
+
+       /* init/finalise object */
+       void (*init)(struct _CamelObject *, struct _CamelObjectClass *);
+       void (*finalise)(struct _CamelObject *);
+
+       /* get/set interface */
+       int (*setv)(struct _CamelObject *, struct _CamelException *ex, CamelArgV *args);
+       int (*getv)(struct _CamelObject *, struct _CamelException *ex, CamelArgGetV *args);
+};
+
+/* The type system .... it's pretty simple..... */
 void camel_type_init (void);
-CamelType camel_type_register (CamelType parent, const gchar * name,
-                              size_t instance_size,
-                              size_t classfuncs_size,
-                              CamelObjectClassInitFunc class_init,
-                              CamelObjectClassFinalizeFunc
-                              class_finalize,
-                              CamelObjectInitFunc instance_init,
-                              CamelObjectFinalizeFunc
-                              instance_finalize);
-CamelObjectClass *camel_type_get_global_classfuncs (CamelType type);
-const gchar *camel_type_to_name (CamelType type);
+CamelType camel_type_register(CamelType parent, const char * name, /*unsigned int ver, unsigned int rev,*/
+                             size_t instance_size,
+                             size_t classfuncs_size,
+                             CamelObjectClassInitFunc class_init,
+                             CamelObjectClassFinalizeFunc  class_finalize,
+                             CamelObjectInitFunc instance_init,
+                             CamelObjectFinalizeFunc instance_finalize);
+
+/* deprecated interface */
+#define camel_type_get_global_classfuncs(x) ((CamelObjectClass *)(x))
+
+/* object class methods (types == classes now) */
+const char *camel_type_to_name (CamelType type);
+CamelType camel_name_to_type(const char *name);
+void camel_object_class_add_event (CamelObjectClass *class, const char * name, CamelObjectEventPrepFunc prep);
+
+void camel_object_class_dump_tree(CamelType root);
+
+/* casting */
+CamelObject *camel_object_cast(CamelObject * obj, CamelType ctype);
+gboolean camel_object_is(CamelObject * obj, CamelType ctype);
+
+CamelObjectClass *camel_object_class_cast (CamelObjectClass *k, CamelType ctype);
+gboolean camel_object_class_is (CamelObjectClass * class, CamelType ctype);
 
 CamelType camel_object_get_type (void);
+
 CamelObject *camel_object_new (CamelType type);
+CamelObject *camel_object_new_name (const char *name);
 
 void camel_object_ref (CamelObject *obj);
 void camel_object_unref (CamelObject *obj);
@@ -124,26 +188,17 @@ void camel_object_unref (CamelObject *obj);
 #define camel_object_unref(o) (printf("%s (%s:%d):unref (%p)\n", __FUNCTION__, __FILE__, __LINE__, o), camel_object_unref (o))
 #endif
 
-CamelObject *camel_object_check_cast (CamelObject *obj,
-                                     CamelType ctype);
-CamelObjectClass *camel_object_class_check_cast (CamelObjectClass *klass,
-                                                CamelType ctype);
-gboolean camel_object_is_of_type (CamelObject *obj, CamelType ctype);
-gboolean camel_object_class_is_of_type (CamelObjectClass *klass,
-                                       CamelType ctype);
-gchar *camel_object_describe (CamelObject *obj);
-void camel_object_class_declare_event (CamelObjectClass *klass,
-                                      const char *name,
-                                      CamelObjectEventPrepFunc prep);
-void camel_object_hook_event (CamelObject *obj, const char * name,
-                             CamelObjectEventHookFunc hook,
-                             gpointer user_data);
-void camel_object_unhook_event (CamelObject *obj, const char * name,
-                               CamelObjectEventHookFunc hook,
-                               gpointer user_data);
-void camel_object_trigger_event (CamelObject *obj,
-                                const char *name,
-                                gpointer event_data);
+/* hooks */
+CamelObjectHookID camel_object_hook_event(CamelObject *obj, const char *name, CamelObjectEventHookFunc hook, void *data);
+void camel_object_remove_event(CamelObject *obj, CamelObjectHookID id);
+void camel_object_unhook_event(CamelObject *obj, const char *name, CamelObjectEventHookFunc hook, void *data);
+void camel_object_trigger_event(CamelObject *obj, const char *name, void *event_data);
+
+/* get/set methods */
+int camel_object_set(CamelObject *obj, struct _CamelException *ex, ...);
+int camel_object_setv(CamelObject *obj, struct _CamelException *ex, CamelArgV *);
+int camel_object_get(CamelObject *obj, struct _CamelException *ex, ...);
+int camel_object_getv(CamelObject *obj, struct _CamelException *ex, CamelArgGetV *);
 
 #ifdef __cplusplus
 }
index 0b87390..3433da3 100644 (file)
@@ -39,7 +39,7 @@ typedef struct _CamelPartitionMap CamelPartitionMap;
 typedef struct _CamelPartitionMapBlock CamelPartitionMapBlock;
 
 typedef struct _CamelPartitionTable CamelPartitionTable;
-typedef struct _CamelPartitionTable CamelPartitionTableClass;
+typedef struct _CamelPartitionTableClass CamelPartitionTableClass;
 
 struct _CamelPartitionKey {
        camel_hash_t hashid;
@@ -97,7 +97,7 @@ typedef struct _CamelKeyBlock CamelKeyBlock;
 typedef struct _CamelKeyRootBlock CamelKeyRootBlock;
 
 typedef struct _CamelKeyTable CamelKeyTable;
-typedef struct _CamelKeyTable CamelKeyTableClass;
+typedef struct _CamelKeyTableClass CamelKeyTableClass;
 
 struct _CamelKeyRootBlock {
        camel_block_t first;
index 5f56b66..76fdc64 100644 (file)
@@ -338,6 +338,8 @@ remote_send_string (CamelRemoteStore *store, CamelException *ex, char *fmt, va_l
                        fprintf (stderr, "sending : ------ LOGIN \"xxxx\" \"xxxx\"\n");
                else if (strstr (cmdbuf, "LOGIN {"))
                        fprintf (stderr, "sending : ------ LOGIN {N+} ....\n");
+               else if (strstr (cmdbuf, "LOGIN "))
+                       fprintf (stderr, "sending : ------ LOGIN xxxx xxxx\n");
                else
                        fprintf (stderr, "sending : %s", cmdbuf);
        }
index 6f11f12..a26d2fa 100644 (file)
@@ -118,7 +118,7 @@ struct _CamelStoreSummaryClass {
        void (*folder_info_set_string)(CamelStoreSummary *, CamelFolderInfo *, int, const char *);
 };
 
-guint                   camel_store_summary_get_type   (void);
+CamelType                       camel_store_summary_get_type   (void);
 CamelStoreSummary      *camel_store_summary_new        (void);
 
 void camel_store_summary_set_filename(CamelStoreSummary *, const char *);
index d230ef3..6764ac0 100644 (file)
@@ -44,7 +44,7 @@
 static CamelServiceClass *parent_class = NULL;
 
 /* Returns the class for a CamelStore */
-#define CS_CLASS(so) ((CamelStoreClass *)((CamelObject *)(so))->classfuncs)
+#define CS_CLASS(so) ((CamelStoreClass *)((CamelObject *)(so))->klass)
 
 static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
                                guint32 flags, CamelException *ex);
@@ -103,11 +103,11 @@ camel_store_class_init (CamelStoreClass *camel_store_class)
        /* virtual method overload */
        camel_service_class->construct = construct;
 
-       camel_object_class_declare_event(camel_object_class, "folder_created", NULL);
-       camel_object_class_declare_event(camel_object_class, "folder_deleted", NULL);
-       camel_object_class_declare_event(camel_object_class, "folder_renamed", NULL);
-       camel_object_class_declare_event(camel_object_class, "folder_subscribed", NULL);
-       camel_object_class_declare_event(camel_object_class, "folder_unsubscribed", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_created", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_deleted", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_renamed", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_subscribed", NULL);
+       camel_object_class_add_event(camel_object_class, "folder_unsubscribed", NULL);
 }
 
 static void
@@ -474,10 +474,10 @@ camel_store_rename_folder (CamelStore *store, const char *old_name, const char *
                        flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
                
                reninfo.old_base = (char *)old_name;
-               reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info(store, new_name, flags, ex);
+               reninfo.new = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, new_name, flags, ex);
                if (reninfo.new != NULL) {
                        camel_object_trigger_event(CAMEL_OBJECT(store), "folder_renamed", &reninfo);
-                       ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->free_folder_info(store, reninfo.new);
+                       ((CamelStoreClass *)((CamelObject *)store)->klass)->free_folder_info(store, reninfo.new);
                }
        } else {
                /* Failed, just unlock our folders for re-use */
index ae50e01..3d265e8 100644 (file)
@@ -49,7 +49,7 @@ struct _CamelStreamFilterClass {
        CamelStreamClass parent_class;
 };
 
-guint                  camel_stream_filter_get_type    (void);
+CamelType                      camel_stream_filter_get_type    (void);
 
 CamelStreamFilter      *camel_stream_filter_new_with_stream    (CamelStream *stream);
 
index f2e1c26..be11da7 100644 (file)
@@ -46,7 +46,7 @@ struct _CamelStreamNullClass {
        CamelStreamClass parent_class;
 };
 
-guint                  camel_stream_null_get_type      (void);
+CamelType                      camel_stream_null_get_type      (void);
 
 CamelStream            *camel_stream_null_new          (void);
 
index 1982321..de2a525 100644 (file)
@@ -97,7 +97,7 @@ struct _CamelTextIndexClass {
        CamelIndexClass parent_class;
 };
 
-guint             camel_text_index_get_type    (void);
+CamelType                 camel_text_index_get_type    (void);
 CamelTextIndex    *camel_text_index_new(const char *path, int flags);
 
 /* static utility functions */
index ab5bcf3..7ccaae7 100644 (file)
@@ -570,7 +570,7 @@ vee_sync(CamelFolder *folder, gboolean expunge, CamelException *ex)
 static void
 vee_expunge (CamelFolder *folder, CamelException *ex)
 {
-       ((CamelFolderClass *)((CamelObject *)folder)->classfuncs)->sync(folder, TRUE, ex);
+       ((CamelFolderClass *)((CamelObject *)folder)->klass)->sync(folder, TRUE, ex);
 }
 
 static CamelMimeMessage *
index c461d80..8d6770b 100644 (file)
@@ -64,7 +64,7 @@ struct _CamelVeeFolderClass {
 
 #define CAMEL_UNMATCHED_NAME "UNMATCHED"
 
-guint        camel_vee_folder_get_type         (void);
+CamelType            camel_vee_folder_get_type         (void);
 CamelFolder  *camel_vee_folder_new             (CamelStore *parent_store, const char *name, guint32 flags);
 void         camel_vee_folder_construct                (CamelVeeFolder *vf, CamelStore *parent_store, const char *name, guint32 flags);
 
index 6fe9e31..e8fa105 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include "camel-exception.h"
 #include "camel-vee-store.h"
 #include "camel-vee-folder.h"
index 974bca5..b7309c3 100644 (file)
@@ -51,7 +51,7 @@ struct _CamelVeeStoreClass {
        CamelStoreClass parent_class;
 };
 
-guint          camel_vee_store_get_type        (void);
+CamelType              camel_vee_store_get_type        (void);
 CamelVeeStore      *camel_vee_store_new        (void);
 
 #ifdef __cplusplus
index 2bdc67b..25807b5 100644 (file)
@@ -64,6 +64,9 @@ camel_init (const char *configdir, gboolean nss_init)
        if (getenv ("CAMEL_VERBOSE_DEBUG"))
                camel_verbose_debug = TRUE;
 
+       /* initialise global camel_object_type */
+       camel_object_get_type();
+
        camel_mime_utils_init();
 
 #ifdef HAVE_NSS
index 6a2382b..f8ea456 100644 (file)
@@ -696,10 +696,14 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
                                        arglen += strlen (store->namespace) + 1;
                        }
                        g_ptr_array_add (args, string);
-                       if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS)
-                               len += arglen + 15;
-                       else
-                               len += arglen * 2;
+                       if (imap_is_atom(string)) {
+                               len += arglen;
+                       } else {
+                               if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS)
+                                       len += arglen + 15;
+                               else
+                                       len += arglen * 2;
+                       }
                        start = p + 1;
                        break;
 
@@ -750,16 +754,21 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
                                string = imap_mailbox_encode (mailbox, strlen (mailbox));
                                g_free (mailbox);
                        }
-                       
-                       if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) {
-                               op += sprintf (op, "{%d+}\r\n%s",
-                                              strlen (string), string);
+
+                       if (imap_is_atom(string)) {
+                               op += sprintf(op, "%s", string);
                        } else {
-                               char *quoted = imap_quote_string (string);
-                               
-                               op += sprintf (op, "%s", quoted);
-                               g_free (quoted);
+                               if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) {
+                                       op += sprintf (op, "{%d+}\r\n%s",
+                                                      strlen (string), string);
+                               } else {
+                                       char *quoted = imap_quote_string (string);
+
+                                       op += sprintf (op, "%s", quoted);
+                                       g_free (quoted);
+                               }
                        }
+
                        if (*p == 'F')
                                g_free (string);
                        break;
index 9d1694c..7664c4c 100644 (file)
@@ -56,7 +56,7 @@ struct _CamelImapSearchClass {
 
 };
 
-guint              camel_imap_search_get_type (void);
+CamelType              camel_imap_search_get_type (void);
 CamelFolderSearch *camel_imap_search_new      (const char *cachedir);
 
 #endif /* ! _CAMEL_IMAP_SEARCH_H */
index ce87174..316ab69 100644 (file)
@@ -1184,7 +1184,7 @@ rename_folder (CamelStore *store, const char *old_name, const char *new_name, Ca
        flags = CAMEL_STORE_FOLDER_INFO_FAST | CAMEL_STORE_FOLDER_INFO_RECURSIVE |
                (store->flags & CAMEL_STORE_SUBSCRIPTIONS ? CAMEL_STORE_FOLDER_INFO_SUBSCRIBED : 0);
        
-       fi = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info (store, old_name, flags, ex);
+       fi = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info (store, old_name, flags, ex);
        if (fi && store->flags & CAMEL_STORE_SUBSCRIPTIONS)
                unsubscribe_folders (store, fi);
        
index b6c048f..f64cc00 100644 (file)
  * Boston, MA 02111-1307, USA.
  */
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <sys/stat.h>
 #include <sys/uio.h>
 #include <unistd.h>
index 14f5dd2..3b203f6 100644 (file)
@@ -63,7 +63,7 @@ struct _CamelImapSummaryClass {
 
 };
 
-guint               camel_imap_summary_get_type     (void);
+CamelType               camel_imap_summary_get_type     (void);
 CamelFolderSummary *camel_imap_summary_new          (const char *filename);
 
 void camel_imap_summary_add_offline (CamelFolderSummary *summary,
index 91d2efb..7ee7ff8 100644 (file)
@@ -271,17 +271,63 @@ imap_parse_flag_list (char **flag_list_p)
        return flags;
 }
 
-static char imap_atom_specials[128] = {
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 
+/*
+ From rfc2060
+
+ATOM_CHAR       ::= <any CHAR except atom_specials>
+
+atom_specials   ::= "(" / ")" / "{" / SPACE / CTL / list_wildcards /
+                    quoted_specials
+
+CHAR            ::= <any 7-bit US-ASCII character except NUL,
+                     0x01 - 0x7f>
+
+CTL             ::= <any ASCII control character and DEL,
+                        0x00 - 0x1f, 0x7f>
+
+SPACE           ::= <ASCII SP, space, 0x20>
+
+list_wildcards  ::= "%" / "*"
+
+quoted_specials ::= <"> / "\"
+*/
+
+static unsigned char imap_atom_specials[256] = {
+/* 00 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 10 */0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 20 */0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,
+/* 30 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 40 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 50 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
+/* 60 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+/* 70 */1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-       1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 
 };
-#define imap_is_atom_char(ch) (isprint (ch) && !imap_atom_specials[ch])
+
+#define imap_is_atom_char(c) ((imap_atom_specials[(c)&0xff] & 0x01) != 0)
+
+gboolean
+imap_is_atom(const char *in)
+{
+       register unsigned char c;
+       register const char *p = in;
+
+       while ((c = (unsigned char)*p)) {
+               if (!imap_is_atom_char(c))
+                       return FALSE;
+               p++;
+       }
+
+       /* check for empty string */
+       return p!=in;
+}
 
 /**
  * imap_parse_string_generic:
index 924b71c..7078e12 100644 (file)
@@ -63,6 +63,7 @@ char    *imap_parse_string_generic (char **str_p, size_t *len, int type);
 void     imap_parse_body           (char **body_p, CamelFolder *folder,
                                    CamelMessageContentInfo *ci);
 
+gboolean imap_is_atom              (const char *in);
 char    *imap_quote_string         (const char *str);
 
 void     imap_skip_list            (char **str_p);
index 6a51046..a0d3708 100644 (file)
@@ -242,10 +242,10 @@ create_folder(CamelStore *store, const char *parent_name, const char *folder_nam
 
        name = g_strdup_printf("%s/%s", parent_name, folder_name);
 
-       folder = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex);
+       folder = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder(store, name, CAMEL_STORE_FOLDER_CREATE, ex);
        if (folder) {
                camel_object_unref((CamelObject *)folder);
-               info = ((CamelStoreClass *)((CamelObject *)store)->classfuncs)->get_folder_info(store, name, 0, ex);
+               info = ((CamelStoreClass *)((CamelObject *)store)->klass)->get_folder_info(store, name, 0, ex);
 
                /* get_folder(CREATE) will emit a folder_created event for us */
                /*if (info)
index 4a4db95..d1153fa 100644 (file)
@@ -62,7 +62,7 @@ struct _CamelLocalSummaryClass {
        int (*decode_x_evolution)(CamelLocalSummary *cls, const char *xev, CamelMessageInfo *info);
 };
 
-guint  camel_local_summary_get_type    (void);
+CamelType      camel_local_summary_get_type    (void);
 void   camel_local_summary_construct   (CamelLocalSummary *new, const char *filename, const char *local_name, CamelIndex *index);
 
 /* load/check the summary */
index ec4d015..6c61da2 100644 (file)
@@ -52,7 +52,7 @@ struct _CamelMboxSummaryClass {
        CamelLocalSummaryClass parent_class;
 };
 
-guint          camel_mbox_summary_get_type     (void);
+CamelType              camel_mbox_summary_get_type     (void);
 CamelMboxSummary      *camel_mbox_summary_new  (const char *filename, const char *mbox_name, CamelIndex *index);
 
 /* generate a From line from headers */
index 5b20e1d..77fa6bd 100644 (file)
@@ -67,7 +67,7 @@ struct _CamelSpoolSummaryClass {
        int (*decode_x_evolution)(CamelSpoolSummary *cls, const char *xev, CamelMessageInfo *info);
 };
 
-guint  camel_spool_summary_get_type    (void);
+CamelType      camel_spool_summary_get_type    (void);
 void   camel_spool_summary_construct   (CamelSpoolSummary *new, const char *filename, const char *spool_name, CamelIndex *index);
 
 /* create the summary, in-memory only */
index e7b732b..eef217c 100644 (file)
@@ -52,7 +52,7 @@ struct _CamelNNTPStreamClass {
        CamelStreamClass parent_class;
 };
 
-guint           camel_nntp_stream_get_type     (void);
+CamelType               camel_nntp_stream_get_type     (void);
 
 CamelStream     *camel_nntp_stream_new         (CamelStream *source);
 
index b822834..82070cd 100644 (file)
@@ -47,7 +47,7 @@ struct _CamelNNTPSummaryClass {
        CamelFolderSummaryClass parent_class;
 };
 
-guint  camel_nntp_summary_get_type     (void);
+CamelType      camel_nntp_summary_get_type     (void);
 CamelNNTPSummary *camel_nntp_summary_new(struct _CamelNNTPFolder *folder);
 
 int camel_nntp_summary_check(CamelNNTPSummary *cns, CamelFolderChangeInfo *, CamelException *ex);
index 6b1f0ce..caf6ca1 100644 (file)
@@ -112,7 +112,7 @@ struct _CamelPOP3EngineClass {
        CamelObjectClass parent_class;
 };
 
-guint            camel_pop3_engine_get_type    (void);
+CamelType                camel_pop3_engine_get_type    (void);
 
 CamelPOP3Engine  *camel_pop3_engine_new                (CamelStream *source);
 
index 2baf48d..2a4ebc0 100644 (file)
@@ -55,7 +55,7 @@ struct _CamelPOP3StreamClass {
        CamelStreamClass parent_class;
 };
 
-guint           camel_pop3_stream_get_type     (void);
+CamelType               camel_pop3_stream_get_type     (void);
 
 CamelStream     *camel_pop3_stream_new         (CamelStream *source);