1 // ----------------------------------------------------------------------------
2 // Copyright (C) 2014
3 //              David Freese, W1HKJ
4 //
5 // This file is part of flmsg
6 //
7 // flrig is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // flrig is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 // ----------------------------------------------------------------------------
20 
21 #include <stdlib.h>
22 #include <iostream>
23 #include <fstream>
24 #include <cstring>
25 #include <ctime>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdio.h>
29 #include <errno.h>
30 
31 #include <FL/Fl.H>
32 #include <FL/Enumerations.H>
33 #include <FL/Fl_Window.H>
34 #include <FL/Fl_Button.H>
35 #include <FL/Fl_Group.H>
36 #include <FL/Fl_Sys_Menu_Bar.H>
37 #include <FL/x.H>
38 #include <FL/Fl_Help_Dialog.H>
39 #include <FL/Fl_Menu_Item.H>
40 #include <FL/Fl_File_Icon.H>
41 
42 #include "config.h"
43 #include "flmsg_config.h"
44 
45 #include "flmsg.h"
46 #include "templates.h"
47 #include "debug.h"
48 #include "util.h"
49 #include "gettext.h"
50 #include "flmsg_dialog.h"
51 #include "flinput2.h"
52 #include "date.h"
53 #include "calendar.h"
54 #include "icons.h"
55 #include "fileselect.h"
56 #include "wrap.h"
57 #include "status.h"
58 #include "parse_xml.h"
59 
60 #ifdef WIN32
61 #  include "flmsgrc.h"
62 #  include "compat.h"
63 #  define dirent fl_dirent_no_thanks
64 #endif
65 
66 #include <FL/filename.H>
67 #include "dirent-check.h"
68 
69 #include <FL/x.H>
70 #include <FL/Fl_Pixmap.H>
71 #include <FL/Fl_Image.H>
72 
73 using namespace std;
74 
75 const char army_precedent[] = "RPOZM";
76 
77 string mars_army_de		= ":de:";
78 string mars_army_nbr	= ":nbr:";
79 
80 string mars_army_prec	= ":pre:";
81 string mars_army_dtg	= ":dtg:";
82 string mars_army_fm		= ":fm:";
83 string mars_army_to		= ":to:";
84 string mars_army_info	= ":info:";
85 string mars_army_subj	= ":subj:";
86 string mars_army_text	= ":text:";
87 
88 string s_mars_army_de;
89 string s_mars_army_nbr;
90 string s_mars_army_prec = "R";
91 string s_mars_army_dtg;
92 string s_mars_army_fm;
93 string s_mars_army_to;
94 string s_mars_army_subj;
95 string s_mars_army_info;
96 string s_mars_army_text;
97 
98 string buffmars_army;
99 string def_mars_army_filename = "";
100 string base_mars_army_filename = "";
101 string def_mars_army_TemplateName = "";
102 
103 bool using_mars_army_template = false;
104 
clear_mars_armyfields()105 void clear_mars_armyfields()
106 {
107 	s_mars_army_prec = "R";
108 	s_mars_army_dtg.clear();
109 	s_mars_army_fm.clear();
110 	s_mars_army_de.clear();
111 	s_mars_army_nbr.clear();
112 	s_mars_army_to.clear();
113 	s_mars_army_subj.clear();
114 	s_mars_army_info.clear();
115 	s_mars_army_text.clear();
116 }
117 
check_mars_armyfields()118 bool check_mars_armyfields()
119 {
120 	string temp;
121 	temp = army_precedent[sel_mars_army_prec->index()];
122 	if (s_mars_army_prec != temp) return true;
123 	if (s_mars_army_dtg != txt_mars_army_dtg->value()) return true;
124 	if (s_mars_army_fm != txt_mars_army_fm->value()) return true;
125 	if (s_mars_army_de != txt_mars_army_de->value()) return true;
126 	if (s_mars_army_nbr != txt_mars_army_nbr->value()) return true;
127 	if (s_mars_army_to != txt_mars_army_to->buffer()->text()) return true;
128 	if (s_mars_army_info != txt_mars_army_info->buffer()->text()) return true;
129 	if (s_mars_army_subj != txt_mars_army_subj->value()) return true;
130 	if (s_mars_army_text != txt_mars_army_text->buffer()->text()) return true;
131 	return false;
132 }
133 
update_mars_armyfields()134 void update_mars_armyfields()
135 {
136 	s_mars_army_prec.clear();
137 	s_mars_army_prec = army_precedent[sel_mars_army_prec->index()];
138 	s_mars_army_dtg = txt_mars_army_dtg->value();
139 	s_mars_army_fm = txt_mars_army_fm->value();
140 	s_mars_army_de = txt_mars_army_de->value();
141 	s_mars_army_nbr = txt_mars_army_nbr->value();
142 	s_mars_army_to = txt_mars_army_to->buffer()->text();
143 	s_mars_army_info = txt_mars_army_info->buffer()->text();
144 	s_mars_army_subj = txt_mars_army_subj->value();
145 	s_mars_army_text = txt_mars_army_text->buffer()->text();
146 	striplf (s_mars_army_dtg);
147 	striplf (s_mars_army_de);
148 	striplf (s_mars_army_fm);
149 	striplf (s_mars_army_nbr);
150 	striplf (s_mars_army_to);
151 	striplf (s_mars_army_info);
152 	striplf (s_mars_army_subj);
153 	striplf (s_mars_army_text);
154 }
155 
update_mars_armyform()156 void update_mars_armyform()
157 {
158 	size_t n = strchr(army_precedent, s_mars_army_prec[0]) - army_precedent;
159 	if (n < 0) n = 0;
160 	if (n > 4) n = 4;
161 	sel_mars_army_prec->index(n);
162 
163 	txt_mars_army_dtg->value(s_mars_army_dtg.c_str());
164 	txt_mars_army_fm->value(s_mars_army_fm.c_str());
165 	txt_mars_army_de->value(s_mars_army_de.c_str());
166 	txt_mars_army_nbr->value(s_mars_army_nbr.c_str());
167 	txt_mars_army_to->add(s_mars_army_to.c_str());
168 	txt_mars_army_info->add(s_mars_army_info.c_str());
169 	txt_mars_army_subj->value(s_mars_army_subj.c_str());
170 	txt_mars_army_text->add(s_mars_army_text.c_str());
171 
172 }
173 
clear_mars_army_form()174 void clear_mars_army_form()
175 {
176 	clear_mars_armyfields();
177 	sel_mars_army_prec->index(0);
178 	txt_mars_army_dtg->value("");
179 	txt_mars_army_fm->value("");
180 	txt_mars_army_de->value("");
181 	txt_mars_army_nbr->value("");
182 
183 	txt_mars_army_to->clear();
184 	txt_mars_army_info->clear();
185 	txt_mars_army_subj->value("");
186 	txt_mars_army_text->clear();
187 }
188 
make_buffmars_army(bool compress=false)189 void make_buffmars_army(bool compress = false)
190 {
191 	string mbuff;
192 	mbuff.clear();
193 	mbuff.append( lineout( mars_army_prec,		s_mars_army_prec ) );
194 	mbuff.append( lineout( mars_army_dtg,		s_mars_army_dtg ) );
195 	mbuff.append( lineout( mars_army_fm,		s_mars_army_fm ) );
196 	mbuff.append( lineout( mars_army_de,		s_mars_army_de ) );
197 	mbuff.append( lineout( mars_army_nbr,		s_mars_army_nbr ) );
198 	mbuff.append( lineout( mars_army_to,		s_mars_army_to ) );
199 	mbuff.append( lineout( mars_army_info,		s_mars_army_info ) );
200 	mbuff.append( lineout( mars_army_subj,		s_mars_army_subj ) );
201 	mbuff.append( lineout( mars_army_text,		s_mars_army_text ) );
202 	if (compress) compress_maybe(mbuff);
203 	buffmars_army.append(mbuff);
204 }
205 
read_mars_army_buffer(string data)206 void read_mars_army_buffer(string data)
207 {
208 	clear_mars_armyfields();
209 // search the file buffer for each of the mars_army fields
210 	s_mars_army_prec = findstr( data, mars_army_prec );
211 	s_mars_army_dtg = findstr( data, mars_army_dtg );
212 	s_mars_army_fm = findstr( data, mars_army_fm );
213 	s_mars_army_de = findstr( data, mars_army_de );
214 	s_mars_army_nbr = findstr( data, mars_army_nbr );
215 	s_mars_army_to = findstr( data, mars_army_to );
216 	s_mars_army_info = findstr( data, mars_army_info );
217 	s_mars_army_subj = findstr( data, mars_army_subj );
218 	s_mars_army_text = findstr( data, mars_army_text );
219 
220 	update_mars_armyform();
221 }
222 
cb_mars_army_new()223 void cb_mars_army_new()
224 {
225 	if (check_mars_armyfields()) {
226 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 1) {
227 			update_header(CHANGED);
228 			cb_mars_army_save();
229 		}
230 	}
231 	clear_mars_army_form();
232 	def_mars_army_filename = ICS_msg_dir;
233 	def_mars_army_filename.append("new").append(FMARSARMY_EXT);
234 	show_filename(def_mars_army_filename);
235 	using_mars_army_template = false;
236 }
237 
cb_mars_army_import()238 void cb_mars_army_import()
239 {
240 	fl_alert2("Not implemented");
241 }
242 
cb_mars_army_export()243 void cb_mars_army_export()
244 {
245 	fl_alert2("Not implemented");
246 }
247 
cb_mars_army_wrap_import(string wrapfilename,string inpbuffer)248 void cb_mars_army_wrap_import(string wrapfilename, string inpbuffer)
249 {
250 	clear_mars_army_form();
251 	read_mars_army_buffer(inpbuffer);
252 	def_mars_army_filename = ICS_msg_dir;
253 	def_mars_army_filename.append(wrapfilename);
254 	show_filename(def_mars_army_filename);
255 	using_mars_army_template = false;
256 }
257 
eval_mars_army_fsize()258 int eval_mars_army_fsize()
259 {
260 	Ccrc16 chksum;
261 	evalstr.assign("[WRAP:beg][WRAP:lf][WRAP:fn ");
262 	evalstr.append(base_mars_army_filename).append("]");
263 	update_mars_armyfields();
264 	update_header(FROM);
265 	evalstr.append(header("<mars_army>"));
266 	buffmars_army.clear();
267 	make_buffmars_army(true);
268 	if (buffmars_army.empty()) return 0;
269 	compress_maybe( buffmars_army );
270 	evalstr.append( buffmars_army );
271 	evalstr.append("[WRAP:chksum ").append(chksum.scrc16(evalstr)).append("][WRAP:end]");
272 	return evalstr.length();
273 }
274 
cb_mars_army_wrap_export()275 void cb_mars_army_wrap_export()
276 {
277 	if (check_mars_armyfields()) {
278 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
279 			return;
280 		update_header(CHANGED);
281 	}
282 	update_mars_armyfields();
283 
284 	if (base_mars_army_filename == string("new").append(FMARSARMY_EXT) ||
285 		base_mars_army_filename == string("default").append(FMARSARMY_EXT) )
286 		if (!cb_mars_army_save_as()) return;
287 
288 	string wrapfilename = WRAP_send_dir;
289 	wrapfilename.append(base_mars_army_filename);
290 	wrapfilename.append(".wrap");
291 	const char *p = FSEL::saveas(
292 			"Save as wrap file",
293 			"Wrap file\t*.{wrap,WRAP}",
294 			wrapfilename.c_str());
295 	if (p) {
296 		string pext = fl_filename_ext(p);
297 		wrapfilename = p;
298 
299 		update_header(FROM);
300 		buffmars_army.assign(header("<mars_army>"));
301 		make_buffmars_army(true);
302 		export_wrapfile(base_mars_army_filename, wrapfilename, buffmars_army, pext != ".wrap");
303 
304 		buffmars_army.assign(header("<mars_army>"));
305 		make_buffmars_army(false);
306 		write_mars_army(def_mars_army_filename);
307 	}
308 }
309 
cb_mars_army_wrap_autosend()310 void cb_mars_army_wrap_autosend()
311 {
312 	if (check_mars_armyfields()) {
313 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
314 			return;
315 		update_header(CHANGED);
316 	}
317 	update_mars_armyfields();
318 
319 	if (base_mars_army_filename == string("new").append(FMARSARMY_EXT) ||
320 		base_mars_army_filename == string("default").append(FMARSARMY_EXT) )
321 		if (!cb_mars_army_save_as()) return;
322 
323 	update_header(FROM);
324 	buffmars_army.assign(header("<mars_army>"));
325 	make_buffmars_army(true);
326 	xfr_via_socket(base_mars_army_filename, buffmars_army);
327 
328 	buffmars_army.assign(header("<mars_army>"));
329 	make_buffmars_army(false);
330 	write_mars_army(def_mars_army_filename);
331 }
332 
cb_mars_army_load_template()333 void cb_mars_army_load_template()
334 {
335 	string def_mars_army_filename = def_mars_army_TemplateName;
336 	const char *p = FSEL::select(
337 			"Open template file",
338 			string("Template file\t*").append(TMARSARMY_EXT).c_str(),
339 			def_mars_army_filename.c_str());
340 	if (p) {
341 		clear_mars_army_form();
342 		read_data_file(p);
343 		def_mars_army_TemplateName = p;
344 		show_filename(def_mars_army_TemplateName);
345 		using_mars_army_template = true;
346 	}
347 }
348 
cb_mars_army_save_template()349 void cb_mars_army_save_template()
350 {
351 	if (!using_mars_army_template) {
352 		cb_mars_army_save_as_template();
353 		return;
354 	}
355 	string def_mars_army_filename = def_mars_army_TemplateName;
356 	const char *p = FSEL::saveas(
357 			"Save template file",
358 			string("Template file\t*").append(TMARSARMY_EXT).c_str(),
359 			def_mars_army_filename.c_str());
360 	if (p)
361 		write_mars_army(p);
362 	if (p) {
363 		update_header(CHANGED);
364 		update_mars_armyfields();
365 		buffmars_army.assign(header("<mars_army>"));
366 		make_buffmars_army();
367 		write_mars_army(p);
368 	}
369 }
370 
cb_mars_army_save_as_template()371 void cb_mars_army_save_as_template()
372 {
373 	string def_mars_army_filename = def_mars_army_TemplateName;
374 	const char *p = FSEL::saveas(
375 			"Save as template file",
376 			string("Template file\t*").append(TMARSARMY_EXT).c_str(),
377 			def_mars_army_filename.c_str());
378 	if (p) {
379 		const char *pext = fl_filename_ext(p);
380 		def_mars_army_TemplateName = p;
381 		if (strlen(pext) == 0) def_mars_army_TemplateName.append(TMARSARMY_EXT);
382 		remove_spaces_from_filename(def_mars_army_TemplateName);
383 
384 		clear_header();
385 		update_header(CHANGED);
386 		update_mars_armyfields();
387 		buffmars_army.assign(header("<mars_army>"));
388 		make_buffmars_army();
389 		write_mars_army(def_mars_army_TemplateName);
390 
391 		show_filename(def_mars_army_TemplateName);
392 		using_mars_army_template = true;
393 	}
394 }
395 
cb_mars_army_open()396 void cb_mars_army_open()
397 {
398 	const char *p = FSEL::select(
399 			_("Open data file"),
400 			string("ICS-mars_army\t*").append(FMARSARMY_EXT).c_str(),
401 			def_mars_army_filename.c_str());
402 	if (!p) return;
403 	if (strlen(p) == 0) return;
404 	clear_mars_army_form();
405 	read_data_file(p);
406 	using_mars_army_template = false;
407 	def_mars_army_filename = p;
408 	show_filename(def_mars_army_filename);
409 }
410 
write_mars_army(string s)411 void write_mars_army(string s)
412 {
413 	FILE *filemars_army = fopen(s.c_str(), "w");
414 	if (!filemars_army) return;
415 	make_buffmars_army();
416 	fwrite(buffmars_army.c_str(), buffmars_army.length(), 1, filemars_army);
417 	fclose(filemars_army);
418 }
419 
cb_mars_army_save_as()420 bool cb_mars_army_save_as()
421 {
422 	const char *p;
423 	string newfilename;
424 
425 	string name = named_file();
426 	if (!name.empty()) {
427 		name.append(FMARSARMY_EXT);
428 		newfilename = ICS_msg_dir;
429 		newfilename.append(name);
430 	} else
431 		newfilename = def_mars_army_filename;
432 
433 	p = FSEL::saveas(
434 			_("Save data file"),
435 			string("ICS-mars_army\t*").append(FMARSARMY_EXT).c_str(),
436 			newfilename.c_str());
437 
438 	if (!p) return false;
439 	if (strlen(p) == 0) return false;
440 
441 	if (progStatus.sernbr_fname) update_sernbr();
442 
443 	const char *pext = fl_filename_ext(p);
444 	def_mars_army_filename = p;
445 	if (strlen(pext) == 0) def_mars_army_filename.append(FMARSARMY_EXT);
446 
447 	remove_spaces_from_filename(def_mars_army_filename);
448 
449 	update_header(NEW);
450 	update_mars_armyfields();
451 	buffmars_army.assign(header("<mars_army>"));
452 	make_buffmars_army();
453 	write_mars_army(def_mars_army_filename);
454 
455 	using_mars_army_template = false;
456 	show_filename(def_mars_army_filename);
457 	return true;
458 }
459 
cb_mars_army_save()460 void cb_mars_army_save()
461 {
462 	if (base_mars_army_filename == string("new").append(FMARSARMY_EXT) ||
463 		base_mars_army_filename == string("default").append(FMARSARMY_EXT) ||
464 		using_mars_army_template == true) {
465 		cb_mars_army_save_as();
466 		return;
467 	}
468 
469 	if (check_mars_armyfields()) update_header(CHANGED);
470 	update_mars_armyfields();
471 	buffmars_army.assign(header("<mars_army>"));
472 	make_buffmars_army();
473 	write_mars_army(def_mars_army_filename);
474 
475 	using_mars_army_template = false;
476 }
477 
cb_mars_army_html()478 void cb_mars_army_html()
479 {
480 	string fname_name = fl_filename_name(def_mars_army_filename.c_str());
481 	size_t p = fname_name.rfind('.');
482 	if (p != string::npos) fname_name.erase(p);
483 
484 	string mars_army_fname = ICS_dir;
485 	mars_army_fname.append(fname_name);
486 	mars_army_fname.append(".html");
487 
488 	update_mars_armyfields();
489 	string formmars_army = mars_army_html_template;
490 
491 	replacestr(formmars_army, TITLE, fname_name);
492 
493 	replacestr(formmars_army, mars_army_prec, s_mars_army_prec );
494 	replacestr(formmars_army, mars_army_dtg, s_mars_army_dtg );
495 	replacestr(formmars_army, mars_army_fm, s_mars_army_fm );
496 	replacestr(formmars_army, mars_army_de, s_mars_army_de );
497 	replacestr(formmars_army, mars_army_nbr, s_mars_army_nbr );
498 	replacestr(formmars_army, mars_army_to, s_mars_army_to );
499 
500 	if (s_mars_army_info.empty())  {
501 		size_t p = formmars_army.find("INFO");
502 		size_t p2 = formmars_army.find('\n', p);
503 		formmars_army.erase(p, p2 - p + 1);
504 	} else
505 		replacestr(formmars_army, mars_army_info, s_mars_army_info );
506 
507 	string text = "";
508 	string temp = "";
509 	if (!s_mars_army_subj.empty()) {
510 		temp = "SUBJ: "; temp.append(s_mars_army_subj);
511 		temp = maxchars(temp, 69, 6);
512 		text = temp;
513 		text += '\n';
514 	}
515 	temp = maxchars(s_mars_army_text, 69);
516 	text.append(temp);
517 
518 	replacestr(formmars_army, mars_army_text, text );
519 
520 	FILE *filemars_army = fopen(mars_army_fname.c_str(), "w");
521 	fprintf(filemars_army,"%s", formmars_army.c_str());
522 	fclose(filemars_army);
523 
524 	open_url(mars_army_fname.c_str());
525 }
526 
cb_mars_army_msg_type()527 void cb_mars_army_msg_type()
528 {
529 	if (tabs_msg_type->value() == tab_mars_army ) {
530 		show_filename(def_mars_army_filename);
531 	} else {
532 		show_filename(def_rg_filename);
533 	}
534 }
535 
cb_mars_army_textout()536 void cb_mars_army_textout()
537 {
538 	string mars_army_fname = ICS_dir;
539 	mars_army_fname.append("mars_army.txt");
540 
541 	update_mars_armyfields();
542 	string formmars_army = mars_army_text_template;
543 
544 	replacestr(formmars_army, mars_army_prec, s_mars_army_prec );
545 	replacestr(formmars_army, mars_army_dtg, s_mars_army_dtg );
546 	replacestr(formmars_army, mars_army_fm, s_mars_army_fm );
547 	replacestr(formmars_army, mars_army_de, s_mars_army_de );
548 	replacestr(formmars_army, mars_army_nbr, s_mars_army_nbr );
549 	replacestr(formmars_army, mars_army_to, s_mars_army_to );
550 
551 	if (s_mars_army_info.empty())  {
552 		size_t p = formmars_army.find("INFO");
553 		size_t p2 = formmars_army.find('\n', p);
554 		formmars_army.erase(p, p2 - p + 1);
555 	} else
556 		replacestr(formmars_army, mars_army_info, s_mars_army_info );
557 
558 	string text = "";
559 	string temp = "";
560 	if (!s_mars_army_subj.empty()) {
561 		temp = "SUBJ: "; temp.append(s_mars_army_subj);
562 		temp = maxchars(temp, 69, 6);
563 		text = temp;
564 		text += '\n';
565 	}
566 	temp = maxchars(s_mars_army_text, 69);
567 	text.append(temp);
568 
569 	replacestr(formmars_army, mars_army_text, text );
570 
571 	FILE *filemars_army = fopen(mars_army_fname.c_str(), "w");
572 	fprintf(filemars_army,"%s", formmars_army.c_str());
573 	fclose(filemars_army);
574 
575 	open_url(mars_army_fname.c_str());
576 }
577 
578