/* This is CondLean's Graphical User Interface source code, written in Java */


/* Importing packages */

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.*;
import se.sics.jasper.*;
import java.util.HashMap;
import java.io.*;



/* ------------------------------------------------------------------------------------------------- */

/* This class represents a proof tree */

class Tree {
  String sequente;
  String regola;
  String antecedente;
  String conseguente;
  Tree leftProof;
  Tree rightProof;
  public Tree (String seq,String reg,String antec,String conseg,Tree left,Tree right){
    sequente=new String(seq);
     regola=new String(reg);
     antecedente=new String(antec);
     conseguente=new String(conseg);
     leftProof=left;
     rightProof=right;
  }
  public int righeOccupate (){
    return calcolaRighe(0);
  }
  private int calcolaRighe (int branches){ 
    /* We have max 3 branches in a proof tree; in that case, the proof tree needs 3 rows */
    if (branches==3) return 3;
     else {
       /* the sequente is an axiom: heigth=2 */
       if (leftProof==null) return 2;
        /* the tree has one son; its heigth is 2+son's heigth */
        else if (rightProof==null)
          return (2+leftProof.calcolaRighe(branches));
        /* the tree has two sons 2+max heigth of its sons */
       else {
          /* the number of branches isincremented */
          int leftRows=leftProof.calcolaRighe(branches+1);
          int rightRows=rightProof.calcolaRighe(branches+1);
          if (leftRows>rightRows) return 2+leftRows;
          else return 2+rightRows;
        }
     }
  }

}




/* ------------------------------------------------------------------------------------------------- */

/* This listener instances a graphical window which shows a proof tree */

class ListenerAlberoDiProva implements ActionListener {
  private String alberoComeStringa;
  private Tree albero;
  private SICStus sp;
  private String messaggio;
  private int dimensione;
  private int seqIndici [];
  public ListenerAlberoDiProva (SICStus sp, String alberoComeStringa, String msg, int sequenzaIndici [], int dim){
     this.alberoComeStringa=alberoComeStringa;
     this.sp=sp;
     messaggio=msg;
     dimensione=dim;
     seqIndici=sequenzaIndici;
  }
  public ListenerAlberoDiProva (Tree t, String msg, int sequenzaIndici [], int dim){
     albero=t;
     messaggio=msg;
     dimensione=dim;
     seqIndici=sequenzaIndici;
  }
  public void actionPerformed (ActionEvent e){
    if(albero==null){
      System.out.println("");
     /* Feedback in the command window */
      System.out.println("Building the proof tree: please, wait a while...");
      int stima=(int)(alberoComeStringa.length()/400);
      System.out.println("Time to elapse: "+Integer.toString(stima)+" seconds");
      albero=new OggettiUtili().costruisciAlberoJava(sp,alberoComeStringa,"[]","[]");
     System.out.println("Operation completed");
    }
    int righe=albero.righeOccupate();
    Prover p=new Prover(new String(messaggio+" of the sequent:  "+new OggettiUtili().eliminaTagHtml(albero.sequente)),righe+1);
    p.pack();
    p.setVisible(true);
    p.paint(albero,1,15,righe-1,seqIndici,dimensione);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Listener that shows the whole sequent in a box of the control window */

class SeqListener implements ActionListener {
  String sequente;
  JLabel where;
  public SeqListener (String seq, JLabel box){
    where=box;
    sequente=new String(seq);
  }
  public void actionPerformed (ActionEvent e){
    /* Html tags lets JLabel to show its text with different colrs */
    where.setText("<html><body><font color=black size=4><center>"+sequente+"</center></font></body></html>");
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Matrix used to show a proof tree in a special window */

class Bottoniera{
  private JButton bottoni [][];

  public Bottoniera (int rows, int cols){
    int i,j;
     bottoni=new JButton [rows][cols];
     for (i=0;i<rows;i++)
       for (j=0;j<cols;j++){
          bottoni[i][j]=new JButton ();
          bottoni[i][j].setBorderPainted(false);
        }
  }

  /* This method introduce a listener for the button */
  public void setListener (int i,int j, ActionListener listener){
    bottoni[i][j].addActionListener(listener);
     bottoni[i][j].setCursor(new Cursor(12));
  }

  public void setValueAt (String value, String seqSulBottone, int i, int j, JLabel where){
    int taglio=19;
     /* Deleting html tags */
     String sulBottone=new String();
     boolean htmlTag=false;
     for (int k=0;k<seqSulBottone.length();k++)
       if ((htmlTag)||(seqSulBottone.charAt(k)=='<')||((htmlTag)&&(seqSulBottone.charAt(k)=='>')))
          if (seqSulBottone.charAt(k)=='>')
            htmlTag=false;
          else htmlTag=true;
        else sulBottone=sulBottone+seqSulBottone.charAt(k);
     boolean hoTagliato=false;
     if (sulBottone.length()<=(taglio+3)) taglio=sulBottone.length();
     else hoTagliato=true;
     sulBottone=sulBottone.substring(0,taglio);
     if (hoTagliato)
       sulBottone=sulBottone+"...";
     bottoni[i][j].setFont(new Font("serif",Font.ITALIC,14));
     bottoni[i][j].setText(sulBottone);  
     setListener(i,j,new SeqListener(value,where));
     bottoni[i][j].setToolTipText("Click here to see the whole sequent");
  }

  public void setValueAt (ImageIcon value, int i, int j){
    bottoni[i][j].setIcon(value);
     bottoni[i][j].setContentAreaFilled(false);
     bottoni[i][j].setFocusPainted(false);
     bottoni[i][j].setBorder(new LineBorder(Color.lightGray,1));
     bottoni[i][j].setMargin(new Insets(1,1,1,1));
  }

  public void setValueAt (int vettoreIndici [], int dim, int i, int j){
    bottoni[i][j].setIcon(new ImageIcon("p.jpg"));
     String seqIndici=new String("<html><body><I><B>");
     for (int ind=0;ind<dim;ind++)
       seqIndici=seqIndici+Integer.toString(vettoreIndici[ind])+",";
     seqIndici=seqIndici.substring(0,seqIndici.length()-1);
     seqIndici=seqIndici+"</B></I></body></html>";
     bottoni[i][j].setText(seqIndici);
     bottoni[i][j].setVerticalTextPosition(JLabel.BOTTOM);
     bottoni[i][j].setHorizontalTextPosition(JLabel.SOUTH_EAST);
     bottoni[i][j].setContentAreaFilled(false);
     bottoni[i][j].setFocusPainted(false);
     bottoni[i][j].setBorder(new LineBorder(Color.lightGray,1));
     bottoni[i][j].setMargin(new Insets(1,1,1,1));
  }

  public JButton getButton (int i, int j){
    return (bottoni[i][j]);
  }

}




/* ------------------------------------------------------------------------------------------------- */

/* This class is a a grphical window which shows a proof tree */

class Prover extends JFrame{
  private Bottoniera screen;
  private int sottoprove;  
  public JLabel box;

  public Prover (String titolo,int rows){
    super(titolo);
    int i,j;
     Container cp=getContentPane();
     cp.setLayout(new BorderLayout());
     screen=new Bottoniera (rows,15);

     JPanel panBot=new JPanel();
     JScrollPane contScroll=new JScrollPane(panBot);
     int dimensioneInRighe=rows*40;
     if (dimensioneInRighe>600) dimensioneInRighe=600;
     contScroll.setPreferredSize(new Dimension(900,dimensioneInRighe));
     cp.add(contScroll,BorderLayout.CENTER);

     JPanel pan2=new JPanel();
     cp.add(pan2,BorderLayout.SOUTH);
     int ind=0;
     while(titolo.charAt(ind)!=':')
       ind++;
     ind=ind+2;
     box=new JLabel("<html><body><center><font size=4 color=black>"+titolo.substring(ind,titolo.length())+"</font></center></body></html>");
     pan2.add(box);
     sottoprove=0;


     /* Inserting window's buttons */
     GridBagLayout gridbag = new GridBagLayout();
     GridBagConstraints c = new GridBagConstraints();
     panBot.setLayout(gridbag);         

     c.fill = GridBagConstraints.BOTH;

     c.weightx = 1.0;   
     JButton bott;  
     for (i=0;i<28;i++){
       bott=new JButton();
        bott.setBorderPainted(false);
       attacca(bott,panBot,gridbag,c);
     }
     c.gridwidth = GridBagConstraints.REMAINDER; 
     bott=new JButton();
     bott.setBorderPainted(false);
     attacca(bott,panBot,gridbag,c);

     for (i=0;i<rows;i++){
       for (j=0;j<14;j=j+2){
         c.gridwidth=1;
         attacca(screen.getButton(i,j),panBot,gridbag,c);
         c.gridwidth=3;
         attacca(screen.getButton(i,j+1),panBot,gridbag,c);
      }
     c.gridwidth=GridBagConstraints.REMAINDER;
     attacca(screen.getButton(i,14),panBot,gridbag,c);
   }

    setSize(400, 300);     

  }

  private void attacca (JButton b, JComponent comp, GridBagLayout gridbag, GridBagConstraints c){
    gridbag.setConstraints(b,c);
     comp.add(b);
  }

  public void paint (Tree alberoDiProva,int da,int a,int riga,int seqIndici [],int dim){
    int colonna=(da+a)/2;
     String sequenteSulBottone=new String();
     sequenteSulBottone=alberoDiProva.antecedente+
       "...|- "+alberoDiProva.conseguente+"...";
    screen.setValueAt(alberoDiProva.sequente,sequenteSulBottone,riga,colonna-1,box);
    if((alberoDiProva.leftProof!=null)&&(alberoDiProva.rightProof!=null)){
      /* the rule applied has two sons */
      if ((colonna%4)!=0){
         /* there is not enough space to show the whole proof tree */
       sottoprove++;
        seqIndici[dim]=sottoprove;
       screen.setValueAt(seqIndici,dim+1,riga-2,colonna-1);
        int copiaSeqIndici [];
        copiaSeqIndici=new int [10];
        for (int w=0;w<dim+1;w++)
          copiaSeqIndici[w]=seqIndici[w];
        screen.setListener(riga-2,colonna-1,new ListenerAlberoDiProva(alberoDiProva,"Sub-proof tree",copiaSeqIndici,dim+1));
        screen.setValueAt(immagineRegola(alberoDiProva.regola,1),riga-1,colonna-1);
        screen.getButton(riga-2,colonna-1).setToolTipText("Click here to view the sub-proof tree");
      }
      else{
      /* The following code introduce an image of the applicated rule */
        if (colonna==8){
        screen.setValueAt(immagineRegola(alberoDiProva.regola,1),riga-1,3);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,4);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,5);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,6);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,7);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,8);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,9);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,10);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,11);
        }
        else if (colonna==4){
        screen.setValueAt(immagineRegola(alberoDiProva.regola,1),riga-1,1);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,2);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,3);
        screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,4);
        screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,5);
        }
        else{
        /* colonna=12 */
          screen.setValueAt(immagineRegola(alberoDiProva.regola,1),riga-1,9);
          screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,10);
          screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,11);
          screen.setValueAt(new ImageIcon("lineacorta.jpg"),riga-1,12);
          screen.setValueAt(new ImageIcon("linea.jpg"),riga-1,13);
        }
      paint(alberoDiProva.leftProof,da,colonna-1,riga-2,seqIndici,dim);
      paint(alberoDiProva.rightProof,colonna+1,a,riga-2,seqIndici,dim);
      }
   }
    else 
       if ((alberoDiProva.rightProof==null)&&(alberoDiProva.leftProof!=null)){
         /* The rule applied has one son */
        screen.setValueAt(immagineRegola(alberoDiProva.regola,1),riga-1,colonna-1);
        paint(alberoDiProva.leftProof,da,a,riga-2,seqIndici,dim);
       }
    /* the sequent is an axiom: computation is terminated */
       else screen.setValueAt(immagineRegola("assioma",1),riga-1,colonna-1);
  }


  /* This method chooses the correct image of each rule*/
  private ImageIcon immagineRegola(String regola,int type){
    String s=new String(regola);
    /* type=0: short line; type=1: long line */
     if (type==0){
          if (s.compareTo("impL")==0) return new ImageIcon("impLcorta.jpg");
          if (s.compareTo("condL")==0) return new ImageIcon("condLcorta.jpg");
          if (s.compareTo("andR")==0) return new ImageIcon("andRcorta.jpg");
          if (s.compareTo("orL")==0) return new ImageIcon("orLcorta.jpg");
          if (s.compareTo("eq")==0) return new ImageIcon("EQcorta.jpg");
          return null;
     }
     else if (type==1){
          if (s.compareTo("assioma")==0) return new ImageIcon("AXlunga.jpg");
          if (s.compareTo("negL")==0) return new ImageIcon("notLlunga.jpg");
          if (s.compareTo("negR")==0) return new ImageIcon("notRlunga.jpg");
          if (s.compareTo("impL")==0) return new ImageIcon("impLlunga.jpg");
          if (s.compareTo("impR")==0) return new ImageIcon("impRlunga.jpg");
          if (s.compareTo("condL")==0) return new ImageIcon("condLlunga.jpg");
          if (s.compareTo("condR")==0) return new ImageIcon("condRlunga.jpg");
          if (s.compareTo("andL")==0) return new ImageIcon("andLlunga.jpg");
          if (s.compareTo("andR")==0) return new ImageIcon("andRlunga.jpg");
          if (s.compareTo("orL")==0) return new ImageIcon("orLlunga.jpg");
          if (s.compareTo("orR")==0) return new ImageIcon("orRlunga.jpg");
          if (s.compareTo("eq")==0) return new ImageIcon("EQlunga.jpg");
          if (s.compareTo("mp")==0) return new ImageIcon("MPlunga.jpg");
          if (s.compareTo("id")==0) return new ImageIcon("IDlunga.jpg");
          if (s.compareTo("contrL")==0) return new ImageIcon("contrLlunga.jpg");
          if (s.compareTo("contrR")==0) return new ImageIcon("contrRlunga.jpg");
          return null;
    }
     else return null;
  }

}





