+2001-05-12 [hoa]
+
+ * src/defs.h
+ prepared some things for new filtering
+ * src/matcher.[ch]
+ added some matching properties
+ inreplyto need to be enhanced
+ prepared some things for new filtering
+ * src/messageview.c
+ added Return-Receipt-To handling
+ * src/prefs_folder_item.c
+ changed default value to TRUE
+ * src/prefs_matcher.c
+ added some matching properties
+ * src/prefs_scoring.[ch]
+ the scoring dialog is finished
+ * src/procheader.c
+ added Return-Receipt-To handling
+ Reference need to be added
+ * src/procmsg.[ch]
+ added Return-Receipt-To handling
+ added threadscore to get a better score sorting when
+ threads are enabled
+ * src/summaryview.c
+ suppressed a bug when we sort the list
+ when no folder is opened.
+ better score sorting when threads are enabled
+
2001-05-12 [alfons]
* reverted previous patch because of potential errors
#define DISPLAY_HEADER_RC "dispheaderrc"
#define FOLDERITEM_RC "folderitemrc"
#define SCORING_RC "scoringrc"
+#define FILTERING_RC "filteringrc"
#define MENU_RC "menurc"
#define ADDRESS_BOOK "addressbook.xml"
#define MANUAL_HTML_INDEX "sylpheed.html"
{MATCHING_AGE_LOWER, "age_lower"},
{MATCHING_NEWSGROUPS, "newsgroups"},
{MATCHING_NOT_NEWSGROUPS, "~newsgroups"},
+ {MATCHING_INREPLYTO, "inreplyto"},
+ {MATCHING_NOT_INREPLYTO, "~inreplyto"},
/* content have to be read */
{MATCHING_HEADER, "header"},
/* actions */
{MATCHING_SCORE, "score"},
+
+ /* actions */
+ {MATCHING_ACTION_MOVE, "move"},
+ {MATCHING_ACTION_COPY, "copy"},
+ {MATCHING_ACTION_DELETE, "delete"},
+ {MATCHING_ACTION_MARK, "mark"},
+ {MATCHING_ACTION_MARK_AS_READ, "mark_as_read"},
+ {MATCHING_ACTION_FORWARD, "forward"},
+ {MATCHING_ACTION_FORWARD_AS_ATTACHEMENT, "forward_as_attachement"}
};
/*
case MATCHING_NOT_TO_AND_NOT_CC:
case MATCHING_NEWSGROUPS:
case MATCHING_NOT_NEWSGROUPS:
+ case MATCHING_INREPLYTO:
+ case MATCHING_NOT_INREPLYTO:
case MATCHING_MESSAGE:
case MATCHING_NOT_MESSAGE:
case MATCHING_HEADERS_PART:
return FALSE;
switch(prop->matchtype) {
- case MATCHING_REGEXP:
case MATCHING_REGEXPCASE:
+ case MATCHING_REGEXP:
if (!prop->preg && (prop->error == 0)) {
prop->preg = g_new0(regex_t, 1);
if (regcomp(prop->preg, prop->expr,
return matcherprop_string_match(prop, info->newsgroups);
case MATCHING_NOT_NEWSGROUPS:
return !matcherprop_string_match(prop, info->newsgroups);
+ case MATCHING_INREPLYTO:
+ return matcherprop_string_match(prop, info->inreplyto);
+ case MATCHING_NOT_INREPLYTO:
+ return !matcherprop_string_match(prop, info->inreplyto);
case MATCHING_HEADER:
default:
return 0;
MATCHING_AGE_LOWER,
MATCHING_NEWSGROUPS,
MATCHING_NOT_NEWSGROUPS,
+ MATCHING_INREPLYTO,
+ MATCHING_NOT_INREPLYTO,
/* file content */
MATCHING_HEADER,
MATCHING_BODY_PART,
MATCHING_NOT_BODY_PART,
+ /* scoring */
MATCHING_SCORE,
+ /* filtering */
+ MATCHING_ACTION_MOVE,
+ MATCHING_ACTION_COPY,
+ MATCHING_ACTION_DELETE,
+ MATCHING_ACTION_MARK,
+ MATCHING_ACTION_MARK_AS_READ,
+ MATCHING_ACTION_FORWARD,
+ MATCHING_ACTION_FORWARD_AS_ATTACHEMENT,
+
MATCHING_MATCH,
MATCHING_REGEXP,
MATCHING_MATCHCASE,
GSList * to_list;
gint ok;
+ if ((!msginfo->returnreceiptto) &&
+ (!msginfo->dispositionnotificationto))
+ return -1;
+
/* write to temporary file */
g_snprintf(tmp, sizeof(tmp), "%s%ctmpmsg%d",
get_rc_dir(), G_DIR_SEPARATOR, (gint)msginfo);
fprintf(fp, "From: %s\n", cur_account->address);
/* To */
- fprintf(fp, "To: %s\n", msginfo->dispositionnotificationto);
+ if (msginfo->dispositionnotificationto)
+ fprintf(fp, "To: %s\n", msginfo->dispositionnotificationto);
+ else
+ fprintf(fp, "To: %s\n", msginfo->returnreceiptto);
/* Subject */
notification_convert_header(buf, sizeof(buf), msginfo->subject,
tmpmsginfo = procheader_parse(file, msginfo->flags, TRUE);
if (prefs_common.return_receipt
- && tmpmsginfo->dispositionnotificationto
+ && (tmpmsginfo->dispositionnotificationto
+ || tmpmsginfo->returnreceiptto)
&& (MSG_IS_UNREAD(msginfo->flags))) {
gint ok;
NULL, NULL, NULL},
{"sort_descending", "FALSE", &tmp_prefs.sort_descending, P_BOOL,
NULL, NULL, NULL},
- {"enable_thread", "FALSE", &tmp_prefs.enable_thread, P_BOOL,
+ {"enable_thread", "TRUE", &tmp_prefs.enable_thread, P_BOOL,
NULL, NULL, NULL},
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
};
CRITERIA_CC = 4,
CRITERIA_TO_OR_CC = 5,
CRITERIA_NEWSGROUPS = 6,
- CRITERIA_AGE_GREATER = 7,
- CRITERIA_AGE_LOWER = 8,
- CRITERIA_HEADER = 9,
- CRITERIA_HEADERS_PART = 10,
- CRITERIA_BODY_PART = 11,
- CRITERIA_MESSAGE = 12,
-
- CRITERIA_UNREAD = 13,
- CRITERIA_NEW = 14,
- CRITERIA_MARKED = 15,
- CRITERIA_DELETED = 16,
- CRITERIA_REPLIED = 17,
- CRITERIA_FORWARDED = 18
+ CRITERIA_INREPLYTO = 7,
+ CRITERIA_AGE_GREATER = 8,
+ CRITERIA_AGE_LOWER = 9,
+ CRITERIA_HEADER = 10,
+ CRITERIA_HEADERS_PART = 11,
+ CRITERIA_BODY_PART = 12,
+ CRITERIA_MESSAGE = 13,
+
+ CRITERIA_UNREAD = 14,
+ CRITERIA_NEW = 15,
+ CRITERIA_MARKED = 16,
+ CRITERIA_DELETED = 17,
+ CRITERIA_REPLIED = 18,
+ CRITERIA_FORWARDED = 19
};
enum {
gchar * criteria_text [] = {
"All messages", "Subject",
"From", "To", "Cc", "To or Cc",
- "Newsgroups",
+ "Newsgroups", "In reply to"
"Age greater than", "Age lower than",
"Header", "Headers part",
"Body part", "Whole message",
return MATCHING_TO_OR_CC;
case CRITERIA_NEWSGROUPS:
return MATCHING_NEWSGROUPS;
+ case CRITERIA_INREPLYTO:
+ return MATCHING_INREPLYTO;
case CRITERIA_AGE_GREATER:
return MATCHING_AGE_GREATER;
case CRITERIA_AGE_LOWER:
return MATCHING_NOT_TO_AND_NOT_CC;
case MATCHING_NEWSGROUPS:
return MATCHING_NOT_NEWSGROUPS;
+ case MATCHING_INREPLYTO:
+ return MATCHING_NOT_INREPLYTO;
case MATCHING_HEADER:
return MATCHING_NOT_HEADER;
case MATCHING_HEADERS_PART:
case CRITERIA_CC:
case CRITERIA_TO_OR_CC:
case CRITERIA_NEWSGROUPS:
+ case CRITERIA_INREPLYTO:
case CRITERIA_HEADERS_PART:
case CRITERIA_BODY_PART:
case CRITERIA_MESSAGE:
case CRITERIA_CC:
case CRITERIA_TO_OR_CC:
case CRITERIA_NEWSGROUPS:
+ case CRITERIA_INREPLYTO:
case CRITERIA_HEADERS_PART:
case CRITERIA_BODY_PART:
case CRITERIA_MESSAGE:
CRITERIA_NEWSGROUPS);
break;
+ case MATCHING_NOT_INREPLYTO:
+ negative_cond = TRUE;
+ case MATCHING_INREPLYTO:
+ gtk_list_select_item(GTK_LIST(matcher.criteria_list),
+ CRITERIA_INREPLYTO);
+ break;
+
case MATCHING_NOT_TO_AND_NOT_CC:
negative_cond = TRUE;
case MATCHING_TO_OR_CC:
case MATCHING_NOT_CC:
case MATCHING_NOT_TO_AND_NOT_CC:
case MATCHING_NOT_NEWSGROUPS:
+ case MATCHING_NOT_INREPLYTO:
case MATCHING_NOT_HEADERS_PART:
case MATCHING_NOT_BODY_PART:
case MATCHING_NOT_MESSAGE:
case MATCHING_CC:
case MATCHING_TO_OR_CC:
case MATCHING_NEWSGROUPS:
+ case MATCHING_INREPLYTO:
case MATCHING_HEADERS_PART:
case MATCHING_BODY_PART:
case MATCHING_MESSAGE:
case CRITERIA_CC:
case CRITERIA_TO_OR_CC:
case CRITERIA_NEWSGROUPS:
+ case CRITERIA_INREPLYTO:
case CRITERIA_HEADERS_PART:
case CRITERIA_BODY_PART:
case CRITERIA_MESSAGE:
/* widget creating functions */
static void prefs_scoring_create (void);
-static void prefs_scoring_set_dialog (void);
+static void prefs_scoring_set_dialog (ScoringProp * prop);
static void prefs_scoring_set_list (void);
/* callback functions */
static void prefs_scoring_condition_define (void);
static gint prefs_scoring_clist_set_row(gint row, ScoringProp * prop);
+static void prefs_scoring_select_set_dialog(ScoringProp * prop);
+static void prefs_scoring_reset_dialog(void);
void prefs_scoring_open(void)
{
manage_window_set_transient(GTK_WINDOW(scoring.window));
gtk_widget_grab_focus(scoring.ok_btn);
- prefs_scoring_set_dialog();
+ prefs_scoring_set_dialog(NULL);
+
+ gtk_widget_show(scoring.window);
+}
+
+void prefs_scoring_open_with_scoring(ScoringProp * prop)
+{
+ inc_autocheck_timer_remove();
+
+ if (!scoring.window) {
+ prefs_scoring_create();
+ }
+
+ manage_window_set_transient(GTK_WINDOW(scoring.window));
+ gtk_widget_grab_focus(scoring.ok_btn);
+
+ prefs_scoring_set_dialog(prop);
gtk_widget_show(scoring.window);
}
scoring.cond_clist = cond_clist;
}
-static void prefs_scoring_set_dialog(void)
+static void prefs_scoring_set_dialog(ScoringProp * cond)
{
GtkCList *clist = GTK_CLIST(scoring.cond_clist);
GSList *cur;
+ if (cond == NULL)
+ prefs_scoring_reset_dialog();
+ else
+ prefs_scoring_select_set_dialog(cond);
+
gtk_clist_freeze(clist);
gtk_clist_clear(clist);
gtk_clist_thaw(clist);
}
+static void prefs_scoring_reset_dialog(void)
+{
+ gtk_entry_set_text(GTK_ENTRY(scoring.cond_entry), "");
+ gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), "");
+}
+
static void prefs_scoring_set_list(void)
{
gint row = 1;
}
}
-static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
- GdkEvent *event)
+static void prefs_scoring_select_set_dialog(ScoringProp * prop)
{
- ScoringProp * prop;
- gchar * tmp;
-
gchar * matcher_str;
- gchar * scoring_str;
gchar * score_str;
- if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
- row, 0, &scoring_str))
- return;
-
- tmp = scoring_str;
- prop = scoringprop_parse(&tmp);
- if (tmp == NULL)
+ if (prop == NULL)
return;
matcher_str = matcherlist_to_string(prop->matchers);
gtk_entry_set_text(GTK_ENTRY(scoring.score_entry), score_str);
g_free(matcher_str);
+}
+
+static void prefs_scoring_select(GtkCList *clist, gint row, gint column,
+ GdkEvent *event)
+{
+ ScoringProp * prop;
+ gchar * tmp;
+
+ gchar * scoring_str;
+
+ if (!gtk_clist_get_text(GTK_CLIST(scoring.cond_clist),
+ row, 0, &scoring_str))
+ return;
+
+ tmp = scoring_str;
+ prop = scoringprop_parse(&tmp);
+ if (tmp == NULL)
+ return;
+
+ prefs_scoring_select_set_dialog(prop);
+
scoringprop_free(prop);
}
#ifndef __PREFS_SCORING_H__
#define __PREFS_SCORING_H__
+#include "scoring.h"
+
/*
void prefs_scoring_read_config (void);
void prefs_scoring_write_config (void);
*/
void prefs_scoring_open (void);
+void prefs_scoring_open_with_scoring(ScoringProp * prop);
#endif /* __PREFS_SCORING_H__ */
H_CONTENT_TYPE = 9,
H_SEEN = 10,
H_X_FACE = 11,
- H_DISPOSITION_NOTIFICATION_TO = 12
+ H_DISPOSITION_NOTIFICATION_TO = 12,
+ H_RETURN_RECEIPT_TO = 13
};
MsgInfo *procheader_parse(const gchar *file, MsgFlags flags, gboolean full)
{"Content-Type:", NULL, FALSE},
{"Seen:", NULL, FALSE},
{"X-Face:", NULL, FALSE},
- {"Disposition-Notification-To:",NULL, FALSE},
+ {"Disposition-Notification-To:", NULL, FALSE},
+ {"Return-Receipt-To:", NULL, FALSE},
{NULL, NULL, FALSE}};
static HeaderEntry hentry_short[] = {{"Date:", NULL, FALSE},
if (msginfo->dispositionnotificationto) break;
msginfo->dispositionnotificationto = g_strdup(hp);
break;
+ case H_RETURN_RECEIPT_TO:
+ if (msginfo->returnreceiptto) break;
+ msginfo->returnreceiptto = g_strdup(hp);
+ break;
default:
}
}
MEMBDUP(xface);
MEMBDUP(dispositionnotificationto);
+ MEMBDUP(returnreceiptto);
MEMBCOPY(score);
+ MEMBCOPY(threadscore);
return newmsginfo;
}
{
if (msginfo == NULL) return;
+ g_free(msginfo->returnreceiptto);
g_free(msginfo->dispositionnotificationto);
g_free(msginfo->xface);
gchar *xface;
gchar *dispositionnotificationto;
+ gchar *returnreceiptto;
- int score;
+ gint score;
+ gint threadscore;
/* used only for encrypted messages */
gchar *plaintext_file;
GtkCList *clist = GTK_CLIST(summaryview->ctree);
GtkCListCompareFunc cmp_func;
+ if (!summaryview->folder_item)
+ return;
+
switch (type) {
case SORT_BY_NUMBER:
cmp_func = (GtkCListCompareFunc)summary_cmp_by_num;
{
GtkCTree *ctree = GTK_CTREE(summaryview->ctree);
MsgInfo *msginfo;
+ MsgInfo *parentinfo;
+ MsgInfo *cur_msginfo;
GtkCTreeNode *node, *parent;
gchar *text[N_SUMMARY_COLS];
GHashTable *msgid_table;
+ GSList * cur;
+ GtkCTreeNode *cur_parent;
if (!mlist) return;
main_window_set_thread_option(summaryview->mainwin);
+ for (cur = mlist ; cur != NULL; cur = cur->next) {
+ msginfo = (MsgInfo *)cur->data;
+ msginfo->threadscore = msginfo->score;
+ }
+
/* if (prefs_common.enable_thread) { */
if (summaryview->folder_item->prefs->enable_thread) {
for (; mlist != NULL; mlist = mlist->next) {
msginfo = (MsgInfo *)mlist->data;
parent = NULL;
- summary_set_header(text, msginfo);
-
/* search parent node for threading */
- if (msginfo->inreplyto && *msginfo->inreplyto)
+ if (msginfo->inreplyto && *msginfo->inreplyto) {
parent = g_hash_table_lookup
(msgid_table, msginfo->inreplyto);
+ }
+
+ summary_set_header(text, msginfo);
node = gtk_ctree_insert_node
(ctree, parent, NULL, text, 2,
== NULL)
g_hash_table_insert(msgid_table,
msginfo->msgid, node);
+
+ cur_parent = parent;
+ cur_msginfo = msginfo;
+ while (cur_parent != NULL) {
+ parentinfo = gtk_ctree_node_get_row_data(ctree, cur_parent);
+
+ if (!parentinfo)
+ break;
+
+ if (parentinfo->threadscore <
+ cur_msginfo->threadscore) {
+ gchar * s;
+ parentinfo->threadscore =
+ cur_msginfo->threadscore;
+ s = itos(parentinfo->threadscore);
+#if 0
+ gtk_ctree_node_set_text(ctree, cur_parent, S_COL_SCORE, s);
+#endif
+ }
+ else break;
+
+ cur_msginfo = parentinfo;
+ if (cur_msginfo->inreplyto &&
+ *cur_msginfo->inreplyto) {
+ cur_parent = g_hash_table_lookup(msgid_table, cur_msginfo->inreplyto);
+ }
+ }
}
/* complete the thread */
text[S_COL_MIME] = NULL;
text[S_COL_NUMBER] = itos_buf(col_number, msginfo->msgnum);
text[S_COL_SIZE] = to_human_readable(msginfo->size);
+#if 0
+ text[S_COL_SCORE] = itos_buf(col_score, msginfo->threadscore);
+#else
text[S_COL_SCORE] = itos_buf(col_score, msginfo->score);
+#endif
if (msginfo->date_t) {
procheader_date_get_localtime(date_modified,
}
g_free(filename);
- if (MSG_IS_NEW(msginfo->flags))
- summaryview->newmsgs--;
- if (MSG_IS_UNREAD(msginfo->flags))
- summaryview->unread--;
- if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
- MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
- summary_set_row_marks(summaryview, row);
- gtk_clist_thaw(GTK_CLIST(ctree));
- summary_status_show(summaryview);
- }
-
if (new_window) {
MessageView *msgview;
gtkut_ctree_node_move_if_on_the_edge(ctree, row);
}
+ if (MSG_IS_NEW(msginfo->flags))
+ summaryview->newmsgs--;
+ if (MSG_IS_UNREAD(msginfo->flags))
+ summaryview->unread--;
+ if (MSG_IS_NEW(msginfo->flags) || MSG_IS_UNREAD(msginfo->flags)) {
+ MSG_UNSET_FLAGS(msginfo->flags, MSG_NEW | MSG_UNREAD);
+ summary_set_row_marks(summaryview, row);
+ gtk_clist_thaw(GTK_CLIST(ctree));
+ summary_status_show(summaryview);
+ }
+
if (GTK_WIDGET_VISIBLE(summaryview->headerwin->window))
header_window_show(summaryview->headerwin, msginfo);
/* if score are equal, sort by date */
- diff = msginfo1->score - msginfo2->score;
+ diff = msginfo1->threadscore - msginfo2->threadscore;
if (diff != 0)
return diff;
else