// -*- compile-command: "g++ -I.. -I../../giac/include -I../include -g -c sheet.cc " -*-
#include "first.h"
/*
 *  Copyright (C) 2002 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 "sheet.h"
#ifdef FL_DEVICE 

//#include <FL/Fl_Printer.H>
#include <FL/Fl_PS_Printer.H>

#ifdef WIN32
  #include <FL/Fl_GDI_Printer.H>
#endif

#include <FL/fl_printer_chooser.H>

  #include "Fl_PS_Printer.cxx"

#ifdef WIN32
  #include "Fl_GDI_Printer.cxx"
#endif

#endif // FL_DEVICE

#include "vecteur.h"
#include "identificateur.h"
#include "usual.h"
#include "prog.h"
#include "xcas.h"
#include "plotfltk.h"

#include <FL/Fl_Text_Editor.H>


using namespace std;

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

#ifdef FL_DEVICE 
  int printer_format=Fl_Printer::A4;
#else // FL_DEVICE
  int printer_format=-1;
#endif // FL_DEVICE
  bool printer_landscape=false;

#ifdef HAVE_LIBFLVW
  vecteur fillsheet(bool is_spreadsheet){
    vecteur res;
    if (is_spreadsheet)
      res=vecteur(3,string2gen(string(""),false));
    else
      res=vecteur(3,zero);
    res[2]=plus_two;
    return res;
  }

  void Flv_Table_Gen::spread_erase(int nrows,int ncols){
    changed=true;
    if ( (nrows>=rows()) || (ncols>=cols()) )
      return;
    m=matrice_erase(m,row(),col(),nrows,ncols);
    rows(rows()-nrows);
    cols(cols()-ncols);
  }


  void Flv_Table_Gen::blank(int row_min,int r,int col_min,int c){
    changed=true;
    vecteur fill(fillsheet(is_spreadsheet));
    if (c<col_min)
      swap(c,col_min);
    if (r<row_min)
      swap(r,row_min);
    ++r;
    ++c;
    if ( (c==col_min) || (r==row_min) )
      return;
    selected.clear();
    selected.reserve(r-row_min);
    for (int i=row_min;i<r;++i){
      vecteur & v=*m[i]._VECTptr;
      vecteur tmp;
      tmp.reserve(c-col_min);
      for (int j=col_min;j<c;++j){
	tmp.push_back(v[j]);
	v[j]=freecopy(fill);
      }
      selected.push_back(tmp);
    }
    redraw();
  }
  void Flv_Table_Gen::blank(){
    changed=true;
    int row_min=select_start_row(),r=row();
    int col_min=select_start_col(),c=col();
    blank(row_min,r,col_min,c);
  }

  void Flv_Table_Gen::spread_insert(int nrows,int ncols){
    changed=true;
    vecteur fill(fillsheet(is_spreadsheet));
    m=matrice_insert(m,row(),col(),nrows,ncols,fill);
    rows(rows()+nrows);
    cols(cols()+ncols);
    redraw();
  }

  void Flv_Table_Gen::addrowatend(){
    changed=true;
    vecteur fill(fillsheet(is_spreadsheet));
    int C=cols();
    vecteur addrow(C);
    for (int j=0;j<C;++j)
      addrow[j]=freecopy(fill);
    m.push_back(addrow);
    rows(rows()+1);
    redraw();
  }

  void Flv_Table_Gen::addcolatend(){
    changed=true;
    vecteur fill(fillsheet(is_spreadsheet));
    int R=rows();
    for (int i=0;i<R;++i){
      m[i]._VECTptr->push_back(freecopy(fill));
    }
    cols(cols()+1);
    redraw();
  }

  void Flv_Table_Gen::resizesheet(int nr,int nc){
    changed=true;
    int cur_r=rows();
    vecteur fill(fillsheet(is_spreadsheet));
    if (nr<cur_r) // erase rows
      m=vecteur(m.begin(),m.begin()+nr);
    else {
      for (;cur_r<nr;++cur_r){
	vecteur tmp;
	for (int j=0;j<nc;++j)
	  tmp.push_back(freecopy(fill));
	m.push_back(tmp);
      }
    }
    for (int i=0;i<nr;++i){
      vecteur & v=*m[i]._VECTptr;
      int cur_c=v.size();
      if (nc<cur_c){
	m[i]=vecteur(v.begin(),v.begin()+nc);
      }
      else {
	for (;cur_c<nc;++cur_c)
	  v.push_back(freecopy(fill));
      }
    }
    rows(nr);
    cols(nc);
    row(0);
    col(0);
    spread_eval_interrupt(m,lc,contextptr);
    redraw();
  }

  void Flv_Table_Gen::copy(){
    int row_min=select_start_row(),r=row();
    int col_min=select_start_col(),c=col();
    selected.clear();
    if (c<col_min)
      swap(c,col_min);
    if (r<row_min)
      swap(r,row_min);
    ++r;
    ++c;
    if ( (c==col_min) || (r==row_min) )
      return;
    selected.reserve(r-row_min);
    for (int i=row_min;i<r;++i){
      vecteur tmp;
      tmp.reserve(c-col_min);
      for (int j=col_min;j<c;++j){
	tmp.push_back(m[i][j]);
      }
      selected.push_back(tmp);
    }
    gen g(extractmatricefromsheet(selected));
    string s(g.print());
    Fl::selection(*this,s.c_str(),s.size());
  }

  void Flv_Table_Gen::copy_right(){
    changed=true;
    int R=row(),C=col();
    int c=cols(),r=rows();
    int R0=select_start_row();
    if (R0<0 || R0>=r)
      R0=R;
    if (R0<R)
      swap<int>(R0,R);
    for (;R<=R0;++R){
      vecteur & v=*m[R]._VECTptr;
      gen g=v[C];
      for (int i=C+1;i<c;++i){
	v[i]=freecopy(g);
      }
    }
    if (is_spreadsheet) spread_eval_interrupt(m,lc,contextptr);
    redraw();
  }

  void Flv_Table_Gen::copy_down(){
    changed=true;
    int R=row(),C=col();
    int r=rows(),c=cols();
    int C0=select_start_col();
    if (C0<0 || C0>=c)
      C0=C;
    if (C0<C)
      swap<int>(C0,C);
    for (;C<=C0;++C){
      gen g=m[R][C];
      for (int i=R+1;i<r;++i){
	vecteur & v=*m[i]._VECTptr;
	v[C]=freecopy(g);
      }
    }
    if (is_spreadsheet) spread_eval_interrupt(m,lc,contextptr);
    redraw();
  }

  void Flv_Table_Gen::copy_first_in_selection(){
    changed=true;
    int R=row(),C=col();
    int r=select_start_row(),c=select_start_col();
    gen g=m[r][c];
    if (r<R)
      swap<int>(r,R);
    if (c<C)
      swap<int>(c,C);
    R=max(R,0); C=max(C,0); r=min(r,rows()-1); c=min(c,cols()-1);
    for (int i=R;i<=r;++i){
      vecteur & v=*m[i]._VECTptr;
      for (int j=C;j<=c;++j)
	v[j]=freecopy(g);
    }
    if (is_spreadsheet) spread_eval_interrupt(m,lc,contextptr);
    redraw();
  }

  void Flv_Table_Gen::paste(const matrice & m_orig){
    changed=true;
    matrice m_copy(makefreematrice(m_orig));
    makespreadsheetmatrice(m_copy);
    int nr,nc;
    mdims(m_copy,nr,nc);
    int r=row(),R=min(rows(),r+nr),c=col(),C=min(cols(),c+nc);
    for (int i=r;i<R;++i){
      vecteur & v=*m[i]._VECTptr;
      for (int j=c;j<C;++j){
	v[j]=m_copy[i-r][j-c];
      }
    }
    if (is_spreadsheet) spread_eval_interrupt(m,lc,contextptr);
    redraw();
  }

  void Flv_Table_Gen::erase_row_col(int i){
    int R=row(),C=col();
    // erase rows push_row -> R && push_col -> C
    if (i==2)
      i=fl_choice(gettext("Remove what?"),gettext("Rows"),gettext("Cols"),gettext("Cancel"));
    int r1=min(push_row,R),r2=absint(push_row-R)+1,c1=min(push_col,C),c2=absint(push_col-C)+1;
    if (i==0){
      row(r1);
      push_row=r1;
      spread_erase(r2,0);
    }
    if (i==1){
      col(c1);
      push_col=c1;
      spread_erase(0,c2);
    }
  }

  void Flv_Table_Gen::enter_move(){
    int R=row(),C=col();
    if (!move_right){
      if (R<rows()-1)
	row(R+1);
      else {
	row(0);
	if (C<cols()-1)
	  col(C+1);
	else
	  col(0);
      }
    }
    else {
      if (C<cols()-1)
	col(C+1);
      else {
	col(0);
	if (R<rows()-1)
	  row(R+1);
	else
	  row(0);
      }
    }
    select_start_row(row());
    select_start_col(col());
  }

  int Flv_Table_Gen::handle(int event){
    if ( (event==FL_FOCUS) || (event==FL_UNFOCUS) || (event==FL_HIDE) || (event==FL_SHOW) )
      return 1;
    if (event==FL_DRAG || event==FL_RELEASE)
      Fl::focus(this);
    if ((event==FL_KEYBOARD && Fl::event_key()==FL_Escape) || !input_value()[0]){
      editing=false;
      // cerr << "Mtrw edit leave"<<endl;
    }
    if (event==FL_KEYBOARD && Fl::event_key()==FL_Delete)
      erase_row_col(2);
    if (event==FL_KEYBOARD && Fl::event_key()==FL_Enter){
      enter_move();
      return 1;
    }
    int res=Flv_Table::handle(event);
    if (res){
      int R=row(),C=col();
      string s;
      printcell_current_row=R;
      printcell_current_col=C;
      s=printcell(makevecteur(makevecteur(0),makevecteur(0)));
      if (event==FL_PUSH){
	push_row=R;
	push_col=C;
      }
      else {
	if (push_row!=R || push_col!=C) {
	  if (editing)
	    s=printcell(makevecteur(makevecteur(push_row-R),makevecteur(push_col-C)))+":"+s;
	  else 
	    if (event==FL_DRAG || event==FL_RELEASE)
	      s=printcell(makevecteur(makevecteur(push_row-R),makevecteur(push_col-C)))+".."+s;
	}
      }
      if (event!=FL_ENTER && event!=FL_LEAVE && event!=FL_MOVE )
	Spread_goto->value(s.c_str());
      if (editing && (event==FL_PUSH || event ==FL_DRAG || event == FL_RELEASE) ){
	input_insert(s.c_str(),true);
	if (event==FL_RELEASE){
	  row(edit_row); col(edit_col); select_start_row(edit_row); select_start_col(edit_col); 
	  feature_add(FLVF_PERSIST_SELECT);
	  Fl::focus(input);
	  int s=strlen(input->value());
	  input->position(s,s);
	  Spread_goto->value(printcell(makevecteur(makevecteur(edit_row-R),makevecteur(edit_col-C))).c_str());
	  return 1;
	}
      }
      if (event==FL_RELEASE && (push_row!=R || push_col!=C)){
	copy();
	return 1;
      }
      if ( !editing && (C>=0) && (R>=0) && (event!=FL_MOVE) && (event!=FL_ENTER) && (event!=FL_LEAVE) ){
	if ( (m[R][C].type==_VECT) && (m[R][C]._VECTptr->size()==3) ){
	  int save_r=printcell_current_row,save_c=printcell_current_col;
	  printcell_current_row=R,printcell_current_col=C;
	  s=m[R][C][0].print();
	  printcell_current_row=save_r;printcell_current_col=save_c;
	}
	else
	  s=m[R][C].print();
        if (current_upper_window[0]==upper_window_mtrw){
          input_value(s.c_str());
	  input_position(0,s.size());
	}
      }
    }
    if (!res && (event==FL_KEYBOARD)){
      editing=true;
      edit_row=row(); edit_col=col();
      Fl::focus(input);
      Fl::handle(FL_KEYBOARD,Xcas);
      return 1;
    }
    return res;
  }

  void Flv_Table_Gen::set_matrix(const matrice & mym,bool interruptible){
    changed=true;
    m=makefreematrice(mym);
    cols(mcols(m));
    rows(m.size());
    makespreadsheetmatrice(m);
    if (is_spreadsheet) {
      if (interruptible)
	spread_eval_interrupt(m,lc,contextptr);
      else
	spread_eval(m,lc,contextptr);
    }
    is_spreadsheet=false;
    if ( !mym.empty() && (!mym.front()._VECTptr->empty()) )
      is_spreadsheet=(mym[0][0].type==_VECT);
    move_on_enter(FLV_MOVE_ON_ENTER_COL_ROW);
    col(0);
    row(0);
    select_start_row(0);
    select_start_col(0);
    redraw();
  }
  
  void Flv_Table_Gen::set_matrix(const gen & g,bool interruptible){
    changed=true;
    if (!ckmatrix(g,true))
      settypeerr();
    set_matrix(*g._VECTptr,interruptible);
  }

  Flv_Table_Gen::Flv_Table_Gen( int X, int Y, int W, int H ,const matrice & mym, const char *l) : move_right(false), Flv_Table(X,Y,W,H,l),contextptr(0),editing(false) {
    if (!ckmatrix(mym))
      settypeerr();
    set_matrix(mym,false);
    changed=false;
  }
  
  Flv_Table_Gen::Flv_Table_Gen( int X, int Y, int W, int H ,const gen &g, const char *l) :  move_right(false), Flv_Table(X,Y,W,H,l),contextptr(0),editing(false) {
    set_matrix(g,false);
    changed=false;
  }
  
  void Flv_Table_Gen::draw_cell( int Offset, int &X, int &Y, int &W, int &H, int R, int C ){
    Flv_Style s;
    
    get_style(s, R, C);
    Flv_Table::draw_cell(Offset,X,Y,W,H,R,C);
    string ss;
    if (C<0){
      if (R>=0){
	if (maple_mode>0)
	  ss=gen(R+1).print();
	else
	  ss=gen(R).print();
      }
    }
    else {
      if (R<0){
	if (is_spreadsheet){
	  int i=C;
	  for(int j=0;;++j){
	    ss=char('A'+i%26-(j!=0))+ss;
	    i=i/26;
	    if (!i)
	      break;
	  }
	}
	else {
	  if (maple_mode>0)
	    ss=gen(C+1).print();
	  else
	    ss=gen(C).print();
	}
      }
      else {
	const gen & g=m[R][C];
	if ((g.type==_VECT) && (g._VECTptr->size()==3) ){
	  int save_r=printcell_current_row,save_c=printcell_current_col;
	  printcell_current_row=R,printcell_current_col=C;
	  ss=(*g._VECTptr)[1].print();
	  printcell_current_row=save_r;printcell_current_col=save_c;
	}
	else
	  ss=g.print();
      }
    }
    fl_color(FL_BLACK);
      fl_draw(ss.c_str(), X-Offset, Y, W, H, s.align() );
  }

  /*
  void Flv_Table_Gen::save_editor( Fl_Widget *e, int R, int C ){
    if ( (R>=0) && (C>=0) ){
      vecteur & v=*m[R]._VECTptr;
      gen g(string( ((Flve_Input *) e)->value() ));
      if ( (v[C].type==_VECT) && (v[C]._VECTptr->size()==3)){
	v[C]._VECTptr->front()=spread_convert(g,R,C);
	if (is_spreadsheet) spread_eval_interrupt(m,lc);
      }
      else
	v[C]=g;
    }
  }

  void Flv_Table_Gen::load_editor( Fl_Widget *e, int R, int C ){
    if ((C>=0) && (R>=0)){
      if ( (m[R][C].type==_VECT) && (m[R][C]._VECTptr->size()==3) ){
	int save_r=printcell_current_row,save_c=printcell_current_col;
	printcell_current_row=R,printcell_current_col=C;
	((Flve_Input *)e)->value( m[R][C][0].print().c_str() );
	printcell_current_row=save_r;printcell_current_col=save_c;
      }
      else
	((Flve_Input *)e)->value( m[R][C].print().c_str() );
      ((Flve_Input *)e)->position(((Flve_Input *)e)->size(), 0 );
    }
  }

  void Flv_Table_Gen::position_editor( Fl_Widget *e, int x, int y, int w, int h, Flv_Style &s ){

    //	Out of cell
    //	e->resize( 10, 10, 200, 20 );
    
    //	In cell
    //	Flv_Table::position_editor(e,x+s.x_margin(),y,w-s.x_margin(),h,s);
    Flv_Table::position_editor(e,x,y,w,h,s);
  }
  */
  
  void spread_eval_interrupt(matrice & m,matrice & lc,GIAC_CONTEXT){
    bool save_interrupt_button=interrupt_button;
    interrupt_button = true;
    Xcas_Computation_progress->show();
    spread_eval(m,lc,contextptr);
    Xcas_Computation_progress->hide();
    interrupt_button=save_interrupt_button;
  }

  void spread_eval_interrupt(matrice & m,GIAC_CONTEXT){
    bool save_interrupt_button=interrupt_button;
    interrupt_button = true;
    Xcas_Computation_progress->show();
    spread_eval(m,contextptr);
    Xcas_Computation_progress->hide();
    interrupt_button=save_interrupt_button;
  }

