/*
    Fichier vmaildir.c
    Auteur Bernard Chardonneau

    Logiciel libre, droits d'utilisation précisés en français
    dans le fichier : licence-fr.txt

    Traductions des droits d'utilisation dans les fichiers :
    licence-de.txt , licence-en.txt , licence-es.txt ,
    licence-it.txt , licence-nl.txt , licence-pt.txt ,
    licence-eo.txt , licence-eo-utf.txt

    Droits d'utilisation également sur la page web :
    http://libremail.tuxfamily.org/voir.php?page=droits


    Ce programme affiche l'arborescence du répertoire passé
    en paramètre, répertoire courant par défaut.

    Il est recommandé de lancer cet outils depuis (ou en
    passant en paramètre) le répertoire racine des fichiers
    mails tel qu'il est défini dans le fichier de configuration
    xxxx.cfg

    Il est possible de sélectionner l'un des répertoires
    affichés pour consulter les fichiers mails qu'il contient
    et éventuellement répondre, transférer, ou détruire le message.

    Pour ces opérations, cet outil appelle vmailsj
*/


#define appli   // pour la déclaration de variables globales à l'application

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "messages.h"
#include "modepage.h"
#include "carspe.h"
#include "szchemin.h"


/*
   Par défaut ce programme détecte les noms
   de fichiers mails issus de libremail.

   Décommenter la ligne qui suit pour accepter
   aussi ceux issus de microsoft internet mail.
*/

// #define compat_msoft

/*
   Les noms du premier mail envoyé et du premier mail
   reçu avec microsoft internet mail sont respectivement
   EAAAAAAA et RAAAAAAA.N (RAAAAAAA.R après lecture).

   Ensuite, les mails sont numérotés en changeant d'abord
   les caractères de droites (36 caractères possibles).

   On peut ainsi numéroter 1296 mails sur 2 caractères,
   46656 mails sur 3 caractères, plus de 1,6 millions
   de mails sur 4 caractères, etc...

   La constante nb_a permet de préciser le nombre minimal
   de A que l'on veut avoir coté gauche pour qu'un nom de
   fichier soit considéré comme celui d'un fichier mail.
*/

#ifdef  compat_msoft
#define nb_a              3  // de 0 à 7
#endif


#define max_mdir_ini    100  // nombre max initial de répertoires de mails
#define mdir_accept   50000  // nombre max de répertoires qu'on accepte
#define lg_nomdir        32  // longueur max d'un nom de répertoire


/* type de données */
typedef char nomdir [lg_nomdir];


/* prototypes */
void exploredir (char *repertoire);
int  ajoutdirpossible ();
int  fichier_mail (char *nomfic);
nomdir *maj_espace (nomdir * oldliste, int * taille);
void trinoms (nomdir *liste, int fin);
void navigation ();
void detectemail (int numrep);
void gen_format_cpt ();
void affligne (int numligne);


/* variables globales au source
   (pour éviter des tonnes de passages de paramètres) */


char **maildir;       // liste des répertoires de mails
int  *nb_mails;       // nombre de mails pour chaque répertoire
int  *nb_nonlus;      // nombre de mails non lus pour chaque répertoire
int  max_maildir;     // nombre max d'éléments dans maildir, nb_mails, nb_nonlus
int  numsortie = 0;   // position du répertoire des mails à envoyer
int  numpoub   = 0;   // position du répertoire des mails détruits
int  deborde_mem = 0; // mémorise un débordement mémoire
int  opt_inv;         // option d'inversion de l'ordre d'affichage pour vmailsj
int  opt_cn;          // options d'affichage du nombre de mails non lus et total
char formatcpt [10];  // format d'affichage du nombre de mails non lus et total
int  coldebnomrep;    // colonne du début d'afffichage d'un nom de répertoire

