diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c
index 424db0d..411e697 100644
--- a/calendar/gui/cal-search-bar.c
+++ b/calendar/gui/cal-search-bar.c
@@ -416,18 +416,25 @@ notify_e_cal_view_contains (CalSearchBar *cal_search, const gchar *field, const
 		return; /* This is an error in the UTF8 conversion, not an empty string! */
 
 	if (text && *text)
-	    sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text);
+		sexp = g_strdup_printf ("(contains? \"%s\" \"%s\")", field, text);
 	else
-	    sexp = g_strdup ("(contains? \"summary\" \"\")"); /* Show all */
+		sexp = NULL; /* Show all */
 
 	g_free (text);
 
 	/* Apply the selected view on search */
-	if (view && *view){
-	    sexp = g_strconcat ("(and ",sexp, view, ")", NULL);
+	if (view && *view) {
+		gchar *tmp = sexp;
+
+		if (sexp)
+			sexp = g_strconcat ("(and ", sexp, view, ")", NULL);
+		else
+			sexp = g_strdup (view);
+
+		g_free (tmp);
 	}
 
-	notify_sexp_changed (cal_search, sexp);
+	notify_sexp_changed (cal_search, sexp ? sexp : "#t");
 
 	g_free (sexp);
 }
diff --git a/calendar/gui/goto-dialog.glade b/calendar/gui/goto-dialog.glade
index aeed7ae..eb82348 100644
--- a/calendar/gui/goto-dialog.glade
+++ b/calendar/gui/goto-dialog.glade
@@ -122,8 +122,8 @@ December</property>
 	    </widget>
 	    <packing>
 	      <property name="padding">0</property>
-	      <property name="expand">True</property>
-	      <property name="fill">True</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
 	    </packing>
 	  </child>
 
diff --git a/calendar/gui/goto.c b/calendar/gui/goto.c
index 06986ef..1725b1f 100644
--- a/calendar/gui/goto.c
+++ b/calendar/gui/goto.c
@@ -27,13 +27,40 @@
 #include <config.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
+#include <glib/gi18n.h>
+#include <libecal/e-cal-time-util.h>
+#include "e-util/e-dialog-utils.h"
 #include "e-util/e-util-private.h"
 #include "calendar-commands.h"
 #include "calendar-config.h"
 #include "tag-calendar.h"
 #include "goto.h"
 
-typedef struct
+struct _GoToDialog;
+
+struct goto_search_found_data
+{
+	time_t start, end; 	/* when the item starts and ends */
+};
+
+struct goto_search_thread_data
+{
+	struct _GoToDialog *dlg; /* is set to NULL when thread should stop fully */
+	gboolean cancel;         /* cancel active searching */
+	gboolean search_next;    /* direction of searching */
+	gint year, month;        /* which year/month start searching */
+	gint min_year, max_year; /* bounds for a year search */
+
+	GCond *cond;		 /* triggered when it should do something */
+	GMutex *mutex;		 /* used with a cond and dlg members */
+
+	GSList *found;		 /* s-list of goto_search_found_data structures;
+				    if not NULL, year/month is set to the proper date;
+				    free each element with g_free and list itself with g_slist_free */
+	guint finished_id;       /* source id of a notification of search finish */
+};
+
+struct _GoToDialog
 {
 	GladeXML *xml;
 	GtkWidget *dialog;
@@ -43,12 +70,23 @@ typedef struct
 	ECalendar *ecal;
 	GtkWidget *vbox;
 
+	GtkWidget *sprev;
+	GtkWidget *snext;
+	GtkWidget *stop;
+
 	GnomeCalendar *gcal;
 	gint year_val;
 	gint month_val;
 	gint day_val;
 
-} GoToDialog;
+	struct goto_search_thread_data *search_data; /* this frees thread itself */
+
+	GSList *found;		 /* s-list of goto_search_found_data structures;
+				    if not NULL, year/month is set to the proper date;
+				    free each element with g_free and list itself with g_slist_free */
+};
+
+typedef struct _GoToDialog GoToDialog;
 
 static GoToDialog *dlg = NULL;
 
@@ -74,11 +112,42 @@ month_changed (GtkToggleButton *toggle, gpointer data)
 }
 
 static void
