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