/* ------------------------------------------------------------------------------------------------- */

/* This class lets the user to close CondLean closing its control (main) window */

class ClosingListener extends WindowAdapter{
  public void windowClosing (WindowEvent e){
    System.exit(0);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Class for CondLean's menù bar */

class BarraMenu extends JMenuBar{
  public BarraMenu (JLabel immagine){

    /* Recovery of old settings: reading from 'param.pos' file */
    int vett[]=null;
    try{
      /* Classes ObjectInputStream, BufferedInputStream and FileInputStream are 
         used to read from a file */
      ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("param.pos")));
      vett=(int [])in.readObject();
      in.close();
     }catch(Exception e){System.out.println("ERROR: read-file failure.");}
    /* vett contains old settings */



    /* 1st menù item: Settings */

    /* 1st item: font size in output file .tex */
    JMenu parametri=new JMenu("Settings");
    parametri.setMnemonic(KeyEvent.VK_S);
    JMenu dimCar=new JMenu("Character size in latex file");
    dimCar.addSeparator();
    ButtonGroup gruppoDimCar=new ButtonGroup();
    JRadioButtonMenuItem [] vettTipiCar=new JRadioButtonMenuItem [5];
    vettTipiCar [0]=new JRadioButtonMenuItem("Very small");
    vettTipiCar [1]=new JRadioButtonMenuItem("Small");
    vettTipiCar [2]=new JRadioButtonMenuItem("Normal");
    vettTipiCar [3]=new JRadioButtonMenuItem("Big");
    vettTipiCar [4]=new JRadioButtonMenuItem("Very big");
    int i;
    for (i=0;i<5;i++)
      vettTipiCar [i].addActionListener(new CambiaParametro(0,i,vett));
    vettTipiCar[vett[0]].setSelected(true);
    for (i=0; i<5; i++){
      gruppoDimCar.add(vettTipiCar [i]);
      dimCar.add(vettTipiCar [i]);
    }

    /* 2nd item: choosing the version of the theorem prover */
    JMenu tipoImplem=new JMenu("Theorem prover's version");
    tipoImplem.addSeparator();
    JRadioButtonMenuItem [] tipiImpl=new JRadioButtonMenuItem [3];
    tipiImpl [0]=new JRadioButtonMenuItem("Constant labels");
    tipiImpl [1]=new JRadioButtonMenuItem("Free variable");
    tipiImpl [2]=new JRadioButtonMenuItem("Euristic version");
    ButtonGroup gruppoTipiImpl=new ButtonGroup();
    for (i=0;i<3;i++)
      tipiImpl [i].addActionListener(new CambiaParametro(1,i,vett));
    tipiImpl[vett[1]].setSelected(true);
    for (i=0; i<3; i++){
      gruppoTipiImpl.add(tipiImpl [i]);
      tipoImplem.add(tipiImpl [i]);
    }


    /* 3rd item: choosing the theorem prover */
    JMenu tipoThPr=new JMenu("Theorem prover");
    tipoThPr.addSeparator();
    JRadioButtonMenuItem [] tipiTP=new JRadioButtonMenuItem [4];
    tipiTP [0]=new JRadioButtonMenuItem("SeqCK (CK system)");
    tipiTP [1]=new JRadioButtonMenuItem("SeqID (CK+ID system)");
    tipiTP [2]=new JRadioButtonMenuItem("SeqMP (CK+MP system)");
    tipiTP [3]=new JRadioButtonMenuItem("SeqID+MP (CK+MP+ID system)");
    ButtonGroup gruppoTP=new ButtonGroup();
    for (i=0;i<4;i++)
      tipiTP [i].addActionListener(new CambiaTheoremProver(i,vett,immagine));
    tipiTP[vett[2]].setSelected(true);
    for (i=0; i<4; i++){
      gruppoTP.add(tipiTP [i]);
      tipoThPr.add(tipiTP [i]);
    }

    parametri.add(tipoThPr);
    parametri.add(tipoImplem);
    parametri.add(dimCar);


    /* 2nd menù item: Options */

    JMenu opzioni=new JMenu("Options");
    opzioni.setMnemonic(KeyEvent.VK_O);
    JMenuItem doveOutput=new JMenuItem("Choose output directory");
    JMenuItem attualeOutput=new JMenuItem("Current directory");
    doveOutput.addActionListener(new LanciaFileChooser(doveOutput));
    attualeOutput.addActionListener(new ImpostazioniAttuali());
    opzioni.add(doveOutput);
    opzioni.add(attualeOutput);


    /* 3rd menù item: Help */
    JMenu help=new JMenu("Help");
    help.setMnemonic(KeyEvent.VK_H);
    JMenuItem [] vettAiuti=new JMenuItem [2];
    vettAiuti[0]=new JMenuItem("How to prove a sequent");
    vettAiuti[1]=new JMenuItem("How to compute your latex file");
    vettAiuti[0].addActionListener(new ListenerAiuto("dimostra.htm"));
    vettAiuti[1].addActionListener(new ListenerAiuto("output.htm"));
    for (i=0;i<2;i++)
      help.add(vettAiuti[i]);

    /* Adds items to the menù bar */
    add(parametri);
    add(opzioni);
    add(help);
  }
}






