Compose window: sender address line gets its own label with a mnemonic, similar to...
[claws.git] / src / compose.c
index a13e4ea6edc1fe8805916a1b78365e9f63aed43f..4df4759ecf1281f38867a6014bc8d3f807fce844 100644 (file)
@@ -84,7 +84,6 @@
 #include "procmime.h"
 #include "statusbar.h"
 #include "about.h"
-#include "base64.h"
 #include "quoted-printable.h"
 #include "codeconv.h"
 #include "utils.h"
@@ -563,6 +562,7 @@ static void compose_attach_update_label(Compose *compose);
 static void compose_set_folder_prefs(Compose *compose, FolderItem *folder,
                                     gboolean respect_default_to);
 static void compose_subject_entry_activated(GtkWidget *widget, gpointer data);
+static void from_name_activate_cb(GtkWidget *widget, gpointer data);
 
 static GtkActionEntry compose_popup_entries[] =
 {
@@ -1206,7 +1206,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
 
                for (curr = attach_files ; curr != NULL ; curr = curr->next) {
                        ainfo = (AttachInfo *) curr->data;
-                       compose_attach_append(compose, ainfo->file, ainfo->name,
+                       compose_attach_append(compose, ainfo->file, ainfo->file,
                                        ainfo->content_type, ainfo->charset);
                }
        }
@@ -3207,7 +3207,7 @@ static gboolean is_subscription(const gchar *ml_post, const gchar *from)
                *(strstr(left_from, "@")) = '\0';
        }
        
-       if (left_ml && left_from && right_ml && right_from
+       if (right_ml && right_from
        &&  !strncmp(left_from, left_ml, strlen(left_ml))
        &&  !strcmp(right_from, right_ml)) {
                result = TRUE;
@@ -3575,7 +3575,6 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
        gint len;
        FILE *fp;
        gboolean prev_autowrap;
-       gboolean badtxt = FALSE;
        struct stat file_stat;
        int ret;
        GString *file_contents = NULL;
@@ -3675,10 +3674,7 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
 
        fclose(fp);
 
-       if (badtxt)
-               return COMPOSE_INSERT_INVALID_CHARACTER;
-       else 
-               return COMPOSE_INSERT_SUCCESS;
+       return COMPOSE_INSERT_SUCCESS;
 }
 
 static gboolean compose_attach_append(Compose *compose, const gchar *file,
@@ -5757,8 +5753,11 @@ static gint compose_write_body_to_file(Compose *compose, const gchar *file)
                (tmp, CS_INTERNAL, conv_get_locale_charset_str());
 
        g_free(tmp);
-       if (!chars) return -1;
-
+       if (!chars) {
+               fclose(fp);
+               claws_unlink(file);
+               return -1;
+       }
        /* write body */
        len = strlen(chars);
        if (fwrite(chars, sizeof(gchar), len, fp) != len) {
@@ -6139,13 +6138,14 @@ static int compose_add_attachments(Compose *compose, MimeInfo *parent)
                        }
                        continue;
                }
+               if (g_stat(ainfo->file, &statbuf) < 0)
+                       return -1;
+
                mimepart = procmime_mimeinfo_new();
                mimepart->content = MIMECONTENT_FILE;
                mimepart->data.filename = g_strdup(ainfo->file);
                mimepart->tmp = FALSE; /* or we destroy our attachment */
                mimepart->offset = 0;
-
-               g_stat(ainfo->file, &statbuf);
                mimepart->length = statbuf.st_size;
 
                type = g_strdup(ainfo->content_type);
@@ -6828,9 +6828,6 @@ static void compose_create_header_entry(Compose *compose)
        gboolean standard_header = FALSE;
        GtkListStore *model;
        GtkTreeIter iter;
-#if !(GTK_CHECK_VERSION(2,12,0))
-       GtkTooltips *tips = compose->tooltips;
-#endif
        
        headerentry = g_new0(ComposeHeaderEntry, 1);
 
@@ -6865,7 +6862,11 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(gtk_bin_get_child(GTK_BIN(combo))), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        gtk_widget_show(combo);
-       
+
+       /* Putting only the combobox child into focus chain of its parent causes
+        * the parent to be skipped when changing focus via Tab or Shift+Tab.
+        * This eliminates need to pres Tab twice in order to really get from the
+        * combobox to next widget. */
        GList *l = NULL;
        l = g_list_prepend(l, gtk_bin_get_child(GTK_BIN(combo)));
        gtk_container_set_focus_chain(GTK_CONTAINER(combo), l);
@@ -7071,9 +7072,9 @@ static GtkWidget *compose_create_header(Compose *compose)
 
        header_table = gtk_table_new(2, 2, FALSE);
        gtk_widget_show(header_table);
-       gtk_container_set_border_width(GTK_CONTAINER(header_table), BORDER_WIDTH);
+       gtk_container_set_border_width(GTK_CONTAINER(header_table), 0);
        gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(header_scrolledwin), header_table);
