Handling a SIGWINCH (which signals a change in window size) not when it

happens but only when checking for keyboard input.  It now reports the
SIGWINCH via a special key value to the calling routine, to allow not
only the main editor but also the help viewer and the file browser to
adapt their display to the new size.
Patch by Mahyar Abbaspour, somewhat edited by Benno.


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@5228 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
This commit is contained in:
Benno Schulenberg 2015-05-28 13:02:29 +00:00
parent c5710d0ef8
commit 75d64e677e
10 changed files with 130 additions and 91 deletions

View File

@ -1,3 +1,15 @@
2015-05-28 Mahyar Abbaspour <mahyar.abaspour@gmail.com>
* src/nano.c (handle_sigwinch, regenerate_screen), src/global.c,
src/prompt.c (do_statusbar_input, get_prompt_string, do_yesno_prompt),
src/browser.c (do_browser, browser_refresh), src/help.c (do_help),
src/winio.c (get_key_buffer, unget_input, get_input, parse_kbinput),
src/text.c (do_justify, do_linter), src/nano.h, src/proto.h:
Handle a SIGWINCH (signalling a change in window size) not when it
happens but only when checking for input. Report the SIGWINCH via
a special key value to the calling routine, to allow not only the
main editor but also the help viewer and the file browser to adapt
their display to the new size. (Patch edited by Benno.)
2015-05-20 Devrim Gündüz <devrim@gunduz.org>
* doc/syntax/postgresql.nanorc: New file -- syntax highlighting for
PostgreSQL, first posted as Savannah patch #8601. Trimmed by Benno.

View File

