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 #include "arl_msgs.h"
60
61 #ifdef WIN32
62 # include "flmsgrc.h"
63 # include "compat.h"
64 # define dirent fl_dirent_no_thanks
65 #endif
66
67 #include <FL/filename.H>
68 #include "dirent-check.h"
69
70 #include <FL/x.H>
71 #include <FL/Fl_Pixmap.H>
72 #include <FL/Fl_Image.H>
73
74 using namespace std;
75
76 string base_rg_filename = "";
77 string def_rg_filename = "";
78 string def_rg_TemplateName = "";
79
80 // Radiogram rgfields
81
82 const char *s_prec[] = {
83 "ROUTINE", "WELFARE", "PRIORITY", "EMERGENCY",
84 "TEST ROUTINE", "TEST WELFARE", "TEST PRIORITY", "TEST EMERGENCY"};
85 const char precitems[] =
86 "ROUTINE|WELFARE|PRIORITY|EMERGENCY|\
87 TEST ROUTINE|TEST WELFARE|TEST PRIORITY|TEST EMERGENCY";
88
89 const char *s_hx[] = {"", "HXA", "HXB", "HXC", "HXD", "HXE", "HXF", "HXG"};
90 const char hxitems[] = " |HXA|HXB|HXC|HXD|HXE|HXF|HXG";
91
92 // compatibility fields required to read older data files
93
94 string a_rg_nbr = "<nbr:"; // 0.
95 string a_rg_prec = "<prec:"; // 1.
96 string a_rg_hx = "<hx:"; // 2.
97 string a_rg_d1 = "<d1:"; // 3.
98 string a_rg_t1 = "<t1:"; // 4.
99 string a_rg_dt2 = "<dt2:"; // 5.
100 string a_rg_dt3 = "<dt3:"; // 6.
101 string a_rg_to = "<to:"; // 7.
102 string a_rg_phone = "<tel:"; // 8.
103 string a_rg_opnote = "<opn:"; // 9
104 string a_rg_msg = "<msg:"; // 10.
105 string a_rg_sig = "<sig:"; // 11.
106 string a_rg_opnote2 = "<op2:"; // 12
107 string a_rg_check = "<ck:"; // 13.
108 string a_rg_station = "<sta:"; // 14.
109 string a_rg_place = "<org:"; // 15
110 string a_rg_orig = "<ori:"; // 16
111 string a_rg_dlvd_to = "<dlv:"; // 17
112 string a_rg_sent_to = "<sto:"; // 18
113 string a_rg_snt_net = "<snt:"; // 19
114 string a_rg_dt4 = "<dt4:"; // 20
115 string a_rg_rcv_fm = "<rfm:"; // 21
116 string a_rg_rcv_net = "<rnt:"; // 22
117 string a_rg_dt5 = "<dt5:"; // 23
118 string a_rg_svc = "<svc:"; // 24
119
120 FIELD argfields[] = {
121 { a_rg_nbr, "", (void **)&txt_rg_nbr, 't' }, // 0
122 { a_rg_prec, "0", (void **)&sel_rg_prec, 's' }, // 1
123 { a_rg_hx, "", (void **)&txt_rg_hx, 't' }, // 2
124 { a_rg_d1, "", (void **)&txt_rg_d1, 't' }, // 3
125 { a_rg_t1, "", (void **)&txt_rg_t1, 't' }, // 4
126 { a_rg_dt2, "", (void **)&txt_rg_dt2, 't' }, // 5
127 { a_rg_dt3, "", (void **)&txt_rg_dt3, 't' }, // 6
128 { a_rg_to, "", (void **)&txt_rg_to, 't' }, // 7
129 { a_rg_phone, "", (void **)&txt_rg_phone, 't' }, // 8
130 { a_rg_opnote, "", (void **)&txt_rg_opnote, 't' }, // 9
131 { a_rg_msg, "", (void **)&txt_rg_msg, 'e' }, // 10
132 { a_rg_sig, "", (void **)&txt_rg_sig, 't' }, // 11
133 { a_rg_opnote2, "", (void **)&txt_rg_opnote2,'t' }, // 12
134 { a_rg_check, "", (void **)&txt_rg_check, 't' }, // 13
135 { a_rg_station, "", (void **)&txt_rg_station,'t' }, // 14
136 { a_rg_place, "", (void **)&txt_rg_place, 't' }, // 15
137 { a_rg_orig, "", (void **)&txt_rg_orig, 't' }, // 16
138 { a_rg_dlvd_to, "", (void **)&txt_rg_dlvd_to,'t' }, // 17
139 { a_rg_sent_to, "", (void **)&txt_rg_sent_to,'t' }, // 18
140 { a_rg_snt_net, "", (void **)&txt_rg_snt_net,'t' }, // 19
141 { a_rg_dt4, "", (void **)&txt_rg_dt4, 't' }, // 20
142 { a_rg_rcv_fm, "", (void **)&txt_rg_rcv_fm, 't' }, // 21
143 { a_rg_rcv_net, "", (void **)&txt_rg_rcv_net,'t' }, // 22
144 { a_rg_dt5, "", (void **)&txt_rg_dt5, 't' }, // 23
145 { a_rg_svc, "", (void **)&btn_rg_svc, 'b' } // 24
146 };
147
148 // new tag strings
149
150 string _rg_nbr = ":nbr:"; // 0.
151 string _rg_prec = ":prec:"; // 1.
152 string _rg_hx = ":hx:"; // 2.
153 string _rg_d1 = ":d1:"; // 3.
154 string _rg_t1 = ":t1:"; // 4.
155 string _rg_dt2 = ":dt2:"; // 5.
156 string _rg_dt3 = ":dt3:"; // 6.
157 string _rg_to = ":to:"; // 7.
158 string _rg_phone = ":tel:"; // 8.
159 string _rg_opnote = ":opn:"; // 9
160 string _rg_msg = ":msg:"; // 10.
161 string _rg_sig = ":sig:"; // 11.
162 string _rg_opnote2 = ":op2:"; // 12
163 string _rg_check = ":ck:"; // 13.
164 string _rg_station = ":sta:"; // 14.
165 string _rg_place = ":org:"; // 15
166 string _rg_orig = ":ori:"; // 16
167 string _rg_dlvd_to = ":dlv:"; // 17
168 string _rg_sent_to = ":sto:"; // 18
169 string _rg_snt_net = ":snt:"; // 19
170 string _rg_dt4 = ":dt4:"; // 20
171 string _rg_rcv_fm = ":rfm:"; // 21
172 string _rg_rcv_net = ":rnt:"; // 22
173 string _rg_dt5 = ":dt5:"; // 23
174 string _rg_svc = ":svc:"; // 24
175 string _rg_standard = ":std:"; // 25
176
177 FIELD rgfields[] = {
178 { _rg_nbr, "", (void **)&txt_rg_nbr, 't' }, // 0
179 { _rg_prec, "0", (void **)&sel_rg_prec, 's' }, // 1
180 { _rg_hx, "", (void **)&txt_rg_hx, 't' }, // 2
181 { _rg_d1, "", (void **)&txt_rg_d1, 't' }, // 3
182 { _rg_t1, "", (void **)&txt_rg_t1, 't' }, // 4
183 { _rg_dt2, "", (void **)&txt_rg_dt2, 't' }, // 5
184 { _rg_dt3, "", (void **)&txt_rg_dt3, 't' }, // 6
185 { _rg_to, "", (void **)&txt_rg_to, 't' }, // 7
186 { _rg_phone, "", (void **)&txt_rg_phone, 't' }, // 8
187 { _rg_opnote, "", (void **)&txt_rg_opnote, 't' }, // 9
188 { _rg_msg, "", (void **)&txt_rg_msg, 'e' }, // 10
189 { _rg_sig, "", (void **)&txt_rg_sig, 't' }, // 11
190 { _rg_opnote2, "", (void **)&txt_rg_opnote2, 't' }, // 12
191 { _rg_check, "", (void **)&txt_rg_check, 't' }, // 13
192 { _rg_station, "", (void **)&txt_rg_station, 't' }, // 14
193 { _rg_place, "", (void **)&txt_rg_place, 't' }, // 15
194 { _rg_orig, "", (void **)&txt_rg_orig, 't' }, // 16
195 { _rg_dlvd_to, "", (void **)&txt_rg_dlvd_to, 't' }, // 17
196 { _rg_sent_to, "", (void **)&txt_rg_sent_to, 't' }, // 18
197 { _rg_snt_net, "", (void **)&txt_rg_snt_net, 't' }, // 19
198 { _rg_dt4, "", (void **)&txt_rg_dt4, 't' }, // 20
199 { _rg_rcv_fm, "", (void **)&txt_rg_rcv_fm, 't' }, // 21
200 { _rg_rcv_net, "", (void **)&txt_rg_rcv_net, 't' }, // 22
201 { _rg_dt5, "", (void **)&txt_rg_dt5, 't' }, // 23
202 { _rg_svc, "F", (void **)&btn_rg_svc, 'b' }, // 24
203 { _rg_standard, "T", (void **)&btn_rg_standard, 'B' } // 25
204 };
205
206 bool using_rg_template = false;
207
208 int num_rgfields = sizeof(rgfields) / sizeof(FIELD);
209
fld_nbr(string & fld)210 int fld_nbr(string &fld)
211 {
212 for (int i = 0; i < num_rgfields; i++)
213 if (fld == rgfields[i].f_type)
214 return i;
215 printf("err %s\n", fld.c_str());
216 exit(1);
217 }
218
219 //======================================================================
220
cb_rgSetDate1()221 void cb_rgSetDate1()
222 {
223 txt_rg_d1->value(szAbbrevDate());
224 }
225
cb_rgSetTime1()226 void cb_rgSetTime1()
227 {
228 txt_rg_t1->value(szTime(progStatus.UTC <= 1 ? 0 : 2));
229 }
230
cb_rgSetDateTime2()231 void cb_rgSetDateTime2()
232 {
233 txt_rg_dt2->value(szDateTime());
234 }
235
cb_rgSetDateTime3()236 void cb_rgSetDateTime3()
237 {
238 txt_rg_dt3->value(szDateTime());
239 }
240
cb_rgSetDateTime4()241 void cb_rgSetDateTime4()
242 {
243 txt_rg_dt4->value(szDateTime());
244 }
245
cb_rgSetDateTime5()246 void cb_rgSetDateTime5()
247 {
248 txt_rg_dt5->value(szDateTime());
249 }
250
cb_rg_nbr(Fl_Widget * wdg)251 void cb_rg_nbr(Fl_Widget *wdg)
252 {
253 Fl_Input2 *inp = (Fl_Input2 *)wdg;
254 string s = inp->value();
255 for (size_t n = 0; n < s.length(); n++)
256 if (!isdigit(s[n])) s.erase(n,1);
257 strip_leading_zeros(s);
258 inp->value(s.c_str());
259 }
260
261 static char valid_input[] = "0123456789/ ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
262
cb_rg_filter_input(Fl_Widget * wdg)263 void cb_rg_filter_input(Fl_Widget *wdg)
264 {
265 Fl_Input2 *inp = (Fl_Input2 *)wdg;
266 int p = inp->position();
267 string s = inp->value();
268 ucase(s);
269 for (size_t n = 0; n < s.length(); n++)
270 if (strchr(valid_input, s[n]) == NULL)
271 s.erase(n,1);
272 inp->value(s.c_str());
273 inp->position(p);
274 }
275
clear_rgfields()276 void clear_rgfields()
277 {
278 for (int i = 0; i < num_rgfields; i++) {
279 switch (rgfields[i].w_type) {
280 case 's':
281 rgfields[i].f_data = "0";
282 break;
283 case 'b':
284 rgfields[i].f_data = "F";
285 break;
286 case 'B':
287 rgfields[i].f_data = "T";
288 break;
289 default:
290 rgfields[i].f_data.clear();
291 }
292 }
293 }
294
numeric(int n)295 string numeric(int n)
296 {
297 static char snum[12];
298 snprintf(snum, sizeof(snum), "%d", n);
299 return snum;
300 }
301
set_rg_choices()302 void set_rg_choices() {
303 sel_rg_prec->clear();
304 sel_rg_prec->add(precitems);
305 sel_rg_prec->index(0);
306 }
307
check_rgfields()308 bool check_rgfields()
309 {
310 string temp;
311 for (int i = 0; i < num_rgfields; i++) {
312 if (rgfields[i].w == NULL) return false;
313 if (rgfields[i].w_type == 'd') {
314 if (rgfields[i].f_data != ((Fl_DateInput *)(*rgfields[i].w))->value())
315 return true;
316 } else if (rgfields[i].w_type == 't') {
317 if (rgfields[i].f_data != ((Fl_Input2 *)(*rgfields[i].w))->value())
318 return true;
319 } else if (rgfields[i].w_type == 's') {
320 int choice = ((Fl_ListBox *)(*rgfields[i].w))->index();
321 if (rgfields[i].f_data != numeric(choice))
322 return true;
323 } else if (rgfields[i].w_type == 'e') {
324 if (rgfields[i].f_data != ((FTextEdit *)(*rgfields[i].w))->buffer()->text())
325 return true;
326 } else if (rgfields[i].w_type == 'b') {
327 temp = ((Fl_Button *)(*rgfields[i].w))->value() ? "T" : "F";
328 if (rgfields[i].f_data != temp)
329 return true;
330 } else if (rgfields[i].w_type == 'B'){
331 temp = ((Fl_Button *)(*rgfields[i].w))->value() ? "T" : "F";
332 if (rgfields[i].f_data != temp)
333 return true;
334 }
335 }
336 return false;
337 }
338
update_rgfields()339 void update_rgfields()
340 {
341 for (int i = 0; i < num_rgfields; i++) {
342 if (rgfields[i].w_type == 'd')
343 rgfields[i].f_data = ((Fl_DateInput *)(*rgfields[i].w))->value();
344 else if (rgfields[i].w_type == 't')
345 rgfields[i].f_data = ((Fl_Input2 *)(*rgfields[i].w))->value();
346 else if (rgfields[i].w_type == 's') {
347 int choice = ((Fl_ListBox *)(*rgfields[i].w))->index();
348 if (choice >= 0)
349 rgfields[i].f_data = numeric(choice);
350 } else if (rgfields[i].w_type == 'e')
351 rgfields[i].f_data = ((FTextEdit *)(*rgfields[i].w))->buffer()->text();
352 else if (rgfields[i].w_type == 'b')
353 rgfields[i].f_data = ((Fl_Button *)(*rgfields[i].w))->value() ? "T" : "F";
354 else if (rgfields[i].w_type == 'B')
355 rgfields[i].f_data = ((Fl_Button *)(*rgfields[i].w))->value() ? "T" : "F";
356 }
357 }
358
clear_rg_form()359 void clear_rg_form()
360 {
361 clear_rgfields();
362
363 if (progStatus.rgnbr_fname)
364 txt_rg_nbr->value(progStatus.rgnbr.c_str());
365 else
366 txt_rg_nbr->value("");
367
368 for (int i = 1; i < num_rgfields; i++)
369 if (rgfields[i].w_type == 'd')
370 ((Fl_DateInput *)(*rgfields[i].w))->value("");
371 else if (rgfields[i].w_type == 't')
372 ((Fl_Input2 *)(*rgfields[i].w))->value("");
373 else if (rgfields[i].w_type == 's')
374 ((Fl_ListBox *)(*rgfields[i].w))->index(0);
375 else if (rgfields[i].w_type == 'e')
376 ((FTextEdit *)(*rgfields[i].w))->clear();
377 else if (rgfields[i].w_type == 'b')
378 ((Fl_Button *)(*rgfields[i].w))->value(0);
379 else if (rgfields[i].w_type == 'B')
380 ((Fl_Button *)(*rgfields[i].w))->value(1);
381 update_rgfields();
382 }
383
update_rg_form()384 void update_rg_form()
385 {
386 for (int i = 0; i < num_rgfields; i++) {
387 if (rgfields[i].w_type == 'd')
388 ((Fl_DateInput *)(*rgfields[i].w))->value(rgfields[i].f_data.c_str());
389 else if (rgfields[i].w_type == 't')
390 ((Fl_Input2 *)(*rgfields[i].w))->value(rgfields[i].f_data.c_str());
391 else if (rgfields[i].w_type == 's')
392 ((Fl_ListBox *)(*rgfields[i].w))->index(atoi(rgfields[i].f_data.c_str()));
393 else if (rgfields[i].w_type == 'e') {
394 ((FTextEdit *)(*rgfields[i].w))->clear();
395 ((FTextEdit *)(*rgfields[i].w))->add(rgfields[i].f_data.c_str());
396 } else if (rgfields[i].w_type == 'b')
397 ((Fl_Button *)(*rgfields[i].w))->value(rgfields[i].f_data == "T" ? 1 : 0);
398 else if (rgfields[i].w_type == 'B')
399 ((Fl_Button *)(*rgfields[i].w))->value(rgfields[i].f_data == "T" ? 1 : 0);
400 }
401 }
402
make_rg_buffer(bool compress=false)403 void make_rg_buffer(bool compress = false)
404 {
405 string mbuff;
406 mbuff.clear();
407 for (int i = 0; i < num_rgfields; i++)
408 mbuff.append( lineout( rgfields[i].f_type, rgfields[i].f_data ) );
409 if (compress) compress_maybe(mbuff);
410 buffer.append(mbuff);
411 }
412
read_rg_buffer(string data)413 void read_rg_buffer(string data)
414 {
415 bool data_ok = false;
416 clear_fields();
417 read_header(data);
418
419 string temp;
420 for (int i = 0; i < num_rgfields; i++) {
421 temp = findstr(data, rgfields[i].f_type);
422 if (!temp.empty()) rgfields[i].f_data = temp;
423 if (!rgfields[i].f_data.empty()) data_ok = true;
424 }
425 if (!data_ok)
426 for (int i = 0; i < num_rgfields; i++)
427 rgfields[i].f_data = findstr(data, argfields[i].f_type);
428
429 update_rg_form();
430 }
431
cb_rg_new()432 void cb_rg_new()
433 {
434 if (check_rgfields()) {
435 if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 1) {
436 update_header(CHANGED);
437 cb_rg_save();
438 }
439 }
440 clear_rg_form();
441 clear_header();
442 def_rg_filename = ICS_msg_dir;
443 def_rg_filename.append("new").append(RGFILE_EXT);
444 using_rg_template = false;
445 show_filename(def_rg_filename);
446 }
447
cb_rg_import()448 void cb_rg_import()
449 {
450 string def_rg_filename = ICS_dir;
451 def_rg_filename.append("DEFAULT.XML");
452 const char *p = FSEL::select(
453 "Open Qforms xml file",
454 "Qforms xml\t*.{xml,XML}",
455 def_rg_filename.c_str());
456 if (p){
457 clear_rg_form();
458 qform_rg_import(p);
459 using_rg_template = false;
460 }
461 }
462
cb_rg_export()463 void cb_rg_export()
464 {
465 string exp_rgFileName = ICS_dir;
466 exp_rgFileName.append(base_rg_filename);
467 exp_rgFileName.append(".XML");
468 const char *p = FSEL::saveas(
469 "Open Qforms xml file",
470 "Qforms xml\t*.{xml,XML}",
471 exp_rgFileName.c_str());
472 if (p) {
473 const char *pext = fl_filename_ext(p);
474 exp_rgFileName = p;
475 if (strlen(pext) == 0) exp_rgFileName.append(".XML");
476 qform_rg_export(exp_rgFileName);
477 }
478 }
479
cb_rg_wrap_import(string wrapfilename,string inpbuffer)480 void cb_rg_wrap_import(string wrapfilename, string inpbuffer)
481 {
482 clear_rg_form();
483 read_rg_buffer(inpbuffer);
484 def_rg_filename = ICS_msg_dir;
485 def_rg_filename.append(wrapfilename);
486 show_filename(def_rg_filename);
487 using_rg_template = false;
488 }
489
eval_rg_fsize()490 int eval_rg_fsize()
491 {
492 Ccrc16 chksum;
493 evalstr.assign("[WRAP:beg][WRAP:lf][WRAP:fn ");
494 evalstr.append(base_rg_filename).append("]");
495 update_rgfields();
496 update_header(FROM);
497 evalstr.append(header("<radiogram>"));
498 buffer.clear();
499 make_rg_buffer(true);
500 if (buffer.empty()) return 0;
501 evalstr.append( buffer );
502 evalstr.append("[WRAP:chksum ").append(chksum.scrc16(evalstr)).append("][WRAP:end]");
503 return evalstr.length();
504 }
505
cb_rg_wrap_export()506 void cb_rg_wrap_export()
507 {
508 if (btn_rg_check->labelcolor() == FL_RED)
509 cb_rg_check();
510
511 if (check_rgfields()) {
512 if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
513 return;
514 update_header(CHANGED);
515 }
516 update_rgfields();
517
518 if (base_rg_filename == string("new").append(RGFILE_EXT) ||
519 base_rg_filename == string("default").append(RGFILE_EXT) )
520 if (!cb_rg_save_as()) return;
521
522 string wrapfilename = WRAP_send_dir;
523 wrapfilename.append(base_rg_filename);
524 wrapfilename.append(WRAP_EXT);
525 const char *p = FSEL::saveas(
526 "Save as wrapped radiogram file",
527 "Wrap file\t*.{wrap,WRAP}",
528 wrapfilename.c_str());
529 if (p) {
530 if (btn_rg_check->labelcolor() == FL_RED)
531 cb_rg_check();
532 string pext = fl_filename_ext(p);
533 wrapfilename = p;
534
535 update_header(FROM);
536 buffer.assign(header("<radiogram>"));
537 make_rg_buffer(true);
538 export_wrapfile(base_rg_filename, wrapfilename, buffer, pext != WRAP_EXT);
539
540 buffer.assign(header("<radiogram>"));
541 make_rg_buffer(false);
542 write_rg(def_rg_filename);
543 }
544 }
545
cb_rg_wrap_autosend()546 void cb_rg_wrap_autosend()
547 {
548 if (btn_rg_check->labelcolor() == FL_RED)
549 cb_rg_check();
550
551 if (check_rgfields()) {
552 if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
553 return;
554 update_header(CHANGED);
555 }
556 update_rgfields();
557
558 if (base_rg_filename == string("new").append(RGFILE_EXT) ||
559 base_rg_filename == string("default").append(RGFILE_EXT) )
560 if (!cb_rg_save_as()) return;
561
562 update_header(FROM);
563 buffer.assign(header("<radiogram>"));
564 make_rg_buffer(true);
565 xfr_via_socket(base_rg_filename, buffer);
566
567 buffer.assign(header("<radiogram>"));
568 make_rg_buffer(false);
569 write_rg(def_rg_filename);
570 }
571
cb_rg_load_template()572 void cb_rg_load_template()
573 {
574 string def_rg_filename = def_rg_TemplateName;
575 const char *p = FSEL::select(
576 "Open template file",
577 string("Template file\t*").append(RGTEMP_EXT).c_str(),
578 def_rg_filename.c_str());
579 if (p) {
580 clear_rg_form();
581 read_data_file(p);
582 def_rg_TemplateName = p;
583 show_filename(def_rg_TemplateName);
584 using_rg_template = true;
585 }
586 }
587
cb_rg_save_template()588 void cb_rg_save_template()
589 {
590 if (!using_rg_template) {
591 cb_rg_save_as_template();
592 return;
593 }
594 string def_rg_filename = def_rg_TemplateName;
595 const char *p = FSEL::saveas(
596 "Save template file",
597 string("Template file\t*").append(RGTEMP_EXT).c_str(),
598 def_rg_filename.c_str());
599 if (p) {
600 update_header(CHANGED);
601 update_rgfields();
602 buffer.assign(header("<radiogram>"));
603 make_rg_buffer();
604 write_rg(p);
605 }
606 }
607
cb_rg_save_as_template()608 void cb_rg_save_as_template()
609 {
610 string def_rg_filename = def_rg_TemplateName;
611 const char *p = FSEL::saveas(
612 "Save as template file",
613 string("Template file\t*").append(RGTEMP_EXT).c_str(),
614 def_rg_filename.c_str());
615 if (p) {
616 const char *pext = fl_filename_ext(p);
617 def_rg_TemplateName = p;
618 if (strlen(pext) == 0) def_rg_TemplateName.append(RGTEMP_EXT);
619 remove_spaces_from_filename(def_rg_TemplateName);
620
621 clear_header();
622 update_header(CHANGED);
623 buffer.assign(header("<radiogram>"));
624 make_rg_buffer();
625 write_rg(def_rg_TemplateName);
626
627 show_filename(def_rg_TemplateName);
628 using_rg_template = true;
629 }
630 }
631
cb_rg_open()632 void cb_rg_open()
633 {
634 const char *p = FSEL::select(
635 _("Open data file"),
636 string("radiogram\t*").append(RGFILE_EXT).c_str(),
637 def_rg_filename.c_str());
638 if (!p) return;
639 if (strlen(p) == 0) return;
640 clear_rg_form();
641 read_data_file(p);
642 using_rg_template = false;
643 def_rg_filename = p;
644 show_filename(def_rg_filename);
645 }
646
write_rg(string s)647 void write_rg(string s)
648 {
649 FILE *rgfile = fopen(s.c_str(), "w");
650 if (!rgfile) return;
651
652 fwrite(buffer.c_str(), buffer.length(), 1, rgfile);
653 fclose(rgfile);
654 }
655
cb_rg_save_as()656 bool cb_rg_save_as()
657 {
658 const char *p;
659 string newfilename;
660 string name = named_file();
661
662 if (!name.empty()) {
663 name.append(RGFILE_EXT);
664 newfilename = ICS_msg_dir;
665 newfilename.append(name);
666 } else
667 newfilename = def_rg_filename;
668 p = FSEL::saveas(
669 _("Save data file"),
670 string("radiogram\t*").append(RGFILE_EXT).c_str(),
671 newfilename.c_str());
672
673 if (!p) return false;
674 if (strlen(p) == 0) return false;
675
676 if (progStatus.rgnbr_fname) {
677 int n = atoi(progStatus.rgnbr.c_str());
678 n++;
679 char szn[12];
680 snprintf(szn, sizeof(szn), "%d", n);
681 progStatus.rgnbr = szn;
682 txt_rgnbr->value(szn);
683 txt_rgnbr->redraw();
684 } else if (progStatus.sernbr_fname)
685 update_sernbr();
686
687 const char *pext = fl_filename_ext(p);
688 def_rg_filename = p;
689 if (strlen(pext) == 0) def_rg_filename.append(RGFILE_EXT);
690
691 remove_spaces_from_filename(def_rg_filename);
692
693 update_header(NEW);
694 update_rgfields();
695 buffer.assign(header("<radiogram>"));
696 make_rg_buffer();
697 write_rg(def_rg_filename);
698
699 using_rg_template = false;
700 show_filename(def_rg_filename);
701 return true;
702 }
703
cb_rg_save()704 void cb_rg_save()
705 {
706 if (base_rg_filename == string("new").append(RGFILE_EXT) ||
707 base_rg_filename == string("default").append(RGFILE_EXT) ||
708 using_rg_template == true) {
709 cb_rg_save_as();
710 return;
711 }
712
713 if (check_rgfields()) update_header(CHANGED);
714 update_rgfields();
715 buffer.assign(header("<radiogram>"));
716 make_rg_buffer();
717 write_rg(def_rg_filename);
718 using_rg_template = false;
719 }
720
721 const char *punctuation[] = {
722 ". ", " X ",
723 ",", " COMMA ",
724 "?", " QUERY ",
725 "\\", " BACKSLASH ",
726 "://", " COLON SLASH SLASH ",
727 "~", " TILDE ",
728 "_", " UNDERSCORE ",
729 "@", " AT ",
730 "#", " POUNDSIGN ",
731 "\"", " QUOTE ",
732 "\'", "",
733 0, 0 };
734
cb_rg_check()735 void cb_rg_check()
736 {
737 string temp = txt_rg_msg->buffer()->text();
738 if (temp.empty()) {
739 txt_rg_check->value("");
740 btn_rg_check->labelcolor(FL_BLACK);
741 btn_rg_check->redraw_label();
742 return;
743 }
744
745 size_t pos = string::npos;
746
747 if (btn_rg_standard->value()) {
748 // convert to uppercase
749 for (size_t n = 0; n < temp.length(); n++)
750 temp[n] = toupper(temp[n]);
751
752 strip_lfs(temp);
753 // remove trailing period
754 if (temp[temp.length()-1] == '.') temp.erase(temp.length()-1,1);
755 // convert punctuation
756 for (int n = 0; punctuation[n]; n += 2)
757 while ((pos = temp.find(punctuation[n])) != string::npos)
758 temp.replace(pos, strlen(punctuation[n]), punctuation[n+1]);
759 //convert embedded periods
760 while ((pos = temp.find(".")) != string::npos)
761 if (isdigit(temp[pos-1]) || isdigit(temp[pos+1]))
762 temp[pos] = 'R';
763 else
764 temp.replace(pos, 1, " DOT ");
765 }
766
767 // remove any user inserted end-of-lines
768 while ((pos = temp.find('\n')) != string::npos) temp[pos] = ' ';
769
770 // only single spaces no trailing spaces, no leading spaces
771 while ((pos = temp.find(" ")) != string::npos) temp.erase(pos,1);
772 while (temp[temp.length() -1] == ' ') temp.erase(temp.length()-1, 1);
773 if (temp[0] == ' ') temp.erase(0,1);
774
775 // count number of words in textdef_rg_filename
776 int numwords = 1;
777 if (temp.length()) {
778 pos = 0;
779 while ((pos = temp.find(" ", pos + 1)) != string::npos) numwords++;
780 }
781
782 // no more than specified # words to a line
783 if (numwords > progStatus.wpl) {
784 int wc = numwords;
785 size_t pos = 0;
786 while (wc > progStatus.wpl) {
787 for (int i = 0; i < progStatus.wpl; i++) pos = temp.find(' ', pos + 1);
788 temp[pos] = '\n';
789 wc -= progStatus.wpl;
790 }
791 }
792 // insert trailing end-of-line
793 temp += '\n';
794
795 // return converted text to editor
796 txt_rg_msg->clear();
797 txt_rg_msg->addstr(temp.c_str());
798
799 char snum[15];
800 snprintf(snum, sizeof(snum), "%s%d",
801 temp.find("ARL") != string::npos ? "ARL " : "",
802 numwords);
803 txt_rg_check->value(snum);
804 update_rgfields();
805 btn_rg_check->labelcolor(FL_BLACK);
806 btn_rg_check->redraw_label();
807 }
808
cb_rg_html()809 void cb_rg_html()
810 {
811 string rgname;
812 string html_text;
813 unsigned int nbr;
814 rgname = ICS_dir;
815 rgname.append("radiogram.html");
816
817 update_rgfields();
818 cb_rg_check();
819 string form;
820 if (progStatus.rri) form = rri_html_template;
821 else form = rg_html_template;
822
823 for (int i = 0; i < num_rgfields; i++) {
824 if (rgfields[i].f_type == _rg_prec) {
825 sscanf(rgfields[i].f_data.c_str(), "%u", &nbr);
826 if (nbr >= 0 && nbr < (sizeof(s_prec) / sizeof(*s_prec)))
827 html_text = s_prec[nbr];
828 else
829 html_text = s_prec[0];
830 replacestr( form, rgfields[i].f_type, html_text );
831 } else if (rgfields[i].w_type == 'b') {
832 replacestr( form, rgfields[i].f_type, rgfields[i].f_data == "T" ? yes : no);
833 } else
834 replacestr( form, rgfields[i].f_type, rgfields[i].f_data );
835 }
836
837 string rxstr = "";
838 rxstr.append(progStatus.my_call).append(" ").append(progStatus.my_tel);
839 rxstr.append("\n").append(progStatus.my_name);
840 rxstr.append("\n").append(progStatus.my_addr);
841 rxstr.append("\n").append(progStatus.my_city);
842 html_text = ":rx:";
843 replacestr( form, html_text, rxstr);
844
845 html_text = ":exp:";
846 string arlmsgs = "";
847 if (progStatus.arl_desc)
848 arlmsgs = expand_arl(rgfields[10].f_data);
849 replacestr( form, html_text, arlmsgs);
850
851 FILE *rgfile = fopen(rgname.c_str(), "w");
852 fprintf(rgfile,"%s", form.c_str());
853 fclose(rgfile);
854
855 open_url(rgname.c_str());
856 }
857
cb_rg_html_fcopy()858 void cb_rg_html_fcopy()
859 {
860 string rgname;
861 string MSG = "";
862 string html_text;
863 unsigned int nbr;
864 rgname = ICS_dir;
865 rgname.append("rg_file_copy.html");
866
867 update_rgfields();
868 cb_rg_check();
869 string form;
870 if (progStatus.rri) form = rri_html_fcopy_template;
871 else form = rg_html_fcopy_template;
872
873 for (int i = 0; i < num_rgfields; i++) {
874 if (rgfields[i].f_type == _rg_prec) {
875 sscanf(rgfields[i].f_data.c_str(), "%u", &nbr);
876 if (nbr >= 0 && nbr < (sizeof(s_prec) / sizeof(*s_prec)))
877 html_text = s_prec[nbr];
878 else
879 html_text = s_prec[0];
880 replacestr( form, rgfields[i].f_type, html_text);
881 } else if (rgfields[i].w_type == 'b') {
882 replacestr( form, rgfields[i].f_type, rgfields[i].f_data == "T" ? yes : no);
883 } else
884 replacestr( form, rgfields[i].f_type, rgfields[i].f_data );
885 }
886
887 string rxstr = "";
888 rxstr.append(progStatus.my_call).append(" ").append(progStatus.my_tel);
889 rxstr.append("\n").append(progStatus.my_name);
890 rxstr.append("\n").append(progStatus.my_addr);
891 rxstr.append("\n").append(progStatus.my_city);
892 html_text = ":rx:";
893 replacestr( form, html_text, rxstr);
894
895 FILE *rgfile = fopen(rgname.c_str(), "w");
896 fprintf(rgfile,"%s", form.c_str());
897 fclose(rgfile);
898
899 open_url(rgname.c_str());
900 }
901
cb_rg_textout()902 void cb_rg_textout()
903 {
904 string rgname;
905 string lines;
906 string str;
907 unsigned int nbr = 0;
908 rgname = ICS_dir;
909 rgname.append("radiogram.txt");
910
911 update_rgfields();
912 cb_rg_check();
913
914 string form;
915 if (progStatus.rri) form = rri_txt_template;
916 else form = rg_txt_template;
917
918 for (int i = 0; i < num_rgfields; i++) {
919 str.clear();
920 if (rgfields[i].f_type == _rg_prec) {
921 sscanf(rgfields[i].f_data.c_str(), "%u", &nbr);
922 if (nbr < 0) nbr = 0;
923 if (nbr >= sizeof(s_prec)/sizeof(*s_prec)) nbr = 0;
924 str = s_prec[nbr];
925 if (str.find("TEST") != string::npos) { // test message
926 if (str.find("EMERGENCY") == string::npos)
927 str = str.substr(0, 6);
928 } else {
929 if (str.find("EMERGENCY") == string::npos)
930 str = str[0];
931 }
932 replacestr( form, rgfields[i].f_type, str);
933 } else if (rgfields[i].w_type == 'e' || rgfields[i].w_type == 't') {
934 if (rgfields[i].f_type == _rg_opnote || rgfields[i].f_type == _rg_opnote2) {
935 if (!rgfields[i].f_data.empty())
936 str.append("\nOPNOTE ").append(rgfields[i].f_data);
937 } else if (rgfields[i].f_type == _rg_hx && !rgfields[i].f_data.empty()) {
938 str = " ";
939 str.append(rgfields[i].f_data);
940 } else {
941 str = rgfields[i].f_data;
942 strip_lfs(str);
943 }
944 replacestr( form, rgfields[i].f_type, str );
945 } else
946 replacestr( form, rgfields[i].f_type, rgfields[i].f_data );
947 }
948
949 FILE *rgfile = fopen(rgname.c_str(), "w");
950 fprintf(rgfile,"%s", form.c_str());
951 fclose(rgfile);
952 open_url(rgname.c_str());
953 }
954
955