[Commits] [SCM] claws branch, gtk3, updated. 4.0.0-154-g69e7131dc
wwp at claws-mail.org
wwp at claws-mail.org
Sat Sep 11 22:32:58 CEST 2021
The branch, gtk3 has been updated
via 69e7131dc87ed1dbec2f9140a03b38feaf192cdf (commit)
from 74059cdc111cdc7ada818eb3a57df6f441acdbe5 (commit)
Summary of changes:
src/account.c | 64 ++++-
src/addrbook.c | 27 ++-
src/addrbook.h | 2 +
src/addrcache.c | 1 +
src/addrcache.h | 1 +
src/addressbook.c | 252 +++++++++++++++++--
src/addrindex.c | 79 +++++-
src/addrindex.h | 6 +
src/addritem.c | 24 ++
src/addritem.h | 3 +
src/common/smtp.c | 62 ++++-
src/common/smtp.h | 3 +
src/compose.c | 58 ++++-
src/compose.h | 1 +
src/folder.c | 1 +
src/folder_item_prefs.c | 4 +
src/folder_item_prefs.h | 1 +
src/gtk/manage_window.c | 50 +++-
src/gtk/quicksearch.c | 9 +-
src/gtk/quicksearch.h | 2 +
src/html.c | 35 ++-
src/html.h | 1 +
src/jpilot.c | 14 ++
src/jpilot.h | 2 +
src/mainwindow.c | 29 ++-
src/matcher.c | 61 +++++
src/matcher.h | 3 +
src/matcher_parser_parse.y | 5 +-
src/messageview.c | 62 +++--
src/mimeview.c | 25 +-
src/plugins/Makefile.am | 3 +-
src/plugins/fancy/fancy_viewer.c | 21 +-
src/plugins/notification/notification_trayicon.c | 4 +
src/plugins/pgpmime/pgpmime.c | 53 +++-
src/plugins/python/composewindowtype.c | 2 +-
src/plugins/rssyl/rssyl.c | 4 +-
src/plugins/rssyl/rssyl_parse_feed.c | 4 +-
src/plugins/rssyl/rssyl_prefs.c | 13 +
src/plugins/rssyl/rssyl_prefs.h | 2 +
src/plugins/rssyl/rssyl_subscribe.c | 4 +-
src/plugins/rssyl/rssyl_update_feed.c | 9 +-
src/plugins/vcalendar/vcal_meeting_gtk.c | 3 +
src/prefs_account.c | 21 ++
src/prefs_account.h | 1 +
src/prefs_common.c | 23 ++
src/prefs_common.h | 14 ++
src/prefs_ext_prog.c | 34 +++
src/prefs_folder_item.c | 295 +++++++++++++++++++----
src/prefs_matcher.c | 215 +++++++++++++----
src/prefs_message.c | 12 +
src/prefs_summaries.c | 18 +-
src/procmime.c | 107 +++++++-
src/procmime.h | 2 +
src/procmsg.c | 12 +-
src/send_message.c | 10 +-
src/send_message.h | 2 +
src/summaryview.c | 23 +-
src/textview.c | 26 ++
src/toolbar.c | 18 +-
src/vcard.c | 20 +-
src/vcard.h | 2 +
61 files changed, 1630 insertions(+), 234 deletions(-)
- Log -----------------------------------------------------------------
commit 69e7131dc87ed1dbec2f9140a03b38feaf192cdf
Author: wwp <subscript at free.fr>
Date: Sat Sep 11 22:31:26 2021 +0200
Fix CID 1491382: malloc size too short by one because, worst case, qp_decode_const
will dump the exact same input string.
diff --git a/src/account.c b/src/account.c
index f25c9ce89..2854808da 100644
--- a/src/account.c
+++ b/src/account.c
@@ -60,6 +60,7 @@
enum {
ACCOUNT_IS_DEFAULT,
ACCOUNT_ENABLE_GET_ALL,
+ ACCOUNT_INCLUDE_IN_LIST,
ACCOUNT_NAME,
ACCOUNT_PROTOCOL,
ACCOUNT_SERVER,
@@ -157,6 +158,10 @@ static void account_get_all_toggled (GtkCellRendererToggle *widget,
gchar *path,
GtkWidget *list_view);
+static void account_selectable_as_current_account_toggled (GtkCellRendererToggle *widget,
+ gchar *path,
+ GtkWidget *list_view);
+
static void account_double_clicked (GtkTreeView *list_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
@@ -208,6 +213,9 @@ void account_read_config_all(void)
memmove(buf, buf + 1, sizeof(buf) - 1);
buf[strlen(buf) - 1] = '\0';
debug_print("Found label: %s\n", buf);
+ if (ac_label_list && g_slist_find_custom(ac_label_list, buf, (GCompareFunc)strcmp)) {
+ g_warning("duplicate account found (%s)", buf);
+ }
ac_label_list = g_slist_append(ac_label_list,
g_strdup(buf));
}
@@ -232,11 +240,8 @@ void account_read_config_all(void)
account_set_menu();
main_window_reflect_prefs_all_now();
- while (ac_label_list) {
- g_free(ac_label_list->data);
- ac_label_list = g_slist_remove(ac_label_list,
- ac_label_list->data);
- }
+ g_slist_foreach(ac_label_list, (GFunc)g_free, NULL);
+ g_slist_free(ac_label_list);
}
void account_write_config_all(void)
@@ -1491,6 +1496,7 @@ static GtkListStore* account_create_data_store(void)
return gtk_list_store_new(N_ACCOUNT_COLUMNS,
G_TYPE_INT, /* ACCOUNT_IS_DEFAULT */
G_TYPE_BOOLEAN, /* ACCOUNT_ENABLE_GET_ALL */
+ G_TYPE_BOOLEAN, /* ACCOUNT_INCLUDE_IN_LIST */
G_TYPE_STRING, /* ACCOUNT_NAME */
G_TYPE_STRING, /* ACCOUNT_PROTOCOL */
G_TYPE_STRING, /* ACCOUNT_SERVER */
@@ -1513,6 +1519,7 @@ static void account_list_store_insert_account_item(GtkListStore *list_store,
ac_prefs->protocol == A_NNTP ||
ac_prefs->protocol == A_LOCAL) &&
ac_prefs->recv_at_getall;
+ gboolean is_selectable_as_current_account = ac_prefs->selectable_as_current_account;
gchar *protocol, *server;
#ifdef USE_GNUTLS
@@ -1548,6 +1555,7 @@ static void account_list_store_insert_account_item(GtkListStore *list_store,
gtk_list_store_set(list_store, &iter,
ACCOUNT_IS_DEFAULT, ac_prefs->is_default ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL,
ACCOUNT_ENABLE_GET_ALL, is_get_all,
+ ACCOUNT_INCLUDE_IN_LIST, is_selectable_as_current_account,
ACCOUNT_NAME, ac_prefs->account_name,
ACCOUNT_PROTOCOL, protocol,
ACCOUNT_SERVER, server,
@@ -1622,6 +1630,23 @@ static void account_create_list_view_columns(GtkWidget *list_view)
G_CALLBACK(account_get_all_toggled),
list_view);
+ renderer = gtk_cell_renderer_toggle_new();
+ g_object_set(renderer,
+ "radio", FALSE,
+ "activatable", TRUE,
+ NULL);
+ column = gtk_tree_view_column_new_with_attributes
+ (C_("Accounts List Selectable Column Name", "S"), renderer,
+ "active", ACCOUNT_INCLUDE_IN_LIST,
+ NULL);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);
+ gtk_tree_view_column_set_alignment (column, 0.5);
+ CLAWS_SET_TIP(gtk_tree_view_column_get_widget(column),
+ _("Selectable as current account"));
+ g_signal_connect(G_OBJECT(renderer), "toggled",
+ G_CALLBACK(account_selectable_as_current_account_toggled),
+ list_view);
+
renderer = gtk_cell_renderer_text_new();
column = gtk_tree_view_column_new_with_attributes
(_("Name"), renderer,
@@ -1817,6 +1842,35 @@ static void account_get_all_toggled(GtkCellRendererToggle *widget,
ac->recv_at_getall ^= TRUE;
}
+/*!
+ *\brief Triggered when "include in list" column is activated or de-activated
+ */
+static void account_selectable_as_current_account_toggled(GtkCellRendererToggle *widget,
+ gchar *path,
+ GtkWidget *list_view)
+{
+ GtkTreeIter iter;
+ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(list_view));
+ PrefsAccount *ac = NULL;
+ gboolean selectable_as_current_account;
+
+ if (!gtk_tree_model_get_iter_from_string(model, &iter, path))
+ return;
+
+ gtk_tree_model_get(model, &iter,
+ ACCOUNT_DATA, &ac,
+ ACCOUNT_INCLUDE_IN_LIST, &selectable_as_current_account,
+ -1);
+
+ /* set value in store */
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+ ACCOUNT_INCLUDE_IN_LIST, !selectable_as_current_account,
+ -1);
+
+ /* set value in account */
+ ac->selectable_as_current_account ^= TRUE;
+}
+
static void account_double_clicked(GtkTreeView *list_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
diff --git a/src/addrbook.c b/src/addrbook.c
index 296af5d23..98bf9336e 100644
--- a/src/addrbook.c
+++ b/src/addrbook.c
@@ -72,6 +72,7 @@ AddressBookFile *addrbook_create_book()
book->tempList = NULL;
book->tempHash = NULL;
book->addressCache->modified = TRUE;
+ book->addressCache->collapsedFlag = TRUE;
return book;
}
@@ -351,11 +352,14 @@ ItemEMail *addrbook_person_remove_email(AddressBookFile *book,
#define AB_ATTAG_EMAIL "email"
#define AB_ATTAG_EID "eid"
#define AB_ATTAG_PID "pid"
+#define AB_ATTAG_COLLAPSED "collapsed"
/* Attribute values */
#define AB_ATTAG_VAL_PERSON "person"
#define AB_ATTAG_VAL_GROUP "group"
#define AB_ATTAG_VAL_FOLDER "folder"
+#define AB_ATTAG_VAL_YES "yes"
+#define AB_ATTAG_VAL_NO "no"
/**
* Parse address item for person from XML file.
@@ -710,6 +714,9 @@ static void addrbook_parse_folder(AddressBookFile *book, XMLFile *file)
ADDRITEM_NAME(folder) = g_strdup(value);
else if (strcmp(name, AB_ATTAG_REMARKS) == 0)
folder->remarks = g_strdup(value);
+ else if (strcmp(name, AB_ATTAG_COLLAPSED) == 0)
+ folder->isCollapsed =
+ (strcmp(value, AB_ATTAG_VAL_YES) == 0) ? TRUE : FALSE;
attr = g_list_next(attr);
}
if (xml_parse_next_tag(file)) { /* Consume closing tag */
@@ -1192,6 +1199,9 @@ static void addrbook_write_item_folder_vis(gpointer key, gpointer value,
data->error = TRUE;
if (addrbook_write_attr(fp, AB_ATTAG_REMARKS, folder->remarks) < 0)
data->error = TRUE;
+ if (addrbook_write_attr(fp, AB_ATTAG_COLLAPSED,
+ folder->isCollapsed ? AB_ATTAG_VAL_YES : AB_ATTAG_VAL_NO ) < 0)
+ data->error = TRUE;
if (claws_fputs(" >\n", fp) == EOF)
data->error = TRUE;
if (addrbook_write_elem_s(fp, 2, AB_ELTAG_ITEM_LIST) < 0)
@@ -2228,6 +2238,21 @@ gchar *addrbook_guess_next_file(AddressBookFile *book)
return newFile;
}
+gboolean addrbook_get_collapsed( AddressBookFile *book )
+{
+ g_return_val_if_fail(book != NULL, FALSE);
+fprintf(stderr, "==> addrbook_get_collapsed: %d\n", book->addressCache->collapsedFlag);
+ return book->addressCache->collapsedFlag;
+}
+
+void addrbook_set_collapsed( AddressBookFile *book, const gboolean value )
+{
+ g_return_if_fail(book != NULL);
+fprintf(stderr, "==> addrbook_set_collapsed: %d\n", value);
+ book->addressCache->collapsedFlag = value;
+ addrcache_set_dirty(book->addressCache, TRUE);
+}
+
void addrbook_delete_book_file(AddressBookFile *book)
{
gchar *book_path;
@@ -2244,5 +2269,3 @@ void addrbook_delete_book_file(AddressBookFile *book)
/*
* End of Source.
*/
-
-
diff --git a/src/addrbook.h b/src/addrbook.h
index 863a8b0a2..51a20b0a1 100644
--- a/src/addrbook.h
+++ b/src/addrbook.h
@@ -58,7 +58,9 @@ void addrbook_set_path ( AddressBookFile *book, const gchar *value );
void addrbook_set_file ( AddressBookFile *book, const gchar *value );
gboolean addrbook_get_modified ( AddressBookFile *book );
gboolean addrbook_get_accessed ( AddressBookFile *book );
+gboolean addrbook_get_collapsed ( AddressBookFile *book );
void addrbook_set_accessed ( AddressBookFile *book, const gboolean value );
+void addrbook_set_collapsed ( AddressBookFile *book, const gboolean value );
gboolean addrbook_get_read_flag ( AddressBookFile *book );
gint addrbook_get_status ( AddressBookFile *book );
ItemFolder *addrbook_get_root_folder ( AddressBookFile *book );
diff --git a/src/addrcache.c b/src/addrcache.c
index 2765b41bb..c58271706 100644
--- a/src/addrcache.c
+++ b/src/addrcache.c
@@ -65,6 +65,7 @@ AddressCache *addrcache_create() {
cache->accessFlag = FALSE;
cache->name = NULL;
cache->modifyTime = 0;
+ cache->collapsedFlag = FALSE;
/* Generate the next ID using system time */
cache->nextID = 1;
diff --git a/src/addrcache.h b/src/addrcache.h
index 33dc2e1ee..fd7cbbe8a 100644
--- a/src/addrcache.h
+++ b/src/addrcache.h
@@ -44,6 +44,7 @@ struct _AddressCache {
gboolean dirtyFlag;
gboolean accessFlag;
gchar *name;
+ gboolean collapsedFlag;
};
/* Function prototypes */
diff --git a/src/addressbook.c b/src/addressbook.c
index a66c8030d..be2ac7147 100644
--- a/src/addressbook.c
+++ b/src/addressbook.c
@@ -198,6 +198,12 @@ static void addressbook_select_row_tree (GtkCMCTree *ctree,
GtkCMCTreeNode *node,
gint column,
gpointer data);
+static void addressbook_tree_expand_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer *data );
+static void addressbook_tree_collapse_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer *data );
static void addressbook_list_row_selected (GtkCMCTree *clist,
GtkCMCTreeNode *node,
gint column,
@@ -233,6 +239,18 @@ static void addressbook_new_folder_cb (GtkAction *action,
gpointer data);
static void addressbook_new_group_cb (GtkAction *action,
gpointer data);
+static void addressbook_treenode_expand_all_cb(gpointer data,
+ guint action,
+ GtkWidget *widget);
+static void addressbook_treenode_expand_sub_cb(gpointer data,
+ guint action,
+ GtkWidget *widget);
+static void addressbook_treenode_collapse_all_cb(gpointer data,
+ guint action,
+ GtkWidget *widget);
+static void addressbook_treenode_collapse_sub_cb(gpointer data,
+ guint action,
+ GtkWidget *widget);
static void addressbook_treenode_edit_cb (GtkAction *action,
gpointer data);
static void addressbook_treenode_delete_cb (GtkAction *action,
@@ -423,10 +441,13 @@ static GtkActionEntry addressbook_entries[] =
{"Book/EditBook", NULL, N_("_Edit book"), NULL, NULL, G_CALLBACK(addressbook_treenode_edit_cb) },
{"Book/DeleteBook", NULL, N_("_Delete book"), NULL, NULL, G_CALLBACK(addressbook_treenode_delete_cb) },
/* {"Book/---", NULL, "---", NULL, NULL, NULL }, */
+ {"Book/ExpandAll", NULL, N_("_Expand all"), NULL, NULL, G_CALLBACK(addressbook_treenode_expand_all_cb) },
+ {"Book/CollapseAll", NULL, N_("_Collapse all"), NULL, NULL, G_CALLBACK(addressbook_treenode_collapse_all_cb) },
+ /* {"Book/---", NULL, "---", NULL, NULL, NULL }, */
{"Book/Save", NULL, N_("_Save"), "<control>S", NULL, G_CALLBACK(addressbook_file_save_cb) },
{"Book/Close", NULL, N_("_Close"), "<control>W", NULL, G_CALLBACK(close_cb) },
-/* Adress menu */
+/* Edit menu */
{"Address/SelectAll", NULL, N_("_Select all"), "<control>A", NULL, G_CALLBACK(addressbook_select_all_cb) },
{"Address/---", NULL, "---", NULL, NULL, NULL },
{"Address/Cut", NULL, N_("C_ut"), "<control>X", NULL, G_CALLBACK(addressbook_clip_cut_cb) },
@@ -957,6 +978,9 @@ static void addressbook_create(void)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "EditBook", "Book/EditBook", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "DeleteBook", "Book/DeleteBook", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Separator2", "Book/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "ExpandAll", "Book/ExpandAll", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "CollapseAll", "Book/CollapseAll", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Separator3", "Book/---", GTK_UI_MANAGER_SEPARATOR)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Save", "Book/Save", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Menu/Book", "Close", "Book/Close", GTK_UI_MANAGER_MENUITEM)
@@ -1025,6 +1049,10 @@ static void addressbook_create(void)
g_signal_connect(G_OBJECT(ctree), "button_release_event",
G_CALLBACK(addressbook_tree_button_released),
NULL);
+ g_signal_connect(G_OBJECT(ctree), "tree_collapse",
+ G_CALLBACK(addressbook_tree_collapse_node), NULL);
+ g_signal_connect(G_OBJECT(ctree), "tree_expand",
+ G_CALLBACK(addressbook_tree_expand_node), NULL);
/* TEMPORARY */
g_signal_connect(G_OBJECT(ctree), "select_row",
G_CALLBACK(addressbook_select_row_tree), NULL);
@@ -1271,6 +1299,7 @@ static void addressbook_create(void)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Copy", "ABListPopup/Copy", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Paste", "ABListPopup/Paste", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator4", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Separator5", "ABListPopup/---", GTK_UI_MANAGER_SEPARATOR)
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "Mailto", "ABListPopup/Mailto", GTK_UI_MANAGER_MENUITEM)
#ifdef USE_LDAP
MENUITEM_ADDUI_MANAGER(ui_manager, "/Popups/ABListPopup", "BrowseEntry", "ABListPopup/BrowseEntry", GTK_UI_MANAGER_MENUITEM)
@@ -1331,6 +1360,10 @@ static void addressbook_create(void)
gtk_paned_set_position(GTK_PANED(hpaned),
prefs_common.addressbook_hpaned_pos);
+ /* update nodes status */
+fprintf(stderr, "==> FORCING addressbook_tree_selected\n");
+ addressbook_tree_selected(GTK_CMCTREE(ctree),
+ gtk_cmctree_node_nth(GTK_CMCTREE(ctree), 0), 0, NULL);
gtk_widget_show_all(window);
}
@@ -1896,6 +1929,7 @@ static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
ItemFolder *rootFolder = NULL;
AddressObjectType aot;
+fprintf(stderr, "==> addressbook_tree_selected:\n");
addrbook.treeSelected = node;
addrbook.listSelected = NULL;
addressbook_status_show( "" );
@@ -1904,6 +1938,7 @@ static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
if( node ) obj = gtk_cmctree_node_get_row_data( ctree, node );
if( obj == NULL ) {
addressbook_set_clist(NULL, TRUE);
+fprintf(stderr, "==> addressbook_tree_selected: return #1\n");
return;
}
addrbook.opened = node;
@@ -1912,6 +1947,7 @@ static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
/* Read from file */
static gboolean tVal = TRUE;
+fprintf(stderr, "==> addressbook_tree_selected: ADDR_DATASOURCE\n");
ads = ADAPTER_DSOURCE(obj);
ds = ads->dataSource;
@@ -1945,7 +1981,8 @@ static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
}
addressbook_node_add_folder( node, ds, rootFolder, aot );
addrindex_ds_set_access_flag( ds, &tVal );
- gtk_cmctree_expand( ctree, node );
+/*TODO*/
+/* gtk_cmctree_expand( ctree, node );*/
}
} else {
addressbook_set_clist(NULL, TRUE);
@@ -1963,10 +2000,12 @@ static void addressbook_tree_selected(GtkCMCTree *ctree, GtkCMCTreeNode *node,
addressbook_edit_person_invalidate(NULL, NULL, NULL);
/* Setup main menu selections */
+fprintf(stderr, "==> addressbook_tree_selected: set sens\n");
addressbook_menubar_set_sensitive( FALSE );
addressbook_menuitem_set_sensitive( obj, node );
addressbook_list_select_clear();
addressbook_list_menu_setup();
+fprintf(stderr, "==> addressbook_tree_selected: return #2\n");
return;
}
@@ -2125,6 +2164,85 @@ static void addressbook_select_row_tree (GtkCMCTree *ctree,
gint column,
gpointer data)
{
+fprintf(stderr, "==> addressbook_select_row_tree\n");
+}
+
+static void addressbook_treenode_collapse (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gboolean collapse)
+{
+ AddressObject *obj = NULL;
+
+ if( node && GTK_CMCTREE_ROW(node)->children )
+ obj = gtk_cmctree_node_get_row_data( ctree, node );
+ if( !obj )
+ return;
+
+fprintf(stderr, "==> addressbook_treenode_collapse: %d\n", collapse);
+ if( obj->type == ADDR_INTERFACE ) {
+ AdapterInterface *adapter = NULL;
+ AddressInterface *iface = NULL;
+ adapter = ADAPTER_INTERFACE(obj);
+ if (!adapter)
+ return;
+ iface = adapter->interface;
+ if( !iface )
+ return;
+
+fprintf(stderr, "==> addressbook_tree_expand_node: if %d %s\n", obj->type, obj->name);
+ iface->isCollapsed = collapse;
+
+ } else if ( obj->type == ADDR_DATASOURCE ) {
+ AdapterDSource *ads = NULL;
+ AddressDataSource *ds = NULL;
+ gboolean val = collapse;
+
+fprintf(stderr, "==> addressbook_tree_expand_node: ds %d %s\n", obj->type, obj->name);
+ ads = ADAPTER_DSOURCE(obj);
+ if( !ads )
+ return;
+ ds = ads->dataSource;
+ if( !ds )
+ return;
+ addrindex_ds_set_collapsed_flag( ds, &val );
+
+ } else if( obj->type == ADDR_ITEM_FOLDER ) {
+ AddressDataSource *ds = NULL;
+ AddrBookBase *adbase = NULL;
+ ItemFolder *folder = NULL;
+ AddressCache *cache = NULL;
+
+fprintf(stderr, "==> addressbook_tree_expand_node: folder %d %s\n", obj->type, obj->name);
+ folder = ADAPTER_FOLDER(obj)->itemFolder;
+ if( !folder )
+ return;
+ addritem_folder_set_collapsed( folder, collapse);
+ ds = addressbook_find_datasource( node );
+ if( !ds )
+ return;
+ adbase = ( AddrBookBase * ) ds->rawDataSource;
+ if( !adbase )
+ return;
+ cache = adbase->addressCache;
+ if( cache)
+ addrcache_set_dirty( cache, TRUE );
+ }
+}
+
+static void addressbook_tree_expand_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer *data )
+{
+fprintf(stderr, "==> addressbook_tree_expand_node\n");
+ addressbook_treenode_collapse(ctree, node, FALSE);
+}
+
+static void addressbook_tree_collapse_node (GtkCMCTree *ctree,
+ GtkCMCTreeNode *node,
+ gpointer *data )
+{
+fprintf(stderr, "==> addressbook_tree_collapse_node\n");
+ addressbook_treenode_collapse(ctree, node, TRUE);
}
/**
@@ -2179,6 +2297,7 @@ static void addressbook_clip_cut_cb( GtkAction *action, gpointer data ) {
addrclip_clear( _clipBoard_ );
addrclip_add( _clipBoard_, _addressSelect_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
+ addressbook_list_menu_setup();
}
/**
@@ -2189,12 +2308,13 @@ static void addressbook_clip_copy_cb(GtkAction *action, gpointer data) {
addrclip_clear( _clipBoard_ );
addrclip_add( _clipBoard_, _addressSelect_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
+ addressbook_list_menu_setup();
}
/**
* Paste clipboard into address list widget.
*/
-static void addressbook_clip_paste_cb( GtkAction *action, gpointer data ) {
+static void addressbook_clip_paste( AddressClipboard *clipBoard, GtkAction *action, gpointer data ) {
GtkCMCTree *ctree = GTK_CMCTREE( addrbook.ctree );
AddressObject *pobj = NULL;
AddressDataSource *ds = NULL;
@@ -2224,25 +2344,25 @@ static void addressbook_clip_paste_cb( GtkAction *action, gpointer data ) {
abf = addressbook_get_book_file();
if( abf == NULL ) return;
- if( _clipBoard_->cutFlag ) {
+ if( clipBoard->cutFlag ) {
/* Paste/Cut */
- folderGroup = addrclip_paste_cut( _clipBoard_, abf, folder );
+ folderGroup = addrclip_paste_cut( clipBoard, abf, folder );
/* Remove all groups and folders in clipboard from tree node */
addressbook_treenode_remove_item();
/* Remove all "cut" items */
- addrclip_delete_item( _clipBoard_ );
+ addrclip_delete_item( clipBoard );
/* Clear clipboard - cut items??? */
- addrclip_clear( _clipBoard_ );
+ addrclip_clear( clipBoard );
}
else {
/* Paste/Copy */
- folderGroup = addrclip_paste_copy( _clipBoard_, abf, folder );
+ folderGroup = addrclip_paste_copy( clipBoard, abf, folder );
}
- /* addrclip_list_show( _clipBoard_, stdout ); */
+ /* addrclip_list_show( clipBoard, stdout ); */
if( folderGroup ) {
/* Update tree by inserting node for each folder or group */
addressbook_treenode_add_list(
@@ -2258,8 +2378,13 @@ static void addressbook_clip_paste_cb( GtkAction *action, gpointer data ) {
gtk_cmctree_node_get_row_data(GTK_CMCTREE(addrbook.ctree),
addrbook.opened),
TRUE);
-
+}
+/**
+ * Paste clipboard into address list widget.
+ */
+static void addressbook_clip_paste_cb( GtkAction *action, gpointer data ) {
+ addressbook_clip_paste( _clipBoard_, action, data);
}
/**
@@ -2322,6 +2447,7 @@ static void addressbook_treenode_cut_cb( GtkAction *action, gpointer data ) {
addrclip_clear( _clipBoard_ );
addrclip_add( _clipBoard_, _addressSelect_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
+ addressbook_list_menu_setup();
}
/**
@@ -2333,13 +2459,14 @@ static void addressbook_treenode_copy_cb( GtkAction *action, gpointer data ) {
addrclip_clear( _clipBoard_ );
addrclip_add( _clipBoard_, _addressSelect_ );
/* addrclip_list_show( _clipBoard_, stdout ); */
+ addressbook_list_menu_setup();
}
/**
* Paste clipboard into address tree widget.
*/
static void addressbook_treenode_paste_cb( GtkAction *action, gpointer data ) {
- addressbook_clip_paste_cb(NULL,NULL);
+ addressbook_clip_paste( _clipBoard_, NULL, NULL);
}
/**
@@ -2530,6 +2657,7 @@ static gboolean addressbook_tree_button_pressed(GtkWidget *ctree,
gboolean canLookup = FALSE;
GtkCMCTreeNode *node = NULL;
+fprintf(stderr, "==> addressbook_tree_button_pressed\n");
if( ! event ) return FALSE;
/* if( ! event || event->type != GDK_BUTTON_PRESS) return FALSE;*/
@@ -2550,7 +2678,7 @@ static gboolean addressbook_tree_button_pressed(GtkWidget *ctree,
/* edit group */
addressbook_treenode_edit_cb(NULL, NULL);
} else {
- /* expand pr collapse */
+ /* expand or collapse */
node = gtk_cmctree_node_nth(GTK_CMCTREE(ctree), row);
gtk_cmctree_toggle_expansion(GTK_CMCTREE(ctree), node);
}
@@ -2667,6 +2795,8 @@ just_set_sens:
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/EditBook", canEdit );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/DeleteBook", canDelete );
+ cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/ExpandAll", TRUE );
+ cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Book/CollapseAll", TRUE );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Edit/Cut", canCut );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Edit/Copy", canCopy );
cm_menu_set_sensitive_full( addrbook.ui_manager, "Menu/Edit/Paste", canPaste );
@@ -2836,6 +2966,60 @@ static gchar *addressbook_edit_datasource( AddressObject *obj, GtkCMCTreeNode *n
return newName;
}
+/*
+* Expand all sub-items of the address book
+*/
+static void addressbook_treenode_expand_all_cb(gpointer data, guint action,
+ GtkWidget *widget)
+{
+ GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
+ gint index = 0;
+ GtkCMCTreeNode* node = gtk_cmctree_node_nth(ctree, index);
+
+ while (node) {
+ gtk_cmctree_expand_recursive(ctree, node);
+ node = gtk_cmctree_node_nth(ctree, ++index);
+ }
+}
+
+/*
+* Expand all sub-items of the current node
+*/
+static void addressbook_treenode_expand_sub_cb(gpointer data, guint action,
+ GtkWidget *widget)
+{
+ if ( ! addrbook.treeSelected )
+ return;
+ gtk_cmctree_expand_recursive(GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected);
+}
+
+/*
+* Collapse all sub-items of the address book
+*/
+static void addressbook_treenode_collapse_all_cb(gpointer data, guint action,
+ GtkWidget *widget)
+{
+ GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
+ gint index = 0;
+ GtkCMCTreeNode* node = gtk_cmctree_node_nth(ctree, index);
+
+ while (node) {
+ gtk_cmctree_collapse_recursive(ctree, node);
+ node = gtk_cmctree_node_nth(ctree, ++index);
+ }
+}
+
+/*
+* Collapse all sub-items of the current node
+*/
+static void addressbook_treenode_collapse_sub_cb(gpointer data, guint action,
+ GtkWidget *widget)
+{
+ if ( ! addrbook.treeSelected )
+ return;
+ gtk_cmctree_collapse_recursive(GTK_CMCTREE(addrbook.ctree), addrbook.treeSelected);
+}
+
/*
* Edit an object that is in the address tree area.
*/
@@ -3184,6 +3368,7 @@ static ItemFolder * addressbook_setup_subf(
/* Now let's see the folder */
nNode = addressbook_node_add_folder( pNode, ds, folder, aoType );
+fprintf(stderr, "==> EXPAND %s: addressbook_setup_subf\n", folder->obj.name);
gtk_cmctree_expand( ctree, pNode );
if( nNode ) {
gtk_sctree_select( GTK_SCTREE(ctree), nNode );
@@ -4406,12 +4591,11 @@ static GtkCMCTreeNode *addressbook_node_add_folder(
{
GtkCMCTree *ctree = GTK_CMCTREE(addrbook.ctree);
GtkCMCTreeNode *newNode = NULL;
- AdapterFolder *adapter;
AddressTypeControlItem *atci = NULL;
GList *listItems = NULL;
- gchar *name;
ItemFolder *rootFolder;
+fprintf(stderr, "==> addressbook_node_add_folder\n");
/* Only visible folders */
if( itemFolder == NULL || itemFolder->isHidden )
return NULL;
@@ -4431,6 +4615,9 @@ static GtkCMCTreeNode *addressbook_node_add_folder(
newNode = node;
}
else {
+ AdapterFolder *adapter;
+ gchar *name = NULL;
+
adapter = g_new0( AdapterFolder, 1 );
ADDRESS_OBJECT_TYPE(adapter) = ADDR_ITEM_FOLDER;
ADDRESS_OBJECT_NAME(adapter) = g_strdup( ADDRITEM_NAME(itemFolder) );
@@ -4444,6 +4631,7 @@ static GtkCMCTreeNode *addressbook_node_add_folder(
gtk_cmctree_node_set_row_data_full( ctree, newNode, adapter,
addressbook_free_treenode );
}
+fprintf(stderr, "==> addressbook_node_add_folder adding FOLDER: %s\n", name);
}
listItems = itemFolder->listFolder;
@@ -4459,6 +4647,25 @@ static GtkCMCTreeNode *addressbook_node_add_folder(
listItems = g_list_next( listItems );
}
gtk_sctree_sort_node( ctree, node );
+
+ /* restore expanded/collapsed status of non-root node */
+ if( !itemFolder->isRoot ) {
+fprintf(stderr, "--- addressbook_node_add_folder RESTORE STATUS: %s -> %d\n", itemFolder->obj.name, addritem_folder_get_collapsed( itemFolder ));
+ if( addritem_folder_get_collapsed( itemFolder ) ) {
+ g_signal_handlers_block_by_func(G_OBJECT(ctree),
+ G_CALLBACK(addressbook_tree_collapse_node), NULL);
+ gtk_cmctree_collapse( ctree, newNode );
+ g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
+ G_CALLBACK(addressbook_tree_collapse_node), NULL);
+ } else {
+ g_signal_handlers_block_by_func(G_OBJECT(ctree),
+ G_CALLBACK(addressbook_tree_expand_node), NULL);
+ gtk_cmctree_expand( ctree, newNode );
+ g_signal_handlers_unblock_by_func(G_OBJECT(ctree),
+ G_CALLBACK(addressbook_tree_expand_node), NULL);
+ }
+ }
+
return newNode;
}
@@ -5844,6 +6051,7 @@ static void addressbook_drag_received_cb(GtkWidget *widget,
gint row, column;
GtkCMCTreeNode *node;
GtkCMCTreeNode *lastopened = addrbook.opened;
+ AddressClipboard *clipBoard = NULL;
if (!strncmp(gtk_selection_data_get_data(data), "Dummy_addr", 10)) {
if (gtk_cmclist_get_selection_info
@@ -5856,17 +6064,23 @@ static void addressbook_drag_received_cb(GtkWidget *widget,
return;
gtk_cmclist_freeze(GTK_CMCLIST(addrbook.clist));
+ clipBoard = addrclip_create();
+ addrclip_set_index( clipBoard, _addressIndex_ ); /* use the master clipBoard index */
if (gdk_drag_context_get_selected_action(drag_context) == GDK_ACTION_COPY ||
- !strcmp(gtk_selection_data_get_data(data), "Dummy_addr_copy"))
- addressbook_clip_copy_cb(NULL, NULL);
- else
- addressbook_clip_cut_cb(NULL, NULL);
+ !strcmp(gtk_selection_data_get_data(data), "Dummy_addr_copy")) {
+ clipBoard->cutFlag = FALSE;
+ addrclip_add( clipBoard, _addressSelect_ );
+ } else {
+ clipBoard->cutFlag = TRUE;
+ addrclip_add( clipBoard, _addressSelect_ );
+ }
gtk_sctree_select( GTK_SCTREE(addrbook.ctree), node);
- addressbook_clip_paste_cb(NULL,NULL);
+ addressbook_clip_paste( clipBoard, NULL, NULL);
gtk_sctree_select( GTK_SCTREE(addrbook.ctree), lastopened);
gtk_cmclist_thaw(GTK_CMCLIST(addrbook.clist));
gtk_drag_finish(drag_context, TRUE, TRUE, time);
}
+ addrclip_free( clipBoard );
}
/*
diff --git a/src/addrindex.c b/src/addrindex.c
index 1517f02e8..a87bb1147 100644
--- a/src/addrindex.c
+++ b/src/addrindex.c
@@ -83,12 +83,15 @@
/* XML Attribute names */
#define ATTAG_BOOK_NAME "name"
#define ATTAG_BOOK_FILE "file"
+#define ATTAG_BOOK_COLLAPSED "collapsed"
#define ATTAG_VCARD_NAME "name"
#define ATTAG_VCARD_FILE "file"
+#define ATTAG_VCARD_COLLAPSED "collapsed"
#define ATTAG_JPILOT_NAME "name"
#define ATTAG_JPILOT_FILE "file"
+#define ATTAG_JPILOT_COLLAPSED "collapsed"
#define ATTAG_JPILOT_CUSTOM_1 "custom-1"
#define ATTAG_JPILOT_CUSTOM_2 "custom-2"
#define ATTAG_JPILOT_CUSTOM_3 "custom-3"
@@ -96,6 +99,7 @@
#define ATTAG_JPILOT_CUSTOM "custom-"
#define ATTAG_LDAP_NAME "name"
+#define ATTAG_LDAP_COLLAPSED "collapsed"
#define ATTAG_LDAP_HOST "host"
#define ATTAG_LDAP_PORT "port"
#define ATTAG_LDAP_BASE_DN "base-dn"
@@ -210,6 +214,7 @@ static AddressInterface *addrindex_create_interface(
iface->getAllGroups = NULL;
iface->getName = NULL;
iface->listSource = NULL;
+ iface->setCollapsedFlag = NULL;
/* Search stuff */
iface->externalQuery = FALSE;
@@ -234,6 +239,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->readOnly = FALSE;
iface->getModifyFlag = ( void * ) addrbook_get_modified;
iface->getAccessFlag = ( void * ) addrbook_get_accessed;
+ iface->getCollapsedFlag = ( void * ) addrbook_get_collapsed;
iface->getReadFlag = ( void * ) addrbook_get_read_flag;
iface->getStatusCode = ( void * ) addrbook_get_status;
iface->getReadData = ( void * ) addrbook_read_data;
@@ -244,6 +250,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->getAllGroups = ( void * ) addrbook_get_all_groups;
iface->getName = ( void * ) addrbook_get_name;
iface->setAccessFlag = ( void * ) addrbook_set_accessed;
+ iface->setCollapsedFlag = ( void * ) addrbook_set_collapsed;
iface->searchOrder = 0;
/* Add to list of interfaces in address book */
@@ -256,6 +263,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
ADDR_IF_VCARD, "vCard", TAG_IF_VCARD, TAG_DS_VCARD );
iface->getModifyFlag = ( void * ) vcard_get_modified;
iface->getAccessFlag = ( void * ) vcard_get_accessed;
+ iface->getCollapsedFlag = ( void * ) vcard_get_collapsed;
iface->getReadFlag = ( void * ) vcard_get_read_flag;
iface->getStatusCode = ( void * ) vcard_get_status;
iface->getReadData = ( void * ) vcard_read_data;
@@ -265,6 +273,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->getAllPersons = ( void * ) vcard_get_all_persons;
iface->getName = ( void * ) vcard_get_name;
iface->setAccessFlag = ( void * ) vcard_set_accessed;
+ iface->setCollapsedFlag = ( void * ) vcard_set_collapsed;
iface->searchOrder = 0;
addrIndex->interfaceList =
g_list_append( addrIndex->interfaceList, iface );
@@ -279,6 +288,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->useInterface = iface->haveLibrary;
iface->getModifyFlag = ( void * ) jpilot_get_modified;
iface->getAccessFlag = ( void * ) jpilot_get_accessed;
+ iface->getCollapsedFlag = ( void * ) jpilot_get_collapsed;
iface->getReadFlag = ( void * ) jpilot_get_read_flag;
iface->getStatusCode = ( void * ) jpilot_get_status;
iface->getReadData = ( void * ) jpilot_read_data;
@@ -288,6 +298,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->getAllPersons = ( void * ) jpilot_get_all_persons;
iface->getName = ( void * ) jpilot_get_name;
iface->setAccessFlag = ( void * ) jpilot_set_accessed;
+ iface->setCollapsedFlag = ( void * ) jpilot_set_collapsed;
iface->searchOrder = 0;
#else
iface->useInterface = FALSE;
@@ -307,6 +318,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->useInterface = iface->haveLibrary;
iface->getModifyFlag = ( void * ) ldapsvr_get_modified;
iface->getAccessFlag = ( void * ) ldapsvr_get_accessed;
+ iface->getCollapsedFlag = NULL;
iface->getReadFlag = ( void * ) ldapsvr_get_read_flag;
iface->getStatusCode = ( void * ) ldapsvr_get_status;
iface->getReadData = ( void * ) ldapsvr_read_data;
@@ -315,6 +327,7 @@ static void addrindex_build_if_list( AddressIndex *addrIndex ) {
iface->getListPerson = ( void * ) ldapsvr_get_list_person;
iface->getName = ( void * ) ldapsvr_get_name;
iface->setAccessFlag = ( void * ) ldapsvr_set_accessed;
+ iface->setCollapsedFlag = NULL;
iface->externalQuery = TRUE;
iface->searchOrder = 1;
#else
@@ -1123,6 +1136,10 @@ static AddressDataSource *addrindex_parse_book( XMLFile *file ) {
else if( strcmp( name, ATTAG_BOOK_FILE ) == 0) {
addrbook_set_file( abf, value );
}
+ else if( strcmp( name, ATTAG_BOOK_COLLAPSED ) == 0) {
+ addrbook_set_collapsed( abf,
+ (strcmp( value, ATVAL_BOOLEAN_YES ) == 0) ? TRUE : FALSE );
+ }
attr = g_list_next( attr );
}
ds->rawDataSource = abf;
@@ -1138,6 +1155,9 @@ static int addrindex_write_book( FILE *fp, AddressDataSource *ds, gint lvl ) {
return -1;
if (addrindex_write_attr( fp, ATTAG_BOOK_FILE, abf->fileName ) < 0)
return -1;
+ if (addrindex_write_attr( fp, ATTAG_BOOK_COLLAPSED,
+ abf->addressCache->collapsedFlag ? ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
+ return -1;
if (claws_fputs( " />\n", fp ) == EOF)
return -1;
}
@@ -1161,6 +1181,10 @@ static AddressDataSource *addrindex_parse_vcard( XMLFile *file ) {
else if( strcmp( name, ATTAG_VCARD_FILE ) == 0) {
vcard_set_file( vcf, value );
}
+ else if( strcmp( name, ATTAG_VCARD_COLLAPSED ) == 0) {
+ vcard_set_collapsed( vcf,
+ (strcmp( value, ATVAL_BOOLEAN_YES ) == 0) ? TRUE : FALSE );
+ }
attr = g_list_next( attr );
}
ds->rawDataSource = vcf;
@@ -1176,6 +1200,9 @@ static int addrindex_write_vcard( FILE *fp, AddressDataSource *ds, gint lvl ) {
return -1;
if (addrindex_write_attr( fp, ATTAG_VCARD_FILE, vcf->path ) < 0)
return -1;
+ if (addrindex_write_attr( fp, ATTAG_VCARD_COLLAPSED,
+ vcf->addressCache->collapsedFlag ? ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
+ return -1;
if (claws_fputs( " />\n", fp ) == EOF)
return -1;
}
@@ -1212,6 +1239,10 @@ static AddressDataSource *addrindex_parse_jpilot( XMLFile *file ) {
else if( strcmp( name, ATTAG_JPILOT_CUSTOM_4 ) == 0 ) {
jpilot_add_custom_label( jpf, value );
}
+ else if( strcmp( name, ATTAG_JPILOT_COLLAPSED ) == 0 ) {
+ jpilot_set_collapsed( jpf,
+ (strcmp( value, ATVAL_BOOLEAN_YES ) == 0) ? TRUE : FALSE );
+ }
attr = g_list_next( attr );
}
ds->rawDataSource = jpf;
@@ -1230,6 +1261,9 @@ static int addrindex_write_jpilot( FILE *fp,AddressDataSource *ds, gint lvl ) {
return -1;
if (addrindex_write_attr( fp, ATTAG_JPILOT_FILE, jpf->path ) < 0)
return -1;
+ if (addrindex_write_attr( fp, ATTAG_JPILOT_COLLAPSED,
+ jpf->addressCache->collapsedFlag ? ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
+ return -1;
node = customLbl;
ind = 1;
while( node ) {
@@ -1357,7 +1391,7 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
gchar *serverName = NULL;
gchar *criteria = NULL;
gboolean bDynSearch;
- gboolean bTLS, bSSL;
+ gboolean bTLS, bSSL, bCollapsed;
gint iMatch;
gchar *password = NULL;
@@ -1433,6 +1467,12 @@ static AddressDataSource *addrindex_parse_ldap( XMLFile *file ) {
bSSL = TRUE;
}
}
+ else if( strcmp( name, ATTAG_LDAP_COLLAPSED ) == 0 ) {
+ bCollapsed = FALSE;
+ if( strcmp( value, ATVAL_BOOLEAN_YES ) == 0 ) {
+ bCollapsed = TRUE;
+ }
+ }
attr = g_list_next( attr );
}
@@ -1712,6 +1752,9 @@ static int addrindex_write_index( AddressIndex *addrIndex, FILE *fp ) {
nodeDS = iface->listSource;
if (addrindex_write_elem_s( fp, lvlList, iface->listTag ) < 0)
return -1;
+ if (addrindex_write_attr( fp, ATTAG_BOOK_COLLAPSED,
+ iface->isCollapsed ? ATVAL_BOOLEAN_YES : ATVAL_BOOLEAN_NO ) < 0)
+ return -1;
if (claws_fputs( ">\n", fp ) == EOF)
return -1;
while( nodeDS ) {
@@ -2400,6 +2443,24 @@ gboolean addrindex_ds_get_read_flag( AddressDataSource *ds ) {
return retVal;
}
+/*
+ * Return collapsed flag for specified data source.
+ */
+gboolean addrindex_ds_get_collapsed_flag( AddressDataSource *ds ) {
+ gboolean retVal = FALSE;
+ AddressInterface *iface;
+
+fprintf(stderr, "==> addrindex_ds_get_collapsed_flag:\n");
+ if( ds == NULL ) return retVal;
+ iface = ds->interface;
+ if( iface == NULL ) return retVal;
+ if( iface->getCollapsedFlag ) {
+fprintf(stderr, "==> addrindex_ds_get_collapsed_flag: invoking iface's getCollapsedFlag\n");
+ retVal = ( iface->getCollapsedFlag ) ( ds->rawDataSource );
+ }
+ return retVal;
+}
+
/*
* Return status code for specified data source.
*/
@@ -2482,6 +2543,22 @@ void addrindex_ds_set_access_flag( AddressDataSource *ds, gboolean *value ) {
}
}
+/*
+ * Set the collapsed flag inside the data source.
+ */
+void addrindex_ds_set_collapsed_flag( AddressDataSource *ds, gboolean *value ) {
+ AddressInterface *iface;
+
+fprintf(stderr, "==> addrindex_ds_set_collapsed_flag:\n");
+ if( ds == NULL ) return;
+ iface = ds->interface;
+ if( iface == NULL ) return;
+ if( iface->setCollapsedFlag) {
+fprintf(stderr, "==> addrindex_ds_set_collapsed_flag: invoking iface's setCollapsedFlag\n");
+ ( iface->setCollapsedFlag ) ( ds->rawDataSource, *value );
+ }
+}
+
/*
* Return read only flag for specified data source.
*/
diff --git a/src/addrindex.h b/src/addrindex.h
index 2db902a90..c8a913ace 100644
--- a/src/addrindex.h
+++ b/src/addrindex.h
@@ -73,8 +73,10 @@ struct _AddressInterface {
gboolean haveLibrary;
gboolean readOnly;
GList *listSource;
+ gboolean isCollapsed;
gboolean (*getModifyFlag)( void * );
gboolean (*getAccessFlag)( void * );
+ gboolean (*getCollapsedFlag)( void * );
gboolean (*getReadFlag)( void * );
gint (*getStatusCode)( void * );
gint (*getReadData)( void * );
@@ -85,6 +87,7 @@ struct _AddressInterface {
GList *(*getAllGroups)( void * );
gchar *(*getName)( void * );
void (*setAccessFlag)( void *, void * );
+ void (*setCollapsedFlag)( void *, const gboolean );
gboolean externalQuery;
gint searchOrder;
void (*startSearch)( void * );
@@ -138,12 +141,15 @@ gint addrindex_save_all_books ( AddressIndex *addrIndex );
gboolean addrindex_ds_get_modify_flag ( AddressDataSource *ds );
gboolean addrindex_ds_get_access_flag ( AddressDataSource *ds );
gboolean addrindex_ds_get_read_flag ( AddressDataSource *ds );
+gboolean addrindex_ds_get_collapsed_flag ( AddressDataSource *ds );
gint addrindex_ds_get_status_code ( AddressDataSource *ds );
gint addrindex_ds_read_data ( AddressDataSource *ds );
ItemFolder *addrindex_ds_get_root_folder( AddressDataSource *ds );
gchar *addrindex_ds_get_name ( AddressDataSource *ds );
void addrindex_ds_set_access_flag ( AddressDataSource *ds,
gboolean *value );
+void addrindex_ds_set_collapsed_flag ( AddressDataSource *ds,
+ gboolean *value );
gboolean addrindex_ds_get_readonly ( AddressDataSource *ds );
/* Search support */
diff --git a/src/addritem.c b/src/addritem.c
index 832a139fa..cf8f81179 100644
--- a/src/addritem.c
+++ b/src/addritem.c
@@ -802,6 +802,7 @@ ItemFolder *addritem_create_item_folder( void ) {
folder->folderType = ADDRFOLDER_NONE;
folder->folderData = NULL;
folder->isHidden = FALSE;
+ folder->isCollapsed = TRUE;
return folder;
}
@@ -850,6 +851,27 @@ void addritem_folder_set_hidden( ItemFolder *folder, const gboolean value ) {
folder->isHidden = value;
}
+/**
+ * Get expanded/collapsed status of folder.
+ * \param folder Folder.
+ */
+gboolean addritem_folder_get_collapsed ( ItemFolder *folder )
+{
+fprintf(stderr, "==> addritem_folder_get_collapsed: %d\n", folder->isCollapsed);
+ return folder->isCollapsed;
+}
+
+/**
+ * Specify expanded/collapsed status of folder.
+ * \param folder Folder.
+ * \param value Set to <code>TRUE</code> if the folder is collapsed.
+ */
+void addritem_folder_set_collapsed ( ItemFolder *folder, const gboolean value)
+{
+fprintf(stderr, "==> addritem_folder_set_collapsed: %d\n", value);
+ folder->isCollapsed = value;
+}
+
/**
* Free address folder. Note: this does not free up the lists of children
* (folders, groups and person). This should be done prior to calling this
@@ -879,6 +901,7 @@ void addritem_free_item_folder( ItemFolder *folder ) {
folder->folderType = ADDRFOLDER_NONE;
folder->folderData = NULL;
folder->isHidden = FALSE;
+ folder->isCollapsed = TRUE;
g_free( folder );
}
@@ -947,6 +970,7 @@ void addritem_print_item_folder( ItemFolder *folder, FILE *stream ) {
fprintf( stream, "\trem: '%s'\n", folder->remarks );
fprintf( stream, "\ttyp: %d\n", folder->folderType );
fprintf( stream, "\thid: %s\n", folder->isHidden ? "hidden" : "visible" );
+ fprintf( stream, "\texp: %s\n", folder->isCollapsed ? "collapsed" : "expanded" );
fprintf( stream, "\t---\n" );
parent = ( ItemFolder * ) ADDRITEM_PARENT(folder);
if( parent ) {
diff --git a/src/addritem.h b/src/addritem.h
index 9bccdf8f2..afacdcae4 100644
--- a/src/addritem.h
+++ b/src/addritem.h
@@ -108,6 +108,7 @@ struct _ItemFolder {
AddressFolderType folderType; /* Folder type */
gpointer *folderData; /* Pointer to folder's data */
gboolean isHidden; /* TRUE if folder is hidden */
+ gboolean isCollapsed; /* TRUE if folder is collapsed */
};
typedef struct _ItemGroup ItemGroup;
@@ -180,6 +181,8 @@ gboolean addritem_folder_add_folder ( ItemFolder *folder, ItemFolder *item );
gboolean addritem_folder_add_group ( ItemFolder *folder, ItemGroup *item );
GList *addritem_folder_get_person_list ( ItemFolder *folder );
GList *addritem_folder_get_group_list ( ItemFolder *folder );
+gboolean addritem_folder_get_collapsed ( ItemFolder *folder );
+void addritem_folder_set_collapsed ( ItemFolder *folder, const gboolean value);
void addritem_parse_first_last ( ItemPerson *person );
GList *addritem_folder_path ( const ItemFolder *folder,
diff --git a/src/common/smtp.c b/src/common/smtp.c
index b0d91c0cc..a6a448f89 100644
--- a/src/common/smtp.c
+++ b/src/common/smtp.c
@@ -106,6 +106,9 @@ Session *smtp_session_new(void *prefs_account)
session->error_val = SM_OK;
session->error_msg = NULL;
+ session->is_dsn_requested = FALSE;
+ session->is_dsn_supported = FALSE;
+
return SESSION(session);
}
@@ -127,6 +130,7 @@ gint smtp_from(SMTPSession *session)
{
gchar buf[MESSAGEBUFSIZE];
gchar *mail_size = NULL;
+ gchar *dsn_parm = NULL;
cm_return_val_if_fail(session->from != NULL, SM_ERROR);
@@ -137,15 +141,20 @@ gint smtp_from(SMTPSession *session)
else
mail_size = g_strdup("");
+ if (session->is_dsn_requested && session->is_dsn_supported)
+ dsn_parm = g_strdup(" RET=HDRS");
+ else
+ dsn_parm = g_strdup("");
if (strchr(session->from, '<'))
- g_snprintf(buf, sizeof(buf), "MAIL FROM:%s%s", session->from,
- mail_size);
+ g_snprintf(buf, sizeof(buf), "MAIL FROM:%s%s%s", session->from,
+ mail_size, dsn_parm);
else
- g_snprintf(buf, sizeof(buf), "MAIL FROM:<%s>%s", session->from,
- mail_size);
+ g_snprintf(buf, sizeof(buf), "MAIL FROM:<%s>%s%s", session->from,
+ mail_size, dsn_parm);
g_free(mail_size);
+ g_free(dsn_parm);
if (session_send_msg(SESSION(session), buf) < 0)
return SM_ERROR;
@@ -335,6 +344,10 @@ static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg)
p += 9;
session->avail_auth_type |= SMTPAUTH_TLS_AVAILABLE;
}
+ if (g_ascii_strncasecmp(p, "DSN", 3) == 0) {
+ p += 4;
+ session->is_dsn_supported = TRUE;
+ }
return SM_OK;
} else if ((msg[0] == '1' || msg[0] == '2' || msg[0] == '3') &&
(msg[3] == ' ' || msg[3] == '\0'))
@@ -460,17 +473,52 @@ static gint smtp_rcpt(SMTPSession *session)
{
gchar buf[MESSAGEBUFSIZE];
gchar *to;
+ gchar *dsn_parm = NULL;
+ gchar *open_bracket = NULL;
+ gchar *close_bracket = NULL;
+ gchar *to822 = NULL;
cm_return_val_if_fail(session->cur_to != NULL, SM_ERROR);
session->state = SMTP_RCPT;
to = (gchar *)session->cur_to->data;
+ open_bracket = strchr(to, '<');
+
+ if (session->is_dsn_requested && session->is_dsn_supported) {
+ to822 = to;
+ if (open_bracket) {
+ /* make it RFC 822 compliant */
+ to822 = g_strdup(open_bracket + 1);
+ close_bracket = strchr(to822, '>');
+ if (close_bracket) { /* should always be true */
+ *close_bracket = '\0';
+ }
+ }
+ g_snprintf(buf, sizeof(buf), /* borrow the buf for a second */
+ " NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;%s", to822);
+ dsn_parm = g_strdup(buf); /* make buf available again */
+ if (open_bracket) {
+ g_free(to822); /* won't need it anymore */
+ }
+ }
+ else {
+ if (session->is_dsn_requested
+ && session->is_dsn_supported == FALSE) {
+ log_warning(LOG_PROTOCOL,
+ _("DSN requested but server does not support it\n"));
+ }
+ dsn_parm = g_strdup("");
+ }
- if (strchr(to, '<'))
- g_snprintf(buf, sizeof(buf), "RCPT TO:%s", to);
+
+ if (open_bracket)
+ g_snprintf(buf, sizeof(buf), "RCPT TO:%s%s", to, dsn_parm);
else
- g_snprintf(buf, sizeof(buf), "RCPT TO:<%s>", to);
+ g_snprintf(buf, sizeof(buf), "RCPT TO:<%s>%s", to, dsn_parm);
+
+ g_free(dsn_parm); /* won't need it anymore */
+
if (session_send_msg(SESSION(session), buf) < 0)
return SM_ERROR;
log_print(LOG_PROTOCOL, "SMTP> %s\n", buf);
diff --git a/src/common/smtp.h b/src/common/smtp.h
index f20bf711c..a0cfeea52 100644
--- a/src/common/smtp.h
+++ b/src/common/smtp.h
@@ -113,6 +113,9 @@ struct _SMTPSession
gchar *error_msg;
gboolean is_esmtp;
ESMTPFlag esmtp_flags;
+
+ gboolean is_dsn_requested;
+ gboolean is_dsn_supported;
void *dialog;
diff --git a/src/compose.c b/src/compose.c
index 70988de11..2446453f5 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -499,6 +499,8 @@ static void compose_activate_privacy_system (Compose *compose,
PrefsAccount *account,
gboolean warn);
static void compose_apply_folder_privacy_settings(Compose *compose, FolderItem *folder_item);
+static void compose_toggle_dsn_requested_cb(GtkToggleAction *action,
+ gpointer data);
static void compose_toggle_return_receipt_cb(GtkToggleAction *action,
gpointer data);
static void compose_toggle_remove_refs_cb(GtkToggleAction *action,
@@ -722,7 +724,8 @@ static GtkToggleActionEntry compose_toggle_entries[] =
{"Edit/AutoIndent", NULL, N_("Auto _indent"), NULL, NULL, G_CALLBACK(compose_toggle_autoindent_cb), FALSE }, /* Toggle */
{"Options/Sign", NULL, N_("Si_gn"), NULL, NULL, G_CALLBACK(compose_toggle_sign_cb), FALSE }, /* Toggle */
{"Options/Encrypt", NULL, N_("_Encrypt"), NULL, NULL, G_CALLBACK(compose_toggle_encrypt_cb), FALSE }, /* Toggle */
- {"Options/RequestRetRcpt", NULL, N_("_Request Return Receipt"), NULL, NULL, G_CALLBACK(compose_toggle_return_receipt_cb), FALSE }, /* Toggle */
+ {"Options/RequestDSN", NULL, N_("Request _Notification of Successful Delivery"), NULL, NULL, G_CALLBACK(compose_toggle_dsn_requested_cb), FALSE }, /* Toggle */
+ {"Options/RequestRetRcpt", NULL, N_("Request _Return Receipt"), NULL, NULL, G_CALLBACK(compose_toggle_return_receipt_cb), FALSE }, /* Toggle */
{"Options/RemoveReferences", NULL, N_("Remo_ve references"), NULL, NULL, G_CALLBACK(compose_toggle_remove_refs_cb), FALSE }, /* Toggle */
{"Tools/ShowRuler", NULL, N_("Show _ruler"), NULL, NULL, G_CALLBACK(compose_toggle_ruler_cb), FALSE }, /* Toggle */
};
@@ -1064,8 +1067,13 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
} else {
compose_set_folder_prefs(compose, item, TRUE);
}
- if (item && item->ret_rcpt) {
- cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
+ if (item) {
+ if (item->prefs && item->prefs->request_dsn) {
+ cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestDSN", TRUE);
+ }
+ if (item->ret_rcpt) {
+ cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
+ }
}
} else {
if (mailto && *mailto != '\0') {
@@ -1566,8 +1574,14 @@ static Compose *compose_generic_reply(MsgInfo *msginfo,
compose_extract_original_charset(compose);
- if (msginfo->folder && msginfo->folder->ret_rcpt)
- cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
+ if (msginfo->folder) {
+ if (msginfo->folder->prefs && msginfo->folder->prefs->request_dsn) {
+ cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestDSN", TRUE);
+ }
+ if (msginfo->folder->ret_rcpt) {
+ cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestRetRcpt", TRUE);
+ }
+ }
/* Set save folder */
if (msginfo->folder && msginfo->folder->prefs && msginfo->folder->prefs->save_copy_to_folder) {
@@ -1753,6 +1767,11 @@ Compose *compose_forward(PrefsAccount *account, MsgInfo *msginfo,
if (!compose->fwdinfo)
compose->fwdinfo = procmsg_msginfo_copy(msginfo);
+ if (compose->deferred_destroy) {
+ compose_destroy(compose);
+ return NULL;
+ }
+
compose_extract_original_charset(compose);
if (msginfo->subject && *msginfo->subject) {
@@ -1956,7 +1975,7 @@ static Compose *compose_forward_multiple(PrefsAccount *account, GSList *msginfo_
for (msginfo = msginfo_list; msginfo != NULL; msginfo = msginfo->next) {
if (msginfo->data) {
- MSG_UNSET_PERM_FLAGS(((MsgInfo *)msginfo->data)->flags, MSG_REPLIED);
+/* MSG_UNSET_PERM_FLAGS(((MsgInfo *)msginfo->data)->flags, MSG_REPLIED);*/
MSG_SET_PERM_FLAGS(((MsgInfo *)msginfo->data)->flags, MSG_FORWARDED);
}
}
@@ -2404,6 +2423,13 @@ Compose *compose_reedit(MsgInfo *msginfo, gboolean batch)
compose_set_save_to(compose, &queueheader_buf[4]);
g_free(queueheader_buf);
}
+ if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "DSN:")) {
+ gint dsn = atoi(&queueheader_buf[strlen("DSN:")]);
+ if (dsn) {
+ cm_toggle_menu_set_active_full(compose->ui_manager, "Menu/Options/RequestDSN", TRUE);
+ }
+ g_free(queueheader_buf);
+ }
if (!procheader_get_header_from_msginfo(msginfo, &queueheader_buf, "RRCPT:")) {
gint active = atoi(&queueheader_buf[strlen("RRCPT:")]);
if (active) {
@@ -5596,6 +5622,7 @@ static gint compose_redirect_write_to_file(Compose *compose, FILE *fdest)
"X-Sylpheed-Privacy", "X-Sylpheed-Sign:", "X-Sylpheed-Encrypt",
"X-Sylpheed-End-Special-Headers:", "X-Sylpheed-Account-Id:",
"X-Claws-Auto-Wrapping:", "X-Claws-Auto-Indent:",
+ "DSN:",
NULL
};
gint ret = 0;
@@ -6262,6 +6289,9 @@ static ComposeQueueResult compose_queue_sub(Compose *compose, gint *msgnum, Fold
if (compose->return_receipt) {
err |= (fprintf(fp, "RRCPT:1\n") < 0);
}
+ if (compose->dsn_requested) {
+ err |= (fprintf(fp, "DSN:1\n") < 0);
+ }
/* Message-ID of message replying to */
if ((compose->replyinfo != NULL) && (compose->replyinfo->msgid != NULL)) {
gchar *folderid = NULL;
@@ -7922,6 +7952,7 @@ static Compose *compose_create(PrefsAccount *account,
MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options/Priority", "Lowest", "Options/Priority/Lowest", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options", "Separator3", "Options/---", GTK_UI_MANAGER_SEPARATOR)
+ MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options", "RequestDSN", "Options/RequestDSN", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options", "RequestRetRcpt", "Options/RequestRetRcpt", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options", "Separator4", "Options/---", GTK_UI_MANAGER_SEPARATOR)
MENUITEM_ADDUI_MANAGER(compose->ui_manager, "/Menu/Options", "RemoveReferences", "Options/RemoveReferences", GTK_UI_MANAGER_MENUITEM)
@@ -9221,7 +9252,7 @@ static void compose_attach_update_label(Compose *compose)
total_size += ainfo->size;
i++;
}
- text = g_strdup_printf(" (%d/%s)", i, to_human_readable(total_size));
+ text = g_strdup_printf(" (%d / %s)", i, to_human_readable(total_size));
gtk_label_set_text(GTK_LABEL(compose->attach_label), text);
g_free(text);
}
@@ -10304,6 +10335,9 @@ gboolean compose_draft (gpointer data, guint action)
if (compose->return_receipt) {
err |= (fprintf(fp, "RRCPT:1\n") < 0);
}
+ if (compose->dsn_requested) {
+ err |= (fprintf(fp, "DSN:1\n") < 0);
+ }
if (compose->privacy_system) {
err |= (fprintf(fp, "X-Claws-Sign:%d\n", compose->use_signing) < 0);
err |= (fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption) < 0);
@@ -11748,6 +11782,16 @@ static void compose_toggle_return_receipt_cb(GtkToggleAction *action, gpointer d
compose->return_receipt = FALSE;
}
+static void compose_toggle_dsn_requested_cb(GtkToggleAction *action, gpointer data)
+{
+ Compose *compose = (Compose *)data;
+
+ if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)))
+ compose->dsn_requested = TRUE;
+ else
+ compose->dsn_requested = FALSE;
+}
+
static void compose_toggle_remove_refs_cb(GtkToggleAction *action, gpointer data)
{
Compose *compose = (Compose *)data;
diff --git a/src/compose.h b/src/compose.h
index 011da35b0..ac68c7a6f 100644
--- a/src/compose.h
+++ b/src/compose.h
@@ -206,6 +206,7 @@ struct _Compose
gboolean sending;
gboolean return_receipt;
+ gboolean dsn_requested;
gboolean batch;
diff --git a/src/folder.c b/src/folder.c
index 8f3e9a363..c9c25ab54 100644
--- a/src/folder.c
+++ b/src/folder.c
@@ -4840,6 +4840,7 @@ gint folder_item_search_msgs_local (Folder *folder,
procmsg_msginfo_free(&msg);
+ gtk_main_iteration_do (FALSE);
if (progress_cb != NULL
&& !progress_cb(progress_data, FALSE, processed_count,
matched_count, msgcount))
diff --git a/src/folder_item_prefs.c b/src/folder_item_prefs.c
index edc4e248d..1d0246561 100644
--- a/src/folder_item_prefs.c
+++ b/src/folder_item_prefs.c
@@ -127,6 +127,8 @@ static PrefParam param[] = {
NULL, NULL, NULL},
{"forward_body_format", NULL, &tmp_prefs.forward_body_format, P_STRING,
NULL, NULL, NULL},
+ {"request_dsn", "FALSE", &tmp_prefs.request_dsn, P_BOOL,
+ NULL, NULL, NULL},
{"config_version", "-1", &tmp_prefs.config_version, P_INT,
NULL, NULL, NULL},
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
@@ -212,6 +214,7 @@ static FolderItemPrefs *folder_item_prefs_clear(FolderItemPrefs *prefs)
prefs->always_sign = SIGN_OR_ENCRYPT_DEFAULT;
prefs->always_encrypt = SIGN_OR_ENCRYPT_DEFAULT;
prefs->save_copy_to_folder = FALSE;
+ prefs->request_dsn = FALSE;
prefs->enable_processing = FALSE;
prefs->enable_processing_when_opening = FALSE;
@@ -327,6 +330,7 @@ void folder_item_prefs_copy_prefs(FolderItem * src, FolderItem * dest)
tmp_prefs.always_encrypt = src->prefs->always_encrypt;
tmp_prefs.save_copy_to_folder = src->prefs->save_copy_to_folder;
tmp_prefs.color = src->prefs->color;
+ tmp_prefs.request_dsn = src->prefs->request_dsn;
tmp_prefs.compose_with_format = src->prefs->compose_with_format;
tmp_prefs.compose_subject_format = g_strdup(src->prefs->compose_subject_format);
diff --git a/src/folder_item_prefs.h b/src/folder_item_prefs.h
index 6f9cac114..3e46116b9 100644
--- a/src/folder_item_prefs.h
+++ b/src/folder_item_prefs.h
@@ -54,6 +54,7 @@ struct _FolderItemPrefs {
gboolean skip_on_goto_unread_or_new;
gboolean request_return_receipt;
+ gboolean request_dsn;
gboolean enable_default_to;
gchar *default_to;
gboolean enable_default_reply_to;
diff --git a/src/gtk/manage_window.c b/src/gtk/manage_window.c
index 47f786ae6..1a6fb14ec 100644
--- a/src/gtk/manage_window.c
+++ b/src/gtk/manage_window.c
@@ -23,64 +23,90 @@
#include "manage_window.h"
#include "utils.h"
+#define DEBUG 0
+
GtkWidget *focus_window;
gint manage_window_focus_in(GtkWidget *widget, GdkEventFocus *event,
gpointer data)
{
-/* const gchar *title = NULL; */
+#if DEBUG
+ const gchar *title = NULL;
+#endif
if (!GTK_IS_WINDOW(widget))
return FALSE;
-
-/* title = gtk_window_get_title(GTK_WINDOW(widget));
+
+#if DEBUG
+ title = gtk_window_get_title(GTK_WINDOW(widget));
debug_print("Focus in event: window: %p - %s\n", widget,
- title ? title : "no title"); */
+ title ? title : "no title");
+#endif
focus_window = widget;
+#if DEBUG
+ debug_print("focus_window = %p\n", focus_window);
+#endif
return FALSE;
}
gint manage_window_focus_out(GtkWidget *widget, GdkEventFocus *event,
gpointer data)
{
-/* const gchar *title = NULL; */
+#if DEBUG
+ const gchar *title = NULL;
+#endif
if (!GTK_IS_WINDOW(widget))
return FALSE;
-/* title = gtk_window_get_title(GTK_WINDOW(widget));
+#if DEBUG
+ title = gtk_window_get_title(GTK_WINDOW(widget));
debug_print("Focus out event: window: %p - %s\n", widget,
- title ? title : "no title"); */
+ title ? title : "no title");
+#endif
if (focus_window == widget)
focus_window = NULL;
+#if DEBUG
+ debug_print("focus_window = %p\n", focus_window);
+#endif
return FALSE;
}
gint manage_window_unmap(GtkWidget *widget, GdkEventAny *event, gpointer data)
{
-/* const gchar *title = gtk_window_get_title(GTK_WINDOW(widget));
+#if DEBUG
+ const gchar *title = gtk_window_get_title(GTK_WINDOW(widget));
debug_print("Unmap event: window: %p - %s\n", widget,
- title ? title : "no title"); */
+ title ? title : "no title");
+#endif
if (focus_window == widget)
focus_window = NULL;
+#if DEBUG
+ debug_print("focus_window = %p\n", focus_window);
+#endif
return FALSE;
}
void manage_window_destroy(GtkWidget *widget, gpointer data)
{
-/* const gchar *title = gtk_window_get_title(GTK_WINDOW(widget));
+#if DEBUG
+ const gchar *title = gtk_window_get_title(GTK_WINDOW(widget));
debug_print("Destroy event: window: %p - %s\n", widget,
- title ? title : "no title"); */
-
+ title ? title : "no title");
+#endif
if (focus_window == widget)
focus_window = NULL;
+
+#if DEBUG
+ debug_print("focus_window = %p\n", focus_window);
+#endif
}
void manage_window_set_transient(GtkWindow *window)
diff --git a/src/gtk/quicksearch.c b/src/gtk/quicksearch.c
index 6ba924203..7c0bb8c9f 100644
--- a/src/gtk/quicksearch.c
+++ b/src/gtk/quicksearch.c
@@ -356,6 +356,11 @@ static gboolean searchbar_pressed(GtkWidget *widget, GdkEventKey *event,
if (event != NULL && (event->keyval == GDK_KEY_Escape)) {
gchar *str;
+ if (quicksearch->running) {
+ advsearch_abort(quicksearch->asearch);
+ return TRUE;
+ }
+
quicksearch->in_typing = FALSE;
str = quicksearch_get_text(quicksearch);
@@ -403,7 +408,7 @@ static gboolean searchbar_pressed(GtkWidget *widget, GdkEventKey *event,
*
* When adding new lines, remember to put 2 strings for each line
*/
-static gchar *search_descr_strings[] = {
+gchar *extended_search_descr_strings[] = {
"a", N_("all messages"),
"ag #", N_("messages whose age is greater than # days"),
"al #", N_("messages whose age is less than # days"),
@@ -471,7 +476,7 @@ static DescriptionWindow search_descr = {
N_("Extended Search allows the user to define criteria that messages must "
"have in order to match and be displayed in the message list.\n"
"The following symbols can be used:"),
- search_descr_strings
+ extended_search_descr_strings
};
static void search_description_cb(GtkWidget *widget)
diff --git a/src/gtk/quicksearch.h b/src/gtk/quicksearch.h
index 9aada6e1f..5ac71d9e0 100644
--- a/src/gtk/quicksearch.h
+++ b/src/gtk/quicksearch.h
@@ -26,6 +26,8 @@
typedef struct _QuickSearch QuickSearch;
typedef void (*QuickSearchExecuteCallback) (QuickSearch *quicksearch, gpointer data);
+extern gchar *extended_search_descr_strings[];
+
#include "procmsg.h"
QuickSearch *quicksearch_new();
diff --git a/src/html.c b/src/html.c
index eb921c706..5b82ce379 100644
--- a/src/html.c
+++ b/src/html.c
@@ -68,6 +68,7 @@ SC_HTMLParser *sc_html_parser_new(FILE *fp, CodeConverter *conv)
parser->empty_line = TRUE;
parser->space = FALSE;
parser->pre = FALSE;
+ parser->msword = FALSE;
parser->indent = 0;
return parser;
@@ -379,10 +380,23 @@ static SC_HTMLState sc_html_parse_tag(SC_HTMLParser *parser)
parser->state = SC_HTML_HREF;
} else if (!strcmp(tag->name, "p")) {
parser->space = FALSE;
+ GList *cur;
+ gboolean realp = TRUE; /* a proper paragraph */
+ if (parser->msword) {
+ /* Look for paragraphs that are just lines without spacing. */
+ for (cur = tag->attr; cur != NULL; cur = cur->next) {
+ if (cur->data &&
+ !strcmp(((SC_HTMLAttr *)cur->data)->name, "class") &&
+ !strcmp(((SC_HTMLAttr *)cur->data)->value, "MsoPlainText")) {
+ realp = FALSE; /* used to be a text/plain line */
+ break;
+ }
+ }
+ }
if (!parser->empty_line) {
parser->space = FALSE;
if (!parser->newline) sc_html_append_char(parser, '\n');
- sc_html_append_char(parser, '\n');
+ if (realp) sc_html_append_char(parser, '\n');
}
parser->state = SC_HTML_PAR;
} else if (!strcmp(tag->name, "pre")) {
@@ -432,7 +446,7 @@ static SC_HTMLState sc_html_parse_tag(SC_HTMLParser *parser)
if (!parser->empty_line) {
parser->space = FALSE;
if (!parser->newline) sc_html_append_char(parser, '\n');
- sc_html_append_char(parser, '\n');
+// sc_html_append_char(parser, '\n');
}
parser->state = SC_HTML_NORMAL;
} else if (!strcmp(tag->name, "/div") ||
@@ -443,7 +457,24 @@ static SC_HTMLState sc_html_parse_tag(SC_HTMLParser *parser)
sc_html_append_char(parser, '\n');
}
parser->state = SC_HTML_NORMAL;
+ } else if (!strcmp(tag->name, "meta")) {
+ /* Look for HTML from MS Outlook, which lists a version of Microsoft Word as Generator */
+ GList *cur;
+ int msword = 0;
+ for (cur = tag->attr; cur != NULL; cur = cur->next) {
+ if (cur->data &&
+ !strcmp(((SC_HTMLAttr *)cur->data)->name, "name") &&
+ !strcmp(((SC_HTMLAttr *)cur->data)->value, "Generator") ) {
+ ++msword;
+ }
+ if (cur->data &&
+ !strcmp(((SC_HTMLAttr *)cur->data)->name, "content") &&
+ !strncmp(((SC_HTMLAttr *)cur->data)->value, "Microsoft Word ", 15) ) {
+ ++msword;
}
+ }
+ if (msword == 2) parser->msword = TRUE;
+ }
sc_html_free_tag(tag);
diff --git a/src/html.h b/src/html.h
index 922389a23..9b59e25d3 100644
--- a/src/html.h
+++ b/src/html.h
@@ -63,6 +63,7 @@ struct _SC_HTMLParser
gboolean empty_line;
gboolean space;
gboolean pre;
+ gboolean msword;
gint indent;
};
diff --git a/src/jpilot.c b/src/jpilot.c
index 9923d766d..d773d1f2c 100644
--- a/src/jpilot.c
+++ b/src/jpilot.c
@@ -190,6 +190,7 @@ JPilotFile *jpilot_create() {
pilotFile->labelInd = NULL;
pilotFile->havePC3 = FALSE;
pilotFile->pc3ModifyTime = 0;
+ pilotFile->addressCache->collapsedFlag = TRUE;
return pilotFile;
}
@@ -1661,6 +1662,19 @@ gboolean jpilot_test_pilot_lib( void ) {
return TRUE;
}
+gboolean jpilot_get_collapsed( JPilotFile *pilotFile ) {
+ g_return_val_if_fail( pilotFile != NULL, FALSE );
+fprintf(stderr, "==> jpilot_get_collapsed: %d\n", pilotFile->addressCache->collapsedFlag);
+ return pilotFile->addressCache->collapsedFlag;
+}
+
+void jpilot_set_collapsed( JPilotFile *pilotFile, const gboolean value ) {
+ g_return_if_fail( pilotFile != NULL );
+fprintf(stderr, "==> jpilot_set_collapsed: %d\n", value);
+ pilotFile->addressCache->collapsedFlag = value;
+ addrcache_set_dirty(pilotFile->addressCache, TRUE);
+}
+
#endif /* USE_JPILOT */
/*
diff --git a/src/jpilot.h b/src/jpilot.h
index 3787d0cf0..2e719a0d0 100644
--- a/src/jpilot.h
+++ b/src/jpilot.h
@@ -79,7 +79,9 @@ void jpilot_free ( JPilotFile *pilotFile );
gint jpilot_get_status ( JPilotFile *pilotFile );
gboolean jpilot_get_modified ( JPilotFile *pilotFile );
gboolean jpilot_get_accessed ( JPilotFile *pilotFile );
+gboolean jpilot_get_collapsed ( JPilotFile *pilotFile );
void jpilot_set_accessed ( JPilotFile *pilotFile, const gboolean value );
+void jpilot_set_collapsed ( JPilotFile *pilotFile, const gboolean value );
gboolean jpilot_get_read_flag ( JPilotFile *pilotFile );
ItemFolder *jpilot_get_root_folder ( JPilotFile *pilotFile );
gchar *jpilot_get_name ( JPilotFile *pilotFile );
diff --git a/src/mainwindow.c b/src/mainwindow.c
index 681bc90e2..373cb00a7 100644
--- a/src/mainwindow.c
+++ b/src/mainwindow.c
@@ -2457,6 +2457,9 @@ static void main_window_set_account_selector_menu(MainWindow *mainwin,
for (cur_ac = account_list; cur_ac != NULL; cur_ac = cur_ac->next) {
ac_prefs = (PrefsAccount *)cur_ac->data;
+ if (!ac_prefs->selectable_as_current_account) {
+ continue;
+ }
menuitem = gtk_menu_item_new_with_label
(ac_prefs->account_name
? ac_prefs->account_name : _("Untitled"));
@@ -2504,6 +2507,8 @@ static void main_window_set_account_receive_menu(MainWindow *mainwin,
for (child = account_list; child != NULL; child = child->next) {
ac_prefs = (PrefsAccount *)child->data;
+ if (!ac_prefs->selectable_as_current_account)
+ continue;
if (ac_prefs->protocol == A_NONE)
continue;
@@ -2537,6 +2542,8 @@ static void main_window_set_toolbar_combo_receive_menu(MainWindow *mainwin,
for (cur_ac = account_list; cur_ac != NULL; cur_ac = cur_ac->next) {
ac_prefs = (PrefsAccount *)cur_ac->data;
+ if (!ac_prefs->selectable_as_current_account)
+ continue;
if (ac_prefs->protocol == A_NONE)
continue;
@@ -2572,6 +2579,9 @@ static void main_window_set_toolbar_combo_compose_menu(MainWindow *mainwin,
for (cur_ac = account_list; cur_ac != NULL; cur_ac = cur_ac->next) {
ac_prefs = (PrefsAccount *)cur_ac->data;
+ if (!ac_prefs->selectable_as_current_account) {
+ continue;
+ }
menuitem = gtk_menu_item_new_with_label
(ac_prefs->account_name
? ac_prefs->account_name : _("Untitled"));
@@ -2947,6 +2957,7 @@ SensitiveCondMask main_window_get_current_state(MainWindow *mainwin)
FolderItem *item = mainwin->summaryview->folder_item;
GList *account_list = account_get_list();
GSList *tmp;
+ guint acc;
selection = summary_get_selection_type(mainwin->summaryview);
@@ -3028,18 +3039,28 @@ SensitiveCondMask main_window_get_current_state(MainWindow *mainwin)
if (item && item->prefs->processing && selection != SUMMARY_NONE)
UPDATE_STATE(M_HAVE_PROCESSING);
- if (g_list_length(account_list) > 1)
- UPDATE_STATE(M_HAVE_MULTI_ACCOUNT);
+ acc = 0;
+ for (account_list = account_get_list(); account_list != NULL; account_list = account_list->next) {
+ if (((PrefsAccount*)account_list->data)->selectable_as_current_account) {
+ if (acc >= 1) {
+ UPDATE_STATE(M_HAVE_MULTI_ACCOUNT);
+ break;
+ }
+ acc++;
+ }
+ }
for (account_list = account_get_list(); account_list != NULL; account_list = account_list->next) {
- if (((PrefsAccount*)account_list->data)->protocol != A_NONE) {
+ if ((((PrefsAccount*)account_list->data)->protocol != A_NONE) &&
+ ((PrefsAccount*)account_list->data)->selectable_as_current_account) {
UPDATE_STATE(M_HAVE_ANY_RETRIEVABLE_ACCOUNT);
break;
}
}
for (account_list = account_get_list(); account_list != NULL; account_list = account_list->next) {
- if (((PrefsAccount*)account_list->data)->protocol == A_NNTP) {
+ if ((((PrefsAccount*)account_list->data)->protocol == A_NNTP) &&
+ ((PrefsAccount*)account_list->data)->selectable_as_current_account) {
UPDATE_STATE(M_HAVE_NEWS_ACCOUNT);
break;
}
diff --git a/src/matcher.c b/src/matcher.c
index 8a1020987..03b31e03f 100644
--- a/src/matcher.c
+++ b/src/matcher.c
@@ -777,6 +777,67 @@ static gboolean matcherprop_match_test(const MatcherProp *prop,
return (retval == 0);
}
+gint matcherprop_parse_date_time(gint criteria, const gchar *s, struct tm *tm_out)
+{
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(struct tm));
+ tm.tm_isdst = -1;
+
+ if (sscanf(s, "%04d-%02d-%02d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday) == 3)
+ {
+ --tm.tm_mon;
+ tm.tm_year -= 1900;
+ }
+
+ if (criteria == MATCHCRITERIA_DATE_AFTER)
+ {
+ tm.tm_hour = 23;
+ tm.tm_min = tm.tm_sec = 59;
+ }
+
+ s = strchr(s, ' ');
+ if (s)
+ {
+ int *v[] = { &tm.tm_hour, &tm.tm_min, &tm.tm_sec };
+ int i;
+
+ tm.tm_hour = tm.tm_min = tm.tm_sec = -1;
+ for (i = 0, ++s; i < 3; ++s)
+ {
+ if (*s >= '0' && *s <= '9')
+ {
+ if (*v[i] < 0)
+ *v[i] = 0;
+ else
+ *v[i] *= 10;
+ *v[i] += *s - '0';
+ }
+ else if (*s == ':')
+ ++i;
+ else
+ break;
+ }
+
+ for (i = 0; i < 3; ++i)
+ {
+ if (*v[i] < 0)
+ *v[i] = (criteria == MATCHCRITERIA_DATE_AFTER) ? 59 : 0;
+ }
+ if (tm.tm_hour > 23)
+ tm.tm_hour = 23;
+ if (tm.tm_min > 59)
+ tm.tm_min = 59;
+ if (tm.tm_sec > 59)
+ tm.tm_sec = 59;
+ }
+
+ if (tm_out)
+ *tm_out = tm;
+
+ return mktime(&tm);
+}
+
/*!
*\brief Check if a message matches the condition in a matcher
* structure.
diff --git a/src/matcher.h b/src/matcher.h
index 6b6fbbe66..a00444cb3 100644
--- a/src/matcher.h
+++ b/src/matcher.h
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <regex.h>
#include <glib.h>
+#include <time.h>
#include "proctypes.h"
#include "matchertypes.h"
@@ -193,4 +194,6 @@ void prefs_matcher_write_config (void);
gchar * matcher_quote_str(const gchar * src);
+gint matcherprop_parse_date_time(gint criteria, const gchar *s, struct tm *tm_out);
+
#endif
diff --git a/src/matcher_parser_parse.y b/src/matcher_parser_parse.y
index 19726de99..19cd3acd7 100644
--- a/src/matcher_parser_parse.y
+++ b/src/matcher_parser_parse.y
@@ -25,7 +25,6 @@
#include "utils.h"
#include "filtering.h"
-#include "procheader.h"
#include "matcher.h"
#include "matcher_parser.h"
#include "matcher_parser_lex.h"
@@ -999,7 +998,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_DATE_AFTER;
expr = $2;
- value = procheader_date_parse(NULL, expr, 0);
+ value = matcherprop_parse_date_time(criteria, expr, NULL);
prop = matcherprop_new(criteria, NULL, 0, expr, value);
}
| MATCHER_DATE_BEFORE MATCHER_STRING
@@ -1010,7 +1009,7 @@ MATCHER_ALL
criteria = MATCHCRITERIA_DATE_BEFORE;
expr = $2;
- value = procheader_date_parse(NULL, expr, 0);
+ value = matcherprop_parse_date_time(criteria, expr, NULL);
prop = matcherprop_new(criteria, NULL, 0, expr, value);
}
| MATCHER_NEWSGROUPS match_type MATCHER_STRING
diff --git a/src/messageview.c b/src/messageview.c
index ecc5a639e..cdc524db9 100644
--- a/src/messageview.c
+++ b/src/messageview.c
@@ -1320,8 +1320,18 @@ static void messageview_find_part_depth_first(MimeInfoSearch *context, MimeMedia
}
}
-gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
- gboolean all_headers)
+static gint real_messageview_show(MessageView *messageview, MsgInfo *msginfo,
+ gboolean all_headers, gboolean decrypt);
+
+static void decrypt_message_clicked(NoticeView *noticeview, MessageView *messageview)
+{
+ noticeview_hide(noticeview);
+ real_messageview_show(messageview, messageview->msginfo,
+ messageview->all_headers, TRUE);
+}
+
+static gint real_messageview_show(MessageView *messageview, MsgInfo *msginfo,
+ gboolean all_headers, gboolean decrypt)
{
gchar *text = NULL;
gchar *file;
@@ -1400,22 +1410,24 @@ gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
return -1;
}
- while ((encinfo = find_encrypted_part(mimeinfo)) != NULL) {
- debug_print("decrypting message part\n");
- if (privacy_mimeinfo_decrypt(encinfo) < 0) {
- text = g_strdup_printf(_("Couldn't decrypt: %s"),
- privacy_get_error());
- noticeview_show(messageview->noticeview);
- noticeview_set_icon(messageview->noticeview,
- STOCK_PIXMAP_NOTICE_WARN);
- noticeview_set_text(messageview->noticeview, text);
- gtk_widget_hide(messageview->noticeview->button);
- gtk_widget_hide(messageview->noticeview->button2);
- g_free(text);
- break;
+ if (decrypt) {
+ while ((encinfo = find_encrypted_part(mimeinfo)) != NULL) {
+ debug_print("decrypting message part\n");
+ if (privacy_mimeinfo_decrypt(encinfo) < 0) {
+ text = g_strdup_printf(_("Couldn't decrypt: %s"),
+ privacy_get_error());
+ noticeview_show(messageview->noticeview);
+ noticeview_set_icon(messageview->noticeview,
+ STOCK_PIXMAP_NOTICE_WARN);
+ noticeview_set_text(messageview->noticeview, text);
+ gtk_widget_hide(messageview->noticeview->button);
+ gtk_widget_hide(messageview->noticeview->button2);
+ g_free(text);
+ break;
+ }
}
}
-
+
if (messageview->msginfo != msginfo) {
procmsg_msginfo_free(&(messageview->msginfo));
messageview->msginfo = NULL;
@@ -1432,6 +1444,17 @@ gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
if (prefs_common.display_header_pane)
headerview_show(messageview->headerview, messageview->msginfo);
+ if (!decrypt && find_encrypted_part(mimeinfo) != NULL) {
+ noticeview_set_text(messageview->noticeview, _("This message is encrypted."));
+ noticeview_set_icon(messageview->noticeview,
+ STOCK_PIXMAP_DOC_INFO);
+ noticeview_set_button_text(messageview->noticeview, _("Decrypt message"));
+ noticeview_set_button_press_callback(messageview->noticeview,
+ G_CALLBACK(decrypt_message_clicked),
+ (gpointer) messageview);
+ noticeview_show(messageview->noticeview);
+ }
+
messageview_register_nav(messageview);
messageview_set_position(messageview, 0);
@@ -1566,6 +1589,13 @@ done:
return 0;
}
+gint messageview_show(MessageView *messageview, MsgInfo *msginfo,
+ gboolean all_headers)
+{
+ return real_messageview_show(messageview, msginfo, all_headers,
+ prefs_common.decrypt_messages);
+}
+
void messageview_reflect_prefs_pixmap_theme(void)
{
GList *cur;
diff --git a/src/mimeview.c b/src/mimeview.c
index 9b2fa0ec1..8bd115bf0 100644
--- a/src/mimeview.c
+++ b/src/mimeview.c
@@ -1889,7 +1889,7 @@ static gboolean mimeview_write_part(const gchar *filename,
gchar *dir;
gint err;
- dir= g_path_get_dirname(filename);
+ dir = g_path_get_dirname(filename);
if (!is_dir_exist(dir))
make_dir_hier(dir);
g_free(dir);
@@ -1898,14 +1898,18 @@ static gboolean mimeview_write_part(const gchar *filename,
AlertValue aval;
gchar *res;
gchar *tmp;
-
- if (!g_utf8_validate(filename, -1, NULL))
+ gint sz;
+
+ sz = get_file_size(filename);
+ if (!g_utf8_validate(filename, -1, NULL)) {
tmp = conv_filename_to_utf8(filename);
- else
+ if (sz == -1)
+ sz = get_file_size(filename);
+ } else
tmp = g_strdup(filename);
-
- res = g_strdup_printf(_("Overwrite existing file '%s'?"),
- tmp);
+
+ res = g_strdup_printf(_("Overwrite existing file '%s' (%ld bytes)\nwith this one (%ld bytes)?"),
+ tmp, sz, partinfo->length);
g_free(tmp);
aval = alertpanel(_("Overwrite"), res, _("_Cancel"),
_("_OK"), NULL, ALERTFOCUS_FIRST);
@@ -1913,7 +1917,12 @@ static gboolean mimeview_write_part(const gchar *filename,
if (G_ALERTALTERNATE != aval) return FALSE;
}
- if ((err = procmime_get_part(filename, partinfo)) < 0) {
+ if ((partinfo->type == MIMETYPE_TEXT) && partinfo->subtype
+ && (strcasecmp(partinfo->subtype, "plain") == 0))
+ err = procmime_get_part_with_bom(filename, partinfo, TRUE);
+ else
+ err = procmime_get_part(filename, partinfo);
+ if (err < 0) {
debug_print("error saving MIME part: %d\n", err);
if (handle_error)
alertpanel_error
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 4af74dd6a..8003c6bd4 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -36,6 +36,7 @@ SUBDIRS = \
spamassassin \
spam_report \
tnef_parse \
- vcalendar
+ vcalendar \
+ vfolder
.PHONY: test
diff --git a/src/plugins/fancy/fancy_viewer.c b/src/plugins/fancy/fancy_viewer.c
index 03cbe0cce..5c9ce757d 100644
--- a/src/plugins/fancy/fancy_viewer.c
+++ b/src/plugins/fancy/fancy_viewer.c
@@ -62,6 +62,7 @@ static void zoom_out_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
static gboolean fancy_prefs_cb(GtkWidget *widget, GdkEventButton *ev, FancyViewer *viewer);
static void zoom_100_cb(GtkWidget *widget, GdkEvent *ev, FancyViewer *viewer);
static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer);
+static void open_in_alt_browser_cb(GtkWidget *widget, FancyViewer *viewer);
static void fancy_create_popup_prefs_menu(FancyViewer *viewer);
static void fancy_show_notice(FancyViewer *viewer, const gchar *message);
static size_t download_file_curl_write_cb(void *buffer, size_t size,
@@ -743,10 +744,17 @@ static void search_the_web_cb(GtkWidget *widget, FancyViewer *viewer)
static void open_in_browser_cb(GtkWidget *widget, FancyViewer *viewer)
{
debug_print("open outer: %s\n", viewer->cur_link);
- if(viewer->cur_link)
+ if (viewer->cur_link)
open_uri(viewer->cur_link, prefs_common_get_uri_cmd());
}
+static void open_in_alt_browser_cb(GtkWidget *widget, FancyViewer *viewer)
+{
+ debug_print("open outer: %s\n", viewer->cur_link);
+ if (viewer->cur_link)
+ open_uri(viewer->cur_link, prefs_common_get_uri_alt_cmd());
+}
+
static size_t download_file_curl_write_cb(void *buffer, size_t size,
size_t nmemb, void *data)
{
@@ -953,6 +961,17 @@ static gboolean context_menu_cb (WebKitWebView *view, WebKitContextMenu *menu,
(GtkCallback)viewer_menu_handler,
viewer);
+ if (prefs_common_get_uri_alt_cmd()) {
+ GtkWidget *openaltbrowser = gtk_image_menu_item_new_with_label(_("Open in Alternate Browser"));
+ GtkWidget *img = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(openaltbrowser), img);
+ gtk_widget_show(GTK_WIDGET(openaltbrowser));
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), openaltbrowser);
+ g_signal_connect(G_OBJECT(openaltbrowser), "activate",
+ G_CALLBACK(open_in_alt_browser_cb),
+ (gpointer *) viewer);
+ }
+
if (plugin) {
GtkWidget *rssyl = gtk_menu_item_new_with_label(_("Import feed"));
gtk_widget_show(GTK_WIDGET(rssyl));
diff --git a/src/plugins/notification/notification_trayicon.c b/src/plugins/notification/notification_trayicon.c
index 7f290a104..3bf934835 100644
--- a/src/plugins/notification/notification_trayicon.c
+++ b/src/plugins/notification/notification_trayicon.c
@@ -367,6 +367,10 @@ static void notification_trayicon_account_list_reset(const gchar *menuname,
if (receive && ac_prefs->protocol == A_NONE)
continue;
+ if (!ac_prefs->selectable_as_current_account) {
+ continue;
+ }
+
menuitem = gtk_menu_item_new_with_label
(ac_prefs->account_name ? ac_prefs->account_name
: _("Untitled"));
diff --git a/src/plugins/pgpmime/pgpmime.c b/src/plugins/pgpmime/pgpmime.c
index e9cb47998..6ca8a4c1c 100644
--- a/src/plugins/pgpmime/pgpmime.c
+++ b/src/plugins/pgpmime/pgpmime.c
@@ -270,24 +270,53 @@ static gboolean pgpmime_is_encrypted(MimeInfo *mimeinfo)
const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----";
const gchar *end_indicator = "-----END PGP MESSAGE-----";
gchar *textdata;
+ guint firstChild = 0;
if (mimeinfo->type != MIMETYPE_MULTIPART)
return FALSE;
- if (g_ascii_strcasecmp(mimeinfo->subtype, "encrypted"))
- return FALSE;
- tmpstr = procmime_mimeinfo_get_parameter(mimeinfo, "protocol");
- if ((tmpstr == NULL) || g_ascii_strcasecmp(tmpstr, "application/pgp-encrypted"))
- return FALSE;
- if (g_node_n_children(mimeinfo->node) != 2)
- return FALSE;
-
- tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 0)->data;
+
+ /* Workaround for mail + gpgmail + exchange
+ * MS Exchange modifies the message structure and
+ * inserts an empty plain text attachment in the beginning,
+ * so the resulting message structure looks like this:
+ *
+ * message/rfc822 (offset:0 length:4534 encoding: 6)
+ * multipart/mixed (offset:1542 length:2992 encoding: 6)
+ * text/plain (offset:1680 length:0 encoding: 3)
+ * application/pgp-encrypted (offset:2142 length:21 encoding: 4)
+ * application/octet-stream (offset:2586 length:1897 encoding: 4)
+ */
+ if (g_node_n_children(mimeinfo->node) == 3)
+ {
+ if (g_ascii_strcasecmp(mimeinfo->subtype, "mixed"))
+ return FALSE;
+ tmpinfo = (MimeInfo*) g_node_nth_child(mimeinfo->node, 0)->data;
+ if (tmpinfo->length != 0)
+ return FALSE;
+ if (tmpinfo->type != MIMETYPE_TEXT)
+ return FALSE;
+ if (g_ascii_strcasecmp(tmpinfo->subtype, "plain"))
+ return FALSE;
+
+ firstChild = 1;
+ }
+ else /* standard PGP MIME email (two children) */
+ {
+ if (g_ascii_strcasecmp(mimeinfo->subtype, "encrypted"))
+ return FALSE;
+ tmpstr = procmime_mimeinfo_get_parameter(mimeinfo, "protocol");
+ if ((tmpstr == NULL) || g_ascii_strcasecmp(tmpstr, "application/pgp-encrypted"))
+ return FALSE;
+ if (g_node_n_children(mimeinfo->node) != 2)
+ return FALSE;
+ }
+
+ tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, firstChild)->data;
if (tmpinfo->type != MIMETYPE_APPLICATION)
return FALSE;
if (g_ascii_strcasecmp(tmpinfo->subtype, "pgp-encrypted"))
return FALSE;
-
- tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 1)->data;
+ tmpinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, firstChild + 1)->data;
if (tmpinfo->type != MIMETYPE_APPLICATION)
return FALSE;
if (g_ascii_strcasecmp(tmpinfo->subtype, "octet-stream"))
@@ -333,7 +362,7 @@ static MimeInfo *pgpmime_decrypt(MimeInfo *mimeinfo)
cm_return_val_if_fail(pgpmime_is_encrypted(mimeinfo), NULL);
- encinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, 1)->data;
+ encinfo = (MimeInfo *) g_node_nth_child(mimeinfo->node, g_node_n_children(mimeinfo->node) - 1)->data;
cipher = sgpgme_data_from_mimeinfo(encinfo);
plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
diff --git a/src/plugins/python/composewindowtype.c b/src/plugins/python/composewindowtype.c
index c6edfb2b5..2b5001124 100644
--- a/src/plugins/python/composewindowtype.c
+++ b/src/plugins/python/composewindowtype.c
@@ -139,7 +139,7 @@ static int ComposeWindow_init(clawsmail_ComposeWindowObject *self, PyObject *arg
list = account_get_list();
for (cur = list ; cur != NULL ; cur = g_list_next(cur)) {
ac = (PrefsAccount *) cur->data;
- if (ac->protocol != A_NNTP) {
+ if (ac->protocol != A_NNTP && !ac->selectable_as_current_account) {
compose = compose_new_with_folderitem(ac, item, NULL);
did_find_compose = TRUE;
}
diff --git a/src/plugins/rssyl/rssyl.c b/src/plugins/rssyl/rssyl.c
index bb1ea4f9c..537f34010 100644
--- a/src/plugins/rssyl/rssyl.c
+++ b/src/plugins/rssyl/rssyl.c
@@ -444,9 +444,9 @@ static FolderItem *rssyl_item_new(Folder *folder)
ritem->fetch_comments_max_age = -1;
ritem->write_heading = TRUE;
ritem->fetching_comments = FALSE;
- ritem->silent_update = 0;
+ ritem->silent_update = 1;
ritem->last_update = 0;
- ritem->ignore_title_rename = FALSE;
+ ritem->ignore_title_rename = TRUE;
ritem->ssl_verify_peer = TRUE;
ritem->feedprop = NULL;
ritem->refresh_id = 0;
diff --git a/src/plugins/rssyl/rssyl_parse_feed.c b/src/plugins/rssyl/rssyl_parse_feed.c
index b7a49ddc7..8e3a58259 100644
--- a/src/plugins/rssyl/rssyl_parse_feed.c
+++ b/src/plugins/rssyl/rssyl_parse_feed.c
@@ -197,7 +197,7 @@ gboolean rssyl_parse_feed(RFolderItem *ritem, Feed *feed)
/* FIXME: store feed properties */
}
- folder_item_update_freeze();
+// folder_item_update_freeze();
/* Read contents of folder, so we can check for duplicates/updates */
rssyl_folder_read_existing(ritem);
@@ -220,7 +220,7 @@ gboolean rssyl_parse_feed(RFolderItem *ritem, Feed *feed)
}
folder_item_scan(&ritem->item);
- folder_item_update_thaw();
+// folder_item_update_thaw();
if( !ritem->fetching_comments )
log_print(LOG_PROTOCOL, RSSYL_LOG_UPDATED, ritem->url);
diff --git a/src/plugins/rssyl/rssyl_prefs.c b/src/plugins/rssyl/rssyl_prefs.c
index adf7e56b4..e25dba014 100644
--- a/src/plugins/rssyl/rssyl_prefs.c
+++ b/src/plugins/rssyl/rssyl_prefs.c
@@ -55,6 +55,8 @@ static PrefParam param[] = {
P_BOOL, NULL, NULL, NULL },
{ "refresh_enabled", "TRUE", &rssyl_prefs.refresh_enabled,
P_BOOL, NULL, NULL, NULL },
+ { "refresh_all_skips", "FALSE", &rssyl_prefs.refresh_all_skips,
+ P_BOOL, NULL, NULL, NULL },
{ "cookies_path", "", &rssyl_prefs.cookies_path,
P_STRING, NULL, NULL, NULL },
{ "ssl_verify_peer", "TRUE", &rssyl_prefs.ssl_verify_peer,
@@ -129,6 +131,7 @@ static void create_rssyl_prefs_page(PrefsPage *page,
GtkWidget *refresh, *refresh_enabled, *refresh_hbox;
GtkWidget *label;
GtkWidget *refresh_on_startup;
+ GtkWidget *refresh_all_skips;
GtkAdjustment *refresh_adj;
GtkWidget *cookies_path, *cookies_btn, *cookies_hbox;
GtkWidget *ssl_verify_peer;
@@ -163,6 +166,13 @@ static void create_rssyl_prefs_page(PrefsPage *page,
rssyl_prefs.refresh_on_startup);
gtk_box_pack_start(GTK_BOX(vbox1), refresh_on_startup, FALSE, FALSE, 0);
+ /* Whether refresh-all will skip feeds that are not programmed to be periodically refreshed or not */
+ refresh_all_skips = gtk_check_button_new_with_label(
+ _("Refresh all skips feeds programmed to be refreshed manually"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(refresh_all_skips),
+ rssyl_prefs.refresh_all_skips);
+ gtk_box_pack_start(GTK_BOX(vbox1), refresh_all_skips, FALSE, FALSE, 0);
+
vbox2 = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6);
/* Whether to verify SSL peer certificate */
@@ -207,6 +217,7 @@ static void create_rssyl_prefs_page(PrefsPage *page,
prefs_page->refresh_enabled = refresh_enabled;
prefs_page->refresh = refresh;
prefs_page->refresh_on_startup = refresh_on_startup;
+ prefs_page->refresh_all_skips = refresh_all_skips;
prefs_page->cookies_path = cookies_path;
prefs_page->ssl_verify_peer = ssl_verify_peer;
}
@@ -230,6 +241,8 @@ static void save_rssyl_prefs(PrefsPage *page)
GTK_SPIN_BUTTON(prefs_page->refresh));
rssyl_prefs.refresh_on_startup = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(prefs_page->refresh_on_startup));
+ rssyl_prefs.refresh_all_skips = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(prefs_page->refresh_all_skips));
g_free(rssyl_prefs.cookies_path);
rssyl_prefs.cookies_path = g_strdup(gtk_entry_get_text(
GTK_ENTRY(prefs_page->cookies_path)));
diff --git a/src/plugins/rssyl/rssyl_prefs.h b/src/plugins/rssyl/rssyl_prefs.h
index 5e746f038..4f12647cb 100644
--- a/src/plugins/rssyl/rssyl_prefs.h
+++ b/src/plugins/rssyl/rssyl_prefs.h
@@ -33,6 +33,7 @@ struct _RPrefs {
gboolean refresh_enabled;
gint refresh;
gboolean refresh_on_startup;
+ gboolean refresh_all_skips;
gchar *cookies_path;
gboolean ssl_verify_peer;
};
@@ -44,6 +45,7 @@ struct _RPrefsPage {
GtkWidget *refresh_enabled;
GtkWidget *refresh;
GtkWidget *refresh_on_startup;
+ GtkWidget *refresh_all_skips;
GtkWidget *cookies_path;
GtkWidget *ssl_verify_peer;
};
diff --git a/src/plugins/rssyl/rssyl_subscribe.c b/src/plugins/rssyl/rssyl_subscribe.c
index 807bafbea..50224eb8d 100644
--- a/src/plugins/rssyl/rssyl_subscribe.c
+++ b/src/plugins/rssyl/rssyl_subscribe.c
@@ -147,7 +147,7 @@ FolderItem *rssyl_subscribe(FolderItem *parent, const gchar *url,
}
/* TODO: handle cases where i reaches 20 */
- folder_item_update_freeze();
+// folder_item_update_freeze();
new_item = folder_create_folder(parent, tmpname2);
g_free(tmpname);
@@ -182,7 +182,7 @@ FolderItem *rssyl_subscribe(FolderItem *parent, const gchar *url,
if (edit_properties)
rssyl_gtk_prop(ritem);
- folder_item_update_thaw();
+// folder_item_update_thaw();
return new_item;
}
diff --git a/src/plugins/rssyl/rssyl_update_feed.c b/src/plugins/rssyl/rssyl_update_feed.c
index bd4ead851..c65d21ac9 100644
--- a/src/plugins/rssyl/rssyl_update_feed.c
+++ b/src/plugins/rssyl/rssyl_update_feed.c
@@ -317,8 +317,13 @@ static gboolean rssyl_update_recursively_func(GNode *node, gpointer data)
ritem = (RFolderItem *)item;
if( ritem->url != NULL ) {
- debug_print("RSSyl: Updating feed '%s'\n", item->name);
- rssyl_update_feed(ritem, 0);
+ if(rssyl_prefs_get()->refresh_all_skips &&
+ (ritem->default_refresh_interval == FALSE) && (ritem->refresh_interval == 0)) {
+ debug_print("RSSyl: Skipping feed '%s'\n", item->name);
+ } else {
+ debug_print("RSSyl: Updating feed '%s'\n", item->name);
+ rssyl_update_feed(ritem, 0);
+ }
} else
debug_print("RSSyl: Updating in folder '%s'\n", item->name);
diff --git a/src/plugins/vcalendar/vcal_meeting_gtk.c b/src/plugins/vcalendar/vcal_meeting_gtk.c
index af39bf0cc..0d758b290 100644
--- a/src/plugins/vcalendar/vcal_meeting_gtk.c
+++ b/src/plugins/vcalendar/vcal_meeting_gtk.c
@@ -1561,6 +1561,9 @@ static VCalMeeting *vcal_meeting_create_real(VCalEvent *event, gboolean visible)
for (i = 0; accounts != NULL; accounts = accounts->next) {
PrefsAccount *ac = (PrefsAccount *)accounts->data;
+ if (!ac->selectable_as_current_account) {
+ continue;
+ }
if (ac->protocol == A_NNTP) {
continue;
}
diff --git a/src/prefs_account.c b/src/prefs_account.c
index 7a9de7275..df7176242 100644
--- a/src/prefs_account.c
+++ b/src/prefs_account.c
@@ -103,6 +103,7 @@ typedef struct BasicPage
GtkWidget *acname_entry;
GtkWidget *default_checkbtn;
+ GtkWidget *selectableascurrentaccount_checkbtn;
GtkWidget *name_entry;
GtkWidget *addr_entry;
@@ -463,6 +464,10 @@ static PrefParam basic_param[] = {
&basic_page.default_checkbtn,
prefs_set_data_from_toggle, prefs_set_toggle},
+ {"selectable_as_current_account", "TRUE", &tmp_ac_prefs.selectable_as_current_account, P_BOOL,
+ &basic_page.selectableascurrentaccount_checkbtn,
+ prefs_set_data_from_toggle, prefs_set_toggle},
+
{"name", NULL, &tmp_ac_prefs.name, P_STRING,
&basic_page.name_entry, prefs_set_data_from_entry, prefs_set_entry},
@@ -1154,6 +1159,7 @@ static void basic_create_widget_func(PrefsPage * _page,
GtkWidget *name_entry;
GtkWidget *addr_entry;
GtkWidget *org_entry;
+ GtkWidget *selectableascurrentaccount_checkbtn;
GtkWidget *serv_frame;
GtkWidget *vbox2;
@@ -1216,6 +1222,10 @@ static void basic_create_widget_func(PrefsPage * _page,
gtk_box_pack_start (GTK_BOX (vbox1), default_checkbtn, FALSE, FALSE, 0);
#endif
+ PACK_CHECK_BUTTON
+ (vbox1, selectableascurrentaccount_checkbtn,
+ _("Selectable as current account"));
+
PACK_FRAME (vbox1, frame1, _("Personal information"));
table1 = gtk_grid_new();
@@ -1457,6 +1467,7 @@ static void basic_create_widget_func(PrefsPage * _page,
page->acname_entry = acname_entry;
page->default_checkbtn = default_checkbtn;
+ page->selectableascurrentaccount_checkbtn = selectableascurrentaccount_checkbtn;
page->name_entry = name_entry;
page->addr_entry = addr_entry;
@@ -4467,6 +4478,7 @@ static void create_privacy_prefs(gpointer key, gpointer _value, gpointer user_da
void prefs_account_write_config_all(GList *account_list)
{
+ GSList *ac_label_list = NULL;
GList *cur;
gchar *rcpath;
PrefFile *pfile;
@@ -4482,6 +4494,12 @@ void prefs_account_write_config_all(GList *account_list)
GString *str;
tmp_ac_prefs = *(PrefsAccount *)cur->data;
+ gchar *buf = g_strdup_printf("%d", tmp_ac_prefs.account_id);
+ if (ac_label_list && g_slist_find_custom(ac_label_list, buf, (GCompareFunc)strcmp)) {
+ g_warning("duplicate account found (%s)", buf);
+ }
+ ac_label_list = g_slist_append(ac_label_list,
+ g_strdup(buf));
if (fprintf(pfile->fp, "[Account: %d]\n",
tmp_ac_prefs.account_id) <= 0)
return;
@@ -4514,6 +4532,9 @@ void prefs_account_write_config_all(GList *account_list)
}
}
+ g_slist_foreach(ac_label_list, (GFunc)g_free, NULL);
+ g_slist_free(ac_label_list);
+
if (prefs_file_close(pfile) < 0)
g_warning("failed to write configuration to file");
diff --git a/src/prefs_account.h b/src/prefs_account.h
index cad95a882..ce095ba99 100644
--- a/src/prefs_account.h
+++ b/src/prefs_account.h
@@ -60,6 +60,7 @@ struct _Folder;
struct _PrefsAccount
{
gchar *account_name;
+ gboolean selectable_as_current_account;
/* Personal info */
gchar *name;
diff --git a/src/prefs_common.c b/src/prefs_common.c
index 6187168e8..df26e0799 100644
--- a/src/prefs_common.c
+++ b/src/prefs_common.c
@@ -107,6 +107,7 @@ static PrefParam param_os_specific[] = {
&prefs_common.normalfont, P_STRING, NULL, NULL, NULL},
{"bold_font_gtk2", "Sans 9 Bold",
&prefs_common.boldfont, P_STRING, NULL, NULL, NULL},
+
/* Message */
{"attach_save_directory", NULL,
&prefs_common.attach_save_dir, P_STRING, NULL, NULL, NULL},
@@ -712,6 +713,7 @@ static PrefParam param[] = {
NULL, NULL, NULL},
{"compose_y", "0", &prefs_common.compose_y, P_INT,
NULL, NULL, NULL},
+
/* Message */
{"enable_color", "TRUE", &prefs_common.enable_color, P_BOOL,
NULL, NULL, NULL},
@@ -802,6 +804,9 @@ static PrefParam param[] = {
{"attach_load_directory", NULL,
&SPECIFIC_PREFS.attach_load_dir, P_STRING, NULL, NULL, NULL},
+ {"decrypt_messages", "TRUE", &prefs_common.decrypt_messages, P_BOOL,
+ NULL, NULL, NULL},
+
/* MIME viewer */
{"mime_textviewer", NULL,
&SPECIFIC_PREFS.mime_textviewer, P_STRING, NULL, NULL, NULL},
@@ -810,6 +815,10 @@ static PrefParam param[] = {
{"show_inline_attachments", "TRUE",
&prefs_common.show_inline_attachments, P_BOOL, NULL, NULL, NULL},
+ {"save_attachment_handle_bom", "0",
+ &prefs_common.save_attachment_handle_bom, P_INT,
+ NULL, NULL, NULL},
+
/* Interface */
#ifndef GENERIC_UMPC
{"layout_mode", "0", &prefs_common.layout_mode, P_INT,
@@ -865,6 +874,9 @@ static PrefParam param[] = {
{"summary_select_prio10", "0", &prefs_common.summary_select_prio[9], P_ENUM,
NULL, NULL, NULL},
+ {"mark_as_read_on_never", "FALSE",
+ &prefs_common.mark_as_read_on_never,
+ P_BOOL, NULL, NULL, NULL},
{"mark_as_read_on_new_window", "FALSE",
&prefs_common.mark_as_read_on_new_window,
P_BOOL, NULL, NULL, NULL},
@@ -920,6 +932,8 @@ static PrefParam param[] = {
#ifndef G_OS_WIN32
{"uri_open_command", DEFAULT_BROWSER_CMD,
&SPECIFIC_PREFS.uri_cmd, P_STRING, NULL, NULL, NULL},
+ {"uri_open_command_alt", DEFAULT_BROWSER_CMD,
+ &SPECIFIC_PREFS.uri_alt_cmd, P_STRING, NULL, NULL, NULL},
#else
{"gtk_theme", DEFAULT_W32_GTK_THEME,
&SPECIFIC_PREFS.gtk_theme, P_STRING, NULL, NULL, NULL},
@@ -1716,6 +1730,15 @@ const gchar *prefs_common_get_uri_cmd(void)
#endif
}
+const gchar *prefs_common_get_uri_alt_cmd(void)
+{
+#ifdef G_OS_WIN32
+ return NULL;
+#else
+ return prefs_common.uri_alt_cmd;
+#endif
+}
+
const gchar *prefs_common_get_ext_editor_cmd(void)
{
return prefs_common.ext_editor_cmd;
diff --git a/src/prefs_common.h b/src/prefs_common.h
index 42f5d38f1..c757165d6 100644
--- a/src/prefs_common.h
+++ b/src/prefs_common.h
@@ -144,6 +144,13 @@ typedef enum
COL_LAST_COLOR_INDEX
} ColorIndex;
+typedef enum
+{
+ HANDLE_BOM_WRITE = 0,
+ HANDLE_BOM_DO_NOT_WRITE,
+ HANDLE_BOM_ASK_USER
+} HandleBom;
+
struct _PrefsCommon
{
gint config_version;
@@ -372,6 +379,8 @@ struct _PrefsCommon
gboolean attach_desc;
+ gboolean decrypt_messages;
+
/* MIME viewer */
gchar *mime_textviewer;
gchar *mime_open_cmd;
@@ -381,6 +390,8 @@ struct _PrefsCommon
GList *mime_open_cmd_history;
gboolean show_inline_attachments;
+ HandleBom save_attachment_handle_bom;
+
/* Addressbook */
gboolean addressbook_use_editaddress_dialog;
gint addressbook_hpaned_pos;
@@ -400,6 +411,7 @@ struct _PrefsCommon
gboolean open_selected_on_directional;
gboolean always_show_msg;
+ gboolean mark_as_read_on_never;
gboolean mark_as_read_on_new_window;
gboolean mark_as_read_delay;
gboolean immediate_exec;
@@ -428,6 +440,7 @@ struct _PrefsCommon
/* Other */
#ifndef G_OS_WIN32
gchar *uri_cmd;
+ gchar *uri_alt_cmd;
#else
gchar *gtk_theme;
#endif
@@ -606,6 +619,7 @@ gchar *pref_get_pref_from_textview(GtkTextView *textview);
gchar *pref_get_pref_from_entry(GtkEntry *entry);
const gchar *prefs_common_translated_header_name(const gchar *header_name);
const gchar *prefs_common_get_uri_cmd(void);
+const gchar *prefs_common_get_uri_alt_cmd(void);
const gchar *prefs_common_get_ext_editor_cmd(void);
#define OPEN_SELECTED(when) (prefs_common.always_show_msg || prefs_common.when)
diff --git a/src/prefs_ext_prog.c b/src/prefs_ext_prog.c
index 62dbaeb68..b89a75b55 100644
--- a/src/prefs_ext_prog.c
+++ b/src/prefs_ext_prog.c
@@ -52,6 +52,9 @@ typedef struct _ExtProgPage
GtkWidget *uri_label;
GtkWidget *uri_combo;
GtkWidget *uri_entry;
+ GtkWidget *uri_alt_label;
+ GtkWidget *uri_alt_combo;
+ GtkWidget *uri_alt_entry;
#endif /* !G_OS_WIN32 */
GtkWidget *exteditor_label;
@@ -76,6 +79,9 @@ static void prefs_ext_prog_create_widget(PrefsPage *_page, GtkWindow *window,
GtkWidget *uri_label;
GtkWidget *uri_combo;
GtkWidget *uri_entry;
+ GtkWidget *uri_alt_label;
+ GtkWidget *uri_alt_combo;
+ GtkWidget *uri_alt_entry;
#endif /* !G_OS_WIN32 */
GtkWidget *exteditor_label;
GtkWidget *exteditor_combo;
@@ -167,6 +173,31 @@ static void prefs_ext_prog_create_widget(PrefsPage *_page, GtkWindow *window,
uri_entry = gtk_bin_get_child(GTK_BIN((uri_combo)));
gtk_entry_set_text(GTK_ENTRY(uri_entry), prefs_common.uri_cmd ? prefs_common.uri_cmd : "");
+
+ uri_alt_label = gtk_label_new (_("Alternate web browser"));
+ gtk_widget_show(uri_alt_label);
+ i++;
+ gtk_label_set_justify(GTK_LABEL (uri_alt_label), GTK_JUSTIFY_RIGHT);
+ gtk_label_set_xalign(GTK_LABEL (uri_alt_label), 1.0);
+ gtk_grid_attach(GTK_GRID(table2), uri_alt_label, 0, i, 1, 1);
+
+ uri_alt_combo = combobox_text_new(TRUE,
+ DEFAULT_BROWSER_CMD,
+ "galeon --new-tab '%s'",
+ "galeon '%s'",
+ "mozilla -remote 'openurl(%s,new-window)'",
+ "netscape -remote 'openURL(%s, new-window)'",
+ "netscape '%s'",
+ "gnome-moz-remote --newwin '%s'",
+ "kfmclient openURL '%s'",
+ "opera -newwindow '%s'",
+ "rxvt -e w3m '%s'",
+ "rxvt -e lynx '%s'",
+ NULL);
+ gtk_grid_attach(GTK_GRID(table2), uri_alt_combo, 1, i, 1, 1);
+
+ uri_alt_entry = gtk_bin_get_child(GTK_BIN((uri_alt_combo)));
+ gtk_entry_set_text(GTK_ENTRY(uri_alt_entry), prefs_common.uri_alt_cmd ? prefs_common.uri_alt_cmd : "");
#endif /* !G_OS_WIN32 */
exteditor_label = gtk_label_new (_("Text editor"));
@@ -234,6 +265,7 @@ static void prefs_ext_prog_create_widget(PrefsPage *_page, GtkWindow *window,
prefs_ext_prog->window = GTK_WIDGET(window);
#ifndef G_OS_WIN32
prefs_ext_prog->uri_entry = uri_entry;
+ prefs_ext_prog->uri_alt_entry = uri_alt_entry;
#endif
prefs_ext_prog->exteditor_entry = exteditor_entry;
prefs_ext_prog->astextviewer_entry = astextviewer_entry;
@@ -248,6 +280,8 @@ static void prefs_ext_prog_save(PrefsPage *_page)
#ifndef G_OS_WIN32
prefs_common.uri_cmd = gtk_editable_get_chars
(GTK_EDITABLE(ext_prog->uri_entry), 0, -1);
+ prefs_common.uri_alt_cmd = gtk_editable_get_chars
+ (GTK_EDITABLE(ext_prog->uri_alt_entry), 0, -1);
#endif /* !G_OS_WIN32 */
prefs_common.ext_editor_cmd = gtk_editable_get_chars
(GTK_EDITABLE(ext_prog->exteditor_entry), 0, -1);
diff --git a/src/prefs_folder_item.c b/src/prefs_folder_item.c
index c79675f65..4d2c4448a 100644
--- a/src/prefs_folder_item.c
+++ b/src/prefs_folder_item.c
@@ -61,6 +61,7 @@
typedef struct _FolderItemGeneralPage FolderItemGeneralPage;
typedef struct _FolderItemComposePage FolderItemComposePage;
+typedef struct _FolderItemSendPage FolderItemSendPage;
typedef struct _FolderItemTemplatesPage FolderItemTemplatesPage;
static gboolean can_save = TRUE;
@@ -114,8 +115,6 @@ struct _FolderItemComposePage
GtkWidget *window;
GtkWidget *table;
GtkWidget *no_save_warning;
- GtkWidget *checkbtn_request_return_receipt;
- GtkWidget *checkbtn_save_copy_to_folder;
GtkWidget *checkbtn_default_to;
GtkWidget *entry_default_to;
GtkWidget *checkbtn_default_reply_to;
@@ -138,8 +137,6 @@ struct _FolderItemComposePage
GtkWidget *always_encrypt;
/* apply to sub folders */
- GtkWidget *request_return_receipt_rec_checkbtn;
- GtkWidget *save_copy_to_folder_rec_checkbtn;
GtkWidget *default_to_rec_checkbtn;
GtkWidget *default_reply_to_rec_checkbtn;
GtkWidget *default_cc_rec_checkbtn;
@@ -154,6 +151,26 @@ struct _FolderItemComposePage
GtkWidget *always_encrypt_rec_checkbtn;
};
+struct _FolderItemSendPage
+{
+ PrefsPage page;
+
+ FolderItem *item;
+
+ GtkWidget *window;
+ GtkWidget *table;
+ GtkWidget *no_save_warning;
+
+ GtkWidget *checkbtn_request_return_receipt;
+ GtkWidget *checkbtn_request_dsn;
+ GtkWidget *checkbtn_save_copy_to_folder;
+
+ /* apply to sub folders */
+ GtkWidget *request_return_receipt_rec_checkbtn;
+ GtkWidget *request_dsn_rec_checkbtn;
+ GtkWidget *save_copy_to_folder_rec_checkbtn;
+};
+
struct _FolderItemTemplatesPage
{
PrefsPage page;
@@ -184,10 +201,12 @@ struct _FolderItemTemplatesPage
static void general_save_folder_prefs(FolderItem *folder, FolderItemGeneralPage *page);
static void compose_save_folder_prefs(FolderItem *folder, FolderItemComposePage *page);
+static void send_save_folder_prefs(FolderItem *folder, FolderItemSendPage *page);
static void templates_save_folder_prefs(FolderItem *folder, FolderItemTemplatesPage *page);
static gboolean general_save_recurse_func(GNode *node, gpointer data);
static gboolean compose_save_recurse_func(GNode *node, gpointer data);
+static gboolean send_save_recurse_func(GNode *node, gpointer data);
static gboolean templates_save_recurse_func(GNode *node, gpointer data);
static gint prefs_folder_item_chmod_mode (gchar *folder_chmod);
@@ -221,6 +240,7 @@ static GtkWidget *prefs_folder_no_save_warning_create_widget() {
return hbox;
}
+/* "General" page functions */
static void prefs_folder_item_general_create_widget_func(PrefsPage * page_,
GtkWindow * window,
gpointer data)
@@ -846,6 +866,7 @@ static RecvProtocol item_protocol(FolderItem *item)
return item->folder->account->protocol;
}
+/* "Compose" page functions */
static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
GtkWindow * window,
gpointer data)
@@ -861,8 +882,6 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
GtkWidget *label;
GtkWidget *no_save_warning = NULL;
- GtkWidget *checkbtn_request_return_receipt = NULL;
- GtkWidget *checkbtn_save_copy_to_folder = NULL;
GtkWidget *checkbtn_default_to = NULL;
GtkWidget *entry_default_to = NULL;
GtkWidget *checkbtn_default_reply_to = NULL;
@@ -890,8 +909,6 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
GtkListStore *always_sign_menu;
GtkWidget *always_encrypt;
GtkListStore *always_encrypt_menu;
- GtkWidget *request_return_receipt_rec_checkbtn = NULL;
- GtkWidget *save_copy_to_folder_rec_checkbtn = NULL;
GtkWidget *default_to_rec_checkbtn = NULL;
GtkWidget *default_reply_to_rec_checkbtn = NULL;
GtkWidget *default_cc_rec_checkbtn = NULL;
@@ -932,28 +949,6 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
rowcount++;
if (item_protocol(item) != A_NNTP) {
- /* Request Return Receipt */
- checkbtn_request_return_receipt = gtk_check_button_new_with_label
- (_("Request Return Receipt"));
- gtk_grid_attach(GTK_GRID(table), checkbtn_request_return_receipt, 0, rowcount, 1, 1);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_request_return_receipt),
- item->ret_rcpt ? TRUE : FALSE);
-
- request_return_receipt_rec_checkbtn = gtk_check_button_new();
- gtk_grid_attach(GTK_GRID(table), request_return_receipt_rec_checkbtn, 2, rowcount, 1, 1);
- rowcount++;
-
- /* Save Copy to Folder */
- checkbtn_save_copy_to_folder = gtk_check_button_new_with_label
- (_("Save copy of outgoing messages to this folder instead of Sent"));
- gtk_grid_attach(GTK_GRID(table), checkbtn_save_copy_to_folder, 0, rowcount, 2, 1);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_save_copy_to_folder),
- item->prefs->save_copy_to_folder ? TRUE : FALSE);
-
- save_copy_to_folder_rec_checkbtn = gtk_check_button_new();
- gtk_grid_attach(GTK_GRID(table), save_copy_to_folder_rec_checkbtn, 2, rowcount, 1, 1);
- rowcount++;
-
/* Default To */
tr = g_strdup(C_("folder properties: %s stands for a header name",
"Default %s"));
@@ -1093,6 +1088,9 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
account_list = account_get_list();
for (cur_ac = account_list; cur_ac != NULL; cur_ac = cur_ac->next) {
ac_prefs = (PrefsAccount *)cur_ac->data;
+ if (!ac_prefs->selectable_as_current_account) {
+ continue;
+ }
if (item->folder->account &&
( (item_protocol(item) == A_NNTP && ac_prefs->protocol != A_NNTP)
||(item_protocol(item) != A_NNTP && ac_prefs->protocol == A_NNTP)))
@@ -1252,13 +1250,12 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
rowcount++;
+ /* Finished ! */
gtk_widget_show_all(table);
page->window = GTK_WIDGET(window);
page->table = table;
page->no_save_warning = no_save_warning;
- page->checkbtn_request_return_receipt = checkbtn_request_return_receipt;
- page->checkbtn_save_copy_to_folder = checkbtn_save_copy_to_folder;
page->checkbtn_default_to = checkbtn_default_to;
page->entry_default_to = entry_default_to;
page->checkbtn_default_reply_to = checkbtn_default_reply_to;
@@ -1280,8 +1277,6 @@ static void prefs_folder_item_compose_create_widget_func(PrefsPage * page_,
page->always_sign = always_sign;
page->always_encrypt = always_encrypt;
- page->request_return_receipt_rec_checkbtn = request_return_receipt_rec_checkbtn;
- page->save_copy_to_folder_rec_checkbtn = save_copy_to_folder_rec_checkbtn;
page->default_to_rec_checkbtn = default_to_rec_checkbtn;
page->default_reply_to_rec_checkbtn = default_reply_to_rec_checkbtn;
page->default_cc_rec_checkbtn = default_cc_rec_checkbtn;
@@ -1334,18 +1329,6 @@ static void compose_save_folder_prefs(FolderItem *folder, FolderItemComposePage
cm_return_if_fail(prefs != NULL);
if (item_protocol(folder) != A_NNTP) {
- if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_return_receipt_rec_checkbtn))) {
- prefs->request_return_receipt =
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_request_return_receipt));
- /* MIGRATION */
- folder->ret_rcpt = prefs->request_return_receipt;
- }
-
- if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->save_copy_to_folder_rec_checkbtn))) {
- prefs->save_copy_to_folder =
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_save_copy_to_folder));
- }
-
if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_to_rec_checkbtn))) {
prefs->enable_default_to =
@@ -1386,8 +1369,6 @@ static void compose_save_folder_prefs(FolderItem *folder, FolderItemComposePage
}
} else {
- prefs->request_return_receipt = FALSE;
- prefs->save_copy_to_folder = FALSE;
prefs->enable_default_to = FALSE;
prefs->enable_default_reply_to = FALSE;
prefs->enable_default_cc = FALSE;
@@ -1442,13 +1423,12 @@ static gboolean compose_save_recurse_func(GNode *node, gpointer data)
compose_save_folder_prefs(item, page);
+
/* optimise by not continuing if none of the 'apply to sub folders'
check boxes are selected - and optimise the checking by only doing
it once */
if ((node == page->item->node) && item_protocol(item) != A_NNTP &&
- !(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_return_receipt_rec_checkbtn)) ||
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->save_copy_to_folder_rec_checkbtn)) ||
- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_to_rec_checkbtn)) ||
+ !(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_to_rec_checkbtn)) ||
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_account_rec_checkbtn)) ||
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_cc_rec_checkbtn)) ||
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->default_bcc_rec_checkbtn)) ||
@@ -1485,6 +1465,195 @@ static void prefs_folder_item_compose_save_func(PrefsPage *page_)
}
+/* "Send" page functions */
+static void prefs_folder_item_send_create_widget_func(PrefsPage * page_,
+ GtkWindow * window,
+ gpointer data)
+{
+ FolderItemSendPage *page = (FolderItemSendPage *) page_;
+ FolderItem *item = (FolderItem *) data;
+ guint rowcount;
+
+ GtkWidget *table;
+ GtkWidget *label;
+
+ GtkWidget *no_save_warning = NULL;
+ GtkWidget *checkbtn_request_return_receipt = NULL;
+ GtkWidget *checkbtn_request_dsn = NULL;
+ GtkWidget *checkbtn_save_copy_to_folder = NULL;
+
+ GtkWidget *request_return_receipt_rec_checkbtn = NULL;
+ GtkWidget *request_dsn_rec_checkbtn = NULL;
+ GtkWidget *save_copy_to_folder_rec_checkbtn = NULL;
+
+ page->item = item;
+
+ /* Table */
+ table = gtk_table_new(3, 3, FALSE);
+ gtk_container_set_border_width (GTK_CONTAINER (table), VBOX_BORDER);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 4);
+ rowcount = 0;
+
+ if (!can_save) {
+ no_save_warning = prefs_folder_no_save_warning_create_widget();
+ gtk_table_attach(GTK_TABLE(table), no_save_warning, 0, 3,
+ rowcount, rowcount + 1, GTK_FILL, 0, 0, 0);
+ rowcount++;
+ }
+
+ /* Apply to subfolders */
+ label = gtk_label_new(_("Apply to\nsubfolders"));
+ gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);
+ gtk_table_attach(GTK_TABLE(table), label, 2, 3,
+ rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+ rowcount++;
+ /* NOTE: the test for NNTP is not strictly needed, because register_send_page()
+ * will test it also and will not create the page in case of A_NNTP.
+ * But it might help if more widgets are created in the future */
+ if (item_protocol(item) != A_NNTP) {
+ /* Request DSN */
+ checkbtn_request_dsn = gtk_check_button_new_with_label
+ (_("Always Request Notification of successful Delivery"));
+ gtk_table_attach(GTK_TABLE(table), checkbtn_request_dsn,
+ 0, 2, rowcount, rowcount + 1, GTK_SHRINK | GTK_FILL,
+ GTK_FILL, 0, 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_request_dsn),
+ item->prefs->request_dsn ? TRUE : FALSE);
+
+ request_dsn_rec_checkbtn = gtk_check_button_new();
+ gtk_table_attach(GTK_TABLE(table), request_dsn_rec_checkbtn, 2, 3,
+ rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+ rowcount++;
+
+ /* Request Return Receipt */
+ checkbtn_request_return_receipt = gtk_check_button_new_with_label
+ (_("Always Request Return Receipt"));
+ gtk_table_attach(GTK_TABLE(table), checkbtn_request_return_receipt,
+ 0, 2, rowcount, rowcount + 1, GTK_SHRINK | GTK_FILL,
+ GTK_FILL, 0, 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_request_return_receipt),
+ item->ret_rcpt ? TRUE : FALSE);
+
+ request_return_receipt_rec_checkbtn = gtk_check_button_new();
+ gtk_table_attach(GTK_TABLE(table), request_return_receipt_rec_checkbtn, 2, 3,
+ rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+ rowcount++;
+
+ /* Save Copy to Folder */
+ checkbtn_save_copy_to_folder = gtk_check_button_new_with_label
+ (_("Save copy of outgoing messages to this folder instead of Sent"));
+ gtk_table_attach(GTK_TABLE(table), checkbtn_save_copy_to_folder, 0, 2,
+ rowcount, rowcount + 1, GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_save_copy_to_folder),
+ item->prefs->save_copy_to_folder ? TRUE : FALSE);
+
+ save_copy_to_folder_rec_checkbtn = gtk_check_button_new();
+ gtk_table_attach(GTK_TABLE(table), save_copy_to_folder_rec_checkbtn, 2, 3,
+ rowcount, rowcount + 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+ rowcount++;
+ }
+ /* Finished ! */
+ gtk_widget_show_all(table);
+
+ page->window = GTK_WIDGET(window);
+ page->table = table;
+ page->no_save_warning = no_save_warning;
+
+ page->request_return_receipt_rec_checkbtn = request_return_receipt_rec_checkbtn;
+ page->request_dsn_rec_checkbtn = request_dsn_rec_checkbtn;
+ page->checkbtn_save_copy_to_folder = checkbtn_save_copy_to_folder;
+
+ page->checkbtn_request_return_receipt = checkbtn_request_return_receipt;
+ page->checkbtn_request_dsn = checkbtn_request_dsn;
+ page->save_copy_to_folder_rec_checkbtn = save_copy_to_folder_rec_checkbtn;
+
+ page->page.widget = table;
+}
+
+static void prefs_folder_item_send_destroy_widget_func(PrefsPage *page_)
+{
+/* FolderItemSendPage *page = (FolderItemSendPage *) page_; */
+}
+
+static void send_save_folder_prefs(FolderItem *folder, FolderItemSendPage *page)
+{
+ FolderItemPrefs *prefs = folder->prefs;
+
+ gboolean all = FALSE;
+
+ if (folder->path == NULL)
+ return;
+
+ if (page->item == folder)
+ all = TRUE;
+
+ cm_return_if_fail(prefs != NULL);
+
+ if (item_protocol(folder) != A_NNTP) {
+ if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_dsn_rec_checkbtn))) {
+ prefs->request_dsn =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_request_dsn));
+ }
+
+ if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_return_receipt_rec_checkbtn))) {
+ prefs->request_return_receipt =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_request_return_receipt));
+ /* MIGRATION */
+ folder->ret_rcpt = prefs->request_return_receipt;
+ }
+
+ if (all || gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->save_copy_to_folder_rec_checkbtn))) {
+ prefs->save_copy_to_folder =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->checkbtn_save_copy_to_folder));
+ }
+
+ }
+ else
+ {
+ prefs->request_dsn = FALSE;
+ prefs->request_return_receipt = FALSE;
+ prefs->save_copy_to_folder = FALSE;
+ }
+}
+
+static gboolean send_save_recurse_func(GNode *node, gpointer data)
+{
+ FolderItem *item = (FolderItem *) node->data;
+ FolderItemSendPage *page = (FolderItemSendPage *) data;
+
+ cm_return_val_if_fail(item != NULL, TRUE);
+ cm_return_val_if_fail(page != NULL, TRUE);
+
+ send_save_folder_prefs(item, page);
+
+ /* optimise by not continuing if none of the 'apply to sub folders'
+ check boxes are selected - and optimise the checking by only doing
+ it once */
+ if ((node == page->item->node) && item_protocol(item) != A_NNTP &&
+ !(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_dsn_rec_checkbtn)) ||
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->request_return_receipt_rec_checkbtn)) ||
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(page->save_copy_to_folder_rec_checkbtn))
+ )) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void prefs_folder_item_send_save_func(PrefsPage *page_)
+{
+ FolderItemSendPage *page = (FolderItemSendPage *) page_;
+
+ g_node_traverse(page->item->node, G_PRE_ORDER, G_TRAVERSE_ALL,
+ -1, send_save_recurse_func, page);
+
+}
+
+
+/* "Templates" page functions */
static void prefs_folder_item_templates_create_widget_func(PrefsPage * page_,
GtkWindow * window,
gpointer data)
@@ -1755,6 +1924,7 @@ static void prefs_folder_item_templates_save_func(PrefsPage *page_)
}
+/* other functions */
static gint prefs_folder_item_chmod_mode(gchar *folder_chmod)
{
gint newmode = 0;
@@ -1921,6 +2091,22 @@ static void register_compose_page(void)
prefs_folder_item_register_page((PrefsPage *) &folder_item_compose_page, NULL);
}
+static void register_send_page(void)
+{
+ static gchar *pfi_send_path[2];
+ static FolderItemSendPage folder_item_send_page;
+
+ pfi_send_path[0] = _("Send");
+ pfi_send_path[1] = NULL;
+
+ folder_item_send_page.page.path = pfi_send_path;
+ folder_item_send_page.page.create_widget = prefs_folder_item_send_create_widget_func;
+ folder_item_send_page.page.destroy_widget = prefs_folder_item_send_destroy_widget_func;
+ folder_item_send_page.page.save_page = prefs_folder_item_send_save_func;
+
+ prefs_folder_item_register_page((PrefsPage *) &folder_item_send_page, NULL);
+}
+
static void register_templates_page(void)
{
static gchar *pfi_templates_path[2];
@@ -1956,6 +2142,13 @@ void prefs_folder_item_open(FolderItem *item)
if (prefs_pages == NULL) {
register_general_page();
+ /* create a "Send" page only for non-NNTP folders.
+ * The page would currently be empty anyway.
+ * Don't forget to remove the test if more widgets
+ * are added in the future that apply to NTTP as well. */
+ if (item_protocol(item) != A_NNTP) {
+ register_send_page();
+ }
register_compose_page();
register_templates_page();
}
diff --git a/src/prefs_matcher.c b/src/prefs_matcher.c
index 68ae94310..7718d3a48 100644
--- a/src/prefs_matcher.c
+++ b/src/prefs_matcher.c
@@ -36,7 +36,6 @@
#include "prefs_gtk.h"
#include "prefs_matcher.h"
#include "prefs_common.h"
-#include "procheader.h"
#include "mainwindow.h"
#include "foldersel.h"
#include "manage_window.h"
@@ -97,9 +96,10 @@ static struct Matcher {
GtkWidget *case_checkbtn;
GtkWidget *regexp_checkbtn;
GtkWidget *color_optmenu;
- GtkWidget *calendar;
- GtkWidget *time_label;
- GtkWidget *time_entry;
+ GtkWidget *date_btn;
+ GtkWidget *hour_entry;
+ GtkWidget *min_entry;
+ GtkWidget *sec_entry;
GtkWidget *test_btn;
GtkWidget *addressbook_select_btn;
@@ -484,6 +484,106 @@ static void prefs_matcher_size_allocate_cb(GtkWidget *widget,
&prefs_common.matcherwin_width, &prefs_common.matcherwin_height);
}
+static void set_date_btn_to(struct tm *tm)
+{
+ GtkLabel *lbl;
+ gchar buf[11];
+
+ lbl = GTK_LABEL(gtk_bin_get_child(GTK_BIN(matcher.date_btn)));
+ snprintf(buf, 11, "%04d-%02d-%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
+
+ gtk_label_set_text(lbl, buf);
+}
+
+static void on_date_selected(GtkCalendar *cal)
+{
+ struct tm tm;
+ time_t ts;
+
+ ts = time(NULL);
+ if (!localtime_r(&ts, &tm))
+ goto done;
+
+ gtk_calendar_get_date(cal, &tm.tm_year, &tm.tm_mon, &tm.tm_mday);
+ tm.tm_year -= 1900;
+ set_date_btn_to(&tm);
+
+done:
+ gtk_widget_destroy(gtk_widget_get_toplevel(GTK_WIDGET(cal)));
+}
+
+static gboolean destroy_on_esc(GtkWidget *w, GdkEventKey *event)
+{
+ if (event->keyval == GDK_KEY_Escape)
+ {
+ gtk_widget_destroy(w);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void date_btn_clicked(GtkWidget *btn)
+{
+ GtkWidget *window;
+ GtkWidget *frame;
+ GtkWidget *cal;
+ GtkCalendarDisplayOptions display_options;
+ const gchar *date;
+ gint year, month, day;
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), TRUE);
+ gtk_window_set_skip_pager_hint(GTK_WINDOW(window), TRUE);
+ gtk_window_set_modal(GTK_WINDOW(window), TRUE);
+ g_signal_connect(G_OBJECT(window), "focus-out-event",
+ G_CALLBACK(gtk_widget_destroy), NULL);
+ g_signal_connect(G_OBJECT(window), "key-press-event",
+ G_CALLBACK(destroy_on_esc), NULL);
+
+ frame = gtk_frame_new(NULL);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(window), frame);
+
+ cal = gtk_calendar_new();
+ display_options = GTK_CALENDAR_SHOW_HEADING |
+ GTK_CALENDAR_SHOW_WEEK_NUMBERS |
+ GTK_CALENDAR_SHOW_DAY_NAMES;
+ gtk_calendar_set_display_options(GTK_CALENDAR(cal), display_options);
+
+ date = gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(matcher.date_btn))));
+ if (sscanf(date, "%04d-%02d-%02d", &year, &month, &day) == 3)
+ {
+ gtk_calendar_select_month(GTK_CALENDAR(cal), month - 1, year);
+ gtk_calendar_select_day(GTK_CALENDAR(cal), day);
+ }
+
+ gtk_container_add(GTK_CONTAINER(frame), cal);
+ g_signal_connect(G_OBJECT(cal), "day-selected-double-click",
+ G_CALLBACK (on_date_selected),
+ NULL);
+
+ /* move window so it looks like a popup */
+ {
+ GtkAllocation alloc;
+ gint wx, wy;
+ gint x, y;
+
+ gtk_window_get_position(GTK_WINDOW(gtk_widget_get_toplevel(btn)), &wx, &wy);
+ if (gtk_widget_translate_coordinates(btn,gtk_widget_get_toplevel(btn), 0, 0, &x, &y))
+ {
+ wx += x;
+ wy += y;
+ }
+ gtk_widget_get_allocation(btn, &alloc);
+ wy += alloc.height;
+ gtk_window_move(GTK_WINDOW(window), wx, wy);
+ }
+
+ gtk_widget_show_all(window);
+}
+
/*!
*\brief Create the matcher dialog
*/
@@ -548,11 +648,11 @@ static void prefs_matcher_create(void)
GtkWidget *test_btn;
GtkWidget *addressbook_select_btn;
GtkWidget *color_optmenu;
- GtkWidget *calendar;
- GtkWidget *time_label;
- GtkWidget *time_entry;
GtkWidget *date_hbox;
- GtkWidget *date_vbox;
+ GtkWidget *date_btn;
+ GtkWidget *hour_entry;
+ GtkWidget *min_entry;
+ GtkWidget *sec_entry;
static GdkGeometry geometry;
GtkSizeGroup *size_group;
@@ -755,21 +855,26 @@ static void prefs_matcher_create(void)
gtk_widget_set_halign(hbox, GTK_ALIGN_FILL);
/* Date widgets */
- date_vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, VSPACING_NARROW);
- calendar = gtk_calendar_new();
- gtk_box_pack_start(GTK_BOX(hbox), calendar, TRUE, TRUE, 0);
- gtk_box_pack_start(GTK_BOX(lower_hbox), date_vbox, FALSE, FALSE, 0);
date_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, HSPACING_NARROW);
- gtk_box_pack_start(GTK_BOX(date_vbox), date_hbox, FALSE, FALSE, 0);
-
- time_entry = gtkut_time_select_combo_new();
- gtk_box_pack_start(GTK_BOX(date_hbox), time_entry, FALSE, FALSE, 0);
- time_label = gtk_label_new(_("on:"));
- gtk_label_set_xalign(GTK_LABEL(time_label),0);
- gtk_label_set_yalign(GTK_LABEL(time_label),0.5);
- gtk_box_pack_start(GTK_BOX(date_hbox), time_label, FALSE, FALSE, 0);
-
+ gtk_box_pack_start(GTK_BOX(lower_hbox), date_hbox, FALSE, FALSE, 0);
+
+ date_btn = gtk_button_new_with_label("YYYY-MM-DD");
+ g_signal_connect(date_btn, "clicked", G_CALLBACK(date_btn_clicked), NULL);
+ gtk_box_pack_start(GTK_BOX(date_hbox), date_btn, TRUE, TRUE, 0);
+
+ hour_entry = gtk_spin_button_new_with_range(0, 23, 1);
+ gtk_spin_button_set_digits(GTK_SPIN_BUTTON(hour_entry), 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), hour_entry, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), gtk_label_new(":"), FALSE, FALSE, 0);
+ min_entry = gtk_spin_button_new_with_range(0, 59, 1);
+ gtk_spin_button_set_digits(GTK_SPIN_BUTTON(min_entry), 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), min_entry, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), gtk_label_new(":"), FALSE, FALSE, 0);
+ sec_entry = gtk_spin_button_new_with_range(0, 59, 1);
+ gtk_spin_button_set_digits(GTK_SPIN_BUTTON(sec_entry), 0);
+ gtk_box_pack_start(GTK_BOX(date_hbox), sec_entry, FALSE, FALSE, 0);
+
/* test info button */
test_btn = gtkut_stock_button("dialog-information", _("_Information"));
gtk_box_pack_start(GTK_BOX(lower_hbox), test_btn, FALSE, FALSE, 0);
@@ -880,9 +985,10 @@ static void prefs_matcher_create(void)
matcher.regexp_checkbtn = regexp_checkbtn;
matcher.bool_op_combo = bool_op_combo;
matcher.test_btn = test_btn;
- matcher.calendar = calendar;
- matcher.time_label = time_label;
- matcher.time_entry = time_entry;
+ matcher.date_btn = date_btn;
+ matcher.hour_entry = hour_entry;
+ matcher.min_entry = min_entry;
+ matcher.sec_entry = sec_entry;
#ifndef USE_ALT_ADDRBOOK
matcher.addressbook_select_btn = addressbook_select_btn;
#endif
@@ -965,6 +1071,18 @@ static gboolean match_combo_model_set(void)
return FALSE;
}
+static void reset_date_btn(void)
+{
+ struct tm tm;
+ time_t ts;
+
+ ts = time(NULL);
+ if (!localtime_r(&ts, &tm))
+ return;
+
+ set_date_btn_to(&tm);
+}
+
/*!
*\brief Clears a condition in the list widget
*/
@@ -985,8 +1103,10 @@ static void prefs_matcher_reset_condition(void)
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.regexp_checkbtn), FALSE);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(matcher.case_checkbtn), FALSE);
- gtk_calendar_select_today(GTK_CALENDAR(matcher.calendar));
- gtkut_time_select_select_by_time(GTK_COMBO_BOX(matcher.time_entry), 0, 0);
+ reset_date_btn();
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.hour_entry), 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.min_entry), 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.sec_entry), 0);
}
/*!
@@ -1497,7 +1617,6 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
const gchar *header;
const gchar *expr;
gint value, sel;
- gint year, month, day, hour, minute;
if (value_criteria == -1)
return NULL;
@@ -1564,16 +1683,11 @@ static MatcherProp *prefs_matcher_dialog_to_matcher(void)
case CRITERIA_DATE_AFTER:
case CRITERIA_DATE_BEFORE:
- expr = NULL;
- gtk_calendar_get_date(GTK_CALENDAR(matcher.calendar), &year, &month, &day);
- if (gtkut_time_select_get_time(GTK_COMBO_BOX(matcher.time_entry), &hour, &minute))
- expr = g_strdup_printf("%4d-%02d-%02d %02d:%02d:00",
- year, month + 1, day, hour, minute);
-
- if (expr == NULL) {
- alertpanel_error(_("Invalid hour."));
- return NULL;
- }
+ expr = g_strdup_printf("%s %02d:%02d:%02d",
+ gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(matcher.date_btn)))),
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matcher.hour_entry)),
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matcher.min_entry)),
+ gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(matcher.sec_entry)));
break;
case CRITERIA_TEST:
@@ -1968,11 +2082,7 @@ static void prefs_matcher_criteria_select(GtkWidget *widget,
prefs_matcher_enable_widget(matcher.string_entry,
(MATCH_CASE_REGEXP(value) ||
value == MATCH_TEST));
- prefs_matcher_enable_widget(matcher.calendar,
- (value == MATCH_DATE));
- prefs_matcher_enable_widget(matcher.time_label,
- (value == MATCH_DATE));
- prefs_matcher_enable_widget(matcher.time_entry,
+ prefs_matcher_enable_widget(gtk_widget_get_parent(matcher.date_btn),
(value == MATCH_DATE));
prefs_matcher_enable_widget(matcher.numeric_entry,
MATCH_NUMERIC(value));
@@ -2012,8 +2122,10 @@ static void prefs_matcher_criteria_select(GtkWidget *widget,
case MATCH_DATE:
prefs_matcher_set_model(matcher.match_combo, matcher.model_date);
gtk_label_set_text(GTK_LABEL(matcher.match_label), _("Date is"));
- gtk_calendar_select_today(GTK_CALENDAR(matcher.calendar));
- gtkut_time_select_select_by_time(GTK_COMBO_BOX(matcher.time_entry), 0, 0);
+ reset_date_btn();
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.hour_entry), 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.min_entry), 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.sec_entry), 0);
break;
case MATCH_AGE:
prefs_matcher_set_model(matcher.match_combo, matcher.model_age);
@@ -2450,8 +2562,6 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
gint criteria;
GtkTreeIter iter;
gboolean is_valid;
- struct tm lt;
- char zone[6];
if (currently_selected)
return TRUE;
@@ -2557,13 +2667,16 @@ static gboolean prefs_matcher_selected(GtkTreeSelection *selector,
case MATCHCRITERIA_DATE_AFTER:
case MATCHCRITERIA_DATE_BEFORE:
- zone[0] = '\0';
- procheader_date_parse_to_tm(prop->expr, <, zone);
- gtk_calendar_select_day(GTK_CALENDAR(matcher.calendar), lt.tm_mday);
- gtk_calendar_select_month(GTK_CALENDAR(matcher.calendar), lt.tm_mon, lt.tm_year + 1900);
- gtkut_time_select_select_by_time(GTK_COMBO_BOX(matcher.time_entry), lt.tm_hour, lt.tm_min);
+ {
+ struct tm tm;
+ matcherprop_parse_date_time(prop->criteria, prop->expr, &tm);
+ set_date_btn_to(&tm);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.hour_entry), tm.tm_hour);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.min_entry), tm.tm_min);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(matcher.sec_entry), tm.tm_sec);
break;
+ }
case MATCHCRITERIA_FOUND_IN_ADDRESSBOOK:
case MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK:
diff --git a/src/prefs_message.c b/src/prefs_message.c
index 7d5da9b15..ab0fb8586 100644
--- a/src/prefs_message.c
+++ b/src/prefs_message.c
@@ -63,6 +63,8 @@ typedef struct _MessagePage
GtkWidget *checkbtn_attach_desc;
GtkWidget *entry_quote_chars;
+
+ GtkWidget *checkbtn_decrypt;
} MessagePage;
static void disphdr_pane_toggled(GtkToggleButton *toggle_btn, GtkWidget *widget)
@@ -114,6 +116,8 @@ static void prefs_message_create_widget(PrefsPage *_page, GtkWindow *window,
GtkWidget *entry_quote_chars;
GtkWidget *label_quote_chars;
+ GtkWidget *checkbtn_decrypt;
+
vbox1 = gtk_box_new(GTK_ORIENTATION_VERTICAL, VSPACING);
gtk_widget_show (vbox1);
gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
@@ -259,6 +263,9 @@ static void prefs_message_create_widget(PrefsPage *_page, GtkWindow *window,
FALSE, FALSE, 0);
gtk_widget_set_size_request (entry_quote_chars, 64, -1);
+ PACK_CHECK_BUTTON(vbox1, checkbtn_decrypt,
+ _("Automatically decrypt messages"));
+
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_disphdrpane),
prefs_common.display_header_pane);
@@ -289,6 +296,8 @@ static void prefs_message_create_widget(PrefsPage *_page, GtkWindow *window,
prefs_common.scroll_step);
gtk_entry_set_text(GTK_ENTRY(entry_quote_chars),
prefs_common.quote_chars?prefs_common.quote_chars:"");
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_decrypt),
+ prefs_common.decrypt_messages);
prefs_message->window = GTK_WIDGET(window);
prefs_message->checkbtn_disphdrpane = checkbtn_disphdrpane;
@@ -305,6 +314,7 @@ static void prefs_message_create_widget(PrefsPage *_page, GtkWindow *window,
prefs_message->checkbtn_halfpage = checkbtn_halfpage;
prefs_message->checkbtn_attach_desc = checkbtn_attach_desc;
prefs_message->entry_quote_chars = entry_quote_chars;
+ prefs_message->checkbtn_decrypt = checkbtn_decrypt;
prefs_message->page.widget = vbox1;
}
@@ -339,6 +349,8 @@ static void prefs_message_save(PrefsPage *_page)
GTK_SPIN_BUTTON(page->spinbtn_linespc));
prefs_common.scroll_step = gtk_spin_button_get_value_as_int(
GTK_SPIN_BUTTON(page->spinbtn_scrollstep));
+ prefs_common.decrypt_messages = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(page->checkbtn_decrypt));
g_free(prefs_common.quote_chars);
prefs_common.quote_chars = gtk_editable_get_chars(
diff --git a/src/prefs_summaries.c b/src/prefs_summaries.c
index e74c7f40a..937b56637 100644
--- a/src/prefs_summaries.c
+++ b/src/prefs_summaries.c
@@ -69,6 +69,7 @@ typedef struct _SummariesPage
GtkWidget *checkbtn_show_on_prevnext;
GtkWidget *checkbtn_show_on_deletemove;
GtkWidget *checkbtn_show_on_directional;
+ GtkWidget *checkbtn_mark_as_read_on_never;
GtkWidget *checkbtn_mark_as_read_on_newwin;
GtkWidget *spinbtn_mark_as_read_delay;
GtkWidget *checkbtn_immedexec;
@@ -361,6 +362,7 @@ static void prefs_summaries_create_widget(PrefsPage *_page, GtkWindow *window,
GtkWidget *optmenu_summaryfromshow;
GtkWidget *optmenu_nextunreadmsgdialog;
GtkWidget *button_edit_actions;
+ GtkWidget *radio_mark_as_read_on_never;
GtkWidget *radio_mark_as_read_on_select;
GtkWidget *radio_mark_as_read_on_new_win;
GtkWidget *optmenu_sort_key;
@@ -540,7 +542,16 @@ static void prefs_summaries_create_widget(PrefsPage *_page, GtkWindow *window,
vbox3 = gtkut_get_options_frame(vbox1, NULL, _("Mark message as read"));
- radio_mark_as_read_on_select = gtk_radio_button_new_with_label(NULL,
+ radio_mark_as_read_on_never = gtk_radio_button_new_with_label(
+ NULL,
+ _("never"));
+ gtk_widget_set_tooltip_text (radio_mark_as_read_on_never,
+ _("Never automatically mark a message as read."));
+ gtk_box_pack_start (GTK_BOX (vbox3), radio_mark_as_read_on_never,
+ FALSE, FALSE, 0);
+
+ radio_mark_as_read_on_select = gtk_radio_button_new_with_label_from_widget(
+ GTK_RADIO_BUTTON(radio_mark_as_read_on_never),
_("when selected, after"));
hbox1 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
@@ -693,6 +704,7 @@ static void prefs_summaries_create_widget(PrefsPage *_page, GtkWindow *window,
prefs_summaries->checkbtn_show_on_deletemove = checkbtn_show_on_deletemove;
prefs_summaries->checkbtn_show_on_directional = checkbtn_show_on_directional;
+ prefs_summaries->checkbtn_mark_as_read_on_never = radio_mark_as_read_on_never;
prefs_summaries->checkbtn_mark_as_read_on_newwin = radio_mark_as_read_on_new_win;
prefs_summaries->spinbtn_mark_as_read_delay = spinbtn_mark_as_read_delay;
prefs_summaries->checkbtn_immedexec = checkbtn_immedexec;
@@ -749,6 +761,8 @@ static void prefs_summaries_create_widget(PrefsPage *_page, GtkWindow *window,
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbtn_show_on_directional),
prefs_common.open_selected_on_directional);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_mark_as_read_on_never),
+ prefs_common.mark_as_read_on_never);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_mark_as_read_on_new_win),
prefs_common.mark_as_read_on_new_window);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbtn_mark_as_read_delay),
@@ -827,6 +841,8 @@ static void prefs_summaries_save(PrefsPage *_page)
prefs_common.open_selected_on_directional = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(page->checkbtn_show_on_directional));
+ prefs_common.mark_as_read_on_never = gtk_toggle_button_get_active(
+ GTK_TOGGLE_BUTTON(page->checkbtn_mark_as_read_on_never));
prefs_common.mark_as_read_on_new_window = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(page->checkbtn_mark_as_read_on_newwin));
prefs_common.immediate_exec = gtk_toggle_button_get_active(
diff --git a/src/procmime.c b/src/procmime.c
index a51782f6d..89e22ea67 100644
--- a/src/procmime.c
+++ b/src/procmime.c
@@ -659,7 +659,8 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, EncodingType encoding)
return TRUE;
}
-static gint procmime_get_part_to_stream(FILE *outfp, MimeInfo *mimeinfo)
+static gint procmime_get_part_to_stream(FILE *outfp, MimeInfo *mimeinfo,
+ const gboolean handle_bom, const gchar *outfile)
{
FILE *infp;
gchar buf[BUFFSIZE];
@@ -686,6 +687,96 @@ static gint procmime_get_part_to_stream(FILE *outfp, MimeInfo *mimeinfo)
restlength = mimeinfo->length;
+/* handle BOM bytes according to hidden option: write them when saving the attachment (default),
+ skip them or ask the user about skipping or writing them */
+/* see: http://en.wikipedia.org/wiki/Byte_order_mark */
+
+/* debug_print("procmime_get_part_with_bom: handle bom: %d, option: %d\n", handle_bom, prefs_common.save_attachment_handle_bom);*/
+ if (handle_bom && (restlength >= 2) && (prefs_common.save_attachment_handle_bom != HANDLE_BOM_WRITE)) {
+ gint bom_length = 0;
+
+#define COMP_4_BYTES(A, B, C, D) \
+ ( ((buf[0]&0xff) == (guchar)(A)) && ((buf[1]&0xff) == (guchar)(B)) && ((buf[2]&0xff) == (guchar)(C)) && ((buf[3]&0xff) == (guchar)(D)) )
+#define COMP_3_BYTES(A, B, C) \
+ ( ((buf[0]&0xff) == (guchar)(A)) && ((buf[1]&0xff) == (guchar)(B)) && ((buf[2]&0xff) == (guchar)(C)) )
+#define COMP_2_BYTES(A, B) \
+ ( ((buf[0]&0xff) == (guchar)(A)) && ((buf[1]&0xff) == (guchar)(B)) )
+
+ debug_print("looking for BOM..\n");
+ if ((readlength = fread(buf, 1, 4, infp)) > 0) {
+ gint i;
+
+ debug_print("looking for BOM: read %d bytes\n", readlength);
+ for (i = 0; i < readlength; i++)
+ debug_print("[%d] = %c %03d %02x\n", i, buf[i]&0xff, buf[i]&0xff, buf[i]&0xff);
+
+ if (readlength == 4) {
+ if (COMP_4_BYTES(0x00, 0x00, 0xfe, 0xff) || /* UTF-32 (Big Endian) */
+ COMP_4_BYTES(0xff, 0xfe, 0x00, 0x00) || /* UTF-32 (Little Endian) */
+ COMP_4_BYTES(0x2b, 0x2f, 0x76, 0x38) || /* UTF-7 */
+ COMP_4_BYTES(0x2b, 0x2f, 0x76, 0x39) || /* UTF-7 */
+ COMP_4_BYTES(0x2b, 0x2f, 0x76, 0x2b) || /* UTF-7 */
+ COMP_4_BYTES(0x2b, 0x2f, 0x76, 0x2f) || /* UTF-7 */
+ COMP_4_BYTES(0xdd, 0x73, 0x66, 0x73) || /* UTF-EBCDIC */
+ COMP_4_BYTES(0xfb, 0xee, 0x28, 0xff) || /* BOCU-1 */
+ COMP_4_BYTES(0x84, 0x31, 0x95, 0x33)) { /* GB-18030 */
+ bom_length = 4;
+ }
+ }
+ if ((bom_length == 0) && (readlength >= 3)) {
+ if (COMP_3_BYTES(0xef, 0xbb, 0xbf) || /* UTF-8 */
+ COMP_3_BYTES(0xf7, 0x64, 0x4c) || /* UTF-1 */
+ COMP_3_BYTES(0x0e, 0xfe, 0xff) || /* SCSU */
+ COMP_3_BYTES(0xfb, 0xee, 0x28)) { /* BOCU-1 */
+ bom_length = 3;
+ }
+ }
+ if ((bom_length == 0) && (readlength >= 2)) {
+ if (COMP_2_BYTES(0xfe, 0xff) || /* UTF-16 (Big Endian) */
+ COMP_2_BYTES(0xff, 0xfe)) { /* UTF-16 (Little Endian) */
+ bom_length = 2;
+ }
+ }
+ debug_print("BOM matched: %d bytes\n", bom_length);
+ if ((bom_length > 0) && (prefs_common.save_attachment_handle_bom == HANDLE_BOM_ASK_USER)) {
+ AlertValue val;
+ gchar *msg;
+ gchar *filename;
+
+ filename = g_path_get_basename(outfile);
+ msg = g_strdup_printf(
+ _("Claws Mail has detected that the attachment '%s' "
+ "starts with a %d-byte Byte Order Mask (BOM).\n\n"
+ "Do you want to save the file exactly as it has been received (with "
+ "the BOM bytes) or skip the BOM bytes when saving the file?"),
+ filename, bom_length);
+ g_free(filename);
+ val = alertpanel_full(_("Write BOM bytes?"), msg,
+ _("Save untouched"), _("Save without BOM"), NULL,
+ ALERTFOCUS_FIRST, FALSE, NULL, ALERT_QUESTION);
+ g_free(msg);
+ if (val != G_ALERTALTERNATE) {
+ /* save untouched attachment: do not skip BOM bytes */
+ bom_length = 0;
+ }
+ }
+
+ debug_print("writing %s BOM bytes: writing %d bytes\n",
+ (bom_length > 0)?"without":"with", readlength - bom_length);
+ if (fwrite(buf + bom_length, 1, readlength - bom_length, outfp) != (readlength - bom_length)) {
+ saved_errno = errno;
+ fclose(infp);
+ fclose(outfp);
+ return -(saved_errno);
+ }
+ restlength -= readlength;
+ }
+
+#undef COMP_2_BYTES
+#undef COMP_3_BYTES
+#undef COMP_4_BYTES
+ }
+
while ((restlength > 0) && ((readlength = claws_fread(buf, 1, restlength > BUFFSIZE ? BUFFSIZE : restlength, infp)) > 0)) {
if (claws_fwrite(buf, 1, readlength, outfp) != readlength) {
saved_errno = errno;
@@ -701,7 +792,8 @@ static gint procmime_get_part_to_stream(FILE *outfp, MimeInfo *mimeinfo)
return 0;
}
-gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
+gint procmime_get_part_with_bom(const gchar *outfile, MimeInfo *mimeinfo,
+ const gboolean handle_bom)
{
FILE *outfp;
gint result;
@@ -720,7 +812,7 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
g_warning("can't change file mode: %s", outfile);
}
- result = procmime_get_part_to_stream(outfp, mimeinfo);
+ result = procmime_get_part_to_stream(outfp, mimeinfo, handle_bom, outfile);
if (claws_fclose(outfp) == EOF) {
saved_errno = errno;
@@ -733,6 +825,11 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
return result;
}
+gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
+{
+ return procmime_get_part_with_bom(outfile, mimeinfo, FALSE);
+}
+
gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
gboolean (*scan_callback)(const gchar *str, gpointer cb_data),
gpointer cb_data)
@@ -770,7 +867,7 @@ gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
return TRUE;
}
- if ((r = procmime_get_part_to_stream(tmpfp, mimeinfo)) < 0) {
+ if ((r = procmime_get_part_to_stream(tmpfp, mimeinfo, FALSE, "")) < 0) {
g_warning("procmime_get_part_to_stream error %d", r);
g_free(tmpfile);
return TRUE;
@@ -905,7 +1002,7 @@ FILE *procmime_get_binary_content(MimeInfo *mimeinfo)
}
#endif
- if (procmime_get_part_to_stream(outfp, mimeinfo) < 0) {
+ if (procmime_get_part_to_stream(outfp, mimeinfo, FALSE, "") < 0) {
return NULL;
}
ftruncate(fileno(outfp), ftell(outfp));
diff --git a/src/procmime.h b/src/procmime.h
index e87a27624..5b80a9745 100644
--- a/src/procmime.h
+++ b/src/procmime.h
@@ -197,6 +197,8 @@ MimeInfo *procmime_scan_mime_header (FILE *fp);
gboolean procmime_decode_content (MimeInfo *mimeinfo);
gboolean procmime_encode_content (MimeInfo *mimeinfo, EncodingType encoding);
+gint procmime_get_part_with_bom (const gchar *outfile,
+ MimeInfo *mimeinfo, const gboolean handle_bom);
gint procmime_get_part (const gchar *outfile,
MimeInfo *mimeinfo);
FILE *procmime_get_first_text_content (MsgInfo *msginfo);
diff --git a/src/procmsg.c b/src/procmsg.c
index 4a60fbe7b..fa73622b4 100644
--- a/src/procmsg.c
+++ b/src/procmsg.c
@@ -76,6 +76,7 @@ enum
Q_ENCRYPT_OLD = 14,
Q_ENCRYPT_DATA_OLD = 15,
Q_CLAWS_HDRS_OLD = 16,
+ Q_DSN = 17,
};
void procmsg_msg_list_free(GSList *mlist)
@@ -906,6 +907,7 @@ parse_again:
if (orig && g_slist_length(orig)) {
if (!last_account && nothing_to_sort) {
/* can't find an account for the rest of the list */
+fprintf(stderr, "==> 1220858 logically dead code\n");
cur = orig;
while (cur) {
result = g_slist_append(result, cur->data);
@@ -1559,6 +1561,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
{"X-Sylpheed-Encrypt:", NULL, FALSE},
{"X-Sylpheed-Encrypt-Data:", NULL, FALSE}, /* 15 */
{"X-Sylpheed-End-Special-Headers:", NULL, FALSE},
+ {"DSN:", NULL, FALSE},
{NULL, NULL, FALSE}};
FILE *fp;
gint filepos;
@@ -1575,6 +1578,7 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
PrefsAccount *mailac = NULL, *newsac = NULL;
gboolean encrypt = FALSE;
FolderItem *outbox;
+ gboolean dsn_requested = FALSE;
cm_return_val_if_fail(file != NULL, -1);
@@ -1628,6 +1632,10 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
if (p[0] == '1')
encrypt = TRUE;
break;
+ case Q_DSN:
+ if (p[0] == '1')
+ dsn_requested = TRUE;
+ break;
case Q_CLAWS_HDRS:
case Q_CLAWS_HDRS_OLD:
/* end of special headers reached */
@@ -1670,7 +1678,7 @@ send_mail:
}
if (mailac) {
- mailval = send_message_smtp_full(mailac, to_list, fp, keep_session);
+ mailval = send_message_smtp_full(mailac, to_list, dsn_requested, fp, keep_session);
if (mailval == -1 && errstr) {
if (*errstr) g_free(*errstr);
*errstr = g_strdup_printf(_("An error happened during SMTP session."));
@@ -1684,7 +1692,7 @@ send_mail:
tmp_ac.address = from;
tmp_ac.smtp_server = smtpserver;
tmp_ac.smtpport = SMTP_PORT;
- mailval = send_message_smtp(&tmp_ac, to_list, fp);
+ mailval = send_message_smtp(&tmp_ac, to_list, dsn_requested, fp);
if (mailval == -1 && errstr) {
if (*errstr) g_free(*errstr);
*errstr = g_strdup_printf(_("No specific account has been found to "
diff --git a/src/send_message.c b/src/send_message.c
index 99941e618..f527e1c66 100644
--- a/src/send_message.c
+++ b/src/send_message.c
@@ -125,7 +125,7 @@ gint send_message(const gchar *file, PrefsAccount *ac_prefs, GSList *to_list)
inc_unlock();
return val;
} else {
- val = send_message_smtp(ac_prefs, to_list, fp);
+ val = send_message_smtp(ac_prefs, to_list, FALSE, fp);
claws_fclose(fp);
inc_unlock();
@@ -212,7 +212,7 @@ gint send_message_local(const gchar *command, FILE *fp)
return 0;
}
-gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, gboolean keep_session)
+gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, gboolean dsn_requested, FILE *fp, gboolean keep_session)
{
Session *session;
SMTPSession *smtp_session;
@@ -385,6 +385,7 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
ac_prefs->session = NULL;
smtp_session = SMTP_SESSION(session);
smtp_session->state = SMTP_HELO;
+ smtp_session->is_dsn_supported = FALSE;
send_dialog = (SendProgressDialog *)smtp_session->dialog;
was_inited = TRUE;
}
@@ -395,6 +396,7 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
smtp_session->cur_to = to_list;
smtp_session->send_data = (guchar *)get_outgoing_rfc2822_str(fp);
smtp_session->send_data_len = strlen((gchar *)smtp_session->send_data);
+ smtp_session->is_dsn_requested = dsn_requested;
if (ac_prefs->use_proxy && ac_prefs->use_proxy_for_send) {
if (ac_prefs->use_default_proxy) {
@@ -488,9 +490,9 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
return ret;
}
-gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
+gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, gboolean dsn_requested, FILE *fp)
{
- return send_message_smtp_full(ac_prefs, to_list, fp, FALSE);
+ return send_message_smtp_full(ac_prefs, to_list, dsn_requested, fp, FALSE);
}
static gint send_recv_message(Session *session, const gchar *msg, gpointer data)
diff --git a/src/send_message.h b/src/send_message.h
index c0861fd47..d7ce9e60d 100644
--- a/src/send_message.h
+++ b/src/send_message.h
@@ -36,9 +36,11 @@ gint send_message_local (const gchar *command,
FILE *fp);
gint send_message_smtp (PrefsAccount *ac_prefs,
GSList *to_list,
+ gboolean dsn_requested,
FILE *fp);
gint send_message_smtp_full (PrefsAccount *ac_prefs,
GSList *to_list,
+ gboolean dsn_requested,
FILE *fp,
gboolean keep_session);
void send_cancel (void);
diff --git a/src/summaryview.c b/src/summaryview.c
index d75d2f63a..77394d1ee 100644
--- a/src/summaryview.c
+++ b/src/summaryview.c
@@ -3784,7 +3784,8 @@ static void summary_display_msg_full(SummaryView *summaryview,
}
}
- if (val == 0 && MSG_IS_UNREAD(msginfo->flags)) {
+ if (val == 0 && MSG_IS_UNREAD(msginfo->flags)
+ && prefs_common.mark_as_read_on_never == 0) {
if (!prefs_common.mark_as_read_on_new_window &&
prefs_common.mark_as_read_delay) {
MarkAsReadData *data = g_new0(MarkAsReadData, 1);
@@ -5007,10 +5008,24 @@ void summary_save_as(SummaryView *summaryview)
if (!dest) return;
if (is_file_exist(dest)) {
+ gchar *res;
+ gint sz;
+
+ sz = get_file_size(dest);
+ if (!g_utf8_validate(dest, -1, NULL)) {
+ tmp = conv_filename_to_utf8(dest);
+ if (sz == -1)
+ sz = get_file_size(dest);
+ } else
+ tmp = g_strdup(dest);
+
+ res = g_strdup_printf(_("Append to existing file or overwrite it ('%s', %ld bytes)\nwith this one (%ld bytes)?"),
+ dest, sz, msginfo->size);
+ g_free(tmp);
aval = alertpanel(_("Append or Overwrite"),
- _("Append or overwrite existing file?"),
- _("_Append"), _("_Overwrite"), _("_Cancel"),
- ALERTFOCUS_FIRST);
+ res, _("_Append"), _("_Overwrite"),
+ _("_Cancel"), ALERTFOCUS_FIRST);
+ g_free(res);
if (aval != 0 && aval != 1)
return;
}
diff --git a/src/textview.c b/src/textview.c
index 5fb20e858..460415634 100644
--- a/src/textview.c
+++ b/src/textview.c
@@ -223,6 +223,8 @@ static void textview_toggle_quote (TextView *textview,
static void open_uri_cb (GtkAction *action,
TextView *textview);
+static void open_uri_alt_cb (GtkAction *action,
+ TextView *textview);
static void copy_uri_cb (GtkAction *action,
TextView *textview);
static void add_uri_to_addrbook_cb (GtkAction *action,
@@ -239,6 +241,7 @@ static GtkActionEntry textview_link_popup_entries[] =
{
{"TextviewPopupLink", NULL, "TextviewPopupLink", NULL, NULL, NULL },
{"TextviewPopupLink/Open", NULL, N_("_Open in web browser"), NULL, NULL, G_CALLBACK(open_uri_cb) },
+ {"TextviewPopupLink/OpenAlt", NULL, N_("_Open in alternate web browser"), NULL, NULL, G_CALLBACK(open_uri_alt_cb) },
{"TextviewPopupLink/Copy", NULL, N_("Copy this _link"), NULL, NULL, G_CALLBACK(copy_uri_cb) },
};
@@ -380,6 +383,8 @@ TextView *textview_create(void)
MENUITEM_ADDUI_MANAGER(textview->ui_manager,
"/Menus/TextviewPopupLink", "Open", "TextviewPopupLink/Open", GTK_UI_MANAGER_MENUITEM)
+ MENUITEM_ADDUI_MANAGER(textview->ui_manager,
+ "/Menus/TextviewPopupLink", "OpenAlt", "TextviewPopupLink/OpenAlt", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(textview->ui_manager,
"/Menus/TextviewPopupLink", "Copy", "TextviewPopupLink/Copy", GTK_UI_MANAGER_MENUITEM)
MENUITEM_ADDUI_MANAGER(textview->ui_manager,
@@ -3151,6 +3156,27 @@ static void open_uri_cb (GtkAction *action, TextView *textview)
}
}
+static void open_uri_alt_cb (GtkAction *action, TextView *textview)
+{
+ ClickableText *uri = g_object_get_data(G_OBJECT(textview->link_popup_menu),
+ "menu_button");
+ const gchar *raw_url = g_object_get_data(G_OBJECT(textview->link_popup_menu),
+ "raw_url");
+
+ if (uri) {
+ if (textview_uri_security_check(textview, uri, FALSE) == TRUE)
+ open_uri(uri->uri,
+ prefs_common_get_uri_alt_cmd());
+ g_object_set_data(G_OBJECT(textview->link_popup_menu), "menu_button",
+ NULL);
+ }
+ if (raw_url) {
+ open_uri(raw_url, prefs_common_get_uri_alt_cmd());
+ g_object_set_data(G_OBJECT(textview->link_popup_menu), "raw_url",
+ NULL);
+ }
+}
+
static void copy_uri_cb (GtkAction *action, TextView *textview)
{
ClickableText *uri = g_object_get_data(G_OBJECT(textview->link_popup_menu),
diff --git a/src/toolbar.c b/src/toolbar.c
index 9bf11381b..843185d14 100644
--- a/src/toolbar.c
+++ b/src/toolbar.c
@@ -1492,19 +1492,29 @@ static void toolbar_next_unread_cb(GtkWidget *widget, gpointer data)
ToolbarItem *toolbar_item = (ToolbarItem*)data;
MainWindow *mainwin;
MessageView *msgview;
+ gboolean save_option_value;
cm_return_if_fail(toolbar_item != NULL);
switch (toolbar_item->type) {
case TOOLBAR_MAIN:
+
mainwin = (MainWindow*)toolbar_item->parent;
+/* (workaround) force marking opened message as read when entering new folders */
+save_option_value = prefs_common.open_selected_on_folder_open;
+prefs_common.open_selected_on_folder_open = TRUE;
summary_select_next_unread(mainwin->summaryview);
+prefs_common.open_selected_on_folder_open = save_option_value;
break;
case TOOLBAR_MSGVIEW:
msgview = (MessageView*)toolbar_item->parent;
msgview->updating = TRUE;
+/* (workaround) force marking opened message as read when entering new folders */
+save_option_value = prefs_common.open_selected_on_folder_open;
+prefs_common.open_selected_on_folder_open = TRUE;
summary_select_next_unread(msgview->mainwin->summaryview);
+prefs_common.open_selected_on_folder_open = save_option_value;
msgview->updating = FALSE;
if (msgview->deferred_destroy) {
@@ -2841,7 +2851,7 @@ do { \
for (cur = toolbar->action_list; cur != NULL; cur = cur->next) {
ToolbarClawsActions *act = (ToolbarClawsActions*)cur->data;
- SET_WIDGET_COND(act->widget, M_TARGET_EXIST, M_UNLOCKED);
+ SET_WIDGET_COND(act->widget, M_TARGET_EXIST);
}
state = main_window_get_current_state(mainwin);
@@ -3141,7 +3151,8 @@ void compose_mail_cb(gpointer data, guint action, GtkWidget *widget)
list = account_get_list();
for (cur = list ; cur != NULL ; cur = g_list_next(cur)) {
ac = (PrefsAccount *) cur->data;
- if (ac->protocol != A_NNTP) {
+ if ((ac->protocol != A_NNTP) &&
+ (ac->selectable_as_current_account)) {
compose_new_with_folderitem(ac, item, NULL);
return;
}
@@ -3167,7 +3178,8 @@ void compose_news_cb(gpointer data, guint action, GtkWidget *widget)
list = account_get_list();
for(cur = list ; cur != NULL ; cur = g_list_next(cur)) {
ac = (PrefsAccount *) cur->data;
- if (ac->protocol == A_NNTP) {
+ if ((ac->protocol == A_NNTP) &&
+ (ac->selectable_as_current_account)) {
compose_new_with_folderitem(ac,
mainwin->summaryview->folder_item, NULL);
return;
diff --git a/src/vcard.c b/src/vcard.c
index 2e8fce511..9b660ab02 100644
--- a/src/vcard.c
+++ b/src/vcard.c
@@ -62,6 +62,7 @@ VCardFile *vcard_create() {
cardFile->file = NULL;
cardFile->path = NULL;
cardFile->bufptr = cardFile->buffer;
+ cardFile->addressCache->collapsedFlag = TRUE;
return cardFile;
}
@@ -390,8 +391,8 @@ static gchar *vcard_unescape_qp( gchar *value ) {
return NULL;
len = strlen(value);
- res = g_malloc(len);
- qp_decode_const(res, len-1, value);
+ res = g_malloc(len + 1);
+ qp_decode_const(res, len, value);
if (!g_utf8_validate(res, -1, NULL)) {
gchar *mybuf = g_malloc(strlen(res)*2 +1);
conv_localetodisp(mybuf, strlen(res)*2 +1, res);
@@ -699,6 +700,21 @@ gint vcard_test_read_file( const gchar *fileSpec ) {
return retVal;
}
+gboolean vcard_get_collapsed( VCardFile *cardFile )
+{
+ g_return_val_if_fail( cardFile != NULL, FALSE );
+fprintf(stderr, "==> vcard_get_collapsed: %d\n", cardFile->addressCache->collapsedFlag);
+ return cardFile->addressCache->collapsedFlag;
+}
+
+void vcard_set_collapsed( VCardFile *cardFile, const gboolean value )
+{
+ g_return_if_fail( cardFile != NULL );
+fprintf(stderr, "==> vcard_set_collapsed: %d\n", value);
+ cardFile->addressCache->collapsedFlag = value;
+ addrcache_set_dirty(cardFile->addressCache, TRUE);
+}
+
/*
* End of Source.
*/
diff --git a/src/vcard.h b/src/vcard.h
index cf0274e59..0869e8660 100644
--- a/src/vcard.h
+++ b/src/vcard.h
@@ -87,8 +87,10 @@ void vcard_set_name ( VCardFile* cardFile, const gchar *value );
void vcard_set_file ( VCardFile* cardFile, const gchar *value );
void vcard_set_modified ( VCardFile *cardFile, const gboolean value );
void vcard_set_accessed ( VCardFile *cardFile, const gboolean value );
+void vcard_set_collapsed ( VCardFile *cardFile, const gboolean value );
gboolean vcard_get_modified ( VCardFile *cardFile );
gboolean vcard_get_accessed ( VCardFile *cardFile );
+gboolean vcard_get_collapsed ( VCardFile *cardFile );
gboolean vcard_get_read_flag ( VCardFile *cardFile );
gint vcard_get_status ( VCardFile *cardFile );
ItemFolder *vcard_get_root_folder ( VCardFile *cardFile );
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list