evolution-3.6.4/composer/e-composer-header-table.c

No issues found

   1 /*
   2  * This program is free software; you can redistribute it and/or
   3  * modify it under the terms of the GNU Lesser General Public
   4  * License as published by the Free Software Foundation; either
   5  * version 2 of the License, or (at your option) version 3.
   6  *
   7  * This program is distributed in the hope that it will be useful,
   8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10  * Lesser General Public License for more details.
  11  *
  12  * You should have received a copy of the GNU Lesser General Public
  13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
  14  *
  15  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
  16  */
  17 
  18 #ifdef HAVE_CONFIG_H
  19 #include <config.h>
  20 #endif
  21 
  22 #include "e-composer-header-table.h"
  23 
  24 #include <glib/gi18n-lib.h>
  25 #include <libedataserverui/libedataserverui.h>
  26 
  27 #include <shell/e-shell.h>
  28 #include <misc/e-mail-signature-combo-box.h>
  29 
  30 #include "e-msg-composer.h"
  31 #include "e-composer-private.h"
  32 #include "e-composer-from-header.h"
  33 #include "e-composer-name-header.h"
  34 #include "e-composer-post-header.h"
  35 #include "e-composer-spell-header.h"
  36 #include "e-composer-text-header.h"
  37 
  38 #define E_COMPOSER_HEADER_TABLE_GET_PRIVATE(obj) \
  39 	(G_TYPE_INSTANCE_GET_PRIVATE \
  40 	((obj), E_TYPE_COMPOSER_HEADER_TABLE, EComposerHeaderTablePrivate))
  41 
  42 #define HEADER_TOOLTIP_TO \
  43 	_("Enter the recipients of the message")
  44 #define HEADER_TOOLTIP_CC \
  45 	_("Enter the addresses that will receive a " \
  46 	  "carbon copy of the message")
  47 #define HEADER_TOOLTIP_BCC \
  48 	_("Enter the addresses that will receive a " \
  49 	  "carbon copy of the message without appearing " \
  50 	  "in the recipient list of the message")
  51 
  52 #define E_COMPOSER_HEADER_TABLE_GET_PRIVATE(obj) \
  53 	(G_TYPE_INSTANCE_GET_PRIVATE \
  54 	((obj), E_TYPE_COMPOSER_HEADER_TABLE, EComposerHeaderTablePrivate))
  55 
  56 struct _EComposerHeaderTablePrivate {
  57 	EComposerHeader *headers[E_COMPOSER_NUM_HEADERS];
  58 	GtkWidget *signature_label;
  59 	GtkWidget *signature_combo_box;
  60 	ENameSelector *name_selector;
  61 	ESourceRegistry *registry;
  62 	EShell *shell;
  63 };
  64 
  65 enum {
  66 	PROP_0,
  67 	PROP_DESTINATIONS_BCC,
  68 	PROP_DESTINATIONS_CC,
  69 	PROP_DESTINATIONS_TO,
  70 	PROP_IDENTITY_UID,
  71 	PROP_POST_TO,
  72 	PROP_REGISTRY,
  73 	PROP_REPLY_TO,
  74 	PROP_SHELL,
  75 	PROP_SIGNATURE_COMBO_BOX,
  76 	PROP_SIGNATURE_UID,
  77 	PROP_SUBJECT
  78 };
  79 
  80 G_DEFINE_TYPE (
  81 	EComposerHeaderTable,
  82 	e_composer_header_table,
  83 	GTK_TYPE_TABLE)
  84 
  85 static void
  86 g_value_set_destinations (GValue *value,
  87                           EDestination **destinations)
  88 {
  89 	GValueArray *value_array;
  90 	GValue element = G_VALUE_INIT;
  91 	gint ii;
  92 
  93 	g_value_init (&element, E_TYPE_DESTINATION);
  94 
  95 	/* Preallocate some reasonable number. */
  96 	value_array = g_value_array_new (64);
  97 
  98 	for (ii = 0; destinations[ii] != NULL; ii++) {
  99 		g_value_set_object (&element, destinations[ii]);
 100 		g_value_array_append (value_array, &element);
 101 	}
 102 
 103 	g_value_take_boxed (value, value_array);
 104 }
 105 
 106 static EDestination **
 107 g_value_dup_destinations (const GValue *value)
 108 {
 109 	EDestination **destinations;
 110 	GValueArray *value_array;
 111 	GValue *element;
 112 	gint ii;
 113 
 114 	value_array = g_value_get_boxed (value);
 115 	destinations = g_new0 (EDestination *, value_array->n_values + 1);
 116 
 117 	for (ii = 0; ii < value_array->n_values; ii++) {
 118 		element = g_value_array_get_nth (value_array, ii);
 119 		destinations[ii] = g_value_dup_object (element);
 120 	}
 121 
 122 	return destinations;
 123 }
 124 
 125 static void
 126 g_value_set_string_list (GValue *value,
 127                          GList *list)
 128 {
 129 	GValueArray *value_array;
 130 	GValue element = G_VALUE_INIT;
 131 
 132 	g_value_init (&element, G_TYPE_STRING);
 133 
 134 	value_array = g_value_array_new (g_list_length (list));
 135 
 136 	while (list != NULL) {
 137 		g_value_set_string (&element, list->data);
 138 		g_value_array_append (value_array, &element);
 139 	}
 140 
 141 	g_value_take_boxed (value, value_array);
 142 }
 143 
 144 static GList *
 145 g_value_dup_string_list (const GValue *value)
 146 {
 147 	GValueArray *value_array;
 148 	GList *list = NULL;
 149 	GValue *element;
 150 	gint ii;
 151 
 152 	value_array = g_value_get_boxed (value);
 153 
 154 	for (ii = 0; ii < value_array->n_values; ii++) {
 155 		element = g_value_array_get_nth (value_array, ii);
 156 		list = g_list_prepend (list, g_value_dup_string (element));
 157 	}
 158 
 159 	return g_list_reverse (list);
 160 }
 161 
 162 static void
 163 composer_header_table_notify_header (EComposerHeader *header,
 164                                      const gchar *property_name)
 165 {
 166 	GtkWidget *parent;
 167 
 168 	parent = gtk_widget_get_parent (header->input_widget);
 169 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (parent));
 170 	g_object_notify (G_OBJECT (parent), property_name);
 171 }
 172 
 173 static void
 174 composer_header_table_notify_widget (GtkWidget *widget,
 175                                      const gchar *property_name)
 176 {
 177 	EShell *shell;
 178 	GtkWidget *parent;
 179 
 180 	/* FIXME Pass this in somehow. */
 181 	shell = e_shell_get_default ();
 182 
 183 	if (e_shell_get_small_screen_mode (shell)) {
 184 		parent = gtk_widget_get_parent (widget);
 185 		parent = g_object_get_data (G_OBJECT (parent), "pdata");
 186 	} else
 187 		parent = gtk_widget_get_parent (widget);
 188 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (parent));
 189 	g_object_notify (G_OBJECT (parent), property_name);
 190 }
 191 
 192 static void
 193 composer_header_table_bind_header (const gchar *property_name,
 194                                    const gchar *signal_name,
 195                                    EComposerHeader *header)
 196 {
 197 	/* Propagate the signal as "notify::property_name". */
 198 
 199 	g_signal_connect (
 200 		header, signal_name,
 201 		G_CALLBACK (composer_header_table_notify_header),
 202 		(gpointer) property_name);
 203 }
 204 
 205 static void
 206 composer_header_table_bind_widget (const gchar *property_name,
 207                                    const gchar *signal_name,
 208                                    GtkWidget *widget)
 209 {
 210 	/* Propagate the signal as "notify::property_name". */
 211 
 212 	g_signal_connect (
 213 		widget, signal_name,
 214 		G_CALLBACK (composer_header_table_notify_widget),
 215 		(gpointer) property_name);
 216 }
 217 
 218 static EDestination **
 219 composer_header_table_update_destinations (EDestination **old_destinations,
 220                                            const gchar * const *auto_addresses)
 221 {
 222 	CamelAddress *address;
 223 	CamelInternetAddress *inet_address;
 224 	EDestination **new_destinations;
 225 	EDestination *destination;
 226 	GQueue queue = G_QUEUE_INIT;
 227 	guint length;
 228 	gint ii;
 229 
 230 	/* Include automatic recipients for the selected account. */
 231 
 232 	if (auto_addresses == NULL)
 233 		goto skip_auto;
 234 
 235 	inet_address = camel_internet_address_new ();
 236 	address = CAMEL_ADDRESS (inet_address);
 237 
 238 	/* XXX Calling camel_address_decode() multiple times on the same
 239 	 *     CamelInternetAddress has a cumulative effect, which isn't
 240 	 *     well documented. */
 241 	for (ii = 0; auto_addresses[ii] != NULL; ii++)
 242 		camel_address_decode (address, auto_addresses[ii]);
 243 
 244 	for (ii = 0; ii < camel_address_length (address); ii++) {
 245 		const gchar *name, *email;
 246 
 247 		if (!camel_internet_address_get (
 248 			inet_address, ii, &name, &email))
 249 			continue;
 250 
 251 		destination = e_destination_new ();
 252 		e_destination_set_auto_recipient (destination, TRUE);
 253 
 254 		if (name != NULL)
 255 			e_destination_set_name (destination, name);
 256 
 257 		if (email != NULL)
 258 			e_destination_set_email (destination, email);
 259 
 260 		g_queue_push_tail (&queue, destination);
 261 	}
 262 
 263 	g_object_unref (inet_address);
 264 
 265 skip_auto:
 266 
 267 	/* Include custom recipients for this message. */
 268 
 269 	if (old_destinations == NULL)
 270 		goto skip_custom;
 271 
 272 	for (ii = 0; old_destinations[ii] != NULL; ii++) {
 273 		if (e_destination_is_auto_recipient (old_destinations[ii]))
 274 			continue;
 275 
 276 		destination = e_destination_copy (old_destinations[ii]);
 277 		g_queue_push_tail (&queue, destination);
 278 	}
 279 
 280 skip_custom:
 281 
 282 	length = g_queue_get_length (&queue);
 283 	new_destinations = g_new0 (EDestination *, length + 1);
 284 
 285 	for (ii = 0; ii < length; ii++)
 286 		new_destinations[ii] = g_queue_pop_head (&queue);
 287 
 288 	/* Sanity check. */
 289 	g_warn_if_fail (g_queue_is_empty (&queue));
 290 
 291 	return new_destinations;
 292 }
 293 
 294 static gboolean
 295 from_header_should_be_visible (EComposerHeaderTable *table)
 296 {
 297 	EShell *shell;
 298 	EComposerHeader *header;
 299 	EComposerHeaderType type;
 300 	GtkComboBox *combo_box;
 301 	GtkTreeModel *tree_model;
 302 
 303 	shell = e_composer_header_table_get_shell (table);
 304 
 305 	/* Always display From in standard mode. */
 306 	if (!e_shell_get_express_mode (shell))
 307 		return TRUE;
 308 
 309 	type = E_COMPOSER_HEADER_FROM;
 310 	header = e_composer_header_table_get_header (table, type);
 311 
 312 	combo_box = GTK_COMBO_BOX (header->input_widget);
 313 	tree_model = gtk_combo_box_get_model (combo_box);
 314 
 315 	return (gtk_tree_model_iter_n_children (tree_model, NULL) > 1);
 316 }
 317 
 318 static void
 319 composer_header_table_setup_mail_headers (EComposerHeaderTable *table)
 320 {
 321 	GSettings *settings;
 322 	gint ii;
 323 
 324 	settings = g_settings_new ("org.gnome.evolution.mail");
 325 
 326 	for (ii = 0; ii < E_COMPOSER_NUM_HEADERS; ii++) {
 327 		EComposerHeader *header;
 328 		const gchar *key;
 329 		gboolean sensitive;
 330 		gboolean visible;
 331 
 332 		header = e_composer_header_table_get_header (table, ii);
 333 
 334 		switch (ii) {
 335 			case E_COMPOSER_HEADER_BCC:
 336 				key = "composer-show-bcc";
 337 				break;
 338 
 339 			case E_COMPOSER_HEADER_CC:
 340 				key = "composer-show-cc";
 341 				break;
 342 
 343 			case E_COMPOSER_HEADER_REPLY_TO:
 344 				key = "composer-show-reply-to";
 345 				break;
 346 
 347 			default:
 348 				key = NULL;
 349 				break;
 350 		}
 351 
 352 		if (key != NULL)
 353 			g_settings_unbind (header, "visible");
 354 
 355 		switch (ii) {
 356 			case E_COMPOSER_HEADER_FROM:
 357 				sensitive = TRUE;
 358 				visible = from_header_should_be_visible (table);
 359 				break;
 360 
 361 			case E_COMPOSER_HEADER_BCC:
 362 			case E_COMPOSER_HEADER_CC:
 363 			case E_COMPOSER_HEADER_REPLY_TO:
 364 			case E_COMPOSER_HEADER_SUBJECT:
 365 			case E_COMPOSER_HEADER_TO:
 366 				sensitive = TRUE;
 367 				visible = TRUE;
 368 				break;
 369 
 370 			default:
 371 				sensitive = FALSE;
 372 				visible = FALSE;
 373 				break;
 374 		}
 375 
 376 		e_composer_header_set_sensitive (header, sensitive);
 377 		e_composer_header_set_visible (header, visible);
 378 
 379 		if (key != NULL)
 380 			g_settings_bind (
 381 				settings, key,
 382 				header, "visible",
 383 				G_SETTINGS_BIND_DEFAULT);
 384 	}
 385 
 386 	g_object_unref (settings);
 387 }
 388 
 389 static void
 390 composer_header_table_setup_post_headers (EComposerHeaderTable *table)
 391 {
 392 	GSettings *settings;
 393 	gint ii;
 394 
 395 	settings = g_settings_new ("org.gnome.evolution.mail");
 396 
 397 	for (ii = 0; ii < E_COMPOSER_NUM_HEADERS; ii++) {
 398 		EComposerHeader *header;
 399 		const gchar *key;
 400 
 401 		header = e_composer_header_table_get_header (table, ii);
 402 
 403 		switch (ii) {
 404 			case E_COMPOSER_HEADER_FROM:
 405 				key = "composer-show-post-from";
 406 				break;
 407 
 408 			case E_COMPOSER_HEADER_REPLY_TO:
 409 				key = "composer-show-post-reply-to";
 410 				break;
 411 
 412 			default:
 413 				key = NULL;
 414 				break;
 415 		}
 416 
 417 		if (key != NULL)
 418 			g_settings_unbind (header, "visible");
 419 
 420 		switch (ii) {
 421 			case E_COMPOSER_HEADER_FROM:
 422 			case E_COMPOSER_HEADER_POST_TO:
 423 			case E_COMPOSER_HEADER_REPLY_TO:
 424 			case E_COMPOSER_HEADER_SUBJECT:
 425 				e_composer_header_set_sensitive (header, TRUE);
 426 				e_composer_header_set_visible (header, TRUE);
 427 				break;
 428 
 429 			default:  /* this includes TO, CC and BCC */
 430 				e_composer_header_set_sensitive (header, FALSE);
 431 				e_composer_header_set_visible (header, FALSE);
 432 				break;
 433 		}
 434 
 435 		if (key != NULL)
 436 			g_settings_bind (
 437 				settings, key,
 438 				header, "visible",
 439 				G_SETTINGS_BIND_DEFAULT);
 440 	}
 441 
 442 	g_object_unref (settings);
 443 }
 444 
 445 static gboolean
 446 composer_header_table_show_post_headers (EComposerHeaderTable *table)
 447 {
 448 	ESourceRegistry *registry;
 449 	GList *list, *link;
 450 	const gchar *extension_name;
 451 	const gchar *target_uid;
 452 	gboolean show_post_headers = FALSE;
 453 
 454 	registry = e_composer_header_table_get_registry (table);
 455 	target_uid = e_composer_header_table_get_identity_uid (table);
 456 
 457 	extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
 458 	list = e_source_registry_list_sources (registry, extension_name);
 459 
 460 	/* Look for a mail account referencing this mail identity.
 461 	 * If the mail account's backend name is "nntp", show the
 462 	 * post headers.  Otherwise show the mail headers.
 463 	 *
 464 	 * XXX What if multiple accounts use this identity but only
 465 	 *     one is "nntp"?  Maybe it should be indicated by the
 466 	 *     transport somehow?
 467 	 */
 468 	for (link = list; link != NULL; link = link->next) {
 469 		ESource *source = E_SOURCE (link->data);
 470 		ESourceExtension *extension;
 471 		const gchar *backend_name;
 472 		const gchar *identity_uid;
 473 
 474 		extension = e_source_get_extension (source, extension_name);
 475 
 476 		backend_name = e_source_backend_get_backend_name (
 477 			E_SOURCE_BACKEND (extension));
 478 		identity_uid = e_source_mail_account_get_identity_uid (
 479 			E_SOURCE_MAIL_ACCOUNT (extension));
 480 
 481 		if (g_strcmp0 (identity_uid, target_uid) != 0)
 482 			continue;
 483 
 484 		if (g_strcmp0 (backend_name, "nntp") != 0)
 485 			continue;
 486 
 487 		show_post_headers = TRUE;
 488 		break;
 489 	}
 490 
 491 	g_list_free_full (list, (GDestroyNotify) g_object_unref);
 492 
 493 	return show_post_headers;
 494 }
 495 
 496 static void
 497 composer_header_table_from_changed_cb (EComposerHeaderTable *table)
 498 {
 499 	ESource *source = NULL;
 500 	ESource *mail_account = NULL;
 501 	ESourceRegistry *registry;
 502 	EComposerHeader *header;
 503 	EComposerHeaderType type;
 504 	EComposerPostHeader *post_header;
 505 	EComposerTextHeader *text_header;
 506 	EDestination **old_destinations;
 507 	EDestination **new_destinations;
 508 	const gchar *reply_to = NULL;
 509 	const gchar * const *bcc = NULL;
 510 	const gchar * const *cc = NULL;
 511 	const gchar *uid;
 512 
 513 	/* Keep "Post-To" and "Reply-To" synchronized with "From" */
 514 
 515 	registry = e_composer_header_table_get_registry (table);
 516 	uid = e_composer_header_table_get_identity_uid (table);
 517 
 518 	if (uid != NULL)
 519 		source = e_source_registry_ref_source (registry, uid);
 520 
 521 	/* Make sure this is really a mail identity source. */
 522 	if (source != NULL) {
 523 		const gchar *extension_name;
 524 
 525 		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
 526 		if (!e_source_has_extension (source, extension_name)) {
 527 			g_object_unref (source);
 528 			source = NULL;
 529 		}
 530 	}
 531 
 532 	if (source != NULL) {
 533 		ESourceMailIdentity *mi;
 534 		ESourceMailComposition *mc;
 535 		const gchar *extension_name;
 536 
 537 		extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY;
 538 		mi = e_source_get_extension (source, extension_name);
 539 
 540 		extension_name = E_SOURCE_EXTENSION_MAIL_COMPOSITION;
 541 		mc = e_source_get_extension (source, extension_name);
 542 
 543 		reply_to = e_source_mail_identity_get_reply_to (mi);
 544 		bcc = e_source_mail_composition_get_bcc (mc);
 545 		cc = e_source_mail_composition_get_cc (mc);
 546 
 547 		g_object_unref (source);
 548 	}
 549 
 550 	type = E_COMPOSER_HEADER_POST_TO;
 551 	header = e_composer_header_table_get_header (table, type);
 552 	post_header = E_COMPOSER_POST_HEADER (header);
 553 	e_composer_post_header_set_mail_account (post_header, mail_account);
 554 
 555 	type = E_COMPOSER_HEADER_REPLY_TO;
 556 	header = e_composer_header_table_get_header (table, type);
 557 	text_header = E_COMPOSER_TEXT_HEADER (header);
 558 	e_composer_text_header_set_text (text_header, reply_to);
 559 
 560 	/* Update automatic CC destinations. */
 561 	old_destinations =
 562 		e_composer_header_table_get_destinations_cc (table);
 563 	new_destinations =
 564 		composer_header_table_update_destinations (
 565 		old_destinations, cc);
 566 	e_composer_header_table_set_destinations_cc (table, new_destinations);
 567 	e_destination_freev (old_destinations);
 568 	e_destination_freev (new_destinations);
 569 
 570 	/* Update automatic BCC destinations. */
 571 	old_destinations =
 572 		e_composer_header_table_get_destinations_bcc (table);
 573 	new_destinations =
 574 		composer_header_table_update_destinations (
 575 		old_destinations, bcc);
 576 	e_composer_header_table_set_destinations_bcc (table, new_destinations);
 577 	e_destination_freev (old_destinations);
 578 	e_destination_freev (new_destinations);
 579 
 580 	if (composer_header_table_show_post_headers (table))
 581 		composer_header_table_setup_post_headers (table);
 582 	else
 583 		composer_header_table_setup_mail_headers (table);
 584 }
 585 
 586 static void
 587 composer_header_table_set_registry (EComposerHeaderTable *table,
 588                                     ESourceRegistry *registry)
 589 {
 590 	g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
 591 	g_return_if_fail (table->priv->registry == NULL);
 592 
 593 	table->priv->registry = g_object_ref (registry);
 594 }
 595 
 596 static void
 597 composer_header_table_set_shell (EComposerHeaderTable *table,
 598                                  EShell *shell)
 599 {
 600 	g_return_if_fail (E_IS_SHELL (shell));
 601 	g_return_if_fail (table->priv->shell == NULL);
 602 
 603 	table->priv->shell = g_object_ref (shell);
 604 }
 605 
 606 static void
 607 composer_header_table_set_property (GObject *object,
 608                                     guint property_id,
 609                                     const GValue *value,
 610                                     GParamSpec *pspec)
 611 {
 612 	EDestination **destinations;
 613 	GList *list;
 614 
 615 	switch (property_id) {
 616 		case PROP_DESTINATIONS_BCC:
 617 			destinations = g_value_dup_destinations (value);
 618 			e_composer_header_table_set_destinations_bcc (
 619 				E_COMPOSER_HEADER_TABLE (object),
 620 				destinations);
 621 			e_destination_freev (destinations);
 622 			return;
 623 
 624 		case PROP_DESTINATIONS_CC:
 625 			destinations = g_value_dup_destinations (value);
 626 			e_composer_header_table_set_destinations_cc (
 627 				E_COMPOSER_HEADER_TABLE (object),
 628 				destinations);
 629 			e_destination_freev (destinations);
 630 			return;
 631 
 632 		case PROP_DESTINATIONS_TO:
 633 			destinations = g_value_dup_destinations (value);
 634 			e_composer_header_table_set_destinations_to (
 635 				E_COMPOSER_HEADER_TABLE (object),
 636 				destinations);
 637 			e_destination_freev (destinations);
 638 			return;
 639 
 640 		case PROP_IDENTITY_UID:
 641 			e_composer_header_table_set_identity_uid (
 642 				E_COMPOSER_HEADER_TABLE (object),
 643 				g_value_get_string (value));
 644 			return;
 645 
 646 		case PROP_POST_TO:
 647 			list = g_value_dup_string_list (value);
 648 			e_composer_header_table_set_post_to_list (
 649 				E_COMPOSER_HEADER_TABLE (object), list);
 650 			g_list_foreach (list, (GFunc) g_free, NULL);
 651 			g_list_free (list);
 652 			return;
 653 
 654 		case PROP_REGISTRY:
 655 			composer_header_table_set_registry (
 656 				E_COMPOSER_HEADER_TABLE (object),
 657 				g_value_get_object (value));
 658 			return;
 659 
 660 		case PROP_REPLY_TO:
 661 			e_composer_header_table_set_reply_to (
 662 				E_COMPOSER_HEADER_TABLE (object),
 663 				g_value_get_string (value));
 664 			return;
 665 
 666 		case PROP_SHELL:
 667 			composer_header_table_set_shell (
 668 				E_COMPOSER_HEADER_TABLE (object),
 669 				g_value_get_object (value));
 670 			return;
 671 
 672 		case PROP_SIGNATURE_UID:
 673 			e_composer_header_table_set_signature_uid (
 674 				E_COMPOSER_HEADER_TABLE (object),
 675 				g_value_get_string (value));
 676 			return;
 677 
 678 		case PROP_SUBJECT:
 679 			e_composer_header_table_set_subject (
 680 				E_COMPOSER_HEADER_TABLE (object),
 681 				g_value_get_string (value));
 682 			return;
 683 	}
 684 
 685 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 686 }
 687 
 688 static void
 689 composer_header_table_get_property (GObject *object,
 690                                     guint property_id,
 691                                     GValue *value,
 692                                     GParamSpec *pspec)
 693 {
 694 	EDestination **destinations;
 695 	GList *list;
 696 
 697 	switch (property_id) {
 698 		case PROP_DESTINATIONS_BCC:
 699 			destinations =
 700 				e_composer_header_table_get_destinations_bcc (
 701 				E_COMPOSER_HEADER_TABLE (object));
 702 			g_value_set_destinations (value, destinations);
 703 			e_destination_freev (destinations);
 704 			return;
 705 
 706 		case PROP_DESTINATIONS_CC:
 707 			destinations =
 708 				e_composer_header_table_get_destinations_cc (
 709 				E_COMPOSER_HEADER_TABLE (object));
 710 			g_value_set_destinations (value, destinations);
 711 			e_destination_freev (destinations);
 712 			return;
 713 
 714 		case PROP_DESTINATIONS_TO:
 715 			destinations =
 716 				e_composer_header_table_get_destinations_to (
 717 				E_COMPOSER_HEADER_TABLE (object));
 718 			g_value_set_destinations (value, destinations);
 719 			e_destination_freev (destinations);
 720 			return;
 721 
 722 		case PROP_IDENTITY_UID:
 723 			g_value_set_string (
 724 				value,
 725 				e_composer_header_table_get_identity_uid (
 726 				E_COMPOSER_HEADER_TABLE (object)));
 727 			return;
 728 
 729 		case PROP_POST_TO:
 730 			list = e_composer_header_table_get_post_to (
 731 				E_COMPOSER_HEADER_TABLE (object));
 732 			g_value_set_string_list (value, list);
 733 			g_list_foreach (list, (GFunc) g_free, NULL);
 734 			g_list_free (list);
 735 			return;
 736 
 737 		case PROP_REGISTRY:
 738 			g_value_set_object (
 739 				value,
 740 				e_composer_header_table_get_registry (
 741 				E_COMPOSER_HEADER_TABLE (object)));
 742 			return;
 743 
 744 		case PROP_REPLY_TO:
 745 			g_value_set_string (
 746 				value,
 747 				e_composer_header_table_get_reply_to (
 748 				E_COMPOSER_HEADER_TABLE (object)));
 749 			return;
 750 
 751 		case PROP_SHELL:
 752 			g_value_set_object (
 753 				value,
 754 				e_composer_header_table_get_shell (
 755 				E_COMPOSER_HEADER_TABLE (object)));
 756 			return;
 757 
 758 		case PROP_SIGNATURE_COMBO_BOX:
 759 			g_value_set_object (
 760 				value,
 761 				e_composer_header_table_get_signature_combo_box (
 762 				E_COMPOSER_HEADER_TABLE (object)));
 763 			return;
 764 
 765 		case PROP_SIGNATURE_UID:
 766 			g_value_set_string (
 767 				value,
 768 				e_composer_header_table_get_signature_uid (
 769 				E_COMPOSER_HEADER_TABLE (object)));
 770 			return;
 771 
 772 		case PROP_SUBJECT:
 773 			g_value_set_string (
 774 				value,
 775 				e_composer_header_table_get_subject (
 776 				E_COMPOSER_HEADER_TABLE (object)));
 777 			return;
 778 	}
 779 
 780 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 781 }
 782 
 783 static void
 784 composer_header_table_dispose (GObject *object)
 785 {
 786 	EComposerHeaderTablePrivate *priv;
 787 	gint ii;
 788 
 789 	priv = E_COMPOSER_HEADER_TABLE_GET_PRIVATE (object);
 790 
 791 	for (ii = 0; ii < G_N_ELEMENTS (priv->headers); ii++) {
 792 		if (priv->headers[ii] != NULL) {
 793 			g_object_unref (priv->headers[ii]);
 794 			priv->headers[ii] = NULL;
 795 		}
 796 	}
 797 
 798 	if (priv->signature_combo_box != NULL) {
 799 		g_object_unref (priv->signature_combo_box);
 800 		priv->signature_combo_box = NULL;
 801 	}
 802 
 803 	if (priv->name_selector != NULL) {
 804 		e_name_selector_cancel_loading (priv->name_selector);
 805 		g_object_unref (priv->name_selector);
 806 		priv->name_selector = NULL;
 807 	}
 808 
 809 	if (priv->registry != NULL) {
 810 		g_object_unref (priv->registry);
 811 		priv->registry = NULL;
 812 	}
 813 
 814 	if (priv->shell != NULL) {
 815 		g_object_unref (priv->shell);
 816 		priv->shell = NULL;
 817 	}
 818 
 819 	/* Chain up to parent's dispose() method. */
 820 	G_OBJECT_CLASS (e_composer_header_table_parent_class)->dispose (object);
 821 }
 822 
 823 static void
 824 composer_header_table_constructed (GObject *object)
 825 {
 826 	EComposerHeaderTable *table;
 827 	ENameSelector *name_selector;
 828 	ESourceRegistry *registry;
 829 	EComposerHeader *header;
 830 	GtkWidget *widget;
 831 	EShell *shell;
 832 	guint ii;
 833 	gint row_padding;
 834 	gboolean small_screen_mode;
 835 
 836 	/* Chain up to parent's constructed() method. */
 837 	G_OBJECT_CLASS (e_composer_header_table_parent_class)->
 838 		constructed (object);
 839 
 840 	table = E_COMPOSER_HEADER_TABLE (object);
 841 	shell = e_composer_header_table_get_shell (table);
 842 	registry = e_composer_header_table_get_registry (table);
 843 
 844 	small_screen_mode = e_shell_get_small_screen_mode (shell);
 845 
 846 	name_selector = e_name_selector_new (registry);
 847 	table->priv->name_selector = name_selector;
 848 
 849 	header = e_composer_from_header_new (registry, _("Fr_om:"));
 850 	composer_header_table_bind_header ("identity-uid", "changed", header);
 851 	g_signal_connect_swapped (
 852 		header, "changed", G_CALLBACK (
 853 		composer_header_table_from_changed_cb), table);
 854 	table->priv->headers[E_COMPOSER_HEADER_FROM] = header;
 855 
 856 	header = e_composer_text_header_new_label (registry, _("_Reply-To:"));
 857 	composer_header_table_bind_header ("reply-to", "changed", header);
 858 	table->priv->headers[E_COMPOSER_HEADER_REPLY_TO] = header;
 859 
 860 	header = e_composer_name_header_new (
 861 		registry, _("_To:"), name_selector);
 862 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_TO);
 863 	composer_header_table_bind_header ("destinations-to", "changed", header);
 864 	table->priv->headers[E_COMPOSER_HEADER_TO] = header;
 865 
 866 	header = e_composer_name_header_new (
 867 		registry, _("_Cc:"), name_selector);
 868 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_CC);
 869 	composer_header_table_bind_header ("destinations-cc", "changed", header);
 870 	table->priv->headers[E_COMPOSER_HEADER_CC] = header;
 871 
 872 	header = e_composer_name_header_new (
 873 		registry, _("_Bcc:"), name_selector);
 874 	e_composer_header_set_input_tooltip (header, HEADER_TOOLTIP_BCC);
 875 	composer_header_table_bind_header ("destinations-bcc", "changed", header);
 876 	table->priv->headers[E_COMPOSER_HEADER_BCC] = header;
 877 
 878 	header = e_composer_post_header_new (registry, _("_Post To:"));
 879 	composer_header_table_bind_header ("post-to", "changed", header);
 880 	table->priv->headers[E_COMPOSER_HEADER_POST_TO] = header;
 881 
 882 	header = e_composer_spell_header_new_label (registry, _("S_ubject:"));
 883 	composer_header_table_bind_header ("subject", "changed", header);
 884 	table->priv->headers[E_COMPOSER_HEADER_SUBJECT] = header;
 885 
 886 	widget = e_mail_signature_combo_box_new (registry);
 887 	composer_header_table_bind_widget ("signature-uid", "changed", widget);
 888 	table->priv->signature_combo_box = g_object_ref_sink (widget);
 889 
 890 	widget = gtk_label_new_with_mnemonic (_("Si_gnature:"));
 891 	gtk_label_set_mnemonic_widget (
 892 		GTK_LABEL (widget), table->priv->signature_combo_box);
 893 	table->priv->signature_label = g_object_ref_sink (widget);
 894 
 895 	/* Use "ypadding" instead of "row-spacing" because some rows may
 896 	 * be invisible and we don't want spacing around them. */
 897 
 898 	/* For small screens, pack the table's rows closely together. */
 899 	row_padding = small_screen_mode ? 0 : 3;
 900 
 901 	for (ii = 0; ii < G_N_ELEMENTS (table->priv->headers); ii++) {
 902 		gtk_table_attach (
 903 			GTK_TABLE (object),
 904 			table->priv->headers[ii]->title_widget, 0, 1,
 905 			ii, ii + 1, GTK_FILL, GTK_FILL, 0, row_padding);
 906 		gtk_table_attach (
 907 			GTK_TABLE (object),
 908 			table->priv->headers[ii]->input_widget, 1, 4,
 909 			ii, ii + 1, GTK_FILL | GTK_EXPAND, 0, 0, row_padding);
 910 	}
 911 
 912 	ii = E_COMPOSER_HEADER_FROM;
 913 
 914 	/* Leave room in the "From" row for signature stuff. */
 915 	gtk_container_child_set (
 916 		GTK_CONTAINER (object),
 917 		table->priv->headers[ii]->input_widget,
 918 		"right-attach", 2, NULL);
 919 
 920 	g_object_bind_property (
 921 		table->priv->headers[ii]->input_widget, "visible",
 922 		table->priv->signature_label, "visible",
 923 		G_BINDING_SYNC_CREATE);
 924 
 925 	g_object_bind_property (
 926 		table->priv->headers[ii]->input_widget, "visible",
 927 		table->priv->signature_combo_box, "visible",
 928 		G_BINDING_SYNC_CREATE);
 929 
 930 	/* Now add the signature stuff. */
 931 	if (!small_screen_mode) {
 932 		gtk_table_attach (
 933 			GTK_TABLE (object),
 934 			table->priv->signature_label,
 935 			2, 3, ii, ii + 1, 0, 0, 0, row_padding);
 936 		gtk_table_attach (
 937 			GTK_TABLE (object),
 938 			table->priv->signature_combo_box,
 939 			3, 4, ii, ii + 1, 0, 0, 0, row_padding);
 940 	} else {
 941 		GtkWidget *box = gtk_hbox_new (FALSE, 0);
 942 
 943 		gtk_box_pack_start (
 944 			GTK_BOX (box),
 945 			table->priv->signature_label,
 946 			FALSE, FALSE, 4);
 947 		gtk_box_pack_end (
 948 			GTK_BOX (box),
 949 			table->priv->signature_combo_box,
 950 			TRUE, TRUE, 0);
 951 		g_object_set_data (G_OBJECT (box), "pdata", object);
 952 		gtk_table_attach (
 953 			GTK_TABLE (object), box,
 954 			3, 4, ii, ii + 1, GTK_FILL, 0, 0, row_padding);
 955 		gtk_widget_hide (box);
 956 	}
 957 
 958 	/* Initialize the headers. */
 959 	composer_header_table_from_changed_cb (table);
 960 }
 961 
 962 static void
 963 e_composer_header_table_class_init (EComposerHeaderTableClass *class)
 964 {
 965 	GObjectClass *object_class;
 966 	GParamSpec *element_spec;
 967 
 968 	g_type_class_add_private (class, sizeof (EComposerHeaderTablePrivate));
 969 
 970 	object_class = G_OBJECT_CLASS (class);
 971 	object_class->set_property = composer_header_table_set_property;
 972 	object_class->get_property = composer_header_table_get_property;
 973 	object_class->dispose = composer_header_table_dispose;
 974 	object_class->constructed = composer_header_table_constructed;
 975 
 976 	/* floating reference */
 977 	element_spec = g_param_spec_object (
 978 		"value-array-element",
 979 		NULL,
 980 		NULL,
 981 		E_TYPE_DESTINATION,
 982 		G_PARAM_READWRITE |
 983 		G_PARAM_STATIC_STRINGS);
 984 
 985 	g_object_class_install_property (
 986 		object_class,
 987 		PROP_DESTINATIONS_BCC,
 988 		g_param_spec_value_array (
 989 			"destinations-bcc",
 990 			NULL,
 991 			NULL,
 992 			element_spec,
 993 			G_PARAM_READWRITE |
 994 			G_PARAM_STATIC_STRINGS));
 995 
 996 	g_object_class_install_property (
 997 		object_class,
 998 		PROP_DESTINATIONS_CC,
 999 		g_param_spec_value_array (
1000 			"destinations-cc",
1001 			NULL,
1002 			NULL,
1003 			element_spec,
1004 			G_PARAM_READWRITE |
1005 			G_PARAM_STATIC_STRINGS));
1006 
1007 	g_object_class_install_property (
1008 		object_class,
1009 		PROP_DESTINATIONS_TO,
1010 		g_param_spec_value_array (
1011 			"destinations-to",
1012 			NULL,
1013 			NULL,
1014 			element_spec,
1015 			G_PARAM_READWRITE |
1016 			G_PARAM_STATIC_STRINGS));
1017 
1018 	g_object_class_install_property (
1019 		object_class,
1020 		PROP_IDENTITY_UID,
1021 		g_param_spec_string (
1022 			"identity-uid",
1023 			NULL,
1024 			NULL,
1025 			NULL,
1026 			G_PARAM_READWRITE |
1027 			G_PARAM_STATIC_STRINGS));
1028 
1029 	/* floating reference */
1030 	element_spec = g_param_spec_string (
1031 		"value-array-element",
1032 		NULL,
1033 		NULL,
1034 		NULL,
1035 		G_PARAM_READWRITE |
1036 		G_PARAM_STATIC_STRINGS);
1037 
1038 	g_object_class_install_property (
1039 		object_class,
1040 		PROP_POST_TO,
1041 		g_param_spec_value_array (
1042 			"post-to",
1043 			NULL,
1044 			NULL,
1045 			element_spec,
1046 			G_PARAM_READWRITE |
1047 			G_PARAM_STATIC_STRINGS));
1048 
1049 	g_object_class_install_property (
1050 		object_class,
1051 		PROP_REGISTRY,
1052 		g_param_spec_object (
1053 			"registry",
1054 			NULL,
1055 			NULL,
1056 			E_TYPE_SOURCE_REGISTRY,
1057 			G_PARAM_READWRITE |
1058 			G_PARAM_CONSTRUCT_ONLY |
1059 			G_PARAM_STATIC_STRINGS));
1060 
1061 	g_object_class_install_property (
1062 		object_class,
1063 		PROP_REPLY_TO,
1064 		g_param_spec_string (
1065 			"reply-to",
1066 			NULL,
1067 			NULL,
1068 			NULL,
1069 			G_PARAM_READWRITE |
1070 			G_PARAM_STATIC_STRINGS));
1071 
1072 	g_object_class_install_property (
1073 		object_class,
1074 		PROP_SHELL,
1075 		g_param_spec_object (
1076 			"shell",
1077 			NULL,
1078 			NULL,
1079 			E_TYPE_SHELL,
1080 			G_PARAM_READWRITE |
1081 			G_PARAM_CONSTRUCT_ONLY |
1082 			G_PARAM_STATIC_STRINGS));
1083 
1084 	g_object_class_install_property (
1085 		object_class,
1086 		PROP_SIGNATURE_COMBO_BOX,
1087 		g_param_spec_string (
1088 			"signature-combo-box",
1089 			NULL,
1090 			NULL,
1091 			NULL,
1092 			G_PARAM_READABLE |
1093 			G_PARAM_STATIC_STRINGS));
1094 
1095 	g_object_class_install_property (
1096 		object_class,
1097 		PROP_SIGNATURE_UID,
1098 		g_param_spec_string (
1099 			"signature-uid",
1100 			NULL,
1101 			NULL,
1102 			NULL,
1103 			G_PARAM_READWRITE |
1104 			G_PARAM_STATIC_STRINGS));
1105 
1106 	g_object_class_install_property (
1107 		object_class,
1108 		PROP_SUBJECT,
1109 		g_param_spec_string (
1110 			"subject",
1111 			NULL,
1112 			NULL,
1113 			NULL,
1114 			G_PARAM_READWRITE |
1115 			G_PARAM_STATIC_STRINGS));
1116 }
1117 
1118 static void
1119 composer_header_table_realize_cb (EComposerHeaderTable *table)
1120 {
1121 	g_return_if_fail (table != NULL);
1122 	g_return_if_fail (table->priv != NULL);
1123 
1124 	g_signal_handlers_disconnect_by_func (
1125 		table, composer_header_table_realize_cb, NULL);
1126 
1127 	e_name_selector_load_books (table->priv->name_selector);
1128 }
1129 
1130 static void
1131 e_composer_header_table_init (EComposerHeaderTable *table)
1132 {
1133 	gint rows;
1134 
1135 	table->priv = E_COMPOSER_HEADER_TABLE_GET_PRIVATE (table);
1136 
1137 	rows = G_N_ELEMENTS (table->priv->headers);
1138 	gtk_table_resize (GTK_TABLE (table), rows, 4);
1139 	gtk_table_set_row_spacings (GTK_TABLE (table), 0);
1140 	gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1141 
1142 	/* postpone name_selector loading, do that only when really needed */
1143 	g_signal_connect (
1144 		table, "realize",
1145 		G_CALLBACK (composer_header_table_realize_cb), NULL);
1146 }
1147 
1148 GtkWidget *
1149 e_composer_header_table_new (EShell *shell,
1150                              ESourceRegistry *registry)
1151 {
1152 	g_return_val_if_fail (E_IS_SHELL (shell), NULL);
1153 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
1154 
1155 	return g_object_new (
1156 		E_TYPE_COMPOSER_HEADER_TABLE,
1157 		"shell", shell, "registry", registry, NULL);
1158 }
1159 
1160 EShell *
1161 e_composer_header_table_get_shell (EComposerHeaderTable *table)
1162 {
1163 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1164 
1165 	return table->priv->shell;
1166 }
1167 
1168 ESourceRegistry *
1169 e_composer_header_table_get_registry (EComposerHeaderTable *table)
1170 {
1171 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1172 
1173 	return table->priv->registry;
1174 }
1175 
1176 EComposerHeader *
1177 e_composer_header_table_get_header (EComposerHeaderTable *table,
1178                                     EComposerHeaderType type)
1179 {
1180 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1181 	g_return_val_if_fail (type < E_COMPOSER_NUM_HEADERS, NULL);
1182 
1183 	return table->priv->headers[type];
1184 }
1185 
1186 EMailSignatureComboBox *
1187 e_composer_header_table_get_signature_combo_box (EComposerHeaderTable *table)
1188 {
1189 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1190 
1191 	return E_MAIL_SIGNATURE_COMBO_BOX (table->priv->signature_combo_box);
1192 }
1193 
1194 EDestination **
1195 e_composer_header_table_get_destinations (EComposerHeaderTable *table)
1196 {
1197 	EDestination **destinations;
1198 	EDestination **to, **cc, **bcc;
1199 	gint total, n_to, n_cc, n_bcc;
1200 
1201 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1202 
1203 	to = e_composer_header_table_get_destinations_to (table);
1204 	for (n_to = 0; to != NULL && to[n_to] != NULL; n_to++);
1205 
1206 	cc = e_composer_header_table_get_destinations_cc (table);
1207 	for (n_cc = 0; cc != NULL && cc[n_cc] != NULL; n_cc++);
1208 
1209 	bcc = e_composer_header_table_get_destinations_bcc (table);
1210 	for (n_bcc = 0; bcc != NULL && bcc[n_bcc] != NULL; n_bcc++);
1211 
1212 	total = n_to + n_cc + n_bcc;
1213 	destinations = g_new0 (EDestination *, total + 1);
1214 
1215 	while (n_bcc > 0 && total > 0)
1216 		destinations[--total] = g_object_ref (bcc[--n_bcc]);
1217 
1218 	while (n_cc > 0 && total > 0)
1219 		destinations[--total] = g_object_ref (cc[--n_cc]);
1220 
1221 	while (n_to > 0 && total > 0)
1222 		destinations[--total] = g_object_ref (to[--n_to]);
1223 
1224 	/* Counters should all be zero now. */
1225 	g_assert (total == 0 && n_to == 0 && n_cc == 0 && n_bcc == 0);
1226 
1227 	e_destination_freev (to);
1228 	e_destination_freev (cc);
1229 	e_destination_freev (bcc);
1230 
1231 	return destinations;
1232 }
1233 
1234 EDestination **
1235 e_composer_header_table_get_destinations_bcc (EComposerHeaderTable *table)
1236 {
1237 	EComposerHeader *header;
1238 	EComposerHeaderType type;
1239 	EComposerNameHeader *name_header;
1240 
1241 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1242 
1243 	type = E_COMPOSER_HEADER_BCC;
1244 	header = e_composer_header_table_get_header (table, type);
1245 	name_header = E_COMPOSER_NAME_HEADER (header);
1246 
1247 	return e_composer_name_header_get_destinations (name_header);
1248 }
1249 
1250 void
1251 e_composer_header_table_add_destinations_bcc (EComposerHeaderTable *table,
1252                                               EDestination **destinations)
1253 {
1254 	EComposerHeader *header;
1255 	EComposerHeaderType type;
1256 	EComposerNameHeader *name_header;
1257 
1258 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1259 
1260 	type = E_COMPOSER_HEADER_BCC;
1261 	header = e_composer_header_table_get_header (table, type);
1262 	name_header = E_COMPOSER_NAME_HEADER (header);
1263 
1264 	e_composer_name_header_add_destinations (name_header, destinations);
1265 
1266 	if (destinations != NULL && *destinations != NULL)
1267 		e_composer_header_set_visible (header, TRUE);
1268 }
1269 
1270 void
1271 e_composer_header_table_set_destinations_bcc (EComposerHeaderTable *table,
1272                                               EDestination **destinations)
1273 {
1274 	EComposerHeader *header;
1275 	EComposerHeaderType type;
1276 	EComposerNameHeader *name_header;
1277 
1278 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1279 
1280 	type = E_COMPOSER_HEADER_BCC;
1281 	header = e_composer_header_table_get_header (table, type);
1282 	name_header = E_COMPOSER_NAME_HEADER (header);
1283 
1284 	e_composer_name_header_set_destinations (name_header, destinations);
1285 
1286 	if (destinations != NULL && *destinations != NULL)
1287 		e_composer_header_set_visible (header, TRUE);
1288 }
1289 
1290 EDestination **
1291 e_composer_header_table_get_destinations_cc (EComposerHeaderTable *table)
1292 {
1293 	EComposerHeader *header;
1294 	EComposerHeaderType type;
1295 	EComposerNameHeader *name_header;
1296 
1297 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1298 
1299 	type = E_COMPOSER_HEADER_CC;
1300 	header = e_composer_header_table_get_header (table, type);
1301 	name_header = E_COMPOSER_NAME_HEADER (header);
1302 
1303 	return e_composer_name_header_get_destinations (name_header);
1304 }
1305 
1306 void
1307 e_composer_header_table_add_destinations_cc (EComposerHeaderTable *table,
1308                                              EDestination **destinations)
1309 {
1310 	EComposerHeader *header;
1311 	EComposerHeaderType type;
1312 	EComposerNameHeader *name_header;
1313 
1314 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1315 
1316 	type = E_COMPOSER_HEADER_CC;
1317 	header = e_composer_header_table_get_header (table, type);
1318 	name_header = E_COMPOSER_NAME_HEADER (header);
1319 
1320 	e_composer_name_header_add_destinations (name_header, destinations);
1321 
1322 	if (destinations != NULL && *destinations != NULL)
1323 		e_composer_header_set_visible (header, TRUE);
1324 }
1325 
1326 void
1327 e_composer_header_table_set_destinations_cc (EComposerHeaderTable *table,
1328                                              EDestination **destinations)
1329 {
1330 	EComposerHeader *header;
1331 	EComposerHeaderType type;
1332 	EComposerNameHeader *name_header;
1333 
1334 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1335 
1336 	type = E_COMPOSER_HEADER_CC;
1337 	header = e_composer_header_table_get_header (table, type);
1338 	name_header = E_COMPOSER_NAME_HEADER (header);
1339 
1340 	e_composer_name_header_set_destinations (name_header, destinations);
1341 
1342 	if (destinations != NULL && *destinations != NULL)
1343 		e_composer_header_set_visible (header, TRUE);
1344 }
1345 
1346 EDestination **
1347 e_composer_header_table_get_destinations_to (EComposerHeaderTable *table)
1348 {
1349 	EComposerHeader *header;
1350 	EComposerHeaderType type;
1351 	EComposerNameHeader *name_header;
1352 
1353 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1354 
1355 	type = E_COMPOSER_HEADER_TO;
1356 	header = e_composer_header_table_get_header (table, type);
1357 	name_header = E_COMPOSER_NAME_HEADER (header);
1358 
1359 	return e_composer_name_header_get_destinations (name_header);
1360 }
1361 
1362 void
1363 e_composer_header_table_add_destinations_to (EComposerHeaderTable *table,
1364                                              EDestination **destinations)
1365 {
1366 	EComposerHeader *header;
1367 	EComposerHeaderType type;
1368 	EComposerNameHeader *name_header;
1369 
1370 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1371 
1372 	type = E_COMPOSER_HEADER_TO;
1373 	header = e_composer_header_table_get_header (table, type);
1374 	name_header = E_COMPOSER_NAME_HEADER (header);
1375 
1376 	e_composer_name_header_add_destinations (name_header, destinations);
1377 }
1378 
1379 void
1380 e_composer_header_table_set_destinations_to (EComposerHeaderTable *table,
1381                                              EDestination **destinations)
1382 {
1383 	EComposerHeader *header;
1384 	EComposerHeaderType type;
1385 	EComposerNameHeader *name_header;
1386 
1387 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1388 
1389 	type = E_COMPOSER_HEADER_TO;
1390 	header = e_composer_header_table_get_header (table, type);
1391 	name_header = E_COMPOSER_NAME_HEADER (header);
1392 
1393 	e_composer_name_header_set_destinations (name_header, destinations);
1394 }
1395 
1396 const gchar *
1397 e_composer_header_table_get_identity_uid (EComposerHeaderTable *table)
1398 {
1399 	EComposerHeader *header;
1400 	EComposerHeaderType type;
1401 	EComposerFromHeader *from_header;
1402 
1403 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1404 
1405 	type = E_COMPOSER_HEADER_FROM;
1406 	header = e_composer_header_table_get_header (table, type);
1407 	from_header = E_COMPOSER_FROM_HEADER (header);
1408 
1409 	return e_composer_from_header_get_active_id (from_header);
1410 }
1411 
1412 void
1413 e_composer_header_table_set_identity_uid (EComposerHeaderTable *table,
1414                                           const gchar *identity_uid)
1415 {
1416 	EComposerHeader *header;
1417 	EComposerHeaderType type;
1418 	EComposerFromHeader *from_header;
1419 
1420 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1421 
1422 	type = E_COMPOSER_HEADER_FROM;
1423 	header = e_composer_header_table_get_header (table, type);
1424 	from_header = E_COMPOSER_FROM_HEADER (header);
1425 
1426 	e_composer_from_header_set_active_id (from_header, identity_uid);
1427 }
1428 
1429 GList *
1430 e_composer_header_table_get_post_to (EComposerHeaderTable *table)
1431 {
1432 	EComposerHeader *header;
1433 	EComposerHeaderType type;
1434 	EComposerPostHeader *post_header;
1435 
1436 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1437 
1438 	type = E_COMPOSER_HEADER_POST_TO;
1439 	header = e_composer_header_table_get_header (table, type);
1440 	post_header = E_COMPOSER_POST_HEADER (header);
1441 
1442 	return e_composer_post_header_get_folders (post_header);
1443 }
1444 
1445 void
1446 e_composer_header_table_set_post_to_base (EComposerHeaderTable *table,
1447                                           const gchar *base_url,
1448                                           const gchar *folders)
1449 {
1450 	EComposerHeader *header;
1451 	EComposerHeaderType type;
1452 	EComposerPostHeader *post_header;
1453 
1454 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1455 
1456 	type = E_COMPOSER_HEADER_POST_TO;
1457 	header = e_composer_header_table_get_header (table, type);
1458 	post_header = E_COMPOSER_POST_HEADER (header);
1459 
1460 	e_composer_post_header_set_folders_base (post_header, base_url, folders);
1461 }
1462 
1463 void
1464 e_composer_header_table_set_post_to_list (EComposerHeaderTable *table,
1465                                           GList *folders)
1466 {
1467 	EComposerHeader *header;
1468 	EComposerHeaderType type;
1469 	EComposerPostHeader *post_header;
1470 
1471 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1472 
1473 	type = E_COMPOSER_HEADER_POST_TO;
1474 	header = e_composer_header_table_get_header (table, type);
1475 	post_header = E_COMPOSER_POST_HEADER (header);
1476 
1477 	e_composer_post_header_set_folders (post_header, folders);
1478 }
1479 
1480 const gchar *
1481 e_composer_header_table_get_reply_to (EComposerHeaderTable *table)
1482 {
1483 	EComposerHeader *header;
1484 	EComposerHeaderType type;
1485 	EComposerTextHeader *text_header;
1486 
1487 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1488 
1489 	type = E_COMPOSER_HEADER_REPLY_TO;
1490 	header = e_composer_header_table_get_header (table, type);
1491 	text_header = E_COMPOSER_TEXT_HEADER (header);
1492 
1493 	return e_composer_text_header_get_text (text_header);
1494 }
1495 
1496 void
1497 e_composer_header_table_set_reply_to (EComposerHeaderTable *table,
1498                                       const gchar *reply_to)
1499 {
1500 	EComposerHeader *header;
1501 	EComposerHeaderType type;
1502 	EComposerTextHeader *text_header;
1503 
1504 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1505 
1506 	type = E_COMPOSER_HEADER_REPLY_TO;
1507 	header = e_composer_header_table_get_header (table, type);
1508 	text_header = E_COMPOSER_TEXT_HEADER (header);
1509 
1510 	e_composer_text_header_set_text (text_header, reply_to);
1511 
1512 	if (reply_to != NULL && *reply_to != '\0')
1513 		e_composer_header_set_visible (header, TRUE);
1514 }
1515 
1516 const gchar *
1517 e_composer_header_table_get_signature_uid (EComposerHeaderTable *table)
1518 {
1519 	EMailSignatureComboBox *combo_box;
1520 
1521 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1522 
1523 	combo_box = e_composer_header_table_get_signature_combo_box (table);
1524 
1525 	return gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box));
1526 }
1527 
1528 void
1529 e_composer_header_table_set_signature_uid (EComposerHeaderTable *table,
1530                                            const gchar *signature_uid)
1531 {
1532 	EMailSignatureComboBox *combo_box;
1533 
1534 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1535 
1536 	combo_box = e_composer_header_table_get_signature_combo_box (table);
1537 
1538 	gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), signature_uid);
1539 }
1540 
1541 const gchar *
1542 e_composer_header_table_get_subject (EComposerHeaderTable *table)
1543 {
1544 	EComposerHeader *header;
1545 	EComposerHeaderType type;
1546 	EComposerTextHeader *text_header;
1547 
1548 	g_return_val_if_fail (E_IS_COMPOSER_HEADER_TABLE (table), NULL);
1549 
1550 	type = E_COMPOSER_HEADER_SUBJECT;
1551 	header = e_composer_header_table_get_header (table, type);
1552 	text_header = E_COMPOSER_TEXT_HEADER (header);
1553 
1554 	return e_composer_text_header_get_text (text_header);
1555 }
1556 
1557 void
1558 e_composer_header_table_set_subject (EComposerHeaderTable *table,
1559                                      const gchar *subject)
1560 {
1561 	EComposerHeader *header;
1562 	EComposerHeaderType type;
1563 	EComposerTextHeader *text_header;
1564 
1565 	g_return_if_fail (E_IS_COMPOSER_HEADER_TABLE (table));
1566 
1567 	type = E_COMPOSER_HEADER_SUBJECT;
1568 	header = e_composer_header_table_get_header (table, type);
1569 	text_header = E_COMPOSER_TEXT_HEADER (header);
1570 
1571 	e_composer_text_header_set_text (text_header, subject);
1572 }
1573 
1574 void
1575 e_composer_header_table_set_header_visible (EComposerHeaderTable *table,
1576                                             EComposerHeaderType type,
1577                                             gboolean visible)
1578 {
1579 	EComposerHeader *header;
1580 
1581 	header = e_composer_header_table_get_header (table, type);
1582 	e_composer_header_set_visible (header, visible);
1583 
1584 	/* Signature widgets track the "From" header. */
1585 	if (type == E_COMPOSER_HEADER_FROM) {
1586 		if (visible) {
1587 			gtk_widget_show (table->priv->signature_label);
1588 			gtk_widget_show (table->priv->signature_combo_box);
1589 		} else {
1590 			gtk_widget_hide (table->priv->signature_label);
1591 			gtk_widget_hide (table->priv->signature_combo_box);
1592 		}
1593 	}
1594 }