Index: shell/ev-marshal.list
===================================================================
--- shell/ev-marshal.list	(revision 3330)
+++ shell/ev-marshal.list	(working copy)
@@ -2,3 +2,4 @@
 VOID:OBJECT,OBJECT
 VOID:ENUM,BOOLEAN
 VOID:STRING,STRING
+VOID:POINTER,INT,INT
Index: shell/ev-sidebar-find-results.c
===================================================================
--- shell/ev-sidebar-find-results.c	(revision 0)
+++ shell/ev-sidebar-find-results.c	(revision 0)
@@ -0,0 +1,365 @@
+/* ev-sidebar-find-results.c
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Sergey Pushkin <pushkinsv@gmail.com>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+
+#include "ev-sidebar-find-results.h"
+#include "ev-marshal.h"
+#include "ev-sidebar-page.h"
+
+struct _EvSidebarFindResultsPrivate {
+	GtkWidget *tree_view;
+
+	guint selection_id;
+
+	EvJob *job;
+};
+
+enum {
+	PROP_0,
+	PROP_WIDGET,
+};
+
+enum {
+	FIND_RESULT_ACTIVATED,
+	N_SIGNALS
+};
+
+static void ev_sidebar_find_results_page_iface_init 		(EvSidebarPageIface *iface);
+static void ev_sidebar_find_results_set_document      	 	(EvSidebarPage  *sidebar_page,
+		    			        	 EvDocument     *document);
+static gboolean ev_sidebar_find_results_support_document	(EvSidebarPage  *sidebar_page,
+						         EvDocument     *document);
+static const gchar* ev_sidebar_find_results_get_label 		(EvSidebarPage *sidebar_page);
+
+static guint signals[N_SIGNALS];
+
+G_DEFINE_TYPE_EXTENDED (EvSidebarFindResults, 
+                        ev_sidebar_find_results, 
+                        GTK_TYPE_VBOX,
+                        0, 
+                        G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE, 
+					       ev_sidebar_find_results_page_iface_init))
+
+
+#define EV_SIDEBAR_FIND_RESULTS_GET_PRIVATE(object) \
+	(G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_FIND_RESULTS, EvSidebarFindResultsPrivate))
+
+static void
+ev_sidebar_find_results_get_property (GObject    *object,
+			       guint       prop_id,
+			       GValue     *value,
+			       GParamSpec *pspec)
+{
+	EvSidebarFindResults *ev_sidebar_find_results;
+  
+	ev_sidebar_find_results = EV_SIDEBAR_FIND_RESULTS (object);
+
+	switch (prop_id)
+	{
+	case PROP_WIDGET:
+		g_value_set_object (value, ev_sidebar_find_results->priv->tree_view);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+
+static void
+ev_sidebar_find_results_dispose (GObject *object)
+{
+	EvSidebarFindResults *sidebar = EV_SIDEBAR_FIND_RESULTS (object);
+
+	if (sidebar->priv->job) {
+		g_object_unref (sidebar->priv->job);
+		sidebar->priv->job = NULL;
+	}
+
+
+	G_OBJECT_CLASS (ev_sidebar_find_results_parent_class)->dispose (object);
+}
+
+static void
+ev_sidebar_find_results_map (GtkWidget *widget)
+{
+	EvSidebarFindResults *find_results;
+
+	find_results = EV_SIDEBAR_FIND_RESULTS (widget);
+
+	GTK_WIDGET_CLASS (ev_sidebar_find_results_parent_class)->map (widget);
+
+}
+
+static void
+ev_sidebar_find_results_class_init (EvSidebarFindResultsClass *sidebar_find_results_class)
+{
+	GObjectClass   *g_object_class;
+	GtkWidgetClass *widget_class;
+
+	g_object_class = G_OBJECT_CLASS (sidebar_find_results_class);
+	widget_class = GTK_WIDGET_CLASS (sidebar_find_results_class);
+
+	g_object_class->get_property = ev_sidebar_find_results_get_property;
+	g_object_class->dispose = ev_sidebar_find_results_dispose;
+
+	widget_class->map = ev_sidebar_find_results_map;
+
+	signals[FIND_RESULT_ACTIVATED] = g_signal_new ("find-result-activated",
+			 G_TYPE_FROM_CLASS (g_object_class),
+		         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		         G_STRUCT_OFFSET (EvSidebarFindResultsClass, find_result_activated),
+		         NULL, NULL,
+		         ev_marshal_VOID__POINTER_INT_INT,
+		         G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT);
+
+	g_object_class_override_property (g_object_class,
+					  PROP_WIDGET,
+					  "main-widget");
+
+	g_type_class_add_private (g_object_class, sizeof (EvSidebarFindResultsPrivate));
+}
+
+static void
+selection_changed_callback (GtkTreeSelection   *selection,
+		            EvSidebarFindResults     *sidebar_find_results)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EvJobFind *job_find;
+
+	job_find=EV_JOB_FIND(sidebar_find_results->priv->job);
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		gint pageno;
+		gint resultno;
+
+		gtk_tree_model_get (model, &iter,
+				    EV_DOCUMENT_FIND_RESULTS_COLUMN_PAGENO, &pageno,
+				    -1);
+		gtk_tree_model_get (model, &iter,
+				    EV_DOCUMENT_FIND_RESULTS_COLUMN_RESULTNO, &resultno,
+				    -1);
+
+		g_signal_emit(sidebar_find_results, signals[FIND_RESULT_ACTIVATED], 0, job_find, pageno-1, resultno);
+	}
+}
+
+static gboolean
+focus_out_cb (GtkWidget *treeview,
+                 GdkEventButton *event,
+                 EvSidebarFindResults *sidebar_find_results)
+{
+	g_signal_emit(sidebar_find_results, signals[FIND_RESULT_ACTIVATED], 0, NULL, 0, 0);
+	return FALSE;
+}
+
+static gboolean
+focus_in_cb (GtkWidget *treeview,
+                 GdkEventButton *event,
+                 EvSidebarFindResults *sidebar_find_results)
+{
+	GtkTreeSelection *selection;
+	EvSidebarFindResultsPrivate *priv;
+	priv = sidebar_find_results->priv;
+
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
+	selection_changed_callback(selection,sidebar_find_results);
+	return FALSE;
+}
+
+
+
+
+static void
+ev_sidebar_find_results_construct (EvSidebarFindResults *ev_sidebar_find_results)
+{
+	EvSidebarFindResultsPrivate *priv;
+	GtkWidget *swindow;
+	GtkTreeViewColumn *column;
+	GtkCellRenderer *renderer;
+
+	priv = ev_sidebar_find_results->priv;
+
+	swindow = gtk_scrolled_window_new (NULL, NULL);
+
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
+					     GTK_SHADOW_IN);
+
+	priv->tree_view = gtk_tree_view_new_with_model (NULL);
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
+	gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
+
+	gtk_box_pack_start (GTK_BOX (ev_sidebar_find_results), swindow, TRUE, TRUE, 0);
+	gtk_widget_show_all (GTK_WIDGET (ev_sidebar_find_results));
+
+	column = gtk_tree_view_column_new ();
+	gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (column), TRUE);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (priv->tree_view), column);
+
+	renderer = (GtkCellRenderer*)
+		g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
+			      "ellipsize", PANGO_ELLIPSIZE_END,
+			      NULL);
+	gtk_tree_view_column_pack_start (GTK_TREE_VIEW_COLUMN (column), renderer, TRUE);
+	gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+					     "markup", EV_DOCUMENT_FIND_RESULTS_COLUMN_TEXT,
+					     NULL);
+
+	
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_end (GTK_TREE_VIEW_COLUMN (column), renderer, FALSE);
+	gtk_tree_view_column_set_attributes (GTK_TREE_VIEW_COLUMN (column), renderer,
+					     "text", EV_DOCUMENT_FIND_RESULTS_COLUMN_PAGENO,
+					     NULL);
+	g_object_set (G_OBJECT (renderer), "style", PANGO_STYLE_ITALIC, NULL);
+
+	g_signal_connect (GTK_TREE_VIEW (priv->tree_view),
+			  "focus_out_event",
+			  G_CALLBACK (focus_out_cb),
+			  ev_sidebar_find_results);
+	g_signal_connect (GTK_TREE_VIEW (priv->tree_view),
+			  "focus_in_event",
+			  G_CALLBACK (focus_in_cb),
+			  ev_sidebar_find_results);
+
+	priv->selection_id = g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view)), "changed",
+					  G_CALLBACK (selection_changed_callback),
+					  ev_sidebar_find_results);
+}
+
+static void
+ev_sidebar_find_results_init (EvSidebarFindResults *ev_sidebar_find_results)
+{
+	ev_sidebar_find_results->priv = EV_SIDEBAR_FIND_RESULTS_GET_PRIVATE (ev_sidebar_find_results);
+
+	ev_sidebar_find_results_construct (ev_sidebar_find_results);
+}
+
+/* Public Functions */
+
+GtkWidget *
+ev_sidebar_find_results_new (void)
+{
+	GtkWidget *ev_sidebar_find_results;
+
+	ev_sidebar_find_results = g_object_new (EV_TYPE_SIDEBAR_FIND_RESULTS, NULL);
+
+	return ev_sidebar_find_results;
+}
+
+
+void
+find_result_activate_result(EvSidebarFindResults *sidebar_find_results,
+			    gpointer results,
+			    gint pageno,
+			    gint resultno)
+{
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	EvSidebarFindResultsPrivate *priv;
+	EvJobFind *job_find;
+	gint i,index;
+	GtkTreePath *path;
+
+	/* Widget is not currently visible */
+	if (!GTK_WIDGET_MAPPED (sidebar_find_results))
+		return;
+
+	priv = sidebar_find_results->priv;
+	if (priv->job==NULL) return;
+	job_find=EV_JOB_FIND(priv->job);
+	if (ev_job_find_get_n_results(job_find,pageno)==0) return;
+
+	
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar_find_results->priv->tree_view));
+
+	if (gtk_tree_selection_get_selected (selection, &model, &iter))
+	{
+		gint page;
+
+		gtk_tree_model_get (model, &iter,
+				    EV_DOCUMENT_FIND_RESULTS_COLUMN_PAGENO, &page,
+				    -1);
+	};
+
+	index=resultno;
+	for (i=0;i<pageno;i++)
+		index+=ev_job_find_get_n_results(job_find,i);
+
+	path=gtk_tree_path_new_from_indices(index,-1);
+	g_signal_handler_block (selection, sidebar_find_results->priv->selection_id);
+	gtk_tree_view_set_cursor(GTK_TREE_VIEW(priv->tree_view),path,NULL,FALSE);
+	g_signal_handler_unblock (selection, sidebar_find_results->priv->selection_id);
+	gtk_tree_path_free(path);
+
+	
+}
+
+static void
+ev_sidebar_find_results_set_document (EvSidebarPage  *sidebar_page,
+			       EvDocument     *document)
+{
+}
+
+void
+ev_sidebar_find_results_update (EvSidebarFindResults  *sidebar_find_results,
+			    EvJobFind *job_find)
+{
+	EvSidebarFindResultsPrivate *priv;
+
+	priv = sidebar_find_results->priv;
+
+	if (priv->job) g_object_unref(priv->job);
+	priv->job=g_object_ref(job_find);
+
+	gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), job_find->model);
+}
+
+static gboolean
+ev_sidebar_find_results_support_document (EvSidebarPage  *sidebar_page,
+				   EvDocument *document)
+{
+	return TRUE;
+}
+
+static const gchar*
+ev_sidebar_find_results_get_label (EvSidebarPage *sidebar_page)
+{
+	return _("Find results");
+}
+
+static void
+ev_sidebar_find_results_page_iface_init (EvSidebarPageIface *iface)
+{
+	iface->support_document = ev_sidebar_find_results_support_document;
+	iface->set_document = ev_sidebar_find_results_set_document;
+	iface->get_label = ev_sidebar_find_results_get_label;
+}
+
+
Index: shell/ev-sidebar-find-results.h
===================================================================
--- shell/ev-sidebar-find-results.h	(revision 0)
+++ shell/ev-sidebar-find-results.h	(revision 0)
@@ -0,0 +1,72 @@
+/* ev-sidebar-find-results.h
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Sergey Pushkin <pushkinsv@gmail.com>
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EV_SIDEBAR_FIND_RESULTS_H__
+#define __EV_SIDEBAR_FIND_RESULTS_H__
+
+#include <gtk/gtk.h>
+
+#include "ev-jobs.h"
+
+G_BEGIN_DECLS
+
+typedef struct _EvSidebarFindResults EvSidebarFindResults;
+typedef struct _EvSidebarFindResultsClass EvSidebarFindResultsClass;
+typedef struct _EvSidebarFindResultsPrivate EvSidebarFindResultsPrivate;
+
+#define EV_TYPE_SIDEBAR_FIND_RESULTS		   (ev_sidebar_find_results_get_type())
+#define EV_SIDEBAR_FIND_RESULTS(object)	   (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_SIDEBAR_FIND_RESULTS, EvSidebarFindResults))
+#define EV_SIDEBAR_FIND_RESULTS_CLASS(klass)	   (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_SIDEBAR_FIND_RESULTS, EvSidebarFindResultsClass))
+#define EV_IS_SIDEBAR_FIND_RESULTS(object)	   (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_SIDEBAR_FIND_RESULTS))
+#define EV_IS_SIDEBAR_FIND_RESULTS_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE((klass), EV_TYPE_SIDEBAR_FIND_RESULTS))
+#define EV_SIDEBAR_FIND_RESULTS_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), EV_TYPE_SIDEBAR_FIND_RESULTS, EvSidebarFindResultsClass))
+
+enum {
+	EV_DOCUMENT_FIND_RESULTS_COLUMN_TEXT,
+	EV_DOCUMENT_FIND_RESULTS_COLUMN_PAGENO,
+	EV_DOCUMENT_FIND_RESULTS_COLUMN_RESULTNO
+};
+
+struct _EvSidebarFindResults {
+	GtkVBox base_instance;
+
+	EvSidebarFindResultsPrivate *priv;
+};
+
+struct _EvSidebarFindResultsClass {
+	GtkVBoxClass base_class;
+
+	void    (* find_result_activated) (EvSidebarFindResults *sidebar_find_results);
+};
+
+GType      ev_sidebar_find_results_get_type       (void);
+GtkWidget *ev_sidebar_find_results_new            (void);
+
+void ev_sidebar_find_results_update (EvSidebarFindResults  *sidebar_find_results,
+				 EvJobFind *job_find);
+void
+find_result_activate_result(EvSidebarFindResults *sidebar_find_results,
+			    gpointer results,
+			    gint pageno,
+			    gint resultno);
+
+G_END_DECLS
+
+#endif /* __EV_SIDEBAR_FIND_RESULTS_H__ */
Index: shell/ev-jobs.c
===================================================================
--- shell/ev-jobs.c	(revision 3330)
+++ shell/ev-jobs.c	(working copy)
@@ -1070,6 +1070,140 @@
 }
 
 /* EvJobFind */
