]> git.wh0rd.org Git - nano.git/commitdiff
minor overhaul of terminal-related things
authorDavid Lawrence Ramsey <pooka109@gmail.com>
Tue, 18 May 2004 01:20:36 +0000 (01:20 +0000)
committerDavid Lawrence Ramsey <pooka109@gmail.com>
Tue, 18 May 2004 01:20:36 +0000 (01:20 +0000)
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1745 35c25a1d-7b9e-4130-9fde-d3aeb78583b8

ChangeLog
src/files.c
src/nano.c
src/nano.h
src/proto.h
src/winio.c

index d3e63bd7c14ca187f16dec0e2e7541eb639f809d..7d9990ec17d0ed6d31fa8bfe9cd3ec73291b454c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,8 @@ CVS code -
        - Make sure the special control keys are handled the same way
          after the window is resized or we come out of suspend mode.
          Changes to do_cont() and handle_sigwinch(). (DLR)
+       - Change some instances of ints that can never be negative to
+         size_t's. (DLR)
        - Add better explanations for and in the "Terminal breakage"
          comments, and handle missing key #ifdefs inside the functions
          that use those keys. (DLR)
@@ -48,6 +50,9 @@ CVS code -
          justify_format() may get a space tacked onto the end of it
          later, so now the entire original paragraph is always backed
          up.) (DLR)
+       - Wrap the long jump code in NANO_SMALL #ifdefs, since we only
+         use it if we're resizing the window, which is disabled when
+         NANO_SMALL is defined. (DLR)
 - files.c:
   add_open_file()
        - Rearrange the NANO_SMALL #ifdef so that the code to set the
@@ -57,6 +62,15 @@ CVS code -
        - Refactor so that no recursion is needed if we try to exit with
          a modified file that has no name when TEMP_OPT is set. (DLR)
 - nano.c:
+  do_toggle(), finish()
+       - Call blank_statusbar() and blank_bottombars() to blank out
+         the statusbar and shortcut list in bottomwin. (DLR)
+  do_early_abort()
+       - Removed, as it's no longer called anywhere. (David Benbennick)
+  open_pipe()
+       - Call enable_signals() at the beginning and disable_signals()
+         at the end, so that we get a SIGINT when Ctrl-C is pressed
+         during wait() and can then call cancel_fork() properly. (DLR)
   do_delete()
        - Tweak for efficiency. (David Benbennick)
   justify_format()
@@ -72,10 +86,32 @@ CVS code -
   print_numlock_warning()
        - Removed, as it's no longer needed and was never called
          anywhere after the input overhaul. (DLR)
+  signal_init()
+       - Don't use termios and _POSIX_VDISABLE to disable keys anymore,
+         as there's no real equivalent of it when the latter isn't
+         defined. (DLR)
+  handle_sigwinch()
+       - Call resetty() to get the original terminal settings back.
+         (DLR)
+       - Rework so that nano properly redraws the screen on systems
+         that don't have resizeterm() and/or wresize().  In curses, we
+         now leave and immediately reenter curses mode via endwin() and
+         refresh(), and then reinitialize all windows via
+         window_init().  In slang, the above routine will only work if
+         the resize made the window smaller, so we now leave and
+         immediately reenter screen management mode via
+         SLsmg_reset_smg() and SLsmg_init_smg(), and then reinitialize
+         all windows via window_init().  (DLR, adapted from code in
+         Minimum Profit 3.3.0 and mutt 1.4.2.1, respectively)
   do_verbatim_input()
