【问题标题】:How to get windows size from Linux如何从 Linux 获取窗口大小
【发布时间】:2013-09-18 00:05:47
【问题描述】:

每个人。我还是编程新手。我真的需要一些关于我面临的问题的帮助。所以,这里的情况是我试图在终端尺寸低于 80x24 时显示警告。作为记录,我的操作系统是 Window,但我使用虚拟机运行 Linux,因为所有文件都在 Linux 中。当我使用终端运行文件时,警告显示正确。但问题是当我尝试使用 PuTTY 从 Windows 运行文件时。警告没有出现。我确定是因为我使用的功能只能读取 Linux 环境而不能读取 Windows。任何人都可以帮助我或指出如何使其能够获得窗户尺寸的方向。这些文件都应该保留在 Linux 中。我正在使用 C。

这里只是显示警告和获取维度的部分代码。

//This is to display warning


int display_warning()
{
 CDKSCREEN *cdkscreen = 0;
 WINDOW *cursesWin    = 0;
 char *mesg[5];
 char *buttons[] = {"[ OK ]"};
 CDKDIALOG *confirm;

 cursesWin = initscr();
 cdkscreen = initCDKScreen (cursesWin);

 initCDKColor();

 mesg[0] = "</2>"The size of Window must be at least 80x24.";
 confirm = newCDKDialog(cdkscreen, CENTER, CENTER, mesg, 1, buttons, A_REVERSE, TRUE,TRUE, FALSE);
 setCDKDialogBackgroundColor(confirm, "</2>");
 injectCDKDialog(confirm,TAB);
 activateCDKDialog(confirm,0);

 if (confirm -> exitType == vNORMAL){
 destroyCDKDialog (confirm);
 destroyCDKScreen (cdkscreen);
 endCDK();
 }
 return 0;
}



//This is to get the dimension

int get_terminal_size()
{
 int cols;
 int lines;

 #ifdef TIOCGSIZE
 struct ttysize ts;
 ioctl(0,TIOCGSIZE, &ts);
 lines = ts.ts_linesl;
 cols = ts.ts_cols;

 #elif defined(TIOCGWINSZ)
 struct winsize ts;
 ioctl(0, TIOCGWINSZ, &ts);
 lines = ts.ws_row;
 cols = ts.ws_col;

 #endif

 if((lines <= 23)||(cols <= 79)){
 display_warning();
 }

 return 0;
}

//then there will be the main function that i think is not necessary to put the code here.

非常感谢所有评论和帮助。我是编程初学者,如果有一些基本的不懂的地方请多多包涵。

菲克里

【问题讨论】:

  • 如果你使用 curses 来做到这一点,我本来希望它可以工作。
  • 似乎有一个错字:#ifdef TIOCFSIZE 而不是#ifdef TIOCGSIZE。我对么?这有什么改变吗?
  • 对不起,这是我在这里输入的错误,真正的代码是 TIOCGSIZE。谢谢你告诉我。
  • @trojanfoe 是的。当我在 Linux 中使用终端运行文件时,它确实有效。当我在 Windows 上使用 PuTTY 运行时,我只是无法工作。

标签: c linux ioctl


【解决方案1】:

这个问题与 PuTTY 本身无关,而与一般的 SSH 客户端和伪终端有关。

为避免此问题,请将 PuTTY 配置为使用伪终端。 (在 TTY 面板中,有一个 “不要分配伪终端” 复选框。确保它没有被选中。)

对于ssh,您需要使用-t 选项告诉ssh 使用伪终端。

这是一个简单的示例程序,您可以在 Linux 中使用它来获取终端大小。它不需要诅咒:

#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>

static int get_size(const int fd, int *const rows, int *const cols)
{
    struct winsize sz;
    int            result;

    do {
        result = ioctl(fd, TIOCGWINSZ, &sz);
    } while (result == -1 && errno == EINTR);
    if (result == -1)
        return errno;

    if (rows)
        *rows = sz.ws_row;

    if (cols)
        *cols = sz.ws_col;

    return 0;
}

int main(void)
{
    int rows, cols;

    if (!get_size(STDIN_FILENO,  &rows, &cols) ||
        !get_size(STDOUT_FILENO, &rows, &cols) ||
        !get_size(STDERR_FILENO, &rows, &cols))
        printf("%d rows, %d columns\n", rows, cols);
    else
        fprintf(stderr, "Terminal size is unknown.\n");
    return 0;
}

使用TIOCGWINSZTTY ioctl获取实际信息。

伪终端大小实际上是由内核维护的。如果没有伪终端,只有标准流,没有行和列;在这种情况下,它只是一个流。特别是,即使tput linestput cols 也会失败。

如果没有伪终端,许多交互式命令行程序将拒绝工作。例如,top 将报告类似 "TERM 环境变量未设置""top: failed tty get" 之类的内容。其他人会工作,只是不是交互的;它们只会输出一次,但就好像终端无限高无限宽一样。

总之,您的应用程序应该识别它是在伪终端(已知终端大小,可能支持诅咒等)中运行,还是在流模式(通过 SSH 或 PuTTY,故意不使用伪终端 - 或者可能只是因为输入和输出都指向/来自文件或类似文件)。

【讨论】:

  • 嗨,我已经设法解决了这个问题。问题实际上来自我没有正确设置的 PuTTY。编码没有问题。感谢所有的指导和帮助。真的很感激!!
猜你喜欢
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多