+static void split_line(gchar *line, glong pos2, glong pos3, gchar **prec, gchar **occ, gchar **succ)
+{
+	glong pos1=pos2;
+	glong pos4=g_utf8_strlen(line,-1);
+
+
+	while (pos1>0 && !g_unichar_isspace(g_utf8_get_char(g_utf8_offset_to_pointer(line,pos1)))) pos1--;
+	while (pos1>0 && g_unichar_isspace(g_utf8_get_char(g_utf8_offset_to_pointer(line,pos1)))) pos1--;
+	while (pos1>0 && !g_unichar_isspace(g_utf8_get_char(g_utf8_offset_to_pointer(line,pos1)))) pos1--;
+	while (pos1<pos2 && g_unichar_isspace(g_utf8_get_char(g_utf8_offset_to_pointer(line,pos1)))) pos1++;
+
+	*occ=g_utf8_strncpy(
+		g_strnfill(g_utf8_offset_to_pointer(line,pos3)-g_utf8_offset_to_pointer(line,pos2)+1,0),
+		g_utf8_offset_to_pointer(line,pos2),
+		pos3-pos2
+	);
+	*prec=g_utf8_strncpy(
+		g_strnfill(g_utf8_offset_to_pointer(line,pos2)-g_utf8_offset_to_pointer(line,pos1)+1,0),
+		g_utf8_offset_to_pointer(line,pos1),
+		pos2-pos1				
+	);
+	*succ=g_utf8_strncpy(
+		g_strnfill(g_utf8_offset_to_pointer(line,pos4)-g_utf8_offset_to_pointer(line,pos3)+1,0),
+		g_utf8_offset_to_pointer(line,pos3),
+		pos4-pos3
+	);
+}
+
+static void add_current_page_to_model(EvJob *job)
+{
+	EvJobFind *job_find;
+	GtkTreeIter iter;
+	gint total_matches=0;
+	gint i,j;
+	EvRectangle r;
+	EvRenderContext *rc;
+	EvPage *page;
+	gchar *occ;
+
+	job_find = EV_JOB_FIND (job);
+
+	if (ev_job_find_get_n_results(job_find,job_find->current_page)==0) return;
+
+	rc = ev_render_context_new (NULL, 0, 1.0f);
+
+	i=job_find->current_page;
+
+	page = ev_document_get_page (job->document, job_find->current_page);
+	ev_render_context_set_page (rc, page);
+	g_object_unref(page);
+
+	total_matches+=ev_job_find_get_n_results(job_find,i);
+	GList  *matches=job_find->pages[i];
+	gint k;
+	gint occno=0;
+	/* for each match on the page */
+	for (j=0;j<g_list_length(matches);j++)
+	{
+		gchar *prec, *succ;
+		r=*(EvRectangle*)g_list_nth_data(matches,j);
+		r.y1=r.y2=(r.y1+r.y2)/2;
+		r.x1=r.x2=(r.x1+r.x2)/2;
+
+		/* get line than contains match and normalize it */
+		gchar *tmp=ev_selection_get_selected_text(EV_SELECTION(job->document),rc,EV_SELECTION_STYLE_LINE,&r);
+		gchar *line=g_utf8_normalize(tmp,-1,G_NORMALIZE_ALL);
+		g_free(tmp);
+		g_assert(line);
+
+		/* for case insensitive search fold case in both line and text */
+		gchar *line_folded=line;
+		gchar *text_folded=job_find->text;
+		if (!job_find->case_sensitive)
+		{
+			line_folded=g_utf8_strdown(line,-1);
+			text_folded=g_utf8_strdown(job_find->text,-1);
+		};
+
+		/* now search the proper occurrence of text in the line */
+		occ=line_folded;
+		tmp=occ;
+		occno++;
+		for (k=0;k<occno;k++)
+		{
+			tmp=g_strstr_len(tmp,-1,text_folded);
+			if (tmp==NULL) break;
+			occ=tmp;
+			if (*tmp) tmp=g_utf8_find_next_char(tmp,NULL);
+		};
+		if (tmp==NULL)
+		{
+			occno=1;
+			occ=g_strstr_len(line_folded,-1,text_folded);
+		};
+
+		/* get character positions for beginning and ending of search text
+		 * (assuming that they are the same for folded and original lines) */
+		glong pos2=g_utf8_pointer_to_offset(line_folded,occ);
+		glong pos3=pos2+g_utf8_strlen(job_find->text,-1);
+
+		/* get line to display in the find results list nicely formatted */
+		split_line(line,pos2,pos3,&prec,&occ,&succ);
+		gchar *markup = g_markup_printf_escaped("%s<span weight=\"bold\">%s</span>%s",prec,occ,succ);
+
+
+		/* insert line into proper position in the list */
+		if (job_find->current_page>=job_find->start_page)
+			gtk_list_store_append(GTK_LIST_STORE (job_find->model), &iter);
+		else
+		{
+			gtk_list_store_insert(GTK_LIST_STORE (job_find->model), &iter, job_find->insert_position);
+			job_find->insert_position++;
+		};
+		gtk_list_store_set (GTK_LIST_STORE (job_find->model), &iter,
+				    0, markup,
+				    1, i+1,
+				    2, j,
+				    -1);
+
+		g_free(occ);
+		g_free(succ);
+		g_free(prec);
+		g_free(markup);
+		if (!job_find->case_sensitive)
+		{
+			g_free(line_folded);
+			g_free(text_folded);
+		};
+		g_free(line);
+
+	};
+
+}
+
 static void
 ev_job_find_init (EvJobFind *job)
 {
@@ -1099,7 +1233,14 @@
 		g_free (job->pages);
 		job->pages = NULL;
 	}
