badeleux
badeleux

Reputation: 592

Cannot determine terminal size with ncurses

I am trying to handle a resize signal (SIGWINCH)

void Server::resizeSignalHandler(int a)
{
signal(SIGWINCH, SIG_IGN);

endwin();
initscr();
refresh();
clear();

int x,y;
getmaxyx(stdscr, y, x);

wmove(upScreen, 0, 0);
wmove(downScreen, y/2, 0);
wresize(upScreen, y/2, x);
wresize(downScreen, y/2, x);
wclear(upScreen);
wclear(downScreen);
waddstr(upScreen, "test1");
waddstr(downScreen, "test2");
wrefresh(upScreen);
wrefresh(downScreen);
refresh();

signal(SIGWINCH, Server::resizeSignalHandler);

}
Server::Server()
{
//ncurses screen initialization
initscr();

if (!upScreen) {
    upScreen = newwin(0, 0, 1, 1);
}
if (!downScreen) {
    downScreen = newwin(0, 0, 1, 1);
}
//adjusting screen when user resize terminal
signal(SIGWINCH, Server::resizeSignalHandler);

//configuring screens
Server::resizeSignalHandler(0);

waddstr(Server::upScreen, "lalfasdfsafd as");
waddstr(downScreen, "supreme!");
wrefresh(Server::upScreen);
wrefresh(downScreen);
}

When I was debugging this code, in resizeSignalHandler var x,y were always the same (size didn't change). I also tried determine size with ioctl, but nothing's changed.

I figured out that many people before me had this problem http://www.mail-archive.com/[email protected]/msg11253.html Sometimes, they solved that (changing /etc/profile ;O (sic!)), but sometimes not. Is there any alternative to mac os x terminal, maybe ncurses is dedicated for xterm and similar.

Upvotes: 4

Views: 2799

Answers (4)

wkordalski
wkordalski

Reputation: 938

getmaxyx(...) gives wrong (not updated) terminal sizes because of custom SIGWINCH signal handler.

You can use ioctl(fileno(stdout), TIOCGWINSZ, struct winsize*) to get updated terminal parameters. But this won't update data returned by getmaxyx(...).

To update getmaxyx(...) data, you should call resize_term(size.ws_row, size.ws_col)

So the signal handler code should look like:

void on_terminal_resize(int n) {
    struct winsize size;

    if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) {
        resize_term(size.ws_row, size.ws_col);
    }
    // Your code goes here...
    signal(SIGWINCH, on_terminal_resize);
}

Upvotes: 1

Émilien Tlapale
Émilien Tlapale

Reputation: 903

That’s because the values you get with getmaxyx are updated themselves by a signal handler listening to SIGWINCH. You need to save the pointer to the old signal with something like:

old_callback = signal(SIGWINCH, Server::resizeSignalHandler);

and then call it in resizeSignalHandler:

old_callback(a);

Upvotes: 1

fireant
fireant

Reputation: 14538

I don't have a mac machine, and cant test this. But I suppose the pseudo terminal bash is running on updates $LINES and $COLUMNS but these updates are not passed to the pseudo terminal your program is assigned to. This is because you say the WINCH signal is caught, but those params are not updated. A workaround is to execute "/usr/X11/bin/resize" / "/usr/bin/resize" in the signal handler. Probably that would properly update $LINES and $COLUMNS.

Upvotes: -1

wallyk
wallyk

Reputation: 57784

I'm not sure, but I think you have to call ioctl(1, TIOCGWINSZ, struct winsize*) to get the updated terminal parameters. See man tty_ioctl.

Upvotes: 0

Related Questions