// FileRRR.pas : récupération des fichiers autre que RW3
unit filerrr;

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

interface

uses sysUtils, clipBrd, classes, forms, controls,
     constreg, maths, regutil, uniteker, compile, math, dialogs,
     valeurs,
     laz2_DOM, laz2_XMLRead, laz2_XMLWrite, laz2_XMLUtils,
     DeLaFitsCommon, DeLaFitsGraphics;


Function LitFichierCSV(const NomFichier : String;NouveauFichier : boolean) : boolean;
Procedure EcritFichierXML(NomFichier : String);
Function LitFichierXML(const NomFichier : String) : boolean;
Function LitFichierVotable(const NomFichier : String) : boolean;
Function LitFichierFITS(const NomFichier : String) : boolean;
Function AjouteFichierFITS(const NomFichier : String) : boolean;

var codeErreurF : string;

implementation

uses graphvar, graphfft, regmain;


procedure EcritXMLTest;
var
 Doc: TXMLDocument;                                  // variable to document
 RootNode, parentNode, nofilho: TDOMNode;                    // variable to nodes
begin
 try
   // Create a document
   Doc := TXMLDocument.Create;

   // Create a root node
   RootNode := Doc.CreateElement('register');
   Doc.Appendchild(RootNode);                           // save root node

   // Create a parent node
   RootNode:= Doc.DocumentElement;
   parentNode := Doc.CreateElement('usuario');
   TDOMElement(parentNode).SetAttribute('id', '001');       // create atributes to parent node
   RootNode.Appendchild(parentNode);                          // save parent node

   // Create a child node
   parentNode := Doc.CreateElement('nome');                // create a child node
   TDOMElement(parentNode).SetAttribute('sexo', 'M');     // create atributes
   nofilho := Doc.CreateTextNode('Fernando');         // insert a value to node
   parentNode.Appendchild(nofilho);                         // save node
   RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert child node in respective parent node

   // Create a child node
   parentNode := Doc.CreateElement('idade');               // create a child node
   TDOMElement(parentNode).SetAttribute('ano', '1976');   // create atributes
   nofilho := Doc.CreateTextNode('32');               // insert a value to node
   parentNode.Appendchild(nofilho);                         // save node
   RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert a childnode in respective parent node

   writeXMLFile(Doc, 'test.xml');                     // write to XML
 finally
   Doc.Free;                                          // free memory
 end;
end;


Function TrimNomGrandeur(const s : String) : string;
var longueur,i : integer;
begin
      result := '';
      longueur := Length(s);
      for i := 1 to longueur do
          if charinset(s[i],['a'..'z','A'..'Z','0'..'9'])
             then result := result+s[i]
end;

Procedure VerifNom(var Anom : string);
begin
      Anom := trimNomGrandeur(Anom);
      if not nomCorrect(Anom,grandeurInconnue) then Anom := '';
end;

// On entre dans les procédures d'extraction avec la première ligne déjà lue
// et on en sort donc avec la ligne suivante déjà lue

Procedure VerifKilo(var exp : String);

function textePrefixe(pref : string) : String;
begin
if pref='p' then textePrefixe := 'E-12'
else if pref='n' then textePrefixe := 'E-9'
else if pref=muMin  then textePrefixe := 'E-6'
else if pref='m' then textePrefixe := 'E-3'
else if pref='k' then textePrefixe := 'E+3'
else if pref='M' then textePrefixe := 'E+6'
else if pref='G' then textePrefixe := 'E+9'
else if pref='T' then textePrefixe := 'E+12'
else textePrefixe := '';
end;

var j : integer;
begin
    j := 2;
    while j<=length(exp) do begin
        if (pos(exp[j],caracPrefixe)>0) and
           charinset(exp[pred(j)],chiffre) then begin
             insert(textePrefixe(exp[j]),exp,succ(j));
             delete(exp,j,1);
             inc(j,3);
        end;
        inc(j);
    end;
end;

function LitFichierCSV(const NomFichier : String;NouveauFichier : boolean) : boolean;
const maxCSV = 12;
var
    ligneCSV : array[0..maxCSV] of string;
    nom,unite : array[0..maxCSV] of string;
    VariabAsuppr : TstringList;
    DecodeVariab : array[0..MaxCSV] of integer;
    NbreCSV : integer;
    fichierCSV : textFile;
    finFichierCSV : boolean;
    uniteTrouvee : boolean;
    isLigneDeChiffres : boolean;
    oldCarac : char;
    avecNoms : boolean;
    indexDate,indexTime,indexDateTime : integer;
    separateurCSV : TSysCharSet; // pour distinguer 1.2,1.3 de 1,2;1,3

procedure litLigneCSV;
var carac : char;
    i : integer;
begin
   try
   NbreCSV := 0;
   for i := 0 to maxCSV do LigneCSV[i] := '';
   isLigneDeChiffres := false;
   if finFichierCSV then exit;
   isLigneDeChiffres := true;
   repeat
         read(fichierCSV,carac);
          if ((carac=crCR) and (oldCarac=crLF)) or
            ((carac=crLF) and (oldCarac=crCR))
             then begin
               carac := #00;
               oldCarac := #00;
             end;
         if charinset(carac,separateurCSV)
            then inc(NbreCSV)
            else if (carac>' ') then begin
                 LigneCSV[NbreCSV] := LigneCSV[NbreCSV]+carac;
                 isLigneDeChiffres := isLigneDeChiffres and
                            charinset(carac,['0'..'9','+','-','E','.',',','e','/',':']); // / et : pour date et Time
            end
            else if carac=' ' then begin
                 if not(LigneCSV[NbreCSV]='') then LigneCSV[NbreCSV] := LigneCSV[NbreCSV]+carac;
            end;
         finFichierCSV := eof(fichierCSV);
   until (carac=crLF) or finFichierCSV or (carac=crCR) or (nbreCsv>maxCsv);
   if (NbreCsv>maxCsv) then begin
      repeat
           read(fichierCSV,carac);
           finFichierCSV := eof(fichierCSV);
      until (carac=crLF) or finFichierCSV or (carac=crCR);
   end;
   oldCarac := carac;
   if LigneCSV[pred(NbreCSV)]='' then dec(NbreCSV);
   isLigneDeChiffres := isLigneDeChiffres and (NbreCsv>0);
   except
        FinFichierCSV := true;
        NbreCSV := 0;
   end;
end;

procedure LitValeurVecteurDoubleVirgule;
var i,NbrePoints : integer;
    index : integer;
    strValeur : string;
begin
   while not(finFichierCSV) and isLigneDeChiffres do with pages[pageCourante] do begin
      NbrePoints := nmes;
      nmes := nmes+1;
      for i := 0 to pred(NbreVariabExp) do begin
          index := decodeVariab[i];
          strValeur := ligneCSV[2*i]+','+ligneCSV[2*i+1];
          valeurVar[index,NbrePoints] := strToFloatWin(strValeur);
      end;
      litLigneCSV;
   end;
end; // litValeurVecteurDoubleVirgule

procedure LitValeurVecteurCSV;
var i,j,k,NbrePoints : integer;
    posDate,posTime : integer;
    index : integer;
    strValeur : string;
    Asuppr : boolean;