-	
+
+	if (job->model)
+	{
+		gtk_list_store_clear(GTK_LIST_STORE(job->model));
+		g_object_unref(job->model);
+		job->model = NULL;
+	};
+
 	(* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
 }
 
@@ -1134,6 +1275,7 @@
 		job_find->has_results = (matches != NULL);
 
 	job_find->pages[job_find->current_page] = matches;
+	add_current_page_to_model(job);
 	g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
 		       
 	job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
@@ -1188,6 +1330,11 @@
 	job->case_sensitive = case_sensitive;
 	job->has_results = FALSE;
 
+	job->model = (GtkTreeModel *)gtk_list_store_new (3,
+						     G_TYPE_STRING,
+						     G_TYPE_INT,
+						     G_TYPE_INT);
+	job->insert_position=0;
 	return EV_JOB (job);
 }
 
Index: shell/ev-jobs.h
===================================================================
--- shell/ev-jobs.h	(revision 3330)
+++ shell/ev-jobs.h	(working copy)
@@ -296,6 +296,9 @@
 	gchar *text;
 	gboolean case_sensitive;
 	gboolean has_results;
+
+	GtkTreeModel *model;
+	gint insert_position;
 };
 
 struct _EvJobFindClass
Index: shell/ev-window.c
===================================================================
--- shell/ev-window.c	(revision 3330)
+++ shell/ev-window.c	(working copy)
@@ -78,6 +78,7 @@
 #include "ev-properties-dialog.h"
 #include "ev-sidebar-attachments.h"
 #include "ev-sidebar.h"