// ces deux variables permettent d'éviter des appels répétitifs de ficdir ()
char dir_sortie [szmax_ficdir]; // sous répertoire des mails à envoyer
char dir_poub   [szmax_ficdir]; // sous répertoire des mails avant destruction


/* programme principal */

int main (int nbarg, char *varg[])
{
    char nomdir [szchemin];
    char *ajout;


    // récupération du nom de l'exécutable
    memcom (*varg);

    // se positionner sur le premier argument de vmaildir
    varg ++;
    nbarg --;

    // initialisations
    nb_lignes = 0;
    opt_inv   = 0;
    opt_cn    = 0;

    // récupération des options de fonctionnement éventuelles
    while (nbarg > 0 && **varg == '-' && varg [0][2] == '\0')
    {
        switch (varg [0][1])
        {
            // option inversion de l'ordre d'affichage (pour vmailsj)
            case 'i' :
            case 'r' : opt_inv = 1;
                       varg ++;
                       nbarg --;
                       break;

            // option d'affichage du nombre de mails non lus
            case 'n' : if (! opt_cn)  // prise en compte si option -c absente
                           opt_cn = 1;
                       varg ++;
                       nbarg --;
                       break;

            // option d'affichage des nombres de mails non lus et total
            case 'c' : opt_cn = 2;   // prioritaire sur l'option -n
                       varg ++;
                       nbarg --;
                       break;

            default  : // "Option %s incorrecte"
                       aff_err_arg ("ERR_OPTION", *varg);

                       // "Syntaxe : %s [-(c|n)] [-i] [répertoire]"
                       psyntaxe ("SYNT_VMAILDIR");
        }
    }

    // récupération éventuelle du nom du répertoire racine des mails
    if (nbarg == 1)
    {
        // se positionner dans ce répertoire
        if (chdir (*varg) < 0)
        {
            // "Répertoire %s inexistant"
            aff_err_arg ("REPERT_INEXISTANT", *varg);
            return (0);
        }
    }

    // récupérer et mémoriser le nom de 2 sous répertoires importants
    strcpy (dir_sortie, ficdir ("DIR_SORTIE"));
    strcpy (dir_poub, ficdir ("DIR_POUBELLE"));

    // récupérer le chemin d'accès absolu de la racine des mails
    getcwd (nomdir, szchemin);

    // déterminer le nom du répertoire d'envoi des mails
    ajout = nomdir + strlen (nomdir);
    *ajout = '/';
    strcpy (ajout + 1, dir_sortie);

    // et le mémoriser dans une variable d'environnement
    setenv ("mailenv", nomdir, 1);

    // faire de même avec le répertoire poubelle des fichiers mail
    strcpy (ajout + 1, dir_poub);
    setenv ("mailpoub", nomdir, 1);

    // fixer la taille initiale de la liste des répertoires
    max_maildir = max_mdir_ini;

    // allouer la liste des répertoires et des compteurs de mails
    // (on commence par les tableaux les moins encombrants)
    nb_mails   = malloc (max_maildir * sizeof (int));
    nb_nonlus  = malloc (max_maildir * sizeof (int));
    maildir    = malloc (max_maildir * sizeof (char *));

    // vérification allocation
    if (! maildir)
        // "Manque de place mémoire, le logiciel %s ne peut fonctionner"
        errfatale ("MANQUE_MEMOIRE", nomcom ());

    // mémoriser l'arborescence du répertoire racine des mails
    exploredir (".");

    // on génère un message en fin de liste si débordement mémoire
    if (deborde_mem || max_maildir > mdir_accept)
    {
        if (nb_lignes + 2 >= max_maildir)
            nb_lignes = nb_lignes - 2;

        maildir [nb_lignes] = "";
        nb_mails [nb_lignes++] = -1;

        // "Trop de sous répertoires, liste tronquée"
        strcpy (nomdir, message ("DEBORD_SOUS_REP"));
        maildir [nb_lignes] = nomdir;
        nb_mails [nb_lignes] = -1;
        nb_nonlus [nb_lignes++] = 1;   // pour la surbrillance
    }

    // si demande d'affichage du nombre de mails (non lus ou/et total)
    if (opt_cn)
        // préparer le format d'affichage de ces valeurs
        gen_format_cpt ();

    // vérification de l'accès à ce message avant le passage en mode raw
    message ("RACINE_MAILS");

    // afficher les répertoire et naviguer dans la liste
    navigation ();

    // pour faire plaisir à gcc qui veut une fonction main de type int
    return (0);
}