-       gtk_viewport_set_shadow_type(GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN((header_scrolledwin)))), GTK_SHADOW_NONE);
+       gtk_viewport_set_shadow_type(GTK_VIEWPORT(gtk_bin_get_child(GTK_BIN(header_scrolledwin))), GTK_SHADOW_NONE);
 
        gtk_table_attach(GTK_TABLE(header_table_main), header_scrolledwin,
                                  0, 2, 1, 2, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 2);
@@ -7375,8 +7376,9 @@ static void compose_dict_changed(void *data)
 {
        Compose *compose = (Compose *) data;
 
-       if(compose->gtkaspell && 
-                  compose->gtkaspell->recheck_when_changing_dict == FALSE)
+       if(!compose->gtkaspell)
+               return; 
+       if(compose->gtkaspell->recheck_when_changing_dict == FALSE)
                return;
 
        gtkaspell_highlight_all(compose->gtkaspell);
@@ -7456,10 +7458,6 @@ static Compose *compose_create(PrefsAccount *account,
        compose->mutex = cm_mutex_new();
        compose->set_cursor_pos = -1;
 
-#if !(GTK_CHECK_VERSION(2,12,0))
-       compose->tooltips = tips;
-#endif
-
        window = gtkut_window_new(GTK_WINDOW_TOPLEVEL, "compose");
 
        gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
@@ -7747,7 +7745,7 @@ static Compose *compose_create(PrefsAccount *account,
        gtk_container_set_border_width(GTK_CONTAINER(subject), 0);
        gtk_widget_show(subject);
 
-       label = gtk_label_new_with_mnemonic(_("Subject:"));
+       label = gtk_label_new_with_mnemonic(_("_Subject:"));
        gtk_box_pack_start(GTK_BOX(subject), label, FALSE, FALSE, 0);
        gtk_widget_show(label);
 
@@ -8050,12 +8048,10 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        GtkWidget *hbox;
        GtkWidget *optmenu;
        GtkWidget *optmenubox;
+       GtkWidget *fromlabel;
        GtkListStore *menu;
        GtkTreeIter iter;
        GtkWidget *from_name = NULL;
-#if !(GTK_CHECK_VERSION(2,12,0))
-       GtkTooltips *tips = compose->tooltips;
-#endif
 
        gint num = 0, def_menu = 0;
        
@@ -8066,11 +8062,13 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        optmenu = gtkut_sc_combobox_create(optmenubox, FALSE);
        menu = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(optmenu)));
 
-       hbox = gtk_hbox_new(FALSE, 6);
+       hbox = gtk_hbox_new(FALSE, 4);
        from_name = gtk_entry_new();
        
        g_signal_connect_after(G_OBJECT(from_name), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
+       g_signal_connect_after(G_OBJECT(from_name), "activate",
+                        G_CALLBACK(from_name_activate_cb), optmenu);
 
        for (; accounts != NULL; accounts = accounts->next, num++) {
                PrefsAccount *ac = (PrefsAccount *)accounts->data;
@@ -8078,7 +8076,7 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
 
                if (ac == compose->account) def_menu = num;
 
-               name = g_markup_printf_escaped(_("From: <i>%s</i>"),
+               name = g_markup_printf_escaped(_("<i>%s</i>"),
                                       ac->account_name);
                
                if (ac == compose->account) {
@@ -8108,8 +8106,21 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
                         G_CALLBACK(compose_entry_popup_extend),
                         NULL);
 
+       fromlabel = gtk_label_new_with_mnemonic(_("_From:"));
+       gtk_label_set_mnemonic_widget(GTK_LABEL(fromlabel), from_name);
+
+       gtk_box_pack_start(GTK_BOX(hbox), fromlabel, FALSE, FALSE, 4);
        gtk_box_pack_start(GTK_BOX(hbox), optmenubox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), from_name, TRUE, TRUE, 0);
+
+       /* Putting only the GtkEntry into focus chain of parent hbox causes
+        * the account selector combobox next to it to be unreachable when
+        * navigating widgets in GtkTable with up/down arrow keys.
+        * Note: gtk_widget_set_can_focus() was not enough. */
+       GList *l = NULL;
+       l = g_list_prepend(l, from_name);
+       gtk_container_set_focus_chain(GTK_CONTAINER(hbox), l);
+       g_list_free(l);
        
        CLAWS_SET_TIP(optmenubox,
                _("Account to use for this email"));
@@ -8655,6 +8666,24 @@ static void compose_template_apply_fields(Compose *compose, Template *tmpl)
                }
        }
 
+       if (tmpl->replyto && *tmpl->replyto != '\0') {
+#ifdef USE_ENCHANT
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account, FALSE,
+                               compose->gtkaspell);
+#else
+               quote_fmt_init(msginfo, NULL, NULL, FALSE, compose->account, FALSE);
+#endif
+               quote_fmt_scan_string(tmpl->replyto);
+               quote_fmt_parse();
+
+               buf = quote_fmt_get_buffer();
+               if (buf == NULL) {
+                       alertpanel_error(_("Template Reply-To format error."));
+               } else {
+                       compose_entry_append(compose, buf, COMPOSE_REPLYTO, PREF_TEMPLATE);
+               }
+       }
+
        /* process the subject */
        if (tmpl->subject && *tmpl->subject != '\0') {
 #ifdef USE_ENCHANT
@@ -8924,7 +8953,7 @@ static void compose_attach_property(GtkAction *action, gpointer data)
                gtk_widget_hide(attach_prop.window);
                gtk_window_set_modal(GTK_WINDOW(attach_prop.window), FALSE);
                
-               if (cancelled) 
+               if (cancelled)
                        break;
 
                entry_text = gtk_entry_get_text(GTK_ENTRY(attach_prop.mimetype_entry));
@@ -9530,7 +9559,7 @@ static void account_activated(GtkComboBox *optmenu, gpointer data)
 
        /* Get ID of active account in the combo box */
        menu = gtk_combo_box_get_model(optmenu);
-       gtk_combo_box_get_active_iter(optmenu, &iter);
+       cm_return_if_fail(gtk_combo_box_get_active_iter(optmenu, &iter));
        gtk_tree_model_get(menu, &iter, 1, &account_id, -1);
 
        ac = account_find_from_id(account_id);
@@ -11074,10 +11103,6 @@ static gboolean completion_set_focus_to_subject
                                         GdkEventKey  *event,
                                         Compose      *compose)
 {
-       GtkTextBuffer *buffer;
-       GtkTextMark *mark;
-       GtkTextIter iter;
-
        cm_return_val_if_fail(compose != NULL, FALSE);
 
        /* make backtab move to subject field */
@@ -11085,25 +11110,6 @@ static gboolean completion_set_focus_to_subject
                gtk_widget_grab_focus(compose->subject_entry);
                return TRUE;
        }
