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 // ---------------------------------------------------------------------
76 // ics 205a field variables and template variables
77 // ---------------------------------------------------------------------
78 
79 string ics205a_incident					= ":inc:";
80 string ics205a_date_fm					= ":dfm:";
81 string ics205a_time_fm					= ":tfm:";
82 string ics205a_date_to					= ":dto:";
83 string ics205a_time_to					= ":tto:";
84 string ics205a_prepared_by				= ":pre:";
85 string ics205a_preparer_position		= ":pos:";
86 string ics205a_preparer_date_time		= ":dtm:";
87 
88 string ics205a_comm_position			= ":asg[n]:"; // 32
89 string ics205a_comm_name				= ":nam[n]:"; // 32
90 string ics205a_comm_info				= ":inf[n]:"; // 32
91 
92 string s205a_incident;
93 string s205a_date_fm;
94 string s205a_time_fm;
95 string s205a_date_to;
96 string s205a_time_to;
97 string s205a_prepared_by;
98 string s205a_preparer_position;
99 string s205a_preparer_date_time;
100 
101 string s205a_comm_position[32];
102 string s205a_comm_name[32];
103 string s205a_comm_info[32];
104 
105 // =====================================================================
106 
107 string buff205a;
108 string def_205a_filename = "";
109 string base_205a_filename = "";
110 string def_205a_TemplateName = "";
111 bool using_ics205a_template = false;
112 
cb_205a_set_date_fm()113 void cb_205a_set_date_fm()
114 {
115 	txt_205a_date_fm->value(szDate(progStatus.dtformat));
116 }
117 
cb_205a_set_time_fm()118 void cb_205a_set_time_fm()
119 {
120 	txt_205a_time_fm->value(szTime(progStatus.UTC));
121 }
122 
cb_205a_set_date_to()123 void cb_205a_set_date_to()
124 {
125 	txt_205a_date_to->value(szDate(progStatus.dtformat));
126 }
127 
cb_205a_set_time_to()128 void cb_205a_set_time_to()
129 {
130 	txt_205a_time_to->value(szTime(progStatus.UTC));
131 }
132 
clear_205afields()133 void clear_205afields()
134 {
135 	s205a_incident.clear();
136 	s205a_date_fm.clear();
137 	s205a_time_fm.clear();
138 	s205a_date_to.clear();
139 	s205a_time_to.clear();
140 	s205a_prepared_by.clear();
141 	s205a_preparer_position.clear();
142 	s205a_preparer_date_time.clear();
143 
144 	for (int i = 0; i < 32; i++) {
145 		s205a_comm_position[i].clear();
146 		s205a_comm_name[i].clear();
147 		s205a_comm_info[i].clear();
148 	}
149 }
150 
check_205afields()151 bool check_205afields()
152 {
153 	if (s205a_incident != txt_205a_incident->value())
154 		return true;
155 	if (s205a_date_fm != txt_205a_date_fm->value())
156 		return true;
157 	if (s205a_time_fm != txt_205a_time_fm->value())
158 		return true;
159 	if (s205a_date_to != txt_205a_date_to->value())
160 		return true;
161 	if (s205a_time_to != txt_205a_time_to->value())
162 		return true;
163 	if (s205a_prepared_by != txt_205a_prepared_by->value())
164 		return true;
165 	if (s205a_preparer_position != txt_205a_preparer_position->value())
166 		return true;
167 	if (s205a_preparer_date_time != txt_205a_preparer_date_time->value())
168 		return true;
169 	for (int i = 0; i < 32; i++) {
170 		if (s205a_comm_position[i] != txt_205a_comm_position[i]->value())
171 			return true;
172 		if (s205a_comm_name[i] != txt_205a_comm_name[i]->value())
173 			return true;
174 		if (s205a_comm_info[i] != txt_205a_comm_info[i]->value())
175 			return true;
176 	}
177 	return false;
178 }
179 
update_205afields()180 void update_205afields()
181 {
182 	s205a_incident = txt_205a_incident->value();
183 	s205a_date_fm = txt_205a_date_fm->value();
184 	s205a_time_fm = txt_205a_time_fm->value();
185 	s205a_date_to = txt_205a_date_to->value();
186 	s205a_time_to = txt_205a_time_to->value();
187 	s205a_prepared_by = txt_205a_prepared_by->value();
188 	s205a_preparer_position = txt_205a_preparer_position->value();
189 	s205a_preparer_date_time = txt_205a_preparer_date_time->value();
190 	for (int i = 0; i < 32; i++) {
191 		s205a_comm_position[i] = txt_205a_comm_position[i]->value();
192 		s205a_comm_name[i] = txt_205a_comm_name[i]->value();
193 		s205a_comm_info[i] = txt_205a_comm_info[i]->value();
194 	}
195 }
196 
update_205aform()197 void update_205aform()
198 {
199 	txt_205a_incident->value(s205a_incident.c_str());
200 	txt_205a_date_fm->value(s205a_date_fm.c_str());
201 	txt_205a_time_fm->value(s205a_time_fm.c_str());
202 	txt_205a_date_to->value(s205a_date_to.c_str());
203 	txt_205a_time_to->value(s205a_time_to.c_str());
204 	txt_205a_prepared_by->value(s205a_prepared_by.c_str());
205 	txt_205a_preparer_position->value(s205a_preparer_position.c_str());
206 	txt_205a_preparer_date_time->value(s205a_preparer_date_time.c_str());
207 
208 	for (int i = 0; i < 32; i++) {
209 		txt_205a_comm_position[i]->value(s205a_comm_position[i].c_str());
210 		txt_205a_comm_name[i]->value(s205a_comm_name[i].c_str());
211 		txt_205a_comm_info[i]->value(s205a_comm_info[i].c_str());
212 	}
213 }
214 
clear_205a_form()215 void clear_205a_form()
216 {
217 	clear_205afields();
218 	update_205aform();
219 }
220 
ics205a_nn(string & subst,int n)221 string &ics205a_nn(string & subst, int n)
222 {
223 	static string garbage = "#$^*!";
224 	static string ics;
225 	ics.clear();
226 	ics = subst;
227 	size_t pos = ics.find("[");
228 	if (pos == string::npos) return garbage;
229 	pos++;
230 	if (n < 10)
231 		ics[pos] = '0' + n;
232 	else {
233 		ics[pos] = n > 29 ? '3' : n > 19 ? '2' : '1';
234 		ics[pos+1] = '0' + n % 10;
235 		ics[pos+2] = ']';
236 		ics += ':';
237 	}
238 	return ics;
239 }
240 
make_buff205a(bool compress=false)241 void make_buff205a(bool compress = false)
242 {
243 	string mbuff;
244 	mbuff.clear();
245 	mbuff.append( lineout( ics205a_incident, s205a_incident ) );
246 	mbuff.append( lineout( ics205a_date_fm, s205a_date_fm ) );
247 	mbuff.append( lineout( ics205a_time_fm, s205a_time_fm ) );
248 	mbuff.append( lineout( ics205a_date_to, s205a_date_to ) );
249 	mbuff.append( lineout( ics205a_time_to, s205a_time_to ) );
250 	mbuff.append( lineout( ics205a_prepared_by, s205a_prepared_by ) );
251 	mbuff.append( lineout( ics205a_preparer_position, s205a_preparer_position ) );
252 	mbuff.append( lineout( ics205a_preparer_date_time, s205a_preparer_date_time ) );
253 
254 	for (int i = 0; i < 32; i++) {
255 		mbuff.append( lineout( ics205a_nn( ics205a_comm_position, i ), s205a_comm_position[i] ) );
256 		mbuff.append( lineout( ics205a_nn( ics205a_comm_name, i ),     s205a_comm_name[i] ) );
257 		mbuff.append( lineout( ics205a_nn( ics205a_comm_info, i ),     s205a_comm_info[i] ) );
258 	}
259 	if (compress) compress_maybe(mbuff);
260 	buff205a.append(mbuff);
261 }
262 
read_205a_buffer(string data)263 void read_205a_buffer(string data)
264 {
265 	clear_205afields();
266 	read_header(data);
267 
268 	s205a_incident = findstr( data, ics205a_incident );
269 	s205a_date_fm = findstr( data, ics205a_date_fm );
270 	s205a_time_fm  = findstr( data, ics205a_time_fm );
271 	s205a_date_to = findstr( data, ics205a_date_to );
272 	s205a_time_to  = findstr( data, ics205a_time_to );
273 	s205a_prepared_by = findstr( data, ics205a_prepared_by );
274 	s205a_preparer_position  = findstr( data, ics205a_preparer_position );
275 	s205a_preparer_date_time = findstr( data, ics205a_preparer_date_time );
276 
277 	for (int i = 0; i < 32; i++) {
278 		s205a_comm_position[i] = findstr( data, ics205a_nn( ics205a_comm_position, i ) );
279 		s205a_comm_name[i]     = findstr( data, ics205a_nn( ics205a_comm_name, i ) );
280 		s205a_comm_info[i]     = findstr( data, ics205a_nn( ics205a_comm_info, i ) );
281 	}
282 
283 	update_205aform();
284 }
285 
cb_205a_new()286 void cb_205a_new()
287 {
288 	if (check_205afields()) {
289 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 1) {
290 			update_header(CHANGED);
291 			cb_205a_save();
292 		}
293 	}
294 	clear_205a_form();
295 	clear_header();
296 	def_205a_filename = ICS_msg_dir;
297 	def_205a_filename.append("new").append(F205A_EXT);
298 	show_filename(def_205a_filename);
299 	using_ics205a_template = false;
300 }
301 
cb_205a_import()302 void cb_205a_import()
303 {
304 	fl_alert2("Not implemented");
305 }
306 
cb_205a_export()307 void cb_205a_export()
308 {
309 	fl_alert2("Not implemented");
310 }
311 
cb_205a_wrap_import(string wrapfilename,string inpbuffer)312 void cb_205a_wrap_import(string wrapfilename, string inpbuffer)
313 {
314 	clear_205a_form();
315 	read_205a_buffer(inpbuffer);
316 	def_205a_filename = ICS_msg_dir;
317 	def_205a_filename.append(wrapfilename);
318 	show_filename(def_205a_filename);
319 	using_ics205a_template = false;
320 }
321 
eval_205a_fsize()322 int eval_205a_fsize()
323 {
324 	Ccrc16 chksum;
325 	evalstr.assign("[WRAP:beg][WRAP:lf][WRAP:fn ");
326 	evalstr.append(base_205a_filename).append("]");
327 	update_205afields();
328 	update_header(FROM);
329 	evalstr.append(header("<ics205a>"));
330 	buff205a.clear();
331 	make_buff205a(true);
332 	if (buff205a.empty()) return 0;
333 	compress_maybe( buff205a );
334 	evalstr.append( buff205a );
335 	evalstr.append("[WRAP:chksum ").append(chksum.scrc16(evalstr)).append("][WRAP:end]");
336 	return evalstr.length();
337 }
338 
cb_205a_wrap_export()339 void cb_205a_wrap_export()
340 {
341 	if (check_205afields()) {
342 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
343 			return;
344 		update_header(CHANGED);
345 	}
346 	update_205afields();
347 
348 	if (base_205a_filename == string("new").append(F205A_EXT) ||
349 		base_205a_filename == string("default").append(F205A_EXT) )
350 		if (!cb_205a_save_as()) return;
351 
352 	string wrapfilename = WRAP_send_dir;
353 	wrapfilename.append(base_205a_filename);
354 	wrapfilename.append(".wrap");
355 	const char *p = FSEL::saveas(
356 			"Save as wrap file",
357 			"Wrap file\t*.{wrap,WRAP}",
358 			wrapfilename.c_str());
359 	if (p) {
360 		string pext = fl_filename_ext(p);
361 		wrapfilename = p;
362 		update_header(FROM);
363 		buff205a.assign(header("<ics205a>"));
364 		make_buff205a(true);
365 		export_wrapfile(base_205a_filename, wrapfilename, buff205a, pext != ".wrap");
366 		write_205a(def_205a_filename);
367 	}
368 }
369 
cb_205a_wrap_autosend()370 void cb_205a_wrap_autosend()
371 {
372 	if (check_205afields()) {
373 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
374 			return;
375 		update_header(CHANGED);
376 	}
377 	update_205afields();
378 
379 	if (base_205a_filename == string("new").append(F205A_EXT) ||
380 		base_205a_filename == string("default").append(F205A_EXT) )
381 		cb_205a_save_as();
382 
383 	update_header(FROM);
384 	buff205a.assign(header("<ics205a>"));
385 	make_buff205a(true);
386 
387 	xfr_via_socket(base_205a_filename, buff205a);
388 	write_205a(def_205a_filename);
389 }
390 
cb_205a_load_template()391 void cb_205a_load_template()
392 {
393 	string def_205a_filename = def_205a_TemplateName;
394 	const char *p = FSEL::select(
395 			"Open template file",
396 			string("Template file\t*").append(F205A_EXT).c_str(),
397 			def_205a_filename.c_str());
398 	if (p) {
399 		clear_205a_form();
400 		read_data_file(p);
401 		def_205a_TemplateName = p;
402 		show_filename(def_205a_TemplateName);
403 		using_ics205a_template = true;
404 	}
405 }
406 
cb_205a_save_template()407 void cb_205a_save_template()
408 {
409 	if (!using_ics205a_template) {
410 		cb_205a_save_as_template();
411 		return;
412 	}
413 	string def_205a_filename = def_205a_TemplateName;
414 	const char *p = FSEL::saveas(
415 			"Save template file",
416 			string("Template file\t*").append(T205A_EXT).c_str(),
417 			def_205a_filename.c_str());
418 	if (p) {
419 		clear_header();
420 		make_buff205a();
421 		write_205a(p);
422 	}
423 }
424 
cb_205a_save_as_template()425 void cb_205a_save_as_template()
426 {
427 	string def_205a_filename = def_205a_TemplateName;
428 	const char *p = FSEL::saveas(
429 			"Save as template file",
430 			string("Template file\t*").append(T205A_EXT).c_str(),
431 			def_205a_filename.c_str());
432 	if (p) {
433 		const char *pext = fl_filename_ext(p);
434 		def_205a_TemplateName = p;
435 		if (strlen(pext) == 0) def_205a_TemplateName.append(T205A_EXT);
436 		remove_spaces_from_filename(def_205a_TemplateName);
437 		clear_header();
438 		make_buff205a();
439 		write_205a(def_205a_TemplateName);
440 		show_filename(def_205a_TemplateName);
441 		using_ics205a_template = true;
442 	}
443 }
444 
cb_205a_open()445 void cb_205a_open()
446 {
447 	const char *p = FSEL::select(
448 			_("Open data file"),
449 			string("ICS-205a\t*").append(F205A_EXT).c_str(),
450 			def_205a_filename.c_str());
451 	if (!p) return;
452 	if (strlen(p) == 0) return;
453 	clear_205a_form();
454 	read_data_file(p);
455 	using_ics205a_template = false;
456 	def_205a_filename = p;
457 	show_filename(def_205a_filename);
458 }
459 
write_205a(string s)460 void write_205a(string s)
461 {
462 	FILE *file205a = fopen(s.c_str(), "w");
463 	if (!file205a) return;
464 
465 	fwrite(buff205a.c_str(), buff205a.length(), 1, file205a);
466 	fclose(file205a);
467 }
468 
cb_205a_save_as()469 bool cb_205a_save_as()
470 {
471 	const char *p;
472 	string newfilename;
473 
474 	string name = named_file();
475 	if (!name.empty()) {
476 		name.append(F205A_EXT);
477 		newfilename = ICS_msg_dir;
478 		newfilename.append(name);
479 	} else
480 		newfilename = def_205a_filename;
481 
482 	p = FSEL::saveas(
483 			_("Save data file"),
484 			string("ICS-205a\t*").append(F205A_EXT).c_str(),
485 			newfilename.c_str());
486 
487 	if (!p) return false;
488 	if (strlen(p) == 0) return false;
489 
490 	if (progStatus.sernbr_fname) update_sernbr();
491 
492 	const char *pext = fl_filename_ext(p);
493 	def_205a_filename = p;
494 	if (strlen(pext) == 0) def_205a_filename.append(F205A_EXT);
495 
496 	remove_spaces_from_filename(def_205a_filename);
497 	update_205afields();
498 	update_header(NEW);
499 	buff205a.assign(header("<ics205a>"));
500 	make_buff205a();
501 	write_205a(def_205a_filename);
502 
503 	using_ics205a_template = false;
504 	show_filename(def_205a_filename);
505 	return true;
506 }
507 
cb_205a_save()508 void cb_205a_save()
509 {
510 	if (base_205a_filename == string("new").append(F205A_EXT) ||
511 		base_205a_filename == string("default").append(F205A_EXT) ||
512 		using_ics205a_template == true) {
513 		cb_205a_save_as();
514 		return;
515 	}
516 	if (check_205afields()) update_header(CHANGED);
517 	update_205afields();
518 	buff205a.assign(header("<ics205a>"));
519 	make_buff205a();
520 	write_205a(def_205a_filename);
521 	using_ics205a_template = false;
522 }
523 
cb_205a_html()524 void cb_205a_html()
525 {
526 	string fname_name = fl_filename_name(def_205a_filename.c_str());
527 	size_t p = fname_name.rfind('.');
528 	if (p != string::npos) fname_name.erase(p);
529 
530 	string ics205a_fname = ICS_dir;
531 	ics205a_fname.append(fname_name);
532 	ics205a_fname.append(".html");
533 
534 	string html_text = "";
535 	string empty = "<br>";
536 
537 	update_205afields();
538 	string form205a = ics205a_html_template;
539 
540 	replacestr(form205a, TITLE, fname_name);
541 	replacestr(form205a, ics205a_incident, s205a_incident );
542 	replacestr(form205a, ics205a_date_fm, s205a_date_fm );
543 	replacestr(form205a, ics205a_time_fm, s205a_time_fm );
544 	replacestr(form205a, ics205a_date_to, s205a_date_to );
545 	replacestr(form205a, ics205a_time_to, s205a_time_to );
546 	replacestr(form205a, ics205a_prepared_by, s205a_prepared_by );
547 	replacestr(form205a, ics205a_preparer_position, s205a_preparer_position );
548 	replacestr(form205a, ics205a_preparer_date_time, s205a_preparer_date_time );
549 
550 	for (int i = 0; i < 32; i++) {
551 		replacestr(form205a, ics205a_nn( ics205a_comm_position, i ),
552 			s205a_comm_position[i].empty() ? empty : s205a_comm_position[i] );
553 		replacestr(form205a, ics205a_nn( ics205a_comm_name, i ),
554 			s205a_comm_name[i].empty() ? empty : s205a_comm_name[i] );
555 		replacestr(form205a, ics205a_nn( ics205a_comm_info, i ),
556 			s205a_comm_info[i].empty() ? empty : s205a_comm_info[i] );
557 	}
558 
559 	FILE *file205a = fopen(ics205a_fname.c_str(), "w");
560 	fprintf(file205a,"%s", form205a.c_str());
561 	fclose(file205a);
562 
563 	open_url(ics205a_fname.c_str());
564 }
565 
cb_205a_msg_type()566 void cb_205a_msg_type()
567 {
568 	if (tabs_msg_type->value() == tab_ics205a ) {
569 		tab_ics205a_type->value(tab_205a_1);
570 		show_filename(def_205a_filename);
571 	}
572 }
573 
cb_205a_textout()574 void cb_205a_textout()
575 {
576 	string ics205a_fname = ICS_dir;
577 	ics205a_fname.append("ics205a.txt");
578 
579 	update_205afields();
580 	string form205a = ics205a_text_template;
581 
582 	replacestr(form205a, ics205a_incident, s205a_incident );
583 	replacestr(form205a, ics205a_date_fm, s205a_date_fm );
584 	replacestr(form205a, ics205a_time_fm, s205a_time_fm );
585 	replacestr(form205a, ics205a_date_to, s205a_date_to );
586 	replacestr(form205a, ics205a_time_to, s205a_time_to );
587 	replacestr(form205a, ics205a_prepared_by, s205a_prepared_by );
588 	replacestr(form205a, ics205a_preparer_position, s205a_preparer_position );
589 	replacestr(form205a, ics205a_preparer_date_time, s205a_preparer_date_time );
590 
591 	for (int i = 0; i < 32; i++) {
592 		replacestr(form205a, ics205a_nn( ics205a_comm_position, i ), s205a_comm_position[i] );
593 		replacestr(form205a, ics205a_nn( ics205a_comm_name, i ), s205a_comm_name[i] );
594 		replacestr(form205a, ics205a_nn( ics205a_comm_info, i ), s205a_comm_info[i] );
595 	}
596 
597 	FILE *file205a = fopen(ics205a_fname.c_str(), "w");
598 	fprintf(file205a,"%s", form205a.c_str());
599 	fclose(file205a);
600 
601 	open_url(ics205a_fname.c_str());
602 }
603