// -*- mode:C++ ; compile-command: "g++ -I.. -I../include -I../../giac/include -g -c plotfltk.cc" -*-
#include "first.h"
/*
 *  Copyright (C) 2000 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "global.h"

#ifdef HAVE_LIBFLTK
#include <FL/fl_ask.H>
#include "xcas.h"
#include <FL/fl_ask.H>
#include "plotfltk.h"
#include "prog.h"
#include "rpn.h"
#include "identificateur.h"
#include "subst.h"
#include "symbolic.h"
#include "tex.h"
#include <fstream>
#include <vector>
#include <algorithm>
#include <fcntl.h>
#include <cmath>
#include <time.h> // for nanosleep
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h> // auto-recovery function
#include "usual.h"
#include "derive.h"
#include "solve.h"
#include "intg.h"
#include "misc.h"
#include "sheet.h"
#include "path.h"
#include "ti89.h"
#include "input_lexer.h"

using namespace std;

#ifndef NO_NAMESPACE_GIAC
namespace giac {
#endif // ndef NO_NAMESPACE_GIAC

#ifdef HAVE_LC_MESSAGES
  std::string xcas_locale(getenv("XCAS_LOCALE")?getenv("XCAS_LOCALE"):giac_locale_location);
  class objet_bidon{
  public:
    objet_bidon(){
      // localization code
       setlocale (LC_MESSAGES, "");
       cerr << "Using locale " << xcas_locale << endl;
       bindtextdomain (PACKAGE, xcas_locale.c_str());
       textdomain (PACKAGE);
    };
  };
  objet_bidon mon_objet_bidon;
#endif
  std::vector<int> current_upper_window(1,upper_window_hist);
  gen save_eqw_data;
  vector<int> history_endlines,history_positions;
  vecteur undo_history_in,undo_history_out;
  // Image PICT(0,0,240,240,"PICT",-1,-1);

  // used to trace where the mouse was pushed to divide screen in 2 parts
  string current_program,save_input_value,save_matrix_input_value;
  int old_upper_window_state=0;
  bool waiting_click=false;
  gen waiting_click_value;
  bool horizontal_split=false;
  int xcas_output_fontsize,Help_text_fontsize;
#ifdef WIN32
  bool interrupt_button=true;
#else
  bool interrupt_button=false;
#endif

  // Added block_signal check, otherwise when recomputing history
  // Fl::check() could be called and make a recompute inside
  // e.g. by dragging the mouse in the geo screen!!
  void plotfltk_readqueue(){
    static clock_t last_check=0,current_check;
    static int sheet_redraw=0;
    if (interrupt_button && !block_signal){
      current_check=clock();
      if (current_check-last_check>CLOCKS_PER_SEC/10 ){
	last_check = current_check ;
	++sheet_redraw;
#ifdef HAVE_LIBFLVW
	if (spread_ptr && !(sheet_redraw %3))
	  spread_ptr->redraw();
#endif
	Fl::check();
      }
    }
  }

  void Eqw_history_set_color(){
    if (user_screen)
      Eqw_history->attr.text_color=FL_BLACK;
    else
      Eqw_history->attr.text_color=FL_BLACK;  
  }

  void swap_io_hist(){
    std::swap(Eqw_history->data,save_eqw_data);
    Eqw_history_set_color();
    Eqw_history->setscroll();
  }

  void modify_history(){ // for double-click -> modif
    if (history_in.empty())
      return;
    if (rpn_mode){
      history_out=undo_history_out;
      history_in=vecteur(history_out.size(),identificateur(" "));
      history_begin_level=0;
      history_redraw(history_out.size());
      return;
    }
    if (run_modif){
      run_modif=false;
      UNDO->label("modif");
      UNDO->redraw();
      input->textcolor(FL_BLACK);
    }
    else {
      run_modif_pos=history_pos(); 
      run_modif=true;
      string s(history_in[run_modif_pos].print());
      input->value(s.c_str());
      int l=s.size();
      input->position(l,l);
      input->textcolor(FL_RED);
      Fl::focus(input);
      UNDO->label("Canc");
      UNDO->redraw();
    }
    input->redraw();
  }

  void ckuser_screen(){
    if (!user_screen){
      user_screen=true;
      update_io();
      swap_io_hist();
      Picture->plot_instructions_ptr=&graph_instructions;
      Eqw_history->redraw();
    } 
    Picture->redraw();
    redraw_mouse_position_only=false;
  }

  gen fltk_input(const gen & arg,GIAC_CONTEXT){
#ifndef WIN32
    if ( (!child_id) || (arg.type==_VECT && arg._VECTptr->empty()) ) 
      return _click(arg,contextptr);
#endif
    // ckuser_screen();
    vecteur v(gen2vecteur(arg));
    if (v.empty()){
      ckuser_screen();
      manage_upper_window(upper_window_geo,false);
      waiting_click=true;
      for (;;) {
	Fl::wait();
	if (!waiting_click)
	  break;
      }
      return waiting_click_value;
    }
    // else return makeform(v);
    const char * s;
    if (v.size()>1)
      s=fl_input(v[0].print().c_str(),v[1].print().c_str());
    else
      s=fl_input(v[0].print().c_str());      
    // cerr << arg << s << endl;
    string ss("undef");
    gen res;
    if (s)
      ss=string(s);
    try {
      if (v.size()<4)
	res=gen(ss);
      else
	res=string2gen(ss,false);
    }
    catch (std::runtime_error & e){
      res=string2gen(e.what(),false);
    }
    return res;
  }

  Fl_Window * Plotfltk_w =(Fl_Window *)0;
  char plotfltk_petit_buffer[2];
  bool plotfltk_maj=false;
  bool plotfltk_shift_on=false;
  void plotfltk_input_char(char ch){
    if (plotfltk_maj && isalpha(ch))
      ch=toupper(ch);
    plotfltk_petit_buffer[0]=ch;
    plotfltk_petit_buffer[1]=0;
    Fl::e_text= plotfltk_petit_buffer;
    Fl::e_length=1;
    Fl::e_keysym=ch;
    Fl::handle(FL_KEYBOARD,Plotfltk_w);
  }

  void plotfltk_input_string(const char * ch,bool pasutilise=false,bool pasutilisenonplus=false){
    for (;*ch;++ch){
      plotfltk_petit_buffer[0]=*ch;
      plotfltk_petit_buffer[1]=0;
      Fl::e_text= plotfltk_petit_buffer;
      Fl::e_length=1;
      Fl::e_keysym=*ch;
      Fl::handle(FL_KEYBOARD,Plotfltk_w);
    }
  }
  Fl_Group *Plotfltk_Scientific_keyboard=(Fl_Group *)0;

  Fl_Group *Plotfltk_Transcendental=(Fl_Group *)0;

  Fl_Group *Plotfltk_Trig_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Sinus_button=(Fl_Button *)0;

  static void cb_Plotfltk_Sinus_button(Fl_Button*, void*) {
    plotfltk_input_string("sin");
  }

  Fl_Button *Plotfltk_Cosinus_button=(Fl_Button *)0;

  static void cb_Plotfltk_Cosinus_button(Fl_Button*, void*) {
    plotfltk_input_string("cos");
  }

  Fl_Button *Plotfltk_Tangeant_button=(Fl_Button *)0;

  static void cb_Plotfltk_Tangeant_button(Fl_Button*, void*) {
    plotfltk_input_string("tan");
  }

  Fl_Group *Plotfltk_Inv_trig_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Asinus_button=(Fl_Button *)0;

  static void cb_Plotfltk_Asinus_button(Fl_Button*, void*) {
    plotfltk_input_string("asin",false,true);
  }

  Fl_Button *Plotfltk_Acosinus_button=(Fl_Button *)0;

  static void cb_Plotfltk_Acosinus_button(Fl_Button*, void*) {
    plotfltk_input_string("acos",false,true);
  }

  Fl_Button *Plotfltk_Atangeant_button=(Fl_Button *)0;

  static void cb_Plotfltk_Atangeant_button(Fl_Button*, void*) {
    plotfltk_input_string("atan",false,true);
  }

  Fl_Group *Plotfltk_Exp_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Puissance=(Fl_Button *)0;

  static void cb_Plotfltk_Puissance(Fl_Button*, void*) {
    plotfltk_input_char('^');
  }

  Fl_Button *Plotfltk_Exp_button=(Fl_Button *)0;

  static void cb_Plotfltk_Exp_button(Fl_Button*, void*) {
    plotfltk_input_string("exp",false,true);
  }

  Fl_Button *Plotfltk_Dix_puissance=(Fl_Button *)0;

  static void cb_Plotfltk_Dix_puissance(Fl_Button*, void*) {
    plotfltk_input_string("10^",false,true);
  }

  Fl_Group *Plotfltk_Ln_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Ln_button=(Fl_Button *)0;

  static void cb_Plotfltk_Ln_button(Fl_Button*, void*) {
    plotfltk_input_string("log",false,true);
  }

  Fl_Group *Plotfltk_Lettre_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Variable_x=(Fl_Button *)0;

  static void cb_Plotfltk_Variable_x(Fl_Button*, void*) {
    plotfltk_input_char('x');
  }

  Fl_Button *Plotfltk_Variable_y=(Fl_Button *)0;

  static void cb_Plotfltk_Variable_y(Fl_Button*, void*) {
    plotfltk_input_char('y');
  }

  Fl_Button *Plotfltk_Variable_z=(Fl_Button *)0;

  static void cb_Plotfltk_Variable_z(Fl_Button*, void*) {
    plotfltk_input_char('z');
  }

  Fl_Button *Plotfltk_Key_t=(Fl_Button *)0;

  static void cb_Plotfltk_Key_t(Fl_Button*, void*) {
    plotfltk_input_char('t');
  }

  Fl_Group *Plotfltk_Binary_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Plus=(Fl_Button *)0;

  static void cb_Plotfltk_Plus(Fl_Button*, void*) {
    plotfltk_input_char('+');
  }

  Fl_Button *Plotfltk_Moins=(Fl_Button *)0;

  static void cb_Plotfltk_Moins(Fl_Button*, void*) {
    plotfltk_input_char('-');
  }

  Fl_Button *Plotfltk_Fois=(Fl_Button *)0;

  static void cb_Plotfltk_Fois(Fl_Button*, void*) {
    plotfltk_input_char('*');
  }

  Fl_Button *Plotfltk_Divise=(Fl_Button *)0;

  static void cb_Plotfltk_Divise(Fl_Button*, void*) {
    plotfltk_input_char('/');
  }

  Fl_Group *Plotfltk_IDS_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_greek_integrate=(Fl_Button *)0;

  static void cb_Plotfltk_greek_integrate(Fl_Button*, void*) {
    plotfltk_input_string("integrate");
  }

  Fl_Button *Plotfltk_greek_derive=(Fl_Button *)0;

  static void cb_Plotfltk_greek_derive(Fl_Button*, void*) {
    plotfltk_input_string("derive");
  }

  Fl_Group *Plotfltk_Cst_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Cst_i=(Fl_Button *)0;

  static void cb_Plotfltk_Cst_i(Fl_Button*, void*) {
    plotfltk_input_char('i');
  }

  Fl_Button *Plotfltk_Cst_pi=(Fl_Button *)0;

  static void cb_Plotfltk_Cst_pi(Fl_Button*, void*) {
    plotfltk_input_char('p'); plotfltk_input_char('i');
  }

  Fl_Group *Plotfltk_Unary_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Racine_carree=(Fl_Button *)0;

  static void cb_Plotfltk_Racine_carree(Fl_Button*, void*) {
    plotfltk_input_string("sqrt",false,true);
  }

  Fl_Button *Plotfltk_Inverse_button=(Fl_Button *)0;

  static void cb_Plotfltk_Inverse_button(Fl_Button*, void*) {
    plotfltk_input_string("inv",false,true);
  }

  Fl_Button *Plotfltk_Plus_moins=(Fl_Button *)0;

  Fl_Button *Plotfltk_Carre=(Fl_Button *)0;

  static void cb_Plotfltk_Carre(Fl_Button*, void*) {
    plotfltk_input_string("sq");
  }

  Fl_Group *Plotfltk_Delim_keyboard=(Fl_Group *)0;

  Fl_Button *Plotfltk_Double_quote=(Fl_Button *)0;

  static void cb_Plotfltk_Double_quote(Fl_Button*, void*) {
    plotfltk_input_char('"'); plotfltk_input_char('"');
  }

  Fl_Button *Plotfltk_RPN_programme=(Fl_Button *)0;

  static void cb_Plotfltk_RPN_programme(Fl_Button*, void*) {
    plotfltk_input_char('('); plotfltk_input_char(')');
  }

  Fl_Button *Plotfltk_Crochets=(Fl_Button *)0;

  static void cb_Plotfltk_Crochets(Fl_Button*, void*) {
    plotfltk_input_char('[');plotfltk_input_char(']');
  }

  Fl_Button *Plotfltk_Quote=(Fl_Button *)0;

  static void cb_Plotfltk_Quote(Fl_Button*, void*) {
    plotfltk_input_char(39);plotfltk_input_char(39);
  }

  Fl_Button *Plotfltk_Virgule=(Fl_Button *)0;

  static void cb_Plotfltk_Virgule(Fl_Button*, void*) {
    plotfltk_input_char(',');
  }

  Fl_Button *Plotfltk_Semi_button=(Fl_Button *)0;

  static void cb_Plotfltk_Semi_button(Fl_Button*, void*) {
    plotfltk_input_char(';');
  }

  Fl_Button *Plotfltk_RPN_space=(Fl_Button *)0;

  static void cb_Plotfltk_RPN_space(Fl_Button*, void*) {
    plotfltk_input_char(' ');
  }

  Fl_Button *Plotfltk_Point=(Fl_Button *)0;

  static void cb_Plotfltk_Point(Fl_Button*, void*) {
    plotfltk_input_char('.');
  }

  Fl_Button *Plotfltk_Shift_Key=(Fl_Button *)0;


  Fl_Group *Plotfltk_Numeric_keypad=(Fl_Group *)0;

  Fl_Button *Plotfltk_BACKSPACE=(Fl_Button *)0;

  static void cb_Plotfltk_BACKSPACE(Fl_Button*, void*) {
    plotfltk_petit_buffer[0]=0;
    Fl::e_length=0;
    Fl::e_text=plotfltk_petit_buffer;
    Fl::e_keysym=FL_BackSpace;
    Fl::handle(FL_KEYBOARD,Plotfltk_w);
  }

  Fl_Group *Plotfltk_Numeric_numbers=(Fl_Group *)0;

  Fl_Button *Plotfltk_Un=(Fl_Button *)0;

  static void cb_Plotfltk_Un(Fl_Button*, void*) {
    plotfltk_input_char('1');
  }

  Fl_Button *Plotfltk_Deux=(Fl_Button *)0;

  static void cb_Plotfltk_Deux(Fl_Button*, void*) {
    plotfltk_input_char('2');
  }

  Fl_Button *Plotfltk_Trois=(Fl_Button *)0;

  static void cb_Plotfltk_Trois(Fl_Button*, void*) {
    plotfltk_input_char('3');
  }

  Fl_Button *Plotfltk_Quatre=(Fl_Button *)0;

  static void cb_Plotfltk_Quatre(Fl_Button*, void*) {
    plotfltk_input_char('4');
  }

  Fl_Button *Plotfltk_Cinq=(Fl_Button *)0;

  static void cb_Plotfltk_Cinq(Fl_Button*, void*) {
    plotfltk_input_char('5');
  }

  Fl_Button *Plotfltk_Six=(Fl_Button *)0;

  static void cb_Plotfltk_Six(Fl_Button*, void*) {
    plotfltk_input_char('6');
  }

  Fl_Button *Plotfltk_Sept=(Fl_Button *)0;

  static void cb_Plotfltk_Sept(Fl_Button*, void*) {
    plotfltk_input_char('7');
  }

  Fl_Button *Plotfltk_Huit=(Fl_Button *)0;

  static void cb_Plotfltk_Huit(Fl_Button*, void*) {
    plotfltk_input_char('8');
  }

  Fl_Button *Plotfltk_Neuf=(Fl_Button *)0;

  static void cb_Plotfltk_Neuf(Fl_Button*, void*) {
    plotfltk_input_char('9');
  }

  Fl_Button *Plotfltk_Zero=(Fl_Button *)0;

  static void cb_Plotfltk_Zero(Fl_Button*, void*) {
    plotfltk_input_char('0');
  }

  Fl_Group *Plotfltk_Alpha_keyboard=(Fl_Group *)0;

  static void cb_Plotfltk_Shift_Key(Fl_Button*, void*) {
    if (plotfltk_shift_on){
      plotfltk_shift_on=false;
      Plotfltk_Alpha_keyboard->hide();
    }
    else {
      plotfltk_shift_on=true;
      Plotfltk_Alpha_keyboard->show();
    };
  }

  Fl_Button *Plotfltk_a_key=(Fl_Button *)0;

  static void cb_Plotfltk_a_key(Fl_Button*, void*) {
    plotfltk_input_char('a');
  }

  Fl_Button *Plotfltk_b_key=(Fl_Button *)0;

  static void cb_Plotfltk_b_key(Fl_Button*, void*) {
    plotfltk_input_char('b');
  }

  Fl_Button *Plotfltk_c_key=(Fl_Button *)0;

  static void cb_Plotfltk_c_key(Fl_Button*, void*) {
    plotfltk_input_char('c');
  }

  Fl_Button *Plotfltk_d_key=(Fl_Button *)0;

  static void cb_Plotfltk_d_key(Fl_Button*, void*) {
    plotfltk_input_char('d');
  }

  Fl_Button *Plotfltk_e_key=(Fl_Button *)0;

  static void cb_Plotfltk_e_key(Fl_Button*, void*) {
    plotfltk_input_char('e');
  }

  Fl_Button *Plotfltk_f_key=(Fl_Button *)0;

  static void cb_Plotfltk_f_key(Fl_Button*, void*) {
    plotfltk_input_char('f');
  }

  Fl_Button *Plotfltk_g_key=(Fl_Button *)0;

  static void cb_Plotfltk_g_key(Fl_Button*, void*) {
    plotfltk_input_char('g');
  }

  Fl_Button *Plotfltk_h_key=(Fl_Button *)0;

  static void cb_Plotfltk_h_key(Fl_Button*, void*) {
    plotfltk_input_char('h');
  }

  Fl_Button *Plotfltk_i_key=(Fl_Button *)0;

  static void cb_Plotfltk_i_key(Fl_Button*, void*) {
    plotfltk_input_char('i');
  }

  Fl_Button *Plotfltk_j_key=(Fl_Button *)0;

  static void cb_Plotfltk_j_key(Fl_Button*, void*) {
    plotfltk_input_char('j');
  }

  Fl_Button *Plotfltk_k_key=(Fl_Button *)0;

  static void cb_Plotfltk_k_key(Fl_Button*, void*) {
    plotfltk_input_char('k');
  }

  Fl_Button *Plotfltk_l_key=(Fl_Button *)0;

  static void cb_Plotfltk_l_key(Fl_Button*, void*) {
    plotfltk_input_char('l');
  }

  Fl_Button *Plotfltk_m_key=(Fl_Button *)0;

  static void cb_Plotfltk_m_key(Fl_Button*, void*) {
    plotfltk_input_char('m');
  }

  Fl_Button *Plotfltk_n_key=(Fl_Button *)0;

  static void cb_Plotfltk_n_key(Fl_Button*, void*) {
    plotfltk_input_char('n');
  }

  Fl_Button *Plotfltk_o_key=(Fl_Button *)0;

  static void cb_Plotfltk_o_key(Fl_Button* o, void*) {
    plotfltk_input_char('o');
  }

  Fl_Button *Plotfltk_p_key=(Fl_Button *)0;

  static void cb_Plotfltk_p_key(Fl_Button*, void*) {
    plotfltk_input_char('p');
  }

  Fl_Button *Plotfltk_q_key=(Fl_Button *)0;

  static void cb_Plotfltk_q_key(Fl_Button*, void*) {
    plotfltk_input_char('q');
  }

  Fl_Button *Plotfltk_r_key=(Fl_Button *)0;

  static void cb_Plotfltk_r_key(Fl_Button*, void*) {
    plotfltk_input_char('r');
  }

  Fl_Button *Plotfltk_s_key=(Fl_Button *)0;

  static void cb_Plotfltk_s_key(Fl_Button*, void*) {
    plotfltk_input_char('s');
  }

  Fl_Button *Plotfltk_t_key=(Fl_Button *)0;

  static void cb_Plotfltk_t_key(Fl_Button*, void*) {
    plotfltk_input_char('t');
  }

  Fl_Button *Plotfltk_u_key=(Fl_Button *)0;

  static void cb_Plotfltk_u_key(Fl_Button*, void*) {
    plotfltk_input_char('u');
  }

  Fl_Button *Plotfltk_v_key=(Fl_Button *)0;

  static void cb_Plotfltk_v_key(Fl_Button*, void* v) {
    plotfltk_input_char('v');
  }

  Fl_Button *Plotfltk_w_key=(Fl_Button *)0;

  static void cb_Plotfltk_w_key(Fl_Button*, void*) {
    plotfltk_input_char('w');
  }

  Fl_Button *Plotfltk_x_key=(Fl_Button *)0;

  static void cb_Plotfltk_x_key(Fl_Button*, void*) {
    plotfltk_input_char('x');
  }

  Fl_Button *Plotfltk_y_key=(Fl_Button *)0;

  static void cb_Plotfltk_y_key(Fl_Button*, void*) {
    plotfltk_input_char('y');
  }

  Fl_Button *Plotfltk_z_key=(Fl_Button *)0;

  static void cb_Plotfltk_z_key(Fl_Button*, void*) {
    plotfltk_input_char('z');
  }

  Fl_Button *Plotfltk_Inferieur_key=(Fl_Button *)0;

  static void cb_Plotfltk_Inferieur_key(Fl_Button*, void*) {
    plotfltk_input_char('<');
  }

  Fl_Button *Plotfltk_Superieur_key=(Fl_Button *)0;

  static void cb_Plotfltk_Superieur_key(Fl_Button*, void*) {
    plotfltk_input_char('>');
  }

  Fl_Button *Plotfltk_Backslash_key=(Fl_Button *)0;

  static void cb_Plotfltk_Backslash_key(Fl_Button*, void*) {
    plotfltk_input_char('\\');
  }

  Fl_Button *Plotfltk_Parenthese_ouvrante_key=(Fl_Button *)0;

  static void cb_Plotfltk_Parenthese_ouvrante_key(Fl_Button*, void*) {
    plotfltk_input_char('(');
  }

  Fl_Button *Plotfltk_Parenthese_fermante_key=(Fl_Button *)0;

  static void cb_Plotfltk_Parenthese_fermante_key(Fl_Button*, void*) {
    plotfltk_input_char(')');
  }

  Fl_Button *Plotfltk_Espace_key=(Fl_Button *)0;

  static void cb_Plotfltk_Espace_key(Fl_Button*, void*) {
    plotfltk_input_char(' ');
  }

  Fl_Button *Plotfltk_Point_exclamation_key=(Fl_Button *)0;

  static void cb_Plotfltk_Point_exclamation_key(Fl_Button*, void*) {
    plotfltk_input_char('!');
  }

  Fl_Button *Plotfltk_Crochet_fermant_key=(Fl_Button *)0;

  static void cb_Plotfltk_Crochet_fermant_key(Fl_Button*, void*) {
    plotfltk_input_char(']');
  }

  Fl_Button *Plotfltk_Crochet_ouvrant_key=(Fl_Button *)0;

  static void cb_Plotfltk_Crochet_ouvrant_key(Fl_Button*, void*) {
    plotfltk_input_char('[');
  }

  Fl_Button *Plotfltk_Accolade_ouvrant_key=(Fl_Button *)0;

  static void cb_Plotfltk_Accolade_ouvrant_key(Fl_Button*, void*) {
    plotfltk_input_char('{');
  }

  Fl_Button *Plotfltk_Accolade_fermant_key=(Fl_Button *)0;

  static void cb_Plotfltk_Accolade_fermant_key(Fl_Button*, void*) {
    plotfltk_input_char('}');
  }

  Fl_Button *Plotfltk_Deux_points_key=(Fl_Button *)0;

  static void cb_Plotfltk_Deux_points_key(Fl_Button*, void*) {
    plotfltk_input_char(':');
  }

  Fl_Button *Plotfltk_Equal_key=(Fl_Button *)0;

  static void cb_Plotfltk_Equal_key(Fl_Button*, void*) {
    plotfltk_input_char('=');
  }

  Fl_Button *Plotfltk_Guillemet_key=(Fl_Button *)0;

  static void cb_Plotfltk_Guillemet_key(Fl_Button*, void*) {
    plotfltk_input_char('"');
  }

  Fl_Button *Plotfltk_Souligne_key=(Fl_Button *)0;

  static void cb_Plotfltk_Souligne_key(Fl_Button*, void*) {
    plotfltk_input_char('_');
  }

  Fl_Button *Plotfltk_Majuscule_key=(Fl_Button *)0;

  static void cb_Plotfltk_Majuscule_key(Fl_Button* o, void* v) {
    if (plotfltk_maj){
      plotfltk_maj=false;
      Plotfltk_Majuscule_key->label("Maj");
      Plotfltk_a_key->label("a");
      Plotfltk_b_key->label("b");
      Plotfltk_c_key->label("c");
      Plotfltk_d_key->label("d");
      Plotfltk_e_key->label("e");
      Plotfltk_f_key->label("f");
      Plotfltk_g_key->label("g");
      Plotfltk_h_key->label("h");
      Plotfltk_i_key->label("i");
      Plotfltk_j_key->label("j");
      Plotfltk_k_key->label("k");
      Plotfltk_l_key->label("l");
      Plotfltk_m_key->label("m");
      Plotfltk_n_key->label("n");
      Plotfltk_o_key->label("o");
      Plotfltk_p_key->label("p");
      Plotfltk_q_key->label("q");
      Plotfltk_r_key->label("r");
      Plotfltk_s_key->label("s");
      Plotfltk_t_key->label("t");
      Plotfltk_u_key->label("u");
      Plotfltk_v_key->label("v");
      Plotfltk_w_key->label("w");
      Plotfltk_x_key->label("x");
      Plotfltk_y_key->label("y");
      Plotfltk_z_key->label("z");
    }
    else {
      plotfltk_maj=true;
      Plotfltk_Majuscule_key->label("Min");
      Plotfltk_a_key->label("A");
      Plotfltk_b_key->label("B");
      Plotfltk_c_key->label("C");
      Plotfltk_d_key->label("D");
      Plotfltk_e_key->label("E");
      Plotfltk_f_key->label("F");
      Plotfltk_g_key->label("G");
      Plotfltk_h_key->label("H");
      Plotfltk_i_key->label("I");
      Plotfltk_j_key->label("J");
      Plotfltk_k_key->label("K");
      Plotfltk_l_key->label("L");
      Plotfltk_m_key->label("M");
      Plotfltk_n_key->label("N");
      Plotfltk_o_key->label("O");
      Plotfltk_p_key->label("P");
      Plotfltk_q_key->label("Q");
      Plotfltk_r_key->label("R");
      Plotfltk_s_key->label("S");
      Plotfltk_t_key->label("T");
      Plotfltk_u_key->label("U");
      Plotfltk_v_key->label("V");
      Plotfltk_w_key->label("W");
      Plotfltk_x_key->label("X");
      Plotfltk_y_key->label("Y");
      Plotfltk_z_key->label("Z");
    }
    Plotfltk_Alpha_keyboard->redraw();
  }

  Fl_Button *Plotfltk_Diese_key=(Fl_Button *)0;

  static void cb_Plotfltk_Diese_key(Fl_Button*, void*) {
    plotfltk_input_char('#');
  }

  Fl_Button *Plotfltk_Pi_key=(Fl_Button *)0;

  static void cb_Plotfltk_Pi_key(Fl_Button*, void*) {
    plotfltk_input_string("pi");
  }

  Fl_Return_Button *Plotfltk_A_la_ligne=(Fl_Return_Button *)0;

  static void cb_Plotfltk_A_la_ligne(Fl_Return_Button*, void*) {
    plotfltk_input_char('\n');
  }

  Fl_Button *Plotfltk_Alpha_virgule_key=(Fl_Button *)0;

  static void cb_Plotfltk_Alpha_virgule_key(Fl_Button*, void*) {
    plotfltk_input_char(',');
  }

  Fl_Button *Plotfltk_Alpha_point_virgule_key=(Fl_Button *)0;

  static void cb_Plotfltk_Alpha_point_virgule_key(Fl_Button*, void*) {
    plotfltk_input_char(';');
  }

  Fl_Button *Plotfltk_Alpha_quote_key=(Fl_Button *)0;

  static void cb_Plotfltk_Alpha_quote_key(Fl_Button*, void*) {
    plotfltk_input_char('\'');
  }

  vector <Fl_Browser *> vbrowser;
  vector<int> gbrowser;
  void cb_plotfltk_browser(Fl_Browser * b,void *){
    if (b->value()){
      vector <Fl_Browser *>::const_iterator it=vbrowser.begin(),itend=vbrowser.end();
      for (;it!=itend;++it){
	if (*it==b)
	  break;
      }
      if (it!=itend)
	gbrowser[it-vbrowser.begin()]=b->value();
    }
  }

  static void cb_Plotfltk_Gnuplot_xminus(Fl_Button*, void*) {
    if (has_gnuplot){
      Rot_x->value(Rot_x->value()-5);
      gnuplot_setview();
    }
  }
  
  static void cb_Plotfltk_Gnuplot_xplus(Fl_Button*, void*) {
    if (has_gnuplot){
      Rot_x->value(Rot_x->value()+5);
      gnuplot_setview();
    }
  }

  static void cb_Plotfltk_Gnuplot_zminus(Fl_Button*, void*) {
    if (has_gnuplot){
      Rot_z->value(Rot_z->value()-5);
      gnuplot_setview();
    }
  }

  static void cb_Plotfltk_Gnuplot_zplus(Fl_Button*, void*) {
    if (has_gnuplot){
      Rot_z->value(Rot_z->value()+5);
      gnuplot_setview();
    }
  }

  void gnuplot_fltk(){
    if (win9x)
      return;
#ifdef IPAQ
    Fl_Window * w = new Fl_Window(60,60);
    Fl_Button * button0 = new Fl_Button(2,2,46,16);
#else
    Fl_Window * w = new Fl_Window(120,120);
    Fl_Button * button0 = new Fl_Button(4,4,92,32);
#endif
    button0->shortcut("^[");
    button0->label(gettext("OK"));
    /*
    Fl_Button * button1 = new Fl_Button(2,2,48,16);
    button1->label(gettext("->hist"));
    */
