/*
    Fichier repmail.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


    Ce programme prépare une réponse pour le fichier mail passé en paramètre
    Le chemin d'accès au fichier peut être absolu ou relatif.

    A partir du squelette généré, la réponse se fait grace à l'éditeur vi

    Le fichier obtenu est ensuite stoqué dans le répertoire des mails à envoyer
    Pour que cela soit possible, il faut :
    - soit que la commande repmail soit lancée depuis la chaine vmail...
    - soit préciser le nom du répertoire de l'arborescence des mails
*/

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "messages.h"
#include "buflect.h"
#include "fmail.h"
#include "trtentete.h"
#include "trtligne.h"
#include "trtbordure.h"
#include "trtsection.h"
#include "numail.h"
#include "genentete.h"
#include "modepage.h"
#include "carspe.h"


#define  szbuf    160   // taille des tableaux mémorisant les champs de l'entête


/* prototypes */
void gene_entete (char *nomfic);
void gene_enteterep (char *nomfic);
void gene_mesrep ();
void copie_texte ();
void aff_debliste (long pos_deblig);
void copchamp (long pos_deblig, int conversion);
void genligne (char *buffer);
void regroupeligne (char *buffer);


/* variable globale au source
   (pour éviter des passages de paramètres) */

long numail;  // numéro que prendra le mail généré


/* programme principal */

