1 // -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -g -c Xcas1.cc -Wall -DHAVE_CONFIG_H -DIN_GIAC" -*- 2 /* 3 * Copyright (C) 2005,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifdef HAVE_CONFIG_H 20 #include "config.h" 21 #endif 22 #ifndef IN_GIAC 23 #include <giac/first.h> 24 #else 25 #include "first.h" 26 #endif 27 #include <string> 28 #ifdef HAVE_LIBFLTK 29 #include <FL/Fl.H> 30 #include <FL/fl_draw.H> 31 #include <FL/Fl_Window.H> 32 #include <FL/fl_ask.H> 33 #include <FL/Fl_File_Chooser.H> 34 #include <FL/Fl_Value_Input.H> 35 #include <FL/Fl_Counter.H> 36 #include <FL/Fl_Tile.H> 37 #include <FL/Fl_Hold_Browser.H> 38 #endif 39 #include "Xcas1.h" 40 #include "Input.h" 41 #include "Equation.h" 42 #include "Graph.h" 43 #include "Graph3d.h" 44 #include "Tableur.h" 45 #include "Editeur.h" 46 #include "Print.h" 47 #include <iostream> 48 #include <fstream> 49 #ifdef HAVE_SSTREAM 50 #include <sstream> 51 #else 52 #include <strstream> 53 #endif 54 #include <typeinfo> 55 #include <fcntl.h> 56 #include <stdio.h> 57 #include <string.h> 58 #include <dirent.h> 59 #include <sys/stat.h> // auto-recovery function 60 #ifdef HAVE_SYS_TIME_H 61 #include <sys/time.h> 62 #endif 63 #ifdef HAVE_LIBPTHREAD 64 #include <semaphore.h> 65 #endif 66 #ifdef HAVE_PTHREAD_H 67 #include <pthread.h> 68 #endif 69 #ifndef IN_GIAC 70 #include <giac/global.h> 71 #include <giac/misc.h> 72 #include <giac/gen.h> 73 #else 74 #include "global.h" 75 #include "misc.h" 76 #include "gen.h" 77 #endif 78 using namespace std; 79 using namespace giac; 80 81 #ifndef NO_NAMESPACE_XCAS 82 namespace xcas { 83 #endif // ndef NO_NAMESPACE_XCAS 84 85 #ifdef HAVE_LIBFLTK 86 87 bool interrupt_button = true ; 88 bool geo_run=false; 89 bool sheet_run=false; 90 bool recovery_mode=false; 91 int fonts_available=1; 92 93 void (*initialize_function)()=0; 94 95 Xcas_config_type Xcas_config; 96 void (* menu2rpn_callback)(Fl_Widget *,void *)=0; 97 Enlargable_Multiline_Output *Xcas_help_output =0 ; 98 xcas::Graph2d *Xcas_DispG=0; 99 xcas::Equation * Xcas_PrintG=0; 100 int show_xcas_dispg=0,redraw_turtle=0; 101 std::string xcas_paused=""; 102 int xcas_dispg_entries=0; 103 Fl_Window * Xcas_DispG_Window=0; 104 Fl_Window * Xcas_Main_Window=0; 105 Fl_Button *Xcas_DispG_Cancel=0; 106 Fl_Button *Xcas_Cancel=0; 107 bool file_save_context=true; 108 xcas_gprintf(unsigned special,const std::string & format,const vecteur & v,GIAC_CONTEXT)109 void xcas_gprintf(unsigned special,const std::string & format,const vecteur & v,GIAC_CONTEXT){ 110 if (Xcas_PrintG){ 111 Fl::lock(); 112 gen g=Xcas_PrintG->get_data(); 113 Fl::unlock(); 114 vecteur w=makevecteur(string2gen("",false));//makevecteur(string2gen("",false),string2gen("Step by step console",false)); 115 if (g.type==_VECT) w=*g._VECTptr; 116 // add format,v at the end of w 117 int posnl=0; 118 unsigned i=0; 119 for (;posnl<int(format.size());){ 120 int nl=int(format.find('\n',posnl)); 121 string curs; 122 bool finish = nl<0 || nl>=int(format.size()); 123 if (finish) 124 curs=format.substr(posnl,format.size()-posnl); 125 else { 126 curs=format.substr(posnl,nl-posnl); 127 posnl=nl+1; 128 } 129 vecteur cur; 130 for (;i<v.size() && !curs.empty();++i){ 131 int p=int(curs.find("%gen")); 132 if (p<0 || p>=int(curs.size())) 133 break; 134 string cursp=curs.substr(0,p); 135 if (!cursp.empty()) 136 cur.push_back(string2gen(cursp,false)); 137 cur.push_back(v[i]); 138 curs=curs.substr(p+4,curs.size()-p-4); 139 } 140 if (!curs.empty()) 141 cur.push_back(string2gen(curs,false)); 142 if (cur.empty()) 143 continue; 144 if (cur.size()==1) 145 w.push_back(cur.front()); 146 else 147 w.push_back(gen(cur,_SEQ__VECT)); 148 if (finish) 149 break; 150 } 151 g=gen(w,_HIST__VECT); 152 Fl::lock(); 153 Xcas_PrintG->set_data(g); 154 Fl::unlock(); 155 } 156 } 157 158 // debugger variables 159 int xcas_debug_ok,xcas_current_instruction; 160 Fl_Double_Window * Xcas_Debug_Window=0; 161 Fl_Tile* Xcas_debug_tile =0; 162 Fl_Browser* Xcas_source_browser =0; 163 xcas::Multiline_Input_tab* Xcas_debug_input =0; 164 Fl_Output* Xcas_debug_messages =0; 165 Fl_Group* Xcas_debug_buttons =0; 166 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; 167 Fl_Browser* Xcas_variable_browser=0; cb_Xcas_source_browser(Fl_Browser *,void * user)168 static void cb_Xcas_source_browser(Fl_Browser*, void* user) { 169 std::string s("breakpoint("); 170 giac::context * contextptr =(giac::context *) user; 171 s += giac::debug_ptr(contextptr)->debug_prog_name->print(); 172 s += ','; 173 s += giac::print_INT_(Xcas_source_browser->value()); 174 s += ')'; 175 Xcas_debug_input->value(s.c_str()); 176 Xcas_debug_input->position(s.size()-1,s.size()-1); 177 Fl::focus(Xcas_debug_input); 178 Fl::flush(); 179 usleep(200000); 180 Xcas_source_browser->value(xcas_current_instruction); 181 } 182 cb_Xcas_debug_input(xcas::Multiline_Input_tab *,void *)183 static void cb_Xcas_debug_input(xcas::Multiline_Input_tab*, void*) { 184 xcas_debug_ok=true; 185 } 186 cb_Xcas_sst_button(Fl_Button *,void *)187 static void cb_Xcas_sst_button(Fl_Button*, void*) { 188 Xcas_debug_input->value("sst"); 189 xcas_debug_ok=true; 190 } 191 cb_Xcas_sst_in_button(Fl_Button *,void *)192 static void cb_Xcas_sst_in_button(Fl_Button*, void*) { 193 Xcas_debug_input->value("sst_in"); 194 xcas_debug_ok=true; 195 } 196 cb_Xcas_cont_button(Fl_Button *,void *)197 static void cb_Xcas_cont_button(Fl_Button*, void*) { 198 Xcas_debug_input->value("cont"); 199 xcas_debug_ok=true; 200 } 201 cb_Xcas_kill_button(Fl_Button *,void *)202 static void cb_Xcas_kill_button(Fl_Button*, void*) { 203 Xcas_debug_input->value("kill"); 204 Xcas_debug_input->position(4,4); 205 Fl::focus(Xcas_debug_input); 206 } 207 cb_Xcas_break_button(Fl_Button *,void * user)208 static void cb_Xcas_break_button(Fl_Button*, void* user) { 209 string s("breakpoint("); 210 giac::context * contextptr =(giac::context *) user; 211 s += giac::debug_ptr(contextptr)->debug_prog_name->print(); 212 s += ','; 213 s += giac::print_INT_(Xcas_source_browser->value()); 214 s += ')'; 215 Xcas_debug_input->value(s.c_str()); 216 Xcas_debug_input->position(s.size()-1,s.size()-1); 217 Fl::focus(Xcas_debug_input); 218 } 219 cb_Xcas_rmbrk_button(Fl_Button *,void * user)220 static void cb_Xcas_rmbrk_button(Fl_Button*, void* user) { 221 string s("rmbreakpoint("); 222 giac::context * contextptr =(giac::context *) user; 223 s += giac::debug_ptr(contextptr)->debug_prog_name->print(); 224 s += ','; 225 s += giac::print_INT_(Xcas_source_browser->value()); 226 s += ')'; 227 Xcas_debug_input->value(s.c_str()); 228 Xcas_debug_input->position(s.size()-1,s.size()-1); 229 Fl::focus(Xcas_debug_input); 230 } 231 cb_Xcas_watch_button(Fl_Button *,void *)232 static void cb_Xcas_watch_button(Fl_Button*, void*) { 233 Xcas_debug_input->value("watch("); 234 Xcas_debug_input->position(6,6); 235 Fl::focus(Xcas_debug_input); 236 } 237 cb_Xcas_rmwatch_button(Fl_Button *,void *)238 static void cb_Xcas_rmwatch_button(Fl_Button*, void*) { 239 Xcas_debug_input->value("rmwatch("); 240 Xcas_debug_input->position(8,8); 241 Fl::focus(Xcas_debug_input); 242 } 243 cb_Xcas_variable_browser(Fl_Browser *,void *)244 static void cb_Xcas_variable_browser(Fl_Browser*, void*) { 245 Xcas_debug_input->insert(Xcas_variable_browser->text(Xcas_variable_browser->value())); 246 } 247 248 // end debugger callbacks and defs 249 250 int autosave_time = 60 ; /* default save session every 60 seconds */ 251 bool autosave_disabled = false; 252 find_fold_autosave_function(bool warn_user)253 bool find_fold_autosave_function(bool warn_user){ 254 History_Fold * hf=0; 255 Fl_Widget * w = xcas::Xcas_input_focus; 256 for (;w;){ 257 if ( (hf=dynamic_cast<History_Fold *>(w)) ) 258 break; 259 w=w->parent(); 260 } 261 if (hf) 262 return hf->autosave(warn_user); 263 else 264 return false; 265 } 266 267 bool (*autosave_function)(bool) = find_fold_autosave_function ; 268 void (*idle_function)()=0; 269 270 unsigned max_debug_printsize=1000; Xcas_debugguer(int status,giac::context * contextptr)271 void Xcas_debugguer(int status,giac::context * contextptr){ 272 if (debug_ptr(contextptr) && debug_ptr(contextptr)->debug_contextptr) 273 contextptr = debug_ptr(contextptr)->debug_contextptr; 274 // 2 -> debug, 3 ->wait click 275 if (status==3){ 276 vecteur v(gen2vecteur(Xcas_DispG?Xcas_DispG->waiting_click_value:undef)); 277 if (v.empty()){ 278 if (Xcas_DispG_Window) Xcas_DispG_Window->show(); 279 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->show(); 280 if (Xcas_DispG) Xcas_DispG->waiting_click=true; 281 for (;;) { 282 Fl::wait(); 283 if (Xcas_DispG_Window && !Xcas_DispG_Window->visible()){ 284 Xcas_DispG->waiting_click=false; 285 Xcas_DispG->waiting_click_value=undef; 286 } 287 bool wait=Xcas_DispG?Xcas_DispG->waiting_click:false; 288 if (!wait) 289 break; 290 } 291 if (Xcas_DispG) Xcas_DispG->waiting_click=false; 292 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); 293 thread_eval_status(1,contextptr); 294 return; 295 } 296 v=inputform_pre_analysis(v,contextptr); 297 gen res=makeform(v,contextptr); 298 if (Xcas_DispG) 299 Xcas_DispG->waiting_click_value=inputform_post_analysis(v,res,contextptr); 300 thread_eval_status(1,contextptr); 301 return; 302 } 303 if (status==2){ 304 if (!Xcas_Debug_Window){ 305 int dx,dy; 306 if (xcas::Xcas_input_focus && xcas::Xcas_input_focus->window()){ 307 dx=8*(2*xcas::Xcas_input_focus->window()->w()/24); 308 dy=11*(2*xcas::Xcas_input_focus->window()->h()/30); 309 } 310 else { 311 dx=400; 312 dy=500; 313 } 314 Fl_Double_Window* o = Xcas_Debug_Window = new Fl_Double_Window(dx,dy, gettext("Xcas Debug Window")); 315 { 316 Fl_Tile* o = Xcas_debug_tile = new Fl_Tile(0, 0, dx,dy); 317 o->box(FL_FLAT_BOX); 318 { Fl_Browser* o = Xcas_source_browser = new Fl_Browser(0,0,dx,4*dy/11); 319 o->tooltip(gettext("Show the source of the program")); 320 o->type(2); 321 o->callback((Fl_Callback*)cb_Xcas_source_browser); 322 } 323 { 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")); 324 o->type(4); 325 o->box(FL_DOWN_BOX); 326 o->color(FL_BACKGROUND2_COLOR); 327 o->selection_color(FL_SELECTION_COLOR); 328 o->labeltype(FL_NORMAL_LABEL); 329 o->labelfont(0); 330 o->labelsize(14); 331 o->labelcolor(FL_FOREGROUND_COLOR); 332 o->textcolor(1); 333 o->callback((Fl_Callback*)cb_Xcas_debug_input); 334 o->align(FL_ALIGN_LEFT); 335 o->when(FL_WHEN_ENTER_KEY); 336 } 337 { Fl_Output* o = Xcas_debug_messages = new Fl_Output(0,5*dy/11,dx,2*dy/11); 338 o->type(12); 339 o->labelcolor(FL_FOREGROUND_COLOR); 340 o->textcolor(4); 341 } 342 { Fl_Group* o = Xcas_debug_buttons = new Fl_Group(0,7*dy/11,dx,dy/11); 343 { Fl_Button* o = Xcas_sst_button = new Fl_Button(0,7*dy/11,dx/8,dy/11, gettext("sst F5")); 344 o->tooltip(gettext("Execute current line, skip function")); 345 o->callback((Fl_Callback*)cb_Xcas_sst_button); 346 o->shortcut(0xffc2); 347 } 348 { Fl_Button* o = Xcas_sst_in_button = new Fl_Button(dx/8,7*dy/11, dx/8, dy/11, gettext("in F6")); 349 o->tooltip(gettext("Execute current line, step in function")); 350 o->callback((Fl_Callback*)cb_Xcas_sst_in_button); 351 o->shortcut(0xffc3); 352 } 353 { Fl_Button* o = Xcas_cont_button = new Fl_Button(2*dx/8,7*dy/11, dx/8, dy/11, gettext("cont F7")); 354 o->tooltip(gettext("Continue execution until next breakpoint")); 355 o->callback((Fl_Callback*)cb_Xcas_cont_button); 356 o->shortcut(0xffc4); 357 } 358 { Fl_Button* o = Xcas_kill_button = new Fl_Button(3*dx/8,7*dy/11, dx/8, dy/11, gettext("kill")); 359 o->tooltip(gettext("Kill current program")); 360 o->callback((Fl_Callback*)cb_Xcas_kill_button); 361 } 362 { Fl_Button* o = Xcas_break_button = new Fl_Button(4*dx/8,7*dy/11, dx/8, dy/11, gettext("break")); 363 o->tooltip(gettext("Add a breakpoint")); 364 o->callback((Fl_Callback*)cb_Xcas_break_button); 365 } 366 { Fl_Button* o = Xcas_rmbrk_button = new Fl_Button(5*dx/8,7*dy/11, dx/8, dy/11, gettext("rmbrk")); 367 o->tooltip(gettext("Remove a breakpoint")); 368 o->callback((Fl_Callback*)cb_Xcas_rmbrk_button); 369 } 370 { Fl_Button* o = Xcas_watch_button = new Fl_Button(6*dx/8,7*dy/11,dx/8, dy/11, gettext("watch")); 371 o->tooltip(gettext("Add a variable name to the watch")); 372 o->callback((Fl_Callback*)cb_Xcas_watch_button); 373 } 374 { Fl_Button* o = Xcas_rmwatch_button = new Fl_Button(7*dx/8,7*dy/11,dx/8, dy/11, gettext("rmwtch")); 375 o->tooltip(gettext("Add a variable name to the watch")); 376 o->callback((Fl_Callback*)cb_Xcas_rmwatch_button); 377 } 378 o->end(); 379 } 380 { Fl_Browser* o = Xcas_variable_browser = new Fl_Browser(0,8*dy/11,dx,3*dy/11); 381 o->tooltip(gettext("Show watch variables")); 382 o->type(2); 383 o->callback((Fl_Callback*)cb_Xcas_variable_browser); 384 } 385 o->end(); 386 } 387 o->end(); 388 o->resizable(o); 389 } 390 Xcas_source_browser->user_data( (void *) contextptr); 391 Xcas_break_button->user_data( (void *) contextptr); 392 Xcas_rmbrk_button->user_data( (void *) contextptr); 393 if (Xcas_Main_Window && Xcas_Debug_Window) 394 change_group_fontsize(Xcas_Debug_Window,Xcas_Main_Window->labelsize()); 395 if (Xcas_Debug_Window){ 396 Xcas_Debug_Window->show(); 397 // Xcas_Debug_Window->set_modal(); 398 Xcas_debug_input->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 399 } 400 // Debugging mode 401 // cerr << "Debugging" << '\n'; 402 debug_struct * dbgptr=debug_ptr(contextptr); 403 if (dbgptr){ 404 if (dbgptr->debug_info_ptr && dbgptr->debug_info_ptr->type==_VECT){ 405 vecteur & w =*dbgptr->debug_info_ptr->_VECTptr; 406 // w[0]=function, args, 407 // w[1]=breakpoints 408 // w[2] = instruction evaled or program source 409 // w[3]= evaluation result 410 // w[4]= current instruction number 411 // w[5] = watch vector, w[6] = watch values 412 string msg; 413 msg += "eval("+w[2].print(contextptr) + ")= " + w[3].print(contextptr) + '\n'; 414 msg += "Stopped in "; 415 if ( w[0].type==_VECT && !w[0]._VECTptr->empty() ){ 416 if (!dbgptr->debug_prog_name) 417 dbgptr->debug_prog_name=new gen; 418 if (*dbgptr->debug_prog_name!=w[0]._VECTptr->front()){ 419 gen prog=w[0]._VECTptr->front(); 420 *dbgptr->debug_prog_name=prog; 421 if (prog.type==_IDNT) 422 prog=prog.eval(1,contextptr); 423 if (prog.is_symb_of_sommet(at_program) && prog.type==_VECT && prog._VECTptr->size()==3 ) 424 prog=prog._VECTptr->back(); 425 if (prog.type==_SYMB) 426 prog=prog._SYMBptr->feuille; 427 if (prog.type==_VECT && prog._VECTptr->size()==3) 428 prog=prog._VECTptr->back(); 429 w[2]=prog; 430 Xcas_source_browser->clear(); 431 vector<string> vs; 432 if (w[2].type==_VECT) 433 debug_print(*w[2]._VECTptr,vs,contextptr); 434 else 435 debug_print(w[2],vs,contextptr); 436 vector<string>::iterator it=vs.begin(),itend=vs.end(); 437 for (;it!=itend;++it){ 438 string & cur=*it; // replace \n by space 439 for (;;){ 440 size_t pos=cur.find('\n'); 441 if (pos<0 || pos>=cur.size()) 442 break; 443 cur[pos]=' '; 444 } 445 Xcas_source_browser->add(cur.c_str()); 446 } 447 } 448 msg += dbgptr->debug_prog_name->print(contextptr) + "(" + gen(vecteur(w[0]._VECTptr->begin()+1,w[0]._VECTptr->end()),_SEQ__VECT).print(contextptr)+")"; 449 msg += ",\nbreakpoint "+w[1].print(contextptr); 450 } // if (w[0].type==_VECT) 451 else 452 msg += w[0].print(contextptr); 453 msg += ",\nline " + w[4].print(contextptr); 454 Xcas_debug_messages->value(msg.c_str()); 455 gen w_in(w[5]),w_out(w[6]); 456 if ( (w_in.type==_VECT) && (w_out.type==_VECT) ){ 457 int pos=max(Xcas_variable_browser->value(),1); 458 Xcas_variable_browser->clear(); 459 const_iterateur it=w_in._VECTptr->begin(),itend=w_in._VECTptr->end(); 460 const_iterateur jt=w_out._VECTptr->begin(),jtend=w_out._VECTptr->end(); 461 for (;(it!=itend)&&(jt!=jtend);++it,++jt){ 462 string tmps = replace(jt->print(contextptr),'\n',' '); 463 if (tmps.size()>max_debug_printsize) 464 tmps=tmps.substr(0,max_debug_printsize); 465 Xcas_variable_browser->add( (it->print(contextptr) + " := " + tmps ).c_str()); 466 } 467 Xcas_variable_browser->value(giacmin(pos,w_in._VECTptr->size())); 468 } 469 xcas_current_instruction=w[4].val; 470 Xcas_source_browser->value(w[4].val); 471 /* console mode debugging 472 if (dbgptr->debug_refresh){ 473 if (dbgptr->fast_debug_info_ptr) 474 cerr << *dbgptr->fast_debug_info_ptr << '\n'; 475 } 476 else { 477 if (dbgptr->debug_info_ptr) 478 cerr << *dbgptr->debug_info_ptr << '\n'; 479 } 480 */ 481 } 482 } 483 gen g(at_sst); 484 gen nxt; 485 xcas_debug_ok=false; 486 while (Xcas_Debug_Window->shown() && !xcas_debug_ok){ 487 Fl::wait(); 488 int cs=context_list().size(),ci=0,status=0; 489 for (;ci<cs;++ci){ 490 status=check_thread(context_list()[ci]); 491 } 492 } 493 /* console mode debugging 494 char buf[10000]; 495 cin.getline(buf,10000-1,'\n'); 496 if (buf[0]){ 497 try { 498 g=gen(buf); 499 } 500 catch (std::runtime_error & err){ 501 cerr << err.what(); 502 } 503 } 504 */ 505 if (!Xcas_Debug_Window->visible()) 506 g=at_kill; 507 else { 508 string buf(Xcas_debug_input->value()); 509 if (!buf.empty()){ 510 try { 511 g=gen(buf,contextptr); 512 } 513 catch (std::runtime_error & err){ 514 cerr << err.what(); 515 } 516 } 517 } 518 *dbgptr->fast_debug_info_ptr = g; 519 thread_eval_status(1,contextptr); 520 } 521 } 522 Xcas_idle_function(void * dontcheck)523 void Xcas_idle_function(void * dontcheck){ 524 static int initialized=-1; 525 static time_t last_save=time(0); 526 int cs=context_list().size(),ci=0,status=0; 527 context * cptr=0; 528 for (;ci<cs;++ci){ 529 cptr=context_list()[ci]; 530 if (!dontcheck || (void *)cptr!=dontcheck) 531 status=check_thread(cptr); 532 if (status>1) 533 break; 534 } 535 if (ci<cs){ 536 context * contextptr=context_list()[ci]; 537 Xcas_debugguer(status,contextptr); 538 } 539 if (Xcas_Debug_Window) { 540 if (status<2 && Xcas_Debug_Window->shown()){ 541 if (cptr){ 542 usleep(100000); 543 status=check_thread(cptr); 544 } 545 if (status<2) 546 Xcas_Debug_Window->hide(); 547 else 548 return; // moved from below otherwise after debugging STOP button is always on 549 } 550 } 551 bool lock=true; // added because DispG freeze in linux 552 if (Xcas_DispG_Window){ 553 if (show_xcas_dispg){ 554 lock=false; 555 if (show_xcas_dispg & 2){ 556 if (!Xcas_DispG_Window->visible()) 557 Xcas_DispG->autoscale(); 558 if (show_xcas_dispg & 1){ 559 Xcas_DispG_Window->show(); 560 Xcas_DispG_Window->iconize(); 561 } 562 else 563 Xcas_DispG_Window->show(); 564 } 565 else 566 Xcas_DispG_Window->hide(); 567 show_xcas_dispg=0; 568 } 569 } 570 if (xcas_paused!=""){ 571 Xcas_Main_Window->redraw(); 572 if (Xcas_DispG) Xcas_DispG->redraw(); 573 fl_message("%s",xcas_paused.c_str()); 574 xcas_paused=""; 575 } 576 ++initialized; 577 if (initialized % 5){ 578 if (lock) Fl::unlock(); 579 #ifdef WIN32 580 usleep(10000); 581 #else 582 usleep(1000); 583 #endif 584 if (lock) Fl::lock(); 585 return; 586 } 587 if (!initialized && initialize_function) 588 initialize_function(); 589 if ( 590 #ifdef WIN32 591 !(initialized%20) && 592 #endif 593 idle_function 594 ) 595 idle_function(); 596 /* autosave */ 597 time_t current=time(0); 598 if (!autosave_disabled && autosave_function && double(current-last_save)>autosave_time){ 599 if (autosave_function(false)) 600 last_save=current; 601 else 602 last_save=current-autosave_time/2; 603 } 604 struct timeval cur; 605 struct timezone tz; 606 gettimeofday(&cur,&tz); 607 vector<Graph2d3d *>::const_iterator it=animations.begin(),itend=animations.end(); 608 for (;it!=itend;++it){ 609 Graph2d3d * gr = *it; 610 if (!gr->paused && gr->animation_dt>0){ 611 double dt=cur.tv_sec-gr->animation_last.tv_sec+double(cur.tv_usec-gr->animation_last.tv_usec)/1e6; 612 if (dt>gr->animation_dt){ 613 gr->redraw(); 614 } 615 } 616 } 617 } 618 operator <(const time_string & ts1,const time_string & ts2)619 bool operator < (const time_string & ts1,const time_string & ts2){ 620 if (ts1.t!=ts2.t) 621 return ts1.t < ts2.t; 622 else 623 return ts1.s < ts2.s; 624 } 625 626 // Check for auto-recovery data in directory s has_autorecover_data(const string & s_orig,vector<time_string> & newest)627 bool has_autorecover_data(const string & s_orig,vector<time_string> & newest){ 628 DIR *dp; 629 struct dirent *ep; 630 string s=s_orig; 631 if (!s.empty() && s[s.size()-1]!='/') 632 s += '/'; 633 else 634 s += '/'; 635 dp = opendir (s.c_str()); 636 if (dp != NULL){ 637 while ( (ep = readdir (dp)) ){ 638 string cur(ep->d_name); 639 if (cur.size()>13&& cur.substr(0,10)=="xcas_auto_"){ 640 string curext=cur.substr(cur.size()-3,3); 641 if (curext=="xws"){ 642 struct stat st; 643 if (!stat((s+ep->d_name).c_str(),&st)){ 644 time_t & t=st.st_mtime; // last modif 645 newest.push_back(time_string(t,s+cur)); 646 } 647 } 648 } 649 } 650 (void) closedir (dp); 651 if (newest.size()==0) // no file 652 return false; 653 return true; 654 } 655 else 656 return false; // Couldn't open the directory 657 } 658 stream_copy(std::istream & in,std::ostream & out)659 bool stream_copy(std::istream & in,std::ostream & out) { 660 char c; 661 while (in){ 662 if (!out){ 663 return false; 664 } 665 c=in.get(); 666 if (in.eof()){ 667 return true; 668 } 669 out << c ; 670 } 671 return false; 672 } 673 674 add_user_menu(Fl_Menu_ * m,const string & s,const string & doc_prefix,Fl_Callback * cb)675 bool add_user_menu(Fl_Menu_ *m,const string & s, const string & doc_prefix,Fl_Callback * cb){ 676 string menufile; 677 bool menufile_found=false; 678 if (is_file_available(s.c_str())){ 679 menufile_found=true; 680 menufile=s; 681 } 682 else { 683 if (getenv("XCAS_HELP")){ 684 menufile=getenv("XCAS_HELP"); 685 int ms=menufile.size(); 686 for (--ms;ms>0;--ms){ 687 if (menufile[ms]=='/') 688 break; 689 } 690 if (ms) 691 menufile=menufile.substr(0,ms+1)+doc_prefix+s; 692 } 693 else 694 menufile=giac::giac_aide_dir()+doc_prefix+s; 695 menufile_found=is_file_available(menufile.c_str()); 696 } 697 if (!menufile_found){ 698 cerr << "// Unable to open menu file "<< menufile << '\n'; 699 return false; 700 } 701 cerr << "// Using menu file " << menufile << '\n'; 702 // Now reading commandnames from file for menus 703 // Syntax is menu/submenu/item, callback inserts item name 704 ifstream in(menufile.c_str()); 705 string lu; 706 int BUFSIZE=10000,endpos; 707 char buf[BUFSIZE+1]; 708 while (in){ 709 in.getline(buf,BUFSIZE,'\n'); 710 endpos=strlen(buf); 711 if (endpos){ 712 if (buf[endpos-1]=='\n') 713 buf[endpos-1]=0; 714 lu=buf; 715 } 716 if (in.eof()) 717 break; 718 m->add(lu.c_str(),0,cb); 719 } 720 return true; 721 } 722 nextfl_menu(Fl_Menu_Item * & m)723 void nextfl_menu(Fl_Menu_Item * & m){ 724 if (m->submenu()){ 725 ++m; 726 for (;m->text;) 727 nextfl_menu(m); 728 } 729 ++m; 730 } 731 copy_menu(Fl_Menu_ * menu,const string & prefix,Fl_Menu_Item * & m)732 void copy_menu(Fl_Menu_ * menu,const string & prefix,Fl_Menu_Item * & m){ 733 for (;m->text;++m){ 734 if (m->submenu()){ 735 string prefix2=prefix+m->label(); 736 prefix2 += '/'; 737 ++m; 738 copy_menu(menu,prefix2,m); 739 } 740 else 741 menu->add((prefix+m->text).c_str(),m->shortcut_,m->callback_,m->user_data_,m->flags); 742 } 743 } 744 fl_menu2rpn_menu(Fl_Menu_Item * & m)745 vecteur fl_menu2rpn_menu(Fl_Menu_Item * & m){ 746 vecteur res; 747 ++m; 748 for (;m->text;++m){ 749 if (m->submenu()){ 750 string s=m->label(); 751 vecteur tmp(fl_menu2rpn_menu(m)); 752 if (!tmp.empty()) 753 res.push_back(makevecteur(string2gen(s,false),tmp)); 754 } 755 else { 756 gen g; 757 if (m->callback_==menu2rpn_callback){ 758 find_or_make_symbol(m->label(),g,0,false,context0); 759 // g=gen(string("'")+m->label()+string("'")); 760 if (g.is_symb_of_sommet(at_quote)) 761 g=g._SYMBptr->feuille; 762 res.push_back(g); 763 } 764 } 765 } 766 return res; 767 } 768 change_menu_fontsize(Fl_Menu * & m,int labelfontsize)769 void change_menu_fontsize(Fl_Menu * & m,int labelfontsize){ 770 if (!m->text) 771 return; 772 m->labelsize(labelfontsize); 773 if (m->submenu()){ 774 ++m; 775 for (;m->text;++m) 776 change_menu_fontsize(m,labelfontsize); 777 } 778 } 779 change_menu_fontsize(Fl_Menu_Item * m,int n,int labelfontsize)780 void change_menu_fontsize(Fl_Menu_Item * m,int n,int labelfontsize){ 781 for (int i=0;i<n;++i){ 782 change_menu_fontsize(m,labelfontsize); 783 ++m; 784 } 785 } 786 change_equation_fontsize(Equation * eq,int labelfontsize)787 void change_equation_fontsize(Equation * eq,int labelfontsize){ 788 if (eq->attr.fontsize==labelfontsize) 789 return; 790 eq->attr.fontsize=labelfontsize; 791 eq->labelsize(labelfontsize); 792 eq->resize(eq->x(),eq->y(),eq->w(),eq->h()); 793 eq->set_data(eq->get_data()); 794 eq->adjust_widget_size(); 795 } 796 change_group_fontsize(Fl_Widget * w,int labelfontsize)797 void change_group_fontsize(Fl_Widget * w,int labelfontsize){ 798 w->labelsize(labelfontsize); 799 w->redraw(); 800 if (Equation * eq=dynamic_cast<Equation *>(w)){ 801 change_equation_fontsize(eq,labelfontsize); 802 return; 803 } 804 Fl_Group * g = dynamic_cast<Fl_Group *>(w); 805 if (!g) 806 return; 807 Fl_Font police=g->labelfont(); 808 Fl_Widget * o; 809 Fl_Widget * const * ptr= g->array(); 810 int n=g->children(); 811 for (int i=0;i<n;++ptr,++i){ 812 o = *ptr; 813 if (o->labelfont()!=FL_SYMBOL) 814 o->labelfont(police); 815 if (Fl_Menu * m=dynamic_cast<Fl_Menu *>(o)){ 816 change_menu_fontsize(m,labelfontsize); 817 continue; 818 } 819 if (Fl_Menu_ * mb=dynamic_cast<Fl_Menu_ *>(o)){ 820 Fl_Menu_Item * mm=(Fl_Menu_Item *)mb->menu(); 821 for (;mm->text;++mm) 822 change_menu_fontsize(mm,labelfontsize); 823 } 824 if (Fl_Input_ * in=dynamic_cast<Fl_Input_ * >(o)){ 825 in->textsize(labelfontsize); 826 in->textfont(police); 827 } 828 if (Equation * eq=dynamic_cast<Equation * >(o)){ 829 eq->labelfont(police); 830 change_equation_fontsize(eq,labelfontsize); 831 } 832 if (Xcas_Text_Editor * xed=dynamic_cast<Xcas_Text_Editor *>(o)){ 833 xed->Fl_Text_Display::textsize(labelfontsize); 834 xed->Fl_Text_Display::textfont(labelfontsize); 835 vector<Fl_Text_Display::Style_Table_Entry> & v=xed->styletable; 836 for (unsigned i=0;i<v.size();++i) 837 v[i].size=labelfontsize; 838 xed->labelsize(labelfontsize); 839 Editeur * ed =dynamic_cast<Editeur *>(xed->parent()); 840 if (!ed && !xed->tableur) 841 xed->resize_nl_before(1); 842 xed->redraw(); 843 } 844 if (Fl_Value_Input * v=dynamic_cast<Fl_Value_Input *>(o)) 845 v->textsize(labelfontsize); 846 if (Fl_Browser * b=dynamic_cast<Fl_Browser *>(o)) 847 b->textsize(labelfontsize); 848 if (Fl_Counter * cc=dynamic_cast<Fl_Counter *>(o)) 849 cc->textsize(labelfontsize); 850 if (Fl_Group * og=dynamic_cast<Fl_Group *>(o)) 851 change_group_fontsize(og,labelfontsize); 852 if (HScroll * os =dynamic_cast<HScroll *>(o)){ 853 // resize childs according to new scrollbar width 854 os->resize(os->x(),os->y(),os->w(),os->h()); 855 } 856 if (Flv_Table_Gen * fl = dynamic_cast<Flv_Table_Gen *>(o)){ 857 fl->global_style.font_size(labelfontsize); 858 fl->global_style.height(labelfontsize+4); 859 fl->redraw(); 860 } 861 o->labelsize(labelfontsize); 862 if (Graph2d3d * gr=dynamic_cast<Graph2d3d *>(o)) 863 if (gr->parent() && !dynamic_cast<Figure *>(gr->parent()) && !dynamic_cast<Tableur_Group *>(gr->parent())) 864 gr->resize_mouse_param_group(gr->legende_size); 865 } 866 } 867 868 // Cut a string for display in a multiline area of size w using fontsize cut_help(const string & s,int fontsize,int w)869 string cut_help(const string & s,int fontsize,int w){ 870 if (s.empty()) 871 return s; 872 int sw; 873 // find 1st cut and add cut_help of the rest of the string to it 874 int begin=0,taille=s.size(),end; // cut is between begin and first \n 875 for (end=0;end<taille;++end){ 876 if (s[end]=='\n') 877 break; 878 } 879 fl_font(FL_HELVETICA,fontsize); 880 sw=int(fl_width(s.substr(0,end).c_str())); 881 if (sw<w){ 882 if (end==taille) 883 return s; 884 return s.substr(0,end+1)+cut_help(s.substr(end+1,taille-end-1),fontsize,w); 885 } 886 for (;end-begin>2;){ 887 int pos=(begin+end)/2,i; // find 1st space after middlepoint 888 for (i=pos;i>begin;--i){ 889 if (s[i]==' ') 890 break; 891 } 892 if (i==begin){ // no space before, try after 893 for (i=pos;i<end;++i){ 894 if (s[i]==' ') 895 break; 896 } 897 } 898 if (i==end){ 899 // No space at all, return 0 -> begin or 0 -> end if begin==0 900 if (begin) 901 pos=begin; 902 else { 903 if (end) 904 pos=end; 905 else 906 return s; 907 } 908 if (pos==taille) 909 return s; 910 return s.substr(0,pos)+'\n'+cut_help(s.substr(pos,taille-pos),fontsize,w); 911 } 912 sw=int(fl_width(s.substr(0,i).c_str())); 913 if (sw<w) 914 begin=i; 915 else 916 end=i; 917 } 918 return s.substr(0,end+1)+cut_help(s.substr(end+1,taille-end-1),fontsize,w); 919 } 920 help_output(const std::string & s,int language)921 void help_output(const std::string & s,int language){ 922 giac::aide cur_aide=helpon(s,(*giac::vector_aide_ptr()),language,(*giac::vector_aide_ptr()).size(),false); 923 if (Xcas_help_output){ 924 string result=cur_aide.cmd_name; 925 if (!cur_aide.syntax.empty()) 926 result=result+"("+cur_aide.syntax+")\n"; 927 vector<localized_string>::const_iterator it=cur_aide.blabla.begin(),itend=cur_aide.blabla.end(); 928 for (;it!=itend;++it){ 929 if (it->language==language){ 930 result = it->chaine +'\n'+result ; 931 break; 932 } 933 } 934 std::vector<std::string>::const_iterator jt=cur_aide.examples.begin(),jtend=cur_aide.examples.end(); 935 for (;jt!=jtend;++jt) 936 result = result + *jt + '\n'; 937 std::vector<indexed_string>::const_iterator kt=cur_aide.related.begin(),ktend=cur_aide.related.end(); 938 for (;kt!=ktend;++kt) 939 result = result + "-> "+print_INT_(kt->index)+": "+kt->chaine+'\n'; 940 Xcas_help_output->value(result.c_str()); 941 Xcas_help_output->redraw(); 942 } 943 } 944 browser_help(const giac::gen & g,int language)945 void browser_help(const giac::gen & g,int language){ 946 giac::gen f(g); 947 string s; 948 if (f.type==giac::_SYMB) 949 f=f._SYMBptr->sommet; 950 if (f.type==giac::_FUNC) 951 s=f._FUNCptr->ptr()->s; 952 giac::html_vtt=giac::html_help(giac::html_mtt,s); 953 help_output(s,language); 954 if (!giac::html_vtt.empty()){ 955 if (use_external_browser) 956 giac::system_browser_command(giac::html_vtt.front()); 957 else { 958 if (xcas::Xcas_help_window){ 959 xcas::Xcas_help_window->load(giac::html_vtt.front().c_str()); 960 if (!xcas::Xcas_help_window->visible()) 961 xcas::Xcas_help_window->show(); 962 } 963 } 964 } 965 } 966 check_browser_help(const giac::gen & g,int language)967 void check_browser_help(const giac::gen & g,int language){ 968 if (g.is_symb_of_sommet(giac::at_findhelp)) 969 browser_help(g._SYMBptr->feuille,language); 970 } 971 dbgprint(const gen & g,vector<string> & vs)972 void dbgprint(const gen & g,vector<string> & vs){ 973 vecteur v(gen2vecteur(g)); 974 const_iterateur it=v.begin(),itend=v.end(); 975 for (;it!=itend;++it) 976 vs.push_back(it->print(context0)); 977 } 978 fl_wait_0001(context * contextptr)979 void fl_wait_0001(context * contextptr){ 980 static int t_sec=0,t_usec=0; 981 int status=thread_eval_status(contextptr); 982 Xcas_debugguer(status,contextptr); 983 // don't flush too often 984 timeval tp; 985 if (!gettimeofday(&tp,0)){ 986 if (tp.tv_sec==t_sec && tp.tv_usec < t_usec+50000){ 987 usleep(100); 988 return; 989 } 990 t_sec=tp.tv_sec; 991 t_usec=tp.tv_usec ; 992 } 993 #ifdef __APPLE__ 994 Fl::wait(0.001); 995 #else 996 Fl::wait(0.0001); 997 #endif 998 Xcas_idle_function(0); 999 } 1000 thread_eval(const giac::gen & g,int level,context * contextptr)1001 giac::gen thread_eval(const giac::gen & g,int level,context * contextptr){ 1002 // Remove idle function for wait to work 1003 // cerr << "remove idle " << '\n'; 1004 Fl::remove_idle(xcas::Xcas_idle_function,0); 1005 gen res=giac::thread_eval(g,level,contextptr,fl_wait_0001); 1006 if (Xcas_Debug_Window) Xcas_Debug_Window->hide(); 1007 fl_wait_0001(contextptr); 1008 // Re-add idle function 1009 Fl::add_idle(xcas::Xcas_idle_function,0); 1010 return res; 1011 } 1012 in_Xcas_eval(Fl_Widget * w,const giac::gen & evaled_g0,int pretty_output,GIAC_CONTEXT)1013 Fl_Widget * in_Xcas_eval(Fl_Widget * w,const giac::gen & evaled_g0,int pretty_output,GIAC_CONTEXT){ 1014 gen evaled_g=evaled_g0; 1015 if (evaled_g.type==_MAP && evaled_g.subtype==1) 1016 evaled_g=giac::maptoarray(*evaled_g._MAPptr,contextptr); 1017 // cleanup 1018 giac::clear_prog_status(contextptr); 1019 giac::cleanup_context(contextptr); 1020 History_Pack * hp = get_history_pack(w); 1021 if (hp) Fl_Group::current(hp); 1022 if (calc_mode(contextptr)==-38) 1023 calc_mode(contextptr)=38; 1024 /* FIXME: use simplifier only if the user ask for it 1025 if (!g.is_symb_of_sommet(at_ifactor)) 1026 evaled_g=giac::_simplifier(evaled_g,contextptr); */ 1027 if (pretty_output){ 1028 int anim=giac::animations(evaled_g); 1029 if (evaled_g.is_symb_of_sommet(at_parameter) && evaled_g._SYMBptr->feuille.type==_VECT){ 1030 Gen_Value_Slider * res = parameter2slider(evaled_g,contextptr); 1031 if (res){ 1032 res->resize(w->x()+3*w->labelsize(),w->y(),w->w()-3*w->labelsize(),w->labelsize()); 1033 res->labelsize(w->labelsize()); 1034 return res; 1035 } 1036 } 1037 int tt; 1038 if (evaled_g.type == _VECT && (tt=graph_output_type(evaled_g)) ){ 1039 if (tt==4){ 1040 // Fl_Tile * g = new Fl_Tile(w->x(),w->y(),w->w(),max(130,w->w()/3)); 1041 // g->labelsize(w->labelsize()); 1042 Turtle * tu = new Turtle(w->x(),w->y(),w->w(),max(130,w->w()/3)); 1043 tu->turtleptr=&turtle_stack(contextptr); 1044 //g->end(); 1045 //change_group_fontsize(g,w->labelsize()); 1046 //return g; 1047 return tu; 1048 } 1049 Fl_Tile * g = new Fl_Tile(w->x(),w->y(),w->w(),max(130,w->w()/3)); 1050 g->labelsize(w->labelsize()); 1051 Graph2d3d * tmp; 1052 #ifdef HAVE_LIBFLTK_GL 1053 if (is3d(evaled_g._VECTptr->back())){ 1054 #ifdef GRAPH_WINDOW 1055 Fl_Window * win=new Fl_Window(w->x(),w->y(),w->w(),g->h()); 1056 tmp =new Graph3d(0,0,w->w(),g->h(),"",hp); 1057 win->end(); win->show(); 1058 Fl_Group::current(g); 1059 #else 1060 tmp =new Graph3d(w->x(),w->y(),w->w(),g->h(),"",hp); 1061 #endif 1062 tmp->show(); 1063 } 1064 else 1065 #endif 1066 { 1067 tmp=new Graph2d(w->x(),w->y(),w->w(),g->h(),"",hp); 1068 if (Xcas_config.ortho) 1069 tmp->orthonormalize(); 1070 } 1071 tmp->add(evaled_g); 1072 if (anim) 1073 tmp->animation_dt=1./5; 1074 if (Xcas_config.autoscale) 1075 tmp->autoscale(); 1076 tmp->update_infos(evaled_g,contextptr); 1077 g->end(); 1078 change_group_fontsize(g,w->labelsize()); 1079 return g; 1080 } 1081 if (is_pnt_or_pixon(evaled_g) || anim){ 1082 Fl_Tile * g = new Fl_Tile(w->x(),w->y(),w->w(),max(130,w->w()/3)); 1083 g->labelsize(w->labelsize()); 1084 Graph2d3d * res; 1085 #ifdef HAVE_LIBFLTK_GL 1086 if (is3d(evaled_g)){ 1087 #ifdef GRAPH_WINDOW 1088 Fl_Window * win=new Fl_Window(w->x(),w->y(),w->w(),g->h()); 1089 res = new Graph3d(0,0,w->w(),g->h(),"",hp); 1090 win->end(); win->show(); 1091 g->add(win); 1092 Fl_Group::current(g); 1093 #else 1094 res = new Graph3d(w->x(),w->y(),w->w(),g->h(),"",hp); 1095 #endif 1096 res->show(); 1097 } 1098 else 1099 #endif 1100 { 1101 res=new Graph2d(w->x(),w->y(),w->w(),g->h(),"",hp); 1102 if (Xcas_config.ortho) 1103 res->orthonormalize(); 1104 } 1105 res->add(evaled_g); 1106 if (anim) 1107 res->animation_dt=1./5; 1108 if (Xcas_config.autoscale) 1109 res->autoscale(); 1110 res->update_infos(evaled_g,contextptr); 1111 g->end(); 1112 change_group_fontsize(g,w->labelsize()); 1113 return g; 1114 } 1115 /* 1116 if (evaled_g.type==_DOUBLE_ || evaled_g.type==_INT_){ 1117 Gen_Output * o = new Gen_Output(w->x(),w->y(),w->w(),w->labelsize()+7); 1118 o->textsize(w->labelsize()); 1119 o->value(evaled_g); 1120 o->textcolor(FL_BLACK); 1121 fl_font(FL_HELVETICA,w->labelsize()); 1122 int hss=int(fl_width(o->Fl_Output::value()))+4; 1123 if (hss<=w->w()) 1124 return o; 1125 else 1126 delete o; 1127 } 1128 */ 1129 unsigned ta=taille(evaled_g,max_prettyprint_equation); 1130 if (ta<max_prettyprint_equation){ 1131 giac::attributs attr(w->labelsize(),Xcas_equation_background_color,Xcas_equation_color); 1132 giac::gen varg=Equation_compute_size(evaled_g,attr,w->w(),contextptr); 1133 giac::eqwdata vv(Equation_total_size(varg)); 1134 int maxh=w->window()?(3*w->window()->h())/5:1000; 1135 int scrollsize=3; 1136 if (vv.dx>w->w()-2*w->labelsize()) 1137 scrollsize=w->labelsize()+3; 1138 int h=min(vv.dy+scrollsize+3,maxh); // =max(min(vv.dy+20,400),60); 1139 Equation * res = new Equation(w->x(),w->y(),w->w(),h,"",evaled_g,attr,contextptr); 1140 res->box(FL_FLAT_BOX); 1141 return res; 1142 } 1143 } 1144 Gen_Output * o = new Gen_Output(w->x(),w->y(),w->w(),w->labelsize()+7); 1145 o->textsize(w->labelsize()); 1146 o->value(evaled_g); 1147 o->textcolor(FL_BLUE); 1148 fl_font(FL_HELVETICA,w->labelsize()); 1149 int hss=int(fl_width(o->Fl_Output::value()))+4; 1150 if (hss<=w->w()) 1151 return o; 1152 o->resize(w->x(),w->y(),hss,w->labelsize()+7); 1153 Fl_Scroll * s = new Fl_Scroll(w->x(),w->y(),w->w(),2*w->labelsize()+9); 1154 s->hscrollbar.resize(s->hscrollbar.x(),w->y()+w->labelsize()+7,s->hscrollbar.w(),w->labelsize()); 1155 s->box(FL_FLAT_BOX); 1156 s->end(); 1157 s->add(o); 1158 return s; 1159 } 1160 Xcas_eval_callback(const giac::gen & evaled_g,void * param)1161 void Xcas_eval_callback(const giac::gen & evaled_g,void * param){ 1162 Fl_Widget * wid=static_cast<Fl_Widget *>(param); 1163 if (!wid) 1164 return; 1165 int hp_pos; 1166 History_Pack * hp = get_history_pack(wid,hp_pos); 1167 context * contextptr = hp?hp->contextptr:0; 1168 Fl_Group * gr = wid->parent(); 1169 if (!hp || !gr) 1170 return; 1171 #ifdef HAVE_LIBPTHREAD 1172 // cerr << "geo2d lock" << '\n'; 1173 pthread_mutex_lock(&interactive_mutex); 1174 #endif 1175 bool b=io_graph(contextptr); 1176 io_graph(contextptr)=false; 1177 bool block=block_signal; 1178 block_signal=true; 1179 // int m=gr->children(); 1180 // reset output 1181 #ifdef WITH_MYOSTREAM 1182 logptr(&my_cerr,contextptr); 1183 #else 1184 logptr(&std::cerr,contextptr); 1185 #endif 1186 if (!giac::history_out(contextptr).empty() && giac::history_out(contextptr).size()==giac::history_in(contextptr).size()) 1187 giac::history_out(contextptr).back()=evaled_g; 1188 else 1189 giac::history_out(contextptr).push_back(evaled_g); 1190 int pos=gr->find(wid); 1191 Fl_Widget * res = in_Xcas_eval(wid,evaled_g,hp->pretty_output,contextptr); 1192 if (Log_Output * lout=find_log_output(gr)) 1193 output_resize_parent(lout,false); 1194 if (res){ 1195 // resize group/pack here 1196 gr->Fl_Widget::resize(gr->x(),gr->y(),gr->w(),gr->h()+res->h()-wid->h()); 1197 res->resize(wid->x(),wid->y(),res->w(),res->h()); 1198 int dy=res->h()-wid->h(); 1199 gr->remove(wid); 1200 Graph2d3d * widgraph = 0; 1201 if (Fl_Group * widgr = dynamic_cast<Fl_Group *>(wid)){ 1202 if (widgr->children()) 1203 widgraph=dynamic_cast<Graph2d3d *>(widgr->child(0)); 1204 } 1205 Graph2d3d * resgraph = 0; 1206 if (Fl_Group * widgr = dynamic_cast<Fl_Group *>(res)){ 1207 if (widgr->children()) 1208 resgraph=dynamic_cast<Graph2d3d *>(widgr->child(0)); 1209 } 1210 gr->insert(*res,pos); 1211 change_group_fontsize(gr,gr->labelsize()); 1212 if (widgraph && resgraph){ 1213 resgraph->copy(*widgraph); 1214 resgraph->resize(resgraph->x(),resgraph->y(),widgraph->w(),resgraph->h()); 1215 resgraph->resize_mouse_param_group(gr->w()-widgraph->w()); 1216 } 1217 // gr->resizable(gr); 1218 hp->resize(); 1219 if (Fl_Scroll * s = dynamic_cast<Fl_Scroll *>(hp->parent())){ 1220 int spos=s->yposition(); 1221 if (spos+s->h()>hp->h()){ 1222 #ifdef _HAVE_FL_UTF8_HDR_ 1223 s->scroll_to(0,max(min(hp->h()-s->h(),spos+dy),0)); 1224 #else 1225 s->position(0,max(min(hp->h()-s->h(),spos+dy),0)); 1226 #endif 1227 } 1228 s->redraw(); 1229 } 1230 Fl_Group * group = parent_skip_scroll(hp); 1231 if (Logo * logo=dynamic_cast<Logo *>(group)){ 1232 logo->redraw(); 1233 } 1234 // show DispG? 1235 if (hp->pretty_output && !Xcas_DispG_Window->visible()){ 1236 int entries=Xcas_DispG->plot_instructions.size(); 1237 if (entries>xcas_dispg_entries){ 1238 if (resgraph){ 1239 vecteur dispgv=vecteur(Xcas_DispG->plot_instructions.begin()+xcas_dispg_entries,Xcas_DispG->plot_instructions.end()),v1,v2; 1240 aplatir(dispgv,v1); 1241 aplatir(resgraph->plot_instructions,v2); 1242 if (v1!=v2){ 1243 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); 1244 show_xcas_dispg=3; 1245 } 1246 } 1247 else { 1248 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); 1249 show_xcas_dispg=3; 1250 } 1251 } 1252 } 1253 block_signal=block; 1254 io_graph(contextptr)=b; 1255 #ifdef HAVE_LIBPTHREAD 1256 pthread_mutex_unlock(&interactive_mutex); 1257 #endif 1258 // if hp has eval_below, call callback on next widget 1259 if (hp->eval_below){ 1260 hp->next(hp_pos); 1261 /* 1262 Fl_Group * hpp = parent_skip_scroll(hp); 1263 if (hpp){ 1264 int N=hpp->children(); 1265 for (int i=0;i<N;++i){ 1266 Graph2d3d * geo = dynamic_cast<Graph2d3d *>(hpp->child(i)); 1267 if (geo){ 1268 geo->handle(FL_FOCUS); 1269 } 1270 } 1271 } 1272 */ 1273 } 1274 else { 1275 Fl_Group * hpp = parent_skip_scroll(hp); 1276 if (hpp){ 1277 int N=hpp->children(); 1278 for (int i=0;i<N;++i){ 1279 Graph2d3d * geo = dynamic_cast<Graph2d3d *>(hpp->child(i)); 1280 if (geo){ 1281 geo->add(evaled_g); 1282 geo->no_handle=false; 1283 } 1284 } 1285 } 1286 hp->focus(hp_pos+1,false); 1287 } 1288 } // if (res) 1289 else { // res==0 no output 1290 if (Fl_Input_ * i=dynamic_cast<Fl_Input_ * >(wid)) 1291 i->value("No_output"); 1292 hp->resize(); 1293 block_signal=block; 1294 io_graph(contextptr)=b; 1295 #ifdef HAVE_LIBPTHREAD 1296 pthread_mutex_unlock(&interactive_mutex); 1297 #endif 1298 } 1299 } 1300 Xcas_eval(Fl_Widget * w,const giac::gen & g_)1301 Fl_Widget * Xcas_eval(Fl_Widget * w,const giac::gen & g_){ 1302 if (!w) 1303 return 0; 1304 if (debug_infolevel>=5) 1305 cerr << "eval " << g_ << '\n'; 1306 Fl_Group * gr=w->parent(); 1307 Fl_Group::current(gr); 1308 // Find history_pack above for context from widget 1309 History_Pack * hp = get_history_pack(w); 1310 context * contextptr=hp?hp->contextptr:0; 1311 check_browser_help(g_,giac::language(contextptr)); 1312 if (!hp) 1313 return 0; 1314 gen g=add_autosimplify(g_,contextptr); 1315 giac::gen evaled_g; 1316 // if w 2nd brother is a graph2d3d, return a graph2d3d with the same 1317 // config 1318 Fl_Widget * res = 0; 1319 if (gr && gr->children()>=3){ 1320 if (Fl_Output * out=dynamic_cast<Fl_Output *>(gr->child(2))){ 1321 if (strcmp(out->value(),gettext("Computing..."))==0){ 1322 out->value(gettext("Unable to launch thread. Press STOP to interrupt.")); 1323 return w; 1324 } 1325 } 1326 if (Fl_Group * grc2=dynamic_cast<Fl_Group * >(gr->child(2))){ 1327 if (grc2->children()){ 1328 if (Graph2d3d * graph=dynamic_cast<Graph2d3d *>(grc2->child(0))){ 1329 Fl_Tile * temptile = new Fl_Tile(w->x(),w->y(),w->w(),w->labelsize()+6); 1330 Graph2d * tmp = new Graph2d(w->x(),w->y(),w->w(),temptile->h(),"",hp); 1331 temptile->end(); 1332 tmp->copy(*graph); 1333 tmp->resize(tmp->x(),tmp->y(),graph->w(),tmp->h()); 1334 temptile->labelsize(w->labelsize()); 1335 res=temptile; 1336 } 1337 } 1338 } 1339 } 1340 giac::history_in(contextptr).push_back(g_); 1341 // commented otherwise ans() does not work 1342 // giac::history_out.push_back(g); 1343 Fl_Output * out=0; 1344 bool graphres=res; 1345 out =new Fl_Output(w->x(),w->y(),w->w(),w->labelsize()); 1346 out->labelsize(w->labelsize()); 1347 if (!res) 1348 res=out; 1349 bool ok=make_thread(g,eval_level(contextptr),Xcas_eval_callback,res,contextptr); 1350 if (graphres){ 1351 if (ok){ 1352 gr->remove(out); 1353 delete out; 1354 return res; 1355 } 1356 gr->remove(res); 1357 delete res; 1358 res=out; 1359 } 1360 out->value(ok?gettext("Computing..."):gettext("Unable to launch thread. Press STOP to interrupt.")); 1361 return res; 1362 } 1363 Xcas_eval(Fl_Widget * w)1364 Fl_Widget * Xcas_eval(Fl_Widget * w) { 1365 giac::gen g; 1366 int res=parse(w,g); 1367 if (res==1) 1368 return Xcas_eval(w,g); 1369 if (res==-1) 1370 return w; 1371 /* Fl_Output * o = new Fl_Output(w->x(),w->y(),w->w(),w->h()); 1372 o->value("Invalid input"); 1373 return o; */ 1374 return 0; 1375 } 1376 1377 print_DOUBLE_(double d)1378 string print_DOUBLE_(double d){ 1379 char s[256]; 1380 #ifdef IPAQ 1381 sprintf(s,"%.4g",d); 1382 #else 1383 sprintf(s,"%.5g",d); 1384 #endif 1385 return s; 1386 } 1387 replaces(const string & s,char c1,const string & c2)1388 string replaces(const string & s,char c1,const string & c2){ 1389 string res; 1390 int l=s.size(); 1391 res.reserve(l); 1392 const char * ch=s.c_str(); 1393 for (int i=0;i<l;++i,++ch){ 1394 if (*ch==c1) res+=c2; else res += *ch; 1395 } 1396 return res; 1397 } 1398 seq2vecteur(const vecteur & v)1399 vecteur seq2vecteur(const vecteur & v){ 1400 vecteur w(v); 1401 iterateur it=w.begin(),itend=w.end(); 1402 for (;it!=itend;++it){ 1403 if (it->type==_VECT) 1404 it->subtype=0; 1405 } 1406 return w; 1407 } 1408 load_history_fold(int sx,int sy,int sw,int sh,int sl,const char * filename,bool modified)1409 History_Fold * load_history_fold(int sx,int sy,int sw,int sh,int sl,const char * filename,bool modified){ 1410 Fl_Group::current(0); 1411 xcas::History_Fold * w = new xcas::History_Fold(sx,sy,sw,sh,1); 1412 w->end(); 1413 w->pack->contextptr = giac::clone_context(giac::context0); 1414 w->pack->labelsize(sl); 1415 w->pack->eval=xcas::Xcas_eval; 1416 w->pack->_insert=xcas::Xcas_pack_insert; 1417 w->pack->_select=xcas::Xcas_pack_select; 1418 w->pack->new_url(filename); 1419 w->pack->insert_url(filename,-1); 1420 w->labelfont(w->pack->labelfont()); 1421 xcas::change_group_fontsize(w,w->pack->labelsize()); 1422 if (!modified) 1423 w->pack->clear_modified(); 1424 else { 1425 w->autosave(true); 1426 if (w->pack->url){ delete w->pack->url; w->pack->url=0; } 1427 w->label("Unnamed"); 1428 } 1429 return w; 1430 } 1431 replace_html5(const string & s)1432 std::string replace_html5(const string & s){ 1433 string res; 1434 size_t ss=s.size(),i; 1435 for (i=0;i<ss;++i){ 1436 char ch=s[i]; 1437 if ( (ch>='0' && ch<='9') || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z')) 1438 res += ch; 1439 else { 1440 res +='%'; 1441 int t=(ch&0xf0)>>4; 1442 if (t<10) res += ('0'+t); else res += 'a'+(t-10); 1443 t=ch&0x0f; 1444 if (t<10) res += ('0'+t); else res += 'a'+(t-10); 1445 } 1446 } 1447 //std::cerr << s << '\n' << res << '\n'; 1448 return res; 1449 } 1450 widget_html5(const Fl_Widget * o)1451 std::string widget_html5(const Fl_Widget * o){ 1452 string res; 1453 const giac::context * contextptr = get_context(o); 1454 // Add here code for specific widgets 1455 if (const Tableur_Group * t = dynamic_cast<const Tableur_Group *>(o)){ 1456 Flv_Table_Gen * g=t->table; 1457 matrice m=g->m; 1458 res = replace_html5(gen(m,_SPREAD__VECT).print(contextptr)); 1459 return '+'+res+'&'; 1460 } 1461 if (const Figure * f = dynamic_cast<const Figure *>(o)){ 1462 res = widget_html5(f->geo->hp); 1463 return res; 1464 } 1465 if (const Logo * l=dynamic_cast<const Logo *>(o)){ 1466 res = widget_html5(l->hp); 1467 return res; 1468 } 1469 if (const Editeur * ed=dynamic_cast<const Editeur *>(o)){ 1470 string s=unlocalize(ed->value()); 1471 res = replace_html5(s); 1472 return '+'+res+'&'; 1473 } 1474 if (const Xcas_Text_Editor * ed=dynamic_cast<const Xcas_Text_Editor *>(o)){ 1475 string s=unlocalize(ed->value()); 1476 res = replace_html5(s); 1477 return '+'+res+'&'; 1478 } 1479 if (dynamic_cast<const Fl_Output *>(o)) 1480 return ""; 1481 if (const Fl_Input_ * i=dynamic_cast<const Fl_Input_ *>(o)){ 1482 string s=i->value(); 1483 if (dynamic_cast<const Comment_Multiline_Input *>(i)) 1484 s = "// "+replaces(s,'\n',"<br>"); 1485 if ( dynamic_cast<const Multiline_Input_tab *>(i) ) 1486 s=unlocalize(s); 1487 if (s.empty()) 1488 return s; 1489 res = replace_html5(s); 1490 return '+'+res+'&' ; 1491 } 1492 if (const Fl_Group * g=dynamic_cast<const Fl_Group *>(o)){ 1493 int ypos=0; 1494 // call widget_sprint on children 1495 int n=g->children(); 1496 for (int i=0;i<n;++i){ 1497 Fl_Widget * wid=g->child(i); 1498 res += widget_html5(wid); 1499 } 1500 return res; 1501 } 1502 if (const Gen_Value_Slider *g=dynamic_cast<const Gen_Value_Slider *>(o)){ 1503 res = string(g->label())+","+print_DOUBLE_(g->value())+","+print_DOUBLE_(g->minimum())+","+print_DOUBLE_(g->maximum())+","+print_DOUBLE_(g->Fl_Valuator::step()); 1504 return '*'+res+'&'; 1505 } 1506 return res ; 1507 } 1508 widget_sprint(const Fl_Widget * o)1509 std::string widget_sprint(const Fl_Widget * o){ 1510 string res; 1511 const giac::context * contextptr = get_context(o); 1512 res = "// fltk " + string(typeid(*o).name()); 1513 int wh=o->h(); 1514 if (const History_Fold * hf=dynamic_cast<const History_Fold *>(o)){ 1515 if (hf->_folded) 1516 wh=hf->_horig; 1517 } 1518 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()) ; 1519 // Add here code for specific widgets 1520 if (const Flv_Table_Gen * g = dynamic_cast<const Flv_Table_Gen *>(o)){ 1521 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'; 1522 return res; 1523 } 1524 if (const Tableur_Group * t = dynamic_cast<const Tableur_Group *>(o)){ 1525 Flv_Table_Gen * g=t->table; 1526 Graph2d3d * gr = g->graph; 1527 matrice m=g->m; 1528 if (!g->m.empty()){ 1529 gen m0=m.front(); 1530 if (m0.type==_VECT && !m0._VECTptr->empty()){ 1531 vecteur m0v=*m0._VECTptr; 1532 gen m00=m0v.front(); 1533 if (m00.type==_VECT && m00._VECTptr->size()==3){ 1534 vecteur rowv,colv,dispv; 1535 for (int i=0;i<g->rows();++i) 1536 rowv.push_back(g->row_height(i)); 1537 for (int i=0;i<g->cols();++i) 1538 colv.push_back(g->col_width(i)); 1539 dispv.push_back(t->disposition); 1540 if (t->disposition/2){ 1541 if (t->disposition % 2){ // graph at right 1542 dispv.push_back(g->w()); 1543 dispv.push_back(g->graph->w()); 1544 dispv.push_back(g->graph->mouse_param_group->w()); 1545 } 1546 else { // graph below 1547 double dtable=double(g->h())/t->h(); 1548 double dgraph=((1-dtable)*g->graph->w())/g->w(); 1549 dispv.push_back(dtable); 1550 dispv.push_back(dgraph); 1551 dispv.push_back(1-dtable-dgraph); 1552 } 1553 } 1554 gen newm002=makevecteur(g->name, 1555 makevecteur(gr->window_xmin,gr->window_xmax,gr->window_ymin,gr->window_ymax), 1556 gr->npixels, 1557 makevecteur(gr->x_tick,gr->y_tick), 1558 gr->show_axes,gr->show_names,dispv,makevecteur(rowv,colv),g->init); 1559 m00=gen(makevecteur(m00[0],m00[1],newm002),m0v[0].subtype); 1560 m0v[0]=m00; 1561 m[0]=gen(m0v,m0[0].subtype); 1562 } 1563 } 1564 } 1565 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'; 1566 return res; 1567 } 1568 if (const Figure * f = dynamic_cast<const Figure *>(o)){ 1569 res += " landscape="+print_INT_(f->disposition)+" history="; 1570 if (f->disposition & 1){ 1571 double tmp=double(f->geo->h())/f->h(); 1572 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()); 1573 } 1574 else 1575 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()); 1576 res += '\n'+widget_sprint(f->geo->hp)+widget_sprint(f->geo)+'\n'; 1577 return res; 1578 } 1579 if (const Logo * l=dynamic_cast<const Logo *>(o)){ 1580 res += '\n'+widget_sprint(l->hp)+widget_sprint(l->ed); 1581 return res; 1582 } 1583 if (const Editeur * ed=dynamic_cast<const Editeur *>(o)){ 1584 string s=unlocalize(ed->value()); 1585 res += '\n'+print_INT_(s.size())+" ,\n"+s; 1586 return res; 1587 } 1588 if (const Xcas_Text_Editor * ed=dynamic_cast<const Xcas_Text_Editor *>(o)){ 1589 string s=unlocalize(ed->value()); 1590 res += '\n'+print_INT_(s.size())+" ,\n"+s; 1591 return res; 1592 } 1593 if (const Gen_Output * i=dynamic_cast<const Gen_Output *>(o)){ 1594 res += '\n'; 1595 string s=taille(i->value(),100)>100?string("Done"):i->value().print(contextptr); 1596 s=unlocalize(s); 1597 res += replace(s,'\n','�'); 1598 // res += '"'; 1599 return res + '\n'; 1600 } 1601 if (const Fl_Input_ * i=dynamic_cast<const Fl_Input_ *>(o)){ 1602 res += '\n'; 1603 string s=i->value(); 1604 if ( dynamic_cast<const Multiline_Input_tab *>(i) ) 1605 s=unlocalize(s); 1606 res += replace(s,'\n','�'); 1607 // res += '"'; 1608 return res + '\n'; 1609 } 1610 if (const Log_Output * i=dynamic_cast<const Log_Output *>(o)){ 1611 res += '\n'; 1612 // res += '"'; 1613 res += replace(i->value(),'\n','�'); 1614 // res += '"'; 1615 return res + '\n'; 1616 } 1617 if (const Equation * i=dynamic_cast<const Equation *>(o)){ 1618 res += " " + giac::print_INT_(i->output_equation); 1619 res += '\n'; 1620 // res += '"'; 1621 string s=taille(i->get_data(),1000)>1000?string("Done"):i->value(); 1622 res += replace(unlocalize(s),'\n','�'); 1623 // res += '"'; 1624 return res + '\n'; 1625 } 1626 if (const Graph2d3d * i=dynamic_cast<const Graph2d3d *>(o)){ 1627 res += '\n'; 1628 res += print_DOUBLE_(i->window_xmin) + ',' + print_DOUBLE_(i->window_xmax) + ','; 1629 res += print_DOUBLE_(i->window_ymin) + ',' + print_DOUBLE_(i->window_ymax) + ','; 1630 res += replace(giac::gen(giac::merge_pixon(seq2vecteur(i->plot_instructions))).print(contextptr),'\n','�'); 1631 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)+','; 1632 if (i->paused) 1633 res += "-"; 1634 res +=print_DOUBLE_(i->animation_dt)+','+print_INT_(i->show_mouse_on_object)+','+print_INT_(i->display_mode); 1635 res += ",["; 1636 if (dynamic_cast<const Graph3d *>(i)){ 1637 for (int j=0;;){ 1638 res += "["+ print_DOUBLE_(i->light_x[j]); 1639 res += ","+ print_DOUBLE_(i->light_y[j]); 1640 res += ","+ print_DOUBLE_(i->light_z[j]); 1641 res += ","+ print_DOUBLE_(i->light_w[j]); 1642 res += ","+ print_DOUBLE_(i->light_diffuse_r[j]); 1643 res += ","+ print_DOUBLE_(i->light_diffuse_g[j]); 1644 res += ","+ print_DOUBLE_(i->light_diffuse_b[j]); 1645 res += ","+ print_DOUBLE_(i->light_diffuse_a[j]); 1646 res += ","+ print_DOUBLE_(i->light_specular_r[j]); 1647 res += ","+ print_DOUBLE_(i->light_specular_g[j]); 1648 res += ","+ print_DOUBLE_(i->light_specular_b[j]); 1649 res += ","+ print_DOUBLE_(i->light_specular_a[j]); 1650 res += ","+ print_DOUBLE_(i->light_ambient_r[j]); 1651 res += ","+ print_DOUBLE_(i->light_ambient_g[j]); 1652 res += ","+ print_DOUBLE_(i->light_ambient_b[j]); 1653 res += ","+ print_DOUBLE_(i->light_ambient_a[j]); 1654 res += ","+ print_DOUBLE_(i->light_spot_x[j]); 1655 res += ","+ print_DOUBLE_(i->light_spot_y[j]); 1656 res += ","+ print_DOUBLE_(i->light_spot_z[j]); 1657 res += ","+ print_DOUBLE_(i->light_spot_w[j]); 1658 res += ","+ print_DOUBLE_(i->light_spot_exponent[j]); 1659 res += ","+ print_DOUBLE_(i->light_spot_cutoff[j]); 1660 res += ","+ print_DOUBLE_(i->light_0[j]); 1661 res += ","+ print_DOUBLE_(i->light_1[j]); 1662 res += ","+ print_DOUBLE_(i->light_2[j])+","+print_INT_(i->light_on[j])+"]"; 1663 ++j; 1664 if (j==8) 1665 break; 1666 res += ","; 1667 } 1668 } // end i is a graph3d 1669 res += "]"; 1670 res += ","+print_INT_(i->ntheta)+","+print_INT_(i->nphi); 1671 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); 1672 res += ","+print_INT_(i->x_axis_color)+","+print_INT_(i->y_axis_color)+","+print_INT_(i->z_axis_color); 1673 return res + '\n'; 1674 } 1675 if (const History_Fold * g=dynamic_cast<const History_Fold *>(o)){ 1676 res += '\n'+replace(g->input->value(),'\n','�') + '\n'; 1677 res += widget_sprint(g->pack); 1678 return res; 1679 } 1680 if (const Fl_Group * g=dynamic_cast<const Fl_Group *>(o)){ 1681 int ypos=0; 1682 if (Fl_Scroll * s=(Fl_Scroll *) dynamic_cast<const Fl_Scroll *>(g)){ 1683 ypos=s->yposition(); 1684 #ifdef _HAVE_FL_UTF8_HDR_ 1685 s->scroll_to(s->xposition(),0); 1686 #else 1687 s->position(s->xposition(),0); 1688 #endif 1689 } 1690 // call widget_sprint on children 1691 int n=g->children(); 1692 res += "\n[\n"; 1693 for (int i=0;i<n;++i){ 1694 Fl_Widget * wid=g->child(i); 1695 res += widget_sprint(wid); 1696 if (i!=n-1) 1697 res += ",\n"; 1698 } 1699 res += "]\n"; 1700 if (Fl_Scroll * s=(Fl_Scroll *) dynamic_cast<const Fl_Scroll *>(g)){ 1701 #ifdef _HAVE_FL_UTF8_HDR_ 1702 s->scroll_to(s->xposition(),ypos); 1703 #else 1704 s->position(s->xposition(),ypos); 1705 #endif 1706 } 1707 return res; 1708 } 1709 if (const Gen_Value_Slider *g=dynamic_cast<const Gen_Value_Slider *>(o)){ 1710 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"; 1711 return res; 1712 } 1713 return res + "\n[]\n"; 1714 } 1715 next_line(const string & s,int L,string & line,int & i)1716 void next_line(const string & s,int L,string & line,int & i){ 1717 line=""; 1718 for (;i<L;++i){ 1719 line += (s[i]=='�'?'\n':s[i]); 1720 if (s[i]=='\n'){ 1721 ++i; 1722 break; 1723 } 1724 } 1725 // cerr << i << " " << line << '\n'; 1726 } 1727 next_line_nonl(const string & s,int L,string & line,int & i)1728 void next_line_nonl(const string & s,int L,string & line,int & i){ 1729 next_line(s,L,line,i); 1730 int t=line.size(); 1731 if (t && line[t-1]=='\n') 1732 line=line.substr(0,t-1); 1733 } 1734 1735 // Read a group of widget from string s starting a pos i widget_group_load(Fl_Group * res,const string & s,int L,int & i,GIAC_CONTEXT)1736 Fl_Group * widget_group_load(Fl_Group * res,const string & s,int L,int & i,GIAC_CONTEXT){ 1737 Fl_Group::current(res); 1738 for (;Fl_Widget * o=widget_load(s,L,i,contextptr,res->w());){ 1739 if (History_Pack * hp=dynamic_cast<History_Pack *>(o)) 1740 hp->contextptr=(giac::context *)contextptr; 1741 if (o->w()>res->w()) 1742 o->resize(o->x(),o->y(),res->w(),o->h()); 1743 if (o->parent()!=res) 1744 res->add(o); 1745 // remove empty group 1746 if (Fl_Group * gr = dynamic_cast<Fl_Group * >(o)){ 1747 if (!gr->children()) 1748 res->remove(gr); 1749 } 1750 if (i<L-1 && s[i]==',' && s[i+1]=='\n') 1751 i += 2; 1752 } 1753 res->end(); 1754 string line; 1755 next_line(s,L,line,i); 1756 if (line=="]\n") 1757 return res; 1758 else 1759 return 0; 1760 } 1761 graphic_load(Graph2d3d * res,const std::string & s,int L,string & line,int & i)1762 void graphic_load(Graph2d3d * res,const std::string & s,int L,string & line,int & i){ 1763 /* 1764 if (res->mouse_param_group && !dynamic_cast<Figure *>(res->parent())){ 1765 int X=res->x(); 1766 int Y=res->y(); 1767 int W=res->parent()->w(); 1768 int H=res->h(); 1769 int l=W/4; 1770 if (l>6*res->labelsize()) 1771 l=6*res->labelsize(); 1772 res->resize(X,Y,W-l,H); 1773 res->resize_mouse_param_group(l); 1774 } 1775 */ 1776 next_line_nonl(s,L,line,i); 1777 if (s[i]=='\n') 1778 ++i; 1779 const giac::context * contextptr = get_context(res); 1780 giac::gen g(line,contextptr); 1781 if (g.type==_VECT && g._VECTptr->size()>=5){ 1782 giac::vecteur & v =*g._VECTptr; 1783 res->window_xmin= giac::evalf_double(v[0],1,contextptr)._DOUBLE_val; 1784 res->window_xmax= giac::evalf_double(v[1],1,contextptr)._DOUBLE_val; 1785 res->window_ymin= giac::evalf_double(v[2],1,contextptr)._DOUBLE_val; 1786 res->window_ymax= giac::evalf_double(v[3],1,contextptr)._DOUBLE_val; 1787 gen gg=v[4]; 1788 if (gg.type==_VECT) 1789 res->add(*gg._VECTptr); 1790 else 1791 res->add(gg); 1792 if (v.size()>=7){ 1793 res->window_zmin= giac::evalf_double(v[5],1,contextptr)._DOUBLE_val; 1794 res->window_zmax= giac::evalf_double(v[6],1,contextptr)._DOUBLE_val; 1795 } 1796 if (v.size()>=11){ 1797 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); 1798 } 1799 if (v.size()>=13){ 1800 res->x_tick=giac::evalf_double(v[11],1,contextptr)._DOUBLE_val; 1801 res->y_tick=giac::evalf_double(v[12],1,contextptr)._DOUBLE_val; 1802 } 1803 if (v.size()>=14) 1804 res->show_axes=v[13].val; 1805 if (v.size()>=16){ 1806 res->couleur=v[14].val; 1807 res->approx=v[15].val; 1808 } 1809 if (v.size()>=17) 1810 res->ylegende=evalf_double(v[16],1,contextptr)._DOUBLE_val; 1811 if (v.size()>=18){ 1812 gen tmp=evalf_double(v[17],1,contextptr); 1813 res->animation_dt=tmp.DOUBLE_val(); 1814 if (std::abs(res->animation_dt<1e-10)) 1815 res->animation_dt=0; 1816 if (res->animation_dt<0){ 1817 res->paused=true; 1818 res->animation_dt=-res->animation_dt; 1819 } 1820 } 1821 if (v.size()>=19) 1822 res->show_mouse_on_object=int(evalf_double(v[18],1,contextptr)._DOUBLE_val); 1823 if (v.size()>=20) 1824 res->display_mode=int(evalf_double(v[19],1,contextptr)._DOUBLE_val); 1825 if (v.size()>=21 && v[20].type==_VECT){ 1826 vecteur & vv=*v[20]._VECTptr; 1827 for (unsigned j=0;j< vv.size() && j<8;++j){ 1828 gen & tmp=vv[j]; 1829 if ( (tmp.type==_VECT && tmp._VECTptr->size()>=25) ){ 1830 vecteur w = *evalf_double(tmp,1,contextptr)._VECTptr; 1831 res->light_x[j]=w[0]._DOUBLE_val; 1832 res->light_y[j]=w[1]._DOUBLE_val; 1833 res->light_z[j]=w[2]._DOUBLE_val; 1834 res->light_w[j]=w[3]._DOUBLE_val; 1835 res->light_diffuse_r[j]=w[4]._DOUBLE_val; 1836 res->light_diffuse_g[j]=w[5]._DOUBLE_val; 1837 res->light_diffuse_b[j]=w[6]._DOUBLE_val; 1838 res->light_diffuse_a[j]=w[7]._DOUBLE_val; 1839 res->light_specular_r[j]=w[8]._DOUBLE_val; 1840 res->light_specular_g[j]=w[9]._DOUBLE_val; 1841 res->light_specular_b[j]=w[10]._DOUBLE_val; 1842 res->light_specular_a[j]=w[11]._DOUBLE_val; 1843 res->light_ambient_r[j]=w[12]._DOUBLE_val; 1844 res->light_ambient_g[j]=w[13]._DOUBLE_val; 1845 res->light_ambient_b[j]=w[14]._DOUBLE_val; 1846 res->light_ambient_a[j]=w[15]._DOUBLE_val; 1847 res->light_spot_x[j]=w[16]._DOUBLE_val; 1848 res->light_spot_y[j]=w[17]._DOUBLE_val; 1849 res->light_spot_z[j]=w[18]._DOUBLE_val; 1850 res->light_spot_w[j]=w[19]._DOUBLE_val; 1851 res->light_spot_exponent[j]=w[20]._DOUBLE_val; 1852 res->light_spot_cutoff[j]=w[21]._DOUBLE_val; 1853 res->light_0[j]=w[22]._DOUBLE_val; 1854 res->light_1[j]=w[23]._DOUBLE_val; 1855 res->light_2[j]=w[24]._DOUBLE_val; 1856 if (tmp._VECTptr->size()>=26) 1857 res->light_on[j]=int(w[25]._DOUBLE_val); 1858 } 1859 } 1860 } 1861 if (v.size()>=23 && v[21].type==_INT_ && v[22].type==_INT_){ 1862 res->ntheta=v[21].val; 1863 res->nphi=v[22].val; 1864 } 1865 if (v.size()>=26 && v[23].type==_INT_ && v[24].type==_INT_&& v[25].type==_INT_){ 1866 res->rotanim_type=v[23].val; 1867 res->rotanim_danim=v[24].val; 1868 res->rotanim_nstep=v[25].val; 1869 } 1870 if (v.size()>=30 && v[26].type==_DOUBLE_ && v[27].type==_DOUBLE_&& v[28].type==_DOUBLE_){ 1871 res->rotanim_rx=v[26]._DOUBLE_val; 1872 res->rotanim_ry=v[27]._DOUBLE_val; 1873 res->rotanim_rz=v[28]._DOUBLE_val; 1874 res->rotanim_tstep=v[29]._DOUBLE_val; 1875 } 1876 if (v.size()>=33 && v[30].type==_INT_ && v[31].type==_INT_&& v[32].type==_INT_){ 1877 res->x_axis_color=v[30].val; 1878 res->y_axis_color=v[31].val; 1879 res->z_axis_color=v[32].val; 1880 } 1881 } 1882 if (Geo2d * geo=dynamic_cast<Geo2d *>(res)){ 1883 geo->hp=geo_find_history_pack(geo); 1884 if (geo_run && geo->hp) 1885 geo->hp->update(); 1886 } 1887 #ifdef HAVE_LIBFLTK_GL 1888 if (Geo3d * geo=dynamic_cast<Geo3d *>(res)){ 1889 geo->hp=geo_find_history_pack(geo); 1890 if (geo_run && geo->hp) 1891 geo->hp->update(); 1892 } 1893 #endif 1894 } 1895 tableur_load(Flv_Table_Gen * & res,const std::string & s,int x,int y,int w,int h)1896 void tableur_load(Flv_Table_Gen * & res,const std::string & s,int x,int y,int w,int h){ 1897 int taille=s.size(),i=0; 1898 for (int j=0;j<4&&i<taille;i++){ 1899 j += (s[i]==' '); 1900 } 1901 string s1=s.substr(0,i); 1902 string s2=s.substr(i,taille-i); 1903 #ifdef HAVE_SSTREAM 1904 istringstream in(s1); 1905 #else 1906 istrstream in(s1.c_str()); 1907 #endif 1908 int is_spreadsheet,matrix_fill_cells,spreadsheet_recompute,matrix_symmetry; 1909 in >> is_spreadsheet >> matrix_fill_cells >> spreadsheet_recompute >> matrix_symmetry ; 1910 giac::context * contextptr=get_context(res); 1911 gen g(s2,contextptr); 1912 if (!ckmatrix(g,true)) 1913 return ; 1914 Tableur_Group * t=dynamic_cast<Tableur_Group *>(res->parent()); 1915 spread_ck(*g._VECTptr); // in place modifications of g 1916 // Find name of tableur in g 1917 matrice m=*g._VECTptr; 1918 if (!res) 1919 res = new Flv_Table_Gen(x,y,w,h,""); 1920 else { 1921 int n,c; 1922 mdims(m,n,c); 1923 res->rows(n); 1924 res->cols(c); 1925 } 1926 if (!m.empty()){ 1927 gen g0=g._VECTptr->front(); 1928 if (g0.type==_VECT && !g0._VECTptr->empty()){ 1929 vecteur m0=*g0._VECTptr; 1930 gen g00= m0.front(); 1931 if (g00.type==_VECT && g00._VECTptr->size()>=3){ 1932 vecteur m00=*g00._VECTptr; 1933 gen g002 = m00.back(); 1934 if (g002.type==_IDNT) 1935 res->name=g002; 1936 if (g002.type==_VECT){ 1937 Graph2d * gr = res->graph; 1938 vecteur & ggv = *g002._VECTptr; 1939 int ggs=ggv.size(); 1940 if (ggs>0 && ggv[0].type==_IDNT) 1941 res->name=ggv[0]; 1942 if (gr && ggs>5){ 1943 if (ggv[1].type==_VECT && ggv[1]._VECTptr->size()>3){ 1944 vecteur & tmpv=*ggv[1]._VECTptr; 1945 gr->window_xmin=evalf_double(tmpv[0],1,contextptr)._DOUBLE_val; 1946 gr->window_xmax=evalf_double(tmpv[1],1,contextptr)._DOUBLE_val; 1947 gr->window_ymin=evalf_double(tmpv[2],1,contextptr)._DOUBLE_val; 1948 gr->window_ymax=evalf_double(tmpv[3],1,contextptr)._DOUBLE_val; 1949 } 1950 if (ggv[2].type==_INT_) 1951 gr->npixels = ggv[2].val; 1952 if (ggv[3].type==_VECT && ggv[3]._VECTptr->size()>1){ 1953 vecteur & tmpv=*ggv[3]._VECTptr; 1954 gr->x_tick=evalf_double(tmpv[0],1,contextptr)._DOUBLE_val; 1955 gr->y_tick=evalf_double(tmpv[1],1,contextptr)._DOUBLE_val; 1956 } 1957 if (ggv[4].type==_INT_) 1958 gr->show_axes = ggv[4].val; 1959 if (ggv[5].type==_INT_) 1960 gr->show_names = ggv[5].val; 1961 } 1962 if (ggs>6 && t){ 1963 if (ggv[6].type==_INT_) 1964 t->disposition=ggv[6].val; 1965 if (ggv[6].type==_VECT){ 1966 vecteur dispv=*ggv[6]._VECTptr; 1967 int dispvs=dispv.size(); 1968 if (dispvs) 1969 t->disposition=dispv[0].val; 1970 if (dispvs>3){ 1971 double d1=evalf_double(dispv[1],1,contextptr)._DOUBLE_val; 1972 double d2=evalf_double(dispv[2],1,contextptr)._DOUBLE_val; 1973 double d3=evalf_double(dispv[3],1,contextptr)._DOUBLE_val; 1974 t->resize2(d1,d2,d3); 1975 } 1976 } 1977 } 1978 if (ggs>7 && t){ // read row_height and col_witdh 1979 if (ggv[7].type==_VECT && ggv[7]._VECTptr->size()==2){ 1980 gen & rowg=ggv[7]._VECTptr->front(); 1981 if (rowg.type==_VECT){ 1982 vecteur & rowv = *rowg._VECTptr; 1983 int rowvs=giacmin(rowv.size(),t->table->rows()); 1984 for (int i=0;i<rowvs ;++i){ 1985 if (rowv[i].type==_INT_) 1986 t->table->row_height(rowv[i].val,i); 1987 } 1988 } 1989 gen & colg=ggv[7]._VECTptr->back(); 1990 if (colg.type==_VECT){ 1991 vecteur & colv = *colg._VECTptr; 1992 int colvs=giacmin(colv.size(),t->table->cols()); 1993 for (int i=0;i<colvs ;++i){ 1994 if (colv[i].type==_INT_) 1995 t->table->col_width(colv[i].val,i); 1996 } 1997 } 1998 } 1999 } 2000 if (ggs>8 && t){ 2001 t->table->init=ggv[8]; 2002 } 2003 } // end g002 of type _VECT 2004 g002=2; 2005 m00.back()=g002; 2006 m0.front()=gen(m00,m0.front().subtype); 2007 m.front()=gen(m0,m.front().subtype); 2008 res->filename = new string(res->name.print(contextptr)+".tab"); 2009 } 2010 } 2011 } 2012 if (res) 2013 res->set_matrix(m,false,false); 2014 res->is_spreadsheet = is_spreadsheet; 2015 res->matrix_fill_cells = matrix_fill_cells; 2016 res->spreadsheet_recompute = spreadsheet_recompute; 2017 res->matrix_symmetry=matrix_symmetry; 2018 res->update_status(); 2019 if (sheet_run) 2020 res->spread_eval_interrupt(); 2021 res->update_spread_graph(); 2022 res->redraw(); 2023 if (t) 2024 t->resize2(); 2025 } 2026 xcas_text_editor_load(Xcas_Text_Editor * & res,const std::string & s,int x,int y,int w,int h)2027 void xcas_text_editor_load(Xcas_Text_Editor * & res,const std::string & s,int x,int y,int w,int h){ 2028 Fl_Text_Buffer * b = new Fl_Text_Buffer; 2029 res = new Xcas_Text_Editor(x,y,w,h,b); 2030 res->callback(History_Pack_cb_eval,0); 2031 res->textcolor(Xcas_input_color); 2032 res->color(Xcas_input_background_color); 2033 res->buffer()->add_modify_callback(style_update, res); 2034 res->buffer()->insert(0,s.c_str()); 2035 res->set_gchanged(); 2036 res->end(); 2037 } 2038 editeur_load(Editeur * & res,const std::string & s,int x,int y,int w,int h)2039 void editeur_load(Editeur * & res,const std::string & s,int x,int y,int w,int h){ 2040 res = new Editeur(x,y,w,h,""); 2041 res->callback(History_Pack_cb_eval,0); 2042 res->editor->buffer()->insert(0,s.c_str()); 2043 } 2044 split_string(const string & s,char sep,string & before,string & after)2045 bool split_string(const string & s,char sep,string & before,string & after){ 2046 int j=s.find('='),ss=s.size(); 2047 if (j>0 && j<ss-1){ 2048 before=s.substr(0,j); 2049 after=s.substr(j+1,ss-j-1); 2050 return true; 2051 } 2052 else 2053 return false; 2054 } 2055 2056 // Read a widget from string s starting at position i 2057 // Return 0 on syntax error or incomplete widget otherwise widget_load(const std::string & s,int L,int & i,GIAC_CONTEXT,int widgetw)2058 Fl_Widget * widget_load(const std::string & s,int L,int & i,GIAC_CONTEXT,int widgetw){ 2059 // Get next line 2060 string line; 2061 int i_orig=i; 2062 next_line(s,L,line,i); 2063 // Check for a fltk comment 2064 if (line.size()>8 && line.substr(0,8)=="// fltk "){ 2065 #ifdef HAVE_SSTREAM 2066 istringstream is(line); 2067 #else 2068 istrstream is(line.c_str()); 2069 #endif 2070 string tmp,attrib; 2071 char ch; 2072 is >> tmp; // get // 2073 is >> tmp; // get fltk 2074 is >> tmp; // get widget type 2075 vector<string> v; 2076 for (;;){ 2077 ch=is.get(); 2078 if (ch=='\n' || !is || is.eof()) 2079 break; 2080 if (ch<=' '){ 2081 if (!attrib.empty()){ 2082 v.push_back(attrib); 2083 attrib=""; 2084 } 2085 } 2086 else 2087 attrib += ch; 2088 } 2089 if (!attrib.empty()) 2090 v.push_back(attrib); 2091 int vs=v.size(); 2092 int x=(vs>0)?atoi(v[0].c_str()):0; 2093 int y=(vs>1)?atoi(v[1].c_str()):0; 2094 int w=(vs>2)?atoi(v[2].c_str()):10; 2095 bool ortho=false; 2096 if (widgetw){ 2097 ortho=(w!=widgetw); 2098 w=widgetw; 2099 } 2100 if (w<10) 2101 w=10; 2102 int h0=(vs>3)?atoi(v[3].c_str()):5; 2103 if (h0<1) 2104 h0=1; 2105 int h=h0; 2106 if (h<5) 2107 h=5; 2108 int lsize=(vs>4)?atoi(v[4].c_str()):14; 2109 Fl_Font police=(vs>5)?Fl_Font(atoi(v[5].c_str())):FL_HELVETICA; 2110 if (police>=fonts_available) 2111 police=FL_HELVETICA; 2112 unsigned pos=tmp.find("History_Fold"),tmps=tmp.size(); 2113 if (pos>0 && pos<tmps){ 2114 next_line_nonl(s,L,line,i); 2115 History_Fold * res= new History_Fold(x,y,w,h); 2116 res->labelsize(lsize); 2117 res->labelfont(police); 2118 res->input->value(line.c_str()); 2119 next_line(s,L,line,i); // should be history_pack... 2120 next_line(s,L,line,i); // should be [\n 2121 res->pack->labelfont(police); 2122 res->pack->eval=xcas::Xcas_eval; 2123 res->pack->_insert=xcas::Xcas_pack_insert; 2124 res->pack->_select=xcas::Xcas_pack_select; 2125 widget_group_load(res->pack,s,L,i,contextptr); 2126 res->fold(); 2127 res->pack->_resize_above=true; 2128 res->redraw(); 2129 return res->pack?res:0; 2130 } 2131 pos = tmp.find("History_Pack"); 2132 if (pos>0 && pos<tmps){ 2133 History_Pack * res= new History_Pack(x,y,w,h); 2134 res->labelsize(lsize); 2135 res->labelfont(police); 2136 next_line(s,L,line,i); // should be [\n 2137 res->eval=xcas::Xcas_eval; 2138 res->_insert=xcas::Xcas_pack_insert; 2139 res->_select=xcas::Xcas_pack_select; 2140 widget_group_load(res,s,L,i,contextptr); 2141 res->redraw(); 2142 // next_line(s,L,line,i); 2143 return res; 2144 } 2145 pos = tmp.find("Tableur_Group"); 2146 if (pos>0 && pos<tmps){ 2147 Tableur_Group * res= new Tableur_Group(x,y,w,h,lsize); 2148 res->labelfont(police); 2149 next_line_nonl(s,L,line,i); 2150 tableur_load(res->table,line,x,y,w,h); 2151 return res; 2152 } 2153 pos=tmp.find("Turtle"); 2154 if (pos>0 && pos<tmps){ 2155 Turtle * tu=new Turtle(x,y,w,h); 2156 tu->turtleptr=&turtle_stack(context0); 2157 next_line(s,L,line,i); // skip [] 2158 return tu; 2159 } 2160 pos=tmp.find("Fl_Scrollbar"); 2161 if (pos>0 && pos<tmps){ 2162 next_line(s,L,line,i); // skip [] 2163 return 0; 2164 } 2165 pos=tmp.find("Mouse_Position"); 2166 if (pos>0 && pos<tmps){ 2167 next_line(s,L,line,i); // skip [] 2168 return new Mouse_Position(x,y,w,h,0); 2169 } 2170 pos=tmp.find("Fl_Button"); 2171 unsigned pos2=tmp.find("Fl_Menu_Bar"); 2172 if ( (pos>0 && pos<tmps) || (pos2>0 && pos2<tmps) ){ 2173 next_line(s,L,line,i); // skip [] 2174 return new Fl_Button(x,y,w,h); 2175 } 2176 pos=tmp.find("Scroll"); 2177 if (pos>0 && pos<tmps){ 2178 next_line(s,L,line,i); 2179 if (line!="[\n") 2180 return 0; 2181 Fl_Scroll * res= new Fl_Scroll(x,y,w,h); 2182 res->labelsize(lsize); 2183 res->labelfont(police); 2184 res->box(FL_FLAT_BOX); 2185 widget_group_load(res,s,L,i,contextptr); 2186 // reorder scrollbars at the end 2187 int n=res->children(); 2188 if (n && dynamic_cast<Fl_Scrollbar *>(res->child(0))) 2189 res->add(res->child(0)); 2190 if (n && dynamic_cast<Fl_Scrollbar *>(res->child(0))) 2191 res->add(res->child(0)); 2192 // skip next scrollbar 2193 next_line(s,L,line,i); // skip Fl_Scrollbar 2194 next_line(s,L,line,i); // skip [] 2195 next_line(s,L,line,i); // skip ] (matching the [ from Fl_Scroll) 2196 return res; 2197 } 2198 pos=tmp.find("Fl_Group"); 2199 if (pos>0 && pos<tmps){ 2200 next_line(s,L,line,i); 2201 if (line!="[\n") 2202 return 0; 2203 int i2=i; 2204 string line2; 2205 next_line(s,L,line2,i2); 2206 Fl_Group * res= new Fl_Group(x,y,w,h); 2207 res->labelsize(lsize); 2208 res->labelfont(police); 2209 widget_group_load(res,s,L,i,contextptr); 2210 tmps=line2.size(); 2211 pos=line2.find("Mouse_Position"); 2212 if (pos>0 && pos <tmps) 2213 res->clear(); // remove this group since it's a param_mouse_group 2214 return res; 2215 } 2216 pos=tmp.find("Fl_Tile"); 2217 if (pos>0 && pos<tmps){ 2218 next_line(s,L,line,i); 2219 if (line!="[\n") 2220 return 0; 2221 int i2=i; 2222 string line2; 2223 next_line(s,L,line2,i2); 2224 Fl_Tile * res= new Fl_Tile(x,y,w,h); 2225 res->labelsize(lsize); 2226 res->labelfont(police); 2227 widget_group_load(res,s,L,i,contextptr); 2228 tmps=line2.size(); 2229 pos=line2.find("Mouse_Position"); 2230 if (pos>0 && pos <tmps) 2231 res->clear(); // remove this group since it's a param_mouse_group 2232 pos=line2.find("Flv_Table_Gen"); 2233 // remove objects not linked inside Flv_Table_Gen 2234 if (pos>0 && pos<tmps){ 2235 int n=res->children(); 2236 Flv_Table_Gen * g = dynamic_cast<Flv_Table_Gen *>(res->child(0)); 2237 if (g){ 2238 for (int i=n-1;i;--i){ 2239 Fl_Widget * w = res->child(i); 2240 if (w==g->_goto || w==g->input || w==g->graph || w==g->graph-> mouse_param_group) 2241 break; 2242 res->remove(w); 2243 delete w; 2244 } 2245 } 2246 } 2247 return res; 2248 } 2249 pos=tmp.find("Figure"); 2250 if (pos>0 && pos<tmps){ 2251 next_line(s,L,line,i); // should be History_Pack 2252 next_line(s,L,line,i); // should be [\n 2253 Figure * fig = new Figure(x,y,w,h,lsize,false); 2254 fig->geo->no_handle=true; 2255 fig->geo->hp->remove_entry(0,false); 2256 fig->geo->hp->eval_below=true; 2257 fig->geo->hp->pretty_output=false; 2258 fig->geo->hp->labelfont(police); 2259 widget_group_load(fig->geo->hp,s,L,i,contextptr); 2260 next_line(s,L,line,i); 2261 pos=line.find("3d");// should be Geo2d or Geo3d 2262 bool dim3= pos>0 && pos<line.size(); 2263 #ifdef HAVE_LIBFLTK_GL 2264 if (dim3){ 2265 Graph2d3d * wid=fig->geo; 2266 Fl_Group * p=wid->parent(); 2267 p->remove(wid); 2268 p->remove(wid->mouse_param_group); 2269 Fl_Group::current(p); 2270 fig->geo=new Geo3d(wid->x(),wid->y(),2*w/3,h-wid->labelsize(),fig->geo->hp); 2271 int pos=p->find(wid); 2272 p->insert(*fig->geo,pos); 2273 delete wid; 2274 } 2275 #endif 2276 graphic_load(fig->geo,s,L,line,i); 2277 // fig->geo->hide(); 2278 // parse further parameters for the figure 2279 string before,after; 2280 double dhp=0.25,dgeo=0.5,dmp=0.25; 2281 for (int i=5;i<vs;++i){ 2282 if (split_string(v[i],'=',before,after)){ 2283 if (before=="landscape" && after=="1"){ 2284 fig->disposition=1; 2285 } 2286 if (before=="history") // percentage for History Pack 2287 dhp=max(0.14,atof(after.c_str())); 2288 if (before=="geo") 2289 dgeo=max(0.28,atof(after.c_str())); 2290 if (before=="mouse_param") 2291 dmp=max(0.14,atof(after.c_str())); 2292 } 2293 } 2294 fig->resize(fig->x(),fig->y(),fig->w(),fig->h(),dhp,dgeo,dmp); 2295 if (ortho) 2296 fig->geo->orthonormalize(); 2297 fig->geo->hp->resize(); 2298 fig->redraw(); 2299 return fig; 2300 } 2301 pos=tmp.find("Logo"); 2302 if (pos>0 && pos<tmps){ 2303 Logo * l = new Logo(x,y,w,h,lsize); 2304 l->hp->remove_entry(0); 2305 next_line(s,L,line,i); // should be History_Pack 2306 next_line(s,L,line,i); // should be [\n 2307 widget_group_load(l->hp,s,L,i,contextptr); 2308 l->hp->resize(); 2309 turtle(contextptr).widget = l->t; 2310 next_line_nonl(s,L,line,i); // should be Editeur 2311 next_line_nonl(s,L,line,i); 2312 // read size 2313 #ifdef HAVE_SSTREAM 2314 istringstream is(line); 2315 #else 2316 istrstream is(line.c_str()); 2317 #endif 2318 int taille; 2319 is >> taille; 2320 l->ed->editor->buffer()->remove(0,l->ed->editor->buffer()->length()); 2321 l->ed->editor->buffer()->insert(0,s.substr(i,taille).c_str()); 2322 // cb_Editeur_Exec_All(l->ed->editor,0); 2323 i += taille ; 2324 return l; 2325 } 2326 pos= tmp.find("Equation"); 2327 if (pos>0 && pos<tmps){ 2328 next_line_nonl(s,L,line,i); 2329 giac::gen g(line,contextptr); 2330 bool output=true; 2331 if (vs>6) 2332 output=atoi(v[6].c_str()); 2333 giac::attributs attr(lsize,output?Xcas_equation_background_color:Xcas_equation_input_background_color,output?Xcas_equation_color:Xcas_equation_input_color); 2334 Equation * res = new Equation(x,y,w,h,"",g,attr); 2335 res->box(FL_FLAT_BOX); 2336 res->labelsize(lsize); 2337 res->labelfont(police); 2338 res->output_equation=output; 2339 if (!output) 2340 res->cb_enter=History_Pack_cb_eval; 2341 return res; 2342 } 2343 pos = tmp.find("Flv_Table_Gen"); 2344 if (pos>0 && pos<tmps){ 2345 Flv_Table_Gen * res=0; 2346 next_line_nonl(s,L,line,i); 2347 tableur_load(res,line,x,y,w,h); 2348 return res; 2349 } 2350 pos = tmp.find("Xcas_Text_Editor"); 2351 if (pos>0 && pos<tmps){ 2352 Xcas_Text_Editor * res=0; 2353 next_line_nonl(s,L,line,i); 2354 // read size 2355 #ifdef HAVE_SSTREAM 2356 istringstream is(line); 2357 #else 2358 istrstream is(line.c_str()); 2359 #endif 2360 int taille; 2361 is >> taille; 2362 string tmp=localize(s.substr(i,taille),language(contextptr)); 2363 xcas_text_editor_load(res,tmp,x,y,w,h); 2364 i += taille ; 2365 return res; 2366 } 2367 pos = tmp.find("Editeur"); 2368 if (pos>0 && pos<tmps){ 2369 Editeur * res=0; 2370 next_line_nonl(s,L,line,i); 2371 // read size 2372 #ifdef HAVE_SSTREAM 2373 istringstream is(line); 2374 #else 2375 istrstream is(line.c_str()); 2376 #endif 2377 int taille; 2378 is >> taille; 2379 string tmp=localize(s.substr(i,taille),language(contextptr)); 2380 editeur_load(res,tmp,x,y,w,h); 2381 i += taille ; 2382 return res; 2383 } 2384 pos= tmp.find("Graph2d"); 2385 if (pos<=0 || pos>=tmps) 2386 pos= tmp.find("Graphic"); 2387 if (pos>0 && pos<tmps){ 2388 Graph2d * res = new Graph2d(x,y,w,h,0); 2389 res->labelfont(police); 2390 graphic_load(res,s,L,line,i); 2391 return res; 2392 } 2393 pos= tmp.find("Geo2d"); 2394 if (pos<=0 || pos>=tmps) 2395 pos= tmp.find("Geometry"); 2396 if (pos>0 && pos<tmps){ 2397 Geo2d * res = new Geo2d(x,y,w,h,0); 2398 res->labelfont(police); 2399 graphic_load(res,s,L,line,i); 2400 return res; 2401 } 2402 #ifdef HAVE_LIBFLTK_GL 2403 pos= tmp.find("Graph3d"); 2404 if (pos>0 && pos<tmps){ 2405 Graph3d * res = new Graph3d(x,y,w,h,"",0); 2406 res->labelfont(police); 2407 graphic_load(res,s,L,line,i); 2408 return res; 2409 } 2410 pos= tmp.find("Geo3d"); 2411 if (pos>0 && pos<tmps){ 2412 Geo3d * res = new Geo3d(x,y,w,h,0); 2413 res->labelfont(police); 2414 graphic_load(res,s,L,line,i); 2415 return res; 2416 } 2417 #endif 2418 pos=tmp.find("Multiline_Input_tab"); 2419 if (pos>0 && pos<tmps){ 2420 Multiline_Input_tab * res = new Multiline_Input_tab(x,y,w,h); 2421 res->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 2422 res->callback(xcas::History_Pack_cb_eval,0); 2423 res->textcolor(Xcas_input_color); 2424 res->labelfont(police); 2425 res->textfont(police); 2426 next_line_nonl(s,L,line,i); 2427 line=localize(line,language(contextptr)); 2428 res->value(line.c_str()); 2429 res->set_changed(); 2430 return res; 2431 } 2432 pos=tmp.find("Input"); 2433 if (pos>0 && pos<tmps){ 2434 Comment_Multiline_Input * res = new Comment_Multiline_Input(x,y,w,h); 2435 next_line_nonl(s,L,line,i); 2436 res->value(line.c_str()); 2437 res->labelfont(police); 2438 res->textfont(police); 2439 res->callback((Fl_Callback*)Comment_cb_eval); 2440 res->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 2441 res->set_changed(); 2442 res->textcolor(Xcas_comment_color); 2443 return res; 2444 } 2445 pos=tmp.find("Gen_Output"); 2446 if (pos>0 && pos<tmps){ 2447 Gen_Output * res = new Gen_Output(x,y,w,h); 2448 res->textcolor(FL_BLACK); 2449 res->labelfont(police); 2450 res->textfont(police); 2451 next_line_nonl(s,L,line,i); 2452 if (line.size()>=65536) 2453 res->value("Object_too_large"); 2454 else 2455 res->value(line.c_str()); 2456 return res; 2457 } 2458 pos=tmp.find("Output"); 2459 if (pos>0 && pos<tmps){ 2460 Log_Output * res = new Log_Output(x,y,w,h0); 2461 res->textcolor(Xcas_log_color); 2462 res->labelfont(police); 2463 res->textfont(police); 2464 next_line_nonl(s,L,line,i); 2465 res->value(line.c_str()); 2466 return res; 2467 } 2468 pos=tmp.find("Gen_Value_Slider"); 2469 if (pos>0 && pos<tmps){ 2470 next_line_nonl(s,L,line,i); 2471 #ifdef HAVE_SSTREAM 2472 istringstream is(line); 2473 #else 2474 istrstream is(line.c_str()); 2475 #endif 2476 double m,M,val,step=0.1; 2477 int pos; 2478 string name; 2479 // is >> name ; // this is not the name but //, name is read below 2480 try { 2481 is >> pos >> m >> M >> val >> name >> step; 2482 } catch(std::runtime_error & e) { 2483 } 2484 Gen_Value_Slider * res=new Gen_Value_Slider(x,y,w-3*lsize,h,pos,m,M,(M-m)/100.,name); 2485 res->value(val); 2486 res->step(step); 2487 res->label(name.c_str()); 2488 res->labelfont(police); 2489 res->labelsize(lsize); 2490 return res; 2491 } 2492 } // end if line begins with // fltk 2493 else 2494 i=i_orig; // restore original position 2495 return 0; 2496 } 2497 Xcas_pack_select(const xcas::History_Pack * pack,int sel_begin,int sel_end)2498 const char * Xcas_pack_select(const xcas::History_Pack * pack,int sel_begin,int sel_end) { 2499 int n=pack->children(); 2500 static std::string s; 2501 s=""; 2502 if (n){ 2503 int s1=sel_begin,s2=sel_end; 2504 if (s1>s2){ s1=sel_end; s2=sel_begin; } 2505 if (s2>=n) s2=n-1; 2506 if (s1<=0) s1=0; 2507 for (int i=s1;i<=s2;i++){ 2508 s += widget_sprint(pack->child(i)); 2509 if (i<s2) 2510 s += ",\n"; 2511 } 2512 } 2513 return s.c_str(); 2514 } 2515 Xcas_pack_insert(xcas::History_Pack * pack,const char * chaine,int length,int before_position)2516 int Xcas_pack_insert(xcas::History_Pack * pack,const char * chaine,int length,int before_position) { 2517 if (!pack) 2518 return 0; 2519 Fl_Group::current(pack); 2520 context * contextptr = pack->contextptr; 2521 int n=pack->children(); 2522 if (!n) 2523 before_position=n; 2524 else 2525 if (before_position<0 || before_position>=n) before_position=n-1; 2526 int l0=strlen(chaine); 2527 if (length>l0) 2528 l0=length; 2529 string s; 2530 for (int i0=0;i0<l0;i0++){ 2531 // if (chaine[i0]!=13) 2532 s += chaine[i0]; 2533 } 2534 // cerr << s << '\n'; 2535 int L=s.size(),i=0; 2536 // Check for an HTML link 2537 if (L>8 && (s.substr(0,6)=="http:/" || s.substr(0,7)=="https:/" || s.substr(0,6)=="file:/") ){ 2538 // find # position, then create normal line for +, slider for * 2539 int pos=s.find('#'); 2540 if (pos>0 && pos<L){ 2541 int police=pack->labelfont(),lsize=pack->labelsize(),y=before_position; 2542 bool finished=false; 2543 while (!finished){ 2544 int nextpos=s.find('&',pos+1); 2545 if (nextpos > L){ 2546 nextpos=L; 2547 finished=true; 2548 } 2549 if (nextpos<pos+2) 2550 break; 2551 string txt=s.substr(pos+2,nextpos-pos-2); 2552 txt=html_filter(txt); 2553 if (s[pos+1]=='*'){ 2554 gen g(txt,contextptr); 2555 if (g.type==_VECT && g._VECTptr->size()>=5){ 2556 txt="assume("+g[0].print(contextptr)+"=["+g[1].print(contextptr)+","+g[2].print(contextptr)+","+g[3].print(contextptr)+","+g[4].print(contextptr)+"])"; 2557 } 2558 } 2559 else { 2560 if (s[pos+1]!='+'){ 2561 pos=nextpos; 2562 continue; 2563 } 2564 if (s.size()>pos+3 && s[pos+2]=='/' && s[pos+3]=='/'){ 2565 txt=replace(txt,'\n',char(163)); // should count \n and ajust size 2566 txt="// fltk 7Fl_Tile 14 68 845 25 18 0\n[\n// fltk N4xcas23Comment_Multiline_InputE 14 68 845 24 18 0\n"+txt.substr(2,txt.size()-2)+"\n,\n// fltk N4xcas10Log_OutputE 14 93 845 1 18 0\n\n]"; 2567 } 2568 else { 2569 int pos=txt.find('\n'); 2570 if (pos>0 && pos<txt.size()){ 2571 txt="// fltk 7Fl_Tile 14 68 845 254 18 0\n[\n// fltk N4xcas16Xcas_Text_EditorE 14 68 845 253 18 0\n"+print_INT_(txt.size())+" ,\n"+txt+",\n// fltk N4xcas10Log_OutputE 14 321 845 1 18 0\n\n]"; 2572 } 2573 } 2574 } 2575 Xcas_pack_insert(pack,txt.c_str(),txt.size(),y); 2576 ++y; 2577 pos=nextpos; 2578 } 2579 pack->redraw(); 2580 // next_line(s,L,line,i); 2581 return 1; 2582 } 2583 } 2584 2585 Fl_Widget * o; 2586 for (;i<L;++before_position){ 2587 if (i+7<L && s.substr(i,7)=="// fltk"){ 2588 if ( (o=widget_load(s,L,i,contextptr,pack->w()-pack->_printlevel_w) )){ 2589 if (Fl_Group * g=dynamic_cast<Fl_Group *>(o)) 2590 pack->add_entry(before_position,g); 2591 else 2592 pack->add_entry(before_position,o); 2593 if (i<L-1 && s[i]==',' && s[i+1]=='\n') 2594 i += 2; 2595 continue; 2596 } 2597 } // end if (i+7<L) 2598 if (i+11<L && s.substr(i,10)=="// context"){ 2599 i+=11; 2600 int nchar=0; 2601 while (i<L && s[i]>='0' && s[i]<='9'){ 2602 nchar *= 10; 2603 nchar += s[i]-'0'; 2604 ++i; 2605 } 2606 if (nchar<=L-i-1){ 2607 string tmps=s.substr(i+1,nchar); 2608 gen replace; 2609 if (!recovery_mode) 2610 unarchive_session_string(tmps,-1,replace,contextptr); 2611 i+=nchar+2; 2612 continue; 2613 } 2614 } 2615 // Now add line in a multiline_input_tab entry 2616 string line; 2617 next_line_nonl(s,L,line,i); 2618 int ls=line.size(); 2619 if (ls>2 && line[ls-1]==';' && line[ls-2]==';') 2620 line = line.substr(0,ls-1); 2621 if (ls>2 && line[0]=='/' && line[1]=='/') 2622 line = "/*"+line.substr(1,ls-1)+"*/"; 2623 if (ls>4 && line[0]=='/' && line[1]=='*' && line[ls-1]=='/' && line[ls-2]=='*'){ 2624 line=line.substr(2,ls-4); 2625 Comment_Multiline_Input * w = dynamic_cast<Comment_Multiline_Input *>(new_comment_input(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+10)); 2626 if (w){ 2627 w->value(line.c_str()); 2628 w->set_changed(); 2629 pack->add_entry(before_position,w); 2630 } 2631 } 2632 else { 2633 #if 0 2634 Multiline_Input_tab * w = dynamic_cast<Multiline_Input_tab *>(new_question_multiline_input(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+10)); 2635 #else 2636 // requires call to update() to be commented in History_Pack::handle(int event) 2637 // for FL_PASTE event 2638 Xcas_Text_Editor * w = dynamic_cast<Xcas_Text_Editor *>(new_question_editor(max(pack->w()-pack->_printlevel_w,1),pack->labelsize()+14)); 2639 #endif 2640 if (w){ 2641 w->value(line.c_str()); 2642 w->set_changed(); 2643 pack->add_entry(before_position,(Fl_Widget*) w); 2644 w->resize_nl_before(1); 2645 } 2646 } 2647 } // end for 2648 change_group_fontsize(pack,pack->labelsize()); 2649 set_context(pack,contextptr); 2650 parent_redraw(pack); 2651 return i; 2652 } 2653 in_Xcas_fltk_interactive(const giac::gen & g,const giac::context * contextptr)2654 giac::gen in_Xcas_fltk_interactive(const giac::gen & g,const giac::context * contextptr){ 2655 if (is_zero(g,contextptr)) 2656 return Xcas_DispG?Xcas_DispG->plot_instructions:undef; 2657 if (g.type==_SYMB){ 2658 unary_function_ptr & u=g._SYMBptr->sommet; 2659 gen f=g._SYMBptr->feuille; 2660 if (u==at_pnt){ 2661 // Xcas_DispG_Window->show(); 2662 // Xcas_Main_Window->show(); 2663 redraw_turtle=1; 2664 if (Xcas_DispG && f.subtype!=_LOGO__VECT) 2665 Xcas_DispG->add(g); 2666 return 1; 2667 } 2668 if (u==at_equal){ 2669 if (Xcas_DispG) Xcas_DispG->add(g); 2670 return 1; 2671 } 2672 if (u==at_erase){ 2673 // Xcas_DispG_Window->show(); 2674 // Xcas_Main_Window->show(); 2675 if (Xcas_DispG) Xcas_DispG->clear(); 2676 return 1; 2677 } 2678 if (u==at_Pictsize){ 2679 if (Xcas_DispG){ 2680 // plot_instructionsw=Xcas_DispG->w(); 2681 // plot_instructionsh=Xcas_DispG->h(); 2682 gnuplot_xmax=Xcas_DispG->window_xmax; 2683 gnuplot_xmin=Xcas_DispG->window_xmin; 2684 gnuplot_ymax=Xcas_DispG->window_ymax; 2685 gnuplot_ymin=Xcas_DispG->window_ymin; 2686 return makevecteur(Xcas_DispG->w(),Xcas_DispG->h()); 2687 } 2688 return makevecteur(0,0); 2689 } 2690 if (u==at_RclPic && f.type==_VECT){ 2691 // Xcas_DispG_Window->show(); 2692 // Xcas_Main_Window->show(); 2693 if (Xcas_DispG) Xcas_DispG->add(*f._VECTptr); 2694 return 1; 2695 } 2696 if (u==at_RplcPic && f.type==_VECT){ 2697 // Xcas_DispG_Window->show(); 2698 // Xcas_Main_Window->show(); 2699 if (Xcas_DispG){ 2700 Xcas_DispG->clear(); 2701 Xcas_DispG->add(*f._VECTptr); 2702 } 2703 return 1; 2704 } 2705 if (u==at_Pause){ 2706 if (f.type==_STRNG) 2707 xcas_paused=*f._STRNGptr; 2708 else 2709 xcas_paused="Paused"; 2710 for (int i=0;i<360000;++i){ 2711 if (xcas_paused.empty()) 2712 break; 2713 usleep(10000); 2714 } 2715 return 1; 2716 } 2717 if (u==at_ClrIO){ 2718 if (Xcas_PrintG) 2719 Xcas_PrintG->set_data(string2gen("",false)); 2720 * logptr(contextptr) << ""; 2721 return 1; 2722 } 2723 if (u==at_DispG){ 2724 if (Xcas_DispG_Window) show_xcas_dispg=2; 2725 #ifndef WIN32 2726 if (Xcas_Main_Window) Xcas_Main_Window->show(); 2727 #endif 2728 return 1; 2729 } 2730 if (u==at_DispHome){ 2731 if (Xcas_DispG_Window) show_xcas_dispg=1; 2732 return 1; 2733 } 2734 /* 2735 if (u==at_Output){ 2736 user_screen_io_x=f[0].val; 2737 user_screen_io_y=f[1].val; 2738 f=f[2]; 2739 } 2740 if (u==at_Output || u==at_print){ 2741 gen tmp=Eqw_compute_size(f,Eqw_history->attr,Eqw_history->w()); 2742 eqwdata v=Eqw_total_size(tmp); 2743 if (Eqw_history->data.type!=_VECT && Eqw_history->data.type!=_EQW){ 2744 Eqw_history->data=tmp; 2745 user_screen_io_y=v.y; // top of next writing 2746 } 2747 else { 2748 eqwdata w=Eqw_total_size(Eqw_history->data); 2749 int h=w.dy,y=w.y; 2750 tmp=Eqw_translate(tmp,user_screen_io_x,user_screen_io_y-v.y-v.dy); 2751 v=Eqw_total_size(tmp); 2752 Eqw_vertical_adjust(v.dy,v.y,h,y); 2753 user_screen_io_y = y; 2754 user_screen_io_x = 0; 2755 vecteur res; 2756 if (Eqw_history->data.type==_EQW) 2757 res.push_back(Eqw_history->data); 2758 else 2759 res=vecteur(Eqw_history->data._VECTptr->begin(),Eqw_history->data._VECTptr->end()-1); 2760 res.push_back(tmp); 2761 res.push_back(eqwdata(max(w.dx,v.dx),h,0,y,Eqw_history->attr,at_makevector,0)); 2762 gen gg=gen(res,_EQW__VECT); 2763 Eqw_history->data=gg; 2764 } 2765 Eqw_history->setscroll(); 2766 return f; 2767 } 2768 */ 2769 } 2770 return 1; 2771 } 2772 Xcas_fltk_interactive(const giac::gen & g,GIAC_CONTEXT)2773 giac::gen Xcas_fltk_interactive(const giac::gen & g,GIAC_CONTEXT){ 2774 #ifdef HAVE_LIBPTHREAD 2775 // cerr << "xcas lock" << g << '\n'; 2776 pthread_mutex_lock(&interactive_mutex); 2777 #endif 2778 if (block_signal){ 2779 cerr << "blocked " << g << '\n'; 2780 #ifdef HAVE_LIBPTHREAD 2781 pthread_mutex_unlock(&interactive_mutex); 2782 #endif 2783 return zero; 2784 } 2785 gen res=in_Xcas_fltk_interactive(g,contextptr); 2786 // FIXME change interactive for context, like input 2787 #ifdef HAVE_LIBPTHREAD 2788 // cerr << "xcas unlock" << '\n'; 2789 pthread_mutex_unlock(&interactive_mutex); 2790 #endif 2791 return res; 2792 } 2793 in_Xcas_fltk_getKey(const giac::gen & g,giac::context * contextptr)2794 giac::gen in_Xcas_fltk_getKey(const giac::gen & g,giac::context * contextptr){ 2795 int ch=Fl::event_key(); 2796 if (Fl::event_key(ch)) 2797 return ch; 2798 else 2799 return -ch; 2800 } 2801 Xcas_fltk_getKey(const giac::gen & g,GIAC_CONTEXT)2802 giac::gen Xcas_fltk_getKey(const giac::gen & g,GIAC_CONTEXT){ 2803 if (block_signal){ 2804 return zero; 2805 } 2806 gen res; 2807 if (is_minus_one(g)){ 2808 Fl::lock(); 2809 res=in_Xcas_fltk_getKey(g,0); 2810 Fl::unlock(); 2811 } 2812 else 2813 res=Xcas_fltk_input(makevecteur(at_getKey,g),contextptr); 2814 // FIXME change interactive for context, like input 2815 if (is_inf(res)) 2816 setsizeerr(); 2817 return res; 2818 } 2819 2820 vector <Fl_Browser *> vbrowser; 2821 vector<int> gbrowser; cb_plotfltk_browser(Fl_Browser * b,void *)2822 void cb_plotfltk_browser(Fl_Browser * b,void *){ 2823 if (b->value()){ 2824 vector <Fl_Browser *>::const_iterator it=vbrowser.begin(),itend=vbrowser.end(); 2825 for (;it!=itend;++it){ 2826 if (*it==b) 2827 break; 2828 } 2829 if (it!=itend) 2830 gbrowser[it-vbrowser.begin()]=b->value(); 2831 } 2832 } 2833 nlines(const string & s)2834 static int nlines(const string & s){ 2835 int res=1; 2836 int ns=s.size()-1; 2837 for (int i=0;i<ns;++i){ 2838 if (s[i]=='\n') ++res; 2839 } 2840 return res; 2841 } 2842 2843 // Given a vector v describing an input form, return makeform(const vecteur & v0,GIAC_CONTEXT)2844 gen makeform(const vecteur & v0,GIAC_CONTEXT) { 2845 vecteur v; 2846 aplatir(v0,v); 2847 if (v.size()==1 && v.front().is_symb_of_sommet(at_output)){ 2848 fl_message("%s",eval(v.front()._SYMBptr->feuille,contextptr).print(contextptr).c_str()); 2849 return plus_one; 2850 } 2851 if (v.size()==1 && v.front().type==_STRNG){ 2852 v.push_back(identificateur("_input_")); 2853 // CERR << v << '\n'; 2854 } 2855 if (!v.empty() && v.front()==at_getKey){ 2856 Fl_Widget * foc=Fl::focus(); 2857 static Fl_Window * getkeywin=0; 2858 static Fl_Button * getkeybut = 0; 2859 static Fl_Input * getkeyin = 0; 2860 static Fl_Multiline_Output * getkeyout = 0; 2861 if (!getkeywin){ 2862 Fl_Group::current(0); 2863 getkeywin=new Fl_Window(50,50,200,200); 2864 getkeywin->label(gettext("Press a key")); 2865 getkeyout= new Fl_Multiline_Output(2,24,196,170); 2866 getkeybut=new Fl_Button(2,2,96,20); 2867 getkeybut->label(gettext("Cancel")); 2868 getkeybut->shortcut("^["); 2869 getkeyin = new Fl_Input(102,2,96,20); 2870 getkeyin->when(FL_WHEN_CHANGED); 2871 getkeywin->end(); 2872 getkeywin->resizable(getkeywin); 2873 } 2874 string msg(gettext("Press a key\n")); 2875 int vs=v.size(); 2876 for (int i=1;i<vs;++i){ 2877 if (v[i].type==_STRNG) 2878 msg += *v[i]._STRNGptr; 2879 else 2880 msg += v[i].print(contextptr); 2881 if (i==vs-1) 2882 break; 2883 msg += '\n'; 2884 } 2885 getkeyout->value(msg.c_str()); 2886 getkeyin->value(""); 2887 getkeywin->show(); 2888 getkeywin->set_modal(); 2889 Fl::focus(getkeyin); 2890 if (Xcas_Main_Window){ 2891 Xcas_Main_Window->redraw(); 2892 } 2893 Fl::flush(); 2894 gen res=undef; 2895 for (;;){ 2896 Fl_Widget *o = Fl::readqueue(); 2897 if (!o) Fl::wait(); 2898 if (o==getkeybut) 2899 res=unsigned_inf; 2900 if (o==getkeybut || o==getkeywin){ 2901 break; 2902 } 2903 if (o==getkeyin){ 2904 int l=strlen(getkeyin->value()); 2905 if (l){ 2906 res=getkeyin->value()[l-1]; 2907 break; 2908 } 2909 } 2910 } 2911 getkeywin->hide(); 2912 Fl::focus(foc); 2913 return res; 2914 } 2915 int initw,inith; 2916 if (Xcas_input_focus && Xcas_input_focus->window()){ 2917 initw=(Xcas_input_focus->window()->w()*3)/4; 2918 inith=(Xcas_input_focus->window()->h()*3)/4; 2919 } 2920 else { 2921 initw = 240; 2922 inith = 320; 2923 } 2924 Fl_Group::current(0); 2925 static Fl_Window * Plotfltk_w = new Fl_Window(initw,inith); 2926 int r; 2927 vecteur res; 2928 Fl_Window * w = Plotfltk_w ; 2929 w->end(); 2930 int taillew=w->w(),tailleh=w->h(); 2931 if (taillew<100 || tailleh<100){ 2932 if (taillew<100) 2933 taillew=100; 2934 if (tailleh<100) 2935 tailleh=100; 2936 w->resize(w->x(),w->y(),taillew,tailleh); 2937 } 2938 Fl_Group::current(w); 2939 static Fl_Button * button0 = new Fl_Button(2+(2*taillew)/3, 0, taillew/4, 20); 2940 button0->shortcut("^["); 2941 button0->resize(2+(2*taillew)/3, 0, taillew/4, 20); 2942 button0->label(gettext("Cancel")); 2943 static Fl_Button * button1 = new Fl_Return_Button(2+taillew/3, 0, taillew/4, 20); 2944 button1->label(gettext("OK")); 2945 button1->resize(2+taillew/3, 0, taillew/4, 20); 2946 static Fl_Button * button2 = new Fl_Button(2, 0, taillew/4, 20); 2947 button2->label(gettext("STOP")); 2948 button2->resize(2, 0, taillew/4, 20); 2949 // Now parse v 2950 int current_y=22; 2951 vector<Fl_Input *> vinput; 2952 vector<Fl_Output *> voutput; 2953 vector<string *> labels; 2954 /* 2955 vector <Fl_Menu_Button *> vpopup; 2956 vector < vector<Fl_Menu_Item * > > vpopupitem; 2957 */ 2958 const_iterateur it=v.begin(),itend=v.end(); 2959 bool focused=false; 2960 for (;it!=itend;++it){ 2961 if (it->type==_IDNT || it->is_symb_of_sommet(at_of) || it->is_symb_of_sommet(at_at)){ 2962 Fl_Input * o; 2963 string * l=new string (it->print(contextptr)); 2964 labels.push_back(l); 2965 int taille=4+int(fl_width(l->c_str())); 2966 if (taille>taillew/2) 2967 taille=taillew/2; 2968 int yadd=6+nlines(*l)*14; 2969 o=new Fl_Input(taille,current_y,taillew-taille,yadd,l->c_str()); 2970 vinput.push_back(o); 2971 if (!focused){ 2972 focused=true; 2973 Fl::focus(o); 2974 } 2975 current_y += yadd; 2976 continue; 2977 } 2978 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)) ){ 2979 Fl_Input * o; 2980 string * l=new string (*it->_STRNGptr); 2981 labels.push_back(l); 2982 int yadd=6+nlines(*l)*14; 2983 int taille=4+int(fl_width(l->c_str())); 2984 if (taille>taillew/2) 2985 taille=taillew/2; 2986 o=new Fl_Input(taille,current_y,taillew-taille,yadd,l->c_str()); 2987 ++it; 2988 vinput.push_back(o); 2989 if (!focused){ 2990 focused=true; 2991 Fl::focus(o); 2992 } 2993 current_y += yadd; 2994 continue; 2995 } 2996 if (it->type!=_SYMB) 2997 continue; 2998 unary_function_ptr & u=it->_SYMBptr->sommet; 2999 gen g=it->_SYMBptr->feuille; 3000 if ( (u==at_click) || (u==at_Request) ) { 3001 vecteur vg(gen2vecteur(g)); 3002 if (vg.empty()) 3003 continue; 3004 Fl_Input * o; 3005 gen tmps=vg[0].eval(eval_level(contextptr),contextptr); 3006 string * l=new string (tmps.type==_STRNG?*tmps._STRNGptr:tmps.print(contextptr)); 3007 labels.push_back(l); 3008 int taille=4+int(fl_width(l->c_str())); 3009 if (taille>taillew/2) 3010 taille=taillew/2; 3011 o=new Fl_Input(taille,current_y,taillew-taille,20,l->c_str()); 3012 if (vg.size()>1&& u!=at_Request) 3013 o->value(vg[1].eval(eval_level(contextptr),contextptr).print(contextptr).c_str()); 3014 vinput.push_back(o); 3015 if (!focused){ 3016 focused=true; 3017 Fl::focus(o); 3018 } 3019 current_y +=20; 3020 continue; 3021 } 3022 if ( (u==at_output) || (u==at_Text) || (u==at_Title) ){ 3023 g=g.eval(eval_level(contextptr),contextptr); 3024 Fl_Output * o; 3025 if (u==at_Title){ 3026 string * l=new string (g.type==_STRNG?*g._STRNGptr:g.print(contextptr)); 3027 labels.push_back(l); 3028 o=new Fl_Output(taillew/2-40,current_y,0,20,l->c_str()); 3029 o->value(""); 3030 } 3031 else { 3032 o=new Fl_Output(40,current_y,taillew-60,20,""); 3033 o->value((g.type==_STRNG?*g._STRNGptr:g.print(contextptr)).c_str()); 3034 } 3035 voutput.push_back(o); 3036 current_y += 20; 3037 continue; 3038 } 3039 /* 3040 if (u==at_popup){ 3041 vecteur vg(gen2vecteur(g)); 3042 if (vg.empty()) 3043 continue; 3044 Fl_Menu_Button * o=new Fl_Menu_Button(10,current_y,100,20,vg[0].print(contextptr).c_str()); 3045 vpopup.push_back(o); 3046 vector<Fl_Menu_Item *> tmpmenu; 3047 const iterateur tmpit=vg.begin()+1,tmpend=vg.end(); 3048 int y=current_y; 3049 for (;tmpit!=tmpend;++tmpit){ 3050 Fl_Menu_Item * o=new Fl_Menu_Item(10,y,100,15,tmpit->print(contextptr).c_str()); 3051 tmpmenu.push_back(o); 3052 y +=15; 3053 } 3054 vpopupitem.push_back(tmpmenu); 3055 o->end(); 3056 current_y +=20; 3057 continue; 3058 } 3059 */ 3060 if ( (u==at_choosebox) || (u==at_DropDown) || (u==at_Popup) ){ 3061 vecteur vg(gen2vecteur(g)); 3062 if (vg.size()==2) 3063 vg.insert(vg.begin(),string2gen("",false)); 3064 if (vg.size()!=3) 3065 continue; 3066 int hs=64; 3067 if (vg[1].type==_VECT) 3068 hs=vg[1]._VECTptr->size()*16+5; 3069 hs=min(hs,160); 3070 Fl_Browser * o =new Fl_Browser(50, current_y+16, 180, hs); 3071 current_y += hs+16; 3072 o->type(2); 3073 string * l=new string (vg[0].type==_STRNG?*vg[0]._STRNGptr:vg[0].print(contextptr)); 3074 labels.push_back(l); 3075 o->label(l->c_str()); 3076 o->align(FL_ALIGN_TOP); 3077 o->callback((Fl_Callback*)cb_plotfltk_browser); 3078 vbrowser.push_back(o); 3079 gbrowser.push_back(0); 3080 vecteur wg(gen2vecteur(vg[1])); 3081 const_iterateur jt=wg.begin(),jtend=wg.end(); 3082 for (;jt!=jtend;++jt){ 3083 o->add(jt->print(contextptr).c_str()); 3084 } 3085 gen g=protecteval(vg[2],eval_level(contextptr),contextptr); 3086 if ( (g.type==_INT_) && (g.val>0) && (g.val<=int(wg.size())) ) 3087 o->value(g.val); 3088 continue; 3089 } 3090 } 3091 Xcas_Main_Window->redraw(); 3092 w->Fl_Widget::resize(w->x(),w->y(),taillew,current_y); 3093 w->resizable(w); 3094 w->set_modal(); 3095 w->show(); 3096 for (;;) { 3097 Fl_Widget *o = Fl::readqueue(); 3098 if (!o) Fl::wait(); 3099 else { 3100 if (o == button0) {r = 0; break;} 3101 if (o == button1) {r = 1; break;} 3102 if (o == button2) {r = 2; break;} 3103 if (o == w) { r=0; break; } 3104 } 3105 } 3106 w->hide(); 3107 bool request=false; 3108 gen gtmp("ok",contextptr); 3109 res.push_back(symb_sto(r,gtmp)); 3110 // store results 3111 it=v.begin(); 3112 int ibrowser=0; 3113 vector<Fl_Input *>::const_iterator vinput_it=vinput.begin(); 3114 gen resadd,tmp; 3115 for (;it!=itend;++it){ 3116 if (it->type==_IDNT || it->is_symb_of_sommet(at_at) || it->is_symb_of_sommet(at_of)){ 3117 if (it+1!=itend && *(it+1)==1) 3118 resadd=string2gen((*vinput_it)->value(),false); 3119 else { 3120 try { 3121 resadd=gen((*vinput_it)->value(),contextptr); 3122 } 3123 catch (std::runtime_error & e){ 3124 resadd=string2gen(e.what(),false); 3125 } 3126 } 3127 tmp=*it; 3128 res.push_back(symb_sto(resadd,tmp)); 3129 ++vinput_it; 3130 } 3131 if (it->type!=_SYMB) 3132 continue; 3133 unary_function_ptr & u=it->_SYMBptr->sommet; 3134 gen & g=it->_SYMBptr->feuille; 3135 if ( (u==at_click) || (u==at_Request) ){ 3136 vecteur vg(gen2vecteur(g)); 3137 try { 3138 if (vg.size()>3|| u==at_Request){ 3139 request=true; 3140 resadd=string2gen((*vinput_it)->value(),false); 3141 } 3142 else 3143 resadd=gen((*vinput_it)->value(),contextptr); 3144 } 3145 catch (std::runtime_error & e){ 3146 resadd=string2gen(e.what(),false); 3147 } 3148 if (u==at_Request && vg.size()>1){ 3149 res.push_back(symb_sto(resadd,vg[1])); 3150 request=true; 3151 } 3152 else { 3153 if (vg.size()>2) 3154 res.push_back(symb_sto(resadd,vg[2])); 3155 } 3156 ++vinput_it; 3157 continue; 3158 } 3159 if ( (u==at_choosebox) || (u==at_DropDown) || (u==at_Popup) ){ 3160 vecteur vg(gen2vecteur(g)); 3161 if (vg.size()==2) 3162 vg.insert(vg.begin(),zero); 3163 if (vg.size()!=3) 3164 continue; 3165 res.push_back(symb_sto(gbrowser[ibrowser],vg[2])); 3166 ++ibrowser; 3167 continue; 3168 } 3169 } 3170 // delete widgets 3171 { 3172 vector<Fl_Input *>::const_iterator jt=vinput.begin(),jtend=vinput.end(); 3173 for (;jt!=jtend;++jt){ 3174 w->Fl_Group::remove(*jt); 3175 delete *jt; 3176 } 3177 vinput.clear(); 3178 } 3179 { 3180 vector<Fl_Output *>::const_iterator jt=voutput.begin(),jtend=voutput.end(); 3181 for (;jt!=jtend;++jt){ 3182 w->Fl_Group::remove(*jt); 3183 delete *jt; 3184 } 3185 voutput.clear(); 3186 } 3187 { 3188 vector<Fl_Browser *>::const_iterator jt=vbrowser.begin(),jtend=vbrowser.end(); 3189 for (;jt!=jtend;++jt){ 3190 w->Fl_Group::remove(*jt); 3191 delete *jt; 3192 } 3193 vbrowser.clear(); 3194 } 3195 { 3196 vector<string *>::const_iterator jt=labels.begin(),jtend=labels.end(); 3197 for (;jt!=jtend;++jt){ 3198 delete *jt; 3199 } 3200 labels.clear(); 3201 } 3202 /* 3203 { 3204 vector<Fl_Menu_Button *>::const_iterator jt=vpopup.begin(),jtend=vpopup.end(); 3205 for (;jt!=jtend;++jt){ 3206 w->Fl_Group::remove(*jt); 3207 delete *jt; 3208 } 3209 } 3210 { 3211 vector< vector<Fl_Menu_Item *> >::const_iterator jt=vpopupitem.begin(),jtend=vpopupitem.end(); 3212 for (;jt!=jtend;++jt){ 3213 vector<Fl_Menu_Item *>::const_iterator jtt=jt->begin(),jttend=jt->end(); 3214 for (;jtt!=jttend;+jtt) 3215 w->Fl_Group::remove(*jt); 3216 delete *jtt; 3217 } 3218 } 3219 */ 3220 // delete button1; 3221 // delete button0; 3222 // delete w; 3223 if (r==2) 3224 return 0; 3225 if (request) 3226 return res; 3227 if (r==0) 3228 return undef; 3229 else 3230 return res; 3231 } 3232 3233 // FIXME: forms should work under win32!! 3234 #if defined WIN32 || defined __APPLE__ Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr)3235 giac::gen Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr){ 3236 Fl::lock(); 3237 if (Xcas_DispG) Xcas_DispG->waiting_click_value=arg; 3238 Fl::unlock(); 3239 thread_eval_status(3,contextptr); 3240 for (;;){ 3241 if (thread_eval_status(contextptr)==1) 3242 break; 3243 usleep(10000); 3244 } 3245 Fl::lock(); 3246 gen res=Xcas_DispG?Xcas_DispG->waiting_click_value:undef; 3247 Fl::unlock(); 3248 return res.eval(eval_level(contextptr),contextptr); 3249 // return res; 3250 } 3251 Xcas_fltk_inputform(const gen & args,const giac::context * contextptr)3252 gen Xcas_fltk_inputform(const gen & args,const giac::context * contextptr){ 3253 return Xcas_fltk_input(args,contextptr); 3254 } 3255 3256 #else 3257 Xcas_fltk_inputform(const gen & args,const giac::context * contextptr)3258 gen Xcas_fltk_inputform(const gen & args,const giac::context * contextptr){ 3259 if (args.type==_VECT && args._VECTptr->empty()) 3260 return Xcas_fltk_inputform(identificateur("tmp_input"),contextptr); 3261 vecteur v(inputform_pre_analysis(args,contextptr)); 3262 Fl::lock(); 3263 gen res=makeform(v,contextptr); 3264 Fl::unlock(); 3265 return inputform_post_analysis(v,res,contextptr); 3266 } 3267 Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr)3268 giac::gen Xcas_fltk_input(const giac::gen & arg,const giac::context * contextptr){ 3269 vecteur v(inputform_pre_analysis(arg,contextptr)); 3270 if (v.empty()){ 3271 Fl::lock(); 3272 if (Xcas_DispG_Window) show_xcas_dispg=2; 3273 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->show(); 3274 if (Xcas_DispG) Xcas_DispG->waiting_click=true; 3275 Fl::unlock(); 3276 for (;;) { 3277 #ifdef HAVE_LIBPTHREAD 3278 usleep(10000); 3279 #else 3280 Fl::wait(); 3281 #endif // HAVE_LIBPTHREAD 3282 Fl::lock(); 3283 bool wait= (Xcas_DispG && Xcas_DispG_Window && Xcas_DispG_Window->visible())? Xcas_DispG->waiting_click : false; 3284 Fl::unlock(); 3285 if (!wait) 3286 break; 3287 } 3288 Fl::lock(); 3289 if (Xcas_DispG) Xcas_DispG->waiting_click=false; 3290 if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide(); 3291 gen res=(Xcas_DispG && Xcas_DispG_Window && Xcas_DispG_Window->visible())?Xcas_DispG->waiting_click_value:undef; 3292 Fl::unlock(); 3293 return res; 3294 } 3295 else { 3296 Fl::lock(); 3297 gen res=makeform(v,contextptr); 3298 Fl::unlock(); 3299 return inputform_post_analysis(v,res,contextptr); 3300 } 3301 } 3302 3303 #endif // WIN32 3304 3305 #endif // HAVE_LIBFLTK 3306 3307 // functions for icas or C-library usage read_file(const giac::gen & g)3308 int read_file(const giac::gen & g){ 3309 if (g.is_symb_of_sommet(giac::at_read)) 3310 return 1; 3311 if (g.is_symb_of_sommet(giac::at_geo2d)) 3312 return 2; 3313 if (g.is_symb_of_sommet(giac::at_geo3d)) 3314 return 3; 3315 if (g.is_symb_of_sommet(giac::at_spreadsheet)) 3316 return 4; 3317 return 0; 3318 } 3319 icas_eval_callback(const giac::gen & evaled_g,void * param)3320 void icas_eval_callback(const giac::gen & evaled_g,void * param){ 3321 giac::gen * resptr=(giac::gen *) param; 3322 // cerr << "icas_eval_callback " << evaled_g << '\n'; 3323 *resptr=evaled_g; 3324 } 3325 3326 // eval g to gg, if g is a read command, replace g by the file content 3327 // and set reading_file to true icas_eval(giac::gen & g,giac::gen & gg,int & reading_file,std::string & filename,giac::context * contextptr)3328 void icas_eval(giac::gen & g,giac::gen & gg,int & reading_file,std::string &filename,giac::context * contextptr){ 3329 if (debug_infolevel) 3330 CERR << CLOCK() << " icas_eval " << g << '\n'; 3331 try { 3332 reading_file=read_file(g); 3333 if (g.type==_SYMB && g._SYMBptr->feuille.type==giac::_STRNG) 3334 filename=reading_file?*g._SYMBptr->feuille._STRNGptr:""; 3335 if (g.type==_SYMB && reading_file){ 3336 if (g._SYMBptr->feuille.type==giac::_VECT && !g._SYMBptr->feuille._VECTptr->empty()){ 3337 gg=_read(g._SYMBptr->feuille,contextptr); 3338 return; 3339 } 3340 else { 3341 if (g._SYMBptr->feuille.type!=giac::_STRNG) 3342 g=g._SYMBptr->feuille; 3343 else 3344 g=quote_read(g._SYMBptr->feuille,contextptr); 3345 } 3346 } 3347 if (g.type==giac::_VECT && !filename.empty()){ 3348 // patch to handle spreadsheet[ correctly 3349 FILE * inf=fopen(filename.c_str(),"r"); 3350 if (inf){ 3351 char ch[13]; 3352 ch[12]=0; 3353 if (fread(ch,1,12,inf)==12 && !strcmp(ch,"spreadsheet[")){ 3354 giac::makespreadsheetmatrice(*g._VECTptr,0); 3355 g.subtype=giac::_SPREAD__VECT; 3356 } 3357 fclose(inf); 3358 } 3359 } 3360 giac::gen g1=giac::approx_mode(contextptr)?giac::symbolic(giac::at_evalf,g):g; 3361 giac::gen result; 3362 signal(SIGINT,ctrl_c_signal_handler); 3363 #ifdef HAVE_LIBPTHREAD 3364 giac::make_thread(g1,eval_level(contextptr),icas_eval_callback,&result,contextptr); 3365 int status; 3366 while (1){ 3367 // look at other threads 3368 int cs=context_list().size(),ci=0; 3369 for (;ci<cs;++ci){ 3370 context * cptr=context_list()[ci]; 3371 if (cptr!=contextptr) 3372 status=check_thread(cptr); 3373 } 3374 // 0 finished, 2/3 debug/wait click 3375 status=giac::check_thread(contextptr); 3376 #ifdef HAVE_LIBFLTK 3377 if (xcas::Xcas_Debug_Window && status<2) 3378 xcas::Xcas_Debug_Window->hide(); 3379 #endif 3380 if (status<=0){ 3381 #ifdef HAVE_LIBFLTK 3382 Fl::flush(); 3383 #endif 3384 break; 3385 } 3386 #ifdef HAVE_LIBFLTK 3387 if (status!=1) 3388 xcas::Xcas_debugguer(status,contextptr); 3389 #else 3390 // FIXME Debugguer without FLTK 3391 if (status!=1) 3392 giac::thread_eval_status(1,contextptr); 3393 #endif 3394 if (ctrl_c){ 3395 if (giac::is_context_busy(contextptr)) 3396 giac::kill_thread(true,contextptr); 3397 ctrl_c=false; interrupted=false; 3398 } 3399 else 3400 usleep(1000); 3401 } 3402 gg=result; 3403 #else 3404 gg=eval(g1,eval_level(contextptr),contextptr); 3405 #endif 3406 } 3407 catch(std::runtime_error & e){ 3408 if (!contextptr) 3409 giac::protection_level=0; 3410 gg=giac::string2gen(e.what(),false); 3411 } 3412 } 3413 3414 int fltk_return_value=-1; 3415 #ifdef HAVE_LIBFLTK cb_Close(Fl_Button * m,void *)3416 static void cb_Close(Fl_Button * m , void*) { 3417 if (m->window()) 3418 m->window()->hide(); 3419 fltk_return_value=0; 3420 } 3421 cb_Cancel(Fl_Button * m,void *)3422 static void cb_Cancel(Fl_Button * m , void*) { 3423 if (m->window()) 3424 m->window()->hide(); 3425 fltk_return_value=1; 3426 } 3427 cb_Kill(Fl_Button * m,void *)3428 static void cb_Kill(Fl_Button * m , void*) { 3429 // FIXME user_data() 3430 giac::kill_thread(true,context0); 3431 } 3432 has_graph3d(Fl_Widget * widget)3433 bool has_graph3d(Fl_Widget * widget){ 3434 Fl_Group * g=dynamic_cast<Fl_Group *>(widget); 3435 if (!g) 3436 return false; 3437 int n=g->children(); 3438 for (int i=0;i<n;++i){ 3439 Fl_Widget * wid = g->child(i); 3440 if (Fl_Group * gr=dynamic_cast<Fl_Group * >(wid)){ 3441 if (has_graph3d(gr)) 3442 return true; 3443 } 3444 if (Graph3d * gr3=dynamic_cast<Graph3d * >(wid)) 3445 return true; 3446 } 3447 return false; 3448 } 3449 #endif 3450 quit_idle_function(void * widget)3451 void quit_idle_function(void * widget){ 3452 static int t=0; 3453 if (!widget){ 3454 t=CLOCK(); 3455 return; 3456 } 3457 #ifdef HAVE_LIBFLTK 3458 Fl_Widget * w=(Fl_Widget *)(widget); 3459 if (has_graph3d(w) && (CLOCK()-t<1e5)) return; 3460 w->hide(); 3461 fltk_return_value=0; 3462 #endif 3463 } 3464 3465 // open a FLTK window, that will be printed to filename when closed 3466 // return false if FLTK not avail fltk_view(const giac::gen & g,giac::gen & ge,const std::string & filename,std::string & figure_filename,int file_type,const giac::context * contextptr)3467 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){ 3468 #ifdef __APPLE__ 3469 // return false; 3470 #endif 3471 #ifdef HAVE_LIBFLTK 3472 #if !defined(__APPLE__) && !defined(WIN32) 3473 if (!getenv("DISPLAY")) 3474 return false; 3475 #endif // FIXME GIAC_CONTEXT 3476 // const giac::context * contextptr = get_context(Fl_Group::current()); 3477 bool geometry=!figure_filename.empty(); 3478 if (file_type==4 && figure_filename.empty()){ 3479 figure_filename="table.tab"; 3480 geometry=true; 3481 } 3482 Fl_Window * w=0; 3483 Fl_Return_Button * button0 = 0 ; 3484 Fl_Button * button1 =0,*button2=0; 3485 if (!w){ 3486 int dx=800,dy=geometry?500:360; 3487 Fl_Group::current(0); 3488 w=new Fl_Window(dx,dy); 3489 button0 = new Fl_Return_Button(2,dy-25,dx/3-4,20); 3490 button0->shortcut(0xff0d); 3491 button0->label(gettext("OK")); 3492 button0->callback( (Fl_Callback *) cb_Close); 3493 button1 = new Fl_Button(dx/3+2,dy-25,dx/3-4,20); 3494 button1->shortcut(0xff1b); 3495 button1->label(gettext("Cancel")); 3496 button1->callback( (Fl_Callback *) cb_Cancel); 3497 button2 = new Fl_Button(2*dx/3+2,dy-25,dx/3-4,20); 3498 button2->shortcut(0xff1b); 3499 button2->label(gettext("STOP")); 3500 button2->callback( (Fl_Callback *) cb_Kill); 3501 w->end(); 3502 w->resizable(w); 3503 } 3504 // xcas::initialize_function=load_autorecover_data; 3505 if (file_type==-1){ 3506 quit_idle_function(0); 3507 Fl::add_idle(quit_idle_function,w); 3508 } 3509 else 3510 Fl::add_idle(xcas::Xcas_idle_function,0); 3511 // xcas::idle_function=Xcas_update_mode; 3512 Fl_Group::current(w); 3513 int dx=w->w(),dy=w->h(); 3514 Fl_Tile * this_graph_tile=new Fl_Tile(0,0,dx,dy-25); 3515 Fl_Widget * wid =0,*print_wid=0; 3516 if (geometry){ 3517 if (file_type==4 || (giac::ckmatrix(ge,true) && ge.subtype==giac::_SPREAD__VECT)){ 3518 xcas::Tableur_Group * t=new xcas::Tableur_Group(0,0,dx,dy-25,20,2); 3519 wid=t; 3520 giac::gen tmp=giac::gen(giac::remove_path(giac::remove_extension(figure_filename)),contextptr); 3521 if (tmp.type==giac::_IDNT) 3522 t->table->name=tmp; 3523 t->table->contextptr=(giac::context *) contextptr; 3524 if (giac::ckmatrix(ge,true) && ge.subtype==giac::_SPREAD__VECT){ 3525 t->table->set_matrix(*ge._VECTptr,true,false); // don't reeval! 3526 // t->table->paste(*ge._VECTptr,false); // don't reeval! 3527 } 3528 if (t->table->filename) 3529 delete t->table->filename; 3530 if ( (t->table->filename = new std::string(figure_filename)) ) 3531 t->fname->label(t->table->filename->c_str()); 3532 t->table->update_status(); 3533 } 3534 else { 3535 wid=new xcas::Figure(0,0,dx,dy-25,20,(is3d(ge)||file_type==3)); 3536 if (wid) 3537 print_wid=((xcas::Figure *)wid)->geo; 3538 } 3539 } 3540 else { 3541 int t=graph_output_type(ge); 3542 if (t==4 || file_type==4){ 3543 xcas::Turtle * tu=new xcas::Turtle(0,0,dx,dy-25); 3544 tu->turtleptr=&turtle_stack(contextptr); 3545 print_wid=wid=tu; 3546 } 3547 else { 3548 if (t==3||file_type==3){ 3549 #ifdef HAVE_LIBFLTK_GL 3550 print_wid=wid=new xcas::Graph3d(0,0,dx,dy-25,"",0); 3551 #endif 3552 } 3553 else { 3554 if (t==2 || file_type==2) 3555 print_wid=wid=new xcas::Graph2d(0,0,dx,dy-25); 3556 else { 3557 print_wid=wid=new Fl_Output(0,0,dx,dy-25); 3558 ((Fl_Output *) (wid))->value("No suitable widget"); 3559 } 3560 } 3561 } 3562 } 3563 if (xcas::Graph2d3d * this_graph = dynamic_cast<xcas::Graph2d3d *>(wid)){ 3564 this_graph->add(ge); 3565 this_graph->autoscale(); 3566 this_graph->update_infos(ge,contextptr); 3567 } 3568 if (xcas::Figure * fig=dynamic_cast<xcas::Figure *>(wid)){ 3569 fig->rename(figure_filename.c_str()); 3570 fig->geo->hp->remove_entry(0); 3571 if (!is_undef(ge)) 3572 fig->geo->add(ge); 3573 // put g in figure history_pack 3574 if (g.type!=giac::_VECT){ 3575 if (!is_undef(ge)){ 3576 xcas::Multiline_Input_tab * mi = dynamic_cast<xcas::Multiline_Input_tab * >(xcas::new_question_multiline_input(100,20)); 3577 mi->set_g(g); 3578 fig->geo->hp->add_entry(-1,mi); 3579 } 3580 } 3581 else { 3582 giac::const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 3583 for (;it!=itend;++it){ 3584 xcas::Multiline_Input_tab * mi = dynamic_cast<xcas::Multiline_Input_tab * >(xcas::new_question_multiline_input(100,20)); 3585 mi->set_g(*it); 3586 fig->geo->hp->add_entry(-1,mi); 3587 } 3588 } 3589 if (fig->geo->hp->children()==0){ 3590 fig->geo->hp->add_entry(-1); 3591 fig->geo->set_mode(0,0,1); 3592 fig->geo->approx=true; 3593 fig->mode->value("point"); 3594 } 3595 fig->geo->hp->update(); 3596 } 3597 this_graph_tile->end(); 3598 w->show(); 3599 w->hotspot(w); 3600 fltk_return_value=-1; 3601 Fl::run(); 3602 if (file_type==-1) 3603 Fl::remove_idle(quit_idle_function,w); 3604 else 3605 Fl::remove_idle(xcas::Xcas_idle_function,0); 3606 w->show(); 3607 if (!fltk_return_value){ 3608 if (xcas::Figure * fig=dynamic_cast<xcas::Figure *>(wid)){ 3609 if (fig->geo->hp->_modified && !figure_filename.empty()){ 3610 int i=fl_ask("Figure modified. Save?"); 3611 if (i) 3612 fig->save_figure_as(figure_filename); 3613 } 3614 } 3615 if (xcas::Tableur_Group * t=dynamic_cast<xcas::Tableur_Group * >(wid)){ 3616 if (t->table->changed_ && !t->table->filename->empty()){ 3617 int i=fl_ask("Sheet modified. Save?"); 3618 if (i){ 3619 ofstream of(t->table->filename->c_str()); 3620 if (!of) 3621 fl_message("%s","Write error"); 3622 else 3623 of << giac::gen(t->table->m,giac::_SPREAD__VECT) << '\n'; 3624 of.close(); 3625 } 3626 } 3627 else { 3628 ge=t->table->m; 3629 ge.subtype=giac::_SPREAD__VECT; 3630 } 3631 } 3632 // now try to print the widget 3633 if (!print_wid) 3634 print_wid=wid; 3635 print_wid->resize(0,0,dx,dy); 3636 if (xcas::Figure * fig=dynamic_cast<xcas::Figure *>(wid)){ 3637 fig->geo->orthonormalize(); 3638 } 3639 if (!filename.empty() 3640 // && !figure_filename.empty() 3641 ) 3642 xcas::widget_ps_print(print_wid,filename,true,0,false,true,false); // don't ask user for pixel size 3643 } 3644 w->hide(); 3645 Fl::wait(0.001); 3646 w->remove(this_graph_tile); 3647 delete wid; 3648 delete this_graph_tile; 3649 delete button0; 3650 delete button1; 3651 delete button2; 3652 delete w; 3653 return !fltk_return_value; 3654 #else // HAVE_LIBFLTK 3655 return false; 3656 #endif 3657 } 3658 3659 #ifdef HAVE_LIBFLTK 3660 // Font selection, borrowed from FLTK tests font.cxx 3661 Fl_Window *form=0; 3662 3663 class FontDisplay : public Fl_Widget { 3664 void draw(); 3665 public: 3666 int font, size; FontDisplay(Fl_Boxtype B,int X,int Y,int W,int H,const char * L=0)3667 FontDisplay(Fl_Boxtype B, int X, int Y, int W, int H, const char* L = 0) : 3668 Fl_Widget(X,Y,W,H,L) {box(B); font = 0; size = 14;} 3669 }; draw()3670 void FontDisplay::draw() { 3671 draw_box(); 3672 fl_font((Fl_Font)font, size); 3673 fl_color(FL_BLACK); 3674 fl_draw(label(), x()+3, y()+3, w()-6, h()-6, align()); 3675 } 3676 3677 FontDisplay *textobj=0; 3678 3679 Fl_Hold_Browser *fontobj=0, *sizeobj=0; 3680 3681 #define FLTK_FONT_MAX 256 3682 int *sizes[FLTK_FONT_MAX]; 3683 int numsizes[FLTK_FONT_MAX]; 3684 int pickedsize = 14; 3685 font_cb(Fl_Widget *,long)3686 void font_cb(Fl_Widget *, long) { 3687 int fn = fontobj->value(); 3688 if (!fn) return; 3689 fn--; 3690 textobj->font = fn; 3691 sizeobj->clear(); 3692 int n = numsizes[fn]; 3693 int *s = sizes[fn]; 3694 if (!n) { 3695 // no sizes 3696 } else if (s[0] == 0) { 3697 // many sizes; 3698 int j = 1; 3699 for (int i = 1; i<64 || i<s[n-1]; i++) { 3700 char buf[20]; 3701 if (j < n && i==s[j]) {sprintf(buf,"@b%d",i); j++;} 3702 else sprintf(buf,"%d",i); 3703 sizeobj->add(buf); 3704 } 3705 sizeobj->value(pickedsize); 3706 } else { 3707 // some sizes 3708 int w = 0; 3709 for (int i = 0; i < n; i++) { 3710 if (s[i]<=pickedsize) w = i; 3711 char buf[20]; 3712 sprintf(buf,"@b%d",s[i]); 3713 sizeobj->add(buf); 3714 } 3715 sizeobj->value(w+1); 3716 } 3717 textobj->redraw(); 3718 } 3719 size_cb(Fl_Widget *,long)3720 void size_cb(Fl_Widget *, long) { 3721 int i = sizeobj->value(); 3722 if (!i) return; 3723 const char *c = sizeobj->text(i); 3724 while (*c < '0' || *c > '9') c++; 3725 pickedsize = atoi(c); 3726 textobj->size = pickedsize; 3727 textobj->redraw(); 3728 } 3729 get_font(Fl_Font & police,int & taille)3730 bool get_font(Fl_Font & police,int & taille){ 3731 static Fl_Return_Button * button0 = 0 ; 3732 static Fl_Button * button1 =0; 3733 static char label[400]; 3734 Fl::scheme(NULL); 3735 if (!form){ 3736 Fl_Group::current(0); 3737 form = new Fl_Window(550,370); 3738 strcpy(label, gettext("What a nice font")); 3739 int i = strlen(label); 3740 uchar c; 3741 label[i++] = char(10); 3742 for (c = ' '+1; c < 127; c++,i++) {if (!(c&0x1f)) label[i]=' '; else label[i]=c;} 3743 label[i++] = char(10); 3744 for (c = 0xA1; c; c++,i++) {if (!(c&0x1f)) label[i]=' '; else label[i]=c;} 3745 label[i] = 0; 3746 button0 = new Fl_Return_Button(100,10,100,20); 3747 button0->shortcut(0xff0d); 3748 button0->label(gettext("OK")); 3749 button1 = new Fl_Button(300,10,100,20); 3750 button1->shortcut(0xff1b); 3751 button1->label(gettext("Cancel")); 3752 3753 textobj = new FontDisplay(FL_FRAME_BOX,10,40,530,140,label); 3754 textobj->align(FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); 3755 textobj->color(9,47); 3756 fontobj = new Fl_Hold_Browser(10, 190, 390, 170); 3757 fontobj->box(FL_FRAME_BOX); 3758 fontobj->color(53,3); 3759 fontobj->callback(font_cb); 3760 form->resizable(fontobj); 3761 sizeobj = new Fl_Hold_Browser(410, 190, 130, 170); 3762 sizeobj->box(FL_FRAME_BOX); 3763 sizeobj->color(53,3); 3764 sizeobj->callback(size_cb); 3765 form->end(); 3766 int k = min(fonts_available,FLTK_FONT_MAX); 3767 for (i = 0; i < k; i++) { 3768 int t; const char *name = Fl::get_font_name((Fl_Font)i,&t); 3769 char buffer[128]; 3770 if (t) { 3771 char *p = buffer; 3772 if (t & FL_BOLD) {*p++ = '@'; *p++ = 'b';} 3773 if (t & FL_ITALIC) {*p++ = '@'; *p++ = 'i';} 3774 strcpy(p,name); 3775 name = buffer; 3776 } 3777 fontobj->add(name); 3778 int *s; int n = Fl::get_font_sizes((Fl_Font)i, s); 3779 numsizes[i] = n; 3780 if (n) { 3781 sizes[i] = new int[n]; 3782 for (int j=0; j<n; j++) sizes[i][j] = s[j]; 3783 } 3784 } 3785 } 3786 pickedsize = taille; 3787 textobj->size = pickedsize; 3788 fontobj->value(police+1); 3789 font_cb(fontobj,0); 3790 form->set_modal(); 3791 form->show(); 3792 form->hotspot(form); 3793 Fl::focus(form); 3794 int r=-1; 3795 for (;;){ 3796 Fl_Widget *o = Fl::readqueue(); 3797 if (!o) Fl::wait(); 3798 else { 3799 if (o==form){ r=1; break; } 3800 if (o == button0) {r = 0; break;} 3801 if (o == button1) {r = 1; break;} 3802 } 3803 } 3804 form->hide(); 3805 if (r) 3806 return false; 3807 police=Fl_Font(textobj->font); 3808 taille=textobj->size; 3809 return true; 3810 } 3811 3812 /* 3813 void test_alert(){ 3814 string s; 3815 for (int i=0;i<256;i++) 3816 s+=char(i); 3817 fl_alert("%s",s.c_str()); 3818 } 3819 */ 3820 3821 #endif // HAVE_LIBFLTK 3822 3823 #ifndef NO_NAMESPACE_XCAS 3824 } // namespace xcas 3825 #endif // ndef NO_NAMESPACE_XCAS 3826 3827