Page suivante Page précédente Table des matières

6. Ecriture des valeurs des capacités dans un terminal

Nous venons d'étudier les fonctions qui permettent de lire les informations contenues dans une base de données, mais pour agir sur l'apparence du terminal nous nous doutons bien qu'il ne suffit pas de recevoir des données mais aussi d'en transmettre.En effet, s'il s'agit d'une action simple que doit réaliser le terminal, nous pouvons penser qu'il suffit de lui transmettre un code qui déclenche l'action, si l'action est plus complexe il faudra certainement que nous puissions transmettre, en plus des paramètres.

Nous allons étudier les deux cas à travers l'examen détaillé de deux nouvelles capacités, clear qui efface l'écran et replace le curseur en haut et à gauche de l'écran, cup qui place le curseur à un emplacement déterminé de l'écran. Enregistrons tout d'abord les chaînes de caractères associées à ces deux capacités.

6.1 Lecture des chaînes de caractères associées aux capacités clear et cup

L'utilisation de la fonction tigetstr avec la capacité clear donne les messages suivants :

[pierre@localhost terminfo]$ ./testcapc  xterm  clear
Traitement correct
La capacité clear est supportée par le terminal xterm
Valeur de clear : \E[H\E[2J
[pierre@localhost terminfo]$ ./testcapc  linux  clear
Traitement correct
La capacité clear est supportée par le terminal linux
Valeur de clear : \E[H\E[J

6.1.1 Analyse de la valeur affectée à la capacité clear

Un petit commentaire s'impose sur la signification de cette chaîne de caractères. J'ai opté pour un affichage semblable à celui que l'on trouve dans les fichiers sources de terminfo et dans l'affichage produit par l'utilitaire infocmp.

Le groupe de caractères \E correspond effectivement au démarrage d'une séquence d'échappement.Si vous faites afficher le code ASCII, vous obtiendrez la valeur 27, c'est à dire ESCAPE.

Le second caractère '[' a pour code ASCII 91. Ce caractère indique l'attente de codes de commandes de contrôle du terminal (CSI).

Le caractère 'H' qui suit est le code de la commande qui déplace le curseur à une position déterminée. Par défaut, c'est à dire en l'absence de paramètres définissant la position en Ligne,Colonne, le curseur est placé dans le coin supérieur gauche de l'écran du terminal (position 0,0).Vous pouvez aisément tester cela en utilisant la fonction printf comme le conseille Cédric dans sa documentation sur ce sujet.

Nous comprenons dès lors que la deuxième chaîne \E[ ouvre une seconde séquence et cette fois le code 'J' est le code qui efface l'écran. Vous noterez que le terminal linux et xterm n'ont pas le même attribut : le terminal linux est sans attribut, xterm utilise la paramètre 2. Rien d'étonnant puisque cela revient au même ! En effet selon la norme ECMA-48/ISO dont le gestionnaire de terminaux Linux, implémente un sous-ensemble important, par défaut cette séquence de codes efface tout l'écran, lorsque l'on place 1 comme attribut l'écran est effacé de son origine jusqu'à la position du curseur, lorqu'il vaut 2, tout l'écran est effacé.

6.1.2 Composition de séquences d'échappement

Ainsi, la capacité clear de la base de données terminfo se présente comme une composition de séquence de codes d'échappement : une première qui envoie une commande de positionnement du curseur, \E[H ; une seconde qui efface l'écran, \EJ ou \E2J.

Vous pouvez vérifier cela en envoyant séparément chacune des commandes au Terminal à l'aide de la fonction printf, de cette manière :

printf("\033[H");
car=getchar();
printf("\033[J");

6.1.3 Analyse d'une valeur de capacité plus complexe : cup

La lecture de la valeur associée à la capacité cup dans la base de données terminfo des terminaux linux et xterm, nous donne ce résultat :

[pierre@localhost terminfo]$ ./testcapc  linux  cup
Traitement correct
La capacité cup est supportée par le terminal linux
Valeur de cup : \E[%i%p1%d;%p2%dH
[pierre@localhost terminfo]$ ./testcapc  xterm  cup
Traitement correct
La capacité cup est supportée par le terminal xterm
Valeur de cup : \E[%i%p1%d;%p2%dH

Cette fois, les bases de données des deux terminaux contiennent la même chaîne de caractères.Si nous isolons le début et la fin de la chaîne de caractères, nous retrouvons bien la séquence \E[...H que nous avions analysé dans le paragraphe précédent et qui correspond à une commande de positionnement du curseur.Entre les deux nous trouvons une succession de caractères séparés par un point-virgule (;), ce point virgule sépare les deux attributs attendus par le terminal, la position dans la ligne, la position en colonne.

Voici donc la signification de chacun de ces signes :

%i indique que les arguments transmis doivent être incrémentés de 1. Cette 
   incrémentation est rendue nécessaire parce que l'origine de l'écran est 0,0.
   Mais cerains terminaux ont une origine 1,1. Donc pour les terminaux à 
   origine 0,0, on incrémente de 1 et on applique la même procédure.
%p1 et %p2 placent respectivement le premier argument et les second argument
   sur la pile.
%d Affiche le sommet de la pile sous forme décimal.

Nous constatons donc que cette chaîne de caractères ne correspond pas à la chaîne de caractères à envoyer au terminal. Puisqu'elle décrit un processus à mettre en oeuvre. Comment allons-nous créer cette chaîne de caractères correspondant à la séquence d'échappement à envoyer au terminal ?

6.2 Chaîne de caractères à envoyer au terminal pour la capacité cup

Deux arguments sont attendus pour cette capacité :

6.2.1 la fonction tparm

Le prototype de cette fonction est le suivant :

char * tparm(const char * str,...);
Cette fonction reçoit comme premier paramètre une chaîne de caractères qui est le résultat de la fonction de lecture d'une capacité tigetstr, les arguments suivants sont de type numérique et doivent être au nombre et dans l'ordre des arguments attendus par la capacité utilisée.

6.2.2 Exemple d'utilisation de tparm avec la capacité cup

Une fois de plus, je me permets de reproduire un programme bien trivial.

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

void affiche(char * m)
{
  int i;

  for(i=0; i<strlen(m);i++)
    if (m[i]==27)
      printf("\\E");
    else 
      printf("%c",m[i]);
}


int main(int argc, char * argv[])
{
  int r,rb;
  char * resu;
  char * esc_seq;
  int erreur;
  char capa[]="cup";
  
  if (argc<2){
    printf("Entrez le nom d'un terminal\n");
    exit(1);
  }
  else
    r=setupterm(argv[1], fileno(stdout),&erreur);//Terminal de la ligne de commande
  if (r==OK){
    printf("Traitement correct\n");
    resu=tigetstr(capa);
    rb=(int)resu;
    switch(rb){
    case -1 :
      printf("%s n'est pas une capacité de type chaîne\n",capa);
      break;
    case 0 :
      printf("La capacité %s n'est pas supportée par le terminal %s\n",capa,argv[1]);
      break;

    /*Si tout s'est bien passé on applique le traitement par défaut suivant.
      La chaîne resu contient alors la valeur dans terminfo de la capacité
      cup pour le terminal transmis par la ligne de commande.
      On fait afficher cette chaîne et on construit à l'aide de la fonction
      tparm la séquence d'échappement à envoyer au terminal enregistrée dans
      esc_seq*/

    default :
      printf("Valeur de la capacité cup lue par tigetstr : ");
      affiche(resu);
      printf("\n");
      esc_seq=tparm(resu,15,30);
      printf("Chaîne à envoyer : ");
      affiche(esc_seq);
      printf(" au terminal %s\n",argv[1]);
      break;
    }
  }
  else
    switch(erreur){
    case 0 : 
      printf("Le terminal %s est inconnu.\n",argv[1]);
      break;
    case -1 :
      printf("Aucune base de données pour le terminal %s.\n",argv[1]);
      break;
    }
  return 0;
}

Voici le résultat affiché par ce programme :

[pierre@localhost terminfo]$ ./testcha linux
Traitement correct
Valeur de la capacité cup lue par tigetstr : \E[%i%p1%d;%p2%dH
Chaîne à envoyer : \E[16;31H au terminal linux
Trois constatations s'imposent à la lecture de cet affichage :
  1. La fonction tigetstr a bien ramené la chaîne de caractères contenue dans la base de données terminfo pour le terminal linux : \E[%i%p1%d;%p2%dH
  2. La fonction tparm a bien construit une séquence de codes d'échappement : \E[16;31H
  3. La fonction tparm est un interpréteur des capacités définies dansterminfo. On remarque en particulier que la fonction tparm a été invoquée avec comme arguments 15,30. Comme prévu par la valeur %i de la capacité cup ces deux nombres ont bien été incrémentés de 1.

6.3 Fonction d'affichage printf ou putp ?

Une fois obtenue la séquence de codes d'échappement à l'aide de la fonction tparm, reste à expédier le tout au terminal. Vous pouvez bien entendu envoyer la séquence de codes à l'aide de la fonction printf. Nous pouvons cependant préférer l'utilisation de la fonction putp qui appartient à la bibliothèque que nous avons utilisée. Le prototype de cette fonction est le suivant :

int putp(const char * str);
De sorte que dans l'exemple précédent nous aurions pu invoquer directement la fonction putp ainsi :
putp(tparm(resu,15,30));
pour obtenir le déplacement du curseur en ligne 15, colonne 30.
Page suivante Page précédente Table des matières