/*

    Bist: a chemical drawing tool
    Copyright (C) 2008 Valerio Benfante

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <global.hpp>

#include <cstdio>


#include <cairo/cairo.h>
#include <cairo/cairo-ps.h>
#include <cairo/cairo-svg.h>
#include <pango/pangocairo.h>
#include <glib.h>
#include <cairo_t_singleton.hpp>


#include <FL/Fl_Pixmap.H>
#include <FL/fl_draw.H>
#include <FL/fl_ask.H>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Progress.H>
#include <FL/Fl_Scroll.H>

#include <interfacce.hpp>
#include <legame.hpp>
#include <etichetta.hpp>
#include <multiline_label.hpp>
#include <multifont_label.hpp>
#include <paragraph_text.hpp>
#include <atomo.hpp>

#include <procedura.hpp>
#include <gruppo.hpp>

#include <immagine.hpp>
#include <bist_plugin.hpp>
#include <mol_canvas.hpp>
#include <finestra_pr.hpp>

#include <atom_prop.hpp>
#include <bond_prop.hpp>
#include <arrow_prop.hpp>
#include <bezier_prop.hpp>
#include <arc_prop.hpp>
#include <box_prop.hpp>
#include <string_prop.hpp>
#include <multiline_label_prop.hpp>
#include <paragraph_text_prop.hpp>
#include <util.hpp>

#include <matr.hpp>
#include <2D_vector.hpp>
#include <prefs.hpp>

extern finestra_pr* MainWindow;

extern Preferences  __pref;



bool ordina_id_decr_elem_selected( pair < int, pair<int,int> >  uno ,
				   pair < int, pair<int,int> >  altro){

  int ui=(uno.second).second;
  int ai=(altro.second).second;
  return ui > ai;
}


/***********immagine***************/


immagine::immagine(bool preview)
  :_trovato_apice(false),
   _trovato_pedice(false),
   _has_error(false),
   _punt_mol(0),
   _filebist(""),
   _is_preview(preview)
{
  /*
  cout << "GRUPPI.SIZE() " << _gruppi.size() << endl;
  cout <<"costr: _legami_selected " << _legami_selected.size() << endl;
  cout << "GRPSZ: " << _gruppi.size() << endl;
  cout << "ETCHSZ " << _stringhe.size() << endl;
  */
  create_progressw();
}

immagine::~immagine(){

#ifdef DEBUG
  cout << "immagine distruttore "  <<   this << endl;
  cout <<"distr: _legami_selected " << _legami_selected.size() << " " << this << endl;
#endif
  for(unsigned int i=0; i<_legami_selected.size();i++){
    delete []  _legami_selected[i];
  }

  
  for(unsigned int i=0; i<_stringhe.size();i++){
    // std::cerr << "elimino stringa " << _stringhe[i] << std::cerr;
    delete _stringhe[i];

  }
  
  delete _export_progressw;
  //no need to free _export_progressw_bar, done from parent
  //delete _export_progressw_bar;

}


