0956eb0fb8d620b66d095c19e423dec2456b6c0f
[modest] / src / modest-tny-msg-actions.c
1 /* modest-ui.c */
2
3 /* insert (c)/licensing information) */
4
5 #include <gtk/gtk.h>
6 #include <gtkhtml/gtkhtml.h>
7
8 /* TODO: put in auto* */
9 #include <tny-text-buffer-stream.h>
10 #include <tny-msg-mime-part-iface.h>
11 #include <tny-msg-iface.h>
12
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif /*HAVE_CONFIG_H */
16
17 #include "modest-tny-msg-actions.h"
18 #include "modest-text-utils.h"
19
20
21 /* private */
22 static gchar *quote_msg (const TnyMsgIface * src, const gchar * from,
23                          time_t sent_date, gint limit, gboolean textorhtml);
24 static GtkTextBuffer *htmltotext (TnyMsgMimePartIface * body);
25
26
27 static GtkTextBuffer *
28 htmltotext (TnyMsgMimePartIface * body)
29 {
30         GtkTextBuffer *buf;
31
32 #ifdef ACTIVATE_HACKS /* it still doesn't work, don't bother! */
33         GtkWidget *html, *win;
34         TnyStreamIface *stream;
35         GtkClipboard *clip;
36         gchar *text;
37
38         win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
39         html = gtk_html_new ();
40         gtk_container_add (GTK_CONTAINER (win), html);
41
42         gtk_html_set_editable (GTK_HTML (html), FALSE);
43         gtk_html_allow_selection (GTK_HTML (html), TRUE);
44         stream = TNY_STREAM_IFACE (modest_tny_stream_gtkhtml_new
45                                    (gtk_html_begin (GTK_HTML (html))));
46
47         tny_stream_iface_reset (stream);
48         tny_msg_mime_part_iface_decode_to_stream (body, stream);
49         tny_stream_iface_reset (stream);
50         g_object_unref (G_OBJECT (stream));
51
52         gtk_widget_show_all (win);
53         gtk_html_select_all (GTK_HTML (html));
54         clip = gtk_widget_get_clipboard (html, GDK_SELECTION_PRIMARY);
55         /*clip = gtk_widget_get_clipboard(html, GDK_SELECTION_CLIPBOARD);*/
56         text = gtk_clipboard_wait_for_text (clip);
57
58         buf = gtk_text_buffer_new (NULL);
59         gtk_text_buffer_set_text (buf, text, -1);
60         g_free (text);
61         /* destroy win & html */
62 #else
63         buf = gtk_text_buffer_new (NULL);
64 #endif
65         return buf;
66 }
67
68 gchar *
69 modest_tny_msg_actions_quote (const TnyMsgIface * self, const gchar * from,
70                               time_t sent_date, gint limit,
71                               const gchar * to_quote)
72 {
73         gchar *quoted;
74
75         /* 3 cases: */
76
77         /* a) quote text from selection */
78         if (to_quote != NULL) 
79                 return modest_text_utils_quote (to_quote, from, sent_date,
80                                                 limit);
81         
82         /* b) try to find a text/plain part in the msg and quote it */
83         quoted = quote_msg (self, from, sent_date, limit, FALSE);
84         if (quoted)
85                 return quoted;
86         
87         /* c) if that fails, try text/html */
88         return quote_msg (self, from, sent_date, limit, TRUE);
89 }
90
91
92 static gchar *
93 quote_msg (const TnyMsgIface * src, const gchar * from, time_t sent_date,
94            gint limit, gboolean want_html)
95 {
96         TnyStreamIface *stream;
97         TnyMsgMimePartIface *body;
98         GtkTextBuffer *buf;
99         GtkTextIter start, end;
100         const gchar *to_quote;
101         gchar *quoted;
102
103         /* the cast makes me uneasy... */
104         body = modest_tny_msg_actions_find_body_part((TnyMsgIface *) src, want_html);
105         if (!body)
106                 return NULL;
107
108         if (want_html) 
109                 buf = htmltotext (body);
110         else {
111                 buf = gtk_text_buffer_new (NULL);
112                 stream = TNY_STREAM_IFACE (tny_text_buffer_stream_new (buf));
113                 tny_stream_iface_reset (stream);
114                 tny_msg_mime_part_iface_decode_to_stream (body, stream);
115                 tny_stream_iface_reset (stream);
116                 g_object_unref (stream);
117         }
118         
119         gtk_text_buffer_get_bounds (buf, &start, &end);
120         to_quote = gtk_text_buffer_get_text (buf, &start, &end, FALSE);
121         quoted = modest_text_utils_quote (to_quote, from, sent_date, limit);
122         g_object_unref (buf);
123
124         return quoted;
125 }
126
127
128 TnyMsgMimePartIface *
129 modest_tny_msg_actions_find_body_part (TnyMsgIface *self, gboolean want_html)
130 {
131         const gchar *mime_type = want_html ? "text/html" : "text/plain";
132         TnyMsgMimePartIface *part = NULL;
133         GList *parts;
134         
135         g_return_val_if_fail (self, NULL);
136         g_return_val_if_fail (mime_type, NULL);
137
138         parts  = (GList*) tny_msg_iface_get_parts (self);
139         while (parts && !part) {
140
141                 part = TNY_MSG_MIME_PART_IFACE(parts->data);
142
143                 if (!tny_msg_mime_part_iface_content_type_is (part, mime_type)
144                     ||tny_msg_mime_part_iface_is_attachment (part))
145                         part = NULL;
146                 parts = parts->next;
147         }
148
149         /* if were trying to find an HTML part and could find it,
150          * try to find a text/plain part instead
151          */
152         if (!part && want_html) 
153                 return modest_tny_msg_actions_find_body_part (self, FALSE);
154         else
155                 return part;
156 }