/* exploration du répertoire passé en paramètre */

void exploredir (char *repertoire)
{
    DIR *repert;
    struct dirent *entree;
    struct stat   descfic;
    char   nomfic [szchemin]; // chemin d'accès à un fichier
    nomdir *listedir;    // liste des sous répertoires trouvés
    int    nbdir_alloc;  // nombre de sous repertoires alloués
    int    nbdir;        // nombre de sous repertoires mémorisés
    int    sznomrep;     // longueur du nom de répertoire qu'on analyse
    int    i;            // simple compteur


    // si trop de répertoires déjà explorés, on sort
    if (max_maildir > mdir_accept)
        return;

    // accéder au répertoire
    repert = opendir (repertoire);

    // sortie sur erreur si l'on n'a pas pu
    if (repert == 0)
        return;

    // mémorisation longueur du nom de répertoire
    sznomrep = strlen (repertoire);

    // mémoriser le chemin d'accès au répertoire
    if (nb_lignes == 0)
    {
        // cas particulier de répertoire racine
        maildir [nb_lignes] = ".";
    }
    // sinon si on peut mémoriser d'autres éléments
    else if (ajoutdirpossible ())
    {
        // cas général : on ne mémorise pas le ./ des noms de sous répertoires
        maildir [nb_lignes] = (char *) malloc (strlen (repertoire) - 1);

        if (maildir [nb_lignes])
            strcpy (maildir [nb_lignes], repertoire + 2);
        else
            // une erreur mémoire à ce niveau n'est pas facilement récupérable
            // "Manque de place mémoire, le logiciel %s ne peut fonctionner"
            errfatale ("MANQUE_MEMOIRE", nomcom ());

        // mémoriser la position des répertoires sortie et poubelle
        if (strcmp (repertoire + 2, dir_sortie) == 0)
            numsortie = nb_lignes;
        else if (strcmp (repertoire + 2, dir_poub) == 0)
            numpoub = nb_lignes;
    }
    // sinon mémoriser un débordement mémoire
    else
    {
        deborde_mem = 1;
        return;
    }

    // initialisation : pas encore de mail trouvé dans ce répertoire
    nb_mails  [nb_lignes] = 0;
    nb_nonlus [nb_lignes] = 0;

    // récupérer le nombre de liens du répertoire
    stat (repertoire, &descfic);

    // et allouer le bon nombre d'entrées dans la liste des
    // sous répertoires avec une sécurité de 2 (correspondant
    // à . et ..) pour éviter erreur de segmentation
    nbdir_alloc = descfic.st_nlink;
    listedir = (nomdir *) calloc (nbdir_alloc, lg_nomdir);

    if (! listedir)
    {
        deborde_mem = 1;
        return;
    }

    // aucun sous répertoire encore mémorisé
    nbdir = 0;

    // lire un nom de fichier ou de répertoire
    entree = readdir (repert);

    // tant qu'il y a des noms de fichier ou de répertoires à lire
    while (entree)
    {
        // si le nom ne commence pas par un .
        // (évitera de boucler sur les répertoires . et ..)
        // et qu'il n'est pas trop long
        if (entree->d_name [0] != '.' &&
           (sznomrep + strlen (entree->d_name) < szchemin))
        {
            // récupérer les caractéristiques du fichier courant
            sprintf (nomfic, "%s/%s", repertoire, entree->d_name);
            stat (nomfic, &descfic);

            // on ne mémorisera que les noms des répertoires
            if ((descfic.st_mode & S_IFMT) == S_IFDIR)
            {
                // tronquer les noms à 32 caractères
                if (strlen (entree->d_name) >= lg_nomdir)
                    entree->d_name [lg_nomdir - 1] = '\0';

                // précaution pour éviter un débordement de tableau
                if (nbdir >= nbdir_alloc)
                    listedir = maj_espace (listedir, &nbdir_alloc);

                // mémoriser le nom du sous répertoire
                strcpy (listedir [nbdir ++], entree->d_name);
            }
            // et la présence de fichiers mail déjà lus ou en attente de lecture
            else if (fichier_mail (entree->d_name))
            {
                nb_mails [nb_lignes] ++;

                // test si mail en attente de lecture
                if (entree->d_name [8] == '.' &&
                                      tolower (entree->d_name [9]) == 'n')
                {
                    nb_nonlus [nb_lignes] ++;
                }
            }
        }

        // et lire le nom du fichier suivant
        entree = readdir (repert);
    }

    // libérer le répertoire
    closedir (repert);

    // mettre à jour le compteur
    nb_lignes ++;

    // tri alphabétique des noms de sous répertoires
    trinoms (listedir, nbdir - 1);

    // exploration des sous répertoires trouvés
    for (i = 0; i < nbdir; i++)
    {
        sprintf (nomfic, "%s/%s", repertoire, listedir [i]);
        exploredir (nomfic);
    }

    // libération de l'espace mémoire du tableau listedir
    free (listedir);
}