immagine::immagine(const immagine& altra)
  :_trovato_apice(altra._trovato_apice),
   _trovato_pedice(altra._trovato_pedice),
   _has_error(false),
   _punt_mol(0),
   _filebist(altra._filebist),
   _molecule(""), //sparagnamo memoria?
   _gruppi(altra._gruppi),
   _elem_selected(altra._elem_selected),
   _is_preview(altra._is_preview)
{
  create_progressw();

  for(unsigned int i=0;i<altra._legami_selected.size();i++){
    int* val=new int[3];
    for(int i2=0;i2<3;i2++){
      val[i2]=(altra._legami_selected[i])[i2];
    }
    _legami_selected.push_back(val);
  }


  
  for(unsigned int i=0;i < (altra._stringhe.size()) ;i++){
       
    if( typeid(*(altra._stringhe[i])) == typeid(multiline_label) ){
      multiline_label* mll=dynamic_cast<multiline_label*>(altra._stringhe[i]);
      multiline_label* tmp=new multiline_label(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if( typeid(*(altra._stringhe[i])) == typeid(paragraph_text) ){
      paragraph_text* mll=dynamic_cast<paragraph_text*>(altra._stringhe[i]);
      paragraph_text* tmp=new paragraph_text(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if(typeid(*(altra._stringhe[i]))==typeid(etichetta)){
      etichetta* tmp=new etichetta(altra._stringhe[i]);
      _stringhe.push_back(tmp);
    }

  }
}


immagine::immagine(const immagine* altra)
  :_trovato_apice(altra->_trovato_apice),
   _trovato_pedice(altra->_trovato_pedice),
   _has_error(false),
   _punt_mol(0),
   _filebist(altra->_filebist),
   _molecule(""),
   _gruppi(altra->_gruppi),
   _elem_selected(altra->_elem_selected),
   _is_preview(altra->_is_preview)
{
  create_progressw();

  for(unsigned int i=0;i<altra->_legami_selected.size();i++){
    int* val=new int[3];
    for(int i2=0;i2<3;i2++){
      val[i2]=(altra->_legami_selected[i])[i2];
    }
    _legami_selected.push_back(val);
  }


  
  for(unsigned int i=0;i < (altra->_stringhe.size()) ;i++){
       
    if( typeid(*(altra->_stringhe[i])) == typeid(multiline_label) ){
      multiline_label* mll=dynamic_cast<multiline_label*>(altra->_stringhe[i]);
      multiline_label* tmp=new multiline_label(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if( typeid(*(altra->_stringhe[i])) == typeid(paragraph_text) ){
      paragraph_text* mll=dynamic_cast<paragraph_text*>(altra->_stringhe[i]);
      paragraph_text* tmp=new paragraph_text(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if(typeid(*(altra->_stringhe[i]))==typeid(etichetta)){
      etichetta* tmp=new etichetta(altra->_stringhe[i]);
      _stringhe.push_back(tmp);
    }

  }
}



immagine& immagine::operator=(const immagine& altra){
  _trovato_apice=altra._trovato_apice;
  _trovato_pedice=altra._trovato_pedice;
  _has_error=false;
  _punt_mol=0;
  _filebist=altra._filebist;
  _molecule=""; //sparagnamo memoria?
  _gruppi=altra._gruppi;
  _elem_selected=altra._elem_selected;
  _is_preview=altra._is_preview;

  create_progressw();

  for(unsigned int i=0;i<altra._legami_selected.size();i++){
    int* val=new int[3];
    for(int i2=0;i2<3;i2++){
      val[i2]=(altra._legami_selected[i])[i2];
    }
    _legami_selected.push_back(val);
  }


  
  for(unsigned int i=0;i < (altra._stringhe.size()) ;i++){
       
    if( typeid(*(altra._stringhe[i])) == typeid(multiline_label) ){
      multiline_label* mll=dynamic_cast<multiline_label*>(altra._stringhe[i]);
      multiline_label* tmp=new multiline_label(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if( typeid(*(altra._stringhe[i])) == typeid(paragraph_text) ){
      paragraph_text* mll=dynamic_cast<paragraph_text*>(altra._stringhe[i]);
      paragraph_text* tmp=new paragraph_text(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if(typeid(*(altra._stringhe[i]))==typeid(etichetta)){
      etichetta* tmp=new etichetta(altra._stringhe[i]);
      _stringhe.push_back(tmp);
    }

  }
  return (*this);
}




immagine& immagine::operator=(const immagine* altra){
  _trovato_apice=altra->_trovato_apice;
  _trovato_pedice=altra->_trovato_pedice;
  _has_error=false;
  _punt_mol=0;
  _filebist=altra->_filebist;
  _molecule="";
  _gruppi=altra->_gruppi;
  _elem_selected=altra->_elem_selected;
  _is_preview=altra->_is_preview;

  create_progressw();

  for(unsigned int i=0;i<altra->_legami_selected.size();i++){
    int* val=new int[3];
    for(int i2=0;i2<3;i2++){
      val[i2]=(altra->_legami_selected[i])[i2];
    }
    _legami_selected.push_back(val);
  }


  
  for(unsigned int i=0;i < (altra->_stringhe.size()) ;i++){
       
    if( typeid(*(altra->_stringhe[i])) == typeid(multiline_label) ){
      multiline_label* mll=dynamic_cast<multiline_label*>(altra->_stringhe[i]);
      multiline_label* tmp=new multiline_label(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if( typeid(*(altra->_stringhe[i])) == typeid(paragraph_text) ){
      paragraph_text* mll=dynamic_cast<paragraph_text*>(altra->_stringhe[i]);
      paragraph_text* tmp=new paragraph_text(mll);
      if(mll){
        _stringhe.push_back(tmp);
      }
      
    }else if(typeid(*(altra->_stringhe[i]))==typeid(etichetta)){
      etichetta* tmp=new etichetta(altra->_stringhe[i]);
      _stringhe.push_back(tmp);
    }

  }
  return (*this);
}




void immagine::paste(int xt,int yt){

  /**
   *Contiene  coppie <tipo, < gruppo, id > > selezionati, se  si e'
   *selezionato una etichetta gruppo e' uguale a NO_VALID_GROUP
   *vector< pair < int, pair<int,int> > > _elem_selected;
   */


  vector<gruppo> nuovi_gruppi;
  vector<int>    id_gruppi_trovati;

  //troviamo i gruppi diversi
  for(unsigned int i=0;i<_elem_selected.size();i++){
    int id_gr_att=(_elem_selected[i].second).first;
    if(id_gr_att!=NO_VALID_GROUP){
      if(find(id_gruppi_trovati.begin(),id_gruppi_trovati.end(),id_gr_att)==
	 id_gruppi_trovati.end() || id_gruppi_trovati.size()<=0){
	gruppo tmp;
	nuovi_gruppi.push_back(tmp);
	id_gruppi_trovati.push_back(id_gr_att);
      }
    }
  }

  //  cout << "iio" << nuovi_gruppi.size() << endl;

  for(unsigned int i=0;i<id_gruppi_trovati.size();i++){
    for(unsigned int grp=0;grp<_gruppi.size();grp++){
      if(id_gruppi_trovati[i]==_gruppi[grp].id()){
	//trovato gruppo di appartenenza copiare gli atomi selezionati
	for(unsigned int ct_atom=0;ct_atom<_elem_selected.size();ct_atom++){
	  if((_elem_selected[ct_atom].second).first==id_gruppi_trovati[i]){
	    switch(_elem_selected[ct_atom].first){
	    case ATOMO:
	      {
		
		atomo* tmp=_gruppi[grp].find_atomo_id((_elem_selected[ct_atom].second).second);
		nuovi_gruppi[i].add_atomo(*tmp);
		// 	cout << "iio copiato " << tmp->id() << " in gruppo " << tmp->id_gruppo() 
		// 		     << endl;
		break;
	      }

	    case PROC_BEZIER:
	    case PROC_ARC:
	    case PROC_ARROW:
            case PROC_BOX:
	      {
		procedura* adding=_gruppi[grp].find_proc_id((_elem_selected[ct_atom].second).second);
		nuovi_gruppi[i].aggiungi_procedura(adding);
		break;
	      }
	    }
	  }
	}
      }
    }
  }

  float ref_x_etic=0;
  float ref_y_etic=0;
  bool etich_found=false;
  float xtrasl=0;
  float ytrasl=0;

  //trasliamo
  if(nuovi_gruppi.size()>0){
    xtrasl=nuovi_gruppi[0].posx();
    ytrasl=nuovi_gruppi[0].posy();

    for(unsigned int i=0;i<nuovi_gruppi.size();i++){
      nuovi_gruppi[i].trasla(xt-xtrasl,
			     yt-ytrasl);
    }
    etich_found=true;
    ref_x_etic=xt-xtrasl;
    ref_y_etic=yt-ytrasl;
    //cerr << "piu di un gruppo " << endl;
  }



  //etichette
  for(unsigned int i=0;i<_elem_selected.size();i++){
    int id_gr_att=(_elem_selected[i].second).first;
    if(id_gr_att==NO_VALID_GROUP){
      etichetta* tmp_ptr=ritorna_etich_pointer((_elem_selected[i].second).second);
      etichetta* to_add=NULL;
      if(typeid(*tmp_ptr)==typeid(etichetta)){
        to_add=new etichetta(tmp_ptr);
      }else if(typeid(*tmp_ptr)==typeid(paragraph_text)){
        to_add=new paragraph_text(dynamic_cast<paragraph_text*>(tmp_ptr));
      }else if(typeid(*tmp_ptr)==typeid(multiline_label)){
        to_add=new multiline_label(dynamic_cast<multiline_label*>(tmp_ptr));
      }

      if(to_add!=NULL){
        //trasliamo 
        if(!etich_found){
          ref_x_etic=xt - tmp_ptr->visual_x();
          ref_y_etic=yt - tmp_ptr->visual_y();
          xtrasl=xt - to_add->visual_x();
          ytrasl=yt - to_add->visual_y();
          etich_found=true;
        }else{
          xtrasl=ref_x_etic;
          ytrasl=ref_y_etic;
        }
        /*
          std::cerr << "PIPOO xtrasl=" << xtrasl << " xt=" << xt  << " - "  << to_add.visual_x() << " = "<< xt - to_add.visual_x() 
          << " descale(xt - to_add.visual_x())= " << descale(xt - to_add.visual_x())<< " " <<std::endl;
        */
        
        to_add->trasla(xtrasl,ytrasl);
        add_etich(to_add);
      }
    }
  }





  //ripuliamo dai legami ad atomi inesistenti
  for(unsigned int i=0;i<nuovi_gruppi.size();i++){
    vector<atomo>::iterator inatom=nuovi_gruppi[i].iniz_atom();
    vector<atomo>::iterator finatom=nuovi_gruppi[i].fin_atom();
    while(inatom!=finatom){
       vector<legame>::iterator primo=(*inatom).primo_leg();
       vector<legame>::iterator ultimo=(*inatom).ultimo_leg();
        while(primo!=ultimo){
	  int id_atom_legato=(*primo).id_atomo();
	  //cout << " iio cerco " << id_atom_legato  << "in " << (*inatom).id() << endl;
	  if(nuovi_gruppi[i].find_atomo_id(id_atom_legato)==0){
	    (*inatom).elimina_legame(id_atom_legato);
	    //cout << "iio eliminato legame " << (*inatom).id() << "->" << id_atom_legato << endl;
	  }
	  primo++;
	}
      inatom++;
    }
  }




  //rimappiamo gli id in modo da evitare conflitti

  if(_gruppi.size()>0){
    int strt=(_gruppi.back()).id_gruppo()+1;
    for(unsigned int i=0;i<nuovi_gruppi.size();i++){
      nuovi_gruppi[i].id_gruppo(strt);
      strt++;
    }
  }


  //copiamo
  for(unsigned int i=0;i<nuovi_gruppi.size();i++){

    int nocomp=-1;
    nuovi_gruppi[i].no_componenti_connesse(nocomp);
    if(nocomp>=0){
      _gruppi.push_back(nuovi_gruppi[i]);
    }
  }

  /**
   *Contiene  coppie <tipo, < gruppo, id > > selezionati, se  si e'
   *selezionato una etichetta gruppo e' uguale a NO_VALID_GROUP
   *vector< pair < int, pair<int,int> > > _elem_selected;
   */
  




  /* LASCIARE O TOGLIERE???
  elimina_elem_selected();
  elimina_legami_selected();
  */
#ifdef DEBUG
  dump_tmp_atom();
#endif
}



/**
 *Disegna l'oggetto.
 */

void immagine::disegna(){
  
  float _progress_value_incr=1./(static_cast<float>(_gruppi.size())+_stringhe.size());
  float _progress_value_mult=1;

  if(cairo_t_singleton::can_export()){ //exporting here do calculation for progressbar
    _export_progressw_bar->value(0);
    _export_progressw->show();
    Fl::check(); 
  }
  
  for (unsigned int i=0;i<_gruppi.size();i++){
    _gruppi[i].disegna();
    if(cairo_t_singleton::can_export()){
      _export_progressw_bar->value(_progress_value_mult*_progress_value_incr);
       _progress_value_mult++;
       Fl::check();
    }
  }
  
  for(unsigned int sct=0;sct<_stringhe.size();sct++){
    _stringhe[sct]->disegna();
    if(cairo_t_singleton::can_export()){
      _export_progressw_bar->value(_progress_value_mult*_progress_value_incr);
      _progress_value_mult++;
      Fl::check();
    }
  }
  
  if(!cairo_t_singleton::can_export()){
    highlight_selected();
  }else{
    _export_progressw->hide();
  }
  
}


void immagine::ruota(float xpiv, float ypiv,float angl){
  for (unsigned int i=0;i<_gruppi.size();i++){
    _gruppi[i].ruota(xpiv,ypiv,angl);
  }
}

void immagine::ruota(){
  for (unsigned int i=0;i<_gruppi.size();i++){
    _gruppi[i].ruota();
  }
}

void immagine::trasla(float dx, float dy){
  for (unsigned int i=0;i<_gruppi.size();i++){
    _gruppi[i].trasla(dx,dy);
  }

  for(unsigned int ie=0;ie<_stringhe.size();ie++){
   _stringhe[ie]->trasla(dx,dy);
 }


}



void immagine::scale(float sc){
 for (unsigned int i=0;i<_gruppi.size();i++){
   _gruppi[i].scale(sc);
 }

 for(unsigned int ie=0;ie<_stringhe.size();ie++){
   _stringhe[ie]->scale(sc);
 }


 /*
  for (int i=0;i<_gruppi.size();i++){
    //trasliamo
    vector<procedura*>::iterator proc_st=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator proc_fin=_gruppi[i].fin_procedure();
    while(proc_st!=proc_fin){
      (*proc_st)->scale(sc);
      proc_st++;
    }

  }
 */
}


float immagine::w(){
  vector<float> x;
  
  for(unsigned int i=0;i<_gruppi.size();i++){
    x.push_back(_gruppi[i].posx()+_gruppi[i].w());
  }
  
  for(unsigned int j=0;j<_stringhe.size();j++){
    x.push_back(_stringhe[j]->x()+_stringhe[j]->w());
  }

  return x.begin()!=x.end() ? (*max_element(x.begin(),x.end())) : 0;
}

float immagine::visual_w(){
  vector<float> x;

  for(unsigned int i=0;i<_gruppi.size();i++){
    x.push_back(_gruppi[i].visual_posx()+_gruppi[i].visual_w());
  }


  for(unsigned int j=0;j<_stringhe.size();j++){
    x.push_back(_stringhe[j]->visual_x()+_stringhe[j]->visual_w());
  }


  return x.begin()!=x.end() ? (*max_element(x.begin(),x.end())) : 0;
}

float immagine::phys_w(){
  vector<float> x;

  for(unsigned int i=0;i<_gruppi.size();i++){
    x.push_back(_gruppi[i].phys_posx()+_gruppi[i].phys_w());
  }


  for(unsigned int j=0;j<_stringhe.size();j++){
    x.push_back(_stringhe[j]->phys_x()+_stringhe[j]->phys_w());
  }


  return x.begin()!=x.end() ? (*max_element(x.begin(),x.end())) : 0;

}

float immagine::h(){

  vector<float> y;
  
  for(unsigned int i=0;i<_gruppi.size();i++){
    y.push_back(_gruppi[i].posy()+_gruppi[i].h());
  }


  for(unsigned int j=0;j<_stringhe.size();j++){
    y.push_back(_stringhe[j]->y()+_stringhe[j]->h());
  }


  return y.begin()!=y.end() ? (*max_element(y.begin(),y.end())) : 0;


}

float immagine::visual_h(){
  vector<float> y;

  for(unsigned int i=0;i<_gruppi.size();i++){
    y.push_back(_gruppi[i].visual_posy()+_gruppi[i].visual_h());
  }


  for(unsigned int j=0;j<_stringhe.size();j++){
    y.push_back(_stringhe[j]->visual_y()+_stringhe[j]->visual_h());
  }


  return y.begin()!=y.end() ? (*max_element(y.begin(),y.end())) : 0;


}

float immagine::phys_h(){
  vector<float> y;

  for(unsigned int i=0;i<_gruppi.size();i++){
    y.push_back(_gruppi[i].phys_posy()+_gruppi[i].phys_h());
  }


  for(unsigned int j=0;j<_stringhe.size();j++){
    y.push_back(_stringhe[j]->phys_y()+_stringhe[j]->phys_h());
  }


  return y.begin()!=y.end() ? (*max_element(y.begin(),y.end())) : 0;

}




/**
 *Costruisce, l'oggetto parsando il file passato come argomento.
 */

immagine::immagine(string path)
  :_trovato_apice(false),
   _trovato_pedice(false),
   _has_error(false),
   _punt_mol(0)
{
  create_progressw();
  filebist(path);
  
}


/**
 *Cancella tutta l'immagine ma senza deallocarla, non e' un distuttore.
 */

 void immagine::reset_all(){
   _has_error=false;
   _gruppi.erase(_gruppi.begin(),_gruppi.end());
   _stringhe.erase(_stringhe.begin(),_stringhe.end());
   elimina_err();
   elimina_warn();
   _molecule="";
   _punt_mol=0;
 }



void immagine::aggiungi_template(string templ_file){
  struct stat attrb;
  stat(templ_file.c_str(),&attrb);
  if(!S_ISDIR(attrb.st_mode)){

    _has_error=false;
    elimina_err();
    elimina_warn();
    _molecule="";
    _punt_mol=0;

    _filebist=templ_file;

    if(templ_file==""){
      return;
    }

    ifstream inf(_filebist.c_str(),ios::in);

    if(!inf){
      _has_error=true;
      string error="Error: file " +  _filebist + " do not exist.";
      _error.push_back(error);
    }else{
      while(!inf.eof()){
	string linea;
	getline(inf,linea,'\n');
	if(static_cast<int>(linea.find("#"))!=0 ||
	   linea.find("#")==string::npos ){
	  _molecule+=linea;
	}
      }

      clean_molecule_from_nullchars();

      //      string::size_type globpos=0;

      //      while(globpos < _molecule.size()){
      //        string::size_type canc=_molecule.find_first_of(NULL_CHAR,globpos);
      //        if(canc!=string::npos){
      // 	 char esc=' ';
      // 	 try{
      // 	   esc=_molecule.at(globpos-1);
      // 	   std::cerr << " esc->" << esc << std::endl;
      // 	   if(string(1,esc)!=string(ESCAPE_CHAR)){
      // 	     globpos=canc;
      // 	     _molecule.erase(globpos,1);
      // 	   }else{
      // 	     std::cerr << "trovato escape! " << std::endl;
      // 	     globpos+=2;
      // 	   }

      // 	 }catch (out_of_range e){
      // 	   std::cerr << " exception" << std::endl;
      // 	   globpos=canc;
      // 	   _molecule.erase(globpos,1);

      // 	 }

      //        }else{
      // 	 break;
      //        }
      //      }

      //cout << _molecule << endl;
    }
    inf.close();
    start();
  }
}



   /**
    *
    */
void immagine::filebist(string path){
  struct stat attrb;
  stat(path.c_str(),&attrb);
  if(!S_ISDIR(attrb.st_mode)){


    reset_all();
    _filebist=path;

    if(path==""){
      return;
    }

    ifstream inf(_filebist.c_str(),ios::in);

    if(!inf){
      _has_error=true;
      string error="Error: file " +  _filebist + " do not exist.";
      _error.push_back(error);
    }else{
      while(!inf.eof()){
	string linea;
	getline(inf,linea,'\n');
	if(static_cast<int>(linea.find("#"))!=0 ||
	   linea.find("#")==string::npos ){
	  _molecule+=linea;
	}
      }

      clean_molecule_from_nullchars();

    }

    inf.close();

  }

}



bool immagine::has_error(){
  return _has_error;
}


void immagine::start(){

  /*
    cout << "GRPSZ: " << _gruppi.size() << endl;
    cout << "ETCHSZ " << _stringhe.size() << endl;
  */
  if(!_has_error){
    setlocale(LC_ALL,"C");
    p_gruppo();
    //inizializziamo tutte le procedure
    //cout << "GRPSZ: " << _gruppi.size() << endl;
    for (unsigned int i=0;i<_gruppi.size();i++){
      vector<procedura*>::iterator st_prc=_gruppi[i].iniz_procedure();
      vector<procedura*>::iterator en_prc=_gruppi[i].fin_procedure();
      
      while(st_prc!=en_prc){
	(*st_prc)->init();
	st_prc++;
      }
    }
    
    //ordiniamo i gruppi
    
    sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
    
#ifdef DEBUG
    dump_tmp_atom();
#endif //DEBUG

    p_stringhe();

#ifdef DEBUG
    for(unsigned int ct=0;ct<_stringhe.size();ct++){
      vector < pair<string,int> > tmp_str_et=_stringhe[ct].vec_str();
      cout << " *** etichetta: " << endl;
      for(unsigned int i2=0;i2<tmp_str_et.size();i2++){
	switch(tmp_str_et[i2].second){
	case ET_STR:
	  cout << "\tSTR: " << tmp_str_et[i2].first;
	  break;
	case ET_APICE:
	  cout << "\tAPICE: " << tmp_str_et[i2].first;
	  break;
	case ET_PEDICE:
	  cout << "\tPEDICE: " << tmp_str_et[i2].first;
	  break;
	}
      }
      cout << "\n";
      cout << "FONT " << _stringhe[ct].font() << endl;
      cout << "DIM_FONT " << _stringhe[ct].dim() << endl;
      cout << "X " << _stringhe[ct].x() << endl;
      cout << "Y " << _stringhe[ct].y() << endl;
      cout << "CR " << _stringhe[ct].cr() << endl;
      cout << "CG " << _stringhe[ct].cg() << endl;
      cout << "CB " << _stringhe[ct].cb() << endl;
      cout << " *** etichetta" << endl;
    }

#endif //DEBUG
    setlocale(LC_ALL,"");
  }else{
    
  }
  
}

/**
 *Fa il dump  dei valori del vettore contenente gli  atomi: utile per il
 *debugging;
 */

void immagine::dump_tmp_atom(){
  
  
  for (unsigned int i=0;i<_gruppi.size();i++){
       cout << "GRUPPI:" << endl;
       vector<atomo>::iterator st=_gruppi[i].iniz_atom();
       vector<atomo>::iterator en=_gruppi[i].fin_atom();
       cout << "ID: " << (_gruppi[i]).id_gruppo() << endl;
       cout << "ANGOLOROT: " << (_gruppi[i]).angolorot() << endl;
       cout << "ROT_XPIVOT: " << (_gruppi[i]).xpivot() << endl;
       cout << "ROT_YPIVOT: " << (_gruppi[i]).ypivot() << endl;

       while(st!=en){
	 cout << (*st).id() << endl;
	 st++;
       }


       vector<atomo>::iterator iniz=(_gruppi[i]).iniz_atom();
       vector<atomo>::iterator fin=(_gruppi[i]).fin_atom();

       while(iniz!=fin){

	 etichetta tmp_et=(*iniz).etich();
	 vector < pair<string,int> > tmp_str_et=tmp_et.vec_str();
	 cout << "Atomo:" << (*iniz).id() << " ";
	 cout << "Tipo:"<< (*iniz).tipo_atomo() << endl;
	 cout << "***etichetta:" << endl;
	 for(unsigned int i2=0;i2<tmp_str_et.size();i2++){
	   // #define ET_STR   0
	   // #define ET_APICE 1
	   // #define ET_PEDICE 2
	   //cout << "#@#" << tmp_str_et.second << endl;
	   switch(tmp_str_et[i2].second){
	   case ET_STR:
	     cout << "\tSTR: " << tmp_str_et[i2].first;
	     break;
	   case ET_APICE:
	     cout << "\tAPICE: " << tmp_str_et[i2].first;
	     break;
	   case ET_PEDICE:
	     cout << "\tPEDICE: " << tmp_str_et[i2].first;
	     break;
	   }
	 }
	 cout << endl;
	 cout << "\tFONT_ET: " << tmp_et.font() << endl;
	 cout << "\tDIM_FONT_ET: " << tmp_et.dim() << endl;;
	 cout << "\tX_ET: " << tmp_et.x() << " dovrebbe essere 0" << endl;
	 cout << "\tY_ET: " << tmp_et.y() << " dovrebbe essere 0" << endl;

	 cout << "\tCR_ET: " << tmp_et.cr() << endl;
	 cout << "\tCG_ET: " << tmp_et.cg() << endl;
	 cout << "\tCB_ET: " << tmp_et.cb() << endl;
	 cout << "\tALLINEAMENTO: " << tmp_et.allineamento() << endl;

	 cout << "***fine etichetta" << endl;
	 cout << "Cariche: " << (*iniz).cariche() << endl;
	 cout << "Doppietti:" << (*iniz).doppietti() << endl;
	 cout << "Elettroni spaiati: " << (*iniz).el_spaiati() << endl;
	 cout << "Numero di massa: " << (*iniz).massa() << endl;
	 cout << "CR: " << (*iniz).cr() << endl;
	 cout << "CG: " << (*iniz).cg() << endl;
	 cout << "CB: " << (*iniz).cb() << endl;
	 cout << "POSX:" << (*iniz).pos_x() << endl;
	 cout << "POSY: " << (*iniz).pos_y() << endl;
	 cout << "ID_GRUPPO: " <<(*iniz).id_gruppo() << endl;
	 cout << "***legami" << endl;
	 vector<legame>::iterator inizl=(*iniz).primo_leg();
	 vector<legame>::iterator finl=(*iniz).ultimo_leg();
	 while(inizl!=finl){
	   cout << "\tid_atomo: " << (*inizl).id_atomo() << endl;
	   cout << "\tid_legame: " << (*inizl).id_legame() << endl;
	   cout << "\ttipo_legame " << (*inizl).tipo_legame() << endl;
	   cout << "\tcr " << (*inizl).cr() << endl;
	   cout << "\tcg " << (*inizl).cg() << endl;
	   cout << "\tcb " << (*inizl).cb() << endl;
	   inizl++;
	 }

	 cout << "*** fine legami ***" << endl;

	 iniz++;
     }



       vector<procedura*>::iterator st2=_gruppi[i].iniz_procedure();
       vector<procedura*>::iterator en2=_gruppi[i].fin_procedure();

       while(st2!=en2){

	 cout << (_gruppi[i]).id_gruppo() <<"-- "<< (*st2) << " tipo: " <<(*st2)->tipo()<< endl;
	 switch((*st2)->tipo()){
	 case PROC_ARC:
	   {
	     proc_arc* arc=dynamic_cast<proc_arc*>(*st2);
	     cout << "TIPO "   << arc->tipo() << endl;
	     cout << "ARC_ID " << arc->id() << endl;
	     cout << "ARC_XSTART " << arc->xstart()<< endl;
	     cout << "ARC_YSTART " << arc->ystart()<< endl;
	     cout << "ARC_XEND " << arc->xend()<< endl;
	     cout << "ARC_YEND " << arc->yend()<< endl;

	     cout << "ARC_X1 " << arc->x1()<< endl;
	     cout << "ARC_Y1 " << arc->y1()<< endl;
	     cout << "ARC_X2 " << arc->x2()<< endl;
	     cout << "ARC_Y2 " << arc->y2()<< endl;
	     cout << "ARC_X3 " << arc->x3()<< endl;
	     cout << "ARC_Y3 " << arc->y3()<< endl;
	     cout << "ARC_X4 " << arc->x4()<< endl;
	     cout << "ARC_Y4 " << arc->y4()<< endl;

	     cout << "ARC_CB " << arc->cb()<< endl;
	     cout << "ARC_CR " << arc->cr()<< endl;
	     cout << "ARC_CG " << arc->cg()<< endl;
	     cout << "ARC_XPIV " << arc->xpivot() << endl;
	     cout << "ARC_YPIV " << arc->ypivot() << endl;
	     cout << "ARC_ANGOLOROT " << arc->angolorot() << endl;
	     cout << "ARC_SPESSORE " << arc->spessore() << endl;
	     cout << "ARC_DASH "      << arc->dash()      << endl;
	     break;
	   }
	 case PROC_ARROW:
	   {
	     proc_arrow* arr=dynamic_cast<proc_arrow*>(*st2);
	     cout << "TIPO "   << arr->tipo() << endl;
	     cout << "ARR_ID " << arr->id() << endl;
	     cout << "ARR_POSX " << arr->posx()<< endl;
	     cout << "ARR_POSY " << arr->posy()<< endl;
	     cout << "ARR_EPOSX " << arr->eposx() << endl;
	     cout << "ARR_EPOSY " << arr->eposy() << endl;
	     cout << "ARR_W " << arr->w()<< endl;
	     cout << "ARR_H " << arr->h()<< endl;
	     cout << "ARR_CB " << arr->cb()<< endl;
	     cout << "ARR_CR " << arr->cr()<< endl;
	     cout << "ARR_CG " << arr->cg()<< endl;
	     cout << "ARR_XPIV " << arr->xpivot() << endl;
	     cout << "ARR_YPIV " << arr->ypivot() << endl;
	     cout << "ARR_ANGOLOROT " << arr->angolorot() << endl;
	     cout << "ARR_SPESSORE " << arr->spessore() << endl;
	     cout << "ARR_DASH "      << arr->dash()      << endl;
	     cout << "ARR_ARR_W "      << arr->arr_w()      << endl;
	     cout << "ARR_ARR_H "      << arr->arr_h()      << endl;
	     cout << "ARR_ARR_GAP "      << arr->arr_gap()      << endl;
	     cout << "ARR_PUNTE ";
	     switch(arr->punte()){
	     case ARR_NO_PUNT:
	       cout << "Nessuna freccia."<< endl;
	       break;
	     case ARR_OMOL_PUNT:
	       cout << "Scissione omolitica."<< endl;
	       break;
	     case ARR_ETEROL_PUNT:
	       cout << "Scissione eterolitica."<< endl;
	       break;

	     case ARR_DOUBLE:
		cout << "Risonanza."<< endl;
		break;

	     case ARR_BLOC:
	       cout << "Fraccia sbarrata."<< endl;
	       break;

	     }
	     break;
	   }


	 case PROC_BEZIER:
	   {
	     proc_bezier* bez=dynamic_cast<proc_bezier*>(*st2);
	     cout << "TIPO "   << bez->tipo() << endl;
	     cout << "BEZIER_ID " << bez->id() << endl;
	     cout << "BEZIER_I_POSX " << bez->ix()<< endl;
	     cout << "BEZIER_I_POSY " << bez->iy()<< endl;
	     cout << "BEZIER_T1_POSX " << bez->tan1x()<< endl;
	     cout << "BEZIER_T1_POSY " << bez->tan1y()<< endl;

	     cout << "BEZIER_T2_POSX " << bez->tan2x()<< endl;
	     cout << "BEZIER_T2_POSY " << bez->tan2y()<< endl;

	     cout << "BEZIER_E_X " << bez->ex() << endl;
	     cout << "BEZIER_E_Y " << bez->ey() << endl;
	     cout << "BEZIER_W " << bez->w()<< endl;
	     cout << "BEZIER_H " << bez->h()<< endl;
	     cout << "BEZIER_CB " << bez->cb()<< endl;
	     cout << "BEZIER_CR " << bez->cr()<< endl;
	     cout << "BEZIER_CG " << bez->cg()<< endl;
	     cout << "BEZIER_XPIV " << bez->xpivot() << endl;
	     cout << "BEZIER_YPIV " << bez->ypivot() << endl;
	     cout << "BEZIER_ANGOLOROT " << bez->angolorot() << endl;
	     cout << "BEZIER_SPESSORE " << bez->spessore() << endl;
	     cout << "BEZIER_DASH "      << bez->dash()      << endl;
	     cout << "BEZIER_PUNTE ";
	     switch(bez->punte()){
	     case ARR_NO_PUNT:
	       cout << "Nessuna freccia."<< endl;
	       break;
	     case ARR_OMOL_PUNT:
	       cout << "Scissione omolitica."<< endl;
	       break;
	     case ARR_ETEROL_PUNT:
	       cout << "Scissione eterolitica."<< endl;
	       break;

	     case ARR_DOUBLE:
		cout << "Risonanza."<< endl;
		break;

	     case ARR_BLOC:
	       cout << "Fraccia sbarrata."<< endl;
	       break;
	     default:
	       cout << "c'e' qualcosa che non va " << endl;
	       break;
	     }
	     break;
	   }
           
	 case PROC_BOX:
	   {
	     BoxProc* box=dynamic_cast<BoxProc*>(*st2);
	     cout << "TIPO "   << box->tipo() << endl;
	     cout << "BOX_ID " << box->id() << endl;
	     cout << "BOX_POSX " << box->posx()<< endl;
             cout << "BOX_POSY " << box->posy()<< endl;
	     cout << "BOX_W " << box->w()<< endl;
	     cout << "BOX_H " << box->h()<< endl;
	     cout << "BOX_CB " << box->cb()<< endl;
	     cout << "BOX_CR " << box->cr()<< endl;
	     cout << "BOX_CG " << box->cg()<< endl;
	     cout << "BOX_XPIV " << box->xpivot() << endl;
	     cout << "BOX_YPIV " << box->ypivot() << endl;
	     cout << "BOX_ANGOLOROT " << box->angolorot() << endl;
	     cout << "BOX_SPESSORE " << box->spessore() << endl;
	     cout << "BOX_DASH "      << box->dash()      << endl;
	     break;
	   }




	 }


	 st2++;
       }

     }


 }

 /*

 ATOMO    := "atomo" ID_ATOMO ":" "tipo_atomo" TIPO_ATOMO APRI
	     "elemento" APRI
			     ETICHETTA SEP CARICHE
			     SEP DOPPIETTI SEP EL_SPAIATI
			     SEP MASSA
			     SEP COLORE SEP COLORE SEP COLORE
			     SEP POSX SEP POSY
			CHIUDI

		     LISTA_DI_ADIACENZA
		 CHIUDI

 */


 void immagine::p_atomo(){

   if(_molecule.substr(_punt_mol,string(ETIC_ATOMO).size())==ETIC_ATOMO){
     atomo buff_atom;
     _tmp_atom.push_back(buff_atom);
     _punt_mol+=string(ETIC_ATOMO).size();
     string::size_type dp=_molecule.find(DP,_punt_mol);
     if(dp==string::npos){
       _has_error=true;
       _error.push_back(gen_err_miss_string(string(DP),_punt_mol,string(DP).size()));
     }else{
       /*Parsiamo un numero*/
       string s_num=_molecule.substr(_punt_mol,dp-_punt_mol);
       int num=p_int(s_num);
       if(_has_error){
	 _error.push_back(gen_err_miss_number(_punt_mol,dp-_punt_mol));
	 return;
       }else{
	 //abbiamo l'id
	 _punt_mol+=dp-_punt_mol+1;
	 (_tmp_atom.back()).id(num);
       }


       if(_molecule.substr(_punt_mol,string(ETIC_TIPO_ATOMO).size())==
	  ETIC_TIPO_ATOMO){

	 _punt_mol+=string(ETIC_TIPO_ATOMO).size();
	 /*cerchiamo l'inizio del blocco*/
	 string::size_type iniz_b=trova_apri();
	 if(_has_error){
	   _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
			       string(APRI).size()));
	   return;
	 }else{
	   //cerchiamo il tipo di atomo
	   string s_num=_molecule.substr(_punt_mol,iniz_b-_punt_mol);
	   int num=p_int(s_num);
	   if(_has_error){
	     _error.push_back(gen_err_miss_number(_punt_mol,iniz_b-_punt_mol));
	     return;
	   }else{
	     _punt_mol=_punt_mol+(iniz_b-_punt_mol)+1;

	     (_tmp_atom.back()).tipo_atomo(num);
	   }
	   //cerchiamo l'elemento e sue caratteristiche
	   p_elemento();
	   //ed infine la lista di adiacenza (i legami)
	   p_lista();
	   //controlliamo che il blocco si sia chiuso
	   chk_chiusura_blocco();

	   (_tmp_atom.back()).costruisci_arrivati();
	   if(_tmp_atom.size()>=2){
	     vector<atomo>::iterator exist=find(_tmp_atom.begin(),_tmp_atom.end()-1,_tmp_atom.back());
	     if(exist==_tmp_atom.end()-2){
	       _warning.push_back(gen_warn_id_conflict("atomo", (_tmp_atom.back()).id()));
	       _tmp_atom.erase(_tmp_atom.end()-1);
	     }
	   }


	   //aggiungiamo l'atomo temporaneo al vettore di atomi
	   //_atomi.push_back(_tmp_atom);
	   //ripuliamo l'atomo usato come buffer
	   //_tmp_atom.elimina_legami();
	   //e poi si ricomincia!!
	   p_atomo();
	 }
       }else{
	 _has_error=true;
	 _error.push_back(gen_err_miss_string(ETIC_TIPO_ATOMO,_punt_mol,
					      string(ETIC_TIPO_ATOMO).size()));
	 return;
       }

     }

   }else{
     return;
   }


 }

 // "elemento"
 // APRI
 //   ETICHETTA SEP CARICHE
 //   SEP DOPPIETTI SEP EL_SPAIATI SEP
 //   POS_X SEP POS_Y
 //CHIUDI

 void immagine::p_elemento(){

   string et_elemento=_molecule.substr(_punt_mol,
				       string(ETIC_ELEMENTO).size());

   if(et_elemento==ETIC_ELEMENTO){
     _punt_mol+=string(ETIC_ELEMENTO).size();
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/
     trova_apri();
     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),
					     _punt_mol,string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       etichetta risul=p_etichetta();

       /*
       vector < pair<string,int> > tmp_str_et=risul.vec_str();
       cout << "#@#@etichetta:" << endl;
       for(int i2=0;i2<tmp_str_et.size();i2++){
	 // #define ET_STR   0
	 // #define ET_APICE 1
	 // #define ET_PEDICE 2
	 //cout << "#@#" << tmp_str_et[i].second << endl;
	 switch(tmp_str_et[i2].second){
	 case ET_STR:
	   cout << "\tSTR: " << tmp_str_et[i2].first;
	   break;
	 case ET_APICE:
	   cout << "\tAPICE: " << tmp_str_et[i2].first;
	   break;
	 case ET_PEDICE:
	   cout << "\tPEDICE: " << tmp_str_et[i2].first;
	   break;
	 }
       }
       */





       if(_has_error){
	 return;
       }


       (_tmp_atom.back()).etich(risul);


       if(string(1,_molecule[_punt_mol])!=string(SEP)){
	 _has_error=true;
	 _error.push_back(gen_err_miss_string(string(SEP),
					      _punt_mol,string(SEP).size()));
       }else{
	 _punt_mol++;
       }

       (_tmp_atom.back()).cariche(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }
       
       (_tmp_atom.back()).position_charge(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }


       (_tmp_atom.back()).doppietti(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).el_spaiati(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).massa(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).cr(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).cg(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).cb(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).pos_x(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       (_tmp_atom.back()).pos_y(trova_campo_etic_float(CHIUDI));
       if(_has_error){
	 return;
       }

       //cout << _molecule.substr(_punt_mol);
     }

   }else{
     //errore, manca l'etichetta
     _has_error=true;
     _error.push_back(gen_err_miss_string(string(ETIC_ELEMENTO),
					  _punt_mol,
					  string(ETIC_ELEMENTO).size() )
		      );
     return;


   }

 }


 /*
 LISTA_DI_ADIACENZA :=  "lista" APRI
				( "legame" APRI
						 ID_ATOMO SEP ID_LEGAME
						 SEP TIPO_LEGAME
						 SEP COLORE
						 SEP COLORE
						 SEP COLORE
					   CHIUDI
				)?
				CHIUDI
 */


 void immagine::p_lista(){

  string et_elemento=_molecule.substr(_punt_mol,
				       string(ETIC_LISTA).size());

   if(et_elemento==ETIC_LISTA){
     _punt_mol+=string(ETIC_LISTA).size();
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/trova_apri();

     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),
					    _punt_mol,string(APRI).size()));
       return;
     }else{
       _punt_mol++;

       p_legami();
       chk_chiusura_blocco();
     }

   }else{
     //errore, manca l'etichetta
     _has_error=true;
     _error.push_back(gen_err_miss_string(string(ETIC_LISTA),
					  _punt_mol,
					  string(ETIC_LISTA).size()
					  )
		      );
     return;
   }

 }

 void immagine::p_legami(){

  string et_elemento=_molecule.substr(_punt_mol,
				       string(ETIC_LEGAME).size());

   if(et_elemento==ETIC_LEGAME){
     _punt_mol+=string(ETIC_LEGAME).size();
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/trova_apri();

     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),
					    _punt_mol,string(APRI).size()));
       return;
     }else{
       _punt_mol++;

       int id_atomico=trova_campo_etic_int(SEP);
       int id_leg=trova_campo_etic_int(SEP);
       int tipo_leg=trova_campo_etic_int(SEP);
       int col_r=trova_campo_etic_int(SEP);
       int col_g=trova_campo_etic_int(SEP);
       int col_b=trova_campo_etic_int(CHIUDI);

       if(_has_error){

	 return;

       }

       //      cout << _molecule.substr(_punt_mol) << endl;

       /////////////DA FARE///////////////////////////////////////////
       legame tmp_leg(id_atomico,id_leg,tipo_leg,col_r,col_g,col_b);

       vector<legame>::iterator exist=find((_tmp_atom.back()).primo_leg(),
					  (_tmp_atom.back()).ultimo_leg(),
					  tmp_leg);
       if((_tmp_atom.back()).primo_leg()!=(_tmp_atom.back()).ultimo_leg()&&
	  exist!=(_tmp_atom.back()).ultimo_leg()){
	 _warning.push_back(gen_warn_id_conflict("legame", tmp_leg.id_legame() ));
       }else{
	 (_tmp_atom.back()).aggiungi_legame(id_atomico,id_leg,tipo_leg,col_r,col_g,col_b);
       }


       //(_tmp_atom.back()).aggiungi_legame(id_atomico,id_leg,tipo_leg,col_r,col_g,col_b);
       p_legami();
     }

   }else{
     //finito;
     return;

     //errore, manca l'etichetta
     //_has_error=true;
     //_error.push_back(gen_err_miss_string(string(ETIC_LISTA),
     //					 _punt_mol,
     //				 string(ETIC_LISTA).size() )
     //	     );
     //return;
   }
 }


 /*
 GRUPPO   := "gruppo" ID_GRUPPO ":" "tipo_gruppo" TIPO_GRUPPO
				 APRI
					 ATOMO?
					 PROCEDURA*
				 CHIUDI
 */

void immagine::p_gruppo(){

  //ordiniamo i gruppi

  sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);

   if(_molecule.substr(_punt_mol,string(ETIC_GRUPPO).size())==ETIC_GRUPPO){
     gruppo buff_gruppo;
     _gruppi.push_back(buff_gruppo);
     _punt_mol+=string(ETIC_GRUPPO).size();

     string::size_type dp=_molecule.find(DP,_punt_mol);
     if(dp==string::npos){
       _has_error=true;
       _error.push_back(gen_err_miss_string(string(DP),_punt_mol,string(DP).size()));
     }else{
       //Parsiamo un numero
       string s_num=_molecule.substr(_punt_mol,dp-_punt_mol);
       int num=p_int(s_num);
       if(_has_error){
	 _error.push_back(gen_err_miss_number(_punt_mol,dp-_punt_mol));
	 return;
       }else{
	 //abbiamo l'id
	 _punt_mol+=dp-_punt_mol+1;

	 (_gruppi.back()).id_gruppo(num);
	 //cout << (_gruppi.back()).id_gruppo() << endl;
       }


       if(_molecule.substr(_punt_mol,string(ETIC_TIPO_GRUPPO).size())==
	  ETIC_TIPO_GRUPPO){

	 _punt_mol+=string(ETIC_TIPO_GRUPPO).size();
	 //cerchiamo l'inizio del blocco
	 string::size_type iniz_b=trova_apri();
	 if(_has_error){
	   _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
			       string(APRI).size()));
	   return;
	 }else{
	   _punt_mol+=string(APRI).size();
	   //cerchiamo il tipo di gruppo
	   string s_num=_molecule.substr(_punt_mol,iniz_b-_punt_mol);
	   int num=p_int(s_num);
	   if(_has_error){
	     _error.push_back(gen_err_miss_number(_punt_mol,iniz_b-_punt_mol));
	     return;
	   }else{
	     _punt_mol=_punt_mol+(iniz_b-_punt_mol)+1;

	     (_gruppi.back()).tipo_gruppo(num);
	   }

	   //cerchiamo le rotazioni
	   p_grot(_gruppi.back());
	   //cerchiamo gli atomi
	   p_atomo();
	   //cerchiamo le eventuali procedure
	   p_procedure();
	   //controlliamo che il blocco si sia chiuso
	   chk_chiusura_blocco();
	   //copiamo i valori dal buffer al vettore effettivo

	   for(unsigned int i=0;i<_tmp_atom.size();i++){
	     //cout << "di suo il gruppo e' " << &_gruppi.back() << " ";
	     _tmp_atom[i].aggiungi_genitore(&_gruppi.back());
	     //cout << "ritornato: " << _tmp_atom[i].id_gruppo() << " " << &_gruppi.back() << endl;
	     (_gruppi.back()).add_atomo(_tmp_atom[i]);
	   }
	   //svuotiamo il buffer
	   _tmp_atom.erase(_tmp_atom.begin(),_tmp_atom.end());
	   //e poi si ricomincia!!

	   if(_gruppi.size()>=2){ // cambiare con >1?
	     vector<gruppo>::iterator exist=find(_gruppi.begin(),_gruppi.end()-1,_gruppi.back());
	     if(exist!=_gruppi.end()-1){
	       //_warning.push_back(gen_warn_id_conflict("gruppo", (_gruppi.back()).id_gruppo()));
	       //_gruppi.erase(_gruppi.end()-1);
	       (_gruppi.back()).id_gruppo(_gruppi[_gruppi.size()-2].id_gruppo()+1);
	       /*
	       int max=-1;
	       for(int ct=0;ct<_gruppi.size()-1;ct++){
		 if(max<_gruppi[ct].id_gruppo()){
		   max=_gruppi[ct].id_gruppo();
		 }
	       }
	       */
	       //cout << "NUOVO ID" << max+1 << endl;
	       //(_gruppi.back()).id_gruppo(max+1);
	     }
	   }

	   if(!_is_preview){
	     //adesso  facciamo  in modo  che  il  gruppo sia  selezionato
	     //dall'interfaccia utente
	     aggiungi_tutto_selected(_gruppi.back());
	   }
	   p_gruppo();
	 }
       }else{
	 _has_error=true;
	 _error.push_back(gen_err_miss_string(ETIC_TIPO_GRUPPO,_punt_mol,
					      string(ETIC_TIPO_GRUPPO).size()));
	 return;
       }

     }

   }else{
#ifdef DEBUG
     cout << "Parsing dei gruppi completato"
	  << endl;
#endif
     return;
   }

}


 void immagine::p_grot(gruppo& grp){
   if(_molecule.substr(_punt_mol,string(ETIC_ROT).size())==ETIC_ROT){
     _punt_mol+=string(ETIC_ROT).size();
     /*string::size_type iniz_b=*/trova_apri();
	 if(_has_error){
	   _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
			       string(APRI).size()));
	   return;
	 }else{
	   _punt_mol+=string(APRI).size();
	   grp.angolorot(trova_campo_etic_float(SEP));
	   if(_has_error){
	     return;
	   }
	   grp.xpivot(trova_campo_etic_float(SEP));
	   if(_has_error){
	     return;
	   }
	   grp.ypivot(trova_campo_etic_float(CHIUDI));
	   if(_has_error){
	     return;
	   }

	 }

   }else{
     return;
   }
 }

 void immagine::p_procedure(){

   if(_molecule.substr(_punt_mol,string(ETIC_ARC).size())==ETIC_ARC){

     proc_arc* tmp_arc=new proc_arc();
     tmp_arc->aggiungi_genitore(&_gruppi.back());
     //cout << "arco" << tmp_arc  << "id " << _gruppi.back().id_gruppo() << endl;

     _punt_mol+=string(ETIC_ARC).size();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/trova_apri();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
					    string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       tmp_arc->id(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->xstart(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->ystart(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->xend(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->yend(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_arc->x1(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->y1(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }



       tmp_arc->x2(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->y2(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_arc->x3(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->y3(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }



       tmp_arc->x4(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->y4(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_arc->cr(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->cg(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->cb(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->xpivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->ypivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_arc->angolorot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->spessore(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arc->dash(trova_campo_etic_int(CHIUDI));
       if(_has_error){
	 return;
       }


       //controlliamo che il blocco si sia chiuso
       //chk_chiusura_blocco();

       bool trovato=find_proc(tmp_arc);

       if(trovato){
	 _warning.push_back(gen_warn_id_conflict("procedura", tmp_arc->id()));
       }else{
	 (_gruppi.back()).aggiungi_procedura(tmp_arc);
       }

       //e poi si ricomincia
       p_procedure();

     }

   }else if(_molecule.substr(_punt_mol,string(ETIC_ARROW).size())==ETIC_ARROW){
     /*
       'ARROW' APRI
	       ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
	       SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
	       SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
	       DASH
	       CHIUDI
     */


     proc_arrow* tmp_arrow=new proc_arrow();
     tmp_arrow->aggiungi_genitore(&_gruppi.back());
     _punt_mol+=string(ETIC_ARROW).size();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/trova_apri();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
					    string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       tmp_arrow->id(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->posx(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->posy(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->eposx(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->eposy(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->cr(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->cg(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->cb(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->xpivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->ypivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_arrow->angolorot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->spessore(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->dash(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->punte(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->arr_w(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_arrow->arr_h(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }
       
       tmp_arrow->arr_gap(trova_campo_etic_float(CHIUDI));
       if(_has_error){
	 return;
       }

       //controlliamo che il blocco si sia chiuso
       //chk_chiusura_blocco();


       bool trovato=find_proc(tmp_arrow);

       if(trovato){
	 _warning.push_back(gen_warn_id_conflict("procedura", tmp_arrow->id()));
       }else{
	 (_gruppi.back()).aggiungi_procedura(tmp_arrow);
       }

       //e poi si ricomincia
       p_procedure();

     }



   }else if(_molecule.substr(_punt_mol,string(ETIC_BEZIER).size())==ETIC_BEZIER){
       /*
	 'BEZIER' APRI
	 ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
	 SEP POSX SEP POSY SEP POSX SEP POSY
	 SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
	 SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
	 DASH SEP NUMPUNTE
	 CHIUDI
       */



       proc_bezier* tmp_bezier=new proc_bezier();
       tmp_bezier->aggiungi_genitore(&_gruppi.back());
       _punt_mol+=string(ETIC_BEZIER).size();
       //cout <<"bez-->" <<  tmp_bezier << endl;
       /*cerchiamo l'inizio del blocco*/
       /*string::size_type iniz_b=*/trova_apri();
       //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
       if(_has_error){
	 _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
					      string(APRI).size()));
	 return;
       }else{
	 _punt_mol++;
	 tmp_bezier->id(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->ix(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->iy(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->tan1x(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->tan1y(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }


	 tmp_bezier->tan2x(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->tan2y(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->ex(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->ey(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }


	 tmp_bezier->cr(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->cg(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->cb(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->xpivot(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->ypivot(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }


	 tmp_bezier->angolorot(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->spessore(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->dash(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }



	 tmp_bezier->punte(trova_campo_etic_int(SEP));
	 if(_has_error){
	   return;
	 }

	 tmp_bezier->arr_w(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }
	 
	 tmp_bezier->arr_h(trova_campo_etic_float(SEP));
	 if(_has_error){
	   return;
	 }
	 
	 tmp_bezier->arr_gap(trova_campo_etic_float(CHIUDI));
	 if(_has_error){
	   return;
	 }


	 //controlliamo che il blocco si sia chiuso
	 //chk_chiusura_blocco();

	 bool trovato=find_proc(tmp_bezier);

	 if(trovato){
	   _warning.push_back(gen_warn_id_conflict("procedura", tmp_bezier->id()));
	 }else{
	   (_gruppi.back()).aggiungi_procedura(tmp_bezier);
	 }

	 //e poi si ricomincia
	 p_procedure();

       }


   }else if(_molecule.substr(_punt_mol,string(ETIC_BOX).size())==ETIC_BOX){
  /*

	     'BOX'   APRI
			ID_PROC SEP LD_X SEP LD_Y SEP RU_X SEP RU_Y
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP BOX_TYPE
		      CHIUDI
  */

     

     BoxProc* tmp_box=new BoxProc();
     tmp_box->aggiungi_genitore(&_gruppi.back());
     _punt_mol+=string(ETIC_BOX).size();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     /*cerchiamo l'inizio del blocco*/
     /*string::size_type iniz_b=*/trova_apri();
     //cout <<"-->" <<  _molecule.substr(_punt_mol) << endl;
     if(_has_error){
       _error.push_back(gen_err_miss_string(string(APRI),_punt_mol,
					    string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       tmp_box->id(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->ld_x(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->ld_y(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->ru_x(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->ru_y(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->cr(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->cg(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->cb(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->xpivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->ypivot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }


       tmp_box->angolorot(trova_campo_etic_float(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->spessore(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }

       tmp_box->dash(trova_campo_etic_int(SEP));
       if(_has_error){
	 return;
       }
              
       tmp_box->b_type(static_cast<box_type>(trova_campo_etic_int(CHIUDI)));

       if(_has_error){
	 return;
       }

       bool trovato=find_proc(tmp_box);

       if(trovato){
	 _warning.push_back(gen_warn_id_conflict("procedura", tmp_box->id()));
       }else{
	 (_gruppi.back()).aggiungi_procedura(tmp_box);
       }

       //e poi si ricomincia
       p_procedure();

     }


   }else{
     return;
   }


 }


 bool immagine::find_proc(procedura* proc){
   vector<procedura*>::iterator inizp=(_gruppi.back()).iniz_procedure();
   vector<procedura*>::iterator finp=(_gruppi.back()).fin_procedure();

   bool found=false;

   while(inizp!=finp){
     if((*inizp)->id()==proc->id()){
       found=true;
       break;
     }
     inizp++;
   }

   return found;

 }


 void immagine::chk_chiusura_blocco(){
   if(_punt_mol>=_molecule.size() ||
      _molecule[_punt_mol]!=(string(CHIUDI))[0]){
     _has_error=true;
     _error.push_back(gen_err_miss_string(string(CHIUDI),
					  _punt_mol,string(CHIUDI).size()));
   }else{
     _punt_mol+=string(CHIUDI).size();
   }
 }


 /*
 ETICHETTA := "etichetta" APRI
				 VALORE SEP FONT SEP DIMENSIONE_FONT SEP X SEP Y
			 CHIUDI
 VALORE := CHAR? VALORE*  |  '_{ CHAR? '}' | '^{ CHAR? '}' | "nada" | "alto"

 */

 etichetta immagine::p_etichetta(){
    string et_etic=_molecule.substr(_punt_mol,
				    string(ETIC_ETIC).size());
    etichetta tmp_etic;

    if(et_etic==ETIC_ETIC){
      _punt_mol+=string(ETIC_ETIC).size();
      /*cerchiamo l'inizio del blocco*/
      /*string::size_type iniz_b=*/trova_apri();
      if(_has_error){
	_error.push_back(gen_err_miss_string(string(APRI),
					      _punt_mol,string(APRI).size()));
	return tmp_etic;
      }else{
	_punt_mol++;
	p_valore(tmp_etic);
	tmp_etic.font(trova_campo_etic_int(SEP));
	if(_has_error){
	  return tmp_etic;
	}


	tmp_etic.dim(trova_campo_etic_int(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	

	tmp_etic.x(trova_campo_etic_float(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	


	tmp_etic.y(trova_campo_etic_float(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	
	tmp_etic.cr(trova_campo_etic_int(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	
	tmp_etic.cg(trova_campo_etic_int(SEP));
	
	
	
	if(_has_error){
	  return tmp_etic;
	}
	
	tmp_etic.cb(trova_campo_etic_int(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	
	tmp_etic.allineamento(trova_campo_etic_int(SEP));
	
	if(_has_error){
	  return tmp_etic;
	}
	
	tmp_etic.v_offset(trova_campo_etic_int(CHIUDI));
	
	if(_has_error){
	  return tmp_etic;
	}



	//abbiamo parsato con successo l'etichetta, ritorniamola

	return tmp_etic;

      }



    }else{
      _has_error=true;
      _error.push_back(gen_err_miss_string(string(ETIC_ETIC),_punt_mol,
					   string(ETIC_ETIC).size()));
      return tmp_etic;
    }

 }



void immagine::p_stringhe(){
  if(_has_error || !(_punt_mol<_molecule.size()) ){
#ifdef DEBUG
    cout << "Parsing delle stringhe completato"
         << endl;
#endif
    return;
  }

  string et_etic="";
  string et_multiline_lb="";
  string et_paragraph="";
  if((_punt_mol + string(ETIC_ETIC).size()) < _molecule.size()){
    et_etic=_molecule.substr(_punt_mol,
                             string(ETIC_ETIC).size());

  }

  if((_punt_mol + string(ETIC_MULTILINE_LABEL).size()) < _molecule.size()){
    et_multiline_lb=_molecule.substr(_punt_mol,
                                     string(ETIC_MULTILINE_LABEL).size());
  }

  if((_punt_mol + string(ETIC_PARAGRAPH).size()) < _molecule.size()){
    et_paragraph=_molecule.substr(_punt_mol,
                                  string(ETIC_PARAGRAPH).size());
  }

  etichetta* tmp=0;


  if(et_etic==ETIC_ETIC){
    tmp=new etichetta(p_etichetta());
  }else if(et_multiline_lb==ETIC_MULTILINE_LABEL){
    tmp=new multiline_label(p_multiline_label());
    //dynamic_cast<multiline_label*>(tmp)->dump_label();
  }else  if(et_paragraph==ETIC_PARAGRAPH){
    tmp=new paragraph_text(p_paragraph_text());
  }

  if(tmp!=0){
    _stringhe.push_back(tmp);
    if(!_is_preview){
      aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,_stringhe.size()-1);
    }
    p_stringhe();
  }


}

/*
  PARAGRAPH := "paragraph" APRI POSX SEP POSY SEP INTERLINE 
                   SEP LAYOUT SEP MULTIFONT_LABEL* CHIUDI

 */
paragraph_text immagine::p_paragraph_text(){
  string et_multi=_molecule.substr(_punt_mol,
                                   string(ETIC_PARAGRAPH).size());
  paragraph_text tmp_label;
  
  if(et_multi==ETIC_PARAGRAPH){
    _punt_mol+=string(ETIC_PARAGRAPH).size();
    trova_apri();
    if(_has_error){
      _error.push_back(gen_err_miss_string(string(APRI),
					      _punt_mol,string(APRI).size()));
      return tmp_label;
    }else{
      _punt_mol++;
    
      tmp_label.x(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }
      
      tmp_label.y(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }

      tmp_label.interline_space(trova_campo_etic_int(SEP));
      
      if(_has_error){
        return tmp_label;
      }


      tmp_label.layout_lines(trova_campo_etic_int(SEP));
      
      if(_has_error){
        return tmp_label;
      }


      string et_etic=_molecule.substr(_punt_mol,
                                      string(ETIC_MULTIFONT_LABEL).size());
       
      while(et_etic==ETIC_MULTIFONT_LABEL){
        multifont_label* line=new multifont_label(p_multifont_label());
        line->go_to_end_of_label();
        tmp_label.add_line(line);
        et_etic=_molecule.substr(_punt_mol,
                                 string(ETIC_MULTIFONT_LABEL).size());
      }

      if(_punt_mol< _molecule.size() &&
         string(1,_molecule[_punt_mol])!=CHIUDI){
        _has_error=true;
      }else{
        _punt_mol++;
      }
      tmp_label.go_to_end_of_label();      
      return tmp_label;
 
    }

  }else{
    _has_error=true;
    _error.push_back(gen_err_miss_string(string(ETIC_PARAGRAPH),_punt_mol,
                                         string(ETIC_PARAGRAPH).size()));
    return tmp_label;
  }

}


/*


MULTIFONT_LABEL:= "multifont_label" APRI POSX SEP POSY SEP INTERLINE 
                   SEP ETICHETTA* CHIUDI

 */
multifont_label immagine::p_multifont_label(){


  string et_multi=_molecule.substr(_punt_mol,
                                   string(ETIC_MULTIFONT_LABEL).size());
  multifont_label tmp_label;
  
  if(et_multi==ETIC_MULTIFONT_LABEL){
    _punt_mol+=string(ETIC_MULTIFONT_LABEL).size();
    trova_apri();
    if(_has_error){
      _error.push_back(gen_err_miss_string(string(APRI),
					      _punt_mol,string(APRI).size()));
      return tmp_label;
    }else{
      _punt_mol++;
    
      tmp_label.x(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }
      
      tmp_label.y(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }

      
      tmp_label.interline_space(trova_campo_etic_int(SEP));
      
      if(_has_error){
        return tmp_label;
      }

      string et_etic=_molecule.substr(_punt_mol,
                                      string(ETIC_ETIC).size());
       
      while(et_etic==ETIC_ETIC){
        etichetta* line=new etichetta(p_etichetta());
        line->go_to_end_of_label();
        tmp_label.add_line(line);
        et_etic=_molecule.substr(_punt_mol,
                                 string(ETIC_ETIC).size());
      }

      if(_punt_mol< _molecule.size() &&
         string(1,_molecule[_punt_mol])!=CHIUDI){
        _has_error=true;
      }else{
        _punt_mol++;
      }


      return tmp_label;
 
    }

  }else{
    _has_error=true;
    _error.push_back(gen_err_miss_string(string(ETIC_MULTIFONT_LABEL),_punt_mol,
                                         string(ETIC_MULTIFONT_LABEL).size()));
    return tmp_label;
  }
    
}


multiline_label immagine::p_multiline_label(){
  string et_multi=_molecule.substr(_punt_mol,
                                   string(ETIC_MULTILINE_LABEL).size());
  multiline_label tmp_label;
  
  if(et_multi==ETIC_MULTILINE_LABEL){
    _punt_mol+=string(ETIC_MULTILINE_LABEL).size();
    trova_apri();
    if(_has_error){
      _error.push_back(gen_err_miss_string(string(APRI),
					      _punt_mol,string(APRI).size()));
      return tmp_label;
    }else{
      _punt_mol++;
    
      tmp_label.x(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }
      
      tmp_label.y(trova_campo_etic_float(SEP));
      
      if(_has_error){
        return tmp_label;
      }

      
      tmp_label.interline_space(trova_campo_etic_int(SEP));
      
      if(_has_error){
        return tmp_label;
      }


      tmp_label.layout_lines(trova_campo_etic_int(SEP));
      
      if(_has_error){
        return tmp_label;
      }


      string et_etic=_molecule.substr(_punt_mol,
                                      string(ETIC_ETIC).size());
       
      while(et_etic==ETIC_ETIC){
        etichetta* line=new etichetta(p_etichetta());
        tmp_label.add_line(line);
        et_etic=_molecule.substr(_punt_mol,
                                 string(ETIC_ETIC).size());
      }

      if(_punt_mol< _molecule.size() &&
         string(1,_molecule[_punt_mol])!=CHIUDI){
        _has_error=true;
      }else{
        _punt_mol++;
      }
      
      return tmp_label;
 
    }

  }else{
    _has_error=true;
    _error.push_back(gen_err_miss_string(string(ETIC_MULTILINE_LABEL),_punt_mol,
                                         string(ETIC_MULTILINE_LABEL).size()));
    return tmp_label;
  }
    
}

 float immagine::trova_campo_etic_float(const char* conc){
 string la_cifr;

  while(_punt_mol< _molecule.size() &&
	(isdigit(_molecule[_punt_mol]) ||
	 _molecule[_punt_mol]=='.'     ||
	 _molecule[_punt_mol]=='-'     ||
         _molecule[_punt_mol]=='e'     ||
         _molecule[_punt_mol]=='E'
         )
	){


    la_cifr+=_molecule[_punt_mol];
    _punt_mol++;
  }



  if(_punt_mol< _molecule.size() &&
     string(1,_molecule[_punt_mol])==conc){
    char* tail;
     float num=strtof(la_cifr.c_str(),&tail);
     if(*tail!='\0'){
       _has_error=true;
       gen_err_miss_number(_punt_mol, la_cifr.size());
       return -1;
     }
    _punt_mol++;

    return num;
  }else{
    _has_error=true;
    _error.push_back(gen_err_miss_string(string(conc),_punt_mol,
					 string(conc).size()));
    return -1;
  }


 }



 int immagine::trova_campo_etic_int(const char* conc){
   string la_cifr;

   while(_punt_mol< _molecule.size() &&(
	 isdigit(_molecule[_punt_mol]) ||  _molecule[_punt_mol]=='-' )){
     la_cifr+=_molecule[_punt_mol];
     _punt_mol++;
   }

   if(_punt_mol< _molecule.size() &&
      string(1,_molecule[_punt_mol])==conc){
     char* tail;
     int num=static_cast<int>(strtol(la_cifr.c_str(),&tail,0));
     if(*tail!='\0'){
       _has_error=true;
       gen_err_miss_number(_punt_mol, la_cifr.size());
       return -1;
     }
     _punt_mol++;
     return num;
   }else{
     _has_error=true;
     _error.push_back(gen_err_miss_string(string(conc),
					  _punt_mol,string(conc).size()));
     return -1;
   }

 }


string immagine::check_escape_char(){
  std::string res("");
  if(string(1,_molecule[_punt_mol])==string(ESCAPE_CHAR)){
    _punt_mol++;
    res=string(1,_molecule[_punt_mol]);
  }
  return res;
}

 //VALORE := CHAR? VALORE*  |  APICE VALORE* | APICE PEDICE VALORE*
 //	PEDICE VALORE* | PEDICE APICE VALORE*  | "nada" | "alto"
 // #define ET_STR   0
 // #define ET_APICE 1
 // #define ET_PEDICE 2

 void immagine::p_valore(etichetta& etic){


   if(!(_punt_mol<_molecule.size())){
     _has_error=true;
     _error.push_back(gen_err_eof());
     return;
   }

   if(string(1,_molecule[_punt_mol])==SEP){
     _trovato_pedice=false;
     _trovato_apice=false;
     _punt_mol++;

     return;
   }else if(string(1,_molecule[_punt_mol])==APICE){
     if(!_trovato_apice){
       _trovato_apice=true;
     }else{
       _error.push_back("La stringa contiene due apici contigui.");
       return;
     }



      _punt_mol++;
     if(string(1,_molecule[_punt_mol])!=APRI){
       _has_error=true;
       _error.push_back(gen_err_miss_string(string(APRI),
					     _punt_mol,string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       string tmpstr("");
       while(string(1,_molecule[_punt_mol]) != CHIUDI &&
	     string(1,_molecule[_punt_mol]) != SEP
	     ){
	 string escaped("");
	 if((escaped=check_escape_char())==""){
	   tmpstr+=_molecule[_punt_mol];
	 }else{
	   tmpstr+=escaped;
	 }


	 //	 tmpstr+=_molecule[_punt_mol];
	 _punt_mol++;
       }

       if(string(1,_molecule[_punt_mol])==SEP){
	 _has_error=true;
	 _error.push_back(gen_err_miss_string(string(CHIUDI),
					      _punt_mol,string(CHIUDI).size()));
	 return;
       }else{

	 etic.aggiungi(tmpstr, ET_APICE);


	 _punt_mol++;
	 p_valore(etic);
       }


     }

   }else if(string(1,_molecule[_punt_mol])==PEDICE){
     if(!_trovato_pedice){
       _trovato_pedice=true;
     }else{
       _error.push_back("La stringa contiene due pedici contigui.");
       return;
     }

     _punt_mol++;
     if(string(1,_molecule[_punt_mol])!=APRI){
       _has_error=true;
       _error.push_back(gen_err_miss_string(string(APRI),
					     _punt_mol,string(APRI).size()));
       return;
     }else{
       _punt_mol++;
       string tmpstr;
       while(string(1,_molecule[_punt_mol]) != CHIUDI &&
	     string(1,_molecule[_punt_mol]) != SEP
	     ){
	 string escaped("");
	 if((escaped=check_escape_char())==""){
	   tmpstr+=_molecule[_punt_mol];
	   //cerr << "pedice " << _molecule[_punt_mol] << std::endl;
	 }else{

	   tmpstr+=escaped;
	 }

	 //tmpstr+=_molecule[_punt_mol];
	 _punt_mol++;
       }

       if(string(1,_molecule[_punt_mol])==SEP){
	 _has_error=true;
	 _error.push_back(gen_err_miss_string(string(CHIUDI),
					       _punt_mol,string(CHIUDI).size()));
	 return;
       }else{
	 etic.aggiungi(tmpstr, ET_PEDICE);

	 _punt_mol++;
	 p_valore(etic);
       }


     }

   }else{
     _trovato_pedice=false;
     _trovato_apice=false;
     string tmpstr;
     while(string(1,_molecule[_punt_mol]) != APICE &&
	   string(1,_molecule[_punt_mol]) != PEDICE &&
	   string(1,_molecule[_punt_mol]) != SEP
	   ){
       string escaped="";
       if((escaped=check_escape_char())==""){
	 tmpstr+=_molecule[_punt_mol];
       }else{
	 tmpstr+=escaped;
       }
       _punt_mol++;
     }

     etic.aggiungi(tmpstr, ET_STR);


     p_valore(etic);
   }

 }

 int immagine::p_int(string num){
   char* resto;
   long int risul=strtol(num.c_str(),&resto,0);
   if((*resto)|='\0'){
     _has_error=true;
     return -1;
   }else{
     return static_cast<int>(risul);
   }
 }

 string::size_type immagine::trova_apri(){
   string::size_type apri=_molecule.find(APRI,_punt_mol);
   if(apri==string::npos){
     _has_error=true;
     _error.push_back(gen_err_miss_string(APRI,_punt_mol,string(APRI).size()));
   }
   return apri;

 }


 string::size_type immagine::trova_chiudi(){
   string::size_type apri=_molecule.find(CHIUDI,_punt_mol);
   if(apri==string::npos){
     _has_error=true;
     _error.push_back(gen_err_miss_string(CHIUDI,_punt_mol,string(CHIUDI).size()));
   }
   return apri;

 }

 string::size_type immagine::trova_sep(){
   string::size_type apri=_molecule.find(SEP,_punt_mol);
   if(apri==string::npos){
     _has_error=true;
     _error.push_back(gen_err_miss_string(SEP,_punt_mol,string(SEP).size()));
   }
   return apri;
 }


 string immagine::gen_err_miss_string(string missing, int start, int length){
   ostringstream ostr;
   ostr << _punt_mol;

   string cite;
   int from=_punt_mol-CITE_ERROR_RG;
   int wide=2*CITE_ERROR_RG;

   if(_punt_mol-CITE_ERROR_RG < 0){
     from=0;
   }

   if(_punt_mol + wide > _molecule.size()){
     wide=_molecule.size()-(_punt_mol + wide);
   }

   if(static_cast<unsigned int>(start + length) > _molecule.size()){
     length=_molecule.size()-(_punt_mol + length);
   }

   return _molecule.substr(from,wide)+
     _("***Position: ") + ostr.str() + _(" expected ") + missing +
     _(" found ") + "\"" +_molecule.substr(start,length) + "\"";
 }

   /**
    *Genera  un  messaggio d'errore  dovuto  al prematura  raggiungimento
    *della fine del file.
    */

 string immagine::gen_err_eof(){
   return _("Unexpected end of file.");
 }


 string immagine::gen_err_miss_number(int start, int length){

   ostringstream ostr;
   ostr << _punt_mol;

   string cite;

   int wide=2*CITE_ERROR_RG;

   if(_punt_mol + wide > _molecule.size()){
     wide=_molecule.size()-(_punt_mol + wide);
   }

   if(static_cast<unsigned int>(start + length) > _molecule.size()){
     length=_molecule.size()-(_punt_mol + length);
   }

   return _molecule.substr(start,wide)+
     " In posizione: " + ostr.str() + " era atteso un numero" +
     " trovato: " + "\""+ _molecule.substr(start,length) +"\"";
 }


 string immagine::gen_warn_id_conflict(string elem, int id){
   ostringstream out;
   out << id;
   string warn="L'elemento " + elem + " con id: " + out.str() + " esiste già";
     return warn;
 }


 void immagine::print_warn(){
    string warn;
    for(unsigned int i=0;i<_warning.size();i++){
      warn +=  _warning[i] + "\n";
    }
    if(warn!=""){
      fl_alert("%s",warn.c_str());
    }
  }
  void immagine::print_errors(){
    string errori;
    for(unsigned int i=0;i<_error.size();i++){
      errori+= _error[i] +"\n";
    }
    if(errori!=""){
      fl_alert("%s",errori.c_str());
    }

  }

  void immagine::elimina_err(){
   _error.erase(_error.begin(),_error.end());
  }

void immagine::elimina_warn(){
  _warning.erase(_warning.begin(),_warning.end());
}


void immagine::copy_flip_group(int id_group , bool hor){
  gruppo* group_ptr=find_group_id(id_group);

  if(group_ptr!=NULL){
    gruppo nw(*group_ptr);
    aggiungi_gruppo(nw);
    int id_nw=ritorna_ultimo_gruppo().id();
    flip_group(id_nw,hor);
    if(hor){
      ritorna_ultimo_gruppo().phys_translate(0,ritorna_ultimo_gruppo().phys_h());
    }else{
      ritorna_ultimo_gruppo().phys_translate(ritorna_ultimo_gruppo().phys_w(),0);
    }
  }

}

void immagine::flip_group(int id_group , bool hor){
  gruppo* group_ptr=find_group_id(id_group);

  if(group_ptr!=NULL){

    float h_2=0;
    if(hor){
      h_2=group_ptr->phys_h()/2+group_ptr->phys_posy();
    }else{
      h_2=group_ptr->phys_w()/2+group_ptr->phys_posx();
    }
    
    vector<procedura*>::iterator proc_beg=group_ptr->iniz_procedure();
    vector<procedura*>::iterator proc_end=group_ptr->fin_procedure();
    
    while(proc_beg!=proc_end){
      switch((*proc_beg)->tipo()){
      case PROC_ARROW:
	{
	  procedura* to_flip_p=*proc_beg;
	  proc_arrow* flipped=dynamic_cast<proc_arrow*>(to_flip_p);
	  
	  if(flipped){
	    if(hor){
	      float dy=flipped->phys_posy()-h_2;
	      float dye=flipped->phys_eposy()-h_2;
	      flipped->posy(h_2-dy);
	      flipped->eposy(h_2-dye);
	    }else{
	      float dx=flipped->phys_posx()-h_2;
	      float dxe=flipped->phys_eposx()-h_2;
	      flipped->posx(h_2-dx);
	      flipped->eposx(h_2-dxe);
	    }
	  }
	}
	break;
      

      case PROC_BEZIER:
	{
	  procedura* to_flip_p=*proc_beg;
	  proc_bezier* flipped=dynamic_cast<proc_bezier*>(to_flip_p);
	  
	  if(flipped){
	    if(hor){
	      float diy=flipped->phys_iy()-h_2;
	      float dtan1y=flipped->phys_tan1y()-h_2;
	      float dtan2y=flipped->phys_tan2y()-h_2;
	      float dey=flipped->phys_ey()-h_2;
	      
	      flipped->iy(h_2-diy);
	      flipped->tan1y(h_2-dtan1y);
	      flipped->tan2y(h_2-dtan2y);
	      flipped->ey(h_2-dey);
	    }else{
	      float dix=flipped->phys_ix()-h_2;
	      float dtan1x=flipped->phys_tan1x()-h_2;
	      float dtan2x=flipped->phys_tan2x()-h_2;
	      float dex=flipped->phys_ex()-h_2;
	      
	      flipped->ix(h_2-dix);
	      flipped->tan1x(h_2-dtan1x);
	      flipped->tan2x(h_2-dtan2x);
	      flipped->ex(h_2-dex);
	      
	      
	    }
	  }
	}
	break;
      
      
      case PROC_ARC:
	{
	  procedura* to_flip_p=*proc_beg;
	  proc_arc* flipped=dynamic_cast<proc_arc*>(to_flip_p);
	  
	  if(flipped){
	    if(hor){
	      float dystart=flipped->phys_ystart()-h_2;
	      float dyend=flipped->phys_yend()-h_2;
	      float dy1=flipped->phys_y1()-h_2;
	      float dy2=flipped->phys_y2()-h_2;
	      float dy3=flipped->phys_y3()-h_2;
	      float dy4=flipped->phys_y4()-h_2;
	      
	      flipped->ystart(h_2-dystart);
	      flipped->yend(h_2-dyend);
	      flipped->y1(h_2-dy1);
	      flipped->y2(h_2-dy2);
	      flipped->y3(h_2-dy3);
	      flipped->y4(h_2-dy4);
	      
	    }else{
	      float dxstart=flipped->phys_xstart()-h_2;
	      float dxend=flipped->phys_xend()-h_2;
	      float dx1=flipped->phys_x1()-h_2;
	      float dx2=flipped->phys_x2()-h_2;
	      float dx3=flipped->phys_x3()-h_2;
	      float dx4=flipped->phys_x4()-h_2;
	      
	      flipped->xstart(h_2-dxstart);
	      flipped->xend(h_2-dxend);
	      flipped->x1(h_2-dx1);
	      flipped->x2(h_2-dx2);
	      flipped->x3(h_2-dx3);
	      flipped->x4(h_2-dx4);
	    }
	  }
	}
	break;
	
	
      case PROC_BOX:
	{
	  
	}
	break;
      }	
      proc_beg++;
    }


    vector<atomo>::iterator atm_beg=group_ptr->iniz_atom();
    vector<atomo>::iterator atm_end=group_ptr->fin_atom();
    while(atm_beg!=atm_end){
      if(hor){
	float dy=(*atm_beg).phys_pos_y()-h_2;
	(*atm_beg).pos_y(h_2-dy);
      }else{
	float dx=(*atm_beg).phys_pos_x()-h_2;
	(*atm_beg).pos_x(h_2-dx);
      }
      atm_beg++;
    }
  }
}

void immagine::flip(int x, int y, bool hor){

  elimina_elem_selected();
  elimina_legami_selected();
  click_gruppo(x, y);

  int id_gruppo=(_elem_selected[0].second).first;
  flip_group(id_gruppo,hor);
  
}

void immagine::copy_flip(int x, int y, bool hor){

  elimina_elem_selected();
  elimina_legami_selected();
  click_gruppo(x, y);

  int id_gruppo=(_elem_selected[0].second).first;
  copy_flip_group(id_gruppo,hor);
  
}


bool  immagine::click_gruppo(int x, int y, bool erase_previous){


  if(erase_previous){
    elimina_legami_selected();
    elimina_elem_selected();
  }


  bool res=true;
  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  
  x-=dx_scroll;
  y-=dy_scroll;


  //cliccato atomo aggiungiamo tutti gli atomi  i legami e le procedure
  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fi= _gruppi[i].fin_atom();
    
    while(in!=fi){
      int click=(*in).sotto_mouse(x,y);
      if(click!=-1){
        aggiungi_tutto_selected(_gruppi[i]);
        return res;
      }
      in++;
    }
  }
  
  // cliccata procedura aggiungiamo tutti gli atomi i legami e le procedure
  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator in=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator fi= _gruppi[i].fin_procedure();
    
    while(in!=fi){
      int click=(*in)->sotto_mouse(x,y);
      if(click!=-1){
        aggiungi_tutto_selected(_gruppi[i]);
        return res;
      }
      in++;
    }
    
  }
  

  //cliccato legame? aggiungiamo tutto
  
  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fin=_gruppi[i].fin_atom();
    int gruppoapp=-1;
    if(in!=fin){
      _gruppi[i].generic_depth_search(&(*in), &gruppoapp, &x ,&y,quale_gruppo);
    }
    
    if(gruppoapp!=-1){
      //cout << "gruppoapp" << gruppoapp << endl;
      aggiungi_tutto_selected(_gruppi[i]);
      return res;
    }
    
  }
  
  return !res;
}



  /**
   *\return l'ennesimo gruppo del vettore dei gruppi
   */

gruppo& immagine::ritorna_gruppo(int i){
  return _gruppi[i];
}

gruppo& immagine::ritorna_ultimo_gruppo(){
  unsigned int sz=_gruppi.size();
  return _gruppi[sz-1];
  
}


gruppo* immagine::find_group_id(int id){
  for(unsigned int i=0;i<_gruppi.size();i++){
    if(_gruppi[i].id()==id){
      return &_gruppi[i];
      break;
    }
  }
  return 0;
}



std::vector<gruppo>::iterator immagine::first_gruppo(){
  return _gruppi.begin();
}

std::vector<gruppo>::iterator immagine::end_gruppo(){
  return _gruppi.end();
}



/**
 *\return l'ennesima etichetta del vettore
 */

etichetta* immagine::ritorna_etich(int i){
  return _stringhe[i];
}

etichetta* immagine::ritorna_etich_pointer(int i){
   return _stringhe[i];
}

void immagine::elimina_elem_selected(){
  
  


#ifdef DEBUG
    cout << "============SELEZIONATI ATOMI ELIMINATI=====================" << endl;

    for(unsigned int i=0;i<_elem_selected.size();i++){
      pair <int, int> eleme;
      cout << " tipo: "    << _elem_selected[i].first
	   << " gruppo: " << eleme.first
	   << " id: "     << eleme.second << endl;

    }

    cout << "============ FINE SELEZIONATI ELIMINATI=====================" << endl;
#endif
    _elem_selected.erase(_elem_selected.begin(),
			 _elem_selected.end());
  }

bool immagine::aggiungi_elem_selected(int tipo,int grp,int id){
  //cout << "actual imm " << this << " " << _elem_selected.size() << endl;
  //cout << "aggiungi_elem_selected " << tipo << " " << grp << " "  << id << endl;
  bool no_exists=true;

    /**
   *Contiene  coppie <tipo, < gruppo, id > > selezionati, se  si e'
   *selezionato una etichetta gruppo e' uguale a NO_VALID_GROUP
   */

  //vector< pair < int, pair<int,int> > > _elem_selected;

  //checking if element exists in vector _elem_selected
  
  for(unsigned int i=0;i<_elem_selected.size();i++){
    if(_elem_selected[i].first==tipo &&
       _elem_selected[i].second.first==grp &&
       _elem_selected[i].second.second==id){
      no_exists=false;
      break;
    }
  }


  if(no_exists){
    pair <int,int> el_elem;
    el_elem.first=grp;
    el_elem.second=id;
    pair < int , pair <int,int> > vec_elem;
    vec_elem.first=tipo;
    vec_elem.second=el_elem;
    _elem_selected.push_back(vec_elem);
  }
  return no_exists;
}




void immagine::elimina_legami_selected(){

#ifdef DEBUG
  cout << "============SELEZIONATI LEGAMI ELIMINATI=====================" << endl;

  for(unsigned int i=0;i<_legami_selected.size();i++){
    cout << "gruppo: "    << _legami_selected[i][0]
	 << " atomo: " << _legami_selected[i][1]
	 << " id: "     << _legami_selected[i][2] << endl;
    
  }

  cout << "============ FINE SELEZIONATI ELIMINATI=====================" << endl;
#endif


  for(unsigned int i=0; i<_legami_selected.size();i++){
    delete []  _legami_selected[i];
  }

  _legami_selected.erase(_legami_selected.begin(),_legami_selected.end());
}

void immagine::aggiungi_legami_selected(int gruppo, int id_atomo_app, int id_legame){
  //cout <<"_legami_selected " << _legami_selected.size() << endl;
  int* valori=new int[3];
  valori[0]=gruppo;
  valori[1]=id_atomo_app;
  valori[2]=id_legame;
  _legami_selected.push_back(valori);
}


 void immagine::aggiungi_se_dentro_bb(float x, float y, float w , float h){
    int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

    x-=dx_scroll;
    y-=dy_scroll;

    for(unsigned int i=0;i<_gruppi.size();i++){
      vector<procedura*>::iterator in=_gruppi[i].iniz_procedure();
      vector<procedura*>::iterator fi= _gruppi[i].fin_procedure();

      while(in!=fi){
	bool dentro=(*in)->dentro_bb(x,y,w,h);
	if(dentro){
	  int tipo_proc=-1;

	  if(typeid( *(*in))==typeid(proc_arc)){
	    tipo_proc=PROC_ARC;
	  }else if(typeid( *(*in))==typeid(proc_arrow)){
	    tipo_proc=PROC_ARROW;
	  }else if(typeid( *(*in))==typeid(proc_bezier)){
	    tipo_proc=PROC_BEZIER;
	  }else if(typeid( *(*in))==typeid(BoxProc)){
	    tipo_proc=PROC_BOX;
          }
	  aggiungi_elem_selected(tipo_proc,_gruppi[i].id(),(*in)->id());

	}
	in++;
      }


      vector<atomo>::iterator inatm=_gruppi[i].iniz_atom();
      vector<atomo>::iterator fiatm= _gruppi[i].fin_atom();

      while(inatm!=fiatm){

	bool dentro=(*inatm).dentro_bb(x,y,w,h);
	if(dentro){
	  aggiungi_elem_selected(ATOMO,_gruppi[i].id(),(*inatm).id());
	}
	inatm++;
      }

      inatm=_gruppi[i].iniz_atom();
      fiatm= _gruppi[i].fin_atom();

      int x_y[2]={static_cast<int>(x),static_cast<int>(y)};
      int w_h[2]={static_cast<int>(w),static_cast<int>(h)};

      if(inatm!=fiatm){
	//appartiene_legame_bb(atomo* da , atomo* fino, void* data, void* data2 ,void* data3)
	_gruppi[i].generic_depth_search(&(*inatm), this, x_y ,w_h,appartiene_legame_bb);
      }

   }

   for(unsigned int i=0;i<_stringhe.size();i++){
//      float xcent=_stringhe[i]->x()+((_stringhe[i]->x()+_stringhe[i]->w()-_stringhe[i]->x())/2);
//      float ycent=_stringhe[i]->y()+((_stringhe[i]->y()+_stringhe[i]->h()-_stringhe[i]->y())/2);

//        if(xcent>x && xcent<x+w &&
// 	  ycent>y && ycent<y+h){
// 	 aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,i);
//        }


     bool dentro=_stringhe[i]->dentro_bb(x,y,w,h);

     if(dentro){
       aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,i);
     }

   }

 }



 atomo*  immagine::ritorna_atomo_ident(int gr_id, int atm_id){

   for(unsigned int i=0;i<_gruppi.size();i++){
     if(_gruppi[i].id()==gr_id){
       vector<atomo>::iterator in=_gruppi[i].iniz_atom();
       vector<atomo>::iterator fi= _gruppi[i].fin_atom();
       while(in!=fi){
	 if((*in).id()==atm_id){
	   return &(*in);
	 }
	 in++;
       }
     }
   }

   return 0;
 }


 int immagine::prova_click_atomo(atomo** ris, int x, int y){
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;


   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<atomo>::iterator in=_gruppi[i].iniz_atom();
     vector<atomo>::iterator fi= _gruppi[i].fin_atom();

     while(in!=fi){
       int click=(*in).sotto_mouse(x,y);
       if(click!=-1){
	 //fl_message("Cliccato atomo %d del gruppo %d", click, _gruppi[i].id());
	 *ris=&(*in); ritorna_atomo_ident(_gruppi[i].id(),click);
	 aggiungi_elem_selected(ATOMO,_gruppi[i].id(),click);
	 //cout << ris << endl;
	 return click;
       }
       in++;
     }
   }
   ris=0;
   return -1;
 }




bool immagine::check_exists_in_elem_selected(int x_m,int y_m,bool& exists){

  exists=false;
  bool res=false;
  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  x_m-=dx_scroll;
  y_m-=dy_scroll;

  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fi= _gruppi[i].fin_atom();

    while(in!=fi){
      int click=(*in).sotto_mouse(x_m,y_m);
      if(click!=-1){
	for(unsigned int i=0;i<_elem_selected.size();i++){
	    if(_elem_selected[i].first==ATOMO &&
	       _elem_selected[i].second.first==(*in).id_gruppo() &&
	       _elem_selected[i].second.second==(*in).id()){
	      exists=true;
	      res=true;
	      return res;
	    }else{
	      exists=false;
	      res=false;
	    }
	}
      }
      in++;
      if(res){
	return res;
      }
    }
  }


  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator in=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator fi= _gruppi[i].fin_procedure();

    while(in!=fi){
      int click=(*in)->sotto_mouse(x_m,y_m);
      if(click!=-1){

	for(unsigned int i=0;i<_elem_selected.size();i++){
	    if((_elem_selected[i].first==PROC_ARC || 
		_elem_selected[i].first==PROC_ARROW ||
		_elem_selected[i].first==PROC_BEZIER ||
                _elem_selected[i].first==PROC_BOX 
		)
		&&
	       _elem_selected[i].second.first==(*in)->id_gruppo() &&
	       _elem_selected[i].second.second==(*in)->id()){
	      exists=true;
	      res=true;
	      return res;
	    }else{
	      exists=true;
	      res=false;
	    }
	}
      }
      in++;
      if(res){
	return res;
      }
    
    }

  }


  for (unsigned int i=0;i<_stringhe.size();i++){
    int click=_stringhe[i]->sotto_mouse(x_m,y_m);
    if(click!=-1){
      exists=true;
      res=false;
      for(unsigned int i2=0;i2<_elem_selected.size();i2++){
	if((_elem_selected[i2].second.first)== NO_VALID_GROUP){
	  for(unsigned int i3=0;i3<_stringhe.size();i3++){
	    if(static_cast<int>(i3)==_elem_selected[i2].second.second){
	      res=true;
	      return res;
	    }
	  }
	}
      }
    }

  }




  return res;
  
}


bool immagine::check_selected_group_bond_coincidence(atomo** selected_1, atomo** selected_2,
                                                     atomo** hook_1    , atomo** hook_2){
  *selected_1=NULL;
  *selected_2=NULL;
  *hook_1=NULL;
  *hook_2=NULL;

  bool res=false;

  if(_elem_selected.size()>0 &&
     _elem_selected[0].second.first!=NO_VALID_GROUP &&
     _elem_selected[0].first==ATOMO){

    int id_sel_grp=_elem_selected[0].second.first;
    gruppo* sel=find_group_id(id_sel_grp);
    std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > > results;

    sel->generic_depth_search(sel->find_atomo_id(sel->iniz_atom()->id()), 
                              static_cast<void*>(&results), 
                              NULL, 
                              NULL,
                              glue_find_line_near_sel);


    std::vector<unsigned int> res_v;
    bool found=false;
    unsigned int res_v_pos=0;

    for(unsigned int i=0;i<_gruppi.size();i++){

      if(_gruppi[i].has_atoms()){
	if(_gruppi[i].id()!=sel->id()){
	  if(_gruppi[i].find_atomo_id(_gruppi[i].iniz_atom()->id())!=NULL){
	    _gruppi[i].generic_depth_search(_gruppi[i].find_atomo_id(_gruppi[i].iniz_atom()->id()), 
					    static_cast<void*>(&results),
					    static_cast<void*>(&res_v),
					    static_cast<void*>(&found),
					    glue_find_line_near_hook);
	    if(found){
	      res_v_pos=i;
	      break;
	    }
	  }
	}
      }
    }
    
    if(found){
      std::pair<atomo*,atomo*> atms=results[res_v[0]].first;
      *selected_1=atms.first;
      *selected_2=atms.second;
      
      *hook_1=_gruppi[res_v_pos].find_atomo_id(res_v[1]);
      *hook_2=_gruppi[res_v_pos].find_atomo_id(res_v[2]);
      res=found;
    }
  }
  return res;
}


bool immagine::check_selected_group_atom_coincidence(atomo** selected, atomo** hook){
  
  static float dist_tolerance=5;
  *selected=NULL;
  *hook=NULL;
  bool res=false;
  int id_sel_grp=_elem_selected[0].second.first;
  gruppo* sel=find_group_id(id_sel_grp);

  if(_elem_selected.size()>0 &&
     _elem_selected[0].second.first!=NO_VALID_GROUP &&
     _elem_selected[0].first==ATOMO){

    for(unsigned int i=0;i<_gruppi.size();i++){
      if(_gruppi[i].id()!=sel->id() &&
	 sel->has_atoms()){
        vector<atomo>::iterator beg=_gruppi[i].iniz_atom();
        vector<atomo>::iterator end=_gruppi[i].fin_atom();
        std::pair<bool,int> found(false,-1);
        
        while(beg!=end){
	  sel->generic_depth_search(sel->find_atomo_id(sel->iniz_atom()->id()), 
				      static_cast<void*>(&dist_tolerance), 
				      static_cast<void*>(&(*beg)), 
				      static_cast<void*>(&found), 
				      glue_find_first_near);
	    
	    if(found.first){
	      
	      *selected=sel->find_atomo_id(found.second);
	      *hook=&(*beg);
	      res=true;
	      break;
	    }
	  
	    
          beg++;
        }
      }
    }
    
  }

  return res;
  
}


bool immagine::prova_click(int x, int y , bool& exists, bool erase_previous){
  if(erase_previous){
    elimina_legami_selected();
    elimina_elem_selected();
  }

  exists=false;
  bool res=false;
  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  x-=dx_scroll;
  y-=dy_scroll;

  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fi= _gruppi[i].fin_atom();

    while(in!=fi){
      int click=(*in).sotto_mouse(x,y);
      if(click!=-1){
	//fl_message("Cliccato atomo %d del gruppo %d", click, _gruppi[i].id());
	bool no_exists=aggiungi_elem_selected(ATOMO,_gruppi[i].id(),click);
	exists=!no_exists;
	res=true;
	return res;
      }
      in++;
    }
  }


  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator in=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator fi= _gruppi[i].fin_procedure();

    while(in!=fi){
      int click=(*in)->sotto_mouse(x,y);
      if(click!=-1){
	//fl_message("Cliccato procedura %d del gruppo %d", click, (*in)->id_gruppo());

	int tipo_proc=-1;

	if(typeid( *(*in))==typeid(proc_arc)){
	  tipo_proc=PROC_ARC;
	}else if(typeid( *(*in))==typeid(proc_arrow)){
	  tipo_proc=PROC_ARROW;
	}else if(typeid( *(*in))==typeid(proc_bezier)){
	  tipo_proc=PROC_BEZIER;
	}else if(typeid( *(*in))==typeid(BoxProc)){
	  tipo_proc=PROC_BOX;
        }
	bool no_exists=aggiungi_elem_selected(tipo_proc,_gruppi[i].id(),click);
	exists=!no_exists;
	res=true;
	return res;
      }
      in++;
    }

  }

  for (unsigned int i=0;i<_stringhe.size();i++){
    int click=_stringhe[i]->sotto_mouse(x,y);
    if(click!=-1 && !_stringhe[i]->can_highlight()){
      //fl_message("Cliccata etichetta %d ",i );
      bool no_exists=aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,i);
      exists=!no_exists;
      res=true;
      return res;
    }

  }

  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fin=_gruppi[i].fin_atom();

    if(in!=fin){
      _gruppi[i].generic_depth_search(&(*in), this, &x ,&y,appartiene_legame);
    }
  }


  if(_legami_selected.size()>0){ 
    res=true;
  }

  return res;
}




bool immagine::check_click_bond(int x, int y, bool& exists, bool erase_previous){
  
  if(erase_previous){
    elimina_legami_selected();
    elimina_elem_selected();
  }

  exists=false;
  bool res=false;

  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  x-=dx_scroll;
  y-=dy_scroll;


  for(unsigned int i=0;i<_gruppi.size();i++){
    
    vector<atomo>::iterator in=_gruppi[i].iniz_atom();
    vector<atomo>::iterator fin=_gruppi[i].fin_atom();
    
    if(in!=fin){
      _gruppi[i].generic_depth_search(&(*in), this, &x ,&y,appartiene_legame);
    }
  }
  
  
  if(_legami_selected.size()>0){ 
    res=true;
  }
  
  return res;

}


bool immagine::check_click_etichetta(int x, int y , bool& exists, bool erase_previous){
  if(erase_previous){
    elimina_legami_selected();
    elimina_elem_selected();
  }

  exists=false;
  bool res=false;
  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  x-=dx_scroll;
  y-=dy_scroll;



  for (unsigned int i=0;i<_stringhe.size();i++){
    int click=_stringhe[i]->sotto_mouse(x,y);
    if(click!=-1){
      //fl_message("Cliccata etichetta %d ",i );
      bool no_exists=aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,i);
      exists=!no_exists;
      res=true;
      break;
    }

  }


  return res;
}


bool immagine::check_control_point_procedura_under_mouse(int x_m,int y_m){


  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  x_m-=dx_scroll;
  y_m-=dy_scroll;
  procedura* hitted=0;
  bool found=false;
  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator beg_p=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator end_p=_gruppi[i].fin_procedure();
      while(beg_p!=end_p){
	if((*beg_p)->control_point_under_mouse(x_m,y_m)>=0){
	  hitted=(*beg_p);
	  break;
	}
	beg_p++;
      }

    if(hitted){
      found=true;
      break;
    }
  }


  return found;
}


void immagine::translate_control_points(float dx, float dy){
 for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator beg_p=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator end_p=_gruppi[i].fin_procedure();
    while(beg_p!=end_p){
      (*beg_p)->control_point_transl(dx,dy);
      beg_p++;
    }
  }
}

void immagine::unset_selected_control_points(){
  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<procedura*>::iterator beg_p=_gruppi[i].iniz_procedure();
    vector<procedura*>::iterator end_p=_gruppi[i].fin_procedure();
    while(beg_p!=end_p){
      (*beg_p)->unset_edit_control_point();
      beg_p++;
    }
  }
}

void immagine::cambia_colore_sel_etich(int r, int g, int b){

  for(unsigned int i=0;i<_elem_selected.size();i++){
    pair <int,int> tmp_elem=_elem_selected[i].second;
    int tipo_elem=_elem_selected[i].first;

    for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
      if(tmp_elem.first==_gruppi[ctgrp].id()){
	if(tipo_elem==ATOMO){
	  vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	  vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	  while(in!=fi){
	    if((*in).id()==tmp_elem.second){
	      (*in).etich_ref().cr(r);
	      (*in).etich_ref().cg(g);
	      (*in).etich_ref().cb(b);
	    }
	    in++;
	  }
	}
      }
    }
  }

}

 void immagine::cambia_colore_sel(int r, int g, int b){
   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){
		 (*in).cr(r);
		 (*in).cg(g);
		 (*in).cb(b);
	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){

	       if((*in)->id()==tmp_elem.second){

		 (*in)->cr(r);
		 (*in)->cg(g);
		 (*in)->cb(b);
	       }
	       in++;
	     }
	   }
	 }
       }

     }else{
       _stringhe[tmp_elem.second]->cr(r);
       _stringhe[tmp_elem.second]->cg(g);
       _stringhe[tmp_elem.second]->cb(b);
     }
   }

   //cambiamo_colore ai legami selezionati

   for (unsigned int i=0;i<_legami_selected.size();i++){
     for(unsigned int gct=0;gct<_gruppi.size();gct++){ //cerchiamo tra i gruppi
       if(_gruppi[gct].id()==_legami_selected[i][0]){
	 vector<atomo>::iterator inat=_gruppi[gct].iniz_atom();
	 vector<atomo>::iterator finat=_gruppi[gct].fin_atom();
	 while(inat!=finat){//cerchiamo tra gli atomi
	   if((*inat).id()==_legami_selected[i][1]){
	     vector<legame>::iterator inleg=(*inat).primo_leg();
	     vector<legame>::iterator finleg=(*inat).ultimo_leg();
	     while(inleg!=finleg){//cerchiamo tra i legami
	       if((*inleg).id_legame()==_legami_selected[i][2]){
		 //cout << "(*inleg).id_legame()" << (*inleg).id_legame() << endl;
		 (*inleg).cr(r);
		 (*inleg).cg(g);
		 (*inleg).cb(b);
	       }
	       inleg++;
	     }
	   }
	   inat++;
	 }

       }
     }
   }

 }



 void immagine::phys_translate_selected(int xn, int yn){

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){

		 (*in).phys_translate(xn,yn);
	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){
	       if((*in)->id()==tmp_elem.second){
		 (*in)->phys_translate(xn,yn);
	       }
	       in++;
	     }
	   }
	 }
       }
     }else{

       _stringhe[tmp_elem.second]->phys_translate(xn,yn);
     }
   }
 }



 void immagine::trasla_selected(int xn, int yn){

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){

		 (*in).trasla(xn,yn);
	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){
	       if((*in)->id()==tmp_elem.second){
		 (*in)->trasla(xn,yn);
	       }
	       in++;
	     }
	   }
	 }
       }
     }else{
       //std::cout << "pippo trasla" << std::endl;
       _stringhe[tmp_elem.second]->trasla(xn,yn);
     }
   }
 }

 void immagine::ruota_selected(float angl,int xpivot,int ypivot){

   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   xpivot-=dx_scroll;
   ypivot-=dy_scroll;

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){

		 (*in).ruota(xpivot,ypivot,angl);
	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){
	       if((*in)->id()==tmp_elem.second){
		 (*in)->ruota(xpivot,ypivot,angl);
	       }
	       in++;
	     }
	   }
	 }
       }
     }else{
       cerr << "per ora le stringhe non possono essere ruotate" << endl;
       //_stringhe[tmp_elem.second].ruota(xpivot,ypivot,angl);
     }
   }
 }


void immagine::rotate_selected_3d(bool axis, float angle){

  //costruiamo la  bounding box
  //
  //Eventualmente  mettere in  una  funziona a  parte  che puo'  tornare
  //sempre utile!!!!!


  /*
         (0,0)
	 left_bottom----------+
	           |          |
		   |          |
		   |          |
		   |          |
		   |          |
		   |          |
		   +----------right_top

  */


  matrix<float> right_top(1,2);
  right_top(0,0)=-1E10;
  right_top(0,1)=-1E10;
  matrix<float> left_bottom(1,2);
  left_bottom(0,0)=1E10;
  left_bottom(0,1)=1E10;

  


  for(unsigned int i=0;i<_elem_selected.size();i++){
    pair <int,int> tmp_elem=_elem_selected[i].second;
    int tipo_elem=_elem_selected[i].first;

    if(tmp_elem.first!=NO_VALID_GROUP){

      for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	if(tmp_elem.first==_gruppi[ctgrp].id()){
	  if(tipo_elem==ATOMO){
	    vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	    vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	    while(in!=fi){
	      if((*in).id()==tmp_elem.second){ //trovato
		try{
		
		  if((*in).phys_pos_x()>right_top(0,0)){
		    right_top(0,0)=(*in).phys_pos_x();
		  }
		  
		  if((*in).phys_pos_y()>right_top(0,1)){
		    right_top(0,1)=(*in).phys_pos_y();
		  }

		  
		  if((*in).phys_pos_x()<left_bottom(0,0)){
		    left_bottom(0,0)=(*in).phys_pos_x();
		  }
		  
		  if((*in).phys_pos_y()<left_bottom(0,1)){
		    left_bottom(0,1)=(*in).phys_pos_y();
		  }
		  
		}catch (matrix_error ex){
		  cerr << "exception in " <<  __LINE__ << " "
		       << __FILE__        <<  ex.what() << endl;
		}
		
	      }
	      in++;
	    }
	  }
	}
      }
    }
  }

  //cout << "right_top: " << endl << right_top << endl;

  //cout << "left_bottom :" << endl << left_bottom << endl;



  matrix<float> midpoint(1,2);
  
  midpoint(0,0)= left_bottom(0,0) + ( right_top(0,0) - left_bottom(0,0) ) / 2.0;

  midpoint(0,1)= left_bottom(0,1) + ( right_top(0,1) - left_bottom(0,1) ) / 2.0;

  //cout << "midpoint: " << midpoint << endl;


  /////////////////////////////////


  matrix<float> rotation(3,3);
  try{
    if(axis){//asse x

      rotation(0,0)=1;
      rotation(0,1)=0;
      rotation(0,2)=0;

      rotation(1,0)=0;
      rotation(1,1)=cos(angle);
      rotation(1,2)=sin(angle);

      rotation(2,0)=0;
      rotation(2,1)=-sin(angle);
      rotation(2,2)=cos(angle);

    }else{//asse y
      rotation(0,0)=cos(angle);
      rotation(0,1)=0;
      rotation(0,2)=-sin(angle);

      rotation(1,0)=0;
      rotation(1,1)=1;
      rotation(1,2)=0;

      rotation(2,0)=sin(angle);
      rotation(2,1)=0;
      rotation(2,2)=cos(angle);
    }
  }catch (matrix_error ex){
    cerr << "exception in " <<  __LINE__ << " "
	 << __FILE__        <<  ex.what() << endl;
  }

  //int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  //int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
   /*
   xpivot-=dx_scroll;
   ypivot-=dy_scroll;
   */
   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){
		 try{
		   matrix<float> vec_3(1,3);

		   vec_3(0,0)=(*in).phys_pos_x() - midpoint(0,0);
		   vec_3(0,1)=(*in).phys_pos_y() - midpoint(0,1);
		   vec_3(0,2)=(*in).phys_pos_z(); //hummmmmm....

		   matrix<float> rotated= vec_3 * rotation;
		   (*in).pos_x(rotated(0,0) + midpoint(0,0) );
		   (*in).pos_y(rotated(0,1) + midpoint(0,1) );
		   (*in).pos_z(rotated(0,2));
		 }catch (matrix_error ex){
		   cerr << "exception in " <<  __LINE__ << " "
			<< __FILE__        << " "
			<<  ex.what() << endl;
		 }

	       }
	       in++;
	     }
	   }
	 }
       }
     }
   }
}



 void immagine::scala_selected(float fat){

   //calcoliamo la bounding box degli elementi selezionati
   float min_xbb=1E20;
   float min_ybb=1E20;
   float max_xbb=1E-20;
   float max_ybb=1E-20;
   for(unsigned int i=0;i<_elem_selected.size();i++){

     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){
       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){
		 if((*in).phys_pos_x() < min_xbb){
		   min_xbb=(*in).phys_pos_x();
		 }

		 if((*in).phys_pos_y() < min_ybb){
		   min_ybb=(*in).phys_pos_y();
		 }

		 if((*in).phys_pos_x() > max_xbb){
		   max_xbb=(*in).phys_pos_x();
		 }

		 if((*in).phys_pos_y() > max_ybb){
		   max_ybb=(*in).phys_pos_y();
		 }

	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){
	       if((*in)->id()==tmp_elem.second){
		 if((*in)->posx() < min_xbb){
		   min_xbb=(*in)->phys_posx();
		 }

		 if((*in)->posy() < min_ybb){
		   min_ybb=(*in)->phys_posy();
		 }

		 if((*in)->posx() > max_xbb){
		   max_xbb=(*in)->phys_posx();
		 }

		 if((*in)->posy() > max_ybb){
		   max_ybb=(*in)->phys_posy();
		 }

	       }
	       in++;
	     }
	   }
	 }
       }
     }else{
       if(_stringhe[tmp_elem.second]->x() < min_xbb){
	 min_xbb=_stringhe[tmp_elem.second]->phys_x();
       }
       
       if(_stringhe[tmp_elem.second]->y() < min_ybb){
	 min_ybb=_stringhe[tmp_elem.second]->phys_y();
       }
       
       if(_stringhe[tmp_elem.second]->x() > max_xbb){
	 max_xbb=_stringhe[tmp_elem.second]->phys_x();
       }
       
       if(_stringhe[tmp_elem.second]->y() > max_ybb){
	 max_ybb=_stringhe[tmp_elem.second]->phys_y();
       }
     }

   }

   //trasliamo il sistema di coordinate facendolo cooincidere con il centro della bb

   float w_sc=max_xbb-min_xbb;
   float h_sc=max_ybb-min_ybb;
   float dx_sc=min_xbb+w_sc/2;
   float dy_sc=min_ybb+h_sc/2;

   /*   
   cout << "rrr min_xbb " << min_xbb << " " << "min_ybb " << min_ybb << "max_xbb "
	<< max_xbb << "max_ybb " << max_ybb << "trx " << dx_sc << "try " << dy_sc <<endl;
   */



   phys_translate_selected(static_cast<int>(rintf(-dx_sc)), static_cast<int>(rintf(-dy_sc)));

   //scaliamo

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){

		 (*in).scale(fat);
	       }
	       in++;
	     }
	   }else{
	     vector<procedura*>::iterator in=_gruppi[ctgrp].iniz_procedure();
	     vector<procedura*>::iterator fi= _gruppi[ctgrp].fin_procedure();
	     while(in!=fi){
	       if((*in)->id()==tmp_elem.second){
		 (*in)->scale(fat);
	       }
	       in++;
	     }
	   }
	 }
       }
     }else{
       
       _stringhe[tmp_elem.second]->scale(fat);
       
     }
   }

   //trasliamo il sistema di coordinate facendolo cooincidere con l'origine dell'immagine

   phys_translate_selected(static_cast<int>(rintf(dx_sc)), static_cast<int>(rintf(dy_sc)));

 }


 void immagine::scale_label_of_atom_selected(float fat){

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> tmp_elem=_elem_selected[i].second;
     int tipo_elem=_elem_selected[i].first;

     if(tmp_elem.first!=NO_VALID_GROUP){

       for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
	 if(tmp_elem.first==_gruppi[ctgrp].id()){
	   if(tipo_elem==ATOMO){
	     vector<atomo>::iterator in=_gruppi[ctgrp].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[ctgrp].fin_atom();
	     while(in!=fi){
	       if((*in).id()==tmp_elem.second){
                 //here, scale here!
                 etichetta* et=(*in).etich_punt();
                 et->scale(fat);
	       }
	       in++;
	     }
	   }
	 }
       }
     }
   }
 }