/* ------------------------------------------------------------------------------------------------- */

/* Listener that shows current settings */

class ImpostazioniAttuali implements ActionListener{
  public void actionPerformed(ActionEvent e){
    /* Recupero della directory attualmente impostata */
    String dirAttuale=new String("");
    try{
      ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("output_dest.pos")));    
      dirAttuale=(String)in.readObject();
      in.close();
    }catch(Exception excp){System.out.println("ERROR reading file 'output_dest.pos'.");}
    JFrame f=new JFrame("Current settings");
    Container cp=f.getContentPane();
    cp.setLayout(new BorderLayout());
    JLabel lab=new JLabel("Current output directory: "+dirAttuale);
    lab.setIcon(new ImageIcon("impostazioni.jpg"));
    cp.add(lab,BorderLayout.CENTER);
    f.pack();
    f.setVisible(true);
  }
}






/* ------------------------------------------------------------------------------------------------- */

/* Listener that shows a html page into a graphical window */

class ListenerAiuto implements ActionListener{
  private String fileName;
  public ListenerAiuto (String fileName){
    this.fileName=fileName;
  }
  public void actionPerformed (ActionEvent e){
    JFrame f=new JFrame("Help");
    Container cp=f.getContentPane();
    cp.setLayout(new BorderLayout());
    JEditorPane editorPane = new JEditorPane();
    JScrollPane scr=new JScrollPane(editorPane);
    scr.setPreferredSize(new Dimension(800,600));
    cp.add(scr,BorderLayout.CENTER);
    editorPane.setEditable(false);
    try {
      String s = null;
      s = "file:" + System.getProperty("user.dir")
      + System.getProperty("file.separator") + fileName;
      editorPane.setPage(s);
    }catch (IOException excp) {System.out.println("ERROR reading help files.");}
    f.pack();
    f.setVisible(true);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Listener for choosing the output directory */

class LanciaFileChooser implements ActionListener{
  JComponent comp;
  public LanciaFileChooser (JComponent c){
    comp=c;
  }
  public void actionPerformed (ActionEvent e){
    JFileChooser fc=new JFileChooser();
    comp.add(fc,BorderLayout.CENTER);
    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    int retValue=fc.showOpenDialog(null);
    File pf;
    if(retValue==JFileChooser.APPROVE_OPTION){
      pf=fc.getSelectedFile();
      /* The selected directory is stored in file 'output_dest.pos' */
    try{
        ObjectOutputStream out=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("output_dest.pos")));
        out.writeObject(pf.getAbsolutePath());
        out.close();
       }catch(Exception excp){System.out.println("ERROR setting the output directory");}
    }
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Listener used to change a parameter */

class CambiaParametro implements ActionListener{
  int indiceParametro;
  int nuovoValore;
  int [] vecchioVettore;
  public CambiaParametro (int indPar, int val, int [] oldVett){
    indiceParametro=indPar;
    nuovoValore=val;
    vecchioVettore=oldVett;
  }
  public void actionPerformed (ActionEvent e){
    vecchioVettore[indiceParametro]=nuovoValore;
    try{
      ObjectOutputStream out=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("param.pos")));
      out.writeObject(vecchioVettore);
      out.close();
      }catch(Exception excp){System.out.println("ERROR updating file 'param.pos'");}
  }
}




/* ------------------------------------------------------------------------------------------------- */

/* Listener used to change the theorem prover SeqS */

class CambiaTheoremProver implements ActionListener{
  int nuovoValore;
  int [] vecchioVettore;
  JLabel immagine;
  public CambiaTheoremProver (int val, int [] oldVett, JLabel immagine){
    nuovoValore=val;
    vecchioVettore=oldVett;
    this.immagine=immagine;
  }
  public void actionPerformed (ActionEvent e){
    vecchioVettore[2]=nuovoValore;
    try{
      ObjectOutputStream out=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("param.pos")));
      out.writeObject(vecchioVettore);
      out.close();
      }catch(Exception excp){System.out.println("ERROR updating file 'param.pos'");}
     switch(nuovoValore){
       case 0 : {immagine.setIcon(new ImageIcon("seqCK.jpg")); break;}
       case 1 : {immagine.setIcon(new ImageIcon("seqID.jpg")); break;}
       case 2 : {immagine.setIcon(new ImageIcon("seqMP.jpg")); break;}
       case 3 : {immagine.setIcon(new ImageIcon("seqIDMP.jpg")); break;}
     }
     immagine.repaint();
  }
}




/* ------------------------------------------------------------------------------------------------- */

/* CondLean' s control (main) window */

