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 string h213_buffer;
76 string h213_base_filename = "";
77 string h213_def_filename = "";
78 string h213_def_template_name = "";
79 
80 bool h213_using_template = false;
81 
82 string h213_tag_fm			= ":1:";
83 string h213_tag_to			= ":2:";
84 string h213_tag_date		= ":3:";
85 string h213_tag_time		= ":4:";
86 string h213_tag_via_phone	= ":5a:";
87 string h213_tag_via_radio	= ":5b:";
88 string h213_tag_via_other	= ":5c:";
89 string h213_tag_reply_yes	= ":6a:";
90 string h213_tag_reply_no	= ":6b:";
91 string h213_tag_reply_to	= ":6c:";
92 string h213_tag_priority	= ":7:";
93 string h213_tag_high		= ":7a:";
94 string h213_tag_medium		= ":7b:";
95 string h213_tag_low			= ":7c:";
96 string h213_tag_msg			= ":8:";
97 string h213_tag_action		= ":9:";
98 string h213_tag_rcvd_by		= ":10:";
99 string h213_tag_time_rcvd	= ":11:";
100 string h213_tag_fwd_to		= ":12:";
101 string h213_tag_comments	= ":13:";
102 string h213_tag_rcvd_by2	= ":14:";
103 string h213_tag_time_rcvd2	= ":15:";
104 string h213_tag_fwd_to2		= ":16:";
105 string h213_tag_comments2	= ":17:";
106 string h213_tag_facility	= ":18:";
107 
108 FIELD h213_fields[] = {
109 { h213_tag_to,			"", (void **)&h213_txt_to,			't' },
110 { h213_tag_fm,			"", (void **)&h213_txt_fm,			't' },
111 { h213_tag_date,		"", (void **)&h213_txt_date,		'd' },
112 { h213_tag_time,		"", (void **)&h213_txt_time,		't' },
113 { h213_tag_via_phone,	"", (void **)&h213_btn_phone,		'b' },
114 { h213_tag_via_radio,	"", (void **)&h213_btn_radio,		'b' },
115 { h213_tag_via_other,	"", (void **)&h213_btn_other,		'b' },
116 { h213_tag_reply_yes,	"", (void **)&h213_btn_yes,			'b' },
117 { h213_tag_reply_no,	"", (void **)&h213_btn_no,			'b' },
118 { h213_tag_reply_to,	"", (void **)&h213_txt_reply_to,	't' },
119 { h213_tag_high,		"", (void **)&h213_btn_high,		'b' },
120 { h213_tag_medium,		"", (void **)&h213_btn_medium,		'b' },
121 { h213_tag_low,			"", (void **)&h213_btn_low,			'b' },
122 { h213_tag_msg,			"", (void **)&h213_txt_msg,			'e' },
123 { h213_tag_action,		"", (void **)&h213_txt_action,		'e' },
124 { h213_tag_rcvd_by,		"", (void **)&h213_txt_rcvd_by,		't' },
125 { h213_tag_time_rcvd,	"", (void **)&h213_txt_time_rcvd,	't' },
126 { h213_tag_fwd_to,		"", (void **)&h213_txt_fwd_to,		't' },
127 { h213_tag_comments,	"", (void **)&h213_txt_comments,	'e' },
128 { h213_tag_rcvd_by2,	"", (void **)&h213_txt_rcvd_by2,	't' },
129 { h213_tag_time_rcvd2,	"", (void **)&h213_txt_time_rcvd2,	't' },
130 { h213_tag_fwd_to2,		"", (void **)&h213_txt_fwd_to2,		't' },
131 { h213_tag_comments2,	"", (void **)&h213_txt_comments2,	'e' },
132 { h213_tag_facility,	"", (void **)&h213_txt_facility,	't' } };
133 
134 int h213_numfields = sizeof(h213_fields) / sizeof(FIELD);
135 
h213_cb_set_date()136 void h213_cb_set_date()
137 {
138 	h213_txt_date->value(szDate(progStatus.dtformat));
139 }
140 
h213_cb_set_time0()141 void h213_cb_set_time0()
142 {
143 	h213_txt_time->value(szTime(progStatus.UTC));
144 }
145 
h213_cb_set_time1()146 void h213_cb_set_time1()
147 {
148 	h213_txt_time_rcvd->value(szTime(progStatus.UTC));
149 }
150 
h213_cb_set_time2()151 void h213_cb_set_time2()
152 {
153 	h213_txt_time_rcvd2->value(szTime(progStatus.UTC));
154 }
155 
h213_clear_fields()156 void h213_clear_fields()
157 {
158 	for (int i = 0; i < h213_numfields; i++)
159 		h213_fields[i].f_data.clear();
160 }
161 
check_hics213fields()162 bool check_hics213fields()
163 {
164 	for (int i = 0; i < h213_numfields; i++) {
165 		if (h213_fields[i].w_type == 'd') {
166 			if (h213_fields[i].f_data != ((Fl_DateInput *)(*h213_fields[i].w))->value())
167 				return true;
168 		} else if (h213_fields[i].w_type == 't') {
169 			if (h213_fields[i].f_data != ((Fl_Input2 *)(*h213_fields[i].w))->value())
170 				return true;
171 		} else if (h213_fields[i].w_type == 'e') {
172 			if (h213_fields[i].f_data != ((FTextEdit *)(*h213_fields[i].w))->buffer()->text())
173 				return true;
174 		} else if (h213_fields[i].w_type == 'b') {
175 			string val = ((Fl_Check_Button *)(*h213_fields[i].w))->value() ? "X" : "";
176 			if (h213_fields[i].f_data != val)
177 				return true;
178 		}
179 	}
180 	return false;
181 }
182 
h213_update_fields()183 void h213_update_fields()
184 {
185 	for (int i = 0; i < h213_numfields; i++) {
186 		if (h213_fields[i].w_type == 'd') {
187 			h213_fields[i].f_data = ((Fl_DateInput *)(*h213_fields[i].w))->value();
188 		} else if (h213_fields[i].w_type == 't') {
189 			h213_fields[i].f_data = ((Fl_Input2 *)(*h213_fields[i].w))->value();
190 		} else if (h213_fields[i].w_type == 'e') {
191 			h213_fields[i].f_data = ((FTextEdit *)(*h213_fields[i].w))->buffer()->text();
192 		} else if (h213_fields[i].w_type == 'b') {
193 			string val = ((Fl_Check_Button *)(*h213_fields[i].w))->value() ? "X" : "";
194 			h213_fields[i].f_data = val;
195 		}
196 	}
197 }
198 
h213_clear_form()199 void h213_clear_form()
200 {
201 	h213_clear_fields();
202 	for (int i = 0; i < h213_numfields; i++) {
203 		if (h213_fields[i].w_type == 'd')
204 			((Fl_DateInput *)(*h213_fields[i].w))->value("");
205 		else if (h213_fields[i].w_type == 'b')
206 			((Fl_Check_Button *)(*h213_fields[i].w))->value(0);
207 		else if (h213_fields[i].w_type == 't')
208 			((Fl_Input2 *)(*h213_fields[i].w))->value("");
209 		else if (h213_fields[i].w_type == 'e')
210 			((FTextEdit *)(*h213_fields[i].w))->clear();
211 	}
212 	h213_update_fields();
213 }
214 
h213_update_form()215 void h213_update_form()
216 {
217 	for (int i = 0; i < h213_numfields; i++) {
218 		if (h213_fields[i].w_type == 'd')
219 			((Fl_DateInput *)(*h213_fields[i].w))->value(h213_fields[i].f_data.c_str());
220 		else if (h213_fields[i].w_type == 'b')
221 			((Fl_Check_Button *)(*h213_fields[i].w))->value(h213_fields[i].f_data == "X");
222 		else if (h213_fields[i].w_type == 't')
223 			((Fl_Input2 *)(*h213_fields[i].w))->value(h213_fields[i].f_data.c_str());
224 		else if (h213_fields[i].w_type == 'e') {
225 			((FTextEdit *)(*h213_fields[i].w))->clear();
226 			((FTextEdit *)(*h213_fields[i].w))->add(h213_fields[i].f_data.c_str());
227 		}
228 	}
229 }
230 
h213_make_buffer(bool compress=false)231 void h213_make_buffer(bool compress = false)
232 {
233 	string mbuff;
234 	mbuff.clear();
235 	for (int i = 0; i < h213_numfields; i++)
236 		mbuff.append( lineout( h213_fields[i].f_type, h213_fields[i].f_data ) );
237 	if (compress) compress_maybe(mbuff);
238 	h213_buffer.append(mbuff);
239 }
240 
h213_read_buffer(string data)241 void h213_read_buffer(string data)
242 {
243 	h213_clear_fields();
244 	read_header(data);
245 	for (int i = 0; i < h213_numfields; i++)
246 		h213_fields[i].f_data = findstr(data, h213_fields[i].f_type);
247 	h213_update_form();
248 }
249 
h213_cb_new()250 void h213_cb_new()
251 {
252 	if (check_hics213fields()) {
253 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 1) {
254 			update_header(CHANGED);
255 			h213_cb_save();
256 		}
257 	}
258 	h213_clear_form();
259 	clear_header();
260 	h213_def_filename = ICS_msg_dir;
261 	h213_def_filename.append("new").append(HF213_EXT);
262 	h213_using_template = false;
263 	show_filename(h213_def_filename);
264 }
265 
h213_cb_import()266 void h213_cb_import()
267 {
268 	fl_alert2("Not implemented");
269 }
270 
h213_cb_export()271 void h213_cb_export()
272 {
273 	fl_alert2("Not implemented");
274 }
275 
h213_cb_wrap_import(string wrapfilename,string inpbuffer)276 void h213_cb_wrap_import(string wrapfilename, string inpbuffer)
277 {
278 	h213_clear_form();
279 	h213_read_buffer(inpbuffer);
280 	h213_def_filename = ICS_msg_dir;
281 	h213_def_filename.append(wrapfilename);
282 	show_filename(h213_def_filename);
283 	h213_using_template = false;
284 }
285 
eval_h213_fsize()286 int eval_h213_fsize()
287 {
288 	Ccrc16 chksum;
289 	evalstr.assign("[WRAP:beg][WRAP:lf][WRAP:fn ");
290 	evalstr.append(h213_base_filename).append("]");
291 	h213_update_fields();
292 	update_header(FROM);
293 	evalstr.append(header("<hics213>"));
294 	h213_buffer.clear();
295 	h213_make_buffer(true);
296 	if (h213_buffer.empty()) return 0;
297 	compress_maybe( h213_buffer );
298 	evalstr.append( h213_buffer );
299 	evalstr.append("[WRAP:chksum ").append(chksum.scrc16(evalstr)).append("][WRAP:end]");
300 	return evalstr.length();
301 }
302 
h213_cb_wrap_export()303 void h213_cb_wrap_export()
304 {
305 	if (check_hics213fields()) {
306 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
307 			return;
308 		update_header(CHANGED);
309 	}
310 	h213_update_fields();
311 
312 	if (h213_base_filename == string("new").append(HF213_EXT) ||
313 		h213_base_filename == string("default").append(HF213_EXT) )
314 		if (!h213_cb_save_as()) return;
315 
316 	string wrapfilename = WRAP_send_dir;
317 	wrapfilename.append(h213_base_filename);
318 	wrapfilename.append(WRAP_EXT);
319 	const char *p = FSEL::saveas(
320 			"Save as wrap file",
321 			"Wrap file\t*.{wrap,WRAP}",
322 			wrapfilename.c_str());
323 	if (p) {
324 		string pext = fl_filename_ext(p);
325 		wrapfilename = p;
326 		update_header(FROM);
327 		h213_buffer.assign(header("<hics213>"));
328 		h213_make_buffer(true);
329 		export_wrapfile(h213_base_filename, wrapfilename, h213_buffer, pext != WRAP_EXT);
330 
331 		h213_buffer.assign(header("<hics213>"));
332 		h213_make_buffer(false);
333 		h213_write(h213_def_filename);
334 	}
335 }
336 
h213_cb_wrap_autosend()337 void h213_cb_wrap_autosend()
338 {
339 	if (check_hics213fields()) {
340 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
341 			return;
342 		update_header(CHANGED);
343 	}
344 	h213_update_fields();
345 
346 	if (h213_base_filename == string("new").append(HF213_EXT) ||
347 		h213_base_filename == string("default").append(HF213_EXT) )
348 		if (!h213_cb_save_as()) return;
349 
350 	update_header(FROM);
351 	h213_buffer.assign(header("<hics213>"));
352 	h213_make_buffer(true);
353 	xfr_via_socket(h213_base_filename, h213_buffer);
354 
355 	h213_buffer.assign(header("<hics213>"));
356 	h213_make_buffer(false);
357 	h213_write(h213_def_filename);
358 }
359 
h213_cb_load_template()360 void h213_cb_load_template()
361 {
362 	string h213_def_filename = h213_def_template_name;
363 	const char *p = FSEL::select(
364 			"Open template file",
365 			string("Template file\t*").append(HT213_EXT).c_str(),
366 			h213_def_filename.c_str());
367 	if (p) {
368 		h213_clear_form();
369 		read_data_file(p);
370 		h213_def_template_name = p;
371 		show_filename(h213_def_template_name);
372 		h213_using_template = true;
373 	}
374 }
375 
h213_cb_save_template()376 void h213_cb_save_template()
377 {
378 	if (!h213_using_template) {
379 		cb_save_as_template();
380 		return;
381 	}
382 	string h213_def_filename = h213_def_template_name;
383 	const char *p = FSEL::saveas(
384 			"Save template file",
385 			string("Template file\t*").append(HT213_EXT).c_str(),
386 			h213_def_filename.c_str());
387 	if (p) {
388 		update_header(CHANGED);
389 		h213_update_fields();
390 		h213_buffer.assign(header("<hics213>"));
391 		h213_make_buffer();
392 		h213_write(p);
393 	}
394 }
395 
h213_cb_save_as_template()396 void h213_cb_save_as_template()
397 {
398 	string h213_def_filename = h213_def_template_name;
399 	const char *p = FSEL::saveas(
400 			"Save as template file",
401 			string("Template file\t*").append(HT213_EXT).c_str(),
402 			h213_def_filename.c_str());
403 	if (p) {
404 		const char *pext = fl_filename_ext(p);
405 		h213_def_template_name = p;
406 		if (strlen(pext) == 0) h213_def_template_name.append(HT213_EXT);
407 		remove_spaces_from_filename(h213_def_template_name);
408 		clear_header();
409 		update_header(CHANGED);
410 		h213_update_fields();
411 		h213_buffer.assign(header("<hics213>"));
412 		h213_make_buffer();
413 		h213_write(h213_def_template_name);
414 		show_filename(h213_def_template_name);
415 		h213_using_template = true;
416 	}
417 }
418 
h213_cb_open()419 void h213_cb_open()
420 {
421 	const char *p = FSEL::select(
422 			_("Open data file"),
423 			"HICS-213\t*.{H213}",
424 			h213_def_filename.c_str());
425 	if (!p) return;
426 	if (strlen(p) == 0) return;
427 	h213_clear_form();
428 	read_data_file(p);
429 	h213_using_template = false;
430 	h213_def_filename = p;
431 	show_filename(h213_def_filename);
432 }
433 
h213_write(string s)434 void h213_write(string s)
435 {
436 	FILE *hicsfile = fopen(s.c_str(), "w");
437 	if (!hicsfile) return;
438 
439 	fwrite(h213_buffer.c_str(), h213_buffer.length(), 1, hicsfile);
440 	fclose(hicsfile);
441 }
442 
h213_cb_save_as()443 bool h213_cb_save_as()
444 {
445 	const char *p;
446 	string newfilename;
447 
448 	string name = named_file();
449 	if (!name.empty()) {
450 	name.append(HF213_EXT);
451 		newfilename = ICS_msg_dir;
452 		newfilename.append(name);
453 	} else
454 		newfilename = h213_def_filename;
455 
456 	p = FSEL::saveas(_("Save data file"), "HICS-213\t*.{H213}",
457 					newfilename.c_str());
458 
459 	if (!p) return false;
460 	if (strlen(p) == 0) return false;
461 
462 	if (progStatus.sernbr_fname) update_sernbr();
463 
464 	const char *pext = fl_filename_ext(p);
465 	h213_def_filename = p;
466 	if (strlen(pext) == 0) h213_def_filename.append(HF213_EXT);
467 
468 	remove_spaces_from_filename(h213_def_filename);
469 	h213_update_fields();
470 	update_header(NEW);
471 	h213_buffer.assign(header("<hics213>"));
472 	h213_make_buffer();
473 	h213_write(h213_def_filename);
474 
475 	h213_using_template = false;
476 	show_filename(h213_def_filename);
477 	return true;
478 }
479 
h213_cb_save()480 void h213_cb_save()
481 {
482 	if (h213_base_filename == string("new").append(HF213_EXT) ||
483 		h213_base_filename == string("default").append(HF213_EXT) ||
484 		h213_using_template == true) {
485 		h213_cb_save_as();
486 		return;
487 	}
488 	if (check_hics213fields()) update_header(CHANGED);
489 	h213_buffer.assign(header("<hics213>"));
490 	h213_update_fields();
491 	h213_make_buffer();
492 	h213_write(h213_def_filename);
493 	h213_using_template = false;
494 }
495 
h213_cb_html()496 void h213_cb_html()
497 {
498 	string fname_name = fl_filename_name(h213_def_filename.c_str());
499 	size_t p = fname_name.rfind('.');
500 	if (p != string::npos) fname_name.erase(p);
501 
502 	string hicsname = ICS_dir;
503 	hicsname.append(fname_name);
504 	hicsname.append(".html");
505 
506 	string html_text = "";
507 
508 	h213_update_fields();
509 	string form = hics213_html_template;
510 
511 	string temp, temp2;
512 	for (int i = 0; i < h213_numfields; i++) {
513 		temp = h213_fields[i].f_type;
514 		if (temp == h213_tag_msg || temp == h213_tag_action ||
515 			temp == h213_tag_comments || temp == h213_tag_comments2 ) {
516 			temp2 = h213_fields[i].f_data;
517 			if (progStatus.autowordwrap)
518 				temp2 = wordwrap(h213_fields[i].f_data, progStatus.charcount);
519 			replacestr( form, h213_fields[i].f_type, temp2 );
520 		} else
521 			replacestr( form, h213_fields[i].f_type, h213_fields[i].f_data );
522 	}
523 
524 	FILE *hicsfile = fopen(hicsname.c_str(), "w");
525 	fprintf(hicsfile,"%s", form.c_str());
526 	fclose(hicsfile);
527 
528 	open_url(hicsname.c_str());
529 }
530 
h213_cb_textout()531 void h213_cb_textout()
532 {
533 	string hicsname = ICS_dir;
534 	hicsname.append("hics213.txt");
535 
536 	h213_update_fields();
537 	string form = hics213_text_template;
538 
539 	for (int i = 0; i < h213_numfields; i++)
540 		replacestr( form, h213_fields[i].f_type, h213_fields[i].f_data);
541 
542 	FILE *hicsfile = fopen(hicsname.c_str(), "w");
543 	fprintf(hicsfile,"%s", form.c_str());
544 	fclose(hicsfile);
545 
546 	open_url(hicsname.c_str());
547 }
548