diff --git a/src/browser.c b/src/browser.c
index 194230e3b64971eaa07499d8d0d6d9e13689f60b..342c29ac083af2f6009890f05ec1753f4d17f7f0 100644
--- a/src/browser.c
+++ b/src/browser.c
@@ -41,8 +41,6 @@ static int longest = 0;
 	/* The number of columns in the longest filename in the list. */
 static size_t selected = 0;
 	/* The currently selected filename in the list; zero-based. */
-static char *path_save = NULL;
-	/* A copy of the current path. */
 
 /* Our main file browser function.  path is the tilde-expanded path we
  * start browsing from. */
@@ -75,7 +73,7 @@ char *do_browser(char *path, DIR *dir)
     path = mallocstrassn(path, get_full_path(path));
 
     /* Save the current path in order to be used later. */
-    path_save = path;
+    present_path = mallocstrcpy(present_path, path);
 
     assert(path != NULL && path[strlen(path) - 1] == '/');
 
@@ -117,7 +115,7 @@ char *do_browser(char *path, DIR *dir)
 #ifndef NANO_TINY
 	if (kbinput == KEY_WINCH) {
 	    /* Rebuild the file list and sort it. */
-	    browser_init(path_save, opendir(path_save));
+	    browser_init(present_path, opendir(present_path));
 	    qsort(filelist, filelist_len, sizeof(char *), diralphasort);
 
 	    /* Make sure the selected file is within range. */
@@ -545,7 +543,7 @@ void browser_refresh(void)
     char *info;
 	/* The additional information that we'll display about a file. */
 
-    titlebar(path_save);
+    titlebar(present_path);
     blank_edit();
 
     wmove(edit, 0, 0);
diff --git a/src/files.c b/src/files.c
index 08c9fd654bd983dc0101d3850978a3bddd55fb5e..99d532c71a2e80d89b95f5049e1e40ca95dcca88 100644
--- a/src/files.c
+++ b/src/files.c
@@ -1120,6 +1120,8 @@ void do_insertfile(
 		_("File to insert [from %s] ");
 	}
 
+	present_path = mallocstrcpy(present_path, "./");
+
 	i = do_prompt(TRUE,
 #ifndef DISABLE_TABCOMP
 		TRUE,
@@ -2280,6 +2282,8 @@ int do_writeout(bool exiting)
 		  (append == APPEND) ? _("File Name to Append to") :
 		  _("File Name to Write");
 
+	present_path = mallocstrcpy(present_path, "./");
+
 	/* If we're using restricted mode, and the filename isn't blank,
 	 * disable tab completion. */
 	i = do_prompt(!ISSET(RESTRICTED) ||
@@ -2684,10 +2688,16 @@ char **cwd_tab_completion(const char *buf, bool allow_files, size_t
 	/* Cut off the filename part after the slash. */
 	*slash = '\0';
 	dirname = real_dir_from_tilde(dirname);
+	/* A non-absolute path is relative to the current browser directory. */
+	if (dirname[0] != '/') {
+	    dirname = charealloc(dirname, strlen(present_path) +
+						strlen(wasdirname) + 1);
+	    sprintf(dirname, "%s%s", present_path, wasdirname);
+	}
 	free(wasdirname);
     } else {
 	filename = dirname;
-	dirname = mallocstrcpy(NULL, "./");
+	dirname = mallocstrcpy(NULL, present_path);
     }
 
     assert(dirname[strlen(dirname) - 1] == '/');
@@ -2784,7 +2794,7 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
 	beep();
     else {
 	size_t match, common_len = 0;
-	char *mzero;
+	char *mzero, *glued;
 	const char *lastslash = revstrstr(buf, "/", buf + *place);
 	size_t lastslash_len = (lastslash == NULL) ? 0 : lastslash - buf + 1;
 	char *match1 = charalloc(mb_cur_max());
@@ -2820,9 +2830,13 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
 	common_len += lastslash_len;
 	mzero[common_len] = '\0';
 
+	/* Cover also the case of the user specifying a relative path. */
+	glued = charalloc(strlen(present_path) + strlen(mzero) + 1);
+	sprintf(glued, "%s%s", present_path, mzero);
+
 	assert(common_len >= *place);
 
-	if (num_matches == 1 && is_dir(mzero)) {
+	if (num_matches == 1 && (is_dir(mzero) || is_dir(glued))) {
 	    mzero[common_len++] = '/';
 
 	    assert(common_len > *place);
@@ -2892,6 +2906,7 @@ char *input_tab(char *buf, bool allow_files, size_t *place,
 	    *listed = TRUE;
 	}
 
+	free(glued);
 	free(mzero);
     }
 
diff --git a/src/global.c b/src/global.c
index 37de0383a31d4d2eac6c4aa53b6aaacc33023898..999595e0e0b26fcb42d9b154fe3711b433c1c789 100644
--- a/src/global.c
+++ b/src/global.c
@@ -57,6 +57,9 @@ ssize_t wrap_at = -CHARS_FROM_EOL;
 char *last_search = NULL;
 	/* The last string we searched for. */
 
+char *present_path = NULL;
+	/* The current browser directory when trying to do tab completion. */
+
 unsigned flags[4] = {0, 0, 0, 0};
 	/* Our flag containing the states of all global options. */
 WINDOW *topwin;
@@ -1647,6 +1650,7 @@ void thanks_for_all_the_fish(void)
 #endif
     free(answer);
     free(last_search);
+    free(present_path);
 #ifndef DISABLE_SPELLER
     free(alt_speller);
 #endif
diff --git a/src/proto.h b/src/proto.h
index 59a44c0681fd2e4b715d786af18c8094692f58e1..2afbbd5cafdc4ea1fe9da6687a01c2e378185db1 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -46,6 +46,8 @@ extern ssize_t wrap_at;
 
 extern char *last_search;
 
+extern char *present_path;
+
 extern unsigned flags[4];
 extern WINDOW *topwin;
 extern WINDOW *edit;