2010-10-03 [colin] 3.7.6cvs53
authorColin Leroy <colin@colino.net>
Sun, 3 Oct 2010 11:46:24 +0000 (11:46 +0000)
committerColin Leroy <colin@colino.net>
Sun, 3 Oct 2010 11:46:24 +0000 (11:46 +0000)
* src/folder.c
* src/folder.h
* src/imap.c
* src/mh.c
* src/procmsg.c
Get rid of GRelation which were, mostly, used as
GHashTables. Probably fixes bug #2277, 'Segfault when
loading inbox for the first time'

ChangeLog
PATCHSETS
configure.ac
src/folder.c
src/folder.h
src/imap.c
src/mh.c
src/procmsg.c

index 4c4a1a3..e89dea3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-10-03 [colin]     3.7.6cvs53
+
+       * src/folder.c
+       * src/folder.h
+       * src/imap.c
+       * src/mh.c
+       * src/procmsg.c
+               Get rid of GRelation which were, mostly, used as
+               GHashTables. Probably fixes bug #2277, 'Segfault when
+               loading inbox for the first time'
+
 2010-10-03 [mir]       3.7.6cvs52
 
        * manual/de/dist/html/Makefile.am
 2010-10-03 [mir]       3.7.6cvs52
 
        * manual/de/dist/html/Makefile.am
index 897b3a4..e6b7c7c 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 manual/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/fr/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/pl/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/txt/Makefile.am;  ) > 3.7.6cvs50.patchset
 ( cvs diff -u -r 1.53.2.36 -r 1.53.2.37 po/POTFILES.in;  ) > 3.7.6cvs51.patchset
 ( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 manual/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/fr/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/pl/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/txt/Makefile.am;  ) > 3.7.6cvs52.patchset
 ( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 manual/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/fr/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/pl/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/txt/Makefile.am;  ) > 3.7.6cvs50.patchset
 ( cvs diff -u -r 1.53.2.36 -r 1.53.2.37 po/POTFILES.in;  ) > 3.7.6cvs51.patchset
 ( cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.1 -r 1.1.2.2 manual/de/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 manual/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.5 -r 1.1.2.6 manual/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 manual/es/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/fr/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/fr/dist/txt/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/html/Makefile.am;  cvs diff -u -r 1.1.2.4 -r 1.1.2.5 manual/pl/dist/pdf/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/ps/Makefile.am;  cvs diff -u -r 1.1.2.3 -r 1.1.2.4 manual/pl/dist/txt/Makefile.am;  ) > 3.7.6cvs52.patchset
+( cvs diff -u -r 1.213.2.196 -r 1.213.2.197 src/folder.c;  cvs diff -u -r 1.87.2.61 -r 1.87.2.62 src/folder.h;  cvs diff -u -r 1.179.2.251 -r 1.179.2.252 src/imap.c;  cvs diff -u -r 1.79.2.69 -r 1.79.2.70 src/mh.c;  cvs diff -u -r 1.150.2.115 -r 1.150.2.116 src/procmsg.c;  ) > 3.7.6cvs53.patchset
index 1a2107b..9dfc299 100644 (file)
@@ -12,7 +12,7 @@ MINOR_VERSION=7
 MICRO_VERSION=6
 INTERFACE_AGE=0
 BINARY_AGE=0
 MICRO_VERSION=6
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=52
+EXTRA_VERSION=53
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 0ee5637..affd58a 100644 (file)
@@ -1883,7 +1883,7 @@ static gint folder_sort_folder_list(gconstpointer a, gconstpointer b)
 
 static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
 {
 
 static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
 {
-       GRelation *relation;
+       GHashTable *relation;
        gint ret = 0;
        GSList *cur;
 
        gint ret = 0;
        GSList *cur;
 
@@ -1894,38 +1894,32 @@ static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist)
        if (item->no_select)
                return 0;
 
        if (item->no_select)
                return 0;
 
-       relation = g_relation_new(2);
-       g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
+       relation = g_hash_table_new(g_direct_hash, g_direct_equal);
        if ((ret = item->folder->klass->get_flags(
            item->folder, item, msglist, relation)) == 0) {
        if ((ret = item->folder->klass->get_flags(
            item->folder, item, msglist, relation)) == 0) {
-               GTuples *tuples;
+               gpointer data, old_key;
                MsgInfo *msginfo;
                MsgPermFlags permflags = 0;
                MsgInfo *msginfo;
                MsgPermFlags permflags = 0;
-               gboolean skip;
 
                folder_item_update_freeze();
                folder_item_set_batch(item, TRUE);
                for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
                        msginfo = (MsgInfo *) cur->data;
                
 
                folder_item_update_freeze();
                folder_item_set_batch(item, TRUE);
                for (cur = msglist; cur != NULL; cur = g_slist_next(cur)) {
                        msginfo = (MsgInfo *) cur->data;
                
-                       tuples = g_relation_select(relation, msginfo, 0);
-                       skip = tuples->len < 1;
-                       if (!skip)
-                               permflags = GPOINTER_TO_INT(g_tuples_index(tuples, 0, 1));
-                       g_tuples_destroy(tuples);
-                       if (skip)
-                               continue;
-                       
-                       if (msginfo->flags.perm_flags != permflags) {
-                               procmsg_msginfo_change_flags(msginfo,
-                                       permflags & ~msginfo->flags.perm_flags, 0,
-                                       ~permflags & msginfo->flags.perm_flags, 0);
+                       if (g_hash_table_lookup_extended(relation, msginfo, &old_key, &data)) {
+                               permflags = GPOINTER_TO_INT(data);
+
+                               if (msginfo->flags.perm_flags != permflags) {
+                                       procmsg_msginfo_change_flags(msginfo,
+                                               permflags & ~msginfo->flags.perm_flags, 0,
+                                               ~permflags & msginfo->flags.perm_flags, 0);
+                               }
                        }
                }
                folder_item_set_batch(item, FALSE);
                folder_item_update_thaw();
        }
                        }
                }
                folder_item_set_batch(item, FALSE);
                folder_item_update_thaw();
        }
