/***************************************
*                                      *
*   Copyright (c) 1998 Jean-Eric Pin   *
*   All rights reserved.               *
*                                      *
*   TAB = 2 spaces                     *
*                                      *
***************************************/

/*-------------------------------------------------------------------
 * Menu.c    Jean-Eric Pin 07/12/96
 *-------------------------------------------------------------------
 */     

#include <stdlib.h>
#include <stdio.h>
#include "Main.h"
#include "Menu.h"
#include "Calcul.h"
#include "Espace.h"
#include "Exemples.h"
#include "FichierUnix.h"
#include "Globales.h"
#include "Initialisation.h"
#include "Inverses.h"
#include "Memoire.h"
#include "Preferences.h"
#include "Reduction.h"
#include "Sortie.h"
#include "SortieLaTeX.h"
#include "SortieDclasses.h"
#include "SortieLaTeXDclasses.h"
#include "SortieVarietes.h"
#include "SortieLaTeXVarietes.h"
#include "Syntactique.h"
#include "Utilitaires.h"

extern unsigned short NbEtats, NbLettres, NbChiffresNbElements, TypeSemigroupe, TypeCalcul,
                      OptionAction, SemigroupeRenverse, SauvegardeSouhaitee,
                      SortieLaTeX, SemiReduit, PartiePointee, EtatInitial1, 
                      InitiauxDejaSpecifies, FinauxDejaSpecifies;
extern unsigned long TailleMaxi, NbElements, NbIdempotents;
extern unsigned long TailleTableDeHachage, TailleTableDeHachageMoinsUn, CalculsEffectues;
extern Entree_ Entree;
extern Lecture_ LectureFichier; 
extern Produit_ Produit, ProduitNormal;
extern info *Table;     /* La table contenant les informations sur les elements */
extern char **Messages;
extern char *Yes, *No;
extern char NomFichier[255];
extern char CheminPref[255];
extern char DirBABEL[255];
extern FILE *fichierLaTeX;    /* Voir Main.c */

lettre *Mot;
short OptionMenu;  

/****************************************************
*
* MenuLaTeX. OK
*
****************************************************/

void MenuLaTeX(void)
{
  char c;
  
  SortieLaTeX = SemiReduit = 0;
  printf("%s \n", Messages[Menu_Sortie_LaTeX]);
  do
  {
    scanf("%c", &c);
  }
  while (!((c == Yes[0]) || (c == Yes[1]) || (c == No[0]) || (c == No[1])));
  SortieLaTeX = ((c == Yes[0]) || (c == Yes[1]));
  if (SortieLaTeX) 
  {
    printf("%s \n", Messages[Menu_LaTeX_Reduit]);
    do
    {
      scanf("%c", &c);
    }
    while (!((c == Yes[0]) || (c == Yes[1]) || (c == No[0]) || (c == No[1])));
    SemiReduit = ((c == Yes[0]) || (c == Yes[1]));
  }
}

/****************************************************
*
* Menu. OK
*
****************************************************/

