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