From 75d64e677ec3f9771ec897a8505bb893825fc42d Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Thu, 28 May 2015 13:02:29 +0000 Subject: [PATCH] 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 --- ChangeLog | 12 ++++++++++++ src/browser.c | 20 ++++++++++++++++++++ src/global.c | 8 ++------ src/help.c | 16 ++++++++++++---- src/nano.c | 36 ++++++++++++----------------------- src/nano.h | 5 ++++- src/prompt.c | 33 +++++++++++++++++++++++++------- src/proto.h | 4 ++-- src/text.c | 35 +++++++++++++++------------------- src/winio.c | 52 +++++++++++++++++++++++++-------------------------- 10 files changed, 130 insertions(+), 91 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5d70dfe4..3b1133da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2015-05-28 Mahyar Abbaspour + * 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 * doc/syntax/postgresql.nanorc: New file -- syntax highlighting for PostgreSQL, first posted as Savannah patch #8601. Trimmed by Benno. diff --git a/src/browser.c b/src/browser.c index 5cfc45a4..ad59baf8 100644 --- a/src/browser.c +++ b/src/browser.c @@ -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); diff --git a/src/global.c b/src/global.c index c93b78c4..614e46d6 100644 --- a/src/global.c +++ b/src/global.c @@ -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; diff --git a/src/help.c b/src/help.c index a14fcbc9..c6821a43 100644 --- a/src/help.c +++ b/src/help.c @@ -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; diff --git a/src/nano.c b/src/nano.c index 137f33c4..6cb9127d 100644 --- a/src/nano.c +++ b/src/nano.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -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(); diff --git a/src/nano.h b/src/nano.h index ffd7d22d..33c4e530 100644 --- a/src/nano.h +++ b/src/nano.h @@ -117,7 +117,7 @@ #include #endif #ifndef NANO_TINY -#include +#include #endif #include @@ -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) diff --git a/src/prompt.c b/src/prompt.c index 38178df7..aa5ddafd 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -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) diff --git a/src/proto.h b/src/proto.h index 337211d8..ca571da1 100644 --- a/src/proto.h +++ b/src/proto.h @@ -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 diff --git a/src/text.c b/src/text.c index 245d0e64..76524faa 100644 --- a/src/text.c +++ b/src/text.c @@ -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; diff --git a/src/winio.c b/src/winio.c index d57f7970..d94a5bab 100644 --- a/src/winio.c +++ b/src/winio.c @@ -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