- 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)
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
- 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()
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
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)
- 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)
- 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()
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()
- 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
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)
#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));
}
/* 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]);
#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
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)
endwin();
curses_ended = TRUE;
- /* Restore the old term settings */
+ /* Restore the old terminal settings. */
tcsetattr(0, TCSANOW, &oldterm);
va_start(ap, msg);
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);
}
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;
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. */
/* 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");
/* 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");
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 */
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));
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! */
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
}
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);
break;
#endif
case TOGGLE_NOHELP_KEY:
- wclear(bottomwin);
+ blank_statusbar();
+ blank_bottombars();
wrefresh(bottomwin);
window_init();
edit_refresh();
}
#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;
#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'},
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);
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;
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)
#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)
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;
/* 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);
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);
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
#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
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
, 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
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);
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);
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
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);
}
}
}
+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. */
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;
wattron(topwin, A_REVERSE);
- mvwaddstr(topwin, 0, 0, hblank);
+ blank_titlebar();
mvwaddnstr(topwin, 0, 2, VERMSG, COLS - 3);
space = COLS - sizeof(VERMSG) - 23;
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;
/* 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++) {
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);
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;
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();
/* 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);
/* 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",
"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();