-       g_relation_destroy(relation);   
+       g_hash_table_destroy(relation); 
 
        return ret;
 }
 
        return ret;
 }
@@ -3123,7 +3117,7 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list,
         Folder *folder;
         gint ret, num, lastnum = -1;
        GSList *file_cur;
         Folder *folder;
         gint ret, num, lastnum = -1;
        GSList *file_cur;
-       GRelation *relation;
+       GHashTable *relation;
        MsgFileInfo *fileinfo = NULL;
        gboolean folderscan = FALSE;
 
        MsgFileInfo *fileinfo = NULL;
        gboolean folderscan = FALSE;
 
@@ -3135,13 +3129,12 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list,
 
         folder = dest->folder;
 
 
         folder = dest->folder;
 
-       relation = g_relation_new(2);
-       g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
+       relation = g_hash_table_new(g_direct_hash, g_direct_equal);
 
        if (folder->klass->add_msgs != NULL) {
                ret = folder->klass->add_msgs(folder, dest, file_list, relation);
                if (ret < 0) {
 
        if (folder->klass->add_msgs != NULL) {
                ret = folder->klass->add_msgs(folder, dest, file_list, relation);
                if (ret < 0) {
-                       g_relation_destroy(relation);
+                       g_hash_table_destroy(relation);
                        return ret;
                }
        } else {
                        return ret;
                }
        } else {
@@ -3150,20 +3143,21 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list,
 
                        ret = folder->klass->add_msg(folder, dest, fileinfo->file, fileinfo->flags);
                        if (ret < 0) {
 
                        ret = folder->klass->add_msg(folder, dest, fileinfo->file, fileinfo->flags);
                        if (ret < 0) {
-                               g_relation_destroy(relation);
+                               g_hash_table_destroy(relation);
                                return ret;
                        }
                                return ret;
                        }
-                       g_relation_insert(relation, fileinfo, GINT_TO_POINTER(ret));
+                       g_hash_table_insert(relation, fileinfo, GINT_TO_POINTER(ret));
                }
        }
 
        for (file_cur = file_list; file_cur != NULL; file_cur = g_slist_next(file_cur)) {
                }
        }
 
        for (file_cur = file_list; file_cur != NULL; file_cur = g_slist_next(file_cur)) {
-               GTuples *tuples;
+               gpointer data, old_key;
 
                fileinfo = (MsgFileInfo *) file_cur->data;
 
                fileinfo = (MsgFileInfo *) file_cur->data;
-               tuples = g_relation_select(relation, fileinfo, 0);
-               num = GPOINTER_TO_INT(g_tuples_index(tuples, 0, 1));
-               g_tuples_destroy(tuples);
+               if (g_hash_table_lookup_extended(relation, fileinfo, &old_key, &data))
+                       num = GPOINTER_TO_INT(data);
+               else
+                       num = -1;
 
                if (num >= 0) {
                        MsgInfo *newmsginfo;
 
                if (num >= 0) {
                        MsgInfo *newmsginfo;
@@ -3199,7 +3193,7 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list,
                }
        }
 
                }
        }
 
-       g_relation_destroy(relation);
+       g_hash_table_destroy(relation);
 
         return lastnum;
 }
 
         return lastnum;
 }
@@ -3351,6 +3345,27 @@ gint folder_item_move_to(FolderItem *src, FolderItem *dest, FolderItem **new_ite
        return F_MOVE_OK;
 }
 
        return F_MOVE_OK;
 }
 
+struct find_data
+{
+       gboolean found;
+};     
+static void find_num(gpointer key, gpointer value, gpointer data)
+{
+       struct find_data *fdata = (struct find_data *)data;
+       if (GPOINTER_TO_INT(value) == 0)
+               fdata->found = TRUE;
+}
+
+static gboolean some_msgs_have_zero_num(GHashTable *hashtable)
+{
+       struct find_data fdata;
+       
+       fdata.found = FALSE;
+       g_hash_table_foreach(hashtable, find_num, &fdata);
+       
+       return fdata.found;
+}
+
 /**
  * Copy a list of message to a new folder and remove
  * source messages if wanted
 /**
  * Copy a list of message to a new folder and remove
  * source messages if wanted
@@ -3361,7 +3376,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
        GSList *l;
        gint num, lastnum = -1;
        gboolean folderscan = FALSE;
        GSList *l;
        gint num, lastnum = -1;
        gboolean folderscan = FALSE;
-       GRelation *relation;
+       GHashTable *relation;
        GSList *not_moved = NULL;
        gint total = 0, curmsg = 0;
        MsgInfo *msginfo = NULL;
        GSList *not_moved = NULL;
        gint total = 0, curmsg = 0;
        MsgInfo *msginfo = NULL;
@@ -3409,9 +3424,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
                return queue_err ? -1:0;
        }
 
                return queue_err ? -1:0;
        }
 
-       relation = g_relation_new(2);
-       g_relation_index(relation, 0, g_direct_hash, g_direct_equal);
-       g_relation_index(relation, 1, g_direct_hash, g_direct_equal);
+       relation = g_hash_table_new(g_direct_hash, g_direct_equal);
 
        for (l = msglist ; l != NULL ; l = g_slist_next(l)) {
                MsgInfo * msginfo = (MsgInfo *) l->data;
 
        for (l = msglist ; l != NULL ; l = g_slist_next(l)) {
                MsgInfo * msginfo = (MsgInfo *) l->data;
@@ -3430,7 +3443,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
         */
        if (folder->klass->copy_msgs != NULL) {
                if (folder->klass->copy_msgs(folder, dest, msglist, relation) < 0) {
         */
        if (folder->klass->copy_msgs != NULL) {
                if (folder->klass->copy_msgs(folder, dest, msglist, relation) < 0) {
-                       g_relation_destroy(relation);
+                       g_hash_table_destroy(relation);
                        return -1;
                }
        } else {
                        return -1;
                }
        } else {
@@ -3441,7 +3454,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
                if (l != NULL) {
                        msginfo = (MsgInfo *) l->data;
                        if (msginfo != NULL && msginfo->folder == dest) {
                if (l != NULL) {
                        msginfo = (MsgInfo *) l->data;
                        if (msginfo != NULL && msginfo->folder == dest) {
-                               g_relation_destroy(relation);
+                               g_hash_table_destroy(relation);
                                return -1;
                        }
                }
                                return -1;
                        }
                }
@@ -3451,7 +3464,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
 
                        num = folder->klass->copy_msg(folder, dest, msginfo);
                        if (num > 0)
 
                        num = folder->klass->copy_msg(folder, dest, msginfo);
                        if (num > 0)
-                               g_relation_insert(relation, msginfo, GINT_TO_POINTER(num));
+                               g_hash_table_insert(relation, msginfo, GINT_TO_POINTER(num));
                        else
                                not_moved = g_slist_prepend(not_moved, msginfo);
                }
                        else
                                not_moved = g_slist_prepend(not_moved, msginfo);
                }