+tag_calendar (struct goto_search_found_data *fd, ECalendarItem *calitem)
+{
+	icaltimezone *zone;
+	struct icaltimetype start_tt, end_tt;
+
+	g_return_if_fail (fd != NULL);
+	g_return_if_fail (calitem != NULL);
+
+	zone = calendar_config_get_icaltimezone ();
+	start_tt = icaltime_from_timet_with_zone (fd->start, FALSE, zone);
+	end_tt = icaltime_from_timet_with_zone (fd->end - 1, FALSE, zone);
+	e_calendar_item_mark_days (calitem,
+				   start_tt.year, start_tt.month - 1,
+				   start_tt.day,
+				   end_tt.year, end_tt.month - 1,
+				   end_tt.day,
+				   E_CALENDAR_ITEM_MARK_BOLD);
+}
+
+static void
 ecal_date_range_changed (ECalendarItem *calitem, gpointer user_data)
 {
 	GoToDialog *dlg = user_data;
 	ECal *client;
 
+	/* use found days for tagging when finished a search */
+	if (dlg->found) {
+		e_calendar_item_clear_marks (dlg->ecal->calitem);
+		g_slist_foreach (dlg->found, (GFunc) tag_calendar, dlg->ecal->calitem);
+		g_slist_foreach (dlg->found, (GFunc) g_free, NULL);
+		g_slist_free (dlg->found);
+		dlg->found = NULL;
+		return;
+	}
+
+	/* otherwise tag with a default client only */
 	client = gnome_calendar_get_default_client (dlg->gcal);
 	if (client)
 		tag_calendar_by_client (dlg->ecal, client);
@@ -133,6 +202,282 @@ get_current_time (ECalendarItem *calitem, gpointer data)
 	return tmp_tm;
 }
 
