The one guideline you should follow is to do as little as possible in interrupt routines. If you're doing anything more than setting a flag, that's when you should consider re-thinking your solution.
The curses
system has a way to handle this problem but it requires a little work on the part of the developer.
You set half-delay mode with a suitable delay, so that getch()
will return with ERR
if there's no keystroke available during that time. That effectively gets you out of the getch()
call so you can then do whatever other curses manipulations you need.
So, here's what I'd suggest. First, change your SIGWINCH handler so it simply sets a flag resized
that your "main" program can detect.
Second, provide your application with a special form of getch()
along the lines of (pseudo-code, obviously):
def getch_10th():
set half delay mode for (for example) 1/10th second
do:
if resized:
do whatever it takes to resize window
set ch to result of real getch() (with timeout, of course)
while timed out
return ch
The half delay mode is a compromise, in terms of efficiency, between waiting forever (and not handling resizing events) and returning immediately (sucking up CPU grunt).
Using it wisely can make your windows respond reasonably fast without having to worry about portability.
See the following C program for an example of putting this into action. First, the signal and intercept function:
#include <curses.h>
#include <signal.h>
// Flag and signal handler.
static volatile int resized = 1;
static void handle_resize (int sig) {
resized = 1;
}
// Get a character, handling resize events.
int getch10th (void) {
int ch;
do {
if (resized) {
resized = 0;
endwin();
refresh();
mvprintw (1, 0, "Size = %dx%d. \n", COLS, LINES);
refresh();
}
halfdelay (1);
ch = getch();
} while (ch == ERR || ch == KEY_RESIZE);
return ch;
}
Then a simple main
to test it out:
// Simplified main capturing keystrokes.
int main (void) {
WINDOW * w = initscr();
noecho();
signal (SIGWINCH, handle_resize);
for (;;) {
int ch = getch10th();
mvprintw(0, 0, "Got character 0x%02x. \n\n", ch);
}
endwin();
return 0;
}
Astute readers will have noticed the presence of KEY_RESIZE
in the getch10th()
function as well. This is because some implementations will actually queue a special key to handle this exact case (forcing getch()
to return after raising SIGWINCH
).
If you're using the above code to allow for those systems that don't do this, you have to remember to handle that spurious key for those systems that do, hence why we capture that as well.