@@ -3472,20 +3485,14 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
                                                                relation);
                }
                for (l = msglist; l != NULL; l = g_slist_next(l)) {
                                                                relation);
                }
                for (l = msglist; l != NULL; l = g_slist_next(l)) {
-                       GTuples *tuples;
+                       gpointer old_key, data;
                        msginfo = (MsgInfo *) l->data;
                        item = msginfo->folder;
 
                        msginfo = (MsgInfo *) l->data;
                        item = msginfo->folder;
 
-                       tuples = g_relation_select(relation, msginfo, 0);
-                       if (tuples) {
-                               if (tuples->len)
-                                       num = GPOINTER_TO_INT(g_tuples_index(tuples, 0, 1));
-                               else
-                                       num = 0;
-                               g_tuples_destroy(tuples);
-                       } else {
+                       if (g_hash_table_lookup_extended(relation, msginfo, &old_key, &data))
+                               num = GPOINTER_TO_INT(data);
+                       else
                                num = -1;
                                num = -1;
-                       }
 
                        if (g_slist_find(not_moved, msginfo))
                                continue;
 
                        if (g_slist_find(not_moved, msginfo))
                                continue;
@@ -3509,7 +3516,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
         * Fetch new MsgInfos for new messages in dest folder,
         * add them to the msgcache and update folder message counts
         */
         * Fetch new MsgInfos for new messages in dest folder,
         * add them to the msgcache and update folder message counts
         */
-       if (g_relation_count(relation, GINT_TO_POINTER(0), 1) > 0) {
+       if (some_msgs_have_zero_num(relation)) {
                folder_item_scan_full(dest, FALSE);
                folderscan = TRUE;
        }
                folder_item_scan_full(dest, FALSE);
                folderscan = TRUE;
        }
@@ -3524,19 +3531,16 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
        folder_item_set_batch(dest, TRUE);
        for (l = msglist; l != NULL; l = g_slist_next(l)) {
                MsgInfo *msginfo = (MsgInfo *) l->data;
        folder_item_set_batch(dest, TRUE);
        for (l = msglist; l != NULL; l = g_slist_next(l)) {
                MsgInfo *msginfo = (MsgInfo *) l->data;
-                GTuples *tuples;
+                gpointer data, old_key;
 
                if (!msginfo)
                        continue;
 
                if (!msginfo)
                        continue;
-                tuples = g_relation_select(relation, msginfo, 0);
-               if (tuples && tuples->len > 0) {
-                       num = GPOINTER_TO_INT(g_tuples_index(tuples, 0, 1));
-                       g_tuples_destroy(tuples);
-               } else {
-                       num = 0;
-                       if (tuples)
-                               g_tuples_destroy(tuples);
-               }
+
+                if (g_hash_table_lookup_extended(relation, msginfo, &old_key, &data))
+                       num = GPOINTER_TO_INT(data);
+               else
+                       num = -1;
+
                statusbar_progress_all(curmsg++,total, 100);
                if (curmsg % 100 == 0)
                        GTK_EVENTS_FLUSH();
                statusbar_progress_all(curmsg++,total, 100);
                if (curmsg % 100 == 0)
                        GTK_EVENTS_FLUSH();
@@ -3590,7 +3594,7 @@ static gint do_copy_msgs(FolderItem *dest, GSList *msglist, gboolean remove_sour
        statusbar_progress_all(0,0,0);
        statusbar_pop_all();
 
        statusbar_progress_all(0,0,0);
        statusbar_pop_all();
 
-       g_relation_destroy(relation);
+       g_hash_table_destroy(relation);
        if (not_moved != NULL) {
                g_slist_free(not_moved);
                return -1;
        if (not_moved != NULL) {
                g_slist_free(not_moved);
                return -1;
index 602cd8e..3c500d7 100644 (file)
@@ -474,7 +474,7 @@ struct _FolderClass
        gint            (*add_msgs)             (Folder         *folder,
                                                 FolderItem     *dest,
                                                 GSList         *file_list,
        gint            (*add_msgs)             (Folder         *folder,
                                                 FolderItem     *dest,
                                                 GSList         *file_list,
-                                                GRelation      *relation);
+                                                GHashTable     *relation);
        /**
         * Copy a message to a FolderItem
         *
        /**
         * Copy a message to a FolderItem
         *
@@ -505,7 +505,7 @@ struct _FolderClass
        gint            (*copy_msgs)            (Folder         *folder,
                                                 FolderItem     *dest,
                                                 MsgInfoList    *msglist,
        gint            (*copy_msgs)            (Folder         *folder,
                                                 FolderItem     *dest,
                                                 MsgInfoList    *msglist,
-                                                GRelation      *relation);
+                                                GHashTable     *relation);
        /**
         * Remove a message from a \c FolderItem.
         *
        /**
         * Remove a message from a \c FolderItem.
         *
@@ -520,7 +520,7 @@ struct _FolderClass
        gint            (*remove_msgs)          (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
        gint            (*remove_msgs)          (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
-                                                GRelation      *relation);
+                                                GHashTable     *relation);
        gint            (*expunge)              (Folder         *folder,
                                                 FolderItem     *item);
        /**
        gint            (*expunge)              (Folder         *folder,
                                                 FolderItem     *item);
        /**
@@ -578,7 +578,7 @@ struct _FolderClass
        gint            (*get_flags)            (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
        gint            (*get_flags)            (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
-                                                GRelation      *msgflags);
+                                                GHashTable     *msgflags);
        
        /* Sets batch mode for a FolderItem. It means that numerous flags updates
         * could follow, and the FolderClass implementation can cache them in order
        
        /* Sets batch mode for a FolderItem. It means that numerous flags updates
         * could follow, and the FolderClass implementation can cache them in order
index 9620ce8..5eaf148 100644 (file)
@@ -212,7 +212,7 @@ static gint         imap_add_msg            (Folder         *folder,
 static gint    imap_add_msgs           (Folder         *folder, 
                                         FolderItem     *dest,
                                         GSList         *file_list,
 static gint    imap_add_msgs           (Folder         *folder, 
                                         FolderItem     *dest,
                                         GSList         *file_list,
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 
 static gint    imap_copy_msg           (Folder         *folder,
                                         FolderItem     *dest, 
 
 static gint    imap_copy_msg           (Folder         *folder,
                                         FolderItem     *dest, 
@@ -220,7 +220,7 @@ static gint         imap_copy_msg           (Folder         *folder,
 static gint    imap_copy_msgs          (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
 static gint    imap_copy_msgs          (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 
 static gint    imap_remove_msg         (Folder         *folder, 
                                         FolderItem     *item, 
 
 static gint    imap_remove_msg         (Folder         *folder, 
                                         FolderItem     *item, 
@@ -228,7 +228,7 @@ static gint         imap_remove_msg         (Folder         *folder,
 static gint    imap_remove_msgs        (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
 static gint    imap_remove_msgs        (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 static gint    imap_expunge            (Folder         *folder, 
                                         FolderItem     *dest);
 static gint    imap_remove_all_msg     (Folder         *folder, 
 static gint    imap_expunge            (Folder         *folder, 
                                         FolderItem     *dest);
 static gint    imap_remove_all_msg     (Folder         *folder, 
@@ -278,7 +278,7 @@ static FolderItem *imap_create_special_folder
 static gint imap_do_copy_msgs          (Folder         *folder,
                                         FolderItem     *dest,
                                         MsgInfoList    *msglist,
 static gint imap_do_copy_msgs          (Folder         *folder,
                                         FolderItem     *dest,
                                         MsgInfoList    *msglist,
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 
 static void imap_delete_all_cached_messages    (FolderItem     *item);
 static void imap_set_batch             (Folder         *folder,
 
 static void imap_delete_all_cached_messages    (FolderItem     *item);
 static void imap_set_batch             (Folder         *folder,
@@ -409,7 +409,7 @@ static void imap_change_flags                       (Folder         *folder,
 static gint imap_get_flags                     (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
 static gint imap_get_flags                     (Folder         *folder,
                                                 FolderItem     *item,
                                                 MsgInfoList    *msglist,
-                                                GRelation      *msgflags);
+                                                GHashTable     *msgflags);
 static gchar *imap_folder_get_path             (Folder         *folder);
 static gchar *imap_item_get_path               (Folder         *folder,
                                                 FolderItem     *item);
 static gchar *imap_folder_get_path             (Folder         *folder);
 static gchar *imap_item_get_path               (Folder         *folder,
                                                 FolderItem     *item);
@@ -1577,7 +1577,7 @@ static gint imap_add_msg(Folder *folder, FolderItem *dest,
 }
 
 static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
 }
 
 static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
-                  GRelation *relation)
+                  GHashTable *relation)
 {
        gchar *destdir;
        IMAPSession *session;
 {
        gchar *destdir;
        IMAPSession *session;
@@ -1672,7 +1672,7 @@ static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
                }
 
                if (relation != NULL)
                }
 
                if (relation != NULL)
-                       g_relation_insert(relation, fileinfo->msginfo != NULL ? 
+                       g_hash_table_insert(relation, fileinfo->msginfo != NULL ? 
                                          (gpointer) fileinfo->msginfo : (gpointer) fileinfo,
                                          GINT_TO_POINTER(new_uid));
                if (last_uid < new_uid) {
                                          (gpointer) fileinfo->msginfo : (gpointer) fileinfo,
                                          GINT_TO_POINTER(new_uid));
                if (last_uid < new_uid) {
@@ -1732,7 +1732,7 @@ static GSList *flatten_mailimap_set(struct mailimap_set * set)
        return result;
 }
 static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest, 
        return result;
 }
 static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest, 
-                             MsgInfoList *msglist, GRelation *relation)
+                             MsgInfoList *msglist, GHashTable *relation)
 {
        FolderItem *src;
        gchar *destdir;
 {
        FolderItem *src;
        gchar *destdir;
@@ -1865,7 +1865,7 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
                
                if (hashval != NULL) {
                        gint num = GPOINTER_TO_INT(hashval);
                
                if (hashval != NULL) {
                        gint num = GPOINTER_TO_INT(hashval);
-                       g_relation_insert(relation, msginfo,
+                       g_hash_table_insert(relation, msginfo,
                                          GINT_TO_POINTER(num));
                        if (num > last_num)
                                last_num = num;
                                          GINT_TO_POINTER(num));
                        if (num > last_num)
                                last_num = num;
@@ -1894,7 +1894,7 @@ static gint imap_do_copy_msgs(Folder *folder, FolderItem *dest,
                                g_free(cache_path);
                        }
                } else
                                g_free(cache_path);
                        }
                } else
-                       g_relation_insert(relation, msginfo,
+                       g_hash_table_insert(relation, msginfo,
                                          GINT_TO_POINTER(0));
        }
        statusbar_pop_all();
                                          GINT_TO_POINTER(0));
        }
        statusbar_pop_all();
@@ -1929,7 +1929,7 @@ static gint imap_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
 }
 
 static gint imap_copy_msgs(Folder *folder, FolderItem *dest, 
 }
 
 static gint imap_copy_msgs(Folder *folder, FolderItem *dest, 
-                   MsgInfoList *msglist, GRelation *relation)
+                   MsgInfoList *msglist, GHashTable *relation)
 {
        MsgInfo *msginfo;
        gint ret;
 {
        MsgInfo *msginfo;
        gint ret;
@@ -1947,7 +1947,7 @@ static gint imap_copy_msgs(Folder *folder, FolderItem *dest,
 
 
 static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest, 
 
 
 static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest, 
-                               MsgInfoList *msglist, GRelation *relation)
+                               MsgInfoList *msglist, GHashTable *relation)
 {
        gchar *destdir, *dir;
        GSList *numlist = NULL, *cur;
 {
        gchar *destdir, *dir;
        GSList *numlist = NULL, *cur;
@@ -2027,7 +2027,7 @@ static gint imap_do_remove_msgs(Folder *folder, FolderItem *dest,
 }
 
 static gint imap_remove_msgs(Folder *folder, FolderItem *dest, 
 }
 
 static gint imap_remove_msgs(Folder *folder, FolderItem *dest, 
-                   MsgInfoList *msglist, GRelation *relation)
+                   MsgInfoList *msglist, GHashTable *relation)
 {
        MsgInfo *msginfo;
 
 {
        MsgInfo *msginfo;
 
@@ -4546,7 +4546,7 @@ typedef struct _get_flags_data {
        Folder *folder;
        FolderItem *item;
        MsgInfoList *msginfo_list;
        Folder *folder;
        FolderItem *item;
        MsgInfoList *msginfo_list;
-       GRelation *msgflags;
+       GHashTable *msgflags;
        gboolean full_search;
        gboolean done;
 } get_flags_data;
        gboolean full_search;
        gboolean done;
 } get_flags_data;
@@ -4557,7 +4557,7 @@ static /*gint*/ void *imap_get_flags_thread(void *data)
        Folder *folder = stuff->folder;
        FolderItem *fitem = (FolderItem *) stuff->item;
        MsgInfoList *msginfo_list = stuff->msginfo_list;
        Folder *folder = stuff->folder;
        FolderItem *fitem = (FolderItem *) stuff->item;
        MsgInfoList *msginfo_list = stuff->msginfo_list;
-       GRelation *msgflags = stuff->msgflags;
+       GHashTable *msgflags = stuff->msgflags;
        GSList *elem;
        carray * lep_uidtab;
        IMAPSession *session;
        GSList *elem;
        carray * lep_uidtab;
        IMAPSession *session;
@@ -4821,7 +4821,7 @@ bail:
                        }
                }
 
                        }
                }
 
-               g_relation_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
+               g_hash_table_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
        }
        
        if (got_alien_tags) {
        }
        
        if (got_alien_tags) {
@@ -4848,7 +4848,7 @@ bail:
 }
 
 static gint imap_get_flags(Folder *folder, FolderItem *item,
 }
 
 static gint imap_get_flags(Folder *folder, FolderItem *item,
-                           MsgInfoList *msginfo_list, GRelation *msgflags)
+                           MsgInfoList *msginfo_list, GHashTable *msgflags)
 {
        gint result;
        get_flags_data *data = g_new0(get_flags_data, 1);
 {
        gint result;
        get_flags_data *data = g_new0(get_flags_data, 1);
index 3cfa7a0..c0dfaf6 100644 (file)
--- a/src/mh.c
+++ b/src/mh.c
@@ -75,21 +75,21 @@ static gint     mh_add_msg          (Folder         *folder,
 static gint     mh_add_msgs            (Folder         *folder,
                                         FolderItem     *dest,
                                         GSList         *file_list,
 static gint     mh_add_msgs            (Folder         *folder,
                                         FolderItem     *dest,
                                         GSList         *file_list,
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 static gint     mh_copy_msg            (Folder         *folder,
                                         FolderItem     *dest,
                                         MsgInfo        *msginfo);
 static gint    mh_copy_msgs            (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
 static gint     mh_copy_msg            (Folder         *folder,
                                         FolderItem     *dest,
                                         MsgInfo        *msginfo);
 static gint    mh_copy_msgs            (Folder         *folder, 
                                         FolderItem     *dest, 
                                         MsgInfoList    *msglist, 
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 static gint     mh_remove_msg          (Folder         *folder,
                                         FolderItem     *item,
                                         gint            num);
 static gint    mh_remove_msgs          (Folder         *folder, 
                                         FolderItem     *item, 
                                         MsgInfoList    *msglist, 
 static gint     mh_remove_msg          (Folder         *folder,
                                         FolderItem     *item,
                                         gint            num);
 static gint    mh_remove_msgs          (Folder         *folder, 
                                         FolderItem     *item, 
                                         MsgInfoList    *msglist, 
-                                        GRelation      *relation);
+                                        GHashTable     *relation);
 static gint     mh_remove_all_msg      (Folder         *folder,
                                         FolderItem     *item);
 static gboolean mh_is_msg_changed      (Folder         *folder,
 static gint     mh_remove_all_msg      (Folder         *folder,
                                         FolderItem     *item);
 static gboolean mh_is_msg_changed      (Folder         *folder,
@@ -134,7 +134,7 @@ static int mh_item_close            (Folder         *folder,
                                         FolderItem     *item);
 #if 0
 static gint mh_get_flags               (Folder *folder, FolderItem *item,
                                         FolderItem     *item);
 #if 0
 static gint mh_get_flags               (Folder *folder, FolderItem *item,
-                                        MsgInfoList *msginfo_list, GRelation *msgflags);
+                                        MsgInfoList *msginfo_list, GHashTable *msgflags);
 #endif
 static void mh_write_sequences         (FolderItem     *item, gboolean remove_unseen);
 
 #endif
 static void mh_write_sequences         (FolderItem     *item, gboolean remove_unseen);
 
@@ -401,7 +401,7 @@ static gint mh_add_msg(Folder *folder, FolderItem *dest, const gchar *file, MsgF
 } 
  
 static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, 
 } 
  
 static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, 
-                 GRelation *relation)
+                 GHashTable *relation)
 { 
        gchar *destfile;
        GSList *cur;
 { 
        gchar *destfile;
        GSList *cur;
@@ -435,7 +435,7 @@ static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list,
 #endif
 
                if (relation != NULL)
 #endif
 
                if (relation != NULL)
-                       g_relation_insert(relation, fileinfo, GINT_TO_POINTER(dest->last_num + 1));
+                       g_hash_table_insert(relation, fileinfo, GINT_TO_POINTER(dest->last_num + 1));
                g_free(destfile);
                dest->last_num++;
        }
                g_free(destfile);
                dest->last_num++;
        }
@@ -456,7 +456,7 @@ static gint mh_copy_msg(Folder *folder, FolderItem *dest, MsgInfo *msginfo)
 }
 
 static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist, 
 }
 
 static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist, 
-                        GRelation *relation)
+                        GHashTable *relation)
 {
        gboolean dest_need_scan = FALSE;
        gboolean src_need_scan = FALSE;
 {
        gboolean dest_need_scan = FALSE;
        gboolean src_need_scan = FALSE;
@@ -578,8 +578,12 @@ static gint mh_copy_msgs(Folder *folder, FolderItem *dest, MsgInfoList *msglist,
                        if (filemode & S_IRGRP) filemode |= S_IWGRP;
                        if (filemode & S_IROTH) filemode |= S_IWOTH;
                }
                        if (filemode & S_IRGRP) filemode |= S_IWGRP;
                        if (filemode & S_IROTH) filemode |= S_IWOTH;
                }
-               if (relation)
-                       g_relation_insert(relation, msginfo, GINT_TO_POINTER(dest->last_num+1));
+               if (relation) {
+                       if (g_hash_table_lookup(relation, msginfo) != NULL)
+                               g_warning("already in : %p", msginfo);
+                       
+                       g_hash_table_insert(relation, msginfo, GINT_TO_POINTER(dest->last_num+1));
+               }
                g_free(srcfile);
                g_free(destfile);
                dest->last_num++;
                g_free(srcfile);
                g_free(destfile);
                dest->last_num++;
@@ -640,7 +644,7 @@ static gint mh_remove_msg(Folder *folder, FolderItem *item, gint num)
 }
 
 static gint mh_remove_msgs(Folder *folder, FolderItem *item, 
 }
 
 static gint mh_remove_msgs(Folder *folder, FolderItem *item, 
-                   MsgInfoList *msglist, GRelation *relation)
+                   MsgInfoList *msglist, GHashTable *relation)
 {
        gboolean need_scan = FALSE;
        gchar *path, *file;
 {
        gboolean need_scan = FALSE;
        gchar *path, *file;
@@ -1239,104 +1243,6 @@ static gchar *get_unseen_seq_name(void)
        return seq_name;        
 }
 
        return seq_name;        
 }
 