+#include "ev-sidebar-find-results.h"
 #include "ev-sidebar-links.h"
 #include "ev-sidebar-page.h"
 #include "ev-sidebar-thumbnails.h"
@@ -138,6 +139,7 @@
 	GtkWidget *password_view;
 	GtkWidget *sidebar_thumbs;
 	GtkWidget *sidebar_links;
+	GtkWidget *sidebar_find_results;
 	GtkWidget *sidebar_attachments;
 	GtkWidget *sidebar_layers;
 
@@ -221,6 +223,7 @@
 #define PRESENTATION_TIMEOUT 5
 
 #define SIDEBAR_DEFAULT_SIZE    132
+#define FIND_RESULTS_SIDEBAR_ID "find_results"
 #define LINKS_SIDEBAR_ID "links"
 #define THUMBNAILS_SIDEBAR_ID "thumbnails"
 #define ATTACHMENTS_SIDEBAR_ID "attachments"
@@ -747,6 +750,40 @@
 		ev_metadata_manager_set_int (ev_window->priv->uri, "page", page);
 }
 
+static void
+ev_view_find_result_hilight_changed_cb(EvView *view,
+		      gpointer find_result,
+		      gint page,
+		      gint result,
+		      EvWindow *window)
+{
+
+	find_result_activate_result(EV_SIDEBAR_FIND_RESULTS(window->priv->sidebar_find_results),find_result,page,result);
+	
+}
+
+static void
+sidebar_find_results_find_result_activated_cb (EvSidebarFindResults *sidebar_find_results, EvJobFind *job, gint pageno, gint resultno, EvWindow *window)
+{
+	if (window->priv->view==NULL) return;
+	if (GTK_WIDGET_VISIBLE (window->priv->find_bar)) return;
+	if (job==NULL)
+	{
+		ev_view_find_changed (EV_VIEW (window->priv->view), NULL, 0);
+		ev_view_find_set_highlight_search (EV_VIEW (window->priv->view), FALSE);
+		
+	}
+	else
+	{
+		ev_view_find_changed (EV_VIEW (window->priv->view),
+				      ev_job_find_get_results (job),
+			      pageno);
+		ev_view_find_set_highlight_search (EV_VIEW (window->priv->view), TRUE);
+		ev_view_find_arbitrary(EV_VIEW(window->priv->view),pageno,resultno);
+	};
+
+}
+
 typedef struct _FindTask {
 	const gchar *page_label;
 	gchar *chapter;
@@ -918,6 +955,7 @@
 	char *uri = window->priv->uri;
 	GtkWidget *sidebar = window->priv->sidebar;
 	GtkWidget *links = window->priv->sidebar_links;
+	GtkWidget *find_results = window->priv->sidebar_find_results;
 	GtkWidget *thumbs = window->priv->sidebar_thumbs;
 	GtkWidget *attachments = window->priv->sidebar_attachments;
 	GtkWidget *layers = window->priv->sidebar_layers;
@@ -936,6 +974,8 @@
 
 		if (strcmp (page_id, LINKS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
 			ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
+		} else if (strcmp (page_id, FIND_RESULTS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (find_results), document)) {
+			ev_sidebar_set_page (EV_SIDEBAR (sidebar), find_results);
 		} else if (strcmp (page_id, THUMBNAILS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
 			ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
 		} else if (strcmp (page_id, ATTACHMENTS_SIDEBAR_ID) == 0 && ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
@@ -947,6 +987,8 @@
 	} else if (document) {
 		if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (links), document)) {
 			ev_sidebar_set_page (EV_SIDEBAR (sidebar), links);
+		} else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (find_results), document)) {
+			ev_sidebar_set_page (EV_SIDEBAR (sidebar), find_results);
 		} else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (thumbs), document)) {
 			ev_sidebar_set_page (EV_SIDEBAR (sidebar), thumbs);
 		} else if (ev_sidebar_page_support_document (EV_SIDEBAR_PAGE (attachments), document)) {
@@ -4334,6 +4376,8 @@
 
 	if (current_page == ev_window->priv->sidebar_links) {
 		id = LINKS_SIDEBAR_ID;
+	} else if (current_page == ev_window->priv->sidebar_find_results) {
+		id = FIND_RESULTS_SIDEBAR_ID;
 	} else if (current_page == ev_window->priv->sidebar_thumbs) {
 		id = THUMBNAILS_SIDEBAR_ID;
 	} else if (current_page == ev_window->priv->sidebar_attachments) {
@@ -4530,6 +4574,7 @@
 				EvWindow  *ev_window)
 {
 	ev_window_update_find_status_message (ev_window);
+	ev_sidebar_find_results_update(EV_SIDEBAR_FIND_RESULTS(ev_window->priv->sidebar_find_results),EV_JOB_FIND (ev_window->priv->find_job));
 }
 
 static void
@@ -4543,6 +4588,7 @@
 			      ev_job_find_get_results (job),
 			      page);
 	ev_window_update_find_status_message (ev_window);
