예제 #1
0
static void
render_contact_column (EABContactFormatter *formatter,
                       EContact *contact,
                       GString *buffer)
{
	GString *accum, *email;
	GList *email_list, *l, *email_attr_list, *al;
	gint email_num = 0;
	const gchar *nl;
	guint32 sip_flags = 0;

	if (formatter->priv->supports_sip)
		sip_flags = E_TEXT_TO_HTML_CONVERT_URLS |
			    E_TEXT_TO_HTML_HIDE_URL_SCHEME |
			    E_TEXT_TO_HTML_URL_IS_WHOLE_TEXT |
			    E_CREATE_SIP_URL;

	email = g_string_new ("");
	nl = "";

	email_list = e_contact_get (contact, E_CONTACT_EMAIL);
	email_attr_list = e_contact_get_attributes (contact, E_CONTACT_EMAIL);

	for (l = email_list, al = email_attr_list; l && al; l = l->next, al = al->next) {
		gchar *name = NULL, *mail = NULL;
		gchar *attr_str = (gchar *) get_email_location ((EVCardAttribute *) al->data);

		if (!eab_parse_qp_email (l->data, &name, &mail))
			mail = e_text_to_html (l->data, 0);

		g_string_append_printf (
			email,
			"%s%s%s<a href=\"internal-mailto:%d\">%s</a>%s "
			"<span class=\"header\">(%s)</span>",
			nl,
			name ? name : "",
			name ? " &lt;" : "",
			email_num,
			mail,
			name ? "&gt;" : "",
			attr_str ? attr_str : "");
		email_num++;
		nl = "<br>";

		g_free (name);
		g_free (mail);
	}
	g_list_foreach (email_list, (GFunc) g_free, NULL);
	g_list_foreach (email_attr_list, (GFunc) e_vcard_attribute_free, NULL);
	g_list_free (email_list);
	g_list_free (email_attr_list);

	accum = g_string_new ("");

	if (email->len)
		render_table_row (accum, _("Email"), email->str, NULL, 0);

	accum_sip (accum, contact, EAB_CONTACT_FORMATTER_SIP_TYPE_OTHER, NULL, sip_flags);

	accum_attribute (accum, contact, _("Nickname"), E_CONTACT_NICKNAME, NULL, 0);
	accum_attribute_multival (accum, contact, _("AIM"), E_CONTACT_IM_AIM, AIM_ICON, 0);
	accum_attribute_multival (accum, contact, _("GroupWise"), E_CONTACT_IM_GROUPWISE, GROUPWISE_ICON, 0);
	accum_attribute_multival (accum, contact, _("ICQ"), E_CONTACT_IM_ICQ, ICQ_ICON, 0);
	accum_attribute_multival (accum, contact, _("Jabber"), E_CONTACT_IM_JABBER, JABBER_ICON, 0);
	accum_attribute_multival (accum, contact, _("MSN"), E_CONTACT_IM_MSN, MSN_ICON, 0);
	accum_attribute_multival (accum, contact, _("Yahoo"), E_CONTACT_IM_YAHOO, YAHOO_ICON, 0);
	accum_attribute_multival (accum, contact, _("Gadu-Gadu"), E_CONTACT_IM_GADUGADU, GADUGADU_ICON, 0);
	accum_attribute_multival (accum, contact, _("Skype"), E_CONTACT_IM_SKYPE, SKYPE_ICON, 0);
	accum_attribute_multival (accum, contact, _("Twitter"), E_CONTACT_IM_TWITTER, TWITTER_ICON, 0);

	if (accum->len)
		g_string_append_printf (
			buffer,
			"<div class=\"column\" id=\"contact-internet\">"
			"<table border=\"0\" cellspacing=\"5\">%s</table>"
			"</div>", accum->str);

	g_string_free (accum, TRUE);
	g_string_free (email, TRUE);
}
예제 #2
0
static void
accum_sip (GString *buffer,
	   EContact *contact,
	   EABContactFormatterSIPType use_sip_type,
	   const gchar *icon,
	   guint html_flags)
{
	const gchar *html_label = _("SIP");
	GList *sip_attr_list, *l;
	GString *val = g_string_new ("");
	gchar *tmp;

	sip_attr_list = e_contact_get_attributes (contact, E_CONTACT_SIP);
	for (l = sip_attr_list; l; l = g_list_next (l)) {
		EVCardAttribute *attr = l->data;
		gchar *sip;
		const gchar *str;
		EABContactFormatterSIPType sip_type;

		if (e_vcard_attribute_has_type (attr, "HOME"))
			sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_HOME;
		else if (e_vcard_attribute_has_type (attr, "WORK"))
			sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_WORK;
		else
			sip_type = EAB_CONTACT_FORMATTER_SIP_TYPE_OTHER;

		if (sip_type != use_sip_type)
			continue;

		sip = e_vcard_attribute_get_value (attr);
		if (!sip || !*sip) {
			g_free (sip);
			continue;
		}

		tmp = maybe_create_url (sip, html_flags);
		if (tmp)
			str = tmp;
		else
			str = sip;

		if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0) {
			gchar *value = e_text_to_html (str, html_flags);

			if (value && *value) {
				if (val->len)
					g_string_append (val, "<br>");
				g_string_append (val, value);
			}

			g_free (value);
		} else {
			if (val->len)
				g_string_append (val, "<br>");
			g_string_append (val, str);
		}

		g_free (tmp);
		g_free (sip);
	}

	if (val->str && *val->str) {
		if ((html_flags & E_TEXT_TO_HTML_CONVERT_URLS) != 0)
			html_flags = 0;

		render_table_row (buffer, html_label, val->str, icon, html_flags);
	}

	g_string_free (val, TRUE);
	g_list_free_full (sip_attr_list, (GDestroyNotify) e_vcard_attribute_free);
}
예제 #3
0
/* utility functions shared between all contact importers */
static void
preview_contact (EWebViewPreview *preview,
                 EContact *contact)
{
	gint idx;
	gboolean had_value = FALSE;

	const gint fields[] = {
		E_CONTACT_FILE_AS,
		E_CONTACT_CATEGORIES,

		E_CONTACT_IS_LIST,
		E_CONTACT_LIST_SHOW_ADDRESSES,
		E_CONTACT_WANTS_HTML,

		E_CONTACT_FULL_NAME,
		E_CONTACT_GIVEN_NAME,
		E_CONTACT_FAMILY_NAME,
		E_CONTACT_NICKNAME,
		E_CONTACT_SPOUSE,
		E_CONTACT_BIRTH_DATE,
		E_CONTACT_ANNIVERSARY,
		E_CONTACT_MAILER,
		E_CONTACT_EMAIL,

		-1,

		E_CONTACT_ORG,
		E_CONTACT_ORG_UNIT,
		E_CONTACT_OFFICE,
		E_CONTACT_TITLE,
		E_CONTACT_ROLE,
		E_CONTACT_MANAGER,
		E_CONTACT_ASSISTANT,

		-1,

		E_CONTACT_PHONE_ASSISTANT,
		E_CONTACT_PHONE_BUSINESS,
		E_CONTACT_PHONE_BUSINESS_2,
		E_CONTACT_PHONE_BUSINESS_FAX,
		E_CONTACT_PHONE_CALLBACK,
		E_CONTACT_PHONE_CAR,
		E_CONTACT_PHONE_COMPANY,
		E_CONTACT_PHONE_HOME,
		E_CONTACT_PHONE_HOME_2,
		E_CONTACT_PHONE_HOME_FAX,
		E_CONTACT_PHONE_ISDN,
		E_CONTACT_PHONE_MOBILE,
		E_CONTACT_PHONE_OTHER,
		E_CONTACT_PHONE_OTHER_FAX,
		E_CONTACT_PHONE_PAGER,
		E_CONTACT_PHONE_PRIMARY,
		E_CONTACT_PHONE_RADIO,
		E_CONTACT_PHONE_TELEX,
		E_CONTACT_PHONE_TTYTDD,

		-1,

		E_CONTACT_ADDRESS_HOME,
		E_CONTACT_ADDRESS_WORK,
		E_CONTACT_ADDRESS_OTHER,

		-1,

		E_CONTACT_HOMEPAGE_URL,
		E_CONTACT_BLOG_URL,
		E_CONTACT_CALENDAR_URI,
		E_CONTACT_FREEBUSY_URL,
		E_CONTACT_ICS_CALENDAR,
		E_CONTACT_VIDEO_URL,

		-1,

		E_CONTACT_IM_AIM,
		E_CONTACT_IM_GROUPWISE,
		E_CONTACT_IM_JABBER,
		E_CONTACT_IM_YAHOO,
		E_CONTACT_IM_MSN,
		E_CONTACT_IM_ICQ,
		E_CONTACT_IM_GADUGADU,
		E_CONTACT_IM_SKYPE,

		-1,

		E_CONTACT_NOTE
	};

	g_return_if_fail (preview != NULL);
	g_return_if_fail (contact != NULL);

	for (idx = 0; idx < G_N_ELEMENTS (fields); idx++) {
		EContactField field;

		if (fields[idx] == -1) {
			if (had_value)
				e_web_view_preview_add_empty_line (preview);
			had_value = FALSE;
			continue;
		}

		field = fields[idx];

		if (field == E_CONTACT_BIRTH_DATE || field == E_CONTACT_ANNIVERSARY) {
			EContactDate *dt = e_contact_get (contact, field);
			if (dt) {
				GDate gd = { 0 };
				struct tm tm;
				gchar *value;

				g_date_set_dmy (&gd, dt->day, dt->month, dt->year);
				g_date_to_struct_tm (&gd, &tm);

				value = e_datetime_format_format_tm (
					"addressbook", "table",
					DTFormatKindDate, &tm);
				if (value) {
					e_web_view_preview_add_section (
						preview,
						e_contact_pretty_name (field),
						value);
					had_value = TRUE;
				}

				g_free (value);
				e_contact_date_free (dt);
			}
		} else if (field == E_CONTACT_IS_LIST ||
			   field == E_CONTACT_WANTS_HTML ||
			   field == E_CONTACT_LIST_SHOW_ADDRESSES) {
			if (e_contact_get (contact, field)) {
				e_web_view_preview_add_text (
					preview, e_contact_pretty_name (field));
				had_value = TRUE;
			}
		} else if (field == E_CONTACT_ADDRESS_HOME ||
			   field == E_CONTACT_ADDRESS_WORK ||
			   field == E_CONTACT_ADDRESS_OTHER) {
			EContactAddress *addr = e_contact_get (contact, field);
			if (addr) {
				gboolean have = FALSE;

				#define add_it(_what)	\
					if (addr->_what && *addr->_what) {	\
						e_web_view_preview_add_section ( \
							preview, have ? NULL : \
							e_contact_pretty_name (field), addr->_what);	\
						have = TRUE;	\
						had_value = TRUE;	\
					}

				add_it (po);
				add_it (ext);
				add_it (street);
				add_it (locality);
				add_it (region);
				add_it (code);
				add_it (country);

				#undef add_it

				e_contact_address_free (addr);
			}
		} else if (field == E_CONTACT_IM_AIM ||
			   field == E_CONTACT_IM_GROUPWISE ||
			   field == E_CONTACT_IM_JABBER ||
			   field == E_CONTACT_IM_YAHOO ||
			   field == E_CONTACT_IM_MSN ||
			   field == E_CONTACT_IM_ICQ ||
			   field == E_CONTACT_IM_GADUGADU ||
			   field == E_CONTACT_IM_SKYPE ||
			   field == E_CONTACT_EMAIL) {
			GList *attrs, *a;
			gboolean have = FALSE;
			const gchar *pretty_name;

			pretty_name = e_contact_pretty_name (field);

			attrs = e_contact_get_attributes (contact, field);
			for (a = attrs; a; a = a->next) {
				EVCardAttribute *attr = a->data;
				GList *value;

				if (!attr)
					continue;

				value = e_vcard_attribute_get_values (attr);

				while (value != NULL) {
					const gchar *str = value->data;

					if (str && *str) {
						e_web_view_preview_add_section (
							preview, have ? NULL :
							pretty_name, str);
						have = TRUE;
						had_value = TRUE;
					}

					value = value->next;
				}

				e_vcard_attribute_free (attr);
			}

			g_list_free (attrs);

		} else if (field == E_CONTACT_CATEGORIES) {
			const gchar *pretty_name;
			const gchar *value;

			pretty_name = e_contact_pretty_name (field);
			value = e_contact_get_const (contact, field);

			if (value != NULL && *value != '\0') {
				e_web_view_preview_add_section (
					preview, pretty_name, value);
				had_value = TRUE;
			}

		} else {
			const gchar *pretty_name;
			const gchar *value;

			pretty_name = e_contact_pretty_name (field);
			value = e_contact_get_const (contact, field);

			if (value != NULL && *value != '\0') {
				e_web_view_preview_add_section (
					preview, pretty_name, value);
				had_value = TRUE;
			}
		}
	}
}
예제 #4
0
static void
vcard_import_contact (VCardImporter *gci,
                      EContact *contact)
{
	EContactPhoto *photo;
	GList *attrs, *attr;
	gchar *uid = NULL;

	/* Apple's addressbook.app exports PHOTO's without a TYPE
	 * param, so let's figure out the format here if there's a
	 * PHOTO attribute missing a TYPE param.
	 *
	 * this is sort of a hack, as EContact sets the type for us if
	 * we use the setter.  so let's e_contact_get + e_contact_set
	 * on E_CONTACT_PHOTO.
	*/
	photo = e_contact_get (contact, E_CONTACT_PHOTO);
	if (photo) {
		e_contact_set (contact, E_CONTACT_PHOTO, photo);
		e_contact_photo_free (photo);
	}

	/* Deal with our XML EDestination stuff in EMAIL attributes, if there is any. */
	attrs = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
	for (attr = attrs; attr; attr = attr->next) {
		EVCardAttribute *a = attr->data;
		GList *v = e_vcard_attribute_get_values (a);

		if (v && v->data) {
			if (!strncmp ((gchar *)v->data, "<?xml", 5)) {
				EDestination *dest = e_destination_import ((gchar *) v->data);

				e_destination_export_to_vcard_attribute (dest, a);

				g_object_unref (dest);

			}
		}
	}
	e_contact_set_attributes (contact, E_CONTACT_EMAIL, attrs);

	/* Deal with TEL attributes that don't conform to what we need.
	 *
	 * 1. if there's no location (HOME/WORK/OTHER), default to OTHER.
	 * 2. if there's *only* a location specified, default to VOICE.
	 */
	attrs = e_vcard_get_attributes (E_VCARD (contact));
	for (attr = attrs; attr; attr = attr->next) {
		EVCardAttribute *a = attr->data;
		gboolean location_only = TRUE;
		gboolean no_location = TRUE;
		gboolean is_work_home = FALSE;
		GList *params, *param;

		if (g_ascii_strcasecmp (e_vcard_attribute_get_name (a),
					EVC_TEL))
			continue;

		params = e_vcard_attribute_get_params (a);
		for (param = params; param; param = param->next) {
			EVCardAttributeParam *p = param->data;
			GList *vs, *v;

			if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (p),
						EVC_TYPE))
				continue;

			vs = e_vcard_attribute_param_get_values (p);
			for (v = vs; v; v = v->next) {
				is_work_home = is_work_home ||
					!g_ascii_strcasecmp ((gchar *)v->data, "WORK") ||
					!g_ascii_strcasecmp ((gchar *)v->data, "HOME");

				if (!g_ascii_strcasecmp ((gchar *)v->data, "WORK") ||
				    !g_ascii_strcasecmp ((gchar *)v->data, "HOME") ||
				    !g_ascii_strcasecmp ((gchar *)v->data, "OTHER"))
					no_location = FALSE;
				else
					location_only = FALSE;
			}
		}

		if (is_work_home) {
			/* only WORK and HOME phone numbers require locations,
			 * the rest should be kept as is */
			if (location_only) {
				/* add VOICE */
				e_vcard_attribute_add_param_with_value (a,
									e_vcard_attribute_param_new (EVC_TYPE),
									"VOICE");
			}
			if (no_location) {
				/* add OTHER */
				e_vcard_attribute_add_param_with_value (a,
									e_vcard_attribute_param_new (EVC_TYPE),
									"OTHER");
			}
		}
	}

	/* Deal with ADR and EMAIL attributes that don't conform to what
	 * we need.  If HOME or WORK isn't specified, add TYPE=OTHER. */
	attrs = e_vcard_get_attributes (E_VCARD (contact));
	for (attr = attrs; attr; attr = attr->next) {
		EVCardAttribute *a = attr->data;
		gboolean no_location = TRUE;
		GList *params, *param;

		if (g_ascii_strcasecmp (e_vcard_attribute_get_name (a), EVC_ADR) &&
		    g_ascii_strcasecmp (e_vcard_attribute_get_name (a), EVC_EMAIL))
			continue;

		params = e_vcard_attribute_get_params (a);
		for (param = params; param; param = param->next) {
			EVCardAttributeParam *p = param->data;
			GList *vs, *v;

			if (g_ascii_strcasecmp (e_vcard_attribute_param_get_name (p),
						EVC_TYPE))
				continue;

			vs = e_vcard_attribute_param_get_values (p);
			for (v = vs; v; v = v->next) {
				if (!g_ascii_strcasecmp ((gchar *)v->data, "WORK") ||
				    !g_ascii_strcasecmp ((gchar *)v->data, "HOME"))
					no_location = FALSE;
			}
		}

		if (no_location) {
			/* add OTHER */
			e_vcard_attribute_add_param_with_value (a,
								e_vcard_attribute_param_new (EVC_TYPE),
								"OTHER");
		}
	}

	/* Work around the fact that these fields no longer show up in the UI */
	add_to_notes (contact, E_CONTACT_OFFICE);
	add_to_notes (contact, E_CONTACT_SPOUSE);
	add_to_notes (contact, E_CONTACT_BLOG_URL);

	/* FIXME Error checking */
	if (e_book_client_add_contact_sync (gci->book_client, contact, &uid, NULL, NULL) && uid) {
		e_contact_set (contact, E_CONTACT_UID, uid);
		g_free (uid);
	}
}
예제 #5
0
static gboolean
check_if_same (EContact *contact,
               EContact *match)
{
	EContactField field;
	gchar *string = NULL, *string1 = NULL;
	gboolean res = TRUE;


	for (field = E_CONTACT_FULL_NAME; res && field != (E_CONTACT_LAST_SIMPLE_STRING -1); field++) {

		if (field == E_CONTACT_EMAIL_1) {
			GList *email_attr_list1, *email_attr_list2, *iter1, *iter2;
			gint num_of_email1, num_of_email2;

			email_attr_list1 = e_contact_get_attributes (contact, E_CONTACT_EMAIL);
			num_of_email1 = g_list_length (email_attr_list1);

			email_attr_list2 = e_contact_get_attributes (match, E_CONTACT_EMAIL);
			num_of_email2 = g_list_length (email_attr_list2);

			if (num_of_email1 != num_of_email2) {
				res = FALSE;
				break;
			} else { /* Do pairwise-comparisons on all of the e-mail addresses. */
				iter1 = email_attr_list1;
				while (iter1) {
					gboolean         match = FALSE;
					EVCardAttribute *attr;
					gchar           *email_address1;

					attr = iter1->data;
					email_address1 = e_vcard_attribute_get_value (attr);

					iter2 = email_attr_list2;
					while ( iter2 && match == FALSE) {
						gchar *email_address2;

						attr = iter2->data;
						email_address2 = e_vcard_attribute_get_value (attr);

						if (g_ascii_strcasecmp (email_address1, email_address2) == 0) {
							match = TRUE;
						}

						g_free (email_address2);
						iter2 = g_list_next (iter2);
					}

					g_free (email_address1);
					iter1 = g_list_next (iter1);

					if (match == FALSE) {
						res = FALSE;
						break;
					}
				}
			}

			g_list_free_full (email_attr_list1, (GDestroyNotify) e_vcard_attribute_free);
			g_list_free_full (email_attr_list2, (GDestroyNotify) e_vcard_attribute_free);
		} else if (field > E_CONTACT_FIRST_EMAIL_ID && field <= E_CONTACT_LAST_EMAIL_ID) {
			/* nothing to do, all emails are checked above */
		}
		else {
			string = (gchar *) e_contact_get_const (contact, field);
			string1 = (gchar *) e_contact_get_const (match, field);
			if ((string && *string) && (string1 && *string1) && (g_ascii_strcasecmp (string1, string))) {
				res = FALSE;
				break;
			/*if the field entry exist in either of the contacts,we'll have to give the choice and thus merge button should be sensitive*/
			} else if ((string && *string) && !(string1 && *string1)) {
				res = FALSE;
				break;
			}
		}
	}

	return res;
}
예제 #6
0
static gint
mergeit (EContactMergingLookup *lookup)
{
	GtkWidget *scrolled_window, *label, *hbox, *dropdown;
	GtkWidget *content_area;
	GtkWidget *dialog;
	GtkTable *table;
	EContactField field;
	gchar *string = NULL, *string1 = NULL;
	GList *use_email_attr_list, *contact_email_attr_list, *match_email_attr_list;
	GList *use_tel_attr_list, *contact_tel_attr_list, *match_tel_attr_list;
	GList *use_im_attr_list, *contact_im_attr_list, *match_im_attr_list;
	GList *use_sip_attr_list, *contact_sip_attr_list, *match_sip_attr_list;
	gint row = -1;
	gint value = 0, result;

	dialog = gtk_dialog_new ();
	gtk_window_set_title (GTK_WINDOW (dialog), _("Merge Contact"));
	gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);

	content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));

	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
	gtk_scrolled_window_set_policy (
		GTK_SCROLLED_WINDOW (scrolled_window),
		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

	table = (GtkTable *) gtk_table_new (20, 2, FALSE);
	gtk_container_set_border_width ((GtkContainer *) table, 12);
	gtk_table_set_row_spacings (table, 6);
	gtk_table_set_col_spacings (table, 2);

	gtk_dialog_add_buttons (
		GTK_DIALOG (dialog),
		_("_Cancel"), GTK_RESPONSE_CANCEL,
		_("_Merge"), GTK_RESPONSE_OK,
		NULL);


	/*we match all the string fields of the already existing contact and the new contact.*/
	for (field = E_CONTACT_FULL_NAME; field != (E_CONTACT_LAST_SIMPLE_STRING -1); field++) {
		dropdown_data *data = NULL;
		string = (gchar *) e_contact_get_const (lookup->contact, field);
		string1 = (gchar *) e_contact_get_const (lookup->match, field);

		/*the field must exist in the new as well as the duplicate contact*/
		if (string && *string) {
			if ((field >= E_CONTACT_FIRST_EMAIL_ID && field <= E_CONTACT_LAST_EMAIL_ID) ||
			    (field >= E_CONTACT_FIRST_PHONE_ID && field <= E_CONTACT_LAST_PHONE_ID) ||
			    (field >= E_CONTACT_IM_AIM_HOME_1 && field <= E_CONTACT_IM_ICQ_WORK_3) ) {
				/* ignore multival attributes, they are compared after this for-loop */
				continue;
			}

			if (!(string1 && *string1) || (g_ascii_strcasecmp (string, string1))) {
				row++;
				label = gtk_label_new (e_contact_pretty_name (field));
				hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) label, FALSE, FALSE, 0);
				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 0, 1, row, row + 1);
				data = g_new0 (dropdown_data, 1);
				dropdown = gtk_combo_box_text_new ();
				gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), string);

				if (string1 && *string1)
					gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), string1);
				else
					gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dropdown), "");

				data->field = field;
				data->match = lookup->match;

				g_signal_connect (
					dropdown, "changed",
					G_CALLBACK (dropdown_changed), data);
				g_object_set_data_full (G_OBJECT (dropdown), "eab-contact-merging::dropdown-data", data, g_free);

				if (field == E_CONTACT_NICKNAME || field == E_CONTACT_GIVEN_NAME || field == E_CONTACT_FAMILY_NAME || field == E_CONTACT_FULL_NAME)
					gtk_combo_box_set_active (GTK_COMBO_BOX (dropdown), 1);
				else
					gtk_combo_box_set_active (GTK_COMBO_BOX (dropdown), 0);

				hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
				gtk_box_pack_start (GTK_BOX (hbox), (GtkWidget *) dropdown, FALSE, FALSE, 0);
				gtk_table_attach_defaults (table, (GtkWidget *) hbox, 1, 2, row, row + 1);
				gtk_widget_show_all ((GtkWidget *) dropdown);
			}
		}
	}

	match_email_attr_list = e_contact_get_attributes (lookup->match, E_CONTACT_EMAIL);
	contact_email_attr_list = e_contact_get_attributes (lookup->contact, E_CONTACT_EMAIL);
	use_email_attr_list = NULL;
	create_dropdowns_for_multival_attr (match_email_attr_list, contact_email_attr_list,
	                                   &use_email_attr_list, &row, table, _("Email"));

	match_tel_attr_list = e_contact_get_attributes (lookup->match, E_CONTACT_TEL);
	contact_tel_attr_list = e_contact_get_attributes (lookup->contact, E_CONTACT_TEL);
	use_tel_attr_list = NULL;
	create_dropdowns_for_multival_attr (match_tel_attr_list, contact_tel_attr_list,
	                                   &use_tel_attr_list, &row, table, _("Phone"));

	match_sip_attr_list = e_contact_get_attributes (lookup->match, E_CONTACT_SIP);
	contact_sip_attr_list = e_contact_get_attributes (lookup->contact, E_CONTACT_SIP);
	use_sip_attr_list = NULL;
	create_dropdowns_for_multival_attr (match_sip_attr_list, contact_sip_attr_list,
	                                   &use_sip_attr_list, &row, table, _("SIP"));

	match_im_attr_list = e_contact_get_attributes_set (lookup->match, im_fetch_set, G_N_ELEMENTS (im_fetch_set));
	contact_im_attr_list = e_contact_get_attributes_set (lookup->contact, im_fetch_set, G_N_ELEMENTS (im_fetch_set));
	use_im_attr_list = NULL;
	create_dropdowns_for_multival_attr (match_im_attr_list, contact_im_attr_list,
	                                   &use_im_attr_list, &row, table, _("IM"));

	gtk_window_set_default_size (GTK_WINDOW (dialog), 420, 300);
	gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), GTK_WIDGET (table));
	gtk_box_pack_start (GTK_BOX (content_area), GTK_WIDGET (scrolled_window), TRUE, TRUE, 0);
	gtk_widget_show (scrolled_window);
	g_signal_connect (
		dialog, "map-event",
		G_CALLBACK (dialog_map), table);
	gtk_widget_show_all ((GtkWidget *) table);
	result = gtk_dialog_run (GTK_DIALOG (dialog));

	switch (result) {
		gint ii;
		GList *ll;
	case GTK_RESPONSE_OK:
		set_attributes (lookup->match, E_CONTACT_EMAIL, use_email_attr_list);
		set_attributes (lookup->match, E_CONTACT_TEL, use_tel_attr_list);
		set_attributes (lookup->match, E_CONTACT_SIP, use_sip_attr_list);

		for (ii = 0; ii < G_N_ELEMENTS (im_fetch_set); ii++) {
			e_contact_set_attributes (lookup->match, im_fetch_set[ii], NULL);
		}

		for (ll = use_im_attr_list; ll; ll = ll->next) {
			EVCard *vcard;
			vcard = E_VCARD (lookup->match);
			e_vcard_append_attribute (vcard, e_vcard_attribute_copy ((EVCardAttribute *) ll->data));
		}

		g_object_unref (lookup->contact);
		lookup->contact = g_object_ref (lookup->match);
		e_book_client_remove_contact (
			lookup->book_client,
			lookup->match, NULL,
			remove_contact_ready_cb, lookup);
		value = 1;
		break;
	case GTK_RESPONSE_CANCEL:
	default:
		value = 0;
		break;
	}
	gtk_widget_destroy (dialog);

	g_list_free_full (match_email_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (contact_email_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free (use_email_attr_list);

	g_list_free_full (match_tel_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (contact_tel_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free (use_tel_attr_list);

	g_list_free_full (match_im_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (contact_im_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free (use_im_attr_list);

	g_list_free_full (match_sip_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free_full (contact_sip_attr_list, (GDestroyNotify) e_vcard_attribute_free);
	g_list_free (use_sip_attr_list);

	return value;
}