-       - Use size_t's instead of ints for the get_verbatim_kbinput()
-         call and the loop that ungetch()es its returned int*,
-         respectively. (DLR)
+       - If PRESERVE is set, disable flow control characters before
+         getting input and reenable them after getting input. (DLR)
+  disable_signals(), enable_signals(), disable_flow_control(),
+  enable_flow_control()
+       - New functions that allow more fine-grained control of the
+         terminal: disabling and enabling signals without having to use
+         _POSIX_VDISABLE and disabling and enabling flow control
+         characters. (DLR)
   main()
        - Don't open the first file in quiet mode, since if we do, an
          error message won't be shown if it's unreadable. (DLR; found
@@ -88,6 +124,17 @@ CVS code -
          the nanorc first, both of which are unintuitive.  Multibuffer
          mode should only affect how the "Read File" command behaves
          anyway. (DLR)
+       - Remove the disabling of implementation-defined input
+         processing, as raw mode appears to turn it off anyway. (DLR)
+       - Use raw mode instead of cbreak mode, since it comes closest to
+         what we need by automatically disabling the special control
+         keys. (DLR)
+       - After noecho(), call disable_signals() and
+         disable_flow_control(), the latter only if PRESERVE is not
+         set. (DLR)
+       - Move the savetty() call down from just after initscr() to just
+         after the terminal is properly set up, so that we can restore
+         it easily after a resize. (DLR)
 - nano.h:
        - Since REGEXP_COMPILED is only used in search.c, convert it
          from a flag to a static int there. (DLR)
@@ -131,8 +178,6 @@ CVS code -
        - Refactor the output in the DEBUG #ifdef.  It didn't work
          properly ever since this function was changed to use an int*
          instead of a char*. (DLR)
-       - Change kbinput_len from an int* to a size_t*, since it should
-         never be negative. (DLR)
        - When reading characters from input, properly reallocate
          verbatim_kbinput via (int*)nrealloc() instead of an uncast
          realloc(). (DLR)
@@ -140,8 +185,6 @@ CVS code -
        - Add proper support for the keypad values and escape sequences
          generated by the NumLock glitch. (DLR)
   get_escape_seq_kbinput()
-       - Change escape_seq_len from an int to a size_t, since it should
-         never be negative. (DLR)
        - Add proper support for the keypad values and escape sequences
          generated by the NumLock glitch. (DLR)
   bottombars()
@@ -152,6 +195,14 @@ CVS code -
   edit_add()
        - Minor cosmetic reformatting.  Also remove unused int
          searched_later_lines. (DLR)
+  blank_bottomwin()
+       - Removed, as it does the same thing as blank_bottombars().
+         (David Benbennick)
+  blank_titlebar()
+       - New function used to blank the titlebar in topwin. (DLR)
+  bottombars()
+       - Call blank_bottombars() instead of blank_bottomwin(). (David
+         Benbennick)
   edit_refresh()
        - Remove apparently unneeded leaveok() calls. (David Benbennick)
   statusbar()
@@ -163,6 +214,7 @@ CVS code -
        - Use napms() instead of nanosleep(), as it does the same thing
          (aside from taking an argument in milliseconds instead of
          microseconds) and curses includes it. (DLR)
+       - Overhaul for efficiency. (David Benbennick)
 - configure.ac:
        - Add tests for isblank() and strcasestr(), and define
          _GNU_SOURCE so that the tests work properly.  Increase the
@@ -171,6 +223,8 @@ CVS code -
          fewer lines than usual, so as to make them easier to read, and
          remove unnecessary inclusion of stdio.h in the slang test
          programs. (DLR)
+       - Remove the checks for resizeterm() and wresize(), as they're
+         no longer needed. (DLR)
 - faq.html:
        - Removed question about the NumLock glitch, as it's no longer
          needed. (DLR)
index bd75be9f8d7df6bb0be33e155c19be74fb398081..d0a803839d11f24fb331f3b9d712e39d0a578f53 100644 (file)
@@ -105,7 +105,8 @@ void new_file(void)
 #endif
 }
 
-filestruct *read_line(char *buf, filestruct *prev, int *line1ins, int len)
+filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
+       len)
 {
     filestruct *fileptr = (filestruct *)nmalloc(sizeof(filestruct));
 
@@ -2454,7 +2455,7 @@ int diralphasort(const void *va, const void *vb)
 }
 
 /* Free our malloc()ed memory */
-void free_charptrarray(char **array, int len)
+void free_charptrarray(char **array, size_t len)
 {
     for (; len > 0; len--)
        free(array[len - 1]);
index 98af0de60125167fcc37b0be40514c1d87f358aa..ac55a3a43d2aac54e0b424cefbb4a71e61ab3cf3 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <signal.h>
-#include <setjmp.h>
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
 #include <getopt.h>
 #endif
 
+#ifndef NANO_SMALL
+#include <setjmp.h>
+#endif
+
 #ifndef DISABLE_WRAPJUSTIFY
 static int fill = 0;   /* Fill - where to wrap lines, basically */
 #endif
@@ -65,21 +68,22 @@ static int same_line_wrap = 0;      /* Whether wrapped text should be
 static struct termios oldterm; /* The user's original term settings */
 static struct sigaction act;   /* For all our fun signal handlers */
 
+#ifndef NANO_SMALL
 static sigjmp_buf jmpbuf;      /* Used to return to mainloop after SIGWINCH */
+#endif
 
 /* What we do when we're all set to exit */
 RETSIGTYPE finish(int sigage)
 {
-    if (!ISSET(NO_HELP)) {
-       mvwaddstr(bottomwin, 1, 0, hblank);
-       mvwaddstr(bottomwin, 2, 0, hblank);
-    } else
-       mvwaddstr(bottomwin, 0, 0, hblank);
+    if (!ISSET(NO_HELP))
+       blank_bottombars();
+    else
+       blank_statusbar();
 
     wrefresh(bottomwin);
     endwin();
 
-    /* Restore the old term settings */
+    /* Restore the old terminal settings. */
     tcsetattr(0, TCSANOW, &oldterm);
 
 #if !defined(NANO_SMALL) && defined(ENABLE_NANORC)
@@ -102,7 +106,7 @@ void die(const char *msg, ...)
     endwin();
     curses_ended = TRUE;
 
-    /* Restore the old term settings */
+    /* Restore the old terminal settings. */
     tcsetattr(0, TCSANOW, &oldterm);
 
     va_start(ap, msg);
@@ -241,7 +245,7 @@ void window_init(void)
     edit = newwin(editwinrows, COLS, 2, 0);
     bottomwin = newwin(3 - no_help(), COLS, LINES - 3 + no_help(), 0);
 
-    /* Turn the keypad on in the windows we'll be reading input from. */
+    /* Turn the keypad back on. */
     keypad(edit, TRUE);
     keypad(bottomwin, TRUE);
 }
@@ -758,13 +762,6 @@ void version(void)
     printf("\n");
 }
 
