/*
Fichier modepage.c
Auteur Bernard Chardonneau
Logiciel libre, droits d'utilisation précisés en français
dans le fichier : licence.fr
Traductions des droits d'utilisation dans les fichiers :
licence.de , licence.en , licence.es , licence.it
licence.nl , licence.pt , licence.eo , licence.eo-utf
Bibliothèque de fonctions permettant de gérer l'affichage en mode page
Certaines de ces fonctions sont des macros de modepage.h
On peut remarquer que les fonctions de déplacement dans le texte
et d'affichage d'une page ne manipulent que des indicateurs
de position dans le texte.
La fonction affligne reste dans le fichier source principal de
chaque application, ce qui permet d'avoir un affichage adapté
aux données à traiter.
*/
#define modepage // pour la déclaration de variables globales à l'application
#include <stdio.h>
#include "modepage.h"
#include "carspe.h"
/* réaffiche la page d'écran courante en tenant
compte du changement de taille de la fenètre */
void affpage ()
{
int i, j;
// récupérer la taille de la fenêtre (qui peut avoir changé)
lig_col ();
// se positionner en haut d'écran et l'effacer
debpage ();
effpage ();
// initialisation
i = 1;
j = lignecour - lignecran + 1;
// réafficher toutes les lignes de la page
while (i++ < lignepage && j < nb_lignes)
{
affligne (j++);
putchar ('\n');
}
// remonter à la ligne sur laquelle on était
while (--i > lignecran)
montecurs ();
}
/* remonte de n lignes (max) dans le texte affiché */
void monte (int n)
{
// limiter le déplacement pour ne pas sortir du texte
if (n > lignecour)
n = lignecour;
// tant qu'on n'est pas en haut de page et déplacement non terminé
while (n > 0 && lignecran > 1)
{
// remonter d'une ligne
montecurs ();
// et mettre à jour les variables
lignecran --;
lignecour --;
n--;
}
// si déplacement de plus d'une page
if (n > lignepage)
{
// on n'affichera pas les lignes intermédiaires
lignecour = lignecour + lignepage - n;
n = lignepage;
}
// tant que déplacement non terminé
while (n-- > 0)
{
// descendre le texte affiché d'une ligne
insligne ();
// et afficher la ligne à rajouter en haut d'écran
affligne (--lignecour);
putchar ('\r');
}
}
/* descend de n lignes (max) dans le texte affiché */
void descend (int n)
{
// limiter le déplacement pour ne pas sortir du texte
if (n > nb_lignes - lignecour - 1)
n = nb_lignes - lignecour - 1;
// tant qu'on n'est pas en bas de page et déplacement non terminé
while (n > 0 && lignecran < lignepage - 1)
{
// descendre d'une ligne
putchar ('\n');
// et mettre à jour les variables
lignecran ++;
lignecour ++;
n--;
}
// si déplacement de plus d'une page
if (n > lignepage)
{
// on n'affichera pas les lignes intermédiaires
lignecour = lignecour + n - lignepage;
n = lignepage;
}
// tant que déplacement non terminé
while (n-- > 0)
{
// afficher la ligne à rajouter en bas de page
// et remonter tout le texte d'une ligne
putchar ('\n');
affligne (++lignecour);
putchar ('\n');
// remonter sur la ligne insérée
montecurs ();
}
}
/* récupère le nombre de lignes et de colonnes d'affichage */
void lig_col ()
{
char commande [28];
FILE *fcaract;
// récupérer les caractéristiques du terminal
sprintf (commande, "stty size > /tmp/fich%X", getpid ());
system (commande);
// ouvrir le fichier créé par la commande stty
fcaract = fopen (commande + 12, "r");
// si ouverture réussie
if (fcaract)
{
// lire le nombre de lignes et de colonnes
fscanf (fcaract, "%d%d", &lignepage, &colonpage);
// fermer et détruire le fichier
fclose (fcaract);
unlink (commande + 12);
}
// cas très particulier : problème de droits d'accès à /tmp
else
{
// message d'avertissement
// "Droit d'accès insuffisants à /tmp, le fonctionnement peut être dégradé"
affiche_msg ("PB_ACCES_TMP");
sleep (3);
// on prend les valeurs par défaut
lignepage = defaut_ligne;
colonpage = defaut_colon;
}
// corriger avec des valeurs par défaut si l'on a récupéré des 0
// (par exemple depuis une fenêtre telnet)
if (! lignepage)
lignepage = defaut_ligne;
if (! colonpage)
colonpage = defaut_colon;
}
/* lit un caractère au clavier et le traite si caractère spécial */
int leccar ()
{
int car, carsuiv;
// attendre qu'un caractère soit tapé
do
car = getchar ();
while (car == -1);
// si caractère ordinaire, on le retourne
if (car != ESC)
return (car);
// lire le caractère qui suit le ESC
car = getchar ();
// traitement du caractère ESC et des séquences d'échappement
if (car == '[' || car == 'O')
{
car = getchar ();
if ('1' <= car && car <= '9')
{
// séquence ESC[n~ où n est une valeur numérique
carsuiv = getchar ();
car = car & 0x0F;
// récupérer la valeur numérique
while ('0' <= carsuiv && carsuiv <= '9')
{
car = (car * 10) + (carsuiv & 0x0F);
carsuiv = getchar ();
}
if (carsuiv == '~')
return (CARSPE | car);
else
// "Caractère spécial non traité"
affiche_msg ("CARSPE_INVALIDE");
}
else if (car == '[')
{
// séquence ESC[[n (certaines touches de fonction)
car = getchar ();
return (CARSPE + 0x0F + car);
}
else
// séquence ESC[lettre
return (CARSPE | car);
}
// caractère ESC classique
else
{
// si après le ESC on a eu un autre caractère de suite
// le remettre dans le buffer
if (car != -1)
ungetc (car, stdin);
// retour du caractère ESCape
return (ESC);
}
}
/* exécute une commande, puis repasse en mode page */
void execom (char *outil, char *fichier)
{
char commande [130]; // chaine contenant la commande à exécuter
unsigned long heuredeb; // pour détecter problème exécution commandes
// effacer le bas de page
effpage ();
fflush (stdout);
// fabriquer la commande à éxécuter
sprintf (commande, "%s %s", outil, fichier);
// récupérer l'heure courante
heuredeb = time (0);
// lancer la commande
system (commande);
// si la commande a rendu la main trop rapidement
// et que c'est une commande interactive
if ((time (0) <= heuredeb + 1) && (strcmp (outil, "lpr") != 0)
&& (strcmp (outil, "recuppj") != 0))
{
// attendre lecture du message d'erreur
sleep (2);
}
// reconfigurer la voie que commande a remit en mode normal en se terminant
mode_raw ();
}