// -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -g -c Xcas1.cc -Wall -DHAVE_CONFIG_H -DIN_GIAC" -*- /* * Copyright (C) 2005,2014 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 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef IN_GIAC #include #else #include "first.h" #endif #include #ifdef HAVE_LIBFLTK #include #include #include #include #include #include #include #include #include #endif #include "Xcas1.h" #include "Input.h" #include "Equation.h" #include "Graph.h" #include "Graph3d.h" #include "Tableur.h" #include "Editeur.h" #include "Print.h" #include #include #ifdef HAVE_SSTREAM #include #else #include #endif #include #include #include #include #include #include // auto-recovery function #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_LIBPTHREAD #include #endif #ifdef HAVE_PTHREAD_H #include #endif #ifndef IN_GIAC #include #include #include #else #include "global.h" #include "misc.h" #include "gen.h" #endif using namespace std; using namespace giac; #ifndef NO_NAMESPACE_XCAS namespace xcas { #endif // ndef NO_NAMESPACE_XCAS #ifdef HAVE_LIBFLTK bool interrupt_button = true ; bool geo_run=false; bool sheet_run=false; bool recovery_mode=false; int fonts_available=1; void (*initialize_function)()=0; Xcas_config_type Xcas_config; void (* menu2rpn_callback)(Fl_Widget *,void *)=0; Enlargable_Multiline_Output *Xcas_help_output =0 ; xcas::Graph2d *Xcas_DispG=0; xcas::Equation * Xcas_PrintG=0; int show_xcas_dispg=0,redraw_turtle=0; std::string xcas_paused=""; int xcas_dispg_entries=0; Fl_Window * Xcas_DispG_Window=0; Fl_Window * Xcas_Main_Window=0; Fl_Button *Xcas_DispG_Cancel=0; Fl_Button *Xcas_Cancel=0; bool file_save_context=true; void xcas_gprintf(unsigned special,const std::string & format,const vecteur & v,GIAC_CONTEXT){ if (Xcas_PrintG){ Fl::lock(); gen g=Xcas_PrintG->get_data(); Fl::unlock(); vecteur w=makevecteur(string2gen("",false),string2gen("Step by step console",false)); if (g.type==_VECT) w=*g._VECTptr; // add format,v at the end of w int posnl=0; unsigned i=0; for (;posnl=int(format.size()); if (finish) curs=format.substr(posnl,format.size()-posnl); else { curs=format.substr(posnl,nl-posnl); posnl=nl+1; } vecteur cur; for (;i=int(curs.size())) break; string cursp=curs.substr(0,p); if (!cursp.empty()) cur.push_back(string2gen(cursp,false)); cur.push_back(v[i]); curs=curs.substr(p+4,curs.size()-p-4); } if (!curs.empty()) cur.push_back(string2gen(curs,false)); if (cur.empty()) continue; if (cur.size()==1) w.push_back(cur.front()); else w.push_back(gen(cur,_SEQ__VECT)); if (finish) break; } g=gen(w,_HIST__VECT); Fl::lock(); Xcas_PrintG->set_data(g); Fl::unlock(); } } // debugger variables int xcas_debug_ok,xcas_current_instruction; Fl_Double_Window * Xcas_Debug_Window=0; Fl_Tile* Xcas_debug_tile =0; Fl_Browser* Xcas_source_browser =0; xcas::Multiline_Input_tab* Xcas_debug_input =0; Fl_Output* Xcas_debug_messages =0; Fl_Group* Xcas_debug_buttons =0; Fl_Button* Xcas_sst_button=0,*Xcas_sst_in_button=0,*Xcas_cont_button=0,* Xcas_kill_button =0, * Xcas_break_button=0,* Xcas_rmbrk_button=0,*Xcas_watch_button =0,*Xcas_rmwatch_button=0; Fl_Browser* Xcas_variable_browser=0; static void cb_Xcas_source_browser(Fl_Browser*, void* user) { std::string s("breakpoint("); giac::context * contextptr =(giac::context *) user; s += giac::debug_ptr(contextptr)->debug_prog_name->print(); s += ','; s += giac::print_INT_(Xcas_source_browser->value()); s += ')'; Xcas_debug_input->value(s.c_str()); Xcas_debug_input->position(s.size()-1,s.size()-1); Fl::focus(Xcas_debug_input); Fl::flush(); usleep(200000); Xcas_source_browser->value(xcas_current_instruction); } static void cb_Xcas_debug_input(xcas::Multiline_Input_tab*, void*) { xcas_debug_ok=true; } static void cb_Xcas_sst_button(Fl_Button*, void*) { Xcas_debug_input->value("sst"); xcas_debug_ok=true; } static void cb_Xcas_sst_in_button(Fl_Button*, void*) { Xcas_debug_input->value("sst_in"); xcas_debug_ok=true; } static void cb_Xcas_cont_button(Fl_Button*, void*) { Xcas_debug_input->value("cont"); xcas_debug_ok=true; } static void cb_Xcas_kill_button(Fl_Button*, void*) { Xcas_debug_input->value("kill"); Xcas_debug_input->position(4,4); Fl::focus(Xcas_debug_input); } static void cb_Xcas_break_button(Fl_Button*, void* user) { string s("breakpoint("); giac::context * contextptr =(giac::context *) user; s += giac::debug_ptr(contextptr)->debug_prog_name->print(); s += ','; s += giac::print_INT_(Xcas_source_browser->value()); s += ')'; Xcas_debug_input->value(s.c_str()); Xcas_debug_input->position(s.size()-1,s.size()-1); Fl::focus(Xcas_debug_input); } static void cb_Xcas_rmbrk_button(Fl_Button*, void* user) { string s("rmbreakpoint("); giac::context * contextptr =(giac::context *) user; s += giac::debug_ptr(contextptr)->debug_prog_name->print(); s += ','; s += giac::print_INT_(Xcas_source_browser->value()); s += ')'; Xcas_debug_input->value(s.c_str()); Xcas_debug_input->position(s.size()-1,s.size()-1); Fl::focus(Xcas_debug_input); } static void cb_Xcas_watch_button(Fl_Button*, void*) { Xcas_debug_input->value("watch("); Xcas_debug_input->position(6,6); Fl::focus(Xcas_debug_input); } static void cb_Xcas_rmwatch_button(Fl_Button*, void*) { Xcas_debug_input->value("rmwatch("); Xcas_debug_input->position(8,8); Fl::focus(Xcas_debug_input); } static void cb_Xcas_variable_browser(Fl_Browser*, void*) { Xcas_debug_input->insert(Xcas_variable_browser->text(Xcas_variable_browser->value())); } // end debugger callbacks and defs int autosave_time = 60 ; /* default save session every 60 seconds */ bool autosave_disabled = false; bool find_fold_autosave_function(bool warn_user){ History_Fold * hf=0; Fl_Widget * w = xcas::Xcas_input_focus; for (;w;){ if ( (hf=dynamic_cast(w)) ) break; w=w->parent(); } if (hf) return hf->autosave(warn_user); else return false; } bool (*autosave_function)(bool) = find_fold_autosave_function ; void (*idle_function)()=0; unsigned max_debug_printsize=1000; void Xcas_debugguer(int status,giac::context * contextptr){ if (debug_ptr(contextptr) && debug_ptr(contextptr)->debug_contextptr) contextptr = debug_ptr(contextptr)->debug_contextptr; // 2 -> debug, 3 ->wait click if (status==3){ vecteur v(gen2vecteur(Xcas_DispG?Xcas_DispG->waiting_click_value:undef)); if (v.empty()){ if (Xcas_DispG_Window) Xcas_DispG_Window->show(); if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->show(); if (Xcas_DispG) Xcas_DispG->waiting_click=true; for (;;) { Fl::wait(); if (Xcas_DispG_Window && !Xcas_DispG_Window->visible()){ Xcas_DispG->waiting_click=false; Xcas_DispG->waiting_click_value=undef; } bool wait=Xcas_DispG?Xcas_DispG->waiting_click:false; if (!wait) break; } if (Xcas_DispG) Xcas_DispG->waiting_click=false; if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); thread_eval_status(1,contextptr); return; } v=inputform_pre_analysis(v,contextptr); gen res=makeform(v,contextptr); if (Xcas_DispG) Xcas_DispG->waiting_click_value=inputform_post_analysis(v,res,contextptr); thread_eval_status(1,contextptr); return; } if (status==2){ if (!Xcas_Debug_Window){ int dx,dy; if (xcas::Xcas_input_focus && xcas::Xcas_input_focus->window()){ dx=8*(2*xcas::Xcas_input_focus->window()->w()/24); dy=11*(2*xcas::Xcas_input_focus->window()->h()/30); } else { dx=400; dy=500; } Fl_Double_Window* o = Xcas_Debug_Window = new Fl_Double_Window(dx,dy, gettext("Xcas Debug Window")); { Fl_Tile* o = Xcas_debug_tile = new Fl_Tile(0, 0, dx,dy); o->box(FL_FLAT_BOX); { Fl_Browser* o = Xcas_source_browser = new Fl_Browser(0,0,dx,4*dy/11); o->tooltip(gettext("Show the source of the program")); o->type(2); o->callback((Fl_Callback*)cb_Xcas_source_browser); } { xcas::Multiline_Input_tab* o = Xcas_debug_input = new xcas::Multiline_Input_tab(dx/8,4*dy/11, dx-dx/8,dy/11, gettext("eval")); o->type(4); o->box(FL_DOWN_BOX); o->color(FL_BACKGROUND2_COLOR); o->selection_color(FL_SELECTION_COLOR); o->labeltype(FL_NORMAL_LABEL); o->labelfont(0); o->labelsize(14); o->labelcolor(FL_FOREGROUND_COLOR); o->textcolor(1); o->callback((Fl_Callback*)cb_Xcas_debug_input); o->align(FL_ALIGN_LEFT); o->when(FL_WHEN_ENTER_KEY); } { Fl_Output* o = Xcas_debug_messages = new Fl_Output(0,5*dy/11,dx,2*dy/11); o->type(12); o->labelcolor(FL_FOREGROUND_COLOR); o->textcolor(4); } { Fl_Group* o = Xcas_debug_buttons = new Fl_Group(0,7*dy/11,dx,dy/11); { Fl_Button* o = Xcas_sst_button = new Fl_Button(0,7*dy/11,dx/8,dy/11, gettext("sst F5")); o->tooltip(gettext("Execute current line, skip function")); o->callback((Fl_Callback*)cb_Xcas_sst_button); o->shortcut(0xffc2); } { Fl_Button* o = Xcas_sst_in_button = new Fl_Button(dx/8,7*dy/11, dx/8, dy/11, gettext("in F6")); o->tooltip(gettext("Execute current line, step in function")); o->callback((Fl_Callback*)cb_Xcas_sst_in_button); o->shortcut(0xffc3); } { Fl_Button* o = Xcas_cont_button = new Fl_Button(2*dx/8,7*dy/11, dx/8, dy/11, gettext("cont F7")); o->tooltip(gettext("Continue execution until next breakpoint")); o->callback((Fl_Callback*)cb_Xcas_cont_button); o->shortcut(0xffc4); } { Fl_Button* o = Xcas_kill_button = new Fl_Button(3*dx/8,7*dy/11, dx/8, dy/11, gettext("kill")); o->tooltip(gettext("Kill current program")); o->callback((Fl_Callback*)cb_Xcas_kill_button); } { Fl_Button* o = Xcas_break_button = new Fl_Button(4*dx/8,7*dy/11, dx/8, dy/11, gettext("break")); o->tooltip(gettext("Add a breakpoint")); o->callback((Fl_Callback*)cb_Xcas_break_button); } { Fl_Button* o = Xcas_rmbrk_button = new Fl_Button(5*dx/8,7*dy/11, dx/8, dy/11, gettext("rmbrk")); o->tooltip(gettext("Remove a breakpoint")); o->callback((Fl_Callback*)cb_Xcas_rmbrk_button); } { Fl_Button* o = Xcas_watch_button = new Fl_Button(6*dx/8,7*dy/11,dx/8, dy/11, gettext("watch")); o->tooltip(gettext("Add a variable name to the watch")); o->callback((Fl_Callback*)cb_Xcas_watch_button); } { Fl_Button* o = Xcas_rmwatch_button = new Fl_Button(7*dx/8,7*dy/11,dx/8, dy/11, gettext("rmwtch")); o->tooltip(gettext("Add a variable name to the watch")); o->callback((Fl_Callback*)cb_Xcas_rmwatch_button); } o->end(); } { Fl_Browser* o = Xcas_variable_browser = new Fl_Browser(0,8*dy/11,dx,3*dy/11); o->tooltip(gettext("Show watch variables")); o->type(2); o->callback((Fl_Callback*)cb_Xcas_variable_browser); } o->end(); } o->end(); o->resizable(o); } Xcas_source_browser->user_data( (void *) contextptr); Xcas_break_button->user_data( (void *) contextptr); Xcas_rmbrk_button->user_data( (void *) contextptr); if (Xcas_Main_Window && Xcas_Debug_Window) change_group_fontsize(Xcas_Debug_Window,Xcas_Main_Window->labelsize()); if (Xcas_Debug_Window){ Xcas_Debug_Window->show(); // Xcas_Debug_Window->set_modal(); Xcas_debug_input->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); } // Debugging mode // cerr << "Debugging" << endl; debug_struct * dbgptr=debug_ptr(contextptr); if (dbgptr){ if (dbgptr->debug_info_ptr && dbgptr->debug_info_ptr->type==_VECT){ vecteur & w =*dbgptr->debug_info_ptr->_VECTptr; // w[0]=function, args, // w[1]=breakpoints // w[2] = instruction evaled or program source // w[3]= evaluation result // w[4]= current instruction number // w[5] = watch vector, w[6] = watch values string msg; msg += "eval("+w[2].print(contextptr) + ")= " + w[3].print(contextptr) + '\n'; msg += "Stopped in "; if ( w[0].type==_VECT && !w[0]._VECTptr->empty() ){ if (!dbgptr->debug_prog_name) dbgptr->debug_prog_name=new gen; if (*dbgptr->debug_prog_name!=w[0]._VECTptr->front()){ gen prog=w[0]._VECTptr->front(); *dbgptr->debug_prog_name=prog; if (prog.type==_IDNT) prog=prog.eval(1,contextptr); if (prog.is_symb_of_sommet(at_program) && prog.type==_VECT && prog._VECTptr->size()==3 ) prog=prog._VECTptr->back(); if (prog.type==_SYMB) prog=prog._SYMBptr->feuille; if (prog.type==_VECT && prog._VECTptr->size()==3) prog=prog._VECTptr->back(); w[2]=prog; Xcas_source_browser->clear(); vector vs; if (w[2].type==_VECT) debug_print(*w[2]._VECTptr,vs,contextptr); else debug_print(w[2],vs,contextptr); vector::iterator it=vs.begin(),itend=vs.end(); for (;it!=itend;++it){ Xcas_source_browser->add(it->c_str()); } } msg += dbgptr->debug_prog_name->print(contextptr) + "(" + gen(vecteur(w[0]._VECTptr->begin()+1,w[0]._VECTptr->end()),_SEQ__VECT).print(contextptr)+")"; msg += ",\nbreakpoint "+w[1].print(contextptr); } // if (w[0].type==_VECT) else msg += w[0].print(contextptr); msg += ",\nline " + w[4].print(contextptr); Xcas_debug_messages->value(msg.c_str()); gen w_in(w[5]),w_out(w[6]); if ( (w_in.type==_VECT) && (w_out.type==_VECT) ){ int pos=max(Xcas_variable_browser->value(),1); Xcas_variable_browser->clear(); const_iterateur it=w_in._VECTptr->begin(),itend=w_in._VECTptr->end(); const_iterateur jt=w_out._VECTptr->begin(),jtend=w_out._VECTptr->end(); for (;(it!=itend)&&(jt!=jtend);++it,++jt){ string tmps = replace(jt->print(contextptr),'\n',' '); if (tmps.size()>max_debug_printsize) tmps=tmps.substr(0,max_debug_printsize); Xcas_variable_browser->add( (it->print(contextptr) + " := " + tmps ).c_str()); } Xcas_variable_browser->value(giacmin(pos,w_in._VECTptr->size())); } xcas_current_instruction=w[4].val; Xcas_source_browser->value(w[4].val); /* console mode debugging if (dbgptr->debug_refresh){ if (dbgptr->fast_debug_info_ptr) cerr << *dbgptr->fast_debug_info_ptr << endl; } else { if (dbgptr->debug_info_ptr) cerr << *dbgptr->debug_info_ptr << endl; } */ } } gen g(at_sst); gen nxt; xcas_debug_ok=false; while (Xcas_Debug_Window->shown() && !xcas_debug_ok){ Fl::wait(); int cs=context_list().size(),ci=0,status=0; for (;civisible()) g=at_kill; else { string buf(Xcas_debug_input->value()); if (!buf.empty()){ try { g=gen(buf,contextptr); } catch (std::runtime_error & err){ cerr << err.what(); } } } *dbgptr->fast_debug_info_ptr = g; thread_eval_status(1,contextptr); } } void Xcas_idle_function(void * dontcheck){ static int initialized=-1; static time_t last_save=time(0); int cs=context_list().size(),ci=0,status=0; context * cptr=0; for (;ci1) break; } if (cishown()){ if (cptr){ usleep(100000); status=check_thread(cptr); } if (status<2) Xcas_Debug_Window->hide(); else return; // moved from below otherwise after debugging STOP button is always on } } if (Xcas_DispG_Window){ if (show_xcas_dispg){ if (show_xcas_dispg & 2){ if (!Xcas_DispG_Window->visible()) Xcas_DispG->autoscale(); if (show_xcas_dispg & 1){ Xcas_DispG_Window->show(); Xcas_DispG_Window->iconize(); } else Xcas_DispG_Window->show(); } else Xcas_DispG_Window->hide(); show_xcas_dispg=0; } } if (xcas_paused!=""){ Xcas_Main_Window->redraw(); if (Xcas_DispG) Xcas_DispG->redraw(); fl_message("%s",xcas_paused.c_str()); xcas_paused=""; } ++initialized; if (initialized % 5){ Fl::unlock(); #ifdef WIN32 usleep(10000); #else usleep(1000); #endif Fl::lock(); return; } if (!initialized && initialize_function) initialize_function(); if ( #ifdef WIN32 !(initialized%20) && #endif idle_function ) idle_function(); /* autosave */ time_t current=time(0); if (!autosave_disabled && autosave_function && double(current-last_save)>autosave_time){ if (autosave_function(false)) last_save=current; else last_save=current-autosave_time/2; } struct timeval cur; struct timezone tz; gettimeofday(&cur,&tz); vector::const_iterator it=animations.begin(),itend=animations.end(); for (;it!=itend;++it){ Graph2d3d * gr = *it; if (!gr->paused && gr->animation_dt>0){ double dt=cur.tv_sec-gr->animation_last.tv_sec+double(cur.tv_usec-gr->animation_last.tv_usec)/1e6; if (dt>gr->animation_dt){ gr->redraw(); } } } } bool operator < (const time_string & ts1,const time_string & ts2){ if (ts1.t!=ts2.t) return ts1.t < ts2.t; else return ts1.s < ts2.s; } // Check for auto-recovery data in directory s bool has_autorecover_data(const string & s_orig,vector & newest){ DIR *dp; struct dirent *ep; string s=s_orig; if (!s.empty() && s[s.size()-1]!='/') s += '/'; else s += '/'; dp = opendir (s.c_str()); if (dp != NULL){ while ( (ep = readdir (dp)) ){ string cur(ep->d_name); if (cur.size()>13&& cur.substr(0,10)=="xcas_auto_"){ string curext=cur.substr(cur.size()-3,3); if (curext=="xws"){ struct stat st; if (!stat((s+ep->d_name).c_str(),&st)){ time_t & t=st.st_mtime; // last modif newest.push_back(time_string(t,s+cur)); } } } } (void) closedir (dp); if (newest.size()==0) // no file return false; return true; } else return false; // Couldn't open the directory } bool stream_copy(std::istream & in,std::ostream & out) { char c; while (in){ if (!out){ return false; } c=in.get(); if (in.eof()){ return true; } out << c ; } return false; } bool add_user_menu(Fl_Menu_ *m,const string & s, const string & doc_prefix,Fl_Callback * cb){ string menufile; bool menufile_found=false; if (is_file_available(s.c_str())){ menufile_found=true; menufile=s; } else { if (getenv("XCAS_HELP")){ menufile=getenv("XCAS_HELP"); int ms=menufile.size(); for (--ms;ms>0;--ms){ if (menufile[ms]=='/') break; } if (ms) menufile=menufile.substr(0,ms+1)+doc_prefix+s; } else menufile=giac::giac_aide_dir()+doc_prefix+s; menufile_found=is_file_available(menufile.c_str()); } if (!menufile_found){ cerr << "// Unable to open menu file "<< menufile << endl; return false; } cerr << "// Using menu file " << menufile << endl; // Now reading commandnames from file for menus // Syntax is menu/submenu/item, callback inserts item name ifstream in(menufile.c_str()); string lu; int BUFSIZE=10000,endpos; char buf[BUFSIZE+1]; while (in){ in.getline(buf,BUFSIZE,'\n'); endpos=strlen(buf); if (endpos){ if (buf[endpos-1]=='\n') buf[endpos-1]=0; lu=buf; } if (in.eof()) break; m->add(lu.c_str(),0,cb); } return true; } void nextfl_menu(Fl_Menu_Item * & m){ if (m->submenu()){ ++m; for (;m->text;) nextfl_menu(m); } ++m; } void copy_menu(Fl_Menu_ * menu,const string & prefix,Fl_Menu_Item * & m){ for (;m->text;++m){ if (m->submenu()){ string prefix2=prefix+m->label(); prefix2 += '/'; ++m; copy_menu(menu,prefix2,m); } else menu->add((prefix+m->text).c_str(),m->shortcut_,m->callback_,m->user_data_,m->flags); } } 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)); if (!tmp.empty()) res.push_back(makevecteur(string2gen(s,false),tmp)); } else { gen g; if (m->callback_==menu2rpn_callback){ find_or_make_symbol(m->label(),g,0,false,context0); // 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_menu_fontsize(Fl_Menu_Item * m,int n,int labelfontsize){ for (int i=0;iattr.fontsize==labelfontsize) return; eq->attr.fontsize=labelfontsize; eq->labelsize(labelfontsize); eq->resize(eq->x(),eq->y(),eq->w(),eq->h()); eq->set_data(eq->get_data()); eq->adjust_widget_size(); } void change_group_fontsize(Fl_Widget * w,int labelfontsize){ w->labelsize(labelfontsize); w->redraw(); if (Equation * eq=dynamic_cast(w)){ change_equation_fontsize(eq,labelfontsize); return; } Fl_Group * g = dynamic_cast(w); if (!g) return; Fl_Font police=g->labelfont(); Fl_Widget * o; Fl_Widget * const * ptr= g->array(); int n=g->children(); for (int i=0;ilabelfont()!=FL_SYMBOL) o->labelfont(police); if (Fl_Menu * m=dynamic_cast(o)){ change_menu_fontsize(m,labelfontsize); continue; } if (Fl_Menu_ * mb=dynamic_cast(o)){ Fl_Menu_Item * mm=(Fl_Menu_Item *)mb->menu(); for (;mm->text;++mm) change_menu_fontsize(mm,labelfontsize); } if (Fl_Input_ * in=dynamic_cast(o)){ in->textsize(labelfontsize); in->textfont(police); } if (Equation * eq=dynamic_cast(o)){ eq->labelfont(police); change_equation_fontsize(eq,labelfontsize); } if (Xcas_Text_Editor * xed=dynamic_cast(o)){ xed->Fl_Text_Display::textsize(labelfontsize); xed->Fl_Text_Display::textfont(labelfontsize); vector & v=xed->styletable; for (unsigned i=0;ilabelsize(labelfontsize); Editeur * ed =dynamic_cast(xed->parent()); if (!ed && !xed->tableur) xed->resize_nl_before(1); xed->redraw(); } if (Fl_Value_Input * v=dynamic_cast(o)) v->textsize(labelfontsize); if (Fl_Browser * b=dynamic_cast(o)) b->textsize(labelfontsize); if (Fl_Counter * cc=dynamic_cast(o)) cc->textsize(labelfontsize); if (Fl_Group * og=dynamic_cast(o)) change_group_fontsize(og,labelfontsize); if (HScroll * os =dynamic_cast(o)){ // resize childs according to new scrollbar width os->resize(os->x(),os->y(),os->w(),os->h()); } if (Flv_Table_Gen * fl = dynamic_cast(o)){ fl->global_style.font_size(labelfontsize); fl->global_style.height(labelfontsize+4); fl->redraw(); } o->labelsize(labelfontsize); if (Graph2d3d * gr=dynamic_cast(o)) if (gr->parent() && !dynamic_cast
(gr->parent()) && !dynamic_cast(gr->parent())) gr->resize_mouse_param_group(gr->legende_size); } } // Cut a string for display in a multiline area of size w using fontsize 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;end2;){ 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 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::const_iterator it=cur_aide.blabla.begin(),itend=cur_aide.blabla.end(); for (;it!=itend;++it){ if (it->language==language){ result = it->chaine +'\n'+result ; break; } } std::vector::const_iterator jt=cur_aide.examples.begin(),jtend=cur_aide.examples.end(); for (;jt!=jtend;++jt) result = result + *jt + '\n'; std::vector::const_iterator kt=cur_aide.related.begin(),ktend=cur_aide.related.end(); for (;kt!=ktend;++kt) result = result + "-> "+print_INT_(kt->index)+": "+kt->chaine+'\n'; Xcas_help_output->value(result.c_str()); Xcas_help_output->redraw(); } } void browser_help(const giac::gen & g,int language){ giac::gen f(g); string s; if (f.type==giac::_SYMB) f=f._SYMBptr->sommet; if (f.type==giac::_FUNC) s=f._FUNCptr->ptr()->s; giac::html_vtt=giac::html_help(giac::html_mtt,s); help_output(s,language); if (!giac::html_vtt.empty()){ if (use_external_browser) giac::system_browser_command(giac::html_vtt.front()); else { if (xcas::Xcas_help_window){ xcas::Xcas_help_window->load(giac::html_vtt.front().c_str()); if (!xcas::Xcas_help_window->visible()) xcas::Xcas_help_window->show(); } } } } void check_browser_help(const giac::gen & g,int language){ if (g.is_symb_of_sommet(giac::at_findhelp)) browser_help(g._SYMBptr->feuille,language); } void dbgprint(const gen & g,vector & vs){ vecteur v(gen2vecteur(g)); const_iterateur it=v.begin(),itend=v.end(); for (;it!=itend;++it) vs.push_back(it->print(context0)); } void fl_wait_0001(context * contextptr){ static int t_sec=0,t_usec=0; int status=thread_eval_status(contextptr); Xcas_debugguer(status,contextptr); // don't flush too often timeval tp; if (!gettimeofday(&tp,0)){ if (tp.tv_sec==t_sec && tp.tv_usec < t_usec+50000){ usleep(100); return; } t_sec=tp.tv_sec; t_usec=tp.tv_usec ; } #ifdef __APPLE__ Fl::wait(0.001); #else Fl::wait(0.0001); #endif Xcas_idle_function(0); } giac::gen thread_eval(const giac::gen & g,int level,context * contextptr){ // Remove idle function for wait to work // cerr << "remove idle " << endl; Fl::remove_idle(xcas::Xcas_idle_function,0); gen res=giac::thread_eval(g,level,contextptr,fl_wait_0001); if (Xcas_Debug_Window) Xcas_Debug_Window->hide(); fl_wait_0001(contextptr); // Re-add idle function Fl::add_idle(xcas::Xcas_idle_function,0); return res; } Fl_Widget * in_Xcas_eval(Fl_Widget * w,const giac::gen & evaled_g0,int pretty_output,GIAC_CONTEXT){ gen evaled_g=evaled_g0; if (evaled_g.type==_MAP && evaled_g.subtype==1) evaled_g=giac::maptoarray(*evaled_g._MAPptr,contextptr); // cleanup giac::clear_prog_status(contextptr); giac::cleanup_context(contextptr); History_Pack * hp = get_history_pack(w); if (hp) Fl_Group::current(hp); if (calc_mode(contextptr)==-38) calc_mode(contextptr)=38; /* FIXME: use simplifier only if the user ask for it if (!g.is_symb_of_sommet(at_ifactor)) evaled_g=giac::_simplifier(evaled_g,contextptr); */ if (pretty_output){ int anim=giac::animations(evaled_g); if (evaled_g.is_symb_of_sommet(at_parameter) && evaled_g._SYMBptr->feuille.type==_VECT){ Gen_Value_Slider * res = parameter2slider(evaled_g,contextptr); if (res){ res->resize(w->x()+3*w->labelsize(),w->y(),w->w()-3*w->labelsize(),w->labelsize()); res->labelsize(w->labelsize()); return res; } } if (evaled_g.type == _VECT && graph_output_type(evaled_g)){ Fl_Tile * g = new Fl_Tile(w->x(),w->y(),w->w(),max(130,w->w()/3)); g->labelsize(w->labelsize()); Graph2d3d * tmp; #ifdef HAVE_LIBFLTK_GL if (is3d(evaled_g._VECTptr->back())){ #ifdef GRAPH_WINDOW Fl_Window * win=new Fl_Window(w->x(),w->y(),w->w(),g->h()); tmp =new Graph3d(0,0,w->w(),g->h(),"",hp); win->end(); win->show(); Fl_Group::current(g); #else tmp =new Graph3d(w->x(),w->y(),w->w(),g->h(),"",hp); #endif tmp->show(); } else #endif { tmp=new Graph2d(w->x(),w->y(),w->w(),g->h(),"",hp); if (Xcas_config.ortho) tmp->orthonormalize(); } tmp->add(evaled_g); if (anim) tmp->animation_dt=1./5; if (Xcas_config.autoscale) tmp->autoscale(); tmp->update_infos(evaled_g,contextptr); g->end(); change_group_fontsize(g,w->labelsize()); return g; } if (evaled_g.is_symb_of_sommet(at_pnt) || anim){ Fl_Tile * g = new Fl_Tile(w->x(),w->y(),w->w(),max(130,w->w()/3)); g->labelsize(w->labelsize()); Graph2d3d * res; #ifdef HAVE_LIBFLTK_GL if (is3d(evaled_g)){ #ifdef GRAPH_WINDOW Fl_Window * win=new Fl_Window(w->x(),w->y(),w->w(),g->h()); res = new Graph3d(0,0,w->w(),g->h(),"",hp); win->end(); win->show(); g->add(win); Fl_Group::current(g); #else res = new Graph3d(w->x(),w->y(),w->w(),g->h(),"",hp); #endif res->show(); } else #endif { res=new Graph2d(w->x(),w->y(),w->w(),g->h(),"",hp); if (Xcas_config.ortho) res->orthonormalize(); } res->add(evaled_g); if (anim) res->animation_dt=1./5; if (Xcas_config.autoscale) res->autoscale(); res->update_infos(evaled_g,contextptr); g->end(); change_group_fontsize(g,w->labelsize()); return g; } /* if (evaled_g.type==_DOUBLE_ || evaled_g.type==_INT_){ Gen_Output * o = new Gen_Output(w->x(),w->y(),w->w(),w->labelsize()+7); o->textsize(w->labelsize()); o->value(evaled_g); o->textcolor(FL_BLACK); fl_font(FL_HELVETICA,w->labelsize()); int hss=int(fl_width(o->Fl_Output::value()))+4; if (hss<=w->w()) return o; else delete o; } */ unsigned ta=taille(evaled_g,max_prettyprint_equation); if (talabelsize(),Xcas_equation_background_color,Xcas_equation_color); giac::gen varg=Equation_compute_size(evaled_g,attr,w->w(),contextptr); giac::eqwdata vv(Equation_total_size(varg)); int maxh=w->window()?(3*w->window()->h())/5:1000; int scrollsize=3; if (vv.dx>w->w()-2*w->labelsize()) scrollsize=w->labelsize()+3; int h=min(vv.dy+scrollsize+3,maxh); // =max(min(vv.dy+20,400),60); Equation * res = new Equation(w->x(),w->y(),w->w(),h,"",evaled_g,attr,contextptr); res->box(FL_FLAT_BOX); return res; } } Gen_Output * o = new Gen_Output(w->x(),w->y(),w->w(),w->labelsize()+7); o->textsize(w->labelsize()); o->value(evaled_g); o->textcolor(FL_BLUE); fl_font(FL_HELVETICA,w->labelsize()); int hss=int(fl_width(o->Fl_Output::value()))+4; if (hss<=w->w()) return o; o->resize(w->x(),w->y(),hss,w->labelsize()+7); Fl_Scroll * s = new Fl_Scroll(w->x(),w->y(),w->w(),2*w->labelsize()+9); s->hscrollbar.resize(s->hscrollbar.x(),w->y()+w->labelsize()+7,s->hscrollbar.w(),w->labelsize()); s->box(FL_FLAT_BOX); s->end(); s->add(o); return s; } void Xcas_eval_callback(const giac::gen & evaled_g,void * param){ Fl_Widget * wid=static_cast(param); if (!wid) return; int hp_pos; History_Pack * hp = get_history_pack(wid,hp_pos); context * contextptr = hp?hp->contextptr:0; Fl_Group * gr = wid->parent(); if (!hp || !gr) return; #ifdef HAVE_LIBPTHREAD // cerr << "geo2d lock" << endl; pthread_mutex_lock(&interactive_mutex); #endif bool b=io_graph(contextptr); io_graph(contextptr)=false; bool block=block_signal; block_signal=true; // int m=gr->children(); // reset output #ifdef WITH_MYOSTREAM logptr(&my_cerr,contextptr); #else logptr(&std::cerr,contextptr); #endif if (!giac::history_out(contextptr).empty() && giac::history_out(contextptr).size()==giac::history_in(contextptr).size()) giac::history_out(contextptr).back()=evaled_g; else giac::history_out(contextptr).push_back(evaled_g); int pos=gr->find(wid); Fl_Widget * res = in_Xcas_eval(wid,evaled_g,hp->pretty_output,contextptr); if (Log_Output * lout=find_log_output(gr)) output_resize_parent(lout,false); if (res){ // resize group/pack here gr->Fl_Widget::resize(gr->x(),gr->y(),gr->w(),gr->h()+res->h()-wid->h()); res->resize(wid->x(),wid->y(),res->w(),res->h()); int dy=res->h()-wid->h(); gr->remove(wid); Graph2d3d * widgraph = 0; if (Fl_Group * widgr = dynamic_cast(wid)){ if (widgr->children()) widgraph=dynamic_cast(widgr->child(0)); } Graph2d3d * resgraph = 0; if (Fl_Group * widgr = dynamic_cast(res)){ if (widgr->children()) resgraph=dynamic_cast(widgr->child(0)); } gr->insert(*res,pos); change_group_fontsize(gr,gr->labelsize()); if (widgraph && resgraph){ resgraph->copy(*widgraph); resgraph->resize(resgraph->x(),resgraph->y(),widgraph->w(),resgraph->h()); resgraph->resize_mouse_param_group(gr->w()-widgraph->w()); } // gr->resizable(gr); hp->resize(); if (Fl_Scroll * s = dynamic_cast(hp->parent())){ int spos=s->yposition(); if (spos+s->h()>hp->h()){ #ifdef _HAVE_FL_UTF8_HDR_ s->scroll_to(0,max(min(hp->h()-s->h(),spos+dy),0)); #else s->position(0,max(min(hp->h()-s->h(),spos+dy),0)); #endif } s->redraw(); } Fl_Group * group = parent_skip_scroll(hp); if (Logo * logo=dynamic_cast(group)){ logo->redraw(); } // show DispG? if (hp->pretty_output && !Xcas_DispG_Window->visible()){ int entries=Xcas_DispG->plot_instructions.size(); if (entries>xcas_dispg_entries){ if (resgraph){ vecteur dispgv=vecteur(Xcas_DispG->plot_instructions.begin()+xcas_dispg_entries,Xcas_DispG->plot_instructions.end()),v1,v2; aplatir(dispgv,v1); aplatir(resgraph->plot_instructions,v2); if (v1!=v2){ if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); show_xcas_dispg=3; } } else { if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); show_xcas_dispg=3; } } } block_signal=block; io_graph(contextptr)=b; #ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&interactive_mutex); #endif // if hp has eval_below, call callback on next widget if (hp->eval_below){ hp->next(hp_pos); /* Fl_Group * hpp = parent_skip_scroll(hp); if (hpp){ int N=hpp->children(); for (int i=0;i(hpp->child(i)); if (geo){ geo->handle(FL_FOCUS); } } } */ } else { Fl_Group * hpp = parent_skip_scroll(hp); if (hpp){ int N=hpp->children(); for (int i=0;i(hpp->child(i)); if (geo){ geo->add(evaled_g); geo->no_handle=false; } } } hp->focus(hp_pos+1,false); } } // if (res) else { // res==0 no output if (Fl_Input_ * i=dynamic_cast(wid)) i->value("No_output"); hp->resize(); block_signal=block; io_graph(contextptr)=b; #ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&interactive_mutex); #endif } } Fl_Widget * Xcas_eval(Fl_Widget * w,const giac::gen & g_){ if (!w) return 0; if (debug_infolevel>=5) cerr << "eval " << g_ << endl; Fl_Group * gr=w->parent(); Fl_Group::current(gr); // Find history_pack above for context from widget History_Pack * hp = get_history_pack(w); context * contextptr=hp?hp->contextptr:0; check_browser_help(g_,giac::language(contextptr)); if (!hp) return 0; gen g=add_autosimplify(g_,contextptr); giac::gen evaled_g; giac::history_in(contextptr).push_back(g_); // if w 2nd brother is a graph2d3d, return a graph2d3d with the same // config Fl_Widget * res = 0; if (gr && gr->children()>=3){ if (Fl_Group * grc2=dynamic_cast(gr->child(2))){ if (grc2->children()){ if (Graph2d3d * graph=dynamic_cast(grc2->child(0))){ Fl_Tile * temptile = new Fl_Tile(w->x(),w->y(),w->w(),w->labelsize()+6); Graph2d * tmp = new Graph2d(w->x(),w->y(),w->w(),temptile->h(),"",hp); temptile->end(); tmp->copy(*graph); tmp->resize(tmp->x(),tmp->y(),graph->w(),tmp->h()); temptile->labelsize(w->labelsize()); res=temptile; } } } } // commented otherwise ans() does not work // giac::history_out.push_back(g); Fl_Output * out=0; bool graphres=res; out =new Fl_Output(w->x(),w->y(),w->w(),w->labelsize()); out->labelsize(w->labelsize()); if (!res) res=out; bool ok=make_thread(g,eval_level(contextptr),Xcas_eval_callback,res,contextptr); if (graphres){ if (ok){ gr->remove(out); delete out; return res; } gr->remove(res); delete res; res=out; } out->value(ok?gettext("Computing..."):gettext("Unable to launch thread. Press STOP to interrupt.")); return res; } Fl_Widget * Xcas_eval(Fl_Widget * w) { giac::gen g; int res=parse(w,g); if (res==1) return Xcas_eval(w,g); if (res==-1) return w; /* Fl_Output * o = new Fl_Output(w->x(),w->y(),w->w(),w->h()); o->value("Invalid input"); return o; */ return 0; } string print_DOUBLE_(double d){ char s[256]; #ifdef IPAQ sprintf(s,"%.4g",d); #else sprintf(s,"%.5g",d); #endif return s; } string replace(const string & s,char c1,char c2){ string res; int l=s.size(); res.reserve(l); const char * ch=s.c_str(); for (int i=0;itype==_VECT) it->subtype=0; } return w; } History_Fold * load_history_fold(int sx,int sy,int sw,int sh,int sl,const char * filename,bool modified){ Fl_Group::current(0); xcas::History_Fold * w = new xcas::History_Fold(sx,sy,sw,sh,1); w->end(); w->pack->contextptr = giac::clone_context(giac::context0); w->pack->labelsize(sl); w->pack->eval=xcas::Xcas_eval; w->pack->_insert=xcas::Xcas_pack_insert; w->pack->_select=xcas::Xcas_pack_select; w->pack->new_url(filename); w->pack->insert_url(filename,-1); w->labelfont(w->pack->labelfont()); xcas::change_group_fontsize(w,w->pack->labelsize()); if (!modified) w->pack->clear_modified(); else { w->autosave(true); if (w->pack->url){ delete w->pack->url; w->pack->url=0; } w->label("Unnamed"); } return w; } std::string widget_html5(const Fl_Widget * o){ string res; const giac::context * contextptr = get_context(o); // Add here code for specific widgets if (const Tableur_Group * t = dynamic_cast(o)){ Flv_Table_Gen * g=t->table; matrice m=g->m; res = replace(gen(m,_SPREAD__VECT).print(contextptr),'\n',' '); return '+'+res+'&'; } if (const Figure * f = dynamic_cast(o)){ res = widget_html5(f->geo->hp); return res; } if (const Logo * l=dynamic_cast(o)){ res = widget_html5(l->hp); return res; } if (const Editeur * ed=dynamic_cast(o)){ string s=unlocalize(ed->value()); res = replace(s,'\n',' '); return '+'+res+'&'; } if (const Xcas_Text_Editor * ed=dynamic_cast(o)){ string s=unlocalize(ed->value()); res = replace(s,'\n',' '); return '+'+res+'&'; } if (dynamic_cast(o)) return ""; if (const Fl_Input_ * i=dynamic_cast(o)){ string s=i->value(); if (dynamic_cast(i)) s = "// "+replace(s,'\n',"
"); if ( dynamic_cast(i) ) s=unlocalize(s); if (s.empty()) return s; res = replace(s,'\n',' '); res = replace(res,'\'',"%27"); return '+'+res+'&' ; } if (const Fl_Group * g=dynamic_cast(o)){ int ypos=0; // call widget_sprint on children int n=g->children(); for (int i=0;ichild(i); res += widget_html5(wid); } return res; } if (const Gen_Value_Slider *g=dynamic_cast(o)){ res = string(g->label())+","+print_DOUBLE_(g->value())+","+print_DOUBLE_(g->minimum())+","+print_DOUBLE_(g->maximum())+","+print_DOUBLE_(g->Fl_Valuator::step()); return '*'+res+'&'; } return res ; } std::string widget_sprint(const Fl_Widget * o){ string res; const giac::context * contextptr = get_context(o); res = "// fltk " + string(typeid(*o).name()); int wh=o->h(); if (const History_Fold * hf=dynamic_cast(o)){ if (hf->_folded) wh=hf->_horig; } res += " " + giac::print_INT_(o->x()) + " " + giac::print_INT_(o->y())+ " " + giac::print_INT_(o->w()) + " " + giac::print_INT_(wh) + " " + giac::print_INT_(o->labelsize()) + " " + giac::print_INT_(o->labelfont()) ; // Add here code for specific widgets if (const Flv_Table_Gen * g = dynamic_cast(o)){ res += '\n'+print_INT_(g->is_spreadsheet)+" "+print_INT_(g->matrix_fill_cells)+" "+print_INT_(g->spreadsheet_recompute)+" "+print_INT_(g->matrix_symmetry)+ " " +replace(gen(g->m,_SPREAD__VECT).print(contextptr),'\n','£')+'\n'; return res; } if (const Tableur_Group * t = dynamic_cast(o)){ Flv_Table_Gen * g=t->table; Graph2d3d * gr = g->graph; matrice m=g->m; if (!g->m.empty()){ gen m0=m.front(); if (m0.type==_VECT && !m0._VECTptr->empty()){ vecteur m0v=*m0._VECTptr; gen m00=m0v.front(); if (m00.type==_VECT && m00._VECTptr->size()==3){ vecteur rowv,colv,dispv; for (int i=0;irows();++i) rowv.push_back(g->row_height(i)); for (int i=0;icols();++i) colv.push_back(g->col_width(i)); dispv.push_back(t->disposition); if (t->disposition/2){ if (t->disposition % 2){ // graph at right dispv.push_back(g->w()); dispv.push_back(g->graph->w()); dispv.push_back(g->graph->mouse_param_group->w()); } else { // graph below double dtable=double(g->h())/t->h(); double dgraph=((1-dtable)*g->graph->w())/g->w(); dispv.push_back(dtable); dispv.push_back(dgraph); dispv.push_back(1-dtable-dgraph); } } gen newm002=makevecteur(g->name, makevecteur(gr->window_xmin,gr->window_xmax,gr->window_ymin,gr->window_ymax), gr->npixels, makevecteur(gr->x_tick,gr->y_tick), gr->show_axes,gr->show_names,dispv,makevecteur(rowv,colv),g->init); m00=gen(makevecteur(m00[0],m00[1],newm002),m0v[0].subtype); m0v[0]=m00; m[0]=gen(m0v,m0[0].subtype); } } } res += '\n'+print_INT_(g->is_spreadsheet)+" "+print_INT_(g->matrix_fill_cells)+" "+print_INT_(g->spreadsheet_recompute)+" "+print_INT_(g->matrix_symmetry)+ " " +replace(gen(m,_SPREAD__VECT).print(contextptr),'\n','£')+'\n'; return res; } if (const Figure * f = dynamic_cast(o)){ res += " landscape="+print_INT_(f->disposition)+" history="; if (f->disposition & 1){ double tmp=double(f->geo->h())/f->h(); res += print_DOUBLE_((1-tmp)*double(f->s->w())/f->w())+ " geo="+print_DOUBLE_(tmp*double(f->geo->w())/f->w())+ " "+" mouse_param="+print_DOUBLE_(tmp*double(f->geo->mouse_param_group->w())/f->w()); } else res += print_DOUBLE_(double(f->s->w())/f->w())+ " geo="+print_DOUBLE_(double(f->geo->w())/f->w())+ " "+" mouse_param="+print_DOUBLE_(double(f->geo->mouse_param_group->w())/f->w()); res += '\n'+widget_sprint(f->geo->hp)+widget_sprint(f->geo)+'\n'; return res; } if (const Logo * l=dynamic_cast(o)){ res += '\n'+widget_sprint(l->hp)+widget_sprint(l->ed); return res; } if (const Editeur * ed=dynamic_cast(o)){ string s=unlocalize(ed->value()); res += '\n'+print_INT_(s.size())+" ,\n"+s; return res; } if (const Xcas_Text_Editor * ed=dynamic_cast(o)){ string s=unlocalize(ed->value()); res += '\n'+print_INT_(s.size())+" ,\n"+s; return res; } if (const Gen_Output * i=dynamic_cast(o)){ res += '\n'; string s=taille(i->value(),100)>100?string("Done"):i->value().print(contextptr); s=unlocalize(s); res += replace(s,'\n','£'); // res += '"'; return res + '\n'; } if (const Fl_Input_ * i=dynamic_cast(o)){ res += '\n'; string s=i->value(); if ( dynamic_cast(i) ) s=unlocalize(s); res += replace(s,'\n','£'); // res += '"'; return res + '\n'; } if (const Log_Output * i=dynamic_cast(o)){ res += '\n'; // res += '"'; res += replace(i->value(),'\n','£'); // res += '"'; return res + '\n'; } if (const Equation * i=dynamic_cast(o)){ res += " " + giac::print_INT_(i->output_equation); res += '\n'; // res += '"'; string s=taille(i->get_data(),1000)>1000?string("Done"):i->value(); res += replace(unlocalize(s),'\n','£'); // res += '"'; return res + '\n'; } if (const Graph2d3d * i=dynamic_cast(o)){ res += '\n'; res += print_DOUBLE_(i->window_xmin) + ',' + print_DOUBLE_(i->window_xmax) + ','; res += print_DOUBLE_(i->window_ymin) + ',' + print_DOUBLE_(i->window_ymax) + ','; res += replace(giac::gen(giac::merge_pixon(seq2vecteur(i->plot_instructions))).print(contextptr),'\n','£'); res += ','+ print_DOUBLE_(i->window_zmin) + ',' + print_DOUBLE_(i->window_zmax)+','+print_DOUBLE_(i->q.w) +','+print_DOUBLE_(i->q.x)+','+print_DOUBLE_(i->q.y)+','+print_DOUBLE_(i->q.z) + ','+print_DOUBLE_(i->x_tick) + ',' + print_DOUBLE_(i->y_tick)+','+print_INT_(i->show_axes)+','+print_INT_(i->couleur)+','+print_INT_(i->approx)+','+print_DOUBLE_(i->ylegende)+','; if (i->paused) res += "-"; res +=print_DOUBLE_(i->animation_dt)+','+print_INT_(i->show_mouse_on_object)+','+print_INT_(i->display_mode); res += ",["; if (dynamic_cast(i)){ for (int j=0;;){ res += "["+ print_DOUBLE_(i->light_x[j]); res += ","+ print_DOUBLE_(i->light_y[j]); res += ","+ print_DOUBLE_(i->light_z[j]); res += ","+ print_DOUBLE_(i->light_w[j]); res += ","+ print_DOUBLE_(i->light_diffuse_r[j]); res += ","+ print_DOUBLE_(i->light_diffuse_g[j]); res += ","+ print_DOUBLE_(i->light_diffuse_b[j]); res += ","+ print_DOUBLE_(i->light_diffuse_a[j]); res += ","+ print_DOUBLE_(i->light_specular_r[j]); res += ","+ print_DOUBLE_(i->light_specular_g[j]); res += ","+ print_DOUBLE_(i->light_specular_b[j]); res += ","+ print_DOUBLE_(i->light_specular_a[j]); res += ","+ print_DOUBLE_(i->light_ambient_r[j]); res += ","+ print_DOUBLE_(i->light_ambient_g[j]); res += ","+ print_DOUBLE_(i->light_ambient_b[j]); res += ","+ print_DOUBLE_(i->light_ambient_a[j]); res += ","+ print_DOUBLE_(i->light_spot_x[j]); res += ","+ print_DOUBLE_(i->light_spot_y[j]); res += ","+ print_DOUBLE_(i->light_spot_z[j]); res += ","+ print_DOUBLE_(i->light_spot_w[j]); res += ","+ print_DOUBLE_(i->light_spot_exponent[j]); res += ","+ print_DOUBLE_(i->light_spot_cutoff[j]); res += ","+ print_DOUBLE_(i->light_0[j]); res += ","+ print_DOUBLE_(i->light_1[j]); res += ","+ print_DOUBLE_(i->light_2[j])+","+print_INT_(i->light_on[j])+"]"; ++j; if (j==8) break; res += ","; } } // end i is a graph3d res += "]"; res += ","+print_INT_(i->ntheta)+","+print_INT_(i->nphi); res += ","+print_INT_(i->rotanim_type)+","+print_INT_(i->rotanim_danim)+","+print_INT_(i->rotanim_nstep)+","+print_DOUBLE_(i->rotanim_rx)+","+print_DOUBLE_(i->rotanim_ry)+","+print_DOUBLE_(i->rotanim_rz)+","+print_DOUBLE_(i->rotanim_tstep); res += ","+print_INT_(i->x_axis_color)+","+print_INT_(i->y_axis_color)+","+print_INT_(i->z_axis_color); return res + '\n'; } if (const History_Fold * g=dynamic_cast(o)){ res += '\n'+replace(g->input->value(),'\n','£') + '\n'; res += widget_sprint(g->pack); return res; } if (const Fl_Group * g=dynamic_cast(o)){ int ypos=0; if (Fl_Scroll * s=(Fl_Scroll *) dynamic_cast(g)){ ypos=s->yposition(); #ifdef _HAVE_FL_UTF8_HDR_ s->scroll_to(s->xposition(),0); #else s->position(s->xposition(),0); #endif } // call widget_sprint on children int n=g->children(); res += "\n[\n"; for (int i=0;ichild(i); res += widget_sprint(wid); if (i!=n-1) res += ",\n"; } res += "]\n"; if (Fl_Scroll * s=(Fl_Scroll *) dynamic_cast(g)){ #ifdef _HAVE_FL_UTF8_HDR_ s->scroll_to(s->xposition(),ypos); #else s->position(s->xposition(),ypos); #endif } return res; } if (const Gen_Value_Slider *g=dynamic_cast(o)){ res += "\n" + giac::print_INT_(g->pos)+" "+print_DOUBLE_(g->minimum())+" "+print_DOUBLE_(g->maximum())+" "+print_DOUBLE_(g->value())+" "+string(g->label())+" "+print_DOUBLE_(g->Fl_Valuator::step())+"\n"; return res; } return res + "\n[]\n"; } void next_line(const string & s,int L,string & line,int & i){ line=""; for (;iw());){ if (History_Pack * hp=dynamic_cast(o)) hp->contextptr=(giac::context *)contextptr; if (o->w()>res->w()) o->resize(o->x(),o->y(),res->w(),o->h()); if (o->parent()!=res) res->add(o); // remove empty group if (Fl_Group * gr = dynamic_cast(o)){ if (!gr->children()) res->remove(gr); } if (iend(); string line; next_line(s,L,line,i); if (line=="]\n") return res; else return 0; } void graphic_load(Graph2d3d * res,const std::string & s,int L,string & line,int & i){ /* if (res->mouse_param_group && !dynamic_cast
(res->parent())){ int X=res->x(); int Y=res->y(); int W=res->parent()->w(); int H=res->h(); int l=W/4; if (l>6*res->labelsize()) l=6*res->labelsize(); res->resize(X,Y,W-l,H); res->resize_mouse_param_group(l); } */ next_line_nonl(s,L,line,i); if (s[i]=='\n') ++i; const giac::context * contextptr = get_context(res); giac::gen g(line,contextptr); if (g.type==_VECT && g._VECTptr->size()>=5){ giac::vecteur & v =*g._VECTptr; res->window_xmin= giac::evalf_double(v[0],1,contextptr)._DOUBLE_val; res->window_xmax= giac::evalf_double(v[1],1,contextptr)._DOUBLE_val; res->window_ymin= giac::evalf_double(v[2],1,contextptr)._DOUBLE_val; res->window_ymax= giac::evalf_double(v[3],1,contextptr)._DOUBLE_val; gen gg=v[4]; if (gg.type==_VECT) res->add(*gg._VECTptr); else res->add(gg); if (v.size()>=7){ res->window_zmin= giac::evalf_double(v[5],1,contextptr)._DOUBLE_val; res->window_zmax= giac::evalf_double(v[6],1,contextptr)._DOUBLE_val; } if (v.size()>=11){ res->q=quaternion_double(giac::evalf_double(v[7],1,contextptr)._DOUBLE_val,giac::evalf_double(v[8],1,contextptr)._DOUBLE_val,giac::evalf_double(v[9],1,contextptr)._DOUBLE_val,giac::evalf_double(v[10],1,contextptr)._DOUBLE_val); } if (v.size()>=13){ res->x_tick=giac::evalf_double(v[11],1,contextptr)._DOUBLE_val; res->y_tick=giac::evalf_double(v[12],1,contextptr)._DOUBLE_val; } if (v.size()>=14) res->show_axes=v[13].val; if (v.size()>=16){ res->couleur=v[14].val; res->approx=v[15].val; } if (v.size()>=17) res->ylegende=evalf_double(v[16],1,contextptr)._DOUBLE_val; if (v.size()>=18){ gen tmp=evalf_double(v[17],1,contextptr); res->animation_dt=tmp.DOUBLE_val(); if (std::abs(res->animation_dt<1e-10)) res->animation_dt=0; if (res->animation_dt<0){ res->paused=true; res->animation_dt=-res->animation_dt; } } if (v.size()>=19) res->show_mouse_on_object=int(evalf_double(v[18],1,contextptr)._DOUBLE_val); if (v.size()>=20) res->display_mode=int(evalf_double(v[19],1,contextptr)._DOUBLE_val); if (v.size()>=21 && v[20].type==_VECT){ vecteur & vv=*v[20]._VECTptr; for (unsigned j=0;j< vv.size() && j<8;++j){ gen & tmp=vv[j]; if ( (tmp.type==_VECT && tmp._VECTptr->size()>=25) ){ vecteur w = *evalf_double(tmp,1,contextptr)._VECTptr; res->light_x[j]=w[0]._DOUBLE_val; res->light_y[j]=w[1]._DOUBLE_val; res->light_z[j]=w[2]._DOUBLE_val; res->light_w[j]=w[3]._DOUBLE_val; res->light_diffuse_r[j]=w[4]._DOUBLE_val; res->light_diffuse_g[j]=w[5]._DOUBLE_val; res->light_diffuse_b[j]=w[6]._DOUBLE_val; res->light_diffuse_a[j]=w[7]._DOUBLE_val; res->light_specular_r[j]=w[8]._DOUBLE_val; res->light_specular_g[j]=w[9]._DOUBLE_val; res->light_specular_b[j]=w[10]._DOUBLE_val; res->light_specular_a[j]=w[11]._DOUBLE_val; res->light_ambient_r[j]=w[12]._DOUBLE_val; res->light_ambient_g[j]=w[13]._DOUBLE_val; res->light_ambient_b[j]=w[14]._DOUBLE_val; res->light_ambient_a[j]=w[15]._DOUBLE_val; res->light_spot_x[j]=w[16]._DOUBLE_val; res->light_spot_y[j]=w[17]._DOUBLE_val; res->light_spot_z[j]=w[18]._DOUBLE_val; res->light_spot_w[j]=w[19]._DOUBLE_val; res->light_spot_exponent[j]=w[20]._DOUBLE_val; res->light_spot_cutoff[j]=w[21]._DOUBLE_val; res->light_0[j]=w[22]._DOUBLE_val; res->light_1[j]=w[23]._DOUBLE_val; res->light_2[j]=w[24]._DOUBLE_val; if (tmp._VECTptr->size()>=26) res->light_on[j]=int(w[25]._DOUBLE_val); } } } if (v.size()>=23 && v[21].type==_INT_ && v[22].type==_INT_){ res->ntheta=v[21].val; res->nphi=v[22].val; } if (v.size()>=26 && v[23].type==_INT_ && v[24].type==_INT_&& v[25].type==_INT_){ res->rotanim_type=v[23].val; res->rotanim_danim=v[24].val; res->rotanim_nstep=v[25].val; } if (v.size()>=30 && v[26].type==_DOUBLE_ && v[27].type==_DOUBLE_&& v[28].type==_DOUBLE_){ res->rotanim_rx=v[26]._DOUBLE_val; res->rotanim_ry=v[27]._DOUBLE_val; res->rotanim_rz=v[28]._DOUBLE_val; res->rotanim_tstep=v[29]._DOUBLE_val; } if (v.size()>=33 && v[30].type==_INT_ && v[31].type==_INT_&& v[32].type==_INT_){ res->x_axis_color=v[30].val; res->y_axis_color=v[31].val; res->z_axis_color=v[32].val; } } if (Geo2d * geo=dynamic_cast(res)){ geo->hp=geo_find_history_pack(geo); if (geo_run && geo->hp) geo->hp->update(); } #ifdef HAVE_LIBFLTK_GL if (Geo3d * geo=dynamic_cast(res)){ geo->hp=geo_find_history_pack(geo); if (geo_run && geo->hp) geo->hp->update(); } #endif } void tableur_load(Flv_Table_Gen * & res,const std::string & s,int x,int y,int w,int h){ int taille=s.size(),i=0; for (int j=0;j<4&&i> is_spreadsheet >> matrix_fill_cells >> spreadsheet_recompute >> matrix_symmetry ; giac::context * contextptr=get_context(res); gen g(s2,contextptr); if (!ckmatrix(g,true)) return ; Tableur_Group * t=dynamic_cast(res->parent()); spread_ck(*g._VECTptr); // in place modifications of g // Find name of tableur in g matrice m=*g._VECTptr; if (!res) res = new Flv_Table_Gen(x,y,w,h,""); else { int n,c; mdims(m,n,c); res->rows(n); res->cols(c); } if (!m.empty()){ gen g0=g._VECTptr->front(); if (g0.type==_VECT && !g0._VECTptr->empty()){ vecteur m0=*g0._VECTptr; gen g00= m0.front(); if (g00.type==_VECT && g00._VECTptr->size()>=3){ vecteur m00=*g00._VECTptr; gen g002 = m00.back(); if (g002.type==_IDNT) res->name=g002; if (g002.type==_VECT){ Graph2d * gr = res->graph; vecteur & ggv = *g002._VECTptr; int ggs=ggv.size(); if (ggs>0 && ggv[0].type==_IDNT) res->name=ggv[0]; if (gr && ggs>5){ if (ggv[1].type==_VECT && ggv[1]._VECTptr->size()>3){ vecteur & tmpv=*ggv[1]._VECTptr; gr->window_xmin=evalf_double(tmpv[0],1,contextptr)._DOUBLE_val; gr->window_xmax=evalf_double(tmpv[1],1,contextptr)._DOUBLE_val; gr->window_ymin=evalf_double(tmpv[2],1,contextptr)._DOUBLE_val; gr->window_ymax=evalf_double(tmpv[3],1,contextptr)._DOUBLE_val; } if (ggv[2].type==_INT_) gr->npixels = ggv[2].val; if (ggv[3].type==_VECT && ggv[3]._VECTptr->size()>1){ vecteur & tmpv=*ggv[3]._VECTptr; gr->x_tick=evalf_double(tmpv[0],1,contextptr)._DOUBLE_val; gr->y_tick=evalf_double(tmpv[1],1,contextptr)._DOUBLE_val; } if (ggv[4].type==_INT_) gr->show_axes = ggv[4].val; if (ggv[5].type==_INT_) gr->show_names = ggv[5].val; } if (ggs>6 && t){ if (ggv[6].type==_INT_) t->disposition=ggv[6].val; if (ggv[6].type==_VECT){ vecteur dispv=*ggv[6]._VECTptr; int dispvs=dispv.size(); if (dispvs) t->disposition=dispv[0].val; if (dispvs>3){ double d1=evalf_double(dispv[1],1,contextptr)._DOUBLE_val; double d2=evalf_double(dispv[2],1,contextptr)._DOUBLE_val; double d3=evalf_double(dispv[3],1,contextptr)._DOUBLE_val; t->resize2(d1,d2,d3); } } } if (ggs>7 && t){ // read row_height and col_witdh if (ggv[7].type==_VECT && ggv[7]._VECTptr->size()==2){ gen & rowg=ggv[7]._VECTptr->front(); if (rowg.type==_VECT){ vecteur & rowv = *rowg._VECTptr; int rowvs=giacmin(rowv.size(),t->table->rows()); for (int i=0;itable->row_height(rowv[i].val,i); } } gen & colg=ggv[7]._VECTptr->back(); if (colg.type==_VECT){ vecteur & colv = *colg._VECTptr; int colvs=giacmin(colv.size(),t->table->cols()); for (int i=0;itable->col_width(colv[i].val,i); } } } } if (ggs>8 && t){ t->table->init=ggv[8]; } } // end g002 of type _VECT g002=2; m00.back()=g002; m0.front()=gen(m00,m0.front().subtype); m.front()=gen(m0,m.front().subtype); res->filename = new string(res->name.print(contextptr)+".tab"); } } } if (res) res->set_matrix(m,false,false); res->is_spreadsheet = is_spreadsheet; res->matrix_fill_cells = matrix_fill_cells; res->spreadsheet_recompute = spreadsheet_recompute; res->matrix_symmetry=matrix_symmetry; res->update_status(); if (sheet_run) res->spread_eval_interrupt(); res->update_spread_graph(); res->redraw(); if (t) t->resize2(); } void xcas_text_editor_load(Xcas_Text_Editor * & res,const std::string & s,int x,int y,int w,int h){ Fl_Text_Buffer * b = new Fl_Text_Buffer; res = new Xcas_Text_Editor(x,y,w,h,b); res->callback(History_Pack_cb_eval,0); res->textcolor(Xcas_input_color); res->color(Xcas_input_background_color); res->buffer()->add_modify_callback(style_update, res); res->buffer()->insert(0,s.c_str()); res->set_gchanged(); res->end(); } void editeur_load(Editeur * & res,const std::string & s,int x,int y,int w,int h){ res = new Editeur(x,y,w,h,""); res->callback(History_Pack_cb_eval,0); res->editor->buffer()->insert(0,s.c_str()); } bool split_string(const string & s,char sep,string & before,string & after){ int j=s.find('='),ss=s.size(); if (j>0 && j8 && line.substr(0,8)=="// fltk "){ #ifdef HAVE_SSTREAM istringstream is(line); #else istrstream is(line.c_str()); #endif string tmp,attrib; char ch; is >> tmp; // get // is >> tmp; // get fltk is >> tmp; // get widget type vector v; for (;;){ ch=is.get(); if (ch=='\n' || !is || is.eof()) break; if (ch<=' '){ if (!attrib.empty()){ v.push_back(attrib); attrib=""; } } else attrib += ch; } if (!attrib.empty()) v.push_back(attrib); int vs=v.size(); int x=(vs>0)?atoi(v[0].c_str()):0; int y=(vs>1)?atoi(v[1].c_str()):0; int w=(vs>2)?atoi(v[2].c_str()):10; bool ortho=false; if (widgetw){ ortho=(w!=widgetw); w=widgetw; } if (w<10) w=10; int h0=(vs>3)?atoi(v[3].c_str()):5; if (h0<1) h0=1; int h=h0; if (h<5) h=5; int lsize=(vs>4)?atoi(v[4].c_str()):14; Fl_Font police=(vs>5)?Fl_Font(atoi(v[5].c_str())):FL_HELVETICA; if (police>=fonts_available) police=FL_HELVETICA; unsigned pos=tmp.find("History_Fold"),tmps=tmp.size(); if (pos>0 && poslabelsize(lsize); res->labelfont(police); res->input->value(line.c_str()); next_line(s,L,line,i); // should be history_pack... next_line(s,L,line,i); // should be [\n res->pack->labelfont(police); res->pack->eval=xcas::Xcas_eval; res->pack->_insert=xcas::Xcas_pack_insert; res->pack->_select=xcas::Xcas_pack_select; widget_group_load(res->pack,s,L,i,contextptr); res->fold(); res->pack->_resize_above=true; res->redraw(); return res->pack?res:0; } pos = tmp.find("History_Pack"); if (pos>0 && poslabelsize(lsize); res->labelfont(police); next_line(s,L,line,i); // should be [\n res->eval=xcas::Xcas_eval; res->_insert=xcas::Xcas_pack_insert; res->_select=xcas::Xcas_pack_select; widget_group_load(res,s,L,i,contextptr); res->redraw(); // next_line(s,L,line,i); return res; } pos = tmp.find("Tableur_Group"); if (pos>0 && poslabelfont(police); next_line_nonl(s,L,line,i); tableur_load(res->table,line,x,y,w,h); return res; } pos=tmp.find("Fl_Scrollbar"); if (pos>0 && pos0 && pos0 && pos0 && pos20 && poslabelsize(lsize); res->labelfont(police); res->box(FL_FLAT_BOX); widget_group_load(res,s,L,i,contextptr); // reorder scrollbars at the end int n=res->children(); if (n && dynamic_cast(res->child(0))) res->add(res->child(0)); if (n && dynamic_cast(res->child(0))) res->add(res->child(0)); // skip next scrollbar next_line(s,L,line,i); // skip Fl_Scrollbar next_line(s,L,line,i); // skip [] next_line(s,L,line,i); // skip ] (matching the [ from Fl_Scroll) return res; } pos=tmp.find("Fl_Group"); if (pos>0 && poslabelsize(lsize); res->labelfont(police); widget_group_load(res,s,L,i,contextptr); tmps=line2.size(); pos=line2.find("Mouse_Position"); if (pos>0 && pos clear(); // remove this group since it's a param_mouse_group return res; } pos=tmp.find("Fl_Tile"); if (pos>0 && poslabelsize(lsize); res->labelfont(police); widget_group_load(res,s,L,i,contextptr); tmps=line2.size(); pos=line2.find("Mouse_Position"); if (pos>0 && pos clear(); // remove this group since it's a param_mouse_group pos=line2.find("Flv_Table_Gen"); // remove objects not linked inside Flv_Table_Gen if (pos>0 && poschildren(); Flv_Table_Gen * g = dynamic_cast(res->child(0)); if (g){ for (int i=n-1;i;--i){ Fl_Widget * w = res->child(i); if (w==g->_goto || w==g->input || w==g->graph || w==g->graph-> mouse_param_group) break; res->remove(w); delete w; } } } return res; } pos=tmp.find("Figure"); if (pos>0 && posgeo->no_handle=true; fig->geo->hp->remove_entry(0,false); fig->geo->hp->eval_below=true; fig->geo->hp->pretty_output=false; fig->geo->hp->labelfont(police); widget_group_load(fig->geo->hp,s,L,i,contextptr); next_line(s,L,line,i); pos=line.find("3d");// should be Geo2d or Geo3d bool dim3= pos>0 && posgeo; Fl_Group * p=wid->parent(); p->remove(wid); p->remove(wid->mouse_param_group); Fl_Group::current(p); fig->geo=new Geo3d(wid->x(),wid->y(),2*w/3,h-wid->labelsize(),fig->geo->hp); int pos=p->find(wid); p->insert(*fig->geo,pos); delete wid; } #endif graphic_load(fig->geo,s,L,line,i); // fig->geo->hide(); // parse further parameters for the figure string before,after; double dhp=0.25,dgeo=0.5,dmp=0.25; for (int i=5;i0 && poslabelfont(),lsize=pack->labelsize(),y=before_position; bool finished=false; while (!finished){ int nextpos=s.find('&',pos+1); if (nextpos > L){ nextpos=L; finished=true; } if (nextpossize()>=5){ txt="assume("+g[0].print(contextptr)+"=["+g[1].print(contextptr)+","+g[2].print(contextptr)+","+g[3].print(contextptr)+","+g[4].print(contextptr)+"])"; } } Xcas_pack_insert(pack,txt.c_str(),txt.size(),y); ++y; pos=nextpos; } pack->redraw(); // next_line(s,L,line,i); return 1; } } Fl_Widget * o; for (;iw()-pack->_printlevel_w) )){ if (Fl_Group * g=dynamic_cast(o)) pack->add_entry(before_position,g); else pack->add_entry(before_position,o); if (i='0' && s[i]<='9'){ nchar *= 10; nchar += s[i]-'0'; ++i; } if (nchar<=L-i-1){ string tmps=s.substr(i+1,nchar); gen replace; if (!recovery_mode) unarchive_session_string(tmps,-1,replace,contextptr); i+=nchar+2; continue; } } // Now add line in a multiline_input_tab entry string line; next_line_nonl(s,L,line,i); int ls=line.size(); if (ls>2 && line[ls-1]==';' && line[ls-2]==';') line = line.substr(0,ls-1); if (ls>2 && line[0]=='/' && line[1]=='/') line = "/*"+line.substr(1,ls-1)+"*/"; if (ls>4 && line[0]=='/' && line[1]=='*' && line[ls-1]=='/' && line[ls-2]=='*'){ line=line.substr(2,ls-4); Comment_Multiline_Input * w = dynamic_cast(new_comment_input(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+10)); if (w){ w->value(line.c_str()); w->set_changed(); pack->add_entry(before_position,w); } } else { #if 0 Multiline_Input_tab * w = dynamic_cast(new_question_multiline_input(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+10)); #else // requires call to update() to be commented in History_Pack::handle(int event) // for FL_PASTE event Xcas_Text_Editor * w = dynamic_cast(new_question_editor(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+14)); #endif if (w){ w->value(line.c_str()); w->set_changed(); pack->add_entry(before_position,(Fl_Widget*) w); w->resize_nl_before(1); } } } // end for change_group_fontsize(pack,pack->labelsize()); set_context(pack,contextptr); parent_redraw(pack); return i; } giac::gen in_Xcas_fltk_interactive(const giac::gen & g,const giac::context * contextptr){ if (is_zero(g,contextptr)) return Xcas_DispG?Xcas_DispG->plot_instructions:undef; if (g.type==_SYMB){ unary_function_ptr & u=g._SYMBptr->sommet; gen f=g._SYMBptr->feuille; if (u==at_pnt){ // Xcas_DispG_Window->show(); // Xcas_Main_Window->show(); redraw_turtle=1; if (Xcas_DispG && f.subtype!=_LOGO__VECT) Xcas_DispG->add(g); return 1; } if (u==at_equal){ if (Xcas_DispG) Xcas_DispG->add(g); return 1; } if (u==at_erase){ // Xcas_DispG_Window->show(); // Xcas_Main_Window->show(); if (Xcas_DispG) Xcas_DispG->clear(); return 1; } if (u==at_Pictsize){ if (Xcas_DispG){ // plot_instructionsw=Xcas_DispG->w(); // plot_instructionsh=Xcas_DispG->h(); gnuplot_xmax=Xcas_DispG->window_xmax; gnuplot_xmin=Xcas_DispG->window_xmin; gnuplot_ymax=Xcas_DispG->window_ymax; gnuplot_ymin=Xcas_DispG->window_ymin; return makevecteur(Xcas_DispG->w(),Xcas_DispG->h()); } return makevecteur(0,0); } if (u==at_RclPic && f.type==_VECT){ // Xcas_DispG_Window->show(); // Xcas_Main_Window->show(); if (Xcas_DispG) Xcas_DispG->add(*f._VECTptr); return 1; } if (u==at_RplcPic && f.type==_VECT){ // Xcas_DispG_Window->show(); // Xcas_Main_Window->show(); if (Xcas_DispG){ Xcas_DispG->clear(); Xcas_DispG->add(*f._VECTptr); } return 1; } if (u==at_Pause){ if (f.type==_STRNG) xcas_paused=*f._STRNGptr; else xcas_paused="Paused"; for (int i=0;i<360000;++i){ if (xcas_paused.empty()) break; usleep(10000); } return 1; } if (u==at_ClrIO){ * logptr(contextptr) << " "; return 1; } if (u==at_DispG){ if (Xcas_DispG_Window) show_xcas_dispg=2; #ifndef WIN32 if (Xcas_Main_Window) Xcas_Main_Window->show(); #endif return 1; } if (u==at_DispHome){ if (Xcas_DispG_Window) show_xcas_dispg=1; return 1; } /* 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.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 1; } giac::gen Xcas_fltk_interactive(const giac::gen & g,GIAC_CONTEXT){ #ifdef HAVE_LIBPTHREAD // cerr << "xcas lock" << g << endl; pthread_mutex_lock(&interactive_mutex); #endif if (block_signal){ cerr << "blocked " << g << endl; #ifdef HAVE_LIBPTHREAD pthread_mutex_unlock(&interactive_mutex); #endif return zero; } gen res=in_Xcas_fltk_interactive(g,contextptr); // FIXME change interactive for context, like input #ifdef HAVE_LIBPTHREAD // cerr << "xcas unlock" << endl; pthread_mutex_unlock(&interactive_mutex); #endif return res; } giac::gen in_Xcas_fltk_getKey(const giac::gen & g,giac::context * contextptr){ int ch=Fl::event_key(); if (Fl::event_key(ch)) return ch; else return -ch; } giac::gen Xcas_fltk_getKey(const giac::gen & g,GIAC_CONTEXT){ if (block_signal){ return zero; } gen res; if (is_minus_one(g)){ Fl::lock(); res=in_Xcas_fltk_getKey(g,0); Fl::unlock(); } else res=Xcas_fltk_input(makevecteur(at_getKey,g),contextptr); // FIXME change interactive for context, like input if (is_inf(res)) setsizeerr(); return res; } vector vbrowser; vector gbrowser; void cb_plotfltk_browser(Fl_Browser * b,void *){ if (b->value()){ vector ::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 int nlines(const string & s){ int res=1; int ns=s.size()-1; for (int i=0;ifeuille,contextptr).print(contextptr).c_str()); return plus_one; } if (!v.empty() && v.front()==at_getKey){ Fl_Widget * foc=Fl::focus(); static Fl_Window * getkeywin=0; static Fl_Button * getkeybut = 0; static Fl_Input * getkeyin = 0; static Fl_Multiline_Output * getkeyout = 0; if (!getkeywin){ Fl_Group::current(0); getkeywin=new Fl_Window(50,50,200,200); getkeywin->label(gettext("Press a key")); getkeyout= new Fl_Multiline_Output(2,24,196,170); getkeybut=new Fl_Button(2,2,96,20); getkeybut->label(gettext("Cancel")); getkeybut->shortcut("^["); getkeyin = new Fl_Input(102,2,96,20); getkeyin->when(FL_WHEN_CHANGED); getkeywin->end(); getkeywin->resizable(getkeywin); } string msg(gettext("Press a key\n")); int vs=v.size(); for (int i=1;ivalue(msg.c_str()); getkeyin->value(""); getkeywin->show(); getkeywin->set_modal(); Fl::focus(getkeyin); if (Xcas_Main_Window){ Xcas_Main_Window->redraw(); } Fl::flush(); gen res=undef; for (;;){ Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); if (o==getkeybut) res=unsigned_inf; if (o==getkeybut || o==getkeywin){ break; } if (o==getkeyin){ int l=strlen(getkeyin->value()); if (l){ res=getkeyin->value()[l-1]; break; } } } getkeywin->hide(); Fl::focus(foc); return res; } int initw,inith; if (Xcas_input_focus && Xcas_input_focus->window()){ initw=(Xcas_input_focus->window()->w()*3)/4; inith=(Xcas_input_focus->window()->h()*3)/4; } else { initw = 240; inith = 320; } Fl_Group::current(0); static Fl_Window * Plotfltk_w = new Fl_Window(initw,inith); int r; vecteur res; Fl_Window * w = Plotfltk_w ; w->end(); int taillew=w->w(),tailleh=w->h(); if (taillew<100 || tailleh<100){ if (taillew<100) taillew=100; if (tailleh<100) tailleh=100; w->resize(w->x(),w->y(),taillew,tailleh); } Fl_Group::current(w); static Fl_Button * button0 = new Fl_Button(2+(2*taillew)/3, 0, taillew/4, 20); button0->shortcut("^["); button0->resize(2+(2*taillew)/3, 0, taillew/4, 20); button0->label(gettext("Cancel")); static Fl_Button * button1 = new Fl_Return_Button(2+taillew/3, 0, taillew/4, 20); button1->label(gettext("OK")); button1->resize(2+taillew/3, 0, taillew/4, 20); static Fl_Button * button2 = new Fl_Button(2, 0, taillew/4, 20); button2->label(gettext("STOP")); button2->resize(2, 0, taillew/4, 20); // Now parse v int current_y=22; vector vinput; vector voutput; vector labels; /* vector vpopup; vector < vector > vpopupitem; */ const_iterateur it=v.begin(),itend=v.end(); bool focused=false; for (;it!=itend;++it){ if (it->type==_IDNT || it->is_symb_of_sommet(at_of) || it->is_symb_of_sommet(at_at)){ Fl_Input * o; string * l=new string (it->print(contextptr)); labels.push_back(l); int taille=4+int(fl_width(l->c_str())); if (taille>taillew/2) taille=taillew/2; int yadd=6+nlines(*l)*14; o=new Fl_Input(taille,current_y,taillew-taille,yadd,l->c_str()); vinput.push_back(o); if (!focused){ focused=true; Fl::focus(o); } current_y += yadd; continue; } if ( (it->type==_STRNG) && it+1!=itend && ((it+1)->type==_IDNT || (it+1)->is_symb_of_sommet(at_at) || (it+1)->is_symb_of_sommet(at_of)) ){ Fl_Input * o; string * l=new string (*it->_STRNGptr); labels.push_back(l); int yadd=6+nlines(*l)*14; int taille=4+int(fl_width(l->c_str())); if (taille>taillew/2) taille=taillew/2; o=new Fl_Input(taille,current_y,taillew-taille,yadd,l->c_str()); ++it; vinput.push_back(o); if (!focused){ focused=true; Fl::focus(o); } current_y += yadd; 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) ) { vecteur vg(gen2vecteur(g)); if (vg.empty()) continue; Fl_Input * o; gen tmps=vg[0].eval(eval_level(contextptr),contextptr); string * l=new string (tmps.type==_STRNG?*tmps._STRNGptr:tmps.print(contextptr)); labels.push_back(l); int taille=4+int(fl_width(l->c_str())); if (taille>taillew/2) taille=taillew/2; o=new Fl_Input(taille,current_y,taillew-taille,20,l->c_str()); if (vg.size()>1&& u!=at_Request) o->value(vg[1].eval(eval_level(contextptr),contextptr).print(contextptr).c_str()); vinput.push_back(o); if (!focused){ focused=true; Fl::focus(o); } current_y +=20; continue; } if ( (u==at_output) || (u==at_Text) || (u==at_Title) ){ g=g.eval(eval_level(contextptr),contextptr); Fl_Output * o; if (u==at_Title){ string * l=new string (g.type==_STRNG?*g._STRNGptr:g.print(contextptr)); labels.push_back(l); o=new Fl_Output(taillew/2-40,current_y,0,20,l->c_str()); o->value(""); } else { o=new Fl_Output(40,current_y,taillew-60,20,""); o->value((g.type==_STRNG?*g._STRNGptr:g.print(contextptr)).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(contextptr).c_str()); vpopup.push_back(o); vector 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(contextptr).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; int hs=64; if (vg[1].type==_VECT) hs=vg[1]._VECTptr->size()*16+5; hs=min(hs,160); Fl_Browser * o =new Fl_Browser(50, current_y+16, 180, hs); current_y += hs+16; o->type(2); string * l=new string (vg[0].type==_STRNG?*vg[0]._STRNGptr:vg[0].print(contextptr)); labels.push_back(l); o->label(l->c_str()); o->align(FL_ALIGN_TOP); 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(contextptr).c_str()); } gen g=protecteval(vg[2],eval_level(contextptr),contextptr); if ( (g.type==_INT_) && (g.val>0) && (g.val<=int(wg.size())) ) o->value(g.val); continue; } } Xcas_Main_Window->redraw(); w->Fl_Widget::resize(w->x(),w->y(),taillew,current_y); 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 == button2) {r = 2; break;} if (o == w) { r=0; break; } } } w->hide(); bool request=false; gen gtmp("ok",contextptr); res.push_back(symb_sto(r,gtmp)); // store results it=v.begin(); int ibrowser=0; vector::const_iterator vinput_it=vinput.begin(); gen resadd,tmp; for (;it!=itend;++it){ if (it->type==_IDNT || it->is_symb_of_sommet(at_at) || it->is_symb_of_sommet(at_of)){ if (it+1!=itend && *(it+1)==1) resadd=string2gen((*vinput_it)->value(),false); else { try { resadd=gen((*vinput_it)->value(),contextptr); } 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){ request=true; resadd=string2gen((*vinput_it)->value(),false); } else resadd=gen((*vinput_it)->value(),contextptr); } 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])); request=true; } 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::const_iterator jt=vinput.begin(),jtend=vinput.end(); for (;jt!=jtend;++jt){ w->Fl_Group::remove(*jt); delete *jt; } vinput.clear(); } { vector::const_iterator jt=voutput.begin(),jtend=voutput.end(); for (;jt!=jtend;++jt){ w->Fl_Group::remove(*jt); delete *jt; } voutput.clear(); } { vector::const_iterator jt=vbrowser.begin(),jtend=vbrowser.end(); for (;jt!=jtend;++jt){ w->Fl_Group::remove(*jt); delete *jt; } vbrowser.clear(); } { vector::const_iterator jt=labels.begin(),jtend=labels.end(); for (;jt!=jtend;++jt){ delete *jt; } labels.clear(); } /* { vector::const_iterator jt=vpopup.begin(),jtend=vpopup.end(); for (;jt!=jtend;++jt){ w->Fl_Group::remove(*jt); delete *jt; } } { vector< vector >::const_iterator jt=vpopupitem.begin(),jtend=vpopupitem.end(); for (;jt!=jtend;++jt){ vector::const_iterator jtt=jt->begin(),jttend=jt->end(); for (;jtt!=jttend;+jtt) w->Fl_Group::remove(*jt); delete *jtt; } } */ // delete button1; // delete button0; // delete w; if (r==2) return 0; if (request) return res; if (r==0) return undef; else return res; } // FIXME: forms should work under win32!! #if defined WIN32 || defined __APPLE__ giac::gen Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr){ Fl::lock(); if (Xcas_DispG) Xcas_DispG->waiting_click_value=arg; Fl::unlock(); thread_eval_status(3,contextptr); for (;;){ if (thread_eval_status(contextptr)==1) break; usleep(10000); } Fl::lock(); gen res=Xcas_DispG?Xcas_DispG->waiting_click_value:undef; Fl::unlock(); return res.eval(eval_level(contextptr),contextptr); // return res; } gen Xcas_fltk_inputform(const gen & args,const giac::context * contextptr){ return Xcas_fltk_input(args,contextptr); } #else gen Xcas_fltk_inputform(const gen & args,const giac::context * contextptr){ vecteur v(inputform_pre_analysis(args,contextptr)); Fl::lock(); gen res=makeform(v,contextptr); Fl::unlock(); return inputform_post_analysis(v,res,contextptr); } giac::gen Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr){ vecteur v(inputform_pre_analysis(arg,contextptr)); if (v.empty()){ Fl::lock(); if (Xcas_DispG_Window) show_xcas_dispg=2; if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->show(); if (Xcas_DispG) Xcas_DispG->waiting_click=true; Fl::unlock(); for (;;) { #ifdef HAVE_LIBPTHREAD usleep(10000); #else Fl::wait(); #endif // HAVE_LIBPTHREAD Fl::lock(); bool wait= (Xcas_DispG && Xcas_DispG_Window && Xcas_DispG_Window->visible())? Xcas_DispG->waiting_click : false; Fl::unlock(); if (!wait) break; } Fl::lock(); if (Xcas_DispG) Xcas_DispG->waiting_click=false; if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); gen res=(Xcas_DispG && Xcas_DispG_Window && Xcas_DispG_Window->visible())?Xcas_DispG->waiting_click_value:undef; Fl::unlock(); return res; } else { Fl::lock(); gen res=makeform(v,contextptr); Fl::unlock(); return inputform_post_analysis(v,res,contextptr); } } #endif // WIN32 #endif // HAVE_LIBFLTK // functions for icas or C-library usage int read_file(const giac::gen & g){ if (g.is_symb_of_sommet(giac::at_read)) return 1; if (g.is_symb_of_sommet(giac::at_geo2d)) return 2; if (g.is_symb_of_sommet(giac::at_geo3d)) return 3; if (g.is_symb_of_sommet(giac::at_spreadsheet)) return 4; return 0; } void icas_eval_callback(const giac::gen & evaled_g,void * param){ giac::gen * resptr=(giac::gen *) param; // cerr << "icas_eval_callback " << evaled_g << endl; *resptr=evaled_g; } // eval g to gg, if g is a read command, replace g by the file content // and set reading_file to true void icas_eval(giac::gen & g,giac::gen & gg,int & reading_file,std::string &filename,giac::context * contextptr){ if (debug_infolevel) CERR << CLOCK() << " icas_eval " << g << endl; try { reading_file=read_file(g); if (g.type==_SYMB && g._SYMBptr->feuille.type==giac::_STRNG) filename=reading_file?*g._SYMBptr->feuille._STRNGptr:""; if (g.type==_SYMB && reading_file){ if (g._SYMBptr->feuille.type==giac::_VECT && !g._SYMBptr->feuille._VECTptr->empty()){ gg=_read(g._SYMBptr->feuille,contextptr); return; } else { if (g._SYMBptr->feuille.type!=giac::_STRNG) g=g._SYMBptr->feuille; else g=quote_read(g._SYMBptr->feuille,contextptr); } } if (g.type==giac::_VECT && !filename.empty()){ // patch to handle spreadsheet[ correctly FILE * inf=fopen(filename.c_str(),"r"); if (inf){ char ch[13]; ch[12]=0; if (fread(ch,1,12,inf)==12 && !strcmp(ch,"spreadsheet[")){ giac::makespreadsheetmatrice(*g._VECTptr,0); g.subtype=giac::_SPREAD__VECT; } fclose(inf); } } giac::gen g1=giac::approx_mode(contextptr)?giac::symbolic(giac::at_evalf,g):g; giac::gen result; signal(SIGINT,ctrl_c_signal_handler); #ifdef HAVE_LIBPTHREAD giac::make_thread(g1,eval_level(contextptr),icas_eval_callback,&result,contextptr); int status; while (1){ // look at other threads int cs=context_list().size(),ci=0; for (;cihide(); #endif if (status<=0){ #ifdef HAVE_LIBFLTK Fl::flush(); #endif break; } #ifdef HAVE_LIBFLTK if (status!=1) xcas::Xcas_debugguer(status,contextptr); #else // FIXME Debugguer without FLTK giac::thread_eval_status(1,contextptr); #endif if (ctrl_c){ if (giac::is_context_busy(contextptr)) giac::kill_thread(true,contextptr); ctrl_c=false; interrupted=false; } else usleep(1000); } gg=result; #else gg=eval(g1,eval_level(contextptr),contextptr); #endif } catch(std::runtime_error & e){ if (!contextptr) giac::protection_level=0; gg=giac::string2gen(e.what(),false); } } int fltk_return_value=-1; #ifdef HAVE_LIBFLTK static void cb_Close(Fl_Button * m , void*) { if (m->window()) m->window()->hide(); fltk_return_value=0; } static void cb_Cancel(Fl_Button * m , void*) { if (m->window()) m->window()->hide(); fltk_return_value=1; } static void cb_Kill(Fl_Button * m , void*) { // FIXME user_data() giac::kill_thread(true,context0); } bool has_graph3d(Fl_Widget * widget){ Fl_Group * g=dynamic_cast(widget); if (!g) return false; int n=g->children(); for (int i=0;ichild(i); if (Fl_Group * gr=dynamic_cast(wid)){ if (has_graph3d(gr)) return true; } if (Graph3d * gr3=dynamic_cast(wid)) return true; } return false; } #endif void quit_idle_function(void * widget){ static int t=0; if (!widget){ t=CLOCK(); return; } #ifdef HAVE_LIBFLTK Fl_Widget * w=(Fl_Widget *)(widget); if (has_graph3d(w) && (CLOCK()-t<1e5)) return; w->hide(); fltk_return_value=0; #endif } // open a FLTK window, that will be printed to filename when closed // return false if FLTK not avail bool fltk_view(const giac::gen & g,giac::gen & ge,const std::string & filename,std::string & figure_filename,int file_type,const giac::context *contextptr){ #ifdef __APPLE__ // return false; #endif #ifdef HAVE_LIBFLTK #if !defined(__APPLE__) && !defined(WIN32) if (!getenv("DISPLAY")) return false; #endif // FIXME GIAC_CONTEXT // const giac::context * contextptr = get_context(Fl_Group::current()); bool geometry=!figure_filename.empty(); if (file_type==4 && figure_filename.empty()){ figure_filename="table.tab"; geometry=true; } Fl_Window * w=0; Fl_Return_Button * button0 = 0 ; Fl_Button * button1 =0,*button2=0; if (!w){ int dx=800,dy=geometry?500:360; Fl_Group::current(0); w=new Fl_Window(dx,dy); button0 = new Fl_Return_Button(2,dy-25,dx/3-4,20); button0->shortcut(0xff0d); button0->label(gettext("OK")); button0->callback( (Fl_Callback *) cb_Close); button1 = new Fl_Button(dx/3+2,dy-25,dx/3-4,20); button1->shortcut(0xff1b); button1->label(gettext("Cancel")); button1->callback( (Fl_Callback *) cb_Cancel); button2 = new Fl_Button(2*dx/3+2,dy-25,dx/3-4,20); button2->shortcut(0xff1b); button2->label(gettext("STOP")); button2->callback( (Fl_Callback *) cb_Kill); w->end(); w->resizable(w); } // xcas::initialize_function=load_autorecover_data; if (file_type==-1){ quit_idle_function(0); Fl::add_idle(quit_idle_function,w); } else Fl::add_idle(xcas::Xcas_idle_function,0); // xcas::idle_function=Xcas_update_mode; Fl_Group::current(w); int dx=w->w(),dy=w->h(); Fl_Tile * this_graph_tile=new Fl_Tile(0,0,dx,dy-25); Fl_Widget * wid =0,*print_wid=0; if (geometry){ if (file_type==4 || (giac::ckmatrix(ge,true) && ge.subtype==giac::_SPREAD__VECT)){ xcas::Tableur_Group * t=new xcas::Tableur_Group(0,0,dx,dy-25,20,2); wid=t; giac::gen tmp=giac::gen(giac::remove_path(giac::remove_extension(figure_filename)),contextptr); if (tmp.type==giac::_IDNT) t->table->name=tmp; t->table->contextptr=(giac::context *) contextptr; if (giac::ckmatrix(ge,true) && ge.subtype==giac::_SPREAD__VECT){ t->table->set_matrix(*ge._VECTptr,true,false); // don't reeval! // t->table->paste(*ge._VECTptr,false); // don't reeval! } if (t->table->filename) delete t->table->filename; if ( (t->table->filename = new std::string(figure_filename)) ) t->fname->label(t->table->filename->c_str()); t->table->update_status(); } else { wid=new xcas::Figure(0,0,dx,dy-25,20,(is3d(ge)||file_type==3)); if (wid) print_wid=((xcas::Figure *)wid)->geo; } } else { int t=graph_output_type(ge); if (t==3||file_type==3){ #ifdef HAVE_LIBFLTK_GL print_wid=wid=new xcas::Graph3d(0,0,dx,dy-25,"",0); #endif } else { if (t==2 || file_type==2) print_wid=wid=new xcas::Graph2d(0,0,dx,dy-25); else { print_wid=wid=new Fl_Output(0,0,dx,dy-25); ((Fl_Output *) (wid))->value("No suitable widget"); } } } if (xcas::Graph2d3d * this_graph = dynamic_cast(wid)){ this_graph->add(ge); this_graph->autoscale(); this_graph->update_infos(ge,contextptr); } if (xcas::Figure * fig=dynamic_cast(wid)){ fig->rename(figure_filename.c_str()); fig->geo->hp->remove_entry(0); if (!is_undef(ge)) fig->geo->add(ge); // put g in figure history_pack if (g.type!=giac::_VECT){ if (!is_undef(ge)){ xcas::Multiline_Input_tab * mi = dynamic_cast(xcas::new_question_multiline_input(100,20)); mi->set_g(g); fig->geo->hp->add_entry(-1,mi); } } else { giac::const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); for (;it!=itend;++it){ xcas::Multiline_Input_tab * mi = dynamic_cast(xcas::new_question_multiline_input(100,20)); mi->set_g(*it); fig->geo->hp->add_entry(-1,mi); } } if (fig->geo->hp->children()==0){ fig->geo->hp->add_entry(-1); fig->geo->set_mode(0,0,1); fig->geo->approx=true; fig->mode->value("point"); } fig->geo->hp->update(); } this_graph_tile->end(); w->show(); w->hotspot(w); fltk_return_value=-1; Fl::run(); if (file_type==-1) Fl::remove_idle(quit_idle_function,w); else Fl::remove_idle(xcas::Xcas_idle_function,0); w->show(); if (!fltk_return_value){ if (xcas::Figure * fig=dynamic_cast(wid)){ if (fig->geo->hp->_modified && !figure_filename.empty()){ int i=fl_ask("Figure modified. Save?"); if (i) fig->save_figure_as(figure_filename); } } if (xcas::Tableur_Group * t=dynamic_cast(wid)){ if (t->table->changed_ && !t->table->filename->empty()){ int i=fl_ask("Sheet modified. Save?"); if (i){ ofstream of(t->table->filename->c_str()); if (!of) fl_message("%s","Write error"); else of << giac::gen(t->table->m,giac::_SPREAD__VECT) << endl; of.close(); } } else { ge=t->table->m; ge.subtype=giac::_SPREAD__VECT; } } // now try to print the widget if (!print_wid) print_wid=wid; print_wid->resize(0,0,dx,dy); if (xcas::Figure * fig=dynamic_cast(wid)){ fig->geo->orthonormalize(); } if (!filename.empty() // && !figure_filename.empty() ) xcas::widget_ps_print(print_wid,filename,true,0,false,true,false); // don't ask user for pixel size } w->hide(); Fl::wait(0.001); w->remove(this_graph_tile); delete wid; delete this_graph_tile; delete button0; delete button1; delete button2; delete w; return !fltk_return_value; #else // HAVE_LIBFLTK return false; #endif } #ifdef HAVE_LIBFLTK // Font selection, borrowed from FLTK tests font.cxx Fl_Window *form=0; class FontDisplay : public Fl_Widget { void draw(); public: int font, size; FontDisplay(Fl_Boxtype B, int X, int Y, int W, int H, const char* L = 0) : Fl_Widget(X,Y,W,H,L) {box(B); font = 0; size = 14;} }; void FontDisplay::draw() { draw_box(); fl_font((Fl_Font)font, size); fl_color(FL_BLACK); fl_draw(label(), x()+3, y()+3, w()-6, h()-6, align()); } FontDisplay *textobj=0; Fl_Hold_Browser *fontobj=0, *sizeobj=0; #define FLTK_FONT_MAX 256 int *sizes[FLTK_FONT_MAX]; int numsizes[FLTK_FONT_MAX]; int pickedsize = 14; void font_cb(Fl_Widget *, long) { int fn = fontobj->value(); if (!fn) return; fn--; textobj->font = fn; sizeobj->clear(); int n = numsizes[fn]; int *s = sizes[fn]; if (!n) { // no sizes } else if (s[0] == 0) { // many sizes; int j = 1; for (int i = 1; i<64 || iadd(buf); } sizeobj->value(pickedsize); } else { // some sizes int w = 0; for (int i = 0; i < n; i++) { if (s[i]<=pickedsize) w = i; char buf[20]; sprintf(buf,"@b%d",s[i]); sizeobj->add(buf); } sizeobj->value(w+1); } textobj->redraw(); } void size_cb(Fl_Widget *, long) { int i = sizeobj->value(); if (!i) return; const char *c = sizeobj->text(i); while (*c < '0' || *c > '9') c++; pickedsize = atoi(c); textobj->size = pickedsize; textobj->redraw(); } bool get_font(Fl_Font & police,int & taille){ static Fl_Return_Button * button0 = 0 ; static Fl_Button * button1 =0; static char label[400]; Fl::scheme(NULL); if (!form){ Fl_Group::current(0); form = new Fl_Window(550,370); strcpy(label, gettext("What a nice font")); int i = strlen(label); uchar c; label[i++] = char(10); for (c = ' '+1; c < 127; c++,i++) {if (!(c&0x1f)) label[i]=' '; else label[i]=c;} label[i++] = char(10); for (c = 0xA1; c; c++,i++) {if (!(c&0x1f)) label[i]=' '; else label[i]=c;} label[i] = 0; button0 = new Fl_Return_Button(100,10,100,20); button0->shortcut(0xff0d); button0->label(gettext("OK")); button1 = new Fl_Button(300,10,100,20); button1->shortcut(0xff1b); button1->label(gettext("Cancel")); textobj = new FontDisplay(FL_FRAME_BOX,10,40,530,140,label); textobj->align(FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); textobj->color(9,47); fontobj = new Fl_Hold_Browser(10, 190, 390, 170); fontobj->box(FL_FRAME_BOX); fontobj->color(53,3); fontobj->callback(font_cb); form->resizable(fontobj); sizeobj = new Fl_Hold_Browser(410, 190, 130, 170); sizeobj->box(FL_FRAME_BOX); sizeobj->color(53,3); sizeobj->callback(size_cb); form->end(); int k = min(fonts_available,FLTK_FONT_MAX); for (i = 0; i < k; i++) { int t; const char *name = Fl::get_font_name((Fl_Font)i,&t); char buffer[128]; if (t) { char *p = buffer; if (t & FL_BOLD) {*p++ = '@'; *p++ = 'b';} if (t & FL_ITALIC) {*p++ = '@'; *p++ = 'i';} strcpy(p,name); name = buffer; } fontobj->add(name); int *s; int n = Fl::get_font_sizes((Fl_Font)i, s); numsizes[i] = n; if (n) { sizes[i] = new int[n]; for (int j=0; jsize = pickedsize; fontobj->value(police+1); font_cb(fontobj,0); form->set_modal(); form->show(); form->hotspot(form); Fl::focus(form); int r=-1; for (;;){ Fl_Widget *o = Fl::readqueue(); if (!o) Fl::wait(); else { if (o==form){ r=1; break; } if (o == button0) {r = 0; break;} if (o == button1) {r = 1; break;} } } form->hide(); if (r) return false; police=Fl_Font(textobj->font); taille=textobj->size; return true; } /* void test_alert(){ string s; for (int i=0;i<256;i++) s+=char(i); fl_alert("%s",s.c_str()); } */ #endif // HAVE_LIBFLTK #ifndef NO_NAMESPACE_XCAS } // namespace xcas #endif // ndef NO_NAMESPACE_XCAS