1 /* setup.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 "mgl2/mgl.h"
18 #include "mgllab.h"
19 #include <string.h>
20 #include <FL/Fl_Spinner.H>
21 #include <FL/Fl_Output.H>
22 #include <FL/Fl_Select_Browser.H>
23 #include <FL/Fl_Toggle_Button.H>
24 //-----------------------------------------------------------------------------
25 const char *cols = " wbgrcmylenuqphkWBGRCMYLENUQPH";
26 Fl_Menu_Item colors[] = {
27 	{"-----", 0,0,0,0,0,0,0, 0},	//
28 	{_("w - white"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,0)},			//w
29 	{_("b - blue"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,255)},		//b
30 	{_("g - lime"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,0)},		//g
31 	{_("r - red"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,0)},			//r
32 	{_("c - cyan"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,255)},		//c
33 	{_("m - magenta"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,255)},	//m
34 	{_("y - yellow"), 0,0,0,0,0,0,0, fl_rgb_color(255,255,0)},	//y
35 	{_("l - springgreen"), 0,0,0,0,0,0,0, fl_rgb_color(0,255,127)},//l
36 	{_("e - lawngreen"), 0,0,0,0,0,0,0, fl_rgb_color(127,255,0)},	//e
37 	{_("n - skyblue"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,255)},	//n
38 	{_("u - blueviolet"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,255)},//u
39 	{_("q - orange"), 0,0,0,0,0,0,0, fl_rgb_color(255,127,0)},	//q
40 	{_("p - deeppink"), 0,0,0,0,0,0,0, fl_rgb_color(255,0,127)},	//p
41 	{_("h - gray"), 0,0,0,0,0,0,0, fl_rgb_color(127,127,127)},	//h
42 
43 	{_("k - black"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,0)},			//k
44 	{_("W - lightgray"), 0,0,0,0,0,0,0, fl_rgb_color(179,179,179)},//W
45 	{_("B - navy"), 0,0,0,0,0,0,0, fl_rgb_color(0,0,127)},		//B
46 	{_("G - green"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,0)},		//G
47 	{_("R - maroon"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,0)},		//R
48 	{_("C - teal"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,127)},		//C
49 	{_("M - purple"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,127)},	//M
50 	{_("Y - olive"), 0,0,0,0,0,0,0, fl_rgb_color(127,127,0)},		//Y
51 	{_("L - seagreen"), 0,0,0,0,0,0,0, fl_rgb_color(0,127,77)},	//L
52 	{_("E - darklawn"), 0,0,0,0,0,0,0, fl_rgb_color(77,127,0)},	//E
53 	{_("N - darkskyblue"), 0,0,0,0,0,0,0, fl_rgb_color(0,77,127)},//N
54 	{_("U - indigo"), 0,0,0,0,0,0,0, fl_rgb_color(77,0,127)},		//U
55 	{_("Q - brown"), 0,0,0,0,0,0,0, fl_rgb_color(127,77,0)},		//Q
56 	{_("P - darkpink"), 0,0,0,0,0,0,0, fl_rgb_color(127,0,77)},	//P
57 	{_("H - darkgray"), 0,0,0,0,0,0,0, fl_rgb_color(77,77,77)},	//H
58 {0}};
59 //-----------------------------------------------------------------------------
cb_dlg_cancel(Fl_Widget *,void * v)60 void cb_dlg_cancel(Fl_Widget*, void *v)	{	if(v)	((GeneralDlg*)v)->hide();	}
cb_dlg_ok(Fl_Widget *,void * v)61 void cb_dlg_ok(Fl_Widget*, void *v)		{	if(v)	((GeneralDlg*)v)->cb_ok();	}
wcstombs(std::wstring wcs)62 std::string wcstombs(std::wstring wcs)
63 {
64 	std::string str;
65 	const wchar_t *ss = wcs.c_str();
66 	size_t s=wcstombs(0,ss,0);	char *buf=new char[s+1];
67 	wcstombs(buf,ss,s); buf[s]=0;
68 	str = buf;	delete []buf;	return str;
69 }
70 //-----------------------------------------------------------------------------
71 void cb_option_change(Fl_Widget *, void *);
72 class OptionDlg : public GeneralDlg
73 {
74 	Fl_Input *x1, *x2, *y1, *y2, *z1, *z2, *c1, *c2;
75 	Fl_Input *val, *meshnum, *size;
76 	Fl_Choice *cut, *light;
77 	Fl_Input *alpha, *amb, *dif, *legend;
78 public:
79 	Fl_Input *ext;
OptionDlg()80 	OptionDlg() : GeneralDlg()
81 	{
82 		e=NULL;	ext=NULL;
83 		Fl_Button *o;
84 		w = new Fl_Double_Window(640, 185, _("Add command option(s)"));
85 		x1 = new Fl_Input(95, 5, 85, 25, _("X-range"));
86 		x1->tooltip(_("Minimal value of X for cutting or for coordinate filling"));
87 		x2 = new Fl_Input(190, 5, 85, 25, "-");
88 		x2->tooltip(_("Maximal value of X for cutting or for coordinate filling"));
89 		y1 = new Fl_Input(95, 35, 85, 25, _("Y-range"));
90 		y1->tooltip(_("Minimal value of Y for cutting or for coordinate filling"));
91 		y2 = new Fl_Input(190, 35, 85, 25, "-");
92 		y2->tooltip(_("Maximal value of Y for cutting or for coordinate filling"));
93 		z1 = new Fl_Input(95, 65, 85, 25, _("Z-range"));
94 		z1->tooltip(_("Minimal value of Z for cutting or for coordinate filling"));
95 		z2 = new Fl_Input(190, 65, 85, 25, "-");
96 		z2->tooltip(_("Maximal value of Z for cutting or for coordinate filling"));
97 		c1 = new Fl_Input(95, 95, 85, 25, _("C-range"));	c1->deactivate();
98 		c1->tooltip(_("Low border for determining color or alpha"));
99 		c2 = new Fl_Input(190, 95, 85, 25, "-");		c2->deactivate();
100 		c2->tooltip(_("Upper border for determining color or alpha"));
101 		val = new Fl_Input(375, 5, 85, 25, _("Value"));	val->labelfont(1);
102 		meshnum = new Fl_Input(375, 35, 85, 25, _("MeshNum"));
103 		meshnum->tooltip(_("Approximate number of mesh lines in plot"));
104 		size = new Fl_Input(375, 65, 85, 25, _("Size"));
105 		size->tooltip(_("Set size for text, marks and others"));
106 		cut = new Fl_Choice(375, 95, 85, 25, _("Cutting"));
107 		cut->add(_("default"));	cut->add("on");	cut->add("off");
108 		cut->tooltip(_("Set cutting off/on for particular plot"));
109 		alpha = new Fl_Input(550, 5, 85, 25, _("Alpha"));
110 		alpha->tooltip(_("Alpha value (transparency) of surface or cloud"));
111 		amb = new Fl_Input(550, 35, 85, 25, _("Ambient"));
112 		amb->tooltip(_("Own brightness of the surface"));
113 		dif = new Fl_Input(550, 65, 85, 25, _("Diffuse"));
114 		dif->tooltip(_("Intensity of diffuse light"));
115 		light = new Fl_Choice(550, 95, 85, 25, _("Light"));
116 		light->add(_("default"));	light->add("on");	light->add("off");
117 		cut->tooltip(_("Set lighting off/on for particular plot"));
118 		legend = new Fl_Input(95, 125, 540, 25, _("Legend"));
119 		cut->tooltip(_("Add legend entry for the plot"));
120 		o = new Fl_Button(455, 155, 85, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
121 		o = new Fl_Return_Button(550, 155, 85, 25, _("OK"));	o->callback(cb_dlg_ok,this);
122 		w->set_modal();	w->end();
123 	}
cb_ok()124 	void cb_ok()
125 	{
126 		int v;	const char *s1, *s2;	result.clear();
127 		s1=val->value();	if(s1 && *s1)	result = result+";value "+s1;
128 		s1=x1->value();	s2=x2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";xrange "+s1+' '+s2;
129 		s1=y1->value();	s2=y2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";yrange "+s1+' '+s2;
130 		s1=z1->value();	s2=z2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";zrange "+s1+' '+s2;
131 //		s1=c1->value();	s2=c2->value();	if(s1 && *s1 && s2 && *s2)	result = result+";crange "+s1+' '+s2;
132 		s1=legend->value();	if(s1 && *s1)	result = result+";legend '"+s1+"'";
133 		s1=size->value();	if(s1 && *s1)	result = result+";size "+s1;
134 		s1=alpha->value();	if(s1 && *s1)	result = result+";alpha "+s1;
135 		s1=amb->value();	if(s1 && *s1)	result = result+";ambient "+s1;
136 		s1=dif->value();	if(s1 && *s1)	result = result+";diffuse "+s1;
137 		s1=meshnum->value();if(s1 && *s1)	result = result+";meshnum "+s1;
138 		v=cut->value();		if(v==1 || v==2)	result = result+";cut "+cut->text();
139 		v=light->value();	if(v==1 || v==2)	result = result+";light "+light->text();
140 		if(e)	e->editor->insert(result.c_str());
141 		if(ext)	ext->value(result.c_str());
142 		hide();
143 	}
144 } option_dlg;
145 //-----------------------------------------------------------------------------
option_dlg_cb(Fl_Widget *,void * v)146 void option_dlg_cb(Fl_Widget *, void *v)
147 {	option_dlg.ext=NULL;	option_dlg.e=(ScriptWindow *)v;	option_dlg.show();	}
148 //-----------------------------------------------------------------------------
option_in_cb(Fl_Widget *,void * v)149 void option_in_cb(Fl_Widget *, void *v)
150 {	option_dlg.ext=(Fl_Input*)v;	option_dlg.e=NULL;	option_dlg.show();	}
151 //-----------------------------------------------------------------------------
152 class DirSelDlg : public GeneralDlg
153 {
154 	Fl_Choice *dir;
155 public:
156 	Fl_Input *ext;
DirSelDlg()157 	DirSelDlg() : GeneralDlg()
158 	{
159 		Fl_Button *o;
160 		w = new Fl_Double_Window(220, 85, _("Select direction"));
161 		dir = new Fl_Choice(80, 10, 135, 25, _("Direction"));
162 		dir->add("xyz");	dir->add("x");	dir->add("y");	dir->add("z");
163 		dir->add("xy");	dir->add("xz");	dir->add("yz");
164 		o = new Fl_Button(55, 50, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
165 		o = new Fl_Return_Button(140, 50, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
166 		w->set_modal();	w->end();
167 	}
cb_ok()168 	void cb_ok()
169 	{
170 		const char *s = dir->text();
171 		if(s && *s)	result = std::string("'")+s+"'";
172 		if(e)	e->editor->insert(result.c_str());
173 		else if(ext)	ext->value(result.c_str());
174 		else	cb_args_set(result.c_str());
175 		hide();
176 	}
177 } dirsel_dlg;
178 //-----------------------------------------------------------------------------
dirsel_dlg_cb(Fl_Widget *,void * v)179 void dirsel_dlg_cb(Fl_Widget *, void *v)
180 {	dirsel_dlg.ext=NULL;	dirsel_dlg.e=(ScriptWindow *)v;	dirsel_dlg.show();	}
181 //-----------------------------------------------------------------------------
182 // void dirsel_in_cb(Fl_Widget *, void *v)
183 // {	dirsel_dlg.ext=(Fl_Input*)v;	dirsel_dlg.e=NULL;	dirsel_dlg.show();	}
184 //-----------------------------------------------------------------------------
185 //const char *arr = "_AKVITSDOX";
186 Fl_Menu_Item arrows[] = {
187 	{_("'_' none")},		//_
188 	{_("'A' arrow")},	//A
189 	{_("'K' size")},		//K
190 	{_("'V' back arrow")},//V
191 	{_("'I' stop")},		//I
192 	{_("'T' triangle")},	//T
193 	{_("'S' square")},	//S
194 	{_("'D' rhomb")},	//D
195 	{_("'O' circle")},	//O
196 	{_("'X' cross")},	//X
197 	{0}};
198 //-----------------------------------------------------------------------------
199 //const char *stl = "-|j;i=: d";
200 Fl_Menu_Item dashing[] = {
201 	{_("'-' solid")},		//-
202 	{_("'|' long dash")},	//|
203 	{_("'j' dash dot")},	//j
204 	{_("';' dash")},		//;
205 	{_("'i' small dash dot")},	//i
206 	{_("'=' small dash")},	//=
207 	{_("':' dots")},		//:
208 	{_("' ' none")},		//
209 	{_("manual")},			// d
210 	{0}};
211 //-----------------------------------------------------------------------------
212 //const char *mrk = "*o+xsd.^v<>";
213 Fl_Menu_Item markers[] = {
214 	{_("none")},			//
215 	{_("'*' star")},		//*
216 	{_("'o' circle")},		//o
217 	{_("'+' plus")},		//+
218 	{_("'x' skew cross")},	//x
219 	{_("'s' square")},		//s
220 	{_("'d' rhomb")},		//d
221 	{_("'.' dot")},			//.
222 	{_("'^' triangle up")},	//^
223 	{_("'v' triangle down")},//v
224 	{_("'<' triangle left")},//<
225 	{_("'>' triangle right")},//>
226 	{0}};
227 //-----------------------------------------------------------------------------
228 //const char *msk = " -+=;joOsS~<>dD*^M";
229 Fl_Menu_Item masks[] = {
230 	{_("none")},			//
231 	{_("'-' lines")},		//-
232 	{_("'+' plus")},		//+
233 	{_("'=' double lines")},//=
234 	{_("';' dash")},		//;
235 	{_("'j' dash dot")},	//j
236 	{_("'o' circle")},		//o
237 	{_("'O' solid circle")},//O
238 	{_("'s' square")},		//s
239 	{_("'S' solid square")},//S
240 	{_("'~' waves")},		//~
241 	{_("'<' left sign")},	//<
242 	{_("'>' right sign")},	//>
243 	{_("'d' rhomb")},		//d
244 	{_("'D' solid rhomb")},	//D
245 	{_("'*' cross")},		//*
246 	{_("'^' hats")},		//^
247 	{_("manual")},			//M
248 	{0}};
249 //-----------------------------------------------------------------------------
get_color(Fl_Choice * c,Fl_Spinner * s,Fl_Input * p)250 std::string get_color(Fl_Choice *c, Fl_Spinner *s, Fl_Input *p)
251 {
252 	std::string res;
253 	const char *ps = p->value();
254 	int cv = c->value(), sv = s->value();
255 	int pv = ps?10*atof(ps):-1;
256 	if(pv<0 || pv>9)	ps = NULL;
257 	if(cv>0 && cv<long(strlen(cols)))
258 	{
259 		if(ps)
260 		{
261 			if(sv>0 && sv<10 && sv!=5)
262 			{
263 				char buf[16];	snprintf(buf,16,"{%c%d,0.%d}",cols[cv],sv,pv);
264 				res = buf;
265 			}
266 			else	res = cols[cv];
267 		}
268 		else
269 		{
270 			if(sv>0 && sv<10 && sv!=5)
271 			{
272 				char buf[16];	snprintf(buf,16,"{%c%d}",cols[cv],sv);
273 				res = buf;
274 			}
275 			else	res = cols[cv];
276 		}
277 	}
278 	return res;
279 }
280 //-----------------------------------------------------------------------------
281 void cb_style_upd(Fl_Widget *, void *);
282 void cb_style_sch(Fl_Widget *, void *);
283 class StyleDlg : public GeneralDlg
284 {
285 	Fl_Choice *arr1, *dash, *arr2;
286 	Fl_Choice *mark;
287 	Fl_Check_Button *solid, *user;
288 	Fl_Spinner *width;
289 	Fl_Button *dash_m[16];
290 
291 	Fl_Choice *c[8], *sch;
292 	Fl_Spinner *s[8];
293 	Fl_Input *p[8];
294 	Fl_Choice *axial, *contt, *mask, *angle;
295 	Fl_Spinner *msize;
296 	Fl_Input *alpha;
297 	Fl_Button *mask_m[64];
298 	Fl_Check_Button *wire, *sharp;
299 
300 	Fl_Check_Button *bold, *ital, *twire, *uline, *oline, *plain;
301 	Fl_Choice *align, *vert;
302 
303 	Fl_Group *gline, *gsurf, *gfont;
304 	Fl_Output *res;
305 	Fl_MathGL *gr;
306 	std::string script;
307 public:
308 	Fl_Input *ext;
StyleDlg()309 	StyleDlg() : GeneralDlg()
310 	{
311 		Fl_Group *g;	Fl_Button *o;
312 		w = new Fl_Double_Window(380, 540, _("Plot style"));
313 		Fl_Tabs* tt = new Fl_Tabs(0, 5, 375, 235);
314 		gline = new Fl_Group(0, 30, 375, 210, _("Line style"));
315 			arr1 = new Fl_Choice(5, 50, 110, 25, _("Arrow at start"));
316 			arr1->align(FL_ALIGN_TOP_LEFT);	arr1->copy(arrows);
317 			arr1->callback(cb_style_upd);
318 			dash = new Fl_Choice(125, 50, 110, 25, _("Dashing"));
319 			dash->align(FL_ALIGN_TOP_LEFT);	dash->copy(dashing);
320 			dash->callback(cb_style_upd);
321 			arr2 = new Fl_Choice(245, 50, 110, 25, _("Arrow at end"));
322 			arr2->align(FL_ALIGN_TOP_LEFT);	arr2->copy(arrows);
323 			arr2->callback(cb_style_upd);
324 			mark = new Fl_Choice(125, 80, 110, 25, _("Marks"));
325 			mark->copy(markers);	mark->callback(cb_style_upd);
326 			solid = new Fl_Check_Button(240, 80, 55, 25, _("solid"));
327 			user = new Fl_Check_Button(300, 80, 55, 25, _("user"));
328 			solid->callback(cb_style_upd);	user->callback(cb_style_upd);
329 			width = new Fl_Spinner(125, 110, 110, 25, _("Width"));
330 			width->range(1,9);	width->value(1);	width->callback(cb_style_upd);
331 			for(int i=0;i<16;i++)
332 			{
333 				dash_m[i] = new Fl_Toggle_Button(10+20*i, 210, 20, 20);
334 				dash_m[i]->callback(cb_style_upd);
335 			}
336 			dash_m[0]->label(_("Manual dashing"));
337 			dash_m[0]->align(FL_ALIGN_TOP_LEFT);
338 			gline->end();
339 		gsurf = new Fl_Group(0, 30, 375, 210, _("Color scheme"));	gsurf->hide();
340 			axial = new Fl_Choice(5, 50, 110, 25, _("Axial direction"));
341 			axial->align(FL_ALIGN_TOP_LEFT);	axial->callback(cb_style_upd);
342 			axial->add("none");	axial->add("x");	axial->add("y");	axial->add("z");
343 			contt = new Fl_Choice(125, 50, 110, 25, _("Text on contours"));
344 			contt->add("none");	contt->add("under");	contt->add("above");
345 			contt->align(FL_ALIGN_TOP_LEFT);	contt->callback(cb_style_upd);
346 			alpha = new Fl_Input(255, 50, 110, 25, _("Transparency"));
347 			alpha->align(FL_ALIGN_TOP_LEFT);	alpha->callback(cb_style_upd);
348 			wire = new Fl_Check_Button(125, 80, 115, 25, _("Wire or mesh"));
349 			wire->callback(cb_style_upd);
350 			sharp = new Fl_Check_Button(250, 80, 110, 25, _("Sharp colors"));
351 			sharp->callback(cb_style_upd);
352 			g = new Fl_Group(10, 105, 360, 130, _("Mask"));
353 				g->box(FL_ENGRAVED_BOX);	g->align(FL_ALIGN_TOP_LEFT);
354 				mask = new Fl_Choice(100, 110, 95, 25, _("Kind"));
355 				mask->copy(masks);	mask->callback(cb_style_upd);
356 				angle = new Fl_Choice(100, 140, 95, 25, _("Rotation"));
357 				angle->add("none");	angle->add("+45");	angle->add("90");	angle->add("-45");
358 				angle->callback(cb_style_upd);
359 				msize = new Fl_Spinner(100, 170, 95, 25, _("Size"));
360 				msize->range(1,9);	msize->value(1);	msize->callback(cb_style_upd);
361 				for(int i=0;i<8;i++)	for(int j=0;j<8;j++)
362 				{
363 					mask_m[i+8*j] = new Fl_Toggle_Button(240+15*i, 110+15*(7-j), 15, 15);
364 					mask_m[i+8*j]->callback(cb_style_upd);
365 				}
366 			g->end();	gsurf->end();
367 		gfont = new Fl_Group(0, 30, 375, 210, _("Text style"));	gfont->hide();
368 			bold = new Fl_Check_Button(5, 40, 150, 25, _("Bold style"));
369 			ital = new Fl_Check_Button(5, 65, 150, 25, _("Italic style"));
370 			twire = new Fl_Check_Button(5, 90, 150, 25, _("Wire style"));
371 			uline = new Fl_Check_Button(5, 115, 150, 25, _("Underline"));
372 			oline = new Fl_Check_Button(5, 140, 150, 25, _("Overline"));
373 			bold->callback(cb_style_upd);	ital->callback(cb_style_upd);
374 			twire->callback(cb_style_upd);	uline->callback(cb_style_upd);
375 			oline->callback(cb_style_upd);
376 			align = new Fl_Choice(270, 40, 95, 25, _("Text align"));
377 			align->add("left");	align->add("center");	align->add("right");
378 			align->value(1);	align->callback(cb_style_upd);
379 			vert = new Fl_Choice(270, 75, 95, 25, _("Vertical align"));
380 			vert->add("default");	vert->add("center");	vert->add("under");
381 			vert->value(0);	vert->callback(cb_style_upd);
382 		gfont->end();	tt->end();	tt->callback(cb_style_upd);
383 
384 		g = new Fl_Group(0, 265, 375, 155, _("Color(s) or color scheme"));
385 		g->box(FL_ENGRAVED_BOX);	g->align(FL_ALIGN_TOP_LEFT);
386 			sch = new Fl_Choice(170, 270, 115, 25, _("Popular color schemes"));
387 			sch->add("BbcyrR");	sch->add("kw");		sch->add("wk");		sch->add("bwr");
388 			sch->add("kHCcw");	sch->add("kBbcw");	sch->add("kRryw");	sch->add("kGgew");
389 			sch->add("BbwrR");	sch->add("BbwgG");	sch->add("GgwmM");	sch->add("UuwqR");
390 			sch->add("QqwcC");	sch->add("CcwyY");	sch->add("bcwyr");	sch->add("wUrqy");
391 			sch->add("UbcyqR");	sch->add("bgr");	sch->callback(cb_style_sch);
392 			plain = new Fl_Check_Button(290, 270, 80, 25, _("plain"));
393 			plain->callback(cb_style_upd);
394 			for(int i=0;i<8;i++)
395 			{
396 				c[i] = new Fl_Choice(5+185*(i/4), 300+30*(i%4), 95, 25);
397 				c[i]->copy(colors);	c[i]->callback(cb_style_upd);
398 				c[i]->tooltip(_("Value for i-th color"));
399 				s[i] = new Fl_Spinner(105+185*(i/4), 300+30*(i%4), 40, 25);
400 				s[i]->range(1,9);	s[i]->value(5);
401 				s[i]->tooltip(_("Brightness of i-th color"));
402 				s[i]->callback(cb_style_upd);
403 				p[i] = new Fl_Input(145+185*(i/4), 300+30*(i%4), 40, 25);
404 				p[i]->tooltip(_("Relative position of i-th color"));
405 				p[i]->callback(cb_style_upd);
406 			}
407 			g->end();
408 		res = new Fl_Output(5, 440, 370, 25, _("Resulting string"));
409 		res->align(FL_ALIGN_TOP_LEFT);
410 		o = new Fl_Button(300, 475, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
411 		o = new Fl_Return_Button(300, 505, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
412 		gr = new Fl_MathGL(5, 470, 285, 65);	gr->box(FL_ENGRAVED_BOX);	gr->use_pthr = false;
413 		mgl_set_size(gr->get_graph(),285,65);	gr->align(FL_ALIGN_LEFT);
414 		w->set_modal();	w->end();
415 	}
init()416 	void init()	{	update();	}
set_scheme()417 	void set_scheme()
418 	{
419 		const char *ss = sch->text();
420 		if(!ss || *ss==0)	return;
421 		for(int i=0;i<8;i++)
422 		{	p[i]->value(NULL);	s[i]->value(5);	c[i]->value(0);	}
423 		for(int i=0;i<8;i++)
424 		{
425 			if(ss[i]==0)	break;
426 			size_t pos = strchr(cols,ss[i])-cols;
427 			c[i]->value(pos);
428 		}
429 		update();
430 	}
stl_color()431 	void stl_color()
432 	{
433 		result.clear();
434 		for(int i=0;i<8;i++)
435 			result += get_color(c[i],s[i],p[i]);
436 	}
stl_line()437 	void stl_line()
438 	{
439 		stl_color();
440 		char dsh = dash->text()[1];
441 		char a1 = arr1->text()[1], a2 = arr2->text()[1];
442 		const char *s = mark->text();
443 		if(*s=='\'')
444 		{
445 			if(user->value())	result += '&';
446 			if(solid->value())	result += '#';
447 			result += s[1];
448 		}
449 		int v = width->value();
450 		if(v>1)	result += char(v+'0');
451 		if(a1!='_')	result = result + a1 + a2;
452 		else if(a2!='_')	result += a2;
453 		if(dsh=='a')
454 		{
455 			unsigned long mask=0;
456 			for(int i=0;i<16;i++)	if(dash_m[i]->value())	mask += 1<<i;
457 			char buf[128];	snprintf(buf,128,"{d%lX}",mask);	// TODO: %llX in 32bit!
458 			result += buf;
459 		}
460 		else if(dsh!='-')	result += dsh;
461 		result = '\''+result+'\'';
462 		script = "new a 5 5 'y':plot a "+result+";size 8";
463 	}
stl_surf()464 	void stl_surf()
465 	{
466 		stl_color();
467 		int v = contt->value();	const char *tt="Tt";
468 		if(v>0 && v<3)	result += tt[v-1];
469 		const char *m = mask->text();
470 		if(*m=='\'')
471 		{
472 			v = angle->value();	const char *rr="/I\\";
473 			if(v>0 && v<4)	result += rr[v-1];
474 			v = msize->value();	if(v>1)	result += char(v+'0');
475 			result += m[1];
476 		}
477 		if(*m=='m')
478 		{
479 			v = angle->value();	const char *rr="/I\\";
480 			if(v>0 && v<4)	result += rr[v-1];
481 			v = msize->value();	if(v>1)	result += char(v+'0');
482 			uint64_t mask=0;
483 			for(int i=0;i<64;i++)	if(mask_m[i]->value())	mask += uint64_t(1)<<i;
484 #ifdef WIN32
485 			char buf[128];	snprintf(buf,128,"{s%llX}",mask);
486 #else
487 			char buf[128];	snprintf(buf,128,"{s%lX}",mask);
488 #endif
489 			result += buf;
490 		}
491 		if(wire->value())	result += '#';
492 		if(sharp->value())	result += '|';
493 		if(plain->value())	result += '%';
494 		v = atoi(alpha->value());
495 		if(v>0 && v<10)	result = result + "{A"+char(v+'0')+'}';
496 		v = axial->value();	const char *ax="xyz";
497 		if(v>0 && v<4)	result = result+':'+ax[v-1];
498 		result = '\''+result+'\'';
499 		script = "fsurf 'x' "+result;
500 	}
stl_font()501 	void stl_font()
502 	{
503 		stl_color();
504 		const char *a="LCR";
505 		result = result+':'+a[align->value()];
506 		if(bold->value())	result += 'b';
507 		if(ital->value())	result += 'i';
508 		if(twire->value())	result += 'w';
509 		if(uline->value())	result += 'u';
510 		if(oline->value())	result += 'o';
511 		if(vert->value()==1)	result += 'V';
512 		if(vert->value()==2)	result += 'T';
513 		result = '\''+result+'\'';
514 		script = "text 0 0 'Font test' "+result+";size -8";
515 	}
update()516 	void update()
517 	{
518 		static int busy=0;
519 		if(!busy)	{	busy=1;
520 			result.clear();
521 			if(gline->visible())		stl_line();
522 			else if(gfont->visible())	stl_font();
523 			else	stl_surf();
524 			res->value(result.c_str());
525 			mglParse pr;
526 			script = "clf:subplot 1 1 0 '':"+script;
527 			mgl_parse_text(gr->get_graph(), pr.Self(), script.c_str());
528 			gr->update();
529 		busy=0;	}
530 	}
cb_ok()531 	void cb_ok()
532 	{
533 		update();
534 		if(e)	e->editor->insert(result.c_str());
535 		else if(ext)	ext->value(result.c_str());
536 		else	cb_args_set(result.c_str());
537 		hide();
538 	}
539 } style_dlg;
540 //-----------------------------------------------------------------------------
cb_style_upd(Fl_Widget *,void *)541 void cb_style_upd(Fl_Widget *, void *)	{	style_dlg.update();	}
cb_style_sch(Fl_Widget *,void *)542 void cb_style_sch(Fl_Widget *, void *)	{	style_dlg.set_scheme();	}
543 //-----------------------------------------------------------------------------
style_dlg_cb(Fl_Widget *,void * v)544 void style_dlg_cb(Fl_Widget *, void *v)
545 {	style_dlg.ext=NULL;	style_dlg.e=(ScriptWindow *)v;	style_dlg.show();	}
546 //-----------------------------------------------------------------------------
547 //void style_in_cb(Fl_Widget *, void *v)
548 //{	style_dlg.ext=(Fl_Input*)v;	style_dlg.e=NULL;	style_dlg.show();	}
549 //-----------------------------------------------------------------------------
550 void cb_datsel_upd(Fl_Widget *, void *);
551 void cb_datsel_act(Fl_Widget *, void *);
552 class DatSelDlg : public GeneralDlg
553 {
554 	Fl_Choice *name;
555 	Fl_Choice *oper;
556 	Fl_Choice *dir;
557 	Fl_Spinner *x1, *x2, *y1, *y2, *z1, *z2;
558 	Fl_Input *clmn;
559 	Fl_Check_Button *ax, *ay, *az;
560 public:
561 	Fl_Input *ext;
DatSelDlg()562 	DatSelDlg() : GeneralDlg()
563 	{
564 		Fl_Button *o;
565 		w = new Fl_Double_Window(355, 255, _("Select data argument"));
566 		name = new Fl_Choice(105, 5, 145, 25, _("Data name"));
567 		name->callback(cb_datsel_upd);
568 		x1 = new Fl_Spinner(105, 35, 60, 25, _("X-slice from"));
569 		x2 = new Fl_Spinner(190, 35, 60, 25, _("to"));
570 		ax = new Fl_Check_Button(260, 35, 90, 25, _("all"));	ax->callback(cb_datsel_act);
571 		y1 = new Fl_Spinner(105, 65, 60, 25, _("Y-slice from"));
572 		y2 = new Fl_Spinner(190, 65, 60, 25, _("to"));
573 		ay = new Fl_Check_Button(260, 65, 90, 25, _("all"));	ay->callback(cb_datsel_act);
574 		z1 = new Fl_Spinner(105, 95, 60, 25, _("Z-slice from"));
575 		z2 = new Fl_Spinner(190, 95, 60, 25, _("to"));
576 		az = new Fl_Check_Button(260, 95, 90, 25, _("all"));	az->callback(cb_datsel_act);
577 		clmn = new Fl_Input(105, 125, 245, 25, _("Column expr"));
578 		oper = new Fl_Choice(105, 155, 130, 25, _("Operation"));
579 		oper->add("none");	oper->add("max");	oper->add("min");	oper->add("sum");
580 		oper->add("trace");	oper->add("pulse");	oper->value(0);
581 		dir = new Fl_Choice(285, 155, 65, 25, _("along"));
582 		dir->add("none");	dir->add("x");	dir->add("y");	dir->add("z");
583 		dir->add("xy");		dir->add("xz");	dir->add("yz");
584 		o = new Fl_Button(190, 190, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
585 		o = new Fl_Return_Button(275, 190, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
586 		w->set_modal();	w->end();
587 	}
cb_ok()588 	void cb_ok()
589 	{
590 		result.clear();
591 		if(name->value()<0)
592 		{	fl_alert(_("You need to select data array"));	return;	}
593 		std::string data = name->text();
594 		const char *eq = clmn->value();
595 		int rx=ax->value(), ry=ay->value(), rz=az->value();
596 		int vx1=x1->value(), vy1=y1->value(), vz1=z1->value();
597 		int vx2=x2->value(), vy2=y2->value(), vz2=z2->value();
598 		if(eq && *eq)	data = data+"('"+eq+"')";
599 		else	if(!rx || !ry || !rz)
600 		{
601 			char bx[256],by[256],bz[256];
602 			if(rx)	strcpy(bx,"(:");
603 			else if(vx2<=vx1)	snprintf(bx,255,"(%d",vx1);
604 			else	snprintf(bx,255,"(%d:%d",vx1,vx2);
605 			if(ry)	strcpy(by,",:");
606 			else if(vy2<=vy1)	snprintf(by,255,",%d",vy1);
607 			else	snprintf(by,255,",%d:%d",vy1,vy2);
608 			if(vz2<=vz1)	snprintf(bz,255,",%d)",vz1);
609 			else	snprintf(bz,255,",%d:%d)",vz1,vz2);
610 			if(!rz)	data = data+bx+by+bz;
611 			else if(!ry)	data = data+bx+by+')';
612 			else if(!rx)	data = data+bx+')';
613 		}
614 		if(oper->value()>0)
615 		{
616 			result = result+'{'+oper->text()+' '+data;
617 			if(dir->value()>0)	result = result+" '"+dir->text()+"'}";
618 			else	result += '}';
619 		}
620 		else	result = data;
621 		if(e)	e->editor->insert(result.c_str());
622 		else if(ext)	ext->value(result.c_str());
623 		else	cb_args_set(result.c_str());
624 		hide();
625 	}
init()626 	void init()
627 	{
628 		name->clear();
629 		long n = Parse->GetNumVar();
630 		for(long i=0;i<n;i++)
631 		{
632 			HCDT d = Parse->GetVar(i);
633 			if(!d->temp)	name->add(wcstombs(d->Name()).c_str());
634 		}
635 		x1->value(0);	x2->value(0);
636 		y1->value(0);	y2->value(0);
637 		z1->value(0);	z2->value(0);
638 	}
update()639 	void update()
640 	{
641 		HCDT d = Parse->FindVar(name->text());
642 		if(d)
643 		{
644 			long nx=d->GetNx()-1, ny=d->GetNy()-1, nz=d->GetNz()-1;
645 			x1->range(0,nx);	if(x1->value()>nx)	x1->value(0);
646 			x2->range(0,nx);	if(x2->value()>nx)	x2->value(0);
647 			y1->range(0,ny);	if(y1->value()>ny)	y1->value(0);
648 			y2->range(0,ny);	if(y2->value()>ny)	y2->value(0);
649 			z1->range(0,nz);	if(z1->value()>nz)	z1->value(0);
650 			z2->range(0,nz);	if(z2->value()>nz)	z2->value(0);
651 			ax->value(1);	ay->value(1);	az->value(1);
652 			x1->deactivate();	y1->deactivate();	z1->deactivate();
653 			x2->deactivate();	y2->deactivate();	z2->deactivate();
654 			clmn->value("");
655 		}
656 	}
activate()657 	void activate()
658 	{
659 		if(!ax->value())	{	x1->activate();	x2->activate();	}
660 		else	{	x1->deactivate();	x2->deactivate();	}
661 		if(!ay->value())	{	y1->activate();	y2->activate();	}
662 		else	{	y1->deactivate();	y2->deactivate();	}
663 		if(!az->value())	{	z1->activate();	z2->activate();	}
664 		else	{	z1->deactivate();	z2->deactivate();	}
665 	}
666 } datsel_dlg;
667 //-----------------------------------------------------------------------------
cb_datsel_upd(Fl_Widget *,void *)668 void cb_datsel_upd(Fl_Widget *, void *)	{	datsel_dlg.update();	}
cb_datsel_act(Fl_Widget *,void *)669 void cb_datsel_act(Fl_Widget *, void *)	{	datsel_dlg.activate();	}
670 //-----------------------------------------------------------------------------
datsel_dlg_cb(Fl_Widget *,void * v)671 void datsel_dlg_cb(Fl_Widget *, void *v)
672 {	datsel_dlg.ext=NULL;	datsel_dlg.e=(ScriptWindow *)v;	datsel_dlg.show();	}
673 //-----------------------------------------------------------------------------
674 // void datsel_in_cb(Fl_Widget *, void *v)
675 // {	datsel_dlg.ext=(Fl_Input*)v;	datsel_dlg.e=NULL;	datsel_dlg.show();	}
676 //-----------------------------------------------------------------------------
with_arg(std::string ss,std::vector<std::string> prev)677 std::string with_arg(std::string ss, std::vector<std::string> prev)
678 {
679 	size_t l=ss.length(), n=prev.size();
680 	for(size_t i=0;i<n;i++)
681 		if(!strncmp(prev[i].c_str(),ss.c_str(),l))
682 		{	ss = prev[i];	break;	}
683 	return ss;
684 }
685 //-----------------------------------------------------------------------------
686 void cb_cmd_type(Fl_Widget*, void*);
687 void cb_cmd_cmd(Fl_Widget*, void*);
688 void cb_cmd_var(Fl_Widget*, void*);
689 void cb_cmd_args(Fl_Widget*, void*);
690 class NewCmdDlg : public GeneralDlg
691 {
692 	Fl_Choice *type, *cmd, *var;
693 	Fl_Group *desc;
694 	Fl_Select_Browser *args;
695 	Fl_Input *opt;
696 	Fl_Help_View *help;
697 	std::vector<std::string> cmds[17];	///< commands divided by type
698 public:
NewCmdDlg()699 	NewCmdDlg() : GeneralDlg()
700 	{
701 		Fl_Button *o;
702 		w = new Fl_Double_Window(780, 300, _("New command"));
703 		Fl_Group *g = new Fl_Group(5,5,315,320);
704 		type = new Fl_Choice(80, 5, 270, 25, _("Kind"));
705 		type->tooltip(_("Groups of MGL commands"));
706 		type->callback(cb_cmd_type);
707 		type->add(_("1D plots"));
708 		type->add(_("2D plots"));
709 		type->add(_("3D plots"));
710 		type->add(_("Dual plots"));
711 		type->add(_("Vector plots"));
712 		type->add(_("Other plots"));
713 		type->add(_("Text and legend"));
714 		type->add(_("Create data and IO"));
715 		type->add(_("Data transform"));
716 		type->add(_("Data handling"));
717 		type->add(_("Axis and colorbar"));
718 		type->add(_("Axis setup"));
719 		type->add(_("General setup"));
720 		type->add(_("Scale and rotate"));
721 		type->add(_("Program flow"));
722 		type->add(_("Primitives"));
723 
724 		cmd = new Fl_Choice(80, 35, 270, 25, _("Command"));
725 		cmd->tooltip(_("MGL commands for selected group"));
726 		cmd->callback(cb_cmd_cmd);
727 		var = new Fl_Choice(80, 95, 270, 25, _("Variant"));
728 		var->tooltip(_("Variant of command argument order. The notation is:\n"
729 								" * Capital arguments are data (like, Ydat);\n"
730 								" * Argument in '' are strings (like, 'fmt');\n"
731 								" * Other arguments are numbers (like, zval);\n"
732 								" * Arguments in [] are optional arguments."));
733 		var->callback(cb_cmd_var);
734 		desc = new Fl_Group(0, 65, 350, 25, _("Description"));
735 		desc->box(FL_ENGRAVED_BOX);	desc->labelsize(12);
736 		desc->align(FL_ALIGN_CENTER);	desc->end();
737 		desc->tooltip(_("Short description of selected command"));
738 		args = new Fl_Select_Browser(5, 140, 345, 95, _("Arguments"));
739 		args->align(FL_ALIGN_TOP_LEFT);	args->callback(cb_cmd_args);
740 		args->tooltip(_("Command arguments. Bold ones are required arguments.\n"
741 			"Other are optional arguments but its order is required.\n"
742 			"You can use '' for default format. See help at right\nfor default values."));
743 		static int widths[] = { 95, 250, 0 };  // widths for each column
744 		args->column_widths(widths);	args->column_char('\t');
745 
746 		opt = new Fl_Input(60, 240, 265, 25, _("Options"));
747 		o = new Fl_Button(325, 240, 25, 25, "...");	o->callback(option_in_cb,opt);
748 
749 		o = new Fl_Button(190, 270, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
750 		o = new Fl_Return_Button(275, 270, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
751 		g->end();	g->resizable(args);
752 
753 		help = new Fl_Help_View(360, 5, 415, 290);	help->labelsize(12);
754 		w->set_modal();	w->end();	w->resizable(help);
755 	}
init()756 	void init()	// fill cmds from parser for all categories
757 	{
758 		long i, n = Parse->GetCmdNum();
759 		for(i=0;i<n;i++)
760 		{
761 			std::string name = Parse->GetCmdName(i);
762 			switch(Parse->CmdType(name.c_str()))
763 			{
764 				case 1:	cmds[5].push_back(name);	break;
765 				case 2:	cmds[5].push_back(name);	break;
766 				case 3:	cmds[12].push_back(name);	break;
767 				case 4:	cmds[9].push_back(name);	break;
768 				case 5:	cmds[7].push_back(name);	break;
769 				case 6:	cmds[13].push_back(name);	break;
770 				case 7:	cmds[14].push_back(name);	break;
771 				case 8:	cmds[0].push_back(name);	break;
772 				case 9:	cmds[1].push_back(name);	break;
773 				case 10:cmds[2].push_back(name);	break;
774 				case 11:cmds[3].push_back(name);	break;
775 				case 12:cmds[4].push_back(name);	break;
776 				case 13:cmds[10].push_back(name);	break;
777 				case 14:cmds[15].push_back(name);	break;
778 				case 15:cmds[11].push_back(name);	break;
779 				case 16:cmds[6].push_back(name);	break;
780 				case 17:cmds[8].push_back(name);	break;
781 			}
782 		}
783 		type->value(0);	type_sel();
784 	}
type_sel()785 	void type_sel()	// fill list of commands for selected type
786 	{
787 		int t = type->value();	cmd->clear();
788 		for(size_t i=0;i<cmds[t].size();i++)	cmd->add(cmds[t][i].c_str());
789 		cmd->value(0);	cmd_sel();
790 	}
cmd_sel()791 	void cmd_sel()	// fill list of variants for selected command
792 	{
793 		static std::string str;
794 		const char *c = cmd->text();
795 		desc->label(Parse->CmdDesc(c));
796 		str = helpname+c;
797 		help->load(str.c_str());
798 		std::string par = Parse->CmdFormat(c), cname;
799 		std::vector<std::string> vars;
800 		size_t isp = par.find_first_of(' ');
801 		if(isp<par.length())
802 		{
803 			cname = par.substr(0,isp+1);
804 			par = par.substr(isp+1);
805 			while((isp=par.find_first_of('|'))<par.length())
806 			{
807 				vars.push_back(cname+par.substr(0,isp));
808 				par = par.substr(isp+1);
809 			}
810 			vars.push_back(cname+par);
811 		}
812 		else	vars.push_back(par);
813 		var->clear();
814 		for(size_t i=0;i<vars.size();i++)	var->add(vars[i].c_str());
815 		var->value(0);	var_sel();
816 	}
var_sel()817 	void var_sel()	// fill list of arguments for selected variant
818 	{
819 		std::string par = var->text(), sec;
820 		size_t isp = par.find_first_of(' ');
821 		par = par.substr(isp+1);	// remove command name
822 		isp = par.find_first_of('[');	// here secional args starts
823 		sec = isp<par.length()?par.substr(isp+1,par.length()-isp-2):"";
824 		par = isp>0?par.substr(0,isp-1):"";
825 		std::vector<std::string> prev_args;
826 		for(int i=1;i<=args->size();i++)
827 		{
828 			const char *s = args->text(i);
829 			if(s && *s && strchr(s,'\t'))	prev_args.push_back(s[0]=='@'?s+3:s);
830 		}
831 		args->clear();
832 		while((isp=par.find_first_of(' '))<par.length())
833 		{
834 			args->add(("@b "+with_arg(par.substr(0,isp), prev_args)).c_str());
835 			par = par.substr(isp+1);
836 		}
837 		if(!par.empty())	args->add(("@b "+with_arg(par, prev_args)).c_str());
838 		while((isp=sec.find_first_of(' '))<sec.length())
839 		{
840 			args->add(with_arg(sec.substr(0,isp), prev_args).c_str());
841 			sec = sec.substr(isp+1);
842 		}
843 		if(!sec.empty())	args->add(with_arg(sec, prev_args).c_str());
844 	}
args_sel()845 	void args_sel()	// fill argument by calling external dialog
846 	{
847 		int a = args->value();
848 		const char *s = args->text(a);	if(!s || *s==0)	return;
849 		std::string arg = s, val;
850 		size_t isp = arg.find_first_of('\t');
851 		val = arg.substr(isp+1);	arg = arg.substr(0,isp);
852 		if(arg[0]=='@')	arg = arg.substr(3);
853 		if(arg[0]>='A' && arg[0]<='Z')	datsel_dlg_cb(0,0);	// this is data
854 		else if(arg=="'fmt'")	style_dlg_cb(0,0);	// this is style
855 		else if(arg=="'fname'")	ins_fname_cb(0,0);	// this is file name
856 		else if(arg=="'path'")	ins_path_cb(0,0);	// this is path
857 		else if(arg=="'dir'")	dirsel_dlg_cb(0,0);	// this is path
858 		else if(arg[0]=='\'')	// this is general string
859 		{
860 			const char *s = fl_input(_("Enter value for %s argument"), val.c_str(), arg.c_str());
861 			if(s)
862 			{	std::string ss=s;	args_set(('\''+ss+'\'').c_str());	}
863 		}
864 		else	// this is general constant
865 		{
866 			const char *s = fl_input(_("Enter value for %s argument"), val.c_str(), arg.c_str());
867 			if(s)	args_set(s);
868 		}
869 	}
args_set(const char * val)870 	void args_set(const char *val)	// set value for current argument
871 	{
872 		int a = args->value();
873 		const char *s = args->text(a);	if(!s || *s==0)	return;
874 		std::string arg = s;
875 		size_t isp = arg.find_first_of('\t');
876 		arg = arg.substr(0,isp)+'\t'+val;
877 		args->text(a,arg.c_str());
878 	}
cb_ok()879 	void cb_ok()
880 	{
881 		std::string par = var->text();
882 		size_t isp = par.find_first_of(' ');
883 		result = par.substr(0,isp);	// command name
884 		for(int i=1;i<=args->size();i++)
885 		{
886 			const char *s = args->text(i);
887 			if(!s)	continue;
888 			const char *p = strchr(s,'\t');
889 			if(s[0]=='@' && !p)
890 			{
891 				fl_alert(_("Required argument %s is not specified!"),s+3);	return;
892 			}
893 			if(p)	result = result+' '+(p+1);
894 		}
895 		result += opt->value();
896 		if(e)
897 		{
898 			int p = textbuf->line_start(e->editor->insert_position());
899 			textbuf->insert(p, (result+'\n').c_str());
900 		}
901 		hide();
902 	}
903 //	void set_cmd(const char *line)	// TODO
904 //	{}
905 } newcmd_dlg;
906 //-----------------------------------------------------------------------------
cb_cmd_type(Fl_Widget *,void *)907 void cb_cmd_type(Fl_Widget*, void*)	{	newcmd_dlg.type_sel();	}
cb_cmd_cmd(Fl_Widget *,void *)908 void cb_cmd_cmd(Fl_Widget*, void*)	{	newcmd_dlg.cmd_sel();	}
cb_cmd_var(Fl_Widget *,void *)909 void cb_cmd_var(Fl_Widget*, void*)	{	newcmd_dlg.var_sel();	}
cb_cmd_args(Fl_Widget *,void *)910 void cb_cmd_args(Fl_Widget*, void*)	{	newcmd_dlg.args_sel();	}
cb_args_set(const char * val)911 void cb_args_set(const char *val)	{	newcmd_dlg.args_set(val);	}
912 //-----------------------------------------------------------------------------
newcmd_dlg_cb(Fl_Widget *,void * v)913 void newcmd_dlg_cb(Fl_Widget*,void *v)		// TODO parse current line?!?
914 {	newcmd_dlg.e=(ScriptWindow *)v;	newcmd_dlg.show();	}
915 //-----------------------------------------------------------------------------
916 void cb_setup_save(Fl_Widget*,void *v);
917 class SetupDlg : public GeneralDlg
918 {
919 	Fl_Choice *xlpos, *ylpos, *zlpos, *clpos;
920 	Fl_Float_Input *x1, *x2, *x0, *xtick, *xstick, *xotick;
921 	Fl_Input *xlabel, *xtmpl, *xfact;
922 	Fl_Float_Input *y1, *y2, *y0, *ytick, *ystick, *yotick;
923 	Fl_Input *ylabel, *ytmpl, *yfact;
924 	Fl_Float_Input *z1, *z2, *z0, *ztick, *zstick, *zotick;
925 	Fl_Input *zlabel, *ztmpl, *zfact;
926 	Fl_Float_Input *c1, *c2, *c0, *ctick;
927 	Fl_Input *clabel, *ctmpl, *cfact;
928 	Fl_Float_Input *alphadef, *ambient, *diffuse;
929 	Fl_Input *palette, *font_stl, *axis_stl, *plotid;
930 	Fl_Float_Input *fog, *fog_dz, *pendelta;
931 	Fl_Float_Input *meshnum, *facenum, *arr_size, *bar_size;
932 	Fl_Float_Input *mrk_size, *txt_size, *tick_size;
933 
934 	Fl_Check_Button *alpha, *light, *cut, *attach;
935 	Fl_Check_Button *origintick, *gray, *rotatetext;
936 	Fl_Choice *time, *tunetick, *ternary, *transptype;
937 	Fl_Spinner *variant;
938 
939 	Fl_Toggle_Button *lb[10];
940 	Fl_Choice *lc[10];
941 	Fl_Float_Input *lx[10], *ly[10], *lz[10], *lbr[10];
942 	Fl_Input *fname;
943 public:
SetupDlg()944 	SetupDlg() : GeneralDlg()
945 	{
946 		Fl_Button *o;	Fl_Group *g, *gg;
947 		w = new Fl_Double_Window(525, 395, _("Setup script"));
948 		Fl_Tabs* tt = new Fl_Tabs(0, 0, 525, 355);
949 		gg = new Fl_Group(0, 25, 525, 330, _("Axis setup"));
950 			new Fl_Box(85, 30, 100, 25, _("X axis"));
951 			x1 = new Fl_Float_Input(85, 55, 100, 25, _("Minimal"));
952 			x2 = new Fl_Float_Input(85, 85, 100, 25, _("Maximal"));
953 			x0 = new Fl_Float_Input(85, 115, 100, 25, _("Origin"));
954 			xlabel = new Fl_Input(85, 145, 100, 25, _("Label"));
955 			xtick = new Fl_Float_Input(85, 205, 100, 25, _("Ticks"));
956 			xlpos = new Fl_Choice(85, 175, 100, 25, _("at position"));
957 			xlpos->add(_("left"));	xlpos->add(_("center"));
958 			xlpos->add(_("right"));	xlpos->value(1);
959 			xstick = new Fl_Float_Input(85, 235, 100, 25, _("Subticks"));
960 			xotick = new Fl_Float_Input(85, 265, 100, 25, _("Ticks start"));
961 			xtmpl = new Fl_Input(85, 295, 100, 25, _("Template"));
962 			xfact = new Fl_Input(85, 325, 100, 25, _("Factor"));
963 			new Fl_Box(195, 30, 100, 25, _("Y axis"));
964 			y1 = new Fl_Float_Input(195, 55, 100, 25);
965 			y2 = new Fl_Float_Input(195, 85, 100, 25);
966 			y0 = new Fl_Float_Input(195, 115, 100, 25);
967 			ylabel = new Fl_Input(195, 145, 100, 25);
968 			ytick = new Fl_Float_Input(195, 205, 100, 25);
969 			ylpos = new Fl_Choice(195, 175, 100, 25);
970 			ylpos->add(_("left"));	ylpos->add(_("center"));
971 			ylpos->add(_("right"));	ylpos->value(1);
972 			ystick = new Fl_Float_Input(195, 235, 100, 25);
973 			yotick = new Fl_Float_Input(195, 265, 100, 25);
974 			ytmpl = new Fl_Input(195, 295, 100, 25);
975 			yfact = new Fl_Input(195, 325, 100, 25);
976 			new Fl_Box(305, 30, 100, 25, _("Z axis"));
977 			z1 = new Fl_Float_Input(305, 55, 100, 25);
978 			z2 = new Fl_Float_Input(305, 85, 100, 25);
979 			z0 = new Fl_Float_Input(305, 115, 100, 25);
980 			zlabel = new Fl_Input(305, 145, 100, 25);
981 			ztick = new Fl_Float_Input(305, 205, 100, 25);
982 			zlpos = new Fl_Choice(305, 175, 100, 25);
983 			zlpos->add(_("left"));	zlpos->add(_("center"));
984 			zlpos->add(_("right"));	zlpos->value(1);
985 			zstick = new Fl_Float_Input(305, 235, 100, 25);
986 			zotick = new Fl_Float_Input(305, 265, 100, 25);
987 			ztmpl = new Fl_Input(305, 295, 100, 25);
988 			zfact = new Fl_Input(305, 325, 100, 25);
989 			new Fl_Box(415, 30, 100, 25, _("C axis"));
990 			c1 = new Fl_Float_Input(415, 55, 100, 25);
991 			c2 = new Fl_Float_Input(415, 85, 100, 25);
992 			c0 = new Fl_Float_Input(415, 115, 100, 25);
993 			clabel = new Fl_Input(415, 145, 100, 25);
994 			ctick = new Fl_Float_Input(415, 205, 100, 25);
995 			clpos = new Fl_Choice(415, 175, 100, 25);
996 			clpos->add(_("left"));	clpos->add(_("center"));
997 			clpos->add(_("right"));	clpos->value(1);
998 			ctmpl = new Fl_Input(415, 295, 100, 25);
999 			cfact = new Fl_Input(415, 325, 100, 25);
1000 			gg->end();
1001 		gg = new Fl_Group(0, 25, 525, 330, _("General setup"));	gg->hide();
1002 			g = new Fl_Group(5, 45, 180, 305, _("Colors"));	g->box(FL_ENGRAVED_BOX);
1003 			alphadef = new Fl_Float_Input(80, 55, 100, 25, _("AlphaDef"));
1004 			ambient = new Fl_Float_Input(80, 85, 100, 25, _("Ambient"));
1005 			diffuse = new Fl_Float_Input(80, 115, 100, 25, _("Diffuse"));
1006 			palette = new Fl_Input(80, 145, 100, 25, _("Palette"));
1007 			font_stl = new Fl_Input(80, 175, 100, 25, _("Font"));
1008 			axis_stl = new Fl_Input(80, 205, 100, 25, _("Axis"));
1009 			fog = new Fl_Float_Input(80, 235, 100, 25, _("Fog"));
1010 			fog_dz = new Fl_Float_Input(80, 265, 100, 25, _("Fog dist."));
1011 			gray = new Fl_Check_Button(80, 290, 100, 25, _("grayscale"));
1012 			alpha = new Fl_Check_Button(10, 315, 65, 25, _("alpha"));
1013 			light = new Fl_Check_Button(80, 315, 100, 25, _("lighting"));
1014 			g->end();
1015 			g = new Fl_Group(185, 45, 180, 250, _("Sizes"));	g->box(FL_ENGRAVED_BOX);
1016 			meshnum = new Fl_Float_Input(260, 55, 100, 25, _("meshnum"));
1017 			facenum = new Fl_Float_Input(260, 85, 100, 25, _("facenum"));
1018 			arr_size = new Fl_Float_Input(260, 115, 100, 25, _("arrows"));
1019 			bar_size = new Fl_Float_Input(260, 145, 100, 25, _("bars"));
1020 			mrk_size = new Fl_Float_Input(260, 175, 100, 25, _("markers"));
1021 			txt_size = new Fl_Float_Input(260, 205, 100, 25, _("text"));
1022 			tick_size = new Fl_Float_Input(260, 235, 100, 25, _("ticks"));
1023 			pendelta = new Fl_Float_Input(260, 265, 100, 25, _("pen blur"));
1024 			g->end();
1025 			g = new Fl_Group(365, 45, 155, 305, _("Others"));	g->box(FL_ENGRAVED_BOX);
1026 			cut = new Fl_Check_Button(370, 50, 115, 25, _("cutting"));
1027 			attach = new Fl_Check_Button(370, 70, 115, 25, _("attach light"));
1028 			origintick = new Fl_Check_Button(370, 90, 115, 25, _("no origin tick"));
1029 			rotatetext = new Fl_Check_Button(370, 110, 115, 25, _("rotate text"));
1030 
1031 			time = new Fl_Choice(370, 150, 145, 25, _("Time ticks"));
1032 			time->add("none");	time->add("x");	time->add("y");	time->add("z");
1033 			time->align(FL_ALIGN_TOP_LEFT);	time->value(0);
1034 			tunetick = new Fl_Choice(370, 195, 145, 25, _("Tune ticks"));
1035 			tunetick->add(_("none"));	tunetick->add(_("factor"));
1036 			tunetick->add(_("increment"));	tunetick->add(_("both"));
1037 			tunetick->align(FL_ALIGN_TOP_LEFT);	tunetick->value(0);
1038 			ternary = new Fl_Choice(370, 235, 145, 25, _("Ternary"));
1039 			ternary->add(_("none"));	ternary->add(_("ternary"));
1040 			ternary->add(_("quaternary"));	ternary->add(_("projection"));
1041 			ternary->add(_("ternary proj"));	ternary->add(_("quaternary proj"));
1042 			ternary->align(FL_ALIGN_TOP_LEFT);	ternary->value(0);
1043 			transptype = new Fl_Choice(370, 275, 145, 25, _("Transparency type"));
1044 			transptype->add(_("default"));	ternary->add(_("glass-like"));
1045 			transptype->add(_("lamp-like"));
1046 			transptype->align(FL_ALIGN_TOP_LEFT);	transptype->value(0);
1047 			variant = new Fl_Spinner(370, 315, 145, 25, _("Variant"));
1048 			variant->align(FL_ALIGN_TOP_LEFT);	variant->range(0,100);	variant->value(0);
1049 			g->end();
1050 		plotid = new Fl_Input(190, 321, 172, 25, _("Plot ID"));
1051 		plotid->align(FL_ALIGN_TOP_LEFT);
1052 		gg->end();
1053 		gg = new Fl_Group(0, 25, 525, 330, _("Light settings"));	gg->hide();
1054 			static const char *id[10]={"0:","1:","2:","3:","4:","5:","6:","7:","8:","9:"};
1055 			for(int i=0;i<10;i++)
1056 			{
1057 				lb[i] = new Fl_Toggle_Button(10, 50+30*i, 25, 25, id[i]);
1058 				lx[i] = new Fl_Float_Input(40, 50+30*i, 90, 25);
1059 				ly[i] = new Fl_Float_Input(135, 50+30*i, 90, 25);
1060 				lz[i] = new Fl_Float_Input(230, 50+30*i, 90, 25);
1061 				lc[i] = new Fl_Choice(325, 50+30*i, 95, 25);
1062 				lbr[i]= new Fl_Float_Input(425, 50+30*i, 90, 25);
1063 				lc[i]->copy(colors);	lc[i]->value(0);
1064 			}
1065 			lx[0]->label(_("X position"));	lx[0]->align(FL_ALIGN_TOP_LEFT);
1066 			ly[0]->label(_("Y position"));	ly[0]->align(FL_ALIGN_TOP_LEFT);
1067 			lz[0]->label(_("Z position"));	lz[0]->align(FL_ALIGN_TOP_LEFT);
1068 			lc[0]->label(_("Color"));			lc[0]->align(FL_ALIGN_TOP_LEFT);
1069 			lbr[0]->label(_("Brightness"));	lbr[0]->align(FL_ALIGN_TOP_LEFT);
1070 			gg->end();	tt->end();
1071 		o = new Fl_Button(365, 365, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
1072 		o = new Fl_Return_Button(445, 365, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
1073 		fname = new Fl_Input(100, 365, 175, 25, _("File to export"));
1074 		o = new Fl_Button(275, 365, 25, 25, "@->");	o->callback(cb_setup_save);
1075 		o->tooltip(_("Keep empty to put at beginning of main script."));
1076 		w->end();
1077 	}
prepare()1078 	void prepare()
1079 	{
1080 		result.clear();
1081 		const char *s1, *s2, *s3, *s4;
1082 		s1=x1->value();	s2=x2->value();
1083 		if(s1 && *s1 && s2 && *s2)	result = result+"xrange "+s1+' '+s2+'\n';
1084 		s1=y1->value();	s2=y2->value();
1085 		if(s1 && *s1 && s2 && *s2)	result = result+"yrange "+s1+' '+s2+'\n';
1086 		s1=z1->value();	s2=z2->value();
1087 		if(s1 && *s1 && s2 && *s2)	result = result+"zrange "+s1+' '+s2+'\n';
1088 		s1=c1->value();	s2=c2->value();
1089 		if(s1 && *s1 && s2 && *s2)	result = result+"crange "+s1+' '+s2+'\n';
1090 		s1=x0->value();	s2=y0->value();	s3=z0->value();
1091 		if(s3 && *s3)	result = result+"origin "+(s1?s1:"nan")+' '+(s2?s2:"nan")+' '+s3+'\n';
1092 		else if(s2 && *s2)	result = result+"origin "+(s1?s1:"nan")+' '+s2+'\n';
1093 		else if(s1 && *s1)	result = result+"origin "+s1+"nan\n";
1094 
1095 		s1=xtmpl->value();	if(s1 && *s1)	result = result+"xtick '"+s1+"'\n";
1096 		s1=ytmpl->value();	if(s1 && *s1)	result = result+"ytick '"+s1+"'\n";
1097 		s1=ztmpl->value();	if(s1 && *s1)	result = result+"ztick '"+s1+"'\n";
1098 		s1=ctmpl->value();	if(s1 && *s1)	result = result+"ctick '"+s1+"'\n";
1099 
1100 		s1=xtick->value();	s2=xstick->value();	s3=xotick->value();	s4=xfact->value();
1101 		if(s4 && *s4)	result = result+"xtick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
1102 		else if(s3 && *s3)	result = result+"xtick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
1103 		else if(s2 && *s2)	result = result+"xtick "+(s1?s1:"0")+' '+s2+'\n';
1104 		else if(s1 && *s1)	result = result+"xtick "+s1+'\n';
1105 		s1=ytick->value();	s2=ystick->value();	s3=yotick->value();	s4=yfact->value();
1106 		if(s4 && *s4)	result = result+"ytick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
1107 		else if(s3 && *s3)	result = result+"ytick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
1108 		else if(s2 && *s2)	result = result+"ytick "+(s1?s1:"0")+' '+s2+'\n';
1109 		else if(s1 && *s1)	result = result+"ytick "+s1+'\n';
1110 		s1=ztick->value();	s2=zstick->value();	s3=zotick->value();	s4=zfact->value();
1111 		if(s4 && *s4)	result = result+"ztick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+(s3?s3:"nan")+" '"+s4+"'\n";
1112 		else if(s3 && *s3)	result = result+"ztick "+(s1?s1:"0")+' '+(s2?s2:"0")+' '+s3+'\n';
1113 		else if(s2 && *s2)	result = result+"ztick "+(s1?s1:"0")+' '+s2+'\n';
1114 		else if(s1 && *s1)	result = result+"ztick "+s1+'\n';
1115 		s1=ctick->value();	s4=cfact->value();
1116 		if(s4 && *s4)	result = result+"ctick "+(s1?s1:"0")+" '"+s4+"'\n";
1117 		else if(s1 && *s1)	result = result+"ctick "+s1+'\n';
1118 		const char *pos[3]={"' -1\n","' 0\n","' 1\n"};
1119 		s1=xlabel->value();	if(s1 && *s1)	result = result+"xlabel '"+s1+pos[xlpos->value()];
1120 		s1=ylabel->value();	if(s1 && *s1)	result = result+"ylabel '"+s1+pos[ylpos->value()];
1121 		s1=zlabel->value();	if(s1 && *s1)	result = result+"zlabel '"+s1+pos[zlpos->value()];
1122 //TODO	s1=clabel->value();	if(s1 && *s1)	result = result+"clabel '"+s1+pos[clpos->value()];
1123 
1124 		s1=alphadef->value();	if(s1 && *s1)	result = result+"alphadef "+s1+'\n';
1125 		s1=ambient->value();	if(s1 && *s1)	result = result+"ambient "+s1+'\n';
1126 		s1=diffuse->value();	if(s1 && *s1)	result = result+"diffuse "+s1+'\n';
1127 		s1=palette->value();	if(s1 && *s1)	result = result+"palette '"+s1+"'\n";
1128 		s1=plotid->value();		if(s1 && *s1)	result = result+"plotid '"+s1+"'\n";
1129 		s1=axis_stl->value();	if(s1 && *s1)	result = result+"axisstl '"+s1+"'\n";
1130 		s1=meshnum->value();	if(s1 && *s1)	result = result+"meshnum "+s1+'\n';
1131 		s1=facenum->value();	if(s1 && *s1)	result = result+"facenum "+s1+'\n';
1132 		s1=arr_size->value();	if(s1 && *s1)	result = result+"arrowsize "+s1+'\n';
1133 		s1=bar_size->value();	if(s1 && *s1)	result = result+"barwidth "+s1+'\n';
1134 		s1=mrk_size->value();	if(s1 && *s1)	result = result+"marksize "+s1+'\n';
1135 		s1=pendelta->value();	if(s1 && *s1)	result = result+"pendelta "+s1+'\n';
1136 		s1=tick_size->value();	if(s1 && *s1)	result = result+"ticklen "+s1+'\n';
1137 
1138 		s1=font_stl->value();	s2=txt_size->value();
1139 		if(s2 && *s2)	result = result+"font '"+(s1?s1:"")+"' "+s2+'\n';
1140 		else if(s1 && *s1)	result = result+"font '"+s1+"'\n";
1141 		s1=fog->value();	s2=fog_dz->value();
1142 		if(s1 && *s1 && s2 && *s2)	result = result+"fog "+s1+' '+s2+'\n';
1143 		else if(s1 && *s1)	result = result+"font "+s1+"\n";
1144 
1145 		if(alpha->value())	result = result+"alpha on\n";
1146 		if(light->value())	result = result+"light on\n";
1147 		if(cut->value())	result = result+"cut on\n";
1148 		if(attach->value())	result = result+"attachlight on\n";
1149 		if(gray->value())	result = result+"gray on\n";
1150 		if(rotatetext->value())	result = result+"rotatetext on\n";
1151 		if(origintick->value())	result = result+"origintick off\n";
1152 		if(variant->value()>0)
1153 		{	char buf[32];	snprintf(buf,31,"variant %ld\n",mgl_int(variant->value()));	result += buf;	}
1154 		const char *stime[4]={"''\n","'x'\n","'y'\n","'z'\n"};
1155 		if(time->value()>0)	result = result+"timetick "+stime[time->value()];
1156 		const char *stune[4]={" 0\n"," 1\n"," 2\n"," 3\n"};
1157 		if(tunetick->value()>0)	result = result+"tunetick "+stune[tunetick->value()];
1158 		const char *stern[6]={" 0\n"," 1\n"," 2\n"," 4\n"," 5\n"," 6\n"};
1159 		if(ternary->value()>0)	result = result+"ternary "+stern[ternary->value()];
1160 		const char *stype[3]={" 0\n"," 1\n"," 2\n"};
1161 		if(transptype->value()>0)	result = result+"ternary "+stype[transptype->value()];
1162 		for(int i=0;i<10;i++)
1163 		{
1164 			if(!lb[i]->value())	continue;
1165 			s1 = lx[i]->value();	s2 = ly[i]->value();
1166 			s3 = lz[i]->value();	s4 = lbr[i]->value();
1167 			char col = cols[lc[i]->value()];	if(col==' ')	col='w';
1168 			if(s1 && *s1 && s2 && *s2 && s3 && *s3)
1169 			{
1170 				result = result+"light "+char('0'+i)+' '+s1+' '+s2+' '+s3+" '"+col+'\'';
1171 				if(s4 && *s4)	result = result+' '+s4;
1172 				result += '\n';
1173 			}
1174 		}
1175 	}
cb_ok()1176 	void cb_ok()
1177 	{
1178 		prepare();
1179 		if(e)	{	e->draw->script=result;	e->graph->update();	}
1180 		hide();
1181 	}
save()1182 	void save()
1183 	{
1184 		prepare();
1185 		const char *s=fname->value();
1186 		if(s && *s)
1187 		{
1188 			FILE *fp = fl_fopen(s,"wt");
1189 			if(fp)	{	fputs(result.c_str(),fp);	fclose(fp);	}
1190 			else	fl_alert(_("Couldn't open file %s"),s);
1191 		}
1192 		else
1193 		{
1194 			textbuf->insert(0, ("##### setup start #####\n" + result + "##### setup end #####\n").c_str());
1195 //			if(e)	e->draw->script="";
1196 		}
1197 	}
1198 } setup_dlg;
1199 //-----------------------------------------------------------------------------
setup_dlg_cb(Fl_Widget *,void * v)1200 void setup_dlg_cb(Fl_Widget*,void *v)
1201 {	setup_dlg.e = (ScriptWindow*)v;	setup_dlg.show();	}
1202 //-----------------------------------------------------------------------------
cb_setup_save(Fl_Widget *,void * v)1203 void cb_setup_save(Fl_Widget*,void *v)	{	setup_dlg.save();	}
1204 //-----------------------------------------------------------------------------
1205 void cp_inplot_upd(Fl_Widget*,void*);
1206 void cb_only_inplot(Fl_Widget*,void*);
1207 class InplotDlg : public GeneralDlg
1208 {
1209 	Fl_Round_Button *k1, *k2, *k3, *k4, *k5, *k6;
1210 	Fl_Spinner *n1, *m1, *i1;
1211 	Fl_Counter *x1, *y1;
1212 	Fl_Spinner *n2, *m2, *i2, *x2, *y2;
1213 	Fl_Spinner *n3, *m3, *i3;
1214 	Fl_Counter *d3;
1215 	Fl_Spinner *n4, *i4;
1216 	Fl_Counter *d4;
1217 	Fl_Spinner *n5, *i5;
1218 	Fl_Float_Input *xx1, *xx2, *yy1, *yy2;
1219 	Fl_Spinner *tet, *phi;
1220 	Fl_Float_Input *ax, *ay;
1221 	Fl_Check_Button *rl, *rb, *rt, *rr, *rw;
1222 	Fl_Input *text;
1223 	Fl_Output *res;
1224 	Fl_MathGL *gr;
1225 public:
InplotDlg()1226 	InplotDlg() : GeneralDlg()
1227 	{
1228 		Fl_Button *o;
1229 		w = new Fl_Double_Window(715, 315, _("Add inplot"));
1230 		k1 = new Fl_Round_Button(5, 5, 105, 25, "SubPlot");
1231 		k1->callback(cb_only_inplot,k1);	k1->type(FL_RADIO_BUTTON);
1232 		n1 = new Fl_Spinner(145, 5, 55, 25, "nx");
1233 		n1->callback(cp_inplot_upd);	n1->range(1,100);
1234 		m1 = new Fl_Spinner(230, 5, 55, 25, "ny");
1235 		m1->callback(cp_inplot_upd);	m1->range(1,100);
1236 		i1 = new Fl_Spinner(315, 5, 55, 25, _("ind"));
1237 		i1->callback(cp_inplot_upd);	i1->value(0);
1238 		x1 = new Fl_Counter(400, 5, 95, 25, "dx");		x1->align(FL_ALIGN_LEFT);
1239 		x1->callback(cp_inplot_upd);	x1->value(0);	x1->step(0.01);	x1->lstep(0.1);
1240 		y1 = new Fl_Counter(525, 5, 95, 25, "dy");		y1->align(FL_ALIGN_LEFT);
1241 		y1->callback(cp_inplot_upd);	y1->value(0);	y1->step(0.01);	y1->lstep(0.1);
1242 
1243 		k2 = new Fl_Round_Button(5, 35, 105, 25, "MultiPlot");
1244 		k2->callback(cb_only_inplot,k2);	k2->type(FL_RADIO_BUTTON);
1245 		n2 = new Fl_Spinner(145, 35, 55, 25, "nx");
1246 		n2->callback(cp_inplot_upd);	n2->range(1,100);
1247 		m2 = new Fl_Spinner(230, 35, 55, 25, "ny");
1248 		m2->callback(cp_inplot_upd);	m2->range(1,100);
1249 		i2 = new Fl_Spinner(315, 35, 55, 25, _("ind"));
1250 		i2->callback(cp_inplot_upd);	i2->value(0);
1251 		x2 = new Fl_Spinner(425, 35, 70, 25, "x-size");
1252 		x2->callback(cp_inplot_upd);	x2->value(1);
1253 		y2 = new Fl_Spinner(550, 35, 70, 25, "y-size");
1254 		y2->callback(cp_inplot_upd);	y2->value(1);
1255 
1256 		k3 = new Fl_Round_Button(5, 65, 105, 25, "GridPlot");
1257 		k3->callback(cb_only_inplot,k3);	k3->type(FL_RADIO_BUTTON);
1258 		n3 = new Fl_Spinner(145, 65, 55, 25, "nx");
1259 		n3->callback(cp_inplot_upd);	n3->range(1,100);
1260 		m3 = new Fl_Spinner(230, 65, 55, 25, "ny");
1261 		m3->callback(cp_inplot_upd);	m3->range(1,100);
1262 		i3 = new Fl_Spinner(315, 65, 55, 25, _("ind"));
1263 		i3->callback(cp_inplot_upd);	i3->value(0);
1264 		d3 = new Fl_Counter(400, 65, 95, 25, "d");	d3->align(FL_ALIGN_LEFT);
1265 		d3->callback(cp_inplot_upd);	d3->step(0.01);	d3->lstep(0.1);
1266 
1267 		k4 = new Fl_Round_Button(5, 95, 105, 25, "ColumnPlot");
1268 		k4->callback(cb_only_inplot,k4);	k4->type(FL_RADIO_BUTTON);
1269 		n4 = new Fl_Spinner(145, 95, 55, 25, "nx");
1270 		n4->callback(cp_inplot_upd);	n4->range(1,100);
1271 		i4 = new Fl_Spinner(315, 95, 55, 25, _("ind"));
1272 		i4->callback(cp_inplot_upd);	i4->value(0);
1273 		d4 = new Fl_Counter(400, 95, 95, 25, "d");	d4->align(FL_ALIGN_LEFT);
1274 		d4->callback(cp_inplot_upd);	d4->step(0.01);	d4->lstep(0.1);
1275 
1276 		k5 = new Fl_Round_Button(5, 125, 105, 25, "StickPlot");
1277 		k5->callback(cb_only_inplot,k5);	k5->type(FL_RADIO_BUTTON);
1278 		n5 = new Fl_Spinner(145, 125, 55, 25, "nx");
1279 		n5->callback(cp_inplot_upd);	n5->range(1,100);
1280 		i5 = new Fl_Spinner(315, 125, 55, 25, _("ind"));
1281 		i5->callback(cp_inplot_upd);	i5->value(0);
1282 
1283 		k6 = new Fl_Round_Button(5, 155, 105, 25, "InPlot");
1284 		k6->callback(cb_only_inplot,k6);	k6->type(FL_RADIO_BUTTON);
1285 		xx1 = new Fl_Float_Input(145, 155, 60, 25, "x:");
1286 		xx1->callback(cp_inplot_upd);	xx1->value("0");
1287 		xx2 = new Fl_Float_Input(225, 155, 60, 25, "...");
1288 		xx2->callback(cp_inplot_upd);	xx2->value("1");
1289 		yy1 = new Fl_Float_Input(315, 155, 60, 25, "y:");
1290 		yy1->callback(cp_inplot_upd);	yy1->value("0");
1291 		yy2 = new Fl_Float_Input(400, 155, 60, 25, "...");
1292 		yy2->callback(cp_inplot_upd);	yy2->value("1");
1293 
1294 		tet = new Fl_Spinner(75, 190, 60, 25, _("Rotate on"));
1295 		tet->callback(cp_inplot_upd);	tet->value(0);	tet->step(5);	tet->range( -90, 90);
1296 		phi = new Fl_Spinner(170, 190, 60, 25, _("and"));
1297 		phi->callback(cp_inplot_upd);	phi->value(0);	phi->step(5);	phi->range(-180,180);
1298 		ax = new Fl_Float_Input(315, 190, 60, 25, _("Aspect x/z"));
1299 		ax->callback(cp_inplot_upd);	ax->value("1");
1300 		ay = new Fl_Float_Input(400, 190, 60, 25, "y/z");
1301 		ay->callback(cp_inplot_upd);	ay->value("1");
1302 
1303 		new Fl_Box(0, 225, 90, 25, _("Reserve at:"));
1304 		rl = new Fl_Check_Button(90, 225, 70, 25, _("left"));
1305 		rl->callback(cp_inplot_upd);	rl->value(1);
1306 		rb = new Fl_Check_Button(160, 225, 70, 25, _("bottom"));
1307 		rb->callback(cp_inplot_upd);	rb->value(1);
1308 		rt = new Fl_Check_Button(230, 225, 70, 25, _("top"));
1309 		rt->callback(cp_inplot_upd);	rt->value(1);
1310 		rr = new Fl_Check_Button(300, 225, 70, 25, _("right"));
1311 		rr->callback(cp_inplot_upd);	rr->value(1);
1312 		rw = new Fl_Check_Button(370, 225, 90, 25, _("whole area"));	rw->callback(cp_inplot_upd);
1313 		text = new Fl_Input(80, 255, 320, 25, _("Title"));	text->callback(cp_inplot_upd);
1314 		o = new Fl_Button(400, 255, 60, 25, _("Style"));	o->callback(style_dlg_cb,0);
1315 		res = new Fl_Output(50, 285, 410, 25, _("Result"));
1316 		gr = new Fl_MathGL(470, 130, 240, 180);	gr->box(FL_ENGRAVED_BOX);	gr->use_pthr = false;
1317 		mgl_set_size(gr->get_graph(),240,180);	gr->align(FL_ALIGN_LEFT);
1318 		o = new Fl_Button(545, 95, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
1319 		o = new Fl_Return_Button(630, 95, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
1320 		o = new Fl_Button(630, 60, 75, 25, _("Refresh"));	o->callback(cp_inplot_upd);
1321 		w->set_modal();	w->end();
1322 	}
init()1323 	void init()	{	style_dlg.result.clear();	}
update()1324 	void update()
1325 	{
1326 		std::string how, title, script;
1327 		if(rw->value())	// prepare space reservation
1328 			how="#";
1329 		else
1330 		{
1331 			if(rl->value())	how+='<';
1332 			if(rb->value())	how+='_';
1333 			if(rt->value())	how+='^';
1334 			if(rr->value())	how+='>';
1335 		}
1336 		char buf[128];	result.clear();
1337 		const char *s=text->value();
1338 		if(s && *s)	// prepare title
1339 		{
1340 			std::string fmt = style_dlg.result;
1341 			snprintf(buf,127,"title '%s'",s);	title = buf;
1342 			if(fmt.empty())	title += ':';
1343 			else	title += ' '+fmt+':';
1344 		}
1345 		if(k1->value())	// subplot
1346 		{
1347 			long n=mgl_int(n1->value()), m=mgl_int(m1->value()), k=mgl_int(i1->value());
1348 			i1->range(0, m*n-1);	// set to be sure if n or m are changed
1349 			snprintf(buf,127,"subplot %ld %ld %ld '%s' %g %g:", n,m,k, how.c_str(), x1->value(), y1->value());
1350 			result = buf+title;
1351 			double t=tet->value(), p=phi->value();
1352 			if(t!=0 || p!=0)
1353 			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
1354 			for(long i=0;i<m*n;i++)	if(i!=k)
1355 			{	snprintf(buf,127,"subplot %ld %ld %ld:box 'c'\n", n,m,i);	script += buf;	}
1356 		}
1357 		else if(k2->value())	// multiplot
1358 		{
1359 			long n=mgl_int(n2->value()), m=mgl_int(m2->value()), k=mgl_int(i2->value());
1360 			long x=mgl_int(x2->value()), y=mgl_int(y2->value());
1361 			i2->range(0, m*n-1);	x2->range(0, n-1);	y2->range(0, m-1);	// set to be sure if n or m are changed
1362 			snprintf(buf,127,"multiplot %ld %ld %ld %ld %ld '%s':", n,m,k,x,y, how.c_str());
1363 			result = buf+title;
1364 			double t=tet->value(), p=phi->value();
1365 			if(t!=0 || p!=0)
1366 			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
1367 			for(long i=0;i<m*n;i++)	if(i!=k)
1368 			{	snprintf(buf,127,"subplot %ld %ld %ld:box 'c'\n", n,m,i);	script += buf;	}
1369 		}
1370 		else if(k3->value())	// gridplot
1371 		{
1372 			long n=mgl_int(n3->value()), m=mgl_int(m3->value()), k=mgl_int(i3->value());
1373 			double d=d3->value();
1374 			i3->range(0, m*n-1);	// set to be sure if n or m are changed
1375 			snprintf(buf,127,"gridplot %ld %ld %ld %g:", n,m,k,d);
1376 			result = buf;
1377 			for(long i=0;i<m*n;i++)	if(i!=k)
1378 			{	snprintf(buf,127,"gridplot %ld %ld %ld %g:box 'c'\n", n,m,k,d);	script += buf;	}
1379 		}
1380 		else if(k4->value())	// columnplot
1381 		{
1382 			long n=mgl_int(n4->value()), k=mgl_int(i4->value());
1383 			double d=d4->value();
1384 			i4->range(0, n-1);	// set to be sure if n or m are changed
1385 			snprintf(buf,127,"columnplot %ld %ld %g:", n,k,d);	result = buf;
1386 			double t=tet->value(), p=phi->value();
1387 			std::string rot="";
1388 			if(t!=0 || p!=0)
1389 			{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	rot = buf;	}
1390 			for(long i=0;i<n;i++)	if(i!=k)
1391 			{	snprintf(buf,127,"columnplot %ld %ld %g:%sbox 'c'\n", n,k,d,rot.c_str());	script += buf;	}
1392 		}
1393 		else if(k5->value())	// stickplot
1394 		{
1395 			long n=mgl_int(n5->value()), k=mgl_int(i5->value());
1396 			i5->range(0, n-1);	// set to be sure if n or m are changed
1397 			double t=tet->value(), p=phi->value();
1398 			snprintf(buf,127,"stickplot %ld %ld %g %g:", n,k,t,p);	result = buf;
1399 			for(long i=0;i<n;i++)	if(i!=k)
1400 			{	snprintf(buf,127,"stickplot %ld %ld %g %g:box 'c'\n", n,k,t,p);	script += buf;	}
1401 		}
1402 		else if(k6->value())	// inplot
1403 		{
1404 			std::string sx1=xx1->value(), sx2=xx2->value(), sy1=yy1->value(), sy2=yy2->value();
1405 			if(!sx1.empty() && !sy1.empty() && !sx2.empty() && !sy2.empty())
1406 			{
1407 				snprintf(buf,127,"inplot %s %s %s %s:", sx1.c_str(), sx2.c_str(), sy1.c_str(), sy2.c_str());
1408 				result = buf;
1409 				double t=tet->value(), p=phi->value();
1410 				if(t!=0 || p!=0)	{	snprintf(buf,127,"rotate %g %g:", t,p);	result += buf;	}
1411 			}
1412 			script = "subplot 1 1 0:box 'c'\n";
1413 		}
1414 		double aspx = atof(ax->value()), aspy = atof(ay->value());
1415 		snprintf(buf,127,"aspect %g %g 1",aspx,aspy);
1416 		if(aspx!=0 && aspy!=0 && (aspx!=1 || aspy!=1))	result += buf;
1417 		script = "clf\n"+script+result+"\nbox\n";
1418 		res->value(result.c_str());
1419 
1420 		mglParse pr;
1421 		mgl_parse_text(gr->get_graph(), pr.Self(), script.c_str());
1422 		gr->update();
1423 	}
cb_ok()1424 	void cb_ok()
1425 	{
1426 		update();
1427 		if(e)
1428 		{
1429 			int p = textbuf->line_start(e->editor->insert_position());
1430 			textbuf->insert(p, (result+'\n').c_str());
1431 		}
1432 		hide();
1433 	}
1434 } inplot_dlg;
1435 //-----------------------------------------------------------------------------
cp_inplot_upd(Fl_Widget *,void *)1436 void cp_inplot_upd(Fl_Widget*,void*)	{	inplot_dlg.update();	}
cb_only_inplot(Fl_Widget *,void * v)1437 void cb_only_inplot(Fl_Widget*,void *v)
1438 {	((Fl_Round_Button*)v)->setonly();	inplot_dlg.update();	}
1439 //-----------------------------------------------------------------------------
inplot_dlg_cb(Fl_Widget *,void * v)1440 void inplot_dlg_cb(Fl_Widget*,void *v)
1441 {	inplot_dlg.e = (ScriptWindow*)v;	inplot_dlg.show();	}
1442 //-----------------------------------------------------------------------------
1443 class PrimDlg : public GeneralDlg
1444 {
1445 	Fl_Choice *kind, *col, *arr1, *arr2, *dash, *mark;
1446 	Fl_Check_Button *fill;
1447 	Fl_Input *text;
1448 	Fl_Spinner *num;
1449 public:
PrimDlg()1450 	PrimDlg() : GeneralDlg()
1451 	{
1452 		Fl_Button *o;
1453 		w = new Fl_Double_Window(295, 200, _("Add primitive"));
1454 		Fl_Menu_Item k[]={{_("marker")}, {_("line")}, { _("rectangle")},
1455 			{_("curve")}, {_("rhomb")}, { _("ellipse")},
1456 			{_("arc")}, {_("polygon")}, { _("text")}, {0}};
1457 		kind = new Fl_Choice(65, 10, 75, 25, _("Kind"));
1458 		kind->copy(k);		kind->value(0);
1459 		col = new Fl_Choice(205, 10, 75, 25, _("Color"));
1460 		col->copy(colors);	col->value(4);
1461 		arr1 = new Fl_Choice(65, 40, 75, 25, _("Begin"));
1462 		arr1->copy(arrows);	arr1->value(0);
1463 		arr2 = new Fl_Choice(205, 40, 75, 25, _("End"));
1464 		arr2->copy(arrows);	arr2->value(0);
1465 		dash = new Fl_Choice(65, 70, 75, 25, _("Dash"));
1466 		dash->copy(dashing);	dash->value(0);
1467 		mark = new Fl_Choice(205, 70, 75, 25, _("Mark"));
1468 		mark->copy(markers);	mark->value(0);	mark->value(2);
1469 		num = new Fl_Spinner(65, 100, 75, 25, _("Edges"));
1470 		num->range(1,100);	num->value(5);
1471 		fill = new Fl_Check_Button(205, 100, 75, 25, _("wire"));	fill->value(1);
1472 		text = new Fl_Input(65, 130, 215, 25, _("Text"));
1473 		o = new Fl_Button(120, 165, 75, 25, _("Cancel"));	o->callback(cb_dlg_cancel,this);
1474 		o = new Fl_Return_Button(205, 165, 75, 25, _("OK"));	o->callback(cb_dlg_ok,this);
1475 		w->set_modal();	w->end();
1476 	}
cb_ok()1477 	void cb_ok()
1478 	{
1479 		result.clear();
1480 		int k = kind->value();
1481 		char c = cols[col->value()];	if(c==' ')	c='w';
1482 		char dsh = dash->text()[1];
1483 		char a1 = arr1->text()[1], a2 = arr2->text()[1];
1484 		const char *s = mark->text();
1485 		char mrk = (s && *s=='\'')? s[1]:0;
1486 		switch(k)
1487 		{
1488 		case 0:
1489 			if(!mrk)	{	fl_alert(_("You need to select marker!"));	return;	}
1490 			result = "ball 0 0 '";
1491 			if(!fill->value())	result += '&';
1492 			result = result+mrk+c+"'\n";	break;
1493 		case 1:
1494 			result = "line -0.2 0 0.2 0 '2";
1495 			if(dsh!=' ' && dsh!='-')	result += dsh;
1496 			if(a1!='_')	result = result+a2+a1;
1497 			else if(a2!='_')	result += a2;
1498 			result = result+c+"'\n";	break;
1499 		case 2:
1500 			result = "rect -0.2 -0.2 0.2 0.2 '2";
1501 			if(!fill->value())	result += '#';
1502 			result = result+c+"'\n";	break;
1503 		case 3:
1504 			result = "curve -0.2 0 0 0.5 0.2 0 0 0.5 '2";
1505 			if(dsh!=' ' && dsh!='-')	result += dsh;
1506 			if(a1!='_')	result = result+a2+a1;
1507 			else if(a2!='_')	result += a2;
1508 			result = result+c+"'\n";	break;
1509 		case 4:
1510 			result = "rhomb -0.2 0 0.2 0 0.1 '2";
1511 			if(!fill->value())	result += '#';
1512 			result = result+c+"'\n";	break;
1513 		case 5:
1514 			result = "ellipse -0.2 0 0.2 0 0.1 '2";
1515 			if(!fill->value())	result += '#';
1516 			result = result+c+"'\n";	break;
1517 		case 6:
1518 			result = "arc 0 0 0.2 0 60 '2";
1519 			if(dsh!=' ' && dsh!='-')	result += dsh;
1520 			if(a1!='_')	result = result+a2+a1;
1521 			else if(a2!='_')	result += a2;
1522 			result = result+c+"'\n";	break;
1523 		case 7:
1524 			result = "polygon 0 0 0 0.2 "+mgl_str_num(num->value())+" '2";
1525 			if(!fill->value())	result += '#';
1526 			result = result+c+"'\n";	break;
1527 		case 8:
1528 			s = text->value();
1529 			if(!s || *s==0)	{	fl_alert(_("You need to enter text!"));	return;	}
1530 			result = result+"text 0 0 0.1 0 '"+s+"' '"+c;
1531 			if(fill->value())	result += ":w";
1532 			result = result+"'\n";	break;
1533 		}
1534 		if(e)	{	e->graph->FMGL->prim += result;	e->graph->update();	}
1535 		hide();
1536 	}
1537 } prim_dlg;
1538 //-----------------------------------------------------------------------------
prim_dlg_cb(Fl_Widget *,void * v)1539 void prim_dlg_cb(Fl_Widget*, void* v)
1540 {	prim_dlg.e=(ScriptWindow*)v;	prim_dlg.show();	}
1541 //-----------------------------------------------------------------------------
1542