[evolution] Bug 580925 – Better search bar for word searches



commit 5d12f06367a0939387381f66cea77766a873aea6
Author: Matthew Barnes <mbarnes redhat com>
Date:   Wed May 20 18:09:34 2009 -0400

    Bug 580925 â?? Better search bar for word searches
    
    Make the word search bar more like Firefox and get rid of the "Current
    Message" search scope in the folder search bar.  Shift+Ctrl+F now
    activates the word search bar.
---
 data/icons/Makefile.am                      |   22 +-
 data/icons/hicolor_status_16x16_wrapped.png |  Bin 0 -> 680 bytes
 mail/Makefile.am                            |    2 +
 mail/e-mail-search-bar.c                    |  774 +++++++++++++++++++++++++++
 mail/e-mail-search-bar.h                    |   85 +++
 mail/e-searching-tokenizer.c                |    4 +-
 mail/e-searching-tokenizer.h                |    2 +-
 mail/em-folder-browser.c                    |   75 ++--
 mail/em-folder-view.c                       |   24 +-
 mail/em-folder-view.h                       |    3 +
 mail/em-format-html-display.c               |  338 ------------
 mail/em-format-html-display.h               |    2 -
 mail/em-format.c                            |   38 ++-
 mail/em-format.h                            |   10 +-
 mail/em-message-browser.c                   |   38 +-
 mail/em-utils.c                             |    2 +-
 widgets/misc/e-filter-bar.c                 |    6 -
 widgets/misc/e-filter-bar.h                 |    2 -
 18 files changed, 1013 insertions(+), 414 deletions(-)

diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am
index 23f4d9d..54b5f4b 100644
--- a/data/icons/Makefile.am
+++ b/data/icons/Makefile.am
@@ -34,19 +34,19 @@ private_icons = \
 	hicolor_actions_16x16_folder-move.png \
 	hicolor_actions_16x16_mail-copy.png \
 	hicolor_actions_16x16_mail-move.png \
- 	hicolor_actions_16x16_go-today.png \
+	hicolor_actions_16x16_go-today.png \
 	hicolor_actions_16x16_view-calendar-day.png \
 	hicolor_actions_16x16_view-calendar-list.png \
 	hicolor_actions_16x16_view-calendar-month.png \
 	hicolor_actions_16x16_view-calendar-week.png \
 	hicolor_actions_16x16_view-calendar-workweek.png \
- 	hicolor_actions_22x22_go-today.png \
+	hicolor_actions_22x22_go-today.png \
 	hicolor_actions_22x22_view-calendar-day.png \
 	hicolor_actions_22x22_view-calendar-list.png \
 	hicolor_actions_22x22_view-calendar-month.png \
 	hicolor_actions_22x22_view-calendar-week.png \
 	hicolor_actions_22x22_view-calendar-workweek.png \
- 	hicolor_actions_24x24_go-today.png \
+	hicolor_actions_24x24_go-today.png \
 	hicolor_actions_24x24_query-free-busy.png \
 	hicolor_actions_24x24_view-calendar-day.png \
 	hicolor_actions_24x24_view-calendar-list.png \
@@ -79,18 +79,28 @@ private_icons = \
 	hicolor_places_24x24_mail-inbox.png \
 	hicolor_places_24x24_mail-outbox.png \
 	hicolor_places_24x24_mail-sent.png \
+	hicolor_status_16x16_wrapped.png \
 	hicolor_status_32x32_offline.png \
 	hicolor_status_32x32_online.png \
 	$(NULL)
 
+# hicolor_status_16x16_wrapped.png was copied from Firefox
+# (toolkit/themes/gnomestripe/global/icons/wrap.png), which
+# contained the following notice:
+#
+#     All files in this directory are assumed to be licensed under the
+#     tri-license (MPL/GPL/LGPL) used throughout this codebase.
+#
+# There is no corresponding SVG file. */
+
 noinst_DATA = \
- 	hicolor_actions_16x16_go-today.svg \
+	hicolor_actions_16x16_go-today.svg \
 	hicolor_actions_16x16_view-calendar-day.svg \
 	hicolor_actions_16x16_view-calendar-list.svg \
 	hicolor_actions_16x16_view-calendar-month.svg \
 	hicolor_actions_16x16_view-calendar-week.svg \
 	hicolor_actions_16x16_view-calendar-workweek.svg \
- 	hicolor_actions_22x22_go-today.svg \
+	hicolor_actions_22x22_go-today.svg \
 	hicolor_actions_22x22_view-calendar-day.svg \
 	hicolor_actions_22x22_view-calendar-list.svg \
 	hicolor_actions_22x22_view-calendar-month.svg \
@@ -109,7 +119,7 @@ noinst_DATA = \
 	hicolor_places_22x22_mail-sent.svg \
 	hicolor_status_32x32_offline.svg \
 	hicolor_status_32x32_online.svg \
- 	$(NULL)
+	$(NULL)
 
 EXTRA_DIST = \
 	$(public_icons)		\
diff --git a/data/icons/hicolor_status_16x16_wrapped.png b/data/icons/hicolor_status_16x16_wrapped.png
new file mode 100644
index 0000000..32492d5
Binary files /dev/null and b/data/icons/hicolor_status_16x16_wrapped.png differ
diff --git a/mail/Makefile.am b/mail/Makefile.am
index 96ed893..793d5c3 100644
--- a/mail/Makefile.am
+++ b/mail/Makefile.am
@@ -55,6 +55,7 @@ idl_DATA = $(MAIL_IDL)
 mailinclude_HEADERS =				\
 	$(MAIL_IDL_GENERATED_H)			\
 	e-mail-attachment-bar.h			\
+	e-mail-search-bar.h			\
 	em-composer-utils.h			\
 	em-config.h				\
 	em-event.h				\
@@ -97,6 +98,7 @@ libevolution_mail_la_SOURCES =			\
 	e-attachment-handler-mail.c		\
 	e-attachment-handler-mail.h		\
 	e-mail-attachment-bar.c			\
+	e-mail-search-bar.c			\
 	e-searching-tokenizer.c			\
 	e-searching-tokenizer.h			\
 	em-account-editor.c			\