/* vérifie si l'on peut insérer un élément de plus dans le tableau
   maildir, et redimmensionne ce tableau si nécessaire */


int ajoutdirpossible ()
{
    char **nouvmaildir;  // adresse du tableau maildir de remplacement
    int  *nouv_nbmails;  // adresse du tableau nb_mails de remplacement
    int  *nouv_nbnonlus; // adresse du tableau nb_nonlus de remplacement
    int  nouvtaille;     // et sa taille
    int  element;        // compteur : numéro d'élément dans les tableaux


    // cas simple : il reste au moins une place de libre dans le tableau
    if (nb_lignes + 1 < max_maildir)
        return (1);

    // calculer la nouvelle taille des tableaux
    // l'augmentation est alternativement de 50 % ou 33 % de manière
    // à ce que la taille double après 2 réallocations
    if (max_maildir % 3)
        nouvtaille = max_maildir + (max_maildir / 2);
    else
        nouvtaille = max_maildir + (max_maildir / 3);

    // allocation mémoire des nouveaux tableaux
    nouv_nbmails  = malloc (nouvtaille * sizeof (int));
    nouv_nbnonlus = malloc (nouvtaille * sizeof (int));
    nouvmaildir   = malloc (nouvtaille * sizeof (char *));

    // vérification allocation
    if (nouvmaildir)
    {
        // copie du contenu des ancientableau dans le nouveaux
        for (element = 0; element < max_maildir; element ++)
        {
            nouvmaildir   [element] = maildir   [element];
            nouv_nbmails  [element] = nb_mails  [element];
            nouv_nbnonlus [element] = nb_nonlus [element];
        }

        // destruction des anciens tableaux
        free (maildir);
        free (nb_mails);
        free (nb_nonlus);

        // que l'on remplace par les nouveaux
        maildir   = nouvmaildir;
        nb_mails  = nouv_nbmails;
        nb_nonlus = nouv_nbnonlus;
        max_maildir = nouvtaille;
    }

    // retourne le résultat de la possibilité d'insertion d'éléments
    return (nb_lignes + 1 < max_maildir);
}



/* détermine si un nom de fichier passé en paramètre
   correspond à un nom de fichier mail */