#ifdef FL_DEVICE
  void print_newpage(Fl_Printer * p);
  void Flv_Table_Gen_widget_print(Flv_Table_Gen * g,Fl_Printer * p){
    print_newpage(p);
    double scale=0.22 * FL_MM;
    double margin=FL_INCH;
    int hp=int((p->page_height()-2*margin)/scale);
    int wp=int((p->page_width()-2*margin)/scale);
    g->resize(0,0,wp,hp);
    int i=0,j=0; // current row/column
    for (;j<g->cols()-1;){
      if (i || j)
	print_newpage(p);
      g->row(g->rows());
      g->col(g->cols());
      g->select_start_row(g->rows());
      g->select_start_col(g->cols());
      g->redraw();
      g->row(i);
      g->col(j);
      g->select_start_row(i);
      g->select_start_col(j);
      g->redraw();
      p->place(0.0, 0.0, margin,margin, scale);
      fl_draw(g);
      i = g->get_row(100,hp-20);
      i = max(i,g->get_row(100,hp-25));
      i = max(i,g->get_row(95,hp-20));
      i = max(i,g->get_row(95,hp-25));
      if (i<0)
	i=g->rows();
      if (i>=g->rows()-3){
	i=0;
	g->row(i);
	j=g->get_col(wp-30,hp-20);
	j=max(j,g->get_col(wp-30,hp-25));
	j=max(j,g->get_col(wp-35,hp-20));
	j=max(j,g->get_col(wp-35,hp-25));
	if (j<0)
	  j=g->cols();
      }
    }    
  }