class Controller extends JFrame {
  public Controller (){
    super("CondLean: a theorem prover for conditional logics");
     JLabel risultato=new JLabel();
     JPanel pannelloBottoneAlbero=new JPanel(); 
     JPanel pannelloStatistiche=new JPanel();
     JPanel pannelloFileLatex=new JPanel();

     Container cp=getContentPane();
     cp.setLayout(new BorderLayout());

     /* Recovery of old settings */
     int vett []=null;
     try{
       ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("param.pos")));
       vett=(int [])in.readObject();
      in.close();
     }catch(Exception excp){System.out.println("ERROR reading file 'param.pos'");}
     String nomeFileImm=null;
     if (vett[2]==0) nomeFileImm=new String("seqCK.jpg");
     else if (vett[2]==1) nomeFileImm=new String("seqID.jpg");
     else if (vett[2]==2) nomeFileImm=new String("seqMP.jpg");
     else nomeFileImm=new String("seqIDMP.jpg");
     JPanel immagine=new JPanel();
     JLabel imm=new JLabel(new ImageIcon(nomeFileImm));
     immagine.add(imm);
     cp.add(immagine,BorderLayout.WEST);

     setJMenuBar(new BarraMenu(imm));

     /* Once cannot resize the main window */
     setResizable(false);


     JPanel finestra=new JPanel();
     cp.add(finestra,BorderLayout.EAST);
     finestra.setLayout(new GridLayout(4,1));
     
     
     JPanel operativo=new JPanel();
     finestra.add(operativo);
     GridBagLayout gridbag = new GridBagLayout();
     GridBagConstraints c = new GridBagConstraints();
     operativo.setLayout(gridbag);         
     c.fill = GridBagConstraints.BOTH;
     c.weightx = 1.0;   
     JButton bott;  
     for (int i=0;i<10;i++){
        bott=new JButton();
        bott.setBorderPainted(false);
       attacca(bott,operativo,gridbag,c);
     }
     c.gridwidth = GridBagConstraints.REMAINDER; 
     bott=new JButton();
     bott.setBorderPainted(false);
     attacca(bott,operativo,gridbag,c);
     c.gridwidth=GridBagConstraints.REMAINDER;
     JLabel infoInput=new JLabel("<html><body><font color=blue><B>Insert a sequent:</B><I> (ex: [x,a], [x,a=>b]</font><font color=black> |- </font><font color=blue>[x,a and b])</I></font></body></html>");
     attacca(infoInput,operativo,gridbag,c);
     
     /* The following code creates the window's graphic components */
     JButton prova=new JButton(new ImageIcon("prova.jpg"));
     JTextField antecedente=new JTextField(16);
     antecedente.setFont(new Font("serif",Font.ITALIC,16));
     antecedente.setForeground(Color.blue);
     JTextField conseguente=new JTextField(16);
     conseguente.setFont(new Font("serif",Font.ITALIC,16));
     conseguente.setForeground(Color.blue);
     prova.setToolTipText("Click here to reset the theorem prover and start another proof");
     prova.setCursor(new Cursor(12));
     prova.addActionListener(new Pulisci (antecedente,conseguente,risultato,
       pannelloBottoneAlbero,pannelloStatistiche,pannelloFileLatex));
     c.gridwidth=5;
     attacca(antecedente,operativo,gridbag,c);
     c.gridwidth=1;
     attacca(prova,operativo,gridbag,c);
     c.gridwidth=GridBagConstraints.REMAINDER;
     attacca(conseguente,operativo,gridbag,c);

     JButton dimostra=new JButton(new ImageIcon("dimostra.jpg"));
     dimostra.setToolTipText("Click here to find a derivation");
     dimostra.setCursor(new Cursor(12));
     dimostra.addActionListener(new PrologListener(antecedente,conseguente,
       risultato,pannelloBottoneAlbero,pannelloStatistiche,pannelloFileLatex));
     JPanel pandim=new JPanel();
     JButton sequenteIntero=new JButton(new ImageIcon("lente.jpg"));
     sequenteIntero.setToolTipText("Click here to see the whole sequent");
     sequenteIntero.setCursor(new Cursor(12));
     sequenteIntero.addActionListener(new MostraSequenteIntero(antecedente,conseguente));
     pandim.add(sequenteIntero);
     pandim.add(dimostra);
     finestra.add(pandim);
     JPanel panris=new JPanel();
     panris.add(risultato);
     finestra.add(panris);

     JPanel opzioni=new JPanel();
     finestra.add(opzioni);
     gridbag = new GridBagLayout();
     c = new GridBagConstraints();
     opzioni.setLayout(gridbag);         
     c.fill = GridBagConstraints.BOTH;
     c.weightx = 1.0;   
     for (int i=0;i<10;i++){
        bott=new JButton();
        bott.setBorderPainted(false);
        attacca(bott,opzioni,gridbag,c);
     }

     c.gridwidth = GridBagConstraints.REMAINDER; 
     bott=new JButton();
     bott.setBorderPainted(false);
     attacca(bott,opzioni,gridbag,c);
     c.gridwidth=1;
     attacca(new JLabel(),opzioni,gridbag,c);
     c.gridwidth=3;
     attacca(pannelloBottoneAlbero,opzioni,gridbag,c);
     c.gridwidth=3;
     attacca(pannelloFileLatex,opzioni,gridbag,c);
     c.gridwidth=3;
     attacca(pannelloStatistiche,opzioni,gridbag,c);
     c.gridwidth=GridBagConstraints.REMAINDER; 
     attacca(new JLabel(),opzioni,gridbag,c);
 }

  private void attacca (JComponent who, JComponent comp, GridBagLayout gridbag, GridBagConstraints c){
     gridbag.setConstraints(who,c);
     comp.add(who);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This listener shows the inserted sequent in a special window */

class MostraSequenteIntero implements ActionListener{
  JTextField antecedente, conseguente;
  public MostraSequenteIntero (JTextField ant, JTextField cons){
    antecedente=ant;
    conseguente=cons;
  }
  public void actionPerformed (ActionEvent e){
    JFrame finestra=new JFrame("Sequent inserted:");
    Container cp=finestra.getContentPane();
    cp.setLayout(new BorderLayout());
    JPanel centro=new JPanel();
    JScrollPane scr=new JScrollPane(centro);
    scr.setPreferredSize(new Dimension(350,60));
    cp.add(scr,BorderLayout.CENTER);
    centro.add(new JLabel(new ImageIcon("lente.jpg")));
    centro.add(new JLabel(antecedente.getText()));
    centro.add(new JLabel(new ImageIcon("prova.jpg")));
    centro.add(new JLabel(conseguente.getText()));
    finestra.pack();
    finestra.setVisible(true);
  }
}




/* ------------------------------------------------------------------------------------------------- */

/* General purpose class: for example, it is used for translating a string representing a
   proof tree in the equivalent Tree object */

class OggettiUtili{
  public Tree costruisciAlberoJava (SICStus sp, String temp, String antecPrem, String consegPrem){
      String regola=new String(), 
             sequente=new String(),
             antecFormPrinc=new String(),
             consegFormPrinc=new String(),
             antecProxPremSx=new String(),
             consegProxPremSx=new String(),
             antecProxPremDx=new String(),
             consegProxPremDx=new String(),
             alberoSinistro=new String(), 
             alberoDestro=new String(),
             antecedente=new String(),
             conseguente=new String();


      if (temp.compareTo("null")==0) return null;
      else
      {
      HashMap altraMappa=new HashMap();
      try{
      Query q1=sp.openPrologQuery("regola("+temp+",Rule).",altraMappa);
      if(q1.nextSolution()){
        regola=altraMappa.toString();
         regola=regola.substring(6,regola.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("sequente("+temp+",Sequente).",altraMappa);
      while(q1.nextSolution()){  
        String par=altraMappa.toString();
        sequente=sequente+par.substring(10,par.length()-1)+" ,";
      }
      sequente=sequente.substring(0,sequente.length()-2);
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("antecedenteFormulaPrincipale("+temp+",Antec).",altraMappa);
      if(q1.nextSolution()){
        antecFormPrinc=altraMappa.toString();
        antecFormPrinc=antecFormPrinc.substring(7,antecFormPrinc.length()-1);
        int k=0;
        while((k<antecFormPrinc.length())&&(antecFormPrinc.charAt(k)!=','))
          k++;
        k=k+3;
       if (k+4<antecFormPrinc.length())
         if ((antecFormPrinc.charAt(k)=='f')&&
              (antecFormPrinc.charAt(k+1)=='a')&&
              (antecFormPrinc.charAt(k+2)=='l')&&
              (antecFormPrinc.charAt(k+3)=='s')&&
              (antecFormPrinc.charAt(k+4)=='e'))
            antecFormPrinc=new String(".("+antecFormPrinc+",[])");
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("conseguenteFormulaPrincipale("+temp+",Conseg).",altraMappa);
      if(q1.nextSolution()){
        consegFormPrinc=altraMappa.toString();
        consegFormPrinc=consegFormPrinc.substring(8,consegFormPrinc.length()-1);
        int k=0;
        while((k<consegFormPrinc.length())&&(consegFormPrinc.charAt(k)!=','))
          k++;
        k=k+3;
        if (k+3<consegFormPrinc.length())
          if ((consegFormPrinc.charAt(k)=='t')&&
              (consegFormPrinc.charAt(k+1)=='r')&&
              (consegFormPrinc.charAt(k+2)=='u')&&
              (consegFormPrinc.charAt(k+3)=='e'))
            consegFormPrinc=new String(".("+consegFormPrinc+",[])");
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("antecedentePremessaSinistra("+temp+",AntPremSx).",altraMappa);
      if(q1.nextSolution()){
      antecProxPremSx=altraMappa.toString();
      antecProxPremSx=antecProxPremSx.substring(11,antecProxPremSx.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("conseguentePremessaSinistra("+temp+",ConPremSx).",altraMappa);
      if(q1.nextSolution()){
        consegProxPremSx=altraMappa.toString();
        consegProxPremSx=consegProxPremSx.substring(11,consegProxPremSx.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("antecedentePremessaDestra("+temp+",AntPremDx).",altraMappa);
      if(q1.nextSolution()){
        antecProxPremDx=altraMappa.toString();
        antecProxPremDx=antecProxPremDx.substring(11,antecProxPremDx.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("conseguentePremessaDestra("+temp+",ConPremDx).",altraMappa);
      if(q1.nextSolution()){
        consegProxPremDx=altraMappa.toString();
        consegProxPremDx=consegProxPremDx.substring(11,consegProxPremDx.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("alberoSinistro("+temp+",Sinistro).",altraMappa);
      if(q1.nextSolution()){
        alberoSinistro=altraMappa.toString();
         alberoSinistro=alberoSinistro.substring(10,alberoSinistro.length()-1);
      }
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("alberoDestro("+temp+",Destro).",altraMappa);
      if(q1.nextSolution()){
        alberoDestro=altraMappa.toString();
         alberoDestro=alberoDestro.substring(8,alberoDestro.length()-1);
      }
      q1.close();

      /* SICStus Prolog is used to extract some informations about the proof tree */
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("append("+antecPrem+","+antecFormPrinc+",Ris).",altraMappa);
      if (q1.nextSolution())
        antecedente=altraMappa.toString().substring(5,altraMappa.toString().length()-1);
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("remove_duplicates("+antecedente+",Ris).",altraMappa);
      if (q1.nextSolution())
        antecedente=altraMappa.toString().substring(5,altraMappa.toString().length()-1);
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("append("+consegPrem+","+consegFormPrinc+",Ris).",altraMappa);
      if (q1.nextSolution())
        conseguente=altraMappa.toString().substring(5,altraMappa.toString().length()-1);
      q1.close();
      altraMappa=new HashMap();
      q1=sp.openPrologQuery("remove_duplicates("+conseguente+",Ris).",altraMappa);
      if (q1.nextSolution())
        conseguente=altraMappa.toString().substring(5,altraMappa.toString().length()-1);
      q1.close();

      }catch (Exception e) { System.out.println("ERROR connecting to SICStus Prolog"+e.getMessage()); }

      antecedente=raffinamento(rendiPresentabile(antecedente));
      conseguente=raffinamento(rendiPresentabile(conseguente));
      sequente=raffinamento(rendiPresentabile(sequente));

      return new Tree(sequente,regola,antecedente,conseguente,
        costruisciAlberoJava(sp,alberoSinistro,antecProxPremSx,consegProxPremSx),
         costruisciAlberoJava(sp,alberoDestro,antecProxPremDx,consegProxPremDx));
      }
  }
  private String rendiPresentabile (String sequente){
    /* This method converts a sequent from
          .(Testa,Coda)
       to
           Testa,Coda
     */
     /* - the sequent is [] */
     if (sequente.charAt(0)=='[')
       return new String("");
     else
     {
     String ris=new String();
     /* Extracting list's queue */
        ris=sequente.substring(2,sequente.length()-1);
        int cont=0,i=0;
        String testa=new String();
        String corpo=new String();
        char c;
        do{
          c=ris.charAt(i);
          testa=testa+c;
          if (c=='(')
            cont++;
          else if (c==')')
            cont--;
          i++;
        }while((cont>0)||(c!=','));
        testa=testa.substring(0,testa.length()-1);
        corpo=ris.substring(i,ris.length());
      /* The following code convert the list's head into an user-friendly representation */
        /* Case 1 : head is *, used for |- */
        if (testa.charAt(0)=='*')
          ris=new String("|-");
        /* Case 2: head is the empty list [] */
       else if (testa.charAt(0)=='[')
          ris=new String("");
        /* Case 3: head is a labelled formula, atomic or complex */
       else if (contaElementi(testa)==2){
          ris=new String();
          String formula=new String();
          /* Finding the label */
          int j=2;
          do{
            ris=ris+testa.charAt(j);
             j++;
          }while(testa.charAt(j)!='.');
          ris=ris.substring(0,ris.length()-1);
          ris=ris+":";
          /* Finding the conditional formula */
          j=j+2;
          do{
            formula=formula+testa.charAt(j);
             j++;
          }while(testa.charAt(j)!='[');
          formula=formula.substring(0,formula.length()-1);
          formula=decodifica(formula);
          ris=ris+formula;
        }
        else{
          /* Case 4:  head is a transition formula */
          ris=new String();
          String formula=new String();
          if (testa.charAt(2)=='.')
            return new String();
          /* Finding the first label */
          int j=2;
          do{
            ris=ris+testa.charAt(j);
             j++;
          }while(testa.charAt(j)!='.');
          ris=ris.substring(0,ris.length()-1);
          ris="<font color=blue>"+ris+"{";
          /* Finding the formula */
          j=j+2;
          do{
            formula=formula+testa.charAt(j);
             j++;
          }while(testa.charAt(j)!='.');
          formula=formula.substring(0,formula.length()-1);
          formula=decodifica(formula);
          ris=ris+formula+"}";
          /* Finding the second label */
          j=j+2;
          do{
            ris=ris+testa.charAt(j);
             j++;
          }while(testa.charAt(j)!='[');
          ris=ris.substring(0,ris.length()-1)+"</font>";
        }
    /* The following code is the recurive call to this method on list's queue */
     corpo=rendiPresentabile(corpo);
     if (corpo.length()>0){
       if (ris.compareTo("|-")!=0)
          ris=ris+",";
     }
     ris=ris+corpo;
     return ris;
    }
  }
  private String decodifica(String formula){
    /* Converts a formula into an user-friendly representation:
           a                             converted in a 
             ->(a,b)                       converted in (a)->(b)
             and(neg(b),or(c,d))               converted in (~(b))&((c)or(d))
     */
     boolean atomo=true;
     for (int i=0;(i<formula.length())&&(atomo);i++)
       if ((formula.charAt(i)=='(')||(formula.charAt(i)==')'))
         atomo=false;
     if (atomo){
       /* Literal (atomic formula) */
        if (formula.compareTo("true")==0)
          formula=new String("T");
        else if (formula.compareTo("false")==0)
          formula=new String("F");
        return formula;
     }
     else{
       /* Formula could be:
                 neg(ARG)
                     or
                OP(ARG1,ARG2)
            where OP= and | -> | => | or 
        */
        if (formula.charAt(0)=='n'){
          /* neg(ARG) */
          String resto=decodifica(formula.substring(4,formula.length()-1));
          if (resto.length()>1)
            return new String("~("+resto+")");
          else return new String("~ "+resto);
        }
      else{ 
          /* OP(ARG1,ARG2) */
          int ind=0;
          while(formula.charAt(ind)!='(')
            ind++;
          ind++;
          String arg1=new String();
          String arg2=new String();
          int parentesi=0;
          char c;
          do{
            c=formula.charAt(ind);
            arg1=arg1+c;
             ind++;
             if (c=='(')
               parentesi++;
             else if (c==')')
               parentesi--;
          }while((c!=',')||(parentesi>0));
          arg1=arg1.substring(0,arg1.length()-1);
          arg2=formula.substring(ind,formula.length()-1);
          arg1=decodifica(arg1);
          arg2=decodifica(arg2);
          if (formula.charAt(0)=='a'){
            if (arg1.length()>1)
               if (arg2.length()>1)
                  return new String("("+arg1+")&("+arg2+")");
                else return new String("("+arg1+")& "+arg2);
             else if (arg2.length()>1)
               return new String(arg1+" &("+arg2+")");
                else return new String(arg1+" & "+arg2);
          }
          else
          if (formula.charAt(0)=='o'){
            if (arg1.length()>1)
               if (arg2.length()>1)
                  return new String("("+arg1+")v("+arg2+")");
                else return new String("("+arg1+")v "+arg2);
             else if (arg2.length()>1)
               return new String(arg1+" v("+arg2+")");
                else return new String(arg1+" v "+arg2);
          }
          else
          if (formula.charAt(0)=='-'){
            if (arg1.length()>1)
               if (arg2.length()>1)
                  return new String("("+arg1+")->("+arg2+")");
                else return new String("("+arg1+")-> "+arg2);
             else if (arg2.length()>1)
               return new String(arg1+" ->("+arg2+")");
                else return new String(arg1+" -> "+arg2);
          }
          else
          if (formula.charAt(0)=='='){
            if (arg1.length()>1)
               if (arg2.length()>1)
                  return new String("("+arg1+")=>("+arg2+")");
                else return new String("("+arg1+")=> "+arg2);
             else if (arg2.length()>1)
               return new String(arg1+" =>("+arg2+")");
                else return new String(arg1+" => "+arg2);
          }
          else return null;
        }
     }
  }

  private int contaElementi(String lista){
    /* Returns the length of the argument list */
     int cont=0;
     for (int i=0;i<lista.length();i++)
       if(lista.charAt(i)=='.') cont++;
     return cont;
  }
  private String raffinamento(String sequente){
    String ris=new String();
     int i=0;
     while(i<sequente.length()){
       if((sequente.charAt(i)=='|')&&(i>0)){
          ris=ris.substring(0,ris.length()-1)+" |- ";
          i=i+2;
      }
       else{
         ris=ris+sequente.charAt(i);
          i++;
       }
     }
     return ris;
  }

  /* Remove html tags from the string */
  public String eliminaTagHtml (String seq){
    boolean found;
     int index=0;
     String other;
     int from=0;
     other=new String("<font color=blue>");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+seq.substring(index+other.length());
        from=index;
     }  
     }while(found);
     other=new String("</font>");
     from=0;
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+seq.substring(index+other.length());
        from=index;
     }  
     }while(found);
     return seq;
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This listener lets users to ask the theorem prover to find a derivation for a sequent; public method
   actionPerformed interacts with SICStus Prolog impleemntation of SeqS using package se.sics.jasper's classes; 
   these implementations consist of files with 'sav' extension */

class PrologListener implements ActionListener{
  JTextField antecedente, conseguente;
  JLabel risultato;
  JPanel panBottoneAlbero, panStatistiche, panFileLatex;
  /* The following object is used to interact with the SICStus Prolog kernel */
  SICStus sp;

  public PrologListener (JTextField antec, JTextField conseg, JLabel ris, 
      JPanel whereBottone, JPanel whereStatistiche, JPanel whereFileLatex){
    antecedente=antec;
    conseguente=conseg;
    risultato=ris;
    panBottoneAlbero=whereBottone;
    panStatistiche=whereStatistiche;
    panFileLatex=whereFileLatex;
    sp=null;
  }
  public void actionPerformed(ActionEvent e){
     Query q;
     HashMap mappa=new HashMap();
     /* The following statement builds the goal to query to the theorem prover */
     String goal=new String("proof(["+antecedente.getText()+"],["+conseguente.getText()+"],ProofTree,"+
       "LunghSeq,GradoSeq,NumEtichette,Altezza,NumNodi,NumCondR,NumCondL,NumEq,NumContr).");
     int vett []=null;
     try{
       ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("param.pos")));
       vett=(int [])in.readObject();
       in.close();
     }catch(Exception excp){System.out.println("ERROR reading file 'param.pos'");}
     try{
       if (sp==null){
         /* Istantiating a SICStus object */
         sp=new SICStus();
        }
        /* Parameter 1 and 2 detrmine the theorem prover to use (SeqS and version) */
        if (vett[2]==0)
          if (vett[1]==0)
            /* For example, when parameter 1 is 0 and parameter 2 is 0, SeqCK - constant labels version is selected */
            sp.restore("ckcostanti.sav");
          else if (vett[1]==1)
            sp.restore("ckfree.sav");
          else sp.restore("ckeuristica.sav");
        else if (vett[2]==1)
          if (vett[1]==0)
            sp.restore("ckidcostanti.sav");
          else if (vett[1]==1)
            sp.restore("ckidfree.sav");
          else sp.restore("ckideuristica.sav");
        else if (vett[2]==2)
          if (vett[1]==0)
            sp.restore("ckmpcostanti.sav");
          else if (vett[1]==1)
            sp.restore("ckmpfree.sav");
          else sp.restore("ckmpeuristica.sav");
        else 
          if (vett[1]==0)
            sp.restore("ckmpidcostanti.sav");
          else if (vett[1]==1)
            sp.restore("ckmpidfree.sav");
          else sp.restore("ckmpideuristica.sav");

        q=sp.openPrologQuery(goal,mappa);
        if(q.nextSolution()){
          risultato.setIcon(new ImageIcon("dimostrabile.jpg"));
          /* The following statements extract the proof tree computed by the theorem prover */
          String mapString=new String(mappa.toString());
          String temp=new String();
          int index=mapString.indexOf(", NumContr");         
          temp=mapString.substring(11,index);

          /* Extracting statistics of the proof */
          index=index+2;
          Integer vettoreStatistiche [];
          vettoreStatistiche=new Integer [9];
          String numero;
          for (int j=0;j<9;j++){
            while(mapString.charAt(index)!='=') index++;
            numero=new String();
             index++;
            while((mapString.charAt(index)!=',')&&(mapString.charAt(index)!='}')){
              numero=numero+mapString.charAt(index);
               index++;
            }
             vettoreStatistiche[j]=new Integer(numero);
            index=index+2;
          }



          /* If the sequent is valid, three buttons are painted on the control (main) window */
          
          JButton bottoneAlbero=new JButton(new ImageIcon("albero.jpg"));
          bottoneAlbero.setCursor(new Cursor(12));
          bottoneAlbero.setToolTipText("Click here to view the proof tree");
          int seqIndici [];
          seqIndici=new int [10];
          bottoneAlbero.addActionListener(new ListenerAlberoDiProva(sp,temp,"Proof tree",seqIndici,0));
          panBottoneAlbero.add(bottoneAlbero);

          JButton bottoneStatistiche=new JButton(new ImageIcon("statistiche.jpg"));
          bottoneStatistiche.addActionListener(new ListenerStatistiche(vettoreStatistiche));
          bottoneStatistiche.setCursor(new Cursor(12));
          bottoneStatistiche.setToolTipText("Click here to view some statistics of the proof");
          panStatistiche.add(bottoneStatistiche);

          JButton bottoneFileLatex=new JButton(new ImageIcon("latex.jpg"));
          bottoneFileLatex.setCursor(new Cursor(12));
          bottoneFileLatex.setToolTipText("Click here to build a latex file containing the proof tree");
          bottoneFileLatex.addActionListener(new OutputInLatex(sp,temp));
          panFileLatex.add(bottoneFileLatex);
        }
        else  risultato.setIcon(new ImageIcon("nondimostrabile.jpg"));
        q.close();
     }
     catch(Exception excpt)
     { 
       System.out.println("ERROR connecting to SICStus Prolog"+excpt.getMessage());
       System.exit(0);
     }
  }

}




/* ------------------------------------------------------------------------------------------------- */

/* This class resets the application after a proof search */

class Pulisci implements ActionListener {
  JTextField antecedente, conseguente;
  JLabel risultato;
  JPanel pannello1, pannello2, pannello3;
  public Pulisci (JTextField antec, JTextField conseg, JLabel ris,
      JPanel pan1, JPanel pan2, JPanel pan3){
    antecedente=antec;
     conseguente=conseg;
     risultato=ris;
     pannello1=pan1;
     pannello2=pan2;
     pannello3=pan3;
  }
  public void actionPerformed (ActionEvent e){
    antecedente.setText("");
     conseguente.setText("");
     risultato.setIcon(new ImageIcon(""));
     pannello1.removeAll();
     pannello2.removeAll();
     pannello3.removeAll();
     pannello1.repaint();
     pannello2.repaint();
     pannello3.repaint();
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This listener is used to view some statistics of the proof */

class ListenerStatistiche implements ActionListener{
  Integer vett [];
  /* Vector with statistics:
     vett[0]: numbero of contractions
     vett[1]: number of (=>R)
     vett[2]: number of (=>L)
     vett[3]: labels used
     vett[4]: proof tree nodes
     vett[5]: proof tree heigth
     vett[6]: sequent degree
     vett[7]: sequent length
     vett[8]: number of (EQ)
  */
  public ListenerStatistiche(Integer vettoreStatistiche []){
    vett=vettoreStatistiche;
  }
  public void actionPerformed(ActionEvent e){
    JFrame f=new JFrame("Statistics");

     JTextField statistiche=new JTextField();
     statistiche.setFont(new Font("serif",Font.PLAIN,14));
     statistiche.setForeground(Color.black);
     statistiche.setBackground(Color.lightGray);
     statistiche.setText("Sequent length: "+vett[7].toString()+
       "\nSequent degree: "+vett[6].toString()+
        "\nProof tree nodes: "+vett[4].toString()+
        "\nProof tree heigth: "+vett[5].toString()+
        "\nLabels used: "+vett[3].toString()+
        "\nApplications of (ContrL): "+vett[0].toString()+
        "\nApplications of (EQ): "+vett[8].toString()+
        "\nApplications of (CondR): "+vett[1].toString()+
        "\nApplications of (CondL): "+vett[2].toString()+"\n");

     f.getContentPane().add(statistiche);
     f.pack();
     f.setVisible(true);
     f.setSize(300,320);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This listener creates a latex file containing the proof tree; compiling file 'alberoDiProvan.tex'
   with a Latex compiler, you will have a pdf or dvi or ps file, showing the proof tree 
   
  NOTE: to create the pdf (or ps or dvi) file, you need file Paul Taylor's 'prooftree.tex' in
  the output directory */

class OutputInLatex implements ActionListener {
  private String alberoComeStringa;
  private static int outputProdotti=0;
  private String [] vettoreSottoprove;
  private int index;
  private SICStus sp;

  public OutputInLatex (SICStus sp, String alberoComeStringa){
     this.alberoComeStringa=alberoComeStringa;
     this.sp=sp;
     index=0;
     vettoreSottoprove=new String [1000];
  }

  private String estraiConclusione (String t){
    if (t.length()==0) return new String("");
     else {
       String s=new String("\\[");
       if (t.regionMatches(0,s,0,s.length())){
          s=new String("\\justifies");
          int i=3;
          while (!t.regionMatches(i,s,0,s.length())){
            i++;
          }
          i=i+11;
          String returnValue=new String();
          do{
            returnValue=returnValue+t.charAt(i);
             i++;
          }while((t.charAt(i)!='\\')||(t.charAt(i+1)!='u'));
          return returnValue;
        }
        else return t;
     }
  }

  private String convertiAlbero (Tree t){
    return convertiAlbero(t, 180);
  }

  private String convertiAlbero (Tree t, int taglio){
    if (t==null)
       return new String("");
     else{
    String s=new String(t.regola);
     if (s.compareTo("assioma")==0){
        String seqOk=convertiSequente(t.sequente);
       return seqOk;
     }
     else {
       String returnValue=new String("\\[\n");
        String rule=argJustifies(t.regola);
        String seqOk=convertiSequente(t.sequente);
       if (t.rightProof==null)
          returnValue=returnValue+convertiAlbero(t.leftProof, taglio)+"\n\\justifies "+seqOk+"\n\\using "+rule+"\n\\]";
        else{
          String left=convertiAlbero(t.leftProof, taglio/2);
          String right=convertiAlbero(t.rightProof, taglio/2);
          String seqLeft=estraiConclusione(left);
          String seqRight=estraiConclusione(right);
          if(seqLeft.length()+seqRight.length()>taglio){
            /* We introduce a sub-proof tree */
                returnValue=returnValue+"\\pi_{"+Integer.toString(index+1)+"} ";
                 for (int j=0;j<10;j++)
                   returnValue=returnValue+" \\quad ";
                 returnValue=returnValue+"\\pi_{"+Integer.toString(index+2)+"}\n\\justifies "+seqOk+"\n\\using "+rule+"\n\\]"; 
                 /* The following statements append the sub-proof trees to the output file */
                 int richiamoUno=index, richiamoDue=index+1;
                      index=index+2;
                 vettoreSottoprove[richiamoUno]=convertiAlbero(t.leftProof);
                 vettoreSottoprove[richiamoDue]=convertiAlbero(t.rightProof);
            }
          else 
            returnValue=returnValue+left+" \\quad \\quad "+right+"\n\\justifies "+seqOk+"\n\\using "+rule+"\n\\]";
          }
        return returnValue;
       }
     }
  }

  
  private String convertiTransizioni (String seq){
     /* This method converts a transition formula */
     int from=0;
     if (seq.length()==0) return new String("");
     else{
     boolean found=false;
     String seqPrimaSost=new String(seq);
    for (int i=0;(i<seq.length()-2)&&(!found);i++){
       if (seq.charAt(i)=='{'){
          found=true;
          int fromSin;
          String effe=new String("{");
          int j=i+1;
          while(seq.charAt(j)!='}'){
            effe=effe+seq.charAt(j);
            j++;
          }
          effe=effe+"}";
          i--;
          String ics=new String("");
          while ((i>=0)&&(seq.charAt(i)!=',')&&(seq.charAt(i)!='-')){
            ics=seq.charAt(i)+ics;
             i--;
          }  
        if (i>=0)
          fromSin=i+1;
        else fromSin=0;
          j++;
          String ipsilon=new String("");
          while((j<seq.length())&&(seq.charAt(j)!=',')&&(seq.charAt(j)!='|')){
            ipsilon=ipsilon+seq.charAt(j);
            j++;
          }
          if (j>=seq.length())
            from=seq.length();
          else from=fromSin+ics.length()+effe.length()+ipsilon.length();
          seq=seq.substring(0,fromSin)+ics+" \\trans"+effe+" "+ipsilon;
       }
     }
     if (from==0)
       return seq;
     else
       return seq+convertiTransizioni(seqPrimaSost.substring(from));
     }
  }

  /* This method converts a sequent in latex format */
  private String convertiSequente (String seq){
    seq=new OggettiUtili().eliminaTagHtml(seq);
    seq=convertiTransizioni(seq);
    boolean found=false;
     int index=0;
     String other;
     int from=0;
     other=new String("v");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\orr "+seq.substring(index+other.length());
        from=index+7;
     }  
     }while(found);
     other=new String("|-");
     found=false;
    for (int i=0;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\prova "+seq.substring(index+other.length());
     }  
     from=0;
     other=new String("&");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\andd "+seq.substring(index+other.length());
        from=index+8;
     }  
     }while(found);
     from=0;
     other=new String("=>");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\cond "+seq.substring(index+other.length());
        from=index+8;
     }  
     }while(found);
     from=0;
     other=new String("->");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\imp "+seq.substring(index+other.length());
        from=index+7;
     }  
     }while(found);
     from=0;
     other=new String("~");
     do{
     found=false;
    for (int i=from;(i<seq.length()-1)&&(!found);i++)
       if (found=seq.regionMatches(i,other,0,other.length()))
          index=i;
     if (found){
       seq=seq.substring(0,index)+" \\nott "+seq.substring(index+other.length());
        from=index+8;
     }  
     }while(found);
     return seq;
  }

  private String argJustifies (String regola){
     String s=new String(regola);
      if (s.compareTo("andL")==0) return new String("(\\andd L)");
      if (s.compareTo("andR")==0) return new String("(\\andd R)");
      if (s.compareTo("negL")==0) return new String("(\\nott L)");
      if (s.compareTo("negR")==0) return new String("(\\nott R)");
      if (s.compareTo("orL")==0) return new String("(\\orr L)");
      if (s.compareTo("orR")==0) return new String("(\\orr R)");
      if (s.compareTo("impL")==0) return new String("(\\imp L)");
      if (s.compareTo("impR")==0) return new String("(\\imp R)");
      if (s.compareTo("condL")==0) return new String("(\\cond L)");
      if (s.compareTo("condR")==0) return new String("(\\cond R)");
      if (s.compareTo("contrL")==0) return new String("(\\cond L_2)");
      if (s.compareTo("id")==0) return new String("(ID)");
      if (s.compareTo("mp")==0) return new String("(MP)");
      if (s.compareTo("eq")==0) return new String("(EQ)");
      return null;
  }

  private String verita (String codiceLatex){
    /* Converts T and F in commands true and false */  
    String nuovoCodice=new String("");
    for (int i=0;i<codiceLatex.length();i++)
      if (codiceLatex.charAt(i)=='T')
        nuovoCodice=nuovoCodice+"\\vero";
      else if (codiceLatex.charAt(i)=='F')
        nuovoCodice=nuovoCodice+"\\falso";
      else nuovoCodice=nuovoCodice+codiceLatex.charAt(i);
    return nuovoCodice;
  }


  public void actionPerformed (ActionEvent ev){
    /* Recovery of the output directory from file 'output_dest.pos' */
    String dirDest=new String("");
    try{
      ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("output_dest.pos")));
      dirDest=(String)in.readObject();
      in.close();
    }catch(Exception excp){System.out.println("ERROR reading file 'output_dest.pos'.");}
    try{
        System.out.println("");
        System.out.println("Building the latex file: please, wait a while...");
        int stima=(int)(alberoComeStringa.length()/400);
        System.out.println("Time to elapse: "+Integer.toString(stima)+" seconds");
        Tree t=new OggettiUtili().costruisciAlberoJava(sp,alberoComeStringa,"[]","[]");
        System.out.println("Operation completed");
        outputProdotti++;
        FileOutputStream out=new FileOutputStream(dirDest+"/alberoDiProva"+outputProdotti+".tex");
        BufferedOutputStream bufOut=new BufferedOutputStream(out);
        DataOutputStream p=new DataOutputStream(bufOut);
        String codiceLatex=new String("\\newcommand {\\imp} {\\rightarrow}\n\\newcommand {\\cond} {\\Rightarrow}\n\\newcommand {\\orr} {\\vee}\n\\newcommand {\\andd} {\\land}\n\\newcommand {\\prova} {\\vdash}\n\\newcommand {\\nott} {\\lnot}\n\\newcommand {\\trans}[1]{\\stackrel{#1}{\\longrightarrow}}\n\\newcommand {\\spazio} {\\vspace {2cm}}\n\\newcommand {\\falso} {\\bot}\n\\newcommand {\\vero} {\\top}\n\\documentstyle{report}\n\\input{prooftree}\n\\begin{document}\n\\begin{");
        /* Recovery of the font size selected by the user */
        String size=new Informazioni().getCurrentSize();
        codiceLatex=codiceLatex+size;
        codiceLatex=codiceLatex+"}\nProof tree:\n\\[\n";
        String albero=convertiAlbero(t);
        if (t.leftProof!=null){
          codiceLatex=codiceLatex+"\\begin{prooftree}\n";
          albero=albero.substring(3,albero.length()-2)+"\\end{prooftree}\\\\\\\\\\\\\\\\\\]";
        }
        else 
          albero=albero+"\\]";
        codiceLatex=codiceLatex+recuperoSottoprove(albero);
        codiceLatex=codiceLatex+"\\end{"+size+"}\n\\end{document}\n";
        codiceLatex=verita(codiceLatex);
        p.writeBytes(codiceLatex);
        p.close();
        /* Creates a graphical window showing a feddback message */
        ComunicazioneScritturaFile mess=new ComunicazioneScritturaFile("alberoDiProva"+outputProdotti+".tex");
        mess.pack();
        mess.setVisible(true);
     }catch(Exception e){System.out.println("ERROR creating latex file");}
  }

  /* This function returns the string for the sub-proof trees */
      private String recuperoSottoprove(String albero){
          String returnValue=new String();
          int ultimoRichiamo=0;
          int daAnalizzare [];
          daAnalizzare=new int [150];
          int ancoraDaAnalizzare=0;
          int i=0;
          String other=new String("\\pi_{");
          while(i<albero.length()){
            if (albero.regionMatches(i,other,0,other.length())){
                i=i+5;
                int da=i;
                String indice=new String("");
                while(albero.charAt(i)!='}'){
                  indice=indice+albero.charAt(i);
                  i++;
                }
                /* Sub-proof trees indexes ore ordered */
                ultimoRichiamo++;
                String nuovoIndice=Integer.toString(ultimoRichiamo);
                albero=albero.substring(0,da)+nuovoIndice+albero.substring(i);
                i=da+nuovoIndice.length();
                int indiceNumerico=new Integer(indice).intValue()-1;
                daAnalizzare[ancoraDaAnalizzare]=indiceNumerico;
                ancoraDaAnalizzare++;
             }
             i++;
          }
         /* Recovered string is inserted into return string */      
         returnValue=albero+"\n";


          int j=0;
          while(j<ancoraDaAnalizzare){
            i=0;
             String sottoprovaInAnalisi=vettoreSottoprove[daAnalizzare[j]];
            while(i<sottoprovaInAnalisi.length()){
              if (sottoprovaInAnalisi.regionMatches(i,other,0,other.length())){
                  i=i+5;
                  int da=i;
                  String indice=new String("");
                  while(sottoprovaInAnalisi.charAt(i)!='}'){
                    indice=indice+sottoprovaInAnalisi.charAt(i);
                    i++;
                  }
                  ultimoRichiamo++;
                  String nuovoIndice=Integer.toString(ultimoRichiamo);
                  sottoprovaInAnalisi=sottoprovaInAnalisi.substring(0,da)+nuovoIndice+sottoprovaInAnalisi.substring(i);
                  i=da+nuovoIndice.length();
                  int indiceNumerico=new Integer(indice).intValue()-1;
                  daAnalizzare[ancoraDaAnalizzare]=indiceNumerico;
                  ancoraDaAnalizzare++;
               }
               i++;
            }
            returnValue=returnValue+"\nProof tree $\\pi_{"+Integer.toString(j+1)+"}$ \\\\\n\\[\n";
            boolean isAxiom=true;
            String keyword=new String("justifies");
            i=0;
            int lungStr=sottoprovaInAnalisi.length();
            while((i<lungStr)&&(isAxiom)){
              if (sottoprovaInAnalisi.regionMatches(i,keyword,0,keyword.length()))
                isAxiom=false;
              i++;
            }  
            if(!isAxiom){
              returnValue=returnValue+"\\begin{prooftree}\n";
              sottoprovaInAnalisi=sottoprovaInAnalisi.substring(3,sottoprovaInAnalisi.length()-3);
            }
            returnValue=returnValue+sottoprovaInAnalisi;
            if(!isAxiom)
              returnValue=returnValue+"\n\\end{prooftree}\\\\\\\\\\\\"; 
            returnValue=returnValue+"\n\\]";
            j++;
          }
          return returnValue;
      }
} 




/* ------------------------------------------------------------------------------------------------- */

/* This window contains a feedback message about creating the latex file */

class ComunicazioneScritturaFile extends JFrame{
  public ComunicazioneScritturaFile (String nomeFile){
    super("Operation completed");
     Container cp=getContentPane();
     cp.setLayout(new BorderLayout());
     JPanel nord=new JPanel();
     nord.add(new JLabel("<html><body><font color=blue>Output in <I>FILE :"+nomeFile+"</I></font></body></html>"));
     cp.add(nord,BorderLayout.NORTH);
     JPanel centrale=new JPanel();
     centrale.add(new JLabel(new ImageIcon("istruzioni.jpg")));
     cp.add(centrale,BorderLayout.CENTER);
     JPanel sud=new JPanel();
     JButton chiudi=new JButton(new ImageIcon("chiudi.jpg"));
     chiudi.setCursor(new Cursor(12));
     chiudi.setToolTipText("Click here to close this window");
     sud.add(chiudi);
     chiudi.addActionListener(new Nascondi(this));
     cp.add(sud,BorderLayout.SOUTH);
     setResizable(false);
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This listener is linked to a button of a window; clicking that button you will close the window */

class Nascondi implements ActionListener{
  private JFrame finestraDaNascondere;
  public Nascondi (JFrame f){
    finestraDaNascondere=f;
  }
  public void actionPerformed(ActionEvent e){
    finestraDaNascondere.setVisible(false);
     finestraDaNascondere=null;
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* Listener for setting parameters */ 

class Informazioni{
  public String getCurrentSize (){
    try{
      ObjectInputStream in=new ObjectInputStream(new BufferedInputStream(new FileInputStream("param.pos")));
     int vett [];
     vett=(int [])in.readObject();
     in.close();
     switch(vett[0]){
        case 0 : {return new String("tiny");}
        case 1 : {return new String("scriptsize");}
        case 2 : {return new String("footnotesize");}
        case 3 : {return new String("small");}
        case 4 : {return new String("normalsize");}
      }
    }catch(Exception e){System.out.println("ERROR reading file 'param.pos'");}
    return null;
  }
}





/* ------------------------------------------------------------------------------------------------- */

/* This is the main class; you have to execute java Vai to execute CondLean */

class Vai {
  public static void main (String args []){
    Controller c=new Controller();
     c.pack();
     c.addWindowListener(new ClosingListener());
     c.setVisible(true);
  }
}


/* ------------------------------------------------------------------------------------------------- */


