aboutsummaryrefslogtreecommitdiffstats
path: root/mail
diff options
context:
space:
mode:
Diffstat (limited to 'mail')
-rw-r--r--mail/ChangeLog13
-rw-r--r--mail/mail-display.c185
-rw-r--r--mail/mail-format.c86
3 files changed, 247 insertions, 37 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index d42fca5110..1088a86345 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,16 @@
+2001-04-23 Jon Trowbridge <trow@ximian.com>
+
+ * mail-display.c (html_button_press_event): Check for mailto:
+ links, and pop up our mail address menu when we find one.
+ (make_popup_window): The main piece of code (ignoring a zillion
+ little callbacks) to pop up our windows with reasonable semantics
+ for having them close automatically.
+ (mail_text_write): Enable converting addresses to mailto links
+ in message bodies.
+
+ * mail-format.c (write_address): Simplify code, removing Radek's
+ <DATA> hacks. Write out addresses as mailto: links.
+
2001-04-23 Jeffrey Stedfast <fejj@ximian.com>
* mail-callbacks.c (do_view_message): Use the message-browser
diff --git a/mail/mail-display.c b/mail/mail-display.c
index d04893d86d..7c88ebcb94 100644
--- a/mail/mail-display.c
+++ b/mail/mail-display.c
@@ -920,7 +920,7 @@ mail_text_write (GtkHTML *html, GtkHTMLStream *stream,
htmltext = e_text_to_html_full (buf,
E_TEXT_TO_HTML_CONVERT_URLS |
- /* E_TEXT_TO_HTML_CONVERT_ADDRESSES | */
+ E_TEXT_TO_HTML_CONVERT_ADDRESSES |
E_TEXT_TO_HTML_CONVERT_NL |
E_TEXT_TO_HTML_CONVERT_SPACES |
(mail_config_get_citation_highlight () ? E_TEXT_TO_HTML_MARK_CITATION : 0),
@@ -1114,6 +1114,170 @@ static EPopupMenu link_menu [] = {
TERMINATOR
};
+
+/*
+ * Create a window and popup our widget, with reasonable semantics for the popup
+ * disappearing, etc.
+ */
+
+typedef struct _PopupInfo PopupInfo;
+struct _PopupInfo {
+ GtkWidget *w;
+ GtkWidget *win;
+ guint destroy_timeout;
+ guint widget_destroy_handle;
+};
+
+/* Aiieee! Global Data! */
+static GtkWidget *the_popup = NULL;
+
+static void
+popup_info_free (PopupInfo *pop)
+{
+ if (pop) {
+ if (pop->destroy_timeout)
+ gtk_timeout_remove (pop->destroy_timeout);
+
+ g_free (pop);
+ }
+}
+
+static void
+popup_widget_destroy_cb (GtkWidget *w, gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ gtk_widget_destroy (pop->win);
+}
+
+static void
+popup_window_destroy_cb (GtkWidget *w, gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ if (pop->widget_destroy_handle) {
+ gtk_signal_disconnect (GTK_OBJECT (pop->w), pop->widget_destroy_handle);
+ pop->widget_destroy_handle = 0;
+ }
+
+ the_popup = NULL;
+
+ popup_info_free (pop);
+}
+
+static gint
+popup_timeout_cb (gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ pop->destroy_timeout = 0;
+ gtk_widget_destroy (pop->win);
+
+ return 0;
+}
+
+static gint
+popup_enter_cb (GtkWidget *w, GdkEventCrossing *ev, gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ if (pop->destroy_timeout)
+ gtk_timeout_remove (pop->destroy_timeout);
+
+ return 0;
+}
+
+static gint
+popup_leave_cb (GtkWidget *w, GdkEventCrossing *ev, gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ if (pop->destroy_timeout)
+ gtk_timeout_remove (pop->destroy_timeout);
+ pop->destroy_timeout = gtk_timeout_add (500, popup_timeout_cb, pop);
+
+ return 0;
+}
+
+static void
+popup_realize_cb (GtkWidget *widget, gpointer user_data)
+{
+ PopupInfo *pop = (PopupInfo *) user_data;
+
+ gtk_widget_add_events (pop->win, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
+ gtk_widget_add_events (pop->w, GDK_BUTTON_PRESS_MASK);
+
+ if (pop->destroy_timeout == 0)
+ pop->destroy_timeout = gtk_timeout_add (5000, popup_timeout_cb, pop);
+}
+
+static void
+popup_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer user_data)
+{
+ gint x, y, w, h, xmax, ymax;
+
+ xmax = gdk_screen_width ();
+ ymax = gdk_screen_height ();
+
+ gdk_window_get_pointer (NULL, &x, &y, NULL);
+ w = alloc->width;
+ h = alloc->height;
+ x = CLAMP (x - w/2, 0, xmax - w);
+ y = CLAMP (y - h/2, 0, ymax - h);
+ gtk_widget_set_uposition (widget, x, y);
+
+}
+
+static void
+make_popup_window (GtkWidget *w)
+{
+ PopupInfo *pop = g_new0 (PopupInfo, 1);
+ GtkWidget *fr;
+
+ /* Only allow for one popup at a time. Ugly. */
+ if (the_popup)
+ gtk_widget_destroy (the_popup);
+
+ pop->w = w;
+ the_popup = pop->win = gtk_window_new (GTK_WINDOW_POPUP);
+ fr = gtk_frame_new (NULL);
+
+ gtk_container_add (GTK_CONTAINER (pop->win), fr);
+ gtk_container_add (GTK_CONTAINER (fr), w);
+
+ gtk_window_set_policy (GTK_WINDOW (pop->win), FALSE, FALSE, FALSE);
+
+
+ pop->widget_destroy_handle = gtk_signal_connect (GTK_OBJECT (w),
+ "destroy",
+ GTK_SIGNAL_FUNC (popup_widget_destroy_cb),
+ pop);
+ gtk_signal_connect (GTK_OBJECT (pop->win),
+ "destroy",
+ GTK_SIGNAL_FUNC (popup_window_destroy_cb),
+ pop);
+ gtk_signal_connect (GTK_OBJECT (pop->win),
+ "enter_notify_event",
+ GTK_SIGNAL_FUNC (popup_enter_cb),
+ pop);
+ gtk_signal_connect (GTK_OBJECT (pop->win),
+ "leave_notify_event",
+ GTK_SIGNAL_FUNC (popup_leave_cb),
+ pop);
+ gtk_signal_connect_after (GTK_OBJECT (pop->win),
+ "realize",
+ GTK_SIGNAL_FUNC (popup_realize_cb),
+ pop);
+ gtk_signal_connect (GTK_OBJECT (pop->win),
+ "size_allocate",
+ GTK_SIGNAL_FUNC (popup_size_allocate_cb),
+ pop);
+
+ gtk_widget_show (w);
+ gtk_widget_show (fr);
+ gtk_widget_show (pop->win);
+}
+
static int
html_button_press_event (GtkWidget *widget, GdkEventButton *event, MailDisplay *mail_display)
{
@@ -1131,25 +1295,32 @@ html_button_press_event (GtkWidget *widget, GdkEventButton *event, MailDisplay *
e = GTK_HTML (widget)->engine;
point = html_engine_get_point_at (e, event->x + e->x_offset, event->y + e->y_offset, FALSE);
+
if (point) {
- email = (const gchar *) html_object_get_data (point->object, "email");
- if (email) {
- name = (const gchar *) html_object_get_data (point->object, "name");
+ const gchar *url;
+
+ url = html_object_get_url (point->object);
+
+ if (url && !g_strncasecmp (url, "mailto:", 7)) {
popup_thing = bonobo_widget_new_control ("OAFIID:GNOME_Evolution_Addressbook_AddressPopup",
CORBA_OBJECT_NIL);
bonobo_widget_set_property (BONOBO_WIDGET (popup_thing),
- "name", name,
- "email", email,
+ "name", "",
+ "email", url+7,
NULL);
- gtk_widget_show (popup_thing);
+ make_popup_window (popup_thing);
} else if ((link = html_object_get_url (point->object))) {
+
e_popup_menu_run (link_menu, (GdkEvent *) event, 0, 0, mail_display);
+
}
+
html_point_destroy (point);
}
+
return TRUE;
}
}
diff --git a/mail/mail-format.c b/mail/mail-format.c
index bd26438db3..3b09e43e8c 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -648,6 +648,22 @@ write_subject (const char *subject, int flags, GtkHTML *html, GtkHTMLStream *str
g_free (encoded_subj);
}
+static gchar *
+elide_quotes (const gchar *str)
+{
+ gchar *cpy = g_strdup (str);
+ gchar *c = cpy;
+
+ if (c) {
+ while (*c) {
+ if (*c == '"')
+ *c = '\'';
+ ++c;
+ }
+ }
+ return cpy;
+}
+
static void
write_address(MailDisplay *md, const CamelInternetAddress *addr, const char *field_name, int flags)
{
@@ -662,43 +678,53 @@ write_address(MailDisplay *md, const CamelInternetAddress *addr, const char *fie
i = 0;
while (camel_internet_address_get (addr, i, &name, &email)) {
-
- if ((name && *name) || (email && *email)) {
+ gboolean have_name = name && *name;
+ gboolean have_email = email && *email;
+ gchar *name_arg = NULL;
+ gchar *email_arg = NULL;
+ gchar *name_disp = NULL;
+ gchar *email_disp = NULL;
+
+ if (have_name) {
+ name_arg = elide_quotes (name);
+ name_disp = e_text_to_html (name, 0);
+ }
- /* we need these <B> </B> to separate HTMLText objects */
- mail_html_write (md->html, md->stream, i ? ",<B> </B> " : "<td>");
- mail_html_write (md->html, md->stream, " ");
+ if (have_email) {
+ email_arg = elide_quotes (email);
+ email_disp = e_text_to_html (email, 0);
+ }
- name_set = mail_set = FALSE;
- if (name && *name) {
- mail_html_write (md->html, md->stream,
- "<!--+GtkHTML:<DATA class=\"Text\" key=\"name\" value=\"%s\">-->",
- name);
- name_set = TRUE;
- }
+ mail_html_write (md->html, md->stream, i ? ", " : "<td>");
+
+ if (have_email || have_name) {
- if (email && *email) {
- mail_html_write (md->html, md->stream,
- "<!--+GtkHTML:<DATA class=\"Text\" key=\"email\" value=\"%s\">-->",
- email);
- mail_set = TRUE;
+ if (!have_email) {
+ email_arg = g_strdup ("???");
+ email_disp = g_strdup ("???");
}
-
- if (name && *name)
- mail_html_write (md->html, md->stream, "%s ", name);
- if (email && *email)
- mail_html_write (md->html, md->stream, "%s%s%s",
- name && *name ? "&lt;" : "",
- email,
- name && *name ? "&gt;" : "");
- if (name_set)
+
+ if (have_name) {
mail_html_write (md->html, md->stream,
- "<!--+GtkHTML:<DATA class=\"Text\" clear=\"name\">-->");
- if (mail_set)
+ "%s &lt;<a href=\"mailto:%s <%s>\">%s</a>&gt;",
+ name_disp, name_arg, email_arg, email_disp);
+ } else {
mail_html_write (md->html, md->stream,
- "<!--+GtkHTML:<DATA class=\"Text\" clear=\"email\">-->");
+ "<a href=\"mailto:%s\">%s</a>",
+ email_arg, email_disp);
+ }
+
+ } else {
+
+ mail_html_write (md->html, md->stream, "<i>Bad Address</i>");
+
}
-
+
+ g_free (name_arg);
+ g_free (email_arg);
+ g_free (name_disp);
+ g_free (email_disp);
+
++i;
}
mail_html_write (md->html, md->stream, "</td></tr>"); /* Finish up the table row */