+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.
/* 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. */
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. */
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;
} 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();
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);
/* 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;
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++;
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) {
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;
#include <stdio.h>
#include <stdarg.h>
-#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
/* 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. */
#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;
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
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
/* 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. */
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();
#include <regex.h>
#endif
#ifndef NANO_TINY
-#include <setjmp.h>
+#include <signal.h>
#endif
#include <assert.h>
#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)
/* 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. */
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)
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. */
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)
/* 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;
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
if (full_justify)
openfile->current = openfile->fileage;
-#ifndef NANO_TINY
- allow_pending_sigwinch(FALSE);
-#endif
-
while (TRUE) {
size_t i;
/* Generic loop variable. */
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))
/* 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) {
/* 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. */
}
kbinput = get_kbinput(bottomwin);
+
+#ifndef NANO_TINY
+ if (kbinput == KEY_WINCH)
+ continue;
+#endif
+
func = func_from_key(&kbinput);
tmplint = curlint;
/* 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,
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();
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
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. */
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. */
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. */
/* 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;
{
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);
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