]> git.wh0rd.org Git - nano.git/commitdiff
DLR: prototype overhaul, etc.
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 6 Sep 2002 20:35:28 +0000 (20:35 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Fri, 6 Sep 2002 20:35:28 +0000 (20:35 +0000)
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1270 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

12 files changed:
ChangeLog
configure.ac
files.c
global.c
move.c
nano.c
nano.h
proto.h
rcfile.c
search.c
utils.c
winio.c

index 2bf8b2181c374ed5b62b8e01c489a3c6e5f58d08..029a69a405c96363c0cd56b2b6b71d31ead057be 100644 (file)
--- 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
index 15186eee6130067684b8a851da4c8f082083fc59..3edbe57c79bd820f3fa1fe448ebc24a45d7002fc 100644 (file)
@@ -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 (file)
--- 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)
 {
index 83691d5a7d6710cadf598bb9707e0057335d01ad..7a9cf7259ed4435244536a6be95e92694a4fca06 100644 (file)
--- 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 (file)
--- a/move.c
+++ b/move.c
 #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 (file)
--- 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 (file)
--- 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 (file)
--- 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);
index 6b7b1e7f4752e682e89833ec26a6f14fa7bf5437..26c5e359f2b5a6078accaac13a77208872bf6b07 100644 (file)
--- 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;
index fe080bd2d4776c66c32bb28c7aa401b8a9b6cde8..319cfa18d9cc3599f64bdeb14cf166ef16632eca 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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 */
-}