diff --git a/ChangeLog b/ChangeLog
index b4e7a20b2d3f7743661294fbe1184b58578187e2..99fb6d811d70b180cdc56b6a3b0b0934aabf949c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -144,6 +144,16 @@ CVS code -
 	  placewewant when a new match is found, so that edit_redraw()
 	  will redraw the screen properly when only placewewant changes.
 	  (DLR, found by Mike Frysinger)
+  do_replace()
+	- Instead of using edit_update() to redraw the screen with
+	  edittop at the top, set edittop beforehand and call
+	  edit_refresh(). (DLR)
+  do_gotoline()
+	- Use parse_num() to interpret a line entered by the user, and
+	  start the search for a line from current instead of fileage.
+	  (DLR)
+  do_gotopos()
+	- Tweak for efficiency. (David Benbennick)
 - utils.c:
   parse_num()
 	- New function to parse numeric values, so that we don't have to
diff --git a/src/proto.h b/src/proto.h
index 37252c73b94bb69ae7c5a92d40ef20188cbe0ac8..43a77c84224677415f9abe81fc60e4a76301f67a 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -402,7 +402,7 @@ char *replace_line(const char *needle);
 int do_replace_loop(const char *needle, const filestruct *real_current,
 	size_t *real_current_x, int wholewords);
 void do_replace(void);
-void do_gotoline(ssize_t line, int save_pos);
+void do_gotoline(int line, int save_pos);
 void do_gotoline_void(void);
 #if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
 void do_gotopos(int line, int pos_x, int pos_y, size_t pos_pww);
diff --git a/src/search.c b/src/search.c
index 4d153c2d052cc47c5b5e7b3bc6c19cde01ac72ca..fc4a78209e0cf7a0e381e529f03184d84cd0b1e7 100644
--- a/src/search.c
+++ b/src/search.c
@@ -822,10 +822,11 @@ void do_replace(void)
     numreplaced = do_replace_loop(last_search, begin, &beginx, FALSE);
 
     /* Restore where we were. */
+    edittop = edittop_save;
     current = begin;
     current_x = beginx;
     renumber_all();
-    edit_update(edittop_save, TOP);
+    edit_refresh();
 
     if (numreplaced >= 0)
 	statusbar(P_("Replaced %d occurrence", "Replaced %d occurrences",
@@ -834,11 +835,11 @@ void do_replace(void)
     replace_abort();
 }
 
-void do_gotoline(ssize_t line, int save_pos)
+void do_gotoline(int line, int save_pos)
 {
-    if (line <= 0) {		/* Ask for it */
+    if (line <= 0) {		/* Ask for it. */
 	char *ans = mallocstrcpy(NULL, answer);
-	int st = statusq(FALSE, goto_list, line != 0 ? ans : "",
+	int st = statusq(FALSE, goto_list, line < 0 ? ans : "",
 #ifndef NANO_SMALL
 		NULL,
 #endif
@@ -854,18 +855,23 @@ void do_gotoline(ssize_t line, int save_pos)
 	    return;
 	}
 
-	line = (ssize_t)atol(answer);
-
 	/* Bounds check. */
-	if (line <= 0) {
+	if (parse_num(answer, &line) == -1 || line < 0) {
 	    statusbar(_("Come on, be reasonable"));
 	    display_main_list();
 	    return;
 	}
     }
 
-    for (current = fileage; current->next != NULL && line > 1; line--)
-	current = current->next;
+    if (current->lineno > line) {
+	for (; current->prev != NULL && current->lineno > line;
+		current = current->prev)
+	    ;
+    } else {
+	for (; current->next != NULL && current->lineno < line;
+		current = current->next)
+	    ;
+    }
 
     current_x = 0;
 
@@ -885,17 +891,17 @@ void do_gotoline_void(void)
 #if defined(ENABLE_MULTIBUFFER) || !defined(DISABLE_SPELLER)
 void do_gotopos(int line, int pos_x, int pos_y, size_t pos_pww)
 {
-    /* since do_gotoline() resets the x-coordinate but not the
-       y-coordinate, set the coordinates up this way */
+    /* Since do_gotoline() resets the x-coordinate but not the
+     * y-coordinate, set the coordinates up this way. */
     current_y = pos_y;
     do_gotoline(line, TRUE);
 
-    /* make sure that the x-coordinate is sane here */
-    if (pos_x > strlen(current->data))
-	pos_x = strlen(current->data);
+    /* Make sure that the x-coordinate is sane here. */
+    current_x = strlen(current->data);
+    if (pos_x < current_x)
+	current_x = pos_x;
 
-    /* set the rest of the coordinates up */
-    current_x = pos_x;
+    /* Set the rest of the coordinates up. */
     placewewant = pos_pww;
     update_line(current, pos_x);
 }