-/* 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();
-}
-
 int no_help(void)
 {
     return ISSET(NO_HELP) ? 2 : 0;
@@ -792,13 +789,10 @@ int open_pipe(const char *command)
     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.
+     * 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. */
@@ -834,6 +828,9 @@ int open_pipe(const char *command)
 
     /* Before we start reading the forked command's output, we set
      * things up so that ^C will cancel the new process. */
+
+    enable_signals();
+
     if (sigaction(SIGINT, NULL, &newaction) == -1) {
        cancel_sigs = 1;
        nperror("sigaction");
@@ -847,24 +844,6 @@ int open_pipe(const char *command)
     /* Note that now oldaction is the previous SIGINT signal handler,
      * to be restored later. */
 
-    /* See if the platform supports disabling individual control
-     * characters. */
-#ifdef _POSIX_VDISABLE
-    if (cancel_sigs == 0 && tcgetattr(0, &term) == -1) {
-       cancel_sigs = 2;
-       nperror("tcgetattr");
-    }
-    if (cancel_sigs == 0) {
-       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 */
-
     f = fdopen(fd[0], "rb");
     if (f == NULL)
       nperror("fdopen");
@@ -878,14 +857,11 @@ int open_pipe(const char *command)
     if (wait(NULL) == -1)
        nperror("wait");
 
-#ifdef _POSIX_VDISABLE
-    if (cancel_sigs == 0 && tcsetattr(0, TCSANOW, &term) == -1)
-       nperror("tcsetattr");
-#endif   /* _POSIX_VDISABLE */
-
     if (cancel_sigs != 1 && sigaction(SIGINT, &oldaction, NULL) == -1)
        nperror("sigaction");
 
+    disable_signals();
+
     return 0;
 }
 #endif /* !NANO_SMALL */
@@ -2769,10 +2745,6 @@ int do_exit(void)
 
 void signal_init(void)
 {
-#ifdef _POSIX_VDISABLE
-    struct termios term;
-#endif
-
     /* Trap SIGINT and SIGQUIT because we want them to do useful
      * things. */
     memset(&act, 0, sizeof(struct sigaction));
@@ -2792,31 +2764,10 @@ void signal_init(void)
     allow_pending_sigwinch(FALSE);
 #endif
 
-#ifdef _POSIX_VDISABLE
-    tcgetattr(0, &term);
-
-    if (!ISSET(PRESERVE)) {
-       /* Trap XOFF (^S) and XON (^Q), much to Chris' chagrin, because
-        * we want to block them. */
-       term.c_cc[VSTOP] = _POSIX_VDISABLE;
-       term.c_cc[VSTART] = _POSIX_VDISABLE;
-    }
-#ifdef VDSUSP
-    /* Trap delayed suspend (^Y) so we can handle it ourselves. */
-    term.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
-
-#endif /* _POSIX_VDISABLE */
-
+    /* Trap normal suspend (^Z) so we can handle it ourselves. */
     if (!ISSET(SUSPEND)) {
-        /* Trap normal suspend (^Z) so we can handle it ourselves.  If
-        * we can't trap the key, trap the signal instead.  Insane! */
-#ifdef _POSIX_VDISABLE
-       term.c_cc[VSUSP] = _POSIX_VDISABLE;
-#else
        act.sa_handler = SIG_IGN;
        sigaction(SIGTSTP, &act, NULL);
-#endif
     } else {
        /* Block all other signals in the suspend and continue handlers.
         * If we don't do this, other stuff interrupts them! */
@@ -2828,54 +2779,44 @@ void signal_init(void)
        act.sa_handler = do_cont;
        sigaction(SIGCONT, &act, NULL);
     }
-
-#ifdef _POSIX_VDISABLE
-    tcsetattr(0, TCSANOW, &term);
-#endif
 }
 
-/* Handler for SIGHUP and SIGTERM. */
+/* Handler for SIGHUP (hangup) and SIGTERM (terminate). */
 RETSIGTYPE handle_hupterm(int signal)
 {
     die(_("Received SIGHUP or SIGTERM\n"));
 }
 
-/* What do we do when we catch the suspend signal */
+/* Handler for SIGTSTP (suspend). */
 RETSIGTYPE do_suspend(int signal)
 {
     endwin();
     printf("\n\n\n\n\n%s\n", _("Use \"fg\" to return to nano"));
     fflush(stdout);
 
-    /* Restore the terminal settings for the disabled keys */
+    /* Restore the old terminal settings. */
     tcsetattr(0, TCSANOW, &oldterm);
 
     /* Trap SIGHUP and SIGTERM so we can properly deal with them while
-       suspended */
+     * suspended. */
     act.sa_handler = handle_hupterm;
     sigaction(SIGHUP, &act, NULL);
     sigaction(SIGTERM, &act, NULL);
 
-    /* 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 */
+    /* Do what mutt does: send ourselves a SIGSTOP. */
     kill(0, SIGSTOP);
 }
 
-/* Restore the suspend handler when we come back into the prog */
+/* Handler for SIGCONT (continue after suspend). */
 RETSIGTYPE do_cont(int signal)
 {
-    /* Now we just update the screen instead of having to reenable the
-     * SIGTSTP handler. */
-    doupdate();
-
 #ifndef NANO_SMALL
-    /* Perhaps the user resized the window while we slept. */
+    /* Perhaps the user resized the window while we slept.  Handle it
+     * and update the screen in the process. */
     handle_sigwinch(0);
 #else
-    /* Set up the signal handlers again, so that the special control
-     * keys all work the same as before. */
-    signal_init();
+    /* Just update the screen. */
+    doupdate();
 #endif
 }
 
@@ -2919,45 +2860,35 @@ void handle_sigwinch(int s)
     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 */
+#ifdef USE_SLANG
+    /* Slang curses emulation brain damage, part 1: If we just do what
+     * curses does here, it'll only work properly if the resize made the
+     * window smaller.  Do what mutt does: Leave and immediately reenter
+     * Slang screen management mode. */
+    SLsmg_reset_smg();
+    SLsmg_init_smg();
+#else
+    /* Do the equivalent of what Minimum Profit does: Leave and
+     * immediately reenter curses mode. */
+    endwin();
+    refresh();
+#endif
 
-    display_main_list();
+    /* Do the equivalent of what both mutt and Minimum Profit do:
+     * Reinitialize all the windows based on the new screen
+     * dimensions. */
+    window_init();
+
+    /* Redraw the contents of the windows that need it. */
     blank_statusbar();
+    display_main_list();
     total_refresh();
 
     /* Turn cursor back on for sure. */
     curs_set(1);
 
-    /* Put the terminal in cbreak mode (read one character at a time and
-     * interpret the special control keys) if we can selectively disable
-     * the special control keys. */
-#ifdef _POSIX_VDISABLE
-    cbreak();
-#endif
-
-    /* Set up the signal handlers again, so that the special control
-     * keys all work the same as before. */
-    signal_init();
-
-    /* Turn the keypad on in the windows we'll be reading input from. */
-    keypad(edit, TRUE);
-    keypad(bottomwin, TRUE);
+    /* Restore the terminal to its previously saved state. */
+    resetty();
 
     /* Jump back to the main loop. */
     siglongjmp(jmpbuf, 1);
@@ -2993,7 +2924,8 @@ void do_toggle(const toggle *which)
        break;
 #endif
     case TOGGLE_NOHELP_KEY:
-       wclear(bottomwin);
+       blank_statusbar();
+       blank_bottombars();
        wrefresh(bottomwin);
        window_init();
        edit_refresh();
@@ -3022,6 +2954,46 @@ void do_toggle(const toggle *which)
 }
 #endif /* !NANO_SMALL */
 