void immagine::shift_type_bond_selected(){
  /*
   *Contiene  triplette: gruppo, atomo di appartenenza e id dei legami selezionati
   */

  if(_legami_selected.size()>0){
    int id_grp=(_legami_selected[0])[0];

    
    gruppo* selgrp=find_group_id(id_grp);

    atomo* atm1=selgrp->find_atomo_id( (_legami_selected[0])[1] );
    legame* b_atm1=atm1->find_leg((_legami_selected[0])[2]);
    atomo* atm2=selgrp->find_atomo_id( b_atm1->id_atomo() );
    legame* b_atm2=NULL;
    
    
    vector<legame>::iterator first=atm2->primo_leg();
    vector<legame>::iterator last=atm2->ultimo_leg();
    
    while(first!=last){
      if((*first).id_atomo()==atm1->id()){
        b_atm2=atm2->find_leg( (*first).id_legame() );
        break;
      }
      first++;
    }
    
    if(b_atm1!=NULL && 
       b_atm2!=NULL){
      bond_type curr=static_cast<bond_type>(b_atm1->tipo_legame());
      
      bond_type nw=shift_bond_type(curr);
      
      b_atm1->tipo_legame(nw);
      b_atm2->tipo_legame(nw);
    }
      
  }
  
}


 bool immagine::cambia_prop_bezier(int x , int y){
   //  cout << "cambia_prop_bezier" << endl;
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<procedura*>::iterator arriniz=_gruppi[i].iniz_procedure();
     vector<procedura*>::iterator arrfin=_gruppi[i].fin_procedure();

     while(arriniz!=arrfin){

       if((*arriniz)->sotto_mouse(x,y)!=-1 &&
	  typeid( *(*arriniz))==typeid(proc_bezier)  ){
	 bezier_win(dynamic_cast<proc_bezier*>(*arriniz));
	 return true;
       }

       arriniz++;
     }

   }

   return false;

 }

 bool immagine::cambia_prop_arc(int x , int y){
   //cout << "cambia_prop_arc" << endl;
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<procedura*>::iterator arriniz=_gruppi[i].iniz_procedure();
     vector<procedura*>::iterator arrfin=_gruppi[i].fin_procedure();

     while(arriniz!=arrfin){

       if((*arriniz)->sotto_mouse(x,y)!=-1 &&
	  typeid( *(*arriniz))==typeid(proc_arc)  ){
	 arc_win(dynamic_cast<proc_arc*>(*arriniz));
	 return true;
       }

       arriniz++;
     }

   }

   return false;

 }


 bool immagine::change_prop_box(int x , int y){
   //cout << "cambia_prop_arc" << endl;
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<procedura*>::iterator arriniz=_gruppi[i].iniz_procedure();
     vector<procedura*>::iterator arrfin=_gruppi[i].fin_procedure();

     while(arriniz!=arrfin){

       if((*arriniz)->sotto_mouse(x,y)!=-1 &&
	  typeid( *(*arriniz))==typeid(BoxProc)  ){
	 box_win(dynamic_cast<BoxProc*>(*arriniz));
	 return true;
       }

       arriniz++;
     }

   }

   return false;

 }


 bool immagine::cambia_prop_frecce(int x , int y){
   //cout << "cambia_prop_frecce" << endl;
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<procedura*>::iterator arriniz=_gruppi[i].iniz_procedure();
     vector<procedura*>::iterator arrfin=_gruppi[i].fin_procedure();

     while(arriniz!=arrfin){

       if((*arriniz)->sotto_mouse(x,y)!=-1 &&
	  typeid( *(*arriniz))==typeid(proc_arrow)  ){
	 arrow_win(dynamic_cast<proc_arrow*>(*arriniz));
	 return true;
       }

       arriniz++;
     }

   }

   return false;
 }




 void immagine::cambia_prop_legami(int x , int y){

   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;


   /**
    *Crea la finetra e ritorna un vettore che contiene nell'ordine:
    * componente r g b del colore el legame e tipo di legame;
    */
   int fatto=0;
   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<atomo>::iterator in=_gruppi[i].iniz_atom();
     vector<atomo>::iterator fin=_gruppi[i].fin_atom();

     if(in!=fin){
       _gruppi[i].generic_depth_search(&(*in), &fatto, &x ,&y,appartiene_legame_prop);
     }
   }
