2007-04-25 [colin] 2.9.1cvs24
[claws.git] / src / compose.c
index aad178a9df37079b0c2740bd75c9626ce372c3ea..7ebe66e7f7cd04240733ec078659ab28cc538846 100644 (file)
@@ -340,7 +340,7 @@ static void compose_undo_state_changed              (UndoMain       *undostruct,
                                                 gpointer        data);
 
 static void compose_create_header_entry        (Compose *compose);
-static void compose_add_header_entry   (Compose *compose, gchar *header, gchar *text);
+static void compose_add_header_entry   (Compose *compose, const gchar *header, gchar *text);
 static void compose_remove_header_entries(Compose *compose);
 
 static void compose_update_priority_menu_item(Compose * compose);
@@ -2105,7 +2105,7 @@ GList *compose_get_compose_list(void)
 void compose_entry_append(Compose *compose, const gchar *address,
                          ComposeEntryType type)
 {
-       gchar *header;
+       const gchar *header;
        gchar *cur, *begin;
        gboolean in_quote = FALSE;
        if (!address || *address == '\0') return;
@@ -2131,7 +2131,7 @@ void compose_entry_append(Compose *compose, const gchar *address,
                header = N_("To:");
                break;
        }
-       header = prefs_common.trans_hdr ? gettext(header) : header;
+       header = prefs_common_translated_header_name(header);
        
        cur = begin = (gchar *)address;
        
@@ -4183,13 +4183,13 @@ gboolean compose_check_for_valid_recipient(Compose *compose) {
                g_strstrip(entry);
                if (entry[0] != '\0') {
                        for (strptr = recipient_headers_mail; *strptr != NULL; strptr++) {
-                               if (!strcmp(header, (prefs_common.trans_hdr ? gettext(*strptr) : *strptr))) {
+                               if (!strcmp(header, prefs_common_translated_header_name(*strptr))) {
                                        compose->to_list = address_list_append(compose->to_list, entry);
                                        recipient_found = TRUE;
                                }
                        }
                        for (strptr = recipient_headers_news; *strptr != NULL; strptr++) {
-                               if (!strcmp(header, (prefs_common.trans_hdr ? gettext(*strptr) : *strptr))) {
+                               if (!strcmp(header, prefs_common_translated_header_name(*strptr))) {
                                        compose->newsgroup_list = newsgroup_list_append(compose->newsgroup_list, entry);
                                        recipient_found = TRUE;
                                }
@@ -4214,7 +4214,7 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                        header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
                        g_strstrip(entry);
                        if (strcmp(entry, compose->account->auto_cc)
-                       ||  strcmp(header, (prefs_common.trans_hdr ? gettext("Cc:") : "Cc:"))) {
+                       ||  strcmp(header, prefs_common_translated_header_name("Cc:"))) {
                                found_other = TRUE;
                                g_free(entry);
                                break;
@@ -4245,7 +4245,7 @@ static gboolean compose_check_for_set_recipients(Compose *compose)
                        header = gtk_editable_get_chars(GTK_EDITABLE(GTK_COMBO(((ComposeHeaderEntry *)list->data)->combo)->entry), 0, -1);
                        g_strstrip(entry);
                        if (strcmp(entry, compose->account->auto_bcc)
-                       ||  strcmp(header, (prefs_common.trans_hdr ? gettext("Bcc:") : "Bcc:"))) {
+                       ||  strcmp(header, prefs_common_translated_header_name("Bcc:"))) {
                                found_other = TRUE;
                                g_free(entry);
                                break;
@@ -4472,13 +4472,13 @@ static gint compose_redirect_write_headers_from_headerlist(Compose *compose,
        GSList *list;
        ComposeHeaderEntry *headerentry;
        const gchar *headerentryname;
-       gchar *cc_hdr;
-       gchar *to_hdr;
+       const gchar *cc_hdr;
+       const gchar *to_hdr;
 
        debug_print("Writing redirect header\n");
 
-       cc_hdr = prefs_common.trans_hdr ? _("Cc:") : "Cc:";
-       to_hdr = prefs_common.trans_hdr ? _("To:") : "To:";
+       cc_hdr = prefs_common_translated_header_name("Cc:");
+       to_hdr = prefs_common_translated_header_name("To:");
 
        first_to_address = TRUE;
        for (list = compose->header_list; list; list = list->next) {
@@ -5297,11 +5297,12 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
                                                    const gchar *fieldname,
                                                    const gchar *seperator)
 {
-       gchar *str, *fieldname_w_colon, *trans_fieldname;
+       gchar *str, *fieldname_w_colon;
        gboolean add_field = FALSE;
        GSList *list;
        ComposeHeaderEntry *headerentry;
-       const gchar * headerentryname;
+       const gchar *headerentryname;
+       const gchar *trans_fieldname;
        GString *fieldstr;
 
        if (IS_IN_CUSTOM_HEADER(fieldname))
@@ -5312,7 +5313,7 @@ static void compose_add_headerfield_from_headerlist(Compose *compose,
        fieldstr = g_string_sized_new(64);
 
        fieldname_w_colon = g_strconcat(fieldname, ":", NULL);
-       trans_fieldname = (prefs_common.trans_hdr ? gettext(fieldname_w_colon) : fieldname_w_colon);
+       trans_fieldname = prefs_common_translated_header_name(fieldname_w_colon);
 
        for (list = compose->header_list; list; list = list->next) {
                headerentry = ((ComposeHeaderEntry *)list->data);
@@ -5546,7 +5547,7 @@ static gchar *compose_get_header(Compose *compose)
                gchar *tmp;
                gchar *headername;
                gchar *headername_wcolon;
-               gchar *headername_trans;
+               const gchar *headername_trans;
                gchar *headervalue;
                gchar **string;
                gboolean standard_header = FALSE;
@@ -5574,8 +5575,8 @@ static gchar *compose_get_header(Compose *compose)
                subst_char(headervalue, '\n', ' ');
                string = std_headers;
                while (*string != NULL) {
-                       headername_trans = prefs_common.trans_hdr ? gettext(*string) : *string;
-                       if (!strcmp(headername_trans,headername_wcolon))
+                       headername_trans = prefs_common_translated_header_name(*string);
+                       if (!strcmp(headername_trans, headername_wcolon))
                                standard_header = TRUE;
                        string++;
                }
@@ -5657,6 +5658,48 @@ static void compose_convert_header(Compose *compose, gchar *dest, gint len, gcha
        g_free(tmpstr);
 }
 
+static void compose_add_to_addressbook_cb(GtkMenuItem *menuitem, gpointer user_data)
+{
+       gchar *address;
+
+       g_return_if_fail(user_data != NULL);
+
+       address = g_strdup(gtk_entry_get_text(GTK_ENTRY(user_data)));
+       g_strstrip(address);
+       if (*address != '\0') {
+               gchar *name = procheader_get_fromname(address);
+               extract_address(address);
+               addressbook_add_contact(name, address, NULL);
+       }
+       g_free(address);
+}
+
+static void compose_entry_popup_extend(GtkEntry *entry, GtkMenu *menu, gpointer user_data)
+{
+       GtkWidget *menuitem;
+       gchar *address;
+
+       g_return_if_fail(menu != NULL);
+       g_return_if_fail(GTK_IS_MENU_SHELL(menu));
+
+       menuitem = gtk_separator_menu_item_new();
+       gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
+       gtk_widget_show(menuitem);
+
+       menuitem = gtk_menu_item_new_with_mnemonic(_("Add to address _book"));
+       gtk_menu_shell_prepend(GTK_MENU_SHELL(menu), menuitem);
+
+       address = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+       g_strstrip(address);
+       if (*address == '\0') {
+               gtk_widget_set_sensitive(GTK_WIDGET(menuitem), FALSE);
+       }
+
+       g_signal_connect(G_OBJECT(menuitem), "activate",
+                        G_CALLBACK(compose_add_to_addressbook_cb), entry);
+       gtk_widget_show(menuitem);
+}
+
 static void compose_create_header_entry(Compose *compose) 
 {
        gchar *headers[] = {"To:", "Cc:", "Bcc:", "Newsgroups:", "Reply-To:", "Followup-To:", NULL};
@@ -5675,7 +5718,7 @@ static void compose_create_header_entry(Compose *compose)
        combo = gtk_combo_new();
        string = headers; 
        while(*string != NULL) {
-               combo_list = g_list_append(combo_list, (prefs_common.trans_hdr ? gettext(*string) : *string));
+               combo_list = g_list_append(combo_list, (gchar*)prefs_common_translated_header_name(*string));
                string++;
        }
        gtk_combo_set_popdown_strings(GTK_COMBO(combo), combo_list);
@@ -5684,9 +5727,12 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(GTK_COMBO(combo)->entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        gtk_widget_show(combo);
-       gtk_table_attach(GTK_TABLE(compose->header_table), combo, 0, 1, compose->header_nextrow, compose->header_nextrow+1, GTK_SHRINK, GTK_FILL, 0, 0);
+       gtk_table_attach(GTK_TABLE(compose->header_table), combo, 0, 1,
+                       compose->header_nextrow, compose->header_nextrow+1,
+                       GTK_SHRINK, GTK_FILL, 0, 0);
        if (compose->header_last) {     
-               const gchar *last_header_entry = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry));
+               const gchar *last_header_entry = gtk_entry_get_text(
+                               GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry));
                string = headers;
                while (*string != NULL) {
                        if (!strcmp(*string, last_header_entry))
@@ -5699,10 +5745,10 @@ static void compose_create_header_entry(Compose *compose)
        if (!compose->header_last || !standard_header) {
                switch(compose->account->protocol) {
                        case A_NNTP:
-                               header = prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:";
+                               header = prefs_common_translated_header_name("Newsgroups:");
                                break;
                        default:
-                               header = prefs_common.trans_hdr ? _("To:") : "To:";
+                               header = prefs_common_translated_header_name("To:");
                                break;
                }                                                                   
        }
@@ -5717,7 +5763,9 @@ static void compose_create_header_entry(Compose *compose)
        gtk_widget_show(entry);
        gtk_tooltips_set_tip(compose->tooltips, entry,
                _("Use <tab> to autocomplete from addressbook"), NULL);
-       gtk_table_attach(GTK_TABLE(compose->header_table), entry, 1, 2, compose->header_nextrow, compose->header_nextrow+1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+       gtk_table_attach(GTK_TABLE(compose->header_table), entry, 1, 2,
+                       compose->header_nextrow, compose->header_nextrow+1,
+                       GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
 
         g_signal_connect(G_OBJECT(entry), "key-press-event", 
                         G_CALLBACK(compose_headerentry_key_press_event_cb), 
@@ -5738,6 +5786,9 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(entry), "drag-drop",
                         G_CALLBACK(compose_drag_drop),
                         compose);
+       g_signal_connect(G_OBJECT(entry), "populate-popup",
+                        G_CALLBACK(compose_entry_popup_extend),
+                        NULL);
        
        address_completion_register_entry(GTK_ENTRY(entry), TRUE);
 
@@ -5747,15 +5798,18 @@ static void compose_create_header_entry(Compose *compose)
         headerentry->headernum = compose->header_nextrow;
 
         compose->header_nextrow++;
-       compose->header_last = headerentry;
+       compose->header_last = headerentry;             
+       compose->header_list =
+               g_slist_append(compose->header_list,
+                              headerentry);
 }
 
-static void compose_add_header_entry(Compose *compose, gchar *header, gchar *text) 
+static void compose_add_header_entry(Compose *compose, const gchar *header, gchar *text) 
 {
        ComposeHeaderEntry *last_header;
        
        last_header = compose->header_last;
-       
+
        gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(last_header->combo)->entry), header);
        gtk_entry_set_text(GTK_ENTRY(last_header->entry), text);
 }
@@ -5770,6 +5824,7 @@ static void compose_remove_header_entries(Compose *compose)
                gtk_widget_destroy(headerentry->entry);
                g_free(headerentry);
        }
+       compose->header_last = NULL;
        g_slist_free(compose->header_list);
        compose->header_list = NULL;
        compose->header_nextrow = 1;
@@ -6361,12 +6416,9 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
                gtk_widget_set_size_request(edit_vbox, -1, mode == COMPOSE_NEW ? 300 : 280);
        else
                gtk_widget_set_size_request(edit_vbox, -1, mode == COMPOSE_NEW ? 250 : 230);
-       gtk_paned_add1(GTK_PANED(paned), edit_vbox);
-       gtk_paned_add2(GTK_PANED(paned), notebook);
-#else
+#endif
        gtk_paned_add1(GTK_PANED(paned), notebook);
        gtk_paned_add2(GTK_PANED(paned), edit_vbox);
-#endif
        gtk_widget_show_all(paned);
 
 
@@ -6409,6 +6461,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
 
        compose->paned = paned;
 
+       compose->notebook      = notebook;
        compose->edit_vbox     = edit_vbox;
        compose->ruler_hbox    = ruler_hbox;
        compose->ruler         = ruler;
@@ -6518,9 +6571,11 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode,
        menu_set_sensitive(ifactory, "/Options/Reply mode", compose->mode == COMPOSE_REPLY);
 
        if (account->protocol != A_NNTP)
-               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), prefs_common.trans_hdr ? _("To:") : "To:");
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry),
+                               prefs_common_translated_header_name("To:"));
        else
-               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry), prefs_common.trans_hdr ? _("Newsgroups:") : "Newsgroups:");
+               gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(compose->header_last->combo)->entry),
+                               prefs_common_translated_header_name("Newsgroups:"));
 
        addressbook_set_target_compose(compose);
        
@@ -6624,6 +6679,9 @@ static GtkWidget *compose_account_option_menu_create(Compose *compose)
        g_signal_connect(G_OBJECT(optmenu), "changed",
                        G_CALLBACK(account_activated),
                        compose);
+       g_signal_connect(G_OBJECT(from_name), "populate-popup",
+                        G_CALLBACK(compose_entry_popup_extend),
+                        NULL);
 
        gtk_box_pack_start(GTK_BOX(hbox), optmenubox, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), from_name, TRUE, TRUE, 0);
@@ -7991,7 +8049,7 @@ static void compose_send_cb(gpointer data, guint action, GtkWidget *widget)
        Compose *compose = (Compose *)data;
        
        if (prefs_common.work_offline && 
-           !inc_offline_should_override(
+           !inc_offline_should_override(TRUE,
                _("Claws Mail needs network access in order "
                  "to send this email.")))
                return;
@@ -8539,15 +8597,21 @@ static void entry_allsel(GtkWidget *entry)
 
 static void compose_cut_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_cut_clipboard(compose->focused_editable);
 }
 
 static void compose_copy_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_copy_clipboard(compose->focused_editable);
 }
 
@@ -8567,8 +8631,11 @@ static void compose_paste_cb(Compose *compose)
 static void compose_paste_as_quote_cb(Compose *compose)
 {
        gint wrap_quote = prefs_common.linewrap_quote;
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable)) {
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           ) {
                /* let text_insert() (called directly or at a later time
                 * after the gtk_editable_paste_clipboard) know that 
                 * text is to be inserted as a quotation. implemented
@@ -8592,8 +8659,11 @@ static void compose_paste_no_wrap_cb(Compose *compose)
        gint prev_autowrap;
        GtkTextBuffer *buffer;
        BLOCK_WRAP();
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_paste_clipboard(compose, compose->focused_editable, FALSE,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
@@ -8604,8 +8674,11 @@ static void compose_paste_wrap_cb(Compose *compose)
        gint prev_autowrap;
        GtkTextBuffer *buffer;
        BLOCK_WRAP();
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_paste_clipboard(compose, compose->focused_editable, TRUE,
                        GDK_SELECTION_CLIPBOARD, NULL);
        UNBLOCK_WRAP();
@@ -8613,8 +8686,11 @@ static void compose_paste_wrap_cb(Compose *compose)
 
 static void compose_allsel_cb(Compose *compose)
 {
-       if (compose->focused_editable &&
-           GTK_WIDGET_HAS_FOCUS(compose->focused_editable))
+       if (compose->focused_editable 
+#ifndef MAEMO
+           && GTK_WIDGET_HAS_FOCUS(compose->focused_editable)
+#endif
+           )
                entry_allsel(compose->focused_editable);
 }
 
@@ -8937,6 +9013,44 @@ static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 
        if (GTK_IS_EDITABLE(widget) || GTK_IS_TEXT_VIEW(widget))
                compose->focused_editable = widget;
+       
+#ifdef MAEMO
+       if (GTK_IS_TEXT_VIEW(widget) 
+           && gtk_paned_get_child1(GTK_PANED(compose->paned)) != compose->edit_vbox) {
+               gtk_widget_ref(compose->notebook);
+               gtk_widget_ref(compose->edit_vbox);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->notebook);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->edit_vbox);
+               gtk_paned_add1(GTK_PANED(compose->paned), compose->edit_vbox);
+               gtk_paned_add2(GTK_PANED(compose->paned), compose->notebook);
+               gtk_widget_unref(compose->notebook);
+               gtk_widget_unref(compose->edit_vbox);
+               g_signal_handlers_block_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+               gtk_widget_grab_focus(widget);
+               g_signal_handlers_unblock_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+       } else if (!GTK_IS_TEXT_VIEW(widget) 
+                  && gtk_paned_get_child1(GTK_PANED(compose->paned)) != compose->notebook) {
+               gtk_widget_ref(compose->notebook);
+               gtk_widget_ref(compose->edit_vbox);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->notebook);
+               gtk_container_remove(GTK_CONTAINER(compose->paned), compose->edit_vbox);
+               gtk_paned_add1(GTK_PANED(compose->paned), compose->notebook);
+               gtk_paned_add2(GTK_PANED(compose->paned), compose->edit_vbox);
+               gtk_widget_unref(compose->notebook);
+               gtk_widget_unref(compose->edit_vbox);
+               g_signal_handlers_block_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+               gtk_widget_grab_focus(widget);
+               g_signal_handlers_unblock_by_func(G_OBJECT(widget),
+                                       G_CALLBACK(compose_grab_focus_cb),
+                                       compose);
+       }
+#endif
 }
 
 static void compose_changed_cb(GtkTextBuffer *textbuf, Compose *compose)
@@ -9248,10 +9362,6 @@ static gboolean compose_headerentry_changed_cb(GtkWidget *entry,
                                    ComposeHeaderEntry *headerentry)
 {
        if (strlen(gtk_entry_get_text(GTK_ENTRY(entry))) != 0) {
-               headerentry->compose->header_list =
-                       g_slist_append(headerentry->compose->header_list,
-                                      headerentry);
-               
                compose_create_header_entry(headerentry->compose);
                g_signal_handlers_disconnect_matched
                        (G_OBJECT(entry), G_SIGNAL_MATCH_DATA,
@@ -9609,7 +9719,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                gchar *entry = gtk_editable_get_chars(
                                                                GTK_EDITABLE(((ComposeHeaderEntry *)list->data)->entry), 0, -1);
 
-               if ( strcasecmp(header, (prefs_common.trans_hdr ? gettext("To:") : "To:")) == 0 ) {
+               if ( strcasecmp(header, prefs_common_translated_header_name("To:")) == 0 ) {
                        if ( newmsginfo->to == NULL ) {
                                newmsginfo->to = g_strdup(entry);
                        } else {
@@ -9618,7 +9728,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                                newmsginfo->to = tmp;
                        }
                } else
-               if ( strcasecmp(header, (prefs_common.trans_hdr ? gettext("Cc:") : "Cc:")) == 0 ) {
+               if ( strcasecmp(header, prefs_common_translated_header_name("Cc:")) == 0 ) {
                        if ( newmsginfo->cc == NULL ) {
                                newmsginfo->cc = g_strdup(entry);
                        } else {
@@ -9628,7 +9738,7 @@ static MsgInfo *compose_msginfo_new_from_compose(Compose *compose)
                        }
                } else
                if ( strcasecmp(header,
-                                               (prefs_common.trans_hdr ? gettext("Newsgroups:") : "Newsgroups:")) == 0 ) {
+                                               prefs_common_translated_header_name("Newsgroups:")) == 0 ) {
                        if ( newmsginfo->newsgroups == NULL ) {
                                newmsginfo->newsgroups = g_strdup(entry);
                        } else {