/*

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

    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/>.
*/

/*
 * Application implements MVC model.
 * editor class represents a model.
 * functions like 'editor_window_cb' represents controller.
 * FLTK is a view.
 * All functionality must be added into the editor class.
 * Global functions are used to verify input data from user
 * and call appropriate editor's method.
 * Friends functions are not allowed. If existing functionality
 * doesn't satisfy your needs just add necessary methods into 
 * editor class. Then call this method inside existing global
 * functions. If you need to create a new callback just create
 * new global function and call all necessary methods inside of it. 
 */

#include <global.hpp>
#include <config.h>
#include <config_path.h>
#include <stddef.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <dirent.h>
#include <dlfcn.h>

#include <deque>

#include <cstdio>
#include <expat.h>


#include <cairo/cairo.h>
#include <cairo-ps.h>
#include <pango/pangocairo.h>

#include <cairo_t_singleton.hpp>

#include <FL/Fl.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Light_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl_Tabs.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Help_Dialog.H>
#include <FL/Fl_Float_Input.H>
#include <FL/Fl_Int_Input.H>
#include <FL/Fl_Input_Choice.H>
#include <FL/Fl_Check_Button.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Tree.H>

//#include <Flu_Enumerations.h>
//#include <Flu_Tree_Browser.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 <immagine_cml.hpp>
#include <immagine_mol.hpp>


#include <mol_canvas.hpp>

#include <finestra_pr.hpp>

#include <prefs.hpp>

#include <pref_dialog.hpp>
#include <lib_dialog.hpp>

#include <chain_prop.hpp>
#include <editor.hpp>

#include <util.hpp>



#include <lb_delete_selected.xpm>
#include <lb_kill.xpm>
#include <lb_select_atom.xpm>

#include <lb_select_color.xpm>
#include <lb_select_font_color.xpm>
#include <lb_select_group.xpm>
#include <lb_draw_bond.xpm>
#include <lb_draw_double_bond.xpm>
#include <lb_draw_triple_bond.xpm>
#include <lb_draw_arrow.xpm>
#include <lb_draw_bezier.xpm>
#include <lb_draw_arc.xpm>
#include <lb_draw_etich.xpm>
#include <lb_rotate.xpm>

#include <lb_scale.xpm>
#include <lb_orb.xpm>
#include <lb_lib.xpm>
#include <lb_load_file.xpm>
#include <lb_save_file.xpm>
#include <lb_exp_ps.xpm>
#include <lb_new.xpm>
#include <lb_exp_png.xpm>
#include <lb_undo.xpm>
#include <lb_redo.xpm>
#include <lb_fixed_rotation.xpm>
#include <lb_save_as_file.xpm>
#include <lb_draw_chain.xpm>
#include <lb_paste.xpm>
#include <lb_flip_v.xpm>
#include <lb_flip_h.xpm>
#include <lb_3D_rotation.xpm>
#include <lb_zoom.xpm>
#include <lb_unzoom.xpm>
#include <lb_unzoom_1on1.xpm>
#include <lb_draw_box.xpm>


extern finestra_pr* MainWindow;

extern Preferences  __pref;

extern bool __close;



Fl_Pixmap img_sel_atom(lb_select_atom_xpm);
Fl_Pixmap img_sel_group(lb_select_group_xpm);
Fl_Pixmap img_sel_color(lb_select_color_xpm);
Fl_Pixmap img_sel_font_color(lb_select_font_color_xpm);
Fl_Pixmap img_delete_selected(lb_delete_selected_xpm);
Fl_Pixmap img_kill(lb_kill_xpm);
Fl_Pixmap img_draw_bond(lb_draw_bond_xpm);
Fl_Pixmap img_draw_double_bond(lb_draw_double_bond_xpm);
Fl_Pixmap img_draw_triple_bond(lb_draw_triple_bond_xpm);
Fl_Pixmap img_draw_arrow(lb_draw_arrow_xpm);
Fl_Pixmap img_draw_bezier(lb_draw_bezier_xpm);
Fl_Pixmap img_draw_arc(lb_draw_arc_xpm);
Fl_Pixmap img_draw_box(lb_draw_box_xpm);
Fl_Pixmap img_draw_etich(lb_draw_etich_xpm);
Fl_Pixmap img_scale(lb_scale_xpm);
Fl_Pixmap img_rotate(lb_rotate_xpm);
Fl_Pixmap img_draw_orb(lb_orb_xpm);
Fl_Pixmap img_add_lib(lb_lib_xpm);
Fl_Pixmap img_load_file(load_file_xpm);
Fl_Pixmap img_save_file(lb_save_file_xpm);
Fl_Pixmap img_exp_ps(lb_exp_ps_xpm);
Fl_Pixmap img_new(lb_new_xpm);
Fl_Pixmap img_exp_png(lb_exp_png_xpm);
Fl_Pixmap img_undo(lb_undo_xpm);
Fl_Pixmap img_redo(lb_redo_xpm);
Fl_Pixmap img_fixed_rotation(lb_fixed_rotation_xpm);
Fl_Pixmap img_save_as_file(lb_save_as_file_xpm);
Fl_Pixmap img_draw_chain(lb_draw_chain_xpm);
Fl_Pixmap img_paste(lb_paste_xpm);
Fl_Pixmap img_flip_v(lb_flip_v_xpm);
Fl_Pixmap img_flip_h(lb_flip_h_xpm);
Fl_Pixmap img_3D_rotation(lb_3D_rotation_xpm);
Fl_Pixmap img_zoom(lb_zoom_xpm);
Fl_Pixmap img_unzoom(lb_unzoom_xpm);
Fl_Pixmap img_unzoom_1o1(lb_unzoom_1on1_xpm);