@ -41,6 +41,8 @@ static int longest = 0;
/* The number of columns in the longest filename in the list. */
static size_t selected = 0;
/* The currently selected filename in the list; zero-based. */
static char *path_save = NULL;
/* A copy of the current path. */
/* Our main file browser function. path is the tilde-expanded path we
* start browsing from. */
@ -75,6 +77,9 @@ char *do_browser(char *path, DIR *dir)
path = mallocstrassn(path, get_full_path(path));
/* Save the current path in order to be used later. */
path_save = path;
assert(path != NULL && path[strlen(path) - 1] == '/');
/* Get the file list, and set longest and width in the process. */
@ -118,6 +123,14 @@ char *do_browser(char *path, DIR *dir)
kbinput = get_kbinput(edit);
#ifndef NANO_TINY
if (kbinput == KEY_WINCH) {
kbinput = ERR;
curs_set(0);
continue;
}
#endif
#ifndef DISABLE_MOUSE
if (kbinput == KEY_MOUSE) {
int mouse_x, mouse_y;
@ -156,6 +169,8 @@ char *do_browser(char *path, DIR *dir)
} else if (func == do_help_void) {
#ifndef DISABLE_HELP
do_help_void();
/* Perhaps the window dimensions have changed. */
browser_refresh();
curs_set(0);
#else
nano_disabled_msg();
@ -547,6 +562,11 @@ void browser_refresh(void)
char *foo;
/* The additional information that we'll display about a file. */
/* Perhaps window dimensions have changed; reinitialize the browser. */
browser_init(path_save, opendir(path_save));
qsort(filelist, filelist_len, sizeof(char *), diralphasort);
titlebar(path_save);
blank_edit();
wmove(edit, 0, 0);

View File

@ -30,12 +30,8 @@
/* Global variables. */
#ifndef NANO_TINY
sigjmp_buf jump_buf;
/* Used to return to either main() or the unjustify routine in
* do_justify() after a SIGWINCH. */
bool jump_buf_main = FALSE;
/* Have we set jump_buf so that we return to main() after a
* SIGWINCH? */
volatile sig_atomic_t sigwinch_counter = 0;
/* Is incremented by the handler whenever a SIGWINCH occurs. */
#endif
bool meta_key;

View File

@ -72,10 +72,13 @@ void do_help(void (*refresh_func)(void))
bottombars(MHELP);
wnoutrefresh(bottomwin);
while (TRUE) {
size_t i;
/* Get the last line of the help text. */
ptr = help_text;
for (; *ptr != '\0'; last_line++) {
for (last_line = 0; *ptr != '\0'; last_line++) {
ptr += help_line_len(ptr);
if (*ptr == '\n')
ptr++;
@ -83,9 +86,6 @@ void do_help(void (*refresh_func)(void))
if (last_line > 0)
last_line--;
while (TRUE) {
size_t i;
/* Display the help text if we don't have a key, or if the help
* text has moved. */
if (kbinput == ERR || line != old_line) {
@ -117,6 +117,14 @@ void do_help(void (*refresh_func)(void))
kbinput = get_kbinput(edit);
#ifndef NANO_TINY
if (kbinput == KEY_WINCH) {
kbinput = ERR;
curs_set(0);
continue;
}
#endif
#ifndef DISABLE_MOUSE
if (kbinput == KEY_MOUSE) {
int mouse_x, mouse_y;

View File

@ -25,7 +25,6 @@
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
@ -1245,7 +1244,6 @@ void signal_init(void)
/* Trap SIGWINCH because we want to handle window resizes. */
act.sa_handler = handle_sigwinch;
sigaction(SIGWINCH, &act, NULL);
allow_pending_sigwinch(FALSE);
#endif
/* Trap normal suspend (^Z) so we can handle it ourselves. */
@ -1343,6 +1341,13 @@ RETSIGTYPE do_continue(int signal)
#ifndef NANO_TINY
/* Handler for SIGWINCH (window size change). */
RETSIGTYPE handle_sigwinch(int signal)
{
/* Let the input routine know that a SIGWINCH has occurred. */
sigwinch_counter++;
}
/* Reinitialize and redraw the screen completely. */
void regenerate_screen(void)
{
const char *tty = ttyname(0);
int fd, result = 0;
@ -1367,10 +1372,6 @@ RETSIGTYPE handle_sigwinch(int signal)
LINES = win.ws_row;
#endif
/* If we've partitioned the filestruct, unpartition it now. */
if (filepart != NULL)
unpartition_filestruct(&filepart);
#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
@ -1397,14 +1398,7 @@ RETSIGTYPE handle_sigwinch(int signal)
window_init();
/* Redraw the contents of the windows that need it. */
blank_statusbar();
wnoutrefresh(bottomwin);
currmenu = MMAIN;
total_refresh();
/* Jump back to either main() or the unjustify routine in
* do_justify(). */
siglongjmp(jump_buf, 1);
}
/* If allow is TRUE, block any SIGWINCH signals that we get, so that we
@ -1599,6 +1593,11 @@ int do_input(bool allow_funcs)
/* Read in a character. */
input = get_kbinput(edit);
#ifndef NANO_TINY
if (input == KEY_WINCH)
return KEY_WINCH;
#endif
#ifndef DISABLE_MOUSE
if (func_key && input == KEY_MOUSE) {
/* We received a mouse click. */
@ -2798,17 +2797,6 @@ int main(int argc, char **argv)
reset_cursor();
wnoutrefresh(edit);
#ifndef NANO_TINY
if (!jump_buf_main) {
/* If we haven't already, we're going to set jump_buf so
* that we return here after a SIGWINCH. Indicate this. */
jump_buf_main = TRUE;
/* Return here after a SIGWINCH. */
sigsetjmp(jump_buf, 1);
}
#endif
/* Just in case we were at the statusbar prompt, make sure the
* statusbar cursor position is reset. */
do_prompt_abort();

View File

@ -117,7 +117,7 @@
#include <regex.h>
#endif
#ifndef NANO_TINY
#include <setjmp.h>
#include <signal.h>
#endif
#include <assert.h>
@ -571,6 +571,9 @@ enum
#define CONTROL_RIGHT 554
#ifndef NANO_TINY
/* An imaginary key for when we get a SIGWINCH (window resize). */
#define KEY_WINCH -2
/* Extra bits for the undo function. */
#define UNdel_del (1<<0)
#define UNdel_backspace (1<<1)

View File

@ -66,6 +66,11 @@ int do_statusbar_input(bool *ran_func, bool *finished,
/* Read in a character. */
input = get_kbinput(bottomwin);
#ifndef NANO_TINY
if (input == KEY_WINCH)
return KEY_WINCH;
#endif
#ifndef DISABLE_MOUSE
/* If we got a mouse click and it was on a shortcut, read in the
* shortcut character. */
@ -794,6 +799,14 @@ functionptrtype get_prompt_string(int *actual, bool allow_tabs,
kbinput = do_statusbar_input(&ran_func, &finished, refresh_func);
assert(statusbar_x <= strlen(answer));
#ifndef NANO_TINY
if (kbinput == KEY_WINCH) {
refresh_func();
update_statusbar_line(answer, statusbar_x);
continue;
}
#endif
func = func_from_key(&kbinput);
if (func == do_cancel || func == do_enter_void)
@ -1055,6 +1068,13 @@ int do_yesno_prompt(bool all, const char *msg)
nostr = _("Nn");
allstr = _("Aa");
do {
int kbinput;
functionptrtype func;
#ifndef DISABLE_MOUSE
int mouse_x, mouse_y;
#endif
if (!ISSET(NO_HELP)) {
char shortstr[3];
/* Temp string for Yes, No, All. */
@ -1098,15 +1118,14 @@ int do_yesno_prompt(bool all, const char *msg)
wnoutrefresh(edit);
wnoutrefresh(bottomwin);
do {
int kbinput;
functionptrtype func;
#ifndef DISABLE_MOUSE
int mouse_x, mouse_y;
#endif
currmenu = MYESNO;
kbinput = get_kbinput(bottomwin);
#ifndef NANO_TINY
if (kbinput == KEY_WINCH)
continue;
#endif
func = func_from_key(&kbinput);
if (func == do_cancel)

View File

@ -28,8 +28,7 @@
/* All external variables. See global.c for their descriptions. */
#ifndef NANO_TINY
extern sigjmp_buf jump_buf;
extern bool jump_buf_main;
extern volatile sig_atomic_t sigwinch_counter;
#endif
extern bool meta_key;
@ -478,6 +477,7 @@ RETSIGTYPE do_suspend(int signal);
RETSIGTYPE do_continue(int signal);
#ifndef NANO_TINY
RETSIGTYPE handle_sigwinch(int signal);
void regenerate_screen(void);
void allow_pending_sigwinch(bool allow);
void do_toggle(int flag);
#endif

View File

@ -1922,10 +1922,6 @@ void do_justify(bool full_justify)
if (full_justify)
openfile->current = openfile->fileage;
#ifndef NANO_TINY
allow_pending_sigwinch(FALSE);
#endif
while (TRUE) {
size_t i;
/* Generic loop variable. */
@ -2207,17 +2203,6 @@ void do_justify(bool full_justify)
edit_refresh();
#ifndef NANO_TINY
/* We're going to set jump_buf so that we return here after a
* SIGWINCH instead of to main(). Indicate this. */
jump_buf_main = FALSE;
/* Return here after a SIGWINCH. */
sigsetjmp(jump_buf, 1);
#endif
statusbar(_("Can now UnJustify!"));
/* If constant cursor position display is on, make sure the current
* cursor position will be properly displayed on the statusbar. */
if (ISSET(CONST_UPDATE))
@ -2229,7 +2214,15 @@ void do_justify(bool full_justify)
/* Now get a keystroke and see if it's unjustify. If not, put back
* the keystroke and return. */
kbinput = do_input(FALSE);
#ifndef NANO_TINY
do {
#endif
statusbar(_("Can now UnJustify!"));
kbinput = do_input(FALSE);
#ifndef NANO_TINY
} while (kbinput == KEY_WINCH);
#endif
func = func_from_key(&kbinput);
if (func == do_uncut_text) {
@ -2295,10 +2288,6 @@ void do_justify(bool full_justify)
/* Display the shortcut list with UnCut. */
uncutfunc->desc = uncut_tag;
display_main_list();
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
#endif
}
/* Justify the current paragraph. */
@ -3183,6 +3172,12 @@ void do_linter(void)
}
kbinput = get_kbinput(bottomwin);
#ifndef NANO_TINY
if (kbinput == KEY_WINCH)
continue;
#endif
func = func_from_key(&kbinput);
tmplint = curlint;

View File

@ -41,6 +41,8 @@ static bool disable_cursorpos = FALSE;
/* Should we temporarily disable constant cursor position
* display? */
static sig_atomic_t sigwinch_counter_save = 0;
/* Control character compatibility:
*
* - NANO_BACKSPACE_KEY is Ctrl-H, which is Backspace under ASCII, ANSI,
@ -112,10 +114,6 @@ void get_key_buffer(WINDOW *win)
if (key_buffer != NULL)
return;
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
#endif
/* Just before reading in the first character, display any pending
* screen updates. */
doupdate();
@ -125,8 +123,17 @@ void get_key_buffer(WINDOW *win)
if (nodelay_mode) {
if ((input = wgetch(win)) == ERR)
return;
} else
} else {
while ((input = wgetch(win)) == ERR) {
#ifndef NANO_TINY
/* Did we get SIGWINCH since we were last here? */
if (sigwinch_counter != sigwinch_counter_save) {
sigwinch_counter_save = sigwinch_counter;
regenerate_screen();
input = KEY_WINCH;
break;
} else
#endif
errcount++;
/* If we've failed to get a character MAX_BUF_SIZE times in a
@ -137,10 +144,7 @@ void get_key_buffer(WINDOW *win)
if (errcount == MAX_BUF_SIZE)
handle_hupterm(0);
}
#ifndef NANO_TINY
allow_pending_sigwinch(FALSE);
#endif
}
/* Increment the length of the keystroke buffer, and save the value
* of the keystroke at the end of it. */
@ -148,14 +152,17 @@ void get_key_buffer(WINDOW *win)
key_buffer = (int *)nmalloc(sizeof(int));
key_buffer[0] = input;
#ifndef NANO_TINY
/* If we got SIGWINCH, get out immediately since the win argument is
* no longer valid. */
if (input == KEY_WINCH)
return;
#endif
/* Read in the remaining characters using non-blocking input. */
nodelay(win, TRUE);
while (TRUE) {
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
#endif
input = wgetch(win);
/* If there aren't any more characters, stop reading. */
@ -168,10 +175,6 @@ void get_key_buffer(WINDOW *win)
key_buffer = (int *)nrealloc(key_buffer, key_buffer_len *
sizeof(int));
key_buffer[key_buffer_len - 1] = input;
#ifndef NANO_TINY
allow_pending_sigwinch(FALSE);
#endif
}
/* Switch back to waiting mode for input. */
@ -191,11 +194,6 @@ size_t get_key_buffer_len(void)
/* Add the keystrokes in input to the keystroke buffer. */
void unget_input(int *input, size_t input_len)
{
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
allow_pending_sigwinch(FALSE);
#endif
/* If input is empty, get out. */
if (input_len == 0)
return;
@ -249,11 +247,6 @@ int *get_input(WINDOW *win, size_t input_len)
{
int *input;
#ifndef NANO_TINY
allow_pending_sigwinch(TRUE);
allow_pending_sigwinch(FALSE);
#endif
if (key_buffer_len == 0) {
if (win != NULL) {
get_key_buffer(win);
@ -643,6 +636,11 @@ int parse_kbinput(WINDOW *win)
retval = sc_seq_or(do_next_word_void, 0);
#endif
break;
#ifndef NANO_TINY
case KEY_WINCH:
retval = KEY_WINCH;
break;
#endif
}
/* If our result is an extended keypad value (i.e. a value