diff --git a/ChangeLog b/ChangeLog
index 13e0b7f4e02590fc22484e2160a85734fe976703..c45ec5437a8f33cf8444786a644688f4368acd46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -149,13 +149,15 @@ CVS code -
 	  get the value of totsize in a few more places.  Changes to
 	  read_line(), read_file(), do_delete(), do_input(),
 	  get_totals(), and do_cursorpos(). (DLR)
-	- Overhaul the tab completion code and a few related functions
-	  to increase efficiency and support multibyte characters.  New
-	  functions strrchrn() and is_dir(); changes to get_full_path(),
-	  check_writable_directory(), safe_tempnam(), diralphasort(),
-	  username_tab_completion(), cwd_tab_completion(), input_tab(),
-	  tail(), and striponedir(); removal of append_slash_if_dir()
-	  and check_wildcard_match(). (David Benbennick)  DLR: Move the
+	- Overhaul the tab completion code, the file browser code, and
+	  related functions to increase efficiency and support multibyte
+	  characters.  New functions strrchrn() and is_dir(); changes to
+	  get_full_path(), check_writable_directory(), safe_tempnam(),
+	  diralphasort(), username_tab_completion(),
+	  cwd_tab_completion(), input_tab(), tail(), striponedir(),
+	  browser_init(), do_browser(), and do_browse_from(); removal of
+	  append_slash_if_dir(), readable_dir(), and
+	  check_wildcard_match(). (David Benbennick)  DLR: Move the
 	  routine to get the current user's home directory into the new
 	  function get_homedir(), and use it where necessary.  Also add
 	  a few miscellaneous tweaks.
diff --git a/src/files.c b/src/files.c
index c244d21d71003f1c80db9cd6902abb0a5e93e55b..3a33b418560be8160396b9582f0a117a03a86902 100644
--- a/src/files.c
+++ b/src/files.c
@@ -2305,460 +2305,504 @@ void free_charptrarray(char **array, size_t len)
     free(array);
 }
 
-/* Strip one dir from the end of a string. */
-void striponedir(char *foo)
+/* Strip one directory from the end of path. */
+void striponedir(char *path)
 {
     char *tmp;
 
-    assert(foo != NULL);
+    assert(path != NULL);
 
-    tmp = strrchr(foo, '/');
+    tmp = strrchr(path, '/');
     if (tmp != NULL)
  	*tmp = '\0';
 }
 
-int readable_dir(const char *path)
+/* Return a list of files contained in the directory path.  *longest is
+ * the maximum display length of a file, up to COLS - 1 (but at least
+ * 7).  *numents is the number of files.  We assume path exists and is a
+ * directory.  If neither is true, we return NULL. */
+char **browser_init(const char *path, int *longest, size_t *numents, DIR
+	*dir)
 {
-    DIR *dir = opendir(path);
+    const struct dirent *next;
+    char **filelist;
+    size_t i, path_len;
 
-    /* If dir is NULL, don't do closedir(), since that changes errno. */
-    if (dir != NULL)
-	closedir(dir);
-    return (dir != NULL);
-}
+    assert(dir != NULL);
 
