1 // -*- mode:C++ ; compile-command: "g++ -I.. -g -c Print.cc" -*- 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 "Print.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_Hold_Browser.H> 35 #include <FL/Fl_Value_Input.H> 36 #include <FL/Fl_Return_Button.H> 37 #include "History.h" 38 #include "Equation.h" 39 #include "Graph.h" 40 #include "Graph3d.h" 41 #include "Tableur.h" 42 #include <iostream> 43 #include <fstream> 44 45 using namespace std; 46 using namespace giac; 47 48 #ifdef FL_DEVICE 49 50 //#include <FL/Fl_Printer.H> 51 #include <FL/Fl_PS_Printer.H> 52 53 #ifdef WIN32 54 #include <FL/Fl_GDI_Printer.H> 55 #endif 56 57 #include <FL/fl_printer_chooser.H> 58 59 #include "Fl_PS_Printer.cxx" 60 61 #ifdef WIN32 62 #include "Fl_GDI_Printer.cxx" 63 #endif 64 65 #define Fl_PostScript_Graphics_Driver Fl_PS_Printer 66 #define Fl_PostScript_File_Device Fl_PS_Printer 67 #define Fl_PrintDevice Fl_Printer 68 #else // FL_DEVICE 69 #include <FL/Fl_PostScript.H> 70 #define Fl_PrintDevice Fl_Paged_Device 71 #endif // FL_DEVICE 72 73 74 75 #ifndef NO_NAMESPACE_XCAS 76 namespace xcas { 77 #endif // ndef NO_NAMESPACE_XCAS 78 79 #ifdef FL_DEVICE 80 double pixel_scale=0.21*FL_MM; // 1000 pixels=21 cm 81 #else 82 double FL_MM=1.0; 83 double FL_INCH=23.0; 84 double pixel_scale=1; // should be fixed to work with scales 85 #endif 86 change_background_color(Fl_Widget * w,int c,int newc)87 int change_background_color(Fl_Widget * w,int c,int newc){ 88 int oldc=w->color(); 89 if (oldc==c) 90 w->color(newc); 91 if (Fl_Group * g=dynamic_cast<Fl_Group *>(w)){ 92 int n=g->children(); 93 for (int i=0;i<n;++i) 94 change_background_color(g->child(i),c,newc); 95 } 96 return oldc; 97 } 98 99 #ifdef Fl_Printer_H 100 #ifdef FL_DEVICE 101 int printer_format=Fl_Printer::A4; 102 #else 103 int printer_format=Fl_Paged_Device::A4; 104 #endif 105 #else // Fl_Printer_H 106 int printer_format=-1; 107 #endif // Fl_Printer_H 108 bool printer_landscape=false; 109 110 #ifdef FL_DEVICE 111 ck_page_height(Fl_Printer * p)112 unsigned ck_page_height(Fl_Printer * p){ 113 int h=p->page_height(); 114 if (h<=0){ 115 cerr << "Bad page height " << h << '\n'; 116 h=806; 117 } 118 } 119 ck_page_width(Fl_Printer * p)120 unsigned ck_page_width(Fl_Printer * p){ 121 int w=p->page_width(); 122 if (w<=0){ 123 cerr << "Bad page width " << w << '\n'; 124 w=559; 125 } 126 } 127 print_newpage(Fl_Printer * p)128 void print_newpage(Fl_Printer * p){ 129 if (printer_landscape) 130 p->page(printer_format | Fl_Printer::LANDSCAPE); 131 else 132 p->page(printer_format); 133 } 134 Flv_Table_Gen_widget_print(Flv_Table_Gen * g,Fl_Printer * p,bool eps)135 void Flv_Table_Gen_widget_print(Flv_Table_Gen * g,Fl_Printer * p,bool eps){ 136 print_newpage(p); 137 double margin=FL_INCH; 138 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 139 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 140 g->resize(0,0,wp,hp); 141 int i=0,j=0; // current row/column 142 for (;j<g->cols()-1;){ 143 if (i || j) 144 print_newpage(p); 145 g->row(g->rows()); 146 g->col(g->cols()); 147 g->select_start_row(g->rows()); 148 g->select_start_col(g->cols()); 149 g->redraw(); 150 g->row(i); 151 g->col(j); 152 g->select_start_row(i); 153 g->select_start_col(j); 154 g->redraw(); 155 p->place(0.0, 0.0, margin,margin, pixel_scale); 156 fl_draw(g); 157 i = g->get_row(100,hp-20); 158 i = max(i,g->get_row(100,hp-25)); 159 i = max(i,g->get_row(95,hp-20)); 160 i = max(i,g->get_row(95,hp-25)); 161 if (i<0) 162 i=g->rows(); 163 if (i>=g->rows()-3){ 164 i=0; 165 g->row(i); 166 j=g->get_col(wp-30,hp-20); 167 j=max(j,g->get_col(wp-30,hp-25)); 168 j=max(j,g->get_col(wp-35,hp-20)); 169 j=max(j,g->get_col(wp-35,hp-25)); 170 if (j<0) 171 j=g->cols(); 172 } 173 } 174 } 175 Equation_widget_print(Equation * g,Fl_Printer * p,bool eps)176 void Equation_widget_print(Equation * g,Fl_Printer * p,bool eps){ 177 print_newpage(p); 178 int x=g->x(),y=g->y();//,h=g->h(),w=g->w(); 179 eqwdata e=Equation_total_size(g->data); 180 double margin=FL_INCH; 181 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 182 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 183 g->resize(x,y,wp,hp); 184 int np=e.dy/hp; 185 for (int i=0;i<=np;++i){ 186 if (i) 187 print_newpage(p); 188 //if (i) 189 //p->page(Fl_Printer::A4); 190 // fprintf(f,"%sPage: %d %d\n","%%",i+1,i+1); 191 g->xleft=e.x; 192 g->ytop=e.y+e.dy-i*hp; 193 p->place(g->xleft, 0, margin,margin, pixel_scale); 194 fl_draw(g); 195 } 196 } 197 Graph2d3d_widget_print(Graph2d3d * i,Fl_Printer * p,bool eps)198 void Graph2d3d_widget_print(Graph2d3d * i,Fl_Printer * p,bool eps){ 199 Graph3d * g3=dynamic_cast<Graph3d *>(i); 200 if (g3){ 201 if (Fl_PS_Printer * ps=dynamic_cast<Fl_PS_Printer * >(p)) 202 g3->printing=ps->file(); 203 } 204 int x=i->x(),y=i->y(),w=i->w(),h=i->h(); 205 if (eps){ 206 i->resize(0,0,w,h); 207 p->place(0.0,0.0,0.0,0.0,pixel_scale); 208 } 209 else { 210 print_newpage(p); 211 double margin=FL_INCH; 212 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 213 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 214 if (wp*h<hp*w) 215 i->resize(0,0,wp,(h*wp)/w); 216 else 217 i->resize(0,0,(hp*w)/h,hp); 218 p->place(0.0, 0.0, margin,margin, pixel_scale); 219 } 220 fl_draw(i); 221 i->resize(x,y,w,h); 222 if (g3) 223 g3->printing=0; 224 } 225 generic_widget_print(Fl_Widget * i,Fl_Printer * p,bool eps)226 void generic_widget_print(Fl_Widget * i,Fl_Printer * p,bool eps){ 227 int x=i->x(),y=i->y(),w=i->w(),h=i->h(); 228 if (eps){ 229 i->resize(0,0,w,h); 230 p->place(0.0,0.0,0.0,0.0,pixel_scale); 231 } 232 else { 233 print_newpage(p); 234 double margin=FL_INCH; 235 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 236 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 237 if (wp*h<hp*w) 238 i->resize(0,0,wp,(h*wp)/w); 239 else 240 i->resize(0,0,(hp*w)/h,hp); 241 p->place(0.0, 0.0, margin,margin, pixel_scale); 242 } 243 fl_draw(i); 244 i->resize(x,y,w,h); 245 } 246 Fl_Text_Editor_widget_print(Fl_Text_Editor * g,Fl_Printer * p,bool eps)247 void Fl_Text_Editor_widget_print(Fl_Text_Editor * g,Fl_Printer * p,bool eps){ 248 print_newpage(p); 249 Fl_Text_Buffer * b=g->buffer(); 250 double margin=FL_INCH; 251 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 252 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 253 int endpos=string(b->text()).size(); 254 int nlines=b->count_lines(0,endpos)+1; 255 int t=g->textsize(); 256 int npoints=nlines*t,np=npoints/hp; 257 if (npoints%hp) 258 np += 1; 259 // np=numbre of pages, adjust hp 260 int ligneparpage=nlines/np; 261 if (nlines%np){ 262 ligneparpage +=1 ; 263 /* 264 int j=np*ligneparpage-nlines; 265 // insert blank lines at end 266 string ins; 267 for (;j;--j) 268 ins += " \n"; 269 b->insert(endpos-1,ins.c_str()); 270 */ 271 } 272 hp=ligneparpage*t+g->scrollbar_width()+10; 273 g->resize(0,0,wp,hp); 274 for (int i=0;i<np;++i){ 275 if (i) 276 print_newpage(p); 277 if (i==np-1) 278 g->resize(0,0,wp,(nlines-i*ligneparpage)*t+g->scrollbar_width()+10); 279 g->scroll(i*ligneparpage+1,0); 280 p->place(0.0, 0.0, margin,margin, pixel_scale); 281 fl_draw(g); 282 } 283 } 284 setgraph3dprintstate(Fl_Widget * widget,FILE * stream,bool hidemouseparam)285 void setgraph3dprintstate(Fl_Widget * widget,FILE * stream,bool hidemouseparam){ 286 Fl_Group * g=dynamic_cast<Fl_Group *>(widget); 287 if (!g) 288 return; 289 int n=g->children(); 290 for (int i=0;i<n;++i){ 291 Fl_Widget * wid = g->child(i); 292 if (Fl_Group * gr=dynamic_cast<Fl_Group * >(wid)) 293 setgraph3dprintstate(gr,stream,hidemouseparam); 294 if (Graph2d3d * gr=dynamic_cast<Graph2d3d * >(wid)){ 295 if (gr->mouse_param_group){ 296 Fl_Group * G=gr->parent(); 297 if (stream){ 298 if (hidemouseparam) 299 gr->mouse_param_group->hide(); 300 } 301 else { 302 gr->mouse_param_group->show(); 303 if (G){ // restore correct sizes 304 gr->resize(gr->x(),gr->y(),G->w()+G->x()-gr->x()-gr->legende_size,gr->h()); 305 gr->resize_mouse_param_group(gr->legende_size); 306 } 307 } 308 } 309 if (Graph3d * gr3=dynamic_cast<Graph3d * >(wid)) 310 gr3->printing=stream; 311 } 312 } 313 } 314 315 // scan s children for last y() <= pos scan(Fl_Group * s,int pos,int hp)316 int scan(Fl_Group * s,int pos,int hp){ 317 if (s->y()+s->h()<=pos) 318 return s->y()+s->h(); 319 int n=s->children(),i; 320 int curpos=0; 321 for (i=0;i<n;++i){ 322 int y=s->child(i)->y(); 323 if (y>pos) 324 break; 325 else 326 curpos=y; 327 } 328 if (curpos<pos-hp/3) 329 return pos; 330 else 331 return curpos; 332 } 333 History_Pack_widget_print(History_Pack * g,Fl_Printer * p,bool eps)334 void History_Pack_widget_print(History_Pack * g,Fl_Printer *p,bool eps){ 335 // Save parent widget and position 336 Fl_Group * gp=g->parent(); 337 if (!gp) 338 return; 339 int pos=gp->find(g); 340 print_newpage(p); 341 int x=g->x(),y=g->y(),h=g->h(),w=g->w(); 342 double margin=FL_INCH; 343 int hp=int((ck_page_height(p)-2*margin)/pixel_scale); 344 int wp=int((ck_page_width(p)-2*margin)/pixel_scale); 345 // Create a scroll group of size hp/wp and put g in it 346 Fl_Group::current(0); 347 Fl_Window * win = new Fl_Window(0,0,wp,hp); 348 Fl_Scroll * s = new Fl_Scroll(0,0,wp,hp); 349 s->end(); 350 win->end(); 351 s->color(g->color()); 352 s->box(FL_FLAT_BOX); 353 s->add(g); 354 g->Fl_Group::resize(0,0,wp-g->labelsize(),h); 355 g->resize(); 356 int ypos=0,newpos=0; 357 for (;ypos<h;){ 358 if (ypos) 359 print_newpage(p); 360 #ifdef _HAVE_FL_UTF8_HDR_ 361 s->scroll_to(0,0); 362 #else 363 s->position(0,0); 364 #endif 365 newpos=scan(g,ypos+hp,hp); 366 s->resize(0,0,wp,newpos-ypos); 367 #ifdef _HAVE_FL_UTF8_HDR_ 368 s->scroll_to(0,ypos); 369 #else 370 s->position(0,ypos); 371 #endif 372 p->place(0.0,0, margin,margin, pixel_scale); 373 fl_draw(s); 374 ypos = newpos; 375 } 376 // Restore g in parent widget 377 g->Fl_Group::resize(x,y,w,h); 378 g->resize(); 379 gp->insert(*g,pos); 380 delete s; 381 } 382 inner_widget_print(Fl_Widget * widget,Fl_Printer * p,bool eps)383 void inner_widget_print(Fl_Widget * widget,Fl_Printer * p,bool eps){ 384 if (History_Pack * f=dynamic_cast<History_Pack *>(widget)){ 385 History_Pack_widget_print(f,p,eps); 386 return ; 387 } 388 if (Fl_Text_Editor * b=dynamic_cast<Fl_Text_Editor *>(widget)){ 389 Fl_Text_Editor_widget_print(b,p,eps); 390 return; 391 } 392 if (Equation * g = dynamic_cast<Equation *> (widget)){ 393 Equation_widget_print(g,p,eps); 394 return; 395 } 396 if (Graph2d3d * i=dynamic_cast<Graph2d3d *>(widget)){ 397 Graph2d3d_widget_print(i,p,eps); 398 return; 399 } 400 if (Flv_Table_Gen * t=dynamic_cast<Flv_Table_Gen *>(widget)){ 401 Flv_Table_Gen_widget_print(t,p,eps); 402 return; 403 } 404 generic_widget_print(widget,p,eps); 405 /* 406 if (Fl_Group * gr=dynamic_cast<Fl_Group *>(widget)){ 407 // print all elements of the group 408 int n=gr->children(); 409 for (int i=0;i<n;++i) 410 inner_widget_print(gr->child(i),p,eps); 411 return; 412 } 413 */ 414 } 415 in_widget_print(Fl_Widget * widget,Fl_Printer * p,bool eps)416 void in_widget_print(Fl_Widget * widget,Fl_Printer * p,bool eps){ 417 if (!widget) return; 418 bool screen_capture=false; 419 if (dynamic_cast<Fl_Window *>(widget)) 420 screen_capture=true; 421 if (!screen_capture) 422 change_background_color(widget,Xcas_background_color,7); 423 Fl_Output_Device * c = p->set_current(); 424 int x=widget->x(),y=widget->y(),h=widget->h(),w=widget->w(); 425 inner_widget_print(widget,p,eps); 426 widget->resize(x,y,w,h); 427 if (!screen_capture){ 428 change_background_color(widget,7,Xcas_background_color); 429 set_colors(widget); 430 } 431 c->set_current(); 432 } 433 434 #else // FL_DEVICE 435 436 #ifdef Fl_Printer_H 437 print_newpage(Fl_PrintDevice * p)438 void print_newpage(Fl_PrintDevice * p){ 439 p->start_page(); 440 } endpage(Fl_PrintDevice * p)441 void endpage(Fl_PrintDevice *p){ 442 p->end_page(); 443 } 444 compute_w_h(Fl_PrintDevice * p,double margin,double pixel_scale,int & wp,int & hp)445 void compute_w_h(Fl_PrintDevice *p,double margin,double pixel_scale,int & wp,int &hp){ 446 p->printable_rect(&wp,&hp); 447 if (wp<=1){ 448 cerr << "Bad width " << wp << '\n'; 449 wp=559; 450 } 451 if (hp<=1){ 452 cerr << "Bad height " << hp << '\n'; 453 hp=806; 454 } 455 } do_print(Fl_Widget * w,Fl_PrintDevice * p,double margin,double pixel_scale)456 void do_print(Fl_Widget * w,Fl_PrintDevice *p,double margin,double pixel_scale){ 457 p->print_widget(w,0,0); 458 } 459 Flv_Table_Gen_widget_print(Flv_Table_Gen * g,Fl_PrintDevice * p,bool eps)460 void Flv_Table_Gen_widget_print(Flv_Table_Gen * g,Fl_PrintDevice * p,bool eps){ 461 print_newpage(p); 462 double margin=FL_INCH; 463 int hp,wp; 464 compute_w_h(p,margin,pixel_scale,wp,hp); 465 g->resize(0,0,wp,hp); 466 int i=0,j=0; // current row/column 467 for (;j<g->cols()-1;){ 468 if (i || j) 469 print_newpage(p); 470 g->row(g->rows()); 471 g->col(g->cols()); 472 g->select_start_row(g->rows()); 473 g->select_start_col(g->cols()); 474 g->redraw(); 475 g->row(i); 476 g->col(j); 477 g->select_start_row(i); 478 g->select_start_col(j); 479 g->redraw(); 480 do_print(g,p,margin,pixel_scale); 481 endpage(p); 482 i = g->get_row(100,hp-20); 483 i = max(i,g->get_row(100,hp-25)); 484 i = max(i,g->get_row(95,hp-20)); 485 i = max(i,g->get_row(95,hp-25)); 486 if (i<0) 487 i=g->rows(); 488 if (i>=g->rows()-3){ 489 i=0; 490 g->row(i); 491 j=g->get_col(wp-30,hp-20); 492 j=max(j,g->get_col(wp-30,hp-25)); 493 j=max(j,g->get_col(wp-35,hp-20)); 494 j=max(j,g->get_col(wp-35,hp-25)); 495 if (j<0) 496 j=g->cols(); 497 } 498 } 499 } 500 Equation_widget_print(Equation * g,Fl_PrintDevice * p,bool eps)501 void Equation_widget_print(Equation * g,Fl_PrintDevice * p,bool eps){ 502 print_newpage(p); 503 int x=g->x(),y=g->y();//,h=g->h(),w=g->w(); 504 eqwdata e=Equation_total_size(g->data); 505 double margin=FL_INCH; 506 int hp,wp; 507 compute_w_h(p,margin,pixel_scale,wp,hp); 508 g->resize(x,y,wp,hp); 509 int np=e.dy/hp; 510 for (int i=0;i<=np;++i){ 511 if (i) 512 print_newpage(p); 513 //if (i) 514 //p->page(Fl_PrintDevice::A4); 515 // fprintf(f,"%sPage: %d %d\n","%%",i+1,i+1); 516 g->xleft=e.x; 517 g->ytop=e.y+e.dy-i*hp; 518 p->print_widget(g,g->xleft,0); 519 endpage(p); 520 } 521 } 522 523 class ps_file_device:public Fl_PostScript_File_Device { 524 public: driver()525 Fl_PostScript_Graphics_Driver * driver() { return Fl_PostScript_File_Device::driver(); }; ps_file_device()526 ps_file_device():Fl_PostScript_File_Device(){}; 527 }; 528 Graph2d3d_widget_print(Graph2d3d * i,Fl_PrintDevice * p,bool eps)529 void Graph2d3d_widget_print(Graph2d3d * i,Fl_PrintDevice * p,bool eps){ 530 Graph3d * g3=dynamic_cast<Graph3d *>(i); 531 if (g3){ 532 if (ps_file_device * ps=dynamic_cast<ps_file_device * >(p)){ 533 g3->printing=ps->driver()->file(); 534 } 535 } 536 int x=i->x(),y=i->y(),w=i->w(),h=i->h(); 537 if (eps){ 538 i->resize(0,0,w,h); 539 print_newpage(p); 540 do_print(i,p,0,pixel_scale); 541 } 542 else { 543 print_newpage(p); 544 double margin=FL_INCH; 545 int hp,wp; 546 compute_w_h(p,margin,pixel_scale,wp,hp); 547 if (wp*h<hp*w) 548 i->resize(0,0,wp,(h*wp)/w); 549 else 550 i->resize(0,0,(hp*w)/h,hp); 551 do_print(i,p,margin,pixel_scale); 552 endpage(p); 553 } 554 i->resize(x,y,w,h); 555 if (g3) 556 g3->printing=0; 557 } 558 generic_widget_print(Fl_Widget * i,Fl_PrintDevice * p,bool eps)559 void generic_widget_print(Fl_Widget * i,Fl_PrintDevice * p,bool eps){ 560 int x=i->x(),y=i->y(),w=i->w(),h=i->h(); 561 if (eps){ 562 print_newpage(p); 563 i->resize(0,0,w,h); 564 do_print(i,p,0,pixel_scale); 565 // endpage(p); 566 } 567 else { 568 print_newpage(p); 569 double margin=FL_INCH; 570 int hp,wp; 571 compute_w_h(p,margin,pixel_scale,wp,hp); 572 if (wp*h<hp*w) 573 i->resize(0,0,wp,(h*wp)/w); 574 else 575 i->resize(0,0,(hp*w)/h,hp); 576 do_print(i,p,margin,pixel_scale); 577 endpage(p); 578 } 579 i->resize(x,y,w,h); 580 } 581 Fl_Text_Editor_widget_print(Fl_Text_Editor * g,Fl_PrintDevice * p,bool eps)582 void Fl_Text_Editor_widget_print(Fl_Text_Editor * g,Fl_PrintDevice * p,bool eps){ 583 print_newpage(p); 584 Fl_Text_Buffer * b=g->buffer(); 585 double margin=FL_INCH; 586 int hp,wp; 587 compute_w_h(p,margin,pixel_scale,wp,hp); 588 int endpos=string(b->text()).size(); 589 int nlines=b->count_lines(0,endpos)+1; 590 int t=g->textsize(); 591 int npoints=nlines*t,np=npoints/hp; 592 if (npoints%hp) 593 np += 1; 594 // np=numbre of pages, adjust hp 595 int ligneparpage=nlines/np; 596 if (nlines%np){ 597 ligneparpage +=1 ; 598 /* 599 int j=np*ligneparpage-nlines; 600 // insert blank lines at end 601 string ins; 602 for (;j;--j) 603 ins += " \n"; 604 b->insert(endpos-1,ins.c_str()); 605 */ 606 } 607 hp=ligneparpage*t+g->scrollbar_width()+10; 608 g->resize(0,0,wp,hp); 609 for (int i=0;i<np;++i){ 610 if (i) 611 print_newpage(p); 612 if (i==np-1) 613 g->resize(0,0,wp,(nlines-i*ligneparpage)*t+g->scrollbar_width()+10); 614 g->scroll(i*ligneparpage+1,0); 615 do_print(g,p,margin,pixel_scale); 616 endpage(p); 617 } 618 } 619 620 // also show or hide mouse param group setgraph3dprintstate(Fl_Widget * widget,FILE * stream,bool hidemouseparam)621 void setgraph3dprintstate(Fl_Widget * widget,FILE * stream,bool hidemouseparam){ 622 Fl_Group * g=dynamic_cast<Fl_Group *>(widget); 623 if (!g) 624 return; 625 int n=g->children(); 626 for (int i=0;i<n;++i){ 627 Fl_Widget * wid = g->child(i); 628 if (Fl_Group * gr=dynamic_cast<Fl_Group * >(wid)) 629 setgraph3dprintstate(gr,stream,hidemouseparam); 630 if (Graph2d3d * gr=dynamic_cast<Graph2d3d * >(wid)){ 631 if (gr->mouse_param_group){ 632 Fl_Group * G=gr->parent(); 633 if (stream){ 634 if (hidemouseparam) 635 gr->mouse_param_group->hide(); 636 } 637 else { 638 gr->mouse_param_group->show(); 639 if (G){ // restore correct sizes 640 gr->resize(gr->x(),gr->y(),G->w()+G->x()-gr->x()-gr->legende_size,gr->h()); 641 gr->resize_mouse_param_group(gr->legende_size); 642 } 643 } 644 } 645 if (Graph3d * gr3=dynamic_cast<Graph3d * >(wid)) 646 gr3->printing=stream; 647 } 648 } 649 } 650 651 // scan s children for last y() <= pos scan(Fl_Group * s,int pos,int hp)652 int scan(Fl_Group * s,int pos,int hp){ 653 if (s->y()+s->h()<=pos) 654 return s->y()+s->h(); 655 int n=s->children(),i; 656 int curpos=0; 657 for (i=0;i<n;++i){ 658 int y=s->child(i)->y(); 659 if (y>pos) 660 break; 661 else 662 curpos=y; 663 } 664 if (curpos<pos-hp/3) 665 return pos; 666 else 667 return curpos; 668 } 669 History_Pack_widget_print(History_Pack * g,Fl_PrintDevice * p,bool eps)670 void History_Pack_widget_print(History_Pack * g,Fl_PrintDevice *p,bool eps){ 671 // Save parent widget and position 672 Fl_Group * gp=g->parent(); 673 if (!gp) 674 return; 675 int pos=gp->find(g); 676 print_newpage(p); 677 int x=g->x(),y=g->y(),h=g->h(),w=g->w(); 678 double margin=FL_INCH; 679 int hp,wp; 680 compute_w_h(p,margin,pixel_scale,wp,hp); 681 // Create a scroll group of size hp/wp and put g in it 682 Fl_Group::current(0); 683 Fl_Window * win = new Fl_Window(0,0,wp,hp); 684 Fl_Scroll * s = new Fl_Scroll(0,0,wp,hp); 685 s->end(); 686 win->end(); 687 s->color(g->color()); 688 s->box(FL_FLAT_BOX); 689 s->add(g); 690 g->Fl_Group::resize(0,0,wp-g->labelsize(),h); 691 g->resize(); 692 int ypos=0,newpos=0; 693 for (;ypos<h;){ 694 if (ypos) 695 print_newpage(p); 696 #ifdef _HAVE_FL_UTF8_HDR_ 697 s->scroll_to(0,0); 698 #else 699 s->position(0,0); 700 #endif 701 newpos=scan(g,ypos+hp,hp); 702 s->resize(0,0,wp,newpos-ypos); 703 #ifdef _HAVE_FL_UTF8_HDR_ 704 s->scroll_to(0,ypos); 705 #else 706 s->position(0,ypos); 707 #endif 708 do_print(s,p,margin,pixel_scale); 709 endpage(p); 710 ypos = newpos; 711 } 712 // Restore g in parent widget 713 g->Fl_Group::resize(x,y,w,h); 714 g->resize(); 715 gp->insert(*g,pos); 716 delete s; 717 } 718 inner_widget_print(Fl_Widget * widget,Fl_PrintDevice * p,bool eps)719 void inner_widget_print(Fl_Widget * widget,Fl_PrintDevice * p,bool eps){ 720 if (History_Pack * f=dynamic_cast<History_Pack *>(widget)){ 721 History_Pack_widget_print(f,p,eps); 722 return ; 723 } 724 if (Fl_Text_Editor * b=dynamic_cast<Fl_Text_Editor *>(widget)){ 725 Fl_Text_Editor_widget_print(b,p,eps); 726 return; 727 } 728 if (Equation * g = dynamic_cast<Equation *> (widget)){ 729 Equation_widget_print(g,p,eps); 730 return; 731 } 732 if (Graph2d3d * i=dynamic_cast<Graph2d3d *>(widget)){ 733 Graph2d3d_widget_print(i,p,eps); 734 return; 735 } 736 if (Flv_Table_Gen * t=dynamic_cast<Flv_Table_Gen *>(widget)){ 737 Flv_Table_Gen_widget_print(t,p,eps); 738 return; 739 } 740 generic_widget_print(widget,p,eps); 741 /* 742 if (Fl_Group * gr=dynamic_cast<Fl_Group *>(widget)){ 743 // print all elements of the group 744 int n=gr->children(); 745 for (int i=0;i<n;++i) 746 inner_widget_print(gr->child(i),p,eps); 747 return; 748 } 749 */ 750 } 751 in_widget_print(Fl_Widget * widget,Fl_PrintDevice * p,bool eps)752 void in_widget_print(Fl_Widget * widget,Fl_PrintDevice * p,bool eps){ 753 if (!widget) return; 754 bool screen_capture=false; 755 if (dynamic_cast<Fl_Window *>(widget)) 756 screen_capture=true; 757 if (!screen_capture) 758 change_background_color(widget,Xcas_background_color,7); 759 int x=widget->x(),y=widget->y(),h=widget->h(),w=widget->w(); 760 inner_widget_print(widget,p,eps); 761 widget->resize(x,y,w,h); 762 if (!screen_capture){ 763 change_background_color(widget,7,Xcas_background_color); 764 set_colors(widget); 765 } 766 } 767 #endif // Fl_Printer_H 768 769 #endif // FL_DEVICE 770 771 #ifdef WIN32 772 string ps_preview="!"; 773 #else 774 #ifdef __APPLE__ 775 string ps_preview="open"; // "/Applications/Preview.app/Contents/MacOS/Preview"; 776 #else 777 string ps_preview="gv"; 778 #endif 779 #endif 780 new_widget_size(int & neww,int & newh)781 bool new_widget_size(int & neww,int & newh){ 782 static Fl_Window * w = 0; 783 static Fl_Value_Input * fw=0, *fh=0,* pxl=0; 784 static Fl_Return_Button * button0 = 0 ; 785 static Fl_Button * button1 =0; 786 if (!w){ 787 int dx=300, dy=100; 788 Fl_Group::current(0); 789 w=new Fl_Window(dx,dy); 790 fw=new Fl_Value_Input(dx/4,2,dx/4-2,dy/3-4,gettext("Width")); 791 fw->tooltip(gettext("Width in pixels for export")); 792 fh=new Fl_Value_Input(3*dx/4,2,dx/4-2,dy/3-4,gettext("Height")); 793 fh->tooltip(gettext("Height in pixels for export")); 794 pxl=new Fl_Value_Input(3*dx/4,2+dy/3,dx/4-2,dy/3-4,gettext("Pixel size")); 795 pxl->tooltip(gettext("Pixel size in mm")); 796 button0 = new Fl_Return_Button(2,2+2*dy/3,dx/2-4,dy/3-4); 797 button0->shortcut(0xff0d); 798 button0->label(gettext("OK")); 799 button1 = new Fl_Button(dx/2+2,2+2*dy/3,dx/2-4,dy/3-4); 800 button1->shortcut(0xff1b); 801 button1->label(gettext("Cancel")); 802 w->end(); 803 w->resizable(w); 804 w->label(gettext("Size in pixels for export")); 805 } 806 fw->value(neww); 807 fh->value(newh); 808 pxl->value(pixel_scale/FL_MM); 809 int r=-1; 810 w->set_modal(); 811 w->show(); 812 w->hotspot(w); 813 Fl::focus(w); 814 for (;;) { 815 Fl_Widget *o = Fl::readqueue(); 816 if (!o) Fl::wait(); 817 else { 818 if (o == button0) {r = 0; break;} 819 if (o == button1) {r = 1; break;} 820 if (o == w) { r=1; break; } 821 } 822 } 823 w->hide(); 824 if (r) 825 return false; 826 neww=int(std::max(1.0,fw->value())); 827 newh=int(std::max(1.0,fh->value())); 828 pixel_scale=pxl->value()*FL_MM; 829 return true; 830 } 831 widget_ps_print(Fl_Widget * widget,const std::string & fname0,bool eps,int pngpdf,bool preview,bool hidemouseparam,bool askusersize)832 void widget_ps_print(Fl_Widget * widget,const std::string & fname0,bool eps,int pngpdf,bool preview,bool hidemouseparam,bool askusersize){ 833 if (!eps) 834 pngpdf=0; 835 #ifdef Fl_Printer_H 836 // Fl_PrintDevice * p = fl_printer_chooser(); 837 int x=widget->x(),y=widget->y(),w=widget->w(),h=widget->h(),neww(giacmin(w,570)),newh(h*double(neww)/w); 838 if (!askusersize && neww==570) 839 newh=300; 840 if (eps){ 841 if (askusersize && !new_widget_size(neww,newh)) 842 return; 843 widget->resize(x,y,neww,newh); 844 } 845 string fname1=replace(fname0,' ','_'); 846 if (fname1.empty()) 847 fname1="session"; 848 if (fname1[0]=='<') 849 fname1="session"; 850 string fname(remove_extension(fname1)+(eps?".eps":".ps")); 851 if (!eps || pngpdf){ 852 char * filename = file_chooser(eps?"Print to EPS/PNG/PDF file":"Print to PS file",eps?"*.eps":"*.ps",fname.c_str()); 853 if(!filename) return; 854 fname=remove_extension(filename)+(eps?".eps":".ps"); 855 } 856 FILE * f = fopen(fname.c_str(),"w"); 857 if(!f) return; 858 Fl_PrintDevice * p; 859 #ifdef FL_DEVICE 860 if (eps) 861 p= new Fl_PS_Printer(f, 3,0,0,int(widget->w()*pixel_scale),int(widget->h()*pixel_scale)); 862 else 863 p=new Fl_PS_Printer(f, 3); 864 #else 865 ps_file_device * ptr=new ps_file_device(); 866 if (!ptr) return; 867 ptr->driver()->pw_=eps?int(widget->w()*pixel_scale):0; 868 ptr->driver()->ph_=eps?int(widget->h()*pixel_scale):0; 869 ptr->start_job(f,eps?0:3); 870 p=ptr; 871 #endif 872 if (p){ 873 // Scan all graph3d widget inside and move their state to printing=p stream 874 #ifdef FL_DEVICE 875 if (Fl_PostScript_File_Device * ps=dynamic_cast<Fl_PostScript_File_Device * >(p)){ 876 setgraph3dprintstate(widget,ps->file(),hidemouseparam); 877 } 878 #else 879 if (ps_file_device * ps=dynamic_cast<ps_file_device * >(p)){ 880 setgraph3dprintstate(widget,ps->driver()->file(),hidemouseparam); 881 } 882 #endif 883 in_widget_print(widget,p,eps); 884 #ifndef FL_DEVICE 885 p->end_job(); 886 #endif 887 // Scan all graph3d widget inside and move their state to printing=true 888 setgraph3dprintstate(widget,0,false); 889 #ifdef FL_DEVICE 890 delete p; 891 #else 892 delete ptr; 893 #endif 894 } 895 fclose(f); //we need close file here 896 if (getenv("GIAC_PREVIEW")) 897 ps_preview=getenv("GIAC_PREVIEW"); 898 #ifdef WIN32 899 if (ps_preview=="!"){ 900 ps_preview="/cygdrive/c/"; 901 if (getenv("XCAS_ROOT")){ 902 string s(getenv("XCAS_ROOT")); 903 if (s.substr(0,10)=="/cygdrive/") 904 ps_preview[10]=s[10]; 905 } 906 ps_preview +="Program\\ Files/Ghostgum/gsview/gsview32.exe"; 907 } 908 pngpdf |= 0x4; 909 #endif 910 // translate into png, (inside GIMP Image->Transform->rotate, not anymore) 911 // inside latex use includegraphics[width=\textwidth{filename} 912 // FIXME add pstopnm pnmtopng libnetpbm to the window mac distributions 913 if (eps){ 914 widget->resize(x,y,w,h); 915 #ifndef WIN32 // def __APPLE__ 916 if (pngpdf & 0x1) 917 system_no_deprecation(("convert "+fname+" "+remove_extension(fname)+".png &").c_str()); 918 if (pngpdf & 0x2) 919 system_no_deprecation(("convert "+fname+" "+remove_extension(fname)+".pdf &").c_str()); 920 if (pngpdf & 0x4) 921 system_no_deprecation(("convert "+fname+" "+remove_extension(fname)+".jpg &").c_str()); 922 #else 923 #ifdef WIN32 924 if (pngpdf & 0x4) 925 system_no_deprecation((xcasroot()+"pstopnm -stdout -portrait '"+fname+"' | "+xcasroot()+"pnmtojpeg > '"+remove_extension(fname)+".jpg'").c_str()); 926 if (pngpdf & 0x1) 927 system_no_deprecation((xcasroot()+"pstopnm -stdout -portrait '"+fname+"' | "+xcasroot()+"pnmtopng > '"+remove_extension(fname)+".png' &").c_str()); 928 if (pngpdf & 0x2){ 929 // epstopdf is a perl script, it won't work wo perl 930 system_no_deprecation(("cp -f '"+fname+"' tmpeps.eps && epstopdf tmpeps.eps && cp -f tmpeps.pdf '"+remove_extension(fname)+".pdf' &").c_str()); 931 } 932 #else // not used anymore, assuming convert is avail. on linux 933 if (pngpdf & 0x1) 934 system_no_deprecation(("pstopnm -stdout -portrait "+fname+" | pnmtopng > "+remove_extension(fname)+".png &").c_str()); 935 if (pngpdf & 0x2) 936 system_no_deprecation(("epstopdf "+fname+" &").c_str()); 937 if (pngpdf & 0x4) 938 system_no_deprecation(("pstopnm -stdout -portrait "+fname+" | pnmtojpeg > "+remove_extension(fname)+".jpg &").c_str()); 939 #endif 940 #endif 941 } 942 // Preview 943 if (ps_preview!="no" && preview){ 944 #ifdef WIN32 945 system_browser_command(fname); 946 /* 947 string fn=absolute_path(fname); 948 if (system_no_deprecation((((ps_preview+" ")+fn)+" &").c_str())){ 949 cerr << (("cygstart.exe '"+remove_extension(fname)+".jpg' &").c_str()) << '\n'; 950 system_no_deprecation((xcasroot()+"cygstart.exe '"+remove_extension(fname)+".jpg' &").c_str()); 951 } 952 */ 953 #else 954 system_no_deprecation((((ps_preview+" ")+fname)+" &").c_str()); 955 #endif 956 } 957 if (eps && pngpdf){ 958 fname=remove_path(remove_extension(fname)); 959 unsigned fnames=fname.size(); 960 static string tmp; 961 tmp=fname+".eps/.png ready for import.\nUse \\includegraphics[width=\\textwidth]{"+fname+"}\nwhere [] is optional, width may also be e.g. 10cm\ninside your latex document, with header\n\\usepackage{graphicx}\n(PNG export requires pstopnm and pnmtopng)"; 962 if (Xcas_help_output){ 963 Xcas_help_output->value(tmp.c_str()); 964 Xcas_help_output->position(32+fnames,68+2*fnames); 965 Fl::copy(Xcas_help_output->Fl_Output::value()+32+fnames,36+fnames,0); 966 Fl::copy(Xcas_help_output->Fl_Output::value()+32+fnames,36+fnames,1); 967 Fl::focus(Xcas_help_output); 968 } 969 else 970 fl_message("%s",tmp.c_str()); 971 } 972 #endif 973 } 974 widget_print(Fl_Widget * widget)975 void widget_print(Fl_Widget * widget){ 976 #ifdef Fl_Printer_H 977 #ifdef FL_DEVICE 978 Fl_PrintDevice * p = fl_printer_chooser(); 979 if (p){ 980 // Scan all graph3d widget inside and move their state to printing=p stream 981 if (Fl_PostScript_Graphics_Driver * ps=dynamic_cast<Fl_PostScript_Graphics_Driver * >(p)) 982 setgraph3dprintstate(widget,ps->file(),true); 983 in_widget_print(widget,p,false); 984 delete p; 985 // Scan all graph3d widget inside and move their state to printing=true 986 setgraph3dprintstate(widget,0,false); 987 } 988 #else 989 Fl_Printer * p = new Fl_Printer(); 990 if (p->start_job(1)) 991 return; // unable to print 992 if (p){ 993 // Scan all graph3d widget inside and move their state to printing=p stream 994 if (Fl_PostScript_Graphics_Driver * ps=dynamic_cast<Fl_PostScript_Graphics_Driver * >(p)) 995 setgraph3dprintstate(widget,ps->file(),true); 996 in_widget_print(widget,p,false); 997 p->end_job(); 998 delete p; 999 // Scan all graph3d widget inside and move their state to printing=true 1000 setgraph3dprintstate(widget,0,false); 1001 } 1002 #endif 1003 #endif 1004 } 1005 1006 #ifndef NO_NAMESPACE_XCAS 1007 } // namespace xcas 1008 #endif // ndef NO_NAMESPACE_XCAS 1009 1010 #endif // HAVE_LIBFLTK 1011