+#if !defined(NANO_SMALL) || defined(USE_SLANG)
+void disable_signals(void)
+{
+    struct termios term;
+
+    tcgetattr(0, &term);
+    term.c_lflag &= ~ISIG;
+    tcsetattr(0, TCSANOW, &term);
+}
+#endif
+
+#ifndef NANO_SMALL
+void enable_signals(void)
+{
+    struct termios term;
+
+    tcgetattr(0, &term);
+    term.c_lflag |= ISIG;
+    tcsetattr(0, TCSANOW, &term);
+}
+#endif
+
+void disable_flow_control(void)
+{
+    struct termios term;
+
+    tcgetattr(0, &term);
+    term.c_iflag &= ~(IXON|IXOFF);
+    tcsetattr(0, TCSANOW, &term);
+}
+
+void enable_flow_control(void)
+{
+    struct termios term;
+
+    tcgetattr(0, &term);
+    term.c_iflag |= (IXON|IXOFF);
+    tcsetattr(0, TCSANOW, &term);
+}
+
 int main(int argc, char *argv[])
 {
     int optchr;
@@ -3036,9 +3008,6 @@ int main(int argc, char *argv[])
 #ifndef NANO_SMALL
     const toggle *t;
 #endif
-#ifdef _POSIX_VDISABLE
-    struct termios term;
-#endif
 #ifdef HAVE_GETOPT_LONG
     const struct option long_options[] = {
        {"help", 0, 0, 'h'},
@@ -3428,36 +3397,35 @@ int main(int argc, char *argv[])
            filename = mallocstrcpy(filename, argv[optind]);
     }
 
-    /* Termios initialization stuff: Back up the old settings so that
-     * they can be restored, disable SIGINT on ^C and SIGQUIT on ^\,
-     * since we need them for Cancel and Replace, and disable
-     * implementation-defined input processing. */
+    /* Back up the old terminal settings so that they can be restored. */
     tcgetattr(0, &oldterm);
-#ifdef _POSIX_VDISABLE
-    term = oldterm;
-    term.c_cc[VINTR] = _POSIX_VDISABLE;
-    term.c_cc[VQUIT] = _POSIX_VDISABLE;
-    term.c_lflag &= ~IEXTEN;
-    tcsetattr(0, TCSANOW, &term);
-#endif
 
    /* Curses initialization stuff: Start curses, save the state of the
-    * the terminal mode, disable translation of carriage return (^M)
-    * into newline (^J) so we can catch the Enter key and use ^J for
-    * Justify, put the terminal in cbreak mode (read one character at a
-    * time and interpret the special control keys) if we can selectively
-    * disable the special control keys or raw mode (read one character
-    * at a time and don't interpret the special control keys) if we
-    * can't, and turn off echoing of characters as they're typed. */
+    * terminal mode, put the terminal in raw mode (read one character at
+    * a time and don't interpret the special control keys), disable
+    * translation of carriage return (^M) into newline (^J) so that we
+    * can tell the difference between the Enter key and ^J, and disable
+    * echoing of characters as they're typed.  Finally, if we're in
+    * preserve mode, turn the flow control characters back on. */
     initscr();
-    savetty();
-    nonl();
-#ifdef _POSIX_VDISABLE
-    cbreak();
-#else
     raw();
+#ifdef USE_SLANG
+    /* Slang curses emulation brain damage, part 2: Raw mode acts just
+     * like cbreak mode here and doesn't disable interpretation of the
+     * special control keys.  Work around this by manually disabling
+     * interpretation of the special control keys. */
+    disable_signals();
 #endif
+    nonl();
     noecho();
+    if (ISSET(PRESERVE))
+       enable_flow_control();
+
+#ifndef NANO_SMALL
+    /* Save the terminal's current state, so that we can restore it
+     * after a resize. */
+    savetty();
+#endif
 
     /* Set up the global variables and the shortcuts. */
     global_init(0);
@@ -3511,8 +3479,10 @@ int main(int argc, char *argv[])
     if (startline > 0)
        do_gotoline(startline, 0);
 
-    /* Return here after a sigwinch */
+#ifndef NANO_SMALL
+    /* Return here after a SIGWINCH. */
     sigsetjmp(jmpbuf, 1);
+#endif
 
     /* SHUT UP GCC! */
     startline = 0;
@@ -3598,13 +3568,12 @@ int main(int argc, char *argv[])
        if (!keyhandled)
            UNSET(KEEP_CUTBUFFER);
 
-#ifdef _POSIX_VDISABLE
        /* Don't even think about changing this string */
        if (kbinput == NANO_CONTROL_Q)
            statusbar(_("XON ignored, mumble mumble."));
        if (kbinput == NANO_CONTROL_S)
            statusbar(_("XOFF ignored, mumble mumble."));
-#endif
+
        /* If we're in raw mode or using Alt-Alt-x, we have to catch
           Control-S and Control-Q */
        if (kbinput == NANO_CONTROL_Q || kbinput == NANO_CONTROL_S)
index ffdd6bfd01b000c0c3731f5dc2480a540cb20b36..5f711d04b68d4a6f66bf702ebf03d572428ff6b7 100644 (file)
 #endif
 
 #ifdef USE_SLANG
-/* Slang support enabled.  Work around Slang's not defining KEY_DC or
- * KEY_IC. */
+/* Slang support enabled. */
 #include <slcurses.h>
+/* Slang curses emulation brain damage, part 3: Slang doesn't define the
+ * curses equivalents of the Insert or Delete keys. */
 #define KEY_DC SL_KEY_DELETE
 #define KEY_IC SL_KEY_IC
 #elif defined(HAVE_NCURSES_H)
index b934c2351f808ae083a057e0ba2f16097fb35d91..0e0ca45aa417aba6400c5a43d5208cb02c0d17cb 100644 (file)
@@ -54,7 +54,7 @@ extern char *quotestr;
 extern char *backup_dir;
 #endif
 
-extern WINDOW *edit, *topwin, *bottomwin;
+extern WINDOW *topwin, *edit, *bottomwin;
 extern char *filename;
 extern struct stat originalfilestat;
 extern char *answer;
@@ -151,7 +151,8 @@ 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);
+filestruct *read_line(char *buf, filestruct *prev, int *line1ins, size_t
+       len);
 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);