begin
   indexDate := grandeurInconnue;
   indexTime := grandeurInconnue;
   indexDateTime := grandeurInconnue;
   while not(finFichierCSV) and isLigneDeChiffres do with pages[pageCourante] do begin
      NbrePoints := nmes;
      nmes := nmes+1;
      for i := 0 to pred(NbreCSV) do begin
          index := decodeVariab[i];
          strValeur := ligneCSV[i];
          posTime := pos(':',strValeur);
          posDate := pos('/',strValeur);
          if strValeur=''
          then valeurVar[index,NbrePoints] := NAN
          else if (posTime>0) or (posDate>0)
            then begin
                try
                if posTime>0
                   then if posDate>0
                        then begin
                            valeurVar[index,NbrePoints] := StrToDateTime(strValeur);
                            indexDateTime := index;
                            Grandeurs[index].formatU := fDateTime;
                        end
                        else begin
                           valeurVar[index,NbrePoints] := StrToTime(strValeur);
                           indexTime := index;
                           Grandeurs[index].formatU := fTime;
                        end
                   else begin
                        valeurVar[index,NbrePoints] := StrToDate(strValeur);
                        indexDate := index;
                        Grandeurs[index].formatU := fDate;
                   end;
                 except
                   valeurVar[index,NbrePoints] := Nan;
                 end;
             end
             else valeurVar[index,NbrePoints] := strToFloatWin(strValeur);
      end;
      litLigneCSV;
   end;
   if (indexTime<>grandeurInconnue) and
      (indexDate<>grandeurInconnue) and
      (indexDateTime=grandeurInconnue) then begin
           Fvaleurs.Memo.lines.add('t='+grandeurs[indexDate].nom+'+'+grandeurs[indexTime].nom);
           Fvaleurs.Memo.lines.add('''t=date et heure');
   end;
   for I := 0 to VariabAsuppr.Count-1 do begin
       index := indexNom(VariabAsuppr[i]);
       SupprimeGrandeurE(index);
   end;
   k := NbreVariab-1;
   while k>=0 do begin
       index := indexVariab[k];
       Asuppr := true;
       for j := 0 to 3 do
          Asuppr := Asuppr and isNan( pages[pageCourante].valeurVar[index,j]);
       if Asuppr then SupprimeGrandeurE(index);
       dec(k);
   end;
end; // litValeurVecteurCSV

Function VerifUnite(num : integer) : string;
var posO,posF,i : integer;
    reponse : string;
begin
   result := '';
   posO := pos('en ',ligneCSV[num]);
   if (posO>1) then begin
      reponse := copy(ligneCSV[num],posO+3,4);
      ligneCSV[num] := copy(ligneCSV[num],1,posO-1);
      i:=1;
      while i<=length(reponse) do
          if charInSet(reponse[i],caracUnite)
             then inc(i)
             else delete(reponse,i,1);
      reponse := copy(reponse,1,posO-2); // on enlève blanc ou ( avant en
      UniteTrouvee := true;
      if reponse='Second' then reponse := 's';
      if reponse='Volt' then reponse := 'V';
      result := reponse;
      exit;
   end;
   posO := pos('(',ligneCSV[num]);
   posF := pos(')',ligneCSV[num]);
   if (posO>1) and (posF>posO) then begin
      reponse := copy(ligneCSV[num],posO+1,posF-posO-1);
      ligneCSV[num] := copy(ligneCSV[num],1,posO-1);
      UniteTrouvee := true;
      if reponse='Second' then reponse := 's';
      if reponse='Volt' then reponse := 'V';
      if (reponse='max') or (reponse='min') then begin
         UniteTrouvee := false;
         ligneCSV[num] := ligneCSV[num]+reponse;
         reponse := '';
      end;
      result := reponse;
   end;
end;

Function LigneDeNom : boolean;
var i : integer;
    NbreNom : integer;
begin
  NbreNom := 0;
  for i := 0 to pred(NbreCSV) do
      if ligneCsv[i]<>'' then inc(NbreNom);
  result := (NbreCsv>1) and (NbreNom>0);
  if (NbreNom<NbreCsv) then
  for i := 0 to pred(NbreCSV) do
      if ligneCsv[i]='' then
      case i of
           0 : ligneCsv[0] := 't';
           1 : ligneCsv[1] := 'V1';
           2 : ligneCsv[2] := 'V2';
           else ligneCsv[i] := 'Var'+IntToStr(i);
      end;
end;

procedure litNomUnite;
const maxU = 3;
      nomCSV : array[0..MaxU,boolean] of string =
           (('Volt²','V2'),
            ('Ampere²','A2'),
            ('Volt','V'),
            ('second','s'));
var i,j,index : integer;
    signif : string;
begin
     for i := 0 to maxCSV do DecodeVariab[i] := i;
if avecNoms then begin
     repeat
         litLigneCSV;
     until FinFichierCSV or LigneDeNom;
     UniteTrouvee := false;
     for i := 0 to pred(NbreCSV) do begin
         signif := LigneCSV[i];
         Unite[i] := VerifUnite(i);
         Nom[i] := Copy(trimNomGrandeur(LigneCSV[i]),1,longNom);
         if nom[i]<>'' then begin
         if indexNom(nom[i])<>grandeurInconnue then nom[i] := nom[i]+intToStr(i);
         if indexNom(nom[i])=grandeurInconnue then begin
               if charInSet(nom[i][1],['0'..'9']) then nom[i] := 'V'+nom[i];
               index := AjouteExperimentale(nom[i],variable);
               grandeurs[index].NomUnite := unite[i];
               grandeurs[index].fonct.expression := signif;
            end
         end;
     end;
     litLigneCSV;
     if not uniteTrouvee and not isLigneDeChiffres then begin
        for i := 0 to pred(NbreCSV) do begin
            Unite[i] := LigneCSV[i];
            for j := 0 to maxU do
                if Unite[i]=nomCSV[j,false] then begin
                   Unite[i] := nomCSV[j,true];
                   break;
                end;
            if pos('_Time',unite[i])>0 then if pos('1',unite[i])>0
                 then begin
                   unite[i] := 's';
                   index := indexNom(nom[i]);
                   if index<>grandeurInconnue then begin
                      grandeurs[index].nom := 't';
                      nom[i] := 't';
                   end;
                 end
                 else VariabAsuppr.Add(nom[i]);
            // chx_Time à supprimer pour x>1
            grandeurs[i].NomUnite := unite[i];
         end;
         litLigneCSV;
     end;
     if not isLigneDeChiffres then begin // commentaires
        for i := 0 to pred(NbreCSV) do
            grandeurs[i].fonct.expression := LigneCSV[i];
        litLigneCSV;
     end;
end
else begin
     litLigneCSV;
     AjouteExperimentale('t',variable);
     grandeurs[0].NomUnite := 's';
     for i := 2 to NbreCSV do begin
        AjouteExperimentale('V'+intToStr(i),variable);
        grandeurs[1].NomUnite := 'V';
     end;
end;
     if not ajoutePage then exit;
     if charInSet(',',separateurCSV) and (NbreCsv>NbrevariabExp)
        then litValeurVecteurDoubleVirgule
        else litValeurVecteurCSV;
     if (NbreGrandeurs>0) and
        (pages[pageCourante].nmes>0)then begin
            LitFichierCSV := true;
            construireIndex;
     end;
end; // litNomUnite

procedure verifNoms;
var i : integer;
    nom : string;
    nomConnu : set of byte;
    compteur : integer;
begin
     for i := 0 to maxCSV do DecodeVariab[i] := i;
     nomConnu := [];
if avecNoms then begin
     litLigneCSV;
     if NbreCSV<>NbreVariabExp then exit;
     for i := 0 to pred(NbreCSV) do begin
         Nom := VerifUnite(i);
         Nom := trimNomGrandeur(LigneCSV[i]);
         DecodeVariab[i] := indexNom(nom);
         if DecodeVariab[i] in nomConnu then begin
            nom := nom+intToStr(i);
            DecodeVariab[i] := indexNom(nom);
         end;
         include(nomConnu,DecodeVariab[i]);
         if DecodeVariab[i]=grandeurInconnue then exit;
     end;
     compteur := 1;
     repeat
        litLigneCSV; // unités ; commentaires
        inc(compteur);
     until isLigneDeChiffres or (compteur>3);
end
else begin
     litLigneCSV;
end;
     if not ajoutePage then exit;
     if charInSet(',',separateurCSV) and (NbreCsv>NbrevariabExp)
        then litValeurVecteurDoubleVirgule
        else litValeurVecteurCSV;
     if pages[pageCourante].nmes>0
          then LitFichierCSV := true
end; // verifNoms

procedure litGoodwill;
var valeurY : array[0..8192] of integer;
    nbre : integer;
    premiereLigne : string;
    posV : integer;

function extraitNombre : double;
begin
    posV := pos(',',premiereLigne);
    premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
    posV := pos(',',premiereLigne);
    if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
    result := strToFloatWin(premiereLigne);
end;

var lecture : boolean;
    penteX,penteY,yzero : double;
    i : integer;
begin // GoodWill
     Reset(fichierCSV);
     if nouveauFichier then begin
        AjouteExperimentale('t',variable);
        grandeurs[0].NomUnite := 's';
        AjouteExperimentale('V',variable);
        grandeurs[1].NomUnite := 'V';
     end;
     if not ajoutePage then exit;
     lecture := false;
     nbre := 0;
     yzero := 0;
     penteX := 1e-6;
     penteY := 0.001;
     while not eof(fichierCSV) and not lecture do begin
           readln(fichierCSV,premiereLigne);
           if pos('Memory Length',premiereLigne)>0 then ;
           if pos('Vertical Units',premiereLigne)>0 then ;
           if pos('Horizontal Units',premiereLigne)>0 then ;
           if pos('Vertical Scale',premiereLigne)>0 then begin
              penteY := extraitNombre/25;
           end;
           if (pos('Sample Period',premiereLigne)>0) or
              (pos('Sampling Period',premiereLigne)>0)
              then begin
              penteX := extraitNombre;
           end;
           if pos('Trigger Level',premiereLigne)>0 then ;
           if pos('Vertical Position',premiereLigne)>0 then begin
              yzero := extraitNombre;
           end;
           if pos('Horizontal Position',premiereLigne)>0 then ;
           if pos('Horizontal Scale',premiereLigne)>0 then ;
           if pos('Firmware',premiereLigne)>0 then ;
           if pos('Waveform Data',premiereLigne)>0 then begin
              lecture := true;
           end;
           if pos('Source',premiereLigne)>0 then begin // CH1
              posV := pos(',',premiereLigne);
              premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
              posV := pos(',',premiereLigne);
              if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
              grandeurs[1].Nom := premiereLigne;
           end;
     end;
     while not eof(fichierCSV) do begin
        readln(fichierCSV,premiereLigne);
        if premiereLigne<>'' then begin
           posV := pos(',',premiereLigne);
           if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
           valeurY[nbre] := strToInt(premiereLigne);
           inc(nbre);
        end;
     end;
     with pages[pageCourante] do begin
          nmes := nbre;
          for i := 0 to pred(Nbre) do begin
              valeurVar[0,i] := i*penteX;
              valeurVar[1,i] := valeurY[i]*penteY+yzero;
          end;
     end;
     result := pages[pageCourante].nmes>128;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
end; // litGoodWill

procedure litGoodwillPC;
var valeurY : array[0..8192] of integer;
    nbre : integer;
    premiereLigne : string;
    posV : integer;

function extraitNombre : double;
begin
    posV := pos(',',premiereLigne);
    premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
    posV := pos(',',premiereLigne);
    if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
    result := strToFloatWin(premiereLigne);
end;

var lecture : boolean;
    penteX,penteY,yzero : double;
    i : integer;
begin  // GoodWill
     Reset(fichierCSV);
     if nouveauFichier then begin
        AjouteExperimentale('t',variable);
        grandeurs[0].NomUnite := 's';
        AjouteExperimentale('V',variable);
        grandeurs[1].NomUnite := 'V';
     end;
     if not ajoutePage then exit;
     lecture := false;
     nbre := 0;
     yzero := 0;
     penteX := 1e-6;
     penteY := 0.001;
     while not eof(fichierCSV) and not lecture do begin
           readln(fichierCSV,premiereLigne);
           if pos('Memory Length',premiereLigne)>0 then ;
           if pos('Vertical Units',premiereLigne)>0 then ;
           if pos('Horizontal Units',premiereLigne)>0 then ;
           if pos('VERTICAL SCALE',premiereLigne)>0 then begin
              penteY := extraitNombre/25;
           end;
           if pos('TIME BASE SCALE',premiereLigne)>0 then begin
              penteX := extraitNombre/256;
               // par division avec 8 divisions sur 256 niveaux soit 32
           end;
           if pos('Trigger Level',premiereLigne)>0 then ;
           if pos('Vertical Position',premiereLigne)>0 then begin
              yzero := extraitNombre;
           end;
           if pos('Horizontal Position',premiereLigne)>0 then ;
           if pos('Horizontal Scale',premiereLigne)>0 then ;
           if pos('Firmware',premiereLigne)>0 then ;
           if pos('POINT,VALUE',premiereLigne)>0 then begin
              lecture := true;
           end;
           if pos('RECORD Length',premiereLigne)>0 then begin
             // NbreMax := round(extraitNombre);
           end;
           if pos('Channel',premiereLigne)>0 then begin // CH1
              posV := pos(',',premiereLigne);
              premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
              posV := pos(',',premiereLigne);
              if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
              grandeurs[1].Nom := premiereLigne;
           end;
     end;
     while not eof(fichierCSV) do begin
        readln(fichierCSV,premiereLigne);
        if premiereLigne<>'' then begin
           posV := pos(',',premiereLigne);   // index X
           if posV>0 then premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
           posV := pos(',',premiereLigne); // indexY
           if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
           valeurY[nbre] := strToInt(premiereLigne);
           inc(nbre);
        end;
     end;
     with pages[pageCourante] do begin
          nmes := nbre;
          for i := 0 to pred(Nbre) do begin
              valeurVar[0,i] := i*penteX;
              valeurVar[1,i] := valeurY[i]*penteY+yzero;
          end;
     end;
     result := pages[pageCourante].nmes>128;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
end; // litGoodWillPC

procedure litTektro;
var penteY,penteX,Yzero,probe,Yoffset : double;

procedure extraitPoint;
const
    filtre : TSysCharSet = ['0'..'9'];
    filtreInterne : TSysCharSet = ['0'..'9','.','-','E'];
var chaine : string;
    nbreCarac,posDebut : integer;
    premiereLigne : string;

function extraitNombre : double;
var posV : integer;
begin
    posV := pos(',',premiereLigne);
    premiereLigne := copy(premiereLigne, posV+1, length(premiereLigne)-posV);
    posV := pos(',',premiereLigne);
    if posV>0 then premiereLigne := copy(premiereLigne, 1, posV-1);
    result := strToFloatWin(premiereLigne);
end;

begin with pages[pageCourante] do begin  // Tektro
   readln(fichierCSV,premiereLigne);
   posDebut := length(premiereLigne);
   while not CharInset(premiereLigne[posDebut],filtre) do dec(posDebut);
   nbreCarac := 0;
   while CharInset(premiereLigne[posDebut],filtreInterne) do begin
     inc(nbreCarac);
     dec(posDebut);
   end;
   chaine := copy(premiereLigne,posDebut+1,nbreCarac);
   valeurVar[1,nmes] := strToFloatWin(chaine);
   while not CharInSet(premiereLigne[posDebut],filtre) do dec(posDebut);
   nbreCarac := 0;
   while charInset(premiereLigne[posDebut],filtre) do begin
     inc(nbreCarac);
     dec(posDebut);
   end;
   chaine := copy(premiereLigne,posDebut+1,nbreCarac);
   valeurVar[0,nmes] := strToFloatWin(chaine);
   nmes := nmes+1;
   if pos('Vertical Scale',premiereLigne)>0 then
         penteY := extraitNombre/2000;
// pleine échelle avec 10 divisions sur 2048 niveaux
   if pos('Horizontal Scale',premiereLigne)>0 then
         penteX := extraitNombre*1e-6/250;
// par division avec 10 divisions sur 2500 points en micro s
    if pos('Vertical Offset',premiereLigne)>0 then
         Yoffset := extraitNombre;
    if pos('Probe Atten',premiereLigne)>0 then
         probe := extraitNombre;
    if pos('Yzero',premiereLigne)>0 then
         yzero := extraitNombre;
end end;

var i : integer;
begin  // Tektro
     Reset(fichierCSV);
     if nouveauFichier then begin
        AjouteExperimentale('t',variable);
        grandeurs[0].NomUnite := 's';
        AjouteExperimentale('V',variable);
        grandeurs[1].NomUnite := 'V';
     end;
     if not ajoutePage then exit;
     while not eof(fichierCSV) do extraitPoint;
     result := pages[pageCourante].nmes>128;
     penteY := penteY/probe;
     for i := 0 to pred(pages[pageCourante].nmes) do begin
         pages[pageCourante].valeurVar[0,i] := i*penteX;
         pages[pageCourante].valeurVar[1,i] := (pages[pageCourante].valeurVar[1,i]-yzero)*penteY+yOffset;
     end;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
end;  // litTektro

function litLigneSecomam : string;
var i : integer;
    uneLigne : string;
begin
    readln(fichierCSV,uneLigne);
    result := '';
    for i := 1 to Length(uneLigne) do
        if ord(uneLigne[i])>1 then result := result+uneLigne[i];
end;

procedure litSecomam;

procedure extraitPoint;
var chaine : string;
    posTab : integer;
    uneLigne : string;
begin with pages[pageCourante] do begin
   uneLigne := litLigneSecomam;
   posTab := pos(crTab,uneLigne);
   if posTab=0 then exit;
   chaine := copy(uneLigne,1,pred(posTab));
   valeurVar[0,nmes] := strToFloatWin(chaine);
   chaine := copy(uneLigne,succ(posTab),length(uneLigne));
   valeurVar[1,nmes] := strToFloatWin(chaine);
   nmes := nmes+1;
end end;

procedure getNU(complet : string;var nom,unite : string);
var posCO,posCF : integer;
begin
    posCO := pos('[',complet);
    posCF := pos('[',complet);
    if posCF>posCO then begin
       unite := copy(complet,succ(posCO),posCF-posCO+1);
       nom := copy(complet,1,pred(posCO))
    end
    else begin
       unite := '';
       nom := complet;
    end;
end;

var uneLigne : string;
    posTab : integer;
    nomComplet,nom,unite : string;
begin  // secomam : csv avec tabulation !
     repeat
         uneLigne := litLigneSecomam;
     until eof(fichierCSV) or (pos('Absorption',uneLigne)>0);
     if eof(fichierCSV) then exit;
     if nouveauFichier then begin
        posTab := pos(crTab,uneLigne);
        nomComplet := copy(uneLigne,1,pred(posTab));
        getNU(nomComplet,nom,unite);
        AjouteExperimentale(nom,variable);
        grandeurs[0].NomUnite := unite;
        grandeurs[0].fonct.expression := nomComplet;
        nomComplet := copy(uneLigne,succ(posTab),length(uneLigne));
        getNU(nomComplet,nom,unite);
        AjouteExperimentale(nom,variable);
        grandeurs[1].NomUnite := unite;
        grandeurs[1].fonct.expression := nomComplet;
     end;
     if not ajoutePage then exit;
     while not eof(fichierCSV) do
        extraitPoint;
     result := pages[pageCourante].nmes>2;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
end;

procedure litChauvinArnoux;

procedure LitValeurs;
var i,NbrePoints : integer;
    posTime,posDateCA : integer;
    strValeur : string;
    index : integer;
begin
   litLigneCSV;
   while not(finFichierCSV) do with pages[pageCourante] do begin
      NbrePoints := nmes;
      nmes := nmes+1;
      for i := 0 to pred(NbreCSV) do begin
          index := decodeVariab[i];
          strValeur := ligneCSV[i];
          posTime := pos(':',strValeur);
          posDateCA := pos('-',strValeur);
          if (posDateCA>0) and (posTime>0) then begin // Date Time Chauvin Arnoux 2012-12-25 12:56:13:000
              posDateCA := pos(' ',strValeur);
              if posDateCA>0 then strValeur := copy(strValeur,posDateCA+1,length(strValeur));
              strValeur := copy(strValeur,1,8);
              // on enlève la date
              if index<>grandeurInconnue then
                 valeurVar[index,NbrePoints] := StrToTime(strValeur);
          end
          else valeurVar[index,NbrePoints] := strToFloatWin(strValeur);
      end;
      litLigneCSV;
   end;
end; // litValeurs

var premiereLigne : string;
    i : integer;
begin // Chauvin Arnoux
    Reset(fichierCSV);
    finFichierCSV := false;
    NbreCSV := 0;
    readln(fichierCSV,premiereLigne);
    for i := 0 to MaxCSV do
        DecodeVariab[i] := grandeurInconnue;
    if nouveauFichier then begin
        AjouteExperimentale('index',variable);
        grandeurs[0].NomUnite := '';
        AjouteExperimentale('t',variable);
        grandeurs[1].NomUnite := 's';
        grandeurs[1].formatU := fTime;
        AjouteExperimentale('T',variable);
        grandeurs[2].NomUnite := '°C';
        for i := 0 to 2 do
            DecodeVariab[i] := i;
     end
     else begin
        DecodeVariab[0] := indexNom('index');
        if DecodeVariab[0]=grandeurInconnue then
           DecodeVariab[0] := 0;
        DecodeVariab[1] := indexNom('t');
        DecodeVariab[2] := indexNom('T');
     end;
     if not ajoutePage then exit;
     pages[pageCourante].commentaireP := premiereLigne;
     readln(fichierCSV,premiereLigne);// en fait la deuxième !
     separateurCSV := [';',crCR,crLF];
     litValeurs;
     if (pages[pageCourante].nmes>0)then begin
         LitFichierCSV := true;
         construireIndex;
     end;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
end;

var premiereLigne : string;
    ls : string;
    avecEnTete : boolean;
    commentaire : string;
    compteur : integer;
begin // LitFichierCSV
     result := false;
     codeErreurF := erFileData;
     oldCarac := #00;
     ModeAcquisition := AcqFichier;
     FileMode := fmOpenRead;
     AssignFile(fichierCSV,NomFichier);
     Reset(fichierCSV);
     readln(fichierCSV,premiereLigne);
     if pos(';',premiereLigne)>0
        then separateurCSV := [';',crCR,crLF]
        else separateurCSV := [',',crCR,crLF];
     if pos('Record Length',premiereLigne)>0 then begin
        litTektro;
        exit;
     end;
     if pos('IR Camera',premiereLigne)>0 then begin
        litChauvinArnoux;
        exit;
     end;
     if pos('Memory Length',premiereLigne)>0 then begin
        litGoodwill;
        exit;
     end;
     if pos('DESCRIPTION',premiereLigne)>0 then begin
         readln(fichierCSV,premiereLigne);
         if pos('MANUFACTURE',premiereLigne)>0 then begin
           litGoodwillPC;
           exit;
         end;
     end;
     avecEnTete := false;
     if (pos(';',premiereLigne)<=0) and
        (pos(',',premiereLigne)<=0) then begin
        readln(fichierCSV,premiereLigne); // deuxième en fait
        avecEnTete := true;
        if pos(';',premiereLigne)>0
           then separateurCSV := [';',crCR,crLF]
           else separateurCSV := [',',crCR,crLF];
     end;
     avecNoms := not ligneDeChiffres(premiereLigne);
     compteur := 1;
     repeat
        ls := litLigneSecomam;
        inc(compteur);
        until eof(fichierCSV) or
             (pos('UviLine',ls)>0) or
             (compteur=5);
     if (pos('UviLine',ls)>0) then begin
         litSecomam;
         exit;
     end;
     VariabAsuppr := TstringList.Create;
     Reset(fichierCSV);
     finFichierCSV := false;
     NbreCSV := 0;
     if avecEnTete
        then readln(fichierCSV,commentaire)
        else commentaire := '';;
     try
     if NouveauFichier
        then litNomUnite
        else verifNoms;
     if result then begin
        pages[pageCourante].affecteVariableP(false);
        pages[pageCourante].commentaireP := commentaire;
     end;
     except
         codeErreurF := erReadFile;
         result := false;
     end;
     CloseFile(fichierCSV);
     FileMode := fmOpenReadWrite;
     VariabASuppr.Free;
end; // LitFichierCSV 

procedure EcritFichierXML(nomFichier : String);
var
    i : integer;
    v : integer;
    p : codePage;
    donnees : TstringList;
    Document: TDOMNode;
    Node1, Node2 : TDOMNode;

begin
     Screen.Cursor := crHourGlass;
     donnees := TstringList.create;
     XMLDoc := TXMLDocument.Create;
     Document := XMLDoc.createElement('Regressi');
     XMLDoc.AppendChild(Document);

     Document := XMLDoc.DocumentElement;

     Node1 := XMLDoc.createElement('SOURCE');
     Document.Appendchild(Node1);
     WriteStringXML(Node1,'Logiciel','Regressi');
     WriteStringXML(Node1,'Version','3.05');
     WriteStringXML(Node1,'Acquisition',NomModeAcq[ModeAcquisition]);
     WriteDateTimeXML(Node1,'Date',now);
     WriteStringXML(Node1,'Copyright','Jean-Michel Millet');

     Node1 := XMLDoc.createElement('OPTIONS');
     Document.AppendChild(Node1);
     WriteBoolXML(Node1,'Trigo',AngleEnDegre);
     WriteIntegerXML(Node1,'NbreDerivee',NbrePointDerivee);

     donnees.clear;
     for I := 0 to FValeurs.Memo.lines.Count - 1 do
         donnees.add(Fvaleurs.Memo.lines[i]);
     donnees.Delimiter := crCR;
     WriteStringXML(Document,'Memo',donnees.DelimitedText);
     for v := 0 to pred(NbreGrandeurs) do with grandeurs[v] do
     if fonct.genreC=g_experimentale then begin
         case genreG of
             variable : begin
                 Node1 := XMLDoc.createElement('VARIABLE');
                 Document.AppendChild(Node1);
             end;
             constante : begin
                 Node1 := XMLDoc.createElement('CONSTANTE');
                 Document.AppendChild(Node1);
             end;
         end;
         writeNomXML(Node1,nom);
         WriteStringXML(Node1,'Unite',nomUnite);
         WriteIntegerXML(Node1,'Precision',precisionU);
         WriteIntegerXML(Node1,'GenreCalcul',ord(fonct.genreC));
         WriteStringXML(Node1,'Description',fonct.expression);
         if v=indexTri then WriteBoolXML(Node1,'Controle',true);
         for p := 1 to NbrePages do with pages[p] do begin
             case genreG of
                 variable : if fonct.genreC=g_texte
                    then begin
                         donnees.clear;
                         for i := 0 to pred(pages[p].nmes) do
                             donnees.Add(TexteVar[v,i]);
                         Node2 := writeStringXML(Node1,'Texte',donnees.text);
                         writePageXML(Node2,p);
                    end
                    else begin
                       donnees.clear;
                       for i := 0 to pred(pages[p].nmes) do
                           donnees.Add(FloatToStrPoint(valeurVar[v,i]));
                       donnees.Delimiter := ' ';
                       Node2 := WriteStringXML(Node1,'Valeur',donnees.DelimitedText);
           //            writePageXML(Node2,p);
                   end;
                 constante : begin
                     Node2 := WriteFloatXML(Node1,'Valeur',valeurConst[v]);
              //       writePageXML(Node2,p);
                 end;
             end;  // case
          end;  // for p
     end; // grandeur
     for v := 1 to NbreParam[paramNormal] do begin
         Node1 := XMLDoc.createElement('PARAMETRE');
         Document.AppendChild(Node1);
         writeNomXML(Node1,parametres[paramNormal,v].nom);
         WriteStringXML(Node1,'Unite',parametres[paramNormal,v].nomUnite);
         for p := 1 to NbrePages do begin
             Node2 := WriteFloatXML(Node1,'Valeur',pages[p].valeurParam[paramNormal,v]);
          //   writePageXML(Node2,p);
         end;
     end;
     if (NbreModele>0) or (TexteModele.count>0) then begin
        Node1 := XMLDoc.createElement('MODELE');
        Document.AppendChild(Node1);
        TexteModele.Delimiter := crCR;
        WriteStringXML(Node1,'Modelisation',TexteModele.delimitedText);
        for i := 1 to NbreModele do
            for p := 1 to NbrePages do begin
                Node2 := writeIntegerXML(Node1,'DEBUT',pages[p].debut[i]);
                writeIndexXML(Node2,i);
           //     writePageXML(Node2,p);
                Node2 := writeIntegerXML(Node1,'FIN',pages[p].fin[i]);
                writeIndexXML(Node2,i);
          //      writePageXML(Node2,p);
            end;
     end;
     Node1 := XMLDoc.CreateElement('Graphe');
     Document.AppendChild(Node1);
     FGrapheVariab.ecritConfigXML(Node1);
     if FgrapheFFT<>nil then begin
        Node1 := XMLDoc.CreateElement('FOURIER');
        Document.AppendChild(Node1);
        FgrapheFFT.ecritConfigXML(Node1);
     end;
     writeXMLFile(XMLDoc,NomFichier);
     donnees.free;
     Screen.Cursor := crDefault;
end; // EcritFichierXML

function LitFichierXML(const NomFichier : String) : boolean;
var
    XmlDoc: TXmlDocument; // Xml document
    indexCourant : integer; // de la grandeur
    modeleCourant : integer;
    chaines : TStringList;

procedure LoadXMLInReg(XMLNode: TDOMNode);

Procedure ExtraitValeurs;
var i : integer;
    strValeur : string;
begin with pages[pageCourante] do begin
    chaines.Delimiter := ' ';
    chaines.DelimitedText := XMLNode.NodeValue;
    nmes := chaines.Count;
    for i := 0 to chaines.Count-1 do begin
        strValeur := chaines[i];
        try
        valeurVar[indexCourant,i] := strToFloatWin(strValeur);
        except
        valeurVar[indexCourant,i] := Nan;
        end;
    end;
end end; // extraitValeurs

Procedure ExtraitChaines;
begin
    chaines.Clear;
    chaines.DelimitedText := XMLNode.NodeValue;
end; // extraitChaines

procedure Suite;
var Node:TDOMNode;
begin
    Node := XMLNode.FirstChild;
    while Node <> Nil do begin
      LoadXMLInReg(Node);
      Node := Node.NextSibling;
    end;
end;

var
I: Integer;
code : integer;
nom : string;

begin //Les noeuds internes sont traitées récursivement

if (XmlNode.NodeName='Regressi') then begin
   suite;
   exit;
end;

if (XmlNode.NodeName='Memo') then begin
   extraitChaines;
   Fvaleurs.Memo.Lines.Assign(chaines);
   exit;
end;

if (XmlNode.NodeName='Graphe') then begin
   FGrapheVariab.LitConfigXML(XMLNode);
   exit;
end;

if (XmlNode.NodeName='FOURIER') then begin
   FgrapheFFT := TfgrapheFFT.create(FRegressiMain);
   FGrapheFFT.LitConfigXML(XMLNode);
   exit;
end;

if (XmlNode.NodeName='Modelisation') then begin
   extraitChaines;
   TexteModele.Assign(chaines);
   exit;
end;

if (XMLNode.NodeName='Valeur') then begin
   pageCourante := getPageXML(XMLNOde);
   if (pageCourante>0) and (pageCourante>NbrePages) then
        ajoutePage;
   case grandeurs[indexCourant].genreG of
      variable : if grandeurs[indexCourant].fonct.genreC=g_texte
                    then begin
                       extraitChaines;
                       for i := 0 to chaines.Count-1 do
                           pages[pageCourante].TexteVar[indexCourant,i] := chaines[i];
                       exit;
                    end
                    else begin
                       ExtraitValeurs;
                    end;
      constante : begin
           pages[pageCourante].valeurConst[indexCourant] := getFloatXML(XMLNode);
           exit;
      end;
      paramNormal : begin
           code := indexToParam(paramNormal,indexCourant);
           pages[pageCourante].valeurParam[paramNormal,code] := getFloatXML(XMLNode);
           exit;
      end;
   end;
end;

if (XmlNode.NodeName='VARIABLE') then begin
    nom := GetNomXML(XMLNode);
    indexCourant := AjouteExperimentale(nom,variable);
    suite;
    exit;
end;

if (XmlNode.NodeName='MODELE') then begin
    suite;
    exit;
end;

if (XmlNode.NodeName='DEBUT') then begin
    pageCourante := getPageXML(XMLNode);
    modeleCourant := getIndexXML(XMLNode);
    pages[pageCourante].debut[modeleCourant] := getIntegerXML(XMLNode);
    exit;
end;

if (XmlNode.NodeName='FIN') then begin
    pageCourante := getPageXML(XMLNode);
    modeleCourant := getIndexXML(XMLNode);
    pages[pageCourante].fin[modeleCourant] := getIntegerXML(XMLNode);
    exit;
end;

if (XmlNode.NodeName='CONSTANTE') then begin
    nom := GetNomXML(XMLNode);
    indexCourant := AjouteExperimentale(nom,constante);
    suite;
    exit;
end;

if (XmlNode.NodeName='PARAMETRE') then begin
    nom := GetNomXML(XMLNode);
    indexCourant := GetIndexXML(XMLNOde);
    parametres[paramNormal,indexCourant].nom := nom;
    if indexCourant>NbreParam[paramNormal] then
       NbreParam[paramNormal] := indexCourant;
    indexCourant := paramToIndex(paramNormal,indexCourant);
    suite;
    exit;
end;

if (XmlNode.NodeName='Trigo') then begin
    AngleEnDegre := GetBoolXML(XMLNode);
    exit;
end;

if (XmlNode.NodeName='NbreDerivee') then begin
    NbrePointDerivee := GetIntegerXML(XMLNode);
    exit;
end;

if (XmlNode.NodeName='SOURCE') then begin
   suite;
   exit;
end;

if XMLNode.NodeName='Unite' then begin
      grandeurs[indexCourant].nomUnite := XMLNode.NodeValue;
      exit;
end;
if XMLNode.NodeName='GenreCalcul' then begin
      code := getIntegerXML(XMLNode);
      grandeurs[indexCourant].fonct.genreC := TGenreCalcul(code);
      exit;
end;
if XMLNode.NodeName='Description' then begin
      grandeurs[indexCourant].fonct.expression := XMLNode.NodeValue;
      exit;
end;

end; // LoadXMLInReg

begin // LitFichierXML
codeErreurF := erFileData;
ModeAcquisition := AcqFichier;
chaines := TStringList.create;
chaines.Delimiter := crCR;
try
ReadXmlFile(XmlDoc,NomFichier);
if (XMLDoc.DocumentElement.NodeName='Regressi')
   then begin
      LoadXMLInReg(XMLDoc.DocumentElement);
      result := true;
   end
   else begin
      result := false;
      codeErreurF := erReadRegressiXML;
   end;
except
    codeErreurF := erReadFile;
    result := false;
    resetEnTete;
end;
chaines.free;
end; // LitFichierXML

function LitFichierVotable(const NomFichier : String) : boolean;
const
  maxVotable = 32;
type
  tVotable = (vChar,vDouble,vCharDate,vCharAngle,vCharheure,vInteger,vBoolean);
var
  TypeColonne : array[0..maxVotable] of TVotable;
  formatISO : TFormatSettings;
  commentaire : string;

Function RecupereAngle(chaine : string) : double;
var N : integer;
    c : integer;
    items : array[1..3] of string;
begin
    for N := 1 to 3 do Items[N] := '';
    N := 1;
    c := 1;
    repeat
       if charInSet(chaine[c],['0'..'9','E','.','-','+'])
          then Items[N] := Items[N] + chaine[c]
          else if CharInSet(chaine[c],[crTab,' ','|']) and
                  (Items[N]<>'') then inc(N);
       inc(c);
    until (N=4) or (c>length(chaine));
    result := StrToFloatSex(Items[1],Items[2],Items[3]);
end;

Function RecupereDate(chaine : string) : double;
var dateStr,heureStr : string;
    posT : integer;
begin

    posT := pos('T',chaine);
    dateStr := DateToStr(now);
    heureStr := '00:00:00';
    if posT>0 then begin
       DateStr := copy(chaine,1,posT-1);
       trimASCII127(dateStr);
       HeureStr := copy(chaine,posT+1,length(chaine)-posT);
       posT := pos('.',HeureStr);
       if posT>0 then delete(heureStr,posT,length(HeureStr));
    end;
    result := double(StrToDate(dateStr,FormatISO))+double(StrToTime(heureStr));
end;

Function recupereHeure(chaine : string) : double;
var posPoint,posPointSuivant : integer;
    compteur : integer;
begin
     posPoint := pos('.',chaine);
     if posPoint>0 then delete(chaine,posPoint,length(chaine)-1);
// on ôte les centième de seconde
     repeat
         posPoint := pos(' ',chaine);
         if posPoint=1 then delete(chaine,1,1);
     until (posPoint>1) or (posPoint=0);
// on ôte les blanc d'en-tête
     compteur := 0;
     repeat
       posPoint := pos(' ',chaine);
       if posPoint>0 then begin
          chaine[posPoint] := ':';
          inc(compteur);
          posPointSuivant := pos(' ',chaine);
          if posPointSuivant=posPoint+1 then chaine[posPointSuivant] := '0';
       end;
     until (posPoint=0); // on remplace blanc par : et double espace par :0
     if compteur<2 then chaine := '0:'+chaine;  // pas d'heure = heure 0
     // angle exprimée en heure transformé en degré
     result := Double(strToTime(chaine));
     result := result*360.0;
end;

var
colC,rowC : integer;

procedure LoadXMLInReg(XMLNode: TDOMNode;fieldEnCours : boolean);
var
I: Integer;
AttributNoeud, Node: TDOMNode;
isField : boolean;
isParam : boolean;
isLigne : boolean;
isInfo : boolean;
valeurStr : string;
begin //Les noeuds internes sont traitées récursivement

if (XmlNode.NodeName='vot:FRESOURCE') then ; // cébut des données

isParam := (XmlNode.NodeName='vot:PARAM');

isField := (XmlNode.NodeName='vot:FIELD');
if isField then begin
   AjouteExperimentale('xxxx',variable);
end;

if (XMLNode.NodeName='vot:TABLEDATA') then begin // début de table
   colC := 0;
   rowC := 0;
   ajoutePage;
end;

isLigne := XmlNode.NodeName='vot:TR';
if isLigne then begin
   pages[pageCourante].nmes := pages[pageCourante].nmes + 1;
end;

if (XmlNode.NodeName='vot:TD') then begin
   valeurStr := XMLNode.NodeValue;
   case typeColonne[colC] of
        vChar : pages[pageCourante].texteVar[colC,rowC] := valeurStr;
        vDouble : pages[pageCourante].valeurVar[colC,rowC] := strToFloatWin(valeurStr);
        vCharDate : pages[pageCourante].valeurVar[colC,rowC] := recupereDate(valeurStr);
        vCharAngle : pages[pageCourante].valeurVar[colC,rowC] := recupereAngle(valeurStr);
        vCharHeure : pages[pageCourante].valeurVar[colC,rowC] := recupereHeure(valeurStr);
   end;
   inc(colC);
end;

if (XmlNode.NodeName='vot:DESCRIPTION') and FieldEnCours then begin
   grandeurs[colC].fonct.expression := XMLNode.NodeValue;
   if pos('ISO',XMLNode.NodeValue)>0 then begin
      typeColonne[colC] := vCharDate;
      grandeurs[colC].formatU := fDate;
   end;
   if typeColonne[colC]=vChar then grandeurs[colC].fonct.genreC := g_texte;
end;

//S'il y a des attributs on les ajoute...
isInfo := false;
for I := 0 to XMLNode.Attributes.Length - 1 do begin
AttributNoeud := XMLNode.Attributes[I];
if isParam then begin
   if AttributNoeud.NodeName='ID' then begin
      if AttributNoeud.NodeValue='coordinates' then isInfo := true;
      if AttributNoeud.NodeValue='framecentre' then isInfo := true;
      if AttributNoeud.NodeValue='targetname' then isInfo := true;
   end;
   if (AttributNoeud.NodeName='value')  and isInfo then
      if commentaire=''
         then Commentaire := AttributNoeud.NodeValue
         else Commentaire := Commentaire + ' - ' + AttributNoeud.NodeValue;
end;
if isField then begin
   if AttributNoeud.NodeName='name' then begin
      grandeurs[colC].nom := AttributNoeud.NodeValue;
   end;
   if AttributNoeud.NodeName='unit' then begin
      if AttributNoeud.NodeValue='"h:m:s"' then begin
         typeColonne[colC] := vCharHeure;
         grandeurs[colC].nomUnite := '°';
      end;
      if AttributNoeud.NodeValue='"d:m:s"' then begin
         typeColonne[colC] := vCharAngle;
         grandeurs[colC].nomUnite := '°';
      end;
      if typeColonne[colC]=vDouble then
         grandeurs[colC].nomUnite := AttributNoeud.NodeValue;
   end;
   if AttributNoeud.NodeName='datatype' then begin
      if AttributNoeud.NodeValue='char' then typeColonne[colC] := vChar;
      if AttributNoeud.NodeValue='unicodechar' then typeColonne[colC] := vChar;
      if AttributNoeud.NodeValue='double' then typeColonne[colC] := vDouble;
      if AttributNoeud.NodeValue='float' then typeColonne[colC] := vDouble;
      if AttributNoeud.NodeValue='short' then typeColonne[colC] := vInteger;
      if AttributNoeud.NodeValue='long' then typeColonne[colC] := vInteger;
      if AttributNoeud.NodeValue='int' then typeColonne[colC] := vInteger;
      if AttributNoeud.NodeValue='boolean' then typeColonne[colC] := vBoolean;
   end;
end;
end;

//si le noeud courant a des noeuds enfants, on les ajoute
if XMLNode.HasChildNodes then begin
    Node := XMLNode.FirstChild;
    while Node <> Nil do begin
      LoadXMLInReg(Node,isField);
      Node := Node.NextSibling;
      if isLigne then begin // ligneSuivante
        inc(rowC);
        colC := 0;
      end;
    end;
end;

if isField then inc(colC); // colonneSuivante
end; // LoadXMLInReg

var XMLDoc : TXMLDocument;
    i : integer;
    indexDateTexte : integer;
    t0 : double;
begin // litFichierVotable
ModeAcquisition := AcqFichier;
for i := 0 to maxVotable do typeColonne[i] := vChar;
XMLDoc := TXMLDocument.Create;
try
readXMLFile(XmlDoc,NomFichier);
colC := 0;
rowC := 1;
//formatISO := TFormatSettings.Create;
formatISO.DateSeparator := '-'; // ISO
formatISO.ShortDateFormat := 'yyyy-MM-dd';
if (XMLDoc.DocumentElement.NodeName='vot:VOTABLE')
   then begin
      LoadXMLInReg(XMLDoc.DocumentElement,false);
      result := true;
      pages[pageCourante].CommentaireP := Commentaire;
      supprimeGrandeurE(0); // target : nom de la planète répété N fois
      if grandeurs[0].nom='Date' then begin
         grandeurs[0].nom := 't';
         grandeurs[0].nomUnite := 'jour';
         indexDateTexte := ajouteExperimentale('Date',variable);
         grandeurs[indexDateTexte].fonct.genreC := g_texte;
         with pages[pageCourante] do begin
         t0 := valeurVar[0,0];
         for i := 0 to nmes-1 do  begin
             texteVar[indexDateTexte,i] := FormatDateTime('dd mmm yyyy',valeurVar[0,i]);
             valeurVar[0,i] := valeurVar[0,i]-t0;
         end;
         end;
      end;
   end
   else begin
      result := false;
      codeErreurF := erReadVotable;
   end;
except
    codeErreurF := erReadFile;
    result := false;
    resetEnTete;
end;
end; // litFichierVotable

function LitFichierFITS(const NomFichier : String) : boolean;
var FFit: TFitsFileBitmap;
    lambda,intensite : Tspectre;
    i,imax : integer;
    coeff : double;
begin
   result := false;
   try
   ModeAcquisition := AcqFichier;
   FFit := TFitsFileBitmap.CreateJoin(NomFichier, cFileRead);
   if FFIT.HduCore.isSpectre then begin
      FFit.SpectreRead(lambda,intensite);
      imax := length(intensite);
      AjouteExperimentale('λ',variable);
      grandeurs[0].fonct.expression := 'Longueur d''onde';
      grandeurs[0].nomUnite := FFit.HduCore.uniteX;
      coeff := 1;
      if (pos('ANG', grandeurs[0].nomUnite)>0) or
         (pos('Ang', grandeurs[0].nomUnite)>0) or
         (grandeurs[0].nomUnite='') then begin
         grandeurs[0].nomUnite := 'nm';
         coeff := 0.1;
      end;
      if ('um'=grandeurs[0].nomUnite) then begin
         grandeurs[0].nomUnite := 'nm';
         coeff := 1000;
      end;
      AjouteExperimentale('I',variable);
      grandeurs[1].fonct.expression := 'Intensite';
      grandeurs[1].nomUnite := FFit.HduCore.uniteY;
      result := ajoutePage;
      if not result then exit;
      pages[pageCourante].nmes := imax;
      for i := 0 to imax do begin
         pages[pageCourante].ValeurVar[0,i] := lambda[i]*coeff;
         pages[pageCourante].ValeurVar[1,i] := intensite[i];
      end;
      result := true;
   end
   else showMessage('N''est pas un fichier de spectre');
   FFit.Free;
   except
      result := false;
      codeErreurF := erFileLoad;
   end;
end;

Function AjouteFichierFITS(const NomFichier : String) : boolean;
var FFit: TFitsFileBitmap;
    lambda,intensite : Tspectre;
    i,imax : integer;
    coeff : double;
begin
   result := false;
   try
   FFit := TFitsFileBitmap.CreateJoin(NomFichier, cFileRead);
   if FFIT.HduCore.isSpectre then begin
      FFit.SpectreRead(lambda,intensite);
      imax := length(intensite);
      coeff := 1;
      if (pos('ANG', FFit.HduCore.uniteX)>0) or
         (pos('Ang',  FFit.HduCore.uniteX)>0) or
         (grandeurs[0].nomUnite='') then begin
         coeff := 0.1;
      end;
      if ('um'=FFit.HduCore.uniteX) then begin
         coeff := 1000;
      end;
      result := ajoutePage;
      if not result then exit;
      pages[pageCourante].nmes := imax;
      for i := 0 to imax do begin
         pages[pageCourante].ValeurVar[0,i] := lambda[i]*coeff;
         pages[pageCourante].ValeurVar[1,i] := intensite[i];
      end;
      result := true;
   end
   else showMessage('N''est pas un fichier de spectre');
   FFit.Free;
   except
      codeErreurF := erFileLoad;
   end;
end;

end.


procedure XML2Tree(XMLDoc:TXMLDocument; TreeView:TTreeView);

  // Local function that outputs all node attributes as a string
  function GetNodeAttributesAsString(pNode: TDOMNode):string;
  var i: integer;
  begin
    Result:='';
    if pNode.HasAttributes then
      for i := 0 to pNode.Attributes.Length -1 do
        with pNode.Attributes[i] do
          Result := Result + format(' %s="%s"', [NodeName, NodeValue]);

    // Remove leading and trailing spaces
    Result:=Trim(Result);
  end;

  // Recursive function to process a node and all its child nodes

  procedure ParseXML(Node:TDOMNode; TreeNode: TTreeNode);
  begin
    // Exit procedure if no more nodes to process
    if Node = nil then Exit;

    // Add node to TreeView
    TreeNode := TreeView.Items.AddChild(TreeNode,
                                          Trim(Node.NodeName+' '+
                                           GetNodeAttributesAsString(Node)+
                                           Node.NodeValue)
                                        );

    // Process all child nodes
    Node := Node.FirstChild;
    while Node <> Nil do
    begin
      ParseXML(Node, TreeNode);
      Node := Node.NextSibling;
    end;
  end;

begin
  TreeView.Items.Clear;
  ParseXML(XMLDoc.DocumentElement,nil);
end;


function CreateElement(const tagName: DOMString): TDOMElement; virtual;
function CreateTextNode(const data: DOMString): TDOMText;
function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
CreateElement creates a new element.
CreateTextNode creates a text node.
CreateAttribute creates an attribute node.

procedure TForm1.EcritXML;
var
 Doc: TXMLDocument;                                  // variable to document
 RootNode, parentNode, nofilho: TDOMNode;                    // variable to nodes
begin
 try
   // Create a document
   Doc := TXMLDocument.Create;

   // Create a root node
   RootNode := Doc.CreateElement('register');
   Doc.Appendchild(RootNode);                           // save root node

   // Create a parent node
   RootNode:= Doc.DocumentElement;
   parentNode := Doc.CreateElement('usuario');
   TDOMElement(parentNode).SetAttribute('id', '001');       // create atributes to parent node
   RootNode.Appendchild(parentNode);                          // save parent node

   // Create a child node
   parentNode := Doc.CreateElement('nome');                // create a child node
   TDOMElement(parentNode).SetAttribute('sexo', 'M');     // create atributes
   nofilho := Doc.CreateTextNode('Fernando');         // insert a value to node
   parentNode.Appendchild(nofilho);                         // save node
   RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert child node in respective parent node

   // Create a child node
   parentNode := Doc.CreateElement('idade');               // create a child node
   TDOMElement(parentNode).SetAttribute('ano', '1976');   // create atributes
   nofilho := Doc.CreateTextNode('32');               // insert a value to node
   parentNode.Appendchild(nofilho);                         // save node
   RootNode.ChildNodes.Item[0].AppendChild(parentNode);       // insert a childnode in respective parent node

   writeXMLFile(Doc, 'test.xml');                     // write to XML
 finally
   Doc.Free;                                          // free memory
 end;
end;