+static gboolean
+search_finished_cb (gpointer pdata)
+{
+	/* uses rather the global 'dlg' pointer */
+	if (!dlg || !dlg->search_data)
+		return FALSE;
+
+	g_mutex_lock (dlg->search_data->mutex);
+	gtk_widget_set_sensitive (dlg->sprev, TRUE);
+	gtk_widget_set_sensitive (dlg->snext, TRUE);
+	gtk_widget_set_sensitive (dlg->stop, FALSE);
+
+	if (dlg->search_data->found) {
+		gtk_combo_box_set_active (GTK_COMBO_BOX (dlg->month_combobox), dlg->search_data->month - 1);
+		gtk_spin_button_set_value (GTK_SPIN_BUTTON (dlg->year), dlg->search_data->year);
+
+		dlg->found = dlg->search_data->found;
+		dlg->search_data->found = NULL;
+	} else if (!dlg->search_data->cancel) {
+		e_notice (NULL, GTK_MESSAGE_INFO, "%s", dlg->search_data->search_next ? _("Cannot find any event in the future.") : _("Cannot find any event in the past."));
+	}
+
+	dlg->search_data->finished_id = 0;
+	g_mutex_unlock (dlg->search_data->mutex);
+
+	return FALSE;
+}
+
+static gboolean
+fill_found_data_cb (ECalComponent *comp, time_t instance_start, time_t instance_end, gpointer user_data)
+{
+	gboolean res = TRUE;
+	struct goto_search_thread_data *data = user_data;
+	struct goto_search_found_data *fd = g_new0 (struct goto_search_found_data, 1);
+
+	/* show here all found comps, even those transparent */
+	fd->start = instance_start;
+	fd->end = instance_end;
+
+	data->found = g_slist_append (data->found, fd);
+
+	g_mutex_lock (data->mutex);
+	if (!data->dlg || data->cancel)
+		res = FALSE;
+	g_mutex_unlock (data->mutex);
+
+	return res;
+}
+
+static gpointer
+search_thread_func (gpointer pdata)
+{
+	struct goto_search_thread_data *data = pdata;
+
+	g_return_val_if_fail (data != NULL, NULL);
+
+	g_mutex_lock (data->mutex);
+
+	while (data->dlg) {
+		gchar *sexp;
+		ECalModel *model;
+		GList *clients, *l;
+		gint year, month, inc;
+		icaltimezone *zone = calendar_config_get_icaltimezone ();
+
+		g_cond_wait (data->cond, data->mutex);
+
+		if (!data->dlg)
+			break;
+
+		data->cancel = FALSE;
+		data->found = NULL;
+		year = data->year;
+		month = data->month;
+		inc = (data->search_next ? 1 : -1) * dlg->ecal->calitem->rows * dlg->ecal->calitem->cols;
+
+		model = gnome_calendar_get_calendar_model (data->dlg->gcal);
+		sexp = g_strdup (e_cal_model_get_search_query (model));
+		clients = e_cal_model_get_client_list (model);
+
+		/* do not let them free before done with them */
+		g_list_foreach (clients, (GFunc) g_object_ref, NULL);
+
+		g_mutex_unlock (data->mutex);
+
+		#define check_cancelled()			\
+			g_mutex_lock (data->mutex);		\
+			if (!data->dlg || data->cancel) {	\
+				g_mutex_unlock (data->mutex);	\
+				break;				\
+			}					\
+			g_mutex_unlock (data->mutex);
+
+		month += inc;
+		while (month < 1) {
+			month += 12;
+			year--;
+		}
+		while (month > 12) {
+			month -= 12;
+			year++;
+		}
+
+		while (year >= data->min_year && year <= data->max_year && !data->found) {
+			struct icaltimetype start_tt = icaltime_null_time ();
+			struct icaltimetype end_tt = icaltime_null_time ();
+			time_t start_time, end_time;
+			gchar *query, *iso_start, *iso_end;
+			GList *objects = NULL;
+
+			start_tt.year = year;
+			start_tt.month = month;
+			start_tt.day = 1;
+
+			end_tt.year = year;
+			end_tt.month = month + (inc > 0 ? inc : ((-1) * inc)) - 1;
+			while (end_tt.month > 12) {
+				end_tt.month -= 12;
+				end_tt.year++;
+			}
+			end_tt.day = icaltime_days_in_month (end_tt.month, end_tt.year);
+
+			icaltime_adjust (&end_tt, 1, 0, 0, 0);
+			start_time = icaltime_as_timet_with_zone (start_tt, zone);
+			end_time = icaltime_as_timet_with_zone (end_tt, zone);
+
+			iso_start = isodate_from_time_t (start_time);
+			if (!iso_start)
+				break;
+
+			iso_end = isodate_from_time_t (end_time);
+			if (!iso_end) {
+				g_free (iso_start);
+				break;
+			}
+
+			query = g_strdup_printf ("(and (occur-in-time-range? (make-time \"%s\") (make-time \"%s\")) %s)",
+						 iso_start, iso_end, sexp);
+
+			g_free (iso_start);
+			g_free (iso_end);
+
+			for (l = clients; l; l = l->next) {
+				ECal *cal = l->data;
+				GError *error = NULL;
+
+				check_cancelled ();
+
+				objects = NULL;
+				if (e_cal_get_object_list (cal, query, &objects, &error)) {
+					GList *o;
+
+					check_cancelled ();
+
+					for (o = objects; o; o = o->next) {
+						e_cal_generate_instances_for_object (cal, o->data, start_time, end_time, fill_found_data_cb, data);
+						check_cancelled ();
+					}
+				}
+
+				if (error) {
+					g_message ("%s: Call of e_cal_get_object_list failed: %s", G_STRFUNC, error->message);
+					g_error_free (error);
+				}
+
+				if (objects) {
+					e_cal_free_object_list (objects);
+					objects = NULL;
+				}
+
+				check_cancelled ();
+			}
+
+			if (data->found) {
+				data->year = year;
+				data->month = month;
+			}
+
+			month += inc;
+			while (month < 1) {
+				month += 12;
+				year--;
+			}
+			while (month > 12) {
+				month -= 12;
+				year++;
+			}
+
+			if (objects) {
+				e_cal_free_object_list (objects);
+				objects = NULL;
+			}
+			g_free (query);
+
+			check_cancelled ();
+		}
+
+		#undef check_cancelled
+
+		g_mutex_lock (data->mutex);
+
+		g_list_foreach (clients, (GFunc) g_object_unref, NULL);
+		g_list_free (clients);
+		g_free (sexp);
+
+		data->finished_id = g_idle_add (search_finished_cb, NULL);
+	}
+
+	if (data->finished_id)
+		g_source_remove (data->finished_id);
+	data->finished_id = 0;
+
+	g_mutex_unlock (data->mutex);
+
+	g_mutex_free (data->mutex);
+	g_cond_free (data->cond);
+	if (data->found) {
+		g_slist_foreach (data->found, (GFunc) g_free, NULL);
+		g_slist_free (data->found);
+	}
+
+	g_free (data);
+
+	return NULL;
+}
+
+static void
+find_event_cb (GtkWidget *button, GoToDialog *dlg)
+{
+	g_return_if_fail (button != NULL);
+	g_return_if_fail (dlg != NULL);
+
+	if (!dlg->search_data) {
+		gdouble min_y = 0.0, max_y = 0.0;
+
+		gtk_spin_button_get_range (GTK_SPIN_BUTTON (dlg->year), &min_y, &max_y);
+
+		/* first invocation of a search, create a thread */
+		dlg->search_data = g_new0 (struct goto_search_thread_data, 1);
+		dlg->search_data->dlg = dlg;
+		dlg->search_data->cond = g_cond_new ();
+		dlg->search_data->mutex = g_mutex_new ();
+		dlg->search_data->min_year = (gint) min_y;
+		dlg->search_data->max_year = (gint) max_y;
+
+		g_thread_create (search_thread_func, dlg->search_data, FALSE, NULL);
+	}
+
+	dlg->search_data->search_next = button == dlg->snext;
+	dlg->search_data->year = dlg->year_val;
+	dlg->search_data->month = dlg->month_val + 1;
+
+	/* do not allow subsequent clicking for searching when searching already */
+	gtk_widget_set_sensitive (dlg->sprev, FALSE);
+	gtk_widget_set_sensitive (dlg->snext, FALSE);
+	gtk_widget_set_sensitive (dlg->stop, TRUE);
+
+	/* wake up thread */
+	g_cond_signal (dlg->search_data->cond);
+}
+
+static void
+stop_search_cb (GtkWidget *button, GoToDialog *dlg)
+{
+	g_return_if_fail (dlg != NULL);
+	g_return_if_fail (dlg->search_data != NULL);
+
+	g_mutex_lock (dlg->search_data->mutex);
+	dlg->search_data->cancel = TRUE;
+
+	/* indicate cancelling in progress */
+	gtk_widget_set_sensitive (dlg->stop, FALSE);
+
+	g_mutex_unlock (dlg->search_data->mutex);
+}
+
 /* Creates the ecalendar */
 static void
 create_ecal (GoToDialog *dlg)