diff --git a/mail/e-mail-search-bar.c b/mail/e-mail-search-bar.c
new file mode 100644
index 0000000..4d55585
--- /dev/null
+++ b/mail/e-mail-search-bar.c
@@ -0,0 +1,774 @@
+/*
+ * e-mail-search-bar.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-mail-search-bar.h"
+
+#include <glib/gi18n.h>
+#include <gdk/gdkkeysyms.h>
+#include <gtkhtml/gtkhtml-search.h>
+
+#include "e-util/e-binding.h"
+
+#define E_MAIL_SEARCH_BAR_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarPrivate))
+
+struct _EMailSearchBarPrivate {
+	GtkHTML *html;
+	GtkWidget *entry;
+	GtkWidget *case_sensitive_button;
+	GtkWidget *wrapped_next_box;
+	GtkWidget *wrapped_prev_box;
+	GtkWidget *matches_label;
+
+	ESearchingTokenizer *tokenizer;
+	gchar *active_search;
+
+	guint rerun_search : 1;
+};
+
+enum {
+	PROP_0,
+	PROP_CASE_SENSITIVE,
+	PROP_HTML,
+	PROP_TEXT
+};
+
+enum {
+	CHANGED,
+	CLEAR,
+	LAST_SIGNAL
+};
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL];
+
+static void
+mail_search_bar_update_matches (EMailSearchBar *search_bar)
+{
+	ESearchingTokenizer *tokenizer;
+	GtkWidget *matches_label;
+	gint matches;
+	gchar *text;
+
+	tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+	matches_label = search_bar->priv->matches_label;
+
+	matches = e_searching_tokenizer_match_count (tokenizer);
+	text = g_strdup_printf (_("Matches: %d"), matches);
+
+	gtk_label_set_text (GTK_LABEL (matches_label), text);
+	gtk_widget_show (matches_label);
+
+	g_free (text);
+}
+
+static void
+mail_search_bar_update_tokenizer (EMailSearchBar *search_bar)
+{
+	ESearchingTokenizer *tokenizer;
+	gboolean case_sensitive;
+	gchar *active_search;
+
+	tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+	case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar);
+
+	if (GTK_WIDGET_VISIBLE (search_bar))
+		active_search = search_bar->priv->active_search;
+	else
+		active_search = NULL;
+
+	e_searching_tokenizer_set_primary_case_sensitivity (
+		tokenizer, case_sensitive);
+	e_searching_tokenizer_set_primary_search_string (
+		tokenizer, active_search);
+
+	e_mail_search_bar_changed (search_bar);
+}
+
+static void
+mail_search_bar_find (EMailSearchBar *search_bar,
+                      gboolean search_forward)
+{
+	GtkHTML *html;
+	GtkWidget *widget;
+	gboolean case_sensitive;
+	gboolean new_search;
+	gboolean wrapped = FALSE;
+	gchar *text;
+
+	html = e_mail_search_bar_get_html (search_bar);
+	case_sensitive = e_mail_search_bar_get_case_sensitive (search_bar);
+	text = e_mail_search_bar_get_text (search_bar);
+
+	if (text == NULL || *text == '\0')
+		gtk_widget_hide (search_bar->priv->matches_label);
+
+	new_search =
+		(search_bar->priv->active_search == NULL) ||
+		(g_strcmp0 (text, search_bar->priv->active_search) != 0);
+
+	/* XXX On a new search, the HTMLEngine's search state gets
+	 *     destroyed when we redraw the message with highlighted
+	 *     matches (EMHTMLStream's write() method triggers this,
+	 *     but it's really GtkHtml's fault).  That's why the first
+	 *     match isn't selected automatically.  It also causes
+	 *     gtk_html_engine_search_next() to return FALSE, which we
+	 *     assume to mean the search wrapped.
+	 *
+	 *     So to avoid mistakenly thinking the search wrapped when
+	 *     it hasn't, we have to trap the first button click after a
+	 *     search and re-run the search to recreate the HTMLEngine's
+	 *     search state, so that gtk_html_engine_search_next() will
+	 *     succeed. */
+	if (new_search) {
+		g_free (search_bar->priv->active_search);
+		search_bar->priv->active_search = text;
+		search_bar->priv->rerun_search = TRUE;
+		mail_search_bar_update_tokenizer (search_bar);
+	} else if (search_bar->priv->rerun_search) {
+		gtk_html_engine_search (
+			html, search_bar->priv->active_search,
+			case_sensitive, search_forward, FALSE);
+		search_bar->priv->rerun_search = FALSE;
+		g_free (text);
+	} else {
+		gtk_html_engine_search_set_forward (html, search_forward);
+		if (!gtk_html_engine_search_next (html))
+			wrapped = TRUE;
+		g_free (text);
+	}
+
+	if (new_search || wrapped)
+		gtk_html_engine_search (
+			html, search_bar->priv->active_search,
+			case_sensitive, search_forward, FALSE);
+
+	/* Update wrapped label visibility. */
+
+	widget = search_bar->priv->wrapped_next_box;
+
+	if (wrapped && search_forward)
+		gtk_widget_show (widget);
+	else
+		gtk_widget_hide (widget);
+
+	widget = search_bar->priv->wrapped_prev_box;
+
+	if (wrapped && !search_forward)
+		gtk_widget_show (widget);
+	else
+		gtk_widget_hide (widget);
+}
+
+static void
+mail_search_bar_changed_cb (EMailSearchBar *search_bar)
+{
+	g_object_notify (G_OBJECT (search_bar), "text");
+}
+
+static void
+mail_search_bar_find_next_cb (EMailSearchBar *search_bar)
+{
+	mail_search_bar_find (search_bar, TRUE);
+}
+
+static void
+mail_search_bar_find_previous_cb (EMailSearchBar *search_bar)
+{
+	mail_search_bar_find (search_bar, FALSE);
+}
+
+static void
+mail_search_bar_icon_release_cb (EMailSearchBar *search_bar,
+                                 GtkEntryIconPosition icon_pos,
+                                 GdkEvent *event)
+{
+	g_return_if_fail (icon_pos == GTK_ENTRY_ICON_SECONDARY);
+
+	e_mail_search_bar_clear (search_bar);
+	gtk_widget_grab_focus (search_bar->priv->entry);
+}
+
+static void
+mail_search_bar_toggled_cb (EMailSearchBar *search_bar)
+{
+	g_free (search_bar->priv->active_search);
+	search_bar->priv->active_search = NULL;
+
+	g_object_notify (G_OBJECT (search_bar), "case-sensitive");
+}
+
+static void
+mail_search_bar_set_html (EMailSearchBar *search_bar,
+                          GtkHTML *html)
+{
+	ESearchingTokenizer *tokenizer;
+
+	g_return_if_fail (search_bar->priv->html == NULL);
+
+	search_bar->priv->html = g_object_ref (html);
+
+	tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+	gtk_html_set_tokenizer (html, HTML_TOKENIZER (tokenizer));
+}
+
+static void
+mail_search_bar_set_property (GObject *object,
+                              guint property_id,
+                              const GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CASE_SENSITIVE:
+			e_mail_search_bar_set_case_sensitive (
+				E_MAIL_SEARCH_BAR (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_HTML:
+			mail_search_bar_set_html (
+				E_MAIL_SEARCH_BAR (object),
+				g_value_get_object (value));
+			return;
+
+		case PROP_TEXT:
+			e_mail_search_bar_set_text (
+				E_MAIL_SEARCH_BAR (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_search_bar_get_property (GObject *object,
+                              guint property_id,
+                              GValue *value,
+                              GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_CASE_SENSITIVE:
+			g_value_set_boolean (
+				value, e_mail_search_bar_get_case_sensitive (
+				E_MAIL_SEARCH_BAR (object)));
+			return;
+
+		case PROP_HTML:
+			g_value_set_object (
+				value, e_mail_search_bar_get_html (
+				E_MAIL_SEARCH_BAR (object)));
+			return;
+
+		case PROP_TEXT:
+			g_value_take_string (
+				value, e_mail_search_bar_get_text (
+				E_MAIL_SEARCH_BAR (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+mail_search_bar_dispose (GObject *object)
+{
+	EMailSearchBarPrivate *priv;
+
+	priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+	if (priv->html != NULL) {
+		g_object_unref (priv->html);
+		priv->html = NULL;
+	}
+
+	if (priv->entry != NULL) {
+		g_object_unref (priv->entry);
+		priv->entry = NULL;
+	}
+
+	if (priv->case_sensitive_button != NULL) {
+		g_object_unref (priv->case_sensitive_button);
+		priv->case_sensitive_button = NULL;
+	}
+
+	if (priv->wrapped_next_box != NULL) {
+		g_object_unref (priv->wrapped_next_box);
+		priv->wrapped_next_box = NULL;
+	}
+
+	if (priv->wrapped_prev_box != NULL) {
+		g_object_unref (priv->wrapped_prev_box);
+		priv->wrapped_prev_box = NULL;
+	}
+
+	if (priv->matches_label != NULL) {
+		g_object_unref (priv->matches_label);
+		priv->matches_label = NULL;
+	}
+
+	if (priv->tokenizer != NULL) {
+		g_object_unref (priv->tokenizer);
+		priv->tokenizer = NULL;
+	}
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+mail_search_bar_finalize (GObject *object)
+{
+	EMailSearchBarPrivate *priv;
+
+	priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+	g_free (priv->active_search);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+mail_search_bar_constructed (GObject *object)
+{
+	EMailSearchBarPrivate *priv;
+
+	priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (object);
+
+	e_mutual_binding_new (
+		G_OBJECT (object), "case-sensitive",
+		G_OBJECT (priv->case_sensitive_button), "active");
+}
+
+static void
+mail_search_bar_show (GtkWidget *widget)
+{
+	EMailSearchBar *search_bar;
+
+	search_bar = E_MAIL_SEARCH_BAR (widget);
+
+	/* Chain up to parent's show() method. */
+	GTK_WIDGET_CLASS (parent_class)->show (widget);
+
+	gtk_widget_grab_focus (search_bar->priv->entry);
+
+	mail_search_bar_update_tokenizer (search_bar);
+}
+
+static void
+mail_search_bar_hide (GtkWidget *widget)
+{
+	EMailSearchBar *search_bar;
+
+	search_bar = E_MAIL_SEARCH_BAR (widget);
+
+	/* Chain up to parent's hide() method. */
+	GTK_WIDGET_CLASS (parent_class)->hide (widget);
+
+	mail_search_bar_update_tokenizer (search_bar);
+}
+
+static gboolean
+mail_search_bar_key_press_event (GtkWidget *widget,
+                                 GdkEventKey *event)
+{
+	if (event->keyval == GDK_Escape) {
+		gtk_widget_hide (widget);
+		return TRUE;
+	}
+
+	/* Chain up to parent's key_press_event() method. */
+	return GTK_WIDGET_CLASS (parent_class)->
+		key_press_event (widget, event);
+}
+
+static void
+mail_search_bar_clear (EMailSearchBar *search_bar)
+{
+	g_free (search_bar->priv->active_search);
+	search_bar->priv->active_search = NULL;
+
+	gtk_widget_hide (search_bar->priv->wrapped_next_box);
+	gtk_widget_hide (search_bar->priv->wrapped_prev_box);
+	gtk_widget_hide (search_bar->priv->matches_label);
+
+	mail_search_bar_update_tokenizer (search_bar);
+}
+
+static void
+mail_search_bar_class_init (EMailSearchBarClass *class)
+{
+	GObjectClass *object_class;
+	GtkWidgetClass *widget_class;
+
+	parent_class = g_type_class_peek_parent (class);
+	g_type_class_add_private (class, sizeof (EMailSearchBarPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = mail_search_bar_set_property;
+	object_class->get_property = mail_search_bar_get_property;
+	object_class->dispose = mail_search_bar_dispose;
+	object_class->finalize = mail_search_bar_finalize;
+	object_class->constructed = mail_search_bar_constructed;
+
+	widget_class = GTK_WIDGET_CLASS (class);
+	widget_class->show = mail_search_bar_show;
+	widget_class->hide = mail_search_bar_hide;
+	widget_class->key_press_event = mail_search_bar_key_press_event;
+
+	class->clear = mail_search_bar_clear;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_CASE_SENSITIVE,
+		g_param_spec_boolean (
+			"case-sensitive",
+			"Case Sensitive",
+			NULL,
+			FALSE,
+			G_PARAM_READWRITE));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_HTML,
+		g_param_spec_object (
+			"html",
+			"HTML Display",
+			NULL,
+			GTK_TYPE_HTML,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT_ONLY));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_TEXT,
+		g_param_spec_string (
+			"text",
+			"Search Text",
+			NULL,
+			NULL,
+			G_PARAM_READWRITE));
+
+	signals[CHANGED] = g_signal_new (
+		"changed",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (EMailSearchBarClass, changed),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+
+	signals[CLEAR] = g_signal_new (
+		"clear",
+		G_TYPE_FROM_CLASS (class),
+		G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
+		G_STRUCT_OFFSET (EMailSearchBarClass, clear),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
+}
+
+static void
+mail_search_bar_init (EMailSearchBar *search_bar)
+{
+	GtkWidget *label;
+	GtkWidget *widget;
+	GtkWidget *container;
+
+	search_bar->priv = E_MAIL_SEARCH_BAR_GET_PRIVATE (search_bar);
+	search_bar->priv->tokenizer = e_searching_tokenizer_new ();
+
+	g_signal_connect_swapped (
+		search_bar->priv->tokenizer, "match",
+		G_CALLBACK (mail_search_bar_update_matches), search_bar);
+
+	gtk_box_set_spacing (GTK_BOX (search_bar), 12);
+
+	container = GTK_WIDGET (search_bar);
+
+	widget = gtk_hbox_new (FALSE, 1);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	container = widget;
+
+	widget = gtk_button_new ();
+	gtk_button_set_image (
+		GTK_BUTTON (widget), gtk_image_new_from_stock (
+		GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+	gtk_widget_set_tooltip_text (widget, _("Close the find bar"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (gtk_widget_hide), search_bar);
+
+	widget = gtk_label_new_with_mnemonic (_("Fin_d:"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 3);
+	gtk_widget_show (widget);
+
+	label = widget;
+
+	widget = gtk_entry_new ();
+	gtk_entry_set_icon_from_stock (
+		GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY,
+		GTK_STOCK_CLEAR);
+	gtk_entry_set_icon_tooltip_text (
+		GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY,
+		_("Clear the search"));
+	gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+	gtk_widget_set_size_request (widget, 200, -1);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	search_bar->priv->entry = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "activate",
+		G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (mail_search_bar_changed_cb), search_bar);
+
+	g_signal_connect_swapped (
+		widget, "icon-release",
+		G_CALLBACK (mail_search_bar_icon_release_cb), search_bar);
+
+	widget = gtk_button_new_with_mnemonic (_("_Previous"));
+	gtk_button_set_image (
+		GTK_BUTTON (widget), gtk_image_new_from_stock (
+		GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+	gtk_widget_set_tooltip_text (
+		widget, _("Find the previous occurrence of the phrase"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_search_bar_find_previous_cb), search_bar);
+
+	widget = gtk_button_new_with_mnemonic (_("_Next"));
+	gtk_button_set_image (
+		GTK_BUTTON (widget), gtk_image_new_from_stock (
+		GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_MENU));
+	gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE);
+	gtk_widget_set_tooltip_text (
+		widget, _("Find the next occurrence of the phrase"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "clicked",
+		G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+	widget = gtk_check_button_new_with_mnemonic (_("Mat_ch case"));
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	search_bar->priv->case_sensitive_button = g_object_ref (widget);
+	gtk_widget_show (widget);
+
+	g_signal_connect_swapped (
+		widget, "toggled",
+		G_CALLBACK (mail_search_bar_toggled_cb), search_bar);
+
+	g_signal_connect_swapped (
+		widget, "toggled",
+		G_CALLBACK (mail_search_bar_find_next_cb), search_bar);
+
+	container = GTK_WIDGET (search_bar);
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	search_bar->priv->wrapped_next_box = g_object_ref (widget);
+	gtk_widget_hide (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_icon_name (
+		"wrapped", GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (
+		_("Reached bottom of page, continued from top"));
+	gtk_label_set_ellipsize (
+		GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = GTK_WIDGET (search_bar);
+
+	widget = gtk_hbox_new (FALSE, 6);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	search_bar->priv->wrapped_prev_box = g_object_ref (widget);
+	gtk_widget_hide (widget);
+
+	container = widget;
+
+	widget = gtk_image_new_from_icon_name (
+		"wrapped", GTK_ICON_SIZE_MENU);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	gtk_widget_show (widget);
+
+	widget = gtk_label_new (
+		_("Reached top of page, continued from bottom"));
+	gtk_label_set_ellipsize (
+		GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
+	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
+	gtk_widget_show (widget);
+
+	container = GTK_WIDGET (search_bar);
+
+	widget = gtk_label_new (NULL);
+	gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 12);
+	search_bar->priv->matches_label = g_object_ref (widget);
+	gtk_widget_show (widget);
+}
+
+GType
+e_mail_search_bar_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo type_info = {
+			sizeof (EMailSearchBarClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) mail_search_bar_class_init,
+			(GClassFinalizeFunc) NULL,
+			NULL,  /* class_data */
+			sizeof (EMailSearchBar),
+			0,     /* n_preallocs */
+			(GInstanceInitFunc) mail_search_bar_init,
+			NULL   /* value_table */
+		};
+
+		type = g_type_register_static (
+			GTK_TYPE_HBOX, "EMailSearchBar", &type_info, 0);
+	}
+
+	return type;
+}
+
+GtkWidget *
+e_mail_search_bar_new (GtkHTML *html)
+{
+	g_return_val_if_fail (GTK_IS_HTML (html), NULL);
+
+	return g_object_new (E_TYPE_MAIL_SEARCH_BAR, "html", html, NULL);
+}
+
+void
+e_mail_search_bar_clear (EMailSearchBar *search_bar)
+{
+	g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+	g_signal_emit (search_bar, signals[CLEAR], 0);
+}
+
+void
+e_mail_search_bar_changed (EMailSearchBar *search_bar)
+{
+	g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+	g_signal_emit (search_bar, signals[CHANGED], 0);
+}
+
+GtkHTML *
+e_mail_search_bar_get_html (EMailSearchBar *search_bar)
+{
+	g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+	return search_bar->priv->html;
+}
+
+ESearchingTokenizer *
+e_mail_search_bar_get_tokenizer (EMailSearchBar *search_bar)
+{
+	g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+	return search_bar->priv->tokenizer;
+}
+
+gboolean
+e_mail_search_bar_get_case_sensitive (EMailSearchBar *search_bar)
+{
+	GtkToggleButton *button;
+
+	g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), FALSE);
+
+	button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button);
+
+	return gtk_toggle_button_get_active (button);
+}
+
+void
+e_mail_search_bar_set_case_sensitive (EMailSearchBar *search_bar,
+                                      gboolean case_sensitive)
+{
+	GtkToggleButton *button;
+
+	g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+	button = GTK_TOGGLE_BUTTON (search_bar->priv->case_sensitive_button);
+
+	gtk_toggle_button_set_active (button, case_sensitive);
+
+	g_object_notify (G_OBJECT (search_bar), "case-sensitive");
+}
+
+gchar *
+e_mail_search_bar_get_text (EMailSearchBar *search_bar)
+{
+	GtkEntry *entry;
+	const gchar *text;
+
+	g_return_val_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar), NULL);
+
+	entry = GTK_ENTRY (search_bar->priv->entry);
+	text = gtk_entry_get_text (entry);
+
+	return g_strstrip (g_strdup (text));
+}
+
+void
+e_mail_search_bar_set_text (EMailSearchBar *search_bar,
+                            const gchar *text)
+{
+	GtkEntry *entry;
+
+	g_return_if_fail (E_IS_MAIL_SEARCH_BAR (search_bar));
+
+	entry = GTK_ENTRY (search_bar->priv->entry);
+
+	if (text == NULL)
+		text = "";
+
+	/* This will trigger a "notify::text" signal. */
+	gtk_entry_set_text (entry, text);
+}
diff --git a/mail/e-mail-search-bar.h b/mail/e-mail-search-bar.h
new file mode 100644
index 0000000..7f19e17
--- /dev/null
+++ b/mail/e-mail-search-bar.h
@@ -0,0 +1,85 @@
+/*
+ * e-mail-search-bar.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>  
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_MAIL_SEARCH_BAR_H
+#define E_MAIL_SEARCH_BAR_H
+
+#include <gtk/gtk.h>
+#include <gtkhtml/gtkhtml.h>
+#include <mail/e-searching-tokenizer.h>
+
+/* Standard GObject macros */
+#define E_TYPE_MAIL_SEARCH_BAR \
+	(e_mail_search_bar_get_type ())
+#define E_MAIL_SEARCH_BAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBar))
+#define E_MAIL_SEARCH_BAR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass))
+#define E_IS_MAIL_SEARCH_BAR(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_MAIL_SEARCH_BAR))
+#define E_IS_MAIL_SEARCH_BAR_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_MAIL_SEARCH_BAR))
+#define E_MAIL_SEARCH_BAR_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_MAIL_SEARCH_BAR, EMailSearchBarClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EMailSearchBar EMailSearchBar;
+typedef struct _EMailSearchBarClass EMailSearchBarClass;
+typedef struct _EMailSearchBarPrivate EMailSearchBarPrivate;
+
+struct _EMailSearchBar {
+	GtkHBox parent;
+	EMailSearchBarPrivate *priv;
+};
+
+struct _EMailSearchBarClass {
+	GtkHBoxClass parent_class;
+
+	/* Signals */
+	void		(*changed)		(EMailSearchBar *search_bar);
+	void		(*clear)		(EMailSearchBar *search_bar);
+};
+
+GType		e_mail_search_bar_get_type	(void);
+GtkWidget *	e_mail_search_bar_new		(GtkHTML *html);
+void		e_mail_search_bar_clear		(EMailSearchBar *search_bar);
+void		e_mail_search_bar_changed	(EMailSearchBar *search_bar);
+GtkHTML *	e_mail_search_bar_get_html	(EMailSearchBar *search_bar);
+ESearchingTokenizer *
+		e_mail_search_bar_get_tokenizer	(EMailSearchBar *search_bar);
+gboolean	e_mail_search_bar_get_case_sensitive
+						(EMailSearchBar *search_bar);
+void		e_mail_search_bar_set_case_sensitive
+						(EMailSearchBar *search_bar,
+						 gboolean case_sensitive);
+gchar *		e_mail_search_bar_get_text	(EMailSearchBar *search_bar);
+void		e_mail_search_bar_set_text	(EMailSearchBar *search_bar,
+						 const gchar *text);
+
+G_END_DECLS
+
+#endif /* E_MAIL_SEARCH_BAR_H */
diff --git a/mail/e-searching-tokenizer.c b/mail/e-searching-tokenizer.c
index 9704ebb..3d98cde 100644
--- a/mail/e-searching-tokenizer.c
+++ b/mail/e-searching-tokenizer.c
@@ -1052,10 +1052,10 @@ e_searching_tokenizer_get_type (void)
 	return type;
 }
 
-HTMLTokenizer *
+ESearchingTokenizer *
 e_searching_tokenizer_new (void)
 {
-	return (HTMLTokenizer *) g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL);
+	return g_object_new (E_TYPE_SEARCHING_TOKENIZER, NULL);
 }
 
 /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/
diff --git a/mail/e-searching-tokenizer.h b/mail/e-searching-tokenizer.h
index ecc914d..37a0048 100644
--- a/mail/e-searching-tokenizer.h
+++ b/mail/e-searching-tokenizer.h
@@ -52,7 +52,7 @@ struct _ESearchingTokenizerClass {
 
 GType e_searching_tokenizer_get_type (void);
 
-HTMLTokenizer *e_searching_tokenizer_new (void);
+ESearchingTokenizer *e_searching_tokenizer_new (void);
 
 /* For now, just a simple API */
 
diff --git a/mail/em-folder-browser.c b/mail/em-folder-browser.c
index 9a80a0c..0aba4c1 100644
--- a/mail/em-folder-browser.c
+++ b/mail/em-folder-browser.c
@@ -79,6 +79,7 @@
 #include "e-util/e-error.h"
 #include "e-util/e-util-private.h"
 #include "e-util/e-util-labels.h"
+#include "e-mail-search-bar.h"
 #include "em-utils.h"
 #include "em-composer-utils.h"
 #include "em-format-html-display.h"
@@ -106,6 +107,7 @@ CamelStore *vfolder_store; /* the 1 static vfolder store */
 struct _EMFolderBrowserPrivate {
 	GtkWidget *preview;	/* container for message display */
 	GtkWidget *scroll;
+	GtkWidget *search_bar;
 
 	GtkWidget *subscribe_editor;
 
@@ -239,7 +241,6 @@ static ESearchBarItem emfb_search_scope_items[] = {
 	E_FILTERBAR_CURRENT_FOLDER,
 	E_FILTERBAR_CURRENT_ACCOUNT,
 	E_FILTERBAR_ALL_ACCOUNTS,
-	E_FILTERBAR_CURRENT_MESSAGE,
 	{ NULL, -1, 0 }
 };
 
@@ -485,6 +486,7 @@ emfb_init(GObject *o)
 	EMFolderBrowser *emfb = (EMFolderBrowser *)o;
 	RuleContext *search_context = mail_component_peek_search_context (mail_component_peek ());
 	struct _EMFolderBrowserPrivate *p;
+	GtkWidget *html;
 
 	EMEvent *eme;
 	EMEventTargetFolderBrowser *target;
@@ -527,7 +529,6 @@ emfb_init(GObject *o)
  		efb->account_search_cancel = NULL;
 		e_search_bar_set_menu ((ESearchBar *)emfb->search, emfb_search_items);
 		e_search_bar_set_scopeoption ((ESearchBar *)emfb->search, emfb_search_scope_items);
-		e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
 		emfb->priv->scope_restricted = TRUE;
 		g_signal_connect(emfb, "realize", G_CALLBACK(emfb_realize), NULL);
 		gtk_widget_show((GtkWidget *)emfb->search);
@@ -561,14 +562,21 @@ emfb_init(GObject *o)
 	gtk_scrolled_window_set_shadow_type((GtkScrolledWindow *)p->scroll, GTK_SHADOW_IN);
 	gtk_widget_show(p->scroll);
 
-	p->preview = gtk_vbox_new (FALSE, 6);
-	gtk_container_add((GtkContainer *)p->scroll, (GtkWidget *)emfb->view.preview->formathtml.html);
-	gtk_widget_show((GtkWidget *)emfb->view.preview->formathtml.html);
+	html = GTK_WIDGET (emfb->view.preview->formathtml.html);
+
+	p->preview = gtk_vbox_new (FALSE, 1);
+	p->search_bar = e_mail_search_bar_new (GTK_HTML (html));
+	gtk_container_add((GtkContainer *)p->scroll, html);
+	gtk_widget_show(html);
 	gtk_box_pack_start ((GtkBox *)p->preview, p->scroll, TRUE, TRUE, 0);
-	gtk_box_pack_start ((GtkBox *)p->preview, em_format_html_get_search_dialog (emfb->view.preview), FALSE, FALSE, 0);
+	gtk_box_pack_start ((GtkBox *)p->preview, p->search_bar, FALSE, FALSE, 0);
 	gtk_paned_pack2 (GTK_PANED (emfb->vpane), p->preview, TRUE, FALSE);
 	gtk_widget_show(p->preview);
 
+	g_signal_connect_swapped (
+		p->search_bar, "changed",
+		G_CALLBACK (em_format_redraw), emfb->view.preview);
+
 	/** @HookPoint-EMFolderBrower: Folder Browser
 	 * @Id: emfb.created
 	 * @Class: org.gnome.evolution.mail.events:1.0
@@ -638,6 +646,14 @@ emfb_destroy(GtkObject *o)
 }
 
 static void
+emfb_show_search_bar (EMFolderView *folder_view)
+{
+	EMFolderBrowser *browser = (EMFolderBrowser *) folder_view;
+
+	gtk_widget_show (browser->priv->search_bar);
+}
+
+static void
 emfb_class_init(GObjectClass *klass)
 {
 	klass->finalize = emfb_finalise;
@@ -666,6 +682,7 @@ emfb_class_init(GObjectClass *klass)
 	((GtkObjectClass *)klass)->destroy = emfb_destroy;
 	((EMFolderViewClass *)klass)->set_folder = emfb_set_folder;
 	((EMFolderViewClass *)klass)->activate = emfb_activate;
+	((EMFolderViewClass *)klass)->show_search_bar = emfb_show_search_bar;
 }
 
 GType
@@ -711,7 +728,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
 	if ((emfb->view.preview_active ^ state) == 0
 	    || emfb->view.list == NULL) {
 		if (state && emfb->priv->scope_restricted && emfb->view.list->cursor_uid && *(emfb->view.list->cursor_uid)) {
-			e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
 			emfb->priv->scope_restricted = FALSE;
 		}
 
@@ -733,7 +749,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
 		if (emfb->view.list->cursor_uid) {
 			char *uid = g_alloca(strlen(emfb->view.list->cursor_uid)+1);
 
-			e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
 			emfb->priv->scope_restricted = FALSE;
 			strcpy(uid, emfb->view.list->cursor_uid);
 			em_folder_view_set_message(&emfb->view, uid, FALSE);
@@ -749,7 +764,6 @@ void em_folder_browser_show_preview(EMFolderBrowser *emfb, gboolean state)
 		emfb->view.displayed_uid = NULL;
 
 		gtk_widget_hide(emfb->priv->preview);
-		e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
 		emfb->priv->scope_restricted = TRUE;
 		/*
 		mail_display_set_message (emfb->mail_display, NULL, NULL, NULL);
@@ -841,6 +855,8 @@ static void
 emfb_search_config_search(EFilterBar *efb, FilterRule *rule, int id, const char *query, void *data)
 {
 	EMFolderBrowser *emfb = data;
+	EMailSearchBar *search_bar;
+	ESearchingTokenizer *tokenizer;
 	GList *partl;
 	struct _camel_search_words *words;
 	int i;
@@ -877,15 +893,26 @@ emfb_search_config_search(EFilterBar *efb, FilterRule *rule, int id, const char
 		partl = partl->next;
 	}
 
-	em_format_html_display_set_search(emfb->view.preview,
-					  EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY|EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE,
-					  strings);
-	while (strings) {
-		GSList *n = strings->next;
-		g_free(strings->data);
-		g_slist_free_1(strings);
-		strings = n;
+	search_bar = E_MAIL_SEARCH_BAR (emfb->priv->search_bar);
+
+	/* XXX This is a hack, but this code is on its way out anyway.
+	 *     Function is called once before the search bar is created. */
+	if (!E_IS_MAIL_SEARCH_BAR (search_bar))
+		return;
+
+	tokenizer = e_mail_search_bar_get_tokenizer (search_bar);
+
+	e_searching_tokenizer_set_secondary_case_sensitivity (tokenizer, FALSE);
+	e_searching_tokenizer_set_secondary_search_string (tokenizer, NULL);
+
+	while (strings != NULL) {
+		e_searching_tokenizer_add_secondary_search_string (
+			tokenizer, strings->data);
+		g_free (strings->data);
+		strings = g_slist_delete_link (strings, strings);
 	}
+
+	e_mail_search_bar_changed (search_bar);
 }
 
 static char *
@@ -1125,18 +1152,6 @@ emfb_search_search_activated(ESearchBar *esb, EMFolderBrowser *emfb)
 	id = e_search_bar_get_search_scope (esb);
 
 	switch (id) {
-	    case E_FILTERBAR_CURRENT_MESSAGE_ID:
-		    word = e_search_bar_get_text (esb);
-		    if ( word && *word ) {
-			    gtk_widget_set_sensitive (esb->option_button, FALSE);
-			    em_format_html_display_search_with (emfb->view.preview, word);
-		    } else {
-			    em_format_html_display_search_close (emfb->view.preview);
-		    }
-		    g_free (word);
-		    return;
-		    break;
-
 	    case E_FILTERBAR_CURRENT_FOLDER_ID:
 		    g_object_get (esb, "query", &search_word, NULL);
 		    break;
@@ -1386,10 +1401,8 @@ emfb_list_message_selected (MessageList *ml, const char *uid, EMFolderBrowser *e
 		return;
 
 	if (uid && *uid && emfb->priv->scope_restricted && emfb->view.preview_active) {
-		e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, TRUE);
 		emfb->priv->scope_restricted = FALSE;
 	} else if ( !(uid && *uid) && !emfb->priv->scope_restricted) {
-		e_search_bar_scope_enable ((ESearchBar *)emfb->search, E_FILTERBAR_CURRENT_MESSAGE_ID, FALSE);
 		emfb->priv->scope_restricted = TRUE;
 	}
 
diff --git a/mail/em-folder-view.c b/mail/em-folder-view.c
index e31d8d7..62bab8a 100644
--- a/mail/em-folder-view.c
+++ b/mail/em-folder-view.c
@@ -956,7 +956,7 @@ emfv_popup_flag_completed(EPopup *ep, EPopupItem *pitem, void *data)
 	em_utils_flag_for_followup_completed((GtkWidget *)emfv, emfv->folder, uids);
 
 	if (emfv->preview)
-		em_format_redraw (emfv->preview);
+		em_format_redraw (EM_FORMAT (emfv->preview));
 }
 
 static void
@@ -968,7 +968,7 @@ emfv_popup_flag_clear(EPopup *ep, EPopupItem *pitem, void *data)
 	em_utils_flag_for_followup_clear((GtkWidget *)emfv, emfv->folder, uids);
 
 	if (emfv->preview)
-		em_format_redraw (emfv->preview);
+		em_format_redraw (EM_FORMAT (emfv->preview));
 }
 
 static void
@@ -1808,13 +1808,7 @@ emfv_message_search(BonoboUIComponent *uic, void *data, const char *path)
 {
 	EMFolderView *emfv = data;
 
-	if (!emfv->list_active) /* We are in new mail window */
-		em_format_html_display_search(emfv->preview);
-	else  {
-                /* We are in top level. Just grab focus to Search Bar */
-		gtk_widget_grab_focus (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->entry);
-		gtk_option_menu_set_history (GTK_OPTION_MENU (((ESearchBar *)((EMFolderBrowser *) emfv)->search)->scopeoption), 3);
-	}
+	em_folder_view_show_search_bar (emfv);
 }
 
 static void
@@ -3271,3 +3265,15 @@ emfv_on_html_button_released_cb (GtkHTML *html, GdkEventButton *button, EMFolder
 	return FALSE;
 }
 
+void
+em_folder_view_show_search_bar (EMFolderView *emfv)
+{
+	EMFolderViewClass *class;
+
+	g_return_if_fail (EM_IS_FOLDER_VIEW (emfv));
+
+	class = EM_FOLDER_VIEW_GET_CLASS (emfv);
+	g_return_if_fail (class->show_search_bar != NULL);
+
+	class->show_search_bar (emfv);
+}
diff --git a/mail/em-folder-view.h b/mail/em-folder-view.h
index 4af4760..b69a4a1 100644
--- a/mail/em-folder-view.h
+++ b/mail/em-folder-view.h
@@ -124,6 +124,8 @@ struct _EMFolderViewClass {
 	void (*set_folder)(EMFolderView *emfv, struct _CamelFolder *folder, const char *uri);
 	void (*set_message)(EMFolderView *emfv, const char *uid, int nomarkseen);
 
+	void (*show_search_bar)(EMFolderView *emfv);
+
 	/* Signals */
 	void (*on_url)(EMFolderView *emfv, const char *uri, const char *nice_uri);
 
@@ -153,6 +155,7 @@ guint32 em_folder_view_disable_mask(EMFolderView *emfv);
 void em_folder_view_set_statusbar(EMFolderView *emfv, gboolean statusbar);
 void em_folder_view_set_hide_deleted(EMFolderView *emfv, gboolean status);
 void em_folder_view_setup_view_instance (EMFolderView *emfv);
+void em_folder_view_show_search_bar (EMFolderView *emfv);
 
 G_END_DECLS
 
diff --git a/mail/em-format-html-display.c b/mail/em-format-html-display.c
index aba9c64..cf1626e 100644
--- a/mail/em-format-html-display.c
+++ b/mail/em-format-html-display.c
@@ -40,7 +40,6 @@
 
 #include <gtkhtml/gtkhtml.h>
 #include <gtkhtml/gtkhtml-embedded.h>
-#include <gtkhtml/gtkhtml-search.h>
 
 #include <glade/glade.h>
 
@@ -76,7 +75,6 @@
 
 #include "e-mail-attachment-bar.h"
 #include "em-format-html-display.h"
-#include "e-searching-tokenizer.h"
 #include "em-icon-stream.h"
 #include "em-utils.h"
 #include "em-popup.h"
@@ -97,17 +95,6 @@
 #define d(x)
 
 struct _EMFormatHTMLDisplayPrivate {
-	/* For the interactive search dialogue */
-	/* TODO: Should this be more subtle, like the mozilla one? */
-	GtkHBox   *search_dialog;
-	GtkWidget *search_entry;
-	GtkWidget *search_entry_box;
-	GtkWidget *search_matches_label;
-	GtkWidget *search_case_check;
-	char *search_text;
-	int search_wrap;	/* are we doing a wrap search */
-	gboolean search_active; /* if the search is active */
-
 	GtkWidget *attachment_view;  /* weak reference */
 };
 
@@ -167,7 +154,6 @@ static void efhd_format_source(EMFormat *, CamelStream *, CamelMimePart *);
 static void efhd_format_attachment(EMFormat *, CamelStream *, CamelMimePart *, const char *, const EMFormatHandler *);
 static void efhd_format_optional(EMFormat *, CamelStream *, CamelMimePart *, CamelStream *);
 static void efhd_format_secure(EMFormat *emf, CamelStream *stream, CamelMimePart *part, CamelCipherValidity *valid);
-static void efhd_complete(EMFormat *);
 
 static void efhd_builtin_init(EMFormatHTMLDisplayClass *efhc);
 
@@ -246,9 +232,6 @@ efhd_init(GObject *o)
 
 	efhd->priv = g_malloc0(sizeof(*efhd->priv));
 
-	efhd->search_tok = (ESearchingTokenizer *)e_searching_tokenizer_new();
-	gtk_html_set_tokenizer (efh->html, (HTMLTokenizer *)efhd->search_tok);
-
 	g_signal_connect(efh->html, "realize", G_CALLBACK(efhd_gtkhtml_realise), o);
 	g_signal_connect(efh->html, "style-set", G_CALLBACK(efhd_gtkhtml_style_set), o);
 	/* we want to convert url's etc */
@@ -265,7 +248,6 @@ efhd_finalise(GObject *o)
 
 	/* check pending stuff */
 
-	g_free(efhd->priv->search_text);
 	g_free(efhd->priv);
 
 	((GObjectClass *)efhd_parent)->finalize(o);
@@ -291,7 +273,6 @@ efhd_class_init(GObjectClass *klass)
 	((EMFormatClass *)klass)->format_attachment = efhd_format_attachment;
 	((EMFormatClass *)klass)->format_optional = efhd_format_optional;
 	((EMFormatClass *)klass)->format_secure = efhd_format_secure;
-	((EMFormatClass *)klass)->complete = efhd_complete;
 
 	klass->finalize = efhd_finalise;
 
@@ -401,316 +382,6 @@ void em_format_html_display_set_caret_mode(EMFormatHTMLDisplay *efhd, gboolean s
 }
 
 void
-em_format_html_display_set_search(EMFormatHTMLDisplay *efhd, int type, GSList *strings)
-{
-	switch(type&3) {
-	case EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY:
-		e_searching_tokenizer_set_primary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0);
-		e_searching_tokenizer_set_primary_search_string(efhd->search_tok, NULL);
-		while (strings) {
-			e_searching_tokenizer_add_primary_search_string(efhd->search_tok, strings->data);
-			strings = strings->next;
-		}
-		break;
-	case EM_FORMAT_HTML_DISPLAY_SEARCH_SECONDARY:
-	default:
-		e_searching_tokenizer_set_secondary_case_sensitivity(efhd->search_tok, (type&EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE) == 0);
-		e_searching_tokenizer_set_secondary_search_string(efhd->search_tok, NULL);
-		while (strings) {
-			e_searching_tokenizer_add_secondary_search_string(efhd->search_tok, strings->data);
-			strings = strings->next;
-		}
-		break;
-	}
-
-	d(printf("redrawing with search\n"));
-	em_format_redraw((EMFormat *)efhd);
-}
-
-static void
-efhd_update_matches(EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-	char *str;
-	/* message-search popup match count string */
-	char *fmt = _("Matches: %d");
-
-	if (p->search_dialog) {
-		str = alloca(strlen(fmt)+32);
-		sprintf(str, fmt, e_searching_tokenizer_match_count(efhd->search_tok));
-		gtk_label_set_text((GtkLabel *)p->search_matches_label, str);
-	}
-	gtk_widget_show((GtkWidget *)p->search_matches_label);
-
-}
-
-static void
-efhd_update_search(EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-	GSList *words = NULL;
-	int flags = 0;
-
-	if (!gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check))
-		flags = EM_FORMAT_HTML_DISPLAY_SEARCH_ICASE | EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY;
-	else
-		flags = EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY;
-
-	if (p->search_text)
-		words = g_slist_append(words, p->search_text);
-
-	em_format_html_display_set_search(efhd, flags, words);
-	g_slist_free(words);
-}
-
-static void
-efhd_search_response(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry));
-
-	g_strstrip(txt);
-	if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) {
-		gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, TRUE);
-		if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html))
-			p->search_wrap = TRUE;
-		g_free(txt);
-	} else {
-		g_free(p->search_text);
-		p->search_text = txt;
-		if (!p->search_wrap)
-			efhd_update_search(efhd);
-		p->search_wrap = FALSE;
-		gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt,
-				       gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check),
-				       TRUE, FALSE);
-	}
-}
-
-
-static void
-efhd_search_response_back (GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	char *txt = g_strdup(gtk_entry_get_text((GtkEntry *)p->search_entry));
-
-	g_strstrip(txt);
-	if (p->search_text && strcmp(p->search_text, txt) == 0 && !p->search_wrap) {
-		gtk_html_engine_search_set_forward (((EMFormatHTML *)efhd)->html, FALSE);
-		if (!gtk_html_engine_search_next(((EMFormatHTML *)efhd)->html))
-			p->search_wrap = TRUE;
-		g_free(txt);
-	} else {
-		g_free(p->search_text);
-		p->search_text = txt;
-		if (!p->search_wrap)
-			efhd_update_search(efhd);
-		p->search_wrap = FALSE;
-		gtk_html_engine_search(((EMFormatHTML *)efhd)->html, txt,
-				       gtk_toggle_button_get_active((GtkToggleButton *)p->search_case_check),
-				       FALSE, FALSE);
-	}
-}
-
-
-static void
-efhd_search_destroy(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-	g_free(p->search_text);
-	p->search_text = NULL;
-	gtk_widget_hide((GtkWidget *)p->search_dialog);
-	em_format_html_display_set_search(efhd, EM_FORMAT_HTML_DISPLAY_SEARCH_PRIMARY, NULL);
-	p->search_active = FALSE;
-}
-
-static void
-efhd_search_case_toggled(GtkWidget *w, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	g_free(p->search_text);
-	p->search_text = NULL;
-	efhd_search_response(w, efhd);
-}
-
-static gboolean
-efhd_key_pressed (GtkWidget *w, GdkEventKey *event, EMFormatHTMLDisplay *efhd)
-{
-	if (event->keyval == GDK_Escape){
-		efhd_search_destroy (w, efhd);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-static void
-clear_button_clicked_cb (GtkWidget *widget, gpointer dummy, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	gtk_entry_set_text (GTK_ENTRY (p->search_entry), "");
-
-	g_signal_emit_by_name (p->search_entry, "activate", efhd);
-}
-
-/* Controlls the visibility of icon_entry's visibility */
-static void
-icon_entry_changed_cb (GtkWidget *widget, GtkWidget *clear_button)
-{
-	const char *text = gtk_entry_get_text (GTK_ENTRY (widget));
-
-	if (text && *text)
-		gtk_widget_show (clear_button);
-	else
-		gtk_widget_hide (clear_button);
-}
-
-GtkWidget *
-em_format_html_get_search_dialog (EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-	GtkWidget *hbox2, *button3, *button2, *label1;
-	GtkWidget *icon_entry, *clear_button;
-
-	p->search_entry_box = gtk_hbox_new (FALSE, 0);
-
-	label1 = gtk_label_new_with_mnemonic (_("Fin_d:"));
-	gtk_widget_show (label1);
-	gtk_box_pack_start ((GtkBox *)(p->search_entry_box), label1, FALSE, FALSE, 5);
-
-	/* Icon entry */
-	icon_entry = e_icon_entry_new ();
-	p->search_entry = e_icon_entry_get_entry (E_ICON_ENTRY (icon_entry));
-	gtk_label_set_mnemonic_widget (GTK_LABEL (label1), p->search_entry);
-	gtk_widget_show (p->search_entry);
-	clear_button = e_icon_entry_create_button ("gtk-clear");
-	e_icon_entry_pack_widget (E_ICON_ENTRY (icon_entry), clear_button, FALSE);
-	gtk_widget_show_all (icon_entry);
-	gtk_widget_hide (clear_button);
-
-	g_signal_connect (G_OBJECT (clear_button), "button-press-event", (GCallback) clear_button_clicked_cb, efhd);
-	g_signal_connect (G_OBJECT (p->search_entry), "changed", (GCallback) icon_entry_changed_cb, clear_button);
-
-	gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, FALSE, FALSE, 0);
-	/* gtk_box_pack_start ((GtkBox *)(p->search_entry_box), icon_entry, TRUE, TRUE, 0); */
-
-	hbox2 = gtk_hbox_new (FALSE, 0);
-	gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, FALSE, FALSE, 5);
-	/* gtk_box_pack_start ((GtkBox *)(hbox2), p->search_entry_box, TRUE, TRUE, 5); */
-
-	button3 = gtk_button_new_with_mnemonic (_("_Previous"));
-	gtk_button_set_image (GTK_BUTTON (button3), GTK_WIDGET(gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON)));
-	gtk_widget_show (button3);
-	gtk_box_pack_start (GTK_BOX (hbox2), button3, FALSE, FALSE, 5);
-
-	button2 = gtk_button_new_with_mnemonic (_("_Next"));
-	gtk_button_set_image (GTK_BUTTON (button2), gtk_image_new_from_stock(GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
-	gtk_widget_show (button2);
-	gtk_box_pack_start (GTK_BOX (hbox2), button2, FALSE, FALSE, 5);
-
-	p->search_case_check = gtk_check_button_new_with_mnemonic (_("M_atch case"));
-	gtk_widget_show (p->search_case_check);
-	gtk_box_pack_start (GTK_BOX (hbox2), p->search_case_check, FALSE, FALSE, 0);
-
-	p->search_matches_label = gtk_label_new ("");
-	gtk_widget_show (p->search_matches_label);
-	gtk_box_pack_start (GTK_BOX (hbox2), p->search_matches_label, TRUE, TRUE, 0);
-	p->search_dialog = GTK_HBOX (hbox2);
-
-	p->search_wrap = FALSE;
-
-	g_signal_connect (p->search_entry, "activate", G_CALLBACK(efhd_search_response), efhd);
-	g_signal_connect (p->search_entry, "key-press-event", G_CALLBACK(efhd_key_pressed), efhd);
-	g_signal_connect (p->search_case_check, "toggled", G_CALLBACK(efhd_search_case_toggled), efhd);
-	g_signal_connect (button2, "clicked", G_CALLBACK(efhd_search_response), efhd);
-	g_signal_connect (button3, "clicked", G_CALLBACK(efhd_search_response_back), efhd);
-
-	p->search_active = FALSE;
-
-	efhd_update_matches(efhd);
-
-	return (GtkWidget *)p->search_dialog;
-
-}
-
-static void
-set_focus_cb (GtkWidget *window, GtkWidget *widget, EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-	GtkWidget *sbar = GTK_WIDGET (p->search_dialog);
-
-	while (widget != NULL && widget != sbar) {
-		widget = widget->parent;
-    	}
-
-	if (widget != sbar)
-		efhd_search_destroy(widget, efhd);
-}
-
-/**
- * em_format_html_display_search:
- * @efhd:
- *
- * Run an interactive search dialogue.
- **/
-void
-em_format_html_display_search(EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	if (p->search_dialog){
-		GtkWidget *toplevel;
-
-		gtk_widget_show (GTK_WIDGET (p->search_dialog));
-		gtk_widget_grab_focus (p->search_entry);
-		gtk_widget_show (p->search_entry_box);
-
-		p->search_active = TRUE;
-
-		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (p->search_dialog));
-
-		g_signal_connect (toplevel, "set-focus",
-                                 G_CALLBACK (set_focus_cb), efhd);
-	}
-
-}
-/**
- * em_format_html_display_search_with:
- * @efhd:
- *
- * Run an interactive search dialogue.
- **/
-void
-em_format_html_display_search_with (EMFormatHTMLDisplay *efhd, char *word)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	if (p->search_dialog){
-		gtk_widget_show (GTK_WIDGET (p->search_dialog));
-		p->search_active = TRUE;
-
-		/* Set the query */
-		gtk_entry_set_text (GTK_ENTRY (p->search_entry), word);
-		gtk_widget_hide (p->search_entry_box);
-
-		/* Trigger the search */
-		g_signal_emit_by_name (p->search_entry, "activate", efhd);
-	}
-}
-
-void
-em_format_html_display_search_close (EMFormatHTMLDisplay *efhd)
-{
-	struct _EMFormatHTMLDisplayPrivate *p = efhd->priv;
-
-	if (p->search_dialog && p->search_active)
-		efhd_search_destroy(GTK_WIDGET (p->search_dialog), efhd);
-}
-
-void
 em_format_html_display_cut (EMFormatHTMLDisplay *efhd)
 {
 	gtk_html_cut (((EMFormatHTML *) efhd)->html);
@@ -889,15 +560,6 @@ efhd_html_on_url (GtkHTML *html, const char *url, EMFormatHTMLDisplay *efhd)
 	g_signal_emit((GObject *)efhd, efhd_signals[EFHD_ON_URL], 0, url);
 }
 
-static void
-efhd_complete(EMFormat *emf)
-{
-	EMFormatHTMLDisplay *efhd = (EMFormatHTMLDisplay *)emf;
-
-	if (efhd->priv->search_dialog && efhd->priv->search_active)
-		efhd_update_matches(efhd);
-}
-
 /* ********************************************************************** */
 
 /* TODO: move the dialogue elsehwere */
diff --git a/mail/em-format-html-display.h b/mail/em-format-html-display.h
index 10a379d..99234e9 100644
--- a/mail/em-format-html-display.h
+++ b/mail/em-format-html-display.h
@@ -105,8 +105,6 @@ void		em_format_html_display_search_with
 void		em_format_html_display_search_close
 						(EMFormatHTMLDisplay *efhd);
 
-GtkWidget *	em_format_html_get_search_dialog(EMFormatHTMLDisplay *efhd);
-
 void		em_format_html_display_cut	(EMFormatHTMLDisplay *efhd);
 void		em_format_html_display_copy	(EMFormatHTMLDisplay *efhd);
 void		em_format_html_display_paste	(EMFormatHTMLDisplay *efhd);
diff --git a/mail/em-format.c b/mail/em-format.c
index 1d5570b..826ef11 100644
--- a/mail/em-format.c
+++ b/mail/em-format.c
@@ -772,7 +772,43 @@ emf_busy(EMFormat *emf)
  * a display refresh, or it can be used to generate an identical layout,
  * e.g. to print what the user has shown inline.
  **/
-/* e_format_format_clone is a macro */
+void
+em_format_format_clone (EMFormat *emf,
+                        CamelFolder *folder,
+                        const gchar *uid,
+                        CamelMimeMessage *message,
+                        EMFormat *source)
+{
+	EMFormatClass *class;
+
+	g_return_if_fail (EM_IS_FORMAT (emf));
+	g_return_if_fail (folder == NULL || CAMEL_IS_FOLDER (folder));
+	g_return_if_fail (message == NULL || CAMEL_IS_MIME_MESSAGE (message));
+	g_return_if_fail (source == NULL || EM_IS_FORMAT (source));
+
+	class = EM_FORMAT_GET_CLASS (emf);
+	g_return_if_fail (class->format_clone != NULL);
+	class->format_clone (emf, folder, uid, message, source);
+}
+
+void
+em_format_format (EMFormat *emf,
+                  CamelFolder *folder,
+                  const gchar *uid,
+                  CamelMimeMessage *message)
+{
+	/* em_format_format_clone() will check the arguments. */
+	em_format_format_clone (emf, folder, uid, message, NULL);
+}
+
+void
+em_format_redraw (EMFormat *emf)
+{
+	g_return_if_fail (EM_IS_FORMAT (emf));
+
+	em_format_format_clone (
+		emf, emf->folder, emf->uid, emf->message, emf);
+}
 
 /**
  * em_format_set_session:
diff --git a/mail/em-format.h b/mail/em-format.h
index 92c6b3d..f11e739 100644
--- a/mail/em-format.h
+++ b/mail/em-format.h
@@ -324,14 +324,10 @@ void em_format_push_level(EMFormat *emf);
 void em_format_pull_level(EMFormat *emf);
 
 /* clones inline state/view and format, or use to redraw */
-#define em_format_format_clone(emf, folder, uid, msg, src) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), (src))
+void em_format_format_clone (EMFormat *emf, CamelFolder *folder, const gchar *uid, CamelMimeMessage *message, EMFormat *source);
 /* formats a new message */
-#define em_format_format(emf, folder, uid, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((emf), (folder), (uid), (msg), NULL)
-#define em_format_redraw(emf) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_clone((EMFormat *)(emf),				\
-										       ((EMFormat *)(emf))->folder,	\
-										       ((EMFormat *)(emf))->uid,	\
-										       ((EMFormat *)(emf))->message,	\
-										       (EMFormat *)(emf))
+void em_format_format(EMFormat *emf, CamelFolder *folder, const gchar *uid, CamelMimeMessage *message);
+void em_format_redraw(EMFormat *emf);
 void em_format_format_error(EMFormat *emf, CamelStream *stream, const char *fmt, ...);
 #define em_format_format_attachment(emf, stream, msg, type, info) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_attachment((emf), (stream), (msg), (type), (info))
 #define em_format_format_source(emf, stream, msg) ((EMFormatClass *)G_OBJECT_GET_CLASS(emf))->format_source((emf), (stream), (msg))
diff --git a/mail/em-message-browser.c b/mail/em-message-browser.c
index 728b27e..973708b 100644
--- a/mail/em-message-browser.c
+++ b/mail/em-message-browser.c
@@ -48,6 +48,7 @@
 
 #include "e-util/e-util-private.h"
 
+#include "e-mail-search-bar.h"
 #include "em-format-html-display.h"
 #include "em-message-browser.h"
 #include "em-menu.h"
@@ -63,6 +64,7 @@
 
 struct _EMMessageBrowserPrivate {
 	GtkWidget *preview;	/* container for message display */
+	GtkWidget *search_bar;
 };
 
 static gpointer parent_class;
@@ -225,6 +227,14 @@ emmb_destroy (GtkObject *gtk_object)
 }
 
 static void
