/***************************************************************************
                          mon_essai.cpp  -  description
                             -------------------
    begin                : dim jui  6 13:54:23 CEST 2003
    copyright            : (C) 2003 by Troumad
    email                : troumad@libertysurf.fr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <string.h>
#include <math.h>

#include "mon_essai.h"

int nbecran=0;
int nb_couleur[5];
char ch_xinerama[100];

QIconViewItem * selection=NULL;

Mon_essai::Mon_essai(QWidget *parent, const char *name) : le_mien(parent, name)
{
}

Mon_essai::~Mon_essai()
{
}

void Mon_essai::placeecran()
{
 ecran(selection,this);
 this->xf_option->setCurrentPage(1);  // astuce pour mettre à jour le premier onglet
 this->xf_option->setCurrentPage(0);
}

void Mon_essai::gardemode()
{
 ecran_n(selection->index())->garde_mode=this->mem_mode->isChecked();
 afficheicone(ecran_n(selection->index())->num_mode,this);
}

void Mon_essai::affichetaille(int taille)
{
 ecran_n(selection->index())->num_mode=taille;
 afficheicone(taille,this);
}

void Mon_essai::afficheecran(QIconViewItem * qui)
{
 char s[5000];
 char ch[100];
 s_sc * lequel;
 s_m * moniteur;
 s_e * ce;
 sub_ecran * mode;
 int i,j,k,taille;

 if (selection!=NULL) ecran(selection,this);
 selection=qui;
 lequel=ecran_n(qui->index());

 sprintf(s,"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;écran : %s ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Carte écran : %s ;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Moniteur : %s<br>Modes existants :",lequel->identifier,lequel->c_e,lequel->moniteur);

 for(mode=lequel->mode;mode->couleurs!=lequel->couleurs && mode->suiv;mode=mode->suiv);
 i=0;j=0;
 while (mode->mode[i][0]!=0)
 {
  sprintf(ch," %c%dx%d%c",'"',mode->mode[i][0],mode->mode[i][1],'"');
  i++;
  while (s[j]!=0) j++;
  strcpy(s+j,ch);
 }
 while (s[j]!=0) j++;
 taille=lequel->num_mode;
 this->choisi_taille->setMaxValue(i-1);
 lequel->num_mode=taille;
 if (lequel->modeline!=NULL)
 if (lequel->modeline[0]!=0)
 {
  i=0;k=0;
  strcpy(s+j,"<br>Modes générés : ");
  j+=20;
  do
  {
   k++;
   i+=10;
   s[j]=' ';
   j++;
   s[j]='"';
   j++;
   while (lequel->modeline[i]!='"')
   {
    s[j]=lequel->modeline[i];
    i++;
    j++;
   }
   i++;
   s[j]='"';
   j++;
   while (lequel->modeline[i]!='\n')
    i++;
   i++;
   if (lequel->mode_perso==TRUE)
   {
    taille=lequel->num_mode;
    this->choisi_taille->setMaxValue(k-1);
    lequel->num_mode=taille;
   }
  } while (lequel->modeline[i]!=0);
  s[j]=0;
 }
 i=min(choisi_taille->maxValue(),lequel->num_mode);// pour être sur de changer de valeurs et de conserver lequel->num_mode
 this->choisi_taille->setValue(choisi_taille->maxValue());
 this->choisi_taille->setValue(choisi_taille->minValue());
 this->choisi_taille->setValue(i);
 this->quel_ecran->setText(s);
 this->mem_mode->setChecked(lequel->garde_mode);

 this->nom_ecran->setText(lequel->moniteur);
 moniteur=((s_m *)(en_xf[monitor].info));
 while (moniteur->suiv!=NULL && strcmp(moniteur->identifier,lequel->moniteur)!=0) moniteur=moniteur->suiv;
 sscanf(moniteur->vert,"%d-%d",&i,&j);
 sprintf(s,"%d",j);
 this->freq_v->setText(s);
 sscanf(moniteur->hori,"%d-%d",&i,&j);
 sprintf(s,"%d",j);
 this->freq_v_min->setText(s);
 sprintf(s,"%d",j);
 this->freq_h->setText(s);
 sprintf(s,"%d",i);
 this->freq_h_min->setText(s);

 if (lequel->modeline!=NULL)
 {
  this->liste_modeline->setText(lequel->modeline);
 }
 else
 {
  this->liste_modeline->setText("Aucune valeur de calculée pour le moment<br>Pour en calculer, passez par l'onglet 'Ecran'");
 }
 sprintf(s,"%d",lequel->nb_mode);
 this->nb_mode->setText(s);
 sprintf(s,"%d",lequel->HSP);
 this->HSP->setText(s);
 sprintf(s,"%d",lequel->HBT);
 this->HBT->setText(s);
 sprintf(s,"%d",lequel->VSP);
 this->VSP->setText(s);
 sprintf(s,"%d",lequel->bp_max);
 this->bp_max->setText(s);
 sprintf(s,"%d",lequel->bp_min);
 this->bp_min->setText(s);
 sprintf(s,"%d",lequel->largeur_max);
 this->plus_grande_largeur->setText(s);
 sprintf(s,"%d",lequel->largeur_min);
 this->plus_petite_largeur->setText(s);
 this->mode_freq->setChecked(lequel->mode_perso);
 this->mode_ori->setChecked(!lequel->mode_perso);
 ajuste_mode_choisi(this);

 this->vendeur_ecran->setText(moniteur->vendeur);

 this->ident_carte_ecran->setText(lequel->c_e);
 ce=((s_e *)(en_xf[device].info));
 while (ce->suiv!=NULL && strcmp(ce->identifier,lequel->c_e)!=0) ce=ce->suiv;
 this->nom_carte_ecran->setText(ce->nom);
 this->vendeur_carte_ecran->setText(ce->vendeur);
 this->pilote_carte_ecran->setText(ce->pilote);
 this->place_carte_ecran->setText(ce->place);
 sprintf(s,"%d",ce->ram);
 this->ram_carte_ecran->setText(s);

 //lequel=((s_sc *)(en_xf[screen].info)); ?????????
 mode=lequel->mode; // parcours du nombre de mode
 i=0;
 while (mode->suiv)
 {
  i++;
  mode=mode->suiv;
 }

 this->choisi_profondeur->setMaxCount(i);

 switch (lequel->couleurs)
 {
  case  8 : this->choisi_profondeur->setCurrentItem(0);break;
  case 15 : this->choisi_profondeur->setCurrentItem(1);break;
  case 16 : this->choisi_profondeur->setCurrentItem(2);break;
  case 24 : this->choisi_profondeur->setCurrentItem(3);break;
  case 30 : this->choisi_profondeur->setCurrentItem(4);break;
 }

 this->xf_option->setCurrentPage(1); // astuce pour raffrichir l'affichage
 this->xf_option->setCurrentPage(0);
}

void Mon_essai::affichememoire()
{
 char s[30];
 int mem;
 s_sc * lequel;
 sub_ecran * mode;
 int i,k,l,L;

 switch (this->choisi_profondeur->currentItem())
 {
  case 0: mem=8;break;
  case 1: mem=15;break;
  case 2: mem=16;break;
  case 3: mem=24;break;
  case 4: mem=30;break;
 }


 lequel=ecran_n(selection->index());

 if (lequel->mode_perso==FALSE)
 {
  for(mode=lequel->mode;mode->couleurs!=lequel->couleurs && mode->suiv;mode=mode->suiv);
  mem*=(mode->mode[this->choisi_taille->value()][0]*mode->mode[this->choisi_taille->value()][1]/8)/1024;
 }
 else
 {
  if (lequel->modeline!=NULL)
  if (lequel->modeline[0]!=0)
  {
   i=0;k=-1; // le premier, k=0 est bon après le k++
   do
   {
    k++;
    i+=10;
    sscanf(lequel->modeline+i,"%dx%d",&l,&L);
    while (lequel->modeline[i]!='\n')
    i++;
    i++;
   } while (lequel->modeline[i]!=0 && k!=this->choisi_taille->value());
  }
  mem*=l*L/8/1024;
 }

 sprintf(s,"Mémoire vidéo requise : %d KiloOctets",mem);

 this->memoire_requise->setText( QString(s));
}

void Mon_essai::affichenbcouleur( int prof)
{
 char s[140];
 s_sc * lequel;
 int couleurs;

 switch (this->choisi_profondeur->currentItem())
 {
  case 0: couleurs=8;break;
  case 1: couleurs=15;break;
  case 2: couleurs=16;break;
  case 3: couleurs=24;break;
  case 4: couleurs=30;break;
  default : couleurs=0; // montrer l'erreur!
 }

 lequel=((s_sc *)(en_xf[screen].info));
 if (ch_xinerama[0]==0)
 {
  while (lequel->suiv!=NULL && strcmp((((s_l *)(en_xf[serverlayout].info))->ecran[selection->index()][0]),lequel->identifier)!=0)
  {
   lequel=lequel->suiv;
  }
  lequel->couleurs=couleurs;
 }
 else
 {
  while (lequel->suiv!=NULL)
  {
   lequel->couleurs=couleurs;
   lequel=lequel->suiv;
  }
  lequel->couleurs=couleurs;
 }

 sprintf(s,"%d couleurs%s",nb_couleur[prof],ch_xinerama);
 this->couleurs->setText( QString(s));
}

void Mon_essai::sauvegarde()
{
 struct lignes_change // Pour la méthode de sauvegarde
 {
  int ligne;
  char * mem;
  lignes_change * suiv;
 };

 struct modeligne // Pour stoquer les nouveaux modeline
 {
  char ligne[5000];
  modeligne*suiv;
 };

 char fin_ligne[5000];
 lignes_change * lc;
 lignes_change * pt_lc=NULL;
 modeligne * pt_ml=NULL;
 modeligne * ml;
 QIconViewItem * lui;
 QIconViewItem * autre;
 char * s;
 s_l * ch;
 s_sc * sc;
 s_m * moniteur;
 sub_ecran * mode;
 int i,j,k,l,x,y;
 char c=0; // Pour faire une chaîne de caractère vide.

 FILE * sortie;

 sortie=fopen("XF86Config-4","w");

 sc=((s_sc *)(en_xf[screen].info));  // recherhe des modes différents
 do
 {
  if (sc->mode_perso==TRUE)
  {
   if (pt_ml==NULL)
   {
    pt_ml=(modeligne *)malloc(sizeof(struct modeligne));
    ml=pt_ml;
   }
   else
   {
    pt_ml->suiv=(modeligne *)malloc(sizeof(struct modeligne));
    pt_ml=pt_ml->suiv;
   }
   pt_ml->suiv=NULL;

   k=0;
   i=0; // fabrication de la nouvelle ligne de mode pour la section screen.
   strcpy(pt_ml->ligne,"        Modes");
   j=13;l=0;
   do
   {
    i+=10;
    k++;
    if (k>sc->num_mode)
    {
     pt_ml->ligne[j]=' ';
     j++;
     pt_ml->ligne[j]='"';
     j++;
    }
    else
    {
     fin_ligne[l]=' ';
     l++;
     fin_ligne[l]='"';
     l++;
    }
    while (sc->modeline[i]!='"')
    {
     if (k>sc->num_mode)
     {
      pt_ml->ligne[j]=sc->modeline[i];
      j++;
     }
     else
     {
      fin_ligne[l]=sc->modeline[i];
      l++;
     }
     i++;
    }
    i++;
    if (k>sc->num_mode)
    {
     pt_ml->ligne[j]='"';
     j++;
    }
    else
    {
     fin_ligne[l]='"';
     l++;
    }
    while (sc->modeline[i]!='\n')
     i++;
    i++;
   } while (sc->modeline[i]!=0);
   pt_ml->ligne[j]=0;
   if (this->mem_mode->isChecked()==0) l=0; // on ne veux pas mémoriser les grands modes : on les détruits
   fin_ligne[l]='\n';
   fin_ligne[l+1]=0;
   strcpy(pt_ml->ligne+j,fin_ligne);

   mode=sc->mode;
   do
   {
    if (pt_lc==NULL)
    {
     pt_lc=(lignes_change *)malloc(sizeof(lignes_change));
     lc=pt_lc;
    }
    else
    {
     pt_lc->suiv=(lignes_change *)malloc(sizeof(lignes_change));
     pt_lc=pt_lc->suiv;
    }
    pt_lc->suiv=NULL;
    pt_lc->ligne=mode->ligne; // mémorisation de l'ancienne ligne
    pt_lc->mem=xf_s_aff[mode->ligne];
    xf_s_aff[mode->ligne]=pt_ml->ligne; // mise ne place de la nouvelle ligne
    mode=mode->suiv;
   }
   while (mode!=NULL);

   moniteur=((s_m *)(en_xf[monitor].info)); //recherche du moniteur
   while (moniteur->suiv!=NULL && strcmp(moniteur->identifier,sc->moniteur)!=0) moniteur=moniteur->suiv;

   for (l=moniteur->ligne;strncmp(xf_s_aff[l],"EndSection",10)!=0;l++)
   {
    i=0;
    while (xf_s_aff[l][i]==' ') i++;
    if (strncmp(xf_s_aff[l]+i,"ModeLine",8)==0)
    {
     pt_lc->suiv=(lignes_change *)malloc(sizeof(lignes_change)); // pas besoin de vérifier s'il est déjà initialiser, on l'a déjà initialiser dans la section screen
     pt_lc=pt_lc->suiv;
     pt_lc->suiv=NULL;
     pt_lc->ligne=l;
     pt_lc->mem=xf_s_aff[l];
     xf_s_aff[l]=&c; // la chaîne vide....
    }
   }
   xf_s_aff[pt_lc->ligne]=sc->modeline;
  }
  else if (sc->num_mode!=0) // juste le choix de la définition
  {

   for(mode=sc->mode;mode;mode=mode->suiv)
   {
    j=14;
    if (pt_lc==NULL)
    {
     pt_lc=(lignes_change *)malloc(sizeof(lignes_change));
     lc=pt_lc;
    }
    else
    {
     pt_lc->suiv=(lignes_change *)malloc(sizeof(lignes_change));
     pt_lc=pt_lc->suiv;
    }
    pt_lc->suiv=NULL;
    pt_lc->ligne=mode->ligne;
    pt_lc->mem=xf_s_aff[mode->ligne];
    if (pt_ml==NULL)
    {
     pt_ml=(modeligne *)malloc(sizeof(struct modeligne));
     ml=pt_ml;
    }
    else
    {
     pt_ml->suiv=(modeligne *)malloc(sizeof(struct modeligne));
     pt_ml=pt_ml->suiv;
    }
    pt_ml->suiv=NULL;
    xf_s_aff[mode->ligne]=pt_ml->ligne;
    strcpy(pt_ml->ligne,"         Modes ");
    for (i=sc->num_mode;mode->mode[i][0]!=0;i++)
    {
     sprintf(pt_ml->ligne+j," %c%dx%d%c",'"',mode->mode[i][0],mode->mode[i][1],'"');
     while (pt_ml->ligne[j]!=0) j++;
    }
    if (this->mem_mode->isChecked()!=0) // on ne veux pas mémoriser les grands modes
     for (i=0;mode->mode[i][0]!=0 && i<sc->num_mode;i++)
     {
      sprintf(pt_ml->ligne+j," %c%dx%d%c",'"',mode->mode[i][0],mode->mode[i][1],'"');
      while (pt_ml->ligne[j]!=0) j++;
     }
    pt_ml->ligne[j]='\n';
    pt_ml->ligne[j+1]=0;
   }
  }

  l=sc->ligne; // mise en place de la profondeur
  do
  {
   l++;
   i=0;
   while (xf_s_aff[l][i]==' ') i++;
  }
  while (strncmp(xf_s_aff[l]+i,"DefaultColorDepth",17)!=0);
  if (pt_lc==NULL)
  {
   pt_lc=(lignes_change *)malloc(sizeof(lignes_change));
   lc=pt_lc;
  }
  else
  {
   pt_lc->suiv=(lignes_change *)malloc(sizeof(lignes_change));
   pt_lc=pt_lc->suiv;
  }
  pt_lc->suiv=NULL;
  pt_lc->ligne=l;
  pt_lc->mem=xf_s_aff[l];
  if (pt_ml==NULL)
  {
   pt_ml=(modeligne *)malloc(sizeof(struct modeligne));
   ml=pt_ml;
  }
  else
  {
   pt_ml->suiv=(modeligne *)malloc(sizeof(struct modeligne));
   pt_ml=pt_ml->suiv;
  }
  pt_ml->suiv=NULL;
  xf_s_aff[l]=pt_ml->ligne;
  sprintf(pt_ml->ligne,"    DefaultColorDepth %d\n",sc->couleurs);
  sc=sc->suiv;
 } while (sc!=NULL);


 ch=((s_l *)(en_xf[serverlayout].info));  // placement des écrans
 if (selection!=NULL) ecran(selection,this);
 /*if (this->decalage-> ==TRUE) // positionnement Gauche-Droite-Dessus-Dessous
 {
  for (i=1;i<nbecran;i++) // lecture du placement des écrans et mise en forme du document
  {
   s=xf_s_aff[((s_l *)(en_xf[serverlayout].info))->ligne[i]]; // Plus simple à manier!
   lui=this->iconView1->firstItem(); // pour le moment, je ne gère que 2 écrans...
   autre=lui->nextItem();

   l=11;
   strcpy(s,"    Screen ");
   s[l]='"';
   l++;

   strcpy(s+l,ch->ecran[i][0]);
   while (s[l]) l++;
   s[l]='"';
   l++;
   s[l]=' ';
   l++;
   s[l]=0;


   if (lui->x()==autre->x())
   {
    if (lui->y()<autre->y())
    {
     strcpy(s+l,"Above");
     l+=5;
    }
    else
    {
     strcpy(s+l,"Below");
     l+=5;
    }
   }
   else
   {
    if (lui->x()<autre->x())
    {
     strcpy(s+l,"RightOf");
     l+=7;
    }
    else
    {
     strcpy(s+l,"LeftOf");
     l+=6;
    }
   }
   while (s[l]) l++;
   s[l]=' ';
   l++;
   s[l]='"';
   l++;
   s[l]=0;
   strcpy(s+l,ch->ecran[0][0]);
   while (s[l]) l++;
   s[l]='"';
   l++;
   s[l]=10;
   l++;
   s[l]=0;
  }
 }
 else // placement Absolu*/
 {
  lui=this->iconView1->firstItem();
  x=lui->x();
  y=lui->y();
  autre=lui;
  for (i=1;i<nbecran;i++) // trouver le x min et le y mzx
  {
   autre=autre->nextItem();
   x=min(x,autre->x());
   y=max(y,autre->y());
  }

  autre=lui;
  for (i=0;i<nbecran;i++,autre=autre->nextItem()) // lecture du placement des écrans et mise en forme du document
  {
   s=xf_s_aff[((s_l *)(en_xf[serverlayout].info))->ligne[i]]; // Plus simple à manier!
   l=11;
   strcpy(s,"    Screen ");
   s[l]='"';
   l++;
   strcpy(s+l,ch->ecran[i][0]);
   while (s[l]) l++;
   s[l]='"';
   l++;
   s[l]=' ';
   l++;
   s[l]=0;
   strcpy(s+l,"Absolute");
   l+=8;
   while (s[l]) l++;
   s[l]=' ';
   l++;
   sprintf(fin_ligne," %d %d %c%c",(autre->x()-x)*ECHELLE,(y-autre->y())*ECHELLE,10,0);
   strcpy(s+l,fin_ligne);
  }
 }

 for(i=0;i<li;i++)
 {
  fprintf(sortie,"%s",xf_s_aff[i]);
 }
 fclose(sortie);

 while (lc!=NULL)
 {
  pt_lc=lc->suiv;
  xf_s_aff[lc->ligne]=lc->mem;
  free(lc);
  lc=pt_lc;
 }

 while (ml!=NULL)
 {
  pt_ml=ml->suiv;
  free(ml);
  ml=pt_ml;
 }
}