#endif // FL_DEVICE
#endif // HAVE_LIBFLVW

#ifdef FL_DEVICE
  void print_newpage(Fl_Printer * p){
    if (printer_landscape)
      p->page(printer_format | Fl_Printer::LANDSCAPE);
    else
      p->page(printer_format);
  }

  void Eqw_widget_print(Eqw * g,Fl_Printer * p){
    print_newpage(p);
    int x=g->x(),y=g->y(),h=g->h(),w=g->w();
    eqwdata e=Eqw_total_size(g->data);
    double scale=0.22 * FL_MM;
    double margin=FL_INCH;
    int hp=int((p->page_height()-2*margin)/scale);
    int wp=int((p->page_width()-2*margin)/scale);
    g->resize(x,y,wp,hp);
    int np=e.dy/hp;
    for (int i=0;i<=np;++i){
      if (i)
	print_newpage(p);
      //if (i)
      //p->page(Fl_Printer::A4);
      // fprintf(f,"%sPage: %d %d\n","%%",i+1,i+1);
      g->xleft=e.x;
      g->ytop=e.y+e.dy-i*hp;
      p->place(g->xleft, 0, margin,margin, scale);
      fl_draw(g);
    }
  }

  void Image_widget_print(Image * i,Fl_Printer * p){
    print_newpage(p);
    double scale=0.22 * FL_MM;
    double margin=FL_INCH;
    p->place(0.0, 0.0, margin,margin, scale);
    redraw_mouse_position_only=false;
    fl_draw(i);
  }

  void Fl_Text_Editor_widget_print(Fl_Text_Editor * g,Fl_Printer * p){
    print_newpage(p);
    Fl_Text_Buffer * b=g->buffer();
    double scale=0.22 * FL_MM;
    double margin=FL_INCH;
    int hp=int((p->page_height()-2*margin)/scale);
    int wp=int((p->page_width()-2*margin)/scale);
    int endpos=string(b->text()).size();
    int nlines=b->count_lines(0,endpos)+1;
    int t=g->textsize();
    int npoints=nlines*t,np=npoints/hp;
    if (npoints%hp)
      np += 1;
    // np=numbre of pages, adjust hp
    int ligneparpage=nlines/np;
    if (nlines%np){
      ligneparpage +=1 ;
      /*
      int j=np*ligneparpage-nlines;
      // insert blank lines at end
      string ins;
      for (;j;--j)
	ins += " \n";
      b->insert(endpos-1,ins.c_str());
      */
    }
    hp=ligneparpage*t+g->scrollbar_width()+10;
    g->resize(0,0,wp,hp);
    for (int i=0;i<np;++i){
      if (i)
	print_newpage(p);
      if (i==np-1)
	g->resize(0,0,wp,(nlines-i*ligneparpage)*t+g->scrollbar_width()+10);
      g->scroll(i*ligneparpage+1,0);
      p->place(0.0, 0.0, margin,margin, scale);
      fl_draw(g);
    }
  }

  void inner_widget_print(Fl_Widget * widget,Fl_Printer * p){
    Fl_Group * gr=dynamic_cast<Fl_Group *>(widget);
    if (gr){ // print all elements of the group
      int n=gr->children();
      for (int i=0;i<n;++i)
	inner_widget_print(gr->child(i),p);
    }
    Eqw * g = dynamic_cast<Eqw *> (widget);
    if (g)
      Eqw_widget_print(g,p);
    Image * i=dynamic_cast<Image *>(widget);
    if (i)
      Image_widget_print(i,p);
#ifdef HAVE_LIBFLVW
    Flv_Table_Gen * t=dynamic_cast<Flv_Table_Gen *>(widget);
    if (t)
      Flv_Table_Gen_widget_print(t,p);
#endif
    Fl_Text_Editor * b=dynamic_cast<Fl_Text_Editor *>(widget);
    if (b)
      Fl_Text_Editor_widget_print(b,p);
  }

  void in_widget_print(Fl_Widget * widget,Fl_Printer * p){
    Fl_Output_Device * c = p->set_current();
    int x=widget->x(),y=widget->y(),h=widget->h(),w=widget->w();
    inner_widget_print(widget,p);
    widget->resize(x,y,w,h);
    c->set_current();
  }