#ifdef DEBUG
   cout << "Dump proveniente da cambia_prop_legami" << endl;
   dump_tmp_atom();
#endif

 }


 bool immagine::cambia_prop_atomo(int x, int y){
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   for(unsigned int i=0;i<_gruppi.size();i++){
     vector<atomo>::iterator atminiz=_gruppi[i].iniz_atom();
     vector<atomo>::iterator atmfin=_gruppi[i].fin_atom();

     while(atminiz!=atmfin){
       if((*atminiz).sotto_mouse(x,y)!=-1){
	 //cout << "ff " <<(*atminiz).id()<<  endl;
	 atom_win(&(*(atminiz)));
	 return true;
	 //break;
       }

       atminiz++;
     }

   }

   return false;

 }

 bool immagine::cambia_prop_etichetta(int x, int y){
   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   x-=dx_scroll;
   y-=dy_scroll;

   bool res=false;

   for(unsigned int i=0;i<_stringhe.size();i++){


       if(_stringhe[i]->sotto_mouse(x,y)!=-1){
	 elimina_legami_selected();
	 elimina_elem_selected();
	 
	 aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,i);

	 highlight_selected();

         if(typeid(*_stringhe[i])==typeid(etichetta)){
           string_prop p(_stringhe[i]);
           
           p.show();
           while(p.shown()){
             Fl::wait();
           }
           
         }else if(typeid(*_stringhe[i])==typeid(multiline_label)){

           multiline_label* mll=dynamic_cast<multiline_label*>(_stringhe[i]);
           if(mll){
             multiline_label_prop p(mll);
           
             p.show();
             while(p.shown()){
               Fl::wait();
             }
             
           }
         }else if(typeid(*_stringhe[i])==typeid(paragraph_text)){
           paragraph_text* mll=dynamic_cast<paragraph_text*>(_stringhe[i]);
           if(mll){
	     
	     elimina_elem_selected();
	     elimina_legami_selected();

             paragraph_text_prop p(mll);
             p.show();
             while(p.shown()){
               Fl::wait();
             }
             
           }
	 }
	 elimina_legami_selected();
	 elimina_elem_selected();

	 res=true;
	 break;
       }
   }

   return res;

 }



 void immagine::aggiungi_tutto_selected(gruppo added){

   //fl_message("added Cliccato gruppo %d", added.id());
   vector<procedura*>::iterator iniz=added.iniz_procedure();
   vector<procedura*>::iterator fin=added.fin_procedure();
   while(iniz!=fin){
     int tipo_proc=-1;

     if(typeid( *(*iniz))==typeid(proc_arc)){
       tipo_proc=PROC_ARC;
     }else if(typeid( *(*iniz))==typeid(proc_arrow)){
       tipo_proc=PROC_ARROW;
     }else if(typeid( *(*iniz))==typeid(proc_bezier)){
       tipo_proc=PROC_BEZIER;
     }else if(typeid( *(*iniz))==typeid(BoxProc)){
       tipo_proc=PROC_BOX;
     }
     aggiungi_elem_selected(tipo_proc,added.id(),(*iniz)->id());
     iniz++;
   }


   vector<atomo>::iterator iniz2=added.iniz_atom();
   vector<atomo>::iterator fin2=added.fin_atom();
   while(iniz2!=fin2){
     aggiungi_elem_selected(ATOMO,added.id(),(*iniz2).id());
     vector<legame>::iterator inizleg=(*iniz2).primo_leg();
     vector<legame>::iterator finleg=(*iniz2).ultimo_leg();

     while(inizleg!=finleg){
       /*
       cout << "AGGIUNTO: " << added.id() << " "
	    << (*inizleg).id_atomo() << " "
	    << (*inizleg).id_legame() << endl;
       */
       aggiungi_legami_selected(added.id(), (*iniz2).id(), (*inizleg).id_legame());
       inizleg++;
     }
     iniz2++;
   }


 }


 void immagine::highlight_selected(){

   int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
   int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

   for(unsigned int i=0;i<_elem_selected.size();i++){
     pair <int,int> grp_id=_elem_selected[i].second;
     switch(_elem_selected[i].first){

     case ETICHETTA:
       {

	 etichetta* etic=_stringhe[grp_id.second];
	 
	 int w=etic->w();
	 int h=etic->h();
	 int x=dx_scroll+static_cast<int>(rintf(etic->x()));
	 int y=dy_scroll+static_cast<int>(rintf(etic->y()));
	 draw_frame(x,y,w,h);
	 break;
       }
     case ATOMO:
       {
	 for(unsigned int i=0;i<_gruppi.size();i++){
	   if(_gruppi[i].id()==grp_id.first){
	     vector<atomo>::iterator in=_gruppi[i].iniz_atom();
	     vector<atomo>::iterator fi= _gruppi[i].fin_atom();
	     while(in!=fi){
	       if((*in).id()==grp_id.second){
		 etichetta etic=(*in).etich();
		 _gruppi[i].allinea_etichetta(etic,(*in));
		 int w=etic.w();
		 int h=etic.h();
		 float x=0;
		 float y=0;

		 //get_bb_etic(etic, x, y);

		 x+=dx_scroll+etic.x();
		 //+static_cast<int>(rintf((*in).pos_x()+etic.x()-w/2));
		 y+=dy_scroll+etic.y();
		 //+static_cast<int>(rintf((*in).pos_y()+etic.y()-h/2));
		 draw_frame(static_cast<int>(rintf(x)),
					 static_cast<int>(rintf(y)),
					 w,h);
	       }
	       in++;
	     }
	   }
	 }
	 break;
       }
     default:

       for(unsigned int i=0;i<_gruppi.size();i++){
	 if(_gruppi[i].id()==grp_id.first){
	   vector<procedura*>::iterator in=_gruppi[i].iniz_procedure();
	   vector<procedura*>::iterator fi= _gruppi[i].fin_procedure();
	   while(in!=fi){
	     if((*in)->id()==grp_id.second){
	       int w=static_cast<int>(rintf((*in)->w()));
	       int h=static_cast<int>(rintf((*in)->h()));
	       int x=dx_scroll+static_cast<int>(rintf((*in)->posx()));
	       int y=dy_scroll+static_cast<int>(rintf((*in)->posy()));
	       draw_frame(x,y,w,h);
	     }
	     in++;
	   }
	 }
       }
     }
   }

  /**
    *Contiene  triplette: gruppo, atomo di appartenenza e id dei legami selezionati
    */

   //  vector<int*> _legami_selected;


   for(unsigned int i=0;i<_legami_selected.size();i++){
     for(unsigned int ctg=0;ctg<_gruppi.size();ctg++){
       if(_legami_selected[i][0]==_gruppi[ctg].id()){
	 vector<atomo>::iterator inatm=_gruppi[ctg].iniz_atom();
	 vector<atomo>::iterator finatm=_gruppi[ctg].fin_atom();
	 while(inatm!=finatm){
	   if(_legami_selected[i][1]==(*inatm).id()){
	     draw_point(static_cast<int>(rintf((*inatm).pos_x()))+dx_scroll,
			     static_cast<int>(rintf((*inatm).pos_y()))+dy_scroll);

	     vector<legame>::iterator inleg=(*inatm).iniz_leg();
	     vector<legame>::iterator finleg=(*inatm).fin_leg();
	     while(inleg!=finleg){
	       if(_legami_selected[i][2]==(*inleg).id_legame()){
		 vector<atomo>::iterator inatm2=_gruppi[ctg].iniz_atom();
		 vector<atomo>::iterator finatm2=_gruppi[ctg].fin_atom();
		 while(inatm2!=finatm2){
		   if((*inleg).id_atomo()==(*inatm2).id()){
		     draw_point(static_cast<int>(rintf((*inatm2).pos_x()))+dx_scroll,
				     static_cast<int>(rintf((*inatm2).pos_y()))+dy_scroll);

		   }
		   inatm2++;
		 }
	       }
	       inleg++;
	     }
	   }
	   inatm++;
	 }
       }
     }
   }


 }


