talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 4afd2bc3aeabe868a03d771fa507abbc0b5183e9
parent 04b3b1ebc6df15a5b8ff8fea47e50ebe071e7991
Author: Colin Leroy <colin@colino.net>
Date:   Sun,  3 Oct 2010 11:46:24 +0000

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'

Diffstat:
MChangeLog | 11+++++++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Msrc/folder.c | 120+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/folder.h | 8++++----
Msrc/imap.c | 34+++++++++++++++++-----------------
Msrc/mh.c | 122+++++++++----------------------------------------------------------------------
Msrc/procmsg.c | 110++++++++++++++++++++++++++++++++++++++++++-------------------------------------
8 files changed, 168 insertions(+), 240 deletions(-)

diff --git 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 diff --git a/PATCHSETS b/PATCHSETS @@ -4048,3 +4048,4 @@ ( 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 diff --git a/configure.ac b/configure.ac @@ -12,7 +12,7 @@ MINOR_VERSION=7 MICRO_VERSION=6 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=52 +EXTRA_VERSION=53 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/folder.c b/src/folder.c @@ -1883,7 +1883,7 @@ static gint folder_sort_folder_list(gconstpointer a, gconstpointer b) static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist) { - GRelation *relation; + GHashTable *relation; gint ret = 0; GSList *cur; @@ -1894,38 +1894,32 @@ static gint syncronize_flags(FolderItem *item, MsgInfoList *msglist) 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) { - GTuples *tuples; + gpointer data, old_key; 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; - 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(); } - g_relation_destroy(relation); + g_hash_table_destroy(relation); 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; - GRelation *relation; + GHashTable *relation; MsgFileInfo *fileinfo = NULL; gboolean folderscan = FALSE; @@ -3135,13 +3129,12 @@ gint folder_item_add_msgs(FolderItem *dest, GSList *file_list, 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) { - g_relation_destroy(relation); + g_hash_table_destroy(relation); 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) { - g_relation_destroy(relation); + g_hash_table_destroy(relation); 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)) { - GTuples *tuples; + gpointer data, old_key; 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; @@ -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; } @@ -3351,6 +3345,27 @@ gint folder_item_move_to(FolderItem *src, FolderItem *dest, FolderItem **new_ite 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 @@ -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; - GRelation *relation; + GHashTable *relation; 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; } - 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; @@ -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) { - g_relation_destroy(relation); + g_hash_table_destroy(relation); 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) { - g_relation_destroy(relation); + g_hash_table_destroy(relation); 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) - 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); } @@ -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)) { - GTuples *tuples; + gpointer old_key, data; 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; - } 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 */ - 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; } @@ -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; - GTuples *tuples; + gpointer data, old_key; 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(); @@ -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(); - g_relation_destroy(relation); + g_hash_table_destroy(relation); if (not_moved != NULL) { g_slist_free(not_moved); return -1; diff --git a/src/folder.h b/src/folder.h @@ -474,7 +474,7 @@ struct _FolderClass gint (*add_msgs) (Folder *folder, FolderItem *dest, GSList *file_list, - GRelation *relation); + GHashTable *relation); /** * Copy a message to a FolderItem * @@ -505,7 +505,7 @@ struct _FolderClass gint (*copy_msgs) (Folder *folder, FolderItem *dest, MsgInfoList *msglist, - GRelation *relation); + GHashTable *relation); /** * Remove a message from a \c FolderItem. * @@ -520,7 +520,7 @@ struct _FolderClass gint (*remove_msgs) (Folder *folder, FolderItem *item, MsgInfoList *msglist, - GRelation *relation); + GHashTable *relation); gint (*expunge) (Folder *folder, FolderItem *item); /** @@ -578,7 +578,7 @@ struct _FolderClass 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 diff --git a/src/imap.c b/src/imap.c @@ -212,7 +212,7 @@ static gint imap_add_msg (Folder *folder, 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, @@ -220,7 +220,7 @@ static gint imap_copy_msg (Folder *folder, static gint imap_copy_msgs (Folder *folder, FolderItem *dest, MsgInfoList *msglist, - GRelation *relation); + GHashTable *relation); 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, - GRelation *relation); + GHashTable *relation); 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, - GRelation *relation); + GHashTable *relation); 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, - GRelation *msgflags); + GHashTable *msgflags); 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, - GRelation *relation) + GHashTable *relation) { gchar *destdir; IMAPSession *session; @@ -1672,7 +1672,7 @@ static gint imap_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, } 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) { @@ -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, - MsgInfoList *msglist, GRelation *relation) + MsgInfoList *msglist, GHashTable *relation) { 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); - g_relation_insert(relation, msginfo, + g_hash_table_insert(relation, msginfo, 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_relation_insert(relation, msginfo, + g_hash_table_insert(relation, msginfo, 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, - MsgInfoList *msglist, GRelation *relation) + MsgInfoList *msglist, GHashTable *relation) { 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, - MsgInfoList *msglist, GRelation *relation) + MsgInfoList *msglist, GHashTable *relation) { 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, - MsgInfoList *msglist, GRelation *relation) + MsgInfoList *msglist, GHashTable *relation) { MsgInfo *msginfo; @@ -4546,7 +4546,7 @@ typedef struct _get_flags_data { Folder *folder; FolderItem *item; MsgInfoList *msginfo_list; - GRelation *msgflags; + GHashTable *msgflags; 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; - GRelation *msgflags = stuff->msgflags; + GHashTable *msgflags = stuff->msgflags; 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) { @@ -4848,7 +4848,7 @@ bail: } 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); diff --git 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, - 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, - 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, - GRelation *relation); + GHashTable *relation); 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, - MsgInfoList *msginfo_list, GRelation *msgflags); + MsgInfoList *msginfo_list, GHashTable *msgflags); #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, - GRelation *relation) + GHashTable *relation) { gchar *destfile; GSList *cur; @@ -435,7 +435,7 @@ static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, #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++; } @@ -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, - GRelation *relation) + GHashTable *relation) { 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 (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++; @@ -640,7 +644,7 @@ static gint mh_remove_msg(Folder *folder, FolderItem *item, gint num) } static gint mh_remove_msgs(Folder *folder, FolderItem *item, - MsgInfoList *msglist, GRelation *relation) + MsgInfoList *msglist, GHashTable *relation) { gboolean need_scan = FALSE; gchar *path, *file; @@ -1239,104 +1243,6 @@ static gchar *get_unseen_seq_name(void) 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; diff --git a/src/procmsg.c b/src/procmsg.c @@ -98,21 +98,22 @@ struct MarkSum { /* 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 - 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 - 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; + 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); @@ -120,19 +121,24 @@ static void subject_relation_insert(GRelation *relation, GNode *node) subject = msginfo->subject; if (subject == NULL) return; + 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; - GTuples *tuples; - GNode *node = NULL; + GSList *list, *cur; + GNode *node = NULL, *hashtable_node = NULL; 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) @@ -142,55 +148,52 @@ static GNode *subject_relation_lookup(GRelation *relation, MsgInfo *msginfo) 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; - 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; - /* 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; } +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; - GRelation *subject_relation = NULL; + GHashTable *subject_hashtable = NULL; 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) { - 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) { @@ -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); - /* CLAWS: add subject to relation (without prefix) */ + /* CLAWS: add subject to hashtable (without prefix) */ 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; - 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 @@ -284,7 +286,10 @@ GNode *procmsg_get_thread_tree(GSList *mlist) } 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(); @@ -1131,7 +1136,8 @@ void procmsg_print_message(MsgInfo *msginfo, const gchar *cmdline) 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)