int fichier_mail (char *nomfic)
{
    char car; // pour éviter de trop manipuler des tableaux
    int  i;   // compteur


    // test du premier caractère du nom de fichier
    car = tolower (nomfic [0]);

    // si le nom de fichier commence par l'une des bonnes lettres possibles
    if (car == 'r' || car == 'e'
#ifdef compat_msoft
                   || car == 's'
#endif
       )
        // on va examiner les caractères qui suivent
        i = 1;
    else
        // sinon ce n'est pas un fichier mail
        return 0;

    // test des caractères qui suivent
    while (i < 8)
    {
#ifdef compat_msoft
        car = tolower (nomfic [i]);
#else
        car = nomfic [i];
#endif

        // si le ième caractère est bon
        if (('0' <= car && car <= '9')
#ifdef compat_msoft
         || (car == 'a')
         || (i >= nb_a && 'b' <= car && car <= 'z')
#endif
           )
            // examiner le caractère suivant
            i++;
        else
            // sinon ce n'est pas un fichier mail
            return 0;
    }

    // le si nom de fichier fait 8 caractères
    if (nomfic [8] == '\0')
        // il s'agit d'un nom de fichier mail
        return 1;

    // sinon si le 9ème caractère est un . et qu'il y a 10 caractères en tout
    else if (nomfic [8] == '.' && nomfic [10] == '\0')
    {
        // examiner le dernier caractère
        car = tolower (nomfic [9]);

        if (car == 'n')
            return 1;    // fichier mail reçu et non encore lu

#ifdef compat_msoft
        else if (car == 'r')
            return 1;   // fichier micro$oft internet mail déjà lu
#endif
        else
            return 0;   // ce n'est pas un fichier mail
    }
    else
        // sinon ce n'est pas un fichier mail
        return 0;
}



/* augmentation de la taille d'une liste de sous répertoires */

nomdir * maj_espace (nomdir * oldliste, int * taille)
{
    nomdir *newliste;    // nouveau tableau


    // allocation d'un tableau plus grand
    newliste = (nomdir *) calloc (*taille + 4, lg_nomdir);

    // controle
    if (! newliste)
        // "Manque de place mémoire, l'application ne peut fonctionner"
        errfatale ("MANQUE_MEMOIRE", NULL);

    // copie de l'ancien tableau
    memcpy (newliste, oldliste, *taille * lg_nomdir);

    // libération de la mémoire
    free (oldliste);

    // retour de la nouvelle adresse et taille du tableau
    *taille = *taille + 4;
    return (newliste);
}



/* tri alphabétique des noms de sous répertoires */

void trinoms (nomdir *liste, int fin)
{
    char tampon [lg_nomdir];  // chaine de caractères pour permutation
    int  i;   // indice dans la liste


    // initialisation
    i = 0;

    while (i < fin)
    {
        // on compare 2 éléments consécutifs
        if (strcmp (liste [i], liste [i+1]) > 0)
        {
            // interversion de 2 noms
            strcpy (tampon, liste [i]);
            strcpy (liste [i], liste [i+1]);
            strcpy (liste [i+1], tampon);

            // ce qui peut supposer de comparer un nom déplacé avec le précédent
            if (i > 0)
                i--;
            else
                i++;
        }
        else
            i++;    // on progresse dans la liste
    }
}


/* affiche la liste des sous répertoire et permet de
   la parcourir même si elle tient sur plusieurs pages */