+	ev_sidebar_find_results_update(EV_SIDEBAR_FIND_RESULTS(ev_window->priv->sidebar_find_results),job);
 }
 
 static void
@@ -5103,6 +5149,8 @@
 	ev_view_handle_link (EV_VIEW (window->priv->view), link);
 }
 
+
+
 static void
 activate_link_cb (EvPageAction *page_action, EvLink *link, EvWindow *window)
 {
@@ -6040,6 +6088,17 @@
 	ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
 			     sidebar_widget);
 
+	sidebar_widget = ev_sidebar_find_results_new ();
+	ev_window->priv->sidebar_find_results = sidebar_widget;
+	g_signal_connect (sidebar_widget,
+			  "notify::model",
+			  G_CALLBACK (sidebar_widget_model_set),
+			  ev_window);
+	sidebar_page_main_widget_update_cb (G_OBJECT (sidebar_widget), NULL, ev_window);
+	gtk_widget_show (sidebar_widget);
+	ev_sidebar_add_page (EV_SIDEBAR (ev_window->priv->sidebar),
+			     sidebar_widget);
+
 	ev_window->priv->view_box = gtk_vbox_new (FALSE, 0);
 	ev_window->priv->scrolled_window =
 		GTK_WIDGET (g_object_new (GTK_TYPE_SCROLLED_WINDOW,
@@ -6088,6 +6147,14 @@
 			  ev_window->priv->find_bar,
 			  FALSE, TRUE, 0);
 
+	/* Find results sidebar */ 
+	g_signal_connect (ev_window->priv->sidebar_find_results,
+			  "find-result-activated",
+			  G_CALLBACK (sidebar_find_results_find_result_activated_cb),
+			  ev_window);
+	g_signal_connect (ev_window->priv->view, "find-result-hilight-changed",
+			  G_CALLBACK (ev_view_find_result_hilight_changed_cb), ev_window);
+
 	/* We own a ref on these widgets, as we can swap them in and out */
 	g_object_ref (ev_window->priv->view);
 	g_object_ref (ev_window->priv->password_view);
Index: shell/ev-view.c
===================================================================
--- shell/ev-view.c	(revision 3330)
+++ shell/ev-view.c	(working copy)
@@ -64,6 +64,7 @@
 	SIGNAL_HANDLE_LINK,
 	SIGNAL_EXTERNAL_LINK,
 	SIGNAL_POPUP_MENU,
+	SIGNAL_FIND_RESULT_HILIGHT_CHANGED,
 	N_SIGNALS,
 };
 