void Mon_essai::changemodefreq()
{
 this->mode_freq->setChecked( this->mode_ori->isChecked()==0 );
 ajuste_mode_choisi(this);
}

void Mon_essai::changemodeori()
{
 this->mode_ori->setChecked( this->mode_freq->isChecked()==0 );
 ajuste_mode_choisi(this);
}


void Mon_essai::validexinerama(int etat)
{
 s_sc * lequel;
 int couleurs;
 char s[140];

 lequel=ecran_n(selection->index());
 switch (this->choisi_profondeur->currentItem())
 {
  case 0: couleurs=8;break;
  case 1: couleurs=15;break;
  case 2: couleurs=16;break;
  case 3: couleurs=24;break;
  case 4: couleurs=30;break;
 }
 if (etat==0)
 {
  ch_xinerama[0]=0;
 }
 else
 {
  ch_xinerama[0]='<';
  lequel=((s_sc *)(en_xf[screen].info));
  while (lequel!=NULL)
  {
   lequel->couleurs=couleurs;
   lequel=lequel->suiv;
  }
  /*Dialogue_Xinerama * averti_xinerama = new Dialogue_Xinerama();
  averti_xinerama->show();*/

  alerte("Attention Xinerama","Avec <b>Xinerama</b>, il faut de <b>tous</b> les écrans aient le même nombre de couleurs");

 }
 sprintf(s,"%d couleurs%s",nb_couleur[couleurs],ch_xinerama);
 this->couleurs->setText( QString(s));

}