void Menu(void)
{
  SemigroupeRenverse   = SauvegardeSouhaitee
                      = InitiauxDejaSpecifies
                      = FinauxDejaSpecifies
                      = PartiePointee
                      = EtatInitial1 
                      = 0;  /* Remise a jour preventive */
  printf("%s\n", Messages[M_Give_your_choice]);                  /* Donner votre choix */
  printf("(%1d) %s\n", Semigroupe, Messages[M_Semigroup]);      /* Semigroupe */
  printf("(%1d) %s\n", Monoide, Messages[M_Monoid]);            /* Monoide */
  printf("(%1d) %s\n", SemigroupeSyntactique, Messages[M_Syntactic_Semigroup]);  /* Semigroupe syntactique ordonne */
  printf("(%1d) %s\n", MonoideSyntactique, Messages[M_Syntactic_Monoid]);        /* Monoide syntactique ordonne */
  printf("(%1d) %s\n", Exemple, Messages[M_Standard_example]);  /* Exemple classique */
  printf("(%1d) %s\n", Fichier, Messages[M_Read_a_file]);        /* Lire un fichier */
  printf("(%1d) %s\n", Prefs, Messages[M_Prefs]);                /* Modifier les preferences */
  printf("(%1d) %s\n", Prefs + 1, Messages[M_Quit_Semigroupe]);  /* Quitter Semigroupe */
  do
  {
    if (scanf("%hd", &OptionMenu) != 1)
    {
      printf("scanf error\n");
      exit(1);
    }
  }
  while ((OptionMenu < Semigroupe) || (OptionMenu > Prefs + 1));
  
  switch (OptionMenu)
  {
    case Semigroupe:
      TypeCalcul = Semigroupe;
      MenuSemigroupe();
    break;
      
    case Monoide:
      TypeCalcul = Monoide;
      MenuSemigroupe();
    break;
      
    case SemigroupeSyntactique:
      TypeCalcul = Semigroupe;
      PartiePointee = 1;
      MenuSemigroupe();
    break;
      
    case MonoideSyntactique:
      TypeCalcul = Monoide;
      PartiePointee = 1;
      MenuSemigroupe();
    break;
      
    case Exemple:
      MenuExemple();
    break;

    case Fichier:
    {
      FILE *fichier;
      
      do
      {
        ChoixNomFichier();
        fichier = Ouverture(NomFichier, "r");
      }
      while (!fichier);
      LectureExemple(fichier);
    }
    break;

    case Prefs:
      ModificationPreferences(CheminPref, DirBABEL);
    break;
      
    case (Prefs + 1):
    break;
  }
  if (SemigroupeRenverse)
    Produit = ProduitRenverse;
  else
    Produit = ProduitNormal;
}    /* Menu. */

/****************************************************
*
* EntreeTailleAlphabet. OK
*
****************************************************/

void EntreeTailleAlphabet(void)
{
  printf("%s \n", Messages[M_Size_alphabet]);
  if (scanf("%hu", &NbLettres) != 1)
  {
    printf("scanf error\n");
    exit(1);
  }
}

/****************************************************
*
* EntreeTypeSemigroupe. OK
*
****************************************************/

void EntreeTypeSemigroupe(void)
{
  printf("%s\n", Messages[M_Type_of_semigroup]);  /* Donner le type du semigroupe */
  printf("(%1d) %s\n", ParTransitions, Messages[M_Transitions]);
  printf("(%1d) %s\n", ParTransitionsPartielles, Messages[M_Partial_transitions]);
  printf("(%1d) %s\n", MatricesBooleennes, Messages[M_Boolean_matrices]);
  printf("(%1d) %s\n", MatricesMaxPlus, Messages[M_MaxPlus_matrices]);
  printf("(%1d) %s\n", MatricesMinPlus, Messages[M_MinPlus_matrices]);
  printf("(%1d) %s\n", MatricesMaxPlusTropicales, Messages[M_MaxPlusTrop_matrices]);
  printf("(%1d) %s\n", MatricesMinPlusTropicales, Messages[M_MinPlusTrop_matrices]);
  printf("(%1d) %s\n", MatricesMaxPlusProjectives, Messages[M_MaxPlusProj_matrices]);
  printf("(%1d) %s\n", MatricesEntieres, Messages[M_Matrices_integer_coefficients]);
  do
  {
    if (scanf("%hu", &TypeSemigroupe) != 1)
    {
      printf("scanf error\n");
      exit(1);
    }
  }
  while ((TypeSemigroupe < ParTransitions) || (TypeSemigroupe > M_Matrices_integer_coefficients));
}

/****************************************************
*
* MenuSemigroupe. OK
*
****************************************************/

