minor overhaul of terminal-related things

git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1745 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
David Lawrence Ramsey 2004-05-18 01:20:36 +00:00
parent 36e363f525
commit d7fd200a6a
6 changed files with 350 additions and 328 deletions

View File

@ -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)

View 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]);

View 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>
@ -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)

View File

@ -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)

View 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);

View 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);
}
napms(700);
wrefresh(edit);
}
if (j < editwinrows / 2 - 1)
j++;
place++;
if (place >= CREDIT_LEN + editwinrows / 2)
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++;
}
start_x = COLS / 2 - strlen(what) / 2 - 1;
mvwaddstr(edit, editwinrows - 1 - editwinrows % 2, start_x, what);
}
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();