From: David Lawrence Ramsey Date: Tue, 18 May 2004 01:20:36 +0000 (+0000) Subject: minor overhaul of terminal-related things X-Git-Tag: v1.3.3~74 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=d7fd200a6a533c692b0f10d3c6c20b27f2144fcb;p=nano.git minor overhaul of terminal-related things git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1745 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/ChangeLog b/ChangeLog index d3e63bd7..7d9990ec 100644 --- 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 index bd75be9f..d0a80383 100644 --- 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 index 98af0de6..ac55a3a4 100644 --- a/src/nano.c +++ b/src/nano.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -54,6 +53,10 @@ #include #endif +#ifndef NANO_SMALL +#include +#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 index ffdd6bfd..5f711d04 100644 --- 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 +/* 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 index b934c235..0e0ca45a 100644 --- 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 index b1e84b18..5fffd4df 100644 --- 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();