aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--addressbook/ChangeLog47
-rw-r--r--addressbook/backend/ebook/e-book.c27
-rw-r--r--addressbook/contact-editor/e-contact-quick-add.c218
-rw-r--r--addressbook/contact-editor/e-contact-quick-add.h2
-rw-r--r--addressbook/gui/component/GNOME_Evolution_Addressbook.oaf.in28
-rw-r--r--addressbook/gui/component/GNOME_Evolution_Addressbook.oafinfo27
-rw-r--r--addressbook/gui/component/Makefile.am4
-rw-r--r--addressbook/gui/component/addressbook-factory.c3
-rw-r--r--addressbook/gui/component/e-address-widget.c414
-rw-r--r--addressbook/gui/component/e-address-widget.h81
-rw-r--r--addressbook/gui/component/select-names/e-select-names-completion.c30
-rw-r--r--addressbook/gui/component/select-names/e-select-names-popup.c32
-rw-r--r--addressbook/gui/component/select-names/e-select-names-text-model.c23
-rw-r--r--addressbook/gui/contact-editor/e-contact-quick-add.c218
-rw-r--r--addressbook/gui/contact-editor/e-contact-quick-add.h2
-rw-r--r--mail/ChangeLog17
-rw-r--r--mail/mail-display.c33
-rw-r--r--mail/mail-format.c74
18 files changed, 1102 insertions, 178 deletions
diff --git a/addressbook/ChangeLog b/addressbook/ChangeLog
index e5c41ac07a..82f54b0458 100644
--- a/addressbook/ChangeLog
+++ b/addressbook/ChangeLog
@@ -1,3 +1,50 @@
+2001-03-08 Jon Trowbridge <trow@ximian.com>
+
+ * gui/component/select-names/e-select-names-popup.c
+ (quick_add_cb): Switched to use e_contact_quick_add_free_form.
+ Removed debugging code, hopefully without introducing any bugs
+ in the process.
+
+ * gui/component/select-names/e-select-names-text-model.c
+ (e_select_names_text_model_insert_length): Fix bug with commas
+ inside of name/address combos. As long as the comma is inside of
+ quotes, it will be treated as part of the name rather than as a
+ break between addresses.
+
+ * gui/component/select-names/e-select-names-completion.c
+ (match_nickname): Use e_card_name_to_string for nickname match
+ strings.
+ (match_email): Use e_card_name_to_string for email match strings.
+ (e_select_names_completion_begin): Strip quotes out of query text,
+ so we don't produce malformed sexps.
+ Added William Blake quote easter egg.
+
+ * contact-editor/e-contact-quick-add.c: Further attempts to fix...
+ mostly unsuccessful.
+ (e_contact_quick_add_free_form): Added. Takes a single string
+ and tries to parse out (using some simple, loose rules) the
+ name and e-mail -- then calls e_contact_quick_add. An attempt to
+ get the computer to automatically Do The Right Thing.
+
+ * backend/ebook/e-book.c: Fixed some broken indentation. Yes, I'm
+ anal.
+
+ * gui/component/GNOME_Evolution_Addressbook.oafinfo: Added oaf_server
+ info for EAddressWidget.
+
+ * gui/component/GNOME_Evolution_Addressbook.oaf.in: Added oaf_server
+ info for EAddressWidget.
+
+ * gui/component/addressbook-factory.c (main): Add call to
+ e_address_widget_factory_init.
+
+ * gui/component/e-address-widget.h:
+ * gui/component/e-address-widget.c: Added. A little widget (and a
+ Bonobo control, BTW) for displaying addresses, with a left-click
+ menu. Used to display addresses in the mail viewer (as embedded
+ GtkHTML objects, replacing the text previously used). Still quite
+ incomplete.
+
2001-03-08 Ettore Perazzoli <ettore@ximian.com>
* gui/component/addressbook-component.c (factory_fn): Specify a
diff --git a/addressbook/backend/ebook/e-book.c b/addressbook/backend/ebook/e-book.c
index a4dd4e196f..1401498d2d 100644
--- a/addressbook/backend/ebook/e-book.c
+++ b/addressbook/backend/ebook/e-book.c
@@ -1008,10 +1008,11 @@ e_book_check_connection (EBook *book)
return TRUE;
}
-gboolean e_book_get_cursor (EBook *book,
- gchar *query,
- EBookCursorCallback cb,
- gpointer closure)
+gboolean
+e_book_get_cursor (EBook *book,
+ gchar *query,
+ EBookCursorCallback cb,
+ gpointer closure)
{
CORBA_Environment ev;
@@ -1041,10 +1042,11 @@ gboolean e_book_get_cursor (EBook *book,
return TRUE;
}
-gboolean e_book_get_book_view (EBook *book,
- gchar *query,
- EBookBookViewCallback cb,
- gpointer closure)
+gboolean
+e_book_get_book_view (EBook *book,
+ gchar *query,
+ EBookBookViewCallback cb,
+ gpointer closure)
{
CORBA_Environment ev;
EBookViewListener *listener;
@@ -1077,10 +1079,11 @@ gboolean e_book_get_book_view (EBook *book,
return TRUE;
}
-gboolean e_book_get_changes (EBook *book,
- gchar *changeid,
- EBookBookViewCallback cb,
- gpointer closure)
+gboolean
+e_book_get_changes (EBook *book,
+ gchar *changeid,
+ EBookBookViewCallback cb,
+ gpointer closure)
{
CORBA_Environment ev;
EBookViewListener *listener;
diff --git a/addressbook/contact-editor/e-contact-quick-add.c b/addressbook/contact-editor/e-contact-quick-add.c
index 8445542975..2592f797a5 100644
--- a/addressbook/contact-editor/e-contact-quick-add.c
+++ b/addressbook/contact-editor/e-contact-quick-add.c
@@ -26,79 +26,78 @@
*/
#include <config.h>
+#include <ctype.h>
#include <gnome.h>
#include <addressbook/backend/ebook/e-book.h>
#include <addressbook/backend/ebook/e-card.h>
#include "e-contact-editor.h"
#include "e-contact-quick-add.h"
-static FILE *out = NULL;
-
static void
e_card_quick_set_name (ECard *card, const gchar *str)
{
+ ECardSimple *simple;
+
g_return_if_fail (card && E_IS_CARD (card));
if (str == NULL)
return;
- if (out)
- fprintf (out, "quick-set name to \"%s\"\n", str);
-
- if (card->name)
- e_card_name_free (card->name);
- card->name = e_card_name_from_string (str);
+ simple = e_card_simple_new (card);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FULL_NAME, str);
+ e_card_simple_sync_card (simple);
+ gtk_object_unref (GTK_OBJECT (simple));
}
static void
e_card_quick_set_email (ECard *card, const gchar *str)
{
+ ECardSimple *simple;
+
g_return_if_fail (card && E_IS_CARD (card));
if (str == NULL)
return;
- if (out)
- fprintf (out, "quick-set email to \"%s\"\n", str);
-
- if (card->email == NULL) {
- card->email = e_list_new ((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
- e_list_append (card->email, str);
- } else {
- EIterator *iter = e_list_get_iterator (card->email);
- e_iterator_reset (iter);
- if (e_iterator_is_valid (iter)) {
- e_iterator_set (iter, str);
- }
- }
+ simple = e_card_simple_new (card);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_EMAIL, str);
+ e_card_simple_sync_card (simple);
+ gtk_object_unref (GTK_OBJECT (simple));
}
static void
book_ready_cb (EBook *book, EBookStatus status, gpointer user_data)
{
- if (status == E_BOOK_STATUS_SUCCESS)
- e_book_add_card (book, E_CARD (user_data), NULL, NULL);
- gtk_object_unref (GTK_OBJECT (book));
+ ECard *card = E_CARD (user_data);
+
+ EContactQuickAddCallback cb = gtk_object_get_data (GTK_OBJECT (card), "e-contact-quick-add-cb");
+ gpointer cb_user_data = gtk_object_get_data (GTK_OBJECT (card), "e-contact-quick-add-user-data");
+
+ if (status == E_BOOK_STATUS_SUCCESS) {
+ e_book_add_card (book, card, NULL, NULL);
+ if (cb)
+ cb (card, cb_user_data);
+ } else {
+ /* Something went wrong... */
+ if (cb)
+ cb (NULL, cb_user_data);
+
+ gtk_object_unref (GTK_OBJECT (book));
+ }
}
static void
add_card (ECard *card)
{
EBook *book = e_book_new ();
- gchar *filename, *uri;
-
- filename = gnome_util_prepend_user_home ("evolution/local/Contacts/addressbook.db");
- uri = g_strdup_printf ("file://%s", filename);
-
- e_book_load_uri (book, uri, book_ready_cb, card);
-
- g_free (filename);
- g_free (uri);
+ e_book_load_local_address_book (book, book_ready_cb, card);
}
+/*
+ * Raise a contact editor with all fields editable, and hook up all signals accordingly.
+ */
+
static void
add_card_cb (EContactEditor *ce, ECard *card, gpointer user_data)
{
@@ -108,12 +107,55 @@ add_card_cb (EContactEditor *ce, ECard *card, gpointer user_data)
static void
editor_closed_cb (GtkWidget *w, gpointer user_data)
{
+ /* w is the contact editor, user_data is an ECard. */
if (user_data)
gtk_object_unref (user_data);
gtk_object_unref (GTK_OBJECT (w));
}
static void
+ce_book_found_fields (EBook *book, EBookStatus status, EList *fields, gpointer user_data)
+{
+ ECard *card = E_CARD (user_data);
+ EContactEditor *contact_editor;
+
+ if (status != E_BOOK_STATUS_SUCCESS) {
+ g_warning ("Couldn't find supported fields for local address book.");
+ return;
+ }
+
+ contact_editor = e_contact_editor_new (card, TRUE, fields);
+
+ gtk_signal_connect (GTK_OBJECT (contact_editor),
+ "add_card",
+ GTK_SIGNAL_FUNC (add_card_cb),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (contact_editor),
+ "editor_closed",
+ GTK_SIGNAL_FUNC (editor_closed_cb),
+ user_data);
+
+ e_contact_editor_raise (contact_editor);
+}
+
+static void
+ce_book_ready (EBook *book, EBookStatus status, gpointer user_data)
+{
+ if (status != E_BOOK_STATUS_SUCCESS) {
+ g_warning ("Couldn't open local address book.");
+ return;
+ }
+
+ e_book_get_supported_fields (book, ce_book_found_fields, user_data);
+}
+
+static void
+edit_card (ECard *card)
+{
+ e_book_load_local_address_book (e_book_new (), ce_book_ready, card);
+}
+
+static void
clicked_cb (GtkWidget *w, gint button, gpointer user_data)
{
ECard *card = E_CARD (user_data);
@@ -149,19 +191,7 @@ clicked_cb (GtkWidget *w, gint button, gpointer user_data)
} else if (button == 1) {
/* EDIT FULL */
- EContactEditor *contact_editor;
- contact_editor = e_contact_editor_new (card, TRUE, NULL);
-
- gtk_signal_connect (GTK_OBJECT (contact_editor),
- "add_card",
- GTK_SIGNAL_FUNC (add_card_cb),
- NULL);
- gtk_signal_connect (GTK_OBJECT (contact_editor),
- "editor_closed",
- GTK_SIGNAL_FUNC (editor_closed_cb),
- user_data);
-
- e_contact_editor_raise (contact_editor);
+ edit_card (card);
} else {
/* CANCEL */
@@ -249,16 +279,6 @@ e_contact_quick_add (const gchar *name, const gchar *email,
ECard *new_card;
GtkWidget *dialog;
- if (out == NULL) {
- out = fopen ("/tmp/barnass", "w");
- if (out)
- setvbuf (out, NULL, _IONBF, 0);
- }
-
- if (out)
- fprintf (out, "\n name: %s\nemail: %s\n", name, email);
-
-
/* We need to have *something* to work with. */
if (name == NULL && email == NULL) {
if (cb)
@@ -280,3 +300,85 @@ e_contact_quick_add (const gchar *name, const gchar *email,
gtk_widget_show_all (dialog);
}
+
+void
+e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer user_data)
+{
+ gchar *name=NULL, *email=NULL;
+ const gchar *last_at, *s;
+ gboolean in_quote;
+
+ if (text == NULL) {
+ e_contact_quick_add (NULL, NULL, cb, user_data);
+ return;
+ }
+
+ /* Look for things that look like e-mail addresses embedded in text */
+ in_quote = FALSE;
+ last_at = NULL;
+ for (s = text; *s; ++s) {
+ if (*s == '@' && !in_quote)
+ last_at = s;
+ else if (*s == '"')
+ in_quote = !in_quote;
+ }
+
+
+ if (last_at == NULL) {
+ /* No at sign, so we treat it all as the name */
+ name = g_strdup (text);
+ } else {
+ gboolean bad_char = FALSE;
+
+ /* walk backwards to whitespace or a < or a quote... */
+ while (last_at >= text && !bad_char
+ && !(isspace ((gint) *last_at) || *last_at == '<' || *last_at == '"')) {
+ /* Check for some stuff that can't appear in a legal e-mail address. */
+ if (*last_at == '['
+ || *last_at == ']'
+ || *last_at == '('
+ || *last_at == ')')
+ bad_char = TRUE;
+ --last_at;
+ }
+ if (last_at < text)
+ last_at = text;
+
+ /* ...and then split the text there */
+ if (!bad_char) {
+ if (text < last_at)
+ name = g_strndup (text, last_at-text);
+ email = g_strdup (last_at);
+ }
+ }
+
+ /* If all else has failed, make it the name. */
+ if (name == NULL && email == NULL)
+ name = g_strdup (text);
+
+
+ /* Clean up name */
+ if (name && *name)
+ g_strstrip (name);
+
+ /* Clean up email, remove bracketing <>s */
+ if (email && *email) {
+ gboolean changed = FALSE;
+ g_strstrip (email);
+ if (*email == '<') {
+ *email = ' ';
+ changed = TRUE;
+ }
+ if (email[strlen (email)-1] == '>') {
+ email[strlen (email)-1] = ' ';
+ changed = TRUE;
+ }
+ if (changed)
+ g_strstrip (email);
+ }
+
+
+ e_contact_quick_add (name, email, cb, user_data);
+ g_free (name);
+ g_free (email);
+}
diff --git a/addressbook/contact-editor/e-contact-quick-add.h b/addressbook/contact-editor/e-contact-quick-add.h
index 630dfd2ad0..9d928e43f4 100644
--- a/addressbook/contact-editor/e-contact-quick-add.h
+++ b/addressbook/contact-editor/e-contact-quick-add.h
@@ -36,5 +36,7 @@ typedef void (*EContactQuickAddCallback) (ECard *new_card, gpointer user_data);
void e_contact_quick_add (const gchar *name, const gchar *email,
EContactQuickAddCallback cb, gpointer user_data);
+void e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer user_data);
+
#endif /* __E_CONTACT_QUICK_ADD_H__ */
diff --git a/addressbook/gui/component/GNOME_Evolution_Addressbook.oaf.in b/addressbook/gui/component/GNOME_Evolution_Addressbook.oaf.in
index 2a523c9dc1..2e604862af 100644
--- a/addressbook/gui/component/GNOME_Evolution_Addressbook.oaf.in
+++ b/addressbook/gui/component/GNOME_Evolution_Addressbook.oaf.in
@@ -87,6 +87,34 @@
<oaf_attribute name="evolution:shell-component-icon" type="string"
value="evolution-contacts.png"/>
+
+</oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressWidgetFactory"
+ type="exe"
+ location="evolution-addressbook">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:GNOME/ObjectFactory:1.0"/>
+ </oaf_attribute>
+
+ <oaf_attribute name="description" type="string"
+ _value="Factory for the Addressbook's address displayer"/>
+
+</oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressWidget"
+ type="factory"
+ location="OAFIID:GNOME_Evolution_Addressbook_AddressWidgetFactory">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:BonoboControl/address-widget:1.0"/>
+ <item value="IDL:GNOME/Control:1.0"/>
+ </oaf_attribute>
+
+ <oaf_attribute name="description" type="string"
+ _value="A Bonobo control for displaying an address."/>
+
</oaf_server>
</oaf_info>
diff --git a/addressbook/gui/component/GNOME_Evolution_Addressbook.oafinfo b/addressbook/gui/component/GNOME_Evolution_Addressbook.oafinfo
index 01474ce90a..03c2e66d19 100644
--- a/addressbook/gui/component/GNOME_Evolution_Addressbook.oafinfo
+++ b/addressbook/gui/component/GNOME_Evolution_Addressbook.oafinfo
@@ -89,4 +89,31 @@
value="evolution-contacts.png"/>
</oaf_server>
+<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressWidgetFactory"
+ type="exe"
+ location="evolution-addressbook">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:GNOME/ObjectFactory:1.0"/>
+ </oaf_attribute>
+
+ <oaf_attribute name="description" type="string"
+ value="Factory for the Addressbook's address displayer"/>
+
+</oaf_server>
+
+<oaf_server iid="OAFIID:GNOME_Evolution_Addressbook_AddressWidget"
+ type="factory"
+ location="OAFIID:GNOME_Evolution_Addressbook_AddressWidgetFactory">
+
+ <oaf_attribute name="repo_ids" type="stringv">
+ <item value="IDL:BonoboControl/address-widget:1.0"/>
+ <item value="IDL:GNOME/Control:1.0"/>
+ </oaf_attribute>
+
+ <oaf_attribute name="description" type="string"
+ value="A Bonobo control for displaying an address."/>
+
+</oaf_server>
+
</oaf_info>
diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am
index eaefdbab96..59b1d4c394 100644
--- a/addressbook/gui/component/Makefile.am
+++ b/addressbook/gui/component/Makefile.am
@@ -36,7 +36,9 @@ evolution_addressbook_SOURCES = \
addressbook.c \
addressbook.h \
e-cardlist-model.c \
- e-cardlist-model.h
+ e-cardlist-model.h \
+ e-address-widget.h \
+ e-address-widget.c
evolution_addressbook_LDADD = \
select-names/libeselectnames.la \
diff --git a/addressbook/gui/component/addressbook-factory.c b/addressbook/gui/component/addressbook-factory.c
index ebfd0d9cfd..3887090a91 100644
--- a/addressbook/gui/component/addressbook-factory.c
+++ b/addressbook/gui/component/addressbook-factory.c
@@ -18,6 +18,7 @@
#include "addressbook.h"
#include "addressbook-component.h"
+#include "e-address-widget.h"
#include "addressbook/gui/widgets/e-minicard-control.h"
#include "select-names/e-select-names-factory.h"
@@ -63,6 +64,8 @@ main (int argc, char **argv)
e_minicard_control_factory_init ();
+ e_address_widget_factory_init ();
+
e_cursors_init();
unicode_init();
diff --git a/addressbook/gui/component/e-address-widget.c b/addressbook/gui/component/e-address-widget.c
new file mode 100644
index 0000000000..2af83e67aa
--- /dev/null
+++ b/addressbook/gui/component/e-address-widget.c
@@ -0,0 +1,414 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * e-address-widget.c
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Developed by Jon Trowbridge <trow@ximian.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+#include <config.h>
+#include <bonobo/bonobo-control.h>
+#include <bonobo/bonobo-property-bag.h>
+#include <bonobo/bonobo-generic-factory.h>
+#include <addressbook/contact-editor/e-contact-quick-add.h>
+#include "e-address-widget.h"
+
+static void e_address_widget_class_init (EAddressWidgetClass *klass);
+static void e_address_widget_init (EAddressWidget *obj);
+static void e_address_widget_destroy (GtkObject *obj);
+
+static gint e_address_widget_button_press_handler (GtkWidget *w, GdkEventButton *ev);
+static void e_address_widget_popup (EAddressWidget *, GdkEventButton *ev);
+
+static GtkObjectClass *parent_class;
+
+static void
+e_address_widget_class_init (EAddressWidgetClass *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_widget_destroy;
+
+ widget_class->button_press_event = e_address_widget_button_press_handler;
+}
+
+static void
+e_address_widget_init (EAddressWidget *addr)
+{
+
+}
+
+static void
+e_address_widget_destroy (GtkObject *obj)
+{
+ EAddressWidget *addr = E_ADDRESS_WIDGET (obj);
+
+ g_free (addr->name);
+ g_free (addr->email);
+ if (addr->card)
+ gtk_object_unref (GTK_OBJECT (addr->card));
+}
+
+static gint
+e_address_widget_button_press_handler (GtkWidget *w, GdkEventButton *ev)
+{
+ EAddressWidget *addr = E_ADDRESS_WIDGET (w);
+ if (ev->button == 3 && ev->state == 0) {
+ e_address_widget_popup (addr, ev);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GtkType
+e_address_widget_get_type (void)
+{
+ static GtkType aw_type = 0;
+
+ if (!aw_type) {
+ GtkTypeInfo aw_info = {
+ "EAddressWidget",
+ sizeof (EAddressWidget),
+ sizeof (EAddressWidgetClass),
+ (GtkClassInitFunc) e_address_widget_class_init,
+ (GtkObjectInitFunc) e_address_widget_init,
+ NULL, NULL, /* reserved... but for what sinister purpose? */
+ (GtkClassInitFunc) NULL
+ };
+
+ aw_type = gtk_type_unique (gtk_event_box_get_type (), &aw_info);
+ }
+
+ return aw_type;
+}
+
+static void
+gtk_widget_visible (GtkWidget *w, gboolean x)
+{
+ if (x)
+ gtk_widget_show (w);
+ else
+ gtk_widget_hide (w);
+}
+
+static void
+e_address_widget_refresh (EAddressWidget *addr)
+{
+ gchar *str;
+ gboolean have_name, have_email;
+
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ have_name = addr->name && *addr->name;
+ have_email = addr->email && *addr->email;
+
+ gtk_label_set_text (GTK_LABEL (addr->name_widget), have_name ? addr->name : "");
+ gtk_widget_visible (addr->name_widget, have_name);
+
+ if (have_email) {
+ str = g_strdup_printf (have_name ? "<%s>" : "%s", addr->email);
+ gtk_label_set_text (GTK_LABEL (addr->email_widget), str);
+ g_free (str);
+ } else {
+ gtk_label_set_text (GTK_LABEL (addr->email_widget), "");
+ }
+ gtk_widget_visible (addr->email_widget, have_email);
+
+ gtk_widget_visible (addr->spacer, have_name && have_email);
+
+ /* Launch a query to find the appropriate card, if necessary. */
+ addr->querying = TRUE;
+}
+
+void
+e_address_widget_set_name (EAddressWidget *addr, const gchar *name)
+{
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ g_free (addr->name);
+ addr->name = g_strdup (name);
+
+ e_address_widget_refresh (addr);
+}
+
+void
+e_address_widget_set_email (EAddressWidget *addr, const gchar *email)
+{
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ g_free (addr->email);
+ addr->email = g_strdup (email);
+
+ e_address_widget_refresh (addr);
+}
+
+
+void
+e_address_widget_set_text (EAddressWidget *addr, const gchar *text)
+{
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ e_address_widget_set_email (addr, text); /* CRAP */
+}
+
+void
+e_address_widget_construct (EAddressWidget *addr)
+{
+ GtkWidget *box;
+
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ box = gtk_hbox_new (FALSE, 2);
+
+ addr->name_widget = gtk_label_new ("");
+ addr->spacer = gtk_label_new (" ");
+ addr->email_widget = gtk_label_new ("");
+
+ gtk_box_pack_start (GTK_BOX (box), addr->name_widget, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (box), addr->spacer, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (box), addr->email_widget, FALSE, FALSE, 0);
+
+
+ gtk_container_add (GTK_CONTAINER (addr), box);
+
+ gtk_widget_show (box);
+ gtk_widget_show (addr->name_widget);
+ gtk_widget_show (addr->email_widget);
+}
+
+GtkWidget *
+e_address_widget_new (void)
+{
+ EAddressWidget *addr = gtk_type_new (e_address_widget_get_type ());
+ e_address_widget_construct (addr);
+ return GTK_WIDGET (addr);
+}
+
+/*
+ *
+ * Popup Menu
+ *
+ */
+
+#define ARBITRARY_UIINFO_LIMIT 64
+static GtkWidget *
+popup_menu_card (EAddressWidget *addr)
+{
+ ECard *card = E_CARD (addr->card);
+ g_return_val_if_fail (card != NULL, NULL);
+
+ return NULL;
+}
+
+static void
+add_contacts_cb (GtkWidget *w, gpointer user_data)
+{
+ EAddressWidget *addr = E_ADDRESS_WIDGET (user_data);
+
+ e_contact_quick_add (addr->name, addr->email, NULL, NULL);
+}
+
+static GtkWidget *
+popup_menu_nocard (EAddressWidget *addr)
+{
+ GnomeUIInfo uiinfo[ARBITRARY_UIINFO_LIMIT];
+ GtkWidget *pop;
+ gint i=0, dead;
+
+ memset (uiinfo, 0, sizeof (uiinfo));
+
+ if (addr->name) {
+ uiinfo[i].type = GNOME_APP_UI_ITEM;
+ uiinfo[i].label = addr->name;
+ ++i;
+ }
+
+ if (addr->email) {
+ uiinfo[i].type = GNOME_APP_UI_ITEM;
+ uiinfo[i].label = addr->email;
+ ++i;
+ }
+ dead = i;
+
+ uiinfo[i].type = GNOME_APP_UI_SEPARATOR;
+ ++i;
+
+ uiinfo[i].type = GNOME_APP_UI_ITEM;
+ uiinfo[i].label = N_("Add to Contacts");
+ uiinfo[i].moreinfo = add_contacts_cb;
+ ++i;
+
+ uiinfo[i].type = GNOME_APP_UI_ENDOFINFO;
+
+
+ pop = gnome_popup_menu_new (uiinfo);
+ for (i=0; i<dead; ++i)
+ dead_item (GTK_ITEM (uiinfo[i].widget));
+ return pop;
+}
+
+static void
+e_address_widget_popup (EAddressWidget *addr, GdkEventButton *ev)
+{
+ GtkWidget *pop;
+
+ g_return_if_fail (addr && E_IS_ADDRESS_WIDGET (addr));
+
+ pop = addr->card ? popup_menu_card (addr) : popup_menu_nocard (addr);
+
+ if (pop)
+ gnome_popup_menu_do_popup (pop, NULL, NULL, ev, addr);
+}
+
+/*
+ *
+ * Bonobo Control Magic
+ *
+ */
+
+enum {
+ ADDRESS_PROPERTY_NAME,
+ ADDRESS_PROPERTY_EMAIL,
+ ADDRESS_PROPERTY_TEXT,
+ ADDRESS_PROPERTY_BACKGROUND_RGB
+};
+
+
+static void
+get_prop (BonoboPropertyBag *bag, BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data)
+{
+ EAddressWidget *addr = E_ADDRESS_WIDGET (user_data);
+
+ switch (arg_id) {
+
+ case ADDRESS_PROPERTY_NAME:
+ BONOBO_ARG_SET_STRING (arg, addr->name ? addr->name :"");
+ break;
+
+ case ADDRESS_PROPERTY_EMAIL:
+ BONOBO_ARG_SET_STRING (arg, addr->email ? addr->email : "");
+ break;
+
+ case ADDRESS_PROPERTY_TEXT:
+ BONOBO_ARG_SET_STRING (arg, "?");
+ break;
+ }
+}
+
+static void
+set_prop (BonoboPropertyBag *bag, const BonoboArg *arg, guint arg_id, CORBA_Environment *ev, gpointer user_data)
+{
+ EAddressWidget *addr = E_ADDRESS_WIDGET (user_data);
+
+ switch (arg_id) {
+ case ADDRESS_PROPERTY_NAME:
+ e_address_widget_set_name (addr, BONOBO_ARG_GET_STRING (arg));
+ break;
+
+ case ADDRESS_PROPERTY_EMAIL:
+ e_address_widget_set_email (addr, BONOBO_ARG_GET_STRING (arg));
+ break;
+
+ case ADDRESS_PROPERTY_TEXT:
+ e_address_widget_set_text (addr, BONOBO_ARG_GET_STRING (arg));
+ break;
+
+
+ case ADDRESS_PROPERTY_BACKGROUND_RGB:
+ {
+ gint bg = BONOBO_ARG_GET_INT (arg);
+ GdkColor color;
+
+ color.red = (bg & 0xff0000) >> 8;
+ color.green = (bg & 0x00ff00);
+ color.blue = (bg & 0x0000ff) << 8;
+
+ if (gdk_colormap_alloc_color (gtk_widget_get_colormap (GTK_WIDGET (addr)), &color, FALSE, TRUE)) {
+ GtkStyle *style = gtk_style_copy (gtk_widget_get_style (GTK_WIDGET (addr)));
+ style->bg[0] = color;
+ gtk_widget_set_style (GTK_WIDGET (addr), style);
+ }
+ }
+
+ break;
+ }
+}
+
+static BonoboControl *
+e_address_widget_factory_new_control (void)
+{
+ BonoboControl *control;
+ BonoboPropertyBag *bag;
+ GtkWidget *w;
+
+ w = e_address_widget_new ();
+ gtk_widget_show (w);
+
+ control = bonobo_control_new (w);
+
+ bag = bonobo_property_bag_new (get_prop, set_prop, w);
+ bonobo_property_bag_add (bag, "name", ADDRESS_PROPERTY_NAME,
+ BONOBO_ARG_STRING, NULL, NULL,
+ BONOBO_PROPERTY_READABLE | BONOBO_PROPERTY_WRITEABLE);
+
+ bonobo_property_bag_add (bag, "email", ADDRESS_PROPERTY_EMAIL,
+ BONOBO_ARG_STRING, NULL, NULL,
+ BONOBO_PROPERTY_READABLE | BONOBO_PROPERTY_WRITEABLE);
+
+ bonobo_property_bag_add (bag, "text", ADDRESS_PROPERTY_TEXT,
+ BONOBO_ARG_STRING, NULL, NULL,
+ BONOBO_PROPERTY_READABLE | BONOBO_PROPERTY_WRITEABLE);
+
+ bonobo_property_bag_add (bag, "background_rgb", ADDRESS_PROPERTY_BACKGROUND_RGB,
+ BONOBO_ARG_INT, NULL, NULL,
+ BONOBO_PROPERTY_WRITEABLE);
+
+ bonobo_control_set_properties (control, bag);
+ bonobo_object_unref (BONOBO_OBJECT (bag));
+
+ return control;
+}
+
+static BonoboObject *
+e_address_widget_factory (BonoboGenericFactory *factory, gpointer user_data)
+{
+ return BONOBO_OBJECT (e_address_widget_factory_new_control ());
+}
+
+void
+e_address_widget_factory_init (void)
+{
+ static BonoboGenericFactory *factory = NULL;
+
+ if (factory != NULL)
+ return;
+
+ factory = bonobo_generic_factory_new ("OAFIID:GNOME_Evolution_Addressbook_AddressWidgetFactory",
+ e_address_widget_factory, NULL);
+
+ if (factory == NULL)
+ g_error ("I could not register an AddressWidget factory.");
+}
diff --git a/addressbook/gui/component/e-address-widget.h b/addressbook/gui/component/e-address-widget.h
new file mode 100644
index 0000000000..7168242323
--- /dev/null
+++ b/addressbook/gui/component/e-address-widget.h
@@ -0,0 +1,81 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * e-address-widget.h
+ *
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Developed by Jon Trowbridge <trow@ximian.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+#ifndef __E_ADDRESS_WIDGET_H__
+#define __E_ADDRESS_WIDGET_H__
+
+#include <gtk/gtk.h>
+#include <libgnome/gnome-defs.h>
+#include <addressbook/backend/ebook/e-card.h>
+
+BEGIN_GNOME_DECLS
+
+#define E_ADDRESS_WIDGET_TYPE (e_address_widget_get_type ())
+#define E_ADDRESS_WIDGET(o) (GTK_CHECK_CAST ((o), E_ADDRESS_WIDGET_TYPE, EAddressWidget))
+#define E_ADDRESS_WIDGET_CLASS(k) (GTK_CHECK_CLASS_CAST ((k), E_ADDRESS_WIDGET_TYPE, EAddressWidgetClass))
+#define E_IS_ADDRESS_WIDGET(o) (GTK_CHECK_TYPE ((o), E_ADDRESS_WIDGET_TYPE))
+#define E_IS_ADDRESS_WIDGET_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), E_ADDRESS_WIDGET_TYPE))
+
+typedef struct _EAddressWidget EAddressWidget;
+typedef struct _EAddressWidgetClass EAddressWidgetClass;
+
+struct _EAddressWidget {
+ GtkEventBox parent;
+
+ gchar *name;
+ gchar *email;
+
+ GtkWidget *name_widget;
+ GtkWidget *email_widget;
+ GtkWidget *spacer;
+
+ gboolean querying;
+ ECard *card;
+};
+
+struct _EAddressWidgetClass {
+ GtkHBoxClass parent_class;
+};
+
+GtkType e_address_widget_get_type (void);
+
+void e_address_widget_set_name (EAddressWidget *, const gchar *name);
+void e_address_widget_set_email (EAddressWidget *, const gchar *email);
+void e_address_widget_set_text (EAddressWidget *, const gchar *text);
+
+void e_address_widget_construct (EAddressWidget *);
+GtkWidget *e_address_widget_new (void);
+
+
+void e_address_widget_factory_init (void);
+
+
+
+END_GNOME_DECLS
+
+#endif /* __E_ADDRESS_WIDGET_H__ */
+
diff --git a/addressbook/gui/component/select-names/e-select-names-completion.c b/addressbook/gui/component/select-names/e-select-names-completion.c
index 5f87144510..aa1bf7e2e3 100644
--- a/addressbook/gui/component/select-names/e-select-names-completion.c
+++ b/addressbook/gui/component/select-names/e-select-names-completion.c
@@ -97,11 +97,14 @@ match_nickname (ESelectNamesCompletion *comp, EDestination *dest, double *score)
if (card->nickname
&& !g_strncasecmp (comp->priv->query_text, card->nickname, len)) {
+ gchar *name = e_card_name_to_string (card->name);
+ gchar *str;
*score = len * 10; /* nickname gives 10 points per matching character */
- return g_strdup_printf ("(%s) %s %s", card->nickname, card->name->given, card->name->family);
-
+ str = g_strdup_printf ("(%s) %s", card->nickname, name);
+ g_free (name);
+ return str;
}
return NULL;
@@ -125,8 +128,12 @@ match_email (ESelectNamesCompletion *comp, EDestination *dest, double *score)
const gchar *email = e_destination_get_email (dest);
if (email && !g_strncasecmp (comp->priv->query_text, email, len)) {
+ gchar *name, *str;
*score = len * 2; /* 2 points for each matching character */
- return g_strdup_printf ("<%s> %s %s", email, card->name->given, card->name->family);
+ name = e_card_name_to_string (card->name);
+ str = g_strdup_printf ("<%s> %s", email, name);
+ g_free (name);
+ return str;
}
return NULL;
@@ -693,7 +700,9 @@ struct _SearchOverride {
const gchar *text[4];
};
static SearchOverride override[] = {
- { "easter egg", { "This is the sample", "Easter Egg text for", "Evolution.", NULL } },
+ { "why?", { "\"I must create a system, or be enslaved by another man's.\"",
+ " -- Wiliam Blake, \"Jerusalem\"",
+ NULL } },
{ NULL, { NULL } } };
static gboolean
@@ -711,6 +720,7 @@ e_select_names_completion_begin (ECompletion *comp, const gchar *text, gint pos,
ESelectNamesCompletion *selcomp = E_SELECT_NAMES_COMPLETION (comp);
const gchar *str;
gint index, j;
+ gchar *s, *t;
g_return_if_fail (comp != NULL);
g_return_if_fail (E_IS_SELECT_NAMES_COMPLETION (comp));
@@ -751,6 +761,18 @@ e_select_names_completion_begin (ECompletion *comp, const gchar *text, gint pos,
g_free (selcomp->priv->pending_query_text);
selcomp->priv->pending_query_text = g_strdup (str);
+
+ /* Strip problematic characters out of query text. */
+ s = t = selcomp->priv->pending_query_text;
+ while (*s) {
+ if (*s != ',' && *s != '"') {
+ if (s != t)
+ *t = *s;
+ ++t;
+ }
+ ++s;
+ }
+ *t = '\0';
e_select_names_completion_do_query (selcomp);
}
diff --git a/addressbook/gui/component/select-names/e-select-names-popup.c b/addressbook/gui/component/select-names/e-select-names-popup.c
index 23898a3079..85c2489b1a 100644
--- a/addressbook/gui/component/select-names/e-select-names-popup.c
+++ b/addressbook/gui/component/select-names/e-select-names-popup.c
@@ -31,8 +31,6 @@
#include <addressbook/contact-editor/e-contact-quick-add.h>
#include "e-select-names-popup.h"
-static FILE *out = NULL;
-
typedef struct _PopupInfo PopupInfo;
struct _PopupInfo {
ESelectNamesModel *model;
@@ -64,9 +62,6 @@ popup_info_free (PopupInfo *info)
{
if (info) {
- if (out)
- fprintf (out, "popup_info_free\n");
-
if (info->model)
gtk_object_unref (GTK_OBJECT (info->model));
@@ -103,8 +98,6 @@ change_email_num_cb (GtkWidget *w, gpointer user_data)
return;
n = GPOINTER_TO_INT (gtk_object_get_data (GTK_OBJECT (w), "number"));
- if (out)
- fprintf (out, "replacing %d\n", n);
if (n != e_destination_get_email_num (info->dest)) {
dest = e_destination_new ();
@@ -157,9 +150,6 @@ popup_menu_card (PopupInfo *info)
EIterator *iterator;
gchar *name_str;
- if (out)
- fprintf (out, "popup_menu_card\n");
-
/*
* Build up our GnomeUIInfo array.
*/
@@ -236,9 +226,6 @@ popup_menu_card (PopupInfo *info)
}
}
- if (out)
- fprintf (out, "leaving popup_menu_card\n");
-
return pop;
}
@@ -246,8 +233,7 @@ static void
quick_add_cb (GtkWidget *w, gpointer user_data)
{
PopupInfo *info = (PopupInfo *) user_data;
- e_contact_quick_add (NULL, e_destination_get_string (info->dest),
- NULL, NULL);
+ e_contact_quick_add_free_form (e_destination_get_string (info->dest), NULL, NULL);
}
static GtkWidget *
@@ -301,15 +287,6 @@ e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos)
g_return_if_fail (ev);
g_return_if_fail (0 <= pos);
- if (out == NULL) {
- out = fopen ("/tmp/evo-debug-select-names-popup", "w");
- if (out)
- setvbuf (out, NULL, _IONBF, 0);
- }
-
- if (out)
- fprintf (out, "\n\ne_select_names_popup\n");
-
e_select_names_model_text_pos (model, pos, &index, NULL, NULL);
if (index < 0 || index >= e_select_names_model_count (model))
return;
@@ -328,9 +305,6 @@ e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos)
GTK_SIGNAL_FUNC (popup_info_cleanup),
info);
- if (out)
- fprintf (out, "doing popup\n");
-
gnome_popup_menu_do_popup (popup, NULL, NULL, ev, info);
} else {
@@ -338,8 +312,4 @@ e_select_names_popup (ESelectNamesModel *model, GdkEventButton *ev, gint pos)
popup_info_free (info);
}
-
- if (out)
- fprintf (out, "leaving e_select_names_popup\n\n");
-
}
diff --git a/addressbook/gui/component/select-names/e-select-names-text-model.c b/addressbook/gui/component/select-names/e-select-names-text-model.c
index d66112d2bc..0e4d5eeb32 100644
--- a/addressbook/gui/component/select-names/e-select-names-text-model.c
+++ b/addressbook/gui/component/select-names/e-select-names-text-model.c
@@ -125,7 +125,7 @@ dump_model (ESelectNamesTextModel *text_model)
if (out == NULL)
return;
-
+
fprintf (out, "\n*** Model State: count=%d\n", e_select_names_model_count (model));
for (i=0; i<e_select_names_model_count (model); ++i)
@@ -297,6 +297,7 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
for (i = 0; i < length && text[i]; ++i) {
gint index, start_pos, text_len;
+ gboolean inside_quote = FALSE;
if (out)
fprintf (out, "processing [%c]\n", text[i]);
@@ -306,8 +307,26 @@ e_select_names_text_model_insert_length (ETextModel *model, gint pos, const gcha
if (out)
fprintf (out, "index=%d start_pos=%d text_len=%d\n", index, start_pos, text_len);
+ if (text[i] == ',' && index >= 0) { /* Is this a quoted or an unquoted comma we are dealing with? */
+ const EDestination *dest = e_select_names_model_get_destination (source, index);
+ if (dest) {
+ const gchar *str = e_destination_get_string (dest);
+ gint j;
+ if (out)
+ fprintf (out, "str=%s pos=%d\n", str, pos);
+ for (j=0; j<pos-start_pos && str[j]; ++j)
+ if (str[j] == '"') {
+ inside_quote = !inside_quote;
+ if (out)
+ fprintf (out, "flip to %d at %d\n", start_pos+j, inside_quote);
+ }
+ }
+ if (out)
+ fprintf (out, inside_quote ? "inside quote\n" : "not inside quote\n");
+ }
+
- if (text[i] == ',') {
+ if (text[i] == ',' && !inside_quote) {
/* This is the case of hitting , first thing in an empty entry */
if (index == -1) {
diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.c b/addressbook/gui/contact-editor/e-contact-quick-add.c
index 8445542975..2592f797a5 100644
--- a/addressbook/gui/contact-editor/e-contact-quick-add.c
+++ b/addressbook/gui/contact-editor/e-contact-quick-add.c
@@ -26,79 +26,78 @@
*/
#include <config.h>
+#include <ctype.h>
#include <gnome.h>
#include <addressbook/backend/ebook/e-book.h>
#include <addressbook/backend/ebook/e-card.h>
#include "e-contact-editor.h"
#include "e-contact-quick-add.h"
-static FILE *out = NULL;
-
static void
e_card_quick_set_name (ECard *card, const gchar *str)
{
+ ECardSimple *simple;
+
g_return_if_fail (card && E_IS_CARD (card));
if (str == NULL)
return;
- if (out)
- fprintf (out, "quick-set name to \"%s\"\n", str);
-
- if (card->name)
- e_card_name_free (card->name);
- card->name = e_card_name_from_string (str);
+ simple = e_card_simple_new (card);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_FULL_NAME, str);
+ e_card_simple_sync_card (simple);
+ gtk_object_unref (GTK_OBJECT (simple));
}
static void
e_card_quick_set_email (ECard *card, const gchar *str)
{
+ ECardSimple *simple;
+
g_return_if_fail (card && E_IS_CARD (card));
if (str == NULL)
return;
- if (out)
- fprintf (out, "quick-set email to \"%s\"\n", str);
-
- if (card->email == NULL) {
- card->email = e_list_new ((EListCopyFunc) g_strdup,
- (EListFreeFunc) g_free,
- NULL);
- e_list_append (card->email, str);
- } else {
- EIterator *iter = e_list_get_iterator (card->email);
- e_iterator_reset (iter);
- if (e_iterator_is_valid (iter)) {
- e_iterator_set (iter, str);
- }
- }
+ simple = e_card_simple_new (card);
+ e_card_simple_set (simple, E_CARD_SIMPLE_FIELD_EMAIL, str);
+ e_card_simple_sync_card (simple);
+ gtk_object_unref (GTK_OBJECT (simple));
}
static void
book_ready_cb (EBook *book, EBookStatus status, gpointer user_data)
{
- if (status == E_BOOK_STATUS_SUCCESS)
- e_book_add_card (book, E_CARD (user_data), NULL, NULL);
- gtk_object_unref (GTK_OBJECT (book));
+ ECard *card = E_CARD (user_data);
+
+ EContactQuickAddCallback cb = gtk_object_get_data (GTK_OBJECT (card), "e-contact-quick-add-cb");
+ gpointer cb_user_data = gtk_object_get_data (GTK_OBJECT (card), "e-contact-quick-add-user-data");
+
+ if (status == E_BOOK_STATUS_SUCCESS) {
+ e_book_add_card (book, card, NULL, NULL);
+ if (cb)
+ cb (card, cb_user_data);
+ } else {
+ /* Something went wrong... */
+ if (cb)
+ cb (NULL, cb_user_data);
+
+ gtk_object_unref (GTK_OBJECT (book));
+ }
}
static void
add_card (ECard *card)
{
EBook *book = e_book_new ();
- gchar *filename, *uri;
-
- filename = gnome_util_prepend_user_home ("evolution/local/Contacts/addressbook.db");
- uri = g_strdup_printf ("file://%s", filename);
-
- e_book_load_uri (book, uri, book_ready_cb, card);
-
- g_free (filename);
- g_free (uri);
+ e_book_load_local_address_book (book, book_ready_cb, card);
}
+/*
+ * Raise a contact editor with all fields editable, and hook up all signals accordingly.
+ */
+
static void
add_card_cb (EContactEditor *ce, ECard *card, gpointer user_data)
{
@@ -108,12 +107,55 @@ add_card_cb (EContactEditor *ce, ECard *card, gpointer user_data)
static void
editor_closed_cb (GtkWidget *w, gpointer user_data)
{
+ /* w is the contact editor, user_data is an ECard. */
if (user_data)
gtk_object_unref (user_data);
gtk_object_unref (GTK_OBJECT (w));
}
static void
+ce_book_found_fields (EBook *book, EBookStatus status, EList *fields, gpointer user_data)
+{
+ ECard *card = E_CARD (user_data);
+ EContactEditor *contact_editor;
+
+ if (status != E_BOOK_STATUS_SUCCESS) {
+ g_warning ("Couldn't find supported fields for local address book.");
+ return;
+ }
+
+ contact_editor = e_contact_editor_new (card, TRUE, fields);
+
+ gtk_signal_connect (GTK_OBJECT (contact_editor),
+ "add_card",
+ GTK_SIGNAL_FUNC (add_card_cb),
+ NULL);
+ gtk_signal_connect (GTK_OBJECT (contact_editor),
+ "editor_closed",
+ GTK_SIGNAL_FUNC (editor_closed_cb),
+ user_data);
+
+ e_contact_editor_raise (contact_editor);
+}
+
+static void
+ce_book_ready (EBook *book, EBookStatus status, gpointer user_data)
+{
+ if (status != E_BOOK_STATUS_SUCCESS) {
+ g_warning ("Couldn't open local address book.");
+ return;
+ }
+
+ e_book_get_supported_fields (book, ce_book_found_fields, user_data);
+}
+
+static void
+edit_card (ECard *card)
+{
+ e_book_load_local_address_book (e_book_new (), ce_book_ready, card);
+}
+
+static void
clicked_cb (GtkWidget *w, gint button, gpointer user_data)
{
ECard *card = E_CARD (user_data);
@@ -149,19 +191,7 @@ clicked_cb (GtkWidget *w, gint button, gpointer user_data)
} else if (button == 1) {
/* EDIT FULL */
- EContactEditor *contact_editor;
- contact_editor = e_contact_editor_new (card, TRUE, NULL);
-
- gtk_signal_connect (GTK_OBJECT (contact_editor),
- "add_card",
- GTK_SIGNAL_FUNC (add_card_cb),
- NULL);
- gtk_signal_connect (GTK_OBJECT (contact_editor),
- "editor_closed",
- GTK_SIGNAL_FUNC (editor_closed_cb),
- user_data);
-
- e_contact_editor_raise (contact_editor);
+ edit_card (card);
} else {
/* CANCEL */
@@ -249,16 +279,6 @@ e_contact_quick_add (const gchar *name, const gchar *email,
ECard *new_card;
GtkWidget *dialog;
- if (out == NULL) {
- out = fopen ("/tmp/barnass", "w");
- if (out)
- setvbuf (out, NULL, _IONBF, 0);
- }
-
- if (out)
- fprintf (out, "\n name: %s\nemail: %s\n", name, email);
-
-
/* We need to have *something* to work with. */
if (name == NULL && email == NULL) {
if (cb)
@@ -280,3 +300,85 @@ e_contact_quick_add (const gchar *name, const gchar *email,
gtk_widget_show_all (dialog);
}
+
+void
+e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer user_data)
+{
+ gchar *name=NULL, *email=NULL;
+ const gchar *last_at, *s;
+ gboolean in_quote;
+
+ if (text == NULL) {
+ e_contact_quick_add (NULL, NULL, cb, user_data);
+ return;
+ }
+
+ /* Look for things that look like e-mail addresses embedded in text */
+ in_quote = FALSE;
+ last_at = NULL;
+ for (s = text; *s; ++s) {
+ if (*s == '@' && !in_quote)
+ last_at = s;
+ else if (*s == '"')
+ in_quote = !in_quote;
+ }
+
+
+ if (last_at == NULL) {
+ /* No at sign, so we treat it all as the name */
+ name = g_strdup (text);
+ } else {
+ gboolean bad_char = FALSE;
+
+ /* walk backwards to whitespace or a < or a quote... */
+ while (last_at >= text && !bad_char
+ && !(isspace ((gint) *last_at) || *last_at == '<' || *last_at == '"')) {
+ /* Check for some stuff that can't appear in a legal e-mail address. */
+ if (*last_at == '['
+ || *last_at == ']'
+ || *last_at == '('
+ || *last_at == ')')
+ bad_char = TRUE;
+ --last_at;
+ }
+ if (last_at < text)
+ last_at = text;
+
+ /* ...and then split the text there */
+ if (!bad_char) {
+ if (text < last_at)
+ name = g_strndup (text, last_at-text);
+ email = g_strdup (last_at);
+ }
+ }
+
+ /* If all else has failed, make it the name. */
+ if (name == NULL && email == NULL)
+ name = g_strdup (text);
+
+
+ /* Clean up name */
+ if (name && *name)
+ g_strstrip (name);
+
+ /* Clean up email, remove bracketing <>s */
+ if (email && *email) {
+ gboolean changed = FALSE;
+ g_strstrip (email);
+ if (*email == '<') {
+ *email = ' ';
+ changed = TRUE;
+ }
+ if (email[strlen (email)-1] == '>') {
+ email[strlen (email)-1] = ' ';
+ changed = TRUE;
+ }
+ if (changed)
+ g_strstrip (email);
+ }
+
+
+ e_contact_quick_add (name, email, cb, user_data);
+ g_free (name);
+ g_free (email);
+}
diff --git a/addressbook/gui/contact-editor/e-contact-quick-add.h b/addressbook/gui/contact-editor/e-contact-quick-add.h
index 630dfd2ad0..9d928e43f4 100644
--- a/addressbook/gui/contact-editor/e-contact-quick-add.h
+++ b/addressbook/gui/contact-editor/e-contact-quick-add.h
@@ -36,5 +36,7 @@ typedef void (*EContactQuickAddCallback) (ECard *new_card, gpointer user_data);
void e_contact_quick_add (const gchar *name, const gchar *email,
EContactQuickAddCallback cb, gpointer user_data);
+void e_contact_quick_add_free_form (const gchar *text, EContactQuickAddCallback cb, gpointer user_data);
+
#endif /* __E_CONTACT_QUICK_ADD_H__ */
diff --git a/mail/ChangeLog b/mail/ChangeLog
index f6a3ef6da5..48757cd6f8 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,3 +1,20 @@
+2001-03-08 Jon Trowbridge <trow@ximian.com>
+
+ * mail-format.c (write_field_row_begin): Added. Table row HTML
+ broken out into its own function.
+ (write_subject): Added. Emits the proper HTML for the subject
+ line.
+ (write_field_to_stream): #ifdef-ed out of existence.
+ (write_address): Take a CamelInternetAddress and spit out an
+ <object> tag with the appropriate <param>s.
+
+ * mail-display.c (on_object_requested): Check for an "address"
+ object. If found, call...
+ (handle_embedded_address_object): ...this function, which creates
+ an AddressWidget bonobo control and passes in the necessary info.
+ I never really realized just quite how much GtkHTML kicks ass
+ until I figured out how to make this work.
+
2001-03-08 Jeffrey Stedfast <fejj@ximian.com>
* mail-vtrash.[c,h]: Removed from cvs
diff --git a/mail/mail-display.c b/mail/mail-display.c
index 9f599bc797..8304cbc595 100644
--- a/mail/mail-display.c
+++ b/mail/mail-display.c
@@ -603,6 +603,33 @@ get_embedded_for_component (const char *iid, MailDisplay *md)
return embedded;
}
+static void
+handle_embedded_address_object (GtkHTMLEmbedded *eb)
+{
+ const gchar *name, *email;
+ GtkWidget *w;
+
+ w = bonobo_widget_new_control ("OAFIID:GNOME_Evolution_Addressbook_AddressWidget",
+ CORBA_OBJECT_NIL);
+
+ name = gtk_html_embedded_get_parameter (eb, "name");
+ email = gtk_html_embedded_get_parameter (eb, "email");
+
+ bonobo_widget_set_property (BONOBO_WIDGET (w),
+ "name", name,
+ "email", email,
+ /* Hackish: this is the bg color defined for the HTML table
+ in mail-format.c. If you change it there, you'd better
+ change it here as well. */
+ "background_rgb", 0xeeeeee,
+ NULL);
+
+ gtk_widget_show (w);
+ gtk_container_add (GTK_CONTAINER (eb), w);
+
+ gtk_html_embedded_set_descent (eb, 0);
+}
+
static gboolean
on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
{
@@ -621,6 +648,12 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data)
char *cid;
cid = eb->classid;
+
+ if (!strcmp (cid, "address")) {
+ handle_embedded_address_object (eb);
+ return TRUE;
+ }
+
if (!strncmp (cid, "popup:", 6))
cid += 6;
if (strncmp (cid, "cid:", 4) != 0)
diff --git a/mail/mail-format.c b/mail/mail-format.c
index 27849d54b7..7c8fed1ff7 100644
--- a/mail/mail-format.c
+++ b/mail/mail-format.c
@@ -575,9 +575,42 @@ enum {
};
static void
+write_field_row_begin (const char *description, gint flags, GtkHTML *html, GtkHTMLStream *stream)
+{
+ char *encoded_desc;
+ int bold = (flags & WRITE_BOLD) == WRITE_BOLD;
+
+ encoded_desc = e_utf8_from_gtk_string (GTK_WIDGET (html), description);
+
+ mail_html_write (html, stream, "<tr><%s align=right> %s </%s>",
+ bold ? "th" : "td", encoded_desc, bold ? "th" : "td");
+
+ g_free (encoded_desc);
+}
+
+static void
+write_subject (const char *subject, int flags, GtkHTML *html, GtkHTMLStream *stream)
+{
+ char *encoded_subj;
+
+ if (subject)
+ encoded_subj = e_text_to_html (subject, E_TEXT_TO_HTML_CONVERT_NL | E_TEXT_TO_HTML_CONVERT_URLS);
+ else
+ encoded_subj = "";
+
+ write_field_row_begin (_("Subject:"), flags, html, stream);
+
+ mail_html_write (html, stream, "<td> %s </td> </tr>", encoded_subj);
+
+ if (subject)
+ g_free (encoded_subj);
+}
+
+#ifdef USE_OBSOLETE_UNUSED_STUFF_AND_GET_COMPILER_WARNINGS
+static void
write_field_to_stream(const char *description, const char *value, int flags, GtkHTML *html, GtkHTMLStream *stream)
{
- char *encoded_desc, *encoded_value;
+ char *encoded_desc, *encoded_value, *embedded_object;
int bold = (flags&WRITE_BOLD) == WRITE_BOLD;
/* The description comes from gettext... */
@@ -590,26 +623,45 @@ write_field_to_stream(const char *description, const char *value, int flags, Gtk
mail_html_write(html, stream,
"<tr valign=top><%s align=right>%s</%s>"
- "<td>%s</td></tr>", bold ? "th" : "td",
+ "<td> %s </td></tr>", bold ? "th" : "td",
encoded_desc, bold ? "th" : "td", encoded_value);
g_free (encoded_desc);
+ g_free (embedded_object);
if (value)
g_free(encoded_value);
}
+#endif
static void
-write_address(MailDisplay *md, const CamelInternetAddress *addr, const char *name, int flags)
+write_address(MailDisplay *md, const CamelInternetAddress *addr, const char *field_name, int flags)
{
- char *string;
+ const char *name, *email;
+ gint i;
- if (addr == NULL)
+ if (addr == NULL || !camel_internet_address_get (addr, 0, NULL, NULL))
return;
- string = camel_address_format((CamelAddress *)addr);
- if (string && string[0]) {
- write_field_to_stream(name, string, flags, md->html, md->stream);
+ write_field_row_begin (field_name, flags, md->html, md->stream);
+
+ i = 0;
+ while (camel_internet_address_get (addr, i, &name, &email)) {
+
+ if ((name && *name) || (email && *email)) {
+
+ mail_html_write (md->html, md->stream, i ? ", " : "<td>");
+
+ mail_html_write (md->html, md->stream, "<object classid=\"address\">");
+ if (name && *name)
+ mail_html_write (md->html, md->stream, "<param name=\"name\" value=\"%s\"/>", name);
+ if (email && *email)
+ mail_html_write (md->html, md->stream, "<param name=\"email\" value=\"%s\"/>", email);
+ mail_html_write (md->html, md->stream, "</object>");
+ }
+
+ ++i;
}
- g_free(string);
+
+ mail_html_write (md->html, md->stream, "</td></tr>"); /* Finish up the table row */
}
@@ -632,9 +684,7 @@ write_headers (CamelMimeMessage *message, MailDisplay *md)
write_address(md, camel_mime_message_get_recipients(message, CAMEL_RECIPIENT_TYPE_CC),
_("Cc:"), WRITE_BOLD);
- write_field_to_stream (_("Subject:"),
- camel_mime_message_get_subject (message),
- TRUE, md->html, md->stream);
+ write_subject (camel_mime_message_get_subject (message), WRITE_BOLD, md->html, md->stream);
mail_html_write (md->html, md->stream,
"</table></td></tr></table></td></tr></table></font>");