void MenuSemigroupe(void)
{
  char c;

  EntreeTailleAlphabet();
  EntreeTypeSemigroupe();
  EtatInitial1 = (!PartiePointee) || (TypeSemigroupe == ParTransitions) || (TypeSemigroupe == ParTransitionsPartielles);
  FinauxDejaSpecifies = (!PartiePointee) || (TypeSemigroupe > MatricesEntieres);
  InitiauxDejaSpecifies = EtatInitial1;
  /* Souhaitez-vous specifier les etats initiaux et finaux (o/n) ? */
  if (!FinauxDejaSpecifies)
  {
    printf("%s ", (InitiauxDejaSpecifies) ? Messages[M_Use_Initial_Final] : Messages[M_Use_Final]);
    do
    {
      scanf("%c", &c);
    }
    while (!((c == Yes[0]) || (c == Yes[1]) || (c == No[0]) || (c == No[1])));
    FinauxDejaSpecifies = ((c == No[0]) || (c == No[1])); /* Il faudra specifier les etats finaux */
  }
  Choix();
  Entree();
  TailleMaxi = EstimationTailleMaxi();  /* La taille du %s doit etre au plus */ 
  printf("%s %s %s %1lu\n", Messages[M_Size_at_most],
          TypeCalcul == Semigroupe ? Messages[M_Of_semigroup] : Messages[M_Of_monoid],
          Messages[M_Size_should_be], TailleMaxi);
/*  printf("%s ", Messages[M_Reverse_semigroup]);   Souhaitez-vous le calcul du semigroupe dual (o/n) ? 
  do
  {
    scanf("%c", &c);
  }
  while (!((c == Yes[0]) || (c == Yes[1]) || (c == No[0]) || (c == No[1])));
  SemigroupeRenverse = ((c == Yes[0]) || (c == Yes[1])); */
   printf("%s ", Messages[M_Save_generators]);  /* Voulez-vous sauvegarder ces generateurs (o/n) ? */
  do
  {
    scanf("%c", &c);
  }
  while (!((c == Yes[0]) || (c == Yes[1]) || (c == No[0]) || (c == No[1])));
  SauvegardeSouhaitee = ((c == Yes[0]) || (c == Yes[1]));
  if (SauvegardeSouhaitee)
    DialogueSauvegardeFichier();
  TailleTableDeHachage = EstimationTailleTableDeHachage(TailleMaxi);
  TailleTableDeHachageMoinsUn = TailleTableDeHachage - 1;
}

/****************************************************
*
* MenuExemple. OK
*
****************************************************/