void immagine::delete_etichetta_at(unsigned int i){
  vector<etichetta*>::iterator beg=_stringhe.begin();
  beg+=i;
  delete_etichetta_at(beg);
}


void immagine::delete_etichetta_at(vector<etichetta*>::iterator i){
  vector<etichetta*>::iterator the_end=_stringhe.end();
  if(i<the_end){
    etichetta* to_delete=(*i);
    _stringhe.erase(i);
    delete  to_delete;
  }else{
    string exc="Errore i > _stringhe.end().";
    throw out_of_range(exc);
  }

}

 void immagine::cancella_elementi_selected(){

   //il vettore andrebbe ordinato in senso decrescente secondo il termine
   //((_elem_selected[i]).second).second
   sort(_elem_selected.begin(),_elem_selected.end(),ordina_id_decr_elem_selected);


   for(unsigned int i=0;i<_elem_selected.size();i++){
     switch(_elem_selected[i].first){

     case ATOMO:
      {
	for(unsigned int ctg=0;ctg<_gruppi.size();ctg++){
	  //	  cout <<" @@@ " << _gruppi[i].id() << " "
	  //     << ((_elem_selected[i]).second).first << endl;
	  if(((_elem_selected[i]).second).first==_gruppi[ctg].id()){ //trovato gruppo

	    vector<atomo>::iterator inatom=_gruppi[ctg].iniz_atom();
	    vector<atomo>::iterator finatom=_gruppi[ctg].fin_atom();
	    while(inatom!=finatom){
	      if((*inatom).id()==((_elem_selected[i]).second).second){ //trovato atomo
		vector<legame>::iterator inleg=(*inatom).iniz_leg();
		vector<legame>::iterator finleg=(*inatom).fin_leg();

		while(inleg!=finleg){
		  vector<atomo>::iterator inatom2=_gruppi[ctg].iniz_atom();
		  vector<atomo>::iterator finatom2=_gruppi[ctg].fin_atom();
		  while(inatom2!=finatom2){
		    if((*inleg).id_atomo()==(*inatom2).id()){
		      //trovato  l'atomo  al  quale e'  legato  quello
		      //selezionato; cancellare l'uno e l'altro.
		      (*inatom).elimina_legame((*inatom2).id());
		      (*inatom2).elimina_legame((*inatom).id());
		    }


		    inatom2++;
		  }
		  inleg++;
		}


	      }
	      inatom++;
	    }

	  }
	}

	//adesso  si devono  eliminare  tutti gli  atomi  che non  hanno
	//legami

	for(unsigned int i=0;i<_gruppi.size();i++){
	   vector<atomo>::iterator inatom=_gruppi[i].iniz_atom();
	   vector<atomo>::iterator finatom=_gruppi[i].fin_atom();
	   while(inatom!=finatom){
	     vector<legame>::iterator inleg=(*inatom).iniz_leg();
	     vector<legame>::iterator finleg=(*inatom).fin_leg();
	     if(inleg==finleg){ //atomo senza legami: cancellare
	       _gruppi[i].elimina_atomo((*inatom).id());
	       inatom=_gruppi[i].iniz_atom();
	       finatom=_gruppi[i].fin_atom();
	     }else{
	       inatom++;

	     }
	   }
	}
	/*
	for(int i=0;i<_gruppi.size();i++){
	   vector<atomo>::iterator inatom=_gruppi[i].iniz_atom();
	   vector<atomo>::iterator finatom=_gruppi[i].fin_atom();
	   while(inatom!=finatom){
	     cout << "id_gr " << _gruppi[i].id()
		  << " id_atm" << (*inatom).id() << endl;
	     inatom++;
	   }
	}
	*/

      break;
      }
    case ETICHETTA:
      {

	if(static_cast<unsigned int>(((_elem_selected[i]).second).second)<=_stringhe.size()-1){
	  vector<etichetta*>::iterator instr=_stringhe.begin();
	  instr+=((_elem_selected[i]).second).second;
          delete_etichetta_at(instr);
	}else{
	  cerr << "Attenzione: eliminando l'etichetta "
               << _elem_selected[i].first << " in posizione "
	       << ((_elem_selected[i]).second).second
	       << "> " <<  "_stringhe.size() " << _stringhe.size() <<  endl;
	}
        break;
      }
    case PROC_ARC:
    case PROC_ARROW:
    case PROC_BEZIER:
    case PROC_BOX:
      {
	//cout << ",,, " << ((_elem_selected[i]).second).first << " "
	//     << ((_elem_selected[i]).second).second <<endl;
	for(unsigned int ctproc2=0;ctproc2<_gruppi.size();ctproc2++){

	  if(_gruppi[ctproc2].id_gruppo()==((_elem_selected[i]).second).first){
	    vector<procedura*>::iterator prcin=_gruppi[ctproc2].iniz_procedure();
	    vector<procedura*>::iterator prcfin=_gruppi[ctproc2].fin_procedure();
	    while(prcin!=prcfin){
	      //cout << "(*prcin)->id() "<< flush  << (*prcin)->id() << endl;
	      if((*prcin)->id()==((_elem_selected[i]).second).second){
		//cout << "+++++ " << ((_elem_selected[i]).second).first << " "
		//<< ((_elem_selected[i]).second).second <<endl;
		_gruppi[ctproc2].elimina_proc((*prcin)->id());

		  prcin=_gruppi[ctproc2].iniz_procedure();
		  prcfin=_gruppi[ctproc2].fin_procedure();

	      }else{
		prcin++;
	      }
	    }
	  }

	}


	break;
      }

    }
   }



  //ok abbiamo eliminato atomi  e procedure abbiamo spezzato le molecole
  //formando i gruppi figli e abbiamo eliminato le etichette
  //adesso tocca ai legami


  /**
   *Contiene  triplette: gruppo, atomo di appartenenza e id dei legami selezionati
   */

  /*
  cout << "contenuto vettore" << endl;
  for(int i=0;i<_legami_selected.size();i++){
    cout<< "<>>>>>>>" << endl;
    cout << _legami_selected[i][0] << ","
	 << _legami_selected[i][1] << ","
	 << _legami_selected[i][2] << endl;
  }
  */

  for(unsigned int i=0;i<_legami_selected.size();i++){
    for(unsigned int ctgrp=0;ctgrp<_gruppi.size();ctgrp++){
      if(_legami_selected[i][0]==_gruppi[ctgrp].id_gruppo()){ //trovato gruppo
	vector<atomo>::iterator inatom=_gruppi[ctgrp].iniz_atom();
	vector<atomo>::iterator finatom=_gruppi[ctgrp].fin_atom();
	while(inatom!=finatom){
	  if((*inatom).id()==_legami_selected[i][1]){ //trovato atomo
	    vector<legame>::iterator inleg=(*inatom).iniz_leg();
	    vector<legame>::iterator finleg=(*inatom).fin_leg();

	    while(inleg!=finleg){
	      if((*inleg).id_legame()==_legami_selected[i][2]){ //trovato id_legame
		vector<atomo>::iterator inatom2=_gruppi[ctgrp].iniz_atom();
		vector<atomo>::iterator finatom2=_gruppi[ctgrp].fin_atom();

		while(inatom2!=finatom2){
		  /*
		  cout << "legame di " << (*inatom).id()
		       << "con id " << _legami_selected[i][2]
		       << " porta id atomo: " << (*inleg).id_atomo()
		       << endl;
		  */
		  if((*inleg).id_atomo()==(*inatom2).id()){
		    //trovato  l'atomo  al  quale e'  legato  quello
		    //selezionato; cancellare l'uno e l'altro.
		    //cout << "cancello: " << (*inatom2).id() << " " << (*inatom).id()<< endl;
		    (*inatom).elimina_legame((*inatom2).id());
		    (*inatom2).elimina_legame((*inatom).id());
		    break;
		  }

		  inatom2++;
		}

	      }
	      inleg++;
	    }
	  }
	  inatom++;
	}
      }
    }
  }


  //adesso  si devono  eliminare  tutti gli  atomi  che non  hanno
  //legami

  for(unsigned int i=0;i<_gruppi.size();i++){
    vector<atomo>::iterator inatom=_gruppi[i].iniz_atom();
    vector<atomo>::iterator finatom=_gruppi[i].fin_atom();
    while(inatom!=finatom){
      vector<legame>::iterator inleg=(*inatom).iniz_leg();
      vector<legame>::iterator finleg=(*inatom).fin_leg();
      if(inleg==finleg){ //atomo senza legami: cancellare
	_gruppi[i].elimina_atomo((*inatom).id());
	inatom=_gruppi[i].iniz_atom();
	finatom=_gruppi[i].fin_atom();
      }else{
	inatom++;

      }
    }
  }



  // e poi  si devono  crere altri gruppi  se si sono  spezzate le
  //molecole.
  spezza_gruppo();





  //cout << "?????????????????????????????????????????????????" << endl;
#ifdef DEBUG
  dump_tmp_atom();
#endif

}



