当我调整 window 大小时,Termcaps 行和列没有改变

Termcaps lines and columns are not changing when I resize the window

我正在尝试获取终端 window 的大小,即使我调整 window 的大小时,我正在为此使用 termcaps,问题是当我调整 window 的大小时],行和列的值保持不变而不是更新,我也尝试使用 ncurses 的 LINES 和 COLS 全局变量,但同样的事情发生了。 这是一个最小的可复制示例:

#include <ncurses.h>
#include <term.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    char * term_type = getenv("TERM");
    int ret;
    int li_cap;
    int co_cap;

    if (!term_type)
    {
        write(2, "TERM env must be set\n", 21);
        return (-1);
    }
    if ((ret = tgetent(NULL, term_type)) == -1)
    {
        write(2, "Could not access to the termcap database\n", 41);
        return (-1);
    }
    if (!ret)
    {
        write(2, "This terminal is not supported by termcaps\n", 43);
        return (-1);
    }
    while (1)
    {
        sleep(1);
        li_cap = tgetnum("li");
        co_cap = tgetnum("co");
        printf("%d %d\n", li_cap, co_cap);
    }
    return (0);
}

所以当我在循环中调整 window 的大小时,值保持不变,我想实时获取行和列,我怎么能用 termcaps 做到这一点?

termcap 数据和环境变量 COLUMNSLINES 不可靠,不会在终端调整大小时更新,尤其是在程序执行期间。 POSIX 系统还有另一种解决方案,您可以:

  • ioctl(0, TIOCGWINSZ, &ws)
  • 检索终端window的大小
  • 注册一个信号处理程序以获得终端尺寸变化的通知。

这里有一个演示程序:

#include <stdio.h>
#include <signal.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <unistd.h>

static volatile unsigned char term_size_updated;

static void term_resize() {
    term_size_updated = 1;
}

static void term_get_size(int *cols, int *rows) {
    struct winsize ws;

    /* get screen dimensions from (pseudo) tty ioctl */
    if (ioctl(0, TIOCGWINSZ, &ws) == 0) {
        *cols = ws.ws_col;
        *rows = ws.ws_row;
    } else {
        *cols = *rows = -1;
    }
}

int main() {
    struct sigaction sig;
    int cols, rows;

    /* set up terminal resize callback */
    sig.sa_handler = term_resize;
    sigemptyset(&sig.sa_mask);
    sig.sa_flags = 0;
    sigaction(SIGWINCH, &sig, NULL);

    term_size_updated = 1;
    for (;;) {
        if (term_size_updated) {
            term_size_updated = 0;
            term_get_size(&cols, &rows);
            fprintf(stderr, "term_resize: cols=%d, rows=%d\n", cols, rows);
        }
        sleep(1);
    }
    return 0;
}