void editor_window_cb(Fl_Widget* w , void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  
  if(ed->no_of_images_undo()>2 && !ed->isFileSaved()){
    if (fl_choice(_("Image modified, exit without saving?"),_("Yes"),_("No"),NULL)==0){
      ed->hide();
    }else{
      editor_save_native(w,d);
    }
  }else{
    ed->hide();
  }
}

void start_plugin_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  Fl_Menu_* m=dynamic_cast<Fl_Menu_*>(w);
  std::map<std::string,std::string> path_plugins=ed->getPluginPath();
  std::string key_path=(m->mvalue())->label();

  if(path_plugins.count(key_path)!=0){
    std::string path_plugin=path_plugins[key_path];
    /*free mem of old plugin*/
    if(ed->getActualPlugin()!=0){
      void* destroy_plg = dlsym(const_cast<void*>(ed->getHandle()), "destroy_plugin");
      void (*dest)(bist_plugin*)=(void (*)(bist_plugin*))(destroy_plg);
      dest(const_cast<bist_plugin*>(ed->getActualPlugin()));
      dlclose(const_cast<void*>(ed->getHandle()));
    }
    
    /**load new plugin*/
    ed->setHandle(dlopen(path_plugin.c_str(),RTLD_LAZY));
    if(!ed->getHandle()){
      std::cerr << dlerror() << endl;
    }
    void* create_plg = dlsym(const_cast<void*>(ed->getHandle()), "create_plugin");
    
    if(!create_plg){
      std::cerr << dlerror() << endl;
    }
    
    bist_plugin* (*gen_plugin)(immagine*,string)=( bist_plugin* (*)(immagine*,string))(create_plg);
    bist_plugin* plugin=gen_plugin(ed->ritorna_immagine(),path_plugin);
    ed->setActualPlugin(plugin);
    ed->reg_modified();  
    const_cast<bist_plugin*>(ed->getActualPlugin())->inizialize();
  }else{
    std::ostringstream ost;
    ost << _("No such plugin ")  << key_path;
    fl_alert("%s",ost.str().c_str());
  }
}

void editor_zoom_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->zoom();
}

void editor_unzoom_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->unzoom();
}


void editor_unzoom_1o1_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->unzoom_1o1();
}

void editor_3D_rotation_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->rotate3d();
}


void editor_flip_v_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->flipV();
}


void editor_flip_h_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->flipH();
}

void editor_paste_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->paste();
}


void editor_draw_chain(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawChain();
}


void export_image(std::string format){

  std::string file_filter=std::string("*.") + format; 
  char* the_file=fl_file_chooser(_("Export..."), file_filter.c_str(), NULL, 0);
  if(the_file!=NULL){
    editor* ed=dynamic_cast<editor*>(MainWindow);
    ed->hide();
    immagine* imm=MainWindow->ritorna_immagine();
    export_image_to_vector_file(*imm,the_file,true);
    ed->show();
  }

}


void editor_export(Fl_Widget* w, void* d){
  export_image("*");
}





void editor_save_as_ps_cb(Fl_Widget* w, void* d){
  export_image("ps");
}

void editor_save_as_png_cb(Fl_Widget* w, void* d){
  export_image("png");
}



void editor_undo_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->undo();
}

void editor_redo_cb(Fl_Widget* w, void* d){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->redo();
}


void editor_set_def_cb(Fl_Widget* w, void* d){
  __pref.Defaults();
  __pref.SavePrefs();
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->canvas_resize(__pref.getPageWidth(),
		    __pref.getPageHeight());
}


void config_cb(Fl_Widget* w, void* v){
  pref_dialog* p=new pref_dialog;
  p->show();
  
  while(p->shown()){
    Fl::wait();
  }
  delete p;
}

void edit_about_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->showAboutDialog();  
}

void edit_tutorial_cb(Fl_Widget* w,void* v){
  editor* ed = dynamic_cast<editor*>(MainWindow);
  ed->showHelpDialog();
}
void edit_nowar_cb(Fl_Widget* w, void* v){
  const static char* man="Copyright (C)  2005  Valerio Benfante.\nThis  is  free software; see the file COPYING for copying conditions.\nThere is NO warranty; not even for MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.\nThe logo is copyright (C) 2005 Luisa Russo and is released under GNU GPL";

  fl_message("%s",man);
}


void add_lib_cb(Fl_Widget* w, void* v){
  editor* tmp=dynamic_cast<editor*>(MainWindow);
  tmp->addLib(MainWindow);
}

void editor_rotate_selected_fixed_cb(Fl_Widget* w, void* v){
  fl_beep(FL_BEEP_QUESTION);
  editor* ed = dynamic_cast<editor*>(MainWindow);
  ed->rotateSelectedFixed();
 }

void rotate_selected_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->rotateSelected();
}


void translate_selected_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->translateSelected();
}

void scale_selected_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->scaleSelected();
}

void draw_single_bond_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawBond(BOND_SINGLE);
}

void draw_double_bond_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawBond(BOND_DOUBLE);
}


void draw_triple_bond_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawBond(BOND_TRIPLE);
}

void draw_arrow_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawArrow();
}


void draw_bezier_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawBezier();
}

void draw_arc_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawArc();
}

void draw_box_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawBox();
}


void draw_etich_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawEtich();
}

void draw_orb_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->drawOrb();
}

void copy_cb(Fl_Widget* w, void* v) {

  //int status;
  pid_t pid;
  
  pid = fork ();
  if(pid == 0){
    execl(ELF_ABS_PATH,ELF,NULL);
    exit (0);
  }else if (pid < 0){
    fl_alert(_("I can not create a new window"));
  }
}