int main (int nbarg, char *varg[])
{
    char ficmail [szchemin];  // fichier mail de réponse
    char fentete [szchemin];  // fichier contenant l'entete du message
    char commande [szchemin]; // commande d'appel de l'éditeur
    char *editeur;            // éditeur utilisé pour saisir la réponse


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

    // si nombre d'arguments correct
    if (--nbarg == 1 || nbarg == 2)
    {
        // ouvrir le fichier mail auquel on doit répondre
        fmail = fopen (varg [1], "r");

        // terminé si le fichier n'a pas pu être ouvert
        if (! fmail)
        {
            if (access (varg [1], 0) == 0)
                // "Problème d'accès au fichier %s"
                errfatale ("ACCES_FICHIER", varg [1]);
            else
                // "Fichier %s inexistant"
                errfatale ("FICH_INEXISTANT", varg [1]);
        }
    }
    // sinon, rappel de la syntaxe de la commande
    else
        // "Syntaxe : %s nom_fichier_mail [répertoire_emails]"
        psyntaxe ("SYNT_REP/TRSF-MAIL");

    // passer en mode standard pour les lectures au clavier
    mode_normal ();

    // récupérer le nom du répertoire des mails à envoyer
    recupdirenv (nbarg, varg [2]);

    // créer un nom de fichier temporaire pour l'entête du mail
    // il a toujours le même nom pour éviter de polluer le
    // répertoire d'envoi en cas de fausse manoeuvre opérateur (^C)
    sprintf (fentete, "%s/tmp-ent", direnv);

    // fabriquer l'entête du mail de réponse
    gene_entete (fentete);

    // créer un nom de fichier temporaire pour le message
    sprintf (ficmail, "%s/tmp-mes", direnv);

    // fabriquer le message de réponse
    gene_enteterep (ficmail);

    // Choix de l'éditeur de textes
    editeur = getenv ("EDITOR");

    if (! editeur)
        editeur = "vi";

    // c'est au tour de l'utilisateur de répondre au mail
    sprintf (commande, "%s %s", editeur, ficmail);
    system (commande);

    // mémoriser les dates et heure d'envoi du message
    ajout_date (fentete);

    // on va regrouper l'entête et le message dans un fichier numéroté définitif
    fusionner (fentete, numail, ficmail);

    // mettre à jour le fichier numail du répertoire de sortie
    sauv_num_dermail (direnv, numail);

    // ajouter la signature au message, si elle existe
    ajout_sign (ficmail);

    // modification avant envoi ?
    // "Voulez vous modifier le fichier complet avant envoi ? "
    printf (message ("MAJ_MAIL_PRET"));

    if (tolower (getchar ()) != 'n')
    {
        // si oui, appeler l'éditeur
        sprintf (commande, "%s %s", editeur, ficmail);
        system (commande);
    }

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


/* lit l'entête du message choisi et fabrique celle de la réponse */

void gene_entete (char *nomfic)
{
    long pos_deblig;  // position dans le fichier en début de ligne courante
    // position dans le fichier des champs pouvant tenir sur plusieurs lignes
    long posTo = -1, posCc = -1, posSubject = -1, posRef = -1;
    // mémorisation directe d'autres champs
    // grosse taille des buffers pour ne pas tronquer une adresse
    // de type confirmation d'inscription à une mailing list
    char bufFrom [szbuf], bufReply [szbuf], bufMesid [szbuf];
    char reponse [10];    // réponse à une question
    int  choix, choixmax; // choix des destinataires
    int  i, j;            // compteurs


    // fabriquer et ouvrir en écriture le fichier d'entête
    fdest = fopen (nomfic, "w");

    if (! fdest)
        // "Impossible de créer un fichier d'entête %s"
        errfatale ("IMPOS_CRE_ENTETE", nomfic);

    // initialisation
    *bufFrom    = '\0';
    *bufReply   = '\0';
    *bufMesid   = '\0';

    // lecture et mémorisation de l'entête du message
    do
    {
        // récupérer la position en début de ligne
        pos_deblig = ftell (fmail);

        // lire une ligne de l'entête du message
        lire_fmail ();

        // pour éviter un débordement de buffer lors d'une copie
        buf_lect [szbuf - 1] = '\0';

        // repérage des champs importants et mémorisation
        // de leur contenu ou de leur position
        if (start ("From"))
        {
            // convertir les caractères spéciaux éventuels
            majlignentete ();

            // analyse et copie dans le bufFrom
            // on n'utilise pas memconvbuf parce qu'il tronque à 80 caractères
            i = 0;
            j = 0;

            do
            {
                // recopier un caractère
                bufFrom [i] = buf_lect [i];

                // mémoriser la présence d'une adresse Email dans la ligne
                if (buf_lect [i] == '@')
                    j = i;
            }
            while (buf_lect [i++]);

            // si aucune adresse email valide n'a été trouvée dans la ligne
            if (buf_lect [j] != '@')
            {
                // lire la ligne suivante
                lire_fmail ();

                // convertir les caractères spéciaux éventuels
                majlignentete ();

                // et copie dans le bufFrom à la suite de la ligne précédente
                j = 0;
                i --;

                while (buf_lect [j] && i < szbuf - 1)
                {
                    // recopier un caractère et passer au suivant
                    bufFrom [i++] = buf_lect [j++];
                }

                // terminer la chaine de caractères
                bufFrom [i] = '\0';
            }
        }
        else if (start ("To"))
            posTo = pos_deblig;      // on mémorise la position de la ligne
        else if (start ("Cc"))
            posCc = pos_deblig;      // on mémorise la position de la ligne
        else if (start ("Reply-To"))
        {
            // pas de conversion des lignes contenant une adresse Email
            // (on évite ainsi de supprimer les _ de certaines adresses)
            strcpy (bufReply, buf_lect);
        }
        else if (start ("Subject"))
            posSubject = pos_deblig; // on mémorise la position de la ligne
        else if (start ("Message-Id"))
        {
            // on récupère juste la valeur du Message-Id sans conversion
            // elle servira à générer les champs In-Reply-To et Reference
            if (buf_lect [11] == ' ')
                strcpy (bufMesid, buf_lect + 12);
            else
                strcpy (bufMesid, buf_lect + 11);
        }
        else if (start ("Reference"))
            posRef = pos_deblig;      // on mémorise la position de la ligne
    }
    while (buf_lect [0] != '\0');  // lecture entête terminée si ligne vide

    // récupérer l'adresse de celui qui répond au mail
    lire_exped ();

    // chercher le numéro du mail que l'on va créer
    numail = num_dermail (direnv) + 1;

    // génération du champ Message-Id
    gen_mes_id (fdest, numail, buf_lect);

    // mettre l'expéditeur du message
    ajouts = 0;
    ajout_adr (buf_lect, "From");
    fputc ('\n', fdest);

    // choix des destinataires
    // pas de sélection manuelle des adresses, mais jusqu'à 6 choix
    // en fonction des caractéristiques du mail auquel on répond
    // "\nRépondre à :\n"
    // "1) L'expéditeur :%s\n\n"
    // "2) L'expéditeur + celui qui répond en copie : %s\n\n"
    // "3) L'expéditeur + destinataires en copie à choisir\n"
    // "4) Au(x) destinataire(s) principal/aux"
    affiche_msg ("CHOIX_REP-0");
    printf (message ("CHOIX_REP-1"), bufFrom + 5);
    printf (message ("CHOIX_REP-2"), buf_lect);
    affiche_msg ("CHOIX_REP-3");
    affiche_msg ("CHOIX_REP-4");

    // cette liste peut tenir sur plusieurs lignes
    aff_debliste (posTo);

    // "5) A l'expéditeur + destinataire(s) principal/aux"
    putchar ('\n');
    affiche_msg ("CHOIX_REP-5");

    // ces choix ne sont rajoutés que s'ils sont possibles
    if (*bufReply)
    {
        // "6) A l'adresse pour répondre :%s\n"
        // "7) A l'adresse pour répondre + celui qui répond en copie\n\n"
        putchar ('\n');
        printf (message ("CHOIX_REP-6"), bufReply + 9);
        putchar ('\n');
        affiche_msg ("CHOIX_REP-7");
        choixmax = 7;
    }
    else
        choixmax = 5;

    // choix opérateur
    do
    {
        // "Votre choix ? "
        putchar ('\n');
        printf (message ("VOTRE_CHOIX"));
        fgets (reponse, sizeof (reponse), stdin);
        choix = atoi (reponse);
    }
    while (choix < 1 || choix > choixmax);

    // génération de la liste des destinataires principaux
    if (choix < 6)
    {
        // expéditeur du message initial
        if (choix != 4)
        {
            fprintf (fdest, "To:%s", bufFrom + 5);

            // qui sera ou non complété par des destinataires principaux
            if (choix != 5)
                fputc ('\n', fdest);

            // + en copie l'expéditeur de celui ci
            if (choix == 2)
            {
                lire_exped ();
                ajouts = 0;
                ajout_adr (buf_lect, "Cc");
                fputc ('\n', fdest);
            }
            // ou des destinataires en copie choisis
            else if (choix == 3)
            {
                // charger le carnet d'adresses
                charge_carnet_adr ();

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

                // et choisir des destinataires
                choixdest ("Cc");

                // on repasse en mode saisie normale
                mode_normal ();
            }
        }

        // destinataires principaux du message initial
        if (choix > 3)
        {
            // se positionner sur le champ à copier
            fseek (fmail, posTo, SEEK_SET);

            // lire et copier la première ligne
            lire_fmail ();

            // en tenant compte éventuellement de la ligne précédente
            if (choix == 4)
                fputs (buf_lect, fdest);
            else
                fprintf (fdest, ",\n\t%s", buf_lect + 4, fdest);

            // tester la ligne suivante
            lire_fmail ();

            // recopier jusqu'à la fin de la liste
            while (*buf_lect == ' ' || *buf_lect == '\t')
            {
                fprintf (fdest, "\n%s", buf_lect);
                lire_fmail ();
            }

            // terminer proprement la liste des destinataires
            fputc ('\n', fdest);
        }
    }
    else
    {
        // adresse en réponse
        fprintf (fdest, "To:%s\n", bufReply + 9);

        // + éventuel expéditeur en copie
        if (choix == 7)
        {
            lire_exped ();
            ajouts = 0;
            ajout_adr (buf_lect, "Cc");
            fputc ('\n', fdest);
        }
    }

    // rajout à la demande des destinataires en copie
    // à la suite de la liste des destinataires principaux
    if (posCc >= 0 && (choix == 4 || choix == 5))
    {
        // "\nDestinataires en copie :"
        affiche_msg ("AJOUT_DESTCOP-1");
        aff_debliste (posCc);

        // "Voulez vous les rajouter ? "
        printf (message ("AJOUT_DESTCOP-2"));
        fgets (reponse, sizeof (reponse), stdin);

        // traitement de la réponse valable en de nombreuses langues
        // si la réponse ne commence pas par 'n', c'est oui
        // (ceux qui obligent à répondre 'y' sont de gros nuls)
        if (tolower (*reponse) != 'n')
        {
            // se positionner sur le champ à copier
            fseek (fmail, posCc, SEEK_SET);

            // lire la première ligne
            lire_fmail ();

            // copier jusqu'à la fin de la liste
            do
            {
                fprintf (fdest, "%s\n", buf_lect);
                lire_fmail ();
            }
            while (*buf_lect == ' ' || *buf_lect == '\t');
        }
    }

    // génération du champ Subject
    if (posSubject >= 0)
    {
        // lire la ligne contenant le sujet
        fseek (fmail, posSubject, SEEK_SET);
        lire_fmail ();

        // convertir les caractères spéciaux éventuels
        // c'est dans envmail qu'on réencodera éventuellement ce champ
        majlignentete ();

        // si la ligne du sujet n'est pas vide
        if (strlen (buf_lect) > 9)
        {
            // si le sujet du mail commence par les lettres re
            if (tolower (buf_lect [9]) == 'r' && tolower (buf_lect [10]) == 'e')
            {
                // si le sujet commence par Re: , RE: , re: etc...
                if (buf_lect [11] == ':')
                    // On utilise la syntaxe la plus courante Re:
                    fprintf (fdest, "Subject: Re:%s", buf_lect + 12);

                // sinon si le sujet commence par Re : , RE : , re : etc...
                else if (buf_lect [11] == ' ' && buf_lect [12] == ':')
                    // on supprime le blanc avant le :
                    fprintf (fdest, "Subject: Re:%s", buf_lect + 13);

                // sinon (les lettres re ne sont pas suivies d'un :
                else
                    // on rajoute un Re: en début de sujet
                    fprintf (fdest, "Subject: Re: %s", buf_lect + 9);
            }
            // sinon
            else
                // on rajoute un Re: en début de sujet
                fprintf (fdest, "Subject: Re: %s", buf_lect + 9);

            // lire la ligne suivante
            lire_fmail ();
        }
        else
        {
            // on va vérifier si le sujet est sur la ligne suivante
            lire_fmail ();

            // le libellé du sujet dépendra du résultat du test
            if (*buf_lect == ' ' || *buf_lect == '\t')
                fputs ("Subject: Re: ", fdest);
            else
            {
                // "Subject: Réponse à message sans objet précisé"
                fputs (message ("SUJET_VIDE"), fdest);
            }
        }

        // tantque c'est aussi une ligne du sujet
        while (*buf_lect == ' ' || *buf_lect == '\t')
        {
            // convertir les caractères spéciaux éventuels
            majlignentete ();

            // rajouter le contenu de la ligne au sujet
            fputs (buf_lect + 1, fdest);

            // et lire la ligne suivante
            lire_fmail ();
        }

        // terminer la ligne contenant le sujet
        fputc ('\n', fdest);
    }
    else
    {
        // "Subject: Réponse à message sans objet précisé"
        fputs (message ("SUJET_VIDE"), fdest);
        fputc ('\n', fdest);
    }

    // si le mail auquel on répond avait un identificateur
    if (*bufMesid)
    {
        // on va générer le champ Reference

        // s'il y avait déjà un champ Reference
        if (posRef >= 0)
        {
            // se positionner sur ce champ
            fseek (fmail, posRef, SEEK_SET);

            // lire la première ligne
            lire_fmail ();

            // copier jusqu'à la fin de la liste
            do
            {
                fprintf (fdest, "%s\n", buf_lect);
                lire_fmail ();
            }
            while (*buf_lect == ' ' || *buf_lect == '\t');

            // rajouter la dernière référence
            fprintf (fdest, "           %s\n", bufMesid);
        }
        // sinon
        else
            // créer un champ référence
            fprintf (fdest, "Reference: %s\n", bufMesid);

        // générer le champ In-Reply-To
        fprintf (fdest, "In-Reply-To: %s\n", bufMesid);
    }

    // jeu de caractères du message
    fprintf (fdest, "Content-Type: text/plain; charset=");

    if (util_utf8 ())
        fprintf (fdest, "UTF-8;\n");
    else
        fprintf (fdest, "ISO-8859-15;\n");

    // mode d'encodage
    fprintf (fdest, "Content-Transfer-Encoding: 8bit\n");

    // variante (qui suppose des conversions avant envoi du mail)
    // fprintf (fdest, "Content-Transfer-Encoding: quoted-printable\n");

    // un copyright qui n'est pas celui d'Outlook ;-))
    // "libremail : logiciel libre multilingue"
    fprintf (fdest, "User-Agent: libremail : %s\n",
                     message ("QUALIF_LIBREMAIL"));

    // permettra de relire ce fichier
    fclose (fdest);
}



/* lit le message choisi et fabrique le squelette de la réponse
   cette fonction traite essentiellement l'entête du mail
   puis appelle gene_mesrep pour le rajout du corps du mail */

void gene_enteterep (char *nomfic)
{
    long pos_deblig;  // position dans le fichier en début de ligne
    // position dans le fichier mail des principaux champs de l'entête
    long posDate, posFrom, posTo, posCc, posReply,
         posSubject, posContent, posUseAgent;


    // fabriquer et ouvrir en écriture le fichier mail
    fdest = fopen (nomfic, "w");

    if (! fdest)
        // "Impossible de créer le fichier mail %s"
        errfatale ("IMPOS_CRE_FICMAIL", nomfic);

    // initialisation
    posDate     = -1;
    posFrom     = -1;
    posTo       = -1;
    posCc       = -1;
    posReply    = -1;
    posSubject  = -1;
    posContent  = -1;
    posUseAgent = -1;

    // on revient au début du fichier mail
    rewind (fmail);

    // lecture de l'entête et mémorisation de la position des champs importants
    do
    {
        // récupérer la position en début de ligne
        pos_deblig = ftell (fmail);

        // lire une ligne de l'entête du message
        lire_fmail ();

        // repérage des champs importants et mémorisation de leur position
        if (start ("X-Mailer") || start ("User-Agent"))
            posUseAgent = pos_deblig;
        else if (start ("Date"))
            posDate = pos_deblig;
        else if (start ("From"))
            posFrom = pos_deblig;
        else if (start ("To"))
            posTo = pos_deblig;
        else if (start ("Cc"))
            posCc = pos_deblig;
        else if (start ("Reply-To"))
            posReply = pos_deblig;
        else if (start ("Subject"))
            posSubject = pos_deblig;
        else if (start ("Content-Type"))
            posContent = pos_deblig;
        else if (start ("Content-Transfer-Encoding"))
            mem_encodage ();
    }
    while (buf_lect [0] != '\0');  // lecture entête terminée si ligne vide

    // sauter des lignes pour réponse avant le message
    fputc ('\n', fdest);
    fputc ('\n', fdest);

    // rappel des caractéristiques du message auquel on répond
    if (posUseAgent >= 0)
        copchamp (posUseAgent, 0);
    if (posDate >= 0)
        copchamp (posDate, 0);
    if (posFrom >= 0)
        copchamp (posFrom, 1);
    if (posTo >= 0)
        copchamp (posTo, 1);
    if (posCc >= 0)
        copchamp (posCc, 1);
    if (posReply >= 0)
        copchamp (posReply, 1);
    if (posSubject >= 0)
        copchamp (posSubject, 1);

    // récupérer le type principal du message et ses caractéristiques
    typeorig (posContent);

    // revenir au début du corps du message
    fseek (fmail, pos_deblig, SEEK_SET);
    lire_fmail ();

    // copie du contenu du mail
    if (ctypeorig & Multipart)
        // il faudra analyser les sections
        gene_mesrep ();
    else
        // une simple copie du texte suffit
        copie_texte ();

    // génération automatique terminée
    fclose (fdest);
}


/* affiche les premières lignes d'une liste de destinataires
   (champs To: ou Cc:) du message auquel on répond */

void aff_debliste (long pos_deblig)
{
    int i; // compteur

    // se positionner sur le champ à afficher
    fseek (fmail, pos_deblig, SEEK_SET);

    // lire et afficher la première ligne
    lire_fmail ();
    majlignentete ();
    printf ("  ");
    puts (buf_lect + 3);

    // tester la ligne suivante
    lire_fmail ();
    i = 0;

    // et continuer l'affichage si nécessaire
    while ((*buf_lect == ' ' || *buf_lect == '\t') && ++i < 9)
    {
        majlignentete ();
        printf ("   ");
        puts (buf_lect + 1);
        lire_fmail ();
    }

    // on abrège l'affichage si la liste est trop longue
    if (i >= 9)
        puts ("   (...)");
}


/* recopie un champ de l'entête d'une ou plusieurs lignes
   repéré à partir de sa position dans le fichier mail */

void copchamp (long pos_deblig, int conversion)
{
    // se positionner sur la ligne contenant le champ
    fseek (fmail, pos_deblig, SEEK_SET);

    // lire cette ligne
    lire_fmail ();

    // répéter
    do
    {
        // interpréter si nécessaire les caractères spéciaux
        if (conversion)
            majlignentete ();

        // et afficher la ligne
        fprintf (fdest, "> %s", buf_lect);

        // en tenant compte d'un éventuel \n dans le buffer
        if (buf_lect [strlen (buf_lect) - 1] != '\n')
            fputc ('\n', fdest);

        // lire la ligne suivante
        lire_fmail ();
    }
    // jusqu'à la dernière ligne du champ
    while (*buf_lect == ' ' || *buf_lect == '\t');
}


/* lecture et copie du contenu d'un mail en mode multipart */

void gene_mesrep ()
{
    // si mode multipart/mixed ou multipart/related, mémoriser
    // le type et la bordure éventuelle de la section suivante
    if ((ctypeorig == MultipMixed) || (ctypeorig == MultipRel))
        mem_soustype ();

    // se positionner sur la section texte du mail (si l'on n'y est pas)
    posit_texte ();

    // message d'avertissement éventuel
    test_encode ();

    // générer une ligne de séparation avec l'entête
    genligne ("\n");

    // si structure du mail non conforme, message d'erreur
    if (! lire_fmail ())
        // "Pas de zone texte dans ce mail !!!"
        genligne (message ("MANQUE_ZONE_TEXTE"));

    // lecture et mémorisation du corps du message
    do
    {
        // mise en forme et mémorisation de la dernière ligne lue
        majligne ();

        if (buf_lect [strlen (buf_lect) - 1] != '\n')
            regroupeligne (buf_lect);
        else
            genligne (buf_lect);

        // et lecture de la suivante
        if (! lire_fmail ())
            return;   // on sort en fin de fichier

        // si mode multipart/report, on saute les entêtes de section
        if (ctypeorig == MultipRep && nbordures && surbordure ())
        {
            do
                lire_fmail ();
            while (*buf_lect);
        }
    }
    // on s'arrête en fin de fichier, ou sur la prochaine bordure
    while (nbordures == 0 || ! surbordure ());

    // si mode multipart mixed on va lister les pièces jointes
    if (ctypeorig == MultipMixed)
        liste_pj ();
}



/* lecture et copie d'un mail de type text/plain */

void copie_texte ()
{
    // message d'avertissement éventuel
    test_encode ();

    // répéter
    do
    {
        // mise en forme de la dernière ligne lue
        majligne ();

        // mémorisation de cette ligne
        if (buf_lect [strlen (buf_lect) - 1] != '\n')
            regroupeligne (buf_lect);
        else
            genligne (buf_lect);

        // et lecture de la suivante
    }
    // on s'arrête en fin de fichier
    while (lire_fmail ());
}



/* mémorise une ligne du mail */

void genligne (char *buffer)
{
    char * nouvligne;
    int  taille_ligne;
    int  i;


    // récupérer la longueur de la ligne
    taille_ligne = strlen (buffer);

    // si ligne longue
    if (taille_ligne > 80)
    {
        // on tente de la tronquer à moins de 80 car
        i = 70;

        // chercher un blanc pour passer à la ligne
        // ou un \n résultant d'un abus de l'encodage Mime
        while (i > 0 && buffer [i] != ' ' && buffer [i] != '\n')
            i--;

        // si pas de blanc trouvé
        if (i == 0)
        {
            // on en cherche un dans l'autre sens
            i = 70;

            while (i < taille_ligne && buffer [i] != ' ' && buffer [i] != '\n')
                i++;
        }

        // mémoriser la taille de la ligne tronquée
        taille_ligne = i;
    }

    // tenir compte d'un '\n' éventuel en cours de ligne !
    // (dans le cas d'un encodage quoted-printable non conforme
    // ou d'un encodage base64)
    for (i = 0; i < taille_ligne - 1; i++)
        if (buffer [i] == '\n')
            taille_ligne = i;

    // recopier les données dans ce tableau
    fputc ('>', fdest);

    if (taille_ligne > 1)
        fputc (' ', fdest);

    for (i = 0; i < taille_ligne; i++)
        fputc (buffer [i], fdest);

    // si la ligne a été tronquée
    if (taille_ligne < strlen (buffer))
    {
        // générer un passage à la ligne
        fputc ('\n', fdest);

        // et traiter la suite
        genligne (buffer + taille_ligne + 1);
    }
}


/* regroupe 2 lignes du fichier mail lorsque le passage
   à la ligne doit être supprimé à l'affichage */

void regroupeligne (char *buffer)
{
    char * lignefusion;


    // allouer un buffer pour contenir les 2 lignes
    lignefusion = (char *) malloc (strlen (buffer) + sizeof (buf_lect) + 1);

    // si espace mémoire suffisant
    if (lignefusion)
    {
        // recopier la dernière ligne lue dans ce buffer
        strcpy (lignefusion, buffer);

        // lire et convertir la suivante et la recopier à la suite
        lire_fmail ();
        majligne ();
        strcat (lignefusion, buf_lect);

        // mémoriser l'ensemble
        if (lignefusion [strlen (lignefusion) - 1] != '\n')
            regroupeligne (lignefusion);
        else
            genligne (lignefusion);

        // libérer le buffer de travail
        free (lignefusion);
    }
    // sinon, on va juste mémoriser la ligne passée en paramètre
    else
        genligne (buffer);
}
