1 // -*- mode:C++ ; compile-command: "g++ -I.. -g -c History.cc" -*- 2 #ifndef _HISTORY_H 3 #define _HISTORY_H 4 #ifdef HAVE_CONFIG_H 5 #include "config.h" 6 #endif 7 #ifndef IN_GIAC 8 #include <giac/first.h> 9 #else 10 #include "first.h" 11 #endif 12 #ifdef HAVE_LIBFLTK 13 #include <FL/Fl_Pack.H> 14 #include <FL/Fl_Button.H> 15 #include <FL/Fl_Box.H> 16 #include <FL/Fl_Scroll.H> 17 #include <FL/Fl_Menu_Bar.H> 18 #include <FL/Fl_Multiline_Output.H> 19 #include <FL/Fl_Multiline_Input.H> 20 #include <FL/Fl_Menu_Button.H> 21 #include <FL/Fl_Tabs.H> 22 #endif 23 #include <string> 24 #ifndef IN_GIAC 25 #include <giac/giac.h> 26 #else 27 #include "giacPCH.h" 28 #include "giac.h" 29 #endif 30 31 #ifdef HAVE_LIBFLTK 32 char *file_chooser(const char *message,const char *pat,const char *fname,int relative=0); 33 char *load_file_chooser(const char *message,const char *pat,const char *fname,int relative,bool save); 34 #endif 35 36 #ifndef NO_NAMESPACE_XCAS 37 namespace xcas { 38 #endif // ndef NO_NAMESPACE_XCAS 39 40 #ifdef HAVE_LIBFLTK 41 void add_recent_filename(const std::string & s,bool writerecent); 42 void read_recent_filenames(Fl_Menu_ * menu); // read xcas_recent and init recent_filenames_menu 43 extern void (*Xcas_load_filename)(const char * filename,bool modified); // set in hist.fl 44 45 #define FL_VERT_PALE 167 46 #define FL_ROUGE_PALE 211 47 48 int confirm_close(const std::string & message); 49 std::string unix_path(const std::string & winpath); 50 extern std::string autosave_folder; 51 52 extern Fl_Color Xcas_comment_color,Xcas_comment_background_color,Xcas_input_color,Xcas_input_background_color,Xcas_log_color,Xcas_log_background_color,Xcas_equation_color,Xcas_equation_background_color,Xcas_equation_input_color,Xcas_equation_input_background_color,Xcas_editor_color,Xcas_editor_background_color,Xcas_background_color; 53 54 extern void (* Keyboard_Switch )(unsigned); 55 56 void set_colors(Fl_Widget *,bool do_redraw=true); 57 void set_cursor(Fl_Widget *t, Fl_Cursor c) ; 58 59 // redraw parent widget if exists, otherwise redraw w 60 void parent_redraw(Fl_Widget * w); 61 // redraw all parent widgets in the hierarchy 62 void parents_redraw(Fl_Widget * w); 63 // Return parent or parent of fl_scroll if the parent is a fl_scroll 64 Fl_Group * parent_skip_scroll(const Fl_Widget * g); 65 66 // Output widget stream borrowed from Dietmar K�hl 67 // http://www.inf.uni-konstanz.de/~kuehl/c++/iostream/ 68 class widgetbuf: public std::streambuf{ 69 private: 70 Fl_Output * text; 71 72 void put_buffer(void); 73 void put_char(int); 74 75 protected: 76 int overflow(int); 77 int sync(); 78 79 public: 80 widgetbuf(Fl_Output *, int = 0); 81 ~widgetbuf(); 82 }; 83 84 #ifdef WITH_MYOSTREAM 85 class owstream: public giac::my_ostream 86 #else 87 class owstream: public my_ostream 88 #endif 89 { 90 public: 91 Fl_Output * output; 92 giac::context * contextptr; 93 owstream(Fl_Output *, giac::context * contextpt , int = 0); 94 virtual ~owstream(); 95 void resize(); 96 }; 97 98 class Log_Output : public Fl_Multiline_Output { 99 public: Fl_Multiline_Output(X,Y,W,H,ch)100 Log_Output(int X,int Y,int W,int H,char * ch=0):Fl_Multiline_Output(X,Y,W,H,ch){ textcolor(Xcas_log_color);}; 101 virtual int handle(int event); 102 }; 103 104 Log_Output * find_log_output(Fl_Group * g); 105 void output_resize(Fl_Input_ * output); 106 void output_resize_parent(Fl_Input_ * output,bool resize_hp=true); 107 // End output widget stream 108 giac::gen warn_equal(const giac::gen & g,const giac::context * contextptr); 109 110 class Clip_Scroll:public Fl_Scroll { 111 public: Fl_Scroll(X,Y,W,H,l)112 Clip_Scroll(int X,int Y,int W,int H,const char * l=0):Fl_Scroll(X,Y,W,H,l) {}; 113 virtual void draw(); 114 }; 115 116 void cb_Paste(Fl_Widget* m , void*); 117 118 extern Fl_Output * Parse_error_output ; // for syntax error msgs 119 extern bool fl_handle_lock; // True when Fl::handle is busy 120 void fl_handle(Fl_Widget * w); // Send event after fl_handle_lock check 121 void xdvi(const std::string & name); // latex preview 122 void dvips(const std::string & name); // latex print 123 124 // a callback if the question widget is a multiline input 125 void History_Pack_cb_eval(Fl_Widget * q , void*); 126 127 class History_Fold; 128 class No_Focus_Button; 129 130 // Like a horizontal Fl_Pack, except that it handles dragging the space 131 // and draws widgets number 132 class History_Pack:public Fl_Group { 133 int _my_push,_widget_i,_widget_h; // internally used by handle 134 bool _selecting,_pushed,_moving,_saving; 135 // Used for undo/redo mechanism: when a widget is created 136 // inside a History_Pack the indexed_string has index -1 137 // just before a widget is deleted, the index_string is created 138 // with widget_sprint and index is set to the undo position 139 std::multimap<Fl_Widget *,giac::indexed_string> widget_history_map; 140 public: 141 int undo_position; 142 std::vector< std::vector<Fl_Widget *> > undo_history; 143 void add_history_map(Fl_Widget * g,int undo_position); 144 Fl_Widget * restore_history_map(Fl_Widget * g,int undo_position); 145 bool _modified,_resize_above; 146 // NB resize_above is also used for next in evaluation 147 // if true then the next entry in above history pack is evaled 148 int _spacing,_printlevel_w,_sel_begin,_sel_end; 149 int pretty_output; 150 int next_delay; 151 // set to true if you want to reeval the remaining items of the pack 152 bool eval_below,doing_eval; 153 bool eval_below_once,eval_next; 154 giac::gen queue_val; // value to be evaled at queue_pos 155 int queue_pos,update_pos; // position in queue, position of 1st eval 156 giac::context * contextptr; 157 // new_question() is provided by the class user 158 // it must return a question widget, it is called every time add_entry 159 // is called. 160 Fl_Widget * (*new_question) (int W,int H); 161 // User defined callback for selection, called when mouse select occurs 162 const char * (*_select)(const History_Pack * pack,int sel_begin,int sel_end); 163 // User defined callback for insertion, called by paste or by insert 164 // should parse widgets and insert them before the int 165 // If before_position==-1, insert at the end 166 int (*_insert)(History_Pack * pack,const char * chaine,int length,int before_position); 167 // Current harddisk filename (FIXME use url syntax) 168 std::string * url; 169 // This function is an "eval" function 170 // it will return an answer widget, given a question widget 171 // For example in a CAS, it would get the value of the arg widget 172 // eval it and return it in an appropriate form (text or eqw...) 173 Fl_Widget * (*eval) (Fl_Widget *); 174 // ******* 175 // Methods 176 // ******* 177 History_Pack(int X,int Y,int W,int H,const char*l=0); 178 virtual FL_EXPORT int handle(int); 179 virtual FL_EXPORT void draw(); 180 void modified(bool do_backup); // backup + in_modified 181 void in_modified(); // no save to undo 182 void backup(); 183 void restore(int dpos); 184 void clear_modified(); 185 void add_entry(int n,Fl_Widget * question); 186 void add_entry(int n,Fl_Group * group); 187 bool add_entry(int n); 188 bool save(const char * ch=0); // use *url as filename 189 bool save_all(); // save all History_Fold inside this history_pack 190 bool save_as(const char * ch); // ask for a filename 191 bool save_as(const char * filename,const char * ch,bool autosave_rm,bool warn_user,bool file_save_context) ; 192 // bool save_as(const char * filename,const char * ch,bool autosave_rm=true,bool warn_user=true,bool save_context=true) ; 193 bool close(const char * ch); 194 bool insert_before(int before_position,bool newurl=false,int mws=0); 195 // ask for a filename (xws or mws extension, mws does a xws translation) 196 bool insert_url(const char * url,int before_position); 197 void new_url(const char * newfile); 198 void fold_selection(); 199 void flatten(); 200 bool resize(); 201 bool resize(int maxh); 202 bool resize(int minh,int maxh); 203 giac::gen parse(int n); // return the gen value of the n-th entry 204 std::string value(int n) const; // return the string value of the n-th entry 205 void set_gen_value(int n,const giac::gen & g,bool exec=true); // set n-th entry value 206 Fl_Group * widget_group(int n); // group corresponding to position n 207 void set_value(int n,const std::string & s,bool exec=true); 208 bool remove_entry(int n,bool check=true); // does not update, call resize() and update() 209 bool remove_selected_levels(bool check_in_history_fold); 210 void update(int n=0); // if eval_below is true, recompute pack 211 void next(int hp_pos=0); // eval next child if eval_below is true 212 int set_sel_begin(const Fl_Widget * w); 213 int focus(const Fl_Widget * w) const; // find focus position 214 bool focus(int pos,bool dofocus=false); // set focus on input no pos 215 void set_scroller(Fl_Group * gr); // make gr visible by scrolling history pack 216 }; 217 218 // Exported so that we can use it inside Geometry Edit menu 219 void cb_Rm_Answers(Fl_Widget* m , void*) ; 220 void cb_Delete(Fl_Widget* m , void*) ; 221 void History_cb_Save(Fl_Widget* m , void*) ; 222 void History_cb_Save_as(Fl_Widget* m , void*) ; 223 void History_cb_Save_as_xcas_casio(Fl_Widget* m , void*) ; 224 void History_cb_Save_as_xcas_text(Fl_Widget* m , void*) ; 225 void History_cb_Save_as_xcaspy_text(Fl_Widget* m , void*) ; 226 void History_cb_Save_as_maple_text(Fl_Widget* m , void*) ; 227 void History_cb_Save_as_mupad_text(Fl_Widget* m , void*) ; 228 void History_cb_Save_as_ti_text(Fl_Widget* m , void*) ; 229 void History_cb_Load(Fl_Widget* m , void*) ; 230 void History_cb_Insert(Fl_Widget* m , void*) ; 231 void History_cb_Insert_Figure(Fl_Widget* m , void*) ; 232 void History_cb_Insert_Tableur(Fl_Widget* m , void*) ; 233 void History_cb_Insert_Program(Fl_Widget* m , void*) ; 234 void History_cb_Kill(Fl_Widget* m , void*) ; 235 void History_cb_Preview(Fl_Widget* m , void*) ; 236 void History_cb_Print(Fl_Widget* m , void*) ; 237 void History_cb_Preview_selected(Fl_Widget* m , void*) ; 238 void History_cb_LaTeX_Preview(Fl_Widget* m , void*) ; 239 void History_cb_LaTeX_Print(Fl_Widget* m , void*) ; 240 void History_cb_LaTeX_Preview_sel(Fl_Widget* m , void*) ; 241 void History_cb_LaTeX_Print_sel(Fl_Widget* m , void*) ; 242 void cb_New_Input(Fl_Widget* m , void*) ; 243 void History_cb_New_Comment_Input(Fl_Widget* m , void*) ; 244 void History_cb_New_Tableur(Fl_Widget* m , void*) ; 245 void History_cb_New_Figure(Fl_Widget* m , void*) ; 246 void History_cb_New_Figure3d(Fl_Widget* m , void*) ; 247 void History_cb_New_Figurex(Fl_Widget* m , void*) ; 248 void History_cb_New_Figure3dx(Fl_Widget* m , void*) ; 249 void History_cb_New_Logo(Fl_Widget* m , void*) ; 250 void History_cb_New_Equation(Fl_Widget* m , void*) ; 251 void History_cb_New_Xcas_Text_Editor(Fl_Widget* m , void*) ; 252 void History_cb_New_Program(Fl_Widget* m , void*) ; 253 void History_cb_New_HF(Fl_Widget* m , void*) ; 254 void History_cb_Run_Worksheet(Fl_Widget* m , void*) ; 255 void History_cb_Run_Below(Fl_Widget* m , void*) ; 256 void History_cb_Newline(Fl_Widget* m , void*) ; 257 void History_cb_Fold(Fl_Widget* m , void*) ; 258 void History_cb_Merge(Fl_Widget* m , void*) ; 259 void History_cb_Flatten(Fl_Widget* m , void*) ; 260 void History_cb_help_index(Fl_Widget * wid,void *); 261 void History_cb_help_button(Fl_Widget* b , void*); 262 void History_cb_Redo(Fl_Widget* m , void*) ; 263 void History_cb_Undo(Fl_Widget* m , void*) ; 264 265 // if w is an Fl_Input or Equation, put it's value in g 266 int parse(Fl_Widget * w,giac::gen & g); 267 bool set_gen_value(Fl_Widget * w,const giac::gen & g); 268 bool set_value(Fl_Widget * w,const std::string & s,bool exec); 269 270 // Get surrounding History_Pack if it exists 271 History_Pack * get_history_pack(const Fl_Widget * w); 272 giac::context * get_context(const Fl_Widget * w); 273 void set_context(Fl_Widget * w,giac::context * contextptr); 274 History_Pack * get_history_pack(const Fl_Widget * w,int & pos); 275 History_Fold * get_history_fold(const Fl_Widget * wid); 276 277 // History is a class for generic history support like in many 278 // scientific softwares (e.g. CAS or matlab-like,...) 279 // It shows a scrollable pack made of a collection of group of widgets 280 // (which are stacked one over the next one) 281 // Each group first widget is a question 282 // When pressing ENTER in a question widget 283 // the following widget will be replaced by new_answer(question) 284 // Each group widget is separated from the next one and the separation 285 // may be dragged 286 // If it is dragged to the bottom, then the group widget will be enlarged 287 // and subsequent widgets will be repositionned 288 // If it is dragged to the top, the group widget will be smaller 289 class History_Fold : public Fl_Group { 290 public: 291 // members 292 bool _folded,_folding; 293 int _horig,_hsorig; // save size of History (and Scroll above) when folding 294 int _bordersize; // size for the history number 295 std::string autosave_filename; 296 char * mode; 297 Fl_Scroll * scroll; 298 History_Pack * pack; 299 Fl_Input * input; 300 Fl_Group * group; 301 Fl_Button * fold_button, * save_button, * close_button,* current_status; 302 No_Focus_Button * help_button,*keyboard_button,*stop_button,*bnd_button,*msg_button; 303 Fl_Menu_Button * mb; // mb=0 if foldable 304 int scroll_position; 305 int update_status_count; 306 // Methods 307 308 History_Fold(int X,int Y,int W,int H,int showmenu=0,const char*l=0); 309 void autosave_rm(); // delete autosave file 310 bool add_entry(int n); // insert a new group at position n (-1=at end) 311 void add_entry(int n,Fl_Widget * question); 312 bool remove_entry(int n); // remove a group at position n 313 void resize(int,int,int,int); // resizes also pack horizontally 314 virtual FL_EXPORT int handle(int); 315 virtual FL_EXPORT void draw(); 316 void fold(); 317 void unfold(); folded()318 bool folded(){ return _folded; } 319 bool reeval(int n); // reeval all question widgets starting at position n 320 void resize_parent(int H); 321 bool autosave(bool warn_user); 322 bool close(); 323 void clear_modified(); 324 void eval(); 325 void update_status(); 326 }; 327 328 class Xcas_Tabs:public Fl_Tabs { 329 public: 330 bool up; Fl_Tabs(X,Y,W,H,l)331 Xcas_Tabs(int X,int Y,int W,int H,const char*l=0):Fl_Tabs(X,Y,W,H,l),up(true) {}; 332 virtual void resize(int X,int Y,int W,int H); 333 }; 334 335 class HScroll:public Fl_Scroll { 336 public: 337 bool resizechildren; Fl_Scroll(X,Y,W,H,l)338 HScroll(int X,int Y,int W,int H,const char*l=0):Fl_Scroll(X,Y,W,H,l),resizechildren(false) {}; 339 virtual void resize(int X,int Y,int W,int H); 340 virtual void draw(); 341 void resize(); 342 // if HScroll contains a History_Pack, 343 // resize all its childrens to the same size 344 }; 345 346 class DispG_Window:public Fl_Window { 347 public: Fl_Window(x,y,w,h,l)348 DispG_Window(int x,int y,int w,int h,const char * l=0):Fl_Window(x,y,w,h,l){} Fl_Window(x,y,l)349 DispG_Window(int x,int y,const char * l=0):Fl_Window(x,y,l){} 350 virtual int handle(int); 351 virtual FL_EXPORT void draw(); 352 }; 353 354 // new_question widget creator 355 Fl_Widget * new_question_multiline_input(int W,int H); 356 Fl_Widget * new_question_equation(int W,int H); 357 Fl_Widget * new_comment_input(int W,int H); 358 Fl_Widget * new_question_editor(int W,int H); 359 360 Fl_Widget * new_program(int W,int H,const History_Pack * pack); 361 Fl_Widget * new_text_input(int W,int H); 362 Fl_Widget * new_tableur(int W,int H,const History_Pack * pack); 363 Fl_Group * new_figure(int W,int H,const History_Pack * pack,bool dim3=false,bool approx=true); 364 Fl_Group * new_logo(int W,int H,const History_Pack * pack); 365 366 void Comment_cb_eval(Fl_Multiline_Input * q , void*); 367 368 #endif // HAVE_LIBFLTK 369 370 #ifndef NO_NAMESPACE_XCAS 371 } // namespace xcas 372 #endif // ndef NO_NAMESPACE_XCAS 373 374 #endif // _HISTORY_H 375