void navigation ()
{
    int car;     // caractère tapé au clavier
    int erreurs; // nombre frappes caractères inconnus comme commandes


    // configurer la liaison clavier pour lecture directe avec timeout
    mode_raw ();

    // initialisation
    lignecran = 1;
    lignecour = 0;
    erreurs = 0;
    affpage ();

    do
    {
        // lire et traiter une touche du clavier
        car = leccar ();

        switch (car)
        {                  // déplacement dans la liste des répertoires
            case MONTE   : monte (1);
                           erreurs = 0;
                           break;

            case DESCEND : descend (1);
                           erreurs = 0;
                           break;

            case PAGEUP  : monte (lignepage + lignecran - 2);
                           erreurs = 0;
                           break;

            case PAGEDOWN: descend (2 * lignepage - lignecran - 2);
                           erreurs = 0;
                           break;

            case HOME    :
            case HOMEg   : monte (lignecour);
                           erreurs = 0;
                           break;

            case FIN     :
            case FINg    : descend (nb_lignes - lignecour - 1);
                           erreurs = 0;
                           break;

            case 0       : // aide si trop d'erreurs ou à la demande
            case F1      : effpage ();
                           // "Touches utilisables :\n"
                           // "flèches Pageup, Pagedown, Home et Fin"
                           // "pour se déplacer d'une ou plusieurs lignes"
                           // "v, l ou entrée pour Voir (Lire)"
                           // "les mails du répertoire"
                           // "n ou Inser pour en créer un Nouveau"
                           // "Control L pour réafficher la page"
                           affiche_msg ("AIDE_CHOIX_ADR-1");
                           affiche_msg ("AIDE_CHOIX_ADR-2");
                           affiche_msg ("AIDE_CHOIX_ADR-3");
                           affiche_msg ("AIDE_VMAILDIR-1");
                           affiche_msg ("AIDE_VMAILDIR-2");
                           affiche_msg ("AIDE_VMAILDIR_SJ");
                           affiche_msg ("AIDE_CHOIX_ADR-7");

                           // variante pour la touche Esc
                           if (util_systemd ())
                               // "q ou Esc (2 fois) pour Quitter ce programme"
                               affiche_msg ("AIDE_VMAIL2");
                           else
                               // "q ou Esc pour Quitter ce programme"
                               affiche_msg ("AIDE_VMAIL");

                           // "Appuyer sur une touche pour continuer"
                           affiche_msg ("ATTENTE_CLAVIER");
                           leccar ();
                           // pas de break, on réaffiche la page

            case CTRL    : affpage ();
                           erreurs = 0;
                           break;

            case 'l'     :
            case 'v'     : // ici, on regarde les descriptifs des mails
            case '\n'    : if (opt_inv)
                               execom ("vmailsj -i", maildir [lignecour]);
                           else
                               execom ("vmailsj", maildir [lignecour]);

                           // maj du mode d'affichage des répertoires
                           detectemail (lignecour);
                           detectemail (numsortie);
                           detectemail (numpoub);

                           // réafficher la page d'écran
                           affpage ();
                           erreurs = 0;
                           break;

            case INSERT  : // création d'un nouveau mail
            case 'n'     : execom ("cremail", " ");

                           // maj du mode affichage répertoire mails à envoyer
                           detectemail (numsortie);

                           // réafficher la page d'écran
                           affpage ();
                           erreurs = 0;

            case 'q'     : // sortie du programme
            case ESC     : break;

                           // sortie aussi sur :q
            case ':'     : car = leccar ();

                           if (car == 'q')
                           {
                               car = ESC;
                               break;
                           }

            default      : putchar (7);  // bip

                           // si trop d'erreurs, afficher l'aide
                           if (++erreurs == 5)
                               ungetc (0, stdin);  // on ira sur l'aide
        }
    }
    while (car != 'q' && car != ESC);

    // descendre en bas de page
    while (lignecran++ < lignepage && lignecour++ < nb_lignes)
        putchar ('\n');

    // retour à la configuration standard du clavier
    mode_normal ();
}



/* recherche de fichiers mail dans le répertoire passé en paramètre */