+emmb_show_search_bar (EMFolderView *folder_view)
+{
+	EMMessageBrowser *browser = EM_MESSAGE_BROWSER (folder_view);
+
+	gtk_widget_show (browser->priv->search_bar);
+}
+
+static void
 emmb_class_init (EMMessageBrowserClass *class)
 {
 	GtkObjectClass *gtk_object_class;
@@ -240,12 +250,14 @@ emmb_class_init (EMMessageBrowserClass *class)
 	folder_view_class->update_message_style = FALSE;
 	folder_view_class->set_message = emmb_set_message;
 	folder_view_class->activate = emmb_activate;
+	folder_view_class->show_search_bar = emmb_show_search_bar;
 }
 
 static void
 emmb_init (EMMessageBrowser *emmb)
 {
 	EMFolderView *emfv = EM_FOLDER_VIEW (emmb);
+	GtkWidget *container;
 	GtkWidget *widget;
 	gchar *filename;
 
@@ -265,25 +277,35 @@ emmb_init (EMMessageBrowser *emmb)
 		EVOLUTION_UIDIR, "evolution-mail-message.xml", NULL);
 	emfv->ui_files = g_slist_append (emfv->ui_files, filename);
 
+	gtk_box_set_spacing (GTK_BOX (emmb), 1);
+
+	container = GTK_WIDGET (emmb);
+
 	widget = gtk_scrolled_window_new (NULL, NULL);
 	gtk_scrolled_window_set_policy (
 		GTK_SCROLLED_WINDOW (widget),
 		GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 	gtk_scrolled_window_set_shadow_type (
 		GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN);
-	gtk_widget_show (widget);
+	gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
 	emmb->priv->preview = widget;
+	gtk_widget_show (widget);
+
+	widget = e_mail_search_bar_new (emfv->preview->formathtml.html);
+	gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0);
+	emmb->priv->search_bar = widget;
+	gtk_widget_hide (widget);
+
+	g_signal_connect_swapped (
+		widget, "changed",
+		G_CALLBACK (em_format_redraw), emfv->preview);
+
+	container = emmb->priv->preview;
 
 	widget = GTK_WIDGET (emfv->preview->formathtml.html);
