diff --git a/ChangeLog b/ChangeLog
index 2bf8b2181c374ed5b62b8e01c489a3c6e5f58d08..029a69a405c96363c0cd56b2b6b71d31ead057be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,13 +11,27 @@ CVS code -
 	  need to keep the translatable strings, and (b) added a
 	  variable inspath to keep track of what the string was before
 	  toggling.  I'm sure there's bugs, have at it.
+ 	- Make sure all functions have prototypes in proto.h, and swap
+ 	  some functions around to put similar functions closer
+ 	  together (for this, rename clear_bottombars() to
+ 	  blank_bottombars()). (DLR; suggested by David Benbennick)
 - configure.ac:
 	- Added pt_BR to ALL_LINGUAS (Jordi).
 	- Changed --enable-color warning to be slightly less severe.
+ 	- Put the configure options in more or less alphabetical order,
+ 	  and remove --enable-undo, since it doesn't do anything. (DLR)
 - files.c:
   open_file()
 	- String change: "File "x" is a directory" -> ""x" is a
 	  directory". (Jordi)
+  do_insertfile()
+	- Disallow multibuffer toggling at the "Insert File" prompt if
+	  we're in both view and multibuffer mode, so as to keep proper
+	  integration between the two, and make sure the toggle
+	  actually works all the time otherwise.  Also, use
+	  NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so
+	  --enable-tiny and --enable-multibuffer can be used together
+	  again. (DLR)
   open_prevfile_void(), open_nextfile_void()
 	- Return the return values of open_prevfile() and
 	  open_nextfile(), respectively, instead of (incorrectly)
@@ -29,6 +43,14 @@ CVS code -
 	- Most likely fixed the check marked with FIXME, so that tab
 	  completion works properly when we're trying to tab-complete a
 	  username and the string already contains data. (DLR)
+- global.c:
+  shortcut_init()
+	- Use NANO_LOAD_KEY as an alias for TOGGLE_LOAD_KEY, so
+	  --enable-tiny and --enable-multibuffer can be used together
+	  again. (DLR)
+  thanks_for_all_the_fish()
+	- Make sure the reference to help_text is #ifdefed out when
+	  --disable-help is used. (DLR) 
 - move.c:
   page_up()
 	- Fix bug where current is moved up two lines when the up arrow
@@ -42,6 +64,12 @@ CVS code -
 	  off, pressing the down arrow on that last line centers the
 	  cursor without updating the edit window. (Jeff DeFouw)
 - nano.c:
+  version()
+	- Put the listed configure options in more or less alphabetical
+	  order. (DLR)
+  open_pipe()
+	- If we're in view mode here (in which case we're also in
+	  multibuffer mode), don't set the modification flag. (DLR)
   do_next_word(), do_prev_word()
   	- If we're on the last/first line of the file, don't center the
   	  screen; Pico doesn't in the former case. (DLR)
@@ -65,6 +93,10 @@ CVS code -
   do_justify()
 	- Fix cosmetic problems caused when justifying on the
 	  magicline. (David Benbennick)
+  main()
+	- When searching through the main shortcut list looking for a
+	  shortcut key, stop searching after finding one; this avoids a
+	  rare segfault. (DLR)
 - nano.h:
 	- Change search toggles for case sensitive searching and regexp
 	  searching to M-C and M-R, respectively. (DLR; suggested by
diff --git a/configure.ac b/configure.ac
index 15186eee6130067684b8a851da4c8f082083fc59..3edbe57c79bd820f3fa1fe448ebc24a45d7002fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,70 +29,55 @@ if test "$debug_support" != "yes"; then
     AC_DEFINE(NDEBUG, 1, [Shut up the assert warnings :-)]) 
 fi
 
+AC_ARG_ENABLE(extra,
+[  --enable-extra          Enable extra (optional) functions, including easter eggs],
+[if test x$enableval = xyes; then
+    AC_DEFINE(NANO_EXTRA, 1, [Define this to enable the extra stuff.]) extra_support=yes
+    AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
+ fi])
+
 AC_ARG_ENABLE(tiny,
 [  --enable-tiny           Disable features for the sake of size
                           (currently disables detailed help and i18n)],
 [if test x$enableval = xyes; then
     AC_DEFINE(NANO_SMALL, 1, [Define this to make the nano executable as small as possible.]) tiny_support=yes
-    AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!]) 
-    AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.]) 
+    AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.]) 
     AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.]) 
     AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.]) 
-    AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.]) 
     AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.]) 
     AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).]) 
+    AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.]) 
+    AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!]) 
  fi])
 
-AC_ARG_ENABLE(extra,
-[  --enable-extra          Enable extra (optional) functions, including easter eggs],
-[if test x$enableval = xyes; then
-    AC_DEFINE(NANO_EXTRA, 1, [Define this to enable the extra stuff.]) extra_support=yes
-    AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
-    AC_DEFINE(ENABLE_UNDO, 1, [Define this to enable undoing... something]) undo_support=yes
- fi])
-
-AC_ARG_ENABLE(undo,
-[  --enable-undo           Enable undo support],
-[if test x$enableval = xyes && test x$tiny_support != xyes; then
-    AC_DEFINE(ENABLE_UNDO, 1, [Define this to enable undoing... something.]) undo_support=yes
+AC_ARG_ENABLE(browser,
+[  --disable-browser       Disable mini file browser],
+ [if test x$enableval != xyes; then
+    AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
  fi])
 
-AC_ARG_ENABLE(multibuffer,
-[  --enable-multibuffer    Enable multiple file buffers],
-[if test x$enableval = xyes; then
-    AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
+AC_ARG_ENABLE(help,
+[  --disable-help          Disable help function (^G)],
+ [if test x$enableval != xyes; then
+    AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
  fi])
 
-AC_ARG_ENABLE(nanorc,
-[  --enable-nanorc         Enable use of .nanorc file],
-[if test x$enableval = xyes; then
-    AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
+AC_ARG_ENABLE(justify,
+[  --disable-justify       Disable justify/unjustify function],
+ [if test x$enableval != xyes; then
+    AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.]) 
  fi])
 
-AC_ARG_ENABLE(color,
-[  --enable-color          Enable color and syntax highlighting],
-[if test x$enableval = xyes; then
-    AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
-    AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting, requires ENABLE_NANORC too!]) color_support=yes
-    AC_MSG_WARN([
-
-***********************************************************************
-*** WARNING: Color support is far from perfect, but functional.     ***
-*** Be careful with syntax in your .nanorc or nano may malfunction. ***
-***********************************************************************
-])
-fi])
-
-AC_ARG_ENABLE(tabcomp,
-[  --disable-tabcomp       Disable tab completion code for a smaller binary],
+AC_ARG_ENABLE(mouse,
+[  --disable-mouse         Disable mouse support (and -m flag)],
  [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!]) 
+    AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
  fi])
 
-AC_ARG_ENABLE(justify,
-[  --disable-justify       Disable justify/unjustify function],
+AC_ARG_ENABLE(operatingdir,
+[  --disable-operatingdir  Disable setting of operating directory (chroot of sorts)],
  [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_JUSTIFY, 1, [Define this to disable the justify routine.]) 
+    AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
  fi])
 
 AC_ARG_ENABLE(speller,
@@ -101,16 +86,10 @@ AC_ARG_ENABLE(speller,
     AC_DEFINE(DISABLE_SPELLER, 1, [Define this to disable the use(full|less) spelling functions.])
  fi])
 
-AC_ARG_ENABLE(help,
-[  --disable-help          Disable help function (^G)],
- [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_HELP, 1, [Define this to disable the ^G help menu.])
- fi])
-
-AC_ARG_ENABLE(browser,
-[  --disable-browser       Disable mini file browser],
+AC_ARG_ENABLE(tabcomp,
+[  --disable-tabcomp       Disable tab completion code for a smaller binary],
  [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_BROWSER, 1, [Define this to disable the built-in (crappy) file browser.])
+    AC_DEFINE(DISABLE_TABCOMP, 1, [Define to disable the tab completion code Chris worked so hard on!]) 
  fi])
 
 AC_ARG_ENABLE(wrapping,
@@ -119,16 +98,30 @@ AC_ARG_ENABLE(wrapping,
     AC_DEFINE(DISABLE_WRAPPING, 1, [Define this to disable any and all text wrapping.])
  fi])
 
-AC_ARG_ENABLE(mouse,
-[  --disable-mouse         Disable mouse support (and -m flag)],
- [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_MOUSE, 1, [Define this to disable the mouse functions.])
+AC_ARG_ENABLE(color,
+[  --enable-color          Enable color and syntax highlighting],
+[if test x$enableval = xyes; then
+    AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
+    AC_DEFINE(ENABLE_COLOR, 1, [Define this to have syntax highlighting, requires ENABLE_NANORC too!]) color_support=yes
+    AC_MSG_WARN([
+
+***********************************************************************
+*** WARNING: Color support is far from perfect, but functional.     ***
+*** Be careful with syntax in your .nanorc or nano may malfunction. ***
+***********************************************************************
+])
+fi])
+
+AC_ARG_ENABLE(multibuffer,
+[  --enable-multibuffer    Enable multiple file buffers],
+[if test x$enableval = xyes; then
+    AC_DEFINE(ENABLE_MULTIBUFFER, 1, [Define this to enable multiple file buffers.]) multibuffer_support=yes
  fi])
 
-AC_ARG_ENABLE(operatingdir,
-[  --disable-operatingdir  Disable setting of operating directory (chroot of sorts)],
- [if test x$enableval != xyes; then
-    AC_DEFINE(DISABLE_OPERATINGDIR, 1, [Define this to disable setting of the operating directory (chroot of sorts).])
+AC_ARG_ENABLE(nanorc,
+[  --enable-nanorc         Enable use of .nanorc file],
+[if test x$enableval = xyes; then
+    AC_DEFINE(ENABLE_NANORC, 1, [Define this to use the .nanorc file.]) nanorc_support=yes
  fi])
 
 AC_MSG_CHECKING([whether to use slang])
diff --git a/files.c b/files.c
index 46d48640ba7f8426f8deb6486326d952e0ea3d9f..7dff3ba90a437600b8a33f8cc6806301ffe1ec77 100644
--- a/files.c
+++ b/files.c
@@ -103,7 +103,6 @@ void new_file(void)
 #ifdef ENABLE_COLOR
     update_color();
 #endif
-
 }
 
 filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len)
@@ -453,14 +452,11 @@ int do_insertfile(int loading_file)
 	    i = statusq(1, insertfile_list, inspath, _("File to insert [from ./] "));
 
     if (i != -1) {
-
 	inspath = mallocstrcpy(inspath, answer);
-
 #ifdef DEBUG
 	fprintf(stderr, _("filename is %s\n"), answer);
 #endif
 
-
 #ifndef DISABLE_TABCOMP
 	realname = real_dir_from_tilde(answer);
 #else
@@ -494,9 +490,12 @@ int do_insertfile(int loading_file)
 #endif
 
 #ifdef ENABLE_MULTIBUFFER
-	if (i == TOGGLE_LOAD_KEY) {
-	    TOGGLE(MULTIBUFFER);
-	    return do_insertfile(loading_file);
+	if (i == NANO_LOAD_KEY) {
+	    /* don't allow toggling if we're in both view mode and
+	       multibuffer mode now */
+	    if (!ISSET(VIEW_MODE) || !ISSET(MULTIBUFFER))
+		TOGGLE(MULTIBUFFER);
+	    return do_insertfile(ISSET(MULTIBUFFER));
 	}
 #endif
 #ifndef NANO_SMALL
@@ -574,8 +573,6 @@ int do_insertfile(int loading_file)
 	}
 #endif
 
-	
-
 	/* If we've gone off the bottom, recenter; otherwise, just redraw */
 	if (current->lineno > editbot->lineno)
 	    edit_update(current, CENTER);
@@ -1139,8 +1136,8 @@ char *get_full_path(char *origpath)
  * get_full_path()).  On error, if the path doesn't reference a
  * directory, or if the directory isn't writable, it returns NULL.
  */
-char *check_writable_directory(char *path) {
-
+char *check_writable_directory(char *path)
+{
     char *full_path = get_full_path(path);
     int writable;
     struct stat fileinfo;
@@ -1178,8 +1175,8 @@ char *check_writable_directory(char *path) {
  * implementation is to go on generating random filenames regardless of
  * it.
  */
-char *safe_tempnam(const char *dirname, const char *filename_prefix) {
-
+char *safe_tempnam(const char *dirname, const char *filename_prefix)
+{
     char *buf, *tempdir = NULL, *full_tempdir = NULL;
     int filedesc;
 
@@ -2221,6 +2218,12 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list)
 	    buf = mallocstrcpy(buf, tmp);
 	    matches = username_tab_completion(tmp, &num_matches);
 	}
+	/* If we're in the middle of the original line, copy the string
+	   only up to the cursor position into buf, so tab completion
+	   will result in buf's containing only the tab-completed
+	   path/filename. */
+	else if (strlen(buf) > strlen(tmp))
+	    buf = mallocstrcpy(buf, tmp);
 
 	/* Try to match everything in the current working directory that
 	 * matches.  */
@@ -2416,51 +2419,6 @@ int diralphasort(const void *va, const void *vb)
 
 }
 
-/* Initialize the browser code, including the list of files in *path */
-char **browser_init(char *path, int *longest, int *numents)
-{
-    DIR *dir;
-    struct dirent *next;
-    char **filelist = (char **) NULL;
-    int i = 0;
-
-    dir = opendir(path);
-    if (!dir) 
-	return NULL;
-
-    *numents = 0;
-    while ((next = readdir(dir)) != NULL) {
-	if (!strcmp(next->d_name, "."))
-	   continue;
-	(*numents)++;
-	if (strlen(next->d_name) > *longest)
-	    *longest = strlen(next->d_name);
-    }
-    rewinddir(dir);
-    *longest += 10;
-
-    filelist = nmalloc(*numents * sizeof (char *));
-
-    while ((next = readdir(dir)) != NULL) {
-	if (!strcmp(next->d_name, "."))
-	   continue;
-	filelist[i] = charalloc(strlen(next->d_name) + strlen(path) + 2);
-
-	if (!strcmp(path, "/"))
-	    snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 1, 
-			"%s%s", path, next->d_name);
-	else
-	    snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 2, 
-			"%s/%s", path, next->d_name);
-	i++;
-    }
-
-    if (*longest > COLS - 1)
-	*longest = COLS - 1;
-
-    return filelist;
-}
-
 /* Free our malloc()ed memory */
 void free_charptrarray(char **array, int len)
 {
@@ -2513,6 +2471,51 @@ void striponedir(char *foo)
     return;
 }
 
+/* Initialize the browser code, including the list of files in *path */
+char **browser_init(char *path, int *longest, int *numents)
+{
+    DIR *dir;
+    struct dirent *next;
+    char **filelist = (char **) NULL;
+    int i = 0;
+
+    dir = opendir(path);
+    if (!dir) 
+	return NULL;
+
+    *numents = 0;
+    while ((next = readdir(dir)) != NULL) {
+	if (!strcmp(next->d_name, "."))
+	   continue;
+	(*numents)++;
+	if (strlen(next->d_name) > *longest)
+	    *longest = strlen(next->d_name);
+    }
+    rewinddir(dir);
+    *longest += 10;
+
+    filelist = nmalloc(*numents * sizeof (char *));
+
+    while ((next = readdir(dir)) != NULL) {
+	if (!strcmp(next->d_name, "."))
+	   continue;
+	filelist[i] = charalloc(strlen(next->d_name) + strlen(path) + 2);
+
+	if (!strcmp(path, "/"))
+	    snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 1, 
+			"%s%s", path, next->d_name);
+	else
+	    snprintf(filelist[i], strlen(next->d_name) + strlen(path) + 2, 
+			"%s/%s", path, next->d_name);
+	i++;
+    }
+
+    if (*longest > COLS - 1)
+	*longest = COLS - 1;
+
+    return filelist;
+}
+
 /* Our browser function.  inpath is the path to start browsing from */
 char *do_browser(char *inpath)
 {
diff --git a/global.c b/global.c
index 83691d5a7d6710cadf598bb9707e0057335d01ad..7a9cf7259ed4435244536a6be95e92694a4fca06 100644
--- a/global.c
+++ b/global.c
@@ -217,19 +217,6 @@ void toggle_init_one(int val, const char *desc, int flag)
     u->next = NULL;
 }
 
-#ifdef DEBUG
-/* Deallocate all of the toggles. */
-void free_toggles(void)
-{
-    while (toggles != NULL) {
-	toggle *pt = toggles;	/* Think "previous toggle" */
-
-	toggles = toggles->next;
-	free(pt);
-    }
-}
-#endif
-
 void toggle_init(void)
 {
     char *toggle_const_msg, *toggle_autoindent_msg, *toggle_suspend_msg,
@@ -288,6 +275,19 @@ void toggle_init(void)
     toggle_init_one(TOGGLE_BACKUP_KEY, toggle_backup_msg, BACKUP_FILE);
     toggle_init_one(TOGGLE_SMOOTH_KEY, toggle_smooth_msg, SMOOTHSCROLL);
 }
+
+#ifdef DEBUG
+/* Deallocate all of the toggles. */
+void free_toggles(void)
+{
+    while (toggles != NULL) {
+	toggle *pt = toggles;	/* Think "previous toggle" */
+
+	toggles = toggles->next;
+	free(pt);
+    }
+}
+#endif
 #endif /* !NANO_SMALL */
 
 /* Deallocate the given shortcut. */
@@ -325,8 +325,8 @@ void shortcut_init(int unjustify)
 	"", *nano_backup_msg = "";
 
 #ifdef ENABLE_MULTIBUFFER
-    char *nano_openprev_msg = "", *nano_opennext_msg = "",
-	*nano_multibuffer_msg = "";
+    char *nano_openprev_msg = "", *nano_opennext_msg =
+	"", *nano_multibuffer_msg = "";
 #endif
 #ifdef HAVE_REGEX_H
     char *nano_regexp_msg = "", *nano_bracket_msg = "";
@@ -727,7 +727,7 @@ void shortcut_init(int unjustify)
 		IFHELP(nano_execute_msg, 0), 0, 0, NOVIEW, 0);
 #endif
 #ifdef ENABLE_MULTIBUFFER