void immagine::spezza_gruppo(){
  vector <gruppo>::iterator globgruppoiniz=_gruppi.begin();
  vector <gruppo>::iterator globgruppofin=_gruppi.end();
  while(globgruppoiniz!=globgruppofin){

	  vector < vector <atomo> > matr;
	  vector<atomo>::iterator inatom=(*globgruppoiniz).iniz_atom();
	  vector<atomo>::iterator finatom=(*globgruppoiniz).fin_atom();
	  vector<int> visti;
	  while(inatom!=finatom){
	    stack<atomo*> pila;
	    vector <atomo> molecola;

	    //molecola.push_back(*inatom);
	    pila.push(&(*inatom));

	    while(pila.size()>0){
	      //cout << "size " << pila.size() << endl;
	      atomo* cima=pila.top();
	      pila.pop();
	      //cout << "estratto " << cima->id()<<endl;

	      bool e_visto=false;





	      for(unsigned int i2=0;i2<visti.size();i2++){
		//cout << "visti " << visti[i2] << " cima " << cima->id() ;
		if(visti[i2]==cima->id()){
		  e_visto=true;
		  //cout << " evisto: " << e_visto << endl;
		  break;
		}
		//cout << " evisto: " << e_visto << endl;
	      }

	      /**
	      cout << "\n------------------"<< endl;
	      for(int i3=0;i3<visti.size();i3++){
		cout << visti[i3] << endl;
	      }
	      cout << "==============="<< endl;


	      cout << cima->id() << " " << e_visto<< endl;
	      */
	      //cout << "gruppo: " <<  id() << endl;
	      if(!e_visto){
		molecola.push_back((*cima));
		vector<legame>::iterator primo=cima->primo_leg();
		vector<legame>::iterator ultimo=cima->ultimo_leg();
		//cout << ultimo -primo << " "<< endl;
		while(primo!=ultimo){
		  //cout << cima->id() << " " << (*primo).id_atomo() << endl;
		  vector<atomo>::iterator inatom2=(*globgruppoiniz).iniz_atom();
		  vector<atomo>::iterator finatom2=(*globgruppoiniz).fin_atom();



		  while(inatom2!=finatom2){



		    if((*inatom2).id()==(*primo).id_atomo()){
		      pila.push(&(*inatom2));
		    }
		    inatom2++;
		  }
		  primo++;
		}
		//cout << "--------------" << endl;
	      }

	      visti.push_back(cima->id());

	    }
	    if(molecola.size()>0){
	      matr.push_back(molecola);
	    }
	    inatom++;
	  }

	  //cout << "gruppo: " << (*globgruppoiniz).id()
	  //     <<" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
	  /*
	  for(unsigned int idu=0;idu<matr.size();idu++){
	    for(unsigned int r=0;r<matr[idu].size();r++){
	      cout << matr[idu][r].id() << ",";
	    }
	    cout << "<-" << endl;
	  }

	  cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" << endl;
	  */
	  if(matr.size()>1){

	    gruppo vecchio=(*globgruppoiniz);
	    globgruppoiniz=_gruppi.erase(globgruppoiniz);

	    for(unsigned int matct=0;matct<matr.size();matct++){
	      gruppo tmp;
	      _gruppi.size() > 0 ? tmp.id_gruppo(_gruppi.back().id_gruppo()+1)
	      	: tmp.id_gruppo(10);

	      for(unsigned int atomct=0;atomct<matr[matct].size();atomct++){
		tmp.add_atomo(matr[matct][atomct]);
	      }
	      if(matct==0){
		vector<procedura*>::iterator prcin=vecchio.iniz_procedure();
		vector<procedura*>::iterator prcfin=vecchio.fin_procedure();
		while(prcin!=prcfin){
		  switch(((*prcin))->tipo()){
		  case PROC_ARC:
		    {
		      proc_arc* arc=dynamic_cast<proc_arc*>((*prcin));
		      proc_arc* arcnw=new proc_arc();
		      arcnw->id(  arc->id() );
		      arcnw->posx(arc->posx());
		      arcnw->posy(arc->posy());
		      arcnw->w(arc->w());
		      arcnw->h(arc->h());
		      arcnw->xstart(arc->xstart());
		      arcnw->ystart(arc->ystart());
		      arcnw->xend(arc->xend());
		      arcnw->yend(arc->yend());
		      arcnw->x1(arc->x1());
		      arcnw->y1(arc->y1());
		      arcnw->x2(arc->x2());
		      arcnw->y2(arc->y2());
		      arcnw->x3(arc->x3());
		      arcnw->y3(arc->y3());
		      arcnw->x4(arc->x4());
		      arcnw->y4(arc->y4());


		      arcnw->cb(arc->cb());
		      arcnw->cr(arc->cr());
		      arcnw->cg(arc->cg());
		      arcnw->xpivot(arc->xpivot());
		      arcnw->ypivot(arc->ypivot());
		      arcnw->angolorot(arc->angolorot());
		      arcnw->spessore(arc->spessore());
		      arcnw->dash(arc->dash());
		      tmp.aggiungi_procedura(arcnw);
		      break;
		    }
		  case PROC_ARROW:
		    {

		      proc_arrow* arr=dynamic_cast<proc_arrow*>((*prcin));
		      proc_arrow* arrnw=new proc_arrow();
		      arrnw->id(  arr->id() );
		      arrnw->posx(arr->posx());
		      arrnw->posy(arr->posy());
		      arrnw->eposx(arr->eposx());
		      arrnw->eposy(arr->eposy());
		      arrnw->cb(arr->cb());
		      arrnw->cr(arr->cr());
		      arrnw->cg(arr->cg());
		      arrnw->xpivot(arr->xpivot());
		      arrnw->ypivot(arr->ypivot());
		      arrnw->angolorot(arr->angolorot());
		      arrnw->spessore(arr->spessore());
		      arrnw->dash(arr->dash());
		      arrnw->punte(arr->punte());
		      tmp.aggiungi_procedura(arrnw);
		      break;
		    }


		  case PROC_BEZIER:
		    {

		      proc_bezier* bez=dynamic_cast<proc_bezier*>((*prcin));
		      proc_bezier* beznw= new proc_bezier();
		      beznw->id(  bez->id() );
		      beznw->ix(bez->ix());
		      beznw->iy(bez->iy());
		      beznw->tan1x(bez->tan1x());
		      beznw->tan1y(bez->tan1y());
		      beznw->tan2x(bez->tan2x());
		      beznw->tan2y(bez->tan2y());
		      beznw->ex(bez->ex());
		      beznw->ey(bez->ey());
		      beznw->cb(bez->cb());
		      beznw->cr(bez->cr());
		      beznw->cg(bez->cg());
		      beznw->xpivot(bez->xpivot());
		      beznw->ypivot(bez->ypivot());
		      beznw->angolorot(bez->angolorot());
		      beznw->spessore(bez->spessore());
		      beznw->dash(bez->dash());
		      beznw->punte(bez->punte());
		      tmp.aggiungi_procedura(beznw);
		      break;
		    }

		  case PROC_BOX:
		    {

		      BoxProc* box=dynamic_cast<BoxProc*>((*prcin));
		      BoxProc* boxnw=new BoxProc();
		      boxnw->id(  box->id() );
		      boxnw->ld_x(box->ld_x());
		      boxnw->ld_y(box->ld_y());
		      boxnw->ru_x(box->ru_x());
		      boxnw->ru_y(box->ru_y());
		      boxnw->cb(box->cb());
		      boxnw->cr(box->cr());
		      boxnw->cg(box->cg());
		      boxnw->xpivot(box->xpivot());
		      boxnw->ypivot(box->ypivot());
		      boxnw->angolorot(box->angolorot());
		      boxnw->spessore(box->spessore());
		      boxnw->dash(box->dash());
		      tmp.aggiungi_procedura(boxnw);
		      break;
		    }



		  }

		  prcin++;
		}
	      }
	       _gruppi.push_back(tmp);
	       globgruppoiniz=_gruppi.begin();
	       globgruppofin=_gruppi.end();
	       sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
	    }



	  }else{
	    globgruppoiniz++;
	  }


  }


}



int immagine::create_empty_group(){
  gruppo nuovo;

  int id_nuovo=0;
  if(_gruppi.size()>0){
    id_nuovo=_gruppi.back().id_gruppo()+1;
  }
  nuovo.id_gruppo(id_nuovo);

  nuovo.tipo_gruppo(DEFAULT_TYPE_GROUP);
  _gruppi.push_back(nuovo);
  sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
  return id_nuovo;

}


void immagine::aggiungi_gruppo(gruppo& added){
  if(_gruppi.size()>0){
    sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
    added.id_gruppo((_gruppi.back().id())+1);
    _gruppi.push_back(added);
    sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
  }else{
    added.id_gruppo(0);
    _gruppi.push_back(added);
  }

}

void immagine::remove_gruppo_id(int gid){
  if(_gruppi.size()>0){
    std::vector<gruppo>::iterator b=first_gruppo();
    std::vector<gruppo>::iterator e=end_gruppo();

    while(b!=e){
      if((*b).id()==gid){
	_gruppi.erase(b);
	break;
      }
      b++;
    }

    std::sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
  }

}


void immagine::crea_freccia_nuova(int dax, int day, int ax, int ay){

  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  float arr_w=__pref.get_arr_w();
  float arr_h=__pref.get_arr_h();
  float arr_gap=__pref.get_arr_gap();

  create_empty_group();

  /*
proc_arrow(int id,float posx, float posy,
	     float eposx,float eposy,
	     int cr, int cb, int cg ,
	     float xpiv, float ypiv, float anglrot,
	     int spess, int tratt, int punte)
  */
  proc_arrow* agg=new proc_arrow(0,descale(dax-dx_scroll),
				 descale(day-dy_scroll),
				 descale(ax-dx_scroll),
				 descale(ay-dy_scroll),
				 0,0,0,0,0,0,2,0,ARR_ETEROL_PUNT,
				 arr_w,arr_h,arr_gap);

  agg->aggiungi_genitore(&_gruppi.back());

  _gruppi.back().aggiungi_procedura(agg);


#ifdef DEBUG
  cout << "Dump proveniente da crea_freccia_nuova" << endl;
  dump_tmp_atom();
#endif

}





void immagine::crea_ellisse_nuova(int xc,int yc, int w, int h){
  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  // xc=descale(xc);
  //yc=descale(yc);
  

  create_empty_group();

  /*

proc_arc::proc_arc(int id, 
         float xst, float yst,
	 float xen, float yen,
	 float x1, float y1,
	 float x2, float y2,
	 float x3, float y3,
	 float x4, float y4,
	 int cr, int cb, int cg ,
	 float xpiv, float ypiv, float anglrot,
	 int spess, int tratt)

  */
  proc_arc* agg=new proc_arc(0,
			     descale(xc-dx_scroll), descale(yc+h/2-dy_scroll),
			     descale(xc+w-dx_scroll), descale(yc+h/2-dy_scroll),
			     descale(xc-dx_scroll), descale(yc-dy_scroll),
			     descale(xc+w-dx_scroll),descale(yc-dy_scroll),
			     descale(xc-dx_scroll),descale(yc+h-dy_scroll),
			     descale(xc+w-dx_scroll), descale(yc+h-dy_scroll),
			     0, 0, 0 ,
			     0, 0, 0,
			     1, 0);
  
  agg->aggiungi_genitore(&_gruppi.back());
  _gruppi.back().aggiungi_procedura(agg);


#ifdef DEBUG
  cout << "Dump proveniente da crea_ellisse_nuova" << endl;
  dump_tmp_atom();
#endif



}


void immagine::crea_bezier_nuova(vector< pair<float,float> > punti){

  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  float arr_w=__pref.get_arr_w();
  float arr_h=__pref.get_arr_h();
  float arr_gap=__pref.get_arr_gap();

  create_empty_group();

  proc_bezier* agg=new proc_bezier(0,
				   descale(punti[0].first-dx_scroll),
				   descale(punti[0].second-dy_scroll),
				   descale(punti[1].first-dx_scroll),
				   descale(punti[1].second-dy_scroll),
				   descale(punti[2].first-dx_scroll),
				   descale(punti[2].second-dy_scroll),
				   descale(punti[3].first-dx_scroll),
				   descale(punti[3].second-dy_scroll),
				   0,0,0,0,0,0,1,0,ARR_NO_PUNT,
				   arr_w,arr_h,arr_gap);

  agg->aggiungi_genitore(&_gruppi.back());
  _gruppi.back().aggiungi_procedura(agg);


}


