aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--addressbook/ChangeLog13
-rw-r--r--addressbook/gui/component/e-address-popup.c119
-rw-r--r--addressbook/gui/component/e-address-popup.h1
-rw-r--r--e-util/ChangeLog6
-rw-r--r--e-util/e-html-utils.c16
-rw-r--r--mail/ChangeLog13
-rw-r--r--mail/mail-display.c185
-rw-r--r--mail/mail-format.c86
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 ? "&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 */