replace deprecated gtk_window_set_policy
[claws.git] / src / compose.c
index 8def5a210cd8201e73ddd728ba0676443208d488..e1adb887f42fdd69bc54acb7e87e6583463b2dcb 100644 (file)
@@ -374,7 +374,9 @@ static void compose_allsel_cb               (Compose        *compose);
 static void compose_advanced_action_cb (Compose                   *compose,
                                         ComposeCallAdvancedAction  action);
 
-static void compose_grab_focus_cb      (GtkWidget      *widget,
+static gboolean compose_grab_focus_cb  (GtkWidget      *widget,
+                                        Compose        *compose);
+static gboolean compose_grab_focus_before_cb   (GtkWidget      *widget,
                                         Compose        *compose);
 
 static void compose_changed_cb         (GtkTextBuffer  *textbuf,
@@ -730,6 +732,7 @@ Compose *compose_generic_new(PrefsAccount *account, const gchar *mailto, FolderI
        textview = GTK_TEXT_VIEW(compose->text);
        textbuf = gtk_text_view_get_buffer(textview);
 
+       undo_block(compose->undostruct);
 #ifdef USE_ASPELL
        if (item && item->prefs && item->prefs->enable_default_dictionary &&
            compose->gtkaspell) 
@@ -988,6 +991,7 @@ static void compose_generic_reply(MsgInfo *msginfo, gboolean quote,
        textview = (GTK_TEXT_VIEW(compose->text));
        textbuf = gtk_text_view_get_buffer(textview);
        
+       undo_block(compose->undostruct);
 #ifdef USE_ASPELL
        if (msginfo->folder && msginfo->folder->prefs && 
            msginfo->folder->prefs && 
@@ -1808,17 +1812,24 @@ static gchar *compose_quote_fmt(Compose *compose, MsgInfo *msginfo,
                g_signal_handlers_block_by_func(G_OBJECT(buffer),
                                        G_CALLBACK(compose_changed_cb),
                                        compose);
+               g_signal_handlers_block_by_func(G_OBJECT(buffer),
+                                       G_CALLBACK(text_inserted),
+                                       compose);
                
                mark = gtk_text_buffer_get_insert(buffer);
                gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
 
                lastp = strchr(p, '\n');
                len = lastp ? lastp - p + 1 : -1;
+
                gtk_text_buffer_insert(buffer, &iter, p, len);
 
                g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
                                        G_CALLBACK(compose_changed_cb),
                                        compose);
+               g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
+                                       G_CALLBACK(text_inserted),
+                                       compose);
                
                if (lastp)
                        p = lastp + 1;
@@ -2123,6 +2134,10 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
        mark = gtk_text_buffer_get_insert(buffer);
        gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark);
 
+       g_signal_handlers_block_by_func(G_OBJECT(buffer),
+                                       G_CALLBACK(text_inserted),
+                                       compose);
+
        while (fgets(buf, sizeof(buf), fp) != NULL) {
                const gchar *cur_encoding = conv_get_current_charset_str();
                gchar *str = conv_codeset_strdup(buf, cur_encoding, CS_UTF_8);
@@ -2142,6 +2157,10 @@ static ComposeInsertResult compose_insert_file(Compose *compose, const gchar *fi
                g_free (str);
        }
 
+       g_signal_handlers_unblock_by_func(G_OBJECT(buffer),
+                                         G_CALLBACK(text_inserted),
+                                         compose);
+
        fclose(fp);
 
        if (badtxt)
@@ -2251,6 +2270,7 @@ static void compose_use_signing(Compose *compose, gboolean use_signing)
        ifactory = gtk_item_factory_from_widget(compose->menubar);
        menuitem = gtk_item_factory_get_item
                (ifactory, "/Message/Sign");
+
        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), 
                                       use_signing);
        compose_update_gnupg_mode_menu_item(compose);
@@ -2704,6 +2724,35 @@ static guint ins_quote(GtkTextBuffer *textbuf, GtkTextIter *iter,
        return ins_len;
 }
 
+static gboolean is_sig_separator(Compose *compose, GtkTextBuffer *textbuf, guint start_pos) 
+{
+       char *text = NULL;
+       GtkTextIter iter; 
+       GtkTextIter end_iter;
+       if (!compose->account->sig_sep)
+               return FALSE;
+       
+       gtk_text_buffer_get_iter_at_offset(textbuf, &iter, start_pos+1);
+       gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter,
+               start_pos+strlen(compose->account->sig_sep)+1);
+
+       if (!strcmp(gtk_text_iter_get_text(&iter, &end_iter),
+                       compose->account->sig_sep)) {
+               /* check \n */
+               gtk_text_buffer_get_iter_at_offset(textbuf, &iter,
+                       start_pos+strlen(compose->account->sig_sep)+1);
+               gtk_text_buffer_get_iter_at_offset(textbuf, &end_iter,
+                       start_pos+strlen(compose->account->sig_sep)+2);
+
+               if (!strcmp(gtk_text_iter_get_text(&iter, &end_iter),"\n"));
+                       return TRUE;
+               
+
+       }
+
+       return FALSE;
+}
+
 /* check if we should join the next line */
 static gboolean join_next_line_is_needed(GtkTextBuffer *textbuf,
                                         guint start_pos, guint tlen,
@@ -2720,6 +2769,7 @@ static gboolean join_next_line_is_needed(GtkTextBuffer *textbuf,
                gtk_text_buffer_get_iter_at_offset(textbuf, &iter,
                                                   start_pos + indent_len);
                GET_CHAR(&iter, cbuf, ch_len);
+               
                if (ch_len > 0 && (cbuf[0] != '\n'))
                        do_join = TRUE;
        }
@@ -2749,7 +2799,8 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
        guint linewrap_len = prefs_common.linewrap_len;
        gchar *qfmt = prefs_common.quotemark;
        gchar cbuf[CHAR_BUF_SIZE];
-
+       GtkTextMark *cursor_mark = gtk_text_buffer_get_insert(textbuf);
+       
        tlen = gtk_text_buffer_get_char_count(textbuf);
 
        for (; cur_pos < tlen; cur_pos++) {
@@ -2770,10 +2821,8 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                        guint tab_width = 8;
                        guint tab_offset = line_len % tab_width;
 
-                       if (tab_offset) {
-                               line_len += tab_width - tab_offset - 1;
-                               cur_len = line_len;
-                       }
+                       line_len += tab_width - tab_offset - 1;
+                       cur_len = line_len;
                }
 
                /* we have encountered line break */
@@ -2783,10 +2832,11 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
 
                        /* should we join the next line */
                        if ((autowrap || i_len != cur_len) && do_delete &&
+                       !is_sig_separator(compose, textbuf, cur_pos+i_len) &&
                            join_next_line_is_needed
-                               (textbuf, cur_pos + 1, tlen, i_len, autowrap))
+                               (textbuf, cur_pos + 1, tlen, i_len, autowrap)) {
                                do_delete = TRUE;
-                       else
+                       else
                                do_delete = FALSE;
 
                        /* skip delete if it is continuous URL */
@@ -2832,8 +2882,20 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                                /* insert space if it's alphanumeric */
                                if ((cur_pos != line_pos) &&
                                    ((clen > 1) || isalnum((guchar)cb[0]))) {
+                                       GtkTextIter cursor_iter;
+                                       gboolean go_back = FALSE;
+                                       gtk_text_buffer_get_iter_at_mark(textbuf, &cursor_iter, cursor_mark);
+                                       if (gtk_text_iter_get_offset(&iter) ==
+                                                gtk_text_iter_get_offset(&cursor_iter))
+                                               go_back = TRUE;
+                                       
                                        gtk_text_buffer_insert(textbuf, &iter,
                                                               " ", 1);
+                                       if (go_back) {
+                                               gtk_text_buffer_get_iter_at_mark(textbuf, &cursor_iter, cursor_mark);
+                                               gtk_text_iter_backward_chars(&cursor_iter, 1);
+                                               gtk_text_buffer_place_cursor(textbuf, &cursor_iter);
+                                       }
                                        tlen++;
                                }
 
@@ -2959,9 +3021,9 @@ static void compose_wrap_line_all_full(Compose *compose, gboolean autowrap)
                        /* start over with current line */
                        is_new_line = TRUE;
                        line_len = cur_len = 0;
-                       if (autowrap || i_len > 0)
+                       if (autowrap || i_len > 0) {
                                do_delete = TRUE;
-                       else
+                       else
                                do_delete = FALSE;
 #ifdef WRAP_DEBUG
                        g_print("after CR insert ");
@@ -4454,6 +4516,7 @@ static gint compose_write_headers(Compose *compose, FILE *fp,
 #endif
        /* Organization */
        if (compose->account->organization &&
+           strlen(compose->account->organization) &&
            !IS_IN_CUSTOM_HEADER("Organization")) {
                compose_convert_header(buf, sizeof(buf),
                                       compose->account->organization,
@@ -4612,7 +4675,7 @@ static void compose_convert_header(gchar *dest, gint len, gchar *src,
 
        if (len < 1) return;
 
-       tmpstr = conv_codeset_strdup(src, CS_UTF_8, conv_get_current_charset_str());
+       tmpstr = g_strdup(src);
 
        subst_char(tmpstr, '\n', ' ');
        subst_char(tmpstr, '\r', ' ');
@@ -4695,6 +4758,10 @@ static void compose_create_header_entry(Compose *compose)
        }
        if (header)
                gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), header);
+       g_signal_connect(G_OBJECT(GTK_COMBO(combo)->entry), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_before_cb), compose);
+       g_signal_connect_after(G_OBJECT(GTK_COMBO(combo)->entry), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_cb), compose);
 
        /* Entry field */
        entry = gtk_entry_new(); 
@@ -4710,6 +4777,8 @@ static void compose_create_header_entry(Compose *compose)
        g_signal_connect(G_OBJECT(entry), "activate", 
                         G_CALLBACK(text_activated), compose);
        g_signal_connect(G_OBJECT(entry), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_before_cb), compose);
+       g_signal_connect_after(G_OBJECT(entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        g_signal_connect(G_OBJECT(entry), "button-press-event", 
                         G_CALLBACK(compose_headerentry_button_pressed),
@@ -4959,6 +5028,8 @@ static GtkWidget *compose_create_others(Compose *compose)
        gtk_table_attach_defaults(GTK_TABLE(table), savemsg_entry, 1, 2, rowcount, rowcount + 1);
        gtk_editable_set_editable(GTK_EDITABLE(savemsg_entry), prefs_common.savemsg);
        g_signal_connect(G_OBJECT(savemsg_entry), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_before_cb), compose);
+       g_signal_connect_after(G_OBJECT(savemsg_entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        if (account_get_special_folder(compose->account, F_OUTBOX)) {
                folderidentifier = folder_item_get_identifier(account_get_special_folder
@@ -5061,7 +5132,7 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        compose->account = account;
 
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-       gtk_window_set_policy(GTK_WINDOW(window), TRUE, TRUE, FALSE);
+       gtk_window_set_resizable(GTK_WINDOW(window), TRUE);
        gtk_widget_set_size_request(window, -1, prefs_common.compose_height);
        gtk_window_set_wmclass(GTK_WINDOW(window), "compose window", "Sylpheed");
 
@@ -5135,6 +5206,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        g_signal_connect(G_OBJECT(subject_entry), "activate", 
                         G_CALLBACK(text_activated), compose);
        g_signal_connect(G_OBJECT(subject_entry), "grab_focus",
+                        G_CALLBACK(compose_grab_focus_before_cb), compose);
+       g_signal_connect_after(G_OBJECT(subject_entry), "grab_focus",
                         G_CALLBACK(compose_grab_focus_cb), compose);
        gtk_widget_show(subject_entry);
        compose->subject_entry = subject_entry;
@@ -5170,10 +5243,6 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
        clipboard = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
        gtk_text_buffer_add_selection_clipboard(buffer, clipboard);
        
-       if (prefs_common.smart_wrapping) {      
-               gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
-       }               
-
        gtk_container_add(GTK_CONTAINER(scrolledwin), text);
 
        g_signal_connect_after(G_OBJECT(text), "size_allocate",
@@ -5349,7 +5418,8 @@ static Compose *compose_create(PrefsAccount *account, ComposeMode mode)
                                                  prefs_common.misspelled_col,
                                                  prefs_common.check_while_typing,
                                                  prefs_common.use_alternate,
-                                                 GTK_TEXT_VIEW(text));
+                                                 GTK_TEXT_VIEW(text),
+                                                 GTK_WINDOW(compose->window));
                        if (!gtkaspell) {
                                alertpanel_error(_("Spell checker could not "
                                                "be started.\n%s"),
@@ -6567,6 +6637,8 @@ static void compose_draft_cb(gpointer data, guint action, GtkWidget *widget)
        if (newmsginfo) {
                procmsg_msginfo_unset_flags(newmsginfo, ~0, ~0);
                procmsg_msginfo_set_flags(newmsginfo, 0, MSG_DRAFT);
+               if (compose_use_attach(compose))
+                       procmsg_msginfo_set_flags(newmsginfo, 0, MSG_HAS_ATTACHMENT);
                procmsg_msginfo_free(newmsginfo);
        }
        
@@ -6613,7 +6685,7 @@ static void compose_attach_cb(gpointer data, guint action, GtkWidget *widget)
        if (compose->redirect_filename != NULL)
                return;
 
-       file_list = filesel_select_multiple_files(_("Select file"));
+       file_list = filesel_select_multiple_files_open(_("Select file"));
 
        if (file_list) {
                GList *tmp;
@@ -6634,7 +6706,7 @@ static void compose_insert_file_cb(gpointer data, guint action,
        Compose *compose = (Compose *)data;
        GList *file_list;
 
-       file_list = filesel_select_multiple_files(_("Select file"));
+       file_list = filesel_select_multiple_files_open(_("Select file"));
 
        if (file_list) {
                GList *tmp;
@@ -7153,10 +7225,38 @@ static void compose_advanced_action_cb(Compose *compose,
        }
 }
 
-static void compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
+static gchar *cliptext = NULL;
+
+static gboolean compose_grab_focus_before_cb(GtkWidget *widget, Compose *compose)
+{
+       gchar *str = NULL;
+       GtkClipboard *clip = gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE));
+       if (cliptext)
+               g_free(cliptext);
+       if (gtk_clipboard_wait_is_text_available(clip))
+               cliptext = gtk_clipboard_wait_for_text(clip);
+       
+       return FALSE;
+}
+
+static gboolean compose_grab_focus_cb(GtkWidget *widget, Compose *compose)
 {
+       gchar *str = NULL;
+       GtkClipboard *clip = gtk_clipboard_get(gdk_atom_intern("PRIMARY", FALSE));
+       
+       if (GTK_IS_EDITABLE(widget)) {
+               str = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
+               gtk_editable_set_position(GTK_EDITABLE(widget), 
+                       strlen(str));
+               g_free(str);
+       }
+       if (cliptext)
+               gtk_clipboard_set_text(clip, cliptext, -1);
+
        if (GTK_IS_EDITABLE(widget) || GTK_IS_TEXT_VIEW(widget))
                compose->focused_editable = widget;
+       
+       return TRUE;
 }
 
 static void compose_changed_cb(GtkTextBuffer *textbuf, Compose *compose)
@@ -7171,7 +7271,6 @@ static void compose_toggle_autowrap_cb(gpointer data, guint action,
                                       GtkWidget *widget)
 {
        Compose *compose = (Compose *)data;
-
        compose->autowrap = GTK_CHECK_MENU_ITEM(widget)->active;
        if (compose->autowrap)
                compose_wrap_line_all_full(compose, TRUE);