void immagine::create_new_box(int ld_x, int ld_y, int ru_x, int ru_y){

  int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
  int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

  create_empty_group();

  /*
BoxProc::BoxProc(int id,float ld_x, float ld_y,
                 float ru_x, float ru_y,
                 int cr, int cb, int cg ,
                 float xpiv, float ypiv, float anglrot,
                 int thick, int dash, box_type type){
  */


  BoxProc* agg=new BoxProc(0,descale(ld_x-dx_scroll),
                           descale(ld_y-dy_scroll),
                           descale(ru_x-dx_scroll),
                           descale(ru_y-dy_scroll),
                           0,0,0,
                           0,0,0,
                           2,0,NORMAL);

  agg->aggiungi_genitore(&_gruppi.back());

  _gruppi.back().aggiungi_procedura(agg);



}




atomo* immagine::crea_legame_nuovo(float x1,float y1,float x2, float y2, int tipo){
  create_empty_group();
  try{
    _gruppi.back().genera_seme(x1, y1, x2, y2,tipo);

#ifdef DEBUG
  cout << "Dump proveniente da crea_legame_nuovo" << endl;
  dump_tmp_atom();
#endif

  return &(*((_gruppi.back()).fin_atom()-1));


  }catch (range_error e){
    cerr << e.what() << endl;
    return 0;
  }


}


atomo* immagine::crea_legame_nuovo(atomo* gen, float x, float y, int tipo){
  int gruppogen=gen->id_gruppo();
  int genid=gen->id();
  atomo nuovo;
  nuovo.pos_x(descale(x));
  nuovo.pos_y(descale(y));

  //id e' diverso da posizione nel vettore
  int gruppogen_pos=-1;
  for(unsigned int i=0;i<_gruppi.size();i++){
    if(_gruppi[i].id()==gruppogen){
      gruppogen_pos=i;
      break;
    }
  }
  //cout << "gruppogen_pos " << gruppogen_pos << "gruppogen "<< gruppogen<<endl;
  nuovo.aggiungi_genitore(&_gruppi[gruppogen_pos]);
  nuovo.etich_punt()->aggiungi(NO_ETIC, ET_STR);
  nuovo.aggiungi_legame(gen->id(),tipo,0,0,0);
  nuovo.costruisci_arrivati();


  _gruppi[gruppogen_pos].add_atomo_id(nuovo);

  //il puntatore a gen non e' piu' valido da questo punto!
  atomo* nuovogen=ritorna_atomo_ident(gruppogen, genid);

  if(tipo==LEGAME_INTERNO || tipo== LEGAME_ESTERNO ||
     tipo==LEGAME_INTERNO_OPP || tipo==LEGAME_ESTERNO_OPP){
    tipo=-tipo;
  }


  nuovogen->aggiungi_legame((*(_gruppi[gruppogen_pos].fin_atom()-1)).id() ,tipo,0,0,0);
  nuovogen->costruisci_arrivati();

#ifdef DEBUG
  cout << "Dump proveniente da crea_legame_nuovo(atomo*, float x, float y, int tipo)" << endl;
  dump_tmp_atom();
#endif

  return &(*(_gruppi[gruppogen_pos].fin_atom()-1));

}


void immagine::crea_legame_nuovo(atomo* st, atomo* arr, int tipo){
  if(st->id_gruppo()==arr->id_gruppo()){
    st->aggiungi_legame(arr->id(),tipo,0,0,0);
    st->costruisci_arrivati();

    if(tipo==LEGAME_INTERNO || tipo== LEGAME_ESTERNO ||
       tipo==LEGAME_INTERNO_OPP || tipo==LEGAME_ESTERNO_OPP){
      tipo=-tipo;
    }

    arr->aggiungi_legame(st->id(),tipo,0,0,0);
    arr->costruisci_arrivati();
    //cout << "crea_legame_nuovo  non funzia!!!" << endl;
  }else{
    //cout << "cerco di legare " << st->id() << " " << arr->id() << endl;
    //cout << "crea_legame_nuovo FUNZICA" << endl;
    //fare il join di due gruppi diversi
    int id_atom_arr_bk=arr->id();
    int id_gruppo_st_bk=st->id_gruppo();
    int id_atom_st_bk=st->id();
    int pos_gruppo_st=0;
    int id_nuovo_arr=arr->id();;

    for(unsigned int i=0;i<_gruppi.size();i++){
      if(_gruppi[i].id()==st->id_gruppo()){
	pos_gruppo_st=i;
	break;
      }
    }

    //cout << "st " << st->id_gruppo() << " " << "arr " << arr->id_gruppo() << endl;

    int pos_gruppo_arr=0;
    for(unsigned int i=0;i<_gruppi.size();i++){

      if(_gruppi[i].id()==arr->id_gruppo()){
	pos_gruppo_arr=i;
	break;
      }
    }
    //id del piu' grande degli id del gruppo cui st appartiene
    int id_st_max=(*(_gruppi[pos_gruppo_st].fin_atom()-1)).id();

    //cerchiamo se nel gruppo di arr esiste id_st_max
    bool exist_in_arr=false;

    vector<atomo>::iterator inatm=_gruppi[pos_gruppo_arr].iniz_atom();
    vector<atomo>::iterator finatm=_gruppi[pos_gruppo_arr].fin_atom();

    while(inatm!=finatm){
      if((*inatm).id()==id_st_max){
	exist_in_arr=true;
	//cout << "esiste " << (*inatm).id() << endl;
	/*
	if(id_atom_arr_bk!=(*inatm).id()){
	  id_nuovo_arr=arr->id();
	  cout << "non qua?" << endl;
	}
	*/
	break;
      }
      inatm++;
    }





    //cout << "id_nuovo_arr " << id_nuovo_arr << endl;

    if(exist_in_arr){

      /*
      vector<atomo>::iterator inatm=_gruppi[pos_gruppo_arr].iniz_atom();
      vector<atomo>::iterator finatm=_gruppi[pos_gruppo_arr].fin_atom();

      while(inatm!=finatm){
	if((*inatm).id()==id_st_max){
	  (*inatm).id(-1);
	}


	vector<legame>::iterator inleg=(*inatm).iniz_leg();
	vector<legame>::iterator finleg=(*inatm).fin_leg();

	while(inleg!=finleg){
	  if((*inleg).id_atomo()==id_st_max){
	    (*inleg).id_atomo(-1);
	  }

	  inleg++;
	}

	inatm++;
      }
      */
    }else{
      if(id_nuovo_arr==-1){
       id_nuovo_arr=id_atom_arr_bk;
      }
    }

    id_st_max++;

    //cout << "id_st_max++=="<< id_st_max << endl;



    int id_legato=_gruppi[pos_gruppo_arr].rimappa_da(id_st_max,id_nuovo_arr);


    /*
    cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;
    dump_tmp_atom();
    cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl;

    cout << "id_legato " << id_legato << endl;
    */

    vector<atomo>::iterator inatm2=_gruppi[pos_gruppo_arr].iniz_atom();
    vector<atomo>::iterator finatm2=_gruppi[pos_gruppo_arr].fin_atom();

    while(inatm2!=finatm2){
      /*
      cout << "ppp aggiungi genitore " << &_gruppi[pos_gruppo_st] << " "
	   << pos_gruppo_st << " id " << _gruppi[pos_gruppo_st].id_gruppo() <<endl;
      */
      (*inatm2).aggiungi_genitore(&_gruppi[pos_gruppo_st]);
      _gruppi[pos_gruppo_st].add_atomo((*inatm2));
      inatm2++;
    }



    //ricopiare anche le procedure!

    vector<procedura*>::iterator inproc=_gruppi[pos_gruppo_arr].iniz_procedure();
    vector<procedura*>::iterator finproc=_gruppi[pos_gruppo_arr].fin_procedure();

    while(inproc!=finproc){
      _gruppi[pos_gruppo_st].aggiungi_procedura((*inproc));
      inproc++;
    }

    /////////////////////////////////////

    //cout << "st->id_gruppo() " << st->id_gruppo() << endl;
    vector<gruppo>::iterator ctgin=_gruppi.begin()+pos_gruppo_arr;
    _gruppi.erase(ctgin);



    //st non e' piu' valido


    for(unsigned int i=0;i<_gruppi.size();i++){
      //cout << "ii" << i << endl;

      if(_gruppi[i].id()==id_gruppo_st_bk){
	//cout << "esce " << endl;
	pos_gruppo_st=i;
	break;
      }

    }
    /*
    cout << "££££££££££££££" << endl;

    cout << "PPPPP " <<  pos_gruppo_st << endl; // << " " << pos_gruppo_arr <<  endl;

    vector<atomo>::iterator inatm4=_gruppi[pos_gruppo_st].iniz_atom();
    vector<atomo>::iterator finatm4=_gruppi[pos_gruppo_st].fin_atom();

    cout << "dddddd " << finatm4 - inatm4 << endl;


    while(inatm4!=finatm4){
      cout << "ii " <<  (*inatm4).id() << endl;
      inatm4++;
    }
    */


    vector<atomo>::iterator inatm4=_gruppi[pos_gruppo_st].iniz_atom();
    vector<atomo>::iterator finatm4=_gruppi[pos_gruppo_st].fin_atom();

    atomo* nuovoarr=0;
    atomo* nuovost=0;
    while(inatm4!=finatm4){
      //cout << "oo" << (*inatm4).id() << endl;
      if((*inatm4).id()==id_legato){
    	nuovoarr=&(*inatm4);
      }

      if((*inatm4).id()==id_atom_st_bk){
	nuovost=&(*inatm4);
      }
      inatm4++;
    }

    //cout << "iiiii " << nuovoarr  << endl;

    //cout << nuovost->id_gruppo() << "==" << nuovoarr->id_gruppo() << endl;




    crea_legame_nuovo(nuovost, nuovoarr, tipo);


    vector<atomo>::iterator inatm3=_gruppi[pos_gruppo_st].iniz_atom();
    vector<atomo>::iterator finatm3=_gruppi[pos_gruppo_st].fin_atom();

    while(inatm3!=finatm3){
      (*inatm3).costruisci_arrivati();
      inatm3++;
    }

  }


  sort(_gruppi.begin(),_gruppi.end(),ordina_gruppo_id);
#ifdef DEBUG
  cout << "Dump proveniente da crea_legame_nuovo(atomo* st, atomo* arr,int tipo)" << endl;
  dump_tmp_atom();
#endif

}



void immagine::w_immagine(string path){

  ofstream file_o(path.c_str());

  if(!file_o){
    fl_alert("Errore: il file %s non puo' essere scritto.",path.c_str());
  }else{
    for(unsigned int i=0;i<_gruppi.size();i++){
      w_gruppo(i,file_o);
    }
  }

  for(unsigned int i=0;i<_stringhe.size();i++){
    w_etichetta(_stringhe[i],file_o);
    file_o << std::endl;
  }

  file_o << std::endl;
  file_o.close();
}

void immagine::w_gruppo(int pos,ofstream& out){
  /*
GRUPPO   := "gruppo" ID_GRUPPO ":" "tipo_gruppo" TIPO_GRUPPO
                                APRI
			                ROT*
					ATOMO*
					PROCEDURA*
				CHIUDI
  */

  /*
    ROT :=  APRI
		XPIVOT	SEP
		YPIVOT 	SEP
		ANGOLOROT
	CHIUDI
  */

  gruppo scriv=_gruppi[pos];

  out << ETIC_GRUPPO << " " << scriv.id() << " " << DP << " "
      << ETIC_TIPO_GRUPPO << " "  << scriv.tipo_gruppo() << APRI << endl
      << "\t" << ETIC_ROT << " " << APRI << scriv.xpivot() << SEP << scriv.xpivot() << SEP
      << scriv.angolorot() << CHIUDI << endl;

  vector<atomo>::iterator inatm=scriv.iniz_atom();
  vector<atomo>::iterator finatm=scriv.fin_atom();

  while(inatm!=finatm){
    w_atomo(*inatm,out);
    inatm++;
  }

  vector<procedura*>::iterator inproc=scriv.iniz_procedure();
  vector<procedura*>::iterator finproc=scriv.fin_procedure();


  while(inproc!=finproc){
    out << "\t";
    switch((*inproc)->tipo()){
    case PROC_ARC:
      /*
	PROCEDURA := 'ARC' APRI
			ID_PROC SEP XSTART SEP YSTART SEP XEND SEP YEND
			SEP X1  SEP Y1 SEP X2 SEP X2 SEP X3 SEP Y3 SEP X4 SEP Y4
			SEP  COLORE SEP COLORE SEP COLORE SEP XPIVOT SEP
			YPIVOT SEP ANGOLOROT SEP SPESSORE SEP DASH
		   CHIUDI |
      */
      {
	proc_arc* arc=dynamic_cast<proc_arc*>(*inproc);
        arc->write_native_format(out,"\t");
	break;
      }
    case PROC_ARROW:
      /*
	'ARROW' APRI
			ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP NUMPUNTE
		   CHIUDI |
       */
      {
	proc_arrow* arrow=dynamic_cast<proc_arrow*>(*inproc);
        arrow->write_native_format(out,"\t");
	break;
      }
    case PROC_BEZIER:
         /*

	     'BEZIER' APRI
			ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
			SEP POSX SEP POSY SEP POSX SEP POSY
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP NUMPUNTE
		      CHIUDI
	 */
      {
	proc_bezier* bez=dynamic_cast<proc_bezier*>(*inproc);
        bez->write_native_format(out,"\t");
	break;
      }

    case PROC_BOX:
      {
        BoxProc* boxp=dynamic_cast<BoxProc*>(*inproc);
        boxp->write_native_format(out,"\t");
      }
      break;
    }

    inproc++;
  }

  //scrivere le procedure

  out << CHIUDI << endl;

}


void immagine::w_atomo(atomo& atm,ofstream& out){
  /*
   "atomo" ID_ATOMO ":" "tipo_atomo" TIPO_ATOMO APRI
	    "elemento" APRI
			    ETICHETTA SEP CARICHE
			    SEP POS_CARICHE
			    SEP DOPPIETTI SEP EL_SPAIATI
			    SEP MASSA
			    SEP COLORE SEP COLORE SEP COLORE
			    SEP POSX SEP POSY
		       CHIUDI

		    LISTA_DI_ADIACENZA
		CHIUDI

  */

  out << "\t";

  out << ETIC_ATOMO << " " << atm.id() << " " << DP << " " << ETIC_TIPO_ATOMO << " "
       << atm.tipo_atomo() << APRI << endl;

  out << "\t\t";
  out << ETIC_ELEMENTO << " " << APRI << endl;

  etichetta sy=atm.etich();
  out << "\t\t\t";
  w_etichetta(sy,out);

  out << SEP << atm.cariche() << SEP << atm.position_charge() << SEP << atm.doppietti() 
      << SEP << atm.el_spaiati()  << SEP << atm.massa()   << SEP << atm.cr() 
      << SEP << atm.cg() << SEP << atm.cb() << SEP << atm.phys_pos_x() 
      << SEP << atm.phys_pos_y() << endl;



  out << "\t\t" << CHIUDI << endl;

  /*
LISTA_DI_ADIACENZA :=  "lista" APRI
			       ( "legame" APRI
				      		ID_ATOMO
						SEP ID_LEGAME
						SEP TIPO_LEGAME
						SEP COLORE
						SEP COLORE
						SEP COLORE
			         	  CHIUDI
			       )?
			       CHIUDI
  */


  out << "\t\t" << ETIC_LISTA << " " << APRI << endl;

  vector<legame>::iterator leginiz=atm.primo_leg();
  vector<legame>::iterator legfin=atm.ultimo_leg();

  while(leginiz!=legfin){
    out << "\t\t\t" << ETIC_LEGAME << APRI
	<< (*leginiz).id_atomo() << SEP << (*leginiz).id_legame() << SEP
	<< (*leginiz).tipo_legame() << SEP << (*leginiz).cr()
	<< SEP << (*leginiz).cg() << SEP << (*leginiz).cb() << CHIUDI;
    out << endl;
    leginiz++;
  }

  out << "\t\t" << CHIUDI << endl;


  out << "\t"   << CHIUDI << endl;
}


void immagine::w_etichetta(etichetta& sy,ofstream& out){
  /*
            "etichetta" APRI
	                        VALORE SEP FONT SEP DIMENSIONE_FONT
				SEP POSX SEP POSY SEP CR SEP CG SEP CG
				SEP ALLINEAMENTO SEP VALIGN
			CHIUDI
  */


  out << ETIC_ETIC << " " << APRI;


  vector < pair<string,int> > coppie=sy.vec_str();

  for(unsigned int i=0;i<coppie.size();i++){
    /*
      #define ET_STR   0
      #define ET_APICE 1
      #define ET_PEDICE 2
    */
    if(coppie[i].second==ET_STR){
      out << add_slash_to_escape(coppie[i].first);
    }else if(coppie[i].second==ET_APICE){
      out << APICE << APRI << add_slash_to_escape(coppie[i].first) << CHIUDI;
    }else{
      out << PEDICE << APRI << add_slash_to_escape(coppie[i].first) << CHIUDI;
    }
  }
  out << SEP << sy.font() << SEP << sy.phys_dim() << SEP << sy.phys_x() << SEP << sy.phys_y()
      << SEP << sy.cr() << SEP << sy.cg() << SEP << sy.cb() 
      << SEP << sy.allineamento() << SEP << sy.v_offset()
      << CHIUDI;

}



void immagine::w_etichetta(etichetta* sy,ofstream& out){
  /*
            "etichetta" APRI
	                        VALORE SEP FONT SEP DIMENSIONE_FONT
				SEP POSX SEP POSY SEP CR SEP CG SEP CG
				SEP ALLINEAMENTO SEP VALIGN
			CHIUDI
  */


  if(typeid(*sy)==typeid(etichetta)){

    out << ETIC_ETIC << " " << APRI;


    vector < pair<string,int> > coppie=sy->vec_str();

    for(unsigned int i=0;i<coppie.size();i++){
      /*
        #define ET_STR   0
        #define ET_APICE 1
        #define ET_PEDICE 2
      */
      if(coppie[i].second==ET_STR){
        out << add_slash_to_escape(coppie[i].first);
      }else if(coppie[i].second==ET_APICE){
        out << APICE << APRI << add_slash_to_escape(coppie[i].first) << CHIUDI;
      }else{
        out << PEDICE << APRI << add_slash_to_escape(coppie[i].first) << CHIUDI;
      }
    }
    out << SEP << sy->font() << SEP << sy->phys_dim() << SEP 
        << sy->phys_x() << SEP << sy->phys_y()
        << SEP << sy->cr() << SEP << sy->cg() << SEP << sy->cb() 
        << SEP << sy->allineamento() << SEP << sy->v_offset()
        << CHIUDI;
  }else if(typeid(*sy)==typeid(multiline_label)){
    w_multiline_label(dynamic_cast<multiline_label*>(sy),out);
  }else if(typeid(*sy)==typeid(paragraph_text)){
    w_paragraph_text(dynamic_cast<paragraph_text*>(sy),out);
  }
}

/*


PARAGRAPH := "paragraph" APRI POSX SEP POSY SEP INTERLINE 
                   SEP LAYOUT SEP MULTIFONT_LABEL* CHIUDI
*/

void immagine::w_paragraph_text(paragraph_text* sy,ofstream& out){
  std::vector<multifont_label*> lines=sy->get_lines_text();

  out << ETIC_PARAGRAPH << APRI << std::endl;
  
  out << sy->phys_x() << SEP << sy->phys_y() << SEP 
      << static_cast<int>(rintf(sy->phys_interline_space())) << SEP 
      << sy->layout_lines() << SEP << std::endl;

  for(unsigned i=0;i<lines.size();i++){
    out << " ";
    w_multifont_label(lines[i],out);
    out << std::endl;
  }

  out << CHIUDI << std::endl;
  
}

/*
MULTIFONT_LABEL:= "multifont_label" APRI POSX SEP POSY SEP INTERLINE 
                   SEP ETICHETTA* CHIUDI
*/

void immagine::w_multifont_label(multifont_label* sy,ofstream& out){

  std::vector<etichetta*> lines=sy->get_lines_text();

  out << ETIC_MULTIFONT_LABEL << APRI << std::endl;
  
  out << sy->phys_x() << SEP << sy->phys_y() << SEP 
      << static_cast<int>(rintf(sy->phys_interline_space())) <<  SEP << std::endl;

  for(unsigned i=0;i<lines.size();i++){
    out << " ";
    w_etichetta(lines[i],out);
    out << std::endl;
  }

  out << CHIUDI << std::endl;


}

void immagine::w_multiline_label(multiline_label* sy,ofstream& out){
  std::vector<etichetta*> lines=sy->get_lines_text();

  out << ETIC_MULTILINE_LABEL << APRI << std::endl;
  
  out << sy->phys_x() << SEP << sy->phys_y() << SEP 
      << static_cast<int>(rintf(sy->phys_interline_space())) << SEP 
      << sy->layout_lines() << SEP << std::endl;

  for(unsigned i=0;i<lines.size();i++){
    out << " ";
    w_etichetta(lines[i],out);
    out << std::endl;
  }

  out << CHIUDI << std::endl;

}

string immagine::add_slash_to_escape(string to_escape){
  const static string escape_chars=string(APRI)+string(CHIUDI)
    +string(SEP)+string(DP)
    +string(" ");
  //std::cerr << "cerco..." << "\"" << escape_chars << "\"" << std::endl;
  string::size_type globpos=0;

  while(globpos < to_escape.size()){
    string::size_type add_slash=to_escape.find_first_of(escape_chars,globpos);
    if(add_slash!=string::npos){
      //std::cerr << "add slash pos: " << add_slash  << "val: " << to_escape.at(add_slash) << std::endl;
      to_escape.insert(add_slash,string(ESCAPE_CHAR));
      globpos=add_slash+2;
    }else{
      break;
    }
  }

  return to_escape;
}

etichetta* immagine::ritorna_punt_etich(int at){
  return _stringhe[at];
}


void immagine::aggiungi_etich(etichetta nuova){
  etichetta* tmp=new etichetta(nuova);
  _stringhe.push_back(tmp);
}

void immagine::aggiungi_etich(etichetta* n){
  _stringhe.push_back(n);
}


void immagine::add_etich(etichetta n){
  etichetta* tmp=new etichetta(n);
  _stringhe.push_back(tmp);
}



void immagine::add_etich(etichetta* n){
  _stringhe.push_back(n);
}


int immagine::size_etich_vector(){
  return _stringhe.size();

}

int immagine::size_gruppi_vector(){
  return _gruppi.size();
}

int immagine::numero_etichetta(){
  return _stringhe.size();

}


unsigned int immagine::elem_selected_size(){
  return _elem_selected.size();
}


void immagine::create_progressw(){
  /**
      Fl_Window*   _export_progressw;
  Fl_Progress* _export_progressw_bar;
  */
  _export_progressw=new Fl_Window(410,60,_("Exporting..."));
  _export_progressw->set_modal();
  _export_progressw_bar=new Fl_Progress(5,5,400,50);
  _export_progressw_bar->minimum(0);
  _export_progressw_bar->maximum(1);
  _export_progressw->add(_export_progressw_bar);
  _export_progressw->end();
  //export_progressw->show();
}


void immagine::clean_molecule_from_nullchars(){

  string::size_type globpos=0;

  while(globpos < _molecule.size()){
    string::size_type canc=_molecule.find_first_of(NULL_CHAR,globpos);
    if(canc!=string::npos){
      char esc=' ';
      try{
	esc=_molecule.at(canc-1);
	if(string(1,esc)!=string(ESCAPE_CHAR)){
	  globpos=canc;
	  _molecule.erase(globpos,1);
	}else{
	  globpos+=2;
	}
	
      }catch (out_of_range e){
	
	std::cerr << " exception " << e.what() << "carattere: " 
		  <<_molecule[ globpos] << std::endl;
	globpos=canc;
	_molecule.erase(globpos,1);
	
      }
    }else{
      
      break;
    }
  }
  


}




/***********************************************************************************/