#endif // FL_DEVICE

#ifdef WIN32
  string ps_preview="!";
#else
#ifdef __APPLE__
  string ps_preview="/Applications/Preview.app/Contents/MacOS/Preview";
#else
  string ps_preview="gv";
#endif
#endif

  void widget_ps_print(Fl_Widget * widget){
#ifdef FL_DEVICE
    // Fl_Printer * p = fl_printer_chooser();
    char * filename = fl_file_chooser("Print to file...","*.ps","*.ps");
    if(!filename) return;
    FILE * f = fopen(filename,"w");
    if(!f) return;
    Fl_Printer * p = new Fl_PS_Printer(f, 3);
    if (p){
      in_widget_print(widget,p);
      delete p;
    }
    fclose(f); //we need close file here
    // Preview
#ifdef WIN32
    if (ps_preview=="!"){
      ps_preview="/cygdrive/c/";
      if (getenv("XCAS_ROOT")){
	string s(getenv("XCAS_ROOT"));
	if (s.substr(0,10)=="/cygdrive/")
	  ps_preview[10]=s[10];
      }
      ps_preview +="Program\\ Files/Ghostgum/gsview/gsview32.exe";
    }
#endif
    if (getenv("GIAC_PREVIEW"))
      ps_preview=getenv("GIAC_PREVIEW");
    if (ps_preview!="no"){
#ifdef WIN32
      string fn=absolute_path(filename);
      system((((ps_preview+" ")+fn)+" &").c_str());
#else
      system((((ps_preview+" ")+filename)+" &").c_str());
#endif
    }
#endif
  }

  void widget_print(Fl_Widget * widget){
#ifdef FL_DEVICE
    Fl_Printer * p = fl_printer_chooser(); 
    if (p){
      in_widget_print(widget,p);      
      delete p;
    }
#endif
  }

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

