diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 13 | ||||
-rw-r--r-- | mail/mail-display.c | 185 | ||||
-rw-r--r-- | mail/mail-format.c | 86 |
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 ? "<" : "", - email, - name && *name ? ">" : ""); - if (name_set) + + if (have_name) { mail_html_write (md->html, md->stream, - "<!--+GtkHTML:<DATA class=\"Text\" clear=\"name\">-->"); - if (mail_set) + "%s <<a href=\"mailto:%s <%s>\">%s</a>>", + 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 */ |