void quit_cb(Fl_Widget* w, void* v) {
  if (fl_choice(_("Really quit?"),_("Yes"),_("No"),NULL)==0){
    editor* ed=dynamic_cast<editor*>(MainWindow);
    ed->hide();
    exit(EXIT_SUCCESS);
  }


  //da aggiornare quando ci saranno piu funzionalita'
}


void choose_font_cb(Fl_Widget* w, void* v){

}



void kill_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->kill(MainWindow); 
}

void delete_selected_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  
  ed->deleteSelected(MainWindow);  

}

void open_file_cb(Fl_Widget* w, void* v){
  char* il_file=fl_file_chooser(_("Pick a file..."), NULL, NULL, 0);

  if(il_file!=NULL){
    
    editor* ed=dynamic_cast<editor*>(MainWindow);
    ed->showOpenFileDialog(il_file);

  }else{
#ifdef DEBUG
    cout << "file null" << endl;
#endif
  }

}


void open_recent_file_cb(Fl_Widget* w, void* v){
  std::string the_file=reinterpret_cast<char*>(v);
  if(the_file!=""){
    editor* ed=dynamic_cast<editor*>(MainWindow);
    ed->file_inp(string(the_file));
    ed->redraw();
  }else{
#ifdef DEBUG
    cerr << __FUNCTION__ <<  " file null" << endl;
#endif
  }

}



void editor_save_native(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  if(ed->isFileOpened()==""){
    save_as_native_file_cb(w,v);
  }else{
    immagine*   la_imm=ed->ritorna_immagine();
    la_imm->w_immagine(ed->isFileOpened());
  }

  ed->saveFile();
}


void save_as_native_file_cb(Fl_Widget* w, void* v){
  char* il_file=fl_file_chooser(_("Save As..."), "*.bist", NULL, 0);

  if(il_file!=NULL){
    string nome=il_file;
    nome=nome.substr(nome.find_last_of("/")+1);
    struct stat attrb;
    stat(il_file,&attrb);

    int scrive=1;
    
    if(errno!=ENOENT){
      scrive=ask_overwrite_file(nome);
    }
    
    if(scrive){
      editor* ed=dynamic_cast<editor*>(MainWindow);
      ed->openFile(il_file);
      immagine*   la_imm=ed->ritorna_immagine();
      la_imm->w_immagine(string(il_file));
      ed->saveFile();
      __pref.set_last_opened_files(il_file);
      __pref.SavePrefs();
    }
  }
}

void select_atom_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->selectAtom(MainWindow);  
}


void select_group_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->selectGroup(MainWindow);
}


void select_box_cb(Fl_Widget* w, void* v){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  ed->selectBox(MainWindow);  
}

void select_color_cb(Fl_Widget* w, void* v){
  unsigned char r,g,b;
  int pushd=fl_color_chooser(_("pick a color..."), r, g, b);
  immagine* imm=MainWindow->ritorna_immagine();
  if(pushd){
    editor* ed=dynamic_cast<editor*>(MainWindow);
    ed->selectColor(imm,r,g,b);
    }
    imm->elimina_elem_selected();
    imm->elimina_legami_selected();
}

extern Fl_Menu_Item* voci_menu;

