diff -upr evince/ChangeLog evince.new/ChangeLog
--- evince/ChangeLog	2005-05-11 13:49:44.000000000 +0400
+++ evince.new/ChangeLog	2005-05-12 16:21:03.000000000 +0400
@@ -1,3 +1,8 @@
+2005-05-12  James Bowes  <bowes@cs.dal.ca>
+ 
+ 	* shell/main.c: (load_files): Add --page command-line option,
+ 	to open to a specified page number or label. Fixes bug #170458
+ 
 2005-05-11  Marco Pesenti Gritti  <mpg@redhat.com>
 
 	* cut-n-paste/zoom-control/ephy-zoom.c:
diff -upr evince/shell/ev-view.c evince.new/shell/ev-view.c
--- evince/shell/ev-view.c	2005-05-11 09:20:51.000000000 +0400
+++ evince.new/shell/ev-view.c	2005-05-12 16:23:28.000000000 +0400
@@ -52,11 +52,11 @@ enum {
 };
 
 enum {
-  TARGET_STRING,
-  TARGET_TEXT,
-  TARGET_COMPOUND_TEXT,
-  TARGET_UTF8_STRING,
-  TARGET_TEXT_BUFFER_CONTENTS
+	TARGET_STRING,
+	TARGET_TEXT,
+	TARGET_COMPOUND_TEXT,
+	TARGET_UTF8_STRING,
+	TARGET_TEXT_BUFFER_CONTENTS
 };
 
 static const GtkTargetEntry targets[] = {
@@ -92,6 +92,12 @@ typedef struct {
 	gdouble vadj;
 } DragInfo;
 
+typedef enum {
+	SCROLL_TO_KEEP_POSITION,
+	SCROLL_TO_CURRENT_PAGE,
+	SCROLL_TO_CENTER
+} PendingScroll;
+
 struct _EvView {
 	GtkWidget parent_instance;
 
@@ -135,6 +141,8 @@ struct _EvView {
 	gboolean fullscreen;
 	gboolean presentation;
 	EvSizingMode sizing_mode;
+	
+	PendingScroll pending_scroll;
 };
 
 struct _EvViewClass {
@@ -150,19 +158,25 @@ struct _EvViewClass {
 };
 
 
-static void ev_view_set_scroll_adjustments     (EvView        *view,
-						GtkAdjustment *hadjustment,
-						GtkAdjustment *vadjustment);
 static void get_bounding_box_size              (EvView        *view,
 						int           *max_width,
 						int           *max_height);
+static void compute_border		       (EvView *view, 
+						int width, 
+						int height, 
+						GtkBorder *border);						 
+static void view_update_adjustments 	       (EvView *view);
+static void ev_view_set_scroll_adjustments     (EvView        *view,
+						GtkAdjustment *hadjustment,
+						GtkAdjustment *vadjustment);
 static void view_update_range_and_current_page (EvView        *view);
-
+static void view_scroll_to_page                (EvView *view, 
+						gint old_page,
+						gint new_page);
 static void page_changed_cb 		       (EvPageCache *page_cache, 
 						int          new_page, 
 					        EvView      *view);
 
-
 G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET)
 
 /*** Helper functions ***/
@@ -186,7 +200,6 @@ view_update_adjustments (EvView *view)
 	if (GTK_WIDGET_REALIZED (view) &&
 	    (view->scroll_x != old_x || view->scroll_y != old_y)) {
 		gdk_window_move (view->bin_window, - view->scroll_x, - view->scroll_y);
-		//		gdk_window_process_updates (view->bin_window, TRUE);
 	}
 
 	if (view->document)
@@ -199,10 +212,12 @@ view_set_adjustment_values (EvView      
 {
 	GtkWidget *widget = GTK_WIDGET (view);
 	GtkAdjustment *adjustment;
-	gboolean value_changed = FALSE;
 	int requisition;
 	int allocation;
 
+	double factor;
+	gint new_value;
+
 	if (orientation == GTK_ORIENTATION_HORIZONTAL)  {
 		requisition = widget->requisition.width;
 		allocation = widget->allocation.width;
@@ -215,6 +230,18 @@ view_set_adjustment_values (EvView      
 
 	if (!adjustment)
 		return;
+	
+	factor = 1.0;
+	switch (view->pending_scroll) {
+    	        case SCROLL_TO_KEEP_POSITION: 
+			factor = adjustment->value / adjustment->upper;
+			break;
+    	        case SCROLL_TO_CURRENT_PAGE: 
+			break;
+    	        case SCROLL_TO_CENTER: 
+			factor = (adjustment->value + adjustment->page_size * 0.5) / adjustment->upper;
+			break;
+	}
 
 	adjustment->page_size = allocation;
 	adjustment->step_increment = allocation * 0.1;
@@ -222,14 +249,23 @@ view_set_adjustment_values (EvView      
 	adjustment->lower = 0;
 	adjustment->upper = MAX (allocation, requisition);
 
-	if (adjustment->value > adjustment->upper - adjustment->page_size) {
-		adjustment->value = adjustment->upper - adjustment->page_size;
-		value_changed = TRUE;
+	switch (view->pending_scroll) {
+    	        case SCROLL_TO_KEEP_POSITION: 
+			new_value = CLAMP (adjustment->upper * factor, 0, adjustment->upper - adjustment->page_size);
+			gtk_adjustment_set_value (adjustment, new_value);
+			break;
+    	        case SCROLL_TO_CURRENT_PAGE: 
+			if (orientation == GTK_ORIENTATION_VERTICAL) {
+				view_scroll_to_page (view, view->current_page, view->current_page);
+			}
+			break;
+    	        case SCROLL_TO_CENTER: 
+			new_value = CLAMP (adjustment->upper * factor - adjustment->page_size * 0.5, 0, adjustment->upper - adjustment->page_size);
+			gtk_adjustment_set_value (adjustment, new_value);
+			break;
 	}
 
 	gtk_adjustment_changed (adjustment);
-	if (value_changed)
-		gtk_adjustment_value_changed (adjustment);
 }
 
 static void
@@ -291,9 +327,8 @@ view_update_range_and_current_page (EvVi
 		current_page = ev_page_cache_get_current_page (view->page_cache);
 
 		if (current_page < view->start_page || current_page > view->end_page) {
-			g_signal_handlers_block_by_func (view->page_cache, page_changed_cb, view);
+			view->current_page = view->start_page;
 			ev_page_cache_set_current_page (view->page_cache, view->start_page);
-		    	g_signal_handlers_unblock_by_func (view->page_cache, page_changed_cb, view);
 		}			
 	} else {
 		if (view->dual_page) {
@@ -318,6 +353,50 @@ view_update_range_and_current_page (EvVi
 }
 
 static void
+view_scroll_to_page (EvView *view, gint old_page, gint new_page)
+{
+	EvPageCache *page_cache = view->page_cache;
+	int old_width, old_height;
+	int new_width, new_height;
+	int max_height, n_rows;
+
+	ev_page_cache_get_size (page_cache,
+				old_page,
+				view->scale,
+				&old_width, &old_height);
+
+	ev_page_cache_get_size (page_cache,
+				new_page,
+				view->scale,
+				&new_width, &new_height);
+
+	compute_border (view, new_width, new_height, &(view->border));
+
+	if (new_width != old_width || new_height != old_height)
+		gtk_widget_queue_resize (GTK_WIDGET (view));
+	else
+		gtk_widget_queue_draw (GTK_WIDGET (view));
+	
+	if (view->continuous) {
+		
+		n_rows = view->dual_page ? new_page / 2 : new_page;
+		
+		get_bounding_box_size (view, NULL, &max_height);
+
+		gtk_adjustment_clamp_page(view->vadjustment,
+					  (max_height + view->spacing) * n_rows, 
+					  (max_height + view->spacing) * n_rows +
+					   view->vadjustment->page_size);
+	} else {
+		gtk_adjustment_set_value (view->vadjustment,
+					  view->vadjustment->lower);
+	}
+
+	view_update_range_and_current_page (view);
+}
+
+
+static void
 clear_selection (EvView *view)
 {
 	g_list_foreach (view->selections, (GFunc)g_free, NULL);
@@ -722,6 +801,8 @@ ev_view_size_allocate (GtkWidget      *w
 
 	view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
 	view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
+	
+	view->pending_scroll = SCROLL_TO_KEEP_POSITION;
 
 	if (GTK_WIDGET_REALIZED (widget)) {
 		gdk_window_resize (view->bin_window,
@@ -1838,6 +1919,7 @@ ev_view_init (EvView *view)
 	view->presentation = FALSE;
 	view->fullscreen = FALSE;
 	view->sizing_mode = EV_SIZING_FIT_WIDTH;
+	view->pending_scroll = SCROLL_TO_KEEP_POSITION;
 }
 
 static void
@@ -1873,10 +1955,7 @@ update_find_status_message (EvView *view
 		}
 
 	}
-//	ev_document_doc_mutex_unlock ();
-
 	ev_view_set_find_status (view, message);
-//	g_free (message);
 }
 
 #define MARGIN 5
@@ -1995,61 +2074,24 @@ job_finished_cb (EvPixbufCache *pixbuf_c
 	gtk_widget_queue_draw (GTK_WIDGET (view));
 }
 
-
 static void
 page_changed_cb (EvPageCache *page_cache,
 		 int          new_page,
 		 EvView      *view)
 {
-	int old_page = view->current_page;
-	int old_width, old_height;
-	int new_width, new_height;
-	int max_height, n_rows;
-
-	if (old_page == new_page)
-		return;
-
-	ev_page_cache_get_size (page_cache,
-				old_page,
-				view->scale,
-				&old_width, &old_height);
-
-	view->current_page = new_page;
-
-	ev_page_cache_get_size (page_cache,
-				new_page,
-				view->scale,
-				&new_width, &new_height);
-
-	compute_border (view, new_width, new_height, &(view->border));
-
-	if (new_width != old_width || new_height != old_height)
-		gtk_widget_queue_resize (GTK_WIDGET (view));
-	else
-		gtk_widget_queue_draw (GTK_WIDGET (view));
-	
-	if (view->continuous) {
-		
-		n_rows = view->dual_page ? new_page / 2 : new_page;
-		
-		get_bounding_box_size (view, NULL, &max_height);
-
-		gtk_adjustment_clamp_page(view->vadjustment,
-					  (max_height + view->spacing) * n_rows, 
-					  (max_height + view->spacing) * n_rows +
-					   view->vadjustment->page_size);
-	} else {
-		gtk_adjustment_set_value (view->vadjustment,
-					  view->vadjustment->lower);
-	}
-
+	gint old_page;
+    
 	if (EV_IS_DOCUMENT_FIND (view->document)) {
 		view->find_page = new_page;
 		view->find_result = 0;
 		update_find_status_message (view);
 	}
-
-	view_update_range_and_current_page (view);
+	
+	old_page = view->current_page;
+	view->current_page = new_page;
+	
+	if (old_page != new_page)
+		view_scroll_to_page (view, old_page, new_page);
 }
 
 void
@@ -2081,6 +2123,7 @@ ev_view_set_document (EvView     *view,
 						  view);
 			}
 			view->page_cache = ev_document_get_page_cache (view->document);
+			view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
 			g_signal_connect (view->page_cache, "page-changed", G_CALLBACK (page_changed_cb), view);
 			view->pixbuf_cache = ev_pixbuf_cache_new (view->document);
 			g_signal_connect (view->pixbuf_cache, "job-finished", G_CALLBACK (job_finished_cb), view);
@@ -2127,6 +2170,7 @@ ev_view_set_continuous (EvView   *view,
 
 	if (view->continuous != continuous) {
 		view->continuous = continuous;
+		view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
 		gtk_widget_queue_resize (GTK_WIDGET (view));
 	}
 
@@ -2143,7 +2187,8 @@ ev_view_set_dual_page (EvView   *view,
 
 	if (view->dual_page == dual_page)
 		return;
-
+    
+	view->pending_scroll = SCROLL_TO_CURRENT_PAGE;
 	view->dual_page = dual_page;
 	/* FIXME: if we're keeping the pixbuf cache around, we should extend the
 	 * preload_cache_size to be 2 if dual_page is set.
@@ -2250,7 +2295,8 @@ void
 ev_view_zoom_in (EvView *view)
 {
 	g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
-
+	
+	view->pending_scroll = SCROLL_TO_CENTER;
 	ev_view_set_zoom (view, ZOOM_IN_FACTOR, TRUE);
 }
 
@@ -2259,6 +2305,7 @@ ev_view_zoom_out (EvView *view)
 {
 	g_return_if_fail (view->sizing_mode == EV_SIZING_FREE);
 
+	view->pending_scroll = SCROLL_TO_CENTER;
 	ev_view_set_zoom (view, ZOOM_OUT_FACTOR, TRUE);
 }
 
diff -upr evince/shell/ev-window.c evince.new/shell/ev-window.c
--- evince/shell/ev-window.c	2005-05-11 13:42:22.000000000 +0400
+++ evince.new/shell/ev-window.c	2005-05-12 16:21:03.000000000 +0400
@@ -458,11 +458,12 @@ update_sizing_buttons (EvWindow *window)
 }
 
 void
-ev_window_open_page (EvWindow *ev_window, int page)
+ev_window_open_page_label (EvWindow   *ev_window, 
+			   const char *label)
 {
 	if (ev_window->priv->page_cache) {
-	    page = CLAMP (page, 0, ev_page_cache_get_n_pages (ev_window->priv->page_cache));
-	    ev_page_cache_set_current_page (ev_window->priv->page_cache, page);
+		ev_page_cache_set_page_label (ev_window->priv->page_cache, 
+					      label);
 	}
 }
 
@@ -1780,7 +1781,11 @@ ev_window_cmd_view_reload (GtkAction *ac
 	uri = g_strdup (ev_window->priv->uri);
 
 	ev_window_open (ev_window, uri);
-	ev_window_open_page (ev_window, page);
+
+	/* In case the number of pages in the document has changed. */
+	page = CLAMP (page, 0, ev_page_cache_get_n_pages (ev_window->priv->page_cache));
+
+	ev_page_cache_set_current_page (ev_window->priv->page_cache, page);
 
 	g_free (uri);
 }
diff -upr evince/shell/ev-window.h evince.new/shell/ev-window.h
--- evince/shell/ev-window.h	2005-04-17 02:54:22.000000000 +0400
+++ evince.new/shell/ev-window.h	2005-05-12 16:21:03.000000000 +0400
@@ -50,12 +50,12 @@ struct _EvWindowClass {
 	GtkWindowClass		base_class;
 };
 
-GType		ev_window_get_type	(void);
-void		ev_window_open		(EvWindow       *ev_window,
-					 const char     *uri);
-void		ev_window_open_page	(EvWindow       *ev_window,
-					 int             page);
-gboolean	ev_window_is_empty	(const EvWindow *ev_window);
+GType		ev_window_get_type		(void);
+void		ev_window_open			(EvWindow	*ev_window,
+						 const char	*uri);
+void		ev_window_open_page_label	(EvWindow       *ev_window, 
+						 const char     *label);
+gboolean	ev_window_is_empty		(const EvWindow *ev_window);
 
 G_END_DECLS
 
diff -upr evince/shell/main.c evince.new/shell/main.c
--- evince/shell/main.c	2005-05-10 16:48:34.000000000 +0400
+++ evince.new/shell/main.c	2005-05-12 16:21:03.000000000 +0400
@@ -34,8 +34,11 @@
 #include "ev-job-queue.h"
 #include "ev-file-helpers.h"
 
+static char *page_label;
+
 static struct poptOption popt_options[] =
 {
+	{ "page-label", 'p', POPT_ARG_STRING, &page_label, 0, N_("The page of the document to display."), N_("PAGE")},
 	{ NULL, 0, 0, NULL, 0, NULL, NULL }
 };
 
@@ -59,9 +62,14 @@ load_files (const char **files)
 		window = GTK_WIDGET (ev_application_new_window (EV_APP));
 		gtk_widget_show (window);
 		ev_window_open (EV_WINDOW (window), uri);
+		
+		if (page_label != NULL)
+			ev_window_open_page_label (EV_WINDOW (window), page_label);
 
 		g_free (uri);
         }
+
+	g_free (page_label);
 }
 
 int