void detectemail (int numrep)
{
    DIR *repert;
    struct dirent *entree;
    struct stat   descfic;
    char   nomfic [szchemin]; // chemin d'accès à un fichier


    // accéder au répertoire
    repert = opendir (maildir [numrep]);

    // sortie sur erreur si l'on n'a pas pu
    if (repert == 0)
        return;

    // initialisation : pas encore de mail trouvé dans ce répertoire
    nb_mails  [numrep] = 0;
    nb_nonlus [numrep] = 0;

    // lire un nom de fichier
    entree = readdir (repert);

    // tant qu'il y a des noms de fichier à lire
    while (entree)
    {
        // récupérer les caractéristiques du fichier courant
        sprintf (nomfic, "%s/%s", maildir [numrep], entree->d_name);
        stat (nomfic, &descfic);

        // si c'est un fichier mail
        if ((descfic.st_mode & S_IFMT) == S_IFREG
                                       && fichier_mail (entree->d_name))
        {
            nb_mails [numrep] ++;

            // test si mail en attente de lecture
            if (entree->d_name [8] == '.' &&
                                  tolower (entree->d_name [9]) == 'n')
            {
                nb_nonlus [numrep] ++;
            }
        }

        // et lire le nom du fichier suivant
        entree = readdir (repert);
    }

    // libérer le répertoire
    closedir (repert);
}



/* génère le format d'affichage du nombre de mails non lus
   et éventuellement du nombre total de mails */


void gen_format_cpt ()
{
    int max_nbmails = 0;
    int max_nonlus  = 0;
    int puis10;
    int col_nl, col_m;
    int i;


    // chercher le plus grand nombre de mails non lus
    // parmi tous les répertoires mémorisés
    for (i = 0; i < nb_lignes; i++)
        if (nb_nonlus [i] > max_nonlus)
            max_nonlus = nb_nonlus [i];

    // calculer le nombre de chiffres pour afficher ce nombre
    puis10 = 10;
    col_nl  = 1;

    while (max_nonlus >= puis10)
    {
        puis10 = puis10 * 10;
        col_nl ++;
    }

    // si on doit afficher aussi le nombre total de mails
    if (opt_cn > 1)
    {
        // chercher le plus grand nombre de mails
        // parmi tous les répertoires mémorisés
        for (i = 0; i < nb_lignes; i++)
            if (nb_mails [i] > max_nbmails)
                max_nbmails = nb_mails [i];

        // calculer le nombre de chiffres pour afficher ce nombre
        puis10 = 10;
        col_m  = 1;

        while (max_nbmails >= puis10)
        {
            puis10 = puis10 * 10;
            col_m ++;
        }

        // générer le format d'affichage des 2 nombres
        sprintf (formatcpt, "%%%dd/%%-%dd ", col_nl, col_m);

        // et mémoriser la largeur de cet affichage
        coldebnomrep = col_nl + col_m + 2;
    }
    // sinon
    else
    {
        // générer le format d'affichage du nombre de mails non lus
        sprintf (formatcpt, "%%%dd ", col_nl);

        // et mémoriser la largeur de cet affichage
        coldebnomrep = col_nl + 1;
    }
}



/* affiche le nom de répertoire passé en
   paramètre sans déborder de la fenêtre */


void affligne (int numlig)
{
    int  i;
    char *carcourant;


    // positionnement au début du nom de répertoire
    if (strcmp (maildir [numlig], ".") == 0)
        // cas particulier du répertoire racine
        // "<racine>"
        carcourant = message ("RACINE_MAILS");
    else
        // cas général
        carcourant = maildir [numlig];

    // afficher en bleu foncé les répertoires sans mail
    if (!nb_mails [numlig])
        sombre ();
    // et en surbrillance ceux qui ont des mails non lus
    else if (nb_nonlus [numlig])
        clair ();

    // si demandé, afficher les nombres de mails
    if (opt_cn)
        printf (formatcpt, nb_nonlus [numlig], nb_mails [numlig]);

    // initialisation numéro de colonne d'affichage
    i = coldebnomrep;

    // on arrête l'affichage en fin de chaine ou en bord de fenêtre
    while (*carcourant  && i++ < colonpage)
    {
        putchar (*carcourant);
        carcourant ++;
    }

    // retour à l'affichage en luminosité normale
    lumnor ();
}