1 // -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -g -c Equation.cc -DHAVE_CONFIG_H -DIN_GIAC -Wall" -*- 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 "Equation.h" 30 #include <FL/Fl.H> 31 #include <FL/fl_draw.H> 32 #include <FL/Fl_Window.H> 33 #include <FL/fl_ask.H> 34 #include <FL/Fl_File_Chooser.H> 35 #include <FL/Fl_Hold_Browser.H> 36 #include <FL/Fl_PNG_Image.H> 37 #include <FL/Fl_Return_Button.H> 38 #ifndef IN_GIAC 39 #include <giac/giac.h> 40 #else 41 #include "giac.h" 42 #include "graphtheory.h" 43 #endif 44 #include "History.h" 45 #include "Xcas1.h" 46 #include "Input.h" 47 #include "Equation.h" 48 #include "Graph.h" 49 #include <iostream> 50 #include <fstream> 51 using namespace std; 52 using namespace giac; 53 54 #ifndef NO_NAMESPACE_XCAS 55 namespace xcas { 56 #endif // ndef NO_NAMESPACE_XCAS 57 58 unsigned max_prettyprint_equation=5000; 59 60 #ifdef _HAVE_FL_UTF8_HDR_ cst_greek_translate(string & s0)61 Fl_Font cst_greek_translate(string & s0){ 62 string s1(s0); 63 s0=""; 64 int n=s1.size(); 65 for (int i=0;i<n;++i){ 66 if (!isalpha(s1[i])){ 67 s0 += s1[i]; 68 continue; 69 } 70 string s; 71 for (;i<n;++i){ 72 if (!isalpha(s1[i])){ 73 --i; 74 break; 75 } 76 s+=s1[i]; 77 } 78 bool done=false; 79 switch (s.size()){ 80 case 2: 81 if (s=="mu"){ 82 s0+="μ"; 83 done=true; 84 } 85 if (s=="nu"){ 86 s0+="ν"; 87 done=true; 88 } 89 if (s=="pi"){ 90 s0+="π"; 91 done=true; 92 } 93 if (s=="xi"){ 94 s0+="ξ"; 95 done=true; 96 } 97 if (s=="Xi"){ 98 s0+="Ξ"; 99 done=true; 100 } 101 break; 102 case 3: 103 if (s=="chi"){ 104 s0+="χ"; 105 done=true; 106 } 107 if (s=="phi"){ 108 s0+="φ"; 109 done=true; 110 } 111 if (s=="Phi"){ 112 s0+="Φ"; 113 done=true; 114 } 115 if (s=="eta"){ 116 s0+="η"; 117 done=true; 118 } 119 if (s=="rho"){ 120 s0+="ρ"; 121 done=true; 122 } 123 if (s=="tau"){ 124 s0+="τ"; 125 done=true; 126 } 127 if (s=="psi"){ 128 s0+="ψ"; 129 done=true; 130 } 131 if (s=="Psi"){ 132 s0+="Ψ"; 133 done=true; 134 } 135 break; 136 case 4: 137 if (s=="beta"){ 138 s0+="β"; 139 done=true; 140 } 141 if (s=="Beta"){ 142 s0+="β"; 143 done=true; 144 } 145 if (s=="zeta"){ 146 s0+="ζ"; 147 done=true; 148 } 149 if (s=="Zeta"){ 150 s0+="ζ"; 151 done=true; 152 } 153 if (s=="alef"){ 154 s0+="ℵ"; 155 done=true; 156 } 157 break; 158 case 5: 159 if (s=="alpha"){ 160 s0+="α"; 161 done=true; 162 } 163 if (s=="delta"){ 164 s0+="δ"; 165 done=true; 166 } 167 if (s=="Delta"){ 168 s0+="Δ"; 169 done=true; 170 } 171 if (s=="gamma"){ 172 s0+="γ"; 173 done=true; 174 } 175 if (s=="Gamma"){ 176 s0+="Γ"; 177 done=true; 178 } 179 if (s=="kappa"){ 180 s0+="κ"; 181 done=true; 182 } 183 if (s=="theta"){ 184 s0+="θ"; 185 done=true; 186 } 187 if (s=="Theta"){ 188 s0+="Θ"; 189 done=true; 190 } 191 if (s=="sigma"){ 192 s0+="σ"; 193 done=true; 194 } 195 if (s=="Sigma"){ 196 s0+="Σ"; 197 done=true; 198 } 199 if (s=="Omega"){ 200 s0+="Ω"; 201 done=true; 202 } 203 if (s=="omega"){ 204 s0+="ω"; 205 done=true; 206 } 207 break; 208 case 6: 209 if (s=="lambda"){ 210 s0+="λ"; 211 done=true; 212 } 213 if (s=="Lambda"){ 214 s0+="λ"; 215 done=true; 216 } 217 break; 218 case 7: 219 if (s=="epsilon"){ 220 s0+="ε"; 221 done=true; 222 } 223 if (s=="product"){ 224 s0="Π"; 225 done=true; 226 } 227 break; 228 case 8: 229 if (s=="infinity"){ 230 s0+="∞"; 231 done=true; 232 } 233 break; 234 case 11: 235 if (s=="euler_gamma"){ 236 s0+="ϒ"; 237 done=true; 238 } 239 break; 240 } // end switch 241 if (!done) 242 s0+=s; 243 } // end for (int i=0;i<n;i++) 244 return FL_HELVETICA; 245 } 246 #else 247 cst_greek_translate(string & s0)248 Fl_Font cst_greek_translate(string & s0){ 249 int n=s0.size(),j; 250 for (j=n-1;j>=2;--j){ 251 if (isalpha(s0[j])) 252 break; 253 } 254 string s=s0.substr(0,j+1),sadd; 255 if (j<n-1) 256 sadd=s0.substr(j+1,n-1-j); 257 switch (s.size()){ 258 case 2: 259 if (s=="mu"){ 260 s0="m"+sadd; 261 return FL_SYMBOL; 262 } 263 if (s=="nu"){ 264 s0="n"+sadd; 265 return FL_SYMBOL; 266 } 267 if (s=="pi"){ 268 s0="p"+sadd; 269 return FL_SYMBOL; 270 } 271 if (s=="xi"){ 272 s0="x"+sadd; 273 return FL_SYMBOL; 274 } 275 if (s=="Xi"){ 276 s0="X"+sadd; 277 return FL_SYMBOL; 278 } 279 if (s=="im"){ 280 s0="Á"+sadd; 281 return FL_SYMBOL; 282 } 283 if (s=="re"){ 284 s0="Â"+sadd; 285 return FL_SYMBOL; 286 } 287 break; 288 case 3: 289 if (s=="chi"){ 290 s0="c"+sadd; 291 return FL_SYMBOL; 292 } 293 if (s=="phi"){ 294 s0="f"+sadd; 295 return FL_SYMBOL; 296 } 297 if (s=="Phi"){ 298 s0="f"+sadd; 299 return FL_SYMBOL; 300 } 301 if (s=="eta"){ 302 s0="h"+sadd; 303 return FL_SYMBOL; 304 } 305 if (s=="rho"){ 306 s0="r"+sadd; 307 return FL_SYMBOL; 308 } 309 if (s=="tau"){ 310 s0="t"+sadd; 311 return FL_SYMBOL; 312 } 313 if (s=="psi"){ 314 s0="y"+sadd; 315 return FL_SYMBOL; 316 } 317 if (s=="Psi"){ 318 s0="Y"+sadd; 319 return FL_SYMBOL; 320 } 321 break; 322 case 4: 323 if (s=="beta"){ 324 s0="b"+sadd; 325 return FL_SYMBOL; 326 } 327 if (s=="Beta"){ 328 s0="b"+sadd; 329 return FL_SYMBOL; 330 } 331 if (s=="zeta"){ 332 s0="z"+sadd; 333 return FL_SYMBOL; 334 } 335 if (s=="Zeta"){ 336 s0="z"+sadd; 337 return FL_SYMBOL; 338 } 339 break; 340 case 5: 341 if (s=="alpha"){ 342 s0="a"+sadd; 343 return FL_SYMBOL; 344 } 345 if (s=="delta"){ 346 s0="d"+sadd; 347 return FL_SYMBOL; 348 } 349 if (s=="Delta"){ 350 s0="D"+sadd; 351 return FL_SYMBOL; 352 } 353 if (s=="gamma"){ 354 s0="g"+sadd; 355 return FL_SYMBOL; 356 } 357 if (s=="Gamma"){ 358 s0="G"+sadd; 359 return FL_SYMBOL; 360 } 361 if (s=="kappa"){ 362 s0="k"+sadd; 363 return FL_SYMBOL; 364 } 365 if (s=="theta"){ 366 s0="q"+sadd; 367 return FL_SYMBOL; 368 } 369 if (s=="Theta"){ 370 s0="Q"+sadd; 371 return FL_SYMBOL; 372 } 373 if (s=="sigma"){ 374 s0="s"+sadd; 375 return FL_SYMBOL; 376 } 377 if (s=="Sigma"){ 378 s0="S"+sadd; 379 return FL_SYMBOL; 380 } 381 if (s=="Omega"){ 382 s0="W"+sadd; 383 return FL_SYMBOL; 384 } 385 if (s=="omega"){ 386 s0="w"+sadd; 387 return FL_SYMBOL; 388 } 389 if (s=="aleph"){ 390 s0="À"+sadd; 391 return FL_SYMBOL; 392 } 393 break; 394 case 6: 395 if (s=="lambda"){ 396 s0="l"+sadd; 397 return FL_SYMBOL; 398 } 399 if (s=="Lambda"){ 400 s0="L"+sadd; 401 return FL_SYMBOL; 402 } 403 if (s=="approx"){ 404 s0="»"+sadd; 405 return FL_SYMBOL; 406 } 407 break; 408 case 7: 409 if (s=="epsilon"){ 410 s0="e"+sadd; 411 return FL_SYMBOL; 412 } 413 if (s=="product"){ 414 s0="P"+sadd; 415 return FL_SYMBOL; 416 } 417 break; 418 case 8: 419 if (s=="infinity"){ 420 s0="¥"+sadd; 421 return FL_SYMBOL; 422 } 423 break; 424 case 11: 425 if (s=="euler_gamma"){ 426 s0="g"+sadd; 427 return FL_SYMBOL; 428 } 429 break; 430 } 431 return FL_HELVETICA; 432 } 433 #endif 434 Equation_binary_search_pos(const eqwdata & e,int x,int y)435 int Equation_binary_search_pos(const eqwdata & e,int x,int y){ 436 int ss=e.g._STRNGptr->size(); 437 int debut=0,fin=ss,pos,l=0; 438 fl_font(FL_HELVETICA,e.eqw_attributs.fontsize); 439 for (;debut+1<fin;){ 440 pos=(debut+fin)/2; 441 l=int(fl_width(e.g._STRNGptr->substr(0,pos).c_str())); 442 if (e.x+l<x) 443 debut=pos; 444 else 445 fin=pos; 446 } 447 int l2=int(fl_width(e.g._STRNGptr->substr(0,fin).c_str())); 448 x=x-e.x; 449 if (x-l>l2-x) 450 return fin; 451 else 452 return debut; 453 } 454 Equation_multistring_selection(const_iterateur & it,const_iterateur & itend,bool search_active)455 bool Equation_multistring_selection(const_iterateur & it,const_iterateur & itend,bool search_active){ 456 for (;it!=itend;++it){ // find first selection 457 if (it->type==_EQW){ 458 if (search_active){ 459 if (it->_EQWptr->active) 460 break; 461 } 462 else { 463 if (it->_EQWptr->selected) 464 break; 465 } 466 } 467 } 468 if (it==itend) 469 return false; // nothing selected 470 const_iterateur it_end_sel=it+1; 471 for (;it_end_sel!=itend;++it_end_sel){ // find last selection 472 if (it_end_sel->type==_EQW){ 473 if (search_active){ 474 if (!it_end_sel->_EQWptr->active) 475 break; 476 } 477 else { 478 if (!it_end_sel->_EQWptr->selected) 479 break; 480 } 481 } 482 } 483 itend=it_end_sel-1; 484 return true; 485 } 486 Equation_total_size(const gen & g)487 eqwdata Equation_total_size(const gen & g){ 488 if (g.type==_EQW) 489 return *g._EQWptr; 490 if (g.type!=_VECT || g._VECTptr->empty()) 491 return eqwdata(0,0,0,0,attributs(0,0,0),undef); 492 return Equation_total_size(g._VECTptr->back()); 493 } 494 495 // find smallest value of y and height Equation_y_dy(const gen & g,int & y,int & dy)496 void Equation_y_dy(const gen & g,int & y,int & dy){ 497 y=0; dy=0; 498 if (g.type==_EQW){ 499 y=g._EQWptr->y; 500 dy=g._EQWptr->dy; 501 } 502 if (g.type==_VECT){ 503 iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 504 for (;it!=itend;++it){ 505 int Y,dY; 506 Equation_y_dy(*it,Y,dY); 507 // Y, Y+dY and y,y+dy 508 int ymax=giacmax(y+dy,Y+dY); 509 if (Y<y) 510 y=Y; 511 dy=ymax-y; 512 } 513 } 514 } 515 Equation_translate(gen & g,int deltax,int deltay)516 void Equation_translate(gen & g,int deltax,int deltay){ 517 if (g.type==_EQW){ 518 g._EQWptr->x += deltax; 519 g._EQWptr->y += deltay; 520 g._EQWptr->baseline += deltay; 521 return ; 522 } 523 if (g.type!=_VECT) 524 setsizeerr(); 525 vecteur & v=*g._VECTptr; 526 iterateur it=v.begin(),itend=v.end(); 527 for (;it!=itend;++it) 528 Equation_translate(*it,deltax,deltay); 529 } 530 Equation_change_attributs(const gen & g,const attributs & newa)531 gen Equation_change_attributs(const gen & g,const attributs & newa){ 532 if (g.type==_EQW){ 533 gen res(*g._EQWptr); 534 res._EQWptr->eqw_attributs = newa; 535 return res; 536 } 537 if (g.type!=_VECT) 538 setsizeerr(); 539 vecteur v=*g._VECTptr; 540 iterateur it=v.begin(),itend=v.end(); 541 for (;it!=itend;++it) 542 *it=Equation_change_attributs(*it,newa); 543 return gen(v,g.subtype); 544 } 545 Equation_subsizes(const gen & arg,const attributs & a,int windowhsize,GIAC_CONTEXT)546 vecteur Equation_subsizes(const gen & arg,const attributs & a,int windowhsize,GIAC_CONTEXT){ 547 vecteur v; 548 if ( (arg.type==_VECT) && ( (arg.subtype==_SEQ__VECT) 549 // || (!ckmatrix(arg)) 550 ) ){ 551 const_iterateur it=arg._VECTptr->begin(),itend=arg._VECTptr->end(); 552 for (;it!=itend;++it) 553 v.push_back(Equation_compute_size(*it,a,windowhsize,contextptr)); 554 } 555 else { 556 v.push_back(Equation_compute_size(arg,a,windowhsize,contextptr)); 557 } 558 return v; 559 } 560 561 // vertical merge with same baseline 562 // for vertical merge of hp,yp at top (like ^) add fontsize to yp 563 // at bottom (like lower bound of int) substract fontsize from yp Equation_vertical_adjust(int hp,int yp,int & h,int & y)564 void Equation_vertical_adjust(int hp,int yp,int & h,int & y){ 565 int yf=min(y,yp); 566 h=max(y+h,yp+hp)-yf; 567 y=yf; 568 } 569 570 // utility for gen embedded widget memory allocation fltk_fl_widget_delete_function(void * ptr)571 void fltk_fl_widget_delete_function(void * ptr){ 572 Fl_Widget * w=(Fl_Widget *) ptr; 573 /* not attached to any group 574 if (w->parent()){ 575 Fl_Group * wg=dynamic_cast<Fl_Group *>(w->parent()); 576 if (wg) 577 wg->remove(w); 578 } 579 */ 580 delete w; 581 } 582 Equation_compute_symb_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT)583 gen Equation_compute_symb_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT){ 584 if (g.type!=_SYMB) 585 return Equation_compute_size(g,a,windowhsize,contextptr); 586 unary_function_ptr & u=g._SYMBptr->sommet; 587 gen arg=g._SYMBptr->feuille,rootof_value; 588 if (u==at_rootof && arg.type==_VECT && arg._VECTptr->size()==2 && arg._VECTptr->front().type==_VECT && has_rootof_value(arg._VECTptr->back(),rootof_value,contextptr)){ 589 return Equation_compute_symb_size(horner_rootof(*arg._VECTptr->front()._VECTptr,rootof_value,contextptr),a,windowhsize,contextptr); 590 } 591 if (u==at_multistring){ 592 gen tmp=_multistring(arg,contextptr); 593 tmp.subtype=1; 594 return Equation_compute_size(tmp,a,windowhsize,contextptr); 595 } 596 if (u==at_makevector){ 597 vecteur v(1,arg); 598 if (arg.type==_VECT) 599 v=*arg._VECTptr; 600 iterateur it=v.begin(),itend=v.end(); 601 for (;it!=itend;++it){ 602 if ( (it->type==_SYMB) && (it->_SYMBptr->sommet==at_makevector) ) 603 *it=_makevector(it->_SYMBptr->feuille,contextptr); 604 } 605 return Equation_compute_size(v,a,windowhsize,contextptr); 606 } 607 if (u==at_makesuite){ 608 if (arg.type==_VECT) 609 return Equation_compute_size(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr); 610 else 611 return Equation_compute_size(arg,a,windowhsize,contextptr); 612 } 613 if (u==at_sqrt) 614 return Equation_compute_size(symbolic(at_pow,gen(makevecteur(arg,plus_one_half),_SEQ__VECT)),a,windowhsize,contextptr); 615 if (u==at_division){ 616 if (arg.type!=_VECT || arg._VECTptr->size()!=2) 617 return Equation_compute_size(arg,a,windowhsize,contextptr); 618 gen tmp; 619 #ifdef SMARTPTR64 620 * ((ulonglong * ) &tmp) = ulonglong(new ref_fraction(Tfraction<gen>(arg._VECTptr->front(),arg._VECTptr->back()))) << 16; 621 #else 622 tmp.__FRACptr = new ref_fraction(Tfraction<gen>(arg._VECTptr->front(),arg._VECTptr->back())); 623 #endif 624 tmp.type=_FRAC; 625 return Equation_compute_size(tmp,a,windowhsize,contextptr); 626 } 627 if (u==at_prod){ 628 gen n,d; 629 if (rewrite_prod_inv(arg,n,d)){ 630 if (n.is_symb_of_sommet(at_neg)) 631 return Equation_compute_size(symbolic(at_neg,Tfraction<gen>(-n,d)),a,windowhsize,contextptr); 632 return Equation_compute_size(Tfraction<gen>(n,d),a,windowhsize,contextptr); 633 } 634 } 635 if (u==at_inv){ 636 if ( (is_integer(arg) && is_positive(-arg,contextptr)) 637 || (arg.is_symb_of_sommet(at_neg))) 638 return Equation_compute_size(symbolic(at_neg,Tfraction<gen>(plus_one,-arg)),a,windowhsize,contextptr); 639 return Equation_compute_size(Tfraction<gen>(plus_one,arg),a,windowhsize,contextptr); 640 } 641 if (u==at_expr && arg.type==_VECT && arg.subtype==_SEQ__VECT && arg._VECTptr->size()==2 && arg._VECTptr->back().type==_INT_){ 642 gen varg1=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr); 643 eqwdata vv(Equation_total_size(varg1)); 644 gen varg2=eqwdata(0,0,0,0,a,arg._VECTptr->back()); 645 vecteur v12(makevecteur(varg1,varg2)); 646 v12.push_back(eqwdata(vv.dx,vv.dy,0,vv.y,a,at_expr,0)); 647 return gen(v12,_SEQ__VECT); 648 } 649 int llp=int(fl_width("(")); 650 int lrp=int(fl_width(")")); 651 int lc=int(fl_width(",")); 652 string us=u.ptr()->s; 653 fl_font(cst_greek_translate(us),a.fontsize); 654 int ls=int(fl_width(us.c_str())); 655 fl_font(FL_HELVETICA,a.fontsize); 656 if (isalpha(u.ptr()->s[0])) 657 ls += 2; 658 if (u==at_abs) 659 ls = 2; 660 // special cases first int, sigma, /, ^ 661 // and if printed as printsommetasoperator 662 // otherwise print with usual functional notation 663 int x=0; 664 int h=a.fontsize; 665 int y=0; 666 if ((u==at_integrate) || (u==at_sum) ){ // Int 667 int s=1; 668 if (arg.type==_VECT) 669 s=arg._VECTptr->size(); 670 else 671 arg=vecteur(1,arg); 672 // s==1 -> general case 673 if ( (s==1) || (s==2) ){ // int f(x) dx and sum f(n) n 674 vecteur v(Equation_subsizes(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr)); 675 eqwdata vv(Equation_total_size(v[0])); 676 if (s==1){ 677 x=a.fontsize; 678 Equation_translate(v[0],x,0); 679 x += int(fl_width(" dx")); 680 } 681 if (s==2){ 682 if (u==at_integrate){ 683 x=a.fontsize; 684 Equation_translate(v[0],x,0); 685 x += vv.dx+int(fl_width(" d")); 686 Equation_vertical_adjust(vv.dy,vv.y,h,y); 687 vv=Equation_total_size(v[1]); 688 Equation_translate(v[1],x,0); 689 Equation_vertical_adjust(vv.dy,vv.y,h,y); 690 } 691 else { 692 Equation_vertical_adjust(vv.dy,vv.y,h,y); 693 eqwdata v1=Equation_total_size(v[1]); 694 x=giacmax(a.fontsize,v1.dx)+a.fontsize/3; // var name size 695 Equation_translate(v[1],0,-v1.dy-v1.y); 696 Equation_vertical_adjust(v1.dy,-v1.dy,h,y); 697 Equation_translate(v[0],x,0); 698 x += vv.dx; // add function size 699 } 700 } 701 if (u==at_integrate){ 702 x += vv.dx; 703 if (h==a.fontsize) 704 h+=2*a.fontsize/3; 705 if (y==0){ 706 y=-2*a.fontsize/3; 707 h+=2*a.fontsize/3; 708 } 709 } 710 v.push_back(eqwdata(x,h,0,y,a,u,0)); 711 return gen(v,_SEQ__VECT); 712 } 713 if (s>=3){ // int _a^b f(x) dx 714 vecteur & intarg=*arg._VECTptr; 715 gen tmp_l,tmp_u,tmp_f,tmp_x; 716 attributs aa(a); 717 if (a.fontsize>=10) 718 aa.fontsize -= 2; 719 tmp_f=Equation_compute_size(intarg[0],a,windowhsize,contextptr); 720 tmp_x=Equation_compute_size(intarg[1],a,windowhsize,contextptr); 721 tmp_l=Equation_compute_size(intarg[2],aa,windowhsize,contextptr); 722 if (s==4) 723 tmp_u=Equation_compute_size(intarg[3],aa,windowhsize,contextptr); 724 x=a.fontsize; 725 eqwdata vv(Equation_total_size(tmp_l)); 726 Equation_translate(tmp_l,x-2,-vv.y-vv.dy); 727 vv=Equation_total_size(tmp_l); 728 Equation_vertical_adjust(vv.dy,vv.y,h,y); 729 int lx = vv.dx; 730 if (s==4){ 731 vv=Equation_total_size(tmp_u); 732 Equation_translate(tmp_u,x,a.fontsize-3-vv.y); 733 vv=Equation_total_size(tmp_u); 734 Equation_vertical_adjust(vv.dy,vv.y,h,y); 735 } 736 x += max(lx,vv.dx); 737 Equation_translate(tmp_f,x,0); 738 vv=Equation_total_size(tmp_f); 739 Equation_vertical_adjust(vv.dy,vv.y,h,y); 740 if (u==at_integrate){ 741 x += vv.dx+int(fl_width(" d")); 742 Equation_translate(tmp_x,x,0); 743 vv=Equation_total_size(tmp_x); 744 Equation_vertical_adjust(vv.dy,vv.y,h,y); 745 x += vv.dx; 746 } 747 else { 748 x += vv.dx; 749 Equation_vertical_adjust(vv.dy,vv.y,h,y); 750 vv=Equation_total_size(tmp_x); 751 x=max(x,vv.dx)+a.fontsize/3; 752 Equation_translate(tmp_x,0,-vv.dy-vv.y); 753 Equation_vertical_adjust(vv.dy,-vv.dy,h,y); 754 } 755 vecteur res(makevecteur(tmp_f,tmp_x,tmp_l)); 756 if (s==4) 757 res.push_back(tmp_u); 758 res.push_back(eqwdata(x,h,0,y,a,u,0)); 759 return gen(res,_SEQ__VECT); 760 } 761 } 762 if (u==at_limit && arg.type==_VECT){ // limit 763 vecteur & limarg=*arg._VECTptr; 764 int s=limarg.size(); 765 if (s>=3){ 766 gen tmp_l,tmp_f,tmp_x,tmp_dir; 767 attributs aa(a); 768 if (a.fontsize>=10) 769 aa.fontsize -= 2; 770 tmp_f=Equation_compute_size(limarg[0],a,windowhsize,contextptr); 771 tmp_x=Equation_compute_size(limarg[1],aa,windowhsize,contextptr); 772 tmp_l=Equation_compute_size(limarg[2],aa,windowhsize,contextptr); 773 if (s==4) 774 tmp_dir=Equation_compute_size(limarg[3],aa,windowhsize,contextptr); 775 eqwdata vf(Equation_total_size(tmp_f)); 776 eqwdata vx(Equation_total_size(tmp_x)); 777 eqwdata vl(Equation_total_size(tmp_l)); 778 eqwdata vdir(Equation_total_size(tmp_dir)); 779 int sous=max(vx.dy,vl.dy); 780 if (s==4) 781 Equation_translate(tmp_f,vx.dx+vl.dx+vdir.dx+a.fontsize+4,0); 782 else 783 Equation_translate(tmp_f,vx.dx+vl.dx+a.fontsize+2,0); 784 Equation_translate(tmp_x,0,-sous-vl.y); 785 Equation_translate(tmp_l,vx.dx+a.fontsize+2,-sous-vl.y); 786 if (s==4) 787 Equation_translate(tmp_dir,vx.dx+vl.dx+a.fontsize+4,-sous-vl.y); 788 h=vf.dy; 789 y=vf.y; 790 vl=Equation_total_size(tmp_l); 791 Equation_vertical_adjust(vl.dy,vl.y,h,y); 792 vecteur res(makevecteur(tmp_f,tmp_x,tmp_l)); 793 if (s==4){ 794 res.push_back(tmp_dir); 795 res.push_back(eqwdata(vf.dx+vx.dx+a.fontsize+4+vl.dx+vdir.dx,h,0,y,a,u,0)); 796 } 797 else 798 res.push_back(eqwdata(vf.dx+vx.dx+a.fontsize+2+vl.dx,h,0,y,a,u,0)); 799 return gen(res,_SEQ__VECT); 800 } 801 } 802 if ( (u==at_of || u==at_at) && arg.type==_VECT && arg._VECTptr->size()==2 ){ 803 // user function, function in 1st arg, arguments in 2nd arg 804 gen varg1=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr); 805 eqwdata vv=Equation_total_size(varg1); 806 Equation_vertical_adjust(vv.dy,vv.y,h,y); 807 gen arg2=arg._VECTptr->back(); 808 if (u==at_at && xcas_mode(contextptr)!=0){ 809 if (arg2.type==_VECT) 810 arg2=gen(addvecteur(*arg2._VECTptr,vecteur(arg2._VECTptr->size(),plus_one)),_SEQ__VECT); 811 else 812 arg2=arg2+plus_one; 813 } 814 gen varg2=Equation_compute_size(arg2,a,windowhsize,contextptr); 815 Equation_translate(varg2,vv.dx+llp,0); 816 vv=Equation_total_size(varg2); 817 Equation_vertical_adjust(vv.dy,vv.y,h,y); 818 vecteur res(makevecteur(varg1,varg2)); 819 res.push_back(eqwdata(vv.dx+vv.x+lrp,h,0,y,a,u,0)); 820 return gen(res,_SEQ__VECT); 821 } 822 if (u==at_pow){ 823 // first arg not translated 824 gen varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr); 825 eqwdata vv=Equation_total_size(varg); 826 // 1/2 ->sqrt, otherwise as exponent 827 if (arg._VECTptr->back()==plus_one_half){ 828 Equation_translate(varg,a.fontsize,0); 829 vecteur res(1,varg); 830 res.push_back(eqwdata(vv.dx+a.fontsize,vv.dy+4,vv.x,vv.y,a,at_sqrt,0)); 831 return gen(res,_SEQ__VECT); 832 } 833 bool needpar=vv.g.type==_FUNC || vv.g.is_symb_of_sommet(at_pow) || need_parenthesis(vv.g); 834 if (needpar) 835 x=llp; 836 Equation_translate(varg,x,0); 837 Equation_vertical_adjust(vv.dy,vv.y,h,y); 838 vecteur res(1,varg); 839 // 2nd arg translated 840 if (needpar) 841 x+=vv.dx+lrp; 842 else 843 x+=vv.dx+1; 844 int arg1dy=vv.dy,arg1y=vv.y; 845 if (a.fontsize>=10){ 846 attributs aa(a); 847 aa.fontsize -= 2; 848 varg=Equation_compute_size(arg._VECTptr->back(),aa,windowhsize,contextptr); 849 } 850 else 851 varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr); 852 vv=Equation_total_size(varg); 853 Equation_translate(varg,x,arg1y+(3*arg1dy)/4-vv.y); 854 res.push_back(varg); 855 vv=Equation_total_size(varg); 856 Equation_vertical_adjust(vv.dy,vv.y,h,y); 857 x += vv.dx; 858 res.push_back(eqwdata(x,h,0,y,a,u,0)); 859 return gen(res,_SEQ__VECT); 860 } 861 if (u==at_factorial){ 862 vecteur v; 863 gen varg=Equation_compute_size(arg,a,windowhsize,contextptr); 864 eqwdata vv=Equation_total_size(varg); 865 bool paren=need_parenthesis(vv.g) || vv.g==at_prod || vv.g==at_division || vv.g==at_pow; 866 if (paren) 867 x+=llp; 868 Equation_translate(varg,x,0); 869 Equation_vertical_adjust(vv.dy,vv.y,h,y); 870 v.push_back(varg); 871 x += vv.dx; 872 if (paren) 873 x+=lrp; 874 varg=eqwdata(x+4,h,0,y,a,u,0); 875 v.push_back(varg); 876 return gen(v,_SEQ__VECT); 877 } 878 if (u==at_sto){ // A:=B, *it -> B 879 gen varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr); 880 eqwdata vv=Equation_total_size(varg); 881 Equation_vertical_adjust(vv.dy,vv.y,h,y); 882 Equation_translate(varg,x,0); 883 vecteur v(2); 884 v[1]=varg; 885 x+=vv.dx; 886 x+=ls+3; 887 // first arg not translated 888 varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr); 889 vv=Equation_total_size(varg); 890 if (need_parenthesis(vv.g)) 891 x+=llp; 892 Equation_translate(varg,x,0); 893 Equation_vertical_adjust(vv.dy,vv.y,h,y); 894 v[0]=varg; 895 x += vv.dx; 896 if (need_parenthesis(vv.g)) 897 x+=lrp; 898 v.push_back(eqwdata(x,h,0,y,a,u,0)); 899 return gen(v,_SEQ__VECT); 900 } 901 if (u==at_program && arg._VECTptr->back().type!=_VECT && !arg._VECTptr->back().is_symb_of_sommet(at_local) ){ 902 gen varg=Equation_compute_size(arg._VECTptr->front(),a,windowhsize,contextptr); 903 eqwdata vv=Equation_total_size(varg); 904 Equation_vertical_adjust(vv.dy,vv.y,h,y); 905 Equation_translate(varg,x,0); 906 vecteur v(2); 907 v[0]=varg; 908 x+=vv.dx; 909 x+=int(fl_width("->"))+3; 910 varg=Equation_compute_size(arg._VECTptr->back(),a,windowhsize,contextptr); 911 vv=Equation_total_size(varg); 912 Equation_translate(varg,x,0); 913 Equation_vertical_adjust(vv.dy,vv.y,h,y); 914 v[1]=varg; 915 x += vv.dx; 916 v.push_back(eqwdata(x,h,0,y,a,u,0)); 917 return gen(v,_SEQ__VECT); 918 } 919 bool binaryop= (u.ptr()->printsommet==&printsommetasoperator) || equalposcomp(binary_op_tab(),u); 920 if ( u!=at_sto && u.ptr()->printsommet!=NULL && !binaryop ){ 921 gen tmp=string2gen(g.print(contextptr),false); 922 return Equation_compute_size(symbolic(at_expr,gen(makevecteur(tmp,xcas_mode(contextptr)),_SEQ__VECT)),a,windowhsize,contextptr); 923 } 924 vecteur v; 925 if (!binaryop || arg.type!=_VECT) 926 v=Equation_subsizes(arg,a,windowhsize,contextptr); 927 else 928 v=Equation_subsizes(gen(*arg._VECTptr,_SEQ__VECT),a,windowhsize,contextptr); 929 iterateur it=v.begin(),itend=v.end(); 930 if ( it==itend || (itend-it==1) ){ 931 gen gtmp; 932 if (it==itend) 933 gtmp=Equation_compute_size(gen(vecteur(0),_SEQ__VECT),a,windowhsize,contextptr); 934 else 935 gtmp=*it; 936 // unary op, shift arg position horizontally 937 eqwdata vv=Equation_total_size(gtmp); 938 bool paren = u!=at_neg || (vv.g!=at_prod && need_parenthesis(vv.g)) ; 939 x=ls+(paren?llp:0); 940 gen tmp=gtmp; Equation_translate(tmp,x,0); 941 x=x+vv.dx+(paren?lrp:0); 942 Equation_vertical_adjust(vv.dy,vv.y,h,y); 943 return gen(makevecteur(tmp,eqwdata(x,h,0,y,a,u,0)),_EQW__VECT); 944 } 945 if (binaryop){ // op (default with par) 946 int currenth=h,largeur=0; 947 iterateur itprec=v.begin(); 948 h=0; 949 if (u==at_plus){ // op without parenthesis 950 llp=0; 951 lrp=0; 952 } 953 for (;;){ 954 eqwdata vv=Equation_total_size(*it); 955 if (need_parenthesis(vv.g)) 956 x+=llp; 957 if (u==at_plus && it!=v.begin() && 958 ( 959 (it->type==_VECT && it->_VECTptr->back().type==_EQW && it->_VECTptr->back()._EQWptr->g==at_neg) 960 || 961 ( it->type==_EQW && (is_integer(it->_EQWptr->g) || it->_EQWptr->g.type==_DOUBLE_) && is_strictly_positive(-it->_EQWptr->g,contextptr) ) 962 ) 963 ) 964 x -= ls; 965 if (x>windowhsize-vv.dx && x>windowhsize/2 && (itend-it)*vv.dx>windowhsize/2){ 966 largeur=max(x,largeur); 967 x=0; 968 if (need_parenthesis(vv.g)) 969 x+=llp; 970 h+=currenth; 971 Equation_translate(*it,x,0); 972 for (iterateur kt=v.begin();kt!=itprec;++kt) 973 Equation_translate(*kt,0,currenth); 974 if (y){ 975 for (iterateur kt=itprec;kt!=it;++kt) 976 Equation_translate(*kt,0,-y); 977 } 978 itprec=it; 979 currenth=vv.dy; 980 y=vv.y; 981 } 982 else { 983 Equation_translate(*it,x,0); 984 vv=Equation_total_size(*it); 985 Equation_vertical_adjust(vv.dy,vv.y,currenth,y); 986 } 987 x+=vv.dx; 988 if (need_parenthesis(vv.g)) 989 x+=lrp; 990 ++it; 991 if (it==itend){ 992 for (iterateur kt=v.begin();kt!=itprec;++kt) 993 Equation_translate(*kt,0,currenth+y); 994 h+=currenth; 995 v.push_back(eqwdata(max(x,largeur),h,0,y,a,u,0)); 996 // cerr << v << '\n'; 997 return gen(v,_SEQ__VECT); 998 } 999 x += ls+3; 1000 } 1001 } 1002 // normal printing 1003 x=ls+llp; 1004 for (;;){ 1005 eqwdata vv=Equation_total_size(*it); 1006 Equation_translate(*it,x,0); 1007 Equation_vertical_adjust(vv.dy,vv.y,h,y); 1008 x+=vv.dx; 1009 ++it; 1010 if (it==itend){ 1011 x+=lrp; 1012 v.push_back(eqwdata(x,h,0,y,a,u,0)); 1013 return gen(v,_SEQ__VECT); 1014 } 1015 x+=lc; 1016 } 1017 } 1018 1019 // windowhsize is used for g of type HIST__VECT (history) right justify answers 1020 // Returns either a eqwdata type object (terminal) or a vector 1021 // (of subtype _EQW__VECT or _HIST__VECT) Equation_compute_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT)1022 gen Equation_compute_size(const gen & g,const attributs & a,int windowhsize,GIAC_CONTEXT){ 1023 fl_font(FL_HELVETICA,a.fontsize); 1024 /************** 1025 * FL_WIDGET * 1026 **************/ 1027 if (g.type==_POINTER_) { 1028 if (g.subtype==_FL_WIDGET_POINTER){ 1029 Fl_Widget * wg=(Fl_Widget *) g._POINTER_val; 1030 return eqwdata(wg->w(),wg->h(),0,0,a,g); 1031 } 1032 #ifndef __APPLE__ 1033 if (g.subtype==_FL_IMAGE_POINTER){ 1034 Fl_Image * ptr=(Fl_Image *) g._POINTER_val; 1035 return eqwdata(ptr->w(),ptr->h(),0,0,a,g); 1036 } 1037 #endif 1038 } 1039 /*************** 1040 * STRINGS * 1041 ***************/ 1042 if (g.type==_STRNG){ 1043 string s; 1044 s=*g._STRNGptr; 1045 string cs; 1046 int ss=s.size(); 1047 /* if (!ss) 1048 return eqwdata(10,6,0,0,a,g); */ 1049 int hsize=0,vsize=0; 1050 bool newline=false; 1051 vecteur res; 1052 gen tmps; 1053 for (int pos=0;pos<ss;++pos){ 1054 char ch=s[pos]; 1055 if (ch=='\n'){ 1056 newline=true; 1057 hsize=max(hsize,int(fl_width((' '+cs).c_str()))); 1058 tmps=string2gen(cs,false); 1059 vsize+=a.fontsize; 1060 res.push_back(eqwdata(hsize,a.fontsize,0,-vsize,a,tmps)); 1061 cs=""; 1062 } 1063 else 1064 cs += ch; 1065 } 1066 hsize=max(hsize,int(fl_width((' '+cs).c_str()))); 1067 vsize+=a.fontsize; 1068 tmps=string2gen(cs,false); 1069 if (!newline){ 1070 tmps.subtype=g.subtype; 1071 return eqwdata(hsize,a.fontsize,0,0,a,tmps); 1072 } 1073 gen tmp=eqwdata(hsize,a.fontsize,0,-vsize,a,tmps); 1074 res.push_back(tmp); 1075 res.push_back(eqwdata(hsize,vsize,0,-vsize,a,at_multistring)); 1076 tmp= gen(res,_EQW__VECT); 1077 Equation_translate(tmp,0,vsize); 1078 return tmp; 1079 } 1080 /* SERIES */ 1081 if (g.type==_SPOL1){ 1082 int sf=series_flags(contextptr); 1083 if (sf & (1<<5) && !(sf & (1<<4))){ 1084 identificateur tt(string(1,series_variable_name(contextptr))); 1085 gen remains,gg=sparse_poly12gen(*g._SPOL1ptr,tt,remains,!(sf & (1<<6))); 1086 if ( (sf & (1<<6)) && !is_zero(remains)) 1087 gg += symb_of(gen("O",contextptr),remains); 1088 return Equation_compute_size(gg,a,windowhsize,contextptr); 1089 } 1090 } 1091 /***************** 1092 * FRACTIONS * 1093 *****************/ 1094 if (g.type==_FRAC){ 1095 if (is_integer(g._FRACptr->num) && is_positive(-g._FRACptr->num,contextptr)) 1096 return Equation_compute_size(symbolic(at_neg,fraction(-g._FRACptr->num,g._FRACptr->den)),a,windowhsize,contextptr); 1097 gen v1=Equation_compute_size(g._FRACptr->num,a,windowhsize,contextptr); 1098 eqwdata vv1=Equation_total_size(v1); 1099 gen v2=Equation_compute_size(g._FRACptr->den,a,windowhsize,contextptr); 1100 eqwdata vv2=Equation_total_size(v2); 1101 // Center the fraction 1102 int w1=vv1.dx,w2=vv2.dx; 1103 int w=max(w1,w2)+6; 1104 vecteur v(3); 1105 v[0]=v1; Equation_translate(v[0],(w-w1)/2,11-vv1.y); 1106 v[1]=v2; Equation_translate(v[1],(w-w2)/2,7-vv2.dy-vv2.y); 1107 v[2]=eqwdata(w,4+vv1.dy+vv2.dy,0,7-vv2.dy,a,at_division,0); 1108 return gen(v,_SEQ__VECT); 1109 } 1110 /*************** 1111 * VECTORS * 1112 ***************/ 1113 if ( (g.type==_VECT) && !g._VECTptr->empty() ){ 1114 if (g.subtype==_GRAPH__VECT){ 1115 string s; 1116 if (is_graphe(g,s,contextptr)) 1117 return Equation_compute_size(string2gen(s,false),a,windowhsize,contextptr); 1118 } 1119 if (g.subtype==_SPREAD__VECT) 1120 return Equation_compute_size(string2gen("spreadsheet",false),a,windowhsize,contextptr); 1121 vecteur v; 1122 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 1123 int x=0,y=0,h=a.fontsize; 1124 /*************** 1125 * HISTORY * 1126 ***************/ 1127 #if 0 1128 if (g.subtype==_HIST__VECT){ 1129 int l=windowhsize; 1130 vecteur vplot; 1131 for (int i=0;it!=itend;++it,++i){ 1132 gen tmpg(*it); 1133 if (!rpn_mode(contextptr) && it->type==_VECT && !it->_VECTptr->empty()){ 1134 if (it->_VECTptr->front().type==_STRNG) 1135 tmpg=makevecteur(it->_VECTptr->front(),string2gen("",false)); 1136 gen tmpback=it->_VECTptr->back(); 1137 if (tmpback.type==_POINTER_ && tmpback.subtype==_FL_WIDGET_POINTER && fl_widget_updatepict_function) 1138 tmpback = fl_widget_updatepict_function(tmpback); 1139 if (tmpback.is_symb_of_sommet(at_pnt) || (tmpback.type==_VECT && !tmpback._VECTptr->empty() && tmpback._VECTptr->back().is_symb_of_sommet(at_pnt))) 1140 vplot.push_back(tmpback); 1141 if (tmpback.is_symb_of_sommet(at_erase)) 1142 vplot.clear(); 1143 gen itfront=it->_VECTptr->front(); 1144 if (itfront.is_symb_of_sommet(at_expr)){ 1145 itfront=itfront._SYMBptr->feuille; 1146 int mode=xcas_mode(contextptr); 1147 if (itfront.type==_VECT && !itfront._VECTptr->empty()){ 1148 mode=itfront._VECTptr->back().val; 1149 itfront=itfront._VECTptr->front(); 1150 } 1151 if (itfront.type==_STRNG){ 1152 int save_maple_mode=xcas_mode(contextptr); 1153 xcas_mode(contextptr)=mode; 1154 try { 1155 itfront=gen(*itfront._STRNGptr,contextptr); 1156 } catch (std::runtime_error & e){ 1157 } 1158 xcas_mode(contextptr)=save_maple_mode; 1159 } 1160 } 1161 } 1162 tmpg.subtype=_SEQ__VECT; 1163 vecteur tmp(Equation_subsizes(tmpg,a,windowhsize,contextptr)); 1164 iterateur jt=tmp.begin(); // this is the question 1165 // compute the size of writing the history level i 1166 eqwdata w(Equation_total_size(*jt)); 1167 if (rpn_mode(contextptr)) // ignore question 1168 v.push_back(eqwdata(1,1,x,-y,w.eqw_attributs,string2gen("",false))); 1169 else { 1170 y += w.dy + 2; 1171 x = int(fl_width((print_INT_(i)+": ").c_str())); 1172 if (l<w.dx+x) 1173 l=w.dx+x; 1174 Equation_translate(*jt,x,-y-w.y); v.push_back(*jt); 1175 } 1176 jt=tmp.end()-1; // this is the answer 1177 *jt=Equation_change_attributs(*jt,attributs(a.fontsize,a.background,a.text_color+4)); 1178 w=Equation_total_size(*jt); 1179 y += w.dy + 2; 1180 x = int(fl_width(" ")); 1181 l=max(l,w.dx+x); 1182 int xshift=x; 1183 if (w.dx+4<windowhsize-a.fontsize){ 1184 if (center_history) 1185 xshift=(windowhsize-w.dx-4)/2; 1186 else 1187 xshift=windowhsize-w.dx-4-a.fontsize; 1188 } 1189 Equation_translate(*jt,xshift,-y-w.y); v.push_back(*jt); 1190 } 1191 v.push_back(eqwdata(l,y,0,-y,a,at_makevector,0)); 1192 // cerr << v << '\n'; 1193 gen res=gen(v,_HIST__VECT); Equation_translate(res,0,y); return res; 1194 } // END HISTORY 1195 #else 1196 if (g.subtype==_HIST__VECT){ 1197 vecteur v; 1198 v.reserve(g._VECTptr->size()); 1199 // vertical gluing 1200 int W=0,H=0; 1201 for (int i=0;it!=itend;++it,++i){ 1202 gen g=*it; 1203 if (g.type==_VECT && g.subtype==_SEQ__VECT) 1204 g.subtype=_PRINT__VECT; 1205 gen cur_size=Equation_compute_size(g,a,windowhsize,contextptr); 1206 eqwdata tmp=Equation_total_size(cur_size); 1207 #if 0 1208 int Y,dY; 1209 Equation_y_dy(cur_size,Y,dY); 1210 Equation_translate(cur_size,0,Y-y-H); 1211 H += dY+2; 1212 #else 1213 if (ckmatrix(*it)) 1214 Equation_translate(cur_size,0,tmp.y-y-H+a.fontsize/2); 1215 else 1216 Equation_translate(cur_size,0,tmp.y-y-H-a.fontsize/2); 1217 H += tmp.dy+2; 1218 #endif 1219 v.push_back(cur_size); 1220 W = giacmax(W,tmp.dx); 1221 } 1222 gen mkvect(at_makevector); 1223 mkvect.subtype=_PRINT__VECT; 1224 v.push_back(eqwdata(W,H,0,-y-H,a,mkvect,0)); 1225 return gen(v,_EQW__VECT); 1226 } // END HISTORY 1227 #endif 1228 /*************** 1229 * MATRICE * 1230 ***************/ 1231 bool gmat=ckmatrix(g); 1232 vector<int> V; int p=0; 1233 if (!gmat && is_mod_vecteur(*g._VECTptr,V,p) && p!=0){ 1234 gen gm=makemodquoted(unmod(g),p); 1235 return Equation_compute_size(gm,a,windowhsize,contextptr); 1236 } 1237 vector< vector<int> > M; 1238 if (gmat && is_mod_matrice(*g._VECTptr,M,p) && p!=0){ 1239 gen gm=makemodquoted(unmod(g),p); 1240 return Equation_compute_size(gm,a,windowhsize,contextptr); 1241 } 1242 if (gmat && g.subtype!=_SEQ__VECT && g.subtype!=_SET__VECT && g.subtype!=_POLY1__VECT && g._VECTptr->front().subtype!=_SEQ__VECT){ 1243 gen mkvect(at_makevector); 1244 mkvect.subtype=_SEQ__VECT; 1245 gen mkmat(at_makevector); 1246 mkmat.subtype=_MATRIX__VECT; 1247 int nrows,ncols; 1248 mdims(*g._VECTptr,nrows,ncols); 1249 if (ncols){ 1250 vecteur all_sizes; 1251 all_sizes.reserve(nrows); 1252 vector<int> row_heights(nrows),row_bases(nrows),col_widths(ncols); 1253 // vertical gluing 1254 for (int i=0;it!=itend;++it,++i){ 1255 gen tmpg=*it; 1256 tmpg.subtype=_SEQ__VECT; 1257 vecteur tmp(Equation_subsizes(tmpg,a,max(windowhsize/ncols-a.fontsize,230),contextptr)); 1258 int h=a.fontsize,y=0; 1259 const_iterateur jt=tmp.begin(),jtend=tmp.end(); 1260 for (int j=0;jt!=jtend;++jt,++j){ 1261 eqwdata w(Equation_total_size(*jt)); 1262 Equation_vertical_adjust(w.dy,w.y,h,y); 1263 col_widths[j]=max(col_widths[j],w.dx); 1264 } 1265 if (i) 1266 row_heights[i]=row_heights[i-1]+h+a.fontsize; 1267 else 1268 row_heights[i]=h; 1269 row_bases[i]=y; 1270 all_sizes.push_back(tmp); 1271 } 1272 // accumulate col widths 1273 col_widths.front() +=(3*a.fontsize)/2; 1274 vector<int>::iterator iit=col_widths.begin()+1,iitend=col_widths.end(); 1275 for (;iit!=iitend;++iit) 1276 *iit += *(iit-1)+a.fontsize; 1277 // translate each cell 1278 it=all_sizes.begin(); 1279 itend=all_sizes.end(); 1280 int h,y,prev_h=0; 1281 for (int i=0;it!=itend;++it,++i){ 1282 h=row_heights[i]; 1283 y=row_bases[i]; 1284 iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end(); 1285 for (int j=0;jt!=jtend;++jt,++j){ 1286 eqwdata w(Equation_total_size(*jt)); 1287 if (j) 1288 Equation_translate(*jt,col_widths[j-1]-w.x,-h-y); 1289 else 1290 Equation_translate(*jt,-w.x+a.fontsize/2,-h-y); 1291 } 1292 it->_VECTptr->push_back(eqwdata(col_widths.back(),h-prev_h,0,-h,a,mkvect,0)); 1293 prev_h=h; 1294 } 1295 all_sizes.push_back(eqwdata(col_widths.back(),row_heights.back(),0,-row_heights.back(),a,mkmat,-row_heights.back()/2)); 1296 gen all_sizesg=all_sizes; Equation_translate(all_sizesg,0,row_heights.back()/2); return all_sizesg; 1297 } 1298 } // end matrices 1299 /************************* 1300 * SEQUENCES/VECTORS * 1301 *************************/ 1302 // horizontal gluing 1303 if (g.subtype!=_PRINT__VECT) x += a.fontsize/2; 1304 int ncols=itend-it; 1305 //ncols=min(ncols,5); 1306 for (;it!=itend;++it){ 1307 gen cur_size=Equation_compute_size(*it,a, 1308 max(windowhsize/ncols-a.fontsize, 1309 #ifdef IPAQ 1310 200 1311 #else 1312 480 1313 #endif 1314 ),contextptr); 1315 eqwdata tmp=Equation_total_size(cur_size); 1316 Equation_translate(cur_size,x-tmp.x,0); v.push_back(cur_size); 1317 x=x+tmp.dx+((g.subtype==_PRINT__VECT)?2:a.fontsize); 1318 Equation_vertical_adjust(tmp.dy,tmp.y,h,y); 1319 } 1320 gen mkvect(at_makevector); 1321 if (g.subtype==_SEQ__VECT) 1322 mkvect=at_makesuite; 1323 else 1324 mkvect.subtype=g.subtype; 1325 v.push_back(eqwdata(x,h,0,y,a,mkvect,0)); 1326 return gen(v,_EQW__VECT); 1327 } // end sequences 1328 if (g.type==_MOD){ 1329 int x=0; 1330 int h=a.fontsize; 1331 int y=0; 1332 bool py=python_compat(contextptr); 1333 int modsize=int(fl_width(py?" mod ":"%"))+4; 1334 bool paren=g._MODptr->type==_SYMB || is_positive(-*g._MODptr,contextptr); 1335 int llp=int(fl_width("(")); 1336 int lrp=int(fl_width(")")); 1337 gen varg1=Equation_compute_size(*g._MODptr,a,windowhsize,contextptr); 1338 if (paren) Equation_translate(varg1,llp,0); 1339 eqwdata vv=Equation_total_size(varg1); 1340 Equation_vertical_adjust(vv.dy,vv.y,h,y); 1341 gen arg2=*(g._MODptr+1); 1342 gen varg2=Equation_compute_size(arg2,a,windowhsize,contextptr); 1343 if (paren) 1344 Equation_translate(varg2,vv.dx+modsize+lrp,0); 1345 else 1346 Equation_translate(varg2,vv.dx+modsize,0); 1347 vv=Equation_total_size(varg2); 1348 Equation_vertical_adjust(vv.dy,vv.y,h,y); 1349 vecteur res(makevecteur(varg1,varg2)); 1350 res.push_back(eqwdata(vv.dx+vv.x,h,0,y,a,at_normalmod,0)); 1351 return gen(res,_SEQ__VECT); 1352 } 1353 if (g.type==_USER){ 1354 if (giac::galois_field *gptr=dynamic_cast<giac::galois_field *>(g._USERptr)){ 1355 if (gptr->a.type==_VECT && gptr->a._VECTptr->size()==1) 1356 return Equation_compute_size(makemod(gptr->a._VECTptr->front(),gptr->p),a,windowhsize,contextptr); 1357 gen g1(g.print(contextptr),contextptr); 1358 return Equation_compute_size(g1,a,windowhsize,contextptr); 1359 } 1360 } 1361 if (g.type!=_SYMB){ 1362 string s=g.print(contextptr); 1363 if (s.size()>2000) 1364 s=s.substr(0,2000)+"..."; 1365 fl_font(cst_greek_translate(s),a.fontsize); 1366 int i=int(fl_width(s.c_str())); 1367 gen tmp=eqwdata(i,a.fontsize,0,0,a,g); 1368 return tmp; 1369 } 1370 /********************** 1371 * SYMBOLIC HANDLING * 1372 **********************/ 1373 vecteur li(lidnt(g)); 1374 if (g.type==_SYMB && g._SYMBptr->sommet!=at_prod && g._SYMBptr->sommet!=at_pow && lvar(g)==li && lop(g,at_inv).empty()){ 1375 // polynomial check if it has modular coefficients 1376 gen p,modulo; 1377 try { 1378 p=_symb2poly(makesequence(g,li),contextptr); 1379 } 1380 catch (std::runtime_error & error){ 1381 p=undef; 1382 } 1383 if (p.type==_POLY && has_mod_coeff(p,modulo)){ 1384 polynome & P=*p._POLYptr; 1385 vector< monomial<gen> >::iterator it=P.coord.begin(),itend=P.coord.end(); 1386 for (;it!=itend;++it){ 1387 if (it->value.type==_MOD){ 1388 if (*(it->value._MODptr+1)!=modulo) 1389 break; 1390 it->value=*it->value._MODptr; 1391 } 1392 } 1393 if (it==itend){ 1394 p=makemod(_poly2symb(makesequence(P,li),contextptr),modulo); 1395 return Equation_compute_size(p,a,windowhsize,contextptr); 1396 } 1397 } 1398 } 1399 return Equation_compute_symb_size(g,a,windowhsize,contextptr); 1400 // return Equation_compute_symb_size(aplatir_fois_plus(g),a,windowhsize,contextptr); 1401 // aplatir_fois_plus is a problem for Equation_replace_selection 1402 // because it will modify the structure of the data 1403 } 1404 Equation_extract_string(const string & cs,int begin_sel,int end_sel)1405 string Equation_extract_string(const string & cs,int begin_sel,int end_sel){ 1406 int css=cs.size(); 1407 if (!css) 1408 return cs; 1409 int sel0=min(max(0,begin_sel),css-1),sel1=css; 1410 if (end_sel>=0) 1411 sel1=min(end_sel,css); 1412 if (sel0>sel1) 1413 giac::swapint(sel0,sel1); 1414 return cs.substr(sel0,sel1-sel0); 1415 } 1416 Equation_draw(const eqwdata & e,int x,int y,int rightx,int lowery,Equation * eq,int begin_sel,int end_sel)1417 void Equation_draw(const eqwdata & e,int x,int y,int rightx,int lowery,Equation * eq,int begin_sel,int end_sel){ 1418 if ( (e.dx+e.x<x) || (e.x>rightx) || (e.y>y) || e.y+e.dy<lowery) 1419 return; // nothing to draw, out of window 1420 const giac::context * contextptr = get_context(eq); 1421 gen gg=e.g; 1422 bool selected=e.selected && Fl::focus()==eq; 1423 int fontsize=e.eqw_attributs.fontsize; 1424 Fl_Color text_color=Fl_Color(e.eqw_attributs.text_color); 1425 Fl_Color background=Fl_Color(e.eqw_attributs.background); 1426 fl_font(FL_HELVETICA,fontsize); 1427 fl_color(selected?background:text_color); 1428 if (gg.type==_POINTER_) { 1429 // wg->resize(e.x-x,y-e.y-e.dy,e.dx,e.dy); 1430 // wg->draw(); // automatically done if it belongs to the group 1431 return; 1432 } 1433 if (gg.type==_STRNG){ 1434 string s; 1435 if (e.active){ 1436 // draw s and the cursor 1437 s=*gg._STRNGptr; 1438 int ss=s.size(); 1439 int pos=max(min(eq->active_pos,ss),0); 1440 if (eq->need_active_parse) 1441 s=s.substr(0,pos)+"|"+s.substr(pos,ss-pos); 1442 else 1443 s='"'+s.substr(0,pos)+"|"+s.substr(pos,ss-pos); 1444 } 1445 else { 1446 if (gg.subtype) 1447 s='"'+*gg._STRNGptr; 1448 else 1449 s=' '+*gg._STRNGptr; 1450 } 1451 string cs; 1452 int ss=s.size(); 1453 int vsize = fontsize -2,pos; 1454 for (pos=0;pos<ss;++pos){ 1455 char ch=s[pos]; 1456 if (ch=='\n'){ 1457 check_fl_draw(cs.c_str(),eq->x()+e.x-x,eq->y()+y-e.y+vsize-e.dy,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1458 cs=""; 1459 vsize += fontsize; 1460 } 1461 else 1462 cs += ch; 1463 } 1464 check_fl_draw(cs.c_str(),eq->x()+e.x-x,eq->y()+y-e.y+vsize-e.dy,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1465 // If selected take care of begin/end selection 1466 int css=cs.size(); // must be >=1 since selected hence not active 1467 if (selected && css){ 1468 int sel0=min(begin_sel+1,css-1),sel1=css; 1469 if (end_sel>=0) 1470 sel1=min(end_sel+1,css); 1471 if (sel0>sel1) 1472 giac::swapint(sel0,sel1); 1473 int deltax=int(fl_width(cs.substr(0,sel0).c_str())); 1474 cs=cs.substr(sel0,sel1-sel0); 1475 int dx=int(fl_width(cs.c_str())); 1476 fl_color(text_color); 1477 check_fl_rectf(eq->x()+e.x-x+deltax,eq->y()+y-e.y-e.dy+1,dx,e.dy+3,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1478 fl_color(background); 1479 check_fl_draw(cs.c_str(),eq->x()+e.x-x+deltax,eq->y()+y-e.y+vsize-e.dy,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1480 } 1481 return; 1482 } 1483 if (selected){ 1484 fl_color(text_color); 1485 check_fl_rectf(eq->x()+e.x-x,eq->y()+y-e.y-e.dy+1,e.dx,e.dy+3,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1486 fl_color(background); 1487 } 1488 string s=gg.print(contextptr); 1489 if (gg.type==_IDNT && !s.empty() && s[0]=='_') 1490 s=s.substr(1,s.size()-1); 1491 if (s.size()>2000) 1492 s=s.substr(0,2000)+"..."; 1493 Fl_Font font=cst_greek_translate(s); 1494 if (gg.type==_IDNT && font==FL_HELVETICA 1495 #if !defined(WIN32) && !defined(__APPLE__) 1496 && gg!=cst_pi 1497 #endif 1498 ) 1499 font=FL_TIMES_BOLD_ITALIC; // FL_HELVETICA_BOLD_ITALIC; 1500 fl_font(font,fontsize); 1501 // cerr << s.size() << '\n'; 1502 check_fl_draw(s.c_str(),eq->x()+e.x-x,eq->y()+y-e.y,eq->clip_x,eq->clip_y,eq->clip_w,eq->clip_h,0,0); 1503 return; 1504 } 1505 Equation_draw(const gen & g,int x,int y,int rightx,int lowery,Equation * equat)1506 void Equation_draw(const gen & g,int x,int y,int rightx,int lowery,Equation * equat){ 1507 const giac::context * contextptr = get_context(equat); 1508 int eqx=equat->x(),eqy=equat->y(); 1509 if (g.type==_EQW){ // terminal 1510 eqwdata & e=*g._EQWptr; 1511 Equation_draw(e,x,y,rightx,lowery,equat,equat->begin_sel,equat->end_sel); 1512 } 1513 if (g.type!=_VECT) 1514 return; 1515 vecteur & v=*g._VECTptr; 1516 if (v.empty()) 1517 return; 1518 gen tmp=v.back(); 1519 if (tmp.type!=_EQW){ 1520 cerr << "EQW error:" << v << '\n'; 1521 return; 1522 } 1523 eqwdata & w=*tmp._EQWptr; 1524 if ( (w.dx+w.x-x<0) || (w.x>rightx) || (w.y>y) || (w.y+w.dy<lowery) ) 1525 return; // nothing to draw, out of window 1526 /******************* 1527 * draw the vector * 1528 *******************/ 1529 // v is the vector, w the master operator eqwdata 1530 gen oper=w.g; 1531 bool selected=w.selected && Fl::focus()==equat; 1532 int fontsize=w.eqw_attributs.fontsize; 1533 int background=w.eqw_attributs.background; 1534 int text_color=w.eqw_attributs.text_color; 1535 int x0=w.x; 1536 int y0=w.y; // lower coordinate of the master vector 1537 int y1=y0+w.dy; // upper coordinate of the master vector 1538 if (selected){ 1539 fl_color(text_color); 1540 check_fl_rectf(eqx+w.x-x,eqy+y-w.y-w.dy+1,w.dx,w.dy+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1541 } 1542 else { 1543 fl_color(background); 1544 // fl_rectf(w.x-x,y-w.y-w.dy,w.dx,w.dy-2); 1545 } 1546 // draw arguments of v 1547 const_iterateur it=v.begin(),itend=v.end()-1; 1548 if (oper==at_multistring){ 1549 const_iterateur it_beg=it,it_end=itend; 1550 if (Equation_multistring_selection(it_beg,it_end,false)){ 1551 // begin_sel and end_sel apply respect. to it_beg and it_end sel. lines 1552 for (;it!=it_beg;++it) 1553 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,-1,-1); 1554 if (it_beg==it_end){ 1555 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,equat->begin_sel,equat->end_sel); 1556 ++it; 1557 } 1558 else { 1559 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,equat->begin_sel,-1); 1560 ++it; 1561 for (;it!=it_end;++it) 1562 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,-1,-1); 1563 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,-1,equat->end_sel); 1564 ++it; 1565 } 1566 for (;it!=itend;++it) 1567 Equation_draw(*it->_EQWptr,x,y,rightx,lowery,equat,-1,-1); 1568 return; 1569 } 1570 } 1571 if (oper==at_expr && v.size()==3){ 1572 Equation_draw(*it,x,y,rightx,lowery,equat); 1573 return; 1574 } 1575 for (;it!=itend;++it) 1576 Equation_draw(*it,x,y,rightx,lowery,equat); 1577 if (oper==at_multistring) 1578 return; 1579 fl_font(FL_HELVETICA,fontsize); 1580 fl_color(selected?background:text_color); 1581 string s; 1582 if (g.subtype==_HIST__VECT){ // For history, we must write history levels 1583 it=v.begin(); 1584 int nlevels=(itend-it)/2-1,wlevel; 1585 int skip=2; // int skip=2-rpn_mode(contextptr); 1586 for (int i=0;it!=itend;it+=skip,++i){ 1587 eqwdata tmp=Equation_total_size(*it); 1588 fl_font(FL_HELVETICA,tmp.eqw_attributs.fontsize); 1589 fl_color(FL_BLUE); 1590 // cerr << tmp << '\n'; 1591 int yy; 1592 // uncommented, seemed previously to be problematic with strings 1593 if (tmp.hasbaseline) 1594 yy=y-tmp.baseline; 1595 else 1596 yy=y-tmp.y-(tmp.dy-tmp.eqw_attributs.fontsize)/2; 1597 if (yy<0 || yy>y-lowery) 1598 continue; 1599 if (rpn_mode(contextptr)) 1600 wlevel=nlevels-i; 1601 else 1602 wlevel=i; 1603 if (wlevel || !rpn_mode(contextptr)) 1604 check_fl_draw((print_INT_(wlevel)+": ").c_str(),eqx-x,eqy+yy,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1605 } 1606 return; // nothing else to do 1607 } 1608 if (oper.type==_FUNC){ 1609 // catch here special cases user function, vect/matr, ^, int, sqrt, etc. 1610 unary_function_ptr & u=*oper._FUNCptr; 1611 if (u==at_at){ // draw brackets around 2nd arg 1612 gen arg2=v[1]; // 2nd arg of at_of, i.e. what's inside the parenth. 1613 eqwdata varg2=Equation_total_size(arg2); 1614 x0=varg2.x; 1615 y0=varg2.y; 1616 y1=y0+varg2.dy; 1617 fontsize=varg2.eqw_attributs.fontsize; 1618 fl_font(FL_HELVETICA,fontsize); 1619 if (x0<rightx) 1620 check_fl_draw("[",eqx+x0-x-int(fl_width("[")),eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1621 x0 += varg2.dx ; 1622 if (x0<rightx) 1623 check_fl_draw("]",eqx+x0-x,eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1624 return; 1625 } 1626 if (u==at_of){ // do we need to draw some parenthesis? 1627 gen arg2=v[1]; // 2nd arg of at_of, i.e. what's inside the parenth. 1628 if (arg2.type!=_VECT || arg2._VECTptr->back().type !=_EQW || arg2._VECTptr->back()._EQWptr->g!=at_makesuite){ // Yes (if not _EQW it's a sequence with parent) 1629 eqwdata varg2=Equation_total_size(arg2); 1630 x0=varg2.x; 1631 y0=varg2.y; 1632 y1=y0+varg2.dy; 1633 fontsize=varg2.eqw_attributs.fontsize; 1634 int pfontsize=max(fontsize,(fontsize+(varg2.baseline-varg2.y))/2); 1635 fl_font(FL_HELVETICA,pfontsize); // was fontsize 1636 if (x0<rightx) 1637 check_fl_draw("(",eqx+x0-x-int(fl_width("(")),eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1638 x0 += varg2.dx ; 1639 if (x0<rightx) 1640 check_fl_draw(")",eqx+x0-x,eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1641 } 1642 return; 1643 } 1644 if (u==at_makesuite){ 1645 bool paren=v.size()!=2; // Sequences with 1 arg don't show parenthesis 1646 int pfontsize=max(fontsize,(fontsize+(w.baseline-w.y))/2); 1647 fl_font(FL_HELVETICA,pfontsize); 1648 if (paren && x0<rightx) 1649 check_fl_draw("(",eqx+x0-x-int(fl_width("("))/2,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1650 x0 += w.dx; 1651 if (paren && x0<rightx) 1652 check_fl_draw(")",eqx+x0-x-int(fl_width("("))/2,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1653 // print commas between args 1654 it=v.begin(),itend=v.end()-2; 1655 for (;it!=itend;++it){ 1656 eqwdata varg2=Equation_total_size(*it); 1657 fontsize=varg2.eqw_attributs.fontsize; 1658 fl_font(FL_HELVETICA,fontsize); 1659 if (varg2.x+varg2.dx<rightx) 1660 check_fl_draw(",",eqx+varg2.x+varg2.dx-x+1,eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1661 } 1662 return; 1663 } 1664 if (u==at_makevector){ // draw [] delimiters for vector/matrices 1665 if (oper.subtype!=_SEQ__VECT && oper.subtype!=_PRINT__VECT){ 1666 int decal=1; 1667 switch (oper.subtype){ 1668 case _MATRIX__VECT: decal=2; break; 1669 case _SET__VECT: decal=4; break; 1670 case _POLY1__VECT: decal=6; break; 1671 } 1672 if (x0+1<rightx){ 1673 check_fl_line(eqx+x0-x+1,eqy+y-y0+1,eqx+x0-x+1,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1674 check_fl_line(eqx+x0-x+decal,eqy+y-y0+1,eqx+x0-x+decal,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1675 check_fl_line(eqx+x0-x+1,eqy+y-y0+1,eqx+x0-x+fontsize/4,eqy+y-y0+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1676 check_fl_line(eqx+x0-x+1,eqy+y-y1+1,eqx+x0-x+fontsize/4,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1677 } 1678 x0 += w.dx ; 1679 if (x0-1<rightx){ 1680 check_fl_line(eqx+x0-x-1,eqy+y-y0+1,eqx+x0-x-1,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1681 check_fl_line(eqx+x0-x-decal,eqy+y-y0+1,eqx+x0-x-decal,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1682 check_fl_line(eqx+x0-x-1,eqy+y-y0+1,eqx+x0-x-fontsize/4,eqy+y-y0+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1683 check_fl_line(eqx+x0-x-1,eqy+y-y1+1,eqx+x0-x-fontsize/4,eqy+y-y1+1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1684 } 1685 } // end if oper.subtype!=SEQ__VECT 1686 if (oper.subtype!=_MATRIX__VECT && oper.subtype!=_PRINT__VECT){ 1687 // print commas between args 1688 it=v.begin(),itend=v.end()-2; 1689 for (;it!=itend;++it){ 1690 eqwdata varg2=Equation_total_size(*it); 1691 fontsize=varg2.eqw_attributs.fontsize; 1692 fl_font(FL_HELVETICA,fontsize); 1693 if (varg2.x+varg2.dx<rightx) 1694 check_fl_draw(",",eqx+varg2.x+varg2.dx-x+1,eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1695 } 1696 } 1697 return; 1698 } 1699 int lpsize=int(fl_width("(")); 1700 int rpsize=int(fl_width(")")); 1701 eqwdata tmp=Equation_total_size(v.front()); // tmp= 1st arg eqwdata 1702 if (u==at_sto) 1703 tmp=Equation_total_size(v[1]); 1704 x0=w.x-x; 1705 y0=y-w.baseline; 1706 if (u==at_pow){ 1707 if (!need_parenthesis(tmp.g)&& tmp.g!=at_pow && tmp.g!=at_prod && tmp.g!=at_division) 1708 return; 1709 if (tmp.g==at_pow){ 1710 fontsize=tmp.eqw_attributs.fontsize+2; 1711 fl_font(FL_HELVETICA,fontsize); 1712 } 1713 if (tmp.x-lpsize<rightx) 1714 check_fl_draw("(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1715 if (tmp.x+tmp.dx<rightx) 1716 check_fl_draw(")",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1717 return; 1718 } 1719 if (u==at_program){ 1720 if (tmp.x+tmp.dx<rightx) 1721 check_fl_draw("->",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1722 return; 1723 } 1724 if (u==at_sum){ 1725 if (x0<rightx){ 1726 check_fl_line(eqx+x0,eqy+y0,eqx+x0+(2*fontsize)/3,eqy+y0,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1727 check_fl_line(eqx+x0,eqy+y0-fontsize,eqx+x0+(2*fontsize)/3,eqy+y0-fontsize,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1728 check_fl_line(eqx+x0,eqy+y0,eqx+x0+fontsize/2,eqy+y0-fontsize/2,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1729 check_fl_line(eqx+x0+fontsize/2,eqy+y0-fontsize/2,eqx+x0,eqy+y0-fontsize,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1730 if (v.size()>2){ // draw the = 1731 eqwdata ptmp=Equation_total_size(v[1]); 1732 if (ptmp.x+ptmp.dx<rightx) 1733 check_fl_draw("=",eqx+ptmp.x+ptmp.dx-x-2,eqy+y-ptmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1734 } 1735 } 1736 return; 1737 } 1738 if (u==at_abs){ 1739 y0 =1+y-w.y; 1740 int h=w.dy; 1741 if (x0<rightx){ 1742 check_fl_line(eqx+x0+2,eqy+y0-1,eqx+x0+2,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1743 check_fl_line(eqx+x0+1,eqy+y0-1,eqx+x0+1,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1744 check_fl_line(eqx+x0+w.dx-1,eqy+y0-1,eqx+x0+w.dx-1,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1745 check_fl_line(eqx+x0+w.dx,eqy+y0-1,eqx+x0+w.dx,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1746 } 1747 return; 1748 } 1749 if (u==at_sqrt){ 1750 y0 =1+y-w.y; 1751 int h=w.dy; 1752 if (x0<rightx){ 1753 check_fl_line(eqx+x0+2,eqy+y0-h/2,eqx+x0+fontsize/2,eqy+y0-1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1754 check_fl_line(eqx+x0+fontsize/2,eqy+y0-1,eqx+x0+fontsize,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1755 check_fl_line(eqx+x0+fontsize,eqy+y0-h+3,eqx+x0+w.dx-1,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1756 ++y0; 1757 check_fl_line(eqx+x0+2,eqy+y0-h/2,eqx+x0+fontsize/2,eqy+y0-1,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1758 check_fl_line(eqx+x0+fontsize/2,eqy+y0-1,eqx+x0+fontsize,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1759 check_fl_line(eqx+x0+fontsize,eqy+y0-h+3,eqx+x0+w.dx-1,eqy+y0-h+3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1760 } 1761 return; 1762 } 1763 if (u==at_factorial){ 1764 check_fl_draw("!",eqx+w.x+w.dx-4-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1765 if (!need_parenthesis(tmp.g) 1766 && tmp.g!=at_pow && tmp.g!=at_prod && tmp.g!=at_division 1767 ) 1768 return; 1769 if (tmp.x-lpsize<rightx) 1770 check_fl_draw("(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1771 if (tmp.x+tmp.dx<rightx) 1772 check_fl_draw(")",eqx+tmp.x+tmp.dx-x,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1773 return; 1774 } 1775 if (u==at_integrate){ 1776 x0+=2; 1777 y0+=fontsize/2; 1778 if (x0<rightx){ 1779 fl_arc(eqx+x0,eqy+y0,fontsize/3,fontsize/3,180,360); 1780 check_fl_line(eqx+x0+fontsize/3,eqy+y0,eqx+x0+fontsize/3,eqy+y0-2*fontsize+4,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1781 fl_arc(eqx+x0+fontsize/3,eqy+y0-2*fontsize+3,fontsize/3,fontsize/3,0,180); 1782 } 1783 if (v.size()!=2){ // if arg has size > 1 draw the d 1784 eqwdata ptmp=Equation_total_size(v[1]); 1785 if (ptmp.x<rightx) 1786 check_fl_draw(" d",eqx+ptmp.x-x-int(fl_width(" d")),eqy+y-ptmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1787 } 1788 else { 1789 eqwdata ptmp=Equation_total_size(v[0]); 1790 if (ptmp.x+ptmp.dx<rightx) 1791 check_fl_draw(" dx",eqx+ptmp.x+ptmp.dx-x,eqy+y-ptmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1792 } 1793 return; 1794 } 1795 if (u==at_division){ 1796 if (x0<rightx){ 1797 int yy=eqy+y0-6; 1798 check_fl_line(eqx+x0+2,yy,eqx+x0+w.dx-2,yy,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1799 ++yy; 1800 check_fl_line(eqx+x0+2,yy,eqx+x0+w.dx-2,yy,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1801 } 1802 return; 1803 } 1804 if (u==at_limit && v.size()>=4){ 1805 if (x0<rightx) 1806 check_fl_draw("lim",eqx+w.x-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1807 gen arg2=v[1]; // 2nd arg of limit, i.e. the variable 1808 if (arg2.type==_EQW){ 1809 eqwdata & varg2=*arg2._EQWptr; 1810 if (varg2.x+varg2.dx+2<rightx) 1811 check_fl_draw("->",eqx+varg2.x+varg2.dx+2-x,eqy+y-varg2.y,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1812 } 1813 if (v.size()>=5){ 1814 arg2=v[2]; // 3rd arg of lim, the point, draw a comma after if dir. 1815 if (arg2.type==_EQW){ 1816 eqwdata & varg2=*arg2._EQWptr; 1817 if (varg2.x+varg2.dx<rightx) 1818 check_fl_draw(",",eqx+varg2.x+varg2.dx-x,eqy+y-varg2.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1819 } 1820 } 1821 return; 1822 } 1823 bool parenthesis=true; 1824 string opstring(","); 1825 if (u.ptr()->printsommet==&printsommetasoperator || equalposcomp(binary_op_tab(),u) ){ 1826 if (u==at_normalmod && python_compat(contextptr)) 1827 opstring=" mod"; 1828 else 1829 opstring=u.ptr()->s; 1830 } 1831 else { 1832 if (u==at_sto) 1833 opstring=":="; 1834 parenthesis=false; 1835 } 1836 // int yy=y0; // y0 is the lower coordinate of the whole eqwdata 1837 // int opsize=int(fl_width(opstring.c_str()))+3; 1838 it=v.begin(); 1839 itend=v.end()-1; 1840 // Reminder: here tmp is the 1st arg eqwdata, w the whole eqwdata 1841 if ( (itend-it==1) && ( (u==at_neg) 1842 || (u==at_plus) // uncommented for +infinity 1843 ) ){ 1844 if (u==at_neg &&need_parenthesis(tmp.g) && tmp.g!=at_prod){ 1845 if (tmp.x-lpsize<rightx) 1846 check_fl_draw("(",eqx+tmp.x-x-lpsize,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1847 if (tmp.x+tmp.dx<rightx) 1848 check_fl_draw(")",eqx+tmp.x-x+tmp.dx,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1849 } 1850 if (w.x<rightx){ 1851 #if 1 1852 if (u==at_neg){ 1853 int xx=w.x-x; 1854 int cx=eqx+xx+2,cy=eqy+y-w.baseline-fontsize/3,ch=giacmax(2,(fontsize+5)/6); 1855 if (fontsize<16) --cx; else ++cy; 1856 if (fontsize<12) --cx; 1857 if (fontsize>23) ++cx; 1858 if (fontsize>29) ++cx; 1859 if (fontsize>37) ++cx; 1860 fl_line(cx-ch,cy,cx+ch-1,cy); 1861 --cy; 1862 fl_line(cx-ch,cy,cx+ch-1,cy); 1863 if (fontsize>13){ 1864 --cy; 1865 fl_line(cx-ch,cy,cx+ch-1,cy); 1866 if (fontsize>23){ 1867 cy+=3; 1868 fl_line(cx-ch,cy,cx+ch-1,cy); 1869 } 1870 } 1871 } 1872 else 1873 check_fl_draw(u.ptr()->s,eqx+w.x-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1874 #else 1875 fl_font(FL_TIMES_BOLD,fontsize); 1876 check_fl_draw(u.ptr()->s,eqx+w.x-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1877 #endif 1878 } 1879 return; 1880 } 1881 // write first open parenthesis 1882 if (u==at_plus) 1883 parenthesis=false; 1884 else { 1885 if (parenthesis && need_parenthesis(tmp.g)){ 1886 if (w.x<rightx){ 1887 int pfontsize=max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2); 1888 fl_font(FL_HELVETICA,pfontsize); 1889 check_fl_draw("(",eqx+w.x-x,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1890 fl_font(FL_HELVETICA,fontsize); 1891 } 1892 } 1893 } 1894 for (;;){ 1895 // write close parenthesis at end 1896 int xx=tmp.dx+tmp.x-x; 1897 if (parenthesis && need_parenthesis(tmp.g)){ 1898 if (xx<rightx){ 1899 int pfontsize=min(max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2),fontsize*2); 1900 int deltapary=(2*(pfontsize-fontsize))/3; 1901 fl_font(FL_HELVETICA,pfontsize); 1902 check_fl_draw(")",eqx+xx,eqy+y-tmp.baseline+deltapary,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1903 fl_font(FL_HELVETICA,fontsize); 1904 } 1905 xx +=rpsize; 1906 } 1907 ++it; 1908 if (it==itend){ 1909 if (u.ptr()->printsommet==&printsommetasoperator || u==at_sto || equalposcomp(binary_op_tab(),u)) 1910 return; 1911 else 1912 break; 1913 } 1914 // write operator 1915 if (u==at_prod){ 1916 #if 1 1917 // check_fl_draw(".",eqx+xx+3,eqy+y-tmp.baseline-fontsize/3,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1918 fl_font(FL_TIMES_ITALIC,fontsize); 1919 check_fl_draw(opstring.c_str(),eqx+xx+1,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1920 #else 1921 int cx=eqx+xx+5,cy=-3+eqy+y-tmp.baseline-fontsize/3,ch=giacmax(2,fontsize/6); 1922 // fl_line(cx-ch+1,cy,cx+ch-1,cy); // horizontal (smaller to avoid confusion with -) 1923 if (fontsize<16) --cx; 1924 if (fontsize<12) --cx; 1925 fl_line(cx,cy+ch,cx,cy-ch); 1926 fl_line(cx-ch,cy+ch,cx+ch,cy-ch); 1927 fl_line(cx-ch,cy-ch,cx+ch,cy+ch); 1928 #endif 1929 } 1930 else { 1931 gen tmpgen; 1932 if (u==at_plus && ( 1933 (it->type==_VECT && it->_VECTptr->back().type==_EQW && it->_VECTptr->back()._EQWptr->g==at_neg) 1934 || 1935 ( it->type==_EQW && (is_integer(it->_EQWptr->g) || it->_EQWptr->g.type==_DOUBLE_) && is_strictly_positive(-it->_EQWptr->g,contextptr) ) 1936 ) 1937 ) 1938 ; 1939 else { 1940 if (xx+1<rightx) 1941 // fl_draw(opstring.c_str(),xx+1,y-tmp.y-tmp.dy/2+fontsize/2); 1942 check_fl_draw(opstring.c_str(),eqx+xx+1,eqy+y-tmp.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1943 } 1944 } 1945 // write right parent, update tmp 1946 tmp=Equation_total_size(*it); 1947 if (parenthesis && (need_parenthesis(tmp.g)) ){ 1948 if (tmp.x-lpsize<rightx){ 1949 int pfontsize=min(max(fontsize,(fontsize+(tmp.baseline-tmp.y))/2),fontsize*2); 1950 int deltapary=(2*(pfontsize-fontsize))/3; 1951 fl_font(FL_HELVETICA,pfontsize); 1952 check_fl_draw("(",eqx+tmp.x-pfontsize*lpsize/fontsize-x,eqy+y-tmp.baseline+deltapary,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1953 fl_font(FL_HELVETICA,fontsize); 1954 } 1955 } 1956 } // end for (;;) 1957 if (w.x<rightx){ 1958 s = u.ptr()->s; 1959 fl_font(cst_greek_translate(s),fontsize); 1960 s += '('; 1961 check_fl_draw(s.c_str(),eqx+w.x-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1962 fl_font(FL_HELVETICA,fontsize); 1963 } 1964 if (w.x+w.dx-rpsize<rightx) 1965 check_fl_draw(")",eqx+w.x+w.dx-x-rpsize,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1966 return; 1967 } 1968 s=oper.print(contextptr); 1969 if (w.x<rightx){ 1970 fl_font(cst_greek_translate(s),fontsize); 1971 check_fl_draw(s.c_str(),eqx+w.x-x,eqy+y-w.baseline,equat->clip_x,equat->clip_y,equat->clip_w,equat->clip_h,0,0); 1972 fl_font(FL_HELVETICA,fontsize); 1973 } 1974 } 1975 draw()1976 void Equation::draw(){ 1977 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 1978 //cout << clip_x << " " << clip_y << " " << clip_w << " " << clip_h << '\n'; 1979 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 1980 fl_color(attr.background); 1981 fl_rectf(clip_x, clip_y, clip_w, clip_h); 1982 fl_color(attr.text_color); 1983 fl_rect(x(), y(), w(), h()); 1984 Equation_draw(data,xleft,ytop,xleft+w()-vscroll->w(),ytop-h()-hscroll->h(),this); 1985 Fl_Group::draw_children(); 1986 fl_pop_clip(); 1987 } 1988 Equation_box_sizes(const gen & g,int & l,int & h,int & x,int & y,attributs & attr,bool & selected,bool search_active=false)1989 bool Equation_box_sizes(const gen & g,int & l,int & h,int & x,int & y,attributs & attr,bool & selected,bool search_active=false){ 1990 if (g.type==_EQW){ 1991 eqwdata & w=*g._EQWptr; 1992 x=w.x; 1993 y=w.y; 1994 l=w.dx; 1995 h=w.dy; 1996 if (search_active) 1997 selected=w.active; 1998 else 1999 selected=w.selected; 2000 attr=w.eqw_attributs; 2001 return true; 2002 } 2003 else { 2004 if (g.type!=_VECT || g._VECTptr->empty() ){ 2005 l=0; 2006 h=0; 2007 x=0; 2008 y=0; 2009 attr=attributs(0,0,0); 2010 selected=false; 2011 return true; 2012 } 2013 gen & g1=g._VECTptr->back(); 2014 Equation_box_sizes(g1,l,h,x,y,attr,selected,search_active); 2015 return false; 2016 } 2017 } 2018 2019 // Set the scrollbars according to data, xleft, ytop setscroll()2020 void Equation::setscroll(){ 2021 int w=this->w()-vscroll->w(); 2022 int h=this->h()-hscroll->h(); 2023 redraw(); 2024 eqwdata e=Equation_total_size(data); 2025 if (e.dx>w){ 2026 xleft=max(e.x,xleft); 2027 xleft=min(e.x+e.dx-w,xleft); 2028 hscroll->value(xleft-e.x,w,0,e.dx); 2029 hscroll->show(); 2030 } 2031 else { 2032 xleft = e.x - (w-e.dx)/2; 2033 hscroll->value(0,1,0,1); 2034 hscroll->hide(); 2035 } 2036 if (e.dy>h){ 2037 ytop=max(e.y+h,ytop); 2038 ytop=min(e.y+e.dy,ytop); 2039 vscroll->value(e.dy+e.y-ytop,h,0,e.dy); 2040 vscroll->show(); 2041 } 2042 else { 2043 ytop = e.y + (e.dy + h)/2; 2044 vscroll->value(0,1,0,1); 2045 vscroll->hide(); 2046 } 2047 } 2048 Equation_cb_scroll(Fl_Widget * w,void *)2049 void Equation_cb_scroll(Fl_Widget * w, void*) { 2050 Equation_Scrollbar * s=dynamic_cast<Equation_Scrollbar *>(w); 2051 if (!s) 2052 return; 2053 if (s->vertical){ 2054 eqwdata e=Equation_total_size(s->eqwptr->data); 2055 s->eqwptr->ytop=e.dy+e.y-s->value(); 2056 } 2057 else 2058 s->eqwptr->xleft=s->value(); 2059 s->eqwptr->setscroll(); 2060 s->eqwptr->redraw(); 2061 } 2062 2063 // select or deselect part of the current eqution 2064 // This is done *in place* Equation_select(gen & g,bool select,bool active_search)2065 void Equation_select(gen & g,bool select,bool active_search){ 2066 if (g.type==_EQW){ 2067 eqwdata & e=*g._EQWptr; 2068 if (active_search) 2069 e.active=select; 2070 else 2071 e.selected=select; 2072 } 2073 if (g.type!=_VECT) 2074 return; 2075 vecteur & v=*g._VECTptr; 2076 iterateur it=v.begin(),itend=v.end(); 2077 for (;it!=itend;++it) 2078 Equation_select(*it,select,active_search); 2079 } 2080 deselect()2081 void Equation::deselect(){ 2082 begin_sel=-1; 2083 end_sel=-1; 2084 Equation_select(data,false); 2085 redraw(); 2086 } 2087 select()2088 void Equation::select(){ 2089 begin_sel=-1; 2090 end_sel=-1; 2091 Equation_select(data,true); 2092 adjust_xy_sel(); 2093 redraw(); 2094 } 2095 fl_select()2096 void Equation::fl_select(){ 2097 const giac::context * contextptr = get_context(this); 2098 gen g=get_selection(); 2099 string s; 2100 if (g.type==_STRNG) s=*g._STRNGptr; else s=g.print(contextptr); 2101 Fl::selection(*this,s.c_str(),s.size()); 2102 if (cb_select) 2103 cb_select(s.c_str()); 2104 } 2105 2106 // check if interval xmin..xmax and x1..x2 have a non empty intersection interval_crossing(int xmin,int xmax,int x1,int x2)2107 bool interval_crossing(int xmin,int xmax,int x1,int x2){ 2108 if (xmax<x1 || xmin>x2) 2109 return false; 2110 return true; 2111 } 2112 2113 // Select in g the subrectangle xmin,ymin,xmax,ymax Equation_select_rectangle(gen & g,int x1,int y1,int x2,int y2,Equation * eq)2114 void Equation_select_rectangle(gen & g,int x1,int y1,int x2,int y2,Equation * eq){ 2115 int xmin=min(x1,x2),xmax=max(x1,x2),ymin=min(y1,y2),ymax=max(y1,y2); 2116 if (g.type==_EQW) { 2117 Equation_select(g,true); 2118 if (g._EQWptr->g.type==_STRNG){ 2119 // compute begin/end_sel 2120 if (y1<y2){ 2121 giac::swapint(y1,y2); 2122 giac::swapint(x1,x2); 2123 } 2124 eq->begin_sel=Equation_binary_search_pos(*g._EQWptr,x1,y1); 2125 eq->end_sel=Equation_binary_search_pos(*g._EQWptr,x2,y2); 2126 } 2127 return; 2128 } 2129 if (g.type!=_VECT) 2130 return; 2131 vecteur & v=*g._VECTptr; 2132 // Find the first element of v containing the whole rectangle 2133 iterateur it=v.begin(),itend=v.end()-1,last_sel_it; 2134 for (;it!=itend;++it){ 2135 int x,y,l,h; 2136 attributs attr(0,0,0); 2137 bool selected; 2138 Equation_box_sizes(*it,l,h,x,y,attr,selected); 2139 if ( (x<=xmin) && (y<=ymin) && (xmax<=x+l) && (ymax<=y+h) ){ 2140 Equation_select_rectangle(*it,x1,y1,x2,y2,eq); 2141 return; 2142 } 2143 } 2144 // None, then we select each element that crosses the rectangle 2145 bool selectall=true,find_first_sel=false,find_last_sel=false; 2146 if (itend->type==_EQW && itend->_EQWptr->g==at_multistring){ 2147 if (y1<y2){ 2148 giac::swapint(y1,y2); 2149 giac::swapint(x1,x2); 2150 } 2151 find_first_sel=true; 2152 selectall=false; 2153 } 2154 it=v.begin(); 2155 for (;it!=itend;++it){ 2156 int x,y,l,h; 2157 attributs attr(0,0,0); 2158 bool selected; 2159 Equation_box_sizes(*it,l,h,x,y,attr,selected); 2160 bool xcross=interval_crossing(xmin,xmax,x,x+l),ycross=interval_crossing(ymin,ymax,y,y+h); 2161 if ( xcross && ycross ){ 2162 Equation_select(*it,true); 2163 last_sel_it=it; 2164 if (find_first_sel){ 2165 find_first_sel=false; 2166 find_last_sel=true; 2167 eq->begin_sel=Equation_binary_search_pos(*it->_EQWptr,x1,y1); 2168 } 2169 } 2170 else { 2171 if (ycross && g.subtype==_HIST__VECT){ 2172 Equation_select(*it,true); 2173 last_sel_it=it; 2174 } 2175 else 2176 selectall=false; 2177 } 2178 } 2179 if (find_last_sel) 2180 eq->end_sel=Equation_binary_search_pos(*last_sel_it->_EQWptr,x2,y2); 2181 if (selectall) 2182 Equation_select(g,true); 2183 } 2184 select_rectangle(int x,int y)2185 void Equation::select_rectangle(int x,int y){ 2186 // x,y are the end of the mouse selection 2187 Equation_select_rectangle(data,xsel,ysel,x,y,this); 2188 } 2189 2190 // return true if g has some selection inside Equation_adjust_xy(const gen & g,int & xleft,int & ytop,int & xright,int & ybottom,bool active_search=false)2191 bool Equation_adjust_xy(const gen & g,int & xleft,int & ytop,int & xright,int & ybottom,bool active_search=false){ 2192 int x,y,w,h; 2193 attributs f(0,0,0); 2194 bool selected; 2195 Equation_box_sizes(g,w,h,x,y,f,selected,active_search); 2196 if ( (g.type==_EQW__VECT) || selected ){ // terminal or selected 2197 xleft=x; 2198 ybottom=y; 2199 if (selected){ // g is selected 2200 ytop=y+h; 2201 xright=x+w; 2202 return true; 2203 } 2204 else { // no selection 2205 xright=x; 2206 ytop=y; 2207 return false; 2208 } 2209 } 2210 if (g.type!=_VECT) 2211 return false; 2212 // last not selected, recurse 2213 iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end()-1; 2214 for (;it!=itend;++it){ 2215 if (Equation_adjust_xy(*it,xleft,ytop,xright,ybottom,active_search)) 2216 return true; 2217 } 2218 return false; 2219 } 2220 adjust_xy()2221 void Equation::adjust_xy(){ 2222 // recalculate xsel, ysel to begin top of selection 2223 // and xcur, ycur to end bottom of selection 2224 Equation_adjust_xy(data,xsel,ysel,xcur,ycur); 2225 } 2226 adjust_xy_sel()2227 void Equation::adjust_xy_sel(){ 2228 // same + recalc xleft 2229 Equation_adjust_xy(data,xsel,ysel,xcur,ycur); 2230 if ((xcur>xleft+w()) || (xsel<xleft) ) 2231 xleft=max(xsel-w()/2,0); 2232 if ( ycur < ytop-h() || ysel >ytop ) 2233 ytop=ysel; 2234 // recalc scrollbars 2235 setscroll(); 2236 } 2237 2238 // Find i position of first selected item in it..itend Equation_find_multistring_pos(const_iterateur it,const_iterateur itend,int & i,int & nrows,bool active_search=false)2239 bool Equation_find_multistring_pos(const_iterateur it,const_iterateur itend,int & i,int &nrows,bool active_search=false){ 2240 int t; 2241 nrows=itend-it; 2242 for (i=0;it!=itend;++it,++i){ // find row 2243 if (it->type!=_EQW || it->_EQWptr->g.type!=_STRNG) 2244 return false; 2245 if (Equation_adjust_xy(*it,t,t,t,t,active_search)) 2246 break; 2247 } 2248 if (it==itend) 2249 return false; 2250 return true; 2251 } 2252 2253 // Assumes it points to the beginning of a string, selects position i Equation_select_multistring_pos(iterateur it,int i)2254 void Equation_select_multistring_pos(iterateur it,int i){ 2255 iterateur jt=(it+i); 2256 Equation_select(*jt,true); 2257 } 2258 2259 // find selection position in it..itend 2260 // Return true if at least 1 item is selected Equation_find_vector_pos(const_iterateur it,const_iterateur itend,int & i,int & nrows)2261 bool Equation_find_vector_pos(const_iterateur it,const_iterateur itend,int & i,int &nrows){ 2262 int t; 2263 nrows=itend-it; 2264 for (i=0;it!=itend;++it,++i){ // find row in i 2265 if (Equation_adjust_xy(*it,t,t,t,t)) 2266 break; 2267 } 2268 if (it==itend){ 2269 --i; 2270 return false; 2271 } 2272 return true; 2273 } 2274 2275 // Find i,j position of first selected item in it..itend Equation_find_matrix_pos(const_iterateur it,const_iterateur itend,int & i,int & j,int & nrows,int & ncols,bool active_search=false)2276 bool Equation_find_matrix_pos(const_iterateur it,const_iterateur itend,int & i,int &j,int &nrows,int & ncols,bool active_search=false){ 2277 // (incomplete) check for a matrix: the first element must be a vector 2278 if (it->type!=_VECT || it->_VECTptr->empty() ) 2279 return false; 2280 gen & tmp=it->_VECTptr->back(); 2281 if (tmp.type!=_EQW || tmp._EQWptr->g !=at_makevector) 2282 return false; 2283 // find selection position and move down 2284 int t; 2285 nrows=itend-it; 2286 int c=it->_VECTptr->size(); 2287 const_iterateur it0=it; 2288 for (;it0!=itend;++it0){ // more complete matrix check 2289 if (it0->type!=_VECT || int(it0->_VECTptr->size())!=c) 2290 return false; 2291 } 2292 for (i=0;it!=itend;++it,++i){ // find row 2293 if (Equation_adjust_xy(*it,t,t,t,t,active_search)) 2294 break; 2295 } 2296 if (it==itend || it->type!=_VECT ) 2297 return false; 2298 // find column 2299 const_iterateur jt=it->_VECTptr->begin(),jtend=it->_VECTptr->end()-1; 2300 ncols=jtend-jt; 2301 for (j=0;jt!=jtend;++jt,++j){ 2302 if (Equation_adjust_xy(*jt,t,t,t,t,active_search)) 2303 break; 2304 } 2305 if (jt==jtend) 2306 return false; 2307 return true; 2308 } 2309 2310 // Assumes it points to the beginning of the matrix, selects position i,j Equation_select_matrix_pos(iterateur it,int i,int j)2311 void Equation_select_matrix_pos(iterateur it,int i,int j){ 2312 iterateur jt=(it+i)->_VECTptr->begin()+j; 2313 Equation_select(*jt,true); 2314 } 2315 2316 // increase selection up (like HP49 eqw Up key) 2317 // x,y is the cursor position Equation_select_up(gen & g,int x,int y,int mode)2318 void Equation_select_up(gen & g,int x,int y,int mode){ 2319 if (g.type==_EQW){ // terminal -> select 2320 g._EQWptr->selected=true; 2321 return; 2322 } 2323 if (g.type!=_VECT || g._VECTptr->empty()) 2324 return; 2325 vecteur & v=*g._VECTptr; 2326 iterateur it=v.begin(),itend=v.end()-1; 2327 if (v.back().type!=_EQW) 2328 setsizeerr(); 2329 eqwdata & w=*v.back()._EQWptr; 2330 int i,j,nrows,ncols; 2331 if ( mode && w.g==at_makevector && Equation_find_matrix_pos(it,itend,i,j,nrows,ncols) ){ 2332 --i; 2333 if (i<0) 2334 i=nrows-1; 2335 Equation_select(g,false); 2336 Equation_select_matrix_pos(it,i,j); 2337 return; 2338 } 2339 if ( mode && w.g==at_multistring && Equation_find_multistring_pos(it,itend,i,nrows) ){ 2340 --i; 2341 if (i<0) 2342 i=nrows-1; 2343 Equation_select(g,false); 2344 Equation_select_multistring_pos(it,i); 2345 return; 2346 } 2347 // find a box containing the cursor 2348 int x0,y0,w0,h0; 2349 attributs attr(0,0,0); 2350 bool selected; 2351 for (;it!=itend;++it){ 2352 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected); 2353 if ( (x0<x) && (x0+w0>=x) && (y0<=y) && (y0+h0>=y) ) 2354 break; 2355 } 2356 if (it==itend) 2357 return; 2358 // if the box is selected select g else recurse 2359 if (selected) 2360 Equation_select(g,true); 2361 else 2362 Equation_select_up(*it,x,y,mode); 2363 } 2364 select_up(int mode)2365 void Equation::select_up(int mode){ 2366 const giac::context * contextptr = get_context(this); 2367 begin_sel=-1; 2368 end_sel=-1; 2369 // mode is 1 for shifted key 2370 Equation_select_up(data,xcur,ycur,mode); 2371 adjust_xy_sel(); 2372 if (cb_select) 2373 cb_select(get_selection().print(contextptr).c_str()); 2374 redraw(); 2375 } 2376 2377 // decrease selection up (like HP49 eqw Down key) Equation_select_down(gen & g,int x,int y,int mode,Equation * eq)2378 void Equation_select_down(gen & g,int x,int y,int mode, Equation * eq){ 2379 const giac::context * contextptr = get_context(eq); 2380 if (g.type==_EQW){ // terminal -> deselect and activate 2381 eqwdata & e=*g._EQWptr; 2382 e.selected=false; 2383 if (eq->modifiable){ 2384 e.active=true; 2385 eq->active_pos=0; 2386 if (e.g.type==_STRNG ) 2387 eq->need_active_parse=false; 2388 else { 2389 eq->need_active_parse=true; 2390 e.g=string2gen(e.g.print(contextptr),false); 2391 e.g.subtype=1; 2392 } 2393 } 2394 return; 2395 } 2396 if (g.type!=_VECT || g._VECTptr->empty() ) 2397 return; 2398 vecteur & v=*g._VECTptr; 2399 iterateur it=v.begin(),itend=v.end()-1; 2400 if (itend->type!=_EQW) 2401 setsizeerr(); 2402 eqwdata & w=*itend->_EQWptr; 2403 if (w.selected){ // deselect operator (sommet of the symbolic) 2404 w.selected=false; 2405 if (itend-it==1) 2406 return; 2407 } 2408 int i,j,nrows,ncols; 2409 if ( mode && w.g==at_makevector && Equation_find_matrix_pos(it,itend,i,j,nrows,ncols) ){ 2410 ++i; 2411 if (i>=nrows) 2412 i=0; 2413 Equation_select(g,false); 2414 Equation_select_matrix_pos(it,i,j); 2415 return; 2416 } 2417 if ( mode && w.g==at_multistring && Equation_find_multistring_pos(it,itend,i,nrows) ){ 2418 ++i; 2419 if (i>=nrows) 2420 i=0; 2421 Equation_select(g,false); 2422 Equation_select_multistring_pos(it,i); 2423 return; 2424 } 2425 // not selected, find the 1st selected element if any 2426 int x0,y0,w0,h0; 2427 attributs attr(0,0,0); 2428 bool selected; 2429 for (;it!=itend;++it){ 2430 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected); 2431 if (selected) 2432 break; 2433 } 2434 if (selected){ // deselect all elements except this one 2435 iterateur it1=v.begin(); 2436 bool des=false; 2437 int tmp; 2438 for (;it1!=itend;++it1){ 2439 if (it1!=it){ // if *it1 was selected deselect it 2440 if (Equation_adjust_xy(*it1,tmp,tmp,tmp,tmp)){ 2441 des=true; 2442 Equation_select(*it1,false); 2443 } 2444 } 2445 } 2446 if (!des){ // nothing else was selected, recurse 2447 Equation_select_down(*it,x,y,mode,eq); 2448 } 2449 return; 2450 } 2451 it=v.begin(); 2452 for (;it!=itend;++it){ 2453 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected); 2454 if ( (x0<=x) && (x0+w0>=x) && (y0<=y) && (y0+h0>=y) ) 2455 break; 2456 } 2457 if (it!=itend) 2458 Equation_select_down(*it,x,y,mode,eq); 2459 } 2460 select_down(int mode)2461 void Equation::select_down(int mode){ 2462 const giac::context * contextptr = get_context(this); 2463 begin_sel=-1; 2464 end_sel=-1; 2465 Equation_select_down(data,xcur,ycur,mode,this); 2466 adjust_xy_sel(); 2467 if (cb_select) 2468 cb_select(get_selection().print(contextptr).c_str()); 2469 redraw(); 2470 } 2471 Equation_data2gen(const gen & g,GIAC_CONTEXT)2472 gen Equation_data2gen(const gen & g,GIAC_CONTEXT){ 2473 if (g.type==_EQW){ 2474 eqwdata & e=*g._EQWptr; 2475 if ( e.g.type==_STRNG && e.active && e.g.subtype ) 2476 return gen(*e.g._STRNGptr,contextptr); 2477 return e.g; 2478 } 2479 if (g.type!=_VECT) 2480 return g; 2481 vecteur & v=*g._VECTptr; 2482 const_iterateur it=v.begin(),itend=v.end()-1; 2483 vecteur res; 2484 if (g.subtype==_HIST__VECT){ 2485 vecteur tmp(2); 2486 for (;it!=itend;++it){ 2487 tmp[0]=Equation_data2gen(*it,contextptr); 2488 ++it; 2489 if (it==itend) 2490 break; 2491 tmp[1]=Equation_data2gen(*it,contextptr); 2492 res.push_back(tmp); 2493 } 2494 return gen(res,_HIST__VECT); 2495 } 2496 res.reserve(itend-it); 2497 for (;it!=itend;++it){ 2498 res.push_back(Equation_data2gen(*it,contextptr)); 2499 } 2500 gen f=Equation_data2gen(*it,contextptr); 2501 if (f==at_makesuite) 2502 return gen(res,_SEQ__VECT); 2503 if (f==at_makevector){ 2504 if (f.subtype==_MATRIX__VECT && ckmatrix(res)){ 2505 iterateur it=res.begin();itend=res.end(); 2506 for (;it!=itend;++it) 2507 it->subtype=0; 2508 return res; 2509 } 2510 return gen(res,f.subtype); 2511 } 2512 if (f==at_program && res.size()==2) 2513 res.insert(res.begin()+1,res.front()*zero); 2514 if (f==at_at && xcas_mode(contextptr)!=0){ 2515 if (res.size()==2){ 2516 if (res.back().type==_VECT){ 2517 vecteur & resv=*res.back()._VECTptr; 2518 res.back()=gen(subvecteur(resv,vecteur(resv.size(),plus_one)),_SEQ__VECT); 2519 } 2520 else 2521 res.back()=res.back()-plus_one; 2522 } 2523 } 2524 gen arg=gen(res,g.subtype); 2525 if (f.type==_FUNC) { 2526 if (res.size()==1) 2527 return symbolic(*f._FUNCptr,res.front()); 2528 else { 2529 if (f==at_multistring){ 2530 gen tmp=_multistring(res,contextptr); 2531 return tmp; 2532 } 2533 return symbolic(*f._FUNCptr,arg); 2534 } 2535 } 2536 else 2537 return f(arg,contextptr); 2538 } 2539 Equation_selected2gen(Equation * eq,const gen & g,bool & selected,bool search_active=false)2540 gen Equation_selected2gen(Equation * eq,const gen & g,bool & selected,bool search_active=false){ 2541 const giac::context * contextptr = get_context(eq); 2542 if (g.type==_EQW){ 2543 eqwdata & e=*g._EQWptr; 2544 if (search_active) 2545 selected = e.active; 2546 else 2547 selected = e.selected; 2548 if (!selected) 2549 return Equation_nullstring(); 2550 if (e.g.type!=_STRNG) 2551 return e.g; 2552 if (e.active && e.g.subtype ) 2553 return gen(*e.g._STRNGptr,contextptr); // parse 2554 // begin_sel/end_sel 2555 string res=*e.g._STRNGptr; 2556 if (!e.active) 2557 res=Equation_extract_string(*e.g._STRNGptr,eq->begin_sel,eq->end_sel); 2558 return string2gen(res,false); 2559 } 2560 selected=false; 2561 if (g.type!=_VECT) 2562 return g; 2563 vecteur & v=*g._VECTptr; 2564 const_iterateur it=v.begin(),itend=v.end()-1; 2565 if (itend->type==_EQW && itend->_EQWptr->g==at_multistring){ 2566 string res; 2567 if (!Equation_multistring_selection(it,itend,search_active)) 2568 return string2gen(res,false); 2569 selected=true; 2570 if (it==itend) // selection inside one string 2571 return Equation_selected2gen(eq,*it,selected,search_active); 2572 res=Equation_extract_string(*it->_EQWptr->g._STRNGptr,eq->begin_sel,-1)+'\n'; 2573 ++it; 2574 for (;it!=itend;++it) 2575 res=res+*it->_EQWptr->g._STRNGptr+'\n'; 2576 res=res+Equation_extract_string(*itend->_EQWptr->g._STRNGptr,-1,eq->end_sel); 2577 return string2gen(res,false); 2578 } 2579 int w0,h0,x0,y0; 2580 attributs attr(0,0,0); 2581 Equation_box_sizes(*itend,w0,h0,x0,y0,attr,selected,search_active); 2582 if (selected) 2583 return Equation_data2gen(g,contextptr); 2584 vecteur res; 2585 res.reserve(itend-it); 2586 for (;it!=itend;++it){ 2587 gen tmp=Equation_selected2gen(eq,*it,selected,search_active); 2588 if (selected) 2589 res.push_back(tmp); 2590 } 2591 selected=!res.empty(); 2592 if (!selected) 2593 return zero; 2594 if (res.size()==1) 2595 return res.front(); 2596 gen f=Equation_data2gen(*it,contextptr); 2597 if (f==at_makesuite) 2598 return gen(res,_SEQ__VECT); 2599 if (f==at_makevector){ 2600 if (f.subtype==_MATRIX__VECT && ckmatrix(res)){ 2601 iterateur it=res.begin();itend=res.end(); 2602 for (;it!=itend;++it) 2603 it->subtype=0; 2604 return res; 2605 } 2606 return gen(res,f.subtype); 2607 } 2608 if (f==at_program && res.size()==2) 2609 res.insert(res.begin()+1,res.front()*zero); 2610 if (f==at_at && xcas_mode(contextptr)!=0){ 2611 if (res.size()==2){ 2612 if (res.back().type==_VECT){ 2613 vecteur & resv=*res.back()._VECTptr; 2614 res.back()=gen(subvecteur(resv,vecteur(resv.size(),plus_one)),_SEQ__VECT); 2615 } 2616 else 2617 res.back()=res.back()-plus_one; 2618 } 2619 } 2620 gen arg=gen(res,g.subtype); 2621 if (f.type==_FUNC) 2622 return symbolic(*f._FUNCptr,arg); 2623 else 2624 return f(arg,contextptr); 2625 } 2626 2627 // return a pointer to the selected object 2628 // it will modify g if for example a subsum of a sum is selected Equation_selected(gen & g,attributs & attr,int windowhsize,vecteur & position,bool active_search,GIAC_CONTEXT)2629 gen * Equation_selected(gen & g,attributs & attr,int windowhsize,vecteur & position,bool active_search,GIAC_CONTEXT){ 2630 // FIXME begin_sel/end_sel 2631 int x0,y0,w0,h0,tmp; 2632 bool selected; 2633 if (!Equation_adjust_xy(g,tmp,tmp,tmp,tmp,active_search)) 2634 return 0; 2635 Equation_box_sizes(g,w0,h0,x0,y0,attr,selected,active_search); 2636 if (selected) 2637 return &g; 2638 if (g.type!=_VECT) 2639 return 0; 2640 vecteur & v=*g._VECTptr; 2641 iterateur it=v.begin(),itend=v.end()-1; 2642 for (;it!=itend;++it){ // search first selected item 2643 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected,active_search); 2644 if (selected) 2645 break; 2646 } 2647 if (it==itend){ 2648 it=v.begin(); 2649 for (;it!=itend;++it){ 2650 if (Equation_adjust_xy(*it,tmp,tmp,tmp,tmp,active_search)){ 2651 position.push_back(int(it-v.begin())); 2652 return Equation_selected(*it,attr,windowhsize,position,active_search,contextptr); 2653 } 2654 } 2655 return 0; 2656 } 2657 iterateur itb=it; 2658 position.push_back(int(it-v.begin())); 2659 // find the end of the selection 2660 ++it; 2661 for (;it!=itend;++it){ 2662 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected,active_search); 2663 if (!selected) 2664 break; 2665 } 2666 --it; 2667 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected,active_search); 2668 if (it==itb) 2669 return &*it; 2670 // arrange v 2671 if (itb==v.begin() && it+1==itend){ 2672 position.pop_back(); 2673 return &g; 2674 } 2675 vecteur subop(itb,it+1); 2676 subop.push_back(v.back()); 2677 gen temp=Equation_data2gen(subop,contextptr); 2678 eqwdata e=Equation_total_size(*it); 2679 *it=Equation_compute_size(temp,attr,windowhsize,contextptr); 2680 Equation_translate(*it,e.x,e.y); 2681 int pos=itb-v.begin(); 2682 v.erase(itb,it); 2683 return &v[pos]; 2684 } 2685 2686 // make a free copy of g Equation_copy(const gen & g)2687 gen Equation_copy(const gen & g){ 2688 if (g.type==_EQW) 2689 return *g._EQWptr; 2690 if (g.type!=_VECT) 2691 return g; 2692 vecteur & v = *g._VECTptr; 2693 const_iterateur it=v.begin(),itend=v.end(); 2694 vecteur res; 2695 res.reserve(itend-it); 2696 for (;it!=itend;++it) 2697 res.push_back(Equation_copy(*it)); 2698 return gen(res,g.subtype); 2699 } 2700 2701 // move selection right (like HP49 eqw Right key) Equation_select_rightleft(gen & g,Equation * eqptr,int windowhsize,bool right,int mode,GIAC_CONTEXT)2702 void Equation_select_rightleft(gen & g,Equation * eqptr,int windowhsize,bool right,int mode,GIAC_CONTEXT){ 2703 if (g.type!=_VECT) // we are on a terminal, nothing to do 2704 return; 2705 // find 1st object with something selected 2706 vecteur & v=*g._VECTptr; 2707 iterateur it=v.begin(),itend=v.end()-1; 2708 eqwdata & w=*itend->_EQWptr; 2709 int i,j,nrows,ncols,tmp; 2710 if ( (mode) && (w.g==at_makevector) && Equation_find_matrix_pos(it,itend,i,j,nrows,ncols) ){ 2711 if (right) 2712 ++j; 2713 else 2714 --j; 2715 if (j<0) 2716 j=ncols-1; 2717 if (j>=ncols) 2718 j=0; 2719 Equation_select(g,false); 2720 Equation_select_matrix_pos(it,i,j); 2721 return; 2722 } 2723 for (;it!=itend;++it){ 2724 if (Equation_adjust_xy(*it,tmp,tmp,tmp,tmp)) 2725 break; 2726 } 2727 if (it==itend) 2728 return; 2729 iterateur it0=it; // save first selected 2730 // find first non selected 2731 if (right || (mode==2) ){ 2732 ++it; 2733 for (;it!=itend;++it){ 2734 if (!Equation_adjust_xy(*it,tmp,tmp,tmp,tmp)) 2735 break; 2736 } 2737 if (mode==2 && it0==v.begin() && it==itend) 2738 return; 2739 --it; 2740 } 2741 // it -> last selected if moving right or exchanging selection right/left 2742 int x0,y0,w0,h0; 2743 attributs attr(0,0,0); 2744 bool selected; 2745 Equation_box_sizes(*it,w0,h0,x0,y0,attr,selected); 2746 if (!selected){ 2747 Equation_select_rightleft(*it,eqptr,windowhsize,right,mode,contextptr); 2748 return; 2749 } 2750 iterateur it1=it; 2751 if (right){ 2752 ++it; 2753 if (it==itend) 2754 it=v.begin(); 2755 } 2756 else { 2757 it=it0; 2758 if (it==v.begin()) 2759 it=itend; 2760 --it; 2761 } 2762 if (mode==2){ // exchange it0->it1 with it 2763 if (it1==it0){ 2764 gen tmp=*it; 2765 *it=*it0; 2766 *it0=tmp; 2767 } 2768 else { 2769 vecteur tmpv(it0,it1+1); 2770 tmpv.push_back(*itend); 2771 gen sel=Equation_data2gen(tmpv,contextptr); 2772 sel=Equation_compute_size(sel,attr,windowhsize,contextptr); 2773 Equation_select(sel,true); 2774 gen tmp=*it; 2775 *it=sel; 2776 *it1=tmp; 2777 v.erase(it0,it1); 2778 } 2779 vecteur position; 2780 gen g_copy=Equation_copy(eqptr->data); 2781 gen * ptr=Equation_selected(eqptr->data,attr,windowhsize,position,false,contextptr); 2782 if (ptr){ 2783 if (ptr->type==_VECT && !ptr->_VECTptr->empty() && ptr->_VECTptr->back().type==_EQW && ptr->_VECTptr->back()._EQWptr->g==at_multistring){ 2784 eqptr->data=g_copy; 2785 return; 2786 } 2787 const gen & tmp=Equation_data2gen(eqptr->data,contextptr); 2788 eqptr->data=Equation_compute_size(tmp,attr,windowhsize,contextptr); 2789 const_iterateur it=position.begin(),itend=position.end(); 2790 ptr=&eqptr->data; 2791 for (;it!=itend;++it){ 2792 ptr=&(*ptr->_VECTptr)[it->val]; 2793 } 2794 Equation_select(*ptr,true); 2795 } 2796 return; 2797 } 2798 else { 2799 // if shift-arrow, extend selection, mode==0 do not deselect 2800 if (mode==1) 2801 Equation_select(g,false); 2802 } 2803 Equation_select(*it,true); 2804 } 2805 select_right(int mode)2806 void Equation::select_right(int mode){ 2807 begin_sel=-1; 2808 end_sel=-1; 2809 const giac::context * contextptr = get_context(this); 2810 Equation_select_rightleft(data,this,w(),true,mode,contextptr); 2811 adjust_xy_sel(); 2812 if (cb_select) 2813 cb_select(get_selection().print(contextptr).c_str()); 2814 redraw(); 2815 } 2816 select_left(int mode)2817 void Equation::select_left(int mode){ 2818 begin_sel=-1; 2819 end_sel=-1; 2820 const giac::context * contextptr = get_context(this); 2821 Equation_select_rightleft(data,this,w(),false,mode,contextptr); 2822 adjust_xy_sel(); 2823 if (cb_select) 2824 cb_select(get_selection().print(contextptr).c_str()); 2825 redraw(); 2826 } 2827 2828 /* // modify g in place 2829 void Equation_eval_function(const gen & f,gen & g,attributs iattr,int windowhsize){ 2830 2831 attributs attr(0,0,0); 2832 vecteur position; 2833 gen g_copy=Equation_copy(g); 2834 gen * ptr=Equation_selected(g,attr,windowhsize,position,contextptr); 2835 if (!ptr) // should begin entry mode here 2836 return; 2837 if (ptr->type==_VECT && !ptr->_VECTptr->empty() && ptr->_VECTptr->back().type==_EQW && ptr->_VECTptr->back()._EQWptr->g==at_multistring){ 2838 g=g_copy; 2839 return; 2840 } 2841 gen tmp=Equation_data2gen(*ptr,contextptr); 2842 tmp=f(eval(tmp)); 2843 * ptr = Equation_compute_size(tmp,attr,windowhsize,contextptr); 2844 tmp=Equation_data2gen(g,contextptr); 2845 g=Equation_compute_size(tmp,iattr,windowhsize,contextptr); 2846 const_iterateur it=position.begin(),itend=position.end(); 2847 ptr=&g; 2848 for (;it!=itend;++it){ 2849 ptr=&(*ptr->_VECTptr)[it->val]; 2850 } 2851 Equation_select(*ptr,true); 2852 } 2853 */ 2854 save_data()2855 void Equation::save_data(){ 2856 int us=undo_history.size(); 2857 if (undo_history_pos>=int(us)){ 2858 undo_history.push_back(get_data()); 2859 } 2860 else { 2861 undo_history[undo_history_pos]=get_data(); 2862 iterateur it=undo_history.begin()+undo_history_pos+1; 2863 undo_history.erase(it,undo_history.end()); 2864 } 2865 us=undo_history.size(); 2866 undo_history_pos=us; 2867 if (us>1){ // check that the last 2 levels are not identical 2868 if (undo_history[us-2]==undo_history[us-1]){ 2869 undo_history.pop_back(); 2870 --undo_history_pos; 2871 } 2872 } 2873 } 2874 rcl_data(int dpos)2875 void Equation::rcl_data(int dpos){ 2876 int us=undo_history.size(); 2877 if (!us) 2878 return; 2879 if (undo_history_pos>=us) 2880 undo_history_pos=us-1; 2881 undo_history_pos += dpos ; 2882 if (undo_history_pos>=us) 2883 undo_history_pos=us-1; 2884 if (undo_history_pos<0) 2885 undo_history_pos=0; 2886 set_data(undo_history[undo_history_pos]); 2887 select(); 2888 // adjust_xy_sel(); 2889 // redraw(); 2890 } 2891 eval_function(const gen & f)2892 void Equation::eval_function(const gen & f){ 2893 save_data(); 2894 gen fx=symbolic(at_of,makevecteur(f,get_selection())); 2895 replace_selection_wo_save(fx); 2896 save_data(); 2897 xcas::History_Pack * hp=get_history_pack(this); 2898 giac::context * cptr=hp?hp->contextptr:0; 2899 //bool ok= 2900 make_thread(fx,eval_level(cptr),Equation_eval_callback,this,cptr); 2901 } 2902 get_selection()2903 gen Equation::get_selection(){ 2904 bool has_selection; 2905 return Equation_selected2gen(this,data,has_selection); 2906 } 2907 get_data() const2908 gen Equation::get_data() const{ 2909 const giac::context * contextptr = get_context(this); 2910 return Equation_data2gen(data,contextptr); 2911 } 2912 value() const2913 string Equation::value() const{ 2914 const giac::context * contextptr = get_context(this); 2915 return Equation_data2gen(data,contextptr).print(contextptr); 2916 } 2917 set_data(const gen & g)2918 void Equation::set_data(const gen & g){ 2919 const giac::context * contextptr = get_context(this); 2920 data=Equation_compute_size(g,attr,w(),contextptr); 2921 eqwdata e = Equation_total_size(data); 2922 // FIXME? ytop = e.y; 2923 ytop=h(); 2924 // FIXME? xleft = e.x; 2925 xleft=0; 2926 setscroll(); 2927 } 2928 Equation_replace_selection(const gen & f,Equation * eqwptr,int windowhsize,bool active_search=false)2929 bool Equation_replace_selection(const gen & f,Equation * eqwptr,int windowhsize,bool active_search=false){ 2930 const giac::context * contextptr = get_context(eqwptr); 2931 eqwptr->redraw(); 2932 gen & g = eqwptr->data; 2933 attributs attr(0,0,0); 2934 vecteur position; 2935 gen save_g=Equation_copy(g); 2936 gen * ptr=Equation_selected(g,attr,windowhsize,position,active_search,contextptr); 2937 if (!ptr) { 2938 g=save_g; 2939 return false; 2940 } 2941 if (g.type==_VECT && g.subtype==_HIST__VECT && !position.empty()){ 2942 if ( (position.front().val%2) ^ rpn_mode(contextptr)){ 2943 g=save_g; 2944 return false; 2945 } 2946 } 2947 bool stringrep= !active_search && ptr->type==_EQW && ptr->_EQWptr->g.type==_STRNG && eqwptr->begin_sel>=0 && eqwptr->end_sel>=0 ; 2948 bool multistringrep= ptr->type==_VECT && !ptr->_VECTptr->empty() && ptr->_VECTptr->back().type==_EQW && ptr->_VECTptr->back()._EQWptr->g==at_multistring; 2949 if (multistringrep){ // check if the whole multistring is replaced or not 2950 *ptr=Equation_nullstring(eqwptr->attr,0,contextptr); 2951 multistringrep= in_multistring(eqwptr->data)!=-1; 2952 } 2953 if (stringrep || multistringrep){ 2954 g=save_g; 2955 eqwptr->remove_selection(); 2956 vecteur position; 2957 gen * act=Equation_selected(eqwptr->data,eqwptr->attr,eqwptr->w(),position,1,contextptr); 2958 string s; 2959 if (f.type==_STRNG) 2960 s=*f._STRNGptr; 2961 else 2962 s=f.print(contextptr); 2963 eqwptr->handle_text(s,act); 2964 return true; 2965 } 2966 if (g.type==_VECT && g.subtype==_HIST__VECT && position.size()>=1 && position.size()<=2){ 2967 int pos=position.front().val; 2968 bool doit=pos>=0 && pos<int(g._VECTptr->size()); 2969 if (doit){ 2970 if (position.size()==2){ 2971 doit=false; 2972 if (is_zero(position.back())){ 2973 gen gtmp=g[pos]; 2974 if (gtmp.type==_VECT && gtmp._VECTptr->back().type==_EQW && gtmp._VECTptr->back()._EQWptr->g==at_expr) 2975 doit=true; 2976 } 2977 } 2978 } 2979 if (doit){ 2980 g = save_g; 2981 Equation_select(g,false,active_search); 2982 vecteur & v = *g._VECTptr; 2983 int s=v.size(),newdx; 2984 eqwdata olde=Equation_total_size(v[pos]); 2985 if (position.size()==2){ 2986 gen vposfront=Equation_data2gen(v[pos],contextptr); 2987 gen vposfrontf=vposfront._SYMBptr->feuille; 2988 if (vposfrontf.type==_VECT && !vposfrontf._VECTptr->empty()){ 2989 vecteur vposfrontv=*vposfrontf._VECTptr; 2990 vposfrontv[0]=f; 2991 vposfrontf=gen(vposfrontv,vposfrontf.subtype); 2992 } 2993 else 2994 vposfrontf=f; 2995 v[pos]=Equation_compute_size(symbolic(at_expr,vposfrontf),olde.eqw_attributs,windowhsize,contextptr); 2996 } 2997 else { 2998 v[pos]=Equation_compute_size(f,olde.eqw_attributs,windowhsize,contextptr); 2999 } 3000 eqwdata newe=Equation_total_size(v[pos]); 3001 int deltady=newe.dy-olde.dy; 3002 if (pos%2){ 3003 int xshift=int(fl_width(" "));; 3004 if (newe.dx+4<windowhsize-eqwptr->attr.fontsize){ 3005 if (center_history) 3006 xshift=(windowhsize-newe.dx-4)/2; 3007 else 3008 xshift=windowhsize-newe.dx-4-eqwptr->attr.fontsize; 3009 } 3010 newdx=newe.dx+xshift; 3011 Equation_translate(v[pos],xshift-newe.x,olde.y-newe.y-deltady); 3012 } 3013 else { 3014 newdx=newe.dx+olde.x; 3015 Equation_translate(v[pos],olde.x-newe.x,olde.y-newe.y-deltady); 3016 } 3017 if (position.size()==2) 3018 Equation_select(v[pos]._VECTptr->front(),true,active_search); 3019 else 3020 Equation_select(v[pos],true,active_search); 3021 // translate the rest of history 3022 for (++pos;pos<s;++pos){ 3023 Equation_translate(v[pos],0,-deltady); 3024 } 3025 --pos; 3026 if (v[pos].type==_EQW){ // should be true! 3027 eqwdata & e = *v[pos]._EQWptr; 3028 e.dx=max(e.dx,newdx); 3029 eqwptr->xleft=e.dx; 3030 } 3031 eqwptr->setscroll(); 3032 return true; 3033 } 3034 } 3035 eqwdata olde=Equation_total_size(*ptr); 3036 *ptr=Equation_compute_size(f,olde.eqw_attributs,windowhsize,contextptr); 3037 gen tmp=Equation_data2gen(g,contextptr); 3038 g=Equation_compute_size(tmp,eqwptr->attr,windowhsize,contextptr); 3039 const_iterateur it=position.begin(),itend=position.end(); 3040 ptr=&g; 3041 for (;it!=itend;++it){ 3042 ptr=&(*ptr->_VECTptr)[it->val]; 3043 } 3044 Equation_select(*ptr,true,active_search); 3045 return true; 3046 } 3047 replace_selection(const gen & f,bool active_search)3048 bool Equation::replace_selection(const gen & f,bool active_search){ 3049 save_data(); 3050 return replace_selection_wo_save(f,active_search); 3051 } 3052 adjust_widget_size()3053 void Equation::adjust_widget_size(){ 3054 // recompute widget size 3055 eqwdata e=Equation_total_size(data); 3056 int maxh=window()?(window()->h())/3:1000; 3057 int scrollsize=3; 3058 if (e.dx>w()-2*labelsize()) 3059 scrollsize=labelsize()+3; 3060 int newh=min(e.dy+scrollsize+1,maxh); // =max(min(vv.dy+20,400),60); 3061 increase_size(this,newh-h()); 3062 int largeur=labelsize(); 3063 vscroll->resize(x()+Fl_Group::w()-largeur,y(),largeur,Fl_Group::h()-labelsize()); 3064 hscroll->resize(x(),y()+Fl_Group::h()-labelsize(),Fl_Group::w()-2*largeur,labelsize()); 3065 menubar->resize(hscroll->x()+hscroll->w(),hscroll->y(),this->w()-hscroll->w(),hscroll->h()); 3066 } 3067 replace_selection_wo_save(const gen & f,bool active_search)3068 bool Equation::replace_selection_wo_save(const gen & f,bool active_search){ 3069 bool res=Equation_replace_selection(f,this,w(),active_search); 3070 if (res) 3071 save_data(); 3072 // recompute widget size 3073 adjust_widget_size(); 3074 if (!active_search) 3075 fl_select(); 3076 adjust_xy_sel(); 3077 redraw(); 3078 return res; 3079 } 3080 3081 // deselect and activate Equation_deselect_and_activate(gen & g)3082 bool Equation_deselect_and_activate(gen & g){ 3083 if (g.type==_EQW){ 3084 if (g._EQWptr->selected){ 3085 g._EQWptr->selected=false; 3086 g._EQWptr->active=true; 3087 return true; 3088 } 3089 else 3090 return false; 3091 } 3092 if (g.type!=_VECT) 3093 return false; 3094 vecteur & v = *g._VECTptr; 3095 iterateur it=v.begin(),itend=v.end()-1; 3096 if (Equation_deselect_and_activate(*itend)) 3097 return true; 3098 for (;it!=itend;++it){ 3099 if (Equation_deselect_and_activate(*it)) 3100 return true; 3101 } 3102 return false; 3103 } 3104 deselect_and_activate()3105 void Equation::deselect_and_activate(){ 3106 begin_sel=-1; 3107 end_sel=-1; 3108 active_pos=0; 3109 Equation_deselect_and_activate(data); 3110 } 3111 Equation_desactivate_and_select(gen & g,bool need_active_parse)3112 bool Equation_desactivate_and_select(gen & g,bool need_active_parse){ 3113 if (g.type==_EQW){ 3114 if (g._EQWptr->active){ 3115 g._EQWptr->active=false; 3116 g._EQWptr->selected=true; 3117 if (need_active_parse && g._EQWptr->g.type==_STRNG ) 3118 g._EQWptr->g=gen(*g._EQWptr->g._STRNGptr,context0); 3119 return true; 3120 } 3121 else 3122 return false; 3123 } 3124 if (g.type!=_VECT) 3125 return false; 3126 vecteur & v = *g._VECTptr; 3127 iterateur it=v.begin(),itend=v.end()-1; 3128 if (Equation_desactivate_and_select(*itend,need_active_parse)) 3129 return true; 3130 for (;it!=itend;++it){ 3131 if (Equation_desactivate_and_select(*it,need_active_parse)) 3132 return true; 3133 } 3134 return false; 3135 } 3136 desactivate_and_select()3137 void Equation::desactivate_and_select(){ 3138 begin_sel=-1; 3139 end_sel=-1; 3140 Equation_desactivate_and_select(data,need_active_parse); 3141 } 3142 3143 // if nothing selected, select active -> select something 3144 // Parse selection insure_something_selected(bool selectall)3145 void Equation::insure_something_selected(bool selectall){ 3146 bool has_selection=false; 3147 gen g=Equation_selected2gen(this,data,has_selection); 3148 if (!has_selection){ 3149 if (selectall) 3150 select(); 3151 else { 3152 // Check for something active, desactive and select 3153 g=Equation_selected2gen(this,data,has_selection,1); 3154 if (has_selection){ 3155 desactivate_and_select(); 3156 } 3157 else { 3158 select_up(0); 3159 g=Equation_selected2gen(this,data,has_selection); 3160 } 3161 } 3162 } 3163 } 3164 Equation_parse_desactivate(gen & g,Equation * eq)3165 bool Equation_parse_desactivate(gen & g,Equation * eq){ 3166 const giac::context * contextptr = get_context(eq); 3167 if (g.type==_EQW){ 3168 eqwdata & e=*g._EQWptr; 3169 if (!e.active) 3170 return false; 3171 e.active=false; 3172 e.selected=true; 3173 if (e.g.type==_STRNG && eq->need_active_parse){ 3174 try { 3175 gen g1=gen(*e.g._STRNGptr,contextptr); 3176 e.g=g1; 3177 eq->replace_selection(g1); 3178 } 3179 catch (std::runtime_error & er){ 3180 cerr << er.what() << '\n'; 3181 } 3182 } 3183 return true; 3184 } 3185 if (g.type!=_VECT) 3186 return false; 3187 vecteur & v =*g._VECTptr; 3188 iterateur it=v.begin(),itend=v.end(); 3189 for (;it!=itend;++it){ 3190 if (Equation_parse_desactivate(*it,eq)) 3191 return true; 3192 } 3193 return false; 3194 } 3195 parse_desactivate()3196 bool Equation::parse_desactivate(){ 3197 begin_sel=-1; 3198 end_sel=-1; 3199 if (!Equation_parse_desactivate(data,this)) 3200 return false; 3201 return true; 3202 } 3203 3204 // return true if something selected inside or whole selected Equation_is_selected(const gen & g,bool inside=false,bool active_search=false)3205 bool Equation_is_selected(const gen & g,bool inside=false,bool active_search=false){ 3206 if (g.type==_EQW){ 3207 if (active_search) 3208 return g._EQWptr->active; 3209 else 3210 return g._EQWptr->selected; 3211 } 3212 if (g.type!=_VECT || g._VECTptr->empty()) 3213 return false; 3214 if (Equation_is_selected(g._VECTptr->back(),inside,active_search)) 3215 return true; 3216 if (!inside) 3217 return false; 3218 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 3219 for (;it!=itend;++it){ 3220 if (Equation_is_selected(*it,inside,active_search)) 3221 return true; 3222 } 3223 return false; 3224 } 3225 is_selected(bool inside,bool active_search)3226 bool Equation::is_selected(bool inside,bool active_search){ 3227 return Equation_is_selected(data,inside,active_search); 3228 } 3229 Equation_nullstring()3230 gen Equation_nullstring(){ 3231 gen tmps=string2gen("",false); 3232 tmps.subtype=1; 3233 return tmps; 3234 } 3235 Equation_nullhistlevel()3236 gen Equation_nullhistlevel(){ 3237 gen hh1,hh2(string2gen("",false)); 3238 hh1=Equation_nullstring(); 3239 gen hh=gen(vecteur(1,makevecteur(hh1,hh2)),_HIST__VECT); 3240 return hh; 3241 } 3242 is_semi_expr(const gen & g)3243 bool is_semi_expr(const gen & g){ 3244 if (!g.is_symb_of_sommet(at_expr)) 3245 return false; 3246 gen tmp=g._SYMBptr->feuille; 3247 return tmp.type==_VECT && tmp.subtype==_SEQ__VECT && tmp._VECTptr->front().type==_STRNG && *tmp._VECTptr->front()._STRNGptr==";"; 3248 } 3249 Equation_nullstring(const attributs & a,int windowhsize,GIAC_CONTEXT)3250 gen Equation_nullstring(const attributs & a,int windowhsize,GIAC_CONTEXT){ 3251 gen g=Equation_compute_size(Equation_nullstring(),a,windowhsize,contextptr); 3252 Equation_select(g,true,1); 3253 return g; 3254 } 3255 Equation_remove_selection(gen & g,int & pos,Equation * eq)3256 void Equation_remove_selection(gen & g,int & pos,Equation * eq){ 3257 const giac::context * contextptr = get_context(eq); 3258 if (g.type==_EQW){ 3259 eqwdata & e=*g._EQWptr; 3260 if (e.g.type==_STRNG){ 3261 eq->need_active_parse=false; 3262 string s = *e.g._STRNGptr; 3263 int ss=s.size(); 3264 if (ss){ 3265 int begin_sel=max(0,min(eq->begin_sel,ss-1)); 3266 int end_sel=ss; 3267 if (eq->end_sel>=0) 3268 end_sel=min(eq->end_sel,ss); 3269 if (end_sel<begin_sel) 3270 giac::swapint(begin_sel,end_sel); 3271 if (end_sel<ss) 3272 s = s.substr(0,begin_sel)+s.substr(end_sel,ss-end_sel); 3273 else 3274 s = s.substr(0,begin_sel); 3275 pos = begin_sel; 3276 } 3277 else 3278 pos=0; 3279 e.g = string2gen(s,false); 3280 } 3281 else { 3282 eq->need_active_parse=true; 3283 e.g=string2gen(e.g.print(contextptr),false); 3284 e.g.subtype=1; 3285 pos=e.g._STRNGptr->size(); 3286 } 3287 e.active=true; 3288 e.selected=false; 3289 return; 3290 } 3291 if (g.type!=_VECT) 3292 return; 3293 vecteur & v =*g._VECTptr; 3294 iterateur it=v.begin(),itend=v.end(); 3295 if (Equation_is_selected(*(itend-1),false)){ 3296 g=Equation_nullstring(v.back()._EQWptr->eqw_attributs,0,contextptr); 3297 pos=0; 3298 return; 3299 } 3300 for (;it!=itend;++it){ 3301 if (Equation_is_selected(*it,false)) 3302 break; 3303 } 3304 if (it!=itend){ 3305 iterateur it0=it; 3306 int pos=it0-v.begin(); 3307 for (;it!=itend;++it){ 3308 if (!Equation_is_selected(*it,false)) 3309 break; 3310 } 3311 if (v.back().type == _EQW && v.back()._EQWptr->g==at_multistring && it0->type==_EQW && it0->_EQWptr->g.type==_STRNG && eq->begin_sel>=0 && eq->end_sel>=0){ 3312 --it; // it0 first selected, it last selected 3313 int ss=it->_EQWptr->g._STRNGptr->size(); 3314 int begin_sel=min(eq->begin_sel,ss),end_sel=min(eq->end_sel,ss); 3315 Equation_select(*it0,false); 3316 if (it==it0){ 3317 *it->_EQWptr->g._STRNGptr=it->_EQWptr->g._STRNGptr->substr(0,begin_sel)+it->_EQWptr->g._STRNGptr->substr(end_sel,ss-end_sel); 3318 Equation_select(*it,true,true); 3319 eq->active_pos=begin_sel; 3320 eq->need_active_parse=false; 3321 return ; 3322 } 3323 begin_sel=giacmin(eq->begin_sel,it0->_EQWptr->g._STRNGptr->size()); 3324 *it0->_EQWptr->g._STRNGptr=it0->_EQWptr->g._STRNGptr->substr(0,begin_sel)+it->_EQWptr->g._STRNGptr->substr(end_sel,ss-end_sel); 3325 Equation_select(*it0,true,true); 3326 eq->active_pos=begin_sel; 3327 eq->need_active_parse=false; 3328 ++it0; 3329 ++it; 3330 iterateur it1=it0; 3331 int deltay=0; 3332 int n=it0-v.begin(); 3333 for (;it1!=it;++it1){ 3334 eqwdata e=Equation_total_size(*it1); 3335 deltay=deltay+e.dy; 3336 } 3337 v.erase(it0,it); 3338 int s=v.size(); 3339 for (int j=n;j<s;++j){ 3340 Equation_translate(v[j],0,deltay); 3341 } 3342 return; 3343 } 3344 // Check whether it0 is a string, in that case erase in the string 3345 if (it0+1==it && it0->type==_EQW && it0->_EQWptr->g.type==_STRNG){ 3346 int ss=it0->_EQWptr->g._STRNGptr->size(); 3347 int begin_sel=max(min(eq->begin_sel,ss),0),end_sel=max(min(eq->end_sel,ss),0); 3348 Equation_select(*it0,false); 3349 *it0->_EQWptr->g._STRNGptr=it0->_EQWptr->g._STRNGptr->substr(0,begin_sel)+it0->_EQWptr->g._STRNGptr->substr(end_sel,ss-end_sel); 3350 Equation_select(*it0,true,true); 3351 eq->active_pos=begin_sel; 3352 eq->need_active_parse=false; 3353 return ; 3354 } 3355 // delete from it0 to it 3356 // NOTE that for history, it must be of even size 3357 if (g.subtype==_HIST__VECT){ 3358 if ( (it0-v.begin())%2) 3359 --it0; 3360 if ( (it-v.begin())%2) 3361 ++it; 3362 } 3363 v.erase(it0,it); 3364 if (v.size()==1){ // only the last item, i.e. operator 3365 g=Equation_nullstring(v.back()._EQWptr->eqw_attributs,0,contextptr); 3366 pos=0; 3367 return; 3368 } 3369 if (v.size()==2 3370 // && (v.back()._EQWptr->g==at_plus || v.back()._EQWptr->g==at_prod) 3371 ){ 3372 g=v.front(); 3373 Equation_select(g,true); 3374 return; 3375 } 3376 /* it=v.begin(),itend=v.end(); 3377 for (;it!=itend;++it) 3378 Equation_select(*it,true); */ 3379 if (pos>1 && pos<int(v.size())) 3380 Equation_select(v[pos-1],true); 3381 return; 3382 } 3383 // Remove 1st selection 3384 it=v.begin(); 3385 for (;it!=itend;++it){ 3386 if (Equation_is_selected(*it,true)){ 3387 Equation_remove_selection(*it,pos,eq); 3388 return; 3389 } 3390 } 3391 } 3392 remove_selection()3393 void Equation::remove_selection(){ 3394 save_data(); 3395 Equation_remove_selection(data,active_pos,this); 3396 begin_sel=-1; 3397 end_sel=-1; 3398 redraw(); 3399 } 3400 replace_down_left_activate(const gen & g)3401 void Equation::replace_down_left_activate(const gen & g){ 3402 if (replace_selection(g)){ 3403 select_down(0); 3404 select_left(0); 3405 deselect_and_activate(); 3406 if (in_multistring(data)==-1) 3407 need_active_parse=true; 3408 } 3409 } 3410 handle_backspace(Equation * eqwptr,int pos,vecteur * vptr)3411 void handle_backspace(Equation * eqwptr,int pos,vecteur * vptr){ 3412 string s=*(*vptr)[pos]._EQWptr->g._STRNGptr; 3413 iterateur it=vptr->begin()+pos; 3414 vptr->erase(it); 3415 --pos; 3416 string s0=*(*vptr)[pos]._EQWptr->g._STRNGptr; 3417 eqwptr->active_pos=s0.size(); 3418 s=s0+s; 3419 Equation_select((*vptr)[pos],true,true); 3420 eqwptr->replace_selection(string2gen(s,false),1); 3421 } 3422 3423 // act = 0 if nothing active or -> the active part 3424 // return true if the new selected part must be copied in clipboard handle_key(unsigned char c,gen * act)3425 bool Equation::handle_key(unsigned char c,gen * act){ 3426 const giac::context * contextptr = get_context(this); 3427 if (!c || c>=0x80) 3428 return false; 3429 if (!act || need_active_parse){ 3430 if (c=='(' || c==')'){ // if selection replace vector by sequences 3431 if (!act){ 3432 insure_something_selected(); 3433 gen g=get_selection(); 3434 if (g.is_symb_of_sommet(at_makevector)) 3435 replace_selection(symbolic(at_makesuite,g._SYMBptr->feuille)); 3436 else { 3437 if (g.type==_VECT && g.subtype!=_SEQ__VECT){ 3438 g.subtype=_SEQ__VECT; 3439 replace_selection(g); 3440 } 3441 else 3442 replace_selection(symbolic(at_of,makevecteur(f__IDNT_e,g))); 3443 } 3444 return true; 3445 } 3446 } 3447 if (c=='[' || c==']'){ // if selection replace seq by vector 3448 if (!act){ 3449 insure_something_selected(); 3450 gen g=get_selection(); 3451 if (g.is_symb_of_sommet(at_makesuite)) 3452 replace_selection(symbolic(at_makevector,g._SYMBptr->feuille)); 3453 else { 3454 if (g.type==_VECT && g.subtype==_SEQ__VECT){ 3455 g.subtype=0; 3456 replace_selection(g); 3457 } 3458 else { 3459 g.subtype=_SEQ__VECT; 3460 replace_selection(symbolic(at_at,makevecteur(m__IDNT_e,g))); 3461 } 3462 } 3463 return true; 3464 } 3465 } 3466 if (!act && (c=='+' || c=='-' || c=='*' || c=='/' || c=='^' || c==',' || c=='<' || c=='>' || c=='=') ){ 3467 insure_something_selected(); 3468 gen g=get_selection(); 3469 gen tmp; 3470 if (c==','){ 3471 if (g.type==_VECT && g.subtype==_SEQ__VECT){ 3472 vecteur v=*g._VECTptr; 3473 v.push_back(zero); 3474 replace_selection(gen(v,g.subtype)); 3475 select_down(0); 3476 select_left(0); 3477 return false; 3478 } 3479 gen oldg=g; 3480 select_up(0); 3481 g=get_selection(); 3482 if (g.type==_VECT && oldg!=g){ 3483 vecteur v=*g._VECTptr; 3484 v.push_back(zero); 3485 replace_selection(gen(v,g.subtype)); 3486 select_down(0); 3487 select_left(0); 3488 return false; 3489 } 3490 if (g.type==_SYMB && g._SYMBptr->feuille.type==_VECT){ 3491 bool inside=g.is_symb_of_sommet(at_of) || g.is_symb_of_sommet(at_at); 3492 int sub=0; 3493 vecteur v; 3494 if (inside){ 3495 if (g._SYMBptr->feuille._VECTptr->back().type==_VECT){ 3496 v=*g._SYMBptr->feuille._VECTptr->back()._VECTptr; 3497 sub=g._SYMBptr->feuille._VECTptr->back().subtype; 3498 } 3499 else { 3500 v=makevecteur(g._SYMBptr->feuille._VECTptr->back()); 3501 sub=_SEQ__VECT; 3502 } 3503 } 3504 else 3505 v=*g._SYMBptr->feuille._VECTptr; 3506 v.push_back(zero); 3507 if (g._SYMBptr->sommet==at_integrate && v.size()==3) 3508 v.push_back(plus_one); 3509 gen tmp; 3510 if (inside) 3511 tmp=symbolic(g._SYMBptr->sommet,gen(makevecteur(g._SYMBptr->feuille._VECTptr->front(),gen(v,sub)),g._SYMBptr->feuille.subtype)); 3512 else 3513 tmp=symbolic(g._SYMBptr->sommet,gen(v,g._SYMBptr->feuille.subtype)); 3514 replace_selection(tmp); 3515 select_down(0); 3516 if (inside){ 3517 select_right(0); 3518 select_down(0); 3519 select_left(0); 3520 } 3521 return false; 3522 } 3523 if (g.type==_SYMB){ 3524 vecteur v(gen2vecteur(g._SYMBptr->feuille)); 3525 if (v.size()==1 && (g._SYMBptr->sommet==at_integrate || g._SYMBptr->sommet==at_sum || g._SYMBptr->sommet==at_limit || g._SYMBptr->sommet==at_derive) ) 3526 v.push_back(vx_var); 3527 v.push_back(zero); 3528 if (g._SYMBptr->sommet==at_integrate || g._SYMBptr->sommet==at_sum) 3529 v.push_back(plus_one); 3530 replace_selection(symbolic(g._SYMBptr->sommet,gen(v,_SEQ__VECT))); 3531 return false; 3532 } 3533 tmp=at_makesuite; 3534 } // end if c==',' 3535 else 3536 tmp=gen(string("'")+char(c)+string("'"),contextptr); 3537 if (tmp.type!=_FUNC) 3538 setsizeerr(); 3539 unary_function_ptr f=*tmp._FUNCptr; 3540 if ( g.is_symb_of_sommet(at_makesuite) && ( (c!='/' && c!='^') || (g._SYMBptr->feuille.type==_VECT && g._SYMBptr->feuille._VECTptr->size()==2) ) ){ 3541 replace_selection(symbolic(f,g._SYMBptr->feuille)); 3542 return true; 3543 } 3544 else { 3545 tmp=gen(makevecteur(g,0),_SEQ__VECT); 3546 // tmp=gen(makevecteur(g,Equation_nullstring()),_SEQ__VECT); 3547 replace_down_left_activate(symbolic(f,tmp)); 3548 return false; 3549 } 3550 } 3551 } // end not active or active_parse 3552 if (act){ 3553 // *act is active and is a terminal of type string 3554 string s=*act->_EQWptr->g._STRNGptr; 3555 int ss=s.size(); 3556 active_pos=max(min(active_pos,ss),0); 3557 vecteur * vptr; 3558 int pos; 3559 switch (c){ 3560 case 0x0b: 3561 if (active_pos>0) 3562 --active_pos; 3563 else { 3564 pos=in_multistring(data,vptr); 3565 if (pos>0){ // back one line and active_pos maximal 3566 Equation_select(*act,false,true); 3567 --pos; 3568 Equation_select((*vptr)[pos],true,true); 3569 active_pos=RAND_MAX; 3570 } 3571 } 3572 return 1; 3573 case 0x0c: 3574 if (active_pos<ss) 3575 ++active_pos; 3576 else { 3577 pos=in_multistring(data,vptr); 3578 if (pos>=0 && pos<int(vptr->size()-1)){ // forward one line and active_pos maximal 3579 Equation_select(*act,false,true); 3580 ++pos; 3581 Equation_select((*vptr)[pos],true,true); 3582 active_pos=0; 3583 } 3584 } 3585 return 1; 3586 case 0x7f: 3587 if (active_pos>0){ 3588 s=s.substr(0,active_pos-1)+s.substr(active_pos,ss-active_pos); 3589 --active_pos; 3590 } 3591 else { 3592 pos=in_multistring(data,vptr); 3593 if (pos==-1) 3594 return 1; 3595 if (pos>0){ 3596 handle_backspace(this,pos,vptr); 3597 return 1; 3598 } 3599 else { 3600 if (ss==0){ 3601 act->_EQWptr->active=false; 3602 act->_EQWptr->selected=true; 3603 begin_sel=-1; 3604 end_sel=-1; 3605 remove_selection(); 3606 return false; 3607 } 3608 } 3609 } 3610 break; 3611 default: 3612 s = s.substr(0,active_pos)+char(c)+s.substr(active_pos,ss-active_pos); 3613 ++active_pos; 3614 } 3615 replace_selection(string2gen(s,false),1); 3616 return false; 3617 } 3618 // nothing active 3619 bool has_selection=false; 3620 gen g=Equation_selected2gen(this,data,has_selection); 3621 if (has_selection){ 3622 string tmp(1,c); 3623 gen tmps=string2gen(tmp,false); 3624 tmps.subtype=1; 3625 if (replace_selection(tmps)){ 3626 // if nothing active, activate 3627 attributs a(0,0,0); 3628 vecteur position; 3629 gen * ptr =Equation_selected(data,a,w(),position,1,contextptr); 3630 if (!ptr){ 3631 deselect_and_activate(); 3632 active_pos=1; 3633 } 3634 if (in_multistring(data)==-1 && g.type!=_STRNG) 3635 need_active_parse=true; 3636 } 3637 return false; 3638 } 3639 // nothing selected 3640 select_up(0); 3641 return true; 3642 } 3643 3644 /* not used // return true if conversion needed and done 3645 bool string2vector(const string & s,vector<string> & v){ 3646 int pos=s.find('\n'),newpos; 3647 int ss=s.size(); 3648 if (pos<0 || pos >= ss) 3649 return false; 3650 v.clear(); 3651 v.push_back(s.substr(0,pos)); 3652 for (;pos<ss;){ 3653 newpos=s.find('\n',pos); 3654 if (newpos<0 || newpos >= ss){ 3655 v.push_back(s.substr(pos,ss-pos)); 3656 return true; 3657 } 3658 v.push_back(s.substr(pos,newpos-pos)); 3659 pos=newpos; 3660 } 3661 } 3662 */ 3663 handle_text(const string & paste_s_orig,gen * act)3664 bool Equation::handle_text(const string & paste_s_orig,gen * act){ 3665 const giac::context * contextptr = get_context(this); 3666 string paste_s(paste_s_orig); 3667 int ps=paste_s.size(); 3668 if (ps>2 && paste_s[0]=='"' && paste_s[ps-1]=='"'){ 3669 ps = ps-2; 3670 paste_s=paste_s.substr(1,ps); 3671 } 3672 int nl=paste_s.find('\n'); 3673 bool needmulti=(nl>=0 && nl<ps); 3674 if (act){ // insert s 3675 string s; 3676 if (act->type!=_EQW || act->_EQWptr->g.type!=_STRNG){ 3677 cerr << "Error " << *act << '\n'; 3678 return false; 3679 } 3680 s=*act->_EQWptr->g._STRNGptr; 3681 int pos=giacmax(giacmin(active_pos,s.size()),0); 3682 active_pos=pos; 3683 int toend=s.size()-pos; 3684 s=s.substr(0,active_pos)+paste_s+s.substr(active_pos,toend); 3685 gen g(s,contextptr); 3686 if (giac::first_error_line(contextptr)) 3687 g=string2gen(s,false); 3688 if (!needmulti){ 3689 if (replace_selection(g,1)) 3690 active_pos = pos+paste_s.size(); 3691 return false; 3692 } 3693 vecteur * vptr; 3694 int n=in_multistring(data,vptr); 3695 if (n==-1){ 3696 if (need_active_parse) 3697 g=symbolic(at_expr,g); 3698 desactivate_and_select(); 3699 if (replace_selection(g)){ 3700 if (need_active_parse) 3701 select_down(0); 3702 select_down(0); 3703 select_left(0); 3704 pos = get_selection()._STRNGptr->size()-toend; 3705 deselect_and_activate(); 3706 active_pos = max(pos,0); 3707 need_active_parse=false; 3708 } 3709 return false; 3710 } 3711 // insert in current multistring 3712 s=""; 3713 const_iterateur it=vptr->begin(),itend=vptr->end()-1; 3714 for (int i=0;i<n;++i,++it){ 3715 if (it->type==_EQW && it->_EQWptr->g.type==_STRNG) 3716 s += *it->_EQWptr->g._STRNGptr + '\n'; 3717 } 3718 string ss=*act->_EQWptr->g._STRNGptr; 3719 s += ss.substr(0,active_pos)+paste_s+ss.substr(active_pos,ss.size()-active_pos); 3720 for (++it;it!=itend;++it){ 3721 if (it->type==_EQW && it->_EQWptr->g.type==_STRNG) 3722 s += '\n'+*it->_EQWptr->g._STRNGptr; 3723 } 3724 g=gen(s,contextptr); 3725 if (giac::first_error_line(contextptr)) 3726 g=string2gen(s,false); 3727 desactivate_and_select(); 3728 // count newline in paste_s, add to n, activate this line, cursor 3729 // at end of this line - the value of toend 3730 for (int i=0;i<ps;++i){ 3731 if (paste_s[i]=='\n') 3732 ++n; 3733 } 3734 select_up(0); 3735 vecteur position; 3736 attributs tmpattr(0,0,0); 3737 gen * ptr = Equation_selected(data,tmpattr,w(),position,false,contextptr); 3738 eqwdata olde=Equation_total_size(*ptr); 3739 * ptr = Equation_compute_size(g,olde.eqw_attributs,w(),contextptr); 3740 Equation_select(data,false); 3741 Equation_select((*ptr->_VECTptr)[n],true); 3742 g=get_selection(); 3743 if (g.type==_STRNG){ 3744 pos = g._STRNGptr->size(); 3745 deselect_and_activate(); 3746 need_active_parse = false; 3747 if (replace_selection(g,1)) 3748 active_pos = max(pos- toend,0) ; 3749 need_active_parse = false; 3750 } 3751 return false; 3752 } 3753 // remove selection and replace 3754 gen g(paste_s,contextptr); 3755 if (giac::first_error_line(contextptr)) 3756 g=string2gen(paste_s,false); 3757 if (needmulti) 3758 g=symbolic(at_expr,g); 3759 replace_selection(g); 3760 return true; 3761 } 3762 handle_text(const string & paste_s_orig)3763 bool Equation::handle_text(const string & paste_s_orig){ 3764 vecteur position; 3765 const giac::context * contextptr = get_context(this); 3766 gen * act=Equation_selected(data,attr,w(),position,1,contextptr); 3767 return handle_text(paste_s_orig,act); 3768 } 3769 3770 // activate at x,y, return cursor position or -1, or -3 for fl_widget_pointer Equation_set_active(int x,int y,gen & g,Equation * eq,bool inmultistring,gen * & activecellptr)3771 int Equation_set_active(int x,int y,gen & g,Equation * eq,bool inmultistring,gen * & activecellptr){ 3772 const giac::context * contextptr = get_context(eq); 3773 activecellptr=0; 3774 if (g.type==_EQW){ 3775 // x,y must be in the box 3776 eqwdata & e=*g._EQWptr; 3777 if (e.x>x || e.x+e.dx<x || e.y>y || e.y+e.dy<y) 3778 return -1; 3779 activecellptr=&e.g; 3780 if (e.g.type==_POINTER_){ 3781 return -3; 3782 } 3783 e.active=true; 3784 if (e.g.type==_STRNG) 3785 eq->need_active_parse=!inmultistring && e.g._STRNGptr->empty(); 3786 else { 3787 eq->need_active_parse=true; 3788 e.g=string2gen(e.g.print(contextptr),false); 3789 e.g.subtype=1; 3790 } 3791 // binary search for active_pos 3792 return Equation_binary_search_pos(e,x,y); 3793 } 3794 if (g.type!=_VECT) 3795 return -1; 3796 vecteur & v =*g._VECTptr; 3797 if (v.empty()) 3798 return -1; 3799 iterateur it=v.begin(),itend=v.end()-1; 3800 if (!inmultistring) 3801 inmultistring = itend->type==_EQW && itend->_EQWptr->g==at_multistring; 3802 int pos; 3803 for (;it!=itend;++it){ 3804 pos=Equation_set_active(x,y,*it,eq,inmultistring,activecellptr); 3805 if (pos!=-1){ 3806 return pos; 3807 } 3808 } 3809 if (it->type==_EQW){ // change operator 3810 eqwdata & e=*it->_EQWptr; 3811 if (e.x>x || e.x+e.dx<x || e.y>y || e.y+e.dy<y) 3812 return -1; 3813 if ((eq && !eq->output_equation) && e.g.type==_FUNC && !e.g._FUNCptr->ptr()->printsommet && e.g!=at_makesuite && e.g!=at_makelist && e.g!=at_makevector ){ 3814 eqwdata f(e); 3815 f.g=string2gen(e.g._FUNCptr->ptr()->s,false); 3816 int pos=Equation_binary_search_pos(f,x,y); 3817 string ans,debut=f.g._STRNGptr->substr(0,pos); 3818 if (handle_tab(debut,*giac::vector_completions_ptr(),eq->h()/2,eq->w()/2,pos,ans)){ 3819 gen tmp(ans,contextptr); 3820 if (tmp.type==_SYMB){ 3821 e.g=tmp._SYMBptr->sommet; 3822 return -2; 3823 } 3824 tmp=gen("'"+ans+"'",contextptr); 3825 if (tmp.type==_FUNC){ 3826 e.g=tmp; 3827 return -2; 3828 } 3829 } 3830 } 3831 } 3832 return -1; 3833 } set_active(int x,int y)3834 gen * Equation::set_active(int x,int y){ 3835 const giac::context * contextptr = get_context(this); 3836 deselect(); 3837 gen * gptr; 3838 int pos=Equation_set_active(x,y,data,this,false,gptr); 3839 if (pos==-3) 3840 return gptr; 3841 if (pos==-2){ 3842 data=Equation_compute_size(get_data(),attr,w(),contextptr); 3843 select(); 3844 redraw(); 3845 return 0; 3846 } 3847 if (pos==-1) 3848 Equation_select(data,false,true); 3849 else 3850 active_pos=pos; 3851 return 0; 3852 } 3853 3854 // Return 0 if the mouse cursor is not on a _POINTER_ object, 3855 // returns a pointer to the gen of type _POINTER_ otherwise Equation_is_pointer_active(Equation * eq,const gen & g,int x,int y)3856 gen * Equation_is_pointer_active(Equation * eq,const gen & g,int x,int y){ 3857 if (g.type==_EQW){ 3858 // x,y must be in the box 3859 eqwdata & e=*g._EQWptr; 3860 if (e.x>x || e.x+e.dx<x || e.y>y || e.y+e.dy<y) 3861 return 0; 3862 if (e.g.type==_POINTER_) 3863 return &e.g; 3864 return 0; 3865 } 3866 if (g.type!=_VECT) 3867 return 0; 3868 vecteur & v =*g._VECTptr; 3869 if (v.empty()) 3870 return 0; 3871 iterateur it=v.begin(),itend=v.end()-1; 3872 gen * pos; 3873 for (;it!=itend;++it){ 3874 pos=Equation_is_pointer_active(eq,*it,x,y); 3875 if (pos) 3876 return pos; 3877 } 3878 return 0; 3879 } 3880 3881 // for multistring Up and Down should not select Equation_multistring_activate(Equation * eq,int direction,int pos)3882 void Equation_multistring_activate(Equation * eq,int direction,int pos){ 3883 gen save_data=Equation_copy(eq->data); 3884 if (direction) 3885 eq->select_down(1); 3886 else 3887 eq->select_up(1); 3888 if (eq->get_selection().type==_STRNG){ 3889 eq->deselect_and_activate(); 3890 eq->active_pos=max(pos,0); 3891 } 3892 else { 3893 eq->data=save_data; 3894 eq->adjust_xy_sel(); 3895 } 3896 } 3897 3898 // return -1 if not in a multistring, position otherwise in_multistring(const gen & data,vecteur * & vptr)3899 int in_multistring(const gen & data,vecteur * & vptr){ 3900 if (data.type!=_VECT) 3901 return -1; 3902 vecteur & v =*data._VECTptr; 3903 iterateur it=v.begin(),itend=v.end(); 3904 if (itend==it) 3905 return -1; 3906 --itend; 3907 if (itend->type==_EQW && itend->_EQWptr->g==at_multistring){ 3908 for (;it!=itend;++it){ 3909 if (it->type==_EQW && it->_EQWptr->active){ 3910 vptr = &v; 3911 return it-v.begin(); 3912 } 3913 } 3914 return -1; 3915 } 3916 for (;it!=itend;++it){ 3917 int i=in_multistring(*it,vptr); 3918 if (i!=-1) 3919 return i; 3920 } 3921 return -1; 3922 } 3923 3924 // return -1 if not in a multistring, position otherwise in_multistring(const gen & data)3925 int in_multistring(const gen & data){ 3926 vecteur * vptr; 3927 return in_multistring(data,vptr); 3928 } 3929 handle_newline(Equation * eqwptr)3930 void handle_newline(Equation * eqwptr){ 3931 const giac::context * contextptr = get_context(eqwptr); 3932 vecteur * vptr; 3933 int n=in_multistring(eqwptr->data,vptr); 3934 if (n!=-1){ 3935 // add a new line here 3936 string s( *(*vptr)[n]._EQWptr->g._STRNGptr); 3937 int ss=s.size(),pos=max(min(eqwptr->active_pos,ss),0); 3938 string s1=s.substr(0,pos); 3939 string s2=s.substr(pos,ss-pos); 3940 (*vptr)[n]=Equation_compute_size(string2gen(s1,false),eqwptr->attr,0,contextptr); 3941 iterateur it=vptr->begin()+(n+1); 3942 vptr->insert(it,Equation_compute_size(string2gen(s2,false),eqwptr->attr,0,contextptr)); 3943 Equation_select((*vptr)[n],false,true); // desactivate line n 3944 Equation_select((*vptr)[n+1],true,true); // activate line n+1 3945 eqwptr->active_pos=0; 3946 eqwptr->replace_selection(string2gen(s2,false),1); 3947 } 3948 else { 3949 // not in a multistring, transform current in a multistring 3950 bool parse=eqwptr->need_active_parse; 3951 eqwptr->need_active_parse=false; 3952 eqwptr->desactivate_and_select(); 3953 gen g=eqwptr->get_selection(); 3954 if (g.type==_STRNG) // FIXME: should add newline at active_pos 3955 g=string2gen(*g._STRNGptr+'\n',false); 3956 bool res; 3957 if (parse){ 3958 g=symbolic(at_expr,g); 3959 res=eqwptr->replace_selection(g); 3960 eqwptr->select_down(0); 3961 } 3962 else { 3963 res=eqwptr->replace_selection(g); 3964 } 3965 if (res){ 3966 eqwptr->select_down(0); 3967 eqwptr->select_right(0); 3968 eqwptr->deselect_and_activate(); 3969 eqwptr->need_active_parse=false; 3970 } 3971 } 3972 } 3973 switch_expr(Equation * eqwptr)3974 bool switch_expr(Equation * eqwptr){ 3975 gen g=eqwptr->get_selection(); 3976 if (g.type==_STRNG){ 3977 eqwptr->replace_selection(symbolic(at_expr,g)); 3978 return true; 3979 } 3980 if (g.is_symb_of_sommet(at_expr)){ 3981 eqwptr->replace_selection(g._SYMBptr->feuille); 3982 return true; 3983 } 3984 return false; 3985 } 3986 handle(int event)3987 int Equation::handle(int event){ 3988 if (event==FL_MOUSEWHEEL){ 3989 eqwdata e=Equation_total_size(data); 3990 if (Fl::event_inside(this) && vscroll && h()<e.dy){ 3991 int n=Fl::e_dy; 3992 int v=vscroll->value(); 3993 if (n<0 && v==0) 3994 return 0; 3995 if (n>0 && v>e.dy-h()+1) 3996 return 0; 3997 return vscroll->handle(event); 3998 } 3999 else 4000 return 0; 4001 } 4002 xcas::History_Pack * hp=get_history_pack(this); 4003 giac::context * cptr=hp?hp->contextptr:0; 4004 if (is_context_busy(cptr)){ 4005 thread_param * ptr= thread_param_ptr(cptr); 4006 if (ptr && ptr->f_param==this) // handle is locked during eval 4007 return 1; 4008 } 4009 int i=Fl_Group::handle(event); 4010 if (i) 4011 return i; 4012 i=in_handle(event); 4013 if (i==-1) 4014 return 1; 4015 // if (i) 4016 // Fl::focus(this); 4017 return i; 4018 } 4019 in_handle(int event)4020 int Equation::in_handle(int event){ 4021 const giac::context * contextptr = get_context(this); 4022 if (event==FL_FOCUS || event==FL_PUSH){ 4023 redraw(); 4024 Xcas_input_focus=this; 4025 Fl::focus(this); 4026 if (event==FL_FOCUS) 4027 return 1; 4028 } 4029 if (event==FL_KEYBOARD) 4030 Xcas_input_focus=this; 4031 bool is_history=(data.type==_VECT && data.subtype==_HIST__VECT); 4032 bool complete_level_selected=false; 4033 eqwdata data_eqwdata=Equation_total_size(data); 4034 if (is_history){ // check if a complete level is selected 4035 const_iterateur it=data._VECTptr->begin(),itend=data._VECTptr->end(); 4036 for (;it!=itend;++it){ 4037 eqwdata e=Equation_total_size(*it); 4038 if (e.selected){ 4039 complete_level_selected=true; 4040 break; 4041 } 4042 } 4043 } 4044 attributs attr; 4045 vecteur position; 4046 gen f,* act=Equation_selected(data,attr,w(),position,1,contextptr); 4047 char ch; 4048 if (act && act->type==_EQW && act->_EQWptr->g.type==_STRNG) 4049 ; 4050 else 4051 act=0; 4052 if (event==FL_RELEASE && Fl::event_button()== FL_MIDDLE_MOUSE ){ 4053 int x,y; 4054 x=Fl::event_x()-this->x()+xleft; 4055 y=Fl::event_y()-this->y(); 4056 deselect(); 4057 gen * gptr=set_active(x,ytop-y); 4058 if (gptr && gptr->type==_POINTER_) 4059 // should call the handle method of the pointer 4060 return 1; 4061 Fl::paste(*this); 4062 return 1; 4063 } 4064 if (event==FL_PASTE) { 4065 handle_text(Fl::event_text(),act); 4066 return 1; 4067 } 4068 if (event==FL_KEYBOARD){ 4069 /* if (Fl::event_state()== FL_CTRL || Fl::event_state()== FL_ALT) 4070 return 0; */ 4071 bool sel_changed=true; 4072 bool shifton= (Fl::event_state()== FL_SHIFT ); 4073 int mode=Fl::event_state(FL_CTRL); 4074 if (mode) 4075 mode=2; 4076 else 4077 mode=shifton?0:1; 4078 int save_active_pos=active_pos; 4079 switch (Fl::event_key()){ 4080 case FL_Left: 4081 if (act) 4082 handle_key(0x0b,act); 4083 else { 4084 if (!parse_desactivate()) 4085 select_left(mode); // it was shift_on 4086 } 4087 break; 4088 case FL_Right: 4089 if (act) 4090 handle_key(0x0c,act); 4091 else { 4092 if (!parse_desactivate()) 4093 select_right(mode); 4094 } 4095 break; 4096 case FL_Up: 4097 if (shifton && complete_level_selected){ 4098 select_left(0); 4099 select_left(0); 4100 } 4101 else { 4102 if (!parse_desactivate()) 4103 select_up(!shifton); 4104 else 4105 if (!shifton) 4106 Equation_multistring_activate(this,0,save_active_pos); 4107 } 4108 break; 4109 case FL_Down: 4110 if (shifton && complete_level_selected){ 4111 select_right(0); 4112 select_right(0); 4113 } 4114 else { 4115 if (!parse_desactivate()) 4116 select_down(!shifton); 4117 else 4118 if (!shifton) 4119 Equation_multistring_activate(this,1,save_active_pos); 4120 } 4121 break; 4122 case FL_Escape: 4123 if (cb_escape) 4124 cb_escape(this); 4125 else 4126 parse_desactivate(); 4127 redraw(); 4128 return 1; 4129 case FL_Shift_L: case FL_Shift_R: 4130 case FL_Caps_Lock: 4131 case FL_Meta_L: case FL_Meta_R: case FL_Menu: case FL_Num_Lock: 4132 case FL_Insert: 4133 return 1; 4134 case FL_Control_R: case FL_Control_L: case FL_Alt_L: case FL_Alt_R: 4135 return 0; 4136 case FL_BackSpace: 4137 case FL_Delete: 4138 if (is_history && complete_level_selected && cb_backspace){ 4139 cb_backspace(this); 4140 return 1; 4141 } 4142 if (modifiable){ 4143 if (act){ 4144 handle_key(0x7f,act); 4145 return 1; 4146 } 4147 else { 4148 f=get_selection(); 4149 if (f.type==_SYMB){ 4150 f=f._SYMBptr->feuille; 4151 if (f.type==_VECT && !f.subtype && !ckmatrix(f)) 4152 f.subtype=_SEQ__VECT; 4153 replace_selection(f); 4154 } 4155 else 4156 remove_selection(); 4157 } 4158 } 4159 break; 4160 case FL_Enter: case FL_KP_Enter: 4161 /* 4162 if (old_upper_window_state==upper_window_mtrw){ 4163 manage_upper_window(upper_window_mtrw,false); 4164 } 4165 else { 4166 manage_upper_window(upper_window_hist,false); 4167 } 4168 input_value(eqw_data2gen(data).print(contextptr).c_str()); 4169 */ 4170 if (shifton) 4171 handle_newline(this); 4172 else { 4173 if (cb_enter) 4174 cb_enter(this,0); 4175 else 4176 parse_desactivate(); 4177 } 4178 redraw(); 4179 return 1; 4180 case FL_Home: 4181 xleft=data_eqwdata.x; 4182 sel_changed=false; 4183 break; 4184 case FL_End: 4185 xleft=data_eqwdata.x+data_eqwdata.dx-w(); 4186 sel_changed=false; 4187 break; 4188 case FL_Page_Up: 4189 ytop -= h(); 4190 sel_changed=false; 4191 break; 4192 case FL_Page_Down: 4193 ytop += h(); 4194 sel_changed=false; 4195 break; 4196 default: 4197 if (modifiable){ 4198 ch=Fl::event_text()?Fl::event_text()[0]:0; 4199 int es=Fl::event_state(); 4200 if (es== FL_ALT || es==1572864){ 4201 return 0; 4202 // ?? 4203 if (ch=='v'){ 4204 gen e; 4205 select_user_var(100,200,e,0); 4206 if (output_equation){ 4207 if (!parse_desactivate()) 4208 insure_something_selected(true); 4209 eval_function(e); 4210 } 4211 return 1; 4212 } 4213 } 4214 if (ch==1){ // Ctrl-A select all 4215 select(); 4216 fl_select(); 4217 return 1; 4218 } 4219 if (ch==3) { // Ctrl-C 4220 static string s; 4221 s=get_selection().print(contextptr); 4222 Fl::copy(s.c_str(),s.size(),1); 4223 return 1; 4224 } 4225 if (ch==18){ // Ctrl-R 4226 in_Xcas_input_1arg(this,"integrate"); 4227 return 1; 4228 } 4229 if (ch==19){ // Ctrl-S 4230 if (!parse_desactivate()) 4231 insure_something_selected(true); 4232 eval_function(at_simplify); 4233 return 1; 4234 } 4235 if (ch==4){ // Ctrl-D 4236 in_Xcas_input_1arg(this,"diff"); 4237 return 1; 4238 } 4239 if (ch==5){ // Ctrl-E 4240 if (!parse_desactivate()) 4241 insure_something_selected(true); 4242 eval_function(at_eval); 4243 return 1; 4244 } 4245 if (ch==6){ // Ctrl-F 4246 if (!parse_desactivate()) 4247 insure_something_selected(true); 4248 eval_function(at_factor); 4249 return 1; 4250 } 4251 if (ch==12){ // Ctrl-L 4252 in_Xcas_input_1arg(this,"limit"); 4253 return 1; 4254 } 4255 if (ch==14){ // Ctrl-N 4256 if (!parse_desactivate()) 4257 insure_something_selected(true); 4258 eval_function(at_normal); 4259 return 1; 4260 } 4261 if (ch==16){ // Ctrl-P 4262 if (!parse_desactivate()) 4263 insure_something_selected(true); 4264 eval_function(at_partfrac); 4265 return 1; 4266 } 4267 if (ch>=17 && ch<=20) // Ctrl-Q T 4268 return 0; 4269 if (ch==22){ // Ctrl-V 4270 Fl::paste(*this,1); 4271 return 1; 4272 } 4273 if (ch==26){ // Ctrl-Z 4274 rcl_data(-1); 4275 adjust_widget_size(); 4276 return 1; 4277 } 4278 if (ch==25){ // Ctrl-Y 4279 rcl_data(1); 4280 adjust_widget_size(); 4281 return 1; 4282 } 4283 if (ch==9){ // tab, ctrl-I 4284 string s,ans; 4285 if (act){ 4286 s=*act->_EQWptr->g._STRNGptr; 4287 int ss=s.size(); 4288 active_pos=max(min(active_pos,ss),0); 4289 string fin=s.substr(active_pos,s.size()-active_pos); 4290 s=s.substr(0,active_pos); 4291 int remove=active_pos; 4292 if (handle_tab(s,(*vector_completions_ptr()),h()/2,w()/2,remove,ans)){ 4293 int l=s.size()-remove; 4294 if (l<0) 4295 l=0; 4296 ans=s.substr(0,l)+ans; 4297 replace_selection(string2gen(ans+fin,false),1); 4298 active_pos=ans.size(); 4299 return 1; 4300 } 4301 } 4302 else { 4303 insure_something_selected(); 4304 gen gs=get_selection(); 4305 s=gs.print(contextptr); 4306 int pos=s.find('('); 4307 if (pos>0 && pos<int(s.size())) 4308 s=s.substr(0,pos); 4309 int remove; 4310 if (gs.type==_SYMB && handle_tab(s,(*vector_completions_ptr()),h()/2,w()/2,remove,ans)){ 4311 // FIXME remove remove chars 4312 gen gf=gen("'"+s+ans+"'",contextptr); 4313 if (gf.type==_FUNC) 4314 replace_selection(symbolic(*gf._FUNCptr,gs._SYMBptr->feuille)); 4315 } 4316 } 4317 return 1; 4318 } 4319 if (ch=='"'){ 4320 if (act && in_multistring(data)==-1){ 4321 // change mode, ! in multistring 4322 need_active_parse=!need_active_parse; 4323 redraw(); 4324 return 1; 4325 } 4326 if (switch_expr(this)){ 4327 redraw(); 4328 return 1; 4329 } 4330 else { 4331 gen g=get_selection(); 4332 replace_selection(string2gen(g.print(),false)); 4333 deselect_and_activate(); 4334 need_active_parse=true; 4335 return 1; 4336 } 4337 } 4338 sel_changed=handle_key(ch,act); 4339 } // end if (modifiable) 4340 } 4341 if (sel_changed){ 4342 fl_select(); 4343 setscroll(); 4344 } 4345 return 1; 4346 } // end event==FL_KEYBOARD 4347 int x,y; 4348 x=Fl::event_x() - this->x() +xleft; 4349 y=Fl::event_y() - this->y(); 4350 if (event==FL_PUSH ){ 4351 if ( (vscroll->visible() && (Fl::event_x() - this->x()>w()-vscroll->w()) ) 4352 || (hscroll->visible() && (y>h()-hscroll->h())) ){ 4353 return 0; 4354 } 4355 if (Fl::event_button()!= FL_MIDDLE_MOUSE) 4356 // desactivate active cell if any 4357 parse_desactivate(); 4358 xsel=x; 4359 ysel=ytop-y; 4360 xcur=xsel; 4361 ycur=ysel; 4362 if (Fl::event_button()!= FL_MIDDLE_MOUSE) 4363 deselect(); 4364 redraw(); 4365 gen * gptr=Equation_is_pointer_active(this,data,x,ytop-y); 4366 if (gptr && gptr->type==_POINTER_ && gptr->subtype==_FL_WIDGET_POINTER){ 4367 // call the handle method of the pointer 4368 Fl_Widget * flptr=(Fl_Widget *) gptr->_POINTER_val; 4369 flptr->handle(event); 4370 Fl::focus(this); 4371 return 1; 4372 } 4373 return 1; 4374 } 4375 if (event==FL_DRAG){ 4376 if (Fl::event_button()!= FL_MIDDLE_MOUSE) 4377 deselect(); 4378 redraw(); 4379 if ( (absint(xsel-x)<=2) && (absint(ysel-(ytop-y))<2) ){ 4380 redraw(); 4381 return 1; 4382 } 4383 gen * gptr=Equation_is_pointer_active(this,data,x,ytop-y); 4384 if (gptr && gptr->type==_POINTER_ && gptr->subtype==_FL_WIDGET_POINTER){ 4385 // call the handle method of the pointer 4386 Fl_Widget * flptr=(Fl_Widget *) gptr->_POINTER_val; 4387 flptr->handle(event); 4388 Fl::focus(this); 4389 return 1; 4390 } 4391 if (Fl::event_button()!= FL_MIDDLE_MOUSE) 4392 select_rectangle(x,ytop-y); 4393 return 1; 4394 } 4395 if (event==FL_RELEASE){ 4396 Fl::focus(this); 4397 deselect(); 4398 redraw(); 4399 gen * gptr=Equation_is_pointer_active(this,data,x,ytop-y); 4400 if (gptr && gptr->type==_POINTER_ && gptr->subtype==_FL_WIDGET_POINTER){ 4401 // call the handle method of the pointer 4402 Fl_Widget * flptr=(Fl_Widget *) gptr->_POINTER_val; 4403 flptr->handle(event); 4404 Fl::focus(this); 4405 return 1; 4406 } 4407 if ( (absint(xsel-x)<=2) && (absint(ysel-(ytop-y))<2) ){ 4408 if (Fl::event_clicks()){ // double-click 4409 // x=xsel+10; 4410 // y=ytop-ysel+4; 4411 desactivate_and_select(); 4412 //gen g=get_selection(); 4413 select_rectangle(x,ytop-y); 4414 } 4415 else 4416 gen * gptr=set_active(x,ytop-y); 4417 return 1; 4418 } 4419 select_rectangle(x,ytop-y); 4420 if (Fl::event_button()!= FL_MIDDLE_MOUSE) 4421 fl_select(); 4422 return 1; 4423 } 4424 return 0; 4425 } 4426 cb_Equation_Select(Fl_Menu_ * m,void *)4427 static void cb_Equation_Select(Fl_Menu_* m , void*) { 4428 if (m){ 4429 Equation * eq = dynamic_cast<Equation *>(m->parent()); 4430 const giac::context * contextptr = get_context(eq); 4431 if (eq){ 4432 Fl::focus(eq); 4433 Xcas_input_focus=eq; 4434 string s =eq->get_data().print(contextptr); 4435 Fl::selection(*eq,s.c_str(),s.size()); 4436 eq->select(); 4437 eq->redraw(); 4438 } 4439 } 4440 } 4441 Equation_eval_callback(const giac::gen & evaled_g,void * param)4442 void Equation_eval_callback(const giac::gen & evaled_g,void * param){ 4443 Fl_Widget * wid=static_cast<Fl_Widget *>(param); 4444 if (!wid) 4445 return; 4446 Equation * eq = dynamic_cast<Equation *>(wid); 4447 if (!eq) 4448 return; 4449 Xcas_input_focus=eq; 4450 eq->replace_selection_wo_save(evaled_g); 4451 } 4452 cb_Equation_Function(Fl_Menu_ * m,const unary_function_ptr * u)4453 void cb_Equation_Function(Fl_Menu_* m ,const unary_function_ptr * u) { 4454 if (m){ 4455 Equation * eq = dynamic_cast<Equation *>(m->parent()); 4456 if (eq){ 4457 Fl::focus(eq); 4458 Xcas_input_focus=eq; 4459 eq->save_data(); 4460 xcas::History_Pack * hp=get_history_pack(eq); 4461 giac::context * cptr=hp?hp->contextptr:0; 4462 make_thread(symbolic(u,eq->get_selection()),eval_level(cptr),Equation_eval_callback,eq,cptr); 4463 } 4464 } 4465 } 4466 cb_Equation_Evalf(Fl_Menu_ * m,void *)4467 static void cb_Equation_Evalf(Fl_Menu_* m , void*) { 4468 cb_Equation_Function(m,at_evalf); 4469 } 4470 cb_Equation_Eval(Fl_Menu_ * m,void *)4471 static void cb_Equation_Eval(Fl_Menu_* m , void*) { 4472 cb_Equation_Function(m,at_eval); 4473 } 4474 cb_Equation_Exact(Fl_Menu_ * m,void *)4475 static void cb_Equation_Exact(Fl_Menu_* m , void*) { 4476 cb_Equation_Function(m,at_exact); 4477 } 4478 cb_Equation_Simplify(Fl_Menu_ * m,void *)4479 static void cb_Equation_Simplify(Fl_Menu_* m , void*) { 4480 cb_Equation_Function(m,at_simplify); 4481 } 4482 4483 cb_Equation_Editselection(Fl_Menu_ * m,void *)4484 static void cb_Equation_Editselection(Fl_Menu_* m , void*) { 4485 if (m){ 4486 Equation * eq = dynamic_cast<Equation *>(m->parent()); 4487 if (eq){ 4488 Fl::focus(eq); 4489 Xcas_input_focus=eq; 4490 eq->save_data(); 4491 xcas::History_Pack * hp=get_history_pack(eq); 4492 giac::context * cptr=hp?hp->contextptr:0; 4493 gen g=eq->get_selection(); 4494 eq->replace_selection(string2gen(g.print(),false)); 4495 eq->deselect_and_activate(); 4496 eq->need_active_parse=true; 4497 } 4498 } 4499 } 4500 cb_Equation_Normal(Fl_Menu_ * m,void *)4501 static void cb_Equation_Normal(Fl_Menu_* m , void*) { 4502 cb_Equation_Function(m,at_normal); 4503 } 4504 cb_Equation_Factor(Fl_Menu_ * m,void *)4505 static void cb_Equation_Factor(Fl_Menu_* m , void*) { 4506 cb_Equation_Function(m,at_factor); 4507 } 4508 cb_Equation_Back(Fl_Menu_ * m,void *)4509 static void cb_Equation_Back(Fl_Menu_* m , void*) { 4510 if (m){ 4511 Equation * eq = dynamic_cast<Equation *>(m->parent()); 4512 if (eq){ 4513 Xcas_input_focus=eq; 4514 eq->rcl_data(-1); 4515 } 4516 } 4517 } 4518 cb_Equation_Forward(Fl_Menu_ * m,void *)4519 static void cb_Equation_Forward(Fl_Menu_* m , void*) { 4520 if (m){ 4521 Equation * eq = dynamic_cast<Equation *>(m->parent()); 4522 if (eq){ 4523 Xcas_input_focus=eq; 4524 eq->rcl_data(1); 4525 } 4526 } 4527 } 4528 4529 Fl_Menu_Item Equation_menu[] = { 4530 {gettext("M"), 0, 0, 0, 64, 0, 0, 14, 56}, 4531 {gettext("Select all"), 0, (Fl_Callback*)cb_Equation_Select, 0, 0, 0, 0, 14, 56}, 4532 {gettext("Edit selection"), 0, (Fl_Callback*)cb_Equation_Editselection, 0, 0, 0, 0, 14, 56}, 4533 {gettext("simplify"), 0, (Fl_Callback*)cb_Equation_Simplify, 0, 0, 0, 0, 14, 56}, 4534 {gettext("normal"), 0, (Fl_Callback*)cb_Equation_Normal, 0, 0, 0, 0, 14, 56}, 4535 {gettext("factor"), 0, (Fl_Callback*)cb_Equation_Factor, 0, 0, 0, 0, 14, 56}, 4536 {gettext("approx"), 0, (Fl_Callback*)cb_Equation_Evalf, 0, 0, 0, 0, 14, 56}, 4537 {gettext("exact"), 0, (Fl_Callback*)cb_Equation_Exact, 0, 0, 0, 0, 14, 56}, 4538 {gettext("eval"), 0, (Fl_Callback*)cb_Equation_Eval, 0, 0, 0, 0, 14, 56}, 4539 {gettext("Back"), 0, (Fl_Callback*)cb_Equation_Back, 0, 0, 0, 0, 14, 56}, 4540 {gettext("Forward"), 0, (Fl_Callback*)cb_Equation_Forward, 0, 0, 0, 0, 14, 56}, 4541 {0}, 4542 {0} 4543 }; 4544 add_scroll_menu()4545 void Equation::add_scroll_menu(){ 4546 int largeur=labelsize(); 4547 vscroll=new Equation_Scrollbar(x()+Fl_Group::w()-largeur,y(),largeur,Fl_Group::h()-labelsize(),this,true); 4548 vscroll->labelsize(largeur); 4549 hscroll=new Equation_Scrollbar(x(),y()+Fl_Group::h()-labelsize(),Fl_Group::w()-2*largeur,labelsize(),this,false); 4550 hscroll->labelsize(largeur); 4551 Fl_Group::add(vscroll); 4552 Fl_Group::add(hscroll); 4553 menubar = new Fl_Menu_Bar(hscroll->x()+hscroll->w(),hscroll->y(),this->w()-hscroll->w(),hscroll->h()); 4554 int s= Equation_menu->size(); 4555 Fl_Menu_Item * menuitem = new Fl_Menu_Item[s]; 4556 for (int i=0;i<s;++i) 4557 *(menuitem+i)=*(Equation_menu+i); 4558 menubar->menu (menuitem); 4559 menubar->tooltip(gettext("Equation menu")); 4560 Fl_Group::add(menubar); 4561 setscroll(); 4562 } 4563 Equation(int x,int y,int w,int h,const char * ch)4564 Equation::Equation(int x, int y, int w, int h,const char * ch): Fl_Group(x, y, max(w,20), max(h,20)){ 4565 xleft=0; 4566 ytop=h; 4567 xcur=0; 4568 ycur=0; 4569 begin_sel=-1; 4570 end_sel=-1; 4571 cb_escape=0; 4572 cb_enter=0; 4573 cb_backspace=0; 4574 cb_select=0; 4575 undo_history.clear(); 4576 undo_history_pos=0; 4577 attr=attributs(14,Xcas_equation_background_color,Xcas_equation_color); 4578 labelsize(14); 4579 modifiable=true; 4580 output_equation=true; 4581 data=Equation_nullstring(attr,0,context0); 4582 Fl_Group::end(); 4583 add_scroll_menu(); 4584 } 4585 Equation(int x,int y,int w,int h,const char * l,const gen & g)4586 Equation::Equation(int x, int y, int w, int h, const char* l,const gen & g): Fl_Group(x, y, max(w,20), max(h,20), l){ 4587 const giac::context * contextptr = get_context(this); 4588 xleft=0; 4589 ytop=h; 4590 xcur=0; 4591 ycur=0; 4592 begin_sel=-1; 4593 end_sel=-1; 4594 cb_escape=0; 4595 cb_enter=0; 4596 cb_backspace=0; 4597 cb_select=0; 4598 undo_history.clear(); 4599 undo_history_pos=0; 4600 attr=attributs(14,Xcas_equation_background_color,Xcas_equation_color); 4601 labelsize(14); 4602 modifiable=true; 4603 output_equation=true; 4604 if (taille(g,max_prettyprint_equation)<max_prettyprint_equation) 4605 data=Equation_compute_size(g,attr,w,contextptr); 4606 else 4607 data=Equation_compute_size(string2gen("Object_too_large",false),attr,w,contextptr); 4608 Fl_Group::end(); 4609 add_scroll_menu(); 4610 } 4611 Equation(int x,int y,int w,int h,const char * l,const gen & g,attributs myattr)4612 Equation::Equation(int x, int y, int w, int h, const char* l,const gen & g,attributs myattr) : Fl_Group(x, y, max(w,20), max(h,20), l){ 4613 const giac::context * contextptr = get_context(this); 4614 labelsize(giacmin(giacmax(myattr.fontsize,10),16)); 4615 xleft=0; 4616 ytop=h; 4617 xcur=0; 4618 ycur=0; 4619 begin_sel=-1; 4620 end_sel=-1; 4621 cb_escape=0; 4622 cb_enter=0; 4623 cb_backspace=0; 4624 cb_select=0; 4625 undo_history.clear(); 4626 undo_history_pos=0; 4627 attr=myattr; 4628 modifiable=true; 4629 output_equation=true; 4630 if (taille(g,max_prettyprint_equation)<max_prettyprint_equation) 4631 data=Equation_compute_size(g,attr,w,contextptr); 4632 else 4633 data=Equation_compute_size(string2gen("Object_too_large",false),attr,w,contextptr); 4634 Fl_Group::end(); 4635 add_scroll_menu(); 4636 } 4637 Equation(int x,int y,int w,int h,const char * l,const gen & g,attributs myattr,GIAC_CONTEXT)4638 Equation::Equation(int x, int y, int w, int h, const char* l,const gen & g,attributs myattr,GIAC_CONTEXT) : Fl_Group(x, y, max(w,20), max(h,20), l){ 4639 labelsize(giacmin(giacmax(myattr.fontsize,10),16)); 4640 xleft=0; 4641 ytop=h; 4642 xcur=0; 4643 ycur=0; 4644 begin_sel=-1; 4645 end_sel=-1; 4646 cb_escape=0; 4647 cb_enter=0; 4648 cb_backspace=0; 4649 cb_select=0; 4650 undo_history.clear(); 4651 undo_history_pos=0; 4652 attr=myattr; 4653 modifiable=true; 4654 output_equation=true; 4655 if (taille(g,max_prettyprint_equation)<max_prettyprint_equation) 4656 data=Equation_compute_size(g,attr,w,contextptr); 4657 else 4658 data=Equation_compute_size(string2gen("Object_too_large",false),attr,w,contextptr); 4659 Fl_Group::end(); 4660 add_scroll_menu(); 4661 } 4662 resize(int x,int y,int w,int h)4663 void Equation::resize(int x, int y, int w, int h){ 4664 Fl_Widget::resize(x,y,w,h); 4665 int L=giac::giacmin(20,labelsize()); 4666 vscroll->resize(x+Fl_Group::w()-L,y,L,Fl_Group::h()-L); 4667 hscroll->resize(x,y+Fl_Group::h()-L,Fl_Group::w()-2*L,L); 4668 menubar->resize(hscroll->x()+hscroll->w(),hscroll->y(),2*L,L); 4669 setscroll(); 4670 } 4671 ~Equation()4672 Equation::~Equation(){ 4673 if (Xcas_input_focus==this) 4674 Xcas_input_focus=0; 4675 remove(hscroll); 4676 remove(vscroll); 4677 remove(menubar); 4678 delete vscroll; 4679 delete hscroll; 4680 delete [] menubar->menu(); 4681 delete menubar; 4682 } 4683 4684 // return a variable from the list of vars select_user_var(int dx,int dy,gen & ans,GIAC_CONTEXT)4685 bool select_user_var(int dx,int dy,gen & ans,GIAC_CONTEXT){ 4686 gen res=_VARS(1,contextptr); 4687 if (res.type!=_VECT) 4688 return false; 4689 vecteur v(*res._VECTptr); 4690 int s=v.size(); 4691 Fl_Group::current(0); 4692 Fl_Window * w = new Fl_Window(dx,dy); 4693 Fl_Return_Button * button0 = new Fl_Return_Button(2,2,dx/2-4,16); 4694 button0->shortcut(0xff0d); 4695 button0->label(gettext("OK")); 4696 Fl_Button * button1 = new Fl_Button(dx/2+2,2,dx/2-4,16); 4697 button1->shortcut(0xff1b); 4698 button1->label(gettext("Cancel")); 4699 Fl_Browser * browser = new Fl_Browser(2,20,dx,dy-22); 4700 browser->type(2); 4701 browser->label("Variables"); 4702 // browser->callback((Fl_Callback*)cb_eqw_browser); 4703 for (int k=0;k<s;++k) 4704 browser->add(v[k].print(contextptr).c_str()); 4705 browser->value(1); 4706 int i=1,r=0; 4707 w->end(); 4708 w->resizable(w); 4709 w->set_modal(); 4710 if (s){ 4711 browser->value(1); 4712 w->show(); 4713 Fl_Widget * savefocus=Fl::focus(); 4714 Fl::focus(button1); 4715 for (;;) { 4716 Fl_Widget *o = Fl::readqueue(); 4717 if (!o) Fl::wait(); 4718 else { 4719 if (o == button0) {r = 0; break;} 4720 if (o == button1) {r = 1; break;} 4721 if (o == w) { r=0; break; } 4722 } 4723 } 4724 Fl::focus(savefocus); 4725 w->hide(); 4726 i=browser->value(); 4727 } 4728 delete browser; 4729 delete button1; 4730 delete button0; 4731 delete w; 4732 if (r==0 && i<=s && i>0){ 4733 ans=v[i-1]; 4734 return true; 4735 } 4736 else 4737 return false; 4738 } 4739 Equation_Scrollbar(int x,int y,int w,int h,Equation * ptr,bool is_vertical)4740 Equation_Scrollbar::Equation_Scrollbar(int x,int y,int w,int h,Equation * ptr,bool is_vertical):Fl_Scrollbar(x,y,w,h),eqwptr(ptr),vertical(is_vertical) { 4741 Fl_Scrollbar * o= this; 4742 o->maximum(1000); 4743 o->step(10); 4744 o->slider_size(1); 4745 o->callback( (Fl_Callback*) Equation_cb_scroll ); 4746 if (is_vertical) 4747 o->type(FL_VERTICAL); 4748 else 4749 o->type(FL_HORIZONTAL); 4750 o->labelsize(giac::giacmin(20,ptr->labelsize())); 4751 }; 4752 4753 #ifndef NO_NAMESPACE_XCAS 4754 } // namespace xcas 4755 #endif // ndef NO_NAMESPACE_XCAS 4756 4757 #endif // HAVE_LIBFLTK 4758