-/* Initialize the browser code, including the list of files in *path */
-char **browser_init(const char *path, int *longest, int *numents)
-{
-    DIR *dir;
-    struct dirent *next;
-    char **filelist;
-    int i = 0;
-    size_t path_len;
+    *longest = 0;
 
-    dir = opendir(path);
-    if (dir == NULL)
-	return NULL;
+    i = 0;
 
-    *numents = 0;
     while ((next = readdir(dir)) != NULL) {
+	size_t dlen;
+
+	/* Don't show the . entry. */
 	if (strcmp(next->d_name, ".") == 0)
 	   continue;
-	(*numents)++;
-	if (strlen(next->d_name) > *longest)
-	    *longest = strlen(next->d_name);
+	i++;
+
+	dlen = strlenpt(next->d_name);
+	if (dlen > *longest)
+	    *longest = dlen;
     }
+
+    *numents = i;
     rewinddir(dir);
     *longest += 10;
 
-    filelist = (char **)nmalloc(*numents * sizeof (char *));
+    filelist = (char **)nmalloc(*numents * sizeof(char *));
 
-    if (strcmp(path, "/") == 0)
-	path = "";
     path_len = strlen(path);
 
-    while ((next = readdir(dir)) != NULL) {
+    i = 0;
+
+    while ((next = readdir(dir)) != NULL && i < *numents) {
+	/* Don't show the "." entry. */
 	if (strcmp(next->d_name, ".") == 0)
 	   continue;
 
-	filelist[i] = charalloc(strlen(next->d_name) + path_len + 2);
-	sprintf(filelist[i], "%s/%s", path, next->d_name);
+	filelist[i] = charalloc(path_len + strlen(next->d_name) + 1);
+	sprintf(filelist[i], "%s%s", path, next->d_name);
 	i++;
     }
+
+    /* Maybe the number of files in the directory changed between the
+     * first time we scanned and the second.  i is the actual length of
+     * filelist, so record it. */
+    *numents = i;
     closedir(dir);
 
     if (*longest > COLS - 1)
 	*longest = COLS - 1;
+    if (*longest < 7)
+	*longest = 7;
 
     return filelist;
 }
 
-/* Our browser function.  inpath is the path to start browsing from */
-char *do_browser(const char *inpath)
+/* Our browser function.  path is the path to start browsing from.
+ * Assume path has already been tilde-expanded. */
+char *do_browser(char *path, DIR *dir)
 {
-    struct stat st;
-    char *foo, *retval = NULL;
-    static char *path = NULL;
-    int numents = 0, i = 0, j = 0, longest = 0, abort = 0, col = 0;
-    int selected = 0, editline = 0, width = 0, filecols = 0, lineno = 0;
-    int kbinput = ERR;
-    bool meta_key, func_key;
-    char **filelist = (char **)NULL;
-#ifndef DISABLE_MOUSE
-    MEVENT mevent;
+    int kbinput, longest, selected, width;
+    bool meta_key, func_key, old_constupdate = ISSET(CONSTUPDATE);
+    size_t numents;
+    char **filelist, *retval = NULL;
+
+    curs_set(0);
+    blank_statusbar();
+    bottombars(browser_list);
+    wrefresh(bottomwin);
+
+#if !defined(DISABLE_HELP) || !defined(DISABLE_MOUSE)
+    /* Set currshortcut so the user can click in the shortcut area, and
+     * so the browser help screen will come up. */
+    currshortcut = browser_list;
 #endif
 
-    assert(inpath != NULL);
+    UNSET(CONSTUPDATE);
 
-    /* If path isn't the same as inpath, we are being passed a new
-	dir as an arg.  We free it here so it will be copied from 
-	inpath below */
-    if (path != NULL && strcmp(path, inpath) != 0) {
-	free(path);
-	path = NULL;
-    }
+  change_browser_directory:
+	/* We go here after the user selects a new directory. */
+
+    kbinput = ERR;
+    selected = 0;
+    width = 0;
+
+    path = mallocstrassn(path, get_full_path(path));
 
-    /* if path doesn't exist, make it so */
-    if (path == NULL)
-	path = mallocstrcpy(NULL, inpath);
+    /* Assume that path exists and ends with a slash. */
+    assert(path != NULL && path[strlen(path) - 1] == '/');
 
-    filelist = browser_init(path, &longest, &numents);
-    foo = charalloc(longest + 8);
+    /* Get the list of files. */
+    filelist = browser_init(path, &longest, &numents, dir);
+
+    assert(filelist != NULL);
 
     /* Sort the list. */
     qsort(filelist, numents, sizeof(char *), diralphasort);
 
     titlebar(path);
-    bottombars(browser_list);
-    curs_set(0);
-    wmove(edit, 0, 0);
-    i = 0;
-    width = 0;
-    filecols = 0;
 
     /* Loop invariant: Microsoft sucks. */
     do {
+	bool abort = FALSE;
+	int j, col = 0, editline = 0, lineno;
+	int filecols = 0;
+	    /* Used only if width == 0, to calculate the number of files
+	     * per row below. */
+	struct stat st;
 	char *new_path;
 	    /* Used by the Go To Directory prompt. */
+#ifndef DISABLE_MOUSE
+	MEVENT mevent;
+#endif
 
 	check_statusblank();
 
-	currshortcut = browser_list;
-
- 	editline = 0;
-	col = 0;
-	    
-	/* Compute line number we're on now, so we don't divide by zero later */
+	/* Compute the line number we're on now, so that we don't divide
+	 * by zero later. */
 	lineno = selected;
 	if (width != 0)
 	    lineno /= width;
 
 	switch (kbinput) {
-
 #ifndef DISABLE_MOUSE
-	case KEY_MOUSE:
-	    if (getmouse(&mevent) == ERR)
-		return retval;
- 
-	    /* If they clicked in the edit window, they probably clicked
-		on a file */
-	    if (wenclose(edit, mevent.y, mevent.x)) { 
-		int selectedbackup = selected;
-
-		mevent.y -= 2;
-
-		/* Longest is the width of each column.  There are two
-		 * spaces between each column. */
-		selected = (lineno / editwinrows) * editwinrows * width
-			+ mevent.y * width + mevent.x / (longest + 2);
-
-		/* If they clicked beyond the end of a row, select the
-		 * end of that row. */
-		if (mevent.x > width * (longest + 2))
-		    selected--;
+	    case KEY_MOUSE:
+		if (getmouse(&mevent) == ERR)
+		    break;
 
-		/* If we're off the screen, reset to the last item.
-		   If we clicked where we did last time, select this name! */
-		if (selected > numents - 1)
-		    selected = numents - 1;
-		else if (selectedbackup == selected)
-		    /* Put back the 'select' key */
-		    unget_kbinput('s', FALSE, FALSE);
-	    } else {
-		/* Must be clicking a shortcut */
-		int mouse_x, mouse_y;
-		get_mouseinput(&mouse_x, &mouse_y, TRUE);
-	    }
+		/* If we clicked in the edit window, we probably clicked
+		 * on a file. */
+		if (wenclose(edit, mevent.y, mevent.x)) {
+		    int selectedbackup = selected;
+
+		    mevent.y -= 2;
+
+		    /* longest is the width of each column.  There are
+		     * two spaces between each column. */
+		    selected = (lineno / editwinrows) * editwinrows *
+			width + mevent.y * width + mevent.x /
+			(longest + 2);
+
+		    /* If they clicked beyond the end of a row, select
+		     * the end of that row. */
+		    if (mevent.x > width * (longest + 2))
+			selected--;
+
+		    /* If we're off the screen, reset to the last item.
+		     * If we clicked the same place as last time, select
+		     * this name! */
+		    if (selected > numents - 1)
+			selected = numents - 1;
+		    else if (selectedbackup == selected)
+			/* Put back the 'select' key. */
+			unget_kbinput('s', FALSE, FALSE);
+		} else {
+		    /* We must have clicked a shortcut.  Put back the
+		     * equivalent shortcut key. */
+		    int mouse_x, mouse_y;
+		    get_mouseinput(&mouse_x, &mouse_y, TRUE);
+		}
 
-            break;
+		break;
 #endif
-	case NANO_PREVLINE_KEY:
-	    if (selected - width >= 0)
-		selected -= width;
-	    break;
-	case NANO_BACK_KEY:
-	    if (selected > 0)
-		selected--;
-	    break;
-	case NANO_NEXTLINE_KEY:
-	    if (selected + width <= numents - 1)
-		selected += width;
-	    break;
-	case NANO_FORWARD_KEY:
-	    if (selected < numents - 1)
-		selected++;
-	    break;
-	case NANO_PREVPAGE_KEY:
-	case NANO_PREVPAGE_FKEY:
-	case '-': /* Pico compatibility */
-	    if (selected >= (editwinrows + lineno % editwinrows) * width)
-		selected -= (editwinrows + lineno % editwinrows) * width;
-	    else
-		selected = 0;
-	    break;
-	case NANO_NEXTPAGE_KEY:
-	case NANO_NEXTPAGE_FKEY:
-	case ' ': /* Pico compatibility */
-	    selected += (editwinrows - lineno % editwinrows) * width;
-	    if (selected >= numents)
-		selected = numents - 1;
-	    break;
-	case NANO_HELP_KEY:
-	case NANO_HELP_FKEY:
-	case '?': /* Pico compatibility */
+	    case NANO_PREVLINE_KEY:
+		if (selected >= width)
+		    selected -= width;
+		break;
+	    case NANO_BACK_KEY:
+		if (selected > 0)
+		    selected--;
+		break;
+	    case NANO_NEXTLINE_KEY:
+		if (selected + width <= numents - 1)
+		    selected += width;
+		break;
+	    case NANO_FORWARD_KEY:
+		if (selected < numents - 1)
+		    selected++;
+		break;
+	    case NANO_PREVPAGE_KEY:
+	    case NANO_PREVPAGE_FKEY:
+	    case '-': /* Pico compatibility. */
+		if (selected >= (editwinrows + lineno % editwinrows) *
+			width)
+		    selected -= (editwinrows + lineno % editwinrows) *
+			width;
+		else
+		    selected = 0;
+		break;
+	    case NANO_NEXTPAGE_KEY:
+	    case NANO_NEXTPAGE_FKEY:
+	    case ' ': /* Pico compatibility. */
+		selected += (editwinrows - lineno % editwinrows) *
+			width;
+		if (selected >= numents)
+		    selected = numents - 1;
+		break;
+	    case NANO_HELP_KEY:
+	    case NANO_HELP_FKEY:
+	    case '?': /* Pico compatibility. */
 #ifndef DISABLE_HELP
-	    do_help();
-	    curs_set(0);
+		do_help();
+		curs_set(0);
 #else
-	    nano_disabled_msg();
+		nano_disabled_msg();
 #endif
-	    break;
-	case NANO_ENTER_KEY:
-	case 'S': /* Pico compatibility */
-	case 's':
-	    /* You can't cd up from / */
-	    if (strcmp(filelist[selected], "/..") == 0 &&
-		strcmp(path, "/") == 0) {
-		statusbar(_("Can't move up a directory"));
-		beep();
 		break;
-	    }
+	    case NANO_ENTER_KEY:
+	    case 'S': /* Pico compatibility. */
+	    case 's':
+		/* You can't move up from "/". */
+		if (strcmp(filelist[selected], "/..") == 0) {
+		    statusbar(_("Can't move up a directory"));
+		    beep();
+		    break;
+		}
 
 #ifndef DISABLE_OPERATINGDIR
-	    /* Note: the selected file can be outside the operating
-	     * directory if it is .. or if it is a symlink to 
-	     * directory outside the operating directory. */
-	    if (check_operating_dir(filelist[selected], FALSE)) {
-		statusbar(_("Can't go outside of %s in restricted mode"),
+		/* Note: the selected file can be outside the operating
+		 * directory if it's ".." or if it's a symlink to a
+		 * directory outside the operating directory. */
+		if (check_operating_dir(filelist[selected], FALSE)) {
+		    statusbar(
+			_("Can't go outside of %s in restricted mode"),
 			operating_dir);
-		beep();
-		break;
-	    }
+		    beep();
+		    break;
+		}
 #endif
 
-	    if (stat(filelist[selected], &st) == -1) {
-		statusbar(_("Can't open \"%s\": %s"), filelist[selected],
-			strerror(errno));
-		beep();
-		break;
-	    }
-
-	    if (!S_ISDIR(st.st_mode)) {
-		retval = mallocstrcpy(retval, filelist[selected]);
-		abort = 1;
-		break;
-	    }
+		if (stat(filelist[selected], &st) == -1) {
+		    statusbar(_("Error reading %s: %s"),
+			filelist[selected], strerror(errno));
+		    beep();
+		    break;
+		}
 
-	    new_path = mallocstrcpy(NULL, filelist[selected]);
+		if (!S_ISDIR(st.st_mode)) {
+		    retval = mallocstrcpy(retval, filelist[selected]);
+		    abort = TRUE;
+		    break;
+		}
 
-	    if (strcmp("..", tail(new_path)) == 0) {
-		/* They want to go up a level, so strip off .. and the
-		   current dir */
-		striponedir(new_path);
-		/* SPK for '.' path, get the current path via getcwd */
-		if (strcmp(new_path, ".") == 0) {
-		    free(new_path);
-		    new_path = getcwd(NULL, PATH_MAX + 1);
+		dir = opendir(filelist[selected]);
+		if (dir == NULL) {
+		    /* We can't open this dir for some reason.
+		     * Complain. */
+		    statusbar(_("Error reading %s: %s"),
+			filelist[selected], strerror(errno));
+		    break;
 		}
-		striponedir(new_path);
-	    }
 
-	    if (!readable_dir(new_path)) {
-		/* We can't open this dir for some reason.  Complain */
-		statusbar(_("Can't open \"%s\": %s"), new_path,
-			strerror(errno));
-		free(new_path);
-		break;
-	    }
+		path = mallocstrcpy(path, filelist[selected]);
 
-	    free_charptrarray(filelist, numents);
-	    free(foo);
-	    free(path);
-	    path = new_path;
-	    return do_browser(path);
-
-	/* Go to a specific directory */
-	case NANO_GOTOLINE_KEY:
-	case NANO_GOTOLINE_FKEY:
-	case 'G': /* Pico compatibility */
-	case 'g':
-	    curs_set(1);
-	    j = statusq(FALSE, gotodir_list, "",
+		/* Start over again with the new path value. */
+		free_charptrarray(filelist, numents);
+		goto change_browser_directory;
+
+	    /* Go to a specific directory. */
+	    case NANO_GOTOLINE_KEY:
+	    case NANO_GOTOLINE_FKEY:
+	    case 'G': /* Pico compatibility. */
+	    case 'g':
+		curs_set(1);
+
+		j = statusq(FALSE, gotodir_list, "",
 #ifndef NANO_SMALL
-		NULL,
+			NULL,
 #endif
-		_("Go To Directory"));
-	    bottombars(browser_list);
-	    curs_set(0);
+			_("Go To Directory"));
 
-	    if (j < 0) {
-		statusbar(_("Cancelled"));
-		break;
-	    }
+		curs_set(0);
+		bottombars(browser_list);
 
-	    new_path = real_dir_from_tilde(answer);
+		if (j < 0) {
+		    statusbar(_("Cancelled"));
+		    break;
+		}
 
-	    if (new_path[0] != '/') {
-		new_path = charealloc(new_path, strlen(path) + strlen(answer) + 2);
-		sprintf(new_path, "%s/%s", path, answer);
-	    }
+		new_path = real_dir_from_tilde(answer);
+
+		if (new_path[0] != '/') {
+		    new_path = charealloc(new_path, strlen(path) +
+			strlen(answer) + 1);
+		    sprintf(new_path, "%s%s", path, answer);
+		}
 
 #ifndef DISABLE_OPERATINGDIR
-	    if (check_operating_dir(new_path, FALSE)) {
-		statusbar(_("Can't go outside of %s in restricted mode"), operating_dir);
-		free(new_path);
-		break;
-	    }
+		if (check_operating_dir(new_path, FALSE)) {
+		    statusbar(
+			_("Can't go outside of %s in restricted mode"),
+			operating_dir);
+		    free(new_path);
+		    break;
+		}
 #endif
 
-	    if (!readable_dir(new_path)) {
-		/* We can't open this dir for some reason.  Complain */
-		statusbar(_("Can't open \"%s\": %s"), answer, strerror(errno));
-		free(new_path);
-		break;
-	    }
+		dir = opendir(new_path);
+		if (dir == NULL) {
+		    /* We can't open this dir for some reason.
+		     * Complain. */
+		    statusbar(_("Error reading %s: %s"), answer,
+			strerror(errno));
+		    free(new_path);
+		    break;
+		}
 
-	    /* Start over again with the new path value */
-	    free_charptrarray(filelist, numents);
-	    free(foo);
-	    free(path);
-	    path = new_path;
-	    return do_browser(path);
-
-	/* Stuff we want to abort the browser */
-	case NANO_CANCEL_KEY:
-	case NANO_EXIT_KEY:
-	case NANO_EXIT_FKEY:
-	case 'E': /* Pico compatibility */
-	case 'e':
-	    abort = 1;
-	    break;
+		/* Start over again with the new path value. */
+		free(path);
+		path = new_path;
+		free_charptrarray(filelist, numents);
+		goto change_browser_directory;
+
+	    /* Abort the browser. */
+	    case NANO_CANCEL_KEY:
+	    case NANO_EXIT_KEY:
+	    case NANO_EXIT_FKEY:
+	    case 'E': /* Pico compatibility. */
+	    case 'e':
+		abort = TRUE;
+		break;
 	}
+
 	if (abort)
 	    break;
 
 	blank_edit();
 
 	if (width != 0)
-	    i = width * editwinrows * ((selected / width) / editwinrows);
+	    j = width * editwinrows *
+		((selected / width) / editwinrows);
 	else
-	    i = 0;
+	    j = 0;
 
 	wmove(edit, 0, 0);
-	for (j = i; j < numents && editline <= editwinrows - 1; j++) {
-	    filecols++;
-
-	    strncpy(foo, tail(filelist[j]), strlen(tail(filelist[j])) + 1);
-	    while (strlen(foo) < longest)
-		strcat(foo, " ");
-	    col += strlen(foo);
-
-	    /* Put file info in the string also */
-	    /* We use lstat here to detect links; then, if we find a
-		symlink, we examine it via stat() to see if it is a
-		directory or just a file symlink */
-	    lstat(filelist[j], &st);
-	    if (S_ISDIR(st.st_mode))
-		strcpy(foo + longest - 5, "(dir)");
-	    else {
-		if (S_ISLNK(st.st_mode)) {
-		     /* Aha!  It's a symlink!  Now, is it a dir?  If so,
-			mark it as such */
-		    stat(filelist[j], &st);
-		    if (S_ISDIR(st.st_mode))
-			strcpy(foo + longest - 5, "(dir)");
-		    else
-			strcpy(foo + longest - 2, "--");
-		} else if (st.st_size < (1 << 10)) /* less than 1 K */
-		    sprintf(foo + longest - 7, "%4d  B", 
-			(int) st.st_size);
-		else if (st.st_size >= (1 << 30)) /* at least 1 gig */
-		    sprintf(foo + longest - 7, "%4d GB", 
-			(int) st.st_size >> 30);
-		else if (st.st_size >= (1 << 20)) /* at least 1 meg */
-		    sprintf(foo + longest - 7, "%4d MB", 
-			(int) st.st_size >>     20);
-		else /* It's more than 1 k and less than a meg */
-		    sprintf(foo + longest - 7, "%4d KB", 
-			(int) st.st_size >> 10);
-	    }
 
-	    /* Highlight the currently selected file/dir */
-	    if (j == selected)
-		wattron(edit, A_REVERSE);
-	    waddstr(edit, foo);
-	    if (j == selected)
-		wattroff(edit, A_REVERSE);
-
-	    /* And add some space between the cols */
-	    waddstr(edit, "  ");
-	    col += 2;
-
-	    /* And if the next entry isn't going to fit on the
-		line, move to the next one */
-	    if (col > COLS - longest) {
-		editline++;
-		wmove(edit, editline, 0);
-		col = 0;
-		if (width == 0)
-		    width = filecols;
+	{
+	    int foo_len = mb_cur_max() * 7;
+	    char *foo = charalloc(foo_len + 1);
+
+	    for (; j < numents && editline <= editwinrows - 1; j++) {
+		char *disp = display_string(tail(filelist[j]), 0,
+			longest, FALSE);
+
+		/* Highlight the currently selected file/dir. */
+		if (j == selected)
+		    wattron(edit, A_REVERSE);
+
+		mvwaddnstr(edit, editline, col, hblank, longest);
+		mvwaddstr(edit, editline, col, disp);
+		free(disp);
+
+		col += longest;
+		filecols++;
+
+		/* Show file info also.  We don't want to report file
+		 * sizes for links, so we use lstat().  Also, stat() and
+		 * lstat() return an error if, for example, the file is
+		 * deleted while the file browser is open.  In that
+		 * case, we report "--" as the file info. */
+		if (lstat(filelist[j], &st) == -1 ||
+			S_ISLNK(st.st_mode)) {
+		    /* Aha!  It's a symlink!  Now, is it a dir?  If so,
+		     * mark it as such. */
+		    if (stat(filelist[j], &st) == 0 &&
+			S_ISDIR(st.st_mode)) {
+			strncpy(foo, _("(dir)"), foo_len);
+			foo[foo_len] = '\0';
+		    } else
+			strcpy(foo, "--");
+		} else if (S_ISDIR(st.st_mode))
+		    strncpy(foo, _("(dir)"), foo_len);
+		else if (st.st_size < (1 << 10)) /* less than 1 k. */
+		    sprintf(foo, "%4u  B", (unsigned int)st.st_size);
+		else if (st.st_size < (1 << 20)) /* less than 1 meg. */
+		    sprintf(foo, "%4u KB",
+			(unsigned int)(st.st_size >> 10));
+		else if (st.st_size < (1 << 30)) /* less than 1 gig. */
+		    sprintf(foo, "%4u MB",
+			(unsigned int)(st.st_size >> 20));
+		else
+		    sprintf(foo, "%4u GB",
+			(unsigned int)(st.st_size >> 30));
+
+		mvwaddnstr(edit, editline, col - strlen(foo), foo,
+			foo_len);
+
+		if (j == selected)
+		    wattroff(edit, A_REVERSE);
+
+		/* Add some space between the columns. */
+		col += 2;
+
+		/* If the next entry isn't going to fit on the line,
+		 * move to the next line. */
+		if (col > COLS - longest) {
+		    editline++;
+		    col = 0;
+		    if (width == 0)
+			width = filecols;
+		}
+		wmove(edit, editline, col);
 	    }
+
+	    free(foo);
 	}
+
 	wrefresh(edit);
     } while ((kbinput = get_kbinput(edit, &meta_key, &func_key)) !=
 	NANO_EXIT_KEY && kbinput != NANO_EXIT_FKEY);
-    curs_set(1);
+
     blank_edit();
     titlebar(NULL);
     edit_refresh();
+    curs_set(1);
+    if (old_constupdate)
+	SET(CONSTUPDATE);
 
-    /* cleanup */
+    /* Clean up. */
     free_charptrarray(filelist, numents);
-    free(foo);
+    free(path);
+
     return retval;
 }
 
-/* Browser front end, checks to see if inpath has a dir in it and, if so,
- starts do_browser from there, else from the current dir */
+/* Browser front end, checks to see if inpath has a dir in it and, if
+   so, starts do_browser from there, else from the current dir */
 char *do_browse_from(const char *inpath)
 {
     struct stat st;
-    char *bob;
-	/* The result of do_browser; the selected file name. */
     char *path;
-	/* inpath, tilde expanded. */
+	/* This holds the tilde-expanded version of inpath. */
+    DIR *dir;
 
     assert(inpath != NULL);
 
     path = real_dir_from_tilde(inpath);
 
-    /*
-     * Perhaps path is a directory.  If so, we will pass that to
-     * do_browser.  Otherwise, perhaps path is a directory / a file.  So
-     * we try stripping off the last path element.  If it still isn't a
-     * directory, just use the current directory. */
-
+    /* Perhaps path is a directory.  If so, we'll pass it to
+     * do_browser().  Or perhaps path is a directory / a file.  If so,
+     * we'll try stripping off the last path element and passing it to
+     * do_browser().  Or perhaps path doesn't have a directory portion
+     * at all.  If so, we'll just pass the current directory to
+     * do_browser(). */
     if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
 	striponedir(path);
 	if (stat(path, &st) == -1 || !S_ISDIR(st.st_mode)) {
 	    free(path);
-	    path = getcwd(NULL, PATH_MAX + 1);
+#if PATH_MAX != -1
+	    path = charalloc(PATH_MAX + 1);
+#else
+	    path = NULL;
+#endif
+	    path = getcwd(path, PATH_MAX + 1);
+#if PATH_MAX != -1
+	    align(&path);
+#endif
 	}
     }
 
 #ifndef DISABLE_OPERATINGDIR
-    /* If the resulting path isn't in the operating directory, use that. */
-    if (check_operating_dir(path, FALSE))
-	path = mallocstrcpy(path, operating_dir);
+    /* If the resulting path isn't in the operating directory, use
+     * the operating directory instead. */
+    if (check_operating_dir(path, FALSE)) {
+	if (path != NULL)
+	    free(path);
+	path = mallocstrcpy(NULL, operating_dir);
+    }
 #endif
 
-    if (!readable_dir(path)) {
+    dir = opendir(path);
+    if (dir == NULL) {
 	beep();
-	bob = NULL;
-    } else
-	bob = do_browser(path);
-    free(path);
-    return bob;
+	free(path);
+	return NULL;
+    }
+
+    return do_browser(path, dir);
 }
 #endif /* !DISABLE_BROWSER */
 
@@ -2791,8 +2835,10 @@ void load_history(void)
 	    if (errno != ENOENT) {
 		/* Don't save history when we quit. */
 		UNSET(HISTORYLOG);
-		rcfile_error(N_("Error reading %s: %s"), nanohist, strerror(errno));
-		fprintf(stderr, _("\nPress Return to continue starting nano\n"));
+		rcfile_error(N_("Error reading %s: %s"), nanohist,
+			strerror(errno));
+		fprintf(stderr,
+			_("\nPress Return to continue starting nano\n"));
 		while (getchar() != '\n')
 		    ;
 	    }
@@ -2853,7 +2899,8 @@ void save_history(void)
 	FILE *hist = fopen(nanohist, "wb");
 
 	if (hist == NULL)
-	    rcfile_error(N_("Error writing %s: %s"), nanohist, strerror(errno));
+	    rcfile_error(N_("Error writing %s: %s"), nanohist,
+		strerror(errno));
 	else {
 	    /* set rw only by owner for security ?? */
 	    chmod(nanohist, S_IRUSR | S_IWUSR);
@@ -2861,7 +2908,8 @@ void save_history(void)
 	    if (!writehist(hist, &search_history) ||
 		    putc('\n', hist) == EOF ||
 		    !writehist(hist, &replace_history))
-		rcfile_error(N_("Error writing %s: %s"), nanohist, strerror(errno));
+		rcfile_error(N_("Error writing %s: %s"), nanohist,
+			strerror(errno));
 	    fclose(hist);
 	}
 	free(nanohist);
diff --git a/src/proto.h b/src/proto.h
index 57cd1c7140d15db2a2b568eb36bf1751e1db9ae4..b7897cd3bf9d506ca19b04c2332680b7c5b7fa47 100644
--- a/src/proto.h
+++ b/src/proto.h
@@ -23,6 +23,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <dirent.h>
 #ifdef HAVE_REGEX_H
 #include <regex.h>
 #endif
@@ -298,10 +299,10 @@ char *input_tab(char *buf, size_t *place, bool *lastwastab, bool *list);
 const char *tail(const char *foo);
 #ifndef DISABLE_BROWSER
 void free_charptrarray(char **array, size_t len);
-void striponedir(char *foo);
-int readable_dir(const char *path);
-char **browser_init(const char *path, int *longest, int *numents);
-char *do_browser(const char *inpath);
+void striponedir(char *path);
+char **browser_init(const char *path, int *longest, size_t *numents, DIR
+	*dir);
+char *do_browser(char *path, DIR *dir);
 char *do_browse_from(const char *inpath);
 #endif
 #if !defined(NANO_SMALL) && defined(ENABLE_NANORC)