-    sc_init_one(&insertfile_list, TOGGLE_LOAD_KEY, _("New Buffer"),
+    sc_init_one(&insertfile_list, NANO_LOAD_KEY, _("New Buffer"),
 		IFHELP(nano_multibuffer_msg, 0), 0, 0, NOVIEW, 0);
 #endif
 
@@ -811,8 +811,10 @@ void thanks_for_all_the_fish(void)
     if (alt_speller != NULL)
 	free(alt_speller);
 #endif
+#ifndef DISABLE_HELP
     if (help_text != NULL)
 	free(help_text);
+#endif
     if (filename != NULL)
 	free(filename);
     if (answer != NULL)
diff --git a/move.c b/move.c
index 27ed9ea3d2a21c35fc6e130b5e2e015e4ead651d..d70edad6d25417cf023994f63d97ce999bffe7ba 100644
--- a/move.c
+++ b/move.c
@@ -35,43 +35,6 @@
 #define _(string) (string)
 #endif
 
-int do_page_down(void)
-{
-    wrap_reset();
-    current_x = 0;
-    placewewant = 0;
-
-    if (current == filebot)
-	return 0;
-
-    /* AHEM, if we only have a screen or less of text, DON'T do an
-       edit_update, just move the cursor to editbot! */
-    if (edittop == fileage && editbot == filebot && totlines < editwinrows) {
-	current = editbot;
-	reset_cursor();
-    } else if (editbot != filebot || edittop == fileage) {
-	current_y = 0;
-	current = editbot;
-
-	if (current->prev != NULL)
-	    current = current->prev;
-	if (current->prev != NULL)
-	    current = current->prev;
-	edit_update(current, TOP);
-    } else {
-	while (current != filebot) {
-	    current = current->next;
-	    current_y++;
-	}
-	edit_update(edittop, TOP);
-    }
-
-    update_cursor();
-    UNSET(KEEP_CUTBUFFER);
-    check_statblank();
-    return 1;
-}
-
 int do_home(void)
 {
     UNSET(KEEP_CUTBUFFER);
@@ -138,6 +101,43 @@ int do_page_up(void)
     return 1;
 }
 
+int do_page_down(void)
+{
+    wrap_reset();
+    current_x = 0;
+    placewewant = 0;
+
+    if (current == filebot)
+	return 0;
+
+    /* AHEM, if we only have a screen or less of text, DON'T do an
+       edit_update, just move the cursor to editbot! */
+    if (edittop == fileage && editbot == filebot && totlines < editwinrows) {
+	current = editbot;
+	reset_cursor();
+    } else if (editbot != filebot || edittop == fileage) {
+	current_y = 0;
+	current = editbot;
+
+	if (current->prev != NULL)
+	    current = current->prev;
+	if (current->prev != NULL)
+	    current = current->prev;
+	edit_update(current, TOP);
+    } else {
+	while (current != filebot) {
+	    current = current->next;
+	    current_y++;
+	}
+	edit_update(edittop, TOP);
+    }
+
+    update_cursor();
+    UNSET(KEEP_CUTBUFFER);
+    check_statblank();
+    return 1;
+}
+
 int do_up(void)
 {
     wrap_reset();
@@ -197,15 +197,13 @@ int do_down(void) {
     return 1;
 }
 
-int do_right(void)
+int do_left(void)
 {
-    assert(current_x <= strlen(current->data));
-
-    if (current->data[current_x] != '\0')
-	current_x++;
-    else if (current->next) {
-	do_down();
-	current_x = 0;
+    if (current_x > 0)
+	current_x--;
+    else if (current != fileage) {
+	do_up();
+	current_x = strlen(current->data);
     }
     placewewant = xplustabs();
     update_line(current, current_x);
@@ -214,13 +212,15 @@ int do_right(void)
     return 1;
 }
 
-int do_left(void)
+int do_right(void)
 {
-    if (current_x > 0)
-	current_x--;
-    else if (current != fileage) {
-	do_up();
-	current_x = strlen(current->data);
+    assert(current_x <= strlen(current->data));
+
+    if (current->data[current_x] != '\0')
+	current_x++;
+    else if (current->next) {
+	do_down();
+	current_x = 0;
     }
     placewewant = xplustabs();
     update_line(current, current_x);
diff --git a/nano.c b/nano.c
index af63a7fd2562b5ca1603422513a64e74cab168a0..521850806717df104aa2ae4ef6e9b4b98f3c8999 100644
--- a/nano.c
+++ b/nano.c
@@ -222,6 +222,258 @@ void global_init(int save_cutbuffer)
     hblank[COLS] = '\0';
 }
 
+void window_init(void)
+{
+    if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
+	die_too_small();
+
+    /* Set up the main text window */
+    edit = newwin(editwinrows, COLS, 2, 0);
+
+    /* And the other windows */
+    topwin = newwin(2, COLS, 0, 0);
+    bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
+
+#ifdef PDCURSES
+    /* Oops, I guess we need this again.
+       Moved here so the keypad still works after a Meta-X, for example */
+    keypad(edit, TRUE);
+    keypad(bottomwin, TRUE);
+#endif
+}
+
+void mouse_init(void)
+{
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
+    if (ISSET(USE_MOUSE)) {
+	keypad_on(edit, 1);
+	keypad_on(bottomwin, 1);
+
+	mousemask(BUTTON1_RELEASED, NULL);
+	mouseinterval(50);
+    } else
+	mousemask(0, NULL);
+#endif
+#endif
+}
+
+#ifndef DISABLE_HELP
+/* This function allocates help_text, and stores the help string in it. 
+ * help_text should be NULL initially. */
+void help_init(void)
+{
+    size_t allocsize = 1;	/* space needed for help_text */
+    char *ptr = NULL;
+#ifndef NANO_SMALL
+    const toggle *t;
+#endif
+    const shortcut *s;
+
+    /* First set up the initial help text for the current function */
+    if (currshortcut == whereis_list || currshortcut == replace_list
+	     || currshortcut == replace_list_2)
+	ptr = _("Search Command Help Text\n\n "
+		"Enter the words or characters you would like to search "
+		"for, then hit enter.  If there is a match for the text you "
+		"entered, the screen will be updated to the location of the "
+		"nearest match for the search string.\n\n "
+		"If using Pico Mode via the -p or --pico flags, the "
+		"Meta-P toggle, or a nanorc file, the previous search "
+		"string will be shown in brackets after the Search: prompt.  "
+		"Hitting Enter without entering any text will perform the "
+		"previous search.  Otherwise, the previous string will be "
+		"placed before the cursor, and can be edited or deleted "
+		"before hitting enter.\n\n The following function keys are "
+		"available in Search mode:\n\n");
+    else if (currshortcut == goto_list)
+	ptr = _("Go To Line Help Text\n\n "
+		"Enter the line number that you wish to go to and hit "
+		"Enter.  If there are fewer lines of text than the "
+		"number you entered, you will be brought to the last line "
+		"of the file.\n\n The following function keys are "
+		"available in Go To Line mode:\n\n");
+    else if (currshortcut == insertfile_list)
+	ptr = _("Insert File Help Text\n\n "
+		"Type in the name of a file to be inserted into the current "
+		"file buffer at the current cursor location.\n\n "
+		"If you have compiled nano with multiple file buffer "
+		"support, and enable multiple buffers with the -F "
+		"or --multibuffer command line flags, the Meta-F toggle, or "
+		"a nanorc file, inserting a file will cause it to be "
+		"loaded into a separate buffer (use Meta-< and > to switch "
+		"between file buffers).\n\n If you need another blank "
+		"buffer, do not enter any filename, or type in a "
+		"nonexistent filename at the prompt and press "
+		"Enter.\n\n The following function keys are "
+		"available in Insert File mode:\n\n");
+    else if (currshortcut == writefile_list)
+	ptr = _("Write File Help Text\n\n "
+		"Type the name that you wish to save the current file "
+		"as and hit Enter to save the file.\n\n If you have "
+		"selected text with Ctrl-^, you will be prompted to "
+		"save only the selected portion to a separate file.  To "
+		"reduce the chance of overwriting the current file with "
+		"just a portion of it, the current filename is not the "
+		"default in this mode.\n\n The following function keys "
+		"are available in Write File mode:\n\n");
+#ifndef DISABLE_BROWSER
+    else if (currshortcut == browser_list)
+	ptr = _("File Browser Help Text\n\n "
+		"The file browser is used to visually browse the "
+		"directory structure to select a file for reading "
+		"or writing.  You may use the arrow keys or Page Up/"
+		"Down to browse through the files, and S or Enter to "
+		"choose the selected file or enter the selected "
+		"directory.  To move up one level, select the directory "
+		"called \"..\" at the top of the file list.\n\n The "
+		"following function keys are available in the file "
+		"browser:\n\n");
+    else if (currshortcut == gotodir_list)
+	ptr = _("Browser Go To Directory Help Text\n\n "
+		"Enter the name of the directory you would like to "
+		"browse to.\n\n If tab completion has not been disabled, "
+		"you can use the TAB key to (attempt to) automatically "
+		"complete the directory name.\n\n The following function "
+		"keys are available in Browser Go To Directory mode:\n\n");
+#endif
+    else if (currshortcut == spell_list)
+	ptr = _("Spell Check Help Text\n\n "
+		"The spell checker checks the spelling of all text "
+		"in the current file.  When an unknown word is "
+		"encountered, it is highlighted and a replacement can "
+		"be edited.  It will then prompt to replace every "
+		"instance of the given misspelled word in the "
+		"current file.\n\n The following other functions are "
+		"available in Spell Check mode:\n\n");
+#ifndef NANO_SMALL
+    else if (currshortcut == extcmd_list)
+	ptr = _("External Command Help Text\n\n "
+		"This menu allows you to insert the output of a command "
+		"run by the shell into the current buffer (or a new "
+		"buffer in multibuffer mode).\n\n The following keys are "
+		"available in this mode:\n\n");
+#endif
+    else /* Default to the main help list */
+	ptr = _(" nano help text\n\n "
+	  "The nano editor is designed to emulate the functionality and "
+	  "ease-of-use of the UW Pico text editor.  There are four main "
+	  "sections of the editor: The top line shows the program "
+	  "version, the current filename being edited, and whether "
+	  "or not the file has been modified.  Next is the main editor "
+	  "window showing the file being edited.  The status line is "
+	  "the third line from the bottom and shows important messages. "
+	  "The bottom two lines show the most commonly used shortcuts "
+	  "in the editor.\n\n "
+	  "The notation for shortcuts is as follows: Control-key "
+	  "sequences are notated with a caret (^) symbol and are entered "
+	  "with the Control (Ctrl) key.  Escape-key sequences are notated "
+	  "with the Meta (M) symbol and can be entered using either the "
+	  "Esc, Alt or Meta key depending on your keyboard setup.  The "
+	  "following keystrokes are available in the main editor window.  "
+	  "Alternative keys are shown in parentheses:\n\n");
+
+    allocsize += strlen(ptr);
+
+    /* The space needed for the shortcut lists, at most COLS characters,
+     * plus '\n'. */
+    allocsize += (COLS + 1) * length_of_list(currshortcut);
+
+#ifndef NANO_SMALL
+    /* If we're on the main list, we also count the toggle help text. 
+     * Each line has "M-%c\t\t\t", which fills 24 columns, plus at most
+     * COLS - 24 characters, plus '\n'.*/
+    if (currshortcut == main_list)
+	for (t = toggles; t != NULL; t = t->next)
+	    allocsize += COLS - 17;
+#endif /* !NANO_SMALL */
+
+    /* help_text has been freed and set to NULL unless the user resized
+     * while in the help screen. */
+    free(help_text);
+
+    /* Allocate space for the help text */
+    help_text = charalloc(allocsize);
+
+    /* Now add the text we want */
+    strcpy(help_text, ptr);
+    ptr = help_text + strlen(help_text);
+
+    /* Now add our shortcut info */
+    for (s = currshortcut; s != NULL; s = s->next) {
+	/* true if the character in s->altval is shown in first column */
+	int meta_shortcut = 0;
+
+	if (s->val > 0 && s->val < 32)
+	    ptr += sprintf(ptr, "^%c", s->val + 64);
+#ifndef NANO_SMALL
+	else if (s->val == NANO_CONTROL_SPACE)
+	    ptr += sprintf(ptr, "^%.6s", _("Space"));
+	else if (s->altval == NANO_ALT_SPACE) {
+	    meta_shortcut = 1;
+	    ptr += sprintf(ptr, "M-%.5s", _("Space"));
+	}
+#endif
+	else if (s->altval > 0) {
+	    meta_shortcut = 1;
+	    ptr += sprintf(ptr, "M-%c", s->altval -
+			(('A' <= s->altval && s->altval <= 'Z') ||
+			'a' <= s->altval ? 32 : 0));
+	}
+	/* Hack */
+	else if (s->val >= 'a') {
+	    meta_shortcut = 1;
+	    ptr += sprintf(ptr, "M-%c", s->val - 32);
+	}
+
+	*(ptr++) = '\t';
+
+	if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
+	    ptr += sprintf(ptr, "(F%d)", s->misc1 - KEY_F0);
+
+	*(ptr++) = '\t';
+
+	if (!meta_shortcut && s->altval > 0)
+	    ptr += sprintf(ptr, "(M-%c)", s->altval -
+		(('A' <= s->altval && s->altval <= 'Z') || 'a' <= s->altval
+			? 32 : 0));
+
+	*(ptr++) = '\t';
+
+	assert(s->help != NULL);
+	ptr += sprintf(ptr, "%.*s\n", COLS - 24, s->help);
+    }
+
+#ifndef NANO_SMALL
+    /* And the toggles... */
+    if (currshortcut == main_list)
+	for (t = toggles; t != NULL; t = t->next) {
+	    ptr += sprintf(ptr, "M-%c\t\t\t", t->val - 32);
+	    assert(t->desc != NULL);
+	    ptr += sprintf(ptr, _("%.*s enable/disable\n"), COLS - 24, t->desc);
+	}
+#endif /* !NANO_SMALL */
+
+    /* If all went well, we didn't overwrite the allocated space for
+       help_text. */
+    assert(strlen(help_text) < allocsize);
+}
+#endif
+
+/* Create a new filestruct node.  Note that we specifically do not set
+ * prevnode->next equal to the new line. */
+filestruct *make_new_node(filestruct *prevnode)
+{
+    filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
+
+    newnode->data = NULL;
+    newnode->prev = prevnode;
+    newnode->next = NULL;
+    newnode->lineno = prevnode != NULL ? prevnode->lineno + 1 : 1;
+
+    return newnode;
+}
+
 /* Make a copy of a node to a pointer (space will be malloc()ed). */
 filestruct *copy_node(const filestruct *src)
 {
@@ -238,6 +490,19 @@ filestruct *copy_node(const filestruct *src)
     return dst;
 }
 
+/* Splice a node into an existing filestruct. */
+void splice_node(filestruct *begin, filestruct *newnode, filestruct *end)
+{
+    if (newnode != NULL) {
+	newnode->next = end;
+	newnode->prev = begin;
+    }
+    if (begin != NULL)
+	begin->next = newnode;
+    if (end != NULL)
+	end->prev = newnode;
+}
+
 /* Unlink a node from the rest of the filestruct. */
 void unlink_node(const filestruct *fileptr)
 {
@@ -329,7 +594,7 @@ void renumber(filestruct *fileptr)
  * strings to translate and takes out the parts that shouldn't be 
  * translatable (the flag names). */
 void print1opt(const char *shortflag, const char *longflag,
-	const char *desc)
+		const char *desc)
 {
     printf(" %s\t", shortflag);
     if (strlen(shortflag) < 8)
@@ -430,46 +695,51 @@ void version(void)
 	   (" Email: nano@nano-editor.org	Web: http://www.nano-editor.org"));
     printf(_("\n Compiled options:"));
 
+#ifdef DEBUG
+    printf(" --enable-debug");
+#endif
 #ifdef NANO_EXTRA
     printf(" --enable-extra");
 #endif
-#ifdef ENABLE_MULTIBUFFER
-    printf(" --enable-multibuffer");
-#endif
-#ifdef ENABLE_NANORC
-    printf(" --enable-nanorc");
-#endif
-#ifdef ENABLE_COLOR
-    printf(" --enable-color");
-#endif
-
 #ifdef NANO_SMALL
     printf(" --enable-tiny");
 #else
 #ifdef DISABLE_BROWSER
     printf(" --disable-browser");
 #endif
-#ifdef DISABLE_TABCOMP
-    printf(" --disable-tabcomp");
+#ifdef DISABLE_HELP
+    printf(" --disable-help");
 #endif
 #ifdef DISABLE_JUSTIFY
     printf(" --disable-justify");
 #endif
-#ifdef DISABLE_SPELLER
-    printf(" --disable-speller");
-#endif
-#ifdef DISABLE_HELP
-    printf(" --disable-help");
-#endif
 #ifdef DISABLE_MOUSE
     printf(" --disable-mouse");
 #endif
 #ifdef DISABLE_OPERATINGDIR
     printf(" --disable-operatingdir");
 #endif
-#endif /* NANO_SMALL */
-#ifdef DISABLE_WRAPPING
-    printf(" --disable-wrapping");
+#ifdef DISABLE_SPELLER
+    printf(" --disable-speller");
+#endif
+#ifdef DISABLE_TABCOMP
+    printf(" --disable-tabcomp");
+#endif
+#endif /* NANO_SMALL */
+#ifdef DISABLE_WRAPPING
+    printf(" --disable-wrapping");
+#endif
+#ifdef ENABLE_COLOR
+    printf(" --enable-color");
+#endif
+#ifdef ENABLE_MULTIBUFFER
+    printf(" --enable-multibuffer");
+#endif
+#ifdef ENABLE_NANORC
+    printf(" --enable-nanorc");
+#endif
+#ifdef ENABLE_UNDO
+    printf(" --enable-undo");
 #endif
 #ifdef USE_SLANG
     printf(" --with-slang");
@@ -477,50 +747,11 @@ void version(void)
     printf("\n");
 }
 
-/* Create a new filestruct node.  Note that we specifically do not set
- * prevnode->next equal to the new line. */
-filestruct *make_new_node(filestruct *prevnode)
-{
-    filestruct *newnode = (filestruct *)nmalloc(sizeof(filestruct));
-
-    newnode->data = NULL;
-    newnode->prev = prevnode;
-    newnode->next = NULL;
-    newnode->lineno = prevnode != NULL ? prevnode->lineno + 1 : 1;
-
-    return newnode;
-}
-
-/* Splice a node into an existing filestruct. */
-void splice_node(filestruct *begin, filestruct *newnode, filestruct *end)
-{
-    if (newnode != NULL) {
-	newnode->next = end;
-	newnode->prev = begin;
-    }
-    if (begin != NULL)
-	begin->next = newnode;
-    if (end != NULL)
-	end->prev = newnode;
-}
-
-int do_mark(void)
+/* Stuff we do when we abort from programs and want to clean up the
+ * screen.  This doesn't do much right now. */
+void do_early_abort(void)
 {
-#ifdef NANO_SMALL
-    nano_disabled_msg();
-#else
-    if (!ISSET(MARK_ISSET)) {
-	statusbar(_("Mark Set"));
-	SET(MARK_ISSET);
-	mark_beginbuf = current;
-	mark_beginx = current_x;
-    } else {
-	statusbar(_("Mark UNset"));
-	UNSET(MARK_ISSET);
-	edit_refresh();
-    }
-#endif
-    return 1;
+    blank_statusbar_refresh();
 }
 
 int no_help(void)
@@ -535,448 +766,264 @@ void nano_disabled_msg(void)
 }
 #endif
 
-/* The user typed a printable character; add it to the edit buffer. */
-void do_char(char ch)
-{
-    size_t current_len = strlen(current->data);
-#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
-    int refresh = 0;
-	/* Do we have to run edit_refresh(), or can we get away with
-	 * update_line()? */
-#endif
-
-    /* magic-line: when a character is inserted on the current magic line,
-     * it means we need a new one! */
-    if (filebot == current && current->data[0] == '\0') {
-	new_magicline();
-	fix_editbot();
-    }
-
-    /* more dangerousness fun =) */
-    current->data = nrealloc(current->data, current_len + 2);
-    assert(current_x <= current_len);
-    memmove(&current->data[current_x + 1],
-	    &current->data[current_x],
-	    current_len - current_x + 1);
-    current->data[current_x] = ch;
-    totsize++;
-    set_modified();
-
 #ifndef NANO_SMALL
-    /* note that current_x has not yet been incremented */
-    if (current == mark_beginbuf && current_x < mark_beginx)
-	mark_beginx++;
-#endif
-
-    do_right();
-
-#ifndef DISABLE_WRAPPING
-    if (!ISSET(NO_WRAP) && ch != '\t')
-	refresh = do_wrap(current);
-#endif
-
-#ifdef ENABLE_COLOR
-    refresh = 1;
-#endif
-
-#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
-    if (refresh)
-	edit_refresh();
-#endif
-
-    check_statblank();
-    UNSET(KEEP_CUTBUFFER);
-}
+static int pid;		/* This is the PID of the newly forked process 
+			 * below.  It must be global since the signal
+			 * handler needs it. */
 
-/* Someone hits return *gasp!* */
-int do_enter(void)
+RETSIGTYPE cancel_fork(int signal)
 {
-    filestruct *newnode;
-    char *tmp;
-
-    newnode = make_new_node(current);
-    assert(current != NULL && current->data != NULL);
-    tmp = &current->data[current_x];
-
-#ifndef NANO_SMALL
-    /* Do auto-indenting, like the neolithic Turbo Pascal editor. */
-    if (ISSET(AUTOINDENT)) {
-	int extra = 0;
-	const char *spc = current->data;
-
-	while (*spc == ' ' || *spc == '\t') {
-	    extra++;
-	    spc++;
-	}
-	/* If current_x < extra, then we are breaking the line in the
-	 * indentation.  Autoindenting should add only current_x
-	 * characters of indentation. */
-	if (current_x < extra)
-	    extra = current_x;
-	else
-	    current_x = extra;
-	totsize += extra;
-
-	newnode->data = charalloc(strlen(tmp) + extra + 1);
-	strncpy(newnode->data, current->data, extra);
-	strcpy(&newnode->data[extra], tmp);
-    } else 
-#endif
-    {
-	current_x = 0;
-	newnode->data = charalloc(strlen(tmp) + 1);
-	strcpy(newnode->data, tmp);
-    }
-    *tmp = '\0';
-
-    if (current->next == NULL) {
-	filebot = newnode;
-	editbot = newnode;
-    }
-    splice_node(current, newnode, current->next);
-
-    totsize++;
-    renumber(current);
-    current = newnode;
-    align(&current->data);
-
-    /* The logic here is as follows:
-     *    -> If we are at the bottom of the buffer, we want to recenter
-     *       (read: rebuild) the screen and forcibly move the cursor.
-     *    -> otherwise, we want simply to redraw the screen and update
-     *       where we think the cursor is.
-     */
-    if (current_y == editwinrows - 1) {
-	edit_update(current, CENTER);
-	reset_cursor();
-    } else {
-	current_y++;
-	edit_refresh();
-	update_cursor();
-    }
-
-    totlines++;
-    set_modified();
-
-    placewewant = xplustabs();
-    return 1;
+    if (kill(pid, SIGKILL)==-1) nperror("kill");
 }
 
-#ifndef NANO_SMALL
-int do_next_word(void)
+int open_pipe(const char *command)
 {
-    filestruct *old = current;
-
-    assert(current != NULL && current->data != NULL);
-
-    /* Skip letters in this word first. */
-    while (current->data[current_x] != '\0' &&
-	    isalnum((int)current->data[current_x]))
-	current_x++;
-
-    for (; current != NULL; current = current->next) {
-	while (current->data[current_x] != '\0' &&
-		!isalnum((int)current->data[current_x]))
-	    current_x++;
-
-	if (current->data[current_x] != '\0')
-	    break;
-
-	current_x = 0;
-    }
-    if (current == NULL)
-	current = filebot;
+    int fd[2];
+    FILE *f;
+    struct sigaction oldaction, newaction;
+			/* original and temporary handlers for SIGINT */
+#ifdef _POSIX_VDISABLE
+    struct termios term, newterm;
+#endif   /* _POSIX_VDISABLE */
+    int cancel_sigs = 0;
+    /* cancel_sigs==1 means that sigaction failed without changing the
+     * signal handlers.  cancel_sigs==2 means the signal handler was
+     * changed, but the tcsetattr didn't succeed.
+     * I use this variable since it is important to put things back when
+     * we finish, even if we get errors. */
 
-    placewewant = xplustabs();
+    /* Make our pipes. */
 
-    if (current->lineno >= editbot->lineno) {
-	/* If we're on the last line, don't center the screen. */
-	if (current->lineno == filebot->lineno)
-	    edit_refresh();
-	else
-	    edit_update(current, CENTER);
-    }
-    else {
-	/* If we've jumped lines, refresh the old line.  We can't just
-	   use current->prev here, because we may have skipped over some
-	   blank lines, in which case the previous line is the wrong
-	   one. */
-	if (current != old) {
-	    update_line(old, 0);
-	    /* If the mark was set, then the lines between old and
-	       current have to be updated too. */
-	    if (ISSET(MARK_ISSET)) {
-		while (old->next != current) {
-		    old = old->next;
-		    update_line(old, 0);
-		}
-	    }
-	}
-	update_line(current, current_x);
+    if (pipe(fd) == -1) {
+	statusbar(_("Could not pipe"));
+	return 1;
     }
-    return 0;
-}
-
-/* The same thing for backwards. */
-int do_prev_word(void)
-{
-    filestruct *old = current;
-
-    assert(current != NULL);
-
-    /* Skip letters in this word first. */
-    while (current_x >= 0 && isalnum((int)current->data[current_x]))
-	current_x--;
 
-    for (; current != NULL; current = current->prev) {
-	while (current_x >= 0 && !isalnum((int)current->data[current_x]))
-	    current_x--;
+    /* Fork a child. */
 
-	if (current_x >= 0)
-	    break;
+    if ((pid = fork()) == 0) {
+	close(fd[0]);
+	dup2(fd[1], fileno(stdout));
+	dup2(fd[1], fileno(stderr));
+	/* If execl() returns at all, there was an error. */
+      
+	execl("/bin/sh","sh","-c",command,0);
+	exit(0);
+    }
 
-	if (current->prev != NULL)
-	    current_x = strlen(current->prev->data);
+    /* Else continue as parent. */
+
+    close(fd[1]);
+
+    if (pid == -1) {
+	close(fd[0]);
+	statusbar(_("Could not fork"));
+	return 1;
     }
 
-    if (current != NULL) {
-	while (current_x > 0 && isalnum((int)current->data[current_x - 1]))
-	    current_x--;
+    /* Before we start reading the forked command's output, we set
+     * things up so that ^C will cancel the new process. */
+    if (sigaction(SIGINT, NULL, &newaction)==-1) {
+	cancel_sigs = 1;
+	nperror("sigaction");
     } else {
-	current = fileage;
-	current_x = 0;
+	newaction.sa_handler = cancel_fork;
+	if (sigaction(SIGINT, &newaction, &oldaction)==-1) {
+	    cancel_sigs = 1;
+	    nperror("sigaction");
+	}
     }
+    /* Note that now oldaction is the previous SIGINT signal handler,
+     * to be restored later. */
 
-    placewewant = xplustabs();
-
-    if (current->lineno <= edittop->lineno) {
-	/* If we're on the first line, don't center the screen. */
-	if (current->lineno == fileage->lineno)
-	    edit_refresh();
-	else
-	    edit_update(current, CENTER);
+    /* See if the platform supports disabling individual control
+     * characters. */
+#ifdef _POSIX_VDISABLE
+    if (!cancel_sigs && tcgetattr(0, &term) == -1) {
+	cancel_sigs = 2;
+	nperror("tcgetattr");
     }
-    else {
-	/* If we've jumped lines, refresh the old line.  We can't just
-	   use current->prev here, because we may have skipped over some
-	   blank lines, in which case the previous line is the wrong
-	   one. */
-	if (current != old) {
-	    update_line(old, 0);
-	    /* If the mark was set, then the lines between old and
-	       current have to be updated too. */
-	    if (ISSET(MARK_ISSET)) {
-		while (old->prev != current) {
-		    old = old->prev;
-		    update_line(old, 0);
-		}
-	    }
+    if (!cancel_sigs) {
+	newterm = term;
+	/* Grab oldterm's VINTR key :-) */
+	newterm.c_cc[VINTR] = oldterm.c_cc[VINTR];
+	if (tcsetattr(0, TCSANOW, &newterm) == -1) {
+	    cancel_sigs = 2;
+	    nperror("tcsetattr");
 	}
-	update_line(current, current_x);
     }
+#endif   /* _POSIX_VDISABLE */
+
+    f = fdopen(fd[0], "rb");
+    if (!f)
+      nperror("fdopen");
+    
+    read_file(f, "stdin", 0);
+    /* if multibuffer mode is on, we could be here in view mode; if so,
+       don't set the modification flag */
+    if (!ISSET(VIEW_MODE))
+	set_modified();
+
+    if (wait(NULL) == -1)
+	nperror("wait");
+
+#ifdef _POSIX_VDISABLE
+    if (!cancel_sigs && tcsetattr(0, TCSANOW, &term) == -1)
+	nperror("tcsetattr");
+#endif   /* _POSIX_VDISABLE */
+
+    if (cancel_sigs!=1 && sigaction(SIGINT, &oldaction, NULL) == -1)
+	nperror("sigaction");
+
     return 0;
 }
-#endif /* !NANO_SMALL */
+#endif /* NANO_SMALL */
 
-#ifndef DISABLE_WRAPPING
-/* We wrap the given line.  Precondition: we assume the cursor has been 
- * moved forward since the last typed character.  Return value:
- * whether we wrapped. */
-int do_wrap(filestruct *inptr)
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
+void do_mouse(void)
 {
-    size_t len = strlen(inptr->data);	/* length of the line we wrap */
-    int i = 0;			/* generic loop variable */
-    int wrap_loc = -1;		/* index of inptr->data where we wrap */
-    int word_back = -1;
-#ifndef NANO_SMALL
-    const char *indentation = NULL;
-	/* indentation to prepend to the new line */
-    int indent_len = 0;		/* strlen(indentation) */
-#endif
-    const char *after_break;	/* text after the wrap point */
-    int after_break_len;	/* strlen(after_break) */
-    int wrapping = 0;		/* do we prepend to the next line? */
-    const char *wrap_line = NULL;
-	/* the next line, minus indentation */
-    int wrap_line_len = 0;	/* strlen(wrap_line) */
-    char *newline = NULL;	/* the line we create */
-    int new_line_len = 0;	/* eventual length of newline */
+    MEVENT mevent;
+    int currslen;
+    const shortcut *s = currshortcut;
 
-/* There are three steps.  First, we decide where to wrap.  Then, we
- * create the new wrap line.  Finally, we clean up. */
+    if (getmouse(&mevent) == ERR)
+	return;
 
-/* Step 1, finding where to wrap.  We are going to replace a white-space
- * character with a new-line.  In this step, we set wrap_loc as the
- * location of this replacement.
- *
- * Where should we break the line?  We need the last "legal wrap point"
- * such that the last word before it ended at or before fill.  If there
- * is no such point, we settle for the first legal wrap point.
- *
- * A "legal wrap point" is a white-space character that is not the last
- * typed character and is not followed by white-space.
- *
- * If there is no legal wrap point or we found the last character of the
- * line, we should return without wrapping.
- *
- * Note that the initial indentation does not count as a legal wrap
- * point if we are going to auto-indent!
- *
- * Note that the code below could be optimised, by not calling strnlenpt()
- * so often. */
+    /* If mouse not in edit or bottom window, return */
+    if (wenclose(edit, mevent.y, mevent.x)) {
 
-#ifndef NANO_SMALL
-    if (ISSET(AUTOINDENT))
-	i = indent_length(inptr->data);
-#endif
-    wrap_line = inptr->data + i;
-    for(; i < len; i++, wrap_line++) {
-	/* record where the last word ended */
-	if (*wrap_line != ' ' && *wrap_line != '\t')
-	    word_back = i;
-	/* if we have found a "legal wrap point" and the current word
-	 * extends too far, then we stop */
-	if (wrap_loc != -1 && strnlenpt(inptr->data, word_back + 1) > fill)
-	    break;
-	/* we record the latest "legal wrap point" */
-	if (i != current_x - 1 && word_back != i &&
-		wrap_line[1] != ' ' && wrap_line[1] != '\t')
-	    wrap_loc = i;
-    }
-    if (wrap_loc < 0 || i == len)
-	return 0;
+	/* Don't let people screw with the marker when they're in a
+	 * subfunction. */
+	if (currshortcut != main_list)
+	    return;
 
-/* Step 2, making the new wrap line.  It will consist of indentation +
- * after_break + " " + wrap_line (although indentation and wrap_line are
- * conditional on flags and #defines). */
+	/* Subtract out size of topwin.  Perhaps we need a constant
+	 * somewhere? */
+	mevent.y -= 2;
 
-    /* after_break is the text that will be moved to the next line. */
-    after_break = inptr->data + wrap_loc + 1;
-    after_break_len = len - wrap_loc - 1;
-    assert(after_break_len == strlen(after_break));
+	/* Selecting where the cursor is sets the mark.  Selecting
+	 * beyond the line length with the cursor at the end of the line
+	 * sets the mark as well. */
+	if ((mevent.y == current_y) &&
+	    ((mevent.x == current_x) || (current_x == strlen(current->data)
+					 && (mevent.x >
+					     strlen(current->data))))) {
+	    if (ISSET(VIEW_MODE)) {
+		print_view_warning();
+		return;
+	    }
+	    do_mark();
+	} else if (mevent.y > current_y) {
+	    while (mevent.y > current_y) {
+		if (current->next != NULL)
+		    current = current->next;
+		else
+		    break;
+		current_y++;
+	    }
+	} else if (mevent.y < current_y) {
+	    while (mevent.y < current_y) {
+		if (current->prev != NULL)
+		    current = current->prev;
+		else
+		    break;
+		current_y--;
+	    }
+	}
+	current_x = actual_x(current, mevent.x);
+	placewewant = current_x;
+	update_cursor();
+	edit_refresh();
+    } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
+	int i, k;
 
-    /* new_line_len will later be increased by the lengths of indentation
-     * and wrap_line. */
-    new_line_len = after_break_len;
+	if (currshortcut == main_list)
+	    currslen = MAIN_VISIBLE;
+	else
+	    currslen = length_of_list(currshortcut);
 
-    /* We prepend the wrapped text to the next line, if the flag is set,
-     * and there is a next line, and prepending would not make the line
-     * too long. */
-    if (ISSET(SAMELINEWRAP) && inptr->next) {
-	wrap_line = inptr->next->data;
-	wrap_line_len = strlen(wrap_line);
+	if (currslen < 2)
+	    k = COLS / 6;
+	else 
+	    k = COLS / ((currslen + (currslen %2)) / 2);
 
-	/* +1 for the space between after_break and wrap_line */
-	if ((new_line_len + 1 + wrap_line_len) <= fill) {
-	    wrapping = 1;
-	    new_line_len += (1 + wrap_line_len);
-	}
-    }
+	/* Determine what shortcut list was clicked */
+	mevent.y -= (editwinrows + 3);
 
-#ifndef NANO_SMALL
-    if (ISSET(AUTOINDENT)) {
-	/* indentation comes from the next line if wrapping, else from
-	 * this line */
-	indentation = (wrapping ? wrap_line : inptr->data);
-	indent_len = indent_length(indentation);
-	if (wrapping)
-	    /* The wrap_line text should not duplicate indentation.  Note
-	     * in this case we need not increase new_line_len. */
-	    wrap_line += indent_len;
-	else
-	    new_line_len += indent_len;
-    }
-#endif
+	if (mevent.y < 0) /* They clicked on the statusbar */
+	    return;
+
+	/* Don't select stuff beyond list length */
+	if (mevent.x / k >= currslen)	
+	    return;
 
-    /* Now we allocate the new line and copy into it. */
-    newline = charalloc(new_line_len + 1);  /* +1 for \0 */
-    *newline = '\0';
+	for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
+	    s = s->next;
 
-#ifndef NANO_SMALL
-    if (ISSET(AUTOINDENT)) {
-	strncpy(newline, indentation, indent_len);
-	newline[indent_len] = '\0';
+	/* And ungetch that value */
+	ungetch(s->val);
+
+	/* And if it's an alt-key sequence, we should probably send alt
+	   too ;-) */
+	if (s->val >= 'a' && s->val <= 'z')
+	   ungetch(27);
     }
+}
 #endif
-    strcat(newline, after_break);
-    /* We end the old line at wrap_loc.  Note this eats the space. */
-    null_at(&inptr->data, wrap_loc);
-    if (wrapping) {
-	/* In this case, totsize does not change.  We ate a space in the
-	 * null_at() above, but we add a space between after_break and
-	 * wrap_line below. */
-	strcat(newline, " ");
-	strcat(newline, wrap_line);
-	free(inptr->next->data);
-	inptr->next->data = newline;
-    } else {
-	filestruct *temp = (filestruct *)nmalloc(sizeof(filestruct));
-
-	/* In this case, the file size changes by -1 for the eaten
-	 * space, +1 for the new line, and +indent_len for the new
-	 * indentation. */
-#ifndef NANO_SMALL
-	totsize += indent_len;
 #endif
-	totlines++;
-	temp->data = newline;
-	temp->prev = inptr;
-	temp->next = inptr->next;
-	temp->prev->next = temp;
-	/* If !temp->next, then temp is the last line of the file, so we
-	 * must set filebot */
-	if (temp->next)
-	    temp->next->prev = temp;
-	else
-	    filebot = temp;
-    }
 
-/* Step 3, clean up.  Here we reposition the cursor and mark, and do some
- * other sundry things. */
+/* The user typed a printable character; add it to the edit buffer. */
+void do_char(char ch)
+{
+    size_t current_len = strlen(current->data);
+#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
+    int refresh = 0;
+	/* Do we have to run edit_refresh(), or can we get away with
+	 * update_line()? */
+#endif
 
-    /* later wraps of this line will be prepended to the next line. */
-    SET(SAMELINEWRAP);
+    /* magic-line: when a character is inserted on the current magic line,
+     * it means we need a new one! */
+    if (filebot == current && current->data[0] == '\0') {
+	new_magicline();
+	fix_editbot();
+    }
 
-    /* Each line knows its line number.  We recalculate these if we
-     * inserted a new line. */
-    if (!wrapping)
-	renumber(inptr);
+    /* more dangerousness fun =) */
+    current->data = nrealloc(current->data, current_len + 2);
+    assert(current_x <= current_len);
+    memmove(&current->data[current_x + 1],
+	    &current->data[current_x],
+	    current_len - current_x + 1);
+    current->data[current_x] = ch;
+    totsize++;
+    set_modified();
 
-    /* If the cursor was after the break point, we must move it. */
-    if (current_x > wrap_loc) {
-	current = current->next;
-	current_x -=
 #ifndef NANO_SMALL
-		-indent_len +
+    /* note that current_x has not yet been incremented */
+    if (current == mark_beginbuf && current_x < mark_beginx)
+	mark_beginx++;
 #endif
-		wrap_loc + 1;
-	wrap_reset();
-	placewewant = xplustabs();
-    }
 
-#ifndef NANO_SMALL
-    /* If the mark was on this line after the wrap point, we move it down.
-     * If it was on the next line and we wrapped, we must move it
-     * right. */
-    if (mark_beginbuf == inptr && mark_beginx > wrap_loc) {
-	mark_beginbuf = inptr->next;
-	mark_beginx -= wrap_loc - indent_len + 1;
-    } else if (wrapping && mark_beginbuf == inptr->next)
-	mark_beginx += after_break_len;
-#endif /* !NANO_SMALL */
+    do_right();
 
-    /* Place the cursor. */
-    reset_cursor();
+#ifndef DISABLE_WRAPPING
+    if (!ISSET(NO_WRAP) && ch != '\t')
+	refresh = do_wrap(current);
+#endif
 
-    return 1;
-}
-#endif /* !DISABLE_WRAPPING */
+#ifdef ENABLE_COLOR
+    refresh = 1;
+#endif
 
-/* Stuff we do when we abort from programs and want to clean up the
- * screen.  This doesn't do much right now. */
-void do_early_abort(void)
-{
-    blank_statusbar_refresh();
+#if !defined(DISABLE_WRAPPING) || defined(ENABLE_COLOR)
+    if (refresh)
+	edit_refresh();
+#endif
+
+    check_statblank();
+    UNSET(KEEP_CUTBUFFER);
 }
 
 int do_backspace(void)
@@ -1116,841 +1163,774 @@ int do_delete(void)
     return 1;
 }
 
-void wrap_reset(void)
+int do_tab(void)
 {
-    UNSET(SAMELINEWRAP);
+    do_char('\t');
+    return 1;
 }
 
-#ifndef DISABLE_SPELLER
-int do_int_spell_fix(const char *word)
+/* Someone hits return *gasp!* */
+int do_enter(void)
 {
-    char *save_search;
-    char *save_replace;
-    filestruct *begin;
-    int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
-#ifndef NANO_SMALL
-    int mark_set;
-#endif
-
-    /* save where we are */
-    begin = current;
-    beginx = current_x + 1;
+    filestruct *newnode;
+    char *tmp;
 
-    /* Make sure Spell Check goes forward only */
-    reverse_search_set = ISSET(REVERSE_SEARCH);
-    UNSET(REVERSE_SEARCH);
+    newnode = make_new_node(current);
+    assert(current != NULL && current->data != NULL);
+    tmp = &current->data[current_x];
 
 #ifndef NANO_SMALL
-    /* Make sure the marking highlight is off during Spell Check */
-    mark_set = ISSET(MARK_ISSET);
-    UNSET(MARK_ISSET);
-#endif
-
-    /* save the current search/replace strings */
-    search_init_globals();
-    save_search = last_search;
-    save_replace = last_replace;
-
-    /* set search/replace strings to mis-spelt word */
-    last_search = mallocstrcpy(NULL, word);
-    last_replace = mallocstrcpy(NULL, word);
-
-    /* start from the top of file */
-    current = fileage;
-    current_x = beginx_top = -1;
-
-    search_last_line = FALSE;
-
-    edit_update(fileage, TOP);
-
-    while (1) {
-	/* make sure word is still mis-spelt (i.e. when multi-errors) */
-	if (findnextstr(TRUE, FALSE, fileage, beginx_top, word) != NULL) {
-
-	    /* find whole words only */
-	    if (!is_whole_word(current_x, current->data, word))
-		continue;
-
-	    do_replace_highlight(TRUE, word);
-
-	    /* allow replace word to be corrected */
-	    i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
-
-	    do_replace_highlight(FALSE, word);
-
-	    /* start from the start of this line again */
-	    current = fileage;
-	    current_x = beginx_top;
-
-	    search_last_line = FALSE;
+    /* Do auto-indenting, like the neolithic Turbo Pascal editor. */
+    if (ISSET(AUTOINDENT)) {
+	int extra = 0;
+	const char *spc = current->data;
 
-	    if (strcmp(word, answer)) {
-		j = i;
-		do_replace_loop(word, fileage, &beginx_top, TRUE, &j);
-	    }
+	while (*spc == ' ' || *spc == '\t') {
+	    extra++;
+	    spc++;
 	}
-	break;
-    }
-
-    /* restore the search/replace strings */
-    free(last_search);    last_search=save_search;
-    free(last_replace);   last_replace=save_replace;
+	/* If current_x < extra, then we are breaking the line in the
+	 * indentation.  Autoindenting should add only current_x
+	 * characters of indentation. */
+	if (current_x < extra)
+	    extra = current_x;
+	else
+	    current_x = extra;
+	totsize += extra;
 
-    /* restore where we were */
-    current = begin;
-    current_x = beginx - 1;
+	newnode->data = charalloc(strlen(tmp) + extra + 1);
+	strncpy(newnode->data, current->data, extra);
+	strcpy(&newnode->data[extra], tmp);
+    } else 
+#endif
+    {
+	current_x = 0;
+	newnode->data = charalloc(strlen(tmp) + 1);
+	strcpy(newnode->data, tmp);
+    }
+    *tmp = '\0';
 
-    /* restore Search/Replace direction */
-    if (reverse_search_set)
-	SET(REVERSE_SEARCH);
+    if (current->next == NULL) {
+	filebot = newnode;
+	editbot = newnode;
+    }
+    splice_node(current, newnode, current->next);
 
-#ifndef NANO_SMALL
-    /* restore marking highlight */
-    if (mark_set)
-	SET(MARK_ISSET);
-#endif
+    totsize++;
+    renumber(current);
+    current = newnode;
+    align(&current->data);
 
-    edit_update(current, CENTER);
+    /* The logic here is as follows:
+     *    -> If we are at the bottom of the buffer, we want to recenter
+     *       (read: rebuild) the screen and forcibly move the cursor.
+     *    -> otherwise, we want simply to redraw the screen and update
+     *       where we think the cursor is.
+     */
+    if (current_y == editwinrows - 1) {
+	edit_update(current, CENTER);
+	reset_cursor();
+    } else {
+	current_y++;
+	edit_refresh();
+	update_cursor();
+    }
 
-    if (i == -1)
-	return FALSE;
+    totlines++;
+    set_modified();
 
-    return TRUE;
+    placewewant = xplustabs();
+    return 1;
 }
 
-/* Integrated spell checking using 'spell' program. */
-int do_int_speller(char *tempfile_name)
+#ifndef NANO_SMALL
+int do_next_word(void)
 {
-    char *read_buff, *read_buff_ptr, *read_buff_word;
-    size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
-    int in_fd[2], tempfile_fd, spell_status;
-    pid_t pid_spell;
-
-    /* Create a pipe to spell program */
-
-    if (pipe(in_fd) == -1)
-	return FALSE;
-
-    /* A new process to run spell in */
-
-    if ((pid_spell = fork()) == 0) {
+    filestruct *old = current;
 
-	/* Child continues, (i.e. future spell process) */
+    assert(current != NULL && current->data != NULL);
 
-	close(in_fd[0]);
+    /* Skip letters in this word first. */
+    while (current->data[current_x] != '\0' &&
+	    isalnum((int)current->data[current_x]))
+	current_x++;
 
-	/* replace the standard in with the tempfile */
+    for (; current != NULL; current = current->next) {
+	while (current->data[current_x] != '\0' &&
+		!isalnum((int)current->data[current_x]))
+	    current_x++;
 
-	if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
-	    close(in_fd[1]);
-	    exit(1);
-	}
+	if (current->data[current_x] != '\0')
+	    break;
 
-	if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
-	    close(tempfile_fd);
-	    close(in_fd[1]);
-	    exit(1);
-	}
-	close(tempfile_fd);
+	current_x = 0;
+    }
+    if (current == NULL)
+	current = filebot;
 
-	/* send spell's standard out to the pipe */
+    placewewant = xplustabs();
 
-	if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
-	    close(in_fd[1]);
-	    exit(1);
+    if (current->lineno >= editbot->lineno) {
+	/* If we're on the last line, don't center the screen. */
+	if (current->lineno == filebot->lineno)
+	    edit_refresh();
+	else
+	    edit_update(current, CENTER);
+    }
+    else {
+	/* If we've jumped lines, refresh the old line.  We can't just
+	   use current->prev here, because we may have skipped over some
+	   blank lines, in which case the previous line is the wrong
+	   one. */
+	if (current != old) {
+	    update_line(old, 0);
+	    /* If the mark was set, then the lines between old and
+	       current have to be updated too. */
+	    if (ISSET(MARK_ISSET)) {
+		while (old->next != current) {
+		    old = old->next;
+		    update_line(old, 0);
+		}
+	    }
 	}
-	close(in_fd[1]);
-
-	/* Start spell program, we are using the PATH here!?!? */
-	execlp("spell", "spell", NULL);
-
-	/* Should not be reached, if spell is found!!! */
-
-	exit(1);
+	update_line(current, current_x);
     }
+    return 0;
+}
 
-    /* Parent continues here */
+/* The same thing for backwards. */
+int do_prev_word(void)
+{
+    filestruct *old = current;
 
-    close(in_fd[1]);
+    assert(current != NULL);
 
-    /* Child process was not forked successfully */
+    /* Skip letters in this word first. */
+    while (current_x >= 0 && isalnum((int)current->data[current_x]))
+	current_x--;
 
-    if (pid_spell < 0) {
-	close(in_fd[0]);
-	return FALSE;
-    }
+    for (; current != NULL; current = current->prev) {
+	while (current_x >= 0 && !isalnum((int)current->data[current_x]))
+	    current_x--;
 
-    /* Get system pipe buffer size */
+	if (current_x >= 0)
+	    break;
 
-    if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
-	close(in_fd[0]);
-	return FALSE;
+	if (current->prev != NULL)
+	    current_x = strlen(current->prev->data);
     }
 
-    /* Read-in the returned spelling errors */
-
-    read_buff_read = 0;
-    read_buff_size = pipe_buff_size + 1;
-    read_buff = read_buff_ptr = charalloc(read_buff_size);
-
-    while ((bytesread = read(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
-	read_buff_read += bytesread;
-	read_buff_size += pipe_buff_size;
-	read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
-	read_buff_ptr += read_buff_read;
+    if (current != NULL) {
+	while (current_x > 0 && isalnum((int)current->data[current_x - 1]))
+	    current_x--;
+    } else {
+	current = fileage;
+	current_x = 0;
     }
 
-    *read_buff_ptr = (char) NULL;
-    close(in_fd[0]);
-
-    /* Process the spelling errors */
-
-    read_buff_word = read_buff_ptr = read_buff;
-
-    while (*read_buff_ptr) {
+    placewewant = xplustabs();
 
-	if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
-	    *read_buff_ptr = (char) NULL;
-	    if (read_buff_word != read_buff_ptr) {
-		if (!do_int_spell_fix(read_buff_word)) {
-		    read_buff_word = read_buff_ptr;
-		    break;
+    if (current->lineno <= edittop->lineno) {
+	/* If we're on the first line, don't center the screen. */
+	if (current->lineno == fileage->lineno)
+	    edit_refresh();
+	else
+	    edit_update(current, CENTER);
+    }
+    else {
+	/* If we've jumped lines, refresh the old line.  We can't just
+	   use current->prev here, because we may have skipped over some
+	   blank lines, in which case the previous line is the wrong
+	   one. */
+	if (current != old) {
+	    update_line(old, 0);
+	    /* If the mark was set, then the lines between old and
+	       current have to be updated too. */
+	    if (ISSET(MARK_ISSET)) {
+		while (old->prev != current) {
+		    old = old->prev;
+		    update_line(old, 0);
 		}
 	    }
-	    read_buff_word = read_buff_ptr + 1;
 	}
-	read_buff_ptr++;
+	update_line(current, current_x);
     }
+    return 0;
+}
+#endif /* !NANO_SMALL */
 
-    /* special case where last word doesn't end with \n or \r */
-    if (read_buff_word != read_buff_ptr)
-	do_int_spell_fix(read_buff_word);
-
-    free(read_buff);
-    replace_abort();
-
-    /* Process end of spell process */
-
-    wait(&spell_status);
-    if (WIFEXITED(spell_status)) {
-	if (WEXITSTATUS(spell_status) != 0)
-	    return FALSE;
-    } else
-	return FALSE;
+int do_mark(void)
+{
+#ifdef NANO_SMALL
+    nano_disabled_msg();
+#else
+    if (!ISSET(MARK_ISSET)) {
+	statusbar(_("Mark Set"));
+	SET(MARK_ISSET);
+	mark_beginbuf = current;
+	mark_beginx = current_x;
+    } else {
+	statusbar(_("Mark UNset"));
+	UNSET(MARK_ISSET);
+	edit_refresh();
+    }
+#endif
+    return 1;
+}
 
-    return TRUE;
+void wrap_reset(void)
+{
+    UNSET(SAMELINEWRAP);
 }
 
-/* External spell checking. */
-int do_alt_speller(char *file_name)
+#ifndef DISABLE_WRAPPING
+/* We wrap the given line.  Precondition: we assume the cursor has been 
+ * moved forward since the last typed character.  Return value:
+ * whether we wrapped. */
+int do_wrap(filestruct *inptr)
 {
-    int alt_spell_status, lineno_cur = current->lineno;
-    int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
-    pid_t pid_spell;
-    char *ptr;
-    static int arglen = 3;
-    static char **spellargs = (char **)NULL;
+    size_t len = strlen(inptr->data);	/* length of the line we wrap */
+    int i = 0;			/* generic loop variable */
+    int wrap_loc = -1;		/* index of inptr->data where we wrap */
+    int word_back = -1;
 #ifndef NANO_SMALL
-    int mark_set = ISSET(MARK_ISSET);
-    int mbb_lineno_cur = 0;
-	/* We're going to close the current file, and open the output of
-	   the alternate spell command.  The line that mark_beginbuf
-	   points to will be freed, so we save the line number and restore
-	   afterwards. */
-
-    if (mark_set) {
-	mbb_lineno_cur = mark_beginbuf->lineno;
-	UNSET(MARK_ISSET);
-    }
+    const char *indentation = NULL;
+	/* indentation to prepend to the new line */
+    int indent_len = 0;		/* strlen(indentation) */
 #endif
+    const char *after_break;	/* text after the wrap point */
+    int after_break_len;	/* strlen(after_break) */
+    int wrapping = 0;		/* do we prepend to the next line? */
+    const char *wrap_line = NULL;
+	/* the next line, minus indentation */
+    int wrap_line_len = 0;	/* strlen(wrap_line) */
+    char *newline = NULL;	/* the line we create */
+    int new_line_len = 0;	/* eventual length of newline */
 
-    endwin();
+/* There are three steps.  First, we decide where to wrap.  Then, we
+ * create the new wrap line.  Finally, we clean up. */
 
-    /* Set up an argument list to pass the execvp function */
-    if (spellargs == NULL) {
-	spellargs = nmalloc(arglen * sizeof(char *));
+/* Step 1, finding where to wrap.  We are going to replace a white-space
+ * character with a new-line.  In this step, we set wrap_loc as the
+ * location of this replacement.
+ *
+ * Where should we break the line?  We need the last "legal wrap point"
+ * such that the last word before it ended at or before fill.  If there
+ * is no such point, we settle for the first legal wrap point.
+ *
+ * A "legal wrap point" is a white-space character that is not the last
+ * typed character and is not followed by white-space.
+ *
+ * If there is no legal wrap point or we found the last character of the
+ * line, we should return without wrapping.
+ *
+ * Note that the initial indentation does not count as a legal wrap
+ * point if we are going to auto-indent!
+ *
+ * Note that the code below could be optimised, by not calling strnlenpt()
+ * so often. */
 
-	spellargs[0] = strtok(alt_speller, " ");
-	while ((ptr = strtok(NULL, " ")) != NULL) {
-	    arglen++;
-	    spellargs = nrealloc(spellargs, arglen * sizeof(char *));
-	    spellargs[arglen - 3] = ptr;
-	}
-	spellargs[arglen - 1] = NULL;
+#ifndef NANO_SMALL
+    if (ISSET(AUTOINDENT))
+	i = indent_length(inptr->data);
+#endif
+    wrap_line = inptr->data + i;
+    for(; i < len; i++, wrap_line++) {
+	/* record where the last word ended */
+	if (*wrap_line != ' ' && *wrap_line != '\t')
+	    word_back = i;
+	/* if we have found a "legal wrap point" and the current word
+	 * extends too far, then we stop */
+	if (wrap_loc != -1 && strnlenpt(inptr->data, word_back + 1) > fill)
+	    break;
+	/* we record the latest "legal wrap point" */
+	if (i != current_x - 1 && word_back != i &&
+		wrap_line[1] != ' ' && wrap_line[1] != '\t')
+	    wrap_loc = i;
     }
-    spellargs[arglen - 2] = file_name;
-
-    /* Start a new process for the alternate speller */
-    if ((pid_spell = fork()) == 0) {
-	/* Start alternate spell program; we are using the PATH here!?!? */
-	execvp(spellargs[0], spellargs);
+    if (wrap_loc < 0 || i == len)
+	return 0;
 
-	/* Should not be reached, if alternate speller is found!!! */
-	exit(1);
-    }
+/* Step 2, making the new wrap line.  It will consist of indentation +
+ * after_break + " " + wrap_line (although indentation and wrap_line are
+ * conditional on flags and #defines). */
 
-    /* Could not fork?? */
-    if (pid_spell < 0)
-	return FALSE;
+    /* after_break is the text that will be moved to the next line. */
+    after_break = inptr->data + wrap_loc + 1;
+    after_break_len = len - wrap_loc - 1;
+    assert(after_break_len == strlen(after_break));
 
-    /* Wait for alternate speller to complete */
+    /* new_line_len will later be increased by the lengths of indentation
+     * and wrap_line. */
+    new_line_len = after_break_len;
 
-    wait(&alt_spell_status);
-    if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0)
-	return FALSE;
+    /* We prepend the wrapped text to the next line, if the flag is set,
+     * and there is a next line, and prepending would not make the line
+     * too long. */
+    if (ISSET(SAMELINEWRAP) && inptr->next) {
+	wrap_line = inptr->next->data;
+	wrap_line_len = strlen(wrap_line);
 
-    refresh();
-    free_filestruct(fileage);
-    global_init(1);
-    open_file(file_name, 0, 1);
+	/* +1 for the space between after_break and wrap_line */
+	if ((new_line_len + 1 + wrap_line_len) <= fill) {
+	    wrapping = 1;
+	    new_line_len += (1 + wrap_line_len);
+	}
+    }
 
 #ifndef NANO_SMALL
-    if (mark_set) {
-	do_gotopos(mbb_lineno_cur, mark_beginx, y_cur, 0);
-	mark_beginbuf = current;
-	mark_beginx = current_x;
-	    /* In case the line got shorter, assign mark_beginx. */
-	SET(MARK_ISSET);
+    if (ISSET(AUTOINDENT)) {
+	/* indentation comes from the next line if wrapping, else from
+	 * this line */
+	indentation = (wrapping ? wrap_line : inptr->data);
+	indent_len = indent_length(indentation);
+	if (wrapping)
+	    /* The wrap_line text should not duplicate indentation.  Note
+	     * in this case we need not increase new_line_len. */
+	    wrap_line += indent_len;
+	else
+	    new_line_len += indent_len;
     }
 #endif
 
-    /* go back to the old position, mark the file as modified, and make
-       sure that the titlebar is refreshed */
-    do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
-    set_modified();
-    clearok(topwin, FALSE);
-    titlebar(NULL);
-
-    return TRUE;
-}
-#endif
-
-int do_spell(void)
-{
-#ifdef DISABLE_SPELLER
-    nano_disabled_msg();
-    return (TRUE);
-#else
-    char *temp;
-    int spell_res;
-
-    if ((temp = safe_tempnam(0, "nano.")) == NULL) {
-	statusbar(_("Could not create a temporary filename: %s"),
-		  strerror(errno));
-	return 0;
-    }
+    /* Now we allocate the new line and copy into it. */
+    newline = charalloc(new_line_len + 1);  /* +1 for \0 */
+    *newline = '\0';
 
-    if (write_file(temp, 1, 0, 0) == -1) {
-	statusbar(_("Spell checking failed: unable to write temp file!"));
-	free(temp);
-	return 0;
+#ifndef NANO_SMALL
+    if (ISSET(AUTOINDENT)) {
+	strncpy(newline, indentation, indent_len);
+	newline[indent_len] = '\0';
     }
-
-#ifdef ENABLE_MULTIBUFFER
-    /* update the current open_files entry before spell-checking, in case
-       any problems occur */
-    add_open_file(1);
 #endif
+    strcat(newline, after_break);
+    /* We end the old line at wrap_loc.  Note this eats the space. */
+    null_at(&inptr->data, wrap_loc);
+    if (wrapping) {
+	/* In this case, totsize does not change.  We ate a space in the
+	 * null_at() above, but we add a space between after_break and
+	 * wrap_line below. */
+	strcat(newline, " ");
+	strcat(newline, wrap_line);
+	free(inptr->next->data);
+	inptr->next->data = newline;
+    } else {
+	filestruct *temp = (filestruct *)nmalloc(sizeof(filestruct));
 
-    if (alt_speller)
-	spell_res = do_alt_speller(temp);
-    else
-	spell_res = do_int_speller(temp);
+	/* In this case, the file size changes by -1 for the eaten
+	 * space, +1 for the new line, and +indent_len for the new
+	 * indentation. */
+#ifndef NANO_SMALL
+	totsize += indent_len;
+#endif
+	totlines++;
+	temp->data = newline;
+	temp->prev = inptr;
+	temp->next = inptr->next;
+	temp->prev->next = temp;
+	/* If !temp->next, then temp is the last line of the file, so we
+	 * must set filebot */
+	if (temp->next)
+	    temp->next->prev = temp;
+	else
+	    filebot = temp;
+    }
 
-    remove(temp);
+/* Step 3, clean up.  Here we reposition the cursor and mark, and do some
+ * other sundry things. */
 
-    if (spell_res)
-	statusbar(_("Finished checking spelling"));
-    else
-	statusbar(_("Spell checking failed"));
+    /* later wraps of this line will be prepended to the next line. */
+    SET(SAMELINEWRAP);
 
-    free(temp);
-    return spell_res;
+    /* Each line knows its line number.  We recalculate these if we
+     * inserted a new line. */
+    if (!wrapping)
+	renumber(inptr);
 
+    /* If the cursor was after the break point, we must move it. */
+    if (current_x > wrap_loc) {
+	current = current->next;
+	current_x -=
+#ifndef NANO_SMALL
+		-indent_len +
 #endif
-}
+		wrap_loc + 1;
+	wrap_reset();
+	placewewant = xplustabs();
+    }
 
 #ifndef NANO_SMALL
-static int pid;		/* This is the PID of the newly forked process 
-			 * below.  It must be global since the signal
-			 * handler needs it. */
+    /* If the mark was on this line after the wrap point, we move it down.
+     * If it was on the next line and we wrapped, we must move it
+     * right. */
+    if (mark_beginbuf == inptr && mark_beginx > wrap_loc) {
+	mark_beginbuf = inptr->next;
+	mark_beginx -= wrap_loc - indent_len + 1;
+    } else if (wrapping && mark_beginbuf == inptr->next)
+	mark_beginx += after_break_len;
+#endif /* !NANO_SMALL */
 
-RETSIGTYPE cancel_fork(int signal)
-{
-    if (kill(pid, SIGKILL)==-1) nperror("kill");
+    /* Place the cursor. */
+    reset_cursor();
+
+    return 1;
 }
+#endif /* !DISABLE_WRAPPING */
 
-int open_pipe(const char *command)
+#ifndef DISABLE_SPELLER
+int do_int_spell_fix(const char *word)
 {
-    int fd[2];
-    FILE *f;
-    struct sigaction oldaction, newaction;
-			/* original and temporary handlers for SIGINT */
-#ifdef _POSIX_VDISABLE
-    struct termios term, newterm;
-#endif   /* _POSIX_VDISABLE */
-    int cancel_sigs = 0;
-    /* cancel_sigs==1 means that sigaction failed without changing the
-     * signal handlers.  cancel_sigs==2 means the signal handler was
-     * changed, but the tcsetattr didn't succeed.
-     * I use this variable since it is important to put things back when
-     * we finish, even if we get errors. */
-
-  /* Make our pipes. */
+    char *save_search;
+    char *save_replace;
+    filestruct *begin;
+    int i = 0, j = 0, beginx, beginx_top, reverse_search_set;
+#ifndef NANO_SMALL
+    int mark_set;
+#endif
 
-    if (pipe(fd) == -1) {
-	statusbar(_("Could not pipe"));
-	return 1;
-    }
+    /* save where we are */
+    begin = current;
+    beginx = current_x + 1;
 
-    /* Fork a child */
+    /* Make sure Spell Check goes forward only */
+    reverse_search_set = ISSET(REVERSE_SEARCH);
+    UNSET(REVERSE_SEARCH);
 
-    if ((pid = fork()) == 0) {
-	close(fd[0]);
-	dup2(fd[1], fileno(stdout));
-	dup2(fd[1], fileno(stderr));
-	/* If execl() returns at all, there was an error. */
-      
-	execl("/bin/sh","sh","-c",command,0);
-	exit(0);
-    }
+#ifndef NANO_SMALL
+    /* Make sure the marking highlight is off during Spell Check */
+    mark_set = ISSET(MARK_ISSET);
+    UNSET(MARK_ISSET);
+#endif
 
-    /* Else continue as parent */
+    /* save the current search/replace strings */
+    search_init_globals();
+    save_search = last_search;
+    save_replace = last_replace;
 
-    close(fd[1]);
+    /* set search/replace strings to mis-spelt word */
+    last_search = mallocstrcpy(NULL, word);
+    last_replace = mallocstrcpy(NULL, word);
 
-    if (pid == -1) {
-	close(fd[0]);
-	statusbar(_("Could not fork"));
-	return 1;
-    }
+    /* start from the top of file */
+    current = fileage;
+    current_x = beginx_top = -1;
 
-    /* before we start reading the forked command's output, we set
-     * things up so that ^C will cancel the new process */
-    if (sigaction(SIGINT, NULL, &newaction)==-1) {
-	cancel_sigs = 1;
-	nperror("sigaction");
-    } else {
-	newaction.sa_handler = cancel_fork;
-	if (sigaction(SIGINT, &newaction, &oldaction)==-1) {
-	    cancel_sigs = 1;
-	    nperror("sigaction");
-	}
-    }
-    /* note that now oldaction is the previous SIGINT signal handler, to
-     * be restored later */
+    search_last_line = FALSE;
 
-    /* if the platform supports disabling individual control characters */
-#ifdef _POSIX_VDISABLE
-    if (!cancel_sigs && tcgetattr(0, &term) == -1) {
-	cancel_sigs = 2;
-	nperror("tcgetattr");
-    }
-    if (!cancel_sigs) {
-	newterm = term;
-	/* Grab oldterm's VINTR key :-) */
-	newterm.c_cc[VINTR] = oldterm.c_cc[VINTR];
-	if (tcsetattr(0, TCSANOW, &newterm) == -1) {
-	    cancel_sigs = 2;
-	    nperror("tcsetattr");
-	}
-    }
-#endif   /* _POSIX_VDISABLE */
+    edit_update(fileage, TOP);
 
-    f = fdopen(fd[0], "rb");
-    if (!f)
-      nperror("fdopen");
-    
-    read_file(f, "stdin", 0);
-    set_modified();
+    while (1) {
+	/* make sure word is still mis-spelt (i.e. when multi-errors) */
+	if (findnextstr(TRUE, FALSE, fileage, beginx_top, word) != NULL) {
 
-    if (wait(NULL) == -1)
-	nperror("wait");
+	    /* find whole words only */
+	    if (!is_whole_word(current_x, current->data, word))
+		continue;
 
-#ifdef _POSIX_VDISABLE
-    if (!cancel_sigs && tcsetattr(0, TCSANOW, &term) == -1)
-	nperror("tcsetattr");
-#endif   /* _POSIX_VDISABLE */
+	    do_replace_highlight(TRUE, word);
 
-    if (cancel_sigs!=1 && sigaction(SIGINT, &oldaction, NULL) == -1)
-	nperror("sigaction");
+	    /* allow replace word to be corrected */
+	    i = statusq(0, spell_list, last_replace, _("Edit a replacement"));
 
-    return 0;
-}
-#endif /* NANO_SMALL */
+	    do_replace_highlight(FALSE, word);
 
-int do_exit(void)
-{
-    int i;
+	    /* start from the start of this line again */
+	    current = fileage;
+	    current_x = beginx_top;
 
-    if (!ISSET(MODIFIED)) {
+	    search_last_line = FALSE;
 
-#ifdef ENABLE_MULTIBUFFER
-	if (!close_open_file()) {
-	    display_main_list();
-	    return 1;
+	    if (strcmp(word, answer)) {
+		j = i;
+		do_replace_loop(word, fileage, &beginx_top, TRUE, &j);
+	    }
 	}
-	else
-#endif
-	    finish(0);
+	break;
     }
 
-    if (ISSET(TEMP_OPT)) {
-	i = 1;
-    } else {
-	i = do_yesno(0, 0,
-		     _
-		     ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
-    }
+    /* restore the search/replace strings */
+    free(last_search);    last_search=save_search;
+    free(last_replace);   last_replace=save_replace;
 
-#ifdef DEBUG
-    dump_buffer(fileage);
-#endif
+    /* restore where we were */
+    current = begin;
+    current_x = beginx - 1;
 
-    if (i == 1) {
-	if (do_writeout(filename, 1, 0) > 0) {
+    /* restore Search/Replace direction */
+    if (reverse_search_set)
+	SET(REVERSE_SEARCH);
 
-#ifdef ENABLE_MULTIBUFFER
-	    if (!close_open_file()) {
-		display_main_list();
-		return 1;
-	    }
-	    else
+#ifndef NANO_SMALL
+    /* restore marking highlight */
+    if (mark_set)
+	SET(MARK_ISSET);
 #endif
-		finish(0);
-	}
-    } else if (i == 0) {
 
-#ifdef ENABLE_MULTIBUFFER
-	if (!close_open_file()) {
-	    display_main_list();
-	    return 1;
-	}
-	else
-#endif
-	    finish(0);
-    } else
-	statusbar(_("Cancelled"));
+    edit_update(current, CENTER);
 
-    display_main_list();
-    return 1;
+    if (i == -1)
+	return FALSE;
+
+    return TRUE;
 }
 
-#ifndef DISABLE_MOUSE
-#ifdef NCURSES_MOUSE_VERSION
-void do_mouse(void)
+/* Integrated spell checking using 'spell' program. */
+int do_int_speller(char *tempfile_name)
 {
-    MEVENT mevent;
-    int currslen;
-    const shortcut *s = currshortcut;
+    char *read_buff, *read_buff_ptr, *read_buff_word;
+    size_t pipe_buff_size, read_buff_size, read_buff_read, bytesread;
+    int in_fd[2], tempfile_fd, spell_status;
+    pid_t pid_spell;
 
-    if (getmouse(&mevent) == ERR)
-	return;
+    /* Create a pipe to spell program */
 
-    /* If mouse not in edit or bottom window, return */
-    if (wenclose(edit, mevent.y, mevent.x)) {
+    if (pipe(in_fd) == -1)
+	return FALSE;
 
-	/* Don't let people screw with the marker when they're in a
-	 * subfunction. */
-	if (currshortcut != main_list)
-	    return;
+    /* A new process to run spell in */
 
-	/* Subtract out size of topwin.  Perhaps we need a constant
-	 * somewhere? */
-	mevent.y -= 2;
+    if ((pid_spell = fork()) == 0) {
 
-	/* Selecting where the cursor is sets the mark.  Selecting
-	 * beyond the line length with the cursor at the end of the line
-	 * sets the mark as well. */
-	if ((mevent.y == current_y) &&
-	    ((mevent.x == current_x) || (current_x == strlen(current->data)
-					 && (mevent.x >
-					     strlen(current->data))))) {
-	    if (ISSET(VIEW_MODE)) {
-		print_view_warning();
-		return;
-	    }
-	    do_mark();
-	} else if (mevent.y > current_y) {
-	    while (mevent.y > current_y) {
-		if (current->next != NULL)
-		    current = current->next;
-		else
-		    break;
-		current_y++;
-	    }
-	} else if (mevent.y < current_y) {
-	    while (mevent.y < current_y) {
-		if (current->prev != NULL)
-		    current = current->prev;
-		else
-		    break;
-		current_y--;
-	    }
-	}
-	current_x = actual_x(current, mevent.x);
-	placewewant = current_x;
-	update_cursor();
-	edit_refresh();
-    } else if (wenclose(bottomwin, mevent.y, mevent.x) && !ISSET(NO_HELP)) {
-	int i, k;
+	/* Child continues, (i.e. future spell process) */
 
-	if (currshortcut == main_list)
-	    currslen = MAIN_VISIBLE;
-	else
-	    currslen = length_of_list(currshortcut);
+	close(in_fd[0]);
 
-	if (currslen < 2)
-	    k = COLS / 6;
-	else 
-	    k = COLS / ((currslen + (currslen %2)) / 2);
+	/* replace the standard in with the tempfile */
 
-	/* Determine what shortcut list was clicked */
-	mevent.y -= (editwinrows + 3);
+	if ((tempfile_fd = open(tempfile_name, O_RDONLY)) == -1) {
+	    close(in_fd[1]);
+	    exit(1);
+	}
+
+	if (dup2(tempfile_fd, STDIN_FILENO) != STDIN_FILENO) {
+	    close(tempfile_fd);
+	    close(in_fd[1]);
+	    exit(1);
+	}
+	close(tempfile_fd);
 
-	if (mevent.y < 0) /* They clicked on the statusbar */
-	    return;
+	/* send spell's standard out to the pipe */
 
-	/* Don't select stuff beyond list length */
-	if (mevent.x / k >= currslen)	
-	    return;
+	if (dup2(in_fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
+	    close(in_fd[1]);
+	    exit(1);
+	}
+	close(in_fd[1]);
 
-	for (i = 0; i < (mevent.x / k) * 2 + mevent.y; i++)
-	    s = s->next;
+	/* Start spell program, we are using the PATH here!?!? */
+	execlp("spell", "spell", NULL);
 
-	/* And ungetch that value */
-	ungetch(s->val);
+	/* Should not be reached, if spell is found!!! */
 
-	/* And if it's an alt-key sequence, we should probably send alt
-	   too ;-) */
-	if (s->val >= 'a' && s->val <= 'z')
-	   ungetch(27);
+	exit(1);
     }
-}
-#endif
-#endif
 
-/* Handler for SIGHUP */
-RETSIGTYPE handle_hup(int signal)
-{
-    die(_("Received SIGHUP"));
-}
+    /* Parent continues here */
 
-/* What do we do when we catch the suspend signal */
-RETSIGTYPE do_suspend(int signal)
-{
-    endwin();
-    printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
-    fflush(stdout);
+    close(in_fd[1]);
 
-    /* Restore the terminal settings for the disabled keys */
-    tcsetattr(0, TCSANOW, &oldterm);
+    /* Child process was not forked successfully */
 
-    /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but 
-	then we could be (and were) interrupted in the middle of the call.
-	So we do it the mutt way instead */
-    kill(0, SIGSTOP);
-}
+    if (pid_spell < 0) {
+	close(in_fd[0]);
+	return FALSE;
+    }
 
-/* Restore the suspend handler when we come back into the prog */
-RETSIGTYPE do_cont(int signal)
-{
-    /* Now we just update the screen instead of having to reenable the
-       SIGTSTP handler. */
+    /* Get system pipe buffer size */
 
-    doupdate();
-    /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
-	start suspending again. */
-    signal_init();
+    if ((pipe_buff_size = fpathconf(in_fd[0], _PC_PIPE_BUF)) < 1) {
+	close(in_fd[0]);
+	return FALSE;
+    }
 
-#ifndef NANO_SMALL
-    /* Perhaps the user resized the window while we slept. */
-    handle_sigwinch(0);
-#endif
-}
+    /* Read-in the returned spelling errors */
 
-#ifndef NANO_SMALL
-void handle_sigwinch(int s)
-{
-    const char *tty = ttyname(0);
-    int fd;
-    int result = 0;
-    struct winsize win;
+    read_buff_read = 0;
+    read_buff_size = pipe_buff_size + 1;
+    read_buff = read_buff_ptr = charalloc(read_buff_size);
 
-    if (!tty)
-	return;
-    fd = open(tty, O_RDWR);
-    if (fd == -1)
-	return;
-    result = ioctl(fd, TIOCGWINSZ, &win);
-    close(fd);
-    if (result == -1)
-	return;
+    while ((bytesread = read(in_fd[0], read_buff_ptr, pipe_buff_size)) > 0) {
+	read_buff_read += bytesread;
+	read_buff_size += pipe_buff_size;
+	read_buff = read_buff_ptr = nrealloc(read_buff, read_buff_size);
+	read_buff_ptr += read_buff_read;
+    }
 
-    /* Could check whether the COLS or LINES changed, and return
-     * otherwise.  EXCEPT, that COLS and LINES are ncurses global
-     * variables, and in some cases ncurses has already updated them. 
-     * But not in all cases, argh. */
-    COLS = win.ws_col;
-    LINES = win.ws_row;
-    if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
-	die_too_small();
+    *read_buff_ptr = (char) NULL;
+    close(in_fd[0]);
 
-#ifndef DISABLE_WRAPJUSTIFY
-    fill = wrap_at;
-    if (fill <= 0)
-	fill += COLS;
-    if (fill < MIN_FILL_LENGTH)
-	die_too_small();
-#endif
+    /* Process the spelling errors */
 
-    hblank = nrealloc(hblank, COLS + 1);
-    memset(hblank, ' ', COLS);
-    hblank[COLS] = '\0';
+    read_buff_word = read_buff_ptr = read_buff;
 
-#ifdef HAVE_RESIZETERM
-    resizeterm(LINES, COLS);
-#ifdef HAVE_WRESIZE
-    if (wresize(topwin, 2, COLS) == ERR)
-	die(_("Cannot resize top win"));
-    if (mvwin(topwin, 0, 0) == ERR)
-	die(_("Cannot move top win"));
-    if (wresize(edit, editwinrows, COLS) == ERR)
-	die(_("Cannot resize edit win"));
-    if (mvwin(edit, 2, 0) == ERR)
-	die(_("Cannot move edit win"));
-    if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
-	die(_("Cannot resize bottom win"));
-    if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
-	die(_("Cannot move bottom win"));
-#endif				/* HAVE_WRESIZE */
-#endif				/* HAVE_RESIZETERM */
+    while (*read_buff_ptr) {
 
-    fix_editbot();
+	if ((*read_buff_ptr == '\n') || (*read_buff_ptr == '\r')) {
+	    *read_buff_ptr = (char) NULL;
+	    if (read_buff_word != read_buff_ptr) {
+		if (!do_int_spell_fix(read_buff_word)) {
+		    read_buff_word = read_buff_ptr;
+		    break;
+		}
+	    }
+	    read_buff_word = read_buff_ptr + 1;
+	}
+	read_buff_ptr++;
+    }
 
-    if (current_y > editwinrows - 1)
-	edit_update(editbot, CENTER);
-    erase();
+    /* special case where last word doesn't end with \n or \r */
+    if (read_buff_word != read_buff_ptr)
+	do_int_spell_fix(read_buff_word);
 
-    /* Do these b/c width may have changed... */
-    refresh();
-    titlebar(NULL);
-    edit_refresh();
-    display_main_list();
-    blank_statusbar();
-    total_refresh();
+    free(read_buff);
+    replace_abort();
 
-    /* Turn cursor back on for sure */
-    curs_set(1);
+    /* Process end of spell process */
 
-    /* Jump back to main loop */
-    siglongjmp(jmpbuf, 1);
+    wait(&spell_status);
+    if (WIFEXITED(spell_status)) {
+	if (WEXITSTATUS(spell_status) != 0)
+	    return FALSE;
+    } else
+	return FALSE;
+
+    return TRUE;
 }
-#endif
 
-void signal_init(void)
+/* External spell checking. */
+int do_alt_speller(char *tempfile_name)
 {
-#ifdef _POSIX_VDISABLE
-    struct termios term;
+    int alt_spell_status, lineno_cur = current->lineno;
+    int x_cur = current_x, y_cur = current_y, pww_cur = placewewant;
+    pid_t pid_spell;
+    char *ptr;
+    static int arglen = 3;
+    static char **spellargs = (char **)NULL;
+#ifndef NANO_SMALL
+    int mark_set = ISSET(MARK_ISSET);
+    int mbb_lineno_cur = 0;
+	/* We're going to close the current file, and open the output of
+	   the alternate spell command.  The line that mark_beginbuf
+	   points to will be freed, so we save the line number and restore
+	   afterwards. */
+
+    if (mark_set) {
+	mbb_lineno_cur = mark_beginbuf->lineno;
+	UNSET(MARK_ISSET);
+    }
 #endif
 
-    /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
-    memset(&act, 0, sizeof(struct sigaction));
-    act.sa_handler = SIG_IGN;
-    sigaction(SIGINT, &act, NULL);
+    endwin();
 
-    /* Trap SIGHUP cuz we want to write the file out. */
-    act.sa_handler = handle_hup;
-    sigaction(SIGHUP, &act, NULL);
+    /* Set up an argument list to pass the execvp function */
+    if (spellargs == NULL) {
+	spellargs = nmalloc(arglen * sizeof(char *));
 
-#ifndef NANO_SMALL
-    act.sa_handler = handle_sigwinch;
-    sigaction(SIGWINCH, &act, NULL);
-#endif
+	spellargs[0] = strtok(alt_speller, " ");
+	while ((ptr = strtok(NULL, " ")) != NULL) {
+	    arglen++;
+	    spellargs = nrealloc(spellargs, arglen * sizeof(char *));
+	    spellargs[arglen - 3] = ptr;
+	}
+	spellargs[arglen - 1] = NULL;
+    }
+    spellargs[arglen - 2] = tempfile_name;
 
-#ifdef _POSIX_VDISABLE
-    tcgetattr(0, &term);
+    /* Start a new process for the alternate speller */
+    if ((pid_spell = fork()) == 0) {
+	/* Start alternate spell program; we are using the PATH here!?!? */
+	execvp(spellargs[0], spellargs);
 
-#ifdef VDSUSP
-    term.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif /* VDSUSP */
+	/* Should not be reached, if alternate speller is found!!! */
+	exit(1);
+    }
 
-#endif /* _POSIX_VDISABLE */
+    /* Could not fork?? */
+    if (pid_spell < 0)
+	return FALSE;
+
+    /* Wait for alternate speller to complete */
+
+    wait(&alt_spell_status);
+    if (!WIFEXITED(alt_spell_status) || WEXITSTATUS(alt_spell_status) != 0)
+	return FALSE;
+
+    refresh();
+    free_filestruct(fileage);
+    global_init(1);
+    open_file(tempfile_name, 0, 1);
+
+#ifndef NANO_SMALL
+    if (mark_set) {
+	do_gotopos(mbb_lineno_cur, mark_beginx, y_cur, 0);
+	mark_beginbuf = current;
+	mark_beginx = current_x;
+	    /* In case the line got shorter, assign mark_beginx. */
+	SET(MARK_ISSET);
+    }
+#endif
 
-    if (!ISSET(SUSPEND)) {
+    /* go back to the old position, mark the file as modified, and make
+       sure that the titlebar is refreshed */
+    do_gotopos(lineno_cur, x_cur, y_cur, pww_cur);
+    set_modified();
+    clearok(topwin, FALSE);
+    titlebar(NULL);
 
-/* Insane! */
-#ifdef _POSIX_VDISABLE
-	term.c_cc[VSUSP] = _POSIX_VDISABLE;
-#else
-	act.sa_handler = SIG_IGN;
-	sigaction(SIGTSTP, &act, NULL);
+    return TRUE;
+}
 #endif
 
-    } else {
-	/* If we don't do this, it seems other stuff interrupts the
-	   suspend handler!  Try using nano with mutt without this
-	   line. */
-	sigfillset(&act.sa_mask);
+int do_spell(void)
+{
+#ifdef DISABLE_SPELLER
+    nano_disabled_msg();
+    return (TRUE);
+#else
+    char *temp;
+    int spell_res;
 
-	act.sa_handler = do_suspend;
-	sigaction(SIGTSTP, &act, NULL);
+    if ((temp = safe_tempnam(0, "nano.")) == NULL) {
+	statusbar(_("Could not create a temporary filename: %s"),
+		  strerror(errno));
+	return 0;
+    }
 
-	act.sa_handler = do_cont;
-	sigaction(SIGCONT, &act, NULL);
+    if (write_file(temp, 1, 0, 0) == -1) {
+	statusbar(_("Spell checking failed: unable to write temp file!"));
+	free(temp);
+	return 0;
     }
 
-#ifdef _POSIX_VDISABLE
-    tcsetattr(0, TCSANOW, &term);
+#ifdef ENABLE_MULTIBUFFER
+    /* update the current open_files entry before spell-checking, in case
+       any problems occur */
+    add_open_file(1);
 #endif
-}
-
-void window_init(void)
-{
-    if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
-	die_too_small();
 
-    /* Set up the main text window */
-    edit = newwin(editwinrows, COLS, 2, 0);
+    if (alt_speller)
+	spell_res = do_alt_speller(temp);
+    else
+	spell_res = do_int_speller(temp);
 
-    /* And the other windows */
-    topwin = newwin(2, COLS, 0, 0);
-    bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
+    remove(temp);
 
-#ifdef PDCURSES
-    /* Oops, I guess we need this again.
-       Moved here so the keypad still works after a Meta-X, for example */
-    keypad(edit, TRUE);
-    keypad(bottomwin, TRUE);
-#endif
-}
+    if (spell_res)
+	statusbar(_("Finished checking spelling"));
+    else
+	statusbar(_("Spell checking failed"));
 
-void mouse_init(void)
-{
-#ifndef DISABLE_MOUSE
-#ifdef NCURSES_MOUSE_VERSION
-    if (ISSET(USE_MOUSE)) {
-	keypad_on(edit, 1);
-	keypad_on(bottomwin, 1);
+    free(temp);
+    return spell_res;
 
-	mousemask(BUTTON1_RELEASED, NULL);
-	mouseinterval(50);
-    } else
-	mousemask(0, NULL);
-#endif
 #endif
 }
 
-int do_tab(void)
-{
-    do_char('\t');
-    return 1;
-}
-
 #if !defined(DISABLE_WRAPPING) && !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
 /* The "indentation" of a line is the white-space between the quote part
  * and the non-white-space of the line. */
-size_t indent_length(const char *line) {
+size_t indent_length(const char *line)
+{
     size_t len = 0;
 
     assert(line != NULL);
@@ -2067,17 +2047,11 @@ size_t quote_length(const char *line)
 }
 #endif	/* !HAVE_REGEX_H */
 
-#ifdef HAVE_REGEX_H
-#  define IFREG(a, b) a, b
-#else
-#  define IFREG(a, b) a
-#endif
-
 /* a_line and b_line are lines of text.  The quotation part of a_line is
  * the first a_quote characters.  Check that the quotation part of
  * b_line is the same. */
 int quotes_match(const char *a_line, size_t a_quote,
-	IFREG(const char *b_line, const regex_t *qreg))
+		IFREG(const char *b_line, const regex_t *qreg))
 {
     /* Here is the assumption about a_quote: */
     assert(a_quote == quote_length(IFREG(a_line, qreg)));
@@ -2088,7 +2062,7 @@ int quotes_match(const char *a_line, size_t a_quote,
 /* We assume a_line and b_line have no quote part.  Then, we return whether
  * b_line could follow a_line in a paragraph. */
 size_t indents_match(const char *a_line, size_t a_indent,
-	const char *b_line, size_t b_indent)
+			const char *b_line, size_t b_indent)
 {
     assert(a_indent == indent_length(a_line));
     assert(b_indent == indent_length(b_line));
@@ -2101,7 +2075,7 @@ size_t indents_match(const char *a_line, size_t a_indent,
  * copies of the lines in place, too.  We return the new copy of
  * first_line. */
 filestruct *backup_lines(filestruct *first_line, size_t par_len,
-	size_t quote_len)
+			size_t quote_len)
 {
     /* We put the original lines, not copies, into the cut buffer, just
      * out of a misguided sense of consistency, so if you un-cut, you
@@ -2515,7 +2489,7 @@ int do_justify(void)
     reset_cursor();
 
     /* Now get a keystroke and see if it's unjustify; if not, unget the
-     * keystroke and return */
+     * keystroke and return. */
 
 #ifndef DISABLE_MOUSE
 #ifdef NCURSES_MOUSE_VERSION
@@ -2585,207 +2559,249 @@ int do_justify(void)
 #endif
 }
 
-#ifndef DISABLE_HELP
-/* This function allocates help_text, and stores the help string in it. 
- * help_text should be NULL initially. */
-void help_init(void)
+int do_exit(void)
 {
-    size_t allocsize = 1;	/* space needed for help_text */
-    char *ptr = NULL;
-#ifndef NANO_SMALL
-    const toggle *t;
+    int i;
+
+    if (!ISSET(MODIFIED)) {
+
+#ifdef ENABLE_MULTIBUFFER
+	if (!close_open_file()) {
+	    display_main_list();
+	    return 1;
+	}
+	else
 #endif
-    const shortcut *s;
+	    finish(0);
+    }
 
-    /* First set up the initial help text for the current function */
-    if (currshortcut == whereis_list || currshortcut == replace_list
-	     || currshortcut == replace_list_2)
-	ptr = _("Search Command Help Text\n\n "
-		"Enter the words or characters you would like to search "
-		"for, then hit enter.  If there is a match for the text you "
-		"entered, the screen will be updated to the location of the "
-		"nearest match for the search string.\n\n "
-		"If using Pico Mode via the -p or --pico flags, the "
-		"Meta-P toggle, or a nanorc file, the previous search "
-		"string will be shown in brackets after the Search: prompt.  "
-		"Hitting Enter without entering any text will perform the "
-		"previous search.  Otherwise, the previous string will be "
-		"placed before the cursor, and can be edited or deleted "
-		"before hitting enter.\n\n The following function keys are "
-		"available in Search mode:\n\n");
-    else if (currshortcut == goto_list)
-	ptr = _("Go To Line Help Text\n\n "
-		"Enter the line number that you wish to go to and hit "
-		"Enter.  If there are fewer lines of text than the "
-		"number you entered, you will be brought to the last line "
-		"of the file.\n\n The following function keys are "
-		"available in Go To Line mode:\n\n");
-    else if (currshortcut == insertfile_list)
-	ptr = _("Insert File Help Text\n\n "
-		"Type in the name of a file to be inserted into the current "
-		"file buffer at the current cursor location.\n\n "
-		"If you have compiled nano with multiple file buffer "
-		"support, and enable multiple buffers with the -F "
-		"or --multibuffer command line flags, the Meta-F toggle, or "
-		"a nanorc file, inserting a file will cause it to be "
-		"loaded into a separate buffer (use Meta-< and > to switch "
-		"between file buffers).\n\n If you need another blank "
-		"buffer, do not enter any filename, or type in a "
-		"nonexistent filename at the prompt and press "
-		"Enter.\n\n The following function keys are "
-		"available in Insert File mode:\n\n");
-    else if (currshortcut == writefile_list)
-	ptr = _("Write File Help Text\n\n "
-		"Type the name that you wish to save the current file "
-		"as and hit Enter to save the file.\n\n If you have "
-		"selected text with Ctrl-^, you will be prompted to "
-		"save only the selected portion to a separate file.  To "
-		"reduce the chance of overwriting the current file with "
-		"just a portion of it, the current filename is not the "
-		"default in this mode.\n\n The following function keys "
-		"are available in Write File mode:\n\n");
-#ifndef DISABLE_BROWSER
-    else if (currshortcut == browser_list)
-	ptr = _("File Browser Help Text\n\n "
-		"The file browser is used to visually browse the "
-		"directory structure to select a file for reading "
-		"or writing.  You may use the arrow keys or Page Up/"
-		"Down to browse through the files, and S or Enter to "
-		"choose the selected file or enter the selected "
-		"directory.  To move up one level, select the directory "
-		"called \"..\" at the top of the file list.\n\n The "
-		"following function keys are available in the file "
-		"browser:\n\n");
-    else if (currshortcut == gotodir_list)
-	ptr = _("Browser Go To Directory Help Text\n\n "
-		"Enter the name of the directory you would like to "
-		"browse to.\n\n If tab completion has not been disabled, "
-		"you can use the TAB key to (attempt to) automatically "
-		"complete the directory name.\n\n The following function "
-		"keys are available in Browser Go To Directory mode:\n\n");
+    if (ISSET(TEMP_OPT)) {
+	i = 1;
+    } else {
+	i = do_yesno(0, 0,
+		     _
+		     ("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES) ? "));
+    }
+
+#ifdef DEBUG
+    dump_buffer(fileage);
 #endif
-    else if (currshortcut == spell_list)
-	ptr = _("Spell Check Help Text\n\n "
-		"The spell checker checks the spelling of all text "
-		"in the current file.  When an unknown word is "
-		"encountered, it is highlighted and a replacement can "
-		"be edited.  It will then prompt to replace every "
-		"instance of the given misspelled word in the "
-		"current file.\n\n The following other functions are "
-		"available in Spell Check mode:\n\n");
+
+    if (i == 1) {
+	if (do_writeout(filename, 1, 0) > 0) {
+
+#ifdef ENABLE_MULTIBUFFER
+	    if (!close_open_file()) {
+		display_main_list();
+		return 1;
+	    }
+	    else
+#endif
+		finish(0);
+	}
+    } else if (i == 0) {
+
+#ifdef ENABLE_MULTIBUFFER
+	if (!close_open_file()) {
+	    display_main_list();
+	    return 1;
+	}
+	else
+#endif
+	    finish(0);
+    } else
+	statusbar(_("Cancelled"));
+
+    display_main_list();
+    return 1;
+}
+
+void signal_init(void)
+{
+#ifdef _POSIX_VDISABLE
+    struct termios term;
+#endif
+
+    /* Trap SIGINT and SIGQUIT cuz we want them to do useful things. */
+    memset(&act, 0, sizeof(struct sigaction));
+    act.sa_handler = SIG_IGN;
+    sigaction(SIGINT, &act, NULL);
+
+    /* Trap SIGHUP cuz we want to write the file out. */
+    act.sa_handler = handle_hup;
+    sigaction(SIGHUP, &act, NULL);
+
 #ifndef NANO_SMALL
-    else if (currshortcut == extcmd_list)
-	ptr = _("External Command Help Text\n\n "
-		"This menu allows you to insert the output of a command "
-		"run by the shell into the current buffer (or a new "
-		"buffer in multibuffer mode).\n\n The following keys are "
-		"available in this mode:\n\n");
+    act.sa_handler = handle_sigwinch;
+    sigaction(SIGWINCH, &act, NULL);
 #endif
-    else /* Default to the main help list */
-	ptr = _(" nano help text\n\n "
-	  "The nano editor is designed to emulate the functionality and "
-	  "ease-of-use of the UW Pico text editor.  There are four main "
-	  "sections of the editor: The top line shows the program "
-	  "version, the current filename being edited, and whether "
-	  "or not the file has been modified.  Next is the main editor "
-	  "window showing the file being edited.  The status line is "
-	  "the third line from the bottom and shows important messages. "
-	  "The bottom two lines show the most commonly used shortcuts "
-	  "in the editor.\n\n "
-	  "The notation for shortcuts is as follows: Control-key "
-	  "sequences are notated with a caret (^) symbol and are entered "
-	  "with the Control (Ctrl) key.  Escape-key sequences are notated "
-	  "with the Meta (M) symbol and can be entered using either the "
-	  "Esc, Alt or Meta key depending on your keyboard setup.  The "
-	  "following keystrokes are available in the main editor window.  "
-	  "Alternative keys are shown in parentheses:\n\n");
 
-    allocsize += strlen(ptr);
+#ifdef _POSIX_VDISABLE
+    tcgetattr(0, &term);
 
-    /* The space needed for the shortcut lists, at most COLS characters,
-     * plus '\n'. */
-    allocsize += (COLS + 1) * length_of_list(currshortcut);
+#ifdef VDSUSP
+    term.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif /* VDSUSP */
 
-#ifndef NANO_SMALL
-    /* If we're on the main list, we also count the toggle help text. 
-     * Each line has "M-%c\t\t\t", which fills 24 columns, plus at most
-     * COLS - 24 characters, plus '\n'.*/
-    if (currshortcut == main_list)
-	for (t = toggles; t != NULL; t = t->next)
-	    allocsize += COLS - 17;
-#endif /* !NANO_SMALL */
+#endif /* _POSIX_VDISABLE */
 
-    /* help_text has been freed and set to NULL unless the user resized
-     * while in the help screen. */
-    free(help_text);
+    if (!ISSET(SUSPEND)) {
 
-    /* Allocate space for the help text */
-    help_text = charalloc(allocsize);
+/* Insane! */
+#ifdef _POSIX_VDISABLE
+	term.c_cc[VSUSP] = _POSIX_VDISABLE;
+#else
+	act.sa_handler = SIG_IGN;
+	sigaction(SIGTSTP, &act, NULL);
+#endif
 
-    /* Now add the text we want */
-    strcpy(help_text, ptr);
-    ptr = help_text + strlen(help_text);
+    } else {
+	/* If we don't do this, it seems other stuff interrupts the
+	   suspend handler!  Try using nano with mutt without this
+	   line. */
+	sigfillset(&act.sa_mask);
 
-    /* Now add our shortcut info */
-    for (s = currshortcut; s != NULL; s = s->next) {
-	/* true if the character in s->altval is shown in first column */
-	int meta_shortcut = 0;
+	act.sa_handler = do_suspend;
+	sigaction(SIGTSTP, &act, NULL);
 
-	if (s->val > 0 && s->val < 32)
-	    ptr += sprintf(ptr, "^%c", s->val + 64);
-#ifndef NANO_SMALL
-	else if (s->val == NANO_CONTROL_SPACE)
-	    ptr += sprintf(ptr, "^%.6s", _("Space"));
-	else if (s->altval == NANO_ALT_SPACE) {
-	    meta_shortcut = 1;
-	    ptr += sprintf(ptr, "M-%.5s", _("Space"));
-	}
+	act.sa_handler = do_cont;
+	sigaction(SIGCONT, &act, NULL);
+    }
+
+#ifdef _POSIX_VDISABLE
+    tcsetattr(0, TCSANOW, &term);
 #endif
-	else if (s->altval > 0) {
-	    meta_shortcut = 1;
-	    ptr += sprintf(ptr, "M-%c", s->altval -
-			(('A' <= s->altval && s->altval <= 'Z') ||
-			'a' <= s->altval ? 32 : 0));
-	}
-	/* Hack */
-	else if (s->val >= 'a') {
-	    meta_shortcut = 1;
-	    ptr += sprintf(ptr, "M-%c", s->val - 32);
-	}
+}
 
-	*(ptr++) = '\t';
+/* Handler for SIGHUP */
+RETSIGTYPE handle_hup(int signal)
+{
+    die(_("Received SIGHUP"));
+}
 
-	if (s->misc1 > KEY_F0 && s->misc1 <= KEY_F(64))
-	    ptr += sprintf(ptr, "(F%d)", s->misc1 - KEY_F0);
+/* What do we do when we catch the suspend signal */
+RETSIGTYPE do_suspend(int signal)
+{
+    endwin();
+    printf("\n\n\n\n\nUse \"fg\" to return to nano\n");
+    fflush(stdout);
 
-	*(ptr++) = '\t';
+    /* Restore the terminal settings for the disabled keys */
+    tcsetattr(0, TCSANOW, &oldterm);
 
-	if (!meta_shortcut && s->altval > 0)
-	    ptr += sprintf(ptr, "(M-%c)", s->altval -
-		(('A' <= s->altval && s->altval <= 'Z') || 'a' <= s->altval
-			? 32 : 0));
+    /* We used to re-enable the default SIG_DFL and raise SIGTSTP, but 
+	then we could be (and were) interrupted in the middle of the call.
+	So we do it the mutt way instead */
+    kill(0, SIGSTOP);
+}
 
-	*(ptr++) = '\t';
+/* Restore the suspend handler when we come back into the prog */
+RETSIGTYPE do_cont(int signal)
+{
+    /* Now we just update the screen instead of having to reenable the
+       SIGTSTP handler. */
 
-	assert(s->help != NULL);
-	ptr += sprintf(ptr, "%.*s\n", COLS - 24, s->help);
-    }
+    doupdate();
+    /* The Hurd seems to need this, otherwise a ^Y after a ^Z will
+	start suspending again. */
+    signal_init();
 
 #ifndef NANO_SMALL
-    /* And the toggles... */
-    if (currshortcut == main_list)
-	for (t = toggles; t != NULL; t = t->next) {
-	    ptr += sprintf(ptr, "M-%c\t\t\t", t->val - 32);
-	    assert(t->desc != NULL);
-	    ptr += sprintf(ptr, _("%.*s enable/disable\n"), COLS - 24, t->desc);
-	}
+    /* Perhaps the user resized the window while we slept. */
+    handle_sigwinch(0);
+#endif
+}
+
+#ifndef NANO_SMALL
+void handle_sigwinch(int s)
+{
+    const char *tty = ttyname(0);
+    int fd;
+    int result = 0;
+    struct winsize win;
+
+    if (!tty)
+	return;
+    fd = open(tty, O_RDWR);
+    if (fd == -1)
+	return;
+    result = ioctl(fd, TIOCGWINSZ, &win);
+    close(fd);
+    if (result == -1)
+	return;
+
+    /* Could check whether the COLS or LINES changed, and return
+     * otherwise.  EXCEPT, that COLS and LINES are ncurses global
+     * variables, and in some cases ncurses has already updated them. 
+     * But not in all cases, argh. */
+    COLS = win.ws_col;
+    LINES = win.ws_row;
+    if ((editwinrows = LINES - 5 + no_help()) < MIN_EDITOR_ROWS)
+	die_too_small();
+
+#ifndef DISABLE_WRAPJUSTIFY
+    fill = wrap_at;
+    if (fill <= 0)
+	fill += COLS;
+    if (fill < MIN_FILL_LENGTH)
+	die_too_small();
+#endif
+
+    hblank = nrealloc(hblank, COLS + 1);
+    memset(hblank, ' ', COLS);
+    hblank[COLS] = '\0';
+
+#ifdef HAVE_RESIZETERM
+    resizeterm(LINES, COLS);
+#ifdef HAVE_WRESIZE
+    if (wresize(topwin, 2, COLS) == ERR)
+	die(_("Cannot resize top win"));
+    if (mvwin(topwin, 0, 0) == ERR)
+	die(_("Cannot move top win"));
+    if (wresize(edit, editwinrows, COLS) == ERR)
+	die(_("Cannot resize edit win"));
+    if (mvwin(edit, 2, 0) == ERR)
+	die(_("Cannot move edit win"));
+    if (wresize(bottomwin, 3 - no_help(), COLS) == ERR)
+	die(_("Cannot resize bottom win"));
+    if (mvwin(bottomwin, LINES - 3 + no_help(), 0) == ERR)
+	die(_("Cannot move bottom win"));
+#endif				/* HAVE_WRESIZE */
+#endif				/* HAVE_RESIZETERM */
+
+    fix_editbot();
+
+    if (current_y > editwinrows - 1)
+	edit_update(editbot, CENTER);
+    erase();
+
+    /* Do these b/c width may have changed... */
+    refresh();
+    titlebar(NULL);
+    edit_refresh();
+    display_main_list();
+    blank_statusbar();
+    total_refresh();
+
+    /* Turn cursor back on for sure */
+    curs_set(1);
+
+    /* Jump back to main loop */
+    siglongjmp(jmpbuf, 1);
+}
 #endif /* !NANO_SMALL */
 
-    /* If all went well, we didn't overwrite the allocated space for
-       help_text. */
-    assert(strlen(help_text) < allocsize);
+/* If the NumLock key has made the keypad go awry, print an error
+   message; hopefully we can address it later. */
+void print_numlock_warning(void)
+{
+    static int didmsg = 0;
+    if (!didmsg) {
+	statusbar(_
+		  ("NumLock glitch detected.  Keypad will malfunction with NumLock off"));
+	didmsg = 1;
+    }
 }
-#endif
 
 #ifndef NANO_SMALL
 void do_toggle(const toggle *which)
@@ -2833,18 +2849,6 @@ void do_toggle(const toggle *which)
 }
 #endif /* !NANO_SMALL */
 
-/* If the NumLock key has made the keypad go awry, print an error
-   message; hopefully we can address it later. */
-void print_numlock_warning(void)
-{
-    static int didmsg = 0;
-    if (!didmsg) {
-	statusbar(_
-		  ("NumLock glitch detected.  Keypad will malfunction with NumLock off"));
-	didmsg = 1;
-    }
-}
-
 /* This function returns the correct keystroke, given the A,B,C or D
    input key.  This is a common sequence of many terms which send
    Esc-O-[A-D] or Esc-[-[A-D]. */
@@ -3460,7 +3464,7 @@ int main(int argc, char *argv[])
 
 	/* Look through the main shortcut list to see if we've hit a
 	   shortcut key */
-        
+
 #if !defined(DISABLE_BROWSER) || !defined(DISABLE_MOUSE) || !defined (DISABLE_HELP)
 	for (s = currshortcut; s != NULL && !keyhandled; s = s->next) {
 #else
@@ -3474,6 +3478,10 @@ int main(int argc, char *argv[])
 		else
 		    s->func();
 		keyhandled = 1;
+		/* rarely, the value of s can change after s->func(),
+		   leading to problems; get around this by breaking out
+		   explicitly once we successfully handle a shortcut */
+		break;
 	    }
 	}
 	/* If we're in raw mode or using Alt-Alt-x, we have to catch
@@ -3489,7 +3497,6 @@ int main(int argc, char *argv[])
 	    keyhandled = 1;
 	}
 
-
 #ifndef USE_SLANG
 	/* Hack, make insert key do something useful, like insert file */
 	if (kbinput == KEY_IC) {
diff --git a/nano.h b/nano.h
index bc34f89fc3551cd09a1bc6d9be85294c14abaad2..74179e6f133ee8953534190a1abad9f3242bbf7c 100644
--- a/nano.h
+++ b/nano.h
@@ -326,6 +326,7 @@ know what you're doing */
 #define NANO_TOFILES_KEY	NANO_CONTROL_T
 #define NANO_APPEND_KEY		NANO_ALT_A
 #define NANO_PREPEND_KEY	NANO_ALT_P
+#define NANO_LOAD_KEY		NANO_ALT_F
 #define NANO_OPENPREV_KEY	NANO_ALT_LCARAT
 #define NANO_OPENNEXT_KEY	NANO_ALT_RCARAT
 #define NANO_OPENPREV_ALTKEY	NANO_ALT_COMMA
diff --git a/proto.h b/proto.h
index c8079e61c7fcffc53e767f5afb5c128311131392..63ba5800dc11320f70ed279ae4f5dbf738d23f7e 100644
--- a/proto.h
+++ b/proto.h
@@ -59,13 +59,7 @@ extern char *operating_dir;
 extern char *full_operating_dir;
 #endif
 #ifndef DISABLE_SPELLER
-extern  char *alt_speller;
-#endif
-#ifndef DISABLE_TABCOMP
-char *real_dir_from_tilde(char *buf);
-#endif
-#ifndef DISABLE_BROWSER
-char *do_browse_from(char *inpath);
+extern char *alt_speller;
 #endif
 
 extern struct stat fileinfo;
@@ -116,23 +110,28 @@ extern toggle *toggles;
 
 /* Public functions in color.c */
 #ifdef ENABLE_COLOR
-void set_colorpairs(void);
 void do_colorinit(void);
 void update_color(void);
 #endif /* ENABLE_COLOR */
 
 /* Public functions in cut.c */
-int do_cut_text(void);
-int do_uncut_text(void);
 filestruct *get_cutbottom(void);
 void add_to_cutbuffer(filestruct *inptr);
 void cut_marked_segment(filestruct *top, size_t top_x, filestruct *bot,
                         size_t bot_x, int destructive);
+int do_cut_text(void);
+int do_uncut_text(void);
 
 /* Public functions in files.c */
+void load_file(int update);
+void new_file(void);
+filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len);
 int write_file(char *name, int tmpfile, int append, int nonamechange);
-int open_file(const char *filename, int insert, int quiet);
 int read_file(FILE *f, const char *filename, int quiet);
+int open_file(const char *filename, int insert, int quiet);
+char *get_next_filename(const char *name);
+int do_insertfile(int loading_file);
+int do_insertfile_void(void);
 #ifdef ENABLE_MULTIBUFFER
 openfilestruct *make_new_opennode(openfilestruct *prevnode);
 void splice_opennode(openfilestruct *begin, openfilestruct *newnode, openfilestruct *end);
@@ -140,157 +139,299 @@ void unlink_opennode(const openfilestruct *fileptr);
 void delete_opennode(openfilestruct *fileptr);
 void free_openfilestruct(openfilestruct *src);
 int add_open_file(int update);
-int close_open_file(void);
+int load_open_file(void);
+int open_prevfile(int closing_file);
 int open_prevfile_void(void);
+int open_nextfile(int closing_file);
 int open_nextfile_void(void);
+int close_open_file(void);
+#endif
+#if !defined(DISABLE_SPELLER) || !defined(DISABLE_OPERATINGDIR)
+char *get_full_path(char *origpath);
+#endif
+#ifndef DISABLE_SPELLER
+char *check_writable_directory(char *path);
+char *safe_tempnam(const char *dirname, const char *filename_prefix);
 #endif
 #ifndef DISABLE_OPERATINGDIR
 int check_operating_dir(char *currpath, int allow_tabcomp);
 #endif
+int write_file(char *name, int tmp, int append, int nonamechange);
 int do_writeout(char *path, int exiting, int append);
-char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
-void new_file(void);
 int do_writeout_void(void);
-int do_insertfile_void(void);
-char *get_next_filename(const char *name);
-#ifndef DISABLE_SPELLER
-char *safe_tempnam(const char *dirname, const char *filename_prefix);
+#ifndef DISABLE_TABCOMP
+char *real_dir_from_tilde(char *buf);
+#endif
+int append_slash_if_dir(char *buf, int *lastwastab, int *place);
+char **username_tab_completion(char *buf, int *num_matches);
+char **cwd_tab_completion(char *buf, int *num_matches);
+char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list);
+#ifndef DISABLE_BROWSER
+struct stat filestat(const char *path);
+int diralphasort(const void *va, const void *vb);
+void free_charptrarray(char **array, int len);
+char *tail(char *foo);
+void striponedir(char *foo);
+char **browser_init(char *path, int *longest, int *numents);
+char *do_browser(char *inpath);
+char *do_browse_from(char *inpath);
 #endif
 
 /* Public functions in global.c */
 int length_of_list(const shortcut *s);
+void sc_init_one(shortcut **shortcutage, int key, const char *desc,
+#ifndef DISABLE_HELP
+	const char *help,
+#endif
+	int alt, int misc1, int misc2, int view, int (*func) (void));
+#ifndef NANO_SMALL
+void toggle_init_one(int val, const char *desc, int flag);
+void toggle_init(void);
+#ifdef DEBUG
+void free_toggles(void);
+#endif
+#endif
+void free_shortcutage(shortcut **shortcutage);
 void shortcut_init(int unjustify);
 #ifdef DEBUG
 void thanks_for_all_the_fish(void);
 #endif
 
 /* Public functions in move.c */
-int do_first_line(void);
-int do_last_line(void);
-size_t xplustabs(void);
-size_t actual_x(const filestruct *fileptr, size_t xplus);
-size_t strnlenpt(const char *buf, size_t size);
-size_t strlenpt(const char *buf);
-void reset_cursor(void);
-void blank_bottombars(void);
-void blank_edit(void);
-void blank_statusbar(void);
-void blank_statusbar_refresh(void);
-void check_statblank(void);
-void titlebar(const char *path);
-void bottombars(const shortcut *s);
-void set_modified(void);
+int do_home(void);
+int do_end(void);
+void page_up(void);
+int do_page_up(void);
+int do_page_down(void);
 int do_up(void);
 int do_down(void);
 int do_left(void);
 int do_right(void);
-void page_up(void);
-int do_page_up(void);
-int do_page_down(void);
-int do_home(void);
-int do_end(void);
 
 /* Public functions in nano.c */
-void renumber(filestruct *fileptr);
+RETSIGTYPE finish(int sigage);
+void die(const char *msg, ...);
+void die_save_file(const char *die_filename);
+void die_too_small(void);
+void print_view_warning(void);
+void global_init(int save_cutbuffer);
+void window_init(void);
+void mouse_init(void);
+#ifndef DISABLE_HELP
+void help_init(void);
+#endif
+filestruct *make_new_node(filestruct *prevnode);
+filestruct *copy_node(const filestruct *src);
+void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
+void unlink_node(const filestruct *fileptr);
+void delete_node(filestruct *fileptr);
+filestruct *copy_filestruct(const filestruct *src);
 void free_filestruct(filestruct *src);
-int no_help(void);
 void renumber_all(void);
-int open_pipe(const char *command);
-int do_prev_word(void);
-int do_next_word(void);
-void delete_node(filestruct *fileptr);
-void wrap_reset(void);
+void renumber(filestruct *fileptr);
+void print1opt(const char *shortflag, const char *longflag,
+		const char *desc);
+void usage(void);
+void version(void);
 void do_early_abort(void);
-void die(const char *msg, ...);
-void splice_node(filestruct *begin, filestruct *newnode, filestruct *end);
+int no_help(void);
+#if defined(DISABLE_JUSTIFY) || defined(DISABLE_SPELLER) || defined(DISABLE_HELP) || defined(NANO_SMALL)
 void nano_disabled_msg(void);
-void window_init(void);
+#endif
+#ifndef NANO_SMALL
+RETSIGTYPE cancel_fork(int signal);
+int open_pipe(const char *command);
+#endif
+#ifndef DISABLE_MOUSE
+#ifdef NCURSES_MOUSE_VERSION
 void do_mouse(void);
-void print_view_warning(void);
-int do_exit(void);
-int do_spell(void);
-int do_mark(void);
-int do_delete(void);
+#endif
+#endif
+void do_char(char ch);
 int do_backspace(void);
+int do_delete(void);
 int do_tab(void);
-int do_justify(void);
 int do_enter(void);
+int do_next_word(void);
+int do_prev_word(void);
+int do_mark(void);
+void wrap_reset(void);
+#ifndef DISABLE_WRAPPING
 int do_wrap(filestruct *inptr);
+#endif
+#ifndef DISABLE_SPELLER
+int do_int_spell_fix(const char *word);
+int do_int_speller(char *tempfile_name);
+int do_alt_speller(char *tempfile_name);
+#endif
+int do_spell(void);
+#if !defined(DISABLE_WRAPPING) && !defined(NANO_SMALL) || !defined(DISABLE_JUSTIFY)
+size_t indent_length(const char *line);
+#endif
+#ifndef DISABLE_JUSTIFY
+int justify_format(int changes_allowed, filestruct *line, size_t skip);
+#ifdef HAVE_REGEX_H
+size_t quote_length(const char *line, const regex_t *qreg);
+#else
+size_t quote_length(const char *line);
+#endif
+#ifdef HAVE_REGEX_H
+#  define IFREG(a, b) a, b
+#else
+#  define IFREG(a, b) a
+#endif
+int quotes_match(const char *a_line, size_t a_quote,
+		IFREG(const char *b_line, const regex_t *qreg));
+size_t indents_match(const char *a_line, size_t a_indent,
+			const char *b_line, size_t b_indent);
+filestruct *backup_lines(filestruct *first_line, size_t par_len,
+			size_t quote_len);
+int break_line(const char *line, int goal, int force);
+#endif /* !DISABLE_JUSTIFY */
+int do_justify(void);
+int do_exit(void);
 void signal_init(void);
+RETSIGTYPE handle_hup(int signal);
+RETSIGTYPE do_suspend(int signal);
+RETSIGTYPE do_cont(int signal);
+#ifndef NANO_SMALL
 void handle_sigwinch(int s);
-void die_save_file(const char *die_filename);
-size_t indent_length(const char *line);
-
-filestruct *copy_node(const filestruct *src);
-filestruct *copy_filestruct(const filestruct *src);
-filestruct *make_new_node(filestruct *prevnode);
-#ifndef DISABLE_HELP
-void help_init(void);
 #endif
+void print_numlock_warning(void);
+#ifndef NANO_SMALL
+void do_toggle(const toggle *which);
+#endif
+int ABCD(int input);
 
 /* Public functions in rcfile.c */
 #ifdef ENABLE_NANORC
+void rcfile_error(const char *msg, ...);
+void rcfile_msg(const char *msg, ...);
+char *parse_next_word(char *ptr);
+char *parse_argument(char *ptr);
+#ifdef ENABLE_COLOR
+int colortoint(const char *colorname, int *bright);
+char *parse_next_regex(char *ptr);
+void parse_syntax(char *ptr);
+void parse_colors(char *ptr);
+#endif /* ENABLE_COLOR */
+void parse_rcfile(FILE *rcstream);
 void do_rcfile(void);
-#endif
+#endif /* ENABLE_NANORC */
 
 /* Public functions in search.c */
-int do_gotoline(int line, int save_pos);
+#ifdef HAVE_REGEX_H
+void regexp_init(const char *regexp);
+void regexp_cleanup(void);
+#endif
+void not_found_msg(const char *str);
+void search_abort(void);
+void search_init_globals(void);
+int search_init(int replacing);
 int is_whole_word(int curr_pos, const char *datastr, const char *searchword);
+filestruct *findnextstr(int quiet, int bracket_mode,
+			const filestruct *begin, int beginx,
+			const char *needle);
+int do_search(void);
+void replace_abort(void);
+#ifdef HAVE_REGEX_H
+int replace_regexp(char *string, int create_flag);
+#endif
+char *replace_line(void);
+void print_replaced(int num);
 int do_replace_loop(const char *prevanswer, const filestruct *begin,
 			int *beginx, int wholewords, int *i);
-int do_find_bracket(void);
+int do_replace(void);
+void goto_abort(void);
+int do_gotoline(int line, int save_pos);
+int do_gotoline_void(void);
 #if defined (ENABLE_MULTIBUFFER) || !defined (DISABLE_SPELLER)
 void do_gotopos(int line, int pos_x, int pos_y, int pos_placewewant);
 #endif
-void search_init_globals(void);
-void replace_abort(void);
-int do_gotoline_void(void);
-int do_search(void);
-int do_replace(void);
-filestruct *findnextstr(int quiet, int bracket_mode, const filestruct *begin,
-		int beginx, const char *needle);
+int do_find_bracket(void);
 
 /* Public functions in utils.c */
-const char *stristr(const char *haystack, const char *needle);
-const char *strstrwrapper(const char *haystack, const char *needle,
-		const char *rev_start, int line_pos);
 int is_cntrl_char(int c);
 int num_of_digits(int n);
-int check_wildcard_match(const char *text, const char *pattern);
 void align(char **strp);
 void null_at(char **data, size_t index);
 void unsunder(char *str, size_t true_len);
 void sunder(char *str);
+#ifndef NANO_SMALL
+const char *revstrstr(const char *haystack, const char *needle,
+			const char *rev_start);
+const char *revstristr(const char *haystack, const char *needle,
+			const char *rev_start);
+#endif
+const char *stristr(const char *haystack, const char *needle);
+const char *strstrwrapper(const char *haystack, const char *needle,
+			const char *rev_start, int line_pos);
 void nperror(const char *s);
-char *mallocstrcpy(char *dest, const char *src);
 void *nmalloc(size_t howmuch);
+char *charalloc(size_t howmuch);
 void *nrealloc(void *ptr, size_t howmuch);
+char *mallocstrcpy(char *dest, const char *src);
 void new_magicline(void);
-char *charalloc(size_t howmuch);
+#ifndef DISABLE_TABCOMP
+int check_wildcard_match(const char *text, const char *pattern);
+#endif
 
 /* Public functions in winio.c */
-int do_yesno(int all, int leavecursor, const char *msg, ...);
-int statusq(int allowtabs, const shortcut *s, const char *def,
-		const char *msg, ...);
-void do_replace_highlight(int highlight_flag, const char *word);
+int do_first_line(void);
+int do_last_line(void);
+int xpt(const filestruct *fileptr, int index);
+size_t xplustabs(void);
+size_t actual_x(const filestruct *fileptr, size_t xplus);
+size_t strnlenpt(const char *buf, size_t size);
+size_t strlenpt(const char *buf);
+void blank_bottombars(void);
+void blank_bottomwin(void);
+void blank_edit(void);
+void blank_statusbar(void);
+void blank_statusbar_refresh(void);
+void check_statblank(void);
+void nanoget_repaint(const char *buf, const char *inputbuf, int x);
+int nanogetstr(int allowtabs, const char *buf, const char *def,
+		const shortcut *s
+#ifndef DISABLE_TABCOMP
+		, int *list
+#endif
+		);
+void set_modified(void);
+void titlebar(const char *path);
+void bottombars(const shortcut *s);
+void onekey(const char *keystroke, const char *desc, int len);
+int get_page_start_virtual(int page);
+int get_page_from_virtual(int virtual);
+int get_page_end_virtual(int page);
+int get_page_start(int column);
+void reset_cursor(void);
+void add_marked_sameline(int begin, int end, filestruct *fileptr, int y,
+			 int virt_cur_x, int this_page);
+void edit_add(filestruct *fileptr, int yval, int start, int virt_cur_x,
+	      int virt_mark_beginx, int this_page);
+void update_line(filestruct *fileptr, int index);
+void update_cursor(void);
+void center_cursor(void);
 void edit_refresh(void);
 void edit_refresh_clearok(void);
 void edit_update(filestruct *fileptr, topmidbotnone location);
-void update_cursor(void);
+int statusq(int tabs, const shortcut *s, const char *def,
+		const char *msg, ...);
+int do_yesno(int all, int leavecursor, const char *msg, ...);
+int total_refresh(void);
+void display_main_list(void);
+void statusbar(const char *msg, ...);
+int do_cursorpos(int constant);
+int do_cursorpos_void(void);
+int do_help(void);
+int keypad_on(WINDOW *win, int newval);
+void do_replace_highlight(int highlight_flag, const char *word);
+void fix_editbot(void);
 #ifdef DEBUG
 void dump_buffer(const filestruct *inptr);
 void dump_buffer_reverse(void);
 #endif
-void update_line(filestruct *fileptr, int index);
-void fix_editbot(void);
-void statusbar(const char *msg, ...);
-void center_cursor(void);
-void display_main_list(void);
 #ifdef NANO_EXTRA
 void do_credits(void);
 #endif
-int do_cursorpos(int constant);
-int do_cursorpos_void(void);
-int total_refresh(void);
-int do_help(void);
-int keypad_on(WINDOW *win, int newval);
diff --git a/rcfile.c b/rcfile.c
index 6b7b1e7f4752e682e89833ec26a6f14fa7bf5437..26c5e359f2b5a6078accaac13a77208872bf6b07 100644
--- a/rcfile.c
+++ b/rcfile.c
@@ -188,24 +188,6 @@ char *parse_argument(char *ptr)
 
 #ifdef ENABLE_COLOR
 
-char *parse_next_regex(char *ptr)
-{
-    while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
-	   && *ptr != '\n' && *ptr != '\0')
-	ptr++;
-
-    if (*ptr == '\0')
-	return NULL;
-
-    /* Null terminate and advance ptr */
-    *ptr++ = '\0';
-
-    while (*ptr == ' ' || *ptr == '\t')
-	ptr++;
-
-    return ptr;
-}
-
 int colortoint(const char *colorname, int *bright)
 {
     int mcolor = 0;
@@ -245,6 +227,24 @@ int colortoint(const char *colorname, int *bright)
     return mcolor;
 }
 
+char *parse_next_regex(char *ptr)
+{
+    while ((*ptr != '"' || (*(ptr + 1) != ' ' && *(ptr + 1) != '\n'))
+	   && *ptr != '\n' && *ptr != '\0')
+	ptr++;
+
+    if (*ptr == '\0')
+	return NULL;
+
+    /* Null terminate and advance ptr */
+    *ptr++ = '\0';
+
+    while (*ptr == ' ' || *ptr == '\t')
+	ptr++;
+
+    return ptr;
+}
+
 void parse_syntax(char *ptr)
 {
     syntaxtype *tmpsyntax = NULL;
diff --git a/search.c b/search.c
index fe080bd2d4776c66c32bb28c7aa401b8a9b6cde8..319cfa18d9cc3599f64bdeb14cf166ef16632eca 100644
--- a/search.c
+++ b/search.c
@@ -53,6 +53,33 @@ void regexp_cleanup(void)
 }
 #endif
 
+void not_found_msg(const char *str)
+{
+    if (strlen(str) <= COLS / 2)
+	statusbar(_("\"%s\" not found"), str);
+    else {
+	char *foo = mallocstrcpy(NULL, str);
+
+	foo[COLS / 2] = '\0';
+	statusbar(_("\"%s...\" not found"), foo);
+	free(foo);
+    }
+}
+
+void search_abort(void)
+{
+    UNSET(KEEP_CUTBUFFER);
+    display_main_list();
+    wrefresh(bottomwin);
+    if (ISSET(MARK_ISSET))
+	edit_refresh_clearok();
+
+#ifdef HAVE_REGEX_H
+    if (ISSET(REGEXP_COMPILED))
+	regexp_cleanup();
+#endif
+}
+
 void search_init_globals(void)
 {
     if (last_search == NULL) {
@@ -67,10 +94,11 @@ void search_init_globals(void)
 
 /* Set up the system variables for a search or replace.  Returns -1 on
    abort, 0 on success, and 1 on rerun calling program 
-   Return -2 to run opposite program (search -> replace, replace -> search)
+   Return -2 to run opposite program (search -> replace, replace ->
+   search).
 
-   replacing = 1 if we call from do_replace, 0 if called from do_search func.
-*/
+   replacing = 1 if we call from do_replace, 0 if called from do_search
+   func. */
 int search_init(int replacing)
 {
     int i = 0;
@@ -196,19 +224,6 @@ int search_init(int replacing)
     return 0;
 }
 
-void not_found_msg(const char *str)
-{
-    if (strlen(str) <= COLS / 2)
-	statusbar(_("\"%s\" not found"), str);
-    else {
-	char *foo = mallocstrcpy(NULL, str);
-
-	foo[COLS / 2] = '\0';
-	statusbar(_("\"%s...\" not found"), foo);
-	free(foo);
-    }
-}
-
 int is_whole_word(int curr_pos, const char *datastr, const char *searchword)
 {
     size_t sln = curr_pos + strlen(searchword);
@@ -223,7 +238,8 @@ static int past_editbuff;
 	/* findnextstr() is now searching lines not displayed */
 
 filestruct *findnextstr(int quiet, int bracket_mode,
-		const filestruct *begin, int beginx, const char *needle)
+			const filestruct *begin, int beginx,
+			const char *needle)
 {
     filestruct *fileptr = current;
     const char *searchstr, *rev_start = NULL, *found = NULL;
@@ -363,20 +379,6 @@ filestruct *findnextstr(int quiet, int bracket_mode,
     return fileptr;
 }
 
-void search_abort(void)
-{
-    UNSET(KEEP_CUTBUFFER);
-    display_main_list();
-    wrefresh(bottomwin);
-    if (ISSET(MARK_ISSET))
-	edit_refresh_clearok();
-
-#ifdef HAVE_REGEX_H
-    if (ISSET(REGEXP_COMPILED))
-	regexp_cleanup();
-#endif
-}
-
 /* Search for a string. */
 int do_search(void)
 {
@@ -430,14 +432,6 @@ int do_search(void)
     return 1;
 }
 
-void print_replaced(int num)
-{
-    if (num > 1)
-	statusbar(_("Replaced %d occurrences"), num);
-    else if (num == 1)
-	statusbar(_("Replaced 1 occurrence"));
-}
-
 void replace_abort(void)
 {
     /* Identical to search_abort, so we'll call it here.  If it
@@ -561,6 +555,14 @@ char *replace_line(void)
     return copy;
 }
 
+void print_replaced(int num)
+{
+    if (num > 1)
+	statusbar(_("Replaced %d occurrences"), num);
+    else if (num == 1)
+	statusbar(_("Replaced 1 occurrence"));
+}
+
 /* step through each replace word and prompt user before replacing word */
 int do_replace_loop(const char *prevanswer, const filestruct *begin,
 			int *beginx, int wholewords, int *i)
diff --git a/utils.c b/utils.c
index 83ea2670e5b592262d51d07a93b747a246960660..acd67a116f357d99686c081f1c6d2d8807db0aff 100644
--- a/utils.c
+++ b/utils.c
@@ -97,7 +97,7 @@ void sunder(char *str)
 /* None of this is needed if we're using NANO_SMALL! */
 #ifndef NANO_SMALL
 const char *revstrstr(const char *haystack, const char *needle,
-	const char *rev_start)
+			const char *rev_start)
 {
     for(; rev_start >= haystack ; rev_start--) {
 	const char *r, *q;
@@ -111,7 +111,7 @@ const char *revstrstr(const char *haystack, const char *needle,
 }
 
 const char *revstristr(const char *haystack, const char *needle,
-	const char *rev_start)
+			const char *rev_start)
 {
     for (; rev_start >= haystack; rev_start--) {
 	const char *r = rev_start, *q = needle;
@@ -147,7 +147,7 @@ const char *stristr(const char *haystack, const char *needle)
 }
 
 const char *strstrwrapper(const char *haystack, const char *needle,
-	const char *rev_start, int line_pos)
+			const char *rev_start, int line_pos)
 {
 #ifdef HAVE_REGEX_H
     if (ISSET(USE_REGEXP)) {
@@ -195,7 +195,8 @@ const char *strstrwrapper(const char *haystack, const char *needle,
 /* This is a wrapper for the perror function.  The wrapper takes care of 
  * ncurses, calls perror (which writes to STDERR), then refreshes the 
  * screen.  Note that nperror causes the window to flicker once. */
-void nperror(const char *s) {
+void nperror(const char *s)
+{
 	/* leave ncurses mode, go to the terminal */
     if (endwin() != ERR) {
 	perror(s);		/* print the error */
diff --git a/winio.c b/winio.c
index 2657f391f2333dc93122832a4aa5d8047dae3217..57609c313ccb5760919dc1e5b83ee0d6cd9aa1bb 100644
--- a/winio.c
+++ b/winio.c
@@ -155,6 +155,15 @@ void blank_bottombars(void)
     }
 }
 
+void blank_bottomwin(void)
+{
+    if (ISSET(NO_HELP))
+	return;
+
+    mvwaddstr(bottomwin, 1, 0, hblank);
+    mvwaddstr(bottomwin, 2, 0, hblank);
+}
+
 void blank_edit(void)
 {
     int i;
@@ -210,11 +219,11 @@ void nanoget_repaint(const char *buf, const char *inputbuf, int x)
 /* Get the input from the kb; this should only be called from
  * statusq(). */
 int nanogetstr(int allowtabs, const char *buf, const char *def,
-			const shortcut *s
+		const shortcut *s
 #ifndef DISABLE_TABCOMP
-			, int *list
+		, int *list
 #endif
-			)
+		)
 {
     int kbinput;
     int x;
@@ -241,7 +250,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 
     nanoget_repaint(buf, answer, x);
 
-    /* Make sure any editor screen updates are displayed before getting input */
+    /* Make sure any editor screen updates are displayed before getting
+       input */
     wrefresh(edit);
 
     while ((kbinput = wgetch(bottomwin)) != 13) {
@@ -253,7 +263,8 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 	    if (kbinput == t->val && kbinput < 32) {
 
 #ifndef DISABLE_HELP
-		/* Have to do this here, it would be too late to do it in statusq */
+		/* Have to do this here, it would be too late to do it
+		   in statusq() */
 		if (kbinput == NANO_HELP_KEY || kbinput == NANO_HELP_FKEY) {
 		    do_help();
 		    break;
@@ -435,6 +446,16 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
 	return 0;
 }
 
+/* If modified is not already set, set it and update titlebar. */
+void set_modified(void)
+{
+    if (!ISSET(MODIFIED)) {
+	SET(MODIFIED);
+	titlebar(NULL);
+	wrefresh(topwin);
+    }
+}
+
 void titlebar(const char *path)
 {
     int namelen, space;
@@ -483,35 +504,6 @@ void titlebar(const char *path)
     reset_cursor();
 }
 
-/* Write a shortcut key to the help area at the bottom of the window. 
- * keystroke is e.g. "^G" and desc is e.g. "Get Help".
- * We are careful to write exactly len characters, even if len is
- * very small and keystroke and desc are long. */
-void onekey(const char *keystroke, const char *desc, int len)
-{
-    wattron(bottomwin, A_REVERSE);
-    waddnstr(bottomwin, keystroke, len);
-    wattroff(bottomwin, A_REVERSE);
-    len -= strlen(keystroke);
-    if (len > 0) {
-	waddch(bottomwin, ' ');
-	len--;
-	waddnstr(bottomwin, desc, len);
-	len -= strlen(desc);
-	for (; len > 0; len--)
-	    waddch(bottomwin, ' ');
-    }
-}
-
-void clear_bottomwin(void)
-{
-    if (ISSET(NO_HELP))
-	return;
-
-    mvwaddstr(bottomwin, 1, 0, hblank);
-    mvwaddstr(bottomwin, 2, 0, hblank);
-}
-
 void bottombars(const shortcut *s)
 {
     int i, j, numcols;
@@ -530,7 +522,7 @@ void bottombars(const shortcut *s)
     /* There will be this many columns of shortcuts */
     numcols = (slen + (slen % 2)) / 2;
 
-    clear_bottomwin();
+    blank_bottomwin();
 
     for (i = 0; i < numcols; i++) {
 	for (j = 0; j <= 1; j++) {
@@ -562,20 +554,30 @@ void bottombars(const shortcut *s)
     wrefresh(bottomwin);
 }
 
-/* If modified is not already set, set it and update titlebar. */
-void set_modified(void)
+/* Write a shortcut key to the help area at the bottom of the window. 
+ * keystroke is e.g. "^G" and desc is e.g. "Get Help".
+ * We are careful to write exactly len characters, even if len is
+ * very small and keystroke and desc are long. */
+void onekey(const char *keystroke, const char *desc, int len)
 {
-    if (!ISSET(MODIFIED)) {
-	SET(MODIFIED);
-	titlebar(NULL);
-	wrefresh(topwin);
+    wattron(bottomwin, A_REVERSE);
+    waddnstr(bottomwin, keystroke, len);
+    wattroff(bottomwin, A_REVERSE);
+    len -= strlen(keystroke);
+    if (len > 0) {
+	waddch(bottomwin, ' ');
+	len--;
+	waddnstr(bottomwin, desc, len);
+	len -= strlen(desc);
+	for (; len > 0; len--)
+	    waddch(bottomwin, ' ');
     }
 }
 
-/* And so start the display update routines */
-/* Given a column, this returns the "page" it is on  */
-/* "page" in the case of the display columns, means which set of 80 */
-/* characters is viewable (e.g.: page 1 shows from 1 to COLS) */
+/* And so start the display update routines.  Given a column, this
+ * returns the "page" it is on.  "page", in the case of the display
+ * columns, means which set of 80 characters is viewable (e.g. page 1
+ * shows from 1 to COLS). */
 int get_page_from_virtual(int virtual)
 {
     int page = 2;
@@ -637,12 +639,10 @@ void reset_cursor(void)
 }
 
 #ifndef NANO_SMALL
-/* This takes care of the case where there is a mark that covers only */
-/* the current line. */
-
-/* It expects a line with no tab characters (i.e.: the type that edit_add */
-/* deals with */
-void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
+/* This takes care of the case where there is a mark that covers only
+ * the current line.  It expects a line with no tab characters (i.e.
+ * the type that edit_add() deals with. */
+void add_marked_sameline(int begin, int end, filestruct *fileptr, int y,
 			 int virt_cur_x, int this_page)
 {
     /*
@@ -691,12 +691,10 @@ void add_marked_sameline(int begin, int end, filestruct * fileptr, int y,
 }
 #endif
 
-/* edit_add takes care of the job of actually painting a line into the
- * edit window.
- * 
- * Called only from update_line.  Expects a converted-to-not-have-tabs
- * line */
-void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
+/* edit_add() takes care of the job of actually painting a line into
+ * the edit window.  Called only from update_line().  Expects a
+ * converted-to-not-have-tabs line. */
+void edit_add(filestruct *fileptr, int yval, int start, int virt_cur_x,
 	      int virt_mark_beginx, int this_page)
 {
 
@@ -1007,12 +1005,10 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
 
 /*
  * Just update one line in the edit buffer.  Basically a wrapper for
- * edit_add
- *
- * index gives us a place in the string to update starting from.
- * Likely args are current_x or 0.
+ * edit_add().  index gives us a place in the string to update starting
+ * from.  Likely args are current_x or 0.
  */
-void update_line(filestruct * fileptr, int index)
+void update_line(filestruct *fileptr, int index)
 {
     filestruct *filetmp;
     int line = 0, col = 0;
@@ -1112,6 +1108,28 @@ void update_line(filestruct * fileptr, int index)
     free(tmp);
 }
 
+/* This function updates current, based on where current_y is;
+ * reset_cursor() does the opposite. */
+void update_cursor(void)
+{
+    int i = 0;
+
+#ifdef DEBUG
+    fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
+	    current_x);
+#endif
+
+    current = edittop;
+    while (i < current_y && current->next != NULL) {
+	current = current->next;
+	i++;
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
+#endif
+}
+
 void center_cursor(void)
 {
     current_y = editwinrows / 2;
@@ -1194,28 +1212,6 @@ void edit_update(filestruct *fileptr, topmidbotnone location)
     edit_refresh();
 }
 
-/* This function updates current, based on where current_y is;
- * reset_cursor() does the opposite. */
-void update_cursor(void)
-{
-    int i = 0;
-
-#ifdef DEBUG
-    fprintf(stderr, _("Moved to (%d, %d) in edit buffer\n"), current_y,
-	    current_x);
-#endif
-
-    current = edittop;
-    while (i < current_y && current->next != NULL) {
-	current = current->next;
-	i++;
-    }
-
-#ifdef DEBUG
-    fprintf(stderr, _("current->data = \"%s\"\n"), current->data);
-#endif
-}
-
 /*
  * Ask a question on the statusbar.  Answer will be stored in answer
  * global.  Returns -1 on aborted enter, -2 on a blank string, and 0
@@ -1278,8 +1274,9 @@ int statusq(int tabs, const shortcut *s, const char *def,
 }
 
 /*
- * Ask a simple yes/no question on the statusbar.  Returns 1 for Y, 0 for
- * N, 2 for All (if all is non-zero when passed in) and -1 for abort (^C)
+ * Ask a simple yes/no question on the statusbar.  Returns 1 for Y, 0
+ * for N, 2 for All (if all is non-zero when passed in) and -1 for
+ * abort (^C).
  */
 int do_yesno(int all, int leavecursor, const char *msg, ...)
 {
@@ -1303,7 +1300,7 @@ int do_yesno(int all, int leavecursor, const char *msg, ...)
     allstr = _("Aa");
 
     /* Write the bottom of the screen */
-    clear_bottomwin();
+    blank_bottomwin();
 
     /* Remove gettext call for keybindings until we clear the thing up */
     if (!ISSET(NO_HELP)) {
@@ -1412,6 +1409,28 @@ int do_yesno(int all, int leavecursor, const char *msg, ...)
 	return ok;
 }
 
+int total_refresh(void)
+{
+    clearok(edit, TRUE);
+    clearok(topwin, TRUE);
+    clearok(bottomwin, TRUE);
+    wnoutrefresh(edit);
+    wnoutrefresh(topwin);
+    wnoutrefresh(bottomwin);
+    doupdate();
+    clearok(edit, FALSE);
+    clearok(topwin, FALSE);
+    clearok(bottomwin, FALSE);
+    edit_refresh();
+    titlebar(NULL);
+    return 1;
+}
+
+void display_main_list(void)
+{
+    bottombars(main_list);
+}
+
 void statusbar(const char *msg, ...)
 {
     va_list ap;
@@ -1452,28 +1471,6 @@ void statusbar(const char *msg, ...)
 	statblank = 25;
 }
 
-void display_main_list(void)
-{
-    bottombars(main_list);
-}
-
-int total_refresh(void)
-{
-    clearok(edit, TRUE);
-    clearok(topwin, TRUE);
-    clearok(bottomwin, TRUE);
-    wnoutrefresh(edit);
-    wnoutrefresh(topwin);
-    wnoutrefresh(bottomwin);
-    doupdate();
-    clearok(edit, FALSE);
-    clearok(topwin, FALSE);
-    clearok(bottomwin, FALSE);
-    edit_refresh();
-    titlebar(NULL);
-    return 1;
-}
-
 int do_cursorpos(int constant)
 {
     filestruct *fileptr;
@@ -1703,45 +1700,20 @@ int do_help(void)
     return 1;
 }
 
-#ifdef DEBUG
-/* Dump the current file structure to stderr */
-void dump_buffer(const filestruct *inptr) {
-    if (inptr == fileage)
-	fprintf(stderr, _("Dumping file buffer to stderr...\n"));
-    else if (inptr == cutbuffer)
-	fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
-    else
-	fprintf(stderr, _("Dumping a buffer to stderr...\n"));
-
-    while (inptr != NULL) {
-	fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
-	inptr = inptr->next;
-    }
-}
-#endif /* DEBUG */
-
-#ifdef DEBUG
-void dump_buffer_reverse(void) {
-    const filestruct *fileptr = filebot;
-
-    while (fileptr != NULL) {
-	fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
-	fileptr = fileptr->prev;
-    }
-}
-#endif /* DEBUG */
-
-/* Fix editbot, based on the assumption that edittop is correct */
-void fix_editbot(void)
+int keypad_on(WINDOW * win, int newval)
 {
-    int i;
-
-    editbot = edittop;
-    for (i = 0; i < editwinrows && editbot->next != NULL; i++)
-	editbot = editbot->next;
+/* This is taken right from aumix.  Don't sue me. */
+#ifdef HAVE_USEKEYPAD
+    int old = win->_use_keypad;
+    keypad(win, newval);
+    return old;
+#else
+    keypad(win, newval);
+    return 1;
+#endif /* HAVE_USEKEYPAD */
 }
 
-/* highlight the current word being replaced or spell checked */
+/* Highlight the current word being replaced or spell checked. */
 void do_replace_highlight(int highlight_flag, const char *word)
 {
     char *highlight_word = NULL;
@@ -1786,6 +1758,44 @@ void do_replace_highlight(int highlight_flag, const char *word)
     free(highlight_word);
 }
 
+/* Fix editbot, based on the assumption that edittop is correct. */
+void fix_editbot(void)
+{
+    int i;
+
+    editbot = edittop;
+    for (i = 0; i < editwinrows && editbot->next != NULL; i++)
+	editbot = editbot->next;
+}
+
+#ifdef DEBUG
+/* Dump the current file structure to stderr */
+void dump_buffer(const filestruct *inptr) {
+    if (inptr == fileage)
+	fprintf(stderr, _("Dumping file buffer to stderr...\n"));
+    else if (inptr == cutbuffer)
+	fprintf(stderr, _("Dumping cutbuffer to stderr...\n"));
+    else
+	fprintf(stderr, _("Dumping a buffer to stderr...\n"));
+
+    while (inptr != NULL) {
+	fprintf(stderr, "(%d) %s\n", inptr->lineno, inptr->data);
+	inptr = inptr->next;
+    }
+}
+#endif /* DEBUG */
+
+#ifdef DEBUG
+void dump_buffer_reverse(void) {
+    const filestruct *fileptr = filebot;
+
+    while (fileptr != NULL) {
+	fprintf(stderr, "(%d) %s\n", fileptr->lineno, fileptr->data);
+	fileptr = fileptr->prev;
+    }
+}
+#endif /* DEBUG */
+
 #ifdef NANO_EXTRA
 #define CREDIT_LEN 52
 #define XLCREDIT_LEN 8
@@ -1904,16 +1914,3 @@ void do_credits(void)
     total_refresh();
 }
 #endif
-
-int keypad_on(WINDOW * win, int newval)
-{
-/* This is taken right from aumix.  Don't sue me. */
-#ifdef HAVE_USEKEYPAD
-    int old = win->_use_keypad;
-    keypad(win, newval);
-    return old;
-#else
-    keypad(win, newval);
-    return 1;
-#endif /* HAVE_USEKEYPAD */
-}