Comment connaît moins la résolution du terminal?

13

Chaque fois que quelqu'un définit une taille différente pour une console virtuelle, lessreconnaît la résolution de la fenêtre (je suppose que ...); selon cela, il change le nombre de lignes de texte qu'il doit visualiser. Comment ce paramètre est-il calculé?

Giuseppe Crinò
la source
Uhm ... ok, mais où puis-je trouver cette procédure qui est exécutée?
Giuseppe Crinò

Réponses:

22

Si vous cherchez un moyen de vérifier à partir d'un script, vous pouvez effectuer l'une des opérations suivantes:

  • Courez tput colset tput lines, comme le suggère la manœuvre
  • vérifier les valeurs de $ LINES et $ COLUMNS

Mais si vous voulez les détails, c'est parti:

Pour les terminaux virtuels (xterm, et al), il existe un ioctl()appel système qui vous indiquera la taille de la fenêtre. Si c'est le cas, lessutilise cet appel. De plus, lorsque vous modifiez la taille de la fenêtre, tout ce qui s'exécute dans cette fenêtre reçoit un SIGWINCHsignal qui indique lessqu'il doit vérifier la nouvelle taille de la fenêtre. Par exemple, j'ai commencé une lessexécution (en tant qu'ID de processus 16663) , je me suis connecté avec straceet j'ai redimensionné la fenêtre. Voici ce que j'ai vu:

$ strace -p 16663
Process 16663 attached - interrupt to quit
read(3, 0xbfb1f10f, 1)                  = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
rt_sigaction(SIGWINCH, {0x805cf10, [WINCH], SA_RESTART}, {0x805cf10, [WINCH], SA_RESTART}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0

C'est aussi ce qu'ils font tput colset ce qu'ils tput linesfont en coulisses, s'ils le peuvent. Pour plus d'informations sur cette méthode, consultez man tty-ioctlet recherchez TIOCGWINSZ.

Pour d'autres terminaux tels que ceux connectés aux ports série, il n'y a aucun moyen d'obtenir directement ces informations. Dans ce cas, lesscommence à rechercher des indices dans les variables d'environnement.

  • LINESet COLUMNSsera souvent réglé aux dimensions du terminal. En fait, si bashou zshpeut trouver les dimensions du terminal, il définira automatiquement ces variables lui-même, pour permettre aux programmes pas si intelligents de voir la taille du terminal. Cependant, la plupart des autres shells, y compris dashet tcsh, ne définissent pas ces variables.
  • TERMest généralement défini sur le type de terminal, auquel cas la base de données terminfo peut contenir la taille attendue du terminal. Si tput rowsvous ne pouvez pas utiliser l'IOCTL (par exemple, si vous êtes connecté sur un port série), il reviendra aux valeurs enregistrées ici. Pour un terminal dont la taille peut changer, ce n'est qu'une supposition et il est probable que ce soit faux.

Pour plus d'informations, reportez-vous man tputà la commande de contrôle du terminal et man terminfoà la liste des choses que vous pouvez dire au terminal de faire.

Jander
la source
La base de données terminfo ne fait pas ce qui est indiqué ici. La réponse de @ warl0ck, qui contient moins d'informations, est plus précise.
Thomas Dickey
@ThomasDickey Vous avez raison; il ne contient que des valeurs attendues. Correction de ma réponse; Merci.
Jander
7

Si vous jetez un œil au code source, vous connaîtrez les lessappels ioctl()pour récupérer la taille de la fenêtre sous Linux.

#ifdef TIOCGWINSZ
    {
        struct winsize w;
        if (ioctl(2, TIOCGWINSZ, &w) == 0)
        {
            if (w.ws_row > 0)
                sys_height = w.ws_row;
            if (w.ws_col > 0)
                sys_width = w.ws_col;
        }
    }
#else
#ifdef WIOCGETD
    {
        struct uwdata w;
        if (ioctl(2, WIOCGETD, &w) == 0)
        {
            if (w.uw_height > 0)
                sys_height = w.uw_height / w.uw_vs;
            if (w.uw_width > 0)
                sys_width = w.uw_width / w.uw_hs;
        }
    }
#endif
Marguerite
la source