@@ -155,6 +500,40 @@ create_ecal (GoToDialog *dlg)
 					       dlg, NULL);
 
 	ecal_date_range_changed (calitem, dlg);
+
+	if (dlg->gcal) {
+		ECalModel *model = gnome_calendar_get_calendar_model (dlg->gcal);
+		const gchar *sexp = e_cal_model_get_search_query (model);
+
+		if (sexp && !g_str_equal (sexp, "#t")) {
+			/* add search buttons only when there is any searching in a GnomeCal */
+			GtkWidget *button, *hbox;
+
+			hbox = gtk_hbox_new (FALSE, 2);
+			gtk_box_pack_start (GTK_BOX (dlg->vbox), hbox, FALSE, FALSE, 2);
+
+			button = gtk_button_new_with_mnemonic (_("Find _previous"));
+			gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
+			g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (find_event_cb), dlg);
+			gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);
+			dlg->sprev = button;
+
+			button = gtk_button_new_with_mnemonic (_("Find _next"));
+			gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
+			g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (find_event_cb), dlg);
+			gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);
+			dlg->snext = button;
+
+			button = gtk_button_new_with_mnemonic (_("_Stop"));
+			gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_BUTTON));
+			g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (stop_search_cb), dlg);
+			gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 2);
+			gtk_widget_set_sensitive (button, FALSE);
+			dlg->stop = button;
+
+			gtk_widget_show_all (hbox);
+		}
+	}
 }
 
 static void
@@ -261,6 +640,17 @@ goto_dialog (GnomeCalendar *gcal)
 	gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (dlg->ecal->calitem));
 
 	b = gtk_dialog_run (GTK_DIALOG (dlg->dialog));
+
+	if (dlg->search_data) {
+		/* all search_data members are freed on a thread end */
+		g_mutex_lock (dlg->search_data->mutex);
+		if (dlg->search_data->finished_id)
+			g_source_remove (dlg->search_data->finished_id);
+		dlg->search_data->dlg = NULL;
+		g_cond_signal (dlg->search_data->cond);
+		g_mutex_unlock (dlg->search_data->mutex);
+	}
+
 	gtk_widget_destroy (dlg->dialog);
 
 	if (b == 0)
diff --git a/widgets/misc/e-calendar-item.c b/widgets/misc/e-calendar-item.c
index 8903556..185dcae 100644
--- a/widgets/misc/e-calendar-item.c
+++ b/widgets/misc/e-calendar-item.c
@@ -1909,6 +1909,7 @@ e_calendar_item_event (GnomeCanvasItem *item, GdkEvent *event)
 		return e_calendar_item_motion (calitem, event);
 	case GDK_FOCUS_CHANGE:
 		gnome_canvas_item_request_update (item);
+		return FALSE;
 	case GDK_KEY_PRESS:
 		return e_calendar_item_key_press_event (calitem, event);
 	default:
diff --git a/widgets/misc/e-canvas.c b/widgets/misc/e-canvas.c
index 53e3eaf..74d7c05 100644
--- a/widgets/misc/e-canvas.c
+++ b/widgets/misc/e-canvas.c
@@ -599,7 +599,7 @@ e_canvas_focus_in (GtkWidget *widget, GdkEventFocus *event)
 {
 	GnomeCanvas *canvas;
 	ECanvas *ecanvas;
-	GdkEvent full_event;
+	GdkEvent full_event = {0};
 
 	canvas = GNOME_CANVAS (widget);
 	ecanvas = E_CANVAS (widget);
@@ -622,7 +622,7 @@ e_canvas_focus_out (GtkWidget *widget, GdkEventFocus *event)
 {
 	GnomeCanvas *canvas;
 	ECanvas *ecanvas;
-	GdkEvent full_event;
+	GdkEvent full_event = {0};
 
 	canvas = GNOME_CANVAS (widget);
 	ecanvas = E_CANVAS (widget);
