1 // -*- mode:C++ ; compile-command: "g++ -DHAVE_CONFIG_H -I. -I.. -I../include -I../../giac/include -g -c Editeur.cc" -*- 2 #include "Editeur.h" 3 #include "Input.h" 4 #include "Tableur.h" 5 /* 6 * Copyright (C) 2000,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 3 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 23 #ifdef HAVE_LIBFLTK 24 #include <FL/fl_ask.H> 25 #include <FL/fl_ask.H> 26 #include <FL/Fl_Return_Button.H> 27 #include <FL/Fl_Tooltip.H> 28 #include <fstream> 29 #include "vector.h" 30 #include <algorithm> 31 #include <fcntl.h> 32 #include <cmath> 33 #include <time.h> // for nanosleep 34 #include <stdio.h> 35 #include <dirent.h> 36 #include <sys/stat.h> // auto-recovery function 37 #include "History.h" 38 #include "Print.h" 39 #include "Equation.h" 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> 42 #endif 43 44 using namespace std; 45 using namespace giac; 46 47 #ifndef NO_NAMESPACE_XCAS 48 namespace xcas { 49 #endif // ndef NO_NAMESPACE_XCAS 50 51 int alt_ctrl=0; 52 void (*alt_ctrl_cb)(int)=0; 53 54 std::vector<std::string> Xcas_Text_Editor::history; 55 int Xcas_Text_Editor::count=0; 56 57 // Highlighting, borrowed from FLTK1.2/test/editor.cxx 58 // Syntax highlighting stuff... 59 60 Fl_Text_Display::Style_Table_Entry styletable_init[] = { // Style table 61 { FL_BLACK, FL_COURIER, 14 }, // A - Plain 62 { FL_DARK_GREEN, FL_COURIER_ITALIC, 14 }, // B - Line comments 63 { FL_DARK_GREEN, FL_COURIER_ITALIC, 14 }, // C - Block comments 64 { FL_CYAN, FL_COURIER, 14 }, // D - Strings 65 { FL_DARK_RED, FL_COURIER, 14 }, // E - Directives 66 { FL_DARK_RED, FL_COURIER_BOLD, 14 }, // F - Types 67 { FL_BLUE, FL_COURIER_BOLD, 14 } // G - Keywords 68 }; 69 int styletable_n=sizeof(styletable_init) / sizeof(styletable_init[0]); 70 const char *code_keywords[] = { // List of known giac keywords... 71 "BEGIN", 72 "BREAK", 73 "CATCH", 74 "CONTINUE", 75 "Cycle", 76 "DO", 77 "Dialog", 78 "ELIF", 79 "ELSE", 80 "END", 81 "Else", 82 "ElseIf", 83 "EndDlog", 84 "EndFor", 85 "EndFunc", 86 "EndIf", 87 "EndLoop", 88 "EndPrgm", 89 "EndTry", 90 "EndWhile", 91 "Exit", 92 "FOR", 93 "FROM", 94 "For", 95 "Func", 96 "Goto", 97 "IF", 98 "If", 99 "LOCAL", 100 "Lbl", 101 "Local" 102 "Loop", 103 "Prgm", 104 "REPEAT", 105 "Return", 106 "STEP", 107 "THEN", 108 "TO", 109 "TRY", 110 "Then", 111 "Try", 112 "WHILE", 113 "While", 114 "alors", 115 "and", 116 "break", 117 "by", 118 "case", 119 "catch", 120 "continue", 121 "de", 122 "def", 123 "default", 124 "do", 125 "downto", 126 "elif", 127 "else", 128 "end", 129 "end_case", 130 "end_for", 131 "end_if", 132 "end_proc", 133 "end_while", 134 "et", 135 "except", 136 "faire", 137 "false", 138 "ffaire", 139 "ffonction", 140 "fi", 141 "fonction", 142 "for", 143 "fpour", 144 "from", 145 "fsi", 146 "ftantque", 147 "function", 148 "global", 149 "goto", 150 "if", 151 "jusqu_a", 152 "jusqua", 153 "jusque", 154 "label", 155 "local", 156 "non", 157 "not", 158 "od", 159 "operator", 160 "or", 161 "ou", 162 "pas", 163 "pour", 164 "proc", 165 "repeat", 166 "repeter", 167 "retourne", 168 "return", 169 "si", 170 "sinon", 171 "step", 172 "switch", 173 "tantque", 174 "then", 175 "throw", 176 "to", 177 "true", 178 "try", 179 "until", 180 "var", 181 "while", 182 "xor" 183 }; 184 185 // 186 // 'compare_keywords()' - Compare two keywords... 187 // 188 189 int compare_keywords(const void * a,const void * b)190 compare_keywords(const void *a, 191 const void *b) { 192 return (strcmp(*((const char **)a), *((const char **)b))); 193 } 194 alpha_order(const string & S1,const string & S2)195 bool alpha_order(const string & S1,const string & S2){ 196 string s1 =S1; 197 string s2 =S2; 198 for (unsigned i=0;i<s1.size();++i) 199 s1[i]=tolower(s1[i]); 200 for (unsigned i=0;i<s2.size();++i) 201 s2[i]=tolower(s2[i]); 202 if (s1!=s2) 203 return s1<s2; 204 return S1< S2; 205 } 206 207 // 208 // 'style_parse()' - Parse text and produce style data. 209 // 210 211 void style_parse(const char * text,char * style,int length)212 style_parse(const char *text, 213 char *style, 214 int length) { 215 char current; 216 int col; 217 int last; 218 char buf[255], 219 *bufptr; 220 const char *temp; 221 222 for (current = *style, col = 0, last = 0; length > 0; length --, text ++) { 223 if (current == 'B' || current>='E') current = 'A'; 224 if (current == 'A') { 225 // Check for directives, comments, strings, and keywords... 226 if (col == 0 && *text == '#' && !python_color) { 227 // Set style to directive 228 current = 'E'; 229 } else if (strncmp(text, "//", 2) == 0 || (python_color &&strncmp(text,"#",1)==0)) { 230 current = 'B'; 231 for (; length > 0 && *text != '\n'; length --, text ++) *style++ = 'B'; 232 233 if (length == 0) break; 234 } else if (strncmp(text, "/*", 2) == 0) { 235 current = 'C'; 236 } else if (strncmp(text, "\\\"", 2) == 0) { 237 // Quoted quote... 238 *style++ = current; 239 *style++ = current; 240 text ++; 241 length --; 242 col += 2; 243 continue; 244 } else if (*text == '\"') { 245 current = 'D'; 246 } else if (!last && isalphan(*text)) { 247 // Might be a keyword... 248 for (temp = text, bufptr = buf; 249 isalphan(*temp) && bufptr < (buf + sizeof(buf) - 1); 250 *bufptr++ = *temp++); 251 252 if (!isalphan(*temp)) { 253 *bufptr = '\0'; 254 255 bufptr = buf; 256 257 if (bsearch(&bufptr, code_keywords, 258 sizeof(code_keywords) / sizeof(code_keywords[0]), 259 sizeof(code_keywords[0]), compare_keywords)) { 260 current='A'; 261 while (text < temp) { 262 *style++ = 'G'; 263 text ++; 264 length --; 265 col ++; 266 } 267 268 text --; 269 length ++; 270 last = 1; 271 continue; 272 } else if (giac::vector_completions_ptr() && binary_search(giac::vector_completions_ptr()->begin(),giac::vector_completions_ptr()->end(),bufptr,alpha_order)) { 273 current='A'; 274 while (text < temp) { 275 *style++ = 'F'; 276 text ++; 277 length --; 278 col ++; 279 } 280 281 text --; 282 length ++; 283 last = 1; 284 continue; 285 } 286 } 287 } 288 } else if (current == 'C' && strncmp(text, "*/", 2) == 0) { 289 // Close a C comment... 290 *style++ = current; 291 *style++ = current; 292 text ++; 293 length --; 294 current = 'A'; 295 col += 2; 296 continue; 297 } else if (current == 'D') { 298 // Continuing in string... 299 if (strncmp(text, "\\\"", 2) == 0) { 300 // Quoted end quote... 301 *style++ = current; 302 *style++ = current; 303 text ++; 304 length --; 305 col += 2; 306 continue; 307 } else if (*text == '\"') { 308 // End quote... 309 *style++ = current; 310 col ++; 311 current = 'A'; 312 continue; 313 } 314 } else if ( (current=='F' || current=='G') && !isalphan(*text)){ 315 current='A'; 316 } 317 // Copy style info... 318 if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G'; 319 else *style++ = current; 320 col ++; 321 322 last = isalphan(*text) || *text == '.'; 323 324 if (*text == '\n') { 325 // Reset column and possibly reset the style 326 col = 0; 327 if (current == 'B' || current >= 'E') current = 'A'; 328 } 329 } 330 } 331 332 333 // 334 // 'style_update()' - Update the style buffer... 335 // 336 337 void style_update(int pos,int nInserted,int nDeleted,int,const char *,void * cbArg)338 style_update(int pos, // I - Position of update 339 int nInserted, // I - Number of inserted chars 340 int nDeleted, // I - Number of deleted chars 341 int /*nRestyled*/, // I - Number of restyled chars 342 const char * /*deletedText*/,// I - Text that was deleted 343 void *cbArg 344 ) { // I - Callback data 345 int start, // Start of text 346 end; // End of text 347 char last, // Last style on line 348 *style, // Style data 349 *text; // Text data 350 351 Fl_Text_Buffer * stylebuf= ((Xcas_Text_Editor *) cbArg)->stylebuf; 352 // If this is just a selection change, just unselect the style buffer... 353 if (nInserted == 0 && nDeleted == 0) { 354 stylebuf->unselect(); 355 return; 356 } 357 358 // Track changes in the text buffer... 359 if (nInserted > 0) { 360 // Insert characters into the style buffer... 361 style = new char[nInserted + 1]; 362 memset(style, 'A', nInserted); 363 style[nInserted] = '\0'; 364 365 stylebuf->replace(pos, pos + nDeleted, style); 366 delete[] style; 367 } else { 368 // Just delete characters in the style buffer... 369 stylebuf->remove(pos, pos + nDeleted); 370 } 371 372 // Select the area that was just updated to avoid unnecessary 373 // callbacks... 374 stylebuf->select(pos, pos + nInserted - nDeleted); 375 376 // Re-parse the changed region; we do this by parsing from the 377 // beginning of the line of the changed region to the end of 378 // the line of the changed region... Then we check the last 379 // style character and keep updating if we have a multi-line 380 // comment character... 381 Fl_Text_Buffer * textbuf=((Fl_Text_Editor *)cbArg)->buffer(); 382 start = textbuf->line_start(pos); 383 end = textbuf->line_end(pos + nInserted); 384 text = textbuf->text_range(start, end); 385 style = stylebuf->text_range(start, end); 386 last = start==end?0:style[end - start - 1]; 387 388 // printf("start = %d, end = %d, text = \"%s\", style = \"%s\"...\n", 389 // start, end, text, style); 390 391 style_parse(text, style, end - start); 392 393 // printf("new style = \"%s\"...\n", style); 394 395 stylebuf->replace(start, end, style); 396 ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); 397 398 if (start==end || last != style[end - start - 1]) { 399 // The last character on the line changed styles, so reparse the 400 // remainder of the buffer... 401 free(text); 402 free(style); 403 404 end = textbuf->length(); 405 text = textbuf->text_range(start, end); 406 style = stylebuf->text_range(start, end); 407 408 style_parse(text, style, end - start); 409 410 stylebuf->replace(start, end, style); 411 ((Fl_Text_Editor *)cbArg)->redisplay_range(start, end); 412 } 413 414 free(text); 415 free(style); 416 } 417 418 // 419 // 'style_unfinished_cb()' - Update unfinished styles. 420 // 421 422 void style_unfinished_cb(int,void *)423 style_unfinished_cb(int, void*) { 424 } 425 426 427 // 428 // 'style_init()' - Initialize the style buffer... 429 // 430 style_init(Xcas_Text_Editor * textbuf)431 void style_init(Xcas_Text_Editor * textbuf ) { 432 } 433 434 bool editor_changed=false; 435 Editor_changed_cb(int,int nInserted,int nDeleted,int,const char *,void * v)436 void Editor_changed_cb(int, int nInserted, int nDeleted,int, const char*, void* v) { 437 if ((nInserted || nDeleted)) 438 editor_changed = true; 439 } 440 do_find_editor(Fl_Widget * widget)441 Fl_Text_Editor * do_find_editor(Fl_Widget * widget){ 442 if (!widget) 443 return 0; 444 Fl_Group * gr = widget->parent(); 445 if (!gr) 446 return 0; 447 Editeur * e=dynamic_cast<Editeur *>(gr); 448 if (e) 449 return e->editor; 450 else 451 return 0; 452 } 453 find_editor(Fl_Widget * widget)454 Fl_Text_Editor * find_editor(Fl_Widget * widget){ 455 Fl_Text_Editor * ed=do_find_editor(widget); 456 if (ed) 457 return ed; 458 ed=do_find_editor(Fl::focus()); 459 if (!ed) 460 fl_alert("%s",gettext("No program editor found. Please click in or add one")); 461 return ed; 462 } 463 cb_Editeur(Fl_Menu_ * m,void *)464 static void cb_Editeur(Fl_Menu_* m , void*) { 465 Fl_Text_Editor * e = find_editor(m); 466 if (e){ 467 } 468 } 469 470 static void cb_Editeur_Save(Fl_Widget * m , void*); 471 editeur_load(Fl_Text_Editor * e)472 std::string editeur_load(Fl_Text_Editor * e){ 473 if (e){ 474 char * newfile = load_file_chooser("Insert program", ("*."+dynamic_cast<Editeur *>(e->parent())->extension).c_str(), "",0,false); 475 if ( file_not_available(newfile) ) 476 return ""; 477 e->buffer()->insertfile(newfile,e->insert_position()); 478 return newfile; 479 } 480 return ""; 481 } 482 cb_Editeur_Load(Fl_Widget * m,void *)483 static void cb_Editeur_Load(Fl_Widget * m , void*) { 484 Fl_Text_Editor * e = find_editor(m); 485 if (e){ 486 if (e->changed()){ 487 int i=fl_ask("%s","Buffer changed. Save?"); 488 if (i) 489 cb_Editeur_Save(m,0); 490 } 491 char * newfile = load_file_chooser("Insert program", ("*."+dynamic_cast<Editeur *>(e->parent())->extension).c_str(), "",0,false); 492 if ( file_not_available(newfile) ) 493 return; 494 e->buffer()->loadfile(newfile); 495 e->label(newfile); 496 if (Editeur * ed=dynamic_cast<Editeur *>(m->parent())){ 497 ed->output->value(remove_path(e->label()).c_str()); 498 ed->output->redraw(); 499 } 500 } 501 } 502 cb_Editeur_Insert(Fl_Menu_ * m,void *)503 static void cb_Editeur_Insert(Fl_Menu_* m , void*) { 504 Fl_Text_Editor * e = find_editor(m); 505 if (e) 506 editeur_load(e); 507 } 508 editeur_insert(Fl_Text_Editor * e,const std::string & newfile,int mode)509 void editeur_insert(Fl_Text_Editor * e,const std::string & newfile,int mode){ 510 ifstream in(newfile.c_str()); 511 char ch; 512 string tmp; 513 const context * contextptr = get_context(e); 514 while (in){ 515 in.get(ch); 516 if (in.eof()) 517 break; 518 tmp += ch; 519 } 520 if (mode<0 || ((mode&0xff)==xcas_mode(contextptr) && (mode>=256)==python_compat(contextptr))){ 521 e->insert(tmp.c_str()); 522 return; 523 } 524 int save_maple_mode=xcas_mode(contextptr); 525 int save_python=python_compat(contextptr); 526 xcas_mode(contextptr)=(mode&0xff); 527 python_compat((mode>=256?1:0),contextptr); 528 gen g; 529 try { 530 g=gen(tmp,contextptr); 531 } 532 catch (std::runtime_error & err){ 533 cerr << err.what() << '\n'; 534 } 535 xcas_mode(contextptr)=save_maple_mode; 536 python_compat(save_python,contextptr); 537 if (g.type==_VECT && g.subtype==_SEQ__VECT && xcas_mode(contextptr) !=3 ){ 538 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 539 for (;it!=itend;++it){ 540 e->insert(it->print(contextptr).c_str()); 541 e->insert(";\n"); 542 } 543 } 544 else 545 e->insert(g.print(contextptr).c_str()); 546 } 547 editeur_translate(Fl_Text_Editor * e,int mode)548 void editeur_translate(Fl_Text_Editor * e,int mode){ 549 if (!Xcas_help_output) 550 return; 551 static string res; 552 gen g; 553 context * contextptr = get_context(e); 554 try { 555 char * ch=e->buffer()->text(); 556 string res(ch); 557 free(ch); 558 g=gen(res,contextptr); 559 } 560 catch (std::runtime_error & err){ 561 cerr << err.what() << '\n'; 562 return; 563 } 564 int save_maple_mode=xcas_mode(contextptr); 565 xcas_mode(contextptr)=mode; 566 res=""; 567 if (g.type==_VECT && g.subtype==_SEQ__VECT && xcas_mode(contextptr) !=3 ){ 568 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 569 for (;it!=itend;++it){ 570 res += it->print_universal(contextptr) ; 571 res += ";\n"; 572 } 573 } 574 else 575 res = g.print_universal(contextptr) + ((xcas_mode(contextptr)==3)?"\n":";\n"); 576 xcas_mode(contextptr)=save_maple_mode; 577 Xcas_help_output->value(res.c_str()); 578 Xcas_help_output->position(0,res.size()); 579 // Xcas_help_output->copy(); 580 Fl::copy(Xcas_help_output->Fl_Output::value(),res.size(),1); 581 Fl::selection(*Xcas_help_output,Xcas_help_output->Fl_Output::value(),res.size()); 582 } 583 editeur_export(Fl_Text_Editor * e,const std::string & newfile,int mode)584 void editeur_export(Fl_Text_Editor * e,const std::string & newfile,int mode){ 585 context * contextptr = get_context(e); 586 gen g; 587 try { 588 char * ch=e->buffer()->text(); 589 string res(ch); 590 free(ch); 591 g=gen(res,contextptr); 592 } 593 catch (std::runtime_error & err){ 594 cerr << err.what() << '\n'; 595 return; 596 } 597 if (is_file_available(newfile.c_str())){ 598 int i=fl_ask("%s",gettext("File exists. Overwrite?")); 599 if (!i) 600 return; 601 } 602 int save_maple_mode=xcas_mode(contextptr); 603 xcas_mode(contextptr)=(mode & 0xff); 604 int save_python=python_compat(contextptr); 605 python_compat((mode>=256?1:0),contextptr); 606 ofstream of(newfile.c_str()); 607 if (g.type==_VECT && g.subtype==_SEQ__VECT && xcas_mode(contextptr) !=3 ){ 608 const_iterateur it=g._VECTptr->begin(),itend=g._VECTptr->end(); 609 for (;it!=itend;++it){ 610 of << it->print_universal(contextptr) ; 611 of << ";\n"; 612 } 613 } 614 else 615 of << g.print_universal(contextptr) << ((xcas_mode(contextptr)==3)?"\n":";\n"); 616 python_compat(save_python,contextptr); 617 xcas_mode(contextptr)=save_maple_mode; 618 } 619 cb_editeur_insert(Fl_Menu_ * m,const string & extension,int mode)620 void cb_editeur_insert(Fl_Menu_ * m,const string & extension,int mode){ 621 Fl_Text_Editor * e = find_editor(m); 622 if (e){ 623 char * newfile = load_file_chooser("Insert program",("*"+extension).c_str(), ("session"+extension).c_str(),0,false); 624 if ( file_not_available(newfile) ) 625 return; 626 editeur_insert(e,newfile,mode); 627 } 628 } 629 cb_Editeur_Insert_File(Fl_Menu_ * m,void *)630 static void cb_Editeur_Insert_File(Fl_Menu_* m , void*) { 631 cb_editeur_insert(m,"",-1); 632 } 633 cb_Editeur_Insert_Xcas(Fl_Menu_ * m,void *)634 static void cb_Editeur_Insert_Xcas(Fl_Menu_* m , void*) { 635 cb_editeur_insert(m,".cxx",0); 636 } 637 cb_Editeur_Insert_Python(Fl_Menu_ * m,void *)638 static void cb_Editeur_Insert_Python(Fl_Menu_* m , void*) { 639 cb_editeur_insert(m,".py",256); 640 } 641 cb_Editeur_Insert_Maple(Fl_Menu_ * m,void *)642 static void cb_Editeur_Insert_Maple(Fl_Menu_* m , void*) { 643 cb_editeur_insert(m,".map",1); 644 } 645 cb_Editeur_Insert_Mupad(Fl_Menu_ * m,void *)646 static void cb_Editeur_Insert_Mupad(Fl_Menu_* m , void*) { 647 cb_editeur_insert(m,".mu",2); 648 } 649 cb_Editeur_Insert_Ti(Fl_Menu_ * m,void *)650 static void cb_Editeur_Insert_Ti(Fl_Menu_* m , void*) { 651 cb_editeur_insert(m,".ti",3); 652 } 653 cb_Editeur_Export_Maple(Fl_Menu_ * m,void *)654 static void cb_Editeur_Export_Maple(Fl_Menu_* m , void*) { 655 Fl_Text_Editor * e = find_editor(m); 656 if (e){ 657 char * newfile = file_chooser("Export program", "*.map", "session.map"); 658 editeur_export(e,newfile,1); 659 } 660 } 661 cb_Editeur_Export_Xcas(Fl_Menu_ * m,void *)662 static void cb_Editeur_Export_Xcas(Fl_Menu_* m , void*) { 663 Fl_Text_Editor * e = find_editor(m); 664 if (e){ 665 char * newfile = file_chooser("Export program", "*.cxx", "session.cxx"); 666 editeur_export(e,newfile,0); 667 } 668 } 669 cb_Editeur_Export_Python(Fl_Menu_ * m,void *)670 static void cb_Editeur_Export_Python(Fl_Menu_* m , void*) { 671 Fl_Text_Editor * e = find_editor(m); 672 if (e){ 673 char * newfile = file_chooser("Export program", "*.py", "session.py"); 674 editeur_export(e,newfile,256); 675 } 676 } 677 cb_Editeur_Export_Mupad(Fl_Menu_ * m,void *)678 static void cb_Editeur_Export_Mupad(Fl_Menu_* m , void*) { 679 Fl_Text_Editor * e = find_editor(m); 680 if (e){ 681 char * newfile = file_chooser("Export program", "*.mu", "session.mu"); 682 editeur_export(e,newfile,2); 683 } 684 } 685 cb_Editeur_Export_Ti(Fl_Menu_ * m,void *)686 static void cb_Editeur_Export_Ti(Fl_Menu_* m , void*) { 687 Fl_Text_Editor * e = find_editor(m); 688 if (e){ 689 char * newfile = file_chooser("Export program", "*.ti", "session.ti"); 690 editeur_export(e,newfile,3); 691 } 692 } 693 cb_Editeur_Translate_Maple(Fl_Menu_ * m,void *)694 static void cb_Editeur_Translate_Maple(Fl_Menu_* m , void*) { 695 Fl_Text_Editor * e = find_editor(m); 696 if (e){ 697 editeur_translate(e,1); 698 } 699 } 700 cb_Editeur_Translate_Python(Fl_Menu_ * m,void *)701 static void cb_Editeur_Translate_Python(Fl_Menu_* m , void*) { 702 Fl_Text_Editor * e = find_editor(m); 703 if (e){ 704 editeur_translate(e,256); // not working 705 } 706 } 707 cb_Editeur_Translate_Xcas(Fl_Menu_ * m,void *)708 static void cb_Editeur_Translate_Xcas(Fl_Menu_* m , void*) { 709 Fl_Text_Editor * e = find_editor(m); 710 if (e){ 711 editeur_translate(e,0); 712 } 713 } 714 cb_Editeur_Translate_Mupad(Fl_Menu_ * m,void *)715 static void cb_Editeur_Translate_Mupad(Fl_Menu_* m , void*) { 716 Fl_Text_Editor * e = find_editor(m); 717 if (e){ 718 editeur_translate(e,2); 719 } 720 } 721 cb_Editeur_Translate_Ti(Fl_Menu_ * m,void *)722 static void cb_Editeur_Translate_Ti(Fl_Menu_* m , void*) { 723 Fl_Text_Editor * e = find_editor(m); 724 if (e){ 725 editeur_translate(e,3); 726 } 727 } 728 cb_Editeur_Save_as(Fl_Widget * m,void *)729 static void cb_Editeur_Save_as(Fl_Widget * m , void*) { 730 static int program_counter=0; 731 Fl_Text_Editor * e = find_editor(m); 732 if (e){ 733 static string tmp; 734 string extension; 735 if (Editeur * ed = dynamic_cast<Editeur *>(m->parent())) 736 extension=ed->extension; 737 for (;;){ 738 char * newfile ; 739 if (extension.empty()) 740 newfile = file_chooser("Store program", "*", ("session"+print_INT_(program_counter)).c_str()); 741 else 742 newfile = file_chooser("Store program", ("*."+extension).c_str(), ("session"+print_INT_(program_counter)+"."+extension).c_str()); 743 if ( (!newfile) || (!*newfile)) 744 return; 745 tmp=newfile; 746 if (!extension.empty()) 747 tmp=remove_extension(tmp.substr(0,1000).c_str())+"."+extension; 748 if (access(tmp.c_str(),R_OK)) 749 break; 750 int i=fl_ask("%s",(tmp+gettext(": file exists. Overwrite?")).c_str()); 751 if (i==1) 752 break; 753 } 754 e->label(tmp.c_str()); 755 if (Editeur * ed=dynamic_cast<Editeur *>(m->parent())){ 756 ed->output->value(remove_path(e->label()).c_str()); 757 ed->output->redraw(); 758 } 759 cb_Editeur_Save(m,0); 760 } 761 } 762 cb_Editeur_Save(Fl_Widget * m,void *)763 static void cb_Editeur_Save(Fl_Widget * m , void*) { 764 Fl_Text_Editor * e = find_editor(m); 765 if (e // && e->changed() 766 ){ 767 if (e->label() && e->label()[0]){ 768 e->buffer()->savefile(e->label()); 769 e->clear_changed(); 770 } 771 else 772 cb_Editeur_Save_as(m,0); 773 } 774 } 775 776 Fl_Widget * Save_Focus_Button::widget=0; handle(int event)777 int Save_Focus_Button::handle(int event){ 778 if (event==FL_FOCUS) 779 return 0; 780 if (event==FL_MOVE){ // search if focus is one of the parent of the button 781 Fl_Widget * w1 =Fl::focus(); 782 Fl_Widget * w2 = this; 783 while (w2){ 784 if (w1==w2) 785 break; 786 w2=w2->parent(); 787 } 788 if (w1 && !w2 && widget!=w1){ 789 // it's not a parent, save it 790 widget=w1; 791 } 792 } 793 return Fl_Button::handle(event); 794 } 795 handle(int event)796 int No_Focus_Button::handle(int event){ 797 switch (event) { 798 case FL_ENTER: 799 case FL_LEAVE: 800 return 1; 801 case FL_RELEASE: 802 do_callback(); 803 case FL_PUSH: case FL_DRAG: 804 return 1; 805 case FL_SHORTCUT: 806 if (!(shortcut() ? 807 Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; 808 if (type() == FL_RADIO_BUTTON && !value()) { 809 setonly(); 810 if (when() & FL_WHEN_CHANGED) do_callback(); 811 } else if (type() == FL_TOGGLE_BUTTON) { 812 value(!value()); 813 if (when() & FL_WHEN_CHANGED) do_callback(); 814 } 815 if (when() & FL_WHEN_RELEASE) do_callback(); else set_changed(); 816 return 1; 817 default: 818 return 0; 819 } 820 } 821 in_Xcas_input_1arg(Fl_Widget * widget,const std::string & chaine,bool eval)822 void in_Xcas_input_1arg(Fl_Widget * widget,const std::string & chaine ,bool eval){ 823 if (!widget) 824 return; 825 Fl::focus(widget); 826 const context * contextptr = get_context(widget); 827 if ( Equation * eqwptr=dynamic_cast<Equation *> (widget) ){ 828 vecteur position; 829 gen * act=Equation_selected(eqwptr->data,eqwptr->attr,eqwptr->w(),position,1,contextptr); 830 if (act){ 831 eqwptr->handle_text(chaine,act); 832 return; 833 } 834 gen f("'"+string(chaine)+"'",contextptr); 835 if (eval || f.type!=_FUNC) 836 eqwptr->eval_function(f); 837 else { 838 // make_new_help(chaine); 839 gen g=eqwptr->get_selection(); 840 if (g.type!=_VECT){ 841 if (f==at_limit) 842 g=gen(makevecteur(g,vx_var,0),_SEQ__VECT); 843 if (f==at_integrate || f==at_derive) 844 g=gen(makevecteur(g,vx_var),_SEQ__VECT); 845 if (f==at_sum) 846 g=gen(makevecteur(g,k__IDNT_e,1,n__IDNT_e),_SEQ__VECT); 847 } 848 eqwptr->replace_selection(symbolic(*f._FUNCptr,g)); 849 } 850 return; 851 } 852 bool par= chaine.empty() || chaine[0]!='_'; 853 string s(chaine); 854 if (Multiline_Input_tab * the_input =dynamic_cast<Multiline_Input_tab *>(widget)){ 855 if (par) 856 s = chaine+"("; 857 the_input->insert_replace(s,false); 858 return; 859 } 860 if (Fl_Input * the_input =dynamic_cast<Fl_Input *>(widget)){ 861 string t(the_input->value()); 862 size_t sel1=the_input->position(),sel2=the_input->mark(); 863 if (sel1>sel2){ 864 size_t tmp=sel1; 865 sel1=sel2; 866 sel2=tmp; 867 } 868 string t_before=t.substr(0,sel1); 869 string t_selected=t.substr(sel1,sel2-sel1); 870 string t_after=t.substr(sel2,t.size()-sel2); 871 if (par) 872 s += '('; 873 s = t_before+s; 874 s += t_selected; 875 s += t_after; 876 the_input->value( s.c_str()); 877 size_t pos1=t_before.size(); 878 size_t pos2=s.size()-t_after.size(); 879 if (sel1==sel2) 880 the_input->position(pos2-1,pos2-1); 881 else 882 the_input->position(pos1,pos2); 883 return; 884 } 885 if (Editeur * ed=dynamic_cast<Editeur *>(widget)){ 886 widget=ed->editor; 887 } 888 if (Xcas_Text_Editor * ed=dynamic_cast<Xcas_Text_Editor *>(widget)){ 889 int i=ed->insert_position(); 890 ed->buffer()->insert(i,(chaine+'(').c_str()); 891 ed->insert_position(i+chaine.size()+1); 892 ed->set_tooltip(); 893 if (History_Pack * hp=get_history_pack(ed)) 894 hp->modified(false); 895 } 896 } 897 Xcas_input_1arg(Save_Focus_Button * m,void *)898 void Xcas_input_1arg(Save_Focus_Button * m , void*) { 899 in_Xcas_input_1arg(m->widget,m->label()); 900 } 901 Xcas_input_arg(Save_Focus_Button * m,const std::string & chaine)902 void Xcas_input_arg(Save_Focus_Button * m , const std::string & chaine) { 903 in_Xcas_input_1arg(m->widget,chaine); 904 } 905 Xcas_input_1arg(No_Focus_Button * m,void *)906 void Xcas_input_1arg(No_Focus_Button * m , void*) { 907 in_Xcas_input_1arg(Fl::focus(),m->label()); 908 } 909 Xcas_input_arg(No_Focus_Button * m,const std::string & chaine)910 void Xcas_input_arg(No_Focus_Button * m , const std::string & chaine) { 911 in_Xcas_input_1arg(Fl::focus(),chaine); 912 } 913 in_Xcas_input_char(Fl_Widget * widget,const std::string & chaine,char keysym)914 void in_Xcas_input_char(Fl_Widget * widget,const std::string & chaine,char keysym){ 915 if (alt_ctrl_cb && alt_ctrl) 916 alt_ctrl_cb(alt_ctrl); 917 if (!widget) 918 return; 919 static string s; 920 if (chaine.empty()) 921 s=" "; 922 else 923 s=chaine; 924 if (alt_ctrl & 2) 925 s[0]=s[0] & 0x1f; 926 if (alt_ctrl & 4) 927 s[0]=s[0] | 0x80; 928 Fl::e_text= (char *) s.c_str(); 929 Fl::e_length=s.size(); 930 if (alt_ctrl & 2) 931 Fl::e_keysym=keysym & 0x1f; 932 else { 933 if (alt_ctrl & 4) 934 Fl::e_keysym=keysym | 0x80; 935 Fl::e_keysym=keysym; 936 } 937 alt_ctrl=0; 938 fl_handle(widget); 939 } 940 Xcas_input_char(Save_Focus_Button * m,void *)941 void Xcas_input_char(Save_Focus_Button * m , void*) { 942 in_Xcas_input_char(m->widget,m->label(),m->label()[0]); 943 } 944 Xcas_input_label(No_Focus_Button * m,void *)945 void Xcas_input_label(No_Focus_Button * m , void*) { 946 in_Xcas_input_char(Fl::focus(),m->label(),m->label()[0]); 947 } 948 Xcas_input_char(No_Focus_Button * m,void *)949 void Xcas_input_char(No_Focus_Button * m , void*) { 950 std::string s(m->label()); 951 if (m->labelfont()==FL_SYMBOL && s.size()==1){ 952 switch (s[0]){ 953 case 'a': 954 s="alpha"; 955 break; 956 case 'b': 957 s="beta"; 958 break; 959 case 'c': 960 s="chi"; 961 break; 962 case 'd': 963 s="delta"; 964 break; 965 case 'e': 966 s="epsilon"; 967 break; 968 case 'f': 969 s="phi"; 970 break; 971 case 'g': 972 s="gamma"; 973 break; 974 case 'h': 975 s="eta"; 976 break; 977 case 'i': 978 s="iota"; 979 break; 980 case 'j': 981 s="varphi"; 982 break; 983 case 'k': 984 s="kappa"; 985 break; 986 case 'l': 987 s="lambda"; 988 break; 989 case 'm': 990 s="mu"; 991 break; 992 case 'n': 993 s="nu"; 994 break; 995 case 'p': 996 s="pi"; 997 break; 998 case 'q': 999 s="theta"; 1000 break; 1001 case 'r': 1002 s="rho"; 1003 break; 1004 case 's': 1005 s="sigma"; 1006 break; 1007 case 't': 1008 s="tau"; 1009 break; 1010 case 'u': 1011 s="upsilon"; 1012 break; 1013 case 'v': 1014 s="omega"; 1015 break; 1016 case 'x': 1017 s="xi"; 1018 break; 1019 case 'y': 1020 s="psi"; 1021 break; 1022 case 'z': 1023 s="zeta"; 1024 break; 1025 case 'C': 1026 s="Chi"; 1027 break; 1028 case 'D': 1029 s="Delta"; 1030 break; 1031 case 'F': 1032 s="Phi"; 1033 break; 1034 case 'G': 1035 s="Gamma"; 1036 break; 1037 case 'L': 1038 s="Lambda"; 1039 break; 1040 case 'P': 1041 s="Pi"; 1042 break; 1043 case 'Q': 1044 s="Theta"; 1045 break; 1046 case 'S': 1047 s="Sigma"; 1048 break; 1049 case 'W': 1050 s="Omega"; 1051 break; 1052 case 'X': 1053 s="Xi"; 1054 break; 1055 case 'Y': 1056 s="Psi"; 1057 break; 1058 } 1059 } 1060 in_Xcas_input_char(Fl::focus(),s,m->label()[0]); 1061 } 1062 Xcas_binary_op(Save_Focus_Button * m,void *)1063 void Xcas_binary_op(Save_Focus_Button * m , void*) { 1064 Xcas_input_char(m,0); 1065 } 1066 Xcas_binary_op(No_Focus_Button * m,void *)1067 void Xcas_binary_op(No_Focus_Button * m , void*) { 1068 Xcas_input_char(m,0); 1069 } 1070 Xcas_input_0arg(Save_Focus_Button * m,const std::string & chaine)1071 void Xcas_input_0arg(Save_Focus_Button * m , const std::string & chaine) { 1072 Fl_Widget * widget = m->widget; 1073 if (!widget) 1074 return; 1075 string s; 1076 if (chaine.empty()) 1077 s=" "; 1078 else 1079 s=chaine; 1080 Fl::e_text= (char *) s.c_str(); 1081 Fl::e_length=s.size(); 1082 Fl::e_keysym=s[0]; 1083 fl_handle(widget); 1084 } 1085 Xcas_input_0arg(No_Focus_Button *,const std::string & chaine)1086 void Xcas_input_0arg(No_Focus_Button * , const std::string & chaine) { 1087 static string s; 1088 if (chaine.empty()) 1089 s=" "; 1090 else 1091 s=chaine; 1092 Fl_Widget * wid = Fl::focus(); 1093 const context * contextptr = get_context(wid); 1094 if (Equation * eq=dynamic_cast<Equation * >(wid)){ 1095 vecteur position; 1096 gen * act=Equation_selected(eq->data,eq->attr,eq->w(),position,1,contextptr); 1097 if (act){ 1098 eq->handle_text(s,act); 1099 return; 1100 } 1101 if (s.size()>1){ 1102 eq->parse_desactivate(); 1103 gen f(s,contextptr); 1104 eq->replace_selection(f); 1105 return; 1106 } 1107 } 1108 else { 1109 Fl::e_text= (char *) s.c_str(); 1110 Fl::e_length=s.size(); 1111 Fl::e_keysym=s[0]; 1112 fl_handle(wid); 1113 } 1114 } 1115 Xcas_input_0arg(const std::string & chaine)1116 void Xcas_input_0arg(const std::string & chaine) { 1117 Xcas_input_0arg((No_Focus_Button *)0,chaine); 1118 } 1119 cb_Editeur_Exec(Save_Focus_Button * m,void *)1120 static void cb_Editeur_Exec(Save_Focus_Button * m , void*) { 1121 Fl_Widget * widget = m->widget; 1122 Fl_Text_Editor * Program_editor = find_editor(m); 1123 if (Program_editor){ 1124 const context * contextptr = get_context(Program_editor); 1125 if (!Program_editor || !widget) 1126 return ; 1127 if ( !dynamic_cast<Fl_Input *>(widget)){ 1128 m->window()->show(); 1129 Fl::focus(Program_editor); 1130 return ; 1131 } 1132 Editeur * ed = dynamic_cast<Editeur *>(Program_editor->parent()); 1133 int r= Program_editor->insert_position(); 1134 char * ch=Program_editor->buffer()->line_text(r); 1135 string s=ch; 1136 free(ch); 1137 // Scan for a line ending with // 1138 int ss=s.size(); 1139 for (int i=ss-2;i>=0;--i){ 1140 if (s[i]=='/' && s[i+1]=='/') 1141 s=s.substr(0,i); 1142 } 1143 ss=s.size(); 1144 bool comment=s.empty(),nextline=true; 1145 for (int i=0;i<ss;++i){ 1146 if (s[i]!=' ') 1147 break; 1148 if (i==ss-1) 1149 comment=true; 1150 } 1151 if (!comment){ 1152 gen g; 1153 bool close=lexer_close_parenthesis(contextptr); 1154 lexer_close_parenthesis(false,contextptr); 1155 try { 1156 if (calc_mode(contextptr)==38) 1157 calc_mode(contextptr)=-38; 1158 g=gen(s,contextptr); 1159 } 1160 catch (std::runtime_error & e){ 1161 cerr << e.what() << '\n'; 1162 } 1163 lexer_close_parenthesis(close,contextptr); 1164 if (giac::first_error_line(contextptr)){ 1165 if (ed && ed->log){ 1166 ed->log->value((gettext("Parse error line ")+print_INT_(giac::first_error_line(contextptr))+ gettext(" column ")+print_INT_(giac::lexer_column_number(contextptr))+gettext(" at ") +giac::error_token_name(contextptr)).c_str()); 1167 ed->log->redraw(); 1168 Fl_Group * gr=ed->log->parent(); 1169 if (gr->children()>2){ 1170 int ah = gr->child(2)->h(); 1171 Fl_Widget * wid=gr->child(2); 1172 gr->remove(wid); 1173 delete wid; 1174 gr->Fl_Widget::resize(gr->x(),gr->y(),gr->w(),gr->h()-ah); 1175 History_Pack * hp=get_history_pack(gr); 1176 if (hp) 1177 hp->redraw(); 1178 } 1179 } 1180 nextline=false; 1181 } 1182 } 1183 if (nextline) { 1184 int next=Program_editor->buffer()->line_end(r)+1; 1185 int nextend=Program_editor->buffer()->line_end(next); 1186 Program_editor->insert_position(next); 1187 Program_editor->show_insert_position(); 1188 Program_editor->buffer()->select(next,nextend); 1189 Program_editor->redraw(); 1190 if (!comment){ 1191 Fl::e_text= (char *) s.c_str(); 1192 Fl::e_length=s.size(); 1193 widget->window()->show(); 1194 fl_handle(widget); 1195 widget->do_callback(); 1196 widget=Fl::focus(); 1197 } 1198 m->window()->show(); 1199 Fl::focus(Program_editor); 1200 Fl::flush(); 1201 usleep(500000); 1202 widget->window()->show(); 1203 Fl::focus(widget); 1204 } 1205 } 1206 } 1207 cb_Editeur_Preview(Fl_Menu_ * m,void *)1208 static void cb_Editeur_Preview(Fl_Menu_* m , void*) { 1209 Fl_Text_Editor * e = find_editor(m); 1210 if (e) 1211 widget_ps_print(e,e->label(),false); 1212 } 1213 cb_Editeur_Print(Fl_Menu_ * m,void *)1214 static void cb_Editeur_Print(Fl_Menu_* m , void*) { 1215 Fl_Text_Editor * e = find_editor(m); 1216 if (e) 1217 widget_print(e); 1218 } 1219 eval()1220 bool Editeur::eval(){ 1221 log = find_log_output(parent()); 1222 const context * contextptr = get_context(this); 1223 static string logs; 1224 if (log){ 1225 logs=gettext("Syntax compatibility mode: ")+print_program_syntax(xcas_mode(contextptr))+"\n"; 1226 } 1227 gen g; 1228 bool close=lexer_close_parenthesis(contextptr); 1229 lexer_close_parenthesis(false,contextptr); 1230 try { 1231 char * ch=editor->buffer()->text(); 1232 string res(ch); 1233 free(ch); 1234 if (calc_mode(contextptr)==38) 1235 calc_mode(contextptr)=-38; 1236 g=gen(res,contextptr); 1237 } 1238 catch (std::runtime_error & er){ 1239 cerr << er.what() << '\n'; 1240 } 1241 lexer_close_parenthesis(close,contextptr); 1242 if (giac::first_error_line(contextptr)){ 1243 int pos1=editor->buffer()->skip_lines(0,giac::first_error_line(contextptr)-1); 1244 // int pos2=editor->buffer()->skip_lines(pos1,1); 1245 int pos2=pos1+giac::lexer_column_number(contextptr)-1; 1246 pos1=giacmax(pos2-giac::error_token_name(contextptr).size(),0); 1247 editor->buffer()->select(pos1,pos2); 1248 editor->show_insert_position(); 1249 editor->redraw(); 1250 if (log){ 1251 logs+=gettext("Parse error line ")+print_INT_(giac::first_error_line(contextptr))+ gettext( " column ")+print_INT_(giac::lexer_column_number(contextptr))+gettext(" at ") +giac::error_token_name(contextptr); 1252 log->value(logs.c_str()); 1253 Fl_Group * gr=log->parent(); 1254 if (gr->children()>2){ 1255 int ah = gr->child(2)->h(); 1256 Fl_Widget * wid=gr->child(2); 1257 gr->remove(wid); 1258 delete wid; 1259 gr->Fl_Widget::resize(gr->x(),gr->y(),gr->w(),gr->h()-ah); 1260 } 1261 // if (Parse_error_output) 1262 // Parse_error_output->value(logs.c_str()); 1263 output_resize_parent(log); 1264 } 1265 return false; 1266 } 1267 else { 1268 if (log){ 1269 string locals=check_local_assign(g,contextptr); 1270 if (locals.empty()) 1271 logs = gettext("Success!"); 1272 else { 1273 logs+=string(gettext("Success but ... "))+locals; 1274 } 1275 log->value(logs.c_str()); 1276 // if (Parse_error_output) 1277 // Parse_error_output->value(logs.c_str()); 1278 output_resize_parent(log); 1279 } 1280 // NOTE: do_callback clears the logs 1281 // protecteval(g,2,contextptr); 1282 do_callback(); 1283 return true; 1284 /* Exec g 1285 context * contextptr = 0; 1286 if (History_Pack * p =get_history_pack(this)){ 1287 contextptr = p->contextptr; 1288 // focus to next 1289 p->_sel_begin=-1; 1290 int pos=p->set_sel_begin(this)+1; 1291 p->focus(pos); 1292 } 1293 if (giac::is_context_busy(contextptr) && log) 1294 log->value((log->value()+string("\nCan not evaluate, system busy")).c_str()); 1295 else 1296 thread_eval(g,eval_level(contextptr),contextptr); 1297 */ 1298 } 1299 } 1300 cb_Editeur_Test(Fl_Widget * m,void *)1301 static void cb_Editeur_Test(Fl_Widget* m , void*) { 1302 Fl_Text_Editor * e = find_editor(m); 1303 if (e){ 1304 Fl::focus(e); 1305 Editeur * ed = dynamic_cast<Editeur *>(m->parent()); 1306 if (ed){ 1307 ed->eval(); 1308 } 1309 } 1310 } 1311 cb_Editeur_Gotoline(Fl_Widget * m,void *)1312 static void cb_Editeur_Gotoline(Fl_Widget* m , void*) { 1313 Fl_Text_Editor * e = find_editor(m); 1314 if (e){ 1315 Fl::focus(e); 1316 Fl_Value_Input * in = dynamic_cast<Fl_Value_Input *>(m); 1317 if (in){ 1318 double l=in->value(); 1319 if (l<1) 1320 l=1; 1321 int newpos=e->buffer()->skip_lines(0,int(l)-1); 1322 e->insert_position(newpos); 1323 } 1324 } 1325 } 1326 cb_Editeur_Indent_line(Fl_Widget * m,void *)1327 static void cb_Editeur_Indent_line(Fl_Widget* m , void*) { 1328 Fl_Text_Editor * e = find_editor(m); 1329 if (e){ 1330 Fl::focus(e); 1331 Editeur * ed = dynamic_cast<Editeur *>(m->parent()); 1332 if (ed){ 1333 ed->editor->indent(e->insert_position()); 1334 } 1335 } 1336 } 1337 cb_Editeur_Indent_all(Fl_Widget * m,void *)1338 static void cb_Editeur_Indent_all(Fl_Widget* m , void*) { 1339 Fl_Text_Editor * e = find_editor(m); 1340 if (e){ 1341 Fl::focus(e); 1342 Editeur * ed = dynamic_cast<Editeur *>(m->parent()); 1343 if (ed){ 1344 ed->editor->indent(); 1345 } 1346 } 1347 } 1348 cb_Editeur_Next(Fl_Widget * m,void *)1349 static void cb_Editeur_Next(Fl_Widget * m , void*) { 1350 Editeur * e = dynamic_cast<Editeur *>(m->parent()); 1351 if (e && e->editor){ 1352 Fl_Text_Editor * ed=e->editor; 1353 int pos = ed->insert_position(); 1354 int found = ed->buffer()->search_forward(pos, e->search.c_str(), &pos); 1355 if (found) { 1356 // Found a match; select and update the position... 1357 ed->buffer()->select(pos, pos+e->search.size()); 1358 ed->insert_position(pos+e->search.size()); 1359 ed->show_insert_position(); 1360 ed->redraw(); 1361 } 1362 else { 1363 fl_alert("%s","No more occurrences of '%s' found!", e->search.c_str()); 1364 ed->insert_position(0); 1365 } 1366 Fl::focus(ed); 1367 } 1368 } 1369 cb_Editeur_Extension(Fl_Menu_ * m,void *)1370 static void cb_Editeur_Extension(Fl_Menu_* m , void*) { 1371 Editeur * e=dynamic_cast<Editeur *>(m->parent()); 1372 if (e){ 1373 const char * res=fl_input("New extension",e->extension.c_str()); 1374 if (res) 1375 e->extension=res; 1376 } 1377 } 1378 cb_Editeur_Extend(Fl_Widget * m,void *)1379 void cb_Editeur_Extend(Fl_Widget * m , void*) { 1380 Editeur * e=dynamic_cast<Editeur *>(m->parent()); 1381 if (e->h()<=e->window()->h()-100){ 1382 increase_size(e->editor,100); 1383 e->editor->redraw(); 1384 } 1385 } 1386 cb_Editeur_Shrink(Fl_Widget * m,void *)1387 void cb_Editeur_Shrink(Fl_Widget * m , void*) { 1388 Editeur * e=dynamic_cast<Editeur *>(m->parent()); 1389 if (e->h()>200){ 1390 increase_size(e->editor,-100); 1391 e->editor->redraw(); 1392 } 1393 } 1394 logo_eval_callback(const giac::gen & evaled_g,void * param)1395 void logo_eval_callback(const giac::gen & evaled_g,void * param){ 1396 Fl_Widget * wid=static_cast<Fl_Widget *>(param); 1397 if (!wid || !wid->parent()) 1398 return; 1399 wid->parent()->redraw(); 1400 } 1401 cb_Editeur_Exec_All(Fl_Widget * m,void *)1402 void cb_Editeur_Exec_All(Fl_Widget * m , void*) { 1403 Editeur * e=dynamic_cast<Editeur *>(m->parent()); 1404 context * contextptr = get_context(e); 1405 if (e){ 1406 if (Logo * l=dynamic_cast<Logo *>(e->parent())){ 1407 char * ch = e->editor->buffer()->text(); 1408 string s=ch; 1409 free(ch); 1410 gen g; 1411 bool close=lexer_close_parenthesis(contextptr); 1412 lexer_close_parenthesis(false,contextptr); 1413 try { 1414 if (calc_mode(contextptr)==38) 1415 calc_mode(contextptr)=-38; 1416 g=gen(s,contextptr); 1417 } 1418 catch (std::runtime_error & e){ cerr << e.what() << '\n'; } 1419 lexer_close_parenthesis(close,contextptr); 1420 if (giac::first_error_line(contextptr)){ 1421 int pos1=e->editor->buffer()->skip_lines(0,giac::first_error_line(contextptr)-1); 1422 // int pos2=e->editor->buffer()->skip_lines(pos1,1); 1423 int pos2=pos1+giac::lexer_column_number(contextptr)-1; 1424 pos1=giacmax(pos2-giac::error_token_name(contextptr).size(),0); 1425 e->editor->buffer()->select(pos1,pos2); 1426 e->editor->show_insert_position(); 1427 e->editor->redraw(); 1428 fl_alert("%s",(gettext("Parse error line ")+print_INT_(giac::first_error_line(contextptr))+ gettext(" column ")+print_INT_(giac::lexer_column_number(contextptr)) + gettext(" at ") +giac::error_token_name(contextptr)).c_str()); 1429 } 1430 else { 1431 if (!is_context_busy(contextptr)){ 1432 #if 1 1433 make_thread(g,eval_level(contextptr),logo_eval_callback,e,contextptr); 1434 // protecteval(g,eval_level(contextptr),contextptr); 1435 #else // crashes sometimes, perhaps something non reentrant 1436 thread_eval(g,eval_level(contextptr),contextptr); 1437 #endif 1438 } 1439 l->t->redraw(); 1440 e->editor->insert_position(s.size()); 1441 } 1442 return; 1443 } 1444 // Not a logo, try to run it inside focus 1445 fl_message("%s",gettext("Should be used inside a Logo level")); 1446 return; 1447 Fl_Widget * wid=Fl::focus(); 1448 History_Pack * hp=get_history_pack(wid); 1449 if (hp){ 1450 hp->set_sel_begin(wid); 1451 int n=hp->_sel_begin; 1452 int r=0; 1453 int taille=e->editor->buffer()->length(); 1454 for (;r<taille;++n){ 1455 char * ch=e->editor->buffer()->line_text(r); 1456 r=e->editor->buffer()->line_end(r)+1; 1457 Fl_Multiline_Input * widget=dynamic_cast<Fl_Multiline_Input *>(new_question_multiline_input(hp->w()-hp->_printlevel_w,hp->labelsize()+4)); 1458 if (!widget) break; 1459 widget->value(ch); 1460 widget->set_changed(); 1461 free(ch); 1462 hp->add_entry(n,widget); 1463 widget->do_callback(); 1464 } 1465 } 1466 } 1467 } 1468 cb_Editeur_Search(Fl_Widget * m,void *)1469 static void cb_Editeur_Search(Fl_Widget* m , void*) { 1470 static Fl_Window * w = 0; 1471 static Fl_Input * i1=0, * i2=0; // i1=search, i2=replace 1472 static Fl_Button * button0 = 0 ; // cancel 1473 static Fl_Button * button1 =0; // next 1474 static Fl_Button * button2 =0; // replace + next 1475 static Fl_Button * button3 =0; // replace all 1476 Fl_Text_Editor * ed = find_editor(m); 1477 if (!ed) return; 1478 Editeur * e =dynamic_cast<Editeur *>(m->parent()); 1479 if (ed && e){ 1480 int dx=400,dy=100; 1481 if (!w){ 1482 Fl_Group::current(0); 1483 w=new Fl_Window(dx,dy); 1484 i1=new Fl_Input(dx/6,2,dx/3-2,dy/3-4,gettext("Search")); 1485 i1->tooltip(gettext("Word to search")); 1486 i1->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 1487 i2=new Fl_Input((2*dx)/3,2,dx/3-2,dy/3-4,"Replace"); 1488 i2->tooltip(gettext("Replace by")); 1489 i2->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 1490 button0 = new Fl_Button(2,2+(2*dy/3),dx/2-4,dy/3-4); 1491 button0->shortcut(0xff0d); 1492 button0->label(gettext("Cancel")); 1493 button1 = new Fl_Button(dx/2+2,2+(2*dy)/3,dx/2-4,dy/3-4); 1494 button1->shortcut(0xff1b); 1495 button1->label(gettext("Next")); 1496 button1->when(FL_WHEN_RELEASE); 1497 button2 = new Fl_Button(2,2+(dy)/3,dx/2-4,dy/3-4); 1498 button2->shortcut(0xff1b); 1499 button2->label(gettext("Replace")); 1500 button2->when(FL_WHEN_RELEASE); 1501 button3 = new Fl_Button(dx/2+2,2+(dy)/3,dx/2-4,dy/3-4); 1502 button3->shortcut(0xff1b); 1503 button3->label(gettext("Replace all")); 1504 button3->when(FL_WHEN_RELEASE); 1505 w->end(); 1506 w->resizable(w); 1507 } 1508 i1->value(e->search.c_str()); 1509 History_Pack * hp=get_history_pack(ed); 1510 w->label("Search/Replace"); 1511 w->set_modal(); 1512 w->show(); 1513 w->hotspot(w); 1514 Fl::focus(i1); 1515 autosave_disabled=true; 1516 for (;;) { 1517 Fl_Widget *o = Fl::readqueue(); 1518 if (!o) Fl::wait(); 1519 else { 1520 if (o == button0) break; 1521 if (o == w) break; 1522 if (o==button3){ // Replace all 1523 e->search=i1->value(); 1524 const char *find = e->search.c_str(); 1525 const char *replace = i2->value(); 1526 int i=1; 1527 if (!replace[0]) 1528 i=fl_ask("%s","Really replace by nothing?"); 1529 if (i && find[0] != 0){ 1530 ed->previous_word(); 1531 int pos = ed->insert_position(); 1532 while (ed->buffer()->search_forward(pos, find, &pos)) { 1533 ed->buffer()->select(pos, pos+strlen(find)); 1534 ed->buffer()->remove_selection(); 1535 ed->buffer()->insert(pos, replace); 1536 ed->redraw(); 1537 pos += strlen(replace); 1538 ed->insert_position(pos); 1539 } 1540 if (hp) 1541 hp->modified(false); 1542 break; 1543 } 1544 } // end button3 1545 if (o==button2 || o==i2){ // Replace+next 1546 if (ed->buffer()->selection_text()==e->search){ 1547 e->search=i1->value(); 1548 const char *find = e->search.c_str(); 1549 const char *replace = i2->value(); 1550 if (find[0] != 0){ 1551 if (ed->insert_position()>0) 1552 ed->previous_word(); 1553 int pos = ed->insert_position(); 1554 if (ed->buffer()->search_forward(pos, find, &pos)) { 1555 ed->buffer()->select(pos, pos+strlen(find)); 1556 ed->buffer()->remove_selection(); 1557 ed->buffer()->insert(pos, replace); 1558 if (hp) 1559 hp->modified(false); 1560 ed->redraw(); 1561 pos += strlen(replace); 1562 ed->insert_position(pos); 1563 } 1564 } 1565 } // end I1!=I2 1566 } // end button2 1567 if (o==i1 || o==i2 || o==button1 || o==button2){ // Find next 1568 e->search=i1->value(); 1569 if (e->search.empty()) 1570 break; 1571 int pos = ed->insert_position(); 1572 int found = ed->buffer()->search_forward(pos, e->search.c_str(), &pos); 1573 if (found) { 1574 // Found a match; select and update the position... 1575 ed->buffer()->select(pos, pos+e->search.size()); 1576 ed->insert_position(pos+e->search.size()); 1577 ed->show_insert_position(); 1578 ed->redraw(); 1579 } 1580 else { 1581 fl_alert("%s","No occurrences of '%s' found!", e->search.c_str()); 1582 ed->insert_position(0); 1583 ed->show_insert_position(); 1584 } 1585 Fl::focus(ed); 1586 } // end button1 1587 if (o==i1){ 1588 ed->window()->show(); 1589 Fl::focus(ed); 1590 break; 1591 } 1592 } // end else of if Fl::wait() 1593 } // end for (;;) 1594 autosave_disabled=false; 1595 w->hide(); 1596 Fl::focus(ed); 1597 } 1598 } 1599 1600 cb_dialog_test(Fl_Text_Editor * ed)1601 static void cb_dialog_test(Fl_Text_Editor * ed){ 1602 int dx=240,dy=300,l=14; 1603 if (ed->window()){ 1604 dx=int(0.5*ed->window()->w()); 1605 dy=int(0.3*ed->window()->h()); 1606 l=ed->window()->labelsize(); 1607 } 1608 static Fl_Window * w = 0; 1609 static Fl_Return_Button * button0 = 0 ; // ok 1610 static Fl_Button * button1 =0; // cancel, quit 1611 static Fl_Input * cond=0; // condition 1612 static Fl_Input * ifclause=0; // if 1613 static Fl_Input * elseclause=0; // else 1614 if (!w){ 1615 Fl_Group::current(0); 1616 w=new Fl_Window(dx,dy); 1617 int dh=dy/5; 1618 int dw=dx/2; 1619 int y_=2; 1620 cond=new Fl_Input(dw/2,y_,3*dw/2-2,dh-2,gettext("if")); 1621 cond->tooltip(gettext("Enter test e.g. x<=0")); 1622 cond->value("x>1"); 1623 y_ += dh; 1624 ifclause=new Fl_Input(dw/2,y_,3*dw/2-2,dh-2,gettext("then")); 1625 ifclause->tooltip(gettext("Enter instruction(s) executed when test returns true, e.g. x:=-x;")); 1626 ifclause->value("x:=1-x;"); 1627 y_ += dh; 1628 elseclause=new Fl_Input(dw/2,y_,3*dw/2-2,dh-2,gettext("else")); 1629 elseclause->tooltip(gettext("Enter instruction(s) executed when test returns false, leave empty if none.")); 1630 elseclause->value(""); 1631 y_ += dh; 1632 y_ += dh; 1633 button0 = new Fl_Return_Button(2,y_,dx/5-4,dh-4); 1634 button0->label(gettext("OK")); 1635 button0->shortcut(0xff0d); 1636 button1 = new Fl_Button(dx/5+2,y_,dx/5-4,dh-4); 1637 button1->label(gettext("Cancel")); 1638 button1->shortcut(0xff1b); 1639 } 1640 w->label((gettext("New test"))); 1641 change_group_fontsize(w,l); 1642 w->set_modal(); 1643 w->show(); 1644 w->hotspot(w); 1645 Fl::focus(cond); 1646 autosave_disabled=true; 1647 context * contextptr=get_context(ed); 1648 int r=-2; 1649 for (;;) { 1650 if (r==-2){ 1651 // re-init fields value for function? 1652 } 1653 r=-1; 1654 Fl_Widget *o = Fl::readqueue(); 1655 if (!o) Fl::wait(); 1656 else { 1657 if (o == button0) r = 0; // apply and quit 1658 if (o == button1) r = 1; // cancel changes, quit 1659 if (r==0){ 1660 gen g(cond->value(),contextptr); 1661 if (g.type!=_SYMB && g.type!=_IDNT) 1662 fl_message("%s",gettext("Invalid condition")); 1663 g=gen(ifclause->value(),contextptr); 1664 if (is_undef(g)) 1665 fl_message("%s",gettext("Invalid if clause")); 1666 } 1667 if (o == w) r=1; 1668 if (r==0 || r==1) 1669 break; 1670 } 1671 } 1672 autosave_disabled=false; 1673 w->hide(); 1674 if (r==0){ 1675 giac::context * contextptr = get_context(ed); 1676 bool python=python_compat(contextptr); 1677 int i=ed->insert_position(); 1678 string s=python?"if ":"si "; 1679 s += cond->value(); 1680 s += python?":\n":" alors "; 1681 s += ifclause->value(); 1682 gen g(elseclause->value(),contextptr); 1683 bool ifonly=is_undef(g); 1684 if (!ifonly){ 1685 s += python?"\nelse:\n":" sinon "; 1686 s += elseclause->value(); 1687 } 1688 if (python) s+="\n"; else s += " fsi;\n"; 1689 ed->buffer()->insert(i,s.c_str()); 1690 int delta=s.size(); 1691 if (Xcas_Text_Editor * xed=dynamic_cast<Xcas_Text_Editor *>(ed)){ 1692 int j=ed->buffer()->line_end(i)+1; 1693 delta += xed->indent(j)-j; 1694 if (python){ 1695 j=ed->buffer()->line_end(j)+1; 1696 delta += xed->indent(j)-j; 1697 //j=ed->buffer()->line_end(j)+1; 1698 //delta += xed->indent(j)-j; 1699 if (!ifonly){ 1700 j=ed->buffer()->line_end(j)+1; 1701 delta += xed->indent(j)-j; 1702 j=ed->buffer()->line_end(j)+1; 1703 delta += xed->indent(j)-j; 1704 } 1705 ed->insert_position(i+delta); 1706 Fl_Text_Editor::kf_backspace(0,ed); 1707 xed->dedent(); 1708 } else ed->insert_position(i+delta); 1709 } 1710 else 1711 ed->insert_position(i+delta); 1712 } 1713 } 1714 cb_dialog_loop(Fl_Text_Editor * ed)1715 static void cb_dialog_loop(Fl_Text_Editor * ed){ 1716 int dx=240,dy=300,l=14; 1717 if (ed->window()){ 1718 dx=int(0.5*ed->window()->w()); 1719 dy=int(0.3*ed->window()->h()); 1720 l=ed->window()->labelsize(); 1721 } 1722 static Fl_Window * w = 0; 1723 static Fl_Return_Button * button0 = 0 ; // ok 1724 static Fl_Button * button1 =0; // cancel, quit 1725 static Fl_Check_Button * pour=0, * tantque=0; 1726 static Fl_Input * count=0; // for variable 1727 static Fl_Input * start=0; 1728 static Fl_Input * stop=0; 1729 static Fl_Input * step=0; 1730 static Fl_Input * loop=0; 1731 static Fl_Input * cond=0; 1732 if (!w){ 1733 Fl_Group::current(0); 1734 w=new Fl_Window(dx,dy); 1735 int dh=dy/5; 1736 int dw=dx/2; 1737 int y_=2; 1738 pour=new Fl_Check_Button(dw/2,y_,dw/2-2,dh-2,gettext("for")); 1739 pour->tooltip(gettext("Check this button for a defined loop")); 1740 pour->value(1); 1741 tantque=new Fl_Check_Button(3*dw/2,y_,dw/2-2,dh-2,gettext("while")); 1742 tantque->tooltip(gettext("Check this button for a undefined loop")); 1743 tantque->value(0); 1744 y_ += dh; 1745 count=new Fl_Input(dw/4,y_,dw/4-2,dh-2,gettext("Var")); 1746 count->tooltip(gettext("Enter counter name, e.g. k")); 1747 count->value("k"); 1748 start=new Fl_Input(3*dw/4,y_,dw/4-2,dh-2,gettext("Start")); 1749 start->tooltip(gettext("First value of counter in the loop")); 1750 start->value("1"); 1751 stop=new Fl_Input(5*dw/4,y_,dw/4-2,dh-2,gettext("Stop")); 1752 stop->tooltip(gettext("Last value of counter in the loop")); 1753 stop->value("10"); 1754 step=new Fl_Input(7*dw/4,y_,dw/4-2,dh-2,gettext("Step")); 1755 step->tooltip(gettext("Increment the counter value at each new execution of the loop")); 1756 step->value(""); 1757 cond=new Fl_Input(dw,y_,dw-2,dh-2,gettext("Condition")); 1758 cond->tooltip(gettext("Enter condition for continuation of loop")); 1759 cond->value("k>=0"); 1760 cond->hide(); 1761 y_ += dh; 1762 loop=new Fl_Input(dw/3,y_,2*dw-dw/3-2,dh-2,gettext("Loop")); 1763 loop->tooltip(gettext("Enter instruction(s) to be executed, for example print(y); print(y*y);")); 1764 loop->value("print(k);"); 1765 y_ += dh; 1766 y_ += dh; 1767 button0 = new Fl_Return_Button(2,y_,dx/5-4,dh-4); 1768 button0->label(gettext("OK")); 1769 button0->shortcut(0xff0d); 1770 button1 = new Fl_Button(dx/5+2,y_,dx/5-4,dh-4); 1771 button1->label(gettext("Cancel")); 1772 button1->shortcut(0xff1b); 1773 } 1774 w->label((gettext("New loop"))); 1775 change_group_fontsize(w,l); 1776 w->set_modal(); 1777 w->show(); 1778 autosave_disabled=true; 1779 w->hotspot(w); 1780 Fl::focus(loop); 1781 context * contextptr=get_context(ed); 1782 int r=-2; 1783 for (;;) { 1784 if (r==-2){ 1785 // re-init fields value for function? 1786 } 1787 r=-1; 1788 Fl_Widget *o = Fl::readqueue(); 1789 if (!o) Fl::wait(); 1790 else { 1791 if (o == button0) r = 0; // apply and quit 1792 if (o == button1) r = 1; // cancel changes, quit 1793 if (r==0 && pour->value()){ 1794 gen g(count->value(),contextptr); 1795 if (g.type!=_IDNT) 1796 fl_message("%s",gettext("Invalid counter")); 1797 } 1798 if (o==tantque) 1799 pour->value(1-tantque->value()); 1800 if (o==pour) 1801 tantque->value(1-pour->value()); 1802 if (tantque->value()==1){ 1803 count->hide(); start->hide(); stop->hide(); step->hide(); cond->show(); 1804 } 1805 else { 1806 count->show(); start->show(); stop->show(); step->show(); cond->hide(); 1807 } 1808 if (o == w) r=1; 1809 if (r==0 || r==1) 1810 break; 1811 } 1812 } 1813 autosave_disabled=false; 1814 w->hide(); 1815 if (r==0){ 1816 giac::context * contextptr = get_context(ed); 1817 bool python=python_compat(contextptr); 1818 int i=ed->insert_position(); 1819 string s; 1820 if (tantque->value()){ 1821 if (python) 1822 s = "while "; 1823 else 1824 s = "tantque "; 1825 s += cond->value(); 1826 if (python) 1827 s += ":\n"; 1828 else 1829 s += " faire\n"; 1830 s += loop->value(); 1831 if (python) s+="\n\n"; else s += "\nftantque;\n"; 1832 } 1833 else { 1834 if (python) 1835 s="for "; 1836 else 1837 s="pour "; 1838 s += count->value(); 1839 if (python){ 1840 s += " in range("; 1841 s += start->value(); 1842 s += ","; 1843 s += stop->value(); 1844 } 1845 else { 1846 s += " de "; 1847 s += start->value(); 1848 s += " jusque "; 1849 s += stop->value()+(python?1:0); 1850 } 1851 gen g(step->value(),contextptr); 1852 if (!is_undef(g)){ 1853 if (python){ 1854 s += ','; 1855 s += step->value(); 1856 } 1857 else { 1858 s += " pas "; 1859 s += step->value(); 1860 } 1861 } 1862 if (python) 1863 s+="):\n"; 1864 else 1865 s += " faire\n"; 1866 s += loop->value(); 1867 if (python) 1868 s += "\n"; 1869 else 1870 s += "\nfpour;\n"; 1871 } 1872 ed->buffer()->insert(i,s.c_str()); 1873 int delta=s.size(); 1874 if (Xcas_Text_Editor * xed=dynamic_cast<Xcas_Text_Editor *>(ed)){ 1875 int j=ed->buffer()->line_end(i)+1; 1876 delta += xed->indent(j)-j; 1877 j=ed->buffer()->line_end(j)+1; 1878 delta += xed->indent(j)-j; 1879 if (!python){ 1880 j=ed->buffer()->line_end(j)+1; 1881 delta += xed->indent(j)-j; 1882 } 1883 ed->insert_position(i+delta); 1884 if (python){ 1885 Fl_Text_Editor::kf_backspace(0,ed); 1886 xed->dedent(); 1887 } 1888 } 1889 else 1890 ed->insert_position(i+delta); 1891 } 1892 } 1893 cb_choose_func(Fl_Text_Editor * ed)1894 void cb_choose_func(Fl_Text_Editor * ed){ 1895 giac::context * contextptr = get_context(ed); 1896 bool python=python_compat(contextptr); 1897 int dx=240,dy=300,l=14; 1898 if (ed->window()){ 1899 dx=int(0.5*ed->window()->w()); 1900 dy=int(0.3*ed->window()->h()); 1901 l=ed->window()->labelsize(); 1902 } 1903 static Fl_Window * w = 0; 1904 static Fl_Return_Button * button0 = 0 ; // ok 1905 static Fl_Button * button1 =0; // cancel, quit 1906 static Fl_Input * args=0; // arguments 1907 static Fl_Input * name=0; // name 1908 static Fl_Input * locs=0; // local variables 1909 static Fl_Input * ret=0; // return value 1910 if (!w){ 1911 Fl_Group::current(0); 1912 w=new Fl_Window(dx,dy); 1913 int dh=dy/5; 1914 int dw=dx/2; 1915 int y_=2; 1916 name=new Fl_Input(dw,y_,dw-2,dh-2,gettext("Name")); 1917 name->tooltip(gettext("Enter function name, e.g. f or myfunc")); 1918 name->value("f"); 1919 y_ += dh; 1920 args=new Fl_Input(dw,y_,dw-2,dh-2,gettext("Arguments")); 1921 args->tooltip(gettext("Enter function argument(s), e.g. x or a,b,c. Leave empty if no argument")); 1922 args->value("x"); 1923 y_ += dh; 1924 locs=new Fl_Input(dw,y_,dw-2,dh-2,gettext("Locals")); 1925 locs->tooltip(gettext("Enter local variable(s), e.g. k or n1,n2,n3. Leave empty if no local variables. Local symbolic variables should be purged after declaration.")); 1926 locs->value("k"); 1927 y_ += dh; 1928 ret=new Fl_Input(dw,y_,dw-2,dh-2,gettext("Return value")); 1929 ret->tooltip(gettext("Enter return value, e.g. x+1 or [a,b]. Leave empty if no local variables")); 1930 ret->value("x*x"); 1931 y_ += dh; 1932 button0 = new Fl_Return_Button(2,y_,dx/5-4,dh-4); 1933 button0->label(gettext("OK")); 1934 button0->shortcut(0xff0d); 1935 button1 = new Fl_Button(dx/5+2,y_,dx/5-4,dh-4); 1936 button1->label(gettext("Cancel")); 1937 button1->shortcut(0xff1b); 1938 } 1939 w->label((gettext("New function"))); 1940 change_group_fontsize(w,l); 1941 w->set_modal(); 1942 if (python) locs->hide(); else locs->show(); 1943 w->show(); 1944 autosave_disabled=true; 1945 w->hotspot(w); 1946 Fl::focus(name); 1947 int lang=language(contextptr); 1948 int r=-2; 1949 for (;;) { 1950 if (r==-2){ 1951 // re-init fields value for function? 1952 } 1953 r=-1; 1954 Fl_Widget *o = Fl::readqueue(); 1955 if (!o) Fl::wait(); 1956 else { 1957 if (o == button0) r = 0; // apply and quit 1958 if (o == button1) r = 1; // cancel changes, quit 1959 if (r==0){ 1960 gen g(name->value(),contextptr); 1961 if (g.type!=_IDNT) 1962 fl_message("%s",gettext("Invalid functionname")); 1963 } 1964 if (o == w) r=1; 1965 if (r==0 || r==1) 1966 break; 1967 } 1968 } 1969 autosave_disabled=false; 1970 w->hide(); 1971 bool syntaxefr=lang==1; // activer apres les concours 2017 1972 if (r==0){ 1973 int i=0,addi=0; // i=ed->insert_position(),addi=0; 1974 string s; 1975 switch (xcas_mode(contextptr)){ 1976 case 0: 1977 if (python) 1978 s += "def "; 1979 else { 1980 if (syntaxefr) 1981 s+="fonction "; 1982 } 1983 s+=name->value(); 1984 s+='('; 1985 s+=args->value(); 1986 s+=")"; 1987 if (python) 1988 s += ":"; 1989 else { 1990 if (!syntaxefr) 1991 s+=":={"; 1992 } 1993 s+="\n"; 1994 if (!python && strlen(locs->value())){ 1995 s+=python?" # local ":" local "; 1996 s+=locs->value(); 1997 if (python) 1998 s+="\n "; 1999 else 2000 s+=";\n "; 2001 } 2002 addi=s.size(); 2003 s += "\n"; 2004 if (strlen(ret->value())){ 2005 if (lang==1 && !python) 2006 s+=" retourne "; 2007 else 2008 s+=python?" return ":" return "; 2009 s+=ret->value(); 2010 if (!python) s+=";"; 2011 } 2012 s += "\n"; 2013 if (python) 2014 ; 2015 else { 2016 if (syntaxefr) 2017 s+="ffonction"; 2018 else 2019 s+="}"; 2020 s+=":;\n\n"; 2021 } 2022 ed->buffer()->insert(i,s.c_str()); 2023 ed->insert_position(i+addi); 2024 break; 2025 case 1: 2026 s+=name->value(); 2027 s+=":=proc("; 2028 s+=args->value(); 2029 s+=")\n"; 2030 if (strlen(locs->value())){ 2031 s+=" local "; 2032 s+=locs->value(); 2033 s+=";\n "; 2034 } 2035 addi=s.size(); 2036 s += "\n"; 2037 if (strlen(ret->value())){ 2038 s+=" return "; 2039 s+=ret->value(); 2040 s+=";"; 2041 } 2042 s += "\nend:\n\n"; 2043 ed->buffer()->insert(i,s.c_str()); 2044 ed->insert_position(i+addi); 2045 break; 2046 case 2: 2047 s+=name->value(); 2048 s+=":=proc("; 2049 s+=args->value(); 2050 s+=")\n"; 2051 if (strlen(locs->value())){ 2052 s+=" local "; 2053 s+=locs->value(); 2054 s+=";\n "; 2055 } 2056 addi=s.size(); 2057 s += "\n"; 2058 if (strlen(ret->value())){ 2059 s+=" return "; 2060 s+=ret->value(); 2061 s+=";"; 2062 } 2063 s += "\nend_proc:\n\n"; 2064 ed->buffer()->insert(i,s.c_str()); 2065 ed->insert_position(i+addi); 2066 break; 2067 case 3: 2068 s+=':'; 2069 s+=name->value(); 2070 s+='('; 2071 s+=args->value(); 2072 s+=")\n:Func\n"; 2073 if (strlen(locs->value())){ 2074 s+="\n:Local "; 2075 s+=locs->value(); 2076 s+="\n:"; 2077 } 2078 addi=s.size(); 2079 s += "\n:"; 2080 if (strlen(ret->value())){ 2081 s+="\n:Return "; 2082 s+=ret->value(); 2083 } 2084 s += "\n:EndFunc\n\n"; 2085 ed->buffer()->insert(i,s.c_str()); 2086 ed->insert_position(i+addi); 2087 break; 2088 } 2089 } 2090 } 2091 cb_prg_func(Fl_Menu_ * m,void *)2092 static void cb_prg_func(Fl_Menu_* m , void*) { 2093 Fl_Text_Editor * ed = do_find_editor(m); 2094 if (ed){ 2095 cb_choose_func(ed); 2096 Fl::focus(ed); 2097 } 2098 else 2099 Xcas_input_0arg("f():={ local ; ; return ;}"); 2100 } 2101 cb_prg_si(Fl_Menu_ * m,void *)2102 static void cb_prg_si(Fl_Menu_* m , void*) { 2103 Fl_Text_Editor * ed = do_find_editor(m); 2104 if (ed){ 2105 cb_dialog_test(ed); 2106 Fl::focus(ed); 2107 } 2108 else 2109 Xcas_input_0arg("si alors sinon fsi;"); 2110 } 2111 cb_prg_pour(Fl_Menu_ * m,void *)2112 static void cb_prg_pour(Fl_Menu_* m , void*) { 2113 Fl_Text_Editor * ed = do_find_editor(m); 2114 if (ed){ 2115 cb_dialog_loop(ed); 2116 Fl::focus(ed); 2117 } 2118 else 2119 Xcas_input_0arg("pour de jusque faire fpour;"); 2120 } 2121 cb_prg_local(Fl_Menu_ * m,void *)2122 static void cb_prg_local(Fl_Menu_* m , void*) { 2123 Fl_Text_Editor * ed = do_find_editor(m); 2124 if (ed){ 2125 giac::context * contextptr = get_context(ed); 2126 int i=ed->insert_position(); 2127 ed->buffer()->insert(i,xcas_mode(contextptr)==3?"\n:Local ":"local ;\n "); 2128 ed->insert_position(i+6); 2129 } 2130 else 2131 Xcas_input_0arg("local ;"); 2132 } 2133 cb_prg_return(Fl_Menu_ * m,void *)2134 static void cb_prg_return(Fl_Menu_* m , void*) { 2135 Fl_Text_Editor * ed = do_find_editor(m); 2136 if (ed){ 2137 giac::context * contextptr = get_context(ed); 2138 int i=ed->insert_position(); 2139 ed->buffer()->insert(i,xcas_mode(contextptr)==3?"\n:Return ":"return ;"); 2140 ed->insert_position(i+7); 2141 } 2142 else 2143 Xcas_input_0arg("return ;"); 2144 } 2145 cb_prg_ifthenelse(Fl_Menu_ * m,void *)2146 static void cb_prg_ifthenelse(Fl_Menu_* m , void*) { 2147 Fl_Text_Editor * ed = do_find_editor(m); 2148 if (ed){ 2149 giac::context * contextptr = get_context(ed); 2150 int i=ed->insert_position(); 2151 switch (xcas_mode(contextptr)){ 2152 case 0: 2153 ed->buffer()->insert(i,"if () { ;} else { ;}\n "); 2154 ed->insert_position(i+4); 2155 break; 2156 case 1: 2157 ed->buffer()->insert(i,"if then ; else ; fi;\n "); 2158 ed->insert_position(i+3); 2159 break; 2160 case 2: 2161 ed->buffer()->insert(i,"if then ; else ; end_if;\n "); 2162 ed->insert_position(i+3); 2163 break; 2164 case 3: 2165 ed->buffer()->insert(i,"\n:If Then\n:Else \n:EndIf;\n"); 2166 ed->insert_position(i+4); 2167 break; 2168 } 2169 } 2170 else { 2171 giac::context * contextptr = get_context(Xcas_input_focus); 2172 switch (xcas_mode(contextptr)){ 2173 case 0: 2174 Xcas_input_0arg("if () { ; } else { ; }"); 2175 break; 2176 case 1: 2177 Xcas_input_0arg("if then ; else ; fi;"); 2178 break; 2179 case 2: 2180 Xcas_input_0arg("if then ; else ; end_if;"); 2181 break; 2182 case 3: 2183 Xcas_input_0arg("\n:If Then\n:Else \n:EndIf;\n"); 2184 break; 2185 } 2186 } 2187 } 2188 cb_prg_sialorssinon(Fl_Menu_ * m,void *)2189 static void cb_prg_sialorssinon(Fl_Menu_* m , void*) { 2190 Fl_Text_Editor * ed = do_find_editor(m); 2191 if (ed){ 2192 giac::context * contextptr = get_context(ed); 2193 int i=ed->insert_position(); 2194 ed->buffer()->insert(i,"si alors ; sinon ; fsi;\n "); 2195 ed->insert_position(i+3); 2196 } 2197 else 2198 Xcas_input_0arg("si alors ; sinon ; fsi"); 2199 } 2200 cb_prg_pour_(Fl_Menu_ * m,void *)2201 static void cb_prg_pour_(Fl_Menu_* m , void*) { 2202 Fl_Text_Editor * ed = do_find_editor(m); 2203 if (ed){ 2204 giac::context * contextptr = get_context(ed); 2205 int i=ed->insert_position(); 2206 ed->buffer()->insert(i,"pour de jusque faire\n ;\n fpour;\n "); 2207 ed->insert_position(i+5); 2208 } 2209 else 2210 Xcas_input_0arg("pour de jusque faire ; fpour;"); 2211 } 2212 cb_prg_tantque(Fl_Menu_ * m,void *)2213 static void cb_prg_tantque(Fl_Menu_* m , void*) { 2214 Fl_Text_Editor * ed = do_find_editor(m); 2215 if (ed){ 2216 giac::context * contextptr = get_context(ed); 2217 int i=ed->insert_position(); 2218 ed->buffer()->insert(i,"tantque faire\n ;\n ftantque;\n "); 2219 ed->insert_position(i+8); 2220 } 2221 else 2222 Xcas_input_0arg("tantque faire ; ftantque;"); 2223 } 2224 cb_prg_repeter(Fl_Menu_ * m,void *)2225 static void cb_prg_repeter(Fl_Menu_* m , void*) { 2226 Fl_Text_Editor * ed = do_find_editor(m); 2227 if (ed){ 2228 giac::context * contextptr = get_context(ed); 2229 int i=ed->insert_position(); 2230 ed->buffer()->insert(i,"repeter\n ;\n jusqu_a ;\n"); 2231 ed->insert_position(i+12); 2232 } 2233 else 2234 Xcas_input_0arg("repeter jusqu_a ;"); 2235 } 2236 cb_prg_ifthen(Fl_Menu_ * m,void *)2237 static void cb_prg_ifthen(Fl_Menu_* m , void*) { 2238 Fl_Text_Editor * ed = do_find_editor(m); 2239 if (ed){ 2240 giac::context * contextptr = get_context(ed); 2241 int i=ed->insert_position(); 2242 switch (xcas_mode(contextptr)){ 2243 case 0: 2244 ed->buffer()->insert(i,"if () { ;}\n"); 2245 ed->insert_position(i+5); 2246 break; 2247 case 1: 2248 ed->buffer()->insert(i,"if then ; fi;\n"); 2249 ed->insert_position(i+4); 2250 break; 2251 case 2: 2252 ed->buffer()->insert(i,"if then ; end_if;\n"); 2253 ed->insert_position(i+4); 2254 break; 2255 case 3: 2256 ed->buffer()->insert(i,"\n:If Then\n:EndIf\n"); 2257 ed->insert_position(i+4); 2258 break; 2259 } 2260 } 2261 else { 2262 giac::context * contextptr = get_context(Xcas_input_focus); 2263 switch (xcas_mode(contextptr)){ 2264 case 0: 2265 Xcas_input_0arg("if () { ;}"); 2266 break; 2267 case 1: 2268 Xcas_input_0arg("if then ; fi;"); 2269 break; 2270 case 2: 2271 Xcas_input_0arg("if then ; end_if;"); 2272 break; 2273 case 3: 2274 Xcas_input_0arg("\n:If Then\n:EndIf\n"); 2275 break; 2276 } 2277 } 2278 } 2279 cb_prg_print(Fl_Menu_ * m,void *)2280 static void cb_prg_print(Fl_Menu_* m , void*) { 2281 Fl_Text_Editor * ed = do_find_editor(m); 2282 if (ed){ 2283 int i=ed->insert_position(); 2284 ed->buffer()->insert(i,gettext("print();")); 2285 ed->insert_position(i+strlen(gettext("print();"))-2); 2286 } 2287 else 2288 Xcas_input_0arg(gettext("print();")); 2289 } 2290 cb_prg_input(Fl_Menu_ * m,void *)2291 static void cb_prg_input(Fl_Menu_* m , void*) { 2292 Fl_Text_Editor * ed = do_find_editor(m); 2293 if (ed){ 2294 int i=ed->insert_position(); 2295 ed->buffer()->insert(i,gettext("input();")); 2296 ed->insert_position(i+strlen(gettext("input();"))-2); 2297 } 2298 else 2299 Xcas_input_0arg(gettext("input();")); 2300 } 2301 cb_prg_switch(Fl_Menu_ * m,void *)2302 static void cb_prg_switch(Fl_Menu_* m , void*) { 2303 Fl_Text_Editor * ed = do_find_editor(m); 2304 if (ed){ 2305 int i=ed->insert_position(); 2306 ed->buffer()->insert(i,"switch(){\n case : break;\n }\n "); 2307 ed->insert_position(i+8); 2308 } 2309 else 2310 Xcas_input_0arg("switch () {case : break;}"); 2311 } 2312 cb_prg_trycatch(Fl_Menu_ * m,void *)2313 static void cb_prg_trycatch(Fl_Menu_* m , void*) { 2314 Fl_Text_Editor * ed = do_find_editor(m); 2315 if (ed){ 2316 giac::context * contextptr = get_context(ed); 2317 int i=ed->insert_position(); 2318 ed->buffer()->insert(i,xcas_mode(contextptr)==3?"\n:Try\n\n:Else\n\n:EndTry":"\ntry {\n ;\n}\ncatch(){\n ;}\n"); 2319 ed->insert_position(i+7); 2320 } 2321 else { 2322 giac::context * contextptr = get_context(Xcas_input_focus); 2323 Xcas_input_0arg(xcas_mode(contextptr)==3?"\n:Try\n\n:Else\n\n:EndTry":"try { ;}catch(){ ;}"); 2324 } 2325 } 2326 cb_prg_for(Fl_Menu_ * m,void *)2327 static void cb_prg_for(Fl_Menu_* m , void*) { 2328 Fl_Text_Editor * ed = do_find_editor(m); 2329 if (ed){ 2330 giac::context * contextptr = get_context(ed); 2331 int i=ed->insert_position(); 2332 switch (xcas_mode(contextptr)){ 2333 case 0: 2334 ed->buffer()->insert(i,"for(;;){\n ;\n }\n "); 2335 ed->insert_position(i+4); 2336 break; 2337 case 1: 2338 ed->buffer()->insert(i,"for from to do\n ;\n od;\n "); 2339 ed->insert_position(i+4); 2340 break; 2341 case 2: 2342 ed->buffer()->insert(i,"for from to do\n ;\n end_for;\n "); 2343 ed->insert_position(i+4); 2344 break; 2345 case 3: 2346 ed->buffer()->insert(i,"\n:For ,,\n\n:EndFor\n"); 2347 ed->insert_position(i+5); 2348 break; 2349 } 2350 } 2351 else { 2352 giac::context * contextptr = get_context(Xcas_input_focus); 2353 switch (xcas_mode(contextptr)){ 2354 case 0: 2355 Xcas_input_0arg("for( ; ; ){ ;}"); 2356 break; 2357 case 1: 2358 Xcas_input_0arg("for from to do ; od;"); 2359 break; 2360 case 2: 2361 Xcas_input_0arg("for from to do ; end_for;"); 2362 break; 2363 case 3: 2364 Xcas_input_0arg("\n:For ,,\n:\n:EndFor;\n"); 2365 break; 2366 } 2367 } 2368 } 2369 cb_prg_while(Fl_Menu_ * m,void *)2370 static void cb_prg_while(Fl_Menu_* m , void*) { 2371 Fl_Text_Editor * ed = do_find_editor(m); 2372 if (ed){ 2373 giac::context * contextptr = get_context(ed); 2374 int i=ed->insert_position(); 2375 switch (xcas_mode(contextptr)){ 2376 case 0: 2377 ed->buffer()->insert(i,"while(){\n ;\n }\n "); 2378 ed->insert_position(i+6); 2379 break; 2380 case 1: 2381 ed->buffer()->insert(i,"while do\n ;\n od;\n "); 2382 ed->insert_position(i+6); 2383 break; 2384 case 2: 2385 ed->buffer()->insert(i,"while do\n ;\n end_while;\n "); 2386 ed->insert_position(i+6); 2387 break; 2388 case 3: 2389 ed->buffer()->insert(i,"\n:While \n:\n:EndWhile\n"); 2390 ed->insert_position(i+7); 2391 break; 2392 } 2393 } 2394 else { 2395 giac::context * contextptr = get_context(Xcas_input_focus); 2396 switch (xcas_mode(contextptr)){ 2397 case 0: 2398 Xcas_input_0arg("while( ){ ;}"); 2399 break; 2400 case 1: 2401 Xcas_input_0arg("while do ; od;"); 2402 break; 2403 case 2: 2404 Xcas_input_0arg("while do ; end_while;"); 2405 break; 2406 case 3: 2407 Xcas_input_0arg("\n:While \n:\n:EndWhile;\n"); 2408 break; 2409 } 2410 } 2411 } 2412 cb_prg_break(Fl_Menu_ * m,void *)2413 static void cb_prg_break(Fl_Menu_* m , void*) { 2414 Fl_Text_Editor * ed = do_find_editor(m); 2415 if (ed){ 2416 giac::context * contextptr = get_context(ed); 2417 int i=ed->insert_position(); 2418 ed->buffer()->insert(i,xcas_mode(contextptr)==3?":Stop \n:":"break;\n "); 2419 ed->insert_position(i+8); 2420 } 2421 else { 2422 giac::context * contextptr = get_context(Xcas_input_focus); 2423 Xcas_input_0arg(xcas_mode(contextptr)==3?":Stop \n":"break;"); 2424 } 2425 } 2426 cb_prg_continue(Fl_Menu_ * m,void *)2427 static void cb_prg_continue(Fl_Menu_* m , void*) { 2428 Fl_Text_Editor * ed = do_find_editor(m); 2429 if (ed){ 2430 giac::context * contextptr = get_context(ed); 2431 int i=ed->insert_position(); 2432 ed->buffer()->insert(i,xcas_mode(contextptr)==3?":Cycle \n":"continue;\n "); 2433 ed->insert_position(i+11); 2434 } 2435 else { 2436 giac::context * contextptr = get_context(Xcas_input_focus); 2437 Xcas_input_0arg(xcas_mode(contextptr)==3?":Cycle \n":"continue;"); 2438 } 2439 } 2440 2441 Fl_Menu_Item Editeur_menu[] = { 2442 {gettext("Prog"), 0, 0, 0, 64, 0, 0, 14, 56}, 2443 {gettext("Load"), 0, (Fl_Callback*)cb_Editeur_Load, 0, 0, 0, 0, 14, 56}, 2444 {gettext("Insert"), 0, 0, 0, 64, 0, 0, 14, 56}, 2445 {gettext("File"), 0, (Fl_Callback*)cb_Editeur_Insert_File, 0, 0, 0, 0, 14, 56}, 2446 {gettext("Xcas text"), 0, (Fl_Callback*)cb_Editeur_Insert_Xcas, 0, 0, 0, 0, 14, 56}, 2447 {gettext("Xcas Python text"), 0, (Fl_Callback*)cb_Editeur_Insert_Python, 0, 0, 0, 0, 14, 56}, 2448 {gettext("Maple text"), 0, (Fl_Callback*)cb_Editeur_Insert_Maple, 0, 0, 0, 0, 14, 56}, 2449 {gettext("Mupad text"), 0, (Fl_Callback*)cb_Editeur_Insert_Mupad, 0, 0, 0, 0, 14, 56}, 2450 {gettext("TI text"), 0, (Fl_Callback*)cb_Editeur_Insert_Ti, 0, 0, 0, 0, 14, 56}, 2451 {0}, 2452 {gettext("Save"), 0, (Fl_Callback*)cb_Editeur_Save, 0, 0, 0, 0, 14, 56}, 2453 {gettext("Save as"), 0, (Fl_Callback*)cb_Editeur_Save_as, 0, 0, 0, 0, 14, 56}, 2454 {gettext("File extension"), 0, (Fl_Callback*)cb_Editeur_Extension, 0, 0, 0, 0, 14, 56}, 2455 {gettext("Export"), 0, 0, 0, 64, 0, 0, 14, 56}, 2456 {gettext("Xcas text"), 0, (Fl_Callback*)cb_Editeur_Export_Xcas, 0, 0, 0, 0, 14, 56}, 2457 {gettext("Xcas-python text"), 0, (Fl_Callback*)cb_Editeur_Export_Python, 0, 0, 0, 0, 14, 56}, 2458 {gettext("Maple text"), 0, (Fl_Callback*)cb_Editeur_Export_Maple, 0, 0, 0, 0, 14, 56}, 2459 {gettext("Mupad text"), 0, (Fl_Callback*)cb_Editeur_Export_Mupad, 0, 0, 0, 0, 14, 56}, 2460 {gettext("TI text"), 0, (Fl_Callback*)cb_Editeur_Export_Ti, 0, 0, 0, 0, 14, 56}, 2461 {0}, 2462 {gettext("Translate"), 0, 0, 0, 64, 0, 0, 14, 56}, 2463 {gettext("Xcas"), 0, (Fl_Callback*)cb_Editeur_Translate_Xcas, 0, 0, 0, 0, 14, 56}, 2464 {gettext("Maple"), 0, (Fl_Callback*)cb_Editeur_Translate_Maple, 0, 0, 0, 0, 14, 56}, 2465 {gettext("Mupad"), 0, (Fl_Callback*)cb_Editeur_Translate_Mupad, 0, 0, 0, 0, 14, 56}, 2466 {gettext("TI"), 0, (Fl_Callback*)cb_Editeur_Translate_Ti, 0, 0, 0, 0, 14, 56}, 2467 {0}, 2468 {gettext("Export/Print"), 0, 0, 0, 64, 0, 0, 14, 56}, 2469 // {gettext("latex preview"), 0, (Fl_Callback*)cb_Tableur_LaTeX_Preview, 0, 0, 0, 0, 14, 56}, 2470 // {gettext("latex printer"), 0, (Fl_Callback*)cb_Tableur_LaTeX_Print, 0, 0, 0, 0, 14, 56}, 2471 {gettext("Preview"), 0, (Fl_Callback*)cb_Editeur_Preview, 0, 0, 0, 0, 14, 56}, 2472 {gettext("to printer"), 0, (Fl_Callback*)cb_Editeur_Print, 0, 0, 0, 0, 14, 56}, 2473 {0}, // end Print 2474 {0}, // end File 2475 {gettext("Edit"), 0, 0, 0, 64, 0, 0, 14, 56}, 2476 {gettext("Paste"), 0, (Fl_Callback *) cb_Paste, 0, 0, 0, 0, 14, 56}, 2477 {gettext("Search (Ctrl-F)"), 0, (Fl_Callback *) cb_Editeur_Search, 0, 0, 0, 0, 14, 56}, 2478 {gettext("Indent line (Esc)"), 0, (Fl_Callback *) cb_Editeur_Indent_line, 0, 0, 0, 0, 14, 56}, 2479 {gettext("Indent all"), 0, (Fl_Callback *) cb_Editeur_Indent_all, 0, 0, 0, 0, 14, 56}, 2480 {gettext("Parse"), 0, (Fl_Callback *) cb_Editeur_Test, 0, 0, 0, 0, 14, 56}, 2481 {gettext("Exec all"), 0xffc4, (Fl_Callback *) cb_Editeur_Exec_All, 0, 0, 0, 0, 14, 56}, 2482 {gettext("Extend editor"), 0xffc2, (Fl_Callback *) cb_Editeur_Extend, 0, 0, 0, 0, 14, 56}, 2483 {gettext("Shrink editor"), 0xffc3, (Fl_Callback *) cb_Editeur_Shrink, 0, 0, 0, 0, 14, 56}, 2484 {0}, // end Edit 2485 {gettext("Add"), 0, 0, 0, 64, 0, 0, 14, 56}, 2486 {gettext("Func"), 0, 0, 0, 64, 0, 0, 14, 56}, 2487 {gettext("new function"), 0, (Fl_Callback *) cb_prg_func, 0, 0, 0, 0, 14, 56}, 2488 {gettext("local"), 0, (Fl_Callback *) cb_prg_local, 0, 0, 0, 0, 14, 56}, 2489 {gettext("return"), 0, (Fl_Callback *) cb_prg_return, 0, 0, 0, 0, 14, 56}, 2490 {0}, // end Func 2491 {gettext("IO"), 0, 0, 0, 64, 0, 0, 14, 56}, 2492 {gettext("print"), 0, (Fl_Callback *) cb_prg_print, 0, 0, 0, 0, 14, 56}, 2493 {gettext("input"), 0, (Fl_Callback *) cb_prg_input, 0, 0, 0, 0, 14, 56}, 2494 {0}, // end IO 2495 {gettext("Test"), 0, 0, 0, 64, 0, 0, 14, 56}, 2496 {gettext("new test"), 0, (Fl_Callback *) cb_prg_si, 0, 0, 0, 0, 14, 56}, 2497 {gettext("si alors sinon"), 0, (Fl_Callback *) cb_prg_sialorssinon, 0, 0, 0, 0, 14, 56}, 2498 {gettext("if"), 0, (Fl_Callback *) cb_prg_ifthen, 0, 0, 0, 0, 14, 56}, 2499 {gettext("if else"), 0, (Fl_Callback *) cb_prg_ifthenelse, 0, 0, 0, 0, 14, 56}, 2500 {gettext("switch"), 0, (Fl_Callback *) cb_prg_switch, 0, 0, 0, 0, 14, 56}, 2501 {gettext("try catch"), 0, (Fl_Callback *) cb_prg_trycatch, 0, 0, 0, 0, 14, 56}, 2502 {0}, // end Test 2503 {gettext("Loop"), 0, 0, 0, 64, 0, 0, 14, 56}, 2504 {gettext("new loop"), 0, (Fl_Callback *) cb_prg_pour, 0, 0, 0, 0, 14, 56}, 2505 {gettext("pour"), 0, (Fl_Callback *) cb_prg_pour_, 0, 0, 0, 0, 14, 56}, 2506 {gettext("tantque"), 0, (Fl_Callback *) cb_prg_tantque, 0, 0, 0, 0, 14, 56}, 2507 {gettext("repeter jusqu_a"), 0, (Fl_Callback *) cb_prg_repeter, 0, 0, 0, 0, 14, 56}, 2508 {gettext("for "), 0, (Fl_Callback *) cb_prg_for, 0, 0, 0, 0, 14, 56}, 2509 {gettext("while "), 0, (Fl_Callback *) cb_prg_while, 0, 0, 0, 0, 14, 56}, 2510 {gettext("break"), 0, (Fl_Callback *) cb_prg_break, 0, 0, 0, 0, 14, 56}, 2511 {gettext("continue"), 0, (Fl_Callback *) cb_prg_continue, 0, 0, 0, 0, 14, 56}, 2512 {0}, // end Loop 2513 {0}, // end Prg 2514 {0} // end menu 2515 }; 2516 clear_gchanged()2517 void Xcas_Text_Editor::clear_gchanged(){ 2518 gchanged=false; 2519 } 2520 set_gchanged()2521 void Xcas_Text_Editor::set_gchanged(){ 2522 gchanged=true; 2523 } 2524 Xcas_Text_Editor(int X,int Y,int W,int H,Fl_Text_Buffer * b,const char * l)2525 Xcas_Text_Editor::Xcas_Text_Editor(int X, int Y, int W, int H, Fl_Text_Buffer *b,const char* l ):Fl_Text_Editor(X,Y,W,H,l){ 2526 styletable=vector<Fl_Text_Display::Style_Table_Entry>(styletable_init,styletable_init+styletable_n); 2527 tableur=0; 2528 gchanged=true; 2529 labeltype(FL_NO_LABEL); 2530 color(FL_WHITE); 2531 buffer(b); 2532 char *style = new char[buffer()->length()+1]; 2533 char *text = buffer()->text(); 2534 2535 2536 memset(style, 'A', buffer()->length()); 2537 style[buffer()->length()] = '\0'; 2538 2539 stylebuf = new Fl_Text_Buffer(buffer()->length()); 2540 2541 style_parse(text, style, buffer()->length()); 2542 2543 stylebuf->text(style); 2544 delete[] style; 2545 free(text); 2546 highlight_data(stylebuf, &styletable.front(),styletable.size(),'A', style_unfinished_cb, 0); 2547 2548 } 2549 Editeur(int x,int y,int w,int h,const char * l)2550 Editeur::Editeur(int x,int y,int w,int h,const char * l):Fl_Group(x,y,w,h,l),contextptr(0){ 2551 bool logo=false; 2552 if (parent()){ 2553 labelsize(parent()->labelsize()); 2554 logo=dynamic_cast<Logo *>(parent()); 2555 contextptr=get_context(parent()); 2556 } 2557 Fl_Group::current(this); 2558 int L=(3*labelsize())/2; 2559 Fl_Text_Buffer * b = new Fl_Text_Buffer; 2560 editor=new Xcas_Text_Editor(x,y+L,w,h-L,b,l); 2561 editor->Fl_Text_Display::textsize(labelsize()); 2562 editor->labelsize(labelsize()); 2563 log = 0; 2564 if (logo){ 2565 menubar = new Fl_Menu_Bar(x,y,w/2,L); 2566 } 2567 else { 2568 menubar = new Fl_Menu_Bar(x,y,w/4,L); 2569 } 2570 int s= Editeur_menu->size(); 2571 Fl_Menu_Item * menuitem = new Fl_Menu_Item[s]; 2572 for (int i=0;i<s;++i) 2573 *(menuitem+i)=*(Editeur_menu+i); 2574 menubar->menu (menuitem); 2575 change_menu_fontsize(menuitem,3,labelsize()); // 3=#submenus 2576 linenumber=0; nxt_button=0; exec_button=0; func_button=0; si_button=0; pour_button=0; 2577 if (!logo){ 2578 linenumber = new Fl_Value_Input(x+w/3-w/12,y,w/12,L); 2579 linenumber->tooltip(gettext("Line number")); 2580 linenumber->callback((Fl_Callback *)cb_Editeur_Gotoline); 2581 linenumber->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED); 2582 nxt_button = new Fl_Button(x+w/3,y,w/12,L); 2583 nxt_button->labelsize(labelsize()); 2584 nxt_button->label(gettext("nxt")); 2585 nxt_button->tooltip(gettext("Find next occurence (defined by Edit->Search)")); 2586 nxt_button->callback((Fl_Callback *) cb_Editeur_Next); 2587 if (parent()==window()){ 2588 exec_button = new Save_Focus_Button(x+w/3-w/12,y,w/12,L); 2589 exec_button->callback((Fl_Callback *)cb_Editeur_Exec); 2590 exec_button->labelsize(labelsize()); 2591 exec_button->label(gettext("exe")); 2592 exec_button->tooltip(gettext("Exec line in current widget")); 2593 } 2594 else { 2595 func_button = new Fl_Button(nxt_button->x()+nxt_button->w(),y,w/12,L); 2596 func_button->labelsize(labelsize()); 2597 func_button->label(gettext("Func")); 2598 func_button->tooltip(gettext("Assistant for function creation")); 2599 func_button->callback((Fl_Callback *) cb_prg_func); 2600 si_button = new Fl_Button(func_button->x()+func_button->w(),y,w/12,L); 2601 si_button->labelsize(labelsize()); 2602 si_button->label(gettext("Test")); 2603 si_button->tooltip(gettext("Assistant for test creation")); 2604 si_button->callback((Fl_Callback *) cb_prg_si); 2605 pour_button = new Fl_Button(si_button->x()+si_button->w(),y,w/12,L); 2606 pour_button->labelsize(labelsize()); 2607 pour_button->label(gettext("Loop")); 2608 pour_button->tooltip(gettext("Assistant for loop creation")); 2609 pour_button->callback((Fl_Callback *) cb_prg_pour); 2610 } 2611 } 2612 button = new Fl_Button(x+w/2+w/6,y,w/12,L); 2613 button->labelsize(labelsize()); 2614 // button->label(logo?"OK":"OK (F9)"); 2615 button->label("OK"); 2616 button->labelcolor(FL_DARK_GREEN); 2617 button->tooltip(gettext("Parse current program")); 2618 button->callback((Fl_Callback *) logo?cb_Editeur_Exec_All:cb_Editeur_Test); 2619 button->shortcut(0xffc6); // FIXME: quick fix, otherwise Esc leaves xcas 2620 save_button = new Fl_Button(x+w/2+w/4,y,w/12,L); 2621 save_button->labelsize(labelsize()); 2622 save_button->label("Save"); 2623 save_button->tooltip(gettext("Save current program")); 2624 save_button->callback((Fl_Callback *) cb_Editeur_Save); 2625 output = new Fl_Output(x+w/2+w/4+save_button->w(),y,w-w/2-w/4-save_button->w(),L); 2626 output->labelsize(labelsize()); 2627 end(); 2628 2629 b->add_modify_callback(style_update, editor); 2630 b->add_modify_callback(Editor_changed_cb, editor); 2631 resizable(editor); 2632 switch (xcas_mode(contextptr)){ 2633 case 0: 2634 if (python_compat(contextptr)) 2635 extension="py"; 2636 else 2637 extension="cxx"; 2638 break; 2639 case 1: 2640 extension="map"; 2641 break; 2642 case 2: 2643 extension="mu"; 2644 break; 2645 case 3: 2646 extension="ti"; 2647 break; 2648 } 2649 parent_redraw(this); 2650 } 2651 position(int & i,int & j) const2652 void Editeur::position(int & i,int & j) const { 2653 if (editor->buffer()->selected()) 2654 editor->buffer()->selection_position(&i,&j); 2655 else { 2656 i=editor->insert_position(); 2657 j=i; 2658 } 2659 } 2660 value() const2661 std::string Editeur::value() const { 2662 char * ch=editor->buffer()->text(); 2663 string res=ch; 2664 free(ch); 2665 return res; 2666 } 2667 value() const2668 std::string Xcas_Text_Editor::value() const { 2669 char * ch=buffer()->text(); 2670 string res=ch; 2671 free(ch); 2672 return res; 2673 } 2674 insert_replace(const string & s,bool select)2675 void Xcas_Text_Editor::insert_replace(const string & s,bool select){ 2676 if (buffer()->selected()){ 2677 int b,e; 2678 buffer()->selection_position(&b,&e); 2679 buffer()->remove_selection(); 2680 buffer()->insert(b,s.c_str()); 2681 buffer()->select(b,b+s.size()); 2682 } 2683 else { 2684 int b=insert_position(); 2685 buffer()->insert(b,s.c_str()); 2686 buffer()->select(b,b+s.size()); 2687 } 2688 set_gchanged(); 2689 } 2690 mark() const2691 int Xcas_Text_Editor::mark() const { 2692 int b,e; 2693 buffer()->selection_position(&b,&e); 2694 return e; 2695 } 2696 match()2697 void Xcas_Text_Editor::match(){ 2698 static bool recursive=false; 2699 if (buffer()->selected()) 2700 return; 2701 int pos=insert_position(); 2702 int lastkey=Fl::event_key(); 2703 if (lastkey!='(' && lastkey!='[' && lastkey!='{' && lastkey!='}' && lastkey!=']' && lastkey!=')' && lastkey!='0' && lastkey!='9' && lastkey!='\'' && lastkey != '=' && lastkey !=FL_Left && lastkey !=FL_Right) 2704 return; 2705 if (recursive) 2706 return; 2707 recursive=true; 2708 // check if cursor is on [, (, ), ] 2709 int p0=pos; 2710 char * ch=buffer()->text(); 2711 string c(ch); 2712 free(ch); 2713 int pmax=c.size(); 2714 bool closing=false,opening=false; 2715 if (pos<pmax) 2716 opening= c[pos]=='(' || c[pos]=='[' || c[pos]=='{'; 2717 if (!opening && pos){ 2718 closing = c[pos-1]==')' || c[pos-1]==']' || c[pos-1]=='}'; 2719 if (closing) 2720 --p0; 2721 } 2722 if (opening || closing){ 2723 bool ok=giac::matchpos(c,p0); 2724 if (!ok){ 2725 if (closing) 2726 p0=pos-1; 2727 else 2728 p0=pos+1; 2729 } 2730 else { 2731 if (opening && pos<pmax) 2732 p0=p0+1; 2733 } 2734 Fl::flush(); 2735 usleep(100000); 2736 if (true || !Fl::get_key(lastkey)){ 2737 Fl::check(); 2738 buffer()->select(pos,p0); 2739 unsigned s=selection_color(); 2740 if (ok){ 2741 if (opening) 2742 selection_color(FL_GREEN); 2743 else 2744 selection_color(fl_color_cube(0,FL_NUM_GREEN-1,2)); 2745 } 2746 else 2747 selection_color(FL_RED); 2748 damage(damage() | FL_DAMAGE_ALL); 2749 redraw(); 2750 Fl::flush(); 2751 usleep(70000); 2752 if (!Fl::ready()){ 2753 for (int i=0;i<giac::PARENTHESIS_NWAIT;++i){ 2754 usleep(50000); 2755 if (Fl::ready()) 2756 break; 2757 } 2758 } 2759 selection_color(s); 2760 buffer()->select(pos,pos); 2761 damage(damage() | FL_DAMAGE_ALL); 2762 redraw(); 2763 Fl::flush(); 2764 } 2765 } 2766 recursive=false; 2767 } 2768 draw()2769 void Xcas_Text_Editor::draw(){ 2770 int clip_x,clip_y,clip_w,clip_h; 2771 fl_clip_box(x(),y(),w(),h(),clip_x,clip_y,clip_w,clip_h); 2772 fl_push_clip(clip_x,clip_y,clip_w,clip_h); 2773 Fl_Text_Editor::draw(); 2774 fl_pop_clip(); 2775 } 2776 2777 const string motscleftab[] = { 2778 "{", 2779 "Else", 2780 "ElseIf", 2781 "EndDlog", 2782 "EndFor", 2783 "EndFunc", 2784 "EndIf", 2785 "EndLoop", 2786 "EndPrgm", 2787 "EndTry", 2788 "EndWhile", 2789 "Exit", 2790 "Func", 2791 "Then", 2792 "alors", 2793 "and", 2794 "break", 2795 "by", 2796 "case", 2797 "catch", 2798 "continue", 2799 "de", 2800 "default", 2801 "do", 2802 "downto", 2803 "elif", 2804 "else", 2805 "end", 2806 "end_case", 2807 "end_for", 2808 "end_if", 2809 "end_proc", 2810 "end_while", 2811 "et", 2812 "faire", 2813 "ffaire", 2814 "fi", 2815 "fpour", 2816 "from", 2817 "fsi", 2818 "ftantque", 2819 "jusqu_a", 2820 "jusqua", 2821 "jusque", 2822 "non", 2823 "not", 2824 "od", 2825 "or", 2826 "ou", 2827 "pas", 2828 "sinon", 2829 "step", 2830 "then", 2831 "to", 2832 "until", 2833 "xor" 2834 }; 2835 2836 const std::vector<string> motsclef(motscleftab,motscleftab+sizeof(motscleftab)/sizeof(motscleftab[0])); 2837 2838 // indent current line at position pos, return new current position indent(int pos)2839 int Xcas_Text_Editor::indent(int pos){ 2840 giac::context * contextptr = get_context(this); 2841 bool python=python_compat(contextptr); 2842 int indentunit=2; 2843 if (python) indentunit=4; 2844 int debut_ligne=buffer()->line_start(pos),indent=0; 2845 // Tab pressed -> indent current line 2846 char Lastchar; 2847 if (debut_ligne){ 2848 char * ch_ = buffer()->line_text(pos-1),*ch=ch_; 2849 bool empty_line=true; 2850 int position=buffer()->line_start(debut_ligne-2); 2851 indent = python?0:2; 2852 while (1){ 2853 free(ch_); 2854 ch_ = buffer()->line_text(position); 2855 ch=ch_; 2856 int save_indent=indent; 2857 // Count spaces in ch 2858 for (;*ch;++ch,++indent){ 2859 if ( (python && *ch=='#') || (!python && *ch=='/' && *(ch+1)=='/') ) 2860 break; 2861 if (*ch!=' '){ 2862 empty_line=false; 2863 break; 2864 } 2865 } 2866 if (position<2 || !empty_line) 2867 break; 2868 // line was empty, restore indent and go one line above 2869 indent = save_indent; 2870 position=buffer()->line_start(position-2); 2871 } 2872 if (empty_line) 2873 indent = 0; 2874 else { 2875 while (*ch==' ') 2876 ++ch; 2877 int firstchar=*ch,lastchar = *ch,prevlast=0; 2878 if (!python && lastchar ==';' && !*(ch+1)) 2879 indent -= indentunit; 2880 // Add spaces for each open (, open {, open [, 2881 // remove spaces for ] } ) 2882 for (;*ch;++ch){ 2883 switch (*ch){ 2884 case '(': case '[': case '{': 2885 indent += indentunit; 2886 break; 2887 case ')': case ']': case '}': 2888 indent -=indentunit; 2889 break; 2890 } 2891 if (*ch=='/' && *(ch+1)=='/') 2892 break; 2893 if (*ch!=' '){ 2894 prevlast=lastchar; 2895 lastchar=*ch; 2896 } 2897 } 2898 Lastchar=lastchar; 2899 if (python){ 2900 if (lastchar==':') 2901 indent += indentunit; 2902 } 2903 else { 2904 // Last non space should be { or ; 2905 if ( (lastchar=='{' && firstchar!='}') || (lastchar=='}' && firstchar!='}') || (lastchar==';' && prevlast!='}' ) ) 2906 indent -=indentunit; 2907 } 2908 free(ch_); 2909 } 2910 } 2911 // Now indent line 2912 char * ch_ = buffer()->line_text(pos), *ch=ch_; 2913 int delta=0; 2914 for (;*ch;++ch,--delta){ 2915 if (*ch!=' ') 2916 break; 2917 } 2918 if (*ch=='}') 2919 indent -= indentunit; 2920 string mot; 2921 mot += *ch; 2922 for(char * ch1=ch+1;*ch1;++ch1){ 2923 if (!isalpha(*ch1)) 2924 break; 2925 mot += *ch1; 2926 } 2927 if (Lastchar!='}' && (equalposcomp(motsclef,mot))) 2928 indent -=indentunit; 2929 indent=max(indent,0); 2930 delta += indent; 2931 string s(indent,' '); 2932 s += ch; 2933 free(ch_); 2934 int fin=buffer()->line_end(pos); 2935 buffer()->remove(debut_ligne,fin); 2936 buffer()->insert(debut_ligne,s.c_str()); 2937 insert_position(pos+delta); 2938 redraw(); 2939 return pos+delta; 2940 } 2941 indent()2942 void Xcas_Text_Editor::indent(){ 2943 int pos=0; 2944 for (;pos<buffer()->length();){ 2945 pos=indent(pos); 2946 pos=buffer()->line_end(pos)+1; 2947 } 2948 } 2949 value(const char * s,bool select)2950 void Xcas_Text_Editor::value(const char * s,bool select){ 2951 if (buffer()->length()>0) 2952 buffer()->remove(0,buffer()->length()); 2953 buffer()->insert(0,s); 2954 insert_position(0); 2955 if (select) 2956 buffer()->select(0,strlen(s)); 2957 else 2958 buffer()->select(0,0); 2959 set_gchanged(); 2960 } 2961 position(int b,int e)2962 void Xcas_Text_Editor::position(int b,int e){ 2963 insert_position(b); 2964 buffer()->select(b,e); 2965 } 2966 resize_nl_before(unsigned nl)2967 void Xcas_Text_Editor::resize_nl_before(unsigned nl){ 2968 if (tableur) 2969 return; 2970 /* 2971 Fl_Widget * wid=this; 2972 while (wid){ 2973 if (dynamic_cast<Figure *>(wid)) 2974 break; 2975 wid=wid->parent(); 2976 } 2977 */ 2978 string s = value(); 2979 unsigned i=0,l=s.size(); 2980 for (;i<l;++i){ 2981 if (s[i]=='\n') 2982 ++nl; 2983 } 2984 // increase_size(this,((nl>1 ||wid)?22:9)+nl*(labelsize()+3)-h()); 2985 double fs = 1.05*fl_height(textfont(), textsize()); 2986 int newsize=(nl>1?23:10)+int(nl*fs+.5); 2987 #ifdef WIN32 2988 newsize += 2; 2989 #endif 2990 if (nl==1){ 2991 fl_font(FL_HELVETICA,labelsize()); 2992 double taille=1.4*fl_width(s.c_str()); 2993 // cerr << ch << " " << taille << " " << labelsize() << '\n'; 2994 if (taille>w()) // make enough room for scrollbar 2995 increase_size(this,25+labelsize()-h()); 2996 else 2997 increase_size(this,newsize-h()); 2998 } 2999 else 3000 increase_size(this,newsize-h()); 3001 // check_scrollbarsize(); 3002 show_insert_position(); 3003 } 3004 set_tooltip()3005 void Xcas_Text_Editor::set_tooltip(){ 3006 static string toolt; 3007 History_Pack * hp=get_history_pack(this); 3008 int pos=insert_position(); 3009 int wbeg=buffer()->line_start(pos); 3010 string s(buffer()->text_range(wbeg,pos)); 3011 s=motclef(s); 3012 unsigned k=0; // quick check : is s a number? 3013 for (;k<s.size();++k){ 3014 if (s[k]!='.' && s[k]!='e' && s[k]!='-' && (s[k]<'0' || s[k]>'9') ) 3015 break; 3016 } 3017 if (s.size()>1 && k<s.size()){ 3018 const aide & help=helpon(s,*giac::vector_aide_ptr(),giac::language(hp?hp->contextptr:0),giac::vector_aide_ptr()->size()); 3019 toolt=writehelp(help,giac::language(hp?hp->contextptr:0)); 3020 toolt += '\n'; 3021 const char * ch=gettext("No help"); 3022 if (toolt.size()>20 && toolt.substr(0,strlen(ch))!=ch) 3023 toolt += gettext("Press F1 to copy examples or for interactive help"); 3024 else { 3025 if (s.size()<4){ 3026 tooltip(""); 3027 return; 3028 } 3029 toolt += gettext("Press F1 to open help index at "); 3030 toolt += s; 3031 } 3032 tooltip(toolt.c_str()); 3033 int hh=height(toolt.c_str(),Fl_Tooltip::size()); 3034 Fl_Tooltip::enter_area(this,0,-hh,0,0,toolt.c_str()); 3035 } 3036 else 3037 tooltip(""); 3038 } 3039 g()3040 gen Xcas_Text_Editor::g() { 3041 if (!gchanged) 3042 return _g; 3043 giac::context * contextptr=get_context(this); 3044 _g=giac::gen(value(),contextptr); 3045 clear_gchanged(); 3046 return _g; 3047 } 3048 completion()3049 int Xcas_Text_Editor::completion(){ 3050 Editeur * ed =dynamic_cast<Editeur *>(parent()); 3051 History_Pack * hp=get_history_pack(this); 3052 int pos=insert_position(); 3053 if (pos) 3054 --pos; 3055 #ifdef FL_DEVICE 3056 char car=buffer()->character(pos); 3057 #else 3058 char car=buffer()->char_at(pos); 3059 #endif 3060 if (car=='\n'){ 3061 ++pos; 3062 #ifdef FL_DEVICE 3063 car=buffer()->character(pos); 3064 #else 3065 car=buffer()->char_at(pos); 3066 #endif 3067 } 3068 bool remove1=false; 3069 if (pos && car=='('){ 3070 --pos; 3071 remove1=true; 3072 #ifdef FL_DEVICE 3073 car=buffer()->character(pos); 3074 #else 3075 car=buffer()->char_at(pos); 3076 #endif 3077 } 3078 if (1 || isalphan(car)){ 3079 int wbeg=buffer()->word_start(pos); 3080 int wend=buffer()->word_end(pos); 3081 if (remove1) ++wend; 3082 pos=wend; 3083 char * cha=buffer()->text_range(wbeg,wend); 3084 string s(cha),ans; 3085 free(cha); 3086 int remove; 3087 if (int ii=handle_tab(s,*giac::vector_completions_ptr(),window()->w(),window()->h()/3,remove,ans,/* immediate out not allowed*/false)){ 3088 window()->show(); 3089 Fl::focus(this); 3090 handle(FL_FOCUS); 3091 pos=wend-remove; 3092 buffer()->remove(pos,wend); 3093 if (ii==1){ 3094 buffer()->insert(pos,(ans+"(").c_str()); 3095 insert_position(pos+ans.size()+1); 3096 } 3097 else { 3098 buffer()->insert(pos,ans.c_str()); 3099 insert_position(pos+ans.size()); 3100 } 3101 set_gchanged(); 3102 if (hp) 3103 hp->modified(false); 3104 set_tooltip(); 3105 if (parent()) 3106 parent_redraw(parent()); 3107 } 3108 return 1; 3109 } 3110 return 0; 3111 } 3112 set_g(const gen & g)3113 void Xcas_Text_Editor::set_g(const gen & g){ 3114 const giac::context * contextptr = get_context(this); 3115 value(g.print(contextptr).c_str()); 3116 redraw(); 3117 clear_gchanged(); 3118 _g=g; 3119 } 3120 check_scrollbarsize()3121 void Xcas_Text_Editor::check_scrollbarsize(){ 3122 if (h()<25+labelsize()){ 3123 char * ch=buffer()->text(),*ptr=ch; 3124 if (ch){ 3125 for (;*ptr;++ptr){ 3126 if (*ptr=='\n') 3127 break; 3128 } 3129 if (!*ptr){ 3130 fl_font(FL_HELVETICA,labelsize()); 3131 double taille=1.4*fl_width(ch); 3132 // cerr << ch << " " << taille << " " << labelsize() << '\n'; 3133 if (taille>w()){ // make enough room for scrollbar 3134 increase_size(this,25+labelsize()-h()); 3135 } 3136 } 3137 free(ch); 3138 } 3139 } 3140 } 3141 dedent()3142 void Xcas_Text_Editor::dedent(){ 3143 // delete several characters 3144 int pos=insert_position(); 3145 int debut_ligne=buffer()->line_start(pos),i; 3146 char * ch=buffer()->line_text(debut_ligne); 3147 string s(ch); free(ch); 3148 // skip spaces ahead 3149 int lpos=pos-debut_ligne; 3150 for (;lpos<s.size();++lpos){ 3151 if (s[lpos]!=' ') 3152 break; 3153 } 3154 if (lpos<s.size()){ 3155 insert_position(lpos+debut_ligne); 3156 pos=insert_position(); 3157 } 3158 int curind=pos-debut_ligne; 3159 for (i=0;i<curind;++i){ 3160 if (s[i]!=' ') 3161 break; 3162 } 3163 if (curind && i==curind){ 3164 while (debut_ligne>1){ 3165 // search position in previous line indentations 3166 pos=debut_ligne-1; 3167 debut_ligne=buffer()->line_start(pos); 3168 ch=buffer()->line_text(debut_ligne); 3169 string s(ch); free(ch); 3170 for (i=0;i<curind;++i){ 3171 if (s[i]!=' ') 3172 break; 3173 } 3174 if (i<curind){ 3175 // std::cerr << "fixme del" << '\n'; 3176 for (;curind>i;--curind) 3177 Fl_Text_Editor::kf_backspace(0,this); 3178 break; 3179 } 3180 } 3181 } 3182 } 3183 handle(int event)3184 int Xcas_Text_Editor::handle(int event){ 3185 if (event==FL_UNFOCUS) 3186 return 1; 3187 if (event==FL_FOCUS || event==FL_PUSH) 3188 Xcas_input_focus=this; 3189 if (event==FL_PUSH && tableur) 3190 tableur->editing=true; 3191 Editeur * ed =dynamic_cast<Editeur *>(parent()); 3192 if (event==FL_MOUSEWHEEL){ 3193 if (!Fl::event_inside(this)) 3194 return 0; 3195 int n=buffer()->count_lines(0,buffer()->length())+1; 3196 if (n*(labelsize()+1)<=h()+10) 3197 return 0; 3198 int l=buffer()->count_lines(0,insert_position())+1; 3199 if (Fl::e_dy<0){ 3200 for (;l>n-h()/(2*labelsize());--l) 3201 move_up(); 3202 if (l<=1) 3203 return 0; 3204 move_up(); 3205 } 3206 else { 3207 for (;l<h()/(2*labelsize());++l) 3208 move_down(); 3209 if (l>=n) 3210 return 0; 3211 move_down(); 3212 } 3213 show_cursor(); 3214 show_insert_position(); 3215 } 3216 if (ed){ 3217 if (ed->linenumber){ 3218 int n=buffer()->count_lines(0,insert_position())+1; 3219 ed->linenumber->value(n); 3220 } 3221 } 3222 if (event==FL_MOUSEWHEEL) 3223 return 1;// Fl_Text_Editor::handle(event); 3224 giac::context * contextptr = get_context(this); 3225 History_Pack * hp=get_history_pack(this); 3226 if (h()<25+labelsize() && !ed && !tableur) 3227 check_scrollbarsize(); 3228 if (event==FL_KEYBOARD){ 3229 Xcas_input_focus=this; 3230 // FIXME: add 2 ([]) and 12 ({}) 3231 if (Fl::event_text() && Fl::event_text()[0]==6){ 3232 cb_Editeur_Search(this,0); 3233 return 1; 3234 } 3235 if (Fl::event_text() && Fl::event_text()[0]==14){ 3236 cb_Editeur_Next(this,0); 3237 return 1; 3238 } 3239 if (!tableur && Fl::event_key()==FL_F+5){ 3240 if (h()<window()->h()){ 3241 increase_size(this,100); 3242 redraw(); 3243 return 1; 3244 } 3245 } 3246 if (!tableur && Fl::event_key()==FL_F+6){ 3247 if (h()>200) 3248 increase_size(this,-100); 3249 return 1; 3250 } 3251 int change_focus=0; 3252 if (!ed && Fl::event_text() && (Fl::event_text()[0]=='\r') && !Fl::event_state(FL_SHIFT | FL_CTRL | FL_ALT) ){ 3253 if (tableur){ 3254 do_callback(); 3255 return 1; 3256 } 3257 else { 3258 if (value().empty()) 3259 change_focus=1; 3260 else { 3261 history.push_back(value()); 3262 count=history.size(); 3263 int pos=-1; 3264 History_Pack * hp=get_history_pack(this,pos); 3265 if (hp) 3266 hp->update_pos=pos; 3267 History_Pack_cb_eval(this,0); 3268 return 1; 3269 } 3270 } 3271 } 3272 if (Fl::event_key()==FL_F+1 || (!ed && Fl::event_text() && (Fl::event_text()[0]==9)) ){ 3273 if (completion()) 3274 return 1; 3275 } 3276 if (Fl::event_text() && (Fl::event_text()[0]==9 || Fl::event_key()==FL_Escape)){ 3277 if (tableur){ 3278 if (tableur->editing){ 3279 tableur->editing=false; 3280 Fl::focus(tableur); 3281 } 3282 else { 3283 Fl::selection(*this,value().c_str(),value().size()); 3284 // Fl::selection(*this,value(),strlen(value())); 3285 value(""); 3286 } 3287 set_gchanged(); 3288 if (hp) 3289 hp->modified(false); 3290 return 1; 3291 } 3292 else { 3293 int pos=insert_position(); 3294 indent(pos); 3295 return 1; 3296 } 3297 } // end if (...) tabulation test 3298 int key=Fl::event_key(); 3299 if (!tableur && buffer()->line_start(insert_position())==0 && 3300 ((key==FL_Up && !Fl::event_state(FL_SHIFT |FL_CTRL | FL_ALT)) 3301 || key==FL_Page_Up) 3302 ) 3303 change_focus=-1; 3304 if (!tableur && buffer()->line_end(insert_position())==buffer()->length() && 3305 ( (key==FL_Down && !Fl::event_state(FL_SHIFT |FL_CTRL | FL_ALT)) 3306 || key==FL_Page_Down) 3307 ) 3308 change_focus=1; 3309 if (change_focus && hp){ 3310 int pos=hp->focus(this); 3311 if (pos+change_focus>=0 && pos+change_focus<hp->children()){ 3312 hp->focus(pos+change_focus,true); 3313 return 1; 3314 } 3315 } 3316 } // end if event==FL_KEYBOARD 3317 if (event==FL_KEYBOARD && !ed && !tableur){ 3318 if (Fl::event_text() && (Fl::event_text()[0]=='\n' || Fl::event_text()[0]=='\r')){ 3319 resize_nl_before(2); 3320 } 3321 } 3322 if (event==FL_KEYBOARD && !ed && Fl::event_state(FL_CTRL | FL_ALT) && (Fl::event_key()==FL_Up || Fl::event_key()==FL_Down)){ 3323 // not handled by the input, use history 3324 int s=history.size(); 3325 Fl::focus(this); 3326 int start, end; 3327 if (count==s && buffer()->selection_position(&start,&end) && start>=0 && end>start){ 3328 char * ch=buffer()->text_range(start,end); 3329 string S(ch); 3330 free(ch); 3331 if (history.empty() || S!=history.back()){ 3332 history.push_back(S); 3333 ++s; 3334 } 3335 } 3336 if (Fl::event_key()==FL_Up){ 3337 --count; 3338 if (count<0) 3339 count=0; 3340 } 3341 else { 3342 ++count; 3343 if (count>=s) 3344 count=max(0,s-1); 3345 } 3346 if (count<s){ 3347 if (buffer()->selection_position(&start,&end) && start>=0 && end>start) 3348 buffer()->remove(start,end); 3349 else 3350 start=insert_position(); 3351 buffer()->insert(start,history[count].c_str()); 3352 end = start + history[count].size(); 3353 buffer()->select(start,end); 3354 set_gchanged(); 3355 if (hp) 3356 hp->modified(false); 3357 } 3358 return 1; 3359 } 3360 char before_ch=buffer()->text()[giacmax(insert_position()-1,0)]; 3361 int res=Fl_Text_Editor::handle(event); 3362 if (!ed && event==FL_PASTE) 3363 resize_nl_before(1); 3364 if (event==FL_KEYBOARD){ 3365 #if 1 //ndef __APPLE__ 3366 if (Fl::event_text() && Fl::event_text()[0]>32){ 3367 count=history.size(); 3368 set_gchanged(); 3369 if (hp) 3370 hp->modified(false); 3371 if (Fl::event_text()[0]==')') 3372 tooltip(""); 3373 else 3374 set_tooltip(); 3375 } 3376 #endif 3377 if (!ed && !tableur && Fl::event_key()==FL_BackSpace){ 3378 resize_nl_before(1); 3379 if (hp) 3380 hp->modified(true); 3381 } 3382 if (!tableur && Fl::event_key()==FL_BackSpace && python_compat(contextptr) && !isalnum(before_ch)){ 3383 dedent(); 3384 } 3385 if (tableur && tableur->editing && Fl::event_key()==FL_BackSpace && value().empty()){ 3386 tableur->editing=false; 3387 Fl::focus(tableur); 3388 return 1; 3389 } 3390 if (ed && !tableur && Fl::event_text() && (Fl::event_text()[0]=='\n' || Fl::event_text()[0]=='\r')){ 3391 indent(insert_position()); 3392 } 3393 else 3394 match(); 3395 } 3396 return res; 3397 } 3398 3399 #ifndef NO_NAMESPACE_XCAS 3400 } // namespace giac 3401 #endif // ndef NO_NAMESPACE_XCAS 3402 3403 #endif // HAVE_LIBFLTK 3404