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