diff options
-rw-r--r-- | addressbook/ChangeLog | 13 | ||||
-rw-r--r-- | addressbook/gui/component/e-address-popup.c | 119 | ||||
-rw-r--r-- | addressbook/gui/component/e-address-popup.h | 1 | ||||
-rw-r--r-- | e-util/ChangeLog | 6 | ||||
-rw-r--r-- | e-util/e-html-utils.c | 16 | ||||
-rw-r--r-- | mail/ChangeLog | 13 | ||||
-rw-r--r-- | mail/mail-display.c | 185 | ||||
-rw-r--r-- | mail/mail-format.c | 86 |
8 files changed, 294 insertions, 145 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog index f5b7730140..9b6ae63628 100644 --- a/addressbook/ChangeLog +++ b/addressbook/ChangeLog @@ -1,3 +1,16 @@ +2001-04-23 Jon Trowbridge <trow@ximian.com> + + * gui/component/e-address-popup.c: Lots of code has been + simplified here. + (e_address_popup_factory_new_control): Rather than directly pop + our control up in a window (via the e_address_popup_popup + function, which is now gone), just return the widget and let the + caller do the popping. This works better, since it means we don't + have to work around the vagaries of bonobo focus & event handling. + (e_address_popup_set_name): Refresh when both name & email have + been set, rather than checking a stupid counter. + (e_address_popup_set_email): Ditto. + 2001-04-22 Christopher James Lahey <clahey@ximian.com> * gui/component/addressbook-storage.c diff --git a/addressbook/gui/component/e-address-popup.c b/addressbook/gui/component/e-address-popup.c index 7aebeacf21..134ce1241b 100644 --- a/addressbook/gui/component/e-address-popup.c +++ b/addressbook/gui/component/e-address-popup.c @@ -31,6 +31,7 @@ #include <bonobo/bonobo-property-bag.h> #include <bonobo/bonobo-generic-factory.h> #include <gal/widgets/e-popup-menu.h> +#include <gal/widgets/e-unicode.h> #include <addressbook/backend/ebook/e-book.h> #include <addressbook/backend/ebook/e-book-util.h> #include <addressbook/contact-editor/e-contact-editor.h> @@ -41,11 +42,6 @@ static GtkObjectClass *parent_class; static EBook *common_book = NULL; /* still sort of lame */ static void e_address_popup_destroy (GtkObject *); -static void e_address_popup_realize (GtkWidget *); -static gint e_address_popup_button_press_event (GtkWidget *, GdkEventButton *ev); -static gint e_address_popup_enter_notify_event (GtkWidget *, GdkEventCrossing *ev); -static gint e_address_popup_leave_notify_event (GtkWidget *, GdkEventCrossing *ev); - static void e_address_popup_query (EAddressPopup *); @@ -53,16 +49,10 @@ static void e_address_popup_class_init (EAddressPopupClass *klass) { GtkObjectClass *object_class = (GtkObjectClass *) klass; - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); parent_class = GTK_OBJECT_CLASS (gtk_type_class (gtk_event_box_get_type ())); object_class->destroy = e_address_popup_destroy; - - widget_class->realize = e_address_popup_realize; - widget_class->button_press_event = e_address_popup_button_press_event; - widget_class->enter_notify_event = e_address_popup_enter_notify_event; - widget_class->leave_notify_event = e_address_popup_leave_notify_event; } static void @@ -89,57 +79,6 @@ e_address_popup_destroy (GtkObject *obj) GTK_OBJECT_CLASS (parent_class)->destroy (obj); } -static void -e_address_popup_realize (GtkWidget *w) -{ - EAddressPopup *pop = E_ADDRESS_POPUP (w); - - if (GTK_WIDGET_CLASS (parent_class)->realize) - GTK_WIDGET_CLASS (parent_class)->realize (w); - - /* Start the death count. */ - pop->leave_timeout_tag = gtk_timeout_add (10000, (GtkFunction) gtk_widget_destroy, pop); -} - -static gint -e_address_popup_button_press_event (GtkWidget *w, GdkEventButton *ev) -{ - gtk_widget_destroy (w); - return FALSE; -} - -static gint -e_address_popup_enter_notify_event (GtkWidget *w, GdkEventCrossing *ev) -{ - EAddressPopup *pop = E_ADDRESS_POPUP (w); - - if (pop->leave_timeout_tag) { - gtk_timeout_remove (pop->leave_timeout_tag); - pop->leave_timeout_tag = 0; - } - - return FALSE; -} - -static gint -e_address_popup_leave_notify_event (GtkWidget *w, GdkEventCrossing *ev) -{ - EAddressPopup *pop = E_ADDRESS_POPUP (w); - const gint slack=5; - gint x, y; - - /* Manually check our "leave" events to avoid weird erroneous leaves - that seem related to bonobo... */ - gdk_window_get_pointer (w->window, &x, &y, NULL); - if (slack <= x && x < w->allocation.width-slack && slack <= y && y < w->allocation.height-slack) - return FALSE; - - if (pop->leave_timeout_tag == 0) - pop->leave_timeout_tag = gtk_timeout_add (1000, (GtkFunction) gtk_widget_destroy, pop); - - return FALSE; -} - GtkType e_address_popup_get_type (void) { @@ -199,9 +138,7 @@ e_address_popup_set_name (EAddressPopup *pop, const gchar *name) pop->name = g_strdup (name); g_strstrip (pop->name); - ++pop->set_count; - - if (pop->set_count >= 2) + if (pop->name && pop->email) e_address_popup_refresh_names (pop); } @@ -214,9 +151,7 @@ e_address_popup_set_email (EAddressPopup *pop, const gchar *email) pop->email = g_strdup (email); g_strstrip (pop->email); - ++pop->set_count; - - if (pop->set_count >= 2) + if (pop->name && pop->email) e_address_popup_refresh_names (pop); } @@ -278,36 +213,6 @@ e_address_popup_new (void) return GTK_WIDGET (pop); } -static GtkWidget * -e_address_popup_popup (EAddressPopup *pop) -{ - GtkWidget *win, *fr; - gint x, y; - - win = gtk_window_new (GTK_WINDOW_POPUP); - fr = gtk_frame_new (NULL); - gtk_container_add (GTK_CONTAINER (win), fr); - gtk_container_add (GTK_CONTAINER (fr), GTK_WIDGET (pop)); - - gtk_window_set_policy (GTK_WINDOW (win), FALSE, FALSE, FALSE); - - gdk_window_get_pointer (NULL, &x, &y, NULL); - x = MAX (x-10, 0); - y = MAX (y-10, 0); - gtk_widget_set_uposition (win, x, y); - - gtk_signal_connect_object (GTK_OBJECT (pop), - "destroy", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - GTK_OBJECT (win)); - - gtk_widget_show (GTK_WIDGET (pop)); - gtk_widget_show (fr); - gtk_widget_show (win); - - return win; -} - static void found_fields_cb (EBook *book, EBookStatus status, EList *writable_fields, gpointer closure) { @@ -351,7 +256,15 @@ e_address_popup_cardify (EAddressPopup *pop, ECard *card) static void add_contacts_cb (EAddressPopup *pop) { - e_contact_quick_add (pop->name, pop->email, NULL, NULL); + if (pop->email && *pop->email) { + + if (pop->name && *pop->name) + e_contact_quick_add (pop->name, pop->email, NULL, NULL); + else + e_contact_quick_add_free_form (pop->email, NULL, NULL); + + } + gtk_widget_destroy (GTK_WIDGET (pop)); } @@ -486,7 +399,13 @@ e_address_popup_factory_new_control (void) GtkWidget *w; w = e_address_popup_new (); - control = bonobo_control_new (e_address_popup_popup (E_ADDRESS_POPUP (w))); + control = bonobo_control_new (w); + gtk_widget_show (w); + + gtk_signal_connect_object (GTK_OBJECT (w), + "destroy", + GTK_SIGNAL_FUNC (bonobo_object_unref), + GTK_OBJECT (control)); bag = bonobo_property_bag_new (NULL, set_prop, w); bonobo_property_bag_add (bag, "name", PROPERTY_NAME, diff --git a/addressbook/gui/component/e-address-popup.h b/addressbook/gui/component/e-address-popup.h index cac060fb4a..1ecfc773c7 100644 --- a/addressbook/gui/component/e-address-popup.h +++ b/addressbook/gui/component/e-address-popup.h @@ -49,7 +49,6 @@ struct _EAddressPopup { guint leave_timeout_tag; gboolean grabbed; - gint set_count; gchar *name; gchar *email; diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 772b217582..27ee510d5a 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,5 +1,11 @@ 2001-04-23 Jon Trowbridge <trow@ximian.com> + * e-html-utils.c (e_text_to_html_full): Removed attempts to use + Radek's evil <DATA> hacks, which were just causing me + (and GtkHTML) grief. + +2001-04-23 Jon Trowbridge <trow@ximian.com> + * e-host-utils.c: Include glib.h, so that the g_warning in e_gethostbyname_r will be treated as a macro and not as an unresolved symbol. diff --git a/e-util/e-html-utils.c b/e-util/e-html-utils.c index 4bcfc920b0..c9c116e754 100644 --- a/e-util/e-html-utils.c +++ b/e-util/e-html-utils.c @@ -65,12 +65,15 @@ url_extract (const unsigned char **text, gboolean check) return out; } -/* FIXME */ +/* FIXME -- this should be smarter */ static gboolean is_email_address (const unsigned char *c) { gboolean seen_at = FALSE, seen_postat = FALSE; + if (c == NULL) + return FALSE; + if (*c == '<') ++c; @@ -100,6 +103,9 @@ email_address_extract (const unsigned char **text) const unsigned char *end = *text; char *out; + if (end == NULL) + return NULL; + while (*end && !isspace (*end) && (*end != '>') && (*end < 0x80)) ++end; @@ -293,12 +299,8 @@ e_text_to_html_full (const char *input, unsigned int flags, guint32 color) dispaddr = e_text_to_html (addr, 0); if (addr) { - gchar *outaddr = g_strdup_printf ("<a href=\"mailto:%s\">" - "<!--+GtkHTML:<DATA class=\"Text\" key=\"email\" value=\"%s\">-->" - "%s" - "<!--+GtkHTML:<DATA class=\"Text\" clear=\"email\">--> " - "</a>", - addr, addr, dispaddr); + gchar *outaddr = g_strdup_printf ("<a href=\"mailto:%s\">%s</a>", + addr, dispaddr); out = check_size (&buffer, &buffer_size, out, strlen(outaddr)); out += sprintf (out, "%s", outaddr); col += strlen (addr); 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 */ |