-	gtk_container_add (GTK_CONTAINER (emmb->priv->preview), widget);
+	gtk_container_add (GTK_CONTAINER (container), widget);
 	gtk_widget_show (widget);
 
-	gtk_box_pack_start (
-		GTK_BOX (emmb), emmb->priv->preview, TRUE, TRUE, 0);
-	gtk_box_pack_start(
-		GTK_BOX (emmb), em_format_html_get_search_dialog (
-		emfv->preview), FALSE, FALSE, 0);
-
 	/** @HookPoint-EMMenu: Standalone Message View Menu
 	 * @Id: org.gnome.evolution.mail.messagebrowser
 	 * @Class: org.gnome.evolution.mail.bonobomenu:1.0
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 7685e76..9588646 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -804,7 +804,7 @@ tag_editor_response (GtkWidget *dialog, int button, struct ted_t *ted)
 		camel_tag_list_free (&tags);
 
 		if (ted->emfv->preview)
-			em_format_redraw(ted->emfv->preview);
+			em_format_redraw (EM_FORMAT (ted->emfv->preview));
 	}
 
 	gtk_widget_destroy (dialog);
diff --git a/widgets/misc/e-filter-bar.c b/widgets/misc/e-filter-bar.c
index ac5012b..aeb4fa3 100644
--- a/widgets/misc/e-filter-bar.c
+++ b/widgets/misc/e-filter-bar.c
@@ -325,12 +325,6 @@ option_changed (ESearchBar *esb, void *data)
 
 	d(printf("option changed, id = %d, setquery = %s %d\n", id, efb->setquery ? "true" : "false", esb->block_search));
 
-	if (esb->scopeitem_id == E_FILTERBAR_CURRENT_MESSAGE_ID) {
-		gtk_widget_set_sensitive (esb->option_button, FALSE);
-	} else {
-		gtk_widget_set_sensitive (esb->option_button, TRUE);
-	}
-
 	if (efb->setquery)
 		return;
 
diff --git a/widgets/misc/e-filter-bar.h b/widgets/misc/e-filter-bar.h
index be7e26c..41e3bde 100644
--- a/widgets/misc/e-filter-bar.h
+++ b/widgets/misc/e-filter-bar.h
@@ -95,7 +95,6 @@ enum {
 
 	/* preset option options */
 	E_FILTERBAR_ADVANCED_ID = -5,
-	E_FILTERBAR_CURRENT_MESSAGE_ID = -6,
 	E_FILTERBAR_CURRENT_FOLDER_ID = -7,
 	E_FILTERBAR_CURRENT_ACCOUNT_ID = -8,
 	E_FILTERBAR_ALL_ACCOUNTS_ID = -9
@@ -107,7 +106,6 @@ enum {
 #define E_FILTERBAR_ALL_ACCOUNTS { N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID, ESB_ITEMTYPE_RADIO }
 #define E_FILTERBAR_CURRENT_ACCOUNT { N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID, ESB_ITEMTYPE_RADIO }
 #define E_FILTERBAR_CURRENT_FOLDER { N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID, ESB_ITEMTYPE_RADIO }
-#define E_FILTERBAR_CURRENT_MESSAGE { N_("Current Message"), E_FILTERBAR_CURRENT_MESSAGE_ID, ESB_ITEMTYPE_RADIO }
 #define E_FILTERBAR_SEPARATOR { NULL, 0, 0 }
 
 #ifdef JUST_FOR_TRANSLATORS



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]