#ifdef IPAQ
    Fl_Button * button2 = new Fl_Button(2,20,20,16);
#else
    Fl_Button * button2 = new Fl_Button(4,40,40,32);
#endif
    button2->label(gettext("x-"));
    button2->callback((Fl_Callback*)cb_Plotfltk_Gnuplot_xminus);
    button2->shortcut(0x4ff54);
#ifdef IPAQ
    Fl_Button * button3 = new Fl_Button(26,20,20,16);
#else
    Fl_Button * button3 = new Fl_Button(52,40,40,32);
#endif
    button3->label(gettext("x+"));
    button3->callback((Fl_Callback*)cb_Plotfltk_Gnuplot_xplus);
    button3->shortcut(0xff52);
#ifdef IPAQ
    Fl_Button * button4 = new Fl_Button(2,40,20,16);
#else
    Fl_Button * button4 = new Fl_Button(4,80,40,32);
#endif
    button4->label(gettext("z-")); 
    button4->callback((Fl_Callback*)cb_Plotfltk_Gnuplot_zminus);
    button4->shortcut(0x4ff53);
#ifdef IPAQ
    Fl_Button * button5 = new Fl_Button(26,40,20,16);
#else
    Fl_Button * button5 = new Fl_Button(52,80,40,32);
#endif
    button5->label(gettext("z+"));
    button5->callback((Fl_Callback*)cb_Plotfltk_Gnuplot_zplus);
    button5->shortcut(0x4ff51);
    w->end();
    // Xcas->hide();
    w->resizable(w);
    w->set_modal();
    w->show();
    int r;
    for (;;) {
      Fl_Widget *o = Fl::readqueue();
      if (!o) Fl::wait();
      else {
	if (o == button0) {r = 0; break;}
	// if (o == button1) {r = 1; break;}
	if (o == w) { r=0; break; }
      }
    }
    w->hide();
    // Xcas->show();
    delete button5;
    delete button4;
    delete button3;
    delete button2;
    // delete button1;
    delete button0;
    delete w;
    /*
    if (r==1){
      input_value("graph3d2tex()");
      input_eval(false);
    }
    */
    bool clrplot;
    int out_handle;
    FILE * gnuplot_out_readstream,* stream = open_gnuplot(clrplot,gnuplot_out_readstream,out_handle);
    latex_replot(stream,(gnuplot_filename+print_INT_(gnuplot_fileno)+".tex").c_str());
    gnuplot_wait(out_handle,gnuplot_out_readstream,5);
    png_replot(gnuplot_fileno);
    Left_Xcas_resize();
    history_redraw(history_out.size());
  }

  // Given a vector v describing an input form, return
  gen makeform(const vecteur & v) {
    if (v.size()==1 && v.front().is_symb_of_sommet(at_output)){
      fl_message(v.front()._SYMBptr->feuille.print().c_str());
      return plus_one;
    }
    ckuser_screen();
    int r;
    vecteur res;
    // w->clear_border();
    // w->box(FL_UP_BOX);
    Fl_Window * w = Plotfltk_w = new Fl_Window(240,300);
    Fl_Button * button0 = new Fl_Button(160, 270, 70, 20);
    button0->shortcut("^[");
    button0->label(gettext("Cancel"));
    Fl_Button * button1 = new Fl_Return_Button(70, 270, 70, 20);
    button1->label(gettext("OK"));
    { Fl_Group* o = Plotfltk_Scientific_keyboard = new Fl_Group(0, 190, 245, 80);
      { Fl_Group* o = Plotfltk_Transcendental = new Fl_Group(0, 190, 180, 80);
        { Fl_Group* o = Plotfltk_Trig_keyboard = new Fl_Group(0, 190, 60, 20);
          { Fl_Button* o = Plotfltk_Sinus_button = new Fl_Button(0, 190, 20, 20, gettext("sin"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Sinus_button);
          }
          { Fl_Button* o = Plotfltk_Cosinus_button = new Fl_Button(20, 190, 20, 20, gettext("cos"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Cosinus_button);
          }
          { Fl_Button* o = Plotfltk_Tangeant_button = new Fl_Button(40, 190, 20, 20, gettext("tan"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Tangeant_button);
          }
          o->end();
        }
        { Fl_Group* o = Plotfltk_Inv_trig_keyboard = new Fl_Group(0, 210, 60, 20);
          { Fl_Button* o = Plotfltk_Asinus_button = new Fl_Button(0, 210, 20, 20, gettext("asin"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Asinus_button);
          }
          { Fl_Button* o = Plotfltk_Acosinus_button = new Fl_Button(20, 210, 20, 20, gettext("acos"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Acosinus_button);
          }
          { Fl_Button* o = Plotfltk_Atangeant_button = new Fl_Button(40, 210, 20, 20, gettext("atan"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Atangeant_button);
          }
          o->end();
        }
        { Fl_Group* o = Plotfltk_Exp_keyboard = new Fl_Group(0, 225, 60, 25);
          { Fl_Button* o = Plotfltk_Puissance = new Fl_Button(0, 230, 20, 20, gettext("^"));
            o->shortcut(0x5e);
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Puissance);
          }
          { Fl_Button* o = Plotfltk_Exp_button = new Fl_Button(20, 230, 20, 20, gettext("e^"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Exp_button);
          }
          { Fl_Button* o = Plotfltk_Dix_puissance = new Fl_Button(40, 230, 20, 20, gettext("10^"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Dix_puissance);
          }
          o->end();
        }
        { Fl_Group* o = Plotfltk_Ln_keyboard = new Fl_Group(0, 250, 60, 20);
          { Fl_Button* o = Plotfltk_Ln_button = new Fl_Button(0, 250, 20, 20, gettext("ln"));
            o->labelsize(10);
            o->callback((Fl_Callback*)cb_Plotfltk_Ln_button);
          }
          o->end();
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Lettre_keyboard = new Fl_Group(100, 190, 80, 20);
        { Fl_Button* o = Plotfltk_Variable_x = new Fl_Button(100, 190, 20, 20, gettext("x"));
          o->shortcut(0x78);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Variable_x);
        }
        { Fl_Button* o = Plotfltk_Variable_y = new Fl_Button(120, 190, 20, 20, gettext("y"));
          o->shortcut(0x79);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Variable_y);
        }
        { Fl_Button* o = Plotfltk_Variable_z = new Fl_Button(140, 190, 20, 20, gettext("z"));
          o->shortcut(0x7a);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Variable_z);
        }
        { Fl_Button* o = Plotfltk_Key_t = new Fl_Button(160, 190, 20, 20, gettext("t"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Key_t);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Binary_keyboard = new Fl_Group(100, 230, 80, 20);
        { Fl_Button* o = Plotfltk_Plus = new Fl_Button(100, 230, 20, 20, gettext("+"));
          o->shortcut(0x2b);
          o->callback((Fl_Callback*)cb_Plotfltk_Plus);
        }
        { Fl_Button* o = Plotfltk_Moins = new Fl_Button(120, 230, 20, 20, gettext("-"));
          o->shortcut(0x2d);
          o->callback((Fl_Callback*)cb_Plotfltk_Moins);
        }
        { Fl_Button* o = Plotfltk_Fois = new Fl_Button(140, 230, 20, 20, gettext("*"));
          o->shortcut(0x2a);
          o->callback((Fl_Callback*)cb_Plotfltk_Fois);
        }
        { Fl_Button* o = Plotfltk_Divise = new Fl_Button(160, 230, 20, 20, gettext("/"));
          o->shortcut(0x2f);
          o->callback((Fl_Callback*)cb_Plotfltk_Divise);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_IDS_keyboard = new Fl_Group(20, 250, 40, 20);
        { Fl_Button* o = Plotfltk_greek_integrate = new Fl_Button(40, 250, 20, 20, gettext("int"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_greek_integrate);
        }
        { Fl_Button* o = Plotfltk_greek_derive = new Fl_Button(20, 250, 20, 20, gettext("d"));
          o->labelfont(12);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_greek_derive);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Cst_keyboard = new Fl_Group(100, 250, 40, 20);
        { Fl_Button* o = Plotfltk_Cst_i = new Fl_Button(100, 250, 20, 20, gettext("i"));
          o->shortcut(0x69);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Cst_i);
        }
        { Fl_Button* o = Plotfltk_Cst_pi = new Fl_Button(120, 250, 20, 20, gettext("p"));
          o->labelfont(12);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Cst_pi);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Unary_keyboard = new Fl_Group(100, 210, 80, 20);
        { Fl_Button* o = Plotfltk_Racine_carree = new Fl_Button(120, 210, 20, 20, gettext("sqrt"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Racine_carree);
        }
        { Fl_Button* o = Plotfltk_Inverse_button = new Fl_Button(160, 210, 20, 20, gettext("inv"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Inverse_button);
        }
        { Fl_Button* o = Plotfltk_Plus_moins = new Fl_Button(100, 210, 20, 20, gettext("+-"));
          o->labelsize(10);
        }
        { Fl_Button* o = Plotfltk_Carre = new Fl_Button(140, 210, 20, 20, gettext("x^2"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Carre);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Delim_keyboard = new Fl_Group(60, 190, 40, 80);
        { Fl_Button* o = Plotfltk_Double_quote = new Fl_Button(60, 210, 20, 20, gettext("\""));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Double_quote);
        }
        { Fl_Button* o = Plotfltk_RPN_programme = new Fl_Button(60, 230, 20, 20, gettext("()"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_RPN_programme);
        }
        { Fl_Button* o = Plotfltk_Crochets = new Fl_Button(80, 230, 20, 20, gettext("[ ]"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Crochets);
        }
        { Fl_Button* o = Plotfltk_Quote = new Fl_Button(80, 190, 20, 20, gettext("\'"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Quote);
        }
        { Fl_Button* o = Plotfltk_Virgule = new Fl_Button(80, 250, 20, 20, gettext(","));
          o->callback((Fl_Callback*)cb_Plotfltk_Virgule);
        }
        { Fl_Button* o = Plotfltk_Semi_button = new Fl_Button(80, 210, 20, 20, gettext(";"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_Semi_button);
        }
        { Fl_Button* o = Plotfltk_RPN_space = new Fl_Button(60, 190, 20, 20);
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_RPN_space);
        }
        { Fl_Button* o = Plotfltk_Point = new Fl_Button(60, 250, 20, 20, gettext("."));
          o->callback((Fl_Callback*)cb_Plotfltk_Point);
        }
        o->end();
      }
      { Fl_Group* o = Plotfltk_Numeric_keypad = new Fl_Group(185, 190, 60, 80);
        o->labeltype(FL_NO_LABEL);
        { Fl_Button* o = Plotfltk_BACKSPACE = new Fl_Button(205, 250, 40, 20, gettext("<-"));
          o->labelsize(10);
          o->callback((Fl_Callback*)cb_Plotfltk_BACKSPACE);
        }
        { Fl_Group* o = Plotfltk_Numeric_numbers = new Fl_Group(185, 190, 60, 80);
          { Fl_Button* o = Plotfltk_Un = new Fl_Button(185, 230, 20, 20, gettext("1"));
            o->shortcut(0x31);
            o->callback((Fl_Callback*)cb_Plotfltk_Un);
          }
          { Fl_Button* o = Plotfltk_Deux = new Fl_Button(205, 230, 20, 20, gettext("2"));
            o->shortcut(0x32);
            o->callback((Fl_Callback*)cb_Plotfltk_Deux);
          }
          { Fl_Button* o = Plotfltk_Trois = new Fl_Button(225, 230, 20, 20, gettext("3"));
            o->shortcut(0x33);
            o->callback((Fl_Callback*)cb_Plotfltk_Trois);
          }
          { Fl_Button* o = Plotfltk_Quatre = new Fl_Button(185, 210, 20, 20, gettext("4"));
            o->shortcut(0x34);
            o->callback((Fl_Callback*)cb_Plotfltk_Quatre);
          }
          { Fl_Button* o = Plotfltk_Cinq = new Fl_Button(205, 210, 20, 20, gettext("5"));
            o->shortcut(0x35);
            o->callback((Fl_Callback*)cb_Plotfltk_Cinq);
          }
          { Fl_Button* o = Plotfltk_Six = new Fl_Button(225, 210, 20, 20, gettext("6"));
            o->shortcut(0x36);
            o->callback((Fl_Callback*)cb_Plotfltk_Six);
          }
          { Fl_Button* o = Plotfltk_Sept = new Fl_Button(185, 190, 20, 20, gettext("7"));
            o->shortcut(0x37);
            o->callback((Fl_Callback*)cb_Plotfltk_Sept);
          }
          { Fl_Button* o = Plotfltk_Huit = new Fl_Button(205, 190, 20, 20, gettext("8"));
            o->shortcut(0x38);
            o->callback((Fl_Callback*)cb_Plotfltk_Huit);
          }
          { Fl_Button* o = Plotfltk_Neuf = new Fl_Button(225, 190, 20, 20, gettext("9"));
            o->shortcut(0x39);
            o->callback((Fl_Callback*)cb_Plotfltk_Neuf);
          }
          { Fl_Button* o = Plotfltk_Zero = new Fl_Button(185, 250, 20, 20, gettext("0"));
            o->shortcut(0x30);
            o->callback((Fl_Callback*)cb_Plotfltk_Zero);
          }
          o->end();
        }
        o->end();
      }
      o->end();
    }
    { Fl_Group* o = Plotfltk_Alpha_keyboard = new Fl_Group(0, 190, 245, 80);
      o->hide();
      { Fl_Button* o = Plotfltk_a_key = new Fl_Button(0, 190, 25, 20, gettext("a"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_a_key);
      }
      { Fl_Button* o = Plotfltk_b_key = new Fl_Button(25, 190, 20, 20, gettext("b"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_b_key);
      }
      { Fl_Button* o = Plotfltk_c_key = new Fl_Button(45, 190, 20, 20, gettext("c"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_c_key);
      }
      { Fl_Button* o = Plotfltk_d_key = new Fl_Button(65, 190, 20, 20, gettext("d"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_d_key);
      }
      { Fl_Button* o = Plotfltk_e_key = new Fl_Button(85, 190, 20, 20, gettext("e"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_e_key);
      }
      { Fl_Button* o = Plotfltk_f_key = new Fl_Button(105, 190, 20, 20, gettext("f"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_f_key);
      }
      { Fl_Button* o = Plotfltk_g_key = new Fl_Button(125, 190, 20, 20, gettext("g"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_g_key);
      }
      { Fl_Button* o = Plotfltk_h_key = new Fl_Button(145, 190, 20, 20, gettext("h"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_h_key);
      }
      { Fl_Button* o = Plotfltk_i_key = new Fl_Button(165, 190, 20, 20, gettext("i"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_i_key);
      }
      { Fl_Button* o = Plotfltk_j_key = new Fl_Button(185, 190, 20, 20, gettext("j"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_j_key);
      }
      { Fl_Button* o = Plotfltk_k_key = new Fl_Button(205, 190, 20, 20, gettext("k"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_k_key);
      }
      { Fl_Button* o = Plotfltk_l_key = new Fl_Button(225, 190, 20, 20, gettext("l"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_l_key);
      }
      { Fl_Button* o = Plotfltk_m_key = new Fl_Button(0, 210, 25, 20, gettext("m"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_m_key);
      }
      { Fl_Button* o = Plotfltk_n_key = new Fl_Button(25, 210, 20, 20, gettext("n"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_n_key);
      }
      { Fl_Button* o = Plotfltk_o_key = new Fl_Button(45, 210, 20, 20, gettext("o"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_o_key);
      }
      { Fl_Button* o = Plotfltk_p_key = new Fl_Button(65, 210, 20, 20, gettext("p"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_p_key);
      }
      { Fl_Button* o = Plotfltk_q_key = new Fl_Button(85, 210, 20, 20, gettext("q"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_q_key);
      }
      { Fl_Button* o = Plotfltk_r_key = new Fl_Button(105, 210, 20, 20, gettext("r"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_r_key);
      }
      { Fl_Button* o = Plotfltk_s_key = new Fl_Button(125, 210, 20, 20, gettext("s"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_s_key);
      }
      { Fl_Button* o = Plotfltk_t_key = new Fl_Button(145, 210, 20, 20, gettext("t"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_t_key);
      }
      { Fl_Button* o = Plotfltk_u_key = new Fl_Button(165, 210, 20, 20, gettext("u"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_u_key);
      }
      { Fl_Button* o = Plotfltk_v_key = new Fl_Button(185, 210, 20, 20, gettext("v"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_v_key);
      }
      { Fl_Button* o = Plotfltk_w_key = new Fl_Button(205, 210, 20, 20, gettext("w"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_w_key);
      }
      { Fl_Button* o = Plotfltk_x_key = new Fl_Button(225, 210, 20, 20, gettext("x"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_x_key);
      }
      { Fl_Button* o = Plotfltk_y_key = new Fl_Button(0, 230, 25, 20, gettext("y"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_y_key);
      }
      { Fl_Button* o = Plotfltk_z_key = new Fl_Button(25, 230, 20, 20, gettext("z"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_z_key);
      }
      { Fl_Button* o = Plotfltk_Inferieur_key = new Fl_Button(45, 230, 20, 20, gettext("<"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Inferieur_key);
      }
      { Fl_Button* o = Plotfltk_Superieur_key = new Fl_Button(65, 230, 20, 20, gettext(">"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Superieur_key);
      }
      { Fl_Button* o = Plotfltk_Backslash_key = new Fl_Button(25, 250, 20, 20, gettext("\\"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Backslash_key);
      }
      { Fl_Button* o = Plotfltk_Parenthese_ouvrante_key = new Fl_Button(85, 230, 20, 20, gettext("("));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Parenthese_ouvrante_key);
      }
      { Fl_Button* o = Plotfltk_Parenthese_fermante_key = new Fl_Button(105, 230, 20, 20, gettext(")"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Parenthese_fermante_key);
      }
      { Fl_Button* o = Plotfltk_Espace_key = new Fl_Button(205, 250, 20, 20);
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Espace_key);
      }
      { Fl_Button* o = Plotfltk_Point_exclamation_key = new Fl_Button(145, 250, 20, 20, gettext("!"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Point_exclamation_key);
      }
      { Fl_Button* o = Plotfltk_Crochet_fermant_key = new Fl_Button(145, 230, 20, 20, gettext("]"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Crochet_fermant_key);
      }
      { Fl_Button* o = Plotfltk_Crochet_ouvrant_key = new Fl_Button(125, 230, 20, 20, gettext("["));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Crochet_ouvrant_key);
      }
      { Fl_Button* o = Plotfltk_Accolade_ouvrant_key = new Fl_Button(165, 230, 20, 20, gettext("{"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Accolade_ouvrant_key);
      }
      { Fl_Button* o = Plotfltk_Accolade_fermant_key = new Fl_Button(185, 230, 20, 20, gettext("}"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Accolade_fermant_key);
      }
      { Fl_Button* o = Plotfltk_Deux_points_key = new Fl_Button(105, 250, 20, 20, gettext(":"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Deux_points_key);
      }
      { Fl_Button* o = Plotfltk_Equal_key = new Fl_Button(125, 250, 20, 20, gettext("="));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Equal_key);
      }
      { Fl_Button* o = Plotfltk_Guillemet_key = new Fl_Button(225, 230, 20, 20, gettext("\""));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Guillemet_key);
      }
      { Fl_Button* o = Plotfltk_Souligne_key = new Fl_Button(45, 250, 20, 20, gettext("_"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Souligne_key);
      }
      { Fl_Button* o = Plotfltk_Majuscule_key = new Fl_Button(0, 250, 25, 20, gettext("Maj"));
        o->color(5);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Majuscule_key);
      }
      { Fl_Button* o = Plotfltk_Diese_key = new Fl_Button(165, 250, 20, 20, gettext("#"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Diese_key);
      }
      { Fl_Button* o = Plotfltk_Pi_key = new Fl_Button(185, 250, 20, 20, gettext("<-"));
        o->color(2);
        o->labelfont(12);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_BACKSPACE);
      }
      { Fl_Return_Button* o = Plotfltk_A_la_ligne = new Fl_Return_Button(225, 250, 20, 20);
        o->color(2);
        o->selection_color(0);
        o->callback((Fl_Callback*)cb_Plotfltk_A_la_ligne);
      }
      { Fl_Button* o = Plotfltk_Alpha_virgule_key = new Fl_Button(65, 250, 20, 20, gettext(","));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Alpha_virgule_key);
      }
      { Fl_Button* o = Plotfltk_Alpha_point_virgule_key = new Fl_Button(85, 250, 20, 20, gettext(";"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Alpha_point_virgule_key);
      }
      { Fl_Button* o = Plotfltk_Alpha_quote_key = new Fl_Button(205, 230, 20, 20, gettext("\'"));
        o->color(2);
        o->labelsize(10);
        o->callback((Fl_Callback*)cb_Plotfltk_Alpha_quote_key);
      }
      o->end();
    }
    { Fl_Button* o = Plotfltk_Shift_Key = new Fl_Button(10, 270, 40, 20);
    o->color(2);
    o->labeltype(FL_NO_LABEL);
    o->labelcolor(2);
    o->callback((Fl_Callback*)cb_Plotfltk_Shift_Key);
    }
    // Now parse v
    Plotfltk_Scientific_keyboard->hide();
    int current_y=0;
    vector<Fl_Input *> vinput;
    vector<Fl_Output *> voutput;
    vector<string *> labels;
    /*
    vector <Fl_Menu_Button *> vpopup;
    vector < vector<Fl_Menu_Item * > > vpopupitem;
    */
    const_iterateur it=v.begin(),itend=v.end();
    for (;it!=itend;++it){
      if (it->type==_IDNT){
	Plotfltk_Scientific_keyboard->show();
	Fl_Input * o;
	string * l=new string (it->print());
	labels.push_back(l);
	o=new Fl_Input(60,current_y,180,20,l->c_str());	  
	vinput.push_back(o);
	Fl::focus(o);
	current_y +=20;
	continue;
      }
      if ( (it->type==_STRNG) && it+1!=itend && ((it+1)->type==_IDNT) ){
	Plotfltk_Scientific_keyboard->show();
	Fl_Input * o;
	string * l=new string (it->print());
	labels.push_back(l);
	o=new Fl_Input(60,current_y,180,20,l->c_str());
	++it;
	vinput.push_back(o);
	Fl::focus(o);
	current_y +=20;
	continue;
      }
      if (it->type!=_SYMB)
	continue;
      unary_function_ptr & u=it->_SYMBptr->sommet;
      gen g=it->_SYMBptr->feuille;
      if ( (u==at_click) || (u==at_Request) ) {
	Plotfltk_Scientific_keyboard->show();
	vecteur vg(gen2vecteur(g));
	if (vg.empty())
	  continue;
	Fl_Input * o;
	string * l=new string (eval(vg[0]).print());
	labels.push_back(l);
	o=new Fl_Input(60,current_y,180,20,l->c_str());
	if (vg.size()>1&& u!=at_Request)
	  o->value(eval(vg[1]).print().c_str());
	vinput.push_back(o);
	Fl::focus(o);
	current_y +=20;
	continue;
      }
      if ( (u==at_output) || (u==at_Text) || (u==at_Title) ){
	g=eval(g);
	Fl_Output * o;
	if (u==at_Title){
	  string * l=new string (g.print());
	  labels.push_back(l);
	  o=new Fl_Output(200,current_y,0,20,l->c_str());
	  o->value("");
	}
	else {
	  o=new Fl_Output(40,current_y,180,20,"");
	  o->value(g.print().c_str());
	}
	voutput.push_back(o);
	current_y += 20;
	continue;
      }
      /*
      if (u==at_popup){
	vecteur vg(gen2vecteur(g));
	if (vg.empty())
	  continue;
	Fl_Menu_Button * o=new Fl_Menu_Button(10,current_y,100,20,vg[0].print().c_str());
	vpopup.push_back(o);
	vector<Fl_Menu_Item *> tmpmenu;
	const iterateur tmpit=vg.begin()+1,tmpend=vg.end();
	int y=current_y;
	for (;tmpit!=tmpend;++tmpit){
	  Fl_Menu_Item * o=new Fl_Menu_Item(10,y,100,15,tmpit->print().c_str());
	  tmpmenu.push_back(o);
	  y +=15;
	}
	vpopupitem.push_back(tmpmenu);
	o->end();
	current_y +=20;
	continue;
      }
      */
      if ( (u==at_choosebox) || (u==at_DropDown) || (u==at_Popup) ){
	vecteur vg(gen2vecteur(g));
	if (vg.size()==2)
	  vg.insert(vg.begin(),string2gen("",false));
	if (vg.size()!=3)
	  continue;
	Fl_Browser * o =new Fl_Browser(50, current_y, 180, 65);
	current_y += 80;
        o->type(2);
	string * l=new string (vg[0].print());
	labels.push_back(l);
        o->label(l->c_str());
        o->callback((Fl_Callback*)cb_plotfltk_browser);
	vbrowser.push_back(o);
	gbrowser.push_back(0);
	vecteur wg(gen2vecteur(vg[1]));
	const_iterateur jt=wg.begin(),jtend=wg.end();
	for (;jt!=jtend;++jt){
	  o->add(jt->print().c_str());
	}
	gen g=protecteval(vg[2],DEFAULT_EVAL_LEVEL,0); // FIXME GIAC_CONTEXT
	if ( (g.type==_INT_) && (g.val>0) && (g.val<=wg.size()) )
	  o->value(g.val);
	continue;
      }
    }
    w->end();
    w->resizable(w);
    w->set_modal();
    w->show();
    for (;;) {
      Fl_Widget *o = Fl::readqueue();
      if (!o) Fl::wait();
      else {
	if (o == button0) {r = 0; break;}
	if (o == button1) {r = 1; break;}
	if (o == w) { r=0; break; }
      }
    }
    w->hide();
    gen gtmp("ok");
    res.push_back(symb_sto(r,gtmp));
    // store results
    it=v.begin();
    int ibrowser=0;
    vector<Fl_Input *>::const_iterator vinput_it=vinput.begin();
    gen resadd,tmp;
    for (;it!=itend;++it){
      if (it->type==_IDNT){
	try {
	  resadd=gen((*vinput_it)->value());
	}
	catch (std::runtime_error & e){
	  resadd=string2gen(e.what(),false);
	}
	tmp=*it;
	res.push_back(symb_sto(resadd,tmp));
	++vinput_it;
      }
      if (it->type!=_SYMB)
	continue;
      unary_function_ptr & u=it->_SYMBptr->sommet;
      gen & g=it->_SYMBptr->feuille;
      if ( (u==at_click) || (u==at_Request) ){
	vecteur vg(gen2vecteur(g));
	try {
	  if (vg.size()>3|| u==at_Request)
	    resadd=string2gen((*vinput_it)->value(),false);
	  else
	    resadd=gen((*vinput_it)->value());
	}
	catch (std::runtime_error & e){
	  resadd=string2gen(e.what(),false);
	}
	if (u==at_Request && vg.size()>1)
	  res.push_back(symb_sto(resadd,vg[1]));
	else {
	  if (vg.size()>2)
	    res.push_back(symb_sto(resadd,vg[2]));
	}
	++vinput_it;
	continue;
      }
      if ( (u==at_choosebox) || (u==at_DropDown) || (u==at_Popup) ){
	vecteur vg(gen2vecteur(g));
	if (vg.size()==2)
	  vg.insert(vg.begin(),zero);
	if (vg.size()!=3)
	  continue;
	res.push_back(symb_sto(gbrowser[ibrowser],vg[2]));
	++ibrowser;
	continue;
      }
    }
    // delete widgets
    { 
      vector<Fl_Input *>::const_iterator jt=vinput.begin(),jtend=vinput.end();
      for (;jt!=jtend;++jt){
	delete *jt;
      }
      vinput.clear();
    }
    { 
      vector<Fl_Output *>::const_iterator jt=voutput.begin(),jtend=voutput.end();
      for (;jt!=jtend;++jt){
	delete *jt;
      }
      voutput.clear();
    }
    { 
      vector<Fl_Browser *>::const_iterator jt=vbrowser.begin(),jtend=vbrowser.end();
      for (;jt!=jtend;++jt){
	delete *jt;
      }
      vbrowser.clear();
    }
    { 
      vector<string *>::const_iterator jt=labels.begin(),jtend=labels.end();
      for (;jt!=jtend;++jt){
	delete *jt;
      }
      labels.clear();
    }
    /*
    { 
      vector<Fl_Menu_Button *>::const_iterator jt=vpopup.begin(),jtend=vpopup.end();
      for (;jt!=jtend;++jt){
	delete *jt;
      }
    }
    { 
      vector< vector<Fl_Menu_Item *> >::const_iterator jt=vpopupitem.begin(),jtend=vpopupitem.end();
      for (;jt!=jtend;++jt){
	vector<Fl_Menu_Item *>::const_iterator jtt=jt->begin(),jttend=jt->end();
	for (;jtt!=jttend;+jtt)
	  delete *jtt;
      }
    }
    */
    delete button0;
    delete button1;
    delete Plotfltk_Sinus_button;
    delete Plotfltk_Cosinus_button;
    delete Plotfltk_Tangeant_button;
    delete Plotfltk_Trig_keyboard;
    delete Plotfltk_Asinus_button;
    delete Plotfltk_Acosinus_button;
    delete Plotfltk_Atangeant_button;
    delete Plotfltk_Inv_trig_keyboard;
    delete Plotfltk_Puissance;
    delete Plotfltk_Exp_button;
    delete Plotfltk_Dix_puissance;
    delete Plotfltk_Exp_keyboard;
    delete Plotfltk_Ln_button;
    delete Plotfltk_Ln_keyboard;
    delete Plotfltk_Transcendental;
    delete Plotfltk_Variable_x;
    delete Plotfltk_Variable_y;
    delete Plotfltk_Variable_z;
    delete Plotfltk_Key_t;
    delete Plotfltk_Lettre_keyboard;
    delete Plotfltk_Plus;
    delete Plotfltk_Moins;
    delete Plotfltk_Fois;
    delete Plotfltk_Divise;
    delete Plotfltk_Binary_keyboard;
    delete Plotfltk_greek_integrate;
    delete Plotfltk_greek_derive;
    delete Plotfltk_IDS_keyboard;
    delete Plotfltk_Cst_i;
    delete Plotfltk_Cst_pi;
    delete Plotfltk_Cst_keyboard;
    delete Plotfltk_Racine_carree;
    delete Plotfltk_Inverse_button;
    delete Plotfltk_Plus_moins;
    delete Plotfltk_Carre;
    delete Plotfltk_Unary_keyboard;
    delete Plotfltk_Double_quote;
    delete Plotfltk_RPN_programme;
    delete Plotfltk_Crochets;
    delete Plotfltk_Quote;
    delete Plotfltk_Virgule;
    delete Plotfltk_Semi_button;
    delete Plotfltk_RPN_space;
    delete Plotfltk_Point;
    delete Plotfltk_Shift_Key;
    delete Plotfltk_Delim_keyboard;
    delete Plotfltk_Zero;
    delete Plotfltk_Un;
    delete Plotfltk_Deux;
    delete Plotfltk_Trois;
    delete Plotfltk_Quatre;
    delete Plotfltk_Cinq;
    delete Plotfltk_Six;
    delete Plotfltk_Sept;
    delete Plotfltk_Huit;
    delete Plotfltk_Neuf;
    delete Plotfltk_BACKSPACE;
    delete Plotfltk_Numeric_numbers;
    delete Plotfltk_Numeric_keypad;
    delete Plotfltk_Scientific_keyboard;
    delete Plotfltk_a_key;
    delete Plotfltk_b_key;
    delete Plotfltk_c_key;
    delete Plotfltk_d_key;
    delete Plotfltk_e_key;
    delete Plotfltk_f_key;
    delete Plotfltk_g_key;
    delete Plotfltk_h_key;
    delete Plotfltk_i_key;
    delete Plotfltk_j_key;
    delete Plotfltk_k_key;
    delete Plotfltk_l_key;
    delete Plotfltk_m_key;
    delete Plotfltk_n_key;
    delete Plotfltk_o_key;
    delete Plotfltk_p_key;
    delete Plotfltk_q_key;
    delete Plotfltk_r_key;
    delete Plotfltk_s_key;
    delete Plotfltk_t_key;
    delete Plotfltk_u_key;
    delete Plotfltk_v_key;
    delete Plotfltk_w_key;
    delete Plotfltk_x_key;
    delete Plotfltk_y_key;
    delete Plotfltk_z_key;
    delete Plotfltk_Inferieur_key;
    delete Plotfltk_Superieur_key;
    delete Plotfltk_Backslash_key;
    delete Plotfltk_Parenthese_ouvrante_key;
    delete Plotfltk_Parenthese_fermante_key;
    delete Plotfltk_Espace_key;
    delete Plotfltk_Point_exclamation_key;
    delete Plotfltk_Crochet_fermant_key;
    delete Plotfltk_Crochet_ouvrant_key;
    delete Plotfltk_Accolade_ouvrant_key;
    delete Plotfltk_Accolade_fermant_key;
    delete Plotfltk_Deux_points_key;
    delete Plotfltk_Equal_key;
    delete Plotfltk_Guillemet_key;
    delete Plotfltk_Souligne_key;
    delete Plotfltk_Majuscule_key;
    delete Plotfltk_Diese_key;
    delete Plotfltk_Pi_key;
    delete Plotfltk_A_la_ligne;
    delete Plotfltk_Alpha_virgule_key;
    delete Plotfltk_Alpha_point_virgule_key;
    delete Plotfltk_Alpha_quote_key;
    delete Plotfltk_Alpha_keyboard;
    delete w;
    if (!r)
      return undef;
    else
      return res;
  }

  gen fltk_inputform(const gen & args){
#ifndef WIN32
    if (!child_id)
      return _inputform(args);
#endif
    vecteur v(gen2vecteur(args));
    gen res=makeform(v);
#ifdef WIN32
    // post-analysis (done by _inputform under Unix)
    return inputform_post_analysis(v,res);
#endif
    return res;
  }

  void nextfl_menu(Fl_Menu_Item * & m){
    if (m->submenu()){
      ++m;
      for (;m->text;)
	nextfl_menu(m);
    }
    ++m;
  }

  vecteur fl_menu2rpn_menu(Fl_Menu_Item * & m){
    vecteur res;
    ++m;
    for (;m->text;++m){
      if (m->submenu()){
	string s=m->label();
	vecteur tmp(fl_menu2rpn_menu(m));
	res.push_back(makevecteur(string2gen(s,false),tmp));
      }
      else {
	gen g;
	int i=find_or_make_symbol(m->label(),g);
	// g=gen(string("'")+m->label()+string("'"));
	if (g.is_symb_of_sommet(at_quote))
	  g=g._SYMBptr->feuille; 
	res.push_back(g);
      }
    }
    return res;
  }

  void change_menu_fontsize(Fl_Menu * & m,int labelfontsize){
    if (!m->text)
      return;
    m->labelsize(labelfontsize);
    if (m->submenu()){
      ++m;
      for (;m->text;++m)
	change_menu_fontsize(m,labelfontsize);
    }
  }

  void change_group_fontsize(Fl_Group * g,int labelfontsize){
    Fl_Widget * o;
    Fl_Widget * const * ptr= g->array();
    int n=g->children();
    for (int i=0;i<n;++ptr,++i){
      o = *ptr;
      Fl_Menu * m=dynamic_cast<Fl_Menu *>(o);
      if (m){
	change_menu_fontsize(m,labelfontsize);
	continue;
      }
      Fl_Menu_Button * mb=dynamic_cast<Fl_Menu_Button *>(o);
      if (mb){
	Fl_Menu_Item * mm=(Fl_Menu_Item *)mb->menu();
	for (;mm->text;++mm)
	  change_menu_fontsize(mm,labelfontsize);
      }
      Fl_Input_ * in=dynamic_cast<Fl_Input_ * >(o);
      if (in)
	in->textsize(labelfontsize);
      Fl_Value_Input * v=dynamic_cast<Fl_Value_Input *>(o);
      if (v)
	v->textsize(labelfontsize);
      Fl_Browser * b=dynamic_cast<Fl_Browser *>(o);
      if (b)
	b->textsize(labelfontsize);
      Fl_Counter * cc=dynamic_cast<Fl_Counter *>(o);
      if (cc)
	cc->textsize(labelfontsize);
      Fl_Group * og=dynamic_cast<Fl_Group *>(o);
      if (og)
	change_group_fontsize(og,labelfontsize);
      else
	o->labelsize(labelfontsize);
    }
  }

  void change_menu_fontsize(Fl_Menu_Item * m,int n,int labelfontsize){
    for (int i=0;i<n;++i){
      change_menu_fontsize(m,labelfontsize);
      ++m;
    }
  }
  void change_button_fontsize(int labelfontsize){
    // Help_text_fontsize=labelfontsize;
    Help_font_output->value(print_INT_(Help_text_fontsize).c_str());
    xcas_output_fontsize=labelfontsize;
    History_font_output->value(print_INT_(labelfontsize).c_str());
    change_group_fontsize(Keyboard_group,labelfontsize);
    change_group_fontsize(Input_group,labelfontsize);
    Help_text->textsize(Help_text_fontsize);
    change_group_fontsize(Direction_group,labelfontsize);
    change_group_fontsize(Direction_group2,labelfontsize);
    change_group_fontsize(Plot_setup_w,labelfontsize);
    change_group_fontsize(Cas_setup_w,labelfontsize);
    change_group_fontsize(General_setup_w,labelfontsize);
    // change_group_fontsize(Help_group,labelfontsize);
    change_group_fontsize(Historique,labelfontsize);
    change_group_fontsize(Spread_group,labelfontsize);
    change_group_fontsize(Eqw_group,labelfontsize);
    change_group_fontsize(Programme,labelfontsize);
    change_group_fontsize(Help_Chooser,labelfontsize);
    // FLTK browser resize bug workaround
    Help_Chooser_Index->textsize(min(12,labelfontsize)); 
    change_group_fontsize(Debug_group,labelfontsize);
    Bighelp->textsize(labelfontsize);
    Eqw_history->attr.fontsize=labelfontsize;
    Eqw_eqw->attr.fontsize=labelfontsize;
    change_group_fontsize(Geo_buttons,labelfontsize);
    change_group_fontsize(Geo_buttons_tortue,labelfontsize);
    Picture->labelsize(labelfontsize);
#ifdef HAVE_LIBFLVW
    spread_ptr->global_style.font_size(labelfontsize);
    spread_ptr->global_style.height(labelfontsize+2);
    spread_ptr->labelsize(labelfontsize);
    // spread_ptr->row_width(labelfontsize+2,-1); ??
#endif
    Program_editor->textsize(labelfontsize);
    // int tmp=min(14,labelfontsize);
    Program_editor->labelsize(labelfontsize);
    /* for (int i=0;i<sizeof(styletable);++i)
      styletable[i].size=tmp; */
    Program_editor->redraw();    
    change_menu_fontsize(menu_xcas,10,labelfontsize);
    change_menu_fontsize(Spread_fill_menu,3,labelfontsize);
    Xcas->redraw();
  }

  string cut_help(const string & s,int fontsize,int w){
    if (s.empty())
      return s;
    int sw;
    // find 1st cut and add cut_help of the rest of the string to it
    int begin=0,taille=s.size(),end; // cut is between begin and first \n
    for (end=0;end<taille;++end){
      if (s[end]=='\n')
	break;
    }
    fl_font(FL_HELVETICA,fontsize);
    sw=int(fl_width(s.substr(0,end).c_str()));
    if (sw<w){
      if (end==taille)
	return s;
      return s.substr(0,end+1)+cut_help(s.substr(end+1,taille-end-1),fontsize,w);
    }
    for (;end-begin>2;){
      int pos=(begin+end)/2,i; // find 1st space after middlepoint
      for (i=pos;i>begin;--i){
	if (s[i]==' ')
	  break;
      }
      if (i==begin){ // no space before, try after
	for (i=pos;i<end;++i){
	  if (s[i]==' ')
	    break;
	}
      }
      if (i==end){ 
	// No space at all, return 0 -> begin or 0 -> end if begin==0
	if (begin)
	  pos=begin;
	else {
	  if (end)
	    pos=end;
	  else
	    return s;
	}
	if (pos==taille)
	  return s;
	return s.substr(0,pos)+'\n'+cut_help(s.substr(pos,taille-pos),fontsize,w);
      }
      sw=int(fl_width(s.substr(0,i).c_str()));
      if (sw<w)
	begin=i;
      else
	end=i;
    }
    return s.substr(0,end+1)+cut_help(s.substr(end+1,taille-end-1),fontsize,w);
  }
  void Image::add(const gen & e){ 
    plot_instructions.push_back(e); this->redraw(); 
  }

  void Image::add(const vecteur & v){
    plot_instructions=mergevecteur(plot_instructions,v); this->redraw(); 
  }

  int ckint(double d){
    int maxpixels=10000; // maximal number of horizontal or vertical pixels
    if (d>maxpixels)
      return maxpixels;
    if (d<-maxpixels)
      return -maxpixels;
    return int(floor(d));
  }

  // evalf_double of a and splt re/im
  void evalfdouble2reim(const gen & a,gen & e,gen & f0,gen & f1){
    try {
      e=a.evalf_double();
    } catch (std::runtime_error & error ){
      cerr << error.what() << endl;
    }
    if (e.type==_CPLX){
      f0=*e._CPLXptr;
      f1=*(e._CPLXptr+1);
    }
    else {
      f0=e;
      f1=0.0;
    }
  }

  void Image::findij(const gen & e0,double x_scale,double y_scale,int & i0,int & j0){
    gen e,f0,f1;
    evalfdouble2reim(e0,e,f0,f1);
    if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_)){
      i0=ckint((f0._DOUBLE_val-window_xmin)*x_scale+.5);
      j0=ckint((window_ymax-f1._DOUBLE_val)*y_scale+0.5);
      return;
    }
    // cerr << "Invalid drawing data" << endl;
  }

  int chooseinvecteur(const vecteur & v){
    int s=v.size();
    if (s==0)
      setsizeerr();
    if ((s==1) || (s>5))
      return 0;
    fl_font(FL_HELVETICA,10);
    fl_message_font(FL_HELVETICA,10);
    if (s==2)
      return fl_choice("Choose",v[0].print().c_str(),v[1].print().c_str(),NULL);
    if (s==3)
      return fl_choice("Choose",v[0].print().c_str(),v[1].print().c_str(),v[2].print().c_str());
    if (s==4)
      return fl_choice("Choose",v[0].print().c_str(),v[1].print().c_str(),v[2].print().c_str(),v[3].print().c_str());
    if (s==5)
      return fl_choice("Choose",v[0].print().c_str(),v[1].print().c_str(),v[2].print().c_str(),v[3].print().c_str(),v[4].print().c_str());
  }

  void input_before_selected_after(string & b,string & s,string & a){
    string t(input_value());
    if (t.empty()){
      b=t;
      s=t;
      a=t;
    }
    size_t sel1=input_position(),sel2=input_mark();
    if (sel1>sel2){
      int tmp=sel1;
      sel1=sel2;
      sel2=tmp;
    }
    b=t.substr(0,sel1);
    if (sel1<t.size())
      s=t.substr(sel1,sel2-sel1);
    else
      s=string();
    if (sel2<t.size())
      a=t.substr(sel2,t.size()-sel2);
    else
      a=string();
  }

  FL_EXPORT void Image::resize_halfscreen(){
    if (!fullscreen)
      return;
    int oldh=h();
    PICT_resize_halfscreen();
    window_ymin=window_ymax+((window_ymin-window_ymax)*h())/oldh;
    fullscreen=false;
    redraw_mouse_position_only=false;
    redraw();
  }
  FL_EXPORT void Image::resize_fullscreen(){
    if (fullscreen )
      return;
    int oldh=h();
    PICT_resize_fullscreen();
    window_ymin=window_ymax+((window_ymin-window_ymax)*h())/oldh;
    fullscreen=true;
    redraw_mouse_position_only=false;
    redraw();
  }

  string printsemi(){
    if (maple_mode==3)
      return "§";
    else
      return ";";
  }

  void xcas_history_select(int h){
    if (Eqw_History_group->visible()){
      Eqw_history_select(h);
      gen g=Eqw_history->get_selection();
      string s=g.print();
      Fl::selection(*Eqw_history,s.c_str(),s.size());
    }
    else {
      int tmp=history_positions[h];
      if (h)
	xcas_output->position(history_positions[h-1]+1,tmp);
      else
	xcas_output->position(0,tmp);
      // #ifdef __APPLE__ // should be ifdef FLTK_1_1
      xcas_output->copy(0);
      //#else
      //xcas_output->copy();
      //#endif
    }
  }


  string cas_recalc_name(){
    if (getenv("XCAS_TMP"))
      return getenv("XCAS_TMP")+("/#c#"+print_INT_(parent_id));
#ifdef WIN32
    return "#c#"+print_INT_(parent_id);
#endif
#ifdef IPAQ
    return "/tmp/#c#"+print_INT_(parent_id);
#endif
    return home_directory()+"#c#"+print_INT_(parent_id);
  }

  // PUSH: select unless moving is active
  // DRAG: if moving redraw figure, else redraw segment
  // RELEASE: if moving redraw figure, else input segment or point
  FL_EXPORT int Image::handle(int event){
    static bool first_move;
    if ( (event==FL_ENTER) || (event==FL_LEAVE) ){
      redraw_mouse_position_only=false;
      redraw();
      return 1;
    }
    if (event==FL_KEYBOARD){
      switch (Fl::event_key()){
      case FL_Escape: case FL_BackSpace: case FL_Tab: case FL_Enter: 
      case FL_Print: case FL_Scroll_Lock: case FL_Pause: case FL_Insert: 
      case FL_Home: case FL_Page_Up: case FL_Delete: case FL_End: 
      case FL_Page_Down: case FL_Left: case FL_Up: case FL_Right: 
      case FL_Down: case FL_Shift_L: case FL_Shift_R: case FL_Control_L: 
      case FL_Control_R: case FL_Caps_Lock: case FL_Alt_L: case FL_Alt_R: 
      case FL_Meta_L: case FL_Meta_R: case FL_Menu: case FL_Num_Lock: 
      case FL_KP_Enter:	
	return 1;
      }
      if (this==Picture)
	Fl::focus(input);
      return 0;
    }
    plot_instructionsh=h();
    plot_instructionsw=w();
    int horizontal_pixels=w()-LEGENDE_SIZE,vertical_pixels=h();
    double y_scale=(window_ymax-window_ymin)/vertical_pixels;
    double x_scale=(window_xmax-window_xmin)/horizontal_pixels;
    double y_size=window_ymax-window_ymin;
    double x_size=window_xmax-window_xmin;
    double eps;
    current_x=Fl::event_x()-deltax,current_y=Fl::event_y()-deltay;
    // If the child process expect a user entry, click -> complex number
    if ( !embedded && ((push_in_legende==-1 && signal_plot_parent) || waiting_click) ){
      if ( (event==FL_RELEASE) && (current_x < horizontal_pixels) && (current_y < vertical_pixels) ){
	gen a(window_xmin+current_x*x_scale,window_ymax-current_y*y_scale);
	if (waiting_click){
	  waiting_click_value=a;
	  waiting_click=false;
	  return 1;
	}
	input_value(a.print().c_str());
	input_eval(false);
      }
      return 1;
    }
    if (!embedded && waiting_click)
      return 1;
    if ( (embedded || user_screen  ) && event==FL_RELEASE && absint(current_x-x_push)<5 && absint(current_y-y_push)<5 ){
      if ( current_x>horizontal_pixels && current_y<COORD_SIZE){ // zoom out
	geo_zoom(1.414);
	return 1;
      }
      // move right/left/up/down
      if (current_y<8){ // up
	double d=(window_ymax-window_ymin)/20;
	window_ymax+=d;
	window_ymin+=d;
	redraw();
	if (this==Picture)
	  Picture2global_window();
      }
      if (current_y+8>h()){ // down
	double d=(window_ymax-window_ymin)/20;
	window_ymax-=d;
	window_ymin-=d;
	redraw();
	if (this==Picture)
	  Picture2global_window();
      }
      if (current_x<8){ // left
	double d=(window_xmax-window_xmin)/20;
	window_xmax-=d;
	window_xmin-=d;
	redraw();
	if (this==Picture)
	  Picture2global_window();
      }
      if (current_x+8>w()){ // right
	double d=(window_xmax-window_xmin)/20;
	window_xmax+=d;
	window_xmin+=d;
	redraw();
	if (this==Picture)
	  Picture2global_window();
      }
      Fl::get_mouse(dx,dy);
      dx -= current_x;
      dy -= current_y;
      return 1;
    }
    if (embedded || user_screen){
      if (event==FL_PUSH){
	red_draw=true;
	x_push=current_x;
	y_push=current_y;
	redraw();
      }
      if (event==FL_DRAG){
	red_draw=true;
	redraw();
      }
      if (event==FL_RELEASE){
	red_draw=false;
	if (absint(current_x-x_push)>20 && absint(current_y-y_push)>20 ){
	  window_xmax=window_xmin+max(current_x,x_push)*x_scale;
	  window_xmin=window_xmin+min(current_x,x_push)*x_scale;
	  window_ymin=window_ymax-max(current_y,y_push)*y_scale;
	  window_ymax=window_ymax-min(current_y,y_push)*y_scale;
	  if (this==Picture){
	    Picture2global_window();
	    string s(input_value());
	    input->value(geo_setup_string().c_str());
	    input_eval(false);
	    input_value(s.c_str());
	  }
	  redraw();
	}
      }
      return 1;
    }
    if (Xcas_turtle->value() && event==FL_RELEASE){
      if ( current_x>horizontal_pixels && current_y<COORD_SIZE){ // zoom out
	Picture->turtlezoom *= .707;
	Picture->redraw();
      }
      if (current_y<8){ // up
	Picture->turtley += int(Picture->h()/(5*Picture->turtlezoom));
	Picture->redraw();
      }
      if (current_y+8>h()){ // down
	Picture->turtley -= int(Picture->h()/(5*Picture->turtlezoom));
	Picture->redraw();
      }
      if (current_x<8){ // left
	Picture->turtlex -= int(Picture->w()/(5*Picture->turtlezoom));
	Picture->redraw();
      }
      if (current_x+8>w()){ // right
	Picture->turtlex += int(Picture->w()/(5*Picture->turtlezoom));
	Picture->redraw();
      }
      return 1;
    }
    if (embedded || Xcas_turtle->value() ){
      return 1;
    }
    // position inside parametric area
    if ( (current_x>horizontal_pixels) && !rpn_mode ){ 
      if (event==FL_PUSH){
	pretty_input=true;
	Recompute_history->value(true);
        Fl::get_mouse(dx,dy);
        dx -= current_x;
        dy -= current_y;
	push_in_legende=1;
      }
      if (event==FL_RELEASE){
	moving=false;
	selected.clear();
	redraw();
        red_draw=false;
	synchronize_history=true;	
	if (!push_in_legende){
	  push_in_legende=-1;
	  return 1;
	}
	else
	  push_in_legende=-1;
	if (current_y<COORD_SIZE) {
	  if (fullscreen)
	    resize_halfscreen();
	  else 
	    resize_fullscreen();
	  return 1;
	}
      }
      if (push_in_legende==0) // 0 means we are moving a geometric object
	return 1;
      if ( (current_y<COORD_SIZE) || 
	   ( (event!=FL_RELEASE) && (event!=FL_DRAG) && (event!=FL_PUSH)) 
	   )
	return 1;
      int j=(current_y-COORD_SIZE)/PARAM_STEP;
      if (j>=parameters.size())
	return 1;
      current_x=min(current_x,w());
      vecteur t=*parameters[j]._VECTptr;
      gen x=t[1]+double(current_x-horizontal_pixels)/double(LEGENDE_SIZE)*(t[2]-t[1]);
      if ( ( (current_y-COORD_SIZE) % PARAM_STEP < PARAM_STEP/3) && (event==FL_RELEASE)){
	const char * chaine=fl_input(("Enter new value for"+t[0].print()).c_str(),x.print().c_str());
	if (chaine){
	  string s(chaine);
	  try {
	    x=gen(s);
	  }
	  catch(std::runtime_error & e){
	    cerr << e.what() << endl;
	  }
	}
      }
      x=x.evalf_double();
      if (x.type!=_DOUBLE_)
	return 1;
      const_iterateur it=history_in.begin()+erase_pos(),itend=history_in.end();
      int is_element=0;
      for (;it!=itend;++it){       // find element() or assume in history
	if (it->type==_SYMB){
	  if ( (it->_SYMBptr->sommet==at_sto) 
	       && (it->_SYMBptr->feuille._VECTptr->back()==t.front()) ){
	    is_element=1;
	    break;
	  }
	  if ( (it->_SYMBptr->sommet==at_assume)
	       && (it->_SYMBptr->feuille.type==_SYMB) ){
	    if ( (it->_SYMBptr->feuille._SYMBptr->sommet==at_equal || it->_SYMBptr->feuille._SYMBptr->sommet==at_same )
	         && (it->_SYMBptr->feuille._SYMBptr->feuille._VECTptr->front()==t.front()) ){
	      is_element=-1;
	      break;
	    }
	    if ( (it->_SYMBptr->feuille._SYMBptr->sommet==at_sto)
	         && (it->_SYMBptr->feuille._SYMBptr->feuille._VECTptr->back()==t.front()) ){
	      is_element=-2;
	      break;
	    }
	  }
	}
      } // end for loop
      if (!is_element)
	return 1;
      gen e;
      vecteur v;
      switch (is_element){
      case -1:
	v=*it->_SYMBptr->feuille._SYMBptr->feuille._VECTptr;
	v.back()=makevecteur(x,t[1],t[2]);
	e=symbolic(at_equal,v);
	e=symbolic(at_assume,e);
	break;
      case 1:
	e=it->_SYMBptr->feuille._VECTptr->front();
	if ( (e.type!=_SYMB) || (e._SYMBptr->sommet!=at_element))
	  return 1;
	e=e._SYMBptr->feuille;
	if ( (e.type==_VECT) && (e._VECTptr->size()) )
	  e=e._VECTptr->front();
	e=symbolic(at_element,makevecteur(e,x));
	e=symbolic(at_sto,makevecteur(e,t.front()));
	break;
      case -2:
	v=*it->_SYMBptr->feuille._SYMBptr->feuille._VECTptr;
	v.front()=makevecteur(x,t[1],t[2]);
	e=symbolic(at_sto,v);
	e=symbolic(at_assume,e);
	break;
      }
      history_position=it-history_in.begin();
      run_modif_pos=history_position;
      run_modif=true;
      int save_digits=decimal_digits;
      decimal_digits=3;
      input_value(e.print().c_str());
      decimal_digits=save_digits;
      input_eval(false);
      run_modif=false;
      return 1;
    } // end position inside parametric area

    // we are inside the geometric area
    if (push_in_legende==1) // 1 means we are moving a parameter
      return 1;
    if (event==FL_PUSH){
      pretty_input=true;
      Recompute_history->value(true);
      push_in_legende=0;
    }
    if (event==FL_RELEASE)
      push_in_legende=-1;
    if (y_size<x_size)
      eps=(npixels*y_size)/vertical_pixels;
    else
      eps=(npixels*x_size)/horizontal_pixels;
    // an object is being moved
    if ( moving && ( (event==FL_PUSH) || (event==FL_RELEASE) || (event==FL_DRAG) ) ){
      int deltax=current_x-x_push,deltay=current_y-y_push;
      if (event==FL_RELEASE){
	moving=false;
	x_push=current_x;
	y_push=current_y;
	selected.clear();
	redraw();
        red_draw=false;
      }
      else
	red_draw=true;
      if (first_move)
	first_move=false;
      else
	synchronize_history=(event!=FL_DRAG);	
      run_modif_pos=history_position;
#ifdef WIN32
      undo_history_out=history_out;
      undo_history_in=history_in;
      if (run_modif_pos<history_in.size()){
	if ( ((absint(deltax)<npixels) && (absint(deltay)<npixels)) || (current_x>horizontal_pixels) || (current_y > vertical_pixels) )
	  history_in[run_modif_pos]=debut_gen;
	else {
	  gen tmp=debut_gen;
	  if (tmp.is_symb_of_sommet(at_sto)){
	    gen & f=tmp._SYMBptr->feuille;
	    if (f.type==_VECT && f._VECTptr->size()==2){
	      tmp=symbolic(at_sto,makevecteur(f._VECTptr->front()+gen(deltax*x_scale,-deltay*y_scale),f._VECTptr->back()));
	      history_in[run_modif_pos]=tmp;
	    }
	  }
	}
	win32_recalc_history();
      }
#else
      int save_digits=decimal_digits;
      decimal_digits=3;
      string s;
      if ( ((absint(deltax)<npixels) && (absint(deltay)<npixels)) || (current_x>horizontal_pixels) || (current_y > vertical_pixels) )
	s=debut;
      else
	s=debut+"+("+gen(deltax*x_scale,-deltay*y_scale).print()+")";
      //cerr << s << endl;
      input_value(s.c_str());
      decimal_digits=save_digits;
      run_modif=true;
      input_eval(false);
      run_modif=false;
#endif
      return 1;
    }

    // select or begin move
    if (event==FL_PUSH){
      red_draw=true;
      Fl::get_mouse(dx,dy);
      dx -= current_x;
      dy -= current_y;
      if ( !rpn_mode && (absint(current_x-x_push)<npixels ) 
	   && (absint(current_y-y_push)<npixels)
	   && (!selected.empty()) ){ // double-click -> move
	moving=true;
	first_move=true;
      }
      else {
	x_push=current_x;
	y_push=current_y;
      }
      return 1;
    }

    // no object moving, we are drawing a point or segment
    // don't do anything before release
    if (event==FL_DRAG){ 
      // should memorize intermediate positions for direct polygon drawing?
      redraw();
      return 1;
    }

    if (event==FL_RELEASE){ 
      // draw line/point 
      red_draw=false;
      synchronize_history=true;	
      redraw();
      if ( (current_x>horizontal_pixels) || (current_y>vertical_pixels) ) 
	return 1; // cancel
      gen p(window_xmin+x_push*x_scale,window_ymax-y_push*y_scale);
      int save_digits=decimal_digits;
      decimal_digits=3;
      string fin=symb_point(window_xmin+current_x*x_scale,window_ymax-current_y*y_scale).print();
      decimal_digits=save_digits;
      selected=nearest_point(plot_instructions,p,eps,0);

      // if release occurs near push draw a point or select an object
      if ( (absint(current_x-x_push)<npixels) && (absint(current_y-y_push)<npixels) ){ 
	if (rpn_mode){
	  input_value(("'"+PICTautoname+":="+fin+"' eval").c_str());
	  PICTautoname_plus_plus();
	  input_eval(false);
	  return 1;
	}
	if (selected.empty()){
	  input_value((PICTautoname+":="+fin).c_str());
	  PICTautoname_plus_plus();
	  input_eval(false);
	  return 1;
	}
	gen res;
	int pnt_pos;
	if ( (find_best(selected,p,eps,-1,pnt_pos,history_position,res) && pnt_pos==-1)){ 
	  selected.clear();
	  input_value((PICTautoname+":="+res.print()).c_str());
	  PICTautoname_plus_plus();
	  input_eval(false);
	  return 1;
	}
	string b,s,t;
	input_before_selected_after(b,s,t);
	s=b;

	if (pnt_pos==-1)
	  history_position=erase_pos()+selected[chooseinvecteur(selection2vecteur(selected))];
	xcas_history_select(history_position);
	bool save_maple_mode=maple_mode;
	maple_mode=0;
	debut_gen=history_in[history_position];
	debut=debut_gen.print();
	maple_mode=save_maple_mode;
	// cerr << debut << endl;
	gen e=remove_sto(history_in[history_position]);
	int j=s.size();
	if (j && (s[j-1]!='('))
	  s +=',';
	s += e.print();
	if (t.size() && (t[0]==','))
	  t = t.substr(1,t.size()-1);
	s += t;
	input_value(s.c_str());
	j=s.size()-t.size();
	input_position(j,j);
	return 1;
      }

      // release not near push: draw a segment
      gen q(window_xmin+current_x*x_scale,window_ymax-current_y*y_scale);
      vector<int> fin_selected=nearest_point(plot_instructions,q,eps,0);
      gen e;
      int pnt_pos1,pnt_pos2;
      ofstream of(cas_recalc_name().c_str());
      if (!selected.empty() && find_best(selected,p,eps,-1,pnt_pos1,history_position,e)){
	bool save_maple_mode=maple_mode;
	maple_mode=0;
	debut_gen=e;
	debut=e.print();
	maple_mode=save_maple_mode;
      }
      else {
	int save_digits=decimal_digits;
	decimal_digits=3;
	of << PICTautoname << ":="<< symb_point(window_xmin+x_push*x_scale,window_ymax-y_push*y_scale) << printsemi() << endl;
	debut=PICTautoname;
	PICTautoname_plus_plus();
	decimal_digits=save_digits;
	history_position=-1;
      }
      if (!fin_selected.empty() && find_best(fin_selected,q,eps,history_position,pnt_pos2,history_position,e) ){
	gen ee=remove_at_pnt(e);
	if ( (ee.type==_SYMB) && (ee._SYMBptr->sommet==at_milieu)){
	  of << PICTautoname << ":=" << e << printsemi() << endl;
	  fin=PICTautoname;
	  PICTautoname_plus_plus();
	}
	else {
	  fin=e.print();
	}
      }
      else {
	of << PICTautoname << ":=" << fin << printsemi() << endl;
	fin=PICTautoname;
	PICTautoname_plus_plus();
      }
      string segment_name;
      if ( (debut.size()==1) && (fin.size()==1) )
	segment_name=debut+fin;
      else
	segment_name=PICTautoname;
      segment_name=segment_name+":=segment("+debut+","+fin+ ")";
      of << segment_name << endl;
      input_value(segment_name.c_str());
      of.close();
      run_file(cas_recalc_name().c_str());
      x_push=current_x;
      y_push=current_y;
      selected.clear();
      return 1;
    }

    // event not handeld by geometric/parametric screen
    // give focus to input
    //Fl::focus(input);
    return 0;
  }

  inline void swapint(int & i0,int & i1){
    int tmp=i0;
    i0=i1;
    i1=tmp;
  }

  // Calls fl_line, checking with bounds
  void check_fl_line(int i0,int j0,int i1,int j1,int imin,int jmin,int imax,int jmax,int delta_i,int delta_j){
    if (i0>i1){
      swapint(i0,i1);
      swapint(j0,j1);
    }
    if (i0>=imax || i1<=imin)
      return;
    if (i0!=i1){
      // Compute line slope
      double m=(j1-j0)/double(i1-i0);
      if (i0<imin){ // replace i0 by imin, compute corresp. j0
	j0 += int(floor((imin-i0)*m+.5));
	i0 = imin;
      }
      if (i1>imax){
	j1 += int(floor((imax-i1)*m+.5));
	i1 = imax;
      }
    }
    if (j0>j1){
      if (j1>=jmax || j0<=jmin)
	return;
      // Compute line slope
      double m=(i1-i0)/double(j1-j0);
      if (j0>jmax){
	i0 += int(floor((jmax-j0)*m+.5));
	j0 = jmax;
      }
      if (j1<jmin){
	i1 += int(floor((jmin-j1)*m+.5));
	j1 = jmin;
      }
    }
    else {
      if (j0>=jmax || j1<=jmin)
	return;
      if (j0!=j1){
	// Compute line slope
	double m=(i1-i0)/double(j1-j0);
	if (j0<jmin){
	  i0 += int(floor((jmin-j0)*m+.5));
	  j0 = jmin;
	}
	if (j1>jmax){
	  i1 += int(floor((jmax-j1)*m+.5));
	  j1 = jmax;
	}
      }
    }
    fl_line(i0+delta_i,j0+delta_j,i1+delta_i,j1+delta_j);
  }

  void draw_legende(const vecteur & f,int i0,int j0,int labelpos,const Image * iptr){
    if (f.size()<3)
      return;
    const gen & legende=f[2];
    string legendes(gen2string(legende));
    int dx=3,dy=1;
    fl_font(FL_HELVETICA,iptr->labelsize());
    int l=int(fl_width(legendes.c_str()));
    switch (labelpos){
    case 1:
      dx=-l-3;
      break;
    case 2:
      dx=-l-3;
      dy=iptr->labelsize()-2;
      break;
    case 3:
      dy=iptr->labelsize()-2;
      break;
    }
    fl_draw(legendes.c_str(),iptr->deltax+i0+dx,iptr->deltay+j0+dy);
  }

  // helper for Image::draw method
  // plot_i is the position we are drawing in plot_instructions
  // f is the vector of arguments and s is the function: we draw s(f)
  // legende_x is the x position in pixels of the parameter subwindow
  // parameter_y is the current y position for parameter drawing
  // x_scale and y_scale are the current scales
  // horizontal_pixels and vertical_pixels the size of the window
  void fltkdraw(Image & Mon_image,int plot_i,const gen & g,double x_scale,double y_scale,int horizontal_pixels,int vertical_pixels){
    if (g.type==_VECT){
      vecteur & v =*g._VECTptr;
      const_iterateur it=v.begin(),itend=v.end();
      for (;it!=itend;++it){
	fltkdraw(Mon_image,plot_i,*it,x_scale,y_scale,horizontal_pixels,vertical_pixels);
	fl_line_style(0); // back to default line style
      } // end for it
    }
    if (g.type!=_SYMB)
      return;
    unary_function_ptr s=g._SYMBptr->sommet;
    if (g._SYMBptr->feuille.type!=_VECT)
      return;
    vecteur f=*g._SYMBptr->feuille._VECTptr;
    int mx=Mon_image.x(),mxw=Mon_image.w(),my=Mon_image.y(),myw=Mon_image.h(),mdx=Mon_image.deltax,mdy=Mon_image.deltay;
    int i0,j0,i0save,j0save,i1,j1;
    int fs=f.size();
    if ((fs==4) && (s==at_parameter)){
      return ;
    }
    vecteur style(1,FL_BLACK);
    if (fs>1){
      gen f1(f[1]);
      if ( f1.type==_VECT && !f1._VECTptr->empty() )
	gen f1=f[1]._VECTptr->front();
      int typ=f1.type;
      if (typ==_INT_ )
	style.front()=f[1];
      if ( typ==_SYMB ){
	gen & f2 =f1._SYMBptr->feuille;
	if (f2.type==_VECT)
	  style=*f2._VECTptr;
	else
	  style.front()=f2;
      }
    }
    // color
    int ensemble_attributs=style.front().val;
    int width           =(ensemble_attributs & 0x00070000) >> 16; // 3 bits
    int epaisseur_point =(ensemble_attributs & 0x00380000) >> 19; // 3 bits
    int type_line       =(ensemble_attributs & 0x01c00000) >> 22; // 3 bits
    int type_point      =(ensemble_attributs & 0x0e000000) >> 25; // 3 bits
    int labelpos        =(ensemble_attributs & 0x30000000) >> 28; // 2 bits
    bool fill_polygon   =(ensemble_attributs & 0x40000000) >> 30;
    int couleur         =(ensemble_attributs & 0x0000ffff);
    if (!epaisseur_point)
      epaisseur_point=2;
    if (s==at_pnt){ 
      // f[0]=complex pnt or vector of complex pnts or symbolic
      // f[1] -> style 
      // f[2] optional=label
      gen point=f[0];
      if (point.type==_VECT && point.subtype==_POINT__VECT)
	return;
      if ( (f[0].type==_SYMB) && (f[0]._SYMBptr->sommet==at_curve) && (f[0]._SYMBptr->feuille.type==_VECT) && (f[0]._SYMBptr->feuille._VECTptr->size()) )
	point=f[0]._SYMBptr->feuille._VECTptr->back();
      if (is_undef(point))
	return;
      if ( equalposcomp(Mon_image.selected,plot_i))
	fl_color(FL_BLUE);
      else
	fl_color(couleur);
      fl_line_style(type_line,width,0); // FIXME type_line 
      if (point.type==_SYMB) {
	if (point._SYMBptr->sommet==at_hyperplan || point._SYMBptr->sommet==at_hypersphere)
	  return;
	if (point._SYMBptr->sommet==at_cercle){
	  vecteur v=*point._SYMBptr->feuille._VECTptr;
	  gen diametre=remove_at_pnt(v[0]);
	  gen e1=diametre._VECTptr->front().evalf_double(),e2=diametre._VECTptr->back().evalf_double();
	  gen centre=rdiv(e1+e2,2.0);
	  Mon_image.findij(centre,x_scale,y_scale,i0,j0);
	  gen diam=abs(e1-e2,0).evalf_double();
	  bool rad=angle_radian(0);
	  angle_radian(true,0);
	  gen angle=arg(e2-e1,0).evalf_double();
	  angle_radian(rad,0);
	  gen a1=v[1].evalf_double(),a2=v[2].evalf_double();
	  if ( (diam.type==_DOUBLE_) && (a1.type==_DOUBLE_) && (a2.type==_DOUBLE_) ){
	    i1=int((diam._DOUBLE_val)*x_scale/2.0+.5);
	    j1=int((diam._DOUBLE_val)*y_scale/2.0+.5);
	    double a1d=a1._DOUBLE_val,a2d=a2._DOUBLE_val,angled=angle._DOUBLE_val;
	    if (a1d>a2d){
	      double tmp=a1d;
	      a1d=a2d;
	      a2d=tmp;
	    }
	    if (fill_polygon)
	      fl_pie(mdx+i0-i1,mdy+j0-j1,mdx+2*i1,mdy+2*j1,(angled+a1d)*180/M_PI,(angled+a2d)*180/M_PI);
	    else 
	      fl_arc(mdx+i0-i1,mdy+j0-j1,mdx+2*i1,mdy+2*j1,(angled+a1d)*180/M_PI,(angled+a2d)*180/M_PI);
	    // Label a few degrees from the start angle, 
	    // FIXME should use labelpos
	    i0=i0+int(i1*std::cos(angled+a1d+0.3)); 
	    j0=j0-int(j1*std::sin(angled+a1d+0.3));
	    draw_legende(f,i0,j0,labelpos,&Mon_image);
	    return;
	  }
	} // end circle
	if (point._SYMBptr->sommet==at_pixon){
	  // pixon (i,j,color,xmin,xmax,ymin,ymax)
	  if (point._SYMBptr->feuille.type!=_VECT)
	    return;
	  vecteur &v=*point._SYMBptr->feuille._VECTptr;
	  if (v.size()<3 || v[0].type!=_INT_ || v[1].type!=_INT_ || v[2].type!=_INT_)
	    return;
	  int delta_i=v[0].val,delta_j=v[1].val;
	  fl_color(v[2].val);
#ifdef IPAQ
	  if (delta_i>0 && delta_i<mxw && delta_j>0 && delta_j<myw)
	    fl_point(mdx+delta_i,mdy+delta_j);
#else
	  delta_i *= 2;
	  delta_j *= 2;
	  if (delta_i>0 && delta_i<mxw && delta_j>0 && delta_j<myw){
	    fl_point(mdx+delta_i,mdy+delta_j);
	    fl_point(mdx+delta_i,mdy+delta_j+1);
	    fl_point(mdx+delta_i+1,mdy+delta_j);
	    fl_point(mdx+delta_i+1,mdy+delta_j+1);
	  }
#endif
	  return;
	}
	if (point._SYMBptr->sommet==at_bitmap){
	  // bitmap(vector of int (1 per line)), 1st line, 1st col, [type]
	  if (point._SYMBptr->feuille.type!=_VECT)
	    return;
	  vecteur &v=*point._SYMBptr->feuille._VECTptr;
	  if (v.size()<3 || v[0].type!=_VECT || v[1].type!=_INT_ || v[2].type!=_INT_ )
	    return;
	  int delta_i=v[1].val,delta_j=v[2].val;
	  double xmin=Mon_image.window_xmin,ymin=Mon_image.window_ymin,xmax=Mon_image.window_xmax,ymax=Mon_image.window_ymax;
	  //gen psize=_Pictsize(0);
	  int picth=myw;
	  int bitmap_w=mxw-LEGENDE_SIZE,bitmap_h=picth;
	  if (v.size()>8){
	    xmin=v[3]._DOUBLE_val;
	    xmax=v[4]._DOUBLE_val;
	    ymin=v[5]._DOUBLE_val;
	    ymax=v[6]._DOUBLE_val;
	    bitmap_w=v[7].val;
	    bitmap_h=v[8].val;
	  }
	  double bitmap_scalex=(xmax-xmin)/bitmap_w,scalex=(Mon_image.window_xmax-Mon_image.window_xmin)/(mxw-LEGENDE_SIZE);
	  double bitmap_scaley=(ymax-ymin)/bitmap_h,scaley=(Mon_image.window_ymax-Mon_image.window_ymin)/picth;
	  double X,Y;
	  int ii,jj;
	  const_iterateur it=v[0]._VECTptr->begin(),itend=v[0]._VECTptr->end();
	  for (;it!=itend;++it,++delta_i){
	    if (it->type!=_INT_ && it->type!=_ZINT)
	      continue;
	    gen z=*it;
	    mpz_t zz,zr;
	    if (it->type==_INT_)
	      mpz_init_set_ui(zz,it->val);
	    else
	      mpz_init_set(zz,*it->_ZINTptr);
	    mpz_init(zr);
	    for (int j=delta_j;mpz_sgn(zz);++j){
	      mpz_tdiv_r_2exp (zr, zz, 1);
	      mpz_tdiv_q_2exp (zz, zz, 1);
	      if (mpz_sgn(zr)){
		X=xmin+j*bitmap_scalex;
		ii=int(0.5+(X-Mon_image.window_xmin)/scalex);
		Y=ymax-delta_i*bitmap_scaley;
		jj=int(0.5+(Mon_image.window_ymax-Y)/scaley);
		if (ii>0 && ii<mxw && jj>0 && jj<myw)
		  fl_point(mdx+ii,mdy+jj);
	      }
	    }
	    mpz_clear(zr);
	    mpz_clear(zz);
	  }
	  return;
	} // end bitmap
      } // end point.type==_SYMB
      if (point.type!=_VECT){ // single point
	Mon_image.findij(point,x_scale,y_scale,i0,j0);
	if (i0>0 && i0<mxw && j0>0 && j0<myw){
	  switch (type_point){
	  case 1: // losange
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0,mdy+j0-epaisseur_point);
	    fl_line(mdx+i0,mdy+j0-epaisseur_point,mdx+i0+epaisseur_point,mdy+j0);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0,mdy+j0+epaisseur_point);
	    fl_line(mdx+i0,mdy+j0+epaisseur_point,mdx+i0+epaisseur_point,mdy+j0);
	    break;
	  case 2: // croix verticale
	    fl_line(mdx+i0,mdy+j0-epaisseur_point,mdx+i0,mdy+j0+epaisseur_point);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0+epaisseur_point,mdy+j0);
	    break;
	  case 3: // carre
	    fl_line(mdx+i0-epaisseur_point,mdy+j0-epaisseur_point,mdx+i0-epaisseur_point,mdy+j0+epaisseur_point);
	    fl_line(mdx+i0+epaisseur_point,mdy+j0-epaisseur_point,mdx+i0+epaisseur_point,mdy+j0+epaisseur_point);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0-epaisseur_point,mdx+i0+epaisseur_point,mdy+j0-epaisseur_point);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0+epaisseur_point,mdx+i0+epaisseur_point,mdy+j0+epaisseur_point);
	    break;
	  case 5: // triangle
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0,mdy+j0-epaisseur_point);
	    fl_line(mdx+i0,mdy+j0-epaisseur_point,mdx+i0+epaisseur_point,mdy+j0);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0+epaisseur_point,mdy+j0);
	    break;
	  case 7: // point
	    fl_point(mdx+i0,mdy+j0);
	    break;
	  case 6: // etoile
	    fl_line(mdx+i0-epaisseur_point,mdy+j0,mdx+i0+epaisseur_point,mdy+j0);
	  default: // 0 et 4 croix diagonale
	    fl_line(mdx+i0-epaisseur_point,mdy+j0-epaisseur_point,mdx+i0+epaisseur_point,mdy+j0+epaisseur_point);
	    fl_line(mdx+i0-epaisseur_point,mdy+j0+epaisseur_point,mdx+i0+epaisseur_point,mdy+j0-epaisseur_point);
	    break;
	  }
	}
	draw_legende(f,i0,j0,labelpos,&Mon_image);
	return;
      }
      // path
      const_iterateur jt=point._VECTptr->begin(),jtend=point._VECTptr->end();
      if (jt==jtend)
	return;
      if (jt->type==_VECT)
	return;
      // initial point
      Mon_image.findij(*jt,x_scale,y_scale,i0,j0);
      if (fill_polygon && *jt==*(jtend-1)){
	gen e,f0,f1;
	fl_begin_complex_polygon();
	for (;jt!=jtend;++jt){
	  evalfdouble2reim(*jt,e,f0,f1);
	  if ((f0.type==_DOUBLE_) && (f1.type==_DOUBLE_))
	    fl_vertex(f0._DOUBLE_val,f1._DOUBLE_val);
	}
	fl_end_complex_polygon();
	draw_legende(f,i0,j0,labelpos,&Mon_image);
	return;
      }
      i0save=i0;
      j0save=j0;
      ++jt;
      if (jt==jtend){
	if (i0>0 && i0<mxw && j0>0 && j0<myw)
	  fl_point(mdx+i0,mdy+j0);
	draw_legende(f,i0,j0,labelpos,&Mon_image);
	return;
      }
      // rest of the path
      for (;;){
	Mon_image.findij(*jt,x_scale,y_scale,i1,j1);
	check_fl_line(i0,j0,i1,j1,0,0,mxw,myw,mdx,mdy);
	++jt;
	if (jt==jtend){ // label of line at midpoint
	  i0=(i0+i1)/2-8;
	  j0=(j0+j1)/2;
	  break;
	}
	i0=i1;
	j0=j1;
      }
      // check for a segment/halfline/line
      if ( ((point.subtype==_LINE__VECT)|| (point.subtype==_HALFLINE__VECT) ) && (point._VECTptr->size()==2)){
	int deltai=i1-i0save;
	int deltaj=j1-j0save;
	if (point.subtype==_LINE__VECT)
	  check_fl_line(i0save-10*deltai,j0save-10*deltaj,i1+10*deltai,j1+10*deltaj,0,0,mxw,myw,mdx,mdy);
	else
	  check_fl_line(i0save,j0save,i1+10*deltai,j1+10*deltaj,0,0,mxw,myw,mdx,mdy);
      }
      if ( (point.subtype==_GROUP__VECT) && (point._VECTptr->size()==2))
	;
      else
	draw_legende(f,i0,j0,labelpos,&Mon_image);
    } // end pnt subcase

  }
    
  FL_EXPORT void Image::draw(){
    plot_instructionsh=h();
    plot_instructionsw=w();
    int horizontal_pixels=w()-LEGENDE_SIZE,vertical_pixels=h();
    double y_scale=vertical_pixels/(window_ymax-window_ymin);
    double x_scale=horizontal_pixels/(window_xmax-window_xmin);
    // Check for fast redraw
    // Then redraw the background
    fl_color(FL_WHITE);
    if (red_draw || embedded)
      redraw_mouse_position_only=false;
    if (!redraw_mouse_position_only)
      fl_rectf(deltax, deltay, w(), h());
    int legende_x=w()-LEGENDE_SIZE;
    // Show mouse or show turtle position/cap
    if (turtleptr && !turtleptr->empty() && Xcas_turtle->value()){
      logo_turtle turtle=turtleptr->back();
      fl_color(FL_YELLOW);
      fl_rectf(deltax+legende_x,deltay,w()-deltax-legende_x,2*COORD_SIZE);
      fl_color(FL_BLACK);
      fl_rect(deltax, deltay, w(), h());
      fl_font(FL_HELVETICA,labelsize());
      fl_draw(("x "+print_INT_(int(turtle.x+.5))).c_str(),deltax+legende_x,deltay+(2*COORD_SIZE)/3-2);
      fl_draw(("y "+print_INT_(int(turtle.y+.5))).c_str(),deltax+legende_x,deltay+(4*COORD_SIZE)/3-3);
      fl_draw(("t "+print_INT_(int(turtle.theta+.5))).c_str(),deltax+legende_x,deltay+2*COORD_SIZE-4);
    }
    else {
      if (user_screen)
	fl_color(FL_GREEN);
      else
	fl_color(FL_CYAN);
      fl_rectf(deltax+legende_x,deltay,w()-deltax-legende_x,COORD_SIZE);
      fl_color(FL_BLACK);
      fl_rect(deltax, deltay, w(), h());
      fl_font(FL_HELVETICA,labelsize());
      if ( (dx>=0) && (dy>=0) ){
	int save_digits=decimal_digits;
	decimal_digits=3;
	int cur_x,cur_y;
	Fl::get_mouse(cur_x,cur_y);
	double d_mouse_x=window_xmin+(cur_x-dx)/x_scale;
	double d_mouse_y=window_ymax-(cur_y-dy)/y_scale;
	gen mouse_x(d_mouse_x),mouse_y(d_mouse_y);
	fl_draw(("x:"+mouse_x.print()).c_str(),deltax+legende_x,deltay+COORD_SIZE/2-2);
	fl_draw(("y:"+mouse_y.print()).c_str(),deltax+legende_x,deltay+COORD_SIZE-2);
	decimal_digits=save_digits;
      }
    }
    if (redraw_mouse_position_only){      
      redraw_mouse_position_only=false;
      return;
    }
    // draw turtle Logo
    if (turtleptr && Xcas_turtle->value()){
      int l=turtleptr->size();
      if (l>0){
	logo_turtle prec =(*turtleptr)[0];
	for (int k=1;k<l;++k){
	  logo_turtle current =(*turtleptr)[k];
	  if (!current.s.empty()){ // Write a string
	    fl_font(FL_HELVETICA,current.radius);
	    fl_color(current.color);
	    fl_draw(current.s.c_str(),int(deltax+turtlezoom*(current.x-turtlex)),int(deltay+h()-turtlezoom*(current.y-turtley)));
	  }
	  else {
	    if (current.radius>0){
	      int r=current.radius & 0x1ff; // bit 0-8
	      double theta1,theta2;
	      if (current.direct){
		theta1=prec.theta+double((current.radius >> 9) & 0x1ff); // bit 9-17
		theta2=prec.theta+double((current.radius >> 18) & 0x1ff); // bit 18-26
	      }
	      else {
		theta1=prec.theta-double((current.radius >> 9) & 0x1ff); // bit 9-17
		theta2=prec.theta-double((current.radius >> 18) & 0x1ff); // bit 18-26
	      }
	      bool rempli=(current.radius >> 27) & 0x1;
	      double angle;
	      int x,y,X,Y,R;
	      R=int(2*turtlezoom*r+.5);
	      angle = M_PI/180*(theta2-90);
	      if (current.direct){
		x=int(turtlezoom*(current.x-turtlex-r*std::cos(angle) - r)+.5);
		y=int(turtlezoom*(current.y-turtley-r*std::sin(angle) + r)+.5);
	      }
	      else {
		x=int(turtlezoom*(current.x-turtlex+r*std::cos(angle) -r)+.5);
		y=int(turtlezoom*(current.y-turtley+r*std::sin(angle) +r)+.5);
	      }
	      fl_color(current.color);
	      if (current.direct){
		if (rempli)
		  fl_pie(deltax+x,deltay+h()-y,R,R,theta1-90,theta2-90);
		else
		  fl_arc(deltax+x,deltay+h()-y,R,R,theta1-90,theta2-90);
	      }
	      else {
		if (rempli)
		  fl_pie(deltax+x,deltay+h()-y,R,R,90+theta2,90+theta1);
		else
		  fl_arc(deltax+x,deltay+h()-y,R,R,90+theta2,90+theta1);
	      }
	    } // end radius>0
	    else {
	      if (prec.mark){
		fl_color(prec.color);
		fl_line(deltax+int(turtlezoom*(prec.x-turtlex)+.5),deltay+int(h()+turtlezoom*(turtley-prec.y)+.5),deltax+int(turtlezoom*(current.x-turtlex)+.5),deltay+int(h()+turtlezoom*(turtley-current.y)+.5));
	      }
	    }
	    if (current.radius<-1 && k+current.radius>=0){
	      // poly-line from (*turtleptr)[k+current.radius] to (*turtleptr)[k]
	      fl_begin_complex_polygon();
	      for (int i=0;i>=current.radius;--i){
		logo_turtle & t=(*turtleptr)[k+i];
		fl_vertex(deltax+turtlezoom*(t.x-turtlex),deltay+h()+turtlezoom*(turtley-t.y));
	      }
	      fl_vertex(deltax+turtlezoom*(current.x-turtlex),deltay+h()+turtlezoom*(turtley-current.y));
	      fl_end_complex_polygon();
	    }
	  } // end else (non-string turtle record)
	  prec=current;
	} // end for (all turtle records)
	logo_turtle & t = (*turtleptr)[l-1];
	int x=int(turtlezoom*(t.x-turtlex)+.5);
	int y=int(turtlezoom*(t.y-turtley)+.5);
	double cost=std::cos(t.theta*deg2rad_d);
	double sint=std::sin(t.theta*deg2rad_d);
	int Dx=int(turtlezoom*t.turtle_length*cost/2+.5);
	int Dy=int(turtlezoom*t.turtle_length*sint/2+.5);
	fl_color(t.color);
	if (t.visible){
	  fl_line(deltax+x+Dy,deltay+h()-(y-Dx),deltax+x-Dy,deltay+h()-(y+Dx));
	  if (!t.mark)
	    fl_color(t.color+1);
	  fl_line(deltax+x+Dy,deltay+h()-(y-Dx),deltax+x+3*Dx,deltay+h()-(y+3*Dy));
	  fl_line(deltax+x-Dy,deltay+h()-(y+Dx),deltax+x+3*Dx,deltay+h()-(y+3*Dy));
	}
      }
      return;
    } // End logo mode
    // Draw axis
    parameters.clear();
    int parameter_y=COORD_SIZE+PARAM_STEP;
    int i_0,j_0;
    findij(zero,x_scale,y_scale,i_0,j_0);
    if ( show_axes && (window_ymax>=0) && (window_ymin<=0)){ // X-axis
      fl_color(FL_BLACK);
      fl_line(deltax,deltay+j_0,deltax+horizontal_pixels,deltay+j_0); 
      if (user_screen)
	fl_color(FL_GREEN);
      else
	fl_color(FL_CYAN);
      fl_line(deltax+i_0,deltay+j_0,deltax+i_0+int(x_scale),deltay+j_0);
      if (x_tick>0 && (w()-LEGENDE_SIZE)/(x_scale*x_tick) < 50){
	fl_color(FL_BLACK);
	int nticks=int((w()-LEGENDE_SIZE-i_0)/(x_scale*x_tick));
	for (int ii=int(-i_0/(x_tick*x_scale));ii<=nticks;++ii){
	  int iii=i_0+int(ii*x_scale*x_tick);
	  fl_line(deltax+iii,deltay+j_0,deltax+iii,deltay+j_0-2);
	}
      }
      fl_draw("x",deltax+w()-LEGENDE_SIZE-5,deltay+j_0+10);
    }
    if ( show_axes && (window_xmax>=0) && (window_xmin<=0) ) {// Y-axis
      fl_color(FL_BLACK);
      fl_line(deltax+i_0,deltay,deltax+i_0,deltay+vertical_pixels);
      if (user_screen)
	fl_color(FL_GREEN);
      else
	fl_color(FL_CYAN);
      fl_line(deltax+i_0,deltay+j_0,deltax+i_0,deltay+j_0-int(y_scale));
      fl_color(FL_BLACK);
      if (y_tick>0 && h()/(y_tick*y_scale) <50 ){
	int nticks=int((h()-j_0)/(y_tick*y_scale));
	for (int jj=int(-j_0/(y_tick*y_scale));jj<=nticks;++jj){
	  int jjj=j_0+int(jj*y_scale*y_tick);
	  fl_line(deltax+i_0,deltay+jjj,deltax+i_0+2,deltay+jjj);
	}
      }
      fl_draw("y",deltax+i_0+2,deltay+10);
    }
    // Ticks
    if (show_axes && (w()-LEGENDE_SIZE)/(x_scale*x_tick) < 20 && h()/(y_tick*y_scale) <20  ){
      if (x_tick>0 && y_tick>0 ){
	int nticks=int((w()-LEGENDE_SIZE-i_0)/(x_scale*x_tick));
	int mticks=int((h()-j_0)/(y_tick*y_scale));
	for (int ii=int(-i_0/(x_tick*x_scale));ii<=nticks;++ii){
	  int iii=i_0+int(ii*x_scale*x_tick);
	  for (int jj=int(-j_0/(y_tick*y_scale));jj<=mticks;++jj){
	    int jjj=j_0+int(jj*y_scale*y_tick);
	    fl_point(deltax+iii,deltay+jjj);
	  }
	}
      }
    }
    // History draw
    fl_color(FL_BLACK);
    // Compute matrix for complex drawing
    fl_push_matrix();
    fl_translate(deltax,deltay);
    fl_mult_matrix(x_scale,0,0,-y_scale,0,0);
    fl_translate(-window_xmin,-window_ymax);
    const_iterateur at=plot_instructions_ptr->begin(),atend=plot_instructions_ptr->end(),it,itend;
    vecteur v;
    for (int plot_i=0;at!=atend;++at,++plot_i){
      if (at->type==_INT_)
	continue;
      if (at->is_symb_of_sommet(at_parameter)){
	gen ff = at->_SYMBptr->feuille;
	vecteur f;
	if (ff.type==_VECT && (f=*ff._VECTptr).size()==4){
	  parameters.push_back(f);
	  fl_color(FL_BLACK);
	  int save_digits=decimal_digits;
	  decimal_digits=3;
	  fl_draw((f[0].print()+":"+f[3].print()+"("+f[1].print()+"|"+f[2].print()+")").c_str(),deltax+legende_x,deltay+parameter_y-6);
	  decimal_digits=save_digits;
	  fl_color(FL_GREEN);
	  fl_line(deltax+legende_x,deltay+parameter_y-2,deltax+w(),deltay+parameter_y-2);
	  int pos=int(LEGENDE_SIZE*(f[3].evalf_double()._DOUBLE_val-f[1].evalf_double()._DOUBLE_val)/(f[2].evalf_double()._DOUBLE_val-f[1].evalf_double()._DOUBLE_val));
	  fl_color(FL_RED);
	  fl_line(deltax+legende_x+pos,deltay+parameter_y-5,deltax+legende_x+pos,deltay+parameter_y);
	  parameter_y += PARAM_STEP;
	}
	continue;
      }
      fltkdraw(*this,plot_i,*at,x_scale,y_scale,horizontal_pixels,vertical_pixels);
      fl_line_style(0); // back to default line style
    } // end for at
    fl_pop_matrix(); // Restore initial matrix
    // draw mouse drag
    if ( red_draw && !waiting_click &&(current_x<=horizontal_pixels) && (current_y <=vertical_pixels) && (user_screen || (x_push!=current_x) || (y_push!=current_y))){
      fl_color(FL_RED);
      if (embedded || user_screen)
	fl_rect(deltax+min(x_push,current_x),deltay+min(y_push,current_y),absint(current_x-x_push),absint(current_y-y_push));
      else
	fl_line(deltax+x_push,deltay+y_push,deltax+current_x,deltay+current_y);
    }
  }

  ostream & fltk_fl_widget_archive_function(ostream & os,void * ptr){
    Fl_Widget * w=(Fl_Widget *) ptr;
    Image *i=dynamic_cast<Image *>(w);
    if (!i)
      return archive(os,string2gen("Done",false));
    os << _POINTER_ << " " << _FL_WIDGET_POINTER << endl;
    archive(os,*i->plot_instructions_ptr);
    archive(os,makevecteur(i->x(),i->y(),i->w(),i->h(),i->window_xmin,i->window_xmax,i->window_ymin,i->window_ymax));
    return os;
  }

  gen fltk_fl_widget_unarchive_function(istream & os,const vecteur & l){
    gen gplot=unarchive(os,l),gparam=unarchive(os,l);
    if (gplot.type!=_VECT || gparam.type!=_VECT || gparam._VECTptr->size()<8)
      return 0;
    vecteur v=*gparam._VECTptr;
    Fl_Group::current(0);
    Image * ptr= new Image(v[0].val,v[1].val,v[2].val,v[3].val,"");
    ptr->embedded=true;
    ptr->autoname=0;
    ptr->plot_instructions_ptr=new vecteur(*gplot._VECTptr);
    ptr->window_xmin=v[4]._DOUBLE_val;
    ptr->window_xmax=v[5]._DOUBLE_val;
    ptr->window_ymin=v[6]._DOUBLE_val;
    ptr->window_ymax=v[7]._DOUBLE_val;
    return gen(ptr,_FL_WIDGET_POINTER);
  }

  std::string fltk_fl_widget_texprint_function(void * ptr){
    static int counter=0;
    Fl_Widget * w=(Fl_Widget *) ptr;
    Image * i=dynamic_cast<Image *>(w);
    ++counter;
    double horiz_unit=horiz_latex/(i->window_xmax-i->window_xmin);
    double vert_unit=vert_latex/(i->window_ymax-i->window_ymin);
    double unit=horiz_unit;
    if (horiz_unit>vert_unit)
      unit=vert_unit;
    string tmpfilename("#tmp"+print_INT_(counter));
    FILE * out =fopen(tmpfilename.c_str(),"w");
    if (!out)
      return "Write error";
    if (!graph2tex(out,*i->plot_instructions_ptr,i->window_xmin,i->window_xmax,i->window_ymin,i->window_ymax,unit,tmpfilename.c_str()))
      return "Graph2tex Error";
    fclose(out);
    FILE * in=fopen(tmpfilename.c_str(),"r");
    if (!in)
      return "Read Error";
    string res;
    while (!feof(in))
      res += fgetc(in);
    return res;
  }

  gen fltk_fl_widget_updatepict_function(const gen &g){
    Fl_Widget * w=(Fl_Widget *) g._POINTER_val;
    Image *i=dynamic_cast<Image *>(w);
    if (!i)
      return g;
    if (i->plot_instructions_ptr->size()==1)
      return i->plot_instructions_ptr->front();
    return g;
  }
  /**********************
   *  EQUATION WRITER   *
   **********************/

  void erase_history_levels(){
    run_modif=false;
    UNDO->label("modif");
    UNDO->redraw();
    input->textcolor(FL_BLACK);
    input->redraw();
    if (history_out.empty() || history_in.empty() || user_screen)
      return;
    int h=history_pos();
    int e=erase_pos();
    // search size of selection
    if (Fl::focus()==Eqw_history){ // FIXME
      gen g=Eqw_history->data;
      if (g.type!=_VECT)
	return;
      vecteur & v=*g._VECTptr;
      int s=v.size();
      if (s<2*h+3)
	return;
      int n=2*h+1;
      for (;n<s;++n){
	eqwdata e=Eqw_total_size(v[n]);
	if (!e.selected)
	  break;
      }
      int l=(n-2*h-1)/2+1;
      if (h+l>history_in.size())
	return;
      gen gsave(vecteur(history_in.begin()+h,history_in.begin()+h+l));
      string ssave(gsave.print());
      Fl::selection(*Fl::focus(),ssave.c_str(),ssave.size());
      history_in.erase(history_in.begin()+h,history_in.begin()+h+l);
      history_out.erase(history_out.begin()+h,history_out.begin()+h+l);
      history_begin_level=0;
      if (h>=e){
	int hl=min(h+l-e,plot_instructions.size());
	plot_instructions.erase(plot_instructions.begin()+min(h-e,plot_instructions.size()),plot_instructions.begin()+hl);
      }
      else {
	if (h+l>=e){
	  int hl=min(h+l-e,plot_instructions.size());;
	  plot_instructions.erase(plot_instructions.begin(),plot_instructions.begin()+hl);	      
	}
      }
    } 
    else {
      history_in.erase(history_in.begin()+h);
      history_out.erase(history_out.begin()+h);
      // cerr << h << " " << e << endl;
      history_begin_level=0;
      if ( (h>=e) && (plot_instructions.size()>(h-e)) ){
	plot_instructions.erase(plot_instructions.begin()+(h-e));
      }
    }
    if (Picture->history_position)
      --Picture->history_position;
    if (h)
      --h;
    history_redraw(h);
    Picture->redraw();
    if (Picture->run_plot_view)
      Fl::focus(eval_last_focus);
  }


  void handle_backspace(){
    char petit_buffer[3];
#ifdef HAVE_LIBFLVW
    if (Fl::focus()==spread_ptr){
      spread_ptr->blank();
      return;
    }
#endif
    if (Fl::focus()==Eqw_history){
      petit_buffer[0]=0;
      Fl::e_length=0;
      Fl::e_text=petit_buffer;
      Fl::e_keysym=FL_BackSpace;
      fl_handle();
      return ;
    }    // cerr <<  (Fl::focus()==input) << " " << rpn_mode << " " << Picture->run_plot_view << " " <<!(*input->value()) <<  " " << shift_on << endl;
    if ( (Fl::focus()==xcas_output) || ( (Fl::focus()==input) && (rpn_mode || Picture->run_plot_view) &&(!(*input->value()) ) ) )
      erase_history_levels();
    else {
      if (Fl::focus()==xcas_output)
	Fl::focus(input);
      petit_buffer[0]=0;
      Fl::e_length=0;
      Fl::e_text=petit_buffer;
      Fl::e_keysym=FL_BackSpace;
      fl_handle();
    }  
  }
  
  gen fltk_interactive(const gen & g){
    static int fltk_interactive_timer=clock();
    if (block_signal){
      // cerr << "Interactive while moving" << g << endl;
      return zero;
    }
#ifndef WIN32
    if (!child_id)
      return _interactive(g);
#endif
    if (is_zero(g))
      return graph_instructions;
#ifdef WIN32
    if (clock()-fltk_interactive_timer>CLOCKS_PER_SEC/10){
      fltk_interactive_timer=clock();
      Picture->redraw();
      Fl::check();
    }
#endif
    if (g.type==_SYMB){
      unary_function_ptr & u=g._SYMBptr->sommet;
      gen f=g._SYMBptr->feuille;
      if (u==at_pnt){
	if (f==minus_one){
	  // logo clear instruction
	  turtle_stack.clear();
	  turtle=logo_turtle();
	  turtle_stack.push_back(turtle);
	  return 0;
	}
	if (f.type==_VECT){
	  // logo add position instruction
	  vecteur & v=*f._VECTptr;
	  if (set_turtle_state(v))
	    return 0;
	}
	graph_instructions.push_back(g);
	return 0;
      }
      if (u==at_erase){
	graph_instructions.clear();
	return 0;
      }
      if (u==at_Pictsize){
	int h=Xcas->h()-xcas->h();
	plot_instructionsw=Picture->w();
	plot_instructionsh=(17*h)/24-History_button->h();	
	return makevecteur(Picture->w(),plot_instructionsh);
      }
      ckuser_screen();
      if (u==at_RclPic && f.type==_VECT){
	graph_instructions=mergevecteur(graph_instructions,*f._VECTptr);
	manage_upper_window(upper_window_geo,false);
	return 0;
      }
      if (u==at_RplcPic && f.type==_VECT){
	graph_instructions=*f._VECTptr;
	manage_upper_window(upper_window_geo,false);
	return 0;
      }
      if (u==at_Pause){
	fl_message("Paused");
	return 0;
      }
      if (u==at_ClrIO){
	// Eqw_history->data=Eqw_nullstring(Eqw_history->attr);
	Eqw_history->data=zero;
	Eqw_history->setscroll();
	return 0;
      }
      if (u==at_DispG){
	manage_upper_window(upper_window_geo,false);
	return 0;
      }
      if (u==at_DispHome){
	manage_upper_window(upper_window_hist,false);
	/*user_screen=false;
	std::swap(eqw_history.data,save_eqw_data);
	Picture->plot_instructions_ptr=&plot_instructions; */
	return 0;
      }
      if (u==at_Output){
	user_screen_io_x=f[0].val;
	user_screen_io_y=f[1].val;
	f=f[2];
      }
      if (u==at_Output || u==at_print){
	gen tmp=Eqw_compute_size(f,Eqw_history->attr,Eqw_history->w());
	eqwdata v=Eqw_total_size(tmp);
	//	if (Eqw_history->data.type!=_VECT || Eqw_history->data._VECTptr->empty()){
	if (Eqw_history->data.type!=_VECT && Eqw_history->data.type!=_EQW){
	  Eqw_history->data=tmp;
	  user_screen_io_y=v.y; // top of next writing
	}
	else {
	  eqwdata w=Eqw_total_size(Eqw_history->data);
	  int h=w.dy,y=w.y;
	  tmp=Eqw_translate(tmp,user_screen_io_x,user_screen_io_y-v.y-v.dy);
	  v=Eqw_total_size(tmp);
	  Eqw_vertical_adjust(v.dy,v.y,h,y);
	  user_screen_io_y = y;
	  user_screen_io_x = 0;
	  vecteur res;
	  if (Eqw_history->data.type==_EQW)
	    res.push_back(Eqw_history->data);
	  else
	    res=vecteur(Eqw_history->data._VECTptr->begin(),Eqw_history->data._VECTptr->end()-1);
	  res.push_back(tmp);
	  res.push_back(eqwdata(max(w.dx,v.dx),h,0,y,Eqw_history->attr,at_makevector,0));
	  gen gg=gen(res,_EQW__VECT);
	  Eqw_history->data=gg;
	}
	Eqw_history->setscroll();
	return f;
      }
    }
    return 0;
  }

  gen fltk_xyztrange(const gen & g){
    gen res=_xyztrange(g);
    if (child_id){
      Picture->window_xmin=global_window_xmin;
      Picture->window_xmax=global_window_xmax;
      Picture->window_ymin=global_window_ymin;
      Picture->window_ymax=global_window_ymax;
    }
    return res;
  }

  int xcas_user_level=0;
  void set_xcas_user_level(int i){
    switch (i){
    case 0:
      Xcas_level_output->value("Universite");
      break;
    case 1:
      Xcas_level_output->value("Terminale");
      break;
    case 2:
      Xcas_level_output->value("Premiere");
      break;
    case 3:
      Xcas_level_output->value("Seconde");
      break;
    case 8:
      Xcas_level_output->value("Tortue");
      Bandeau->value(1);
      bandeau->show(); bandeau2->hide();
      angle_radian(false,0);
      Xcas_turtle->value(1);
      show_axes=false;
      break;
    default:
      Xcas_level_output->value("");
    }
    if (i!=8)
      Xcas_turtle->value(0);
    xcas_user_level=i;
  }

  gen fltk_widget_size(const gen & g){
#ifndef WIN32
    if (!child_id)
      return _signal(symbolic(at_quote,symbolic(at_widget_size,g)));
#endif
    int f=14;
    int x=Xcas->x(),y=Xcas->y(),w=Xcas->w(),h=Xcas->h();
    if (g.type==_VECT){
      vecteur & v=*g._VECTptr;
      int s=v.size();
      if (s && v[0].type==_INT_)
	f=v[0].val;
      if (s && v[0].type==_DOUBLE_)
	f=int(v[0]._DOUBLE_val);
      if (s>1 && v[1].type==_INT_)
	x=v[1].val;
      if (s>1 && v[1].type==_DOUBLE_)
	x=int(v[1]._DOUBLE_val);
      if (s>2 && v[2].type==_INT_)
	y=v[2].val;
      if (s>2 && v[2].type==_DOUBLE_)
	y=int(v[2]._DOUBLE_val);
      if (s>3 && v[3].type==_INT_)
	w=v[3].val;
      if (s>3 && v[3].type==_DOUBLE_)
	w=int(v[3]._DOUBLE_val);
      if (s>4 && v[4].type==_INT_)
	h=v[4].val;
      if (s>4 && v[4].type==_DOUBLE_)
	h=int(v[4]._DOUBLE_val);
      if (s>5) {
	if (is_zero(v[5])){
	  if (!Picture->fullscreen)
	    Picture->resize_fullscreen();
	}
	else {
	  if (Picture->fullscreen)
	    Picture->resize_halfscreen();
	}
      }
      if (s>6){
	int n=1;
	if (v[6].type==_INT_)
	  n=v[6].val;
	if (v[6].type==_DOUBLE_)
	  n=int(v[6]._DOUBLE_val);
	if (n<0){
	  horizontal_split=true;
	  n=-n;
	}
	else
	  horizontal_split=false;
        Horizontal_split->value(horizontal_split);
	n=max(1,n);
	n=min(6,n);
	xcas_windows(n);
      }
      if (s>7 && v[7].type==_INT_){
	Bandeau->value(v[7].val);
	if (v[7].val)
	  bandeau->show();
	else
	  bandeau->hide();
      }
      if (s>7 && v[7].type==_DOUBLE_){
	Bandeau->value(int(v[7]._DOUBLE_val));
	if (v[7]._DOUBLE_val)
	  bandeau->show();
	else
	  bandeau->hide();
      }
      // Recompute history & Pretty print
      if (s>8){
	int pretty=0;
	if (v[8].type==_INT_)
	  pretty=v[8].val;
	if (v[8].type==_DOUBLE_)
	  pretty=int(v[8]._DOUBLE_val);
	if (pretty%2){
	  Recompute_history->value(0);
	}
	else {
	  Recompute_history->value(1);
	}
	pretty /= 2;
	if (pretty%2)
	  pretty_input=false;
	else
	  pretty_input=true;
	pretty /= 2;
	if (pretty%2)
	  Pretty_print->value(false);
	else
	  Pretty_print->value(true);
	pretty /= 2;
	if (pretty%2)
	  Eqw_history_freezed->value(true);
	else
	  Eqw_history_freezed->value(false);
	Eqw_history->modifiable=!Eqw_history_freezed->value();
      }
      if (s>9 && v[9].type==_STRNG){
	string browser=*v[9]._STRNGptr;
	if (browser.size()!=0)
	  setenv("BROWSER",browser.c_str(),1);
      }
      if (s>10){ // User level
	int i=0;
	if (v[10].type==_INT_)
	  i=v[10].val;
	if (v[10].type==_DOUBLE_)
	  i=int(v[10]._DOUBLE_val);
	set_xcas_user_level(i);
      }
      if (s>11 && v[11].type==_STRNG){
	string browser=*v[11]._STRNGptr;
	if (browser.size()!=0)
	  setenv("GIAC_PREVIEW",browser.c_str(),1);
      }
    }
    else {
      if (g.type!=_INT_)
	return zero;
      f=g.val;
    }
    f=max(f,-f);
    f=max(f,8);
    f=min(f,24);
    Help_text_fontsize=max(8,(2*f+2)/3);
    change_button_fontsize(f);
    Xcas->resize(x,y,w,h);
    Left_Xcas_resize();    
    return plus_one;
  }

  gen fltk_keyboard(const gen & g){
#ifndef WIN32
    if (!child_id){
      return _signal(symbolic(at_quote,symbolic(at_keyboard,g)));
    }
#endif
    // cerr << "fltk_keyboard "  << g << endl;
    if (is_zero(g)){
      if (!Picture->fullscreen)
	Picture->resize_fullscreen();
    }
    else {
      if (Picture->fullscreen)
	Picture->resize_halfscreen();
    }
    Left_Xcas_resize();    
    return plus_one;
  }

  // Check that g is one of the following form
  // col1,col2...coln
  // cell1..row,col2,...,coln
  // return the corresponding submatrix of m in mselect
  bool iscell_range(const gen & g,const matrice & m,matrice & mselect,void * ptr){
    if (g.is_symb_of_sommet(at_interval)){
      gen & f=g._SYMBptr->feuille;
      if (f.type!=_VECT || f._VECTptr->size()!=2)
	return false;
      int r1,r2,c1,c2;
      if (!iscell(f._VECTptr->front(),c1,r1) || !iscell(f._VECTptr->back(),c2,r2))
	return false;
      if (r1>r2)
	std::swap<int>(r1,r2);
      r2=min(r2+1,m.size());
      r1=max(r1,0);
      mselect=vecteur(m.begin()+r1,m.begin()+r2);
      mselect=mtran(mselect);
      if (c1>c2)
	std::swap<int>(c1,c2);
      c2=min(c2+1,m.size());
      c1=max(c1,0);
      mselect=vecteur(mselect.begin()+c1,mselect.begin()+c2);
      mselect=mtran(mselect);
#ifdef HAVE_LIBFLVW
      if (ptr){
	giac::Flv_Table_Gen * sptr=(Flv_Table_Gen *) ptr;
	sptr->select_start_row(r1);
	if (r2)
	  sptr->row(r2-1);
	sptr->select_start_col(c1);
	if (c2)
	  sptr->col(c2-1);
      }
#endif
      return true;
    }
    if (g.type!=_VECT)
      return false;
    vecteur v=*g._VECTptr;
    int s=v.size();
    if (s<2)
      return false;
    int r1=0,r2=m.size();
    if (v.front().is_symb_of_sommet(at_interval) || v.front().is_symb_of_sommet(at_deuxpoints)){ // compute r1, r2
      gen & f=v.front()._SYMBptr->feuille;
      if (f.type!=_VECT || f._VECTptr->size()!=2)
	return false;
      vecteur & w=*f._VECTptr;
      int c;
      if (!iscell(w[0],c,r1))
	return false;
      r1=max(min(r1,m.size()),0);
      if (w[1].type==_INT_)
	r2=w[1].val-(maple_mode!=0);
      else {
	if (!iscell(w[1],c,r2))
	  return false;
      }
      r2=max(min(r2+1,m.size()),0);
      v[0]=c; // replace by the column
    }
    // full columns selection
    matrice mt(mtran(m));
    int mts=mt.size();
    matrice tselect;
    for (int i=0;i<s;++i){
      gen h=v[i];
      if (h.type==_INT_ && h.val>=0 && h.val<mts)
	tselect.push_back(mt[h.val]);
      if (h.type!=_IDNT)
	continue;
      string & ss=*h._IDNTptr->name;
      int sss=ss.size();
      if (sss<1)
	return false;
      int c,ii=alphaposcell(ss,c);
      if (c>=0 && c<mts)
	tselect.push_back(mt[c]);
    }
    mselect=mtran(tselect);
    mselect=vecteur(mselect.begin()+r1,mselect.begin()+r2);
    return true;
  }

  gen fltk_current_sheet(const gen & g){
#ifndef WIN32
    if (!child_id){
      return _signal(symbolic(at_quote,symbolic(at_current_sheet,g)));
    }
#endif
#ifdef HAVE_LIBFLVW
    // cerr << "fltk_current_sheet "  << g << endl;
    int r,c;
    if (iscell(g,c,r)){
      if (r>=spread_ptr->rows()||c>=spread_ptr->cols())
	return undef;
      gen tmp=spread_ptr->m[r];
      tmp=tmp[c];
      return tmp[1];
    }
    if (iscell_range(g,spread_ptr->m,spread_ptr->selected) ){
      return extractmatricefromsheet(spread_ptr->selected);
    }
    return  gen(extractmatricefromsheet(spread_ptr->m),_MATRIX__VECT)[g];
#else
    return 0;
#endif
  }

  string current_sheet_string(){
#ifdef HAVE_LIBFLVW
    string s("current_sheet(");
    int r2=spread_ptr->select_start_row();
    int r1=spread_ptr->row();
    int c2=spread_ptr->select_start_col();
    int c1=spread_ptr->col();
    if (r1>r2)
      std::swap<int>(r1,r2);
    if (c1>c2)
      std::swap<int>(c1,c2);
    if (r1==r2 && c1==c2)
      s += Spread_goto->value();
    else
      s += print_INT_(r1)+".."+print_INT_(r2)+","+print_INT_(c1)+".."+print_INT_(c2);
    return s+")";
#else
    return "error";
#endif
  }

  bool thesheetsort(const gen & a,const gen &b){
#ifdef HAVE_LIBFLVW
    gen a1=a[spread_ptr->sort_col][1].evalf_double(),a2=b[spread_ptr->sort_col][1].evalf_double();
    if (a1.type!=_DOUBLE_ || a2.type!=_DOUBLE_)
      return a1.islesscomplexthan(a2);
    return a1._DOUBLE_val<a2._DOUBLE_val;
#else
    return true;
#endif
  }

  gen fltk_Row(const gen & g){
#ifndef WIN32
    if (!child_id){
      return _signal(symbolic(at_quote,symbolic(at_Row,g)));
    }
#endif
    if (spread_Row(0)>=0)
      return spread_Row(0);
#ifdef HAVE_LIBFLVW
    return spread_ptr->row();
#endif
    return 0;
  }

  gen fltk_Col(const gen & g){
#ifndef WIN32
    if (!child_id){
      return _signal(symbolic(at_quote,symbolic(at_Col,g)));
    }
#endif
    if (spread_Col(0)>=0)
      return spread_Col(0);
#ifdef HAVE_LIBFLVW
    return spread_ptr->col();
#endif
    return 0;
  }

  void Picture2global_window(){
    global_window_xmin=Picture->window_xmin;
    global_window_xmax=Picture->window_xmax;
    global_window_ymin=Picture->window_ymin;
    global_window_ymax=Picture->window_ymax;
  }

  void Image::geo_zoom(double d){
    window_ymin=window_ymax-d*(window_ymax-window_ymin);
    window_xmin=window_xmax-d*(window_xmax-window_xmin);
  }

  // Check for auto-recovery data in directory s
  bool has_autorecover_data(const string & s,string & newest){
    DIR *dp;
    struct dirent *ep;
    dp = opendir (s.c_str());
    if (dp != NULL)
      {
	time_t t0(0);
	while (ep = readdir (dp)){
	  string cur(ep->d_name);
	  if (cur.size()>9&& cur.substr(0,5)=="xcas_"){ 
	    string curext=cur.substr(cur.size()-3,3);
	    if (curext==".ar"){
	      struct stat st;
	      if (!stat(ep->d_name,&st)){
		time_t & t=st.st_mtime; // last modif
		if (t>=t0){
		  newest=cur;
		  t0=t;
		}
	      }
	    }
	  }
	}
	(void) closedir (dp);
	if (newest.size()==0) // no file
	  return false;
	// Ask user: ignore or run file
	int i=fl_ask((gettext("Auto-recovery file ")+newest+ gettext(" found. Run it?")).c_str(),gettext("Yes"),gettext("No"));
	if (i!=1){
	  i=fl_ask((gettext("Remove ")+newest+ " ?").c_str(),gettext("Yes"),gettext("No"));
	  if (i==1)
	    unlink(newest.c_str());
	  return false;
	}
	return true;
      }
    else
      return false; // Couldn't open the directory
    
  }

  string translate_html_title(const string & s){
    if (debug_infolevel)
      cerr << s << endl;
    int l=s.size();
    string res;
    for (int i=0;i<l;++i){
      if (s[i]!='&'){
	if (s[i]=='\n')
	  res += ' ';
	else
	  res += s[i];
      }
      else {
	int pos=s.find(';',i);
	if (pos>=l || pos<=i)
	  res +=s[i];
	else {
	  string motif=s.substr(i,pos-i);
	  i=pos;
	  if (motif=="&#233")
	    res += "é";
	  if (motif=="&#232")
	    res += "è";
	  if (motif=="&#234")
	    res += "ê";
	  if (motif=="&#224")
	    res += "à";
	  if (motif=="&#244")
	    res += "ô";
	  if (motif=="&#246")
	    res += "o";
	  if (motif=="&#201")
	    res += "E";
	  if (motif=="&#238")
	    res += "î";
	}
      }
    }
    return res;
  }

  string help_translate(const string & s){
    int l=s.size();
    string res;
    for (int i=0;i<l;++i){
      switch (s[i]){
      case 'é':
	res += "&#233;";
	break;
      case 'è':
	res +="&#232;";
	break;
      case 'ê':
	res += "&#234;";
	break;
      case 'à':
	res += "&#224;";
	break;
      case 'î':
	res += "&#238;";
	break;
      default:
	res += s[i];
      }
    }
    return res;
  }

  // help on topic s
  void help_fltk(const string & s_orig){
    string s(help_translate(s_orig));
#ifdef IPAQ
    Fl_Window * w = new Fl_Window(230,134);
    Fl_Button * button0 = new Fl_Button(2,2,111,16);
    button0->shortcut("^[");
    button0->label(gettext("View"));
    Fl_Button * button1 = new Fl_Button(117,2,111,16);
    button1->label(gettext("Finish"));
    Fl_Hold_Browser * br = new Fl_Hold_Browser(2,18,226,96);
    Fl_Output * out = new Fl_Output(2,116,226,16);
    out->value((gettext("Searching for ")+s).c_str());
    w->end();
#else
    Fl_Window * w = new Fl_Window(460,268);
    Fl_Output * out = new Fl_Output(4,4,452,32);
    out->value((gettext("Searching for ")+s).c_str());
    Fl_Hold_Browser * br = new Fl_Hold_Browser(4,36,452,192);
    Fl_Button * button0 = new Fl_Button(4,236,222,32);
    button0->shortcut("^[");
    button0->label(gettext("View"));
    Fl_Button * button1 = new Fl_Button(234,236,222,32);
    button1->label(gettext("Finish"));
    w->end();
#endif
    // Xcas->hide();
    w->resizable(w);
    w->set_modal();
    w->show();
    int r=0;
    // fill browser
    //multimap<string,string>::const_iterator it=html_mtt.begin(),itend=html_mtt.end();
    vector<string>::const_iterator it=html_vall.begin(),itend=html_vall.end();
    vector<string> v;
    for (;it!=itend;++it){
      Fl_Widget *o = Fl::readqueue();
      if (o){
	if (o==button0) {break;}
	if (o==button1 || o==w){ r=1; break; }
      }
      //string fname(absolute_path(it->second));
      string fname(absolute_path(*it));
      // remove #... part at the end of the URL
      int lf=fname.size()-1;
      for (;lf>0;--lf){
	if (fname[lf]=='#'){
	  fname=fname.substr(0,lf);
	  break;
	}
      }
      if (grep(fname,s)){
	FILE * f=fopen(fname.c_str(),"r");
	if (grep(f,"<TITLE>")){
	  string title;
	  for (;!feof(f) && !ferror(f);){
	    char c=fgetc(f);
	    if (c=='<')
	      break;
	    title += c;
	  }
	  fclose(f);
	  br->add(translate_html_title(title).c_str()); 
	  //v.push_back(it->second);
	  v.push_back(*it);
	  br->redraw();
	}
      }
    }
    out->value((gettext("Search result for ")+s).c_str());
    for (;r!=1;) {
      Fl_Widget *o = Fl::readqueue();
      if (!o) Fl::wait();
      else {
	if (o == button0) { // view help file
	  int tmp=br->value(); 
	  if (tmp) 
	    system(browser_command(v[tmp-1]).c_str());
	} 
	if (o == button1) {r = 1; break;}
	if (o == w) { r=1; break; }
      }
    }
    w->hide();
    // Xcas->show();
    delete out;
    delete br;
    delete button1;
    delete button0;
    delete w;
  }

  // Highlighting, borrowed from FLTK1.2/test/editor.cxx
  // Syntax highlighting stuff...
  Fl_Text_Buffer     *stylebuf = 0;
  Fl_Text_Display::Style_Table_Entry
  styletable[] = {	// Style table
    { FL_BLACK,      FL_COURIER,        14 }, // A - Plain
    { FL_DARK_GREEN, FL_COURIER_ITALIC, 14 }, // B - Line comments
    { FL_DARK_GREEN, FL_COURIER_ITALIC, 14 }, // C - Block comments
    { FL_BLUE,       FL_COURIER,        14 }, // D - Strings
    { FL_DARK_RED,   FL_COURIER,        14 }, // E - Directives
    { FL_DARK_RED,   FL_COURIER_BOLD,   14 }, // F - Types
    { FL_BLUE,       FL_COURIER_BOLD,   14 }  // G - Keywords
  };
  const char         *code_keywords[] = {   // List of known giac keywords...
    "Cycle",
    "Dialog",
    "Else",
    "ElseIf",
    "EndDlog",
    "EndFor",
    "EndFunc",
    "EndIf",
    "EndLoop",
    "EndPrgm",
    "EndTry",
    "EndWhile",
    "Exit",
    "For",
    "Func",
    "Goto",
    "If",
    "Lbl",
    "Local"
    "Loop",
    "Prgm",
    "Then",
    "Try",
    "While",
    "and",
    "break",
    "by",
    "case",
    "catch",
    "continue",
    "default",
    "do",
    "elif",
    "else",
    "end_case",
    "end_for",
    "end_if",
    "end_proc",
    "end_while",
    "false",
    "fi",
    "for",
    "from",
    "goto",
    "if",
    "label",
    "not",
    "od",
    "operator",
    "or",
    "proc",
    "return",
    "step",
    "switch",
    "then",
    "throw",
    "true",
    "try",
    "while",
    "xor"
  };
  const char         *code_types[] = {	// List of known giac types...
    "DOM_COMPLEX",
    "DOM_FLOAT",
    "DOM_IDENT",
    "DOM_INT",
    "DOM_LIST",
    "DOM_MATRIX",
    "DOM_RAT",
    "DOM_STRING",
    "DOM_SYMBOLIC",
    "algebraic",
    "array",
    "complex",
    "double",
    "float",
    "integer",
    "local",
    "negint",
    "nonnegint",
    "nonposint",
    "posint",
    "rational"
  };
  
  
//
// 'compare_keywords()' - Compare two keywords...
//

  int
  compare_keywords(const void *a,
		   const void *b) {
    return (strcmp(*((const char **)a), *((const char **)b)));
}
  
  
//
// 'style_parse()' - Parse text and produce style data.
//

  void
  style_parse(const char *text,
	      char       *style,
	      int        length) {
    char	     current;
    int	     col;
    int	     last;
    char	     buf[255],
      *bufptr;
    const char *temp;
    
    for (current = *style, col = 0, last = 0; length > 0; length --, text ++) {
      if (current == 'B') current = 'A';
      if (current == 'A') {
	// Check for directives, comments, strings, and keywords...
	if (col == 0 && *text == '#') {
	  // Set style to directive
	  current = 'E';
	} else if (strncmp(text, "//", 2) == 0) {
	  current = 'B';
	  for (; length > 0 && *text != '\n'; length --, text ++) *style++ = 'B';
	  
	  if (length == 0) break;
	} else if (strncmp(text, "/*", 2) == 0) {
	  current = 'C';
	} else if (strncmp(text, "\\\"", 2) == 0) {
	  // Quoted quote...
	  *style++ = current;
	  *style++ = current;
	  text ++;
	  length --;
	  col += 2;
	  continue;
	} else if (*text == '\"') {
	  current = 'D';
	} else if (!last && isalpha(*text)) {
	  // Might be a keyword...
	  for (temp = text, bufptr = buf;
	       isalpha(*temp) && bufptr < (buf + sizeof(buf) - 1);
	       *bufptr++ = *temp++);
	  
	  if (!isalpha(*temp)) {
	    *bufptr = '\0';
	    
	    bufptr = buf;
	    
	    if (bsearch(&bufptr, code_types,
			sizeof(code_types) / sizeof(code_types[0]),
			sizeof(code_types[0]), compare_keywords)) {
	      current='A';
	      while (text < temp) {
		*style++ = 'F';
		text ++;
		length --;
		col ++;
	      }
	      
	    text --;
	    length ++;
	    last = 1;
	    continue;
	    } else if (bsearch(&bufptr, code_keywords,
			       sizeof(code_keywords) / sizeof(code_keywords[0]),
			       sizeof(code_keywords[0]), compare_keywords)) {
	      current='A';
	      while (text < temp) {
		*style++ = 'G';
		text ++;
		length --;
		col ++;
	      }
	      
	      text --;
	      length ++;
	      last = 1;
	      continue;
	    }
	  }
	}
      } else if (current == 'C' && strncmp(text, "*/", 2) == 0) {
	// Close a C comment...
	*style++ = current;
	*style++ = current;
	text ++;
	length --;
	current = 'A';
	col += 2;
	continue;
      } else if (current == 'D') {
	// Continuing in string...
	if (strncmp(text, "\\\"", 2) == 0) {
	  // Quoted end quote...
	  *style++ = current;
	  *style++ = current;
	  text ++;
	  length --;
	  col += 2;
	  continue;
	} else if (*text == '\"') {
	  // End quote...
	  *style++ = current;
	  col ++;
	  current = 'A';
	  continue;
	}
      } else if ( (current=='F' || current=='G') && !isalpha(*text)){
	current='A';
      }
      // Copy style info...
      if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G';
      else *style++ = current;
      col ++;
      
      last = isalnum(*text) || *text == '.';
      
      if (*text == '\n') {
	// Reset column and possibly reset the style
	col = 0;
	if (current == 'B' || current == 'E') current = 'A';
      }
    }
  }
  

//
// 'style_update()' - Update the style buffer...
//

  void
  style_update(int        pos,		// I - Position of update
	       int        nInserted,	// I - Number of inserted chars
	       int        nDeleted,	// I - Number of deleted chars
	       int        /*nRestyled*/,	// I - Number of restyled chars
	       const char * /*deletedText*/,// I - Text that was deleted
	       void       *cbArg) {	// I - Callback data
    int	start,				// Start of text
      end;				// End of text
    char	last,				// Last style on line
      *style,				// Style data
      *text;				// Text data
    
    
    // If this is just a selection change, just unselect the style buffer...
    if (nInserted == 0 && nDeleted == 0) {
      stylebuf->unselect();
      return;
    }
    
    // Track changes in the text buffer...
    if (nInserted > 0) {
      // Insert characters into the style buffer...
      style = new char[nInserted + 1];
      memset(style, 'A', nInserted);
      style[nInserted] = '\0';
      
      stylebuf->replace(pos, pos + nDeleted, style);
      delete[] style;
    } else {
      // Just delete characters in the style buffer...
      stylebuf->remove(pos, pos + nDeleted);
    }
    
    // Select the area that was just updated to avoid unnecessary
    // callbacks...
    stylebuf->select(pos, pos + nInserted - nDeleted);
    
    // Re-parse the changed region; we do this by parsing from the
    // beginning of the line of the changed region to the end of
    // the line of the changed region...  Then we check the last
    // style character and keep updating if we have a multi-line
    // comment character...
    Fl_Text_Buffer * textbuf=((Fl_Text_Editor *)cbArg)->buffer();
    start = textbuf->line_start(pos);
    end   = textbuf->line_end(pos + nInserted);
    text  = textbuf->text_range(start, end);
    style = stylebuf->text_range(start, end);
    last  = style[end - start - 1];
    
    //  printf("start = %d, end = %d, text = \"%s\", style = \"%s\"...\n",
    //         start, end, text, style);
    
    style_parse(text, style, end - start);
    
    //  printf("new style = \"%s\"...\n", style);
    
    stylebuf->replace(start, end, style);
    ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
    
    if (last != style[end - start - 1]) {
      // The last character on the line changed styles, so reparse the
      // remainder of the buffer...
      free(text);
      free(style);
      
      end   = textbuf->length();
      text  = textbuf->text_range(start, end);
      style = stylebuf->text_range(start, end);
      
      style_parse(text, style, end - start);
      
      stylebuf->replace(start, end, style);
      ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end);
    }
    
    free(text);
    free(style);
  }

  //
  // 'style_unfinished_cb()' - Update unfinished styles.
  //
  
  void
  style_unfinished_cb(int, void*) {
  }


  //
  // 'style_init()' - Initialize the style buffer...
  //
  
  void  style_init(Fl_Text_Buffer * textbuf ) {
    char *style = new char[textbuf->length() + 1];
    char *text = textbuf->text();
    
    
    memset(style, 'A', textbuf->length());
    style[textbuf->length()] = '\0';
    
    if (!stylebuf) stylebuf = new Fl_Text_Buffer(textbuf->length());
    
    style_parse(text, style, textbuf->length());
    
    stylebuf->text(style);
    delete[] style;
    free(text);
  }

  bool editor_changed=false;

  void Editor_changed_cb(int, int nInserted, int nDeleted,int, const char*, void* v) {
    if ((nInserted || nDeleted)) 
      editor_changed = true;
  }



#ifndef NO_NAMESPACE_GIAC
} // namespace giac
#endif // ndef NO_NAMESPACE_GIAC

#endif // HAVE_LIBFLTK