editor::editor(int W,int H, const char* titolo)
  :Fl_Double_Window(W,H,titolo),
   _actual_plugin(0),
   _scroller(LARGH_BUTTON_BAR,ALT_MENU+ALT_TOOLBAR, w()-LARGH_BUTTON_BAR, h()-ALT_MENU-ALT_TOOLBAR*2),
   _mol_can(LARGH_BUTTON_BAR,ALT_MENU+ALT_TOOLBAR,__pref.getPageWidth(),__pref.getPageHeight()),
   _il_menu(0, 0,w() , ALT_MENU),
   //upper frame (just under the menu)
   _sup_frame(FL_UP_FRAME, 0, ALT_MENU, LARGH_FIN, ALT_TOOLBAR,""),
   _new_b(PADD_BUTT,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _open_file_b(PADD_BUTT+LARG_BUTTON_TOP,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _save_file_b(PADD_BUTT+LARG_BUTTON_TOP*2,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _save_file_as_b(PADD_BUTT+LARG_BUTTON_TOP*3,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _exp_ps_b(PADD_BUTT+LARG_BUTTON_TOP*4,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _exp_png_b(PADD_BUTT+LARG_BUTTON_TOP*5,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _delete_selected(PADD_BUTT+LARG_BUTTON_TOP*6,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   _undo_b(PADD_BUTT+LARG_BUTTON_TOP*8,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _redo_b(PADD_BUTT+LARG_BUTTON_TOP*9,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   _b_paste(PADD_BUTT+LARG_BUTTON_TOP*10,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),

   _zoom_b(PADD_BUTT+LARG_BUTTON_TOP*12,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _unzoom_1o1_b(PADD_BUTT+LARG_BUTTON_TOP*13,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),
   _unzoom_b(PADD_BUTT+LARG_BUTTON_TOP*14,ALT_MENU+PADD_BUTT,LARG_BUTTON_TOP,ALT_BUTT_TOP),


   //left buttons bar
   _select_atom(PADD_BUTT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR,LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _select_group(PADD_BUTT*2+LARG_BUTTON_LEFT,
		 ALT_MENU+PADD_BUTT+ALT_TOOLBAR,
		 LARG_BUTTON_LEFT,
		 ALT_BUTT_LEFT),

   _rotate_sel(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _b_fixed_rotation(PADD_BUTT*2+LARG_BUTTON_LEFT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _b_rotate_3d(PADD_BUTT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*2,
		LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _scale_sel(PADD_BUTT*2+LARG_BUTTON_LEFT,ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*2,
	      LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _b_flip_v(PADD_BUTT,
	     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*3,
	     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _b_flip_h(PADD_BUTT*2+LARG_BUTTON_LEFT,
	     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*3,
	     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),



   _kill(PADD_BUTT,
	 ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*4,
	 LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _select_color(PADD_BUTT*2+LARG_BUTTON_LEFT,
		 ALT_MENU+PADD_BUTT+ALT_TOOLBAR+LARG_BUTTON_LEFT*4,
		 LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   //SPACER from here
   _draw_single_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*5,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_arrow(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*5,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),



   _draw_double_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*6,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_bezier(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*6,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),

   _draw_triple_bond(PADD_BUTT,
		     ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*7,
		     LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_arc(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*7,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_box(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*8,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_chain(PADD_BUTT*2+LARG_BUTTON_LEFT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*8,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _draw_etich(PADD_BUTT,
	       ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*9,
	       LARG_BUTTON_LEFT,ALT_BUTT_LEFT),


   _draw_orb(PADD_BUTT*2+LARG_BUTTON_LEFT,
	    ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*9,
	    LARG_BUTTON_LEFT,ALT_BUTT_LEFT),
   _add_lib(PADD_BUTT,
	    ALT_MENU+PADD_BUTT+ALT_TOOLBAR+SPACER+LARG_BUTTON_LEFT*10,
	    LARG_BUTTON_LEFT,ALT_BUTT_LEFT),


   //INFORMATION BOX
   _inf_frame(FL_EMBOSSED_BOX,0,h()-ALT_BUTT_TOP,FIN_W,HEIGHT_INF_BAR,""),
   _file_saved(false)
   

{

#ifndef DEBUG
  callback(editor_window_cb);
#endif

  _help_dialog=new Fl_Help_Dialog;

  _il_menu.copy(voci_menu);
  
  add(_il_menu);



  //get recent files and add to menu

  std::vector<std::string> recent_v=__pref.get_last_opened_files();



  for(unsigned int i=0;i<recent_v.size();i++){
    std::string path=std::string(_("&File")) + 
      std::string("/") + 
      std::string(PREFS_RECENT_FILES_LABEL)
      + std::string("/")  + recent_v[i];
    _il_menu.add(path.c_str(),0,
                 open_recent_file_cb, 
                 reinterpret_cast<void*>(const_cast<char *>(recent_v[i].c_str())),0);
  }




  
  string the_plugin_user_home_dir=getenv("HOME") + string(PLUGIN_PATH_HOME);
  populate_plugin_menu(the_plugin_user_home_dir);
  populate_plugin_menu(PLUGIN_PATH_SHARED);
  
  //barra sopra
  add(_sup_frame);

  _new_b.image(img_new);
  _new_b.callback(copy_cb);
  _new_b.tooltip(_("Create a new window"));
  add(_new_b);
  
  _open_file_b.image(img_load_file);
  _open_file_b.callback(open_file_cb);
  _open_file_b.tooltip(_("Open a file"));
  add(_open_file_b);

  _save_file_b.image(img_save_file);
  _save_file_b.callback(editor_save_native);
  _save_file_b.tooltip(_("Save"));
  add(_save_file_b);
  
  _save_file_as_b.image(img_save_as_file);
  _save_file_as_b.callback(save_as_native_file_cb);
  _save_file_as_b.tooltip(_("Save as"));
  add(_save_file_as_b);

  _exp_ps_b.image(img_exp_ps);
  _exp_ps_b.callback(editor_save_as_ps_cb);
  _exp_ps_b.tooltip(_("Export as PostScript"));
  add(_exp_ps_b);
  

  _exp_png_b.image(img_exp_png);
  _exp_png_b.callback(editor_save_as_png_cb);
  _exp_png_b.tooltip(_("Export as PNG"));
  add(_exp_png_b);


  _delete_selected.image(img_delete_selected);
  _delete_selected.callback(delete_selected_cb);
  _delete_selected.tooltip(_("Delete selected"));
  add(_delete_selected);

  _undo_b.image(img_undo);
  _undo_b.callback(editor_undo_cb);
  _undo_b.tooltip(_("Undo!"));
  add(_undo_b);

  _redo_b.image(img_redo);
  _redo_b.callback(editor_redo_cb);
  _redo_b.tooltip(_("Redo!"));
  add(_redo_b);


  _b_paste.image(img_paste);
  _b_paste.callback(editor_paste_cb);
  _b_paste.type(FL_RADIO_BUTTON);
  _b_paste.tooltip(_("Paste"));
  add(_b_paste);


  _zoom_b.image(img_zoom);
  _zoom_b.callback(editor_zoom_cb);
  _zoom_b.tooltip(_("Zoom"));
  _zoom_b.type(FL_RADIO_BUTTON);
  add(_zoom_b);


  _unzoom_1o1_b.image(img_unzoom_1o1);
  _unzoom_1o1_b.callback(editor_unzoom_1o1_cb);
  _unzoom_1o1_b.tooltip(_("Actual view"));
  add(_unzoom_1o1_b);

  
  _unzoom_b.image(img_unzoom);
  _unzoom_b.callback(editor_unzoom_cb);
  _unzoom_b.tooltip(_("Unzoom"));
  _unzoom_b.type(FL_RADIO_BUTTON);
  add(_unzoom_b);


  //canvas

  _scroller.type(Fl_Scroll::BOTH_ALWAYS);
  _scroller.box(FL_UP_FRAME);
  _scroller.add(_mol_can);
  _scroller.end();
  resizable(_scroller);
  
  add(_scroller);

  _mol_can.position(_mol_can.parent()->w()/2-_mol_can.w()/2,
		    _mol_can.parent()->h()/2-_mol_can.h()/2);
  

  _select_atom.set();
  _select_atom.image(img_sel_atom);
  _select_atom.callback(select_atom_cb);
  _select_atom.type(FL_RADIO_BUTTON);
  _select_atom.tooltip(_("Select Element"));
  add(_select_atom);



  _select_group.callback(select_group_cb);
  _select_group.image(img_sel_group);
  _select_group.type(FL_RADIO_BUTTON);
  _select_group.tooltip(_("Select a molecule"));
  add(_select_group);


  _rotate_sel.callback(rotate_selected_cb);
  _rotate_sel.image(img_rotate);
  _rotate_sel.type(FL_RADIO_BUTTON);
  _rotate_sel.tooltip(_("Rotate selected element"));
  add(_rotate_sel);

  _b_fixed_rotation.image(img_fixed_rotation);
  _b_fixed_rotation.callback(editor_rotate_selected_fixed_cb);
  _b_fixed_rotation.type(FL_RADIO_BUTTON);
  _b_fixed_rotation.tooltip(_("Fixed angle rotation"));
  add(_b_fixed_rotation);


  _b_rotate_3d.image(img_3D_rotation);
  _b_rotate_3d.callback(editor_3D_rotation_cb);
  _b_rotate_3d.type(FL_RADIO_BUTTON);
  _b_rotate_3d.tooltip(_("3D rotation"));
  add(_b_rotate_3d);


  _scale_sel.callback(scale_selected_cb);
  _scale_sel.image(img_scale);
  _scale_sel.type(FL_RADIO_BUTTON);
  _scale_sel.tooltip(_("Scale selected element"));
  add(_scale_sel);


  _b_flip_v.image(img_flip_v);
  _b_flip_v.callback(editor_flip_v_cb);
  _b_flip_v.type(FL_RADIO_BUTTON);
  _b_flip_v.tooltip(_("Vertical flip"));
  add(_b_flip_v);

  _b_flip_h.image(img_flip_h);
  _b_flip_h.callback(editor_flip_h_cb);
  _b_flip_h.type(FL_RADIO_BUTTON);
  _b_flip_h.tooltip(_("Orizontal flip"));
  add(_b_flip_h);


  _kill.image(img_kill);
  _kill.callback(kill_cb);
  _kill.type(FL_RADIO_BUTTON);
  _kill.tooltip(_("Kill"));
  add(_kill);

  _select_color.image(img_sel_color);
  _select_color.callback(select_color_cb);
  _select_color.tooltip(_("Select color"));
  add(_select_color);


  _draw_single_bond.image(img_draw_bond);
  _draw_single_bond.callback(draw_single_bond_cb);
  _draw_single_bond.type(FL_RADIO_BUTTON);
  _draw_single_bond.tooltip(_("Draw single bond"));
  add(_draw_single_bond);


  _draw_arrow.image(img_draw_arrow);
  _draw_arrow.callback(draw_arrow_cb);
  _draw_arrow.type(FL_RADIO_BUTTON);
  _draw_arrow.tooltip(_("Draw arrow"));
  add(_draw_arrow);


  _draw_double_bond.image(img_draw_double_bond);
  _draw_double_bond.callback(draw_double_bond_cb);
  _draw_double_bond.type(FL_RADIO_BUTTON);
  _draw_double_bond.tooltip(_("Draw double bond"));
  add(_draw_double_bond);
  
  _draw_bezier.image(img_draw_bezier);
  _draw_bezier.callback(draw_bezier_cb);
  _draw_bezier.type(FL_RADIO_BUTTON);
  _draw_bezier.tooltip(_("Draw bezier curve"));
  add(_draw_bezier);


  _draw_triple_bond.image(img_draw_triple_bond);
  _draw_triple_bond.callback(draw_triple_bond_cb);
  _draw_triple_bond.type(FL_RADIO_BUTTON);
  _draw_triple_bond.tooltip(_("Draw triple bond"));
  add(_draw_triple_bond);

  _draw_arc.image(img_draw_arc);
  _draw_arc.callback(draw_arc_cb);
  _draw_arc.type(FL_RADIO_BUTTON);
  _draw_arc.tooltip(_("Draw circle/ellipse"));
  add(_draw_arc);


  _draw_box.image(img_draw_box);
  _draw_box.callback(draw_box_cb);
  _draw_box.type(FL_RADIO_BUTTON);
  _draw_box.tooltip(_("Draw box"));
  add(_draw_box);


  _draw_chain.image(img_draw_chain);
  _draw_chain.callback(editor_draw_chain);
  _draw_chain.type(FL_RADIO_BUTTON);
  _draw_chain.tooltip(_("Draw chain"));
  add(_draw_chain);


  _draw_etich.image(img_draw_etich);
  _draw_etich.callback(draw_etich_cb);
  _draw_etich.type(FL_RADIO_BUTTON);
  _draw_etich.tooltip(_("Draw string"));
  add(_draw_etich);


  _draw_orb.image(img_draw_orb);
  _draw_orb.callback(draw_orb_cb);
  _draw_orb.type(FL_RADIO_BUTTON);
  _draw_orb.tooltip(_("Draw p orbital"));
  add(_draw_orb);

  _add_lib.image(img_add_lib);
  _add_lib.callback(add_lib_cb);
  _add_lib.tooltip(_("Insert template"));
  add(_add_lib);


  //information box
  add(_inf_frame);

  _mol_can.action(ACT_SEL_ATOM);

  file_inp("");


  

}

void editor::showHelpDialog(){
  _help_dialog->load(TUTORIAL_HTML);
  _help_dialog->show();
}

void editor::zoom(){
     _mol_can.action(ACT_ZOOM); 
}

void editor::unzoom(){
  _mol_can.action(ACT_UNZOOM);
}

void editor::unzoom_1o1(){
  _mol_can.action(ACT_NOTHING);
  int oldaction=get_button_value_as_action(); 
  __pref.setZoom(1.0);
  int posx_canv=_mol_can.parent()->x() - _mol_can.x() + _mol_can.parent()->w()/2 - __pref.getPageWidth()/2;
  int posy_canv=_mol_can.parent()->y() - _mol_can.y() + _mol_can.parent()->h()/2 - __pref.getPageHeight()/2;
  _mol_can.zoom(0,posx_canv,posy_canv);

  set_button(oldaction, true);
  redraw();
}

void editor::rotate3d(){
_mol_can.action(ACT_3D_ROT); 
}

void editor::flipV(){
_mol_can.action(ACT_FLIP_VER); 
}

void editor::flipH(){
_mol_can.action(ACT_FLIP_HOR); 
}

void editor::paste(){
set_button(ACT_PASTE,true);
}

void editor::drawChain(){
  chain_prop* p = new chain_prop;
  p->show();

  while(p->shown()){
    Fl::wait();
  }
  _mol_can.action(ACT_DRAW_CHAIN);
  _mol_can.num_atom_chain(p->_no_c);
  _mol_can.orient_chain(p->_angl);
  delete p;
}

void editor::undo(){
  if (_immagini.size() > 1){
    
    immagine the_front=ritorna_immagine(); 
    _immagini.pop_front();
    _redo_immagini.push_front(the_front);
    _mol_can.add_immagine(ritorna_immagine());
  }
  redraw();
}

void editor::redo(){
  if (_redo_immagini.size() >= 1){
    immagine the_front=_redo_immagini.front();
    _redo_immagini.pop_front();
    _immagini.push_front(the_front);
    _mol_can.add_immagine(ritorna_immagine());
  }
  redraw();
}



bool editor::isFileSaved() const {
  return _file_saved;
}
void editor::saveFile(){
  _file_saved = true;
}

const std::string& editor::isFileOpened() const {
  return _file_opened;
}

void editor::openFile(const string& fname){
  _file_opened = fname;
}
void editor::showAboutDialog(){
  _help_dialog->load(ABOUT_HTML);
  _help_dialog->show();
}

void editor::rotateSelectedFixed(){
  fl_beep(FL_BEEP_QUESTION);
  const char * risposta=fl_input(_("Please insert rotation entity in degrees."), "90");
  char* tail;
  if(risposta!=NULL){
    float rot_deg=strtof(risposta,&tail);
    if(tail[0]=='\0'){
      rot_deg=rot_deg*2.0*M_PI/360.0;
      _mol_can.action(ACT_FIXED_ROTATION);
      _mol_can.fixed_rotation_degree(rot_deg);
    }
  }
}

void editor::rotateSelected(){
  _mol_can.action(ACT_ROTATE_SELECTED);

  pair<float,float> ld;
  pair<float,float> ru;
  immagine* img = ritorna_immagine();
  if(img->elem_selected_size()>0){
    img->aabb_elem_selected(ld,
                            ru);
    int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();

    _mol_can.rotation_pivot_pos(ld.first + (ru.first -ld.first) /2 + dx_scroll,
                                    ld.second + (ru.second -ld.second) /2 +dy_scroll);
  }
}

void editor::drawEtich(){
  _mol_can.action(ACT_DRAW_ETICH);
}

void editor::deleteSelected(finestra_pr* finestra){
  reg_modified();
  immagine* imm=finestra->ritorna_immagine();
  imm->cancella_elementi_selected();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  this->redraw();

}

void editor::selectAtom(finestra_pr* finestra){
  this->_mol_can.action(ACT_SEL_ATOM);
  this->_mol_can.take_focus();
  immagine* imm=finestra->ritorna_immagine();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  this->redraw();

}

void editor::selectGroup(finestra_pr* finestra){
  this->_mol_can.action(ACT_SEL_GROUP);
  this->_mol_can.take_focus();
  immagine* imm=finestra->ritorna_immagine();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  this->redraw();

}

void editor::selectBox(finestra_pr* finestra){
  this->_mol_can.action(ACT_SEL_BOX);
  this->_mol_can.take_focus();
  immagine* imm=finestra->ritorna_immagine();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  this->redraw();
}

void editor::selectColor(immagine* immPtr,unsigned int r,
			 unsigned int g,unsigned int b){

    switch(this->_mol_can.action()){
    case ACT_NOTHING:
      break;
    case ACT_SEL_ATOM:
      immPtr->cambia_colore_sel(r,g,b);
      break; 
    case ACT_SEL_BOX:  
    case ACT_SEL_GROUP:
      immPtr->cambia_colore_sel(r,g,b);
      immPtr->cambia_colore_sel_etich(r,g,b);
      break;
    }
}

void editor::showOpenFileDialog(const char* fname){
  if (fname){
    file_inp(string(fname));
    __pref.set_last_opened_files(fname);
    __pref.SavePrefs();
    this->redraw();
  }
}

const std::map<std::string,std::string>&
editor::getPluginPath() const {
  return this->_dl_plugin_path;
}

const void* editor::getHandle() const{
  return _dl_handle;
}

const bist_plugin* editor::getActualPlugin() const{
  return _actual_plugin;
}
void editor::setActualPlugin(bist_plugin* newPlugin){
  _actual_plugin = newPlugin;
}

void editor::setHandle(void* newHandle){
  _dl_handle = newHandle;
}
 
void editor::kill(finestra_pr* finestra){
  immagine* imm= finestra->ritorna_immagine();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  this->_mol_can.action(ACT_KILL);
  this->redraw();

}
void editor::addLib(finestra_pr* fin){
 lib_dialog* p=new lib_dialog;
  MainWindow=p;
  p->show();
  
  while(p->shown()){
    Fl::wait();
  }


  string templ=p->get_template_file();
  delete p;
  MainWindow=this;

  immagine* imm=MainWindow->ritorna_immagine();
  imm->elimina_elem_selected();
  imm->elimina_legami_selected();
  imm->aggiungi_template(templ);
  this->redraw();

}

void editor::translateSelected(){
  _mol_can.action(ACT_TRANSLATE_SELECTED);
}

void editor::drawBond(BondType bt){
  switch(bt){
  case BOND_SINGLE: _mol_can.action(ACT_DRAW_SINGLE_BOND); break;
  case BOND_DOUBLE: _mol_can.action(ACT_DRAW_DOUBLE_BOND); break;
  case BOND_TRIPLE: _mol_can.action(ACT_DRAW_TRIPLE_BOND);break;
  }
}
void editor::drawArc(){
  _mol_can.action(ACT_DRAW_ARC);
}
void editor::drawOrb(){
  _mol_can.action(ACT_DRAW_ORB);
}
void editor::drawBezier(){
  _mol_can.action(ACT_DRAW_BEZIER);
}
void editor::drawBox(){
  _mol_can.action(ACT_DRAW_BOX);
}
void editor::drawArrow(){
 _mol_can.action(ACT_DRAW_ARROW);
}

void editor::scaleSelected(){
  _mol_can.action(ACT_SCALE_SELECTED);
  _mol_can.take_focus();

}
void editor::canvas_resize(int nw_width,int nw_height){
  if (nw_width > 0 && nw_height > 0)
    _mol_can.size(nw_width, nw_height);
}


void editor::canvas_give_focus(){
  _mol_can.take_focus();
}

void editor::canvas_translate(int dx, int dy){
  _mol_can.translate(dx,dy);
}


void editor::reg_modified(){
  _mol_can.reg_modified();
}

void editor::register_images_undo(immagine* imm){
  _immagini.push_front(*imm);
  if(_actual_plugin!=0){
    _actual_plugin->image(ritorna_immagine());
#ifdef DEBUG
    cout << "actual reg: " << imm << endl; 
#endif
  }
#ifdef DEBUG
  cout << "registrato" << imm << " " << _immagini.size() << endl;
#endif
}

deque<immagine>::size_type editor::no_of_images_undo(){
  return  _immagini.size();
}


editor::~editor(){
  if(_actual_plugin!=0){
    void* handle=dlopen(_actual_plugin->libpath().c_str(),RTLD_LAZY);
    if(!handle){
      cout << dlerror() << endl;
    }
    
    void* destroy_plg = dlsym(_dl_handle, "destroy_plugin");
    if(!destroy_plg){
      cout << dlerror() << endl;
    }
    void (*dest)(bist_plugin*)=(void (*)(bist_plugin*))(destroy_plg);
    dest(_actual_plugin);
    
    dlclose(_dl_handle);
  }

  delete _help_dialog;

#ifdef DEBUG
  cerr << "Eliminata finestra." << endl;
#endif
  
}


bist_plugin* editor::actual_plugin(){
  return _actual_plugin;
}

void editor::file_inp(string file){
  immagine* la_imm=NULL;
  
  if(guess_is_cml_file(file)){
    la_imm=new immagine_cml();
  }else if(guess_is_mdl_file(file)){
    la_imm=new immagine_mol();
  }else {
    la_imm=new immagine();
  }

  try{
    la_imm->filebist(file);
    la_imm->start();
    la_imm->print_warn();
    la_imm->print_errors();
  }catch (...){
    not_impl();
  }
    
  if(!la_imm->has_error()){
    _file_opened=file;
    _immagini.push_front(static_cast<immagine>(*la_imm));
    _mol_can.add_immagine(ritorna_immagine());

  }
    
  delete la_imm;

}



Fl_Scroll* editor::ritorna_scroll(){
  return &_scroller;
}

immagine* editor::ritorna_immagine(){
  return &_immagini.front();
}

mol_canvas* editor::ritorna_mol_canvas(){
  return &_mol_can;
}


void editor::draw(){
  damage(FL_DAMAGE_ALL);
  _inf_frame.damage(FL_DAMAGE_ALL);
  this->Fl_Double_Window::draw();
  int w_coord=draw_mouse_cordinate_inf_bar();

  
  int res_w=0;
  int res_h=0;
  int wt=w_coord;
  if(_mol_can.glue_mode()){
    std::string g_s(_("Glue mode "));
    fl_measure(g_s.c_str(), res_w, res_h);
    fl_draw(g_s.c_str(),wt, h()-ALT_BUTT_TOP/2+ res_h/4);
    wt+=res_w;
  }

  
  if(getActualPlugin()!=NULL && const_cast<bist_plugin*>(getActualPlugin())->time_to_act()){
    res_h=0;
    res_w=0;
    std::string g_s(_("Plugin enabled "));
    fl_measure(g_s.c_str(), res_w, res_h);
    fl_draw(g_s.c_str(),wt,h()-ALT_BUTT_TOP/2 + res_h/4);
    wt+=res_w;    

  }

}

int editor::handle(int e){
  int res=this->Fl_Double_Window::handle(e);

  switch(e){
  case FL_MOVE:
    redraw();
    break;
  }
  return res;
}

int editor::draw_mouse_cordinate_inf_bar(int x, int font_size){
  
  int p_font=fl_font();
  int p_font_size=fl_size();

  fl_font(FL_HELVETICA_BOLD,font_size);
  
  int res_w=0;
  int res_h=0;
  int act_x=Fl::event_x() - LARGH_BUTTON_BAR;
  int act_y=Fl::event_y() - ALT_TOOLBAR - ALT_MENU;

  act_x= act_x < 0 ? 0 : act_x;
  act_y= act_y < 0 ? 0 : act_y;

  std::ostringstream ost;

  ost << " x: " << act_x << " y: "<< act_y << " " << std::ends;

  fl_measure(ost.str().c_str(), res_w, res_h);
  
  fl_draw(ost.str().c_str(),x,h()-ALT_BUTT_TOP/2 + res_h/4);

  /*revert to saved value*/
  fl_font(p_font,p_font_size);

  
  return res_w;

}



int editor::get_button_value_as_action(){
  int res= ACT_NOTHING;
  if(_select_atom.value()){
    res=ACT_SEL_ATOM;
  }else if(_select_group.value()){
    res=ACT_SEL_GROUP;
  }

  //TODO: all the others buttons

  return res;

}

void editor::set_button(int which, bool set_action){
  _select_atom.value(0);
  _select_group.value(0);
  _rotate_sel.value(0);
  _scale_sel.value(0);
  _kill.value(0);
  _draw_single_bond.value(0);
  _draw_double_bond.value(0);
  _draw_triple_bond.value(0);
  _draw_arrow.value(0);
  _draw_bezier.value(0);
  _draw_arc.value(0);
  _draw_box.value(0);
  _draw_etich.value(0);
  _draw_orb.value(0);
  _add_lib.value(0);
  _new_b.value(0);
  _open_file_b.value(0);
  _save_file_b.value(0);
  _save_file_as_b.value(0);
  _exp_ps_b.value(0);
  _exp_png_b.value(0);
  _undo_b.value(0);
  _draw_chain.value(0);
  _b_fixed_rotation.value(0);
  _b_paste.value(0);
  _b_flip_v.value(0);
  _b_flip_h.value(0);
  _b_rotate_3d.value(0);
  _select_color.value(0);
  _delete_selected.value(0);
  _zoom_b.value(0);
  _unzoom_b.value(0);
  _unzoom_1o1_b.value(0);

  if(set_action){
    _mol_can.action(which);
  }
  switch(which){
  case ACT_NOTHING:
    break;
  case ACT_SEL_ATOM:
    _select_atom.value(1);
    break;
  case ACT_SEL_GROUP:
    _select_group.value(1);
    break;
  case ACT_SEL_BOX:
    _draw_box.value(1);
    break;
  case ACT_DELETE_SELECTED:
    _delete_selected.value(1);
    break;
  case ACT_KILL:
    _kill.value(1);
    break;
  case ACT_DRAW_SINGLE_BOND:
    _draw_single_bond.value(1);
    break;
  case ACT_DRAW_DOUBLE_BOND:
    _draw_double_bond.value(1);
    break;
  case ACT_DRAW_TRIPLE_BOND:
    _draw_triple_bond.value(1);
    break;
  case ACT_DRAW_ARROW:
    _draw_arrow.value(1);
    break;
  case ACT_DRAW_BEZIER:
    _draw_bezier.value(1);
    break;
  case ACT_DRAW_ARC:
    _draw_arc.value(1);
    break;
  case ACT_DRAW_ETICH:
    _draw_etich.value(1);
    break;
  case ACT_TRANSLATE_SELECTED:
    break;
  case ACT_ROTATE_SELECTED:
    _rotate_sel.value(1);
    break;
  case ACT_SCALE_SELECTED:
    _scale_sel.value(1);
    break;
  case ACT_DRAW_ORB:
    _draw_orb.value(1);
    break;
  case ACT_DRAW_LIBRARY:
    _add_lib.value(1);
    break;
  case ACT_FIXED_ROTATION:
    _b_fixed_rotation.value(1);
    break;
  case ACT_DRAW_CHAIN:
    _draw_chain.value(1);
    break; 
  case ACT_FLIP_HOR:
    _b_flip_h.value(1);
    break; 
  case ACT_FLIP_VER:
    _b_flip_v.value(1);
    break; 
  case ACT_COPY:
  case ACT_PASTE:
    _b_paste.value(1);
    break; 
  case ACT_3D_ROT:
    _b_rotate_3d.value(1);
    break; 
  case ACT_ZOOM:
    _zoom_b.value(1);
    break; 
  case ACT_UNZOOM:
    _unzoom_b.value(1);
    break; 
  default:
    break; 
  }

}


void editor::populate_plugin_menu(std::string startdir){

  DIR* shared_plug=opendir(startdir.c_str());

  if(shared_plug!=0){
    struct dirent* actplug;
    while((actplug=readdir(shared_plug))!=NULL){
      string actnameplug=actplug->d_name;
      if(actnameplug!="." && actnameplug!=".."){
	
	string nameplug = startdir + actnameplug;
        if(is_ELF_shared_object(nameplug)){
          std::pair<std::string,std::string> the_pair(actnameplug,nameplug);
          _dl_plugin_path.insert(the_pair);
          
          //start the plugin to get its menu entry
          void* dl_handle=dlopen(nameplug.c_str(),RTLD_LAZY);
          if(!dl_handle){
            std::cerr << dlerror() << endl;
          }
          void* create_plg = dlsym(dl_handle, "create_plugin");
          
          if(!create_plg){
            std::cerr << dlerror() << endl;
          }
    
          bist_plugin* (*gen_plugin)(immagine*,string)=( bist_plugin* (*)(immagine*,string))(create_plg);
          bist_plugin* plugin=gen_plugin(ritorna_immagine(),nameplug);

          std::ostringstream menu_entry;
          
          menu_entry << "&Plug-in/" <<  plugin->menu_path()  << actnameplug;

          void* destroy_plg = dlsym(dl_handle, "destroy_plugin");
          void (*dest)(bist_plugin*)=(void (*)(bist_plugin*))(destroy_plg);
          dest(plugin);
          dlclose(dl_handle);

          _il_menu.add(menu_entry.str().c_str(),0,start_plugin_cb,reinterpret_cast<void*>(&_dl_plugin_path));
        }
      }
    }
  }

}
