
/*-------------------------------------------------------------------------

                              O P T E X T E . C

---------------------------------------------------------------------------

   Alain FONTANIN 13 Traverse du Gamay Les Fougéres F38090 VilleFontaine

---------------------------------------------------------------------------

  Ce source est à prendre comme exemple d'utilisation du gestionnaire de 
  listes chainées. Il n'est pas totalement complet et c'est la que vous en-
  trez en scéne:

        - On ne peut insérer des lignes qu'avant une ligne existante, donc
        on ne peut pas ajouter de lignes à la fin.

        - Il manque la possibilité d'y inclure un autre document.

  PS: Les numéros de lignes ne sont pas mis à jour lors d'insertion, effa-
  cement pour permettre dans vérifier la validité.

-------------------------------------------------------------------------*/





#include<exec/types.h>
#include<exec/memory.h>
#include<stdio.h>
#include<string.h>


#include<DEV/GLC.H>     /* Le prototypage de GLC */


#define     FIN_OK      TRUE
#define     FIN_ERR     FALSE




void       Fin(char *, BOOL);
struct SL  *LireFichier(char *);



void main(
/********/
int  argc,
char *argv[])
    {
    struct SL *Document_Ancre, *LDoc, *Laff, *Ldel;
    char      LigneCommande[201];
    int       iter;
    BOOL      CONTINUE=TRUE;

    if(argc < 1)
        Fin("Pas de nom de document spécifié!", FIN_ERR);

    Document_Ancre = LireFichier(argv[1]);
    if(!Document_Ancre)
        Fin("Je ne peut accéder au document!", FIN_ERR);

    LDoc = Document_Ancre;   /* On initialise la ligne courante sur la téte  */
                            /*  de la liste */
    printf("OpTexte exemple d'utilisation de GLC \n");
    while(CONTINUE)
        {
        printf("\n*");
        scanf("%200s", LigneCommande);
        switch(LigneCommande[0])
            {
            case 'a':
            case 'A':
                    Laff = LDoc;
                    for(iter=0;iter<20;iter++)
                        {
                        printf("%05d %s\n", Laff->Num, Laff->PtrData);
                        if(Laff->PtrSuiv)  /* si il y a un élément suivant   */
                            Laff = Laff->PtrSuiv;   /* il devient le courant */
                        else
                            break;  /* sinon on quitte la boucle */
                        }
                    break;
            case 'd':
            case 'D':
/*-------------------------------------------------------------------------
  On recherche les deux adresses des éléments, la fonction RetireListe né-
cessite un borne de début < a la borne de fin. Içi le test n'est pas fait
( à vous de jouer!) . 
  Pour effacer une sous-liste, on la retire d'abord de la liste avec la
fonction RetireListe puis on l'efface avec la fonction EffaceListe
-------------------------------------------------------------------------*/
                    iter = atoi(&LigneCommande[1]);
                    Ldel = AllerAElement(iter, Document_Ancre);
                    if(Ldel)
                        {
                        iter = atoi((strchr(LigneCommande, ',') + 1));
                        Laff = AllerAElement(iter, Document_Ancre);
                        if(Laff)
                            {
                            Document_Ancre = RetireListe(Ldel, Laff, Document_Ancre);
                            EffaceListe(Ldel, EFF_DATA);
                            LDoc = Document_Ancre;/*Mesure facile pour éviter */
                            }                     /*Les adresses plus valides */
                        }
                    break;
            case 'f':
            case 'F':
                    Laff = Document_Ancre;
                    iter=1;
                    while(Laff)  /* on compte le nombre d'éléments en dérou-  */
                        {       /* lant complétement la liste */
                        if(Laff->PtrSuiv)
                            {
                            iter++;
                            Laff=Laff->PtrSuiv;
                            }
                        else
                            break;
                        }
                    printf("Il y a %d ligne%sdans le document\n", iter, (iter > 1) ? "s " : " ");
                    break;
            case 'g':
            case 'G':
                    /* Pour qu'une ligne devienne courante: */
                    /* On demande son adresse à GLC gràce à la fonction: */
                    /*AllerAElement();*/

                    iter = atoi(&LigneCommande[1]);
                    Laff = AllerAElement(iter, Document_Ancre);
                    if(!Laff)        /*si elle n'existe pas: Laff == NULL */
                        printf("Numéro de ligne invalide!\n");
                    else
                        LDoc = Laff; /* sinon on assigne cette adresse à */
                    break;          /* Ldoc*/
            case 'i':
            case 'I':
                   /*on demande l'adresse de l'élément avant lequel doit étre   */
                    iter = atoi(&LigneCommande[1]);         /*inséré la ligne   */
                    Laff = AllerAElement(iter, Document_Ancre);
                    if(Laff)
                        {
                        Ldel = InitialiseListe(1);
                        if(Ldel)
                            {
                            printf("\n**");
                            scanf("%200s", LigneCommande);
                            Ldel->PtrData = (char *) AllocMem(strlen(LigneCommande) + 1, MEMF_PUBLIC);
                            if(Ldel->PtrData)
                                strcpy(Ldel->PtrData, LigneCommande);
                            Document_Ancre = InsereListe(Laff, Ldel, Document_Ancre);
                            }
                        }
                    break;
            case 'q':
            case 'Q':
                    CONTINUE = FALSE;
                    break;
            default:
                    if(LigneCommande[0] != 'h' && LigneCommande[0] != 'H')
                        printf("Commande inconnue!\n");
                    printf("\nAide:\n");
                    printf("-----\n\n");
                    printf("\ta/A:    Affiche une page à partir de la ligne courante\n");
                    printf("\td/Dx,y: Elimine les lignes comprit entre x et y\n");
                    printf("\tf/F:    Affiche le nombre de lignes composant le document\n");
                    printf("\tg/Gx:   Déplace la ligne courante en x\n");
                    printf("\th/H:    Affiche cette page d'aide\n");
                    printf("\ti/Ix:   Insére une ligne avant la ligne x\n");
                    printf("\tq/Q:    Quitter\n\n");
                    break;
            }
        }
    EffaceListe(Document_Ancre, EFF_DATA);
    Fin("Fin.", FIN_OK);
    }