int appartiene_legame_prop(atomo* da , atomo* fino, void* data, void* data2 ,void* data3){
  int* x_m=static_cast<int*>(data2);
  int* y_m=static_cast<int*>(data3);
  int* fatto=static_cast<int*>(data);
  int sensleg=__pref.get_sensib_leg();

  if(*fatto) return -1;

  /*
  cout << "calcolo: " << da->id() << " " << fino->id() << " " << da->pos_x() << " " << da->pos_y()
       << " " << fino->pos_x() << " " << fino->pos_y() <<"  " << *x_m << " " << *y_m ;
  */

  if(line_belongs(*x_m, *y_m,
		      static_cast<int>(rintf(da->pos_x())),
		      static_cast<int>(rintf(da->pos_y())),
		      static_cast<int>(rintf(fino->pos_x())),
		      static_cast<int>(rintf(fino->pos_y())),
		      sensleg)){



    int x_a=static_cast<int>(da->pos_x()<=fino->pos_x() ? da->pos_x() : fino->pos_x());
    int y_a=static_cast<int>(da->pos_y()<=fino->pos_y() ? da->pos_y() : fino->pos_y());
    int x_max=static_cast<int>(da->pos_x()>=fino->pos_x() ? da->pos_x() : fino->pos_x());
    int y_max=static_cast<int>(da->pos_y()>=fino->pos_y() ? da->pos_y() : fino->pos_y());


    //cout << (*y_m >= y_a) << " " << (*y_m <= y_max) << endl;

    if((*x_m >= x_a && *x_m <= x_max)  ||
       (*y_m >= y_a && *y_m <= y_max) ){


      std::vector<float> propert;

      std::vector<legame>::iterator in=da->primo_leg();
      std::vector<legame>::iterator fin=da->ultimo_leg();

      int tipoprec=-100;
      while(in!=fin){
	if((*in).id_atomo()==fino->id()){
	  propert=bond_win(in->tipo_legame());

	  if(propert[0]!=-1){
	    in->cr(static_cast<int>(propert[0]));
	    in->cg(static_cast<int>(propert[1]));
	    in->cb(static_cast<int>(propert[2]));
	  }

	  if(propert[3]!=-1){
	    in->tipo_legame(static_cast<int>(propert[3]));

	  }
	  tipoprec=in->tipo_legame();
	  break;
	}
	in++;
      }




      vector<legame>::iterator in2=fino->primo_leg();
      vector<legame>::iterator fin2=fino->ultimo_leg();
      while(in2!=fin2){


	if((*in2).id_atomo()==da->id()){
	  if(propert[0]!=-1){
	    in2->cr(static_cast<int>(propert[0]));
	    in2->cg(static_cast<int>(propert[1]));
	    in2->cb(static_cast<int>(propert[2]));
	  }



	  if(propert[3]!=-1){
	    if(tipoprec==LEGAME_INTERNO ||
	       tipoprec==LEGAME_INTERNO_OPP ||
	       tipoprec==LEGAME_ESTERNO     ||
	       tipoprec==LEGAME_ESTERNO_OPP){
	      in2->tipo_legame(-tipoprec);
	    }else{
	      in2->tipo_legame(static_cast<int>(propert[3]));
	    }
	  }
	  *fatto=1;
	  break;
	}
	in2++;
      }

      //now scaling
      double scaling_value=propert[4];
      if(!similar_to(scaling_value,1.,0.01)){
	float displx=fino->pos_x() - da->pos_x();
	float disply=fino->pos_y() - da->pos_y();

	float dx=-displx + displx * scaling_value;
	float dy=-disply + disply * scaling_value;

	gruppo* the_group=dynamic_cast<gruppo*>(da->ritorna_genitore());

	trasl_subgroup_as_subtree(the_group, da, fino, dx, dy);

      }
      
    }
  }
  
  return 0;
}



int appartiene_legame(atomo* da , atomo* fino, void* data, void* data2 ,void* data3){
  int* x_m=static_cast<int*>(data2);
  int* y_m=static_cast<int*>(data3);
  immagine* evet=static_cast<immagine*>(data);
  int sensleg=__pref.get_sensib_leg();

  if(line_belongs(*x_m, *y_m,
		      static_cast<int>(rintf(da->pos_x())),
		      static_cast<int>(rintf(da->pos_y())),
		      static_cast<int>(rintf(fino->pos_x())),
		      static_cast<int>(rintf(fino->pos_y())),
		      sensleg)){

    gruppo* par=dynamic_cast<gruppo*>(da->ritorna_genitore());

    float x_lu=da->pos_x();
    float y_lu=da->pos_y();

    etichetta lb_da=da->etich();
    par->allinea_etichetta(lb_da,*da);


    if(true || (lb_da.vec_str())[0].first!=string(NO_ETIC)){
      par->clip_leg(lb_da.x(), lb_da.y(), lb_da.w(), lb_da.h(),
                    *da , *fino, x_lu, y_lu);
    }

    float x_rb=fino->pos_x();
    float y_rb=fino->pos_y();

    etichetta lb_fino=fino->etich();
    par->allinea_etichetta(lb_fino,*fino);


    if(true || (lb_fino.vec_str())[0].first!=string(NO_ETIC)){
      par->clip_leg(lb_fino.x(), lb_fino.y(), lb_fino.w(), lb_fino.h(),
                    *fino , *da, x_rb, y_rb);
    }



    x_lu=static_cast<int>(x_lu<x_rb ? x_lu : x_rb);
    y_lu=static_cast<int>(y_lu>y_rb ? y_lu : y_rb);
    x_rb=static_cast<int>(x_lu>x_rb ? x_lu : x_rb);
    y_rb=static_cast<int>(y_lu<y_rb ? y_lu : y_rb);

    float m;
    float q;

    bool par_y=rett_eqn(x_lu, y_lu, 
                        x_rb, y_rb, 
                        m,     q);
    int more_sens_x=0;
    int more_sens_y=0;
    
    if(!par_y){
      more_sens_x=__pref.get_sensib_leg();
    }else if(similar_to<float>(y_lu,y_lu,1)){
      more_sens_y=__pref.get_sensib_leg();
    }

    if((*x_m >= static_cast<int>(x_lu - more_sens_x ) && *x_m <= static_cast<int>(x_rb +  more_sens_x ))  &&
       (*y_m <= static_cast<int>(y_lu + more_sens_y ) && *y_m >= static_cast<int>(y_rb -  more_sens_y)) ){

      vector<legame>::iterator in=da->primo_leg();
      vector<legame>::iterator fin=da->ultimo_leg();


      while(in!=fin){
	if((*in).id_atomo()==fino->id()){
	  evet->aggiungi_legami_selected(da->id_gruppo(),da->id(),(*in).id_legame());
	  break;
	}
	in++;
      }



      //int* valori2=new int[3];
      vector<legame>::iterator in2=fino->primo_leg();
      vector<legame>::iterator fin2=fino->ultimo_leg();
      while(in2!=fin2){
	if((*in2).id_atomo()==da->id()){
	  //cout << "@#@#" << da->id() << " " << (*in2).id_atomo()<<endl;
	  evet->aggiungi_legami_selected(fino->id_gruppo(),fino->id(),(*in2).id_legame());
	  break;
	}
	in2++;
      }
    }
  }

  return 0;
}




int appartiene_legame_bb(atomo* da , atomo* fino, void* data, void* data2 ,void* data3){
  int* x_m=static_cast<int*>(data2); //x,y
  int* y_m=static_cast<int*>(data3); //w,h
  immagine* evet=static_cast<immagine*>(data);

  int xcent=static_cast<int>(da->pos_x()+((fino->pos_x()-da->pos_x())/2));
  int ycent=static_cast<int>(da->pos_y()+((fino->pos_y()-da->pos_y())/2));


  if(xcent>x_m[0] && xcent<x_m[0]+y_m[0] &&
     ycent>x_m[1] && ycent<x_m[1]+y_m[1]){
    vector<legame>::iterator in=da->primo_leg();
    vector<legame>::iterator fin=da->ultimo_leg();

    //	cout << "@#@#" << da->id() << " " << (*in).id_legame()<<endl;

    while(in!=fin){
      if((*in).id_atomo()==fino->id()){
	evet->aggiungi_legami_selected(da->id_gruppo(),da->id(),(*in).id_legame());
	break;
      }
      in++;
    }
  }
  return 0;
}




int quale_gruppo(atomo* da , atomo* fino, void* data, void* data2 ,void* data3){
  int* x_m=static_cast<int*>(data2);
  int* y_m=static_cast<int*>(data3);
  int* gruppo=static_cast<int*>(data);

  if( line_belongs(*x_m, *y_m,
		       da->pos_x(), da->pos_y(),
		       fino->pos_x(), fino->pos_y(),
		       5)){

    *gruppo=da->id_gruppo();
  }
  return 0;
}




void trasl_subgroup_as_subtree(gruppo* the_group, atomo* root, atomo* start, float dx, float dy){
  stack<atomo*> the_stack;
  vector<int> seen;
  the_stack.push(start);
	
  while(the_stack.size()>0){
    atomo* upper=the_stack.top();
    the_stack.pop();
    if(root->id()!=upper->id()){
      bool e_visto=false;
	    
      for(unsigned int i=0;i<seen.size();i++){
	if(seen[i]==upper->id()){
	  e_visto=true;
	  break;
	}
      }
	    
      if(!e_visto){
	upper->trasla(dx,dy);
	vector<legame>::iterator primo=upper->primo_leg();
	vector<legame>::iterator ultimo=upper->ultimo_leg();
	while(primo!=ultimo){
	  the_stack.push((the_group->find_atomo_id((*primo).id_atomo())));
	  primo++;
	}
	
      }
      seen.push_back(upper->id());
    }
  }
  
}


int glue_find_first_near(atomo* from , atomo* to,
                         void* dist, void* atom_other, void* res){
  float*  tol_dist=static_cast<float*>(dist);
  atomo* check_atom=static_cast<atomo*>(atom_other);
  std::pair<bool,int>*  results=static_cast<std::pair<bool,int>*>(res);

  std::pair<float,float> a(from->pos_x(),from->pos_y());
  std::pair<float,float> b(check_atom->pos_x(),check_atom->pos_y());

  std::pair<float,float> dff= bidimensional_vector::diff(a,b);
  float magnitude=bidimensional_vector::magn(dff);

  if(magnitude < *tol_dist){
    results->first=true;
    results->second=from->id();
  }
  return 1;
}


/**
 *\param res_sel_ std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >
 */

int glue_find_line_near_sel(atomo* from , atomo* to,
                            void* res, void* d, void* d1){
  
  float m=0;
  float q=0;

  std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >* results=
    static_cast<std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >*>(res);

  bool eqn_res=rett_eqn(from->pos_x(), from->pos_y(), 
                        to->pos_x(), to->pos_y(), 
                        m, q);
  
  if(!eqn_res){
    q=from->pos_x();
    m=INFINITY;
  }

  std::pair<atomo*,atomo*> atm(from,to);
  std::pair<float,float> mq(m,q); 
  
  std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > r(atm,mq);

  results->push_back(r);

  return 1;
}


/**
 *\param res_sel_ std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >
 *\param res std::vector<unsigned int> where res_sel[res[0]] are pointers to atom in selected group for bond
 * and res[1] , res[2] are id of atoms in the other group
 */

int glue_find_line_near_hook(atomo* from , atomo* to,
                             void* res_sel, void* res, void* found){
  float m=0;
  float q=0;
  bool* is_found=static_cast<bool*>(found);

  if(!(*is_found)){

    std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >* sel=
      static_cast<std::vector< std::pair< std::pair<atomo*,atomo*>, std::pair<float,float> > >*>(res_sel);
    
    std::vector<unsigned int>* res_v=static_cast<vector<unsigned int>*>(res);

    for(unsigned int i=0;i<sel->size();i++){
      bool eqn_res=rett_eqn(from->pos_x(), from->pos_y(), 
                            to->pos_x(), to->pos_y(), 
                            m, q);
    
      if(!eqn_res){
        q=from->pos_x();
        m=INFINITY;
      }


      
      std::pair<float,float> sel_mq=(*sel)[i].second;
      float sel_m=sel_mq.first;
      float sel_q=sel_mq.second;
      atomo* selected_1=(*sel)[i].first.first;
      atomo* selected_2=(*sel)[i].first.second;


      std::pair<float, float> sel1_v(selected_1->pos_x(),selected_1->pos_y());
      std::pair<float, float> sel2_v(selected_2->pos_x(),selected_2->pos_y());

      if(similar_to<float>(m,sel_m,10)){
	if(similar_to<float>(q,sel_q,1) &&
	   similar_to<float>((from)->pos_y(),(to)->pos_y(),1)){
	  if(((selected_1)->pos_x() >= std::min((from)->pos_x(),(to)->pos_x()) &&
	      (selected_1)->pos_x() <= std::max((from)->pos_x(),(to)->pos_x())) || 
	     ((selected_2)->pos_x() >= std::min((from)->pos_x(),(to)->pos_x()) &&
	      (selected_2)->pos_x() <= std::max((from)->pos_x(),(to)->pos_x()))){
	    
	    res_v->push_back(i);
	    res_v->push_back(from->id());
	    res_v->push_back(to->id());
	    *is_found=true;
	    break;
	  }
	}else if(similar_to<float>(q,sel_q,1) &&
		 similar_to<float>((from)->pos_x(),(to)->pos_x(),1)){
	  if(((selected_1)->pos_y() >= std::min((from)->pos_y(),(to)->pos_y()) &&
	      (selected_1)->pos_y() <= std::max((from)->pos_y(),(to)->pos_y())) || 
	     ((selected_2)->pos_y() >= std::min((from)->pos_y(),(to)->pos_y()) &&
	      (selected_2)->pos_y() <= std::max((from)->pos_y(),(to)->pos_y()))){
	    
	      
	    res_v->push_back(i);
	    res_v->push_back(from->id());
	    res_v->push_back(to->id());
	    *is_found=true;
	    break;
	  }
	}else if(similar_to<float>(q,sel_q,100)){
	  if(((selected_1)->pos_x() <= std::max((from)->pos_x(),(to)->pos_x()) &&
	      (selected_1)->pos_x() >= std::min((from)->pos_x(),(to)->pos_x()) &&
	      (selected_1)->pos_y() <= std::max((from)->pos_y(),(to)->pos_y()) &&
	      (selected_1)->pos_y() >= std::min((from)->pos_y(),(to)->pos_y())) ||
	     ((selected_2)->pos_x() <= std::max((from)->pos_x(),(to)->pos_x()) &&
	      (selected_2)->pos_x() >= std::min((from)->pos_x(),(to)->pos_x()) &&
	      (selected_2)->pos_y() <= std::max((from)->pos_y(),(to)->pos_y()) &&
	      (selected_2)->pos_y() >= std::min((from)->pos_y(),(to)->pos_y()))){
	    
	  
	    res_v->push_back(i);
	    res_v->push_back(from->id());
	    res_v->push_back(to->id());
	    *is_found=true;
	    break;
	  }
	}
      }
    }
  }
  return 1;
}



void export_image_to_vector_file(immagine imm,std::string output_file, bool graphics){
  int can_write=1;
  struct stat dummy;
  
  int res_stat=stat(output_file.c_str(),&dummy);

  if(res_stat==0){
    can_write=0; 
    if(graphics){
      can_write=ask_overwrite_file(output_file);
    }else{
      can_write=ask_overwrite_file_console(output_file);
    }
  }else if(errno==ENOENT){
    can_write=1;
  }else{
    if(graphics){
      fl_message("%s",strerror(errno));
    }else{
      perror(NULL);
    }
  }


  
  if(can_write){
    string filename=output_file;
    string format=filename.substr(filename.rfind(".")+1);
    
    if(format_supported(format)){
      if(format==EXPORT_FORMAT_PS){
        export_image_to_EPS_file_cairo(imm,output_file);
      }else if(format==EXPORT_FORMAT_SVG){
        export_image_to_SVG_file_cairo(imm,output_file);
      }else if(format==EXPORT_FORMAT_PNG){
        export_image_to_PNG_file_cairo(imm,output_file);
      }
    }else{
      export_image_to_EPS_file_cairo(imm,output_file);
    }
    
  }
  

}


void export_image_to_EPS_file_cairo(immagine imm,std::string output_file){
  std::vector<float> x;
  std::vector<float> y;

  x.push_back(0);
  y.push_back(0);


  for(int i=0;i<imm.size_gruppi_vector();i++){
    gruppo grp=imm.ritorna_gruppo(i);
    x.push_back(grp.phys_posx()+grp.phys_w());
    y.push_back(grp.phys_posy()+grp.phys_h());
    grp.arrows_points(x,y);
    
  }

  for(int cts=0;cts<imm.size_etich_vector();cts++){
    etichetta* et=imm.ritorna_etich_pointer(cts);
    x.push_back(et->phys_x()+et->phys_w());
    y.push_back(et->phys_y()+et->phys_h());
  }

  pair<float,float> ld;
  pair<float,float> ru;

  calc_bb_gen(x,y,ld,ru);

  float wb=ru.first-ld.first + __pref.get_width_single_bond() * 2;
  float hb=ru.second-ld.second + __pref.get_width_single_bond() * 2;

  //std::cerr << wb << " " << hb << std::endl;
  
  cairo_surface_t *surface=cairo_ps_surface_create(output_file.c_str(),wb,hb);

  setlocale (LC_ALL, "C");  
  cairo_ps_surface_set_eps(surface,TRUE);

  cairo_t* cr=cairo_t_singleton::get_context(surface);
  
  cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
  cairo_set_line_width (cr, __pref.get_width_single_bond());
  cairo_move_to(cr,0,0);
  
  cairo_translate(cr,
                  __pref.get_width_single_bond(),
                  __pref.get_width_single_bond());
  imm.disegna();

  
  cairo_stroke(cr);
  cairo_show_page(cr);
  cairo_surface_destroy(surface);
  cairo_t_singleton::destroy();

  setlocale (LC_ALL, "");

}


void export_image_to_SVG_file_cairo(immagine imm,std::string output_file){

  std::vector<float> x;
  std::vector<float> y;

  //x.push_back(0);
  //y.push_back(0);


  for(int i=0;i<imm.size_gruppi_vector();i++){
    gruppo grp=imm.ritorna_gruppo(i);
    if(grp.iniz_atom()!=grp.fin_atom() ||
       grp.iniz_procedure()!=grp.fin_procedure()){
      x.push_back(grp.phys_posx());
      y.push_back(grp.phys_posy());
      x.push_back(grp.phys_posx()+grp.phys_w());
      y.push_back(grp.phys_posy()+grp.phys_h());
      grp.arrows_points(x,y);
    }
    
  }


  for(int cts=0;cts<imm.size_etich_vector();cts++){
    etichetta* et=imm.ritorna_etich_pointer(cts);
    x.push_back(et->phys_x());
    y.push_back(et->phys_y());
    x.push_back(et->phys_x()+et->phys_w());
    y.push_back(et->phys_y()+et->phys_h());
  }


  pair<float,float> ld;
  pair<float,float> ru;

  calc_bb_gen(x,y,ld,ru);


  float wb=ru.first-ld.first + __pref.get_width_single_bond()*2;
  float hb=ru.second-ld.second + __pref.get_width_single_bond()*2;

  std::cerr << wb << " " << hb << std::endl;
  
  cairo_surface_t *surface=cairo_svg_surface_create(output_file.c_str(),wb,hb);
  
  setlocale (LC_ALL, "C");  

  cairo_t* cr=cairo_t_singleton::get_context(surface);
  
  cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
  cairo_set_line_width (cr, __pref.get_width_single_bond());
  cairo_move_to(cr,0,0);


  cairo_translate(cr,
                  -ld.first+__pref.get_width_single_bond(),
                  -ld.second+__pref.get_width_single_bond());  
  cairo_save(cr); 
  imm.disegna();
  
  cairo_stroke(cr);
  cairo_show_page(cr);
  cairo_surface_destroy(surface);
  cairo_t_singleton::destroy();

  setlocale (LC_ALL, "");

}

void export_image_to_PNG_file_cairo(immagine imm,std::string output_file){

  std::vector<float> x;
  std::vector<float> y;

  x.push_back(0);
  y.push_back(0);

  for(int i=0;i<imm.size_gruppi_vector();i++){
    gruppo grp=imm.ritorna_gruppo(i);
    if(grp.iniz_atom()!=grp.fin_atom() ||
       grp.iniz_procedure()!=grp.fin_procedure()){
      x.push_back(grp.phys_posx()+grp.phys_w());
      y.push_back(grp.phys_posy()+grp.phys_h());
      grp.arrows_points(x,y);
    }
    
  }


  for(int cts=0;cts<imm.size_etich_vector();cts++){
    etichetta* et=imm.ritorna_etich_pointer(cts);
    x.push_back(et->phys_x()+et->phys_w());
    y.push_back(et->phys_y()+et->phys_h());
  }


  pair<float,float> ld;
  pair<float,float> ru;

  calc_bb_gen(x,y,ld,ru);

  float wb=ru.first-ld.first+ __pref.get_width_single_bond()*2;
  float hb=ru.second-ld.second + __pref.get_width_single_bond()*2;

  cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                                        wb,
                                                        hb);

  x.erase(x.begin(),x.end());
  y.erase(y.begin(),y.end());

  for(int i=0;i<imm.size_gruppi_vector();i++){
    gruppo grp=imm.ritorna_gruppo(i);
    if(grp.iniz_atom()!=grp.fin_atom() ||
       grp.iniz_procedure()!=grp.fin_procedure()){
      x.push_back(grp.phys_posx());
      y.push_back(grp.phys_posy());
      x.push_back(grp.phys_posx()+grp.phys_w());
      y.push_back(grp.phys_posy()+grp.phys_h());
      grp.arrows_points(x,y);
    }

  }

  for(int cts=0;cts<imm.size_etich_vector();cts++){
    etichetta* et=imm.ritorna_etich_pointer(cts);
    x.push_back(et->phys_x());
    y.push_back(et->phys_y());
    x.push_back(et->phys_x()+et->phys_w());
    y.push_back(et->phys_y()+et->phys_h());
  }


  pair<float,float> ld_min;
  pair<float,float> ru_min;


  calc_bb_gen(x,y,ld_min,ru_min);
  float wb_min=ru_min.first-ld_min.first + __pref.get_width_single_bond()*2;
  float hb_min=ru_min.second-ld_min.second +  __pref.get_width_single_bond()*2;

  cairo_t* cr=cairo_t_singleton::get_context(surface);

  cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
  cairo_set_line_width (cr, __pref.get_width_single_bond());
  cairo_move_to(cr,0,0);


  cairo_translate(cr,
                  __pref.get_width_single_bond(),
                  __pref.get_width_single_bond());  
  cairo_save(cr); 
  imm.disegna();
  
  cairo_show_page(cr);

  cairo_surface_t* surfacedest = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                                            wb_min + RAGGIO_EL *2,
                                                            hb_min + RAGGIO_EL *2);
  cairo_t* context_dest=cairo_create(surfacedest);

  cairo_set_source_surface (context_dest, surface, RAGGIO_EL-ld_min.first, RAGGIO_EL-ld_min.second);
  cairo_rectangle (context_dest,RAGGIO_EL,RAGGIO_EL, wb,  hb);
  cairo_set_operator (context_dest, CAIRO_OPERATOR_SOURCE);
  cairo_fill (context_dest);
  cairo_stroke(context_dest);
  cairo_show_page(context_dest);


  cairo_surface_write_to_png(surfacedest,
                             output_file.c_str());


  cairo_surface_destroy(surface);
  cairo_t_singleton::destroy();

  cairo_surface_destroy(surfacedest);
  cairo_destroy(context_dest);

}


void immagine::aabb_elem_selected(pair<float,float>& ld,
                                  pair<float,float>& ru){
  
  std::vector<float> x;
  std::vector<float> y;

   for(unsigned int i=0;i<_elem_selected.size();i++){
     switch(_elem_selected[i].first){

     case ATOMO:
      {
        gruppo* grp=find_group_id((_elem_selected[i].second).first);
        atomo* start=grp->find_atomo_id((_elem_selected[i].second).second);
        x.push_back(start->pos_x());
        y.push_back(start->pos_y());
      }
      break;
     case ETICHETTA:
       {
         etichetta* laet=ritorna_etich_pointer((_elem_selected[i].second).second);
         x.push_back(laet->x());
         y.push_back(laet->y());
       }
       break;
     case PROC_ARC:
     case PROC_ARROW:
     case PROC_BEZIER:
     case PROC_BOX:
       {
          gruppo* the_grp=find_group_id((_elem_selected[i].second).first);
	  procedura* proc=the_grp->find_proc_id((_elem_selected[i].second).second);
          x.push_back(proc->posx());
          y.push_back(proc->posy());
       }
       break;
       
     }
   }
   calc_bb_gen(x, y, ld, ru);
}
