1 // ----------------------------------------------------------------------------
2 //
3 // 	newinstall.cxx
4 //
5 // Copyright (C) 2007-2014 Dave Freese, W1HKJ
6 // Copyright (C) 2010 Stelios Bounanos, M0GLD
7 //
8 // This file is part of fldigi.
9 //
10 // Fldigi is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Fldigi is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
22 // ----------------------------------------------------------------------------
23 
24 #include <config.h>
25 
26 #include "macros.h"
27 
28 #include "main.h"
29 
30 #include "fl_digi.h"
31 #include "configuration.h"
32 #include "confdialog.h"
33 #include "record_browse.h"
34 #include "record_loader.h"
35 #include "logger.h"
36 #include "tabdefs.h"
37 
38 #include <string>
39 #include <ctime>
40 #include <iostream>
41 #include <fstream>
42 #include <sys/stat.h>
43 
44 using namespace std;
45 
46 static string label[24];
47 static string text[24];
48 
newmacros()49 void newmacros()
50 {
51 label[0] = "RsID CQ";
52 text[0] = "<TXRSID:on><TX>\n\
53 CQ CQ CQ de <MYCALL> <MYCALL> <MYCALL>\n\
54 CQ CQ CQ de <MYCALL> <MYCALL> <MYCALL> pse k\n\
55 <RX><@TXRSID:off>";
56 
57 label[1] = "ANS @>|";
58 text[1] = "<TX>\
59 <CALL> <CALL> de <MYCALL> <MYCALL> <MYCALL> kn\n\
60 <RX>";
61 
62 label[2] ="QSO @>>";
63 text[2] = "<TX>\n\
64 <CALL> de <MYCALL> ";
65 
66 label[3] = "KN @||";
67 text[3] = " btu <NAME> <CALL> de <MYCALL> k\n\
68 <RX>";
69 
70 label[4] = "SK @||";
71 text[4] = "\n\
72 tnx fer QSO <NAME>, 73.\n\
73 <ZDT> <CALL> de <MYCALL> sk\n\
74 <RX>";
75 
76 label[5] = "Me/Qth";
77 text[5] = "\n\
78 op:  <MYNAME>\n\
79 qth: <MYQTH>\n\
80 loc: <MYLOC>\n";
81 
82 label[6] = "Brag";
83 text[6] = "\n\
84 << <MYCALL>, <MYNAME> >>\n\
85 Age:   \n\
86 Rig:   \n\
87 Pwr:   \n\
88 Ant:   \n\
89 OS:    \n\
90 Soft:  <VER>\n\
91 Web:   \n\
92 Email: ";
93 
94 label[7] = "";
95 text[7] = "";
96 
97 label[8] = "T/R";
98 text[8] = "<TX/RX>";
99 
100 label[9] = "Tx @>>";
101 text[9] = "<TX>";
102 
103 label[10] = "Rx @||";
104 text[10] = "<RX>";
105 
106 label[11] = "TX @>|";
107 text[11] = "<TX>\n\
108 de <MYCALL> k\n\
109 <RX>";
110 
111 label[12] = "C Ans @>|";
112 text[12] = "<TX>de <MYCALL> <MYCALL><RX>";
113 
114 label[13] = "C rpt @>|";
115 text[13] = "<TX><CNTR> <CNTR> QSL DE <MYCALL> K\n\
116 <RX>";
117 
118 label[14] = "C Rep @>|";
119 text[14] = "<TX>\n\
120 <CALL> RR NBR <CNTR> <CNTR> TU DE <MYCALL> K\n\
121 <RX>";
122 
123 label[15] = "C Incr";
124 text[15] = "<INCR>";
125 
126 label[16] = "C Decr";
127 text[16] = "<DECR>";
128 
129 label[17] = "Log QSO";
130 text[17] = "<LOG><INCR>";
131 
132 label[18] = "CW-CQ @>|";
133 text[18] = "<TX>CQ CQ CQ DE <MYCALL> <MYCALL>  CQ CQ CQ DE <MYCALL> K<RX>";
134 
135 label[19] = "";
136 text[19] = "";
137 
138 label[20] = "CQ @-3+";
139 text[20] = "<TX>\n\
140 <IDLE:5>CQ CQ CQ de <MYCALL> <MYCALL>\n\
141 CQ CQ CQ de <MYCALL> k<RX><TIMER:15>";
142 
143 label[21] = "CQ-ID @>|";
144 text[21] = "<TX><ID>\n\
145 CQ CQ CQ de <MYCALL> <MYCALL>\n\
146 CQ CQ CQ de <MYCALL> <MYCALL> K\n\
147 <RX>";
148 
149 label[22] = "";
150 text[22] = "";
151 
152 label[23] = "";
153 text[23] = "";
154 
155 	for (int i = 0; i < 24; i++) {
156 		macros.text[i] = text[i];
157 		macros.name[i] = label[i];
158 	}
159 	for (int i = 24; i < MAXMACROS; i++) {
160 		macros.text[i] = "";
161 		macros.name[i] = "";
162 	}
163 }
164 
165 struct paldata {
166 	const char *fname;
167 	const char *rgbstr0;
168 	const char *rgbstr1;
169 	const char *rgbstr2;
170 	const char *rgbstr3;
171 	const char *rgbstr4;
172 	const char *rgbstr5;
173 	const char *rgbstr6;
174 	const char *rgbstr7;
175 	const char *rgbstr8;
176 };
177 
178 paldata palfiles[] = {
179 	{	"banana.pal", "  0;  0;  0",
180 		" 59; 59; 27","119;119; 59","179;179; 91","227;227;123",
181 		"235;235;151","239;239;183","247;247;219","255;255;255"
182 	},
183 	{	"blue1.pal","  0;  0;  2",
184 		"  0;  0; 64","  7; 11;128"," 39; 47;192"," 95;115;217",
185 		"151;179;231","187;203;239","219;227;247","255;255;255"
186 	},
187 	{	"blue2.pal","  3;  3; 64",
188 		"  7; 11;128"," 39; 47;192"," 95;115;217","151;179;231",
189 		"187;203;239","219;227;247","255;255;255","255;253;108"
190 	},
191 	{	"blue3.pal","  0;  0;  0",
192 		" 31; 31; 31"," 63; 63; 63"," 91; 91;167","119;119;191",
193 		"155;155;219","191;191;191","223;223;223","255;255;255"
194 	},
195 	{	"brown.pal","  0;  0;  0",
196 		"107; 63; 11","175; 95; 31","199;119; 43","215;163; 63",
197 		"231;211; 87","243;247;111","247;251;179","255;255;255"
198 	},
199 	{	"cyan1.pal","  0;  0;  0",
200 		"  5; 10; 10"," 22; 42; 42"," 52; 99; 99"," 94;175;175",
201 		"131;209;209","162;224;224","202;239;239","255;255;255"
202 	},
203 	{	"cyan2.pal","  0;  0;  0",
204 		" 35; 51; 51"," 75;103;103","115;159;159","155;211;211",
205 		"183;231;231","203;239;239","227;247;247","255;255;255"
206 	},
207 	{	"cyan3.pal","  0;  0;  0",
208 		" 94;114;114","138;162;162","171;201;201","199;232;232",
209 		"216;243;243","228;247;247","241;251;251","255;255;255"
210 	},
211 	{   "default.pal", "  0;  0;  0",
212         "  0;  6;136","  0; 19;198","  0; 32;239","172;167;105",
213         "194;198; 49","225;228;107","255;255;  0","255; 51;  0"
214     },
215 	{	"digipan.pal","  0;  0;  0",
216         "  0;  0; 64","  0;  0;128","  0;  0;217","150;147; 92",
217         "183;186; 46","225;228;107","255;255;  0","255; 51;  0"
218 	},
219 	{	"fldigi.pal","  0;  0;  0",
220         "  0;  0;177","  3;110;227","  0;204;204","223;223;223",
221         "  0;234;  0","244;244;  0","250;126;  0","244;  0;  0"
222 	},
223 	{	"gmfsk.pal","  0;  0;256",
224 		"  0; 62;194","  0;126;130","  0;190; 66","  0;254;  2",
225 		" 62;194;  0","126;130;  0","190; 66;  0","254;  2;  0"
226 	},
227 	{	"gray1.pal","  0;  0;  0",
228 		" 69; 69; 69"," 99; 99; 99","121;121;121","140;140;140",
229 		"157;157;157","172;172;172","186;186;186","199;199;199"
230 	},
231 	{	"gray2.pal","  0;  0;  0",
232 		" 88; 88; 88","126;126;126","155;155;155","179;179;179",
233 		"200;200;200","220;220;220","237;237;237","254;254;254"
234 	},
235 	{	"green1.pal","  0;  0;  0",
236 		"  0; 32;  0","  0; 64;  0","  0; 96;  0","  0;128;  0",
237 		"  0;160;  0","  0;192;  0","  0;224;  0","255;255;255"
238 	},
239 	{	"green2.pal","  0;  0;  0",
240 		"  0; 60;  0","  0;102;  0","  0;151;  0","  0;242;  0",
241 		"255;255; 89","240;120;  0","255;148; 40","255;  0;  0"
242 	},
243 	{	"jungle.pal","  0;  0;  0",
244 		"107; 67;  0","223;143;  0","255;123; 27","255; 91; 71",
245 		"255;195; 95","195;255;111","151;255;151","255;255;255"
246 	},
247 	{	"negative.pal","255;255;255",
248 		"223;223;223","191;191;191","159;159;159","127;127;127",
249 		" 95; 95; 95"," 63; 63; 63"," 31; 31; 31","  0;  0;  0"
250 	},
251 	{	"orange.pal","  0;  0;  0",
252 		" 63; 27;  0","131; 63;  0","199; 95;  0","251;127; 11",
253 		"251;155; 71","251;187;131","251;219;191","255;255;255"
254 	},
255 	{	"pink.pal","  0;  0;  0",
256 		" 63; 35; 35","135; 75; 75","203;111;111","255;147;147",
257 		"255;175;175","255;199;199","255;227;227","255;255;255"
258 	},
259 	{	"rainbow.pal","  0;  0;163",
260 		"  0; 87;191","  0;207;219","  0;247;139","  0;255; 23",
261 		" 95;255;  0","219;255;  0","255;171;155","255;255;255"
262 	},
263 	{	"scope.pal","  0;  0;  0",
264 		"  0;  0;167","  0; 79;255","  0;239;255","  0;255; 75",
265 		" 95;255;  0","255;255;  0","255;127;  0","255;  0;  0"
266 	},
267 	{	"sunburst.pal","  0;  0;  0",
268 		"  0;  0; 59","  0;  0;123","131;  0;179","235;  0; 75",
269 		"255; 43; 43","255;215;111","255;255;183","255;255;255"
270 	},
271 	{	"vk4bdj.pal","  0;  0;  0",
272 		"  0; 32;  0","  0;154;  0","  0;161;  0","  0;177;  0",
273 		"156;209;144","192;185;183","214;222;224","255;255;255"
274 	},
275 	{	"yellow1.pal", "  0;  0;  0",
276 		" 31; 31;  0"," 63; 63;  0"," 95; 95;  0","127;127;  0",
277 		"159;159;  0","191;191;  0","223;223;  0","255;255;  0"
278 	},
279 	{	"yellow2.pal", "  0;  0;  0",
280 		" 39; 39;  0"," 75; 75;  0","111;111;  0","147;147;  0",
281 		"183;183;  0","219;219;  0","255;255;  0","255;255;255"
282 	},
283 	{	"yl2kf.pal","  0;  0;  0",
284 		"  0;  0;119","  7; 11;195"," 39; 47;159"," 95;115;203",
285 		"151;179;255","187;203;255","219;227;255","255;255;  5"
286 	},
287 	{	0,0,
288 		0,0,0,0,
289 		0,0,0,0
290 	}
291 };
292 
create_new_palettes()293 void create_new_palettes()
294 {
295 	paldata *pd = palfiles;
296 	string Filename;
297 	while (pd->fname) {
298 		Filename = PalettesDir;
299 		Filename.append(pd->fname);
300 		ofstream pfile(Filename.c_str());
301 		pfile << pd->rgbstr0 << endl;
302 		pfile << pd->rgbstr1 << endl;
303 		pfile << pd->rgbstr2 << endl;
304 		pfile << pd->rgbstr3 << endl;
305 		pfile << pd->rgbstr4 << endl;
306 		pfile << pd->rgbstr5 << endl;
307 		pfile << pd->rgbstr6 << endl;
308 		pfile << pd->rgbstr7 << endl;
309 		pfile << pd->rgbstr8 << endl;
310 		pfile.close();
311 		pd++;
312 	}
313 }
314 
create_new_macros()315 void create_new_macros()
316 {
317 	string Filename = MacrosDir;
318 	Filename.append("macros.mdf");
319 	newmacros();
320 	macros.saveMacros(Filename);
321 }
322 
323 // =============================================================================
324 
325 #include <vector>
326 #include <sstream>
327 
328 #include <FL/Fl_Window.H>
329 #include <FL/Fl_Wizard.H>
330 #include <FL/Fl_Button.H>
331 #include <FL/Fl_Box.H>
332 #include <FL/fl_draw.H>
333 
334 #include "configuration.h"
335 #include "confdialog.h"
336 #include "icons.h"
337 #include "gettext.h"
338 
339 class Wizard : public Fl_Window
340 {
341 public:
342 	struct wizard_tab {
343 		Fl_Group* tab;
344 		Fl_Group* parent;
345 		int position;
346 		int x, y, w, h;
347 	};
348 
Wizard(int w,int h,const char * l=0)349 	Wizard(int w, int h, const char* l = 0)
350 		: Fl_Window(w, h, l)
351 	{ create_wizard(); }
352 
~Wizard()353 	~Wizard() { destroy_wizard(); }
354 
355 private:
356 	void create_wizard(void);
357 	Fl_Group* make_intro(void);
358 	void destroy_wizard(void);
359 
360 	static void wizard_cb(Fl_Widget* w, void* arg);
361 
362 	Fl_Wizard *wizard;
363 	Fl_Button *prev, *next, *done;
364 	typedef vector<wizard_tab> tab_t;
365 	tab_t tabs;
366 };
367 
368 static int btn_h = 22;
369 static int pad = 4;
370 
create_wizard(void)371 void Wizard::create_wizard(void)
372 {
373 	createRecordLoader();
374 
375 	callback(wizard_cb, this);
376 	xclass(PACKAGE_TARNAME);
377 
378 	wizard = new Fl_Wizard(0, 0, w(), h());
379 	wizard->end();
380 
381 	// create the buttons
382 	fl_font(FL_HELVETICA, FL_NORMAL_SIZE);
383 	struct {
384 		Fl_Button** button;
385 		const char* label;
386 	} buttons[] = {
387 		{ &done, _("Finish") },
388 		{ &next, _("Next") },
389 		{ &prev, _("Back") },
390 	};
391 	int x = w() - 10;
392 	int bw = 0;
393 	for (size_t i = 0; i < sizeof(buttons)/sizeof(*buttons); i++) {
394 		bw = fl_width(buttons[i].label) + 10;
395 		Fl_Button* b = *buttons[i].button = new Fl_Button(
396 						(x = x - bw - 10), wizard->y() + grpOperator->h() + pad,
397 						bw, btn_h,
398 						buttons[i].label);
399 		b->callback(wizard_cb, this);
400 	}
401 	done->activate();
402 	prev->deactivate();
403 	next->activate();
404 
405 	end();
406 	position(MAX(0, fl_digi_main->x() + (fl_digi_main->w() - w()) / 2),
407 		 MAX(0, fl_digi_main->y() + (fl_digi_main->h() - h()) / 2));
408 
409 	// populate the Fl_Wizard group
410 	struct wizard_tab tabs_[] = {
411 		{ NULL },
412 		{ grpOperator },
413 		{ grpSoundDevices },
414 		{ grpRigFlrig },
415 		{ grpRigCat },
416 		{ grpRigHamlib },
417 		{ tabDataFiles }
418 	};
419 
420 	tabs.resize(sizeof(tabs_)/sizeof(*tabs_));
421 	memcpy(&tabs[0], tabs_, sizeof(tabs_));
422 
423 	for (tab_t::iterator i = tabs.begin() + 1; i != tabs.end(); ++i) {
424 		i->parent = i->tab->parent();
425 		i->position = i->parent->find(i->tab);
426 		i->x = i->tab->x();
427 		i->y = i->tab->y();
428 		i->w = i->tab->w();
429 		i->h = i->tab->h();
430 	}
431 
432 	tabs[0].tab = make_intro();
433 	tabs[0].w = grpOperator->w();
434 	tabs[0].h = grpOperator->h();
435 
436 	for (tab_t::iterator i = tabs.begin(); i != tabs.end(); ++i) {
437 		i->tab->resize(0, 0, grpOperator->w(), grpOperator->h());
438 		wizard->add(i->tab);
439 	}
440 	wizard->value(tabs[0].tab);
441 }
442 
destroy_wizard(void)443 void Wizard::destroy_wizard(void)
444 {
445 	// re-parent tabs
446 	for (tab_t::const_iterator i = tabs.begin() + 1; i != tabs.end(); ++i) {
447 		i->parent->insert(*i->tab, i->position);
448 		if (i < tabs.end() - 1)
449 			i->tab->hide();
450 		i->tab->resize(i->x, i->y, i->w, i->h);
451 		i->parent->init_sizes();
452 	}
453 
454 	Fl_Button* b[] = { prev, next, done };
455 	for (size_t i = 0; i < sizeof(b)/sizeof(*b); i++)
456 		delete b[i];
457 
458 }
459 
wizard_cb(Fl_Widget * w,void * arg)460 void Wizard::wizard_cb(Fl_Widget* w, void* arg)
461 {
462 	Wizard* wiz = static_cast<Wizard*>(arg);
463 
464 	if (w == wiz || w == wiz->done) {
465 		delete wiz;
466 		return;
467 	}
468 
469 	if (w == wiz->prev)
470 		wiz->wizard->prev();
471 	else if (w == wiz->next)
472 		wiz->wizard->next();
473 
474 	Fl_Group* cur = static_cast<Fl_Group*>(wiz->wizard->value());
475 
476 // modify buttons
477 	if (cur == wiz->tabs[0].tab) {
478 		wiz->prev->deactivate();
479 		wiz->next->activate();
480 		wiz->done->activate();
481 	} else if (cur == wiz->tabs.back().tab) {
482 		wiz->prev->activate();
483 		wiz->next->deactivate();
484 		wiz->done->activate();
485 	} else {
486 		wiz->prev->activate();
487 		wiz->next->activate();
488 		wiz->done->activate();
489 	}
490 	wiz->prev->show();
491 	wiz->next->show();
492 	wiz->done->show();
493 	wiz->prev->redraw();
494 	wiz->next->redraw();
495 	wiz->done->redraw();
496 }
497 
make_intro(void)498 Fl_Group* Wizard::make_intro(void)
499 {
500 	Fl_Group* intro = new Fl_Group(
501 					0, 0,
502 					grpOperator->w(), grpOperator->h(),
503 					"");
504 
505 	ostringstream help_;
506 	help_ << "\n" <<
507 _("The wizard will guide you through the basic fldigi settings:") << "\n\n\t- " <<
508 _("Operator")                 << "\n\t- " <<
509 _("Sound Card Interface")     << "\n\t- " <<
510 _("Transceiver control, flrig/rigcat/hamlib")      << "\n\n" <<
511 _("Feel free to skip any pages or exit the wizard at any time") << ". " <<
512 _("All settings shown here can be changed later via the Configure menu") << '.';
513 
514 	Fl_Box* help = new Fl_Box(20, intro->y() + intro->h() / 4,
515 				  intro->w() - 40, 3 * intro->h()/ 4);
516 	help->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE | FL_ALIGN_WRAP);
517 	help->copy_label(help_.str().c_str());
518 
519 	intro->end();
520 
521 	return intro;
522 }
523 
524 
show_wizard(int argc,char ** argv)525 void show_wizard(int argc, char** argv)
526 {
527 	Wizard* w = new Wizard(grpOperator->w(), grpOperator->h() + (btn_h + 2 * pad), _("Fldigi configuration wizard"));
528 
529 	if (argc && argv)
530 		w->show(argc, argv);
531 	else {
532 		w->show();
533 		w->set_modal();
534 	}
535 	first_use = true;
536 }
537