@@ -4028,6 +4029,14 @@
 		         g_cclosure_marshal_VOID__OBJECT,
 		         G_TYPE_NONE, 1,
 			 G_TYPE_OBJECT);
+	signals[SIGNAL_FIND_RESULT_HILIGHT_CHANGED] = g_signal_new ("find-result-hilight-changed",
+	  	         G_TYPE_FROM_CLASS (object_class),
+		         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+		         0,
+		         NULL, NULL,
+		         ev_marshal_VOID__POINTER_INT_INT,
+		         G_TYPE_NONE, 3,
+			 G_TYPE_POINTER, G_TYPE_INT, G_TYPE_INT);
 
 
 	g_object_class_install_property (object_class,
@@ -4265,6 +4274,8 @@
 	}
 
 	view->find_result = 0;
+
+	g_signal_emit(view,signals[SIGNAL_FIND_RESULT_HILIGHT_CHANGED],0,view->find_pages,new_page,view->find_result);
 }
 
 static void
@@ -5103,6 +5114,8 @@
 		ensure_rectangle_is_visible (view, &view_rect);
 		view->jump_to_find_result = FALSE;
 	}
+
+	g_signal_emit(view,signals[SIGNAL_FIND_RESULT_HILIGHT_CHANGED],0,view->find_pages,page,view->find_result);
 }
 
 /**
@@ -5146,6 +5159,7 @@
 void
 ev_view_find_changed (EvView *view, GList **results, gint page)
 {
+
 	view->find_pages = results;
 	
 	if (view->jump_to_find_result == TRUE) {
@@ -5191,6 +5205,15 @@
 }
 
 void
+ev_view_find_arbitrary (EvView *view, gint page, gint result)
+{
+	ev_page_cache_set_current_page (view->page_cache, page);
+	view->find_result=result;
+	jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0);
+	jump_to_find_result (view);
+}
+
+void
 ev_view_find_search_changed (EvView *view)
 {
 	/* search string has changed, focus on new search result */