-
-       // Up key should also move the focus to subject field, if the cursor
-       // is on the first line.
-       if ((event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up)
-         && (event->state & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == 0) {
-               buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
-               g_return_val_if_fail(buffer != NULL, FALSE);
-
-               mark = gtk_text_buffer_get_mark(buffer, "insert");
-               g_return_val_if_fail(mark != NULL, FALSE);
-
-               gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
-
-               if (gtk_text_iter_get_line(&iter) == 0) {
-                       gtk_widget_grab_focus(compose->subject_entry);
-                       return TRUE;
-               }
-       }
-
        return FALSE;
 }
 
@@ -11192,10 +11198,7 @@ static void compose_insert_drag_received_cb (GtkWidget         *widget,
                g_list_free(list);
                gtk_drag_finish(drag_context, TRUE, FALSE, time);
                return;
-       } else {
-               return;
        }
-       gtk_drag_finish(drag_context, TRUE, FALSE, time);
 }
 
 static void compose_header_drag_received_cb (GtkWidget         *widget,
@@ -11565,7 +11568,7 @@ gboolean compose_close(Compose *compose)
                }
                return TRUE;
        }
-       
+
        if (compose->draft_timeout_tag >= 0) {
                g_source_remove(compose->draft_timeout_tag);
                compose->draft_timeout_tag = COMPOSE_DRAFT_TIMEOUT_FORBIDDEN;
@@ -11865,6 +11868,12 @@ static void compose_subject_entry_activated(GtkWidget *widget, gpointer data)
        gtk_widget_grab_focus(compose->text);
 }
 
+static void from_name_activate_cb(GtkWidget *widget, gpointer data)
+{
+       gtk_combo_box_popup(GTK_COMBO_BOX(data));
+}
+
+
 /*
  * End of Source.
  */