commit d7fd200a6a533c692b0f10d3c6c20b27f2144fcb
parent 36e363f5254fb6deb8e72df8ed77fea24c5c6eff
Author: David Lawrence Ramsey <pooka109@gmail.com>
Date: Tue, 18 May 2004 01:20:36 +0000
minor overhaul of terminal-related things
git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1745 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
Diffstat:
M | ChangeLog | | | 68 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | src/files.c | | | 5 | +++-- |
M | src/nano.c | | | 271 | +++++++++++++++++++++++++++++++++++-------------------------------------------- |
M | src/nano.h | | | 5 | +++-- |
M | src/proto.h | | | 26 | +++++++++++++++++--------- |
M | src/winio.c | | | 299 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
6 files changed, 348 insertions(+), 326 deletions(-)
diff --git 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)
diff --git a/src/files.c b/src/files.c
@@ -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]);
diff --git a/src/nano.c b/src/nano.c
@@ -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>
@@ -54,6 +53,10 @@
#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)
diff --git a/src/nano.h b/src/nano.h
@@ -54,9 +54,10 @@
#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)
diff --git a/src/proto.h b/src/proto.h
@@ -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);
diff --git a/src/winio.c b/src/winio.c
@@ -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();