void Fin(
/*******/
char *ErrStr,
BOOL TypeFin)
    {

    printf("%s\n", ErrStr);

    if(TypeFin == FIN_ERR)
        exit(10);
    else
        exit(0);
    }


struct SL *LireFichier(
/*********************/
char *NomFichier)
    {
    struct SL *Fichier_Ancre = NULL, *L1 = NULL, *L2 = NULL;
    char      *BufLecture, *compare, *StrPtr;
    int       NumLigne=1;
    FILE      *entree, *fopen();
    BOOL      LECTURE = TRUE;

    BufLecture = (char *) AllocMem(1025, MEMF_PUBLIC | MEMF_CLEAR);
    if(BufLecture)
        {
        entree = fopen(NomFichier, "r+t");
        if(entree)
            {
            printf("Lecture de %s en cours...", NomFichier);
/*-------------------------------------------------------------------------
  On initialise 100 éléments d'avance pour recevoir les premiéres lignes, 
puis on ajoutera des sous-listes de 100 éléments à cette liste chaque fois
que cela sera nécessaire.
-------------------------------------------------------------------------*/
            Fichier_Ancre = InitialiseListe(100);
            if(Fichier_Ancre)
                {
                L1 = Fichier_Ancre;
                while(LECTURE)
                    {
                    fgets(BufLecture, 1024, entree);
                    if(!strlen(BufLecture))
                        LECTURE=FALSE;
                    else
/*-------------------------------------------------------------------------
  Oui il y eut quelque chose lu!
-------------------------------------------------------------------------*/
                        {
                        L1->Num = NumLigne;
                        compare = strchr(BufLecture, '\n');
                        if(compare)
                            *compare = '\0';
/*-------------------------------------------------------------------------
  Y a-t-il quelque chose dans notre élément, car il se peut que le fichier
contient des lignes de plus de 1024 caractéres?
-------------------------------------------------------------------------*/
                        if(L1->PtrData)
                            {
                            StrPtr = L1->PtrData;
                            L1->PtrData = (char *) AllocMem(strlen(StrPtr) + strlen(BufLecture) + 1 , MEMF_PUBLIC);
                            strcpy(L1->PtrData, StrPtr);
                            strcat(L1->PtrData, BufLecture);
                            FreeMem(StrPtr, strlen(StrPtr) + 1);
                            }
                        else
                            {
                            L1->PtrData = (char *) AllocMem(strlen(BufLecture) + 1 , MEMF_PUBLIC);
                            strcpy(L1->PtrData, BufLecture);
                            }
/*-------------------------------------------------------------------------
  Si le Buffer contient un '\n' alors on doit déplacer notre pointeur d'un
élément, si cela  est possible sinon il faut initialiser une nouvelle liste
et la lier à la principale, cette technique de lier des listes de 100 élé- 
ments permet de ne pas consommer trop de temps CPU entre chaque lecture de
lignes.
-------------------------------------------------------------------------*/
                        if(compare)
                            {
                            NumLigne++;
                            if(L1->PtrSuiv)
                                L1 = L1->PtrSuiv;
                            else
                                {
                                L2 = InitialiseListe(100);
                                if(L2)
                                    {
                                    ConcateneListe(L1, L2);
                                    L1=L1->PtrSuiv;
                                    }
                                else
                                    LECTURE=FALSE;
                                }
                            }
                        }
                    }
/*-------------------------------------------------------------------------
  La lecture vient de se terminer, mais est-ce que notre liste n'est pas
trop longue, vu qu'on lui insére des sous-listes de 100 éléments?
-------------------------------------------------------------------------*/
                if(!L1->PtrData)  /* il y a t-il qque chose sur notre élé-   */
                    L1=L1->PtrPrec;   /* ment? Non: élément précédent*/
                if(L1->PtrSuiv) 
                    {                /* si il y des éléments aprés le dernier */
                    L2 = L1->PtrSuiv;/* éléments traité alors on récupére l'a */
                    L1->PtrSuiv = NULL; /*dresse du premier et on les efface  */
                    EffaceListe(L2, EFF_RIEN);  /* comme une liste */
                    }
                }
            fclose(entree);
            printf("\n");
            }
        FreeMem(BufLecture, 1025);
        }
    return(Fichier_Ancre);
    }
