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 "combo.h"
53 #include "date.h"
54 #include "calendar.h"
55 #include "icons.h"
56 #include "fileselect.h"
57 #include "wrap.h"
58 #include "status.h"
59 #include "parse_xml.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 wxhc_rptsta;
77 string wxhc_email;
78 string wxhc_phone;
79 string wxhc_addr;
80 string wxhc_city;
81 string wxhc_state;
82 string wxhc_country;
83 string wxhc_lat;
84 string wxhc_long;
85 string wxhc_date;
86 string wxhc_time;
87 
88 bool wxhc_meas;
89 bool wxhc_est;
90 string wxhc_wind_speed;
91 string wxhc_wind_speed_units;
92 string wxhc_wind_gusts;
93 string wxhc_wind_gusts_units;
94 string wxhc_wind_dir;
95 string wxhc_wind_degrees;
96 string wxhc_baro_press;
97 string wxhc_baro_units;
98 
99 string wxhc_comments;
100 
101 const char *s_wsu_units[] = { "MPH", "KNOTS", "KPH", NULL };
102 const char *s_wdu_units[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", NULL };
103 const char *s_baro_units[] = { "Inches", "Millibars", NULL };
104 
105 // could not use real names ... WIN32 barfs
106 enum NHC_QTYPE { B, S, M, T, I, F, C, O, E };
107 // bool, string, multi-line string, text, int, float, character, cOmbo, empty
108 
109 struct NHC_QUAD {
110 	NHC_QTYPE  qtype;  // type of field
111 	string html_fld;
112 	void   *ptr;
113 	Fl_Widget *widget; };
114 
115 NHC_QUAD wxhc_QUAD[] = {
116 { S,	":rptsta:",		&wxhc_rptsta,			w_wxhc_rptsta },			// 0
117 { S,	":email:",		&wxhc_email,			w_wxhc_email },				// 1
118 { S,	":phone:",		&wxhc_phone,			w_wxhc_phone },				// 2
119 { S,	":addr:",		&wxhc_addr,				w_wxhc_addr },				// 3
120 { S,	":city:",		&wxhc_city,				w_wxhc_city },				// 4
121 { S,	":state:",		&wxhc_state,			w_wxhc_state },				// 5
122 { S,	":country:",	&wxhc_country,			w_wxhc_country },			// 6
123 { S,	":lat:",		&wxhc_lat,				w_wxhc_lat },				// 7
124 { S,	":long:",		&wxhc_long,				w_wxhc_long },				// 8
125 { S,	":date:",		&wxhc_date,				w_wxhc_date },				// 9
126 { S,	":time:",		&wxhc_time,				w_wxhc_time },				// 10
127 
128 { B,	":meas:",		&wxhc_meas,				w_wxhc_meas },				// 11
129 { B,	":est:",		&wxhc_est,				w_wxhc_est },				// 12
130 { S,	":wspd:",		&wxhc_wind_speed,		w_wxhc_wind_speed },		// 13
131 { O,	":wsunits:",	&wxhc_wind_speed_units,	w_wxhc_wind_speed_units},	// 14
132 { S,	":wgst:",		&wxhc_wind_gusts,		w_wxhc_wind_gusts },		// 15
133 { O,	":wgunits:",	&wxhc_wind_gusts_units,	w_wxhc_wind_gusts_units },	// 16
134 { O,	":wdir:",		&wxhc_wind_dir,			w_wxhc_wind_dir },			// 17
135 { S,	":wdeg:",		&wxhc_wind_degrees,		w_wxhc_wind_degrees },		// 18
136 { S,	":baro:",		&wxhc_baro_press,		w_wxhc_baro_press },		// 19
137 { O,	":bunits:",		&wxhc_baro_units,		w_wxhc_baro_units },		// 20
138 
139 { T,	":cmmts:",		&wxhc_comments,			w_wxhc_comments },			// 21
140 
141 { E,	"",				NULL,					NULL }
142 };
143 
144 string buffwxhc;
145 string def_wxhc_filename = "";
146 string base_wxhc_filename = "";
147 string def_wxhc_TemplateName = "";
148 
149 bool using_wxhc_template = false;
150 static bool fields_initialized = false;
151 
152 // required to initialize the control pointers in the QUAD array
153 
init_widgets()154 static void init_widgets()
155 {
156 	wxhc_QUAD[0].widget  = w_wxhc_rptsta;
157 	wxhc_QUAD[1].widget  = w_wxhc_email;
158 	wxhc_QUAD[2].widget  = w_wxhc_phone;
159 	wxhc_QUAD[3].widget  = w_wxhc_addr;
160 	wxhc_QUAD[4].widget  = w_wxhc_city;
161 	wxhc_QUAD[5].widget  = w_wxhc_state;
162 	wxhc_QUAD[6].widget  = w_wxhc_country;
163 	wxhc_QUAD[7].widget  = w_wxhc_lat;
164 	wxhc_QUAD[8].widget  = w_wxhc_long;
165 	wxhc_QUAD[9].widget  = w_wxhc_date;
166 	wxhc_QUAD[10].widget = w_wxhc_time;
167 	wxhc_QUAD[11].widget = w_wxhc_meas;
168 	wxhc_QUAD[12].widget = w_wxhc_est;
169 	wxhc_QUAD[13].widget = w_wxhc_wind_speed;
170 	wxhc_QUAD[14].widget = w_wxhc_wind_speed_units;
171 	wxhc_QUAD[15].widget = w_wxhc_wind_gusts;
172 	wxhc_QUAD[16].widget = w_wxhc_wind_gusts_units;
173 	wxhc_QUAD[17].widget = w_wxhc_wind_dir;
174 	wxhc_QUAD[18].widget = w_wxhc_wind_degrees;
175 	wxhc_QUAD[19].widget = w_wxhc_baro_press;
176 	wxhc_QUAD[20].widget = w_wxhc_baro_units;
177 	wxhc_QUAD[21].widget = w_wxhc_comments;
178 
179 	fields_initialized = true;
180 }
181 
182 //enum NHC_QTYPE { B, S, T, I, F, C, E };
183 // bool, string, text, int, float, character, empty
184 
clearQUAD(NHC_QUAD * p)185 static void clearQUAD(NHC_QUAD *p)
186 {
187 	NHC_QTYPE qt = E;
188 	while ((qt = p->qtype) != E) {
189 		switch (qt) {
190 			case B : (*(bool *)(p->ptr)) = false; break;
191 			case S :
192 			case M : ((string *)(p->ptr))->clear(); break;
193 			case T : ((string *)(p->ptr))->clear(); break;
194 			case C : (*(char *)(p->ptr)) = ' '; break;
195 			case I : (*(int *)(p->ptr)) = 0; break;
196 			case F : (*(float *)(p->ptr)) = 0.0; break;
197 			case O : break;
198 			case E : return;
199 		}
200 		p++;
201 	}
202 	wxhc_est = true;
203 	wxhc_wind_speed_units = s_wsu_units[0];
204 	wxhc_wind_gusts_units = s_wsu_units[0];
205 	wxhc_wind_dir = s_wdu_units[0];
206 	wxhc_baro_units = s_baro_units[0];
207 }
208 
clear_wxhcfields()209 void clear_wxhcfields()
210 {
211 	if (!fields_initialized) init_widgets();
212 	clearQUAD(wxhc_QUAD);
213 }
214 
checkQUAD(NHC_QUAD * p)215 static bool checkQUAD(NHC_QUAD *p)
216 {
217 	int i = 0;
218 	float f = 0;
219 	char c = ' ';
220 	NHC_QTYPE qt = E;
221 	while ((qt = p->qtype) != E) {
222 		if (p->widget == NULL) return false;
223 		switch (qt) {
224 			case B:
225 				if (*((bool *)(p->ptr)) != ((Fl_Check_Button *)p->widget)->value())
226 					return true;
227 				break;
228 			case S:
229 			case M:
230 				if (*((string *)(p->ptr)) != ((Fl_Input2 *)p->widget)->value())
231 					return true;
232 				break;
233 			case T:
234 				if (*((string *)(p->ptr)) != ((FTextEdit *)p->widget)->buffer()->text())
235 					return true;
236 				break;
237 			case C:
238 				c = ' ';
239 				if (((Fl_Input2 *)p->widget)->value()[0])
240 					c = ((Fl_Input2 *)p->widget)->value()[0];
241 				if (*((char *)(p->ptr)) != c)
242 					return true;
243 				break;
244 			case I:
245 				i = 0;
246 				if (((Fl_Input2 *)p->widget)->value()[0])
247 					sscanf( ((Fl_Input2 *)p->widget)->value(), "%d", &i);
248 				if (*((int *)(p->ptr)) != i)
249 					return true;
250 				break;
251 			case F:
252 				f = 0;
253 				if (((Fl_Input2 *)p->widget)->value()[0])
254 					sscanf( ((Fl_Input2 *)p->widget)->value(), "%f", &f);
255 				if (*((float *)(p->ptr)) != f)
256 					return true;
257 				break;
258 			case O:
259 				if (*((string *)(p->ptr)) != ((Fl_ListBox *)p->widget)->value())
260 					return true;
261 				break;
262 			case E:
263 			default: return false;
264 		}
265 		p++;
266 	}
267 	return false;
268 }
269 
check_wxhcfields()270 bool check_wxhcfields()
271 {
272 	return checkQUAD(wxhc_QUAD);
273 }
274 
updateQUAD(NHC_QUAD * p)275 static void updateQUAD(NHC_QUAD *p)
276 {
277 	int i = 0;
278 	float f = 0;
279 	char c = ' ';
280 	NHC_QTYPE qt = E;
281 	while ((qt = p->qtype) != E) {
282 		switch (qt) {
283 			case B:
284 				*((bool *)(p->ptr)) = ((Fl_Check_Button *)p->widget)->value();
285 				break;
286 			case S:
287 			case M:
288 				*((string *)(p->ptr)) = ((Fl_Input2 *)p->widget)->value();
289 				break;
290 			case O:
291 				*((string *)(p->ptr)) = ((Fl_ListBox *)p->widget)->value();
292 				break;
293 			case T:
294 				*((string *)(p->ptr)) = ((FTextEdit *)p->widget)->buffer()->text();
295 				break;
296 			case C:
297 				c = ' ';
298 				if (((Fl_Input2 *)p->widget)->value()[0])
299 					c = ((Fl_Input2 *)p->widget)->value()[0];
300 				*((char *)(p->ptr)) = c;
301 				break;
302 			case I:
303 				i = 0;
304 				if (((Fl_Input2 *)p->widget)->value()[0])
305 					sscanf( ((Fl_Input2 *)p->widget)->value(), "%d", &i);
306 				*((int *)(p->ptr)) = i;
307 				break;
308 			case F:
309 				f = 0;
310 				if (((Fl_Input2 *)p->widget)->value()[0])
311 					sscanf( ((Fl_Input2 *)p->widget)->value(), "%f", &f);
312 				*((float *)(p->ptr)) = f;
313 				break;
314 			case E:
315 			default: return;
316 		}
317 		p++;
318 	}
319 }
320 
update_wxhcfields()321 void update_wxhcfields()
322 {
323 	if (!fields_initialized) init_widgets();
324 	updateQUAD(wxhc_QUAD);
325 }
326 
set_nhc_wx_combos()327 void set_nhc_wx_combos() {
328 	const char **s = s_wsu_units;
329 	int i = 0;
330 	w_wxhc_wind_speed_units->clear();
331 	while (s[i]) { w_wxhc_wind_speed_units->add(s[i]);
332 	i++;}
333 
334 	s = s_wsu_units;
335 	i = 0;
336 	w_wxhc_wind_gusts_units->clear();
337 	while (s[i]) { w_wxhc_wind_gusts_units->add(s[i]); i++; }
338 
339 	s = s_wdu_units;
340 	i = 0;
341 	w_wxhc_wind_dir->clear();
342 	while (s[i]) { w_wxhc_wind_dir->add(s[i]); i++; }
343 
344 	s = s_baro_units;
345 	i = 0;
346 	w_wxhc_baro_units->clear();
347 	while (s[i]) { w_wxhc_baro_units->add(s[i]); i++; }
348 
349 }
350 
updateFORM(NHC_QUAD * p)351 static void updateFORM(NHC_QUAD *p)
352 {
353 	char val[20];
354 	NHC_QTYPE qt = E;
355 	while ((qt = p->qtype) != E) {
356 		switch (qt) {
357 			case B:
358 				((Fl_Check_Button *)p->widget)->value(*((bool *)(p->ptr)));
359 				break;
360 			case S:
361 			case M:
362 				((Fl_Input2 *)p->widget)->value(((string *)(p->ptr))->c_str());
363 				break;
364 			case O:
365 				((Fl_ListBox *)p->widget)->put_value(((string *)(p->ptr))->c_str());
366 				break;
367 			case T:
368 				((FTextEdit *)p->widget)->clear();
369 				((FTextEdit *)p->widget)->add(((string *)(p->ptr))->c_str());
370 				break;
371 			case C:
372 				val[0] = *((char *)(p->ptr));
373 				val[1] = 0;
374 				((Fl_Input2 *)p->widget)->value(val);
375 				break;
376 			case I:
377 				if (*((int *)(p->ptr)) == 0)
378 					((Fl_Input2 *)p->widget)->value("");
379 				else {
380 					snprintf(val, sizeof(val), "%d", *((int *)(p->ptr)));
381 					((Fl_Input2 *)p->widget)->value(val);
382 				}
383 				break;
384 			case F:
385 				snprintf(val, sizeof(val), "%f", *((float *)(p->ptr)));
386 				((Fl_Input2 *)p->widget)->value(val);
387 				break;
388 			case E:
389 			default: return;
390 		}
391 		p++;
392 	}
393 }
394 
update_wxhcform()395 void update_wxhcform()
396 {
397 	if (!fields_initialized) init_widgets();
398 	updateFORM(wxhc_QUAD);
399 }
400 
clear_wxhc_form()401 void clear_wxhc_form()
402 {
403 	clear_wxhcfields();
404 	update_wxhcform();
405 }
406 
407 static string mbuff;
408 
make_buffQUAD(NHC_QUAD * p)409 static void make_buffQUAD(NHC_QUAD *p)
410 {
411 	string one = "1"; string zero = "0";
412 	string sval = " ";
413 	char szval[20];
414 	NHC_QTYPE qt = E;
415 	while ((qt = p->qtype) != E) {
416 		switch (qt) {
417 			case B:
418 				if (*((bool *)(p->ptr)) == true)
419 					mbuff.append( lineout( p->html_fld, *((bool *)(p->ptr)) ? one : zero));
420 				break;
421 			case O:
422 			case S:
423 			case M:
424 				if (((string *)(p->ptr))->length())
425 					mbuff.append( lineout( p->html_fld, *((string *)(p->ptr))));
426 				break;
427 			case T:
428 				mbuff.append( lineout( p->html_fld, *((string *)(p->ptr))));
429 				break;
430 			case C:
431 				if ((*(char *)(p->ptr)) != 0 && *((char *)(p->ptr)) != ' ') {
432 					sval = " ";
433 					sval[0] = *((char *)(p->ptr));
434 					mbuff.append( lineout( p->html_fld, sval));
435 				}
436 				break;
437 			case I:
438 				if (*((int*)(p->ptr)) > 0) {
439 					snprintf(szval, sizeof(szval), "%d", *((int *)(p->ptr)) );
440 					sval = szval;
441 					mbuff.append( lineout( p->html_fld, sval) );
442 				}
443 				break;
444 			case F:
445 				if (*((float *)(p->ptr)) > 0) {
446 					snprintf(szval, sizeof(szval), "%f", *((float *)(p->ptr)));
447 					sval = szval;
448 					mbuff.append( lineout( p->html_fld, sval) );
449 				}
450 				break;
451 			case E:
452 			default: return;
453 		}
454 		p++;
455 	}
456 }
457 
make_buffwxhc(bool compress=false)458 void make_buffwxhc(bool compress = false)
459 {
460 	mbuff.clear();
461 	make_buffQUAD(wxhc_QUAD);
462 	if (compress) compress_maybe(mbuff);
463 	buffwxhc.append(mbuff);
464 }
465 
readQUAD(string data,NHC_QUAD * p)466 static void readQUAD(string data, NHC_QUAD *p)
467 {
468 	int i = 0;
469 	float f;
470 	NHC_QTYPE qt = p->qtype;
471 	while (qt != E) {
472 		switch (qt) {
473 			case B:
474 				*((bool *)(p->ptr)) = (findstr( data, p->html_fld ) == "1");
475 				break;
476 			case O:
477 			case S:
478 			case M:
479 				*((string *)(p->ptr)) = findstr( data, p->html_fld );
480 				break;
481 			case T:
482 				*((string *)(p->ptr)) = findstr( data, p->html_fld );
483 				break;
484 			case C:
485 				*((char *)(p->ptr)) = findstr( data, p->html_fld )[0];
486 				break;
487 			case I:
488 				i = 0;
489 				sscanf( findstr( data, p->html_fld ).c_str(), "%d", &i);
490 				*((int *)(p->ptr)) = i;
491 				break;
492 			case F:
493 				f = 0;
494 				sscanf( findstr( data, p->html_fld ).c_str(), "%f", &f);
495 				*((float *)(p->ptr)) = f;
496 				break;
497 			case E:
498 			default: return;
499 		}
500 		p++;
501 		qt = p->qtype;
502 	}
503 }
504 
read_wxhc_buffer(string data)505 void read_wxhc_buffer(string data)
506 {
507 	clear_wxhcfields();
508 	read_header(data);
509 
510 	readQUAD (data, wxhc_QUAD);
511 	update_wxhcform();
512 }
513 
cb_wxhc_new()514 void cb_wxhc_new()
515 {
516 	if (check_wxhcfields()) {
517 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 1) {
518 			update_header(CHANGED);
519 			cb_wxhc_save();
520 		}
521 	}
522 	clear_wxhc_form();
523 	clear_header();
524 	def_wxhc_filename = ICS_msg_dir;
525 	def_wxhc_filename.append("new").append(FWXHC_EXT);
526 	show_filename(def_wxhc_filename);
527 	using_wxhc_template = false;
528 }
529 
cb_wxhc_import()530 void cb_wxhc_import()
531 {
532 	fl_alert2("Not implemented");
533 }
534 
cb_wxhc_export()535 void cb_wxhc_export()
536 {
537 	fl_alert2("Not implemented");
538 }
539 
cb_wxhc_wrap_import(string wrapfilename,string inpbuffer)540 void cb_wxhc_wrap_import(string wrapfilename, string inpbuffer)
541 {
542 	clear_wxhc_form();
543 	read_wxhc_buffer(inpbuffer);
544 	def_wxhc_filename = ICS_msg_dir;
545 	def_wxhc_filename.append(wrapfilename);
546 	show_filename(def_wxhc_filename);
547 	using_wxhc_template = false;
548 }
549 
eval_wxhc_fsize()550 int eval_wxhc_fsize()
551 {
552 	Ccrc16 chksum;
553 	evalstr.assign("[WRAP:beg][WRAP:lf][WRAP:fn ");
554 	evalstr.append(base_wxhc_filename).append("]");
555 	update_wxhcfields();
556 	update_header(FROM);
557 	evalstr.append(header("<nhc_wx>"));
558 	buffwxhc.clear();
559 	make_buffwxhc(true);
560 	if (buffwxhc.empty()) return 0;
561 	compress_maybe( buffwxhc );
562 	evalstr.append( buffwxhc );
563 	evalstr.append("[WRAP:chksum ").append(chksum.scrc16(evalstr)).append("][WRAP:end]");
564 	return evalstr.length();
565 }
566 
cb_wxhc_wrap_export()567 void cb_wxhc_wrap_export()
568 {
569 	if (check_wxhcfields()) {
570 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
571 			return;
572 		update_header(CHANGED);
573 	}
574 	update_wxhcfields();
575 
576 	if (base_wxhc_filename == string("new").append(FWXHC_EXT) ||
577 		base_wxhc_filename == string("default").append(FWXHC_EXT) )
578 		if (!cb_wxhc_save_as()) return;
579 
580 	string wrapfilename = WRAP_send_dir;
581 	wrapfilename.append(base_wxhc_filename);
582 	wrapfilename.append(".wrap");
583 	const char *p = FSEL::saveas(
584 			"Save as wrap file",
585 			"Wrap file\t*.{wrap,WRAP}",
586 			wrapfilename.c_str());
587 	if (p) {
588 		string pext = fl_filename_ext(p);
589 		wrapfilename = p;
590 
591 		update_header(FROM);
592 		buffwxhc.assign(header("<nhc_wx>"));
593 		make_buffwxhc(true);
594 		export_wrapfile(base_wxhc_filename, wrapfilename, buffwxhc, pext != ".wrap");
595 
596 		buffwxhc.assign(header("<nhc_wx>"));
597 		make_buffwxhc(false);
598 		write_wxhc(def_wxhc_filename);
599 	}
600 }
601 
cb_wxhc_wrap_autosend()602 void cb_wxhc_wrap_autosend()
603 {
604 	if (check_wxhcfields()) {
605 		if (fl_choice2("Form modified, save?", "No", "Yes", NULL) == 0)
606 			return;
607 		update_header(CHANGED);
608 	}
609 	update_wxhcfields();
610 
611 	if (base_wxhc_filename == string("new").append(FWXHC_EXT) ||
612 		base_wxhc_filename == string("default").append(FWXHC_EXT) )
613 		if (!cb_wxhc_save_as()) return;
614 
615 	update_header(FROM);
616 	buffwxhc.assign(header("<nhc_wx>"));
617 	make_buffwxhc(true);
618 	xfr_via_socket(base_wxhc_filename, buffwxhc);
619 
620 	buffwxhc.assign(header("<nhc_wx>"));
621 	make_buffwxhc(false);
622 	write_wxhc(def_wxhc_filename);
623 }
624 
cb_wxhc_load_template()625 void cb_wxhc_load_template()
626 {
627 	string def_wxhc_filename = def_wxhc_TemplateName;
628 	const char *p = FSEL::select(
629 			"Open template file",
630 			string("Template file\t*").append(TWXHC_EXT).c_str(),
631 			def_wxhc_filename.c_str());
632 	if (p) {
633 		clear_wxhc_form();
634 		read_data_file(p);
635 		def_wxhc_TemplateName = p;
636 		show_filename(def_wxhc_TemplateName);
637 		using_wxhc_template = true;
638 	}
639 }
640 
cb_wxhc_save_template()641 void cb_wxhc_save_template()
642 {
643 	if (!using_wxhc_template) {
644 		cb_wxhc_save_as_template();
645 		return;
646 	}
647 	string def_wxhc_filename = def_wxhc_TemplateName;
648 	const char *p = FSEL::saveas(
649 			"Save template file",
650 			string("Template file\t*").append(TWXHC_EXT).c_str(),
651 			def_wxhc_filename.c_str());
652 	if (p) {
653 		update_header(CHANGED);
654 		update_wxhcfields();
655 		buffwxhc.assign(header("<nhc_wx>"));
656 		make_buffwxhc();
657 		write_wxhc(p);
658 	}
659 }
660 
cb_wxhc_save_as_template()661 void cb_wxhc_save_as_template()
662 {
663 	string def_wxhc_filename = def_wxhc_TemplateName;
664 	const char *p = FSEL::saveas(
665 			"Save as template file",
666 			string("Template file\t*").append(TWXHC_EXT).c_str(),
667 			def_wxhc_filename.c_str());
668 	if (p) {
669 		const char *pext = fl_filename_ext(p);
670 		def_wxhc_TemplateName = p;
671 		if (strlen(pext) == 0) def_wxhc_TemplateName.append(TWXHC_EXT);
672 		remove_spaces_from_filename(def_wxhc_TemplateName);
673 
674 		clear_header();
675 		update_header(CHANGED);
676 		update_wxhcfields();
677 		buffwxhc.assign(header("<nhc_wx>"));
678 		make_buffwxhc();
679 		write_wxhc(def_wxhc_TemplateName);
680 
681 		show_filename(def_wxhc_TemplateName);
682 		using_wxhc_template = true;
683 	}
684 }
685 
cb_wxhc_open()686 void cb_wxhc_open()
687 {
688 	const char *p = FSEL::select(
689 			_("Open data file"),
690 			string("ICS-wxhc\t*").append(FWXHC_EXT).c_str(),
691 			def_wxhc_filename.c_str());
692 	if (!p) return;
693 	if (strlen(p) == 0) return;
694 	clear_wxhc_form();
695 	read_data_file(p);
696 	using_wxhc_template = false;
697 	def_wxhc_filename = p;
698 	show_filename(def_wxhc_filename);
699 }
700 
write_wxhc(string s)701 void write_wxhc(string s)
702 {
703 	FILE *filewxhc = fopen(s.c_str(), "w");
704 	if (!filewxhc) return;
705 
706 	fwrite(buffwxhc.c_str(), buffwxhc.length(), 1, filewxhc);
707 	fclose(filewxhc);
708 }
709 
710 
cb_wxhc_save_as()711 bool cb_wxhc_save_as()
712 {
713 	const char *p;
714 	string newfilename;
715 
716 	string name = named_file();
717 	if (!name.empty()) {
718 		name.append(FWXHC_EXT);
719 		newfilename = ICS_msg_dir;
720 		newfilename.append(name);
721 	} else
722 		newfilename = def_wxhc_filename;
723 
724 	p = FSEL::saveas(
725 			_("Save data file"),
726 			string("ICS-wxhc\t*").append(FWXHC_EXT).c_str(),
727 			newfilename.c_str());
728 
729 	if (!p) return false;
730 	if (strlen(p) == 0) return false;
731 
732 	if (progStatus.sernbr_fname) update_sernbr();
733 
734 	const char *pext = fl_filename_ext(p);
735 	def_wxhc_filename = p;
736 	if (strlen(pext) == 0) def_wxhc_filename.append(FWXHC_EXT);
737 
738 	remove_spaces_from_filename(def_wxhc_filename);
739 
740 	update_header(NEW);
741 	update_wxhcfields();
742 	buffwxhc.assign(header("<nhc_wx>"));
743 	make_buffwxhc();
744 	write_wxhc(def_wxhc_filename);
745 
746 	using_wxhc_template = false;
747 	show_filename(def_wxhc_filename);
748 	return true;
749 }
750 
cb_wxhc_save()751 void cb_wxhc_save()
752 {
753 	if (base_wxhc_filename == string("new").append(FWXHC_EXT) ||
754 		base_wxhc_filename == string("default").append(FWXHC_EXT) ||
755 		using_wxhc_template == true) {
756 		cb_wxhc_save_as();
757 		return;
758 	}
759 
760 	if (check_wxhcfields()) update_header(CHANGED);
761 	update_wxhcfields();
762 	buffwxhc.assign(header("<nhc_wx>"));
763 	make_buffwxhc();
764 	write_wxhc(def_wxhc_filename);
765 
766 	using_wxhc_template = false;
767 }
768 
quad_to_html(string & target,NHC_QUAD * p)769 static void quad_to_html( string &target, NHC_QUAD *p)
770 {
771 	string X = "X"; string SP = " ";
772 	string sval = " ";
773 	char szval[20];
774 	while (p->qtype != E) {
775 		if (p->qtype == B)
776 			replacestr(target, p->html_fld, *((bool *)(p->ptr)) ? X : SP);
777 		else if (p->qtype == S || p->qtype == O)
778 			replacestr(target, p->html_fld, *((string *)(p->ptr)));
779 		else if (p->qtype == M) {
780 			sval = *((string *)(p->ptr));
781 			size_t np = string::npos;
782 			while ( (np = sval.find("\n")) != string::npos)
783 				sval.replace(np, 1, "<br>");
784 			replacestr(target, p->html_fld, sval);
785 		} else if (p->qtype == T)
786 			replacestr(target, p->html_fld, *((string *)(p->ptr)));
787 		else if (p->qtype == C) {
788 			sval = " ";
789 			sval[0] = *((char *)(p->ptr));
790 			replacestr(target, p->html_fld, sval);
791 		}
792 		else if (p->qtype == I) {
793 			if (*((int *)(p->ptr)) > 0) {
794 				snprintf(szval, sizeof(szval), "%d", *((int *)(p->ptr)) );
795 				sval = szval;
796 			} else sval.clear();
797 				replacestr(target, p->html_fld, sval);
798 		}
799 		else if (p->qtype == F) {
800 			if (*((float *)(p->ptr)) != 0) {
801 				snprintf(szval, sizeof(szval), "%f", *((float *)(p->ptr)));
802 				sval = szval;
803 			} else sval.clear();
804 			replacestr(target, p->html_fld, sval);
805 		}
806 		p++;
807 	}
808 }
809 
cb_wxhc_html()810 void cb_wxhc_html()
811 {
812 	string name_name = fl_filename_name(def_wxhc_filename.c_str());
813 	size_t p = name_name.rfind('.');
814 	if (p != string::npos) name_name.erase(p);
815 
816 	string wxhc_rptsta = ICS_dir;
817 	wxhc_rptsta.append(name_name);
818 	wxhc_rptsta.append(".html");
819 
820 	update_wxhcfields();
821 	string formwxhc = wxhc_html_template;
822 
823 	replacestr(formwxhc, TITLE, name_name);
824 
825 	quad_to_html (formwxhc, wxhc_QUAD);
826 
827 	FILE *filewxhc = fopen(wxhc_rptsta.c_str(), "w");
828 	fprintf(filewxhc,"%s", formwxhc.c_str());
829 	fclose(filewxhc);
830 
831 	open_url(wxhc_rptsta.c_str());
832 }
833 
quad_to_text(string & target,NHC_QUAD * p)834 static void quad_to_text( string &target, NHC_QUAD *p)
835 {
836 	string X = "X"; string SP = " ";
837 	string sval = " ";
838 	string del = "DELETE";
839 	char szval[20];
840 	while (p->qtype != E) {
841 		if (p->qtype == B) {
842 			bool b = *((bool *)(p->ptr));
843 			if (b) replacestr(target, p->html_fld, X);
844 			else replacestr(target, p->html_fld, SP);
845 		} else if (p->qtype == S || p->qtype == M || p->qtype == O) {
846 			if (((string *)(p->ptr))->length())
847 				replacestr(target, p->html_fld, *((string *)(p->ptr)));
848 			else replacestr(target, p->html_fld, del);
849 		} else if (p->qtype == T) {
850 			if (((string *)(p->ptr))->length())
851 				replacestr(target, p->html_fld, *((string *)(p->ptr)));
852 			else replacestr(target, p->html_fld, del);
853 		} else if (p->qtype == C) {
854 			sval = " ";
855 			sval[0] = *((char *)(p->ptr));
856 			if (sval[0] != 0 && sval[0] != ' ')
857 				replacestr(target, p->html_fld, sval);
858 			else replacestr(target, p->html_fld, del);
859 		}
860 		else if (p->qtype == I) {
861 			if (*((int *)(p->ptr)) > 0) {
862 				snprintf(szval, sizeof(szval), "%d", *((int *)(p->ptr)) );
863 				sval = szval;
864 				replacestr(target, p->html_fld, sval);
865 			} else replacestr(target, p->html_fld, del);
866 		}
867 		else if (p->qtype == F) {
868 			if (*((float *)(p->ptr)) != 0) {
869 				snprintf(szval, sizeof(szval), "%f", *((float *)(p->ptr)));
870 				sval = szval;
871 				replacestr(target, p->html_fld, sval);
872 			} else replacestr(target, p->html_fld, del);
873 		}
874 		p++;
875 	}
876 }
877 
strip_text(string & target)878 static void strip_text( string &target )
879 {
880 	size_t p = 0, p1, p2;
881 	while ((p = target.find ("DELETE"), p) != string::npos) {
882 		p1 = target.rfind ("\n", p);
883 		p2 = target.find ("\n", p);
884 		if (p1 != string::npos && p2 != string::npos)
885 			target.erase( p1, p2 - p1 );
886 		p++;
887 	}
888 }
889 
cb_wxhc_textout()890 void cb_wxhc_textout()
891 {
892 	string wxhc_rptsta = ICS_dir;
893 	wxhc_rptsta.append("wxhc.txt");
894 
895 	update_wxhcfields();
896 	string formwxhc = wxhc_text_template;
897 
898 	quad_to_text (formwxhc, wxhc_QUAD);
899 
900 	strip_text (formwxhc);
901 
902 	FILE *filewxhc = fopen(wxhc_rptsta.c_str(), "w");
903 	fprintf(filewxhc,"%s", formwxhc.c_str());
904 	fclose(filewxhc);
905 
906 	open_url(wxhc_rptsta.c_str());
907 }
908 
909