-#if 0
-static gint mh_get_flags(Folder *folder, FolderItem *item,
-                           MsgInfoList *msginfo_list, GRelation *msgflags)
-{
-       gchar *mh_sequences_filename;
-       FILE *mh_sequences_file;
-       gchar buf[BUFFSIZE];
-       gchar *unseen_list = NULL;
-       gchar *path;
-       MsgInfoList *mcur = NULL;
-/*
-       GTimer *timer = g_timer_new();
-       g_timer_start(timer);
-*/
-       if (!item)
-               return 0;
-
-       /* don't update from .mh_sequences if the item's opened: mails may have
-        * been marked read/unread and it's not yet written in the file. */     
-       if (item->opened)
-               return 0;
-
-       path = folder_item_get_path(item);
-
-       mh_sequences_filename = g_strconcat(path, G_DIR_SEPARATOR_S,
-                                           ".mh_sequences", NULL);
-       g_free(path);
-       if ((mh_sequences_file = g_fopen(mh_sequences_filename, "r+b")) != NULL) {
-               while (fgets(buf, sizeof(buf), mh_sequences_file) != NULL) {
-                       if (!strncmp(buf, get_unseen_seq_name(), strlen(get_unseen_seq_name()))) {
-                               unseen_list = g_strdup(buf+strlen(get_unseen_seq_name()));
-                               break;
-                       }
-               }
-               fclose(mh_sequences_file);
-       }
-       
-       g_free(mh_sequences_filename);
-       
-       if (unseen_list) {
-               gchar *cur = NULL;
-               gchar *token = NULL, *next = NULL, *boundary = NULL;
-               gint num = 0;
-               GHashTable *unseen_table = g_hash_table_new(g_direct_hash, g_direct_equal);
-
-               cur = unseen_list = strretchomp(unseen_list);
-               debug_print("found unseen list in .mh_sequences: %s\n", unseen_list);
-next_token:
-               while (*cur && *cur == ' ')
-                       cur++;
-               
-               if ((next = strchr(cur, ' ')) != NULL) {
-                       token = cur;
-                       cur = next+1;
-                       *next = '\0';
-               } else {
-                       token = cur;
-                       cur = NULL;
-               }
-               
-               if ((boundary = strchr(token, '-')) != NULL) {
-                       gchar *start, *end;
-                       int i;
-                       start = token;
-                       end = boundary+1;
-                       *boundary='\0';
-                       for (i = atoi(start); i <= atoi(end); i++) {
-                               g_hash_table_insert(unseen_table, GINT_TO_POINTER(i), GINT_TO_POINTER(1));
-                       }
-               } else if ((num = atoi(token)) > 0) {
-                       g_hash_table_insert(unseen_table, GINT_TO_POINTER(num), GINT_TO_POINTER(1));
-               }
-               
-               if (cur)
-                       goto next_token;
-               for (mcur = msginfo_list; mcur; mcur = mcur->next) {
-                       MsgInfo *msginfo = (MsgInfo *)mcur->data;
-                       MsgPermFlags flags = msginfo->flags.perm_flags;
-                       if (g_hash_table_lookup(unseen_table, GINT_TO_POINTER(msginfo->msgnum))) {
-                               flags |= MSG_UNREAD;
-                       } else if (!(flags & MSG_NEW)) { /* don't mark new msgs as read */
-                               flags &= ~(MSG_UNREAD);
-                       }
-                       if (flags != msginfo->flags.perm_flags)
-                               g_relation_insert(msgflags, msginfo, GINT_TO_POINTER(flags));
-               }
-               g_hash_table_destroy(unseen_table);
-               g_free(unseen_list);
-       }
-/*
-       g_timer_stop(timer);
-       g_print("mh_get_flags: %f secs\n", g_timer_elapsed(timer, NULL));
-       g_timer_destroy(timer);
-*/
-       return 0;
-}
-#endif
-
 static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
 {
        gchar *mh_sequences_old, *mh_sequences_new;
 static void mh_write_sequences(FolderItem *item, gboolean remove_unseen)
 {
        gchar *mh_sequences_old, *mh_sequences_new;
index 1daa89a..4577c14 100644 (file)
@@ -98,21 +98,22 @@ struct MarkSum {
 /* CLAWS subject threading:
   
   in the first round it inserts subject lines in a 
 /* CLAWS subject threading:
   
   in the first round it inserts subject lines in a 
-  relation (subject <-> node)
+  hashtable (subject <-> node)
 
   the second round finishes the threads by attaching
   matching subject lines to the one found in the
 
   the second round finishes the threads by attaching
   matching subject lines to the one found in the
-  relation. will use the oldest node with the same
+  hashtable. will use the oldest node with the same
   subject that is not more then thread_by_subject_max_age
   subject that is not more then thread_by_subject_max_age
-  days old (see subject_relation_lookup)
+  days old (see subject_hashtable_lookup)
 */  
 
 */  
 
-static void subject_relation_insert(GRelation *relation, GNode *node)
+static void subject_hashtable_insert(GHashTable *hashtable, GNode *node)
 {
        gchar *subject;
        MsgInfo *msginfo;
 {
        gchar *subject;
        MsgInfo *msginfo;
+       GSList *list = NULL;
 
 
-       cm_return_if_fail(relation != NULL);
+       cm_return_if_fail(hashtable != NULL);
        cm_return_if_fail(node != NULL);
        msginfo = (MsgInfo *) node->data;
        cm_return_if_fail(msginfo != NULL);
        cm_return_if_fail(node != NULL);
        msginfo = (MsgInfo *) node->data;
        cm_return_if_fail(msginfo != NULL);
@@ -120,19 +121,24 @@ static void subject_relation_insert(GRelation *relation, GNode *node)
        subject = msginfo->subject;
        if (subject == NULL)
                return;
        subject = msginfo->subject;
        if (subject == NULL)
                return;
+
        subject += subject_get_prefix_length(subject);
 
        subject += subject_get_prefix_length(subject);
 
-       g_relation_insert(relation, subject, node);
+       list = g_hash_table_lookup(hashtable, subject);
+       list = g_slist_prepend(list, node);
+       g_hash_table_insert(hashtable, subject, list);
 }
 
 }
 
-static GNode *subject_relation_lookup(GRelation *relation, MsgInfo *msginfo)
+static GNode *subject_hashtable_lookup(GHashTable *hashtable, MsgInfo *msginfo)
 {
        gchar *subject;
 {
        gchar *subject;
-       GTuples *tuples;
-       GNode *node = NULL;
+       GSList *list, *cur;
+       GNode *node = NULL, *hashtable_node = NULL;
        gint prefix_length;
        gint prefix_length;
+       MsgInfo *hashtable_msginfo = NULL, *best_msginfo = NULL;
+       gboolean match;
     
     
-       cm_return_val_if_fail(relation != NULL, NULL);
+       cm_return_val_if_fail(hashtable != NULL, NULL);
 
        subject = msginfo->subject;
        if (subject == NULL)
 
        subject = msginfo->subject;
        if (subject == NULL)
@@ -142,55 +148,52 @@ static GNode *subject_relation_lookup(GRelation *relation, MsgInfo *msginfo)
                return NULL;
        subject += prefix_length;
        
                return NULL;
        subject += prefix_length;
        
-       tuples = g_relation_select(relation, subject, 0);
-       if (tuples == NULL)
+       list = g_hash_table_lookup(hashtable, subject);
+       if (list == NULL)
                return NULL;
 
                return NULL;
 
-       if (tuples->len > 0) {
-               int i;
-               GNode *relation_node;
-               MsgInfo *relation_msginfo = NULL, *best_msginfo = NULL;
-               gboolean match;
-
-               /* check all nodes with the same subject to find the best parent */
-               for (i = 0; i < tuples->len; i++) {
-                       relation_node = (GNode *) g_tuples_index(tuples, i, 1);
-                       relation_msginfo = (MsgInfo *) relation_node->data;
+       /* check all nodes with the same subject to find the best parent */
+       for (cur = list; cur; cur = cur->next) {
+               hashtable_node = (GNode *)cur->data;
+               hashtable_msginfo = (MsgInfo *) hashtable_node->data;
+               match = FALSE;
+
+               /* best node should be the oldest in the found nodes */
+               /* parent node must not be older then msginfo */
+               if ((hashtable_msginfo->date_t < msginfo->date_t) &&
+                   ((best_msginfo == NULL) ||
+                    (best_msginfo->date_t > hashtable_msginfo->date_t)))
+                       match = TRUE;
+
+               /* parent node must not be more then thread_by_subject_max_age
+                  days older then msginfo */
+               if (abs(difftime(msginfo->date_t, hashtable_msginfo->date_t)) >
+                    prefs_common.thread_by_subject_max_age * 3600 * 24)
                        match = FALSE;
 
                        match = FALSE;
 
-                       /* best node should be the oldest in the found nodes */
-                       /* parent node must not be older then msginfo */
-                       if ((relation_msginfo->date_t < msginfo->date_t) &&
-                           ((best_msginfo == NULL) ||
-                            (best_msginfo->date_t > relation_msginfo->date_t)))
-                               match = TRUE;
-
-                       /* parent node must not be more then thread_by_subject_max_age
-                          days older then msginfo */
-                       if (abs(difftime(msginfo->date_t, relation_msginfo->date_t)) >
-                            prefs_common.thread_by_subject_max_age * 3600 * 24)
-                               match = FALSE;
-
-                       /* can add new tests for all matching
-                          nodes found by subject */
-
-                       if (match) {
-                               node = relation_node;
-                               best_msginfo = relation_msginfo;
-                       }
-               }           
+               /* can add new tests for all matching
+                  nodes found by subject */
+
+               if (match) {
+                       node = hashtable_node;
+                       best_msginfo = hashtable_msginfo;
+               }
        }
 
        }
 
-       g_tuples_destroy(tuples);
        return node;
 }
 
        return node;
 }
 
+static void subject_hashtable_free(gpointer key, gpointer value, gpointer data)
+{
+       g_slist_free(value);
+}
+
 /* return the reversed thread tree */
 GNode *procmsg_get_thread_tree(GSList *mlist)
 {
        GNode *root, *parent, *node, *next;
        GHashTable *msgid_table;
 /* return the reversed thread tree */
 GNode *procmsg_get_thread_tree(GSList *mlist)
 {
        GNode *root, *parent, *node, *next;
        GHashTable *msgid_table;
-       GRelation *subject_relation = NULL;
+       GHashTable *subject_hashtable = NULL;
        MsgInfo *msginfo;
        const gchar *msgid;
         GSList *reflist;
        MsgInfo *msginfo;
        const gchar *msgid;
         GSList *reflist;
@@ -199,8 +202,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
        msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
        
        if (prefs_common.thread_by_subject) {
        msgid_table = g_hash_table_new(g_str_hash, g_str_equal);
        
        if (prefs_common.thread_by_subject) {
-               subject_relation = g_relation_new(2);
-               g_relation_index(subject_relation, 0, g_str_hash, g_str_equal);
+               subject_hashtable = g_hash_table_new(g_str_hash, g_str_equal);
        }
 
        for (; mlist != NULL; mlist = mlist->next) {
        }
 
        for (; mlist != NULL; mlist = mlist->next) {
@@ -219,9 +221,9 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL)
                        g_hash_table_insert(msgid_table, (gchar *)msgid, node);
 
                if ((msgid = msginfo->msgid) && g_hash_table_lookup(msgid_table, msgid) == NULL)
                        g_hash_table_insert(msgid_table, (gchar *)msgid, node);
 
-               /* CLAWS: add subject to relation (without prefix) */
+               /* CLAWS: add subject to hashtable (without prefix) */
                if (prefs_common.thread_by_subject) {
                if (prefs_common.thread_by_subject) {
-                       subject_relation_insert(subject_relation, node);
+                       subject_hashtable_insert(subject_hashtable, node);
                }
        }
 
                }
        }
 
@@ -261,7 +263,7 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
                        next = node->next;
                        msginfo = (MsgInfo *) node->data;
                        
                        next = node->next;
                        msginfo = (MsgInfo *) node->data;
                        
-                       parent = subject_relation_lookup(subject_relation, msginfo);
+                       parent = subject_hashtable_lookup(subject_hashtable, msginfo);
                        
                        /* the node may already be threaded by IN-REPLY-TO, so go up 
                         * in the tree to 
                        
                        /* the node may already be threaded by IN-REPLY-TO, so go up 
                         * in the tree to 
@@ -284,7 +286,10 @@ GNode *procmsg_get_thread_tree(GSList *mlist)
        }
        
        if (prefs_common.thread_by_subject)
        }
        
        if (prefs_common.thread_by_subject)
-               g_relation_destroy(subject_relation);
+       {
+               g_hash_table_foreach(subject_hashtable, subject_hashtable_free, NULL);
+               g_hash_table_destroy(subject_hashtable);
+       }
 
        g_hash_table_destroy(msgid_table);
        END_TIMING();
 
        g_hash_table_destroy(msgid_table);
        END_TIMING();
@@ -1131,7 +1136,8 @@ void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline)
 
        g_strchomp(buf);
        if (buf[strlen(buf) - 1] != '&') strcat(buf, "&");
 
        g_strchomp(buf);
        if (buf[strlen(buf) - 1] != '&') strcat(buf, "&");
-       system(buf);
+       if (system(buf) == -1)
+               g_warning("system(%s) failed.", buf);
 }
 
 MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo)
 }
 
 MsgInfo *procmsg_msginfo_new_ref(MsgInfo *msginfo)