@@ -202,7 +203,7 @@ char *input_tab(char *buf, int place, int *lastwastab, int *newplace, int *list)
 const char *tail(const char *foo);
 #ifndef DISABLE_BROWSER
 int diralphasort(const void *va, const void *vb);
-void free_charptrarray(char **array, int len);
+void free_charptrarray(char **array, size_t len);
 void striponedir(char *foo);
 int readable_dir(const char *path);
 char **browser_init(const char *path, int *longest, int *numents);
@@ -268,7 +269,6 @@ void print1opt(const char *shortflag, const char *longflag,
                const char *desc);
 void usage(void);
 void version(void);
-void do_early_abort(void);
 int no_help(void);
 int nano_disabled_msg(void);
 #ifndef NANO_SMALL
@@ -342,6 +342,14 @@ void allow_pending_sigwinch(int allow);
 #ifndef NANO_SMALL
 void do_toggle(const toggle *which);
 #endif
+#if !defined(NANO_SMALL) || defined(USE_SLANG)
+void disable_signals(void);
+#endif
+#ifndef NANO_SMALL
+void enable_signals(void);
+#endif
+void disable_flow_control(void);
+void enable_flow_control(void);
 
 /* Public functions in rcfile.c */
 #ifdef ENABLE_NANORC
@@ -469,13 +477,13 @@ size_t xplustabs(void);
 size_t actual_x(const char *str, 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_titlebar(void);
 void blank_edit(void);
 void blank_statusbar(void);
 void blank_statusbar_refresh(void);
 void check_statblank(void);
-char *display_string(const char *buf, size_t start_col, int len);
+void blank_bottombars(void);
+char *display_string(const char *buf, size_t start_col, size_t len);
 void nanoget_repaint(const char *buf, const char *inputbuf, size_t x);
 int nanogetstr(int allowtabs, const char *buf, const char *def,
 #ifndef NANO_SMALL
@@ -486,8 +494,9 @@ int nanogetstr(int allowtabs, const char *buf, const char *def,
                , int *list
 #endif
                );
-void set_modified(void);
 void titlebar(const char *path);
+void set_modified(void);
+void statusbar(const char *msg, ...);
 void bottombars(const shortcut *s);
 void onekey(const char *keystroke, const char *desc, int len);
 #ifndef NDEBUG
@@ -511,7 +520,6 @@ int statusq(int allowtabs, const shortcut *s, const char *def,
 int do_yesno(int all, 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 line_len(const char *ptr);
index b1e84b18ef8b4576cd4ce8c6e27239ab9bc0e29e..5fffd4df443c243d9f5925405b8d47f59ec97af1 100644 (file)
@@ -129,14 +129,11 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len, int
     allow_pending_sigwinch(TRUE);
 #endif
 
-    /* Switch to raw mode if necessary so that we can type ^C, ^Q, ^S,
-     * ^Z, and ^\ (and ^Y on systems supporting delayed suspend) without
-     * getting interrupts, and turn the keypad off so that we don't get
-     * extended keypad values, all of which are outside the ASCII
-     * range. */
-#ifdef _POSIX_VDISABLE
-    raw();
-#endif
+    /* Turn off flow control characters if necessary so that we can type
+     * them in verbatim, and turn the keypad off so that we don't get
+     * extended keypad values outside the ASCII range. */
+    if (ISSET(PRESERVE))
+       disable_flow_control();
     keypad(win, FALSE);
 
     kbinput = wgetch(win);
@@ -165,11 +162,10 @@ int *get_verbatim_kbinput(WINDOW *win, size_t *kbinput_len, int
        nodelay(win, FALSE);
     }
 
-    /* Switch back to cbreak mode if necessary and turn the keypad back
-     * on now that we're done. */
-#ifdef _POSIX_VDISABLE
-    cbreak();
-#endif
+    /* Turn flow control characters back on if necessary and turn the
+     * keypad back on now that we're done. */
+    if (ISSET(PRESERVE))
+       enable_flow_control();
     keypad(win, TRUE);
 
 #ifndef NANO_SMALL
@@ -1096,26 +1092,14 @@ size_t strlenpt(const char *buf)
     return strnlenpt(buf, (size_t)-1);
 }
 
-void blank_bottombars(void)
+void blank_titlebar(void)
 {
-    if (!ISSET(NO_HELP)) {
-       mvwaddstr(bottomwin, 1, 0, hblank);
-       mvwaddstr(bottomwin, 2, 0, hblank);
-    }
-}
-
-void blank_bottomwin(void)
-{
-    if (ISSET(NO_HELP))
-       return;
-
-    mvwaddstr(bottomwin, 1, 0, hblank);
-    mvwaddstr(bottomwin, 2, 0, hblank);
+    mvwaddstr(topwin, 0, 0, hblank);
 }
 
 void blank_edit(void)
 {
-    int i;
+    size_t i;
     for (i = 0; i < editwinrows; i++)
        mvwaddstr(edit, i, 0, hblank);
 }
@@ -1141,12 +1125,20 @@ void check_statblank(void)
     }
 }
 
+void blank_bottombars(void)
+{
+    if (!ISSET(NO_HELP)) {
+       mvwaddstr(bottomwin, 1, 0, hblank);
+       mvwaddstr(bottomwin, 2, 0, hblank);
+    }
+}
+
 /* Convert buf into a string that can be displayed on screen.  The
  * caller wants to display buf starting with column start_col, and
  * extending for at most len columns.  start_col is zero-based.  len is
  * one-based, so len == 0 means you get "" returned.  The returned
  * string is dynamically allocated, and should be freed. */
-char *display_string(const char *buf, size_t start_col, int len)
+char *display_string(const char *buf, size_t start_col, size_t len)
 {
     size_t start_index;
        /* Index in buf of first character shown in return value. */
@@ -1539,16 +1531,6 @@ 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;
@@ -1559,7 +1541,7 @@ void titlebar(const char *path)
 
     wattron(topwin, A_REVERSE);
 
-    mvwaddstr(topwin, 0, 0, hblank);
+    blank_titlebar();
     mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
 
     space = COLS - sizeof(VERMSG) - 23;
@@ -1597,6 +1579,64 @@ void titlebar(const char *path)
     reset_cursor();
 }
 
+/* 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 statusbar(const char *msg, ...)
+{
+    va_list ap;
+
+    va_start(ap, msg);
+
+    /* Curses mode is turned off.  If we use wmove() now, it will muck
+     * up the terminal settings.  So we just use vfprintf(). */
+    if (curses_ended) {
+       vfprintf(stderr, msg, ap);
+       va_end(ap);
+       return;
+    }
+
+    /* Blank out the line. */
+    blank_statusbar();
+
+    if (COLS >= 4) {
+       char *bar;
+       char *foo;
+       size_t start_x = 0, foo_len;
+       bar = charalloc(COLS - 3);
+       vsnprintf(bar, COLS - 3, msg, ap);
+       va_end(ap);
+       foo = display_string(bar, 0, COLS - 4);
+       free(bar);
+       foo_len = strlen(foo);
+       start_x = (COLS - foo_len - 4) / 2;
+
+       wmove(bottomwin, 0, start_x);
+       wattron(bottomwin, A_REVERSE);
+
+       waddstr(bottomwin, "[ ");
+       waddstr(bottomwin, foo);
+       free(foo);
+       waddstr(bottomwin, " ]");
+       wattroff(bottomwin, A_REVERSE);
+       wnoutrefresh(bottomwin);
+       reset_cursor();
+       wrefresh(edit);
+           /* Leave the cursor at its position in the edit window, not
+            * in the statusbar. */
+    }
+
+    SET(DISABLE_CURPOS);
+    statblank = 26;
+}
+
 void bottombars(const shortcut *s)
 {
     int i, j, numcols;
@@ -1620,7 +1660,7 @@ void bottombars(const shortcut *s)
     /* There will be this many columns of shortcuts */
     numcols = (slen + (slen % 2)) / 2;
 
-    blank_bottomwin();
+    blank_bottombars();
 
     for (i = 0; i < numcols; i++) {
        for (j = 0; j <= 1; j++) {
@@ -2370,15 +2410,15 @@ int do_yesno(int all, const char *msg)
 
 int total_refresh(void)
 {
-    clearok(edit, TRUE);
     clearok(topwin, TRUE);
+    clearok(edit, TRUE);
     clearok(bottomwin, TRUE);
-    wnoutrefresh(edit);
     wnoutrefresh(topwin);
+    wnoutrefresh(edit);
     wnoutrefresh(bottomwin);
     doupdate();
-    clearok(edit, FALSE);
     clearok(topwin, FALSE);
+    clearok(edit, FALSE);
     clearok(bottomwin, FALSE);
     edit_refresh();
     titlebar(NULL);
@@ -2390,62 +2430,13 @@ void display_main_list(void)
     bottombars(main_list);
 }
 
-void statusbar(const char *msg, ...)
-{
-    va_list ap;
-
-    va_start(ap, msg);
-
-    /* Curses mode is turned off.  If we use wmove() now, it will muck
-     * up the terminal settings.  So we just use vfprintf(). */
-    if (curses_ended) {
-       vfprintf(stderr, msg, ap);
-       va_end(ap);
-       return;
-    }
-
-    /* Blank out the line. */
-    blank_statusbar();
-
-    if (COLS >= 4) {
-       char *bar;
-       char *foo;
-       int start_x = 0;
-       size_t foo_len;
-       bar = charalloc(COLS - 3);
-       vsnprintf(bar, COLS - 3, msg, ap);
-       va_end(ap);
-       foo = display_string(bar, 0, COLS - 4);
-       free(bar);
-       foo_len = strlen(foo);
-       start_x = (COLS - foo_len - 4) / 2;
-
-       wmove(bottomwin, 0, start_x);
-       wattron(bottomwin, A_REVERSE);
-
-       waddstr(bottomwin, "[ ");
-       waddstr(bottomwin, foo);
-       free(foo);
-       waddstr(bottomwin, " ]");
-       wattroff(bottomwin, A_REVERSE);
-       wnoutrefresh(bottomwin);
-       reset_cursor();
-       wrefresh(edit);
-           /* Leave the cursor at its position in the edit window, not
-            * in the statusbar. */
-    }
-
-    SET(DISABLE_CURPOS);
-    statblank = 26;
-}
-
-/* If constant is false, the user typed ^C so we unconditionally display
+/* If constant is FALSE, the user typed ^C so we unconditionally display
  * the cursor position.  Otherwise, we display it only if the character
  * position changed, and DISABLE_CURPOS is not set.
  *
- * If constant and DISABLE_CURPOS is set, we unset it and update old_i and
- * old_totsize.  That way, we leave the current statusbar alone, but next
- * time we will display. */
+ * If constant is TRUE and DISABLE_CURPOS is set, we unset it and update
+ * old_i and old_totsize.  That way, we leave the current statusbar
+ * alone, but next time we will display. */
 int do_cursorpos(int constant)
 {
     const filestruct *fileptr;
@@ -2533,7 +2524,7 @@ int line_len(const char *ptr)
 int do_help(void)
 {
     int i, page = 0, kbinput = ERR, meta_key, no_more = 0;
-    int no_help_flag = 0;
+    int no_help_flag = FALSE;
     const shortcut *oldshortcut;
 
     blank_edit();
@@ -2553,7 +2544,7 @@ int do_help(void)
 
        /* Well, if we're going to do this, we should at least do it the
         * right way. */
-       no_help_flag = 1;
+       no_help_flag = TRUE;
        UNSET(NO_HELP);
        window_init();
        bottombars(help_list);
@@ -2701,17 +2692,13 @@ void dump_buffer_reverse(void)
 /* Easter egg: Display credits.  Assume nodelay(edit) is FALSE. */
 void do_credits(void)
 {
-    int i, j = 0, k, place = 0, start_x;
-
-    const char *what;
-    const char *xlcredits[XLCREDIT_LEN];
-
-    const char *credits[CREDIT_LEN] = { 
-       "0",                            /* "The nano text editor" */
-       "1",                            /* "version" */
+    int crpos = 0, xlpos = 0;
+    const char *credits[CREDIT_LEN] = {
+       NULL,                           /* "The nano text editor" */
+       NULL,                           /* "version" */
        VERSION,
        "",
-       "2",                            /* "Brought to you by:" */
+       NULL,                           /* "Brought to you by:" */
        "Chris Allegretta",
        "Jordi Mallach",
        "Adam Rogoyski",
@@ -2734,80 +2721,82 @@ void do_credits(void)
        "Ryan Krebs",
        "Albert Chin",
        "",
-       "3",                            /* "Special thanks to:" */
+       NULL,                           /* "Special thanks to:" */
        "Plattsburgh State University",
        "Benet Laboratories",
        "Amy Allegretta",
        "Linda Young",
        "Jeremy Robichaud",
        "Richard Kolb II",
-       "4",                            /* "The Free Software Foundation" */
+       NULL,                           /* "The Free Software Foundation" */
        "Linus Torvalds",
-       "5",                            /* "For ncurses:" */
+       NULL,                           /* "For ncurses:" */
        "Thomas Dickey",
        "Pavel Curtis",
        "Zeyd Ben-Halim",
        "Eric S. Raymond",
-       "6",                            /* "and anyone else we forgot..." */
-       "7",                            /* "Thank you for using nano!\n" */
-       "", "", "", "",
+       NULL,                           /* "and anyone else we forgot..." */
+       NULL,                           /* "Thank you for using nano!" */
+       "",
+       "",
+       "",
+       "",
        "(c) 1999-2004 Chris Allegretta",
-       "", "", "", "",
+       "",
+       "",
+       "",
+       "",
        "http://www.nano-editor.org/"
     };
 
-    xlcredits[0] = _("The nano text editor");
-    xlcredits[1] = _("version ");
-    xlcredits[2] = _("Brought to you by:");
-    xlcredits[3] = _("Special thanks to:");
-    xlcredits[4] = _("The Free Software Foundation");
-    xlcredits[5] = _("For ncurses:");
-    xlcredits[6] = _("and anyone else we forgot...");
-    xlcredits[7] = _("Thank you for using nano!\n");
+    const char *xlcredits[XLCREDIT_LEN] = {
+       _("The nano text editor"),
+       _("version"),
+       _("Brought to you by:"),
+       _("Special thanks to:"),
+       _("The Free Software Foundation"),
+       _("For ncurses:"),
+       _("and anyone else we forgot..."),
+       _("Thank you for using nano!")
+    };
 
     curs_set(0);
     nodelay(edit, TRUE);
-    blank_bottombars();
-    mvwaddstr(topwin, 0, 0, hblank);
+    scrollok(edit, TRUE);
+    blank_titlebar();
     blank_edit();
+    blank_statusbar();
+    blank_bottombars();
+    wrefresh(topwin);
     wrefresh(edit);
     wrefresh(bottomwin);
-    wrefresh(topwin);
 
-    while (wgetch(edit) == ERR) {
-       for (k = 0; k <= 1; k++) {
-           blank_edit();
-           for (i = editwinrows / 2 - 1; i >= (editwinrows / 2 - 1 - j);
-                i--) {
-               mvwaddstr(edit, i * 2 - k, 0, hblank);
-
-               if (place - (editwinrows / 2 - 1 - i) < CREDIT_LEN) {
-                   what = credits[place - (editwinrows / 2 - 1 - i)];
-
-                   /* God I've missed hacking.  If what is exactly
-                       1 char long, it's a sentinel for a translated
-                       string, so use that instead.  This means no
-                       thanking people with 1 character long names ;-) */
-                   if (strlen(what) == 1)
-                       what = xlcredits[atoi(what)];
-               } else
-                   what = "";
-
-               start_x = COLS / 2 - strlen(what) / 2 - 1;
-               mvwaddstr(edit, i * 2 - k, start_x, what);
+    for (crpos = 0; crpos < CREDIT_LEN + editwinrows / 2; crpos++) {
+       if (wgetch(edit) != ERR)
+           break;
+       if (crpos < CREDIT_LEN) {
+           const char *what = credits[crpos];
+           size_t start_x;
+
+           if (what == NULL) {
+               assert(0 <= xlpos && xlpos < XLCREDIT_LEN);
+               what = xlcredits[xlpos];
+               xlpos++;
            }
-           napms(700);
-           wrefresh(edit);
+           start_x = COLS / 2 - strlen(what) / 2 - 1;
+           mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
        }
-       if (j < editwinrows / 2 - 1)
-           j++;
-
-       place++;
-
-       if (place >= CREDIT_LEN + editwinrows / 2)
+       napms(700);
+       scroll(edit);
+       wrefresh(edit);
+       if (wgetch(edit) != ERR)
            break;
+       napms(700);
+       scroll(edit);
+       wrefresh(edit);
     }
 
+    scrollok(edit, FALSE);
     nodelay(edit, FALSE);
     curs_set(1);
     display_main_list();