1 /* main.cpp is part of UDAV
2 * Copyright (C) 2007-2014 Alexey Balakin <mathgl.abalakin@gmail.ru>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public License
6 * as published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17 #include <ctype.h>
18 #include <errno.h>
19 #include <locale.h>
20 #include <getopt.h>
21 #include "mgllab.h"
22 #include <FL/Fl_Spinner.H>
23 #include <FL/Fl_Output.H>
24 #include <FL/Fl_Select_Browser.H>
25 #include <FL/Fl_Printer.H>
26 //-----------------------------------------------------------------------------
27 #ifndef MGL_DOC_DIR
28 #ifdef WIN32
29 #define MGL_DOC_DIR ""
30 #else
31 #define MGL_DOC_DIR "/usr/local/share/doc/mathgl/"
32 #endif
33 #endif
34 //-----------------------------------------------------------------------------
35 //int num_windows = 0, auto_exec=1, plastic_scheme=1, internal_font=0;
36 int num_windows = 0;
37 int auto_exec;
38 int exec_save;
39 int highlight;
40 int mouse_zoom;
41 int use_thr;
42 int complete_word;
43 int wndW=930, wndH=510, txtW=300;
44 std::string docdir;
45 std::string helpname;
46 std::string fontname;
47 int lang;
48 int scheme;
49 int dark;
50 std::string lastfiles[5];
51 Fl_Preferences pref(Fl_Preferences::USER,"abalakin","mgllab");
52 //-----------------------------------------------------------------------------
53 #define NUM_LOCALE 4
54 const char *sch[4]={"base","gtk+","plastic","gleam"};
55 const char *loc[]={"en_EN.UTF8", "ru_RU.utf8", "ru_RU.cp1251", "es_ES.utf8", ""};
56 const char *hlp[]={"mgl_en.html#","mgl_ru.html#", "mgl_ru.html#", "mgl_en.html#", ""};
set_scheme_lang(int s,int l)57 void set_scheme_lang(int s, int l)
58 {
59 if(s<0 || s>3) s=1;
60 if(l<0 || l>NUM_LOCALE-1) l=1;
61 mgl_textdomain(NULL,loc[l]);
62 Fl::scheme(sch[s]);
63 scheme = s; lang = l;
64 #ifdef WIN32
65 char sep = '\\';
66 #else
67 char sep = '/';
68 #endif
69 helpname = docdir+sep+hlp[l];
70 }
71 //-----------------------------------------------------------------------------
save_pref()72 void save_pref()
73 {
74 pref.set("locale",lang);
75 pref.set("scheme",scheme);
76 pref.set("help_dir",docdir.c_str());
77 pref.set("auto_exec",auto_exec);
78 pref.set("exec_save",exec_save);
79 pref.set("highlight",highlight);
80 pref.set("mouse_zoom",mouse_zoom);
81 pref.set("use_thr", use_thr);
82 pref.set("font_kind",font_kind);
83 pref.set("font_size",font_size);
84 pref.set("complete_word",complete_word);
85 pref.set("font_name",fontname.c_str());
86 pref.set("fname1",lastfiles[0].c_str());
87 pref.set("fname2",lastfiles[1].c_str());
88 pref.set("fname3",lastfiles[2].c_str());
89 pref.set("fname4",lastfiles[3].c_str());
90 pref.set("fname5",lastfiles[4].c_str());
91
92 pref.set("wnd_width", wndW);
93 pref.set("wnd_height",wndH);
94 pref.set("txt_width", txtW);
95 pref.set("dark",dark);
96 }
97 //-----------------------------------------------------------------------------
load_pref(ScriptWindow * w)98 void load_pref(ScriptWindow *w)
99 {
100 static char *s=0;
101 pref.get("locale",lang,1);
102 pref.get("scheme",scheme,2);
103 pref.get("help_dir",s,MGL_DOC_DIR);
104 if(s) { docdir=s; free(s); }
105 pref.get("auto_exec",auto_exec,1);
106 pref.get("exec_save",exec_save,1);
107 pref.get("highlight",highlight,1);
108 pref.get("mouse_zoom",mouse_zoom,0);
109 pref.get("use_thr",use_thr,1);
110 pref.get("complete_word",complete_word,1);
111 pref.get("font_kind",font_kind,1);
112 pref.get("font_size",font_size,14);
113 pref.get("dark", dark,0);
114 set_style(font_kind, font_size,dark);
115 pref.get("font_name",s,"");
116 if(s) { fontname=s; free(s); }
117
118 pref.get("wnd_width", wndW,930);
119 pref.get("wnd_height",wndH,510);
120 pref.get("txt_width", txtW,300);
121
122 pref.get("fname1",s,""); if(s) { lastfiles[0]=s; free(s); }
123 pref.get("fname2",s,""); if(s) { lastfiles[1]=s; free(s); }
124 pref.get("fname3",s,""); if(s) { lastfiles[2]=s; free(s); }
125 pref.get("fname4",s,""); if(s) { lastfiles[3]=s; free(s); }
126 pref.get("fname5",s,""); if(s) { lastfiles[4]=s; free(s); }
127 set_scheme_lang(scheme,lang); // NOTE: must be after setting docdir
128 if(w && w->graph)
129 {
130 w->graph->FMGL->use_pthr = use_thr;
131 mgl_load_font(w->graph->get_graph(),fontname.c_str(),NULL);
132 example_cb(NULL, w);
133 w->graph->parent()->show();
134 }
135 }
136 //-----------------------------------------------------------------------------
set_title(Fl_Window * w)137 void set_title(Fl_Window* w)
138 {
139 static std::string title;
140 if (filename.empty()) title=_("Untitled");
141 else
142 {
143 size_t sep = filename.find_last_of('/');
144 #ifdef WIN32
145 if(sep==std::string::npos)
146 sep = filename.find_last_of('\\');
147 #endif
148 if(sep!=std::string::npos) title = filename.substr(sep+1);
149 else title = filename;
150 }
151 if(changed) title += " *";
152 title = title + " - mgllab";
153 w->label(title.c_str());
154 }
155 //-----------------------------------------------------------------------------
close_dlg_cb(Fl_Widget *,void * v)156 void close_dlg_cb(Fl_Widget *, void *v) { ((Fl_Window *)v)->hide(); }
157 //-----------------------------------------------------------------------------
158 //-----------------------------------------------------------------------------
new_cb(Fl_Widget *,void *)159 void new_cb(Fl_Widget*, void*)
160 {
161 if (!check_save()) return;
162 filename[0] = '\0';
163 textbuf->select(0, textbuf->length());
164 textbuf->remove_selection();
165 changed = 0;
166 textbuf->call_modify_callbacks();
167 }
168 //-----------------------------------------------------------------------------
open_cb(Fl_Widget *,void * v)169 void open_cb(Fl_Widget*, void *v)
170 {
171 if (!check_save()) return;
172 const char *newfile = mgl_file_chooser(_("Open File?"),
173 _("MGL files \t*.mgl\nDAT files \t*.{dat,csv}"));
174 if(newfile != NULL)
175 {
176 ScriptWindow* e = (ScriptWindow*)v;
177 load_file(newfile, -1,e);
178 if(auto_exec) e->graph->update();
179 }
180 }
181 //-----------------------------------------------------------------------------
close_cb(Fl_Widget *,void * v)182 void close_cb(Fl_Widget*, void* v)
183 {
184 Fl_Window* w = (Fl_Window*)v;
185 if (num_windows == 1 && !check_save()) return;
186
187 w->hide();
188 textbuf->remove_modify_callback(changed_cb, w);
189 ScriptWindow *wnd = dynamic_cast<ScriptWindow*>(w);
190 if(wnd)
191 {
192 wndW = wnd->w();
193 wndH = wnd->h();
194 txtW = wnd->editor->w();
195 save_pref();
196 }
197 delete w;
198 num_windows--;
199 if (!num_windows) exit(0);
200 }
201 //-----------------------------------------------------------------------------
quit_cb(Fl_Widget *,void *)202 void quit_cb(Fl_Widget*, void*)
203 {
204 if (changed && !check_save()) return;
205 exit(0);
206 }
207 //-----------------------------------------------------------------------------
save_cb(Fl_Widget * w,void * v)208 void save_cb(Fl_Widget*w, void*v)
209 {
210 if(filename.empty()) { saveas_cb(w,v); return; } // No filename - get one!
211 else save_file(filename.c_str(),(ScriptWindow*)v);
212 }
213 //-----------------------------------------------------------------------------
saveas_cb(Fl_Widget *,void * v)214 void saveas_cb(Fl_Widget*, void *v)
215 {
216 const char *newfile;
217 char *fname=0;
218 while(1)
219 {
220 newfile = mgl_file_chooser(_("Save File As?"), _("MGL files \t*.mgl"), true);
221 if(!newfile || !newfile[0]) break;
222 if(!strchr(newfile,'.'))
223 {
224 if(fname) delete []fname;
225 fname = new char[strlen(newfile)+5];
226 strcpy(fname,newfile); strcat(fname,".mgl");
227 newfile = fname;
228 }
229 FILE *fp = fl_fopen(newfile,"r");
230 if(fp)
231 {
232 fclose(fp);
233 if(fl_choice(_("File exist. Overwrite it?"),0,_("No"),_(" Yes "))==2)
234 break;
235 }
236 else break;
237 }
238 if (newfile != NULL) save_file(newfile, (ScriptWindow*)v);
239 if(fname) delete []fname;
240 }
241 //-----------------------------------------------------------------------------
242 ScriptWindow *new_view();
243 //void view_cb(Fl_Widget*, void*)
244 //{ Fl_Window* w = new_view(); w->show(); }
245 //-----------------------------------------------------------------------------
246 // void hint_cb(Fl_Widget*, void*) {}
lastfile1_cb(Fl_Widget *,void * v)247 void lastfile1_cb(Fl_Widget*, void *v)
248 { if (!check_save()) return;
249 load_file(lastfiles[0].c_str(),-1,(ScriptWindow*)v); }
lastfile2_cb(Fl_Widget *,void * v)250 void lastfile2_cb(Fl_Widget*, void *v)
251 { if (!check_save()) return;
252 load_file(lastfiles[1].c_str(),-1,(ScriptWindow*)v); }
lastfile3_cb(Fl_Widget *,void * v)253 void lastfile3_cb(Fl_Widget*, void *v)
254 { if (!check_save()) return;
255 load_file(lastfiles[2].c_str(),-1,(ScriptWindow*)v); }
lastfile4_cb(Fl_Widget *,void * v)256 void lastfile4_cb(Fl_Widget*, void *v)
257 { if (!check_save()) return;
258 load_file(lastfiles[3].c_str(),-1,(ScriptWindow*)v); }
lastfile5_cb(Fl_Widget *,void * v)259 void lastfile5_cb(Fl_Widget*, void *v)
260 { if (!check_save()) return;
261 load_file(lastfiles[4].c_str(),-1,(ScriptWindow*)v); }
262 //-----------------------------------------------------------------------------
print_plot_cb(Fl_Widget *,void * v)263 void print_plot_cb(Fl_Widget*,void *v)
264 {
265 ScriptWindow *w = (ScriptWindow*)v;
266 Fl_Printer *p = new Fl_Printer;
267 if(!p->start_job(1) && !p->start_page())
268 {
269 int wp,hp, ww=w->graph->FMGL->w(), hh=w->graph->FMGL->h();
270 p->printable_rect(&wp,&hp);
271 double s=1, sw=double(wp)/ww, sh=double(hp)/hh;
272 if(sw<s) s=sw;
273 if(sh<s) s=sh;
274 // if(sw<sh) p->rotate(90); // TODO add rotation ???
275 p->scale(s,s);
276 p->print_widget(w->graph->FMGL);
277 p->end_page(); p->end_job();
278 }
279 delete p;
280 }
281 //-----------------------------------------------------------------------------
282 Fl_Menu_Item menuitems[] = {
283 {_("File"), 0, 0, 0, FL_SUBMENU},
284 {_("New script"), 0, new_cb},
285 {_("Open file ..."), FL_CTRL+'o', open_cb},
286 {_("Save file"), FL_CTRL+'s', save_cb},
287 {_("Save as ..."), 0, saveas_cb, 0, FL_MENU_DIVIDER},
288 {_("Print plot"), 0, print_plot_cb, 0, FL_MENU_DIVIDER},
289 {_("Recent files"), 0, 0, 0, FL_SUBMENU|FL_MENU_DIVIDER},
290 {"1.", 0, lastfile1_cb},
291 {"2.", 0, lastfile2_cb},
292 {"3.", 0, lastfile3_cb},
293 {"4.", 0, lastfile4_cb},
294 {"5.", 0, lastfile5_cb},
295 {0},
296 {_("Exit"), 0, quit_cb},
297 {0},
298 {_("Edit"), 0, 0, 0, FL_SUBMENU},
299 {_("Undo"), FL_CTRL+'z', undo_cb},
300 {_("Cut text"), FL_CTRL+'x', cut_cb},
301 {_("Copy text"), FL_CTRL+'c', copy_cb},
302 {_("Paste text"), FL_CTRL+'v', paste_cb},
303 {_("Select all"), FL_CTRL+'a', select_all_cb, 0, FL_MENU_DIVIDER},
304 {_("Hidden plots"), FL_CTRL+'d', hide_cb},
305 {_("Show lines"), FL_CTRL+FL_SHIFT+'d', unhide_cb, 0, FL_MENU_DIVIDER},
306 {_("Find|Replace"), FL_CTRL+'f', find_dlg_cb},
307 {_("Find next"), FL_F+3, find_next_cb, 0, FL_MENU_DIVIDER},
308 {_("Insert"), 0, 0, 0, FL_SUBMENU},
309 {_("File path"), FL_META+'p', ins_fname_cb},
310 {_("Folder path"), 0, ins_path_cb},
311 {_("Command"), FL_META+'c', newcmd_dlg_cb},
312 {_("Inplot"), FL_META+'i', inplot_dlg_cb},
313 {_("Fitted formula"), FL_META+'f', ins_fits_cb},
314 {_("Manual primitives"), 0, ins_prim_cb},
315 {_("Plot style"), 0, style_dlg_cb},
316 {_("Options"), FL_META+'o', option_dlg_cb},
317 {0},
318 // TODO{_("Selection"), 0, 0, 0, FL_SUBMENU|FL_MENU_DIVIDER},
319 // TODO{_("Hide"), 0, 0},
320 // TODO{_("Delete"), 0, 0},
321 // TODO{_("Move up"), 0, 0},
322 // TODO{_("Move down"), 0, 0},
323 // TODO{_("Show hidden"), FL_F+8, 0, 0, FL_MENU_TOGGLE},
324 {0},
325 {_("Graphics"), 0, 0, 0, FL_SUBMENU},
326 {0},
327 {_("Setup"), 0, 0, 0, FL_SUBMENU},
328 {_("Properties"), 0, prop_dlg_cb},
329 {_("Set arguments"), 0, args_dlg_cb},
330 {_("Setup animation"), 0, animate_dlg_cb},
331 {_("Plot setup"), FL_META+'g', setup_dlg_cb, 0, FL_MENU_DIVIDER},
332 {_("Calculator"), FL_F+4, calc_dlg_cb},
333 {_("Messages"), FL_F+2, message_cb},
334 {0},
335 {_("Help"), 0, 0, 0, FL_SUBMENU},
336 {_("Help"), FL_F+1, help_cb},
337 {_("Hints"), 0, hint_dlg_cb},
338 {_("About"), 0, about_cb},
339 {_("Icon list"), 0, iconlist_cb}, // TODO remove before release
340 {0},
341 {0}
342 };
343 //-----------------------------------------------------------------------------
mem_upd_cb(Fl_Widget *,void * v)344 void mem_upd_cb(Fl_Widget *, void *v)
345 { ((ScriptWindow*)v)->mem_init(); }
346 //-----------------------------------------------------------------------------
347 extern Fl_RGB_Image img_udav;
new_view()348 ScriptWindow *new_view()
349 {
350 Fl_Group *gg;
351 ScriptWindow *w = new ScriptWindow(wndW, wndH, _("Untitled - mgllab"));
352 w->begin();
353 w->menu = new Fl_Menu_Bar(0, 0, wndW, 30);
354 w->menu->copy(menuitems, w);
355 w->label(_("Untitled - mgllab"));
356
357 Fl_Tile *t = new Fl_Tile(0,30,wndW,wndH-55);
358 add_editor(w, txtW, wndH);
359
360 w->rtab = new Fl_Tabs(txtW,30,wndW-txtW,wndH-55,0);
361 w->gplot = new Fl_Group(txtW,30,wndW-txtW,wndH-80,_("Canvas"));
362 w->graph = new Fl_MGLView(txtW,30,wndW-txtW,wndH-80,_("Canvas"));
363 w->gplot->resizable(w->graph); w->gplot->end(); w->graph->adjust();
364 w->ghelp = new Fl_Group(txtW,30,wndW-txtW,wndH-80,_("Help"));
365 add_help(w, txtW, wndW, wndH); w->ghelp->end(); w->ghelp->hide();
366 gg = new Fl_Group(txtW,30,wndW-txtW,wndH-80,_("Memory")); gg->hide();
367 add_mem(w, txtW, wndW, wndH); gg->end();
368 w->rtab->end();
369
370 // w->status = new Fl_Output(0,485,wndW,25);
371 w->status = new Fl_Box(0,wndH-25,wndW,25); w->status->box(FL_ENGRAVED_BOX);
372 w->status->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
373 w->set_status(_("Ready"));
374 w->draw = new Fl_MGL(w->graph); w->draw->e = w;
375 mgl_makemenu_fltk(w->menu, w->graph);
376 w->menu->add(_("Graphics/Primitive"), FL_CTRL+'m', prim_dlg_cb, w);
377 w->menu->add(_("Graphics/Animation/Setup animation"), 0, animate_dlg_cb, w);
378 int index = w->menu->find_index(_("Graphics/Pause calc"));
379 if(index>=0) w->menu->remove(index);
380 // m->add(_("Graphics/Pause calc"), "^t", mgl_pause_cb, w, FL_MENU_TOGGLE);
381
382
383 t->end(); w->end(); w->resizable(t);
384 w->rtab->callback(mem_upd_cb, w);
385 w->callback(close_cb, w); w->icon(&img_udav);
386 num_windows++; return w;
387 }
388 //-----------------------------------------------------------------------------
389 void argument_set(int n, const char *s);
main(int argc,char ** argv)390 int main(int argc, char **argv)
391 {
392 // Fl::lock();
393 mgl_ask_func = mgl_ask_fltk;
394 mgl_progress_func = mgl_progress_fltk;
395 load_pref(NULL);
396
397 textbuf = new Fl_Text_Buffer;
398 style_init();
399 textbuf->tab_distance(4);
400 ScriptWindow *w = new_view();
401 Fl::visual(FL_DOUBLE|FL_RGB);
402 load_pref(w);
403 int ir = w->menu->find_index(_("File/Recent files"));
404 if(ir<0) ir = 6;
405 w->menu->replace(ir+1, lastfiles[0].c_str());
406 w->menu->replace(ir+2, lastfiles[1].c_str());
407 w->menu->replace(ir+3, lastfiles[2].c_str());
408 w->menu->replace(ir+4, lastfiles[3].c_str());
409 w->menu->replace(ir+5, lastfiles[4].c_str());
410 int sh; pref.get("show_hint",sh,1);
411 if(sh) hint_dlg_cb(0,0);
412
413 std::string fname;
414 while(1)
415 {
416 char ch = getopt(argc, argv, "1:2:3:4:5:6:7:8:9:ho:L:");
417 if(ch>='1' && ch<='9') argument_set(ch-'0', optarg);
418 else if(ch=='L')
419 { setlocale(LC_CTYPE, optarg); setlocale(LC_NUMERIC, "C"); }
420 else if(ch=='h')
421 {
422 printf(_("mgllab draw mgl script interactively.\nCurrent version is 2.%g\n"),MGL_VER2);
423 printf(_("Usage:\tmgllab [parameter(s)] scriptfile\n"));
424 printf(_("\t-1 str set str as argument $1 for script\n"
425 "\t... ...\n"
426 "\t-9 str set str as argument $9 for script\n"
427 "\t-L loc set locale to loc\n"
428 // "\t- get script from standard input\n"
429 "\t-h print this message\n") );
430 return 0;
431 }
432 // NOTE: I will not parse stdin here
433 else if(ch==-1)
434 { if(optind<argc) fname = argv[optind];
435 break; }
436 }
437
438 w->show(1, argv);
439 if(!fname.empty() && fname[0]!='-')
440 {
441 load_file(fname.c_str(), -1,w);
442 if(auto_exec) w->graph->update();
443 }
444 return Fl::run();
445 }
446 //-----------------------------------------------------------------------------
447 void cb_filech(Fl_Widget*, void *v);
448 class PropDlg : public GeneralDlg
449 {
450 friend void cb_filech(Fl_Widget*, void *v);
451 Fl_Choice *fkind;
452 Fl_Spinner *fsize;
453 Fl_File_Input *help_path;
454 Fl_File_Input *font_path;
455 Fl_Check_Button *auto_exec_w;
456 Fl_Check_Button *exec_save_w;
457 Fl_Check_Button *complete_w;
458 Fl_Check_Button *highlight_w;
459 Fl_Check_Button *mouse_zoom_w;
460 Fl_Check_Button *use_thr_w;
461 Fl_Check_Button *dark_w;
462 Fl_Choice *lang_w;
463 Fl_Choice *scheme_w;
464 public:
PropDlg()465 PropDlg() : GeneralDlg()
466 {
467 Fl_Button *o;
468 w = new Fl_Double_Window(340, 415, _("Properties"));
469 w->align(Fl_Align(FL_ALIGN_CLIP|FL_ALIGN_INSIDE));
470 fkind = new Fl_Choice(75, 10, 90, 25, _("Font kind"));
471 fkind->add("Helvetica"); fkind->add("Courier"); fkind->add("Times");
472 fsize = new Fl_Spinner(245, 10, 90, 25, _("Font size"));
473 help_path = new Fl_File_Input(5, 55, 305, 35, _("Path for help files"));
474 help_path->align(FL_ALIGN_TOP_LEFT);
475 o = new Fl_Button(310, 65, 25, 25, "..."); o->callback(cb_filech, 0);
476 font_path = new Fl_File_Input(5, 110, 305, 35, _("Path for MathGL font (without extension)"));
477 font_path->align(FL_ALIGN_TOP_LEFT);
478 o = new Fl_Button(310, 120, 25, 25, "..."); o->callback(cb_filech, (void *)1);
479 auto_exec_w = new Fl_Check_Button(5, 145, 330, 25, _("Execute script after loading"));
480 exec_save_w = new Fl_Check_Button(5, 170, 330, 25, _("Save file before redrawing"));
481 complete_w = new Fl_Check_Button(5, 195, 330, 25, _("Enable keywords completion"));
482 highlight_w = new Fl_Check_Button(5, 220, 330, 25, _("Highlight current object(s)"));
483 mouse_zoom_w = new Fl_Check_Button(5, 245, 330, 25, _("Enable mouse wheel for zooming"));
484 use_thr_w = new Fl_Check_Button(5, 270, 330, 25, _("Use multi-threading for drawing"));
485 dark_w = new Fl_Check_Button(5, 295, 330, 25, _("Use dark color scheme"));
486 lang_w = new Fl_Choice(160, 325, 175, 25, _("Language for mgllab"));
487 for(long i=0;i<NUM_LOCALE;i++) lang_w->add(loc[i]);
488 scheme_w = new Fl_Choice(160, 355, 175, 25, _("Widget scheme"));
489 scheme_w->add("base"); scheme_w->add("gtk+"); scheme_w->add("plastic"); scheme_w->add("gleam");
490 o = new Fl_Button(85, 385, 75, 25, _("Cancel")); o->callback(cb_dlg_cancel,this);
491 o = new Fl_Return_Button(180, 385, 75, 25, _("OK")); o->callback(cb_dlg_ok,this);
492 w->set_modal(); w->end();
493 }
init()494 void init()
495 {
496 fkind->value(styletable[0].font/4);
497 fsize->value(styletable[0].size);
498 font_path->value(fontname.c_str());
499 help_path->value(docdir.c_str());
500 auto_exec_w->value(auto_exec);
501 exec_save_w->value(exec_save);
502 complete_w->value(complete_word);
503 highlight_w->value(highlight);
504 mouse_zoom_w->value(mouse_zoom);
505 use_thr_w->value(use_thr);
506 lang_w->value(lang);
507 scheme_w->value(scheme);
508 dark_w->value(dark);
509 }
cb_ok()510 void cb_ok()
511 {
512 auto_exec = auto_exec_w->value();
513 exec_save = exec_save_w->value();
514 highlight = highlight_w->value();
515 mouse_zoom = mouse_zoom_w->value();
516 complete_word = complete_w->value();
517 use_thr = use_thr_w->value();
518 docdir = help_path->value();
519 fontname = font_path->value();
520 dark = dark_w->value();
521 set_style(fkind->value(),fsize->value(),dark);
522 if(e->graph->get_graph())
523 mgl_load_font(e->graph->get_graph(),fontname.c_str(),NULL);
524 set_scheme_lang(scheme_w->value(),lang_w->value()); // NOTE: must be after setting docdir
525 example_cb(NULL, e); e->graph->parent()->show();
526 save_pref(); hide();
527 }
528 } prop_dlg;
529 //-----------------------------------------------------------------------------
cb_filech(Fl_Widget *,void * v)530 void cb_filech(Fl_Widget*, void *v)
531 {
532 if(v)
533 {
534 const char *s = mgl_file_chooser(_("Font file name"), "MGL font files \t*.vfm*");
535 if(s)
536 { std::string ss = s;
537 size_t pos = ss.find(".vfm");
538 if(pos!=std::string::npos) ss = ss.substr(0,pos);
539 prop_dlg.font_path->value(ss.c_str()); }
540 }
541 else
542 {
543 const char *s = mgl_dir_chooser(_("Folder for help files"), prop_dlg.help_path->value());
544 if(s) prop_dlg.help_path->value(s);
545 }
546 }
prop_dlg_cb(Fl_Widget *,void * v)547 void prop_dlg_cb(Fl_Widget *, void *v)
548 { prop_dlg.e = (ScriptWindow *)v; prop_dlg.show(); }
549 //-----------------------------------------------------------------------------
550 void cb_calc_key(Fl_Widget *, void *v);
551 void cb_calc_ins(Fl_Widget *, void *);
552 void cb_calc_prev(Fl_Widget *, void *);
553 void cb_calc_edit(Fl_Widget *, void *);
554 void cb_calc_kind(Fl_Widget *, void *);
555 void cb_calc_func(Fl_Widget *, void *);
556 class CalcDlg : public GeneralDlg
557 {
558 public:
559 Fl_Input *edit;
560 Fl_Output *output;
561 Fl_Browser *prev;
562 Fl_Choice *kind;
563 Fl_Choice *func;
CalcDlg()564 CalcDlg() : GeneralDlg()
565 {
566 Fl_Button *o; Fl_Group* g, *gg;
567 w = new Fl_Double_Window(275, 275, _("Calculator"));
568 g = new Fl_Group(5, 5, 265, 25);
569 edit = new Fl_Input(5, 5, 240, 25); //edit->callback(cb_calc_edit);
570 o = new Fl_Return_Button(245, 5, 25, 25, "@>");
571 o->callback(cb_calc_edit); g->end(); g->resizable(edit);
572 g = new Fl_Group(5, 35, 265, 25);
573 output = new Fl_Output(30, 35, 145, 25, "@->");
574 o = new Fl_Button(180, 35, 90, 25, _("to script"));
575 o->callback(cb_calc_ins); g->end(); g->resizable(output);
576 prev = new Fl_Select_Browser(5, 80, 265, 70, _("Previous expressions"));
577 prev->align(FL_ALIGN_TOP_LEFT); prev->callback(cb_calc_prev);
578 static int widths[] = { 200, 65, 0 }; // widths for each column
579 prev->column_widths(widths); prev->column_char('\t');
580 gg = new Fl_Group(5, 155, 265, 115);
581 o = new Fl_Button(5, 155, 25, 25, "7"); o->callback(cb_calc_key,o);
582 o = new Fl_Button(35, 155, 25, 25, "8"); o->callback(cb_calc_key,o);
583 o = new Fl_Button(65, 155, 25, 25, "9"); o->callback(cb_calc_key,o);
584 o = new Fl_Button(95, 155, 25, 25, "+"); o->callback(cb_calc_key,o);
585 o = new Fl_Button(125, 155, 25, 25, "pi"); o->callback(cb_calc_key,o);
586 o = new Fl_Button(5, 185, 25, 25, "4"); o->callback(cb_calc_key,o);
587 o = new Fl_Button(35, 185, 25, 25, "5"); o->callback(cb_calc_key,o);
588 o = new Fl_Button(65, 185, 25, 25, "6"); o->callback(cb_calc_key,o);
589 o = new Fl_Button(95, 185, 25, 25, "-"); o->callback(cb_calc_key,o);
590 o = new Fl_Button(125, 185, 25, 25, "^"); o->callback(cb_calc_key,o);
591 o = new Fl_Button(5, 215, 25, 25, "1"); o->callback(cb_calc_key,o);
592 o = new Fl_Button(35, 215, 25, 25, "2"); o->callback(cb_calc_key,o);
593 o = new Fl_Button(65, 215, 25, 25, "3"); o->callback(cb_calc_key,o);
594 o = new Fl_Button(95, 215, 25, 25, "*"); o->callback(cb_calc_key,o);
595 o = new Fl_Button(125, 215, 25, 25, "("); o->callback(cb_calc_key,o);
596 o = new Fl_Button(5, 245, 25, 25, "0"); o->callback(cb_calc_key,o);
597 o = new Fl_Button(35, 245, 25, 25, "."); o->callback(cb_calc_key,o);
598 o = new Fl_Button(65, 245, 25, 25, "E"); o->callback(cb_calc_key,o);
599 o = new Fl_Button(95, 245, 25, 25, "/"); o->callback(cb_calc_key,o);
600 o = new Fl_Button(125, 245, 25, 25, ")"); o->callback(cb_calc_key,o);
601
602 g = new Fl_Group(155, 175, 115, 95, _("Function"));
603 kind = new Fl_Choice(160, 179, 105, 25); kind->callback(cb_calc_kind);
604 kind->add("Basic"); kind->add("Exp and log"); kind->add("Trigonometric");
605 kind->add("Hyperbolic"); kind->add("Bessel"); kind->add("Elliptic");
606 kind->add("Jacobi"); kind->add("Airy and Gamma");
607 kind->add("Exp-integrals"); kind->add("Special"); kind->value(0);
608
609 func = new Fl_Choice(160, 209, 105, 25);
610 o = new Fl_Button(160, 239, 105, 25, _("Put function")); o->callback(cb_calc_func);
611 g->end(); g->box(FL_DOWN_BOX);
612 gg->end(); gg->resizable(g);
613
614 w->end(); w->resizable(prev);
615 }
eval()616 void eval()
617 {
618 const char *eq = edit->value();
619 mglData d = Parse->Calc(eq);
620 result = mgl_str_num(d.a[0]);
621 output->value(result.c_str());
622 std::string buf = eq+('\t'+result);
623 prev->insert(0,buf.c_str());
624 }
set_kind()625 void set_kind()
626 {
627 int val = kind->value(); func->clear();
628 switch(val)
629 {
630 case 0: // basic
631 func->add("abs()"); func->add("sign()"); func->add("step()"); func->add("sqrt()");
632 func->add("mod(,)"); func->add("arg(,)"); break;
633 case 1: // exp and logarithms
634 func->add("exp()"); func->add("pow(,)"); func->add("ln()"); func->add("lg()");
635 func->add("log(,)"); break;
636 case 2: // trigonometric
637 func->add("sin()"); func->add("cos()"); func->add("tan()"); func->add("sinc()");
638 func->add("asin()"); func->add("acos()"); func->add("atan()"); break;
639 case 3: // hyperbolic
640 func->add("sinh()"); func->add("cosh()"); func->add("tanh()"); func->add("asinh()");
641 func->add("acosh()"); func->add("atanh()"); break;
642 case 4: // bessel
643 func->add("bessel_j(,)"); func->add("bessel_y(,)"); func->add("bessel_i(,)"); func->add("bessel_k(,)"); break;
644 case 5: // elliptic
645 func->add("elliptic_e(,)"); func->add("elliptic_f(,)"); func->add("elliptic_ec()"); func->add("elliptic_kc()"); break;
646 case 6: // jacobi
647 func->add("sn(,)"); func->add("cn(,)"); func->add("dn(,)"); func->add("sc(,)");
648 func->add("dc(,)"); func->add("nc(,)"); func->add("cs(,)"); func->add("ds(,)");
649 func->add("ns(,)"); func->add("sd(,)"); func->add("cd(,)"); func->add("nd(,)"); break;
650 case 7: // airy and gamma
651 func->add("airy_ai()"); func->add("airy_bi()"); func->add("airy_dai()");func->add("airy_dbi()");
652 func->add("gamma()"); func->add("psi()"); func->add("beta(,)"); break;
653 case 8: // exp integrals
654 func->add("ci()"); func->add("si()"); func->add("ei()"); func->add("e1()");
655 func->add("e2()"); func->add("ei3()"); break;
656 case 9: // special
657 func->add("erf()"); func->add("z()"); func->add("legendre(,)"); func->add("dilog()");
658 func->add("eta()"); func->add("zeta()"); func->add("w0()"); func->add("w1()"); break;
659 }
660 // func->value(0);
661 }
662 } calc_dlg;
663 //-----------------------------------------------------------------------------
cb_calc_key(Fl_Widget *,void * v)664 void cb_calc_key(Fl_Widget *, void *v)
665 { Fl_Button *o=(Fl_Button *)v; calc_dlg.edit->insert(o->label()); }
cb_calc_ins(Fl_Widget *,void *)666 void cb_calc_ins(Fl_Widget *, void *)
667 { if(calc_dlg.e) calc_dlg.e->editor->insert(calc_dlg.output->value()); }
cb_calc_prev(Fl_Widget *,void *)668 void cb_calc_prev(Fl_Widget *, void *)
669 {
670 const char *s = calc_dlg.prev->text(calc_dlg.prev->value());
671 if(s && *s)
672 {
673 std::string ss(s); size_t l=ss.length();
674 for(size_t i=0;i<l;i++) if(ss[i]=='\t') ss[i]=0;
675 calc_dlg.edit->value(ss.c_str());
676 }
677 }
cb_calc_edit(Fl_Widget *,void *)678 void cb_calc_edit(Fl_Widget *, void *) { calc_dlg.eval(); }
cb_calc_kind(Fl_Widget *,void *)679 void cb_calc_kind(Fl_Widget *, void *) { calc_dlg.set_kind(); }
cb_calc_func(Fl_Widget *,void *)680 void cb_calc_func(Fl_Widget *, void *)
681 { const char *s = calc_dlg.func->text();
682 if(s && *s) calc_dlg.edit->insert(s); }
683 //-----------------------------------------------------------------------------
calc_dlg_cb(Fl_Widget *,void * v)684 void calc_dlg_cb(Fl_Widget *, void *v)
685 { calc_dlg.e = (ScriptWindow *)v; calc_dlg.show(); }
686 //-----------------------------------------------------------------------------
687