Index: shell/ev-view.h
===================================================================
--- shell/ev-view.h	(revision 3330)
+++ shell/ev-view.h	(working copy)
@@ -108,6 +108,9 @@
 /* Find */
 void            ev_view_find_next                 (EvView         *view);
 void            ev_view_find_previous             (EvView         *view);
+void            ev_view_find_arbitrary            (EvView         *view,
+						   gint            page,
+						   gint            result);
 void            ev_view_find_search_changed       (EvView         *view);
 void     	ev_view_find_set_highlight_search (EvView         *view,
 						   gboolean        value);
Index: shell/Makefile.am
===================================================================
--- shell/Makefile.am	(revision 3330)
+++ shell/Makefile.am	(working copy)
@@ -86,6 +86,8 @@
 	ev-sidebar.h			\
 	ev-sidebar-attachments.c	\
 	ev-sidebar-attachments.h	\
+	ev-sidebar-find-results.c	\
+	ev-sidebar-find-results.h	\
 	ev-sidebar-layers.c		\
 	ev-sidebar-layers.h		\
 	ev-sidebar-links.c		\
Index: po/ru.po
===================================================================
--- po/ru.po	(revision 3330)
+++ po/ru.po	(working copy)
@@ -1128,6 +1128,11 @@
 msgid "Make the current document fill the window width"
 msgstr "Масштабировать документ для соответствия ширине окна"
 
+#. Find results
+#: ../shell/ev-sidebar-find-results.c:362
+msgid "Find results"
+msgstr "Результаты поиска"
+
 #. Links
 #: ../shell/ev-window.c:4567
 msgid "_Open Link"