void MenuExemple(void)
{
  short n, p, s, OptionExemple;
  
  printf("%s\n", Messages[M_Type_of_computation]);    /* Donner le type de calcul : */
  printf("(%1d) %s\n", OptionSn, Messages[M_Symmetric_group]);
  printf("(%1d) %s\n", OptionTn, Messages[M_Monoid_Tn]);
  printf("(%1d) %s\n", OptionFn, Messages[M_Monoid_Fn]);
  printf("(%1d) %s\n", OptionIn, Messages[M_Monoid_In]);
  printf("(%1d) %s\n", OptionMultn, Messages[M_Monoid_Multn]);
  printf("(%1d) %s\n", OptionRBn, Messages[M_Monoid_RBn]);
  printf("(%1d) %s\n", OptionOn, Messages[M_Monoid_On]);
  printf("(%1d) %s\n", OptionPOIn, Messages[M_Monoid_POIn]);
  printf("(%1d) %s\n", OptionPOPIn, Messages[M_Monoid_POPIn]);
  printf("(%1d) %s\n", OptionZnZ, Messages[M_GroupZn]);
  printf("(%1d) %s\n", OptionBAn, Messages[M_Semigroup_BAn]);
  printf("(%1d) %s\n", OptionMBAn, Messages[M_Monoid_BAn]);
  printf("(%1d) %s\n", OptionTrn, Messages[M_Triangular_Boolean_matrices]);
  printf("(%1d) %s\n", OptionUn, Messages[M_Unitriangular_Boolean_matrices]);
  printf("(%1d) %s\n", OptionSyntactic, Messages[M_Syntactic]);
  printf("(%1d) %s\n", OptionThresholdCountern, Messages[M_Threshold_Counter]);
  printf("(%1d) %s\n", OptionTwoLittleMatrices, Messages[M_Two_little_matrices]);
  printf("(%1d) %s\n", OptionNonKnast, Messages[M_LJ_not_in_B1]);
  printf("(%1d) %s\n", OptionExempleTransitions, Messages[M_Example_transitions_semigroup]);
  printf("(%1d) %s\n", OptionMatricesBooleennes, Messages[M_Example_Boolean_matrices]);
  printf("(%1d) %s\n", OptionMatricesEntieres, Messages[M_Example_matrices_integer_entries]);
  printf("(%1d) %s\n", OptionMatricesMaxPlus, Messages[M_Example_matrices_MaxPlus]);
  
  do
  {
    if (scanf("%hd", &OptionExemple) != 1)
    {
      printf("scanf error\n");
      exit(1);
    }
  }
  while ((OptionExemple < OptionSn) || (OptionExemple > OptionMatricesMaxPlus));

  switch (OptionExemple)
  {
    case OptionSn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 8)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Sn(n);
    break;
      
    case OptionTn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 7)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Tn(n);
    break;

    case OptionFn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 7)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Fn(n);
    break;

    case OptionIn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 8)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      In(n);
    break;

    case OptionMultn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Multiplication(n);
    break;

    case OptionRBn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 4)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      RBn(n);
    break;

    case OptionOn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 13)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      On(n);
    break;

    case OptionPOIn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 12)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      POIn(n);
    break;

    case OptionPOPIn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 11)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      POPIn(n);
    break;

    case OptionZnZ:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      ZnZ(n);
    break;

    case OptionBAn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      BAn(n);
    break;

    case OptionMBAn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      MBAn(n);
    break;

    case OptionTrn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 6)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Trn(n);
    break;

    case OptionUn:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf("(%s 7)", Messages[M_at_most]);
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      Un(n);
    break;
      
    case OptionSyntactic:
      ExempleSyntactiqueOrdonne();
    break;
      
    case OptionThresholdCountern:
      printf("%s ", Messages[M_Give_the_value_of_n]);  /* Donner la valeur de n */
      printf(" : ");
      if (scanf("%hd", &n) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      CompteurSeuil(n);
    break;

    case OptionTwoLittleMatrices:
      printf("%s\n", Messages[M_Z_st]);    /* Semianneau Z_st */
      printf("%s ", Messages[M_Threshold_semiring]);  /* Donner la valeur du seuil s */
      printf(" : ");
      if (scanf("%hd", &s) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      printf("%s ", Messages[M_Period_semiring]);  /* Donner la valeur de la periode p */
#if SYSTEME == MAC
      printf("(%s 20)", Messages[M_at_most]);
#endif   
      printf(" : ");
      if (scanf("%hd", &p) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      DeuxPetitesMatrices(s, p);
    break;

    case OptionNonKnast:
      ExempleNonKnast();
    break;

    case OptionExempleTransitions:
      ExempleTransitions();
    break;

    case OptionMatricesBooleennes:
      ExempleMatricesBooleennes();
    break;

    case OptionMatricesEntieres:
      ExempleMatricesEntieres();
    break;
      
    case OptionMatricesMaxPlus:
      ExempleMatricesMaxPlus();
    break;
  }
  TailleTableDeHachage = EstimationTailleTableDeHachage(TailleMaxi + 1);
  TailleTableDeHachageMoinsUn = TailleTableDeHachage - 1;
/* "La taille du %s est */
  printf("%s %s %s ", Messages[M_The_size_of], TypeCalcul == Semigroupe ? Messages[M_this_semi] : Messages[M_this_mono], Messages[M_is]);
  printf(" <= %1lu\n", TailleMaxi);  
}

/****************************************************
*
* MenuVariete. OK
*
****************************************************/

void MenuVariete(void)
{
  short OptionsVariete[11];
  short option = 0, i, OptionVariete = 0;
  
  SortieLaTeX ? SortieLaTeXEstCommutatif(fichierLaTeX) : SortieEstCommutatif();
   SortieLaTeX ? SortieLaTeXEstIdempotent(fichierLaTeX) : SortieEstIdempotent();
   SortieLaTeX ? SortieLaTeXEstNilpotent(fichierLaTeX) : SortieEstNilpotent();
   SortieLaTeX ? SortieLaTeXEstAperiodique(fichierLaTeX) : SortieEstAperiodique();
   SortieLaTeX ? SortieLaTeXEstUnGroupe(fichierLaTeX) : SortieEstUnGroupe();
   SortieLaTeX ? SortieLaTeXEstJRLtrivial(fichierLaTeX) : SortieEstJRLtrivial();
  if ((CalculsEffectues & CALCUL_IDEMPOTENTS) == 0)
    CalculIdempotents();
  /* Si le calcul est rapide, on applique les algorithmes sans poser de question */
  if ((NbIdempotents * NbIdempotents) < SMALL)  /* Algorithmes en O(|E(S)|^2) */
  {
     SortieLaTeX ? SortieLaTeXEstEcom(fichierLaTeX) : SortieEstEcom();
     SortieLaTeX ? SortieLaTeXEstBG(fichierLaTeX) : SortieEstBG();
  }
  else
  {
    OptionsVariete[++option] = M_Ecom;
    OptionsVariete[++option] = M_BG;
  }
  if (TypeCalcul == Semigroupe)    /* Calcul de semigroupes */
  {
    /* Si le calcul est rapide, on applique les algorithmes sans poser de question */    
    if ((NbElements * NbIdempotents) < SMALL)  /* Algorithmes en O(|S||E(S)|) */
    {
       SortieLaTeX ? SortieLaTeXEstL1(fichierLaTeX) : SortieEstL1();
      SortieLaTeX ? SortieLaTeXEstLG(fichierLaTeX) : SortieEstLG();
    }
    else
    {
      OptionsVariete[++option] = M_L1;
      OptionsVariete[++option] = M_LG;
    }
    OptionsVariete[++option] = M_B1;
    if (PartiePointee)
      OptionsVariete[++option] = M_B1Plus;
  }
  /* Si le calcul est rapide, on applique les algorithmes sans poser de question */
  if ((NbElements * NbElements) < SMALL)  /* Algorithmes en O(|S|^2) */
  {
     SortieLaTeX ? SortieLaTeXEstDA(fichierLaTeX) : SortieEstDA();
     SortieLaTeX ? SortieLaTeXEstDS(fichierLaTeX) : SortieEstDS();
  }
  else
  {
    OptionsVariete[++option] = M_DA;
    OptionsVariete[++option] = M_DS;
  }
  /* Si le calcul est rapide, on applique les algorithmes sans poser de question */
  if ((NbElements * NbElements * NbElements) < SMALL)  /* Algorithmes en O(|S|^3) */
  {
     SortieLaTeX ? SortieLaTeXEstRvL(fichierLaTeX) : SortieEstRvL();
  }
  else
  {
    OptionsVariete[++option] = M_RvL;
  }
  if (option != 0)
  {
    printf("%s\n", Messages[M_Which_variety]);  /* Sur quelle variete souhaitez-vous effectuer le test ? */
    for (i = 1; i <= option; i++)
      printf("(%1d) %s\n", i, Messages[OptionsVariete[i]]);
    do
    {
      if (scanf("%hd", &OptionVariete) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
    }
    while ((OptionVariete < 1) || (OptionVariete > option));
  }
  OptionVariete = OptionsVariete[OptionVariete];
  switch (OptionVariete)
  {
    case M_Ecom:
       SortieLaTeX ? SortieLaTeXEstEcom(fichierLaTeX) : SortieEstEcom();
    break;

    case M_BG:
       SortieLaTeX ? SortieLaTeXEstBG(fichierLaTeX) : SortieEstBG();
    break;

    case M_DA:
       SortieLaTeX ? SortieLaTeXEstDA(fichierLaTeX) : SortieEstDA();
    break;

    case M_DS:
       SortieLaTeX ? SortieLaTeXEstDS(fichierLaTeX) : SortieEstDS();
    break;

    case M_RvL:
       SortieLaTeX ? SortieLaTeXEstRvL(fichierLaTeX) : SortieEstRvL();
    break;

    case M_L1:
       SortieLaTeX ? SortieLaTeXEstL1(fichierLaTeX) : SortieEstL1();
    break;

    case M_LG:
       SortieLaTeX ? SortieLaTeXEstLG(fichierLaTeX) : SortieEstLG();
    break;

    case M_B1:
       SortieLaTeX ? SortieLaTeXEstB1(fichierLaTeX) : SortieEstB1();
    break; 
      
    case M_B1Plus:
       SortieLaTeX ? SortieLaTeXEstB1Plus(fichierLaTeX) : SortieEstB1Plus();
    break;         
  }
}

/****************************************************
*
* Options. OK
*
****************************************************/

void MenuActions(void)
{
  unsigned long n, e;
  
  NbChiffresNbElements = NombreDeChiffres(NbElements);
  printf("%s\n", Messages[M_Options]);                                                          /* Options : */
  printf("(%1d) %s\n", OptionListeElements, Messages[M_List_of_elements]);                      /* Liste des elements */
  printf("(%1d) %s\n", OptionListeRelations, Messages[M_List_of_relations]);                    /* Liste des relations */
  printf("(%1d) %s\n", OptionListeIdempotents, Messages[M_List_of_idempotents]);                /* Liste des idempotents */
  if (PartiePointee)
    printf("(%1d) %s\n", OptionOrdreSyntactique, Messages[M_SyntacticOrder]);                    /* Ordre syntactique */  
  printf("(%1d) %s\n", OptionIdealMinimal - !PartiePointee, Messages[M_MinimalIdeal]);          /* Relations de Green */
  printf("(%1d) %s\n", OptionRelationsDeGreen - !PartiePointee, Messages[M_GreenRelations]);    /* Relations de Green */
  printf("(%1d) %s\n", OptionInverses - !PartiePointee, Messages[M_Inverses]);                  /* Calcul des inverses */
  printf("(%1d) %s\n", OptionMonoideLocal - !PartiePointee, Messages[M_Local_monoid]);          /* Calcul de monoide local */
  printf("(%1d) %s\n", OptionIdealDroit - !PartiePointee, Messages[M_Right_Ideal]);              /* Calcul de l'ideal a droite */
  printf("(%1d) %s\n", OptionIdealGauche - !PartiePointee, Messages[M_Left_Ideal]);              /* Calcul de l'ideal a gauche */
  printf("(%1d) %s\n", OptionCalculElement - !PartiePointee, Messages[M_Computation_element]);  /* Calcul d'un element */
  printf("(%1d) %s\n", OptionNoyau - !PartiePointee, Messages[M_Kernel]);                        /* Appartenance a une variete */
  printf("(%1d) %s\n", OptionCalculVariete - !PartiePointee, Messages[M_Variety_tests]);        /* Appartenance a une variete */
  printf("(%1d) %s\n", OptionRetour - !PartiePointee, Messages[M_Do_another_computation]);      /* Effectuer un autre calcul */
  printf("(%1d) %s\n", OptionFin - !PartiePointee, Messages[M_Quit_Semigroupe]);                /* Quitter Semigroupe */

  do
  {
    if (scanf("%hu", &OptionAction) != 1)
    {
      printf("scanf error\n");
      exit(1);
    }
  }
  while ((OptionAction < OptionListeElements) || (OptionAction > (OptionFin - !PartiePointee)));

  if (OptionAction >= OptionOrdreSyntactique)
    OptionAction = OptionAction + !PartiePointee;
  switch (OptionAction)
  {
    case OptionListeElements: 
       SortieLaTeX ? SortieLaTeXListeElements(fichierLaTeX) : SortieListeElements();
    break;
      
    case OptionListeRelations:
      SortieLaTeX ? SortieLaTeXRelations(fichierLaTeX) : SortieRelations();
    break;
      
    case OptionListeIdempotents:
      SortieLaTeX ? SortieLaTeXIdempotents(fichierLaTeX) : SortieListeIdempotents();
    break;
      
    case OptionOrdreSyntactique:
      if (!(CalculsEffectues & CALCUL_P))
        CalculSyntactique();   

      SortieLaTeX ? SortieLaTeXSyntactique(fichierLaTeX) : SortieSyntactique();
    break;
      
    case OptionIdealMinimal:
      SortieLaTeX ? SortieLaTeXIdealMinimal(fichierLaTeX) : SortieIdealMinimal();
    break;
      
    case OptionRelationsDeGreen:
       SortieLaTeX ? SortieLaTeXDclasses(fichierLaTeX) : SortieDclasses();
    break;
      
    case OptionInverses:
      CalculInverses();
      SortieLaTeX ? SortieLaTeXInverses(fichierLaTeX) : SortieInverses();
    break;
      
    case OptionMonoideLocal:
      Mot = AlloueMemoireMot(LONGUEURMOTMAX);
      printf("%s\ne = ", Messages[M_Give_idempotent]);  /* Donner l'idempotent */  
      if (scanf("%s", Mot) != 1)
      {
        printf("scanf error\n");
        exit(1);
      }
      e = Reduction(Mot);
      if ((Table[e].Statut & IDEMPOTENT) == 0)
        printf("%s\n", Messages[M_Is_not_idempotent]);  /* Cet element n'est pas idempotent ! */
      else
      {
        CalculMonoideLocal(e);
        SortieLaTeX ? SortieLaTeXMonoideLocal(e, fichierLaTeX) : SortieMonoideLocal(e);
      }
      free(Mot);
    break;
    
    case OptionIdealDroit:
      Mot = AlloueMemoireMot(LONGUEURMOTMAX);
      do
      {
        printf("%s\nu = ", Messages[M_Give_word]);  /* Donner le mot*/
        if (scanf("%s", Mot) != 1)
        {
          printf("scanf error\n");
          exit(1);
        }
      }
      while (FiltreAlphabet(Mot) == 0);
      n = Reduction(Mot);
      CalculIdealDroit(n);
      SortieLaTeX ? SortieLaTeXIdealDroit(n, fichierLaTeX) : SortieIdealDroit(n);
      free(Mot);
    break;
    
    case OptionIdealGauche:
      Mot = AlloueMemoireMot(LONGUEURMOTMAX);
      do
      {
        printf("%s\nu = ", Messages[M_Give_word]);  /* Donner le mot*/
        if (scanf("%s", Mot) != 1)
        {
          printf("scanf error\n");
          exit(1);
        }
      }
      while (FiltreAlphabet(Mot) == 0);
      n = Reduction(Mot);
      CalculIdealGauche(n);
      SortieLaTeX ? SortieLaTeXIdealGauche(n, fichierLaTeX) : SortieIdealGauche(n);
      free(Mot);
    break;
    
    case OptionCalculElement: 
      Mot = AlloueMemoireMot(LONGUEURMOTMAX);
      do
      {
        printf("%s\nu = ", Messages[M_Give_word]);  /* Donner le mot*/
        if (scanf("%s", Mot) != 1)
        {
          printf("scanf error\n");
          exit(1);
        }
      }
      while (FiltreAlphabet(Mot) == 0);
      n = Reduction(Mot);
      SortieMot(n);
      printf("\n");
      free(Mot);
    break;  
    
    case OptionNoyau:
      if ((CalculsEffectues & CALCUL_KS) == 0)
        CalculKS();
      SortieLaTeX ? SortieLaTeXKS(fichierLaTeX) : SortieKS();
    break;  
    
    case OptionCalculVariete:
      MenuVariete(); 
    break;  
    
    case OptionRetour: case OptionFin:
      printf("%s\n\n", Messages[M_FreeMemory]);  
      LibereMemoire();  
    break;  
    
    default: 
    break;
  }
}