void Mon_essai::calculemodeecran()
{
 // les variables sont celles du fichier http://www.freenix.org/unix/linux/HOWTO/XFree86-Video-Timings-HOWTO.html
 int DCF;     // nb max de pt/sec
 int DCFm;
 int HSF;     // fréquence horizontale max
 int HSFm;
 int VSF;     // freq vert max
 //int VSFm;    // Comme RRm
 int HFL;     // longueur de trame horizontale DCF/HSF.80%<HFL
 int VFL;     // l de trame v
 //int RR;      // fréquence de rafraichissement 72 (vue) < RR=DCF/(HFL.VFL) < VSF
 int RRm;     // RR minimun toléré (72 souvent car après l'écran clignote)
 //int RRM;     // RR maximum supporté par le matériel (utile uniquement pour les petites résolutions)
 int HR;      // résolution horizontale HR<HFL
 int VR;      // résolution verticale   VR<VFL, VR=3HR/4 pour les écrans 3/4 habituels
 float HSP;   // longueur du signal de synchronisation : 3,8 microsecondes (entre 3,5 et 4)
 int VSP;     // temps de suppresion verticale en microseconde
 int GT1,GT2; // tics "de sécurité" (guard time) de part et d'autre de l'impulsion de synchronisation
 //int HAT;     // durée utile : équivalent à HR, mais en millisecondes. HAT * DCF = HR
 float HBT;   // durée de service : équivalent à (HFL - HR), mais en millisecondes (micro?). HBT * DCF = (HFL - HR)
 //int HFP;     // fenêtre avant : synonyme d'HGT1
 //int HBP;     // fenêtre arrière : synonyme d'HGT2
 //int VAT;     // durée utile : équivalent à VR, mais en millisecondes. VAT * VSF = VR
 //int VBT;     // durée de service : équivalent à (VFL - VR), mais en millisecondes. VBT * VSF = (VFL - VR)
 //int VFP;     // fenêtre avant : synonyme de VGT
 //int VBT;     // fenêtre arrière : une seconde temporisation de sécurité après l'impulsion de synchronisation verticale. Souvent nulle.
 int SH1;     // le point où commencera l'impulsion de synchronisation horizontale
 int SH2;     // le point où se terminera cette impulsion de synchronisation
 int SV1;     // le numéro de la ligne où commencera l'impulsion de synchronisation verticale
 int SV2;     // le numéro de ligne où se terminera cette impulsion de synchronisation

 int freq; // fréquence réelle*10
 char *s;
 char *ch;
 char mot[200];
 int nb_mode;
 int largeur_max;
 int largeur_min;
 int pas;
 s_sc * lequel;
 QIconViewItem * s1;
 s1=selection;
 //int nb_point_max_visible;

 //int i;

 sscanf(this->bp_max->text(),"%d",&DCF);
 sscanf(this->bp_min->text(),"%d",&DCFm);
 sscanf(this->freq_h->text(),"%d",&HSF);
 sscanf(this->freq_v->text(),"%d",&VSF);
 sscanf(this->freq_h_min->text(),"%d",&HSFm);
 sscanf(this->freq_v_min->text(),"%d",&RRm);
 sscanf(this->HBT->text(),"%f",&HBT);   // pour mon écran SONY HMD-A200 au moins...
 sscanf(this->HSP->text(),"%f",&HSP);
 sscanf(this->VSP->text(),"%d",&VSP); // je ne sais pas si les données sont toujours données comme ça quand elles sont disponibles.



 GT1=(HBT-HSP)*DCF/2;
 GT2=GT1-GT1%8;
 GT1+=GT1%8;

 // Pour plus de fun, je commence à calculer le mode le plus puissant...

 // #Nom de mode  horloge  valeurs horizontales  valeurs verticales
 // Nom des variables :  DCF      HR  SH1 SH2 HFL       VR  SV1 SV2 VFL
 //    "752x564"         40       752 784 944 1088      564 567 569 611
 //                      44.5     752 792 976 1240      564 567 570 600
 // Attention : le nombre de points horizontaux doit être divisible par huit : 800 864 1024 1088...
 // Pour les lignes verticales, rien de cela : 600 603 609 630...

 // nb_point_max_visible=(DCF/RRm)*0.74/1.05=(nb_point_max)*reste
 // nb_point_max_visible=1000000*DCF/RRm*(0.74/1.05);
 // reste : 20% de perte avec les synchros horizontale (de chaque côté) et temps de montée du signal (5% de perte)
 // nb_point_max_visible=HR*VR=3HR²/4 => HR_max=sqrt(4nb_point_max_visible/3), mais attention, ce nombre doit être multiple de 8!
 // donc HR_max=sqrt(4nb_point_max_visible/3)-sqrt(4nb_point_max_visible/3)%8
 // HR=sqrt(4*nb_point_max_visible/3); // Méthode qui plante un peu : je cherche autrement!

 // autre méthode de calcul :
 // HFL=HR+HBT*DCP ou HR=HFL-HBT*DCF
 // de même : VFL=VR+VSP*DCF/HFL=3HR/4+VSP*DCF/HFL=3(HFL-HBT*DCF)/4+VSP*DCF/HFL
 // de ce fait le nombre de points parcouru est HFL*VFL=3HFL²/4-3HFL*HBT*DCF/4+VSP*DCF
 // Le maximum sera de : DCF/RRm. Attention à l'unité : il faudra miltiplier par 1000000 (RRm en Hz)
 // Il reste donc à résoudre : 3HFL²/4-3HFL*HBT*DCF/4+VSP*DCF=DCF*1000000/RRm une équation du second degrès pour obtenir HFL
 // Delta=(3*HBT*DCF/4)^2+4*3/4*(1000000*DCF/RRm-VSP*DCF)=(9*HBT²/16+(3000000/RRm-3*VSF)/DCF)*DCF² >0 car 1000000*RRm/DCF-VSP/DCF>0
 // puisque le nombre de point total est plus petit que le nombre de points dans les lignes supprimées
 // Ceci implique aussi que notre équation a deux racines réelles, une positive (la grande) et une négative.
 // Donc HFL=(3*HBT*DCF/4+Delta^(1/2))/(2(3/4))=(HBT/2+2sqrt(9*HBT²/16+(3000000/RRm-3*VSF)/3//DCF)*DCF
 // D'où HR=HFL-HBT*DCP
 HFL=(2*sqrt(9.0*HBT*HBT/16+(3000000/RRm-3*VSP)/DCF)/3+HBT/2)*DCF;
 // vérifier que HFL=DCF/HSF, prendre la plus petite des 2 valeurs : HFL_max=min(HFL_max,DCF/HSF)
//printf("%d<HFL<%d\n",1000*DCF/HSF,1000*DCF/HSFm);
 HFL=min(HFL,1000*DCF/HSFm);  // éviter une trop petite fréqunece horizontale si HFL est trop grand
 HR=HFL-HBT*DCF;
 if (this->plus_grande_largeur->text()[0]!=0)
 {
  sscanf(this->plus_grande_largeur->text(),"%d",&largeur_max);
  if (largeur_max!=0)
  {
   if (largeur_max<600)
   {
    sprintf(mot,"640");
    this->plus_grande_largeur->setText(mot);
    largeur_max=640;
   }
   HR=min(HR,largeur_max);
  }
 }

 HR-=HR%8;
 largeur_max=HR;

 if (this->plus_petite_largeur->text()[0]!=0)
 {
  sscanf(this->plus_petite_largeur->text(),"%d",&largeur_min);
  if  (largeur_min!=0)
  {
   if (largeur_min<300 || largeur_min>HR)
   {
    sprintf(mot,"320");
    this->plus_petite_largeur->setText(mot);
    largeur_min=320;
   }
   largeur_min-=largeur_min%8;
  }
  else
  {
   pas =8;
   largeur_min=320;
  }
 }
 else
 {
  pas =8;
  largeur_min=320;
 }

 if ( this->nb_mode->text()[0]!=0)
 {
  sscanf(this->nb_mode->text(),"%d",&nb_mode);
  if (nb_mode!=0)
  {
   if (nb_mode<1)
   {
    sprintf(mot,"10");
    this->nb_mode->setText(mot);
    nb_mode=10;
   }
   pas=(HR-largeur_min)/nb_mode;
  }
  else
  {
   pas=8;
  }
 }
 else
 {
  pas=8;
 }

 pas+=pas%8;
 pas=max(pas,8);
 nb_mode=(HR-largeur_min)/pas+1;
 s=(char *)malloc(120*nb_mode);
 ch=s;
 for(;HR>=largeur_min;HR-=pas)
 {
//printf("HR=%d\n",HR);

  //HFL=HR/.74; // longueur de trame -> plus valable...
  HFL=HR+HBT*DCF;
  if (HFL%8!=0)
  {
   HFL+=8-HFL%8; // par précaussion : multiple de 8.
  }



  // |___ __ __ __ __ __ __ __ __ __ __ __ __
  // |_ _ _ _ _ _ _ _ _ _ _ _                |
  // |_______________________|_______________|_____
  // 0                       ^               ^     unité : tic
  //                         |   ^       ^   |
  //                         HR  |       |  HFL
  //                         |   |<----->|   |
  //                         |<->|  HSP  |<->|
  //                         HGT1         HGT2

  // nouvelle méthode : HGT1+HSP+HGT2=HBT
  // => on peut considérer ces trois éléments indépendant de la configuration,
  // à la limite pour les petites configs, on aura des temps plus longs, mais ce n'est pas grave!

  //GT1=(HFL-HR-freq*HSP)/2;
  //if (GT1<32) printf("GT trop petit pour HR=%d, GT=%d\n",HR,GT1); // une trentène de cliques de sécurité minumum
  // GT1-=GT1%8;
  // GT2=GT1;
  // SH2=HFL-GT2;
  SH2=HFL-GT2;
  // SH1=HR+GT1;
  SH1=HR+GT1;

//printf("1000*%d<%d*%d=%d\n",DCF,HFL,HSFm,HFL*HSFm);
//  HFL=max(HFL,1000*DCF/HSF);  // éviter une trop grande fréqunece horizontale si HFL est trop grand => baisser freq?
// 1000*DCF/HSF<HFL<1000*DCF/HSFm
 freq=min(DCF*10,HSF*HFL/100);

  VR=3*HR/4;    // ici pas de multiples de quoi que ce soit!

  // |___ __ __ __ __ __ __ __ __ __ __ __ __
  // |_ _ _ _ _ _ _ _ _ _ _ _                |
  // |_______________________|_______________|_____
  // 0                      VR              VFL     unités : tics
  //                         ^   ^       ^
  //                         |   |       |
  //                         |<->|<----->|
  //                          VGT    VSP

  // VFL=VR*1.05; -> changement de méthode -> plus valable
  VFL=VR+VSP*freq/(HFL*10);

  if (100000*freq>VSF*HFL*VFL) // trop grande fréquence verticale
  {  // si la fréquence verticale est trop grande : petite résolution
   freq=0.00001*VSF*HFL*VFL; // dix fois la fréquence!
   if (freq<DCFm*10) // trop petite petite fréquence d'affichage des points
   {
    VFL=1000000*DCFm/(VSF*HFL)+1;
    freq=0.00001*VSF*HFL*VFL; // dix fois la fréquence!
   }
  }
  SV1=VR+3;     // VGT : trois cycles
  SV2=VR+VSP*freq/(HFL*10); // C'est régulièrement VFL

  //if (SV2>VFL) printf ("SV2 trop grand pour HR=%d\n",HR);

  if (100000.0*freq/(HFL*VFL)<RRm) // fréquence de raffraichissement trop petite!
  {
   largeur_max-=pas;
  }
  else
  if (100.0*freq/HFL<HSFm)
  {
   largeur_min=HR;HR=0;
  }
  else
  {
   sprintf(ch,"ModeLine %c%dx%d%c %d.%d %d %d %d %d %d %d %d %d #%f Hz\n",'"',HR,VR,'"',(freq/10),freq-10*(freq/10),HR,SH1,SH2,HFL,VR,SV1,SV2,VFL,100000.0*freq/(HFL*VFL));
   while (ch[0]!=0) ch++;

   if (HR>largeur_min && HR-pas<largeur_min)
   {
    HR=largeur_min+pas;
   }
  }
 }
 this->liste_modeline->setText(s);

 sprintf(mot,"Plus grand mode %c%dx%d%c, plus petit mode %c%dx%d%c.<br>Nombre de modes générés : %d. Pour voir tous les modes, regarder l'onglet <i>'ModeLine'</i>%c",'"',largeur_max,largeur_max*3/4,'"','"',largeur_min,largeur_min*3/4,'"',nb_mode,0); // 0 pour finir la chaîne...
 this->app_modeline->setText(mot);

 lequel=ecran_n(selection->index());

 if (lequel->modeline!=NULL)
  free(lequel->modeline);
 lequel->modeline=s;
 lequel->nb_mode=nb_mode;
 lequel->HSP=HSP;
 lequel->HBT=HBT;
 lequel->VSP=VSP;
 lequel->bp_max=DCF;
 lequel->bp_min=DCFm;
 lequel->largeur_max=largeur_max;
 lequel->largeur_min=largeur_min;
 sprintf(mot,"%d",largeur_max);
 this->plus_grande_largeur->setText(mot);
 sprintf(mot,"%d",largeur_min);
 this->plus_petite_largeur->setText(mot);

 this->iconView1->setCurrentItem(this->iconView1->firstItem());
 this->iconView1->setCurrentItem(this->iconView1->lastItem());
 this->iconView1->setCurrentItem(s1); // astuce pour afficher les nouveaux modes dans le premier onglet
 this->xf_option->setCurrentPage(1);  // parrer l'astuce pour mettre à jour le premier onglet
}

