Как узнать ширину окна терминала? - PullRequest
3 голосов
/ 16 декабря 2011

Я работаю над встроенной системой, используя C и linux.Пользователь может подключиться к устройству через SSH или консольный последовательный кабель.Он может сделать это через PuTTY или Tera Term.Мой вопрос, после того, как он подключен, как я могу узнать ширину его окна?Я пробовал разные подходы, они работают, если я симулирую свою систему на компьютере с Linux, но ни один из них не работает на устройстве:

  1. ioctl()

    struct winsize ws;
    ioctl(..., TIOCGWINSZ, &ws); 
    

    Этот метод работает на ПК, но на устройстве он всегда возвращает 0.

  2. tgetnum()

    setupterm((char *)0, 1, (int *)0);
    CGR_INT columns = tgetnum("co");
    

    Этот метод работает на ПК, но всегда возвращает80x24 на устройстве.

  3. getmaxyx()

    CGR_INT xdim;
    CGR_INT ydim;
    initscr();
    refresh();
    getmaxyx(stdscr, ydim, xdim);
    

    Этот метод работает на ПК, но всегда возвращает 0 на устройстве

Ответы [ 3 ]

3 голосов
/ 16 декабря 2011

Я использую этот код для печати набора знаков равенства в качестве делителя. Работает на большинстве ящиков / терминов, которые я пробовал. Не уверен, о каких устройствах ты говоришь. Я думаю, стоит попробовать; -)

#include <termios.h>
#include <sys/ioctl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
   struct winsize ws;
   ioctl(0, TIOCGWINSZ, &ws);

   int i=0;
   for(;i<10*ws.ws_col;++i) printf("=");
   printf("\n");
   return 0;
}
2 голосов
/ 16 декабря 2011

TIOCGWINSZ это путь. Ваше устройство должно объявить его размер, иначе это просто не может работать. Возьмите xterm в качестве примера:

device —— ttyS driver —— ttyS0 devnode —— screen/minicom
xterm —— pty devnode —— pty driver —— pts devnode —— bash

xterm делает ioctl (TIOCSWINSZ) в первый раз, когда он вызывается, чтобы tty драйвер узнал размер окна. bash и программы, созданные из него, могут запросить его. Если вы измените размер окна xterm, он сообщит драйверу tty новый размер, и xterm также отправит SIGWINCH своему дочернему процессу (в данном случае bash), чтобы уведомить его об изменении размера.

Ничего этого не происходит с устройствами (такими как ваше), которые не имеют ни малейшего представления, к чему они подключены. Драйвер tty также не знает, что с ним связано. (И обычно это не важно.) Xterm может сообщить драйверу размер, потому что он может выдавать ioctl, но ioctl не передаются, например, через последовательный порт. Теоретически для этого потребуется специализированный драйвер ядра, который знает, как сообщать об изменениях размера с вашим конкретным устройством (возможно, протокол поверх последовательного интерфейса, так что не требуется перезапись основного компонента).

Обратите внимание, что подключенное устройство может даже не иметь понятия фиксированной области, например можно считать, что принтер имеет практически бесконечное число строк.

ncurses просто принимает 80x24, если видит 0x0, потому что программист определил его таким образом. Этот размер может быть неправильным, и на практике это обычно не так, потому что люди могут изменять размеры своих окон (даже если они не могут, например, на tty1, они все равно могут использовать такие вещи, как screen (1) и уменьшать размер до размера, меньшего 80x24 ).

0 голосов
/ 13 марта 2012

Последовательная линия не может согласовать размер терминала.Запустив настоящий xterm et.al.через пару устройств TTY / PTY для передачи этой информации используется пара TIOCSWINSZ / TIOCGWINSZ ioctl().

Традиционно эта информация хранилась в termcap или terminfo о реальном физическом элементе.- терминалы со стеклянным покрытием и люминофором, такие как DEC VT220.Это статическая база данных с фиксированными значениями, известными заранее, которая была верна в то время, когда «терминал» буквально был этим фиксированным компонентом аппаратного обеспечения, но не очень хорошо работает в наше время, когда терминалы являются просто частью программы.который обращается к кадровому буферу или тому подобному.

Я бы посоветовал лучший способ попробовать TIOCGWINSZ, если это не удастся, использовать terminfo tgetnum("co"), а если это не удастся, просто предположить 80x24.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...