Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调整窗口大小时,Termcaps线条和列不会更改_C_Ncurses - Fatal编程技术网

调整窗口大小时,Termcaps线条和列不会更改

调整窗口大小时,Termcaps线条和列不会更改,c,ncurses,C,Ncurses,我正在尝试获取终端窗口的大小,即使在调整窗口大小时,我也在使用termcaps,问题是当我调整窗口大小时,行和列的值保持不变而不是更新,我也尝试使用ncurses的line和COLS globals,但同样的情况也会发生。 下面是一个最小的可复制示例: #include <ncurses.h> #include <term.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h

我正在尝试获取终端窗口的大小,即使在调整窗口大小时,我也在使用termcaps,问题是当我调整窗口大小时,行和列的值保持不变而不是更新,我也尝试使用ncurses的line和COLS globals,但同样的情况也会发生。 下面是一个最小的可复制示例:

#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);
}
#包括
#包括
#包括
#包括
#包括
内部主(空)
{
char*term_type=getenv(“术语”);
int ret;
国际礼帽;
int co_cap;
如果(!术语类型)
{
写入(2,“必须设置术语环境”,21);
返回(-1);
}
if((ret=tgetent(NULL,术语类型))=-1)
{
写入(2,“无法访问termcap数据库”,41);
返回(-1);
}
如果(!ret)
{
写入(2,“termcaps不支持此终端,\n”,43);
返回(-1);
}
而(1)
{
睡眠(1);
li_cap=tgetnum(“li”);
co_cap=tgetnum(“co”);
printf(“%d%d\n”,li\u cap,co\u cap);
}
返回(0);
}

因此,当我调整循环内窗口的大小时,值保持不变,我想实时获取行和列,如何使用termcaps做到这一点?

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

  • 使用
    ioctl(0,TIOCGWINSZ,&ws)
  • 注册一个信号处理程序以获得终端大小更改的通知
下面是一个演示程序:

#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_resize(&cols, &rows);
            fprintf(stderr, "term_resize: cols=%d, rows=%d\n", cols, rows);
        }
        sleep(1);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
静态易失性无符号字符项大小更新;
静态无效项_resize(){
术语大小更新=1;
}
静态无效项获取大小(int*cols,int*rows){
结构winsize ws;
/*从(伪)tty ioctl获取屏幕尺寸*/
if(ioctl(0,TIOCGWINSZ,&ws)==0){
*cols=ws.ws_col;
*行=ws.ws_行;
}否则{
*cols=*行=-1;
}
}
int main(){
结构sig动作sig;
int列,行;
/*设置终端大小回调*/
sig.sa_handler=term_resize;
sigemptyset(&sig.sa_mask);
sig.sa_标志=0;
sigaction(SIGWINCH,&sig,NULL);
术语大小更新=1;
对于(;;){
如果(术语尺寸更新){
术语大小更新=0;
术语\调整大小(&cols,&rows);
fprintf(标准字符,“字词大小:cols=%d,行=%d\n”,cols,行);
}
睡眠(1);
}
返回0;
}

使用此代码,您将遇到竞争条件<代码>术语\u更新
应该是一个
易失性信号\u原子\u t
。另一种选择是使用“自我管道技巧”。@michaelmeyer:事实上,这个程序是一个快速而肮脏的例子。没有规定保护中断驱动代码访问的变量。@michaelmeyer什么是sig_原子?我不确定ioctl()是否是信号安全的。@chqrlie是的,谢谢,抱歉等待,我忘记将答案设置为acceptedmaybe此问题可以通过
使用tioctl(true)解决