flmsg-4.0.23/ 0000775 0001750 0001750 00000000000 14474644701 007726 5 0000000 0000000 flmsg-4.0.23/src/ 0000775 0001750 0001750 00000000000 14474644702 010516 5 0000000 0000000 flmsg-4.0.23/src/Makefile.am 0000664 0001750 0001750 00000022340 14463050240 012455 0000000 0000000 # Copyright (c) 2008 Dave Freese, W1HKJ (w1hkj AT w1hkj DOT com)
bin_PROGRAMS = flmsg
MINGW32_SRC = flmsg-rc.rc include/flmsgrc.h \
utils/mingw.c include/mingw.h include/compat.h \
utils/getsysinfo.c
# Build the xmlrpcpp source if libflxmlrpc is not found
XMLRPCPP_SRC = \
xmlrpcpp/XmlRpcBase64.h \
xmlrpcpp/XmlRpcClient.cpp \
xmlrpcpp/XmlRpcClient.h \
xmlrpcpp/XmlRpcDispatch.cpp \
xmlrpcpp/XmlRpcDispatch.h \
xmlrpcpp/XmlRpcException.h \
xmlrpcpp/XmlRpc.h \
xmlrpcpp/XmlRpcMutex.cpp \
xmlrpcpp/XmlRpcMutex.h \
xmlrpcpp/XmlRpcServerConnection.cpp \
xmlrpcpp/XmlRpcServerConnection.h \
xmlrpcpp/XmlRpcServer.cpp \
xmlrpcpp/XmlRpcServer.h \
xmlrpcpp/XmlRpcServerMethod.cpp \
xmlrpcpp/XmlRpcServerMethod.h \
xmlrpcpp/XmlRpcSocket.cpp \
xmlrpcpp/XmlRpcSocket.h \
xmlrpcpp/XmlRpcSource.cpp \
xmlrpcpp/XmlRpcSource.h \
xmlrpcpp/XmlRpcUtil.cpp \
xmlrpcpp/XmlRpcUtil.h \
xmlrpcpp/XmlRpcValue.cpp \
xmlrpcpp/XmlRpcValue.h
# We distribute these but do not always compile them
EXTRA_flmsg_SOURCES = $(FLMSG_WIN32_RES_SRC) $(MINGW32_SRC) $(XMLRPCPP_SRC)
flmsg_SOURCES =
if !ENABLE_FLXMLRPC
flmsg_SOURCES += $(XMLRPCPP_SRC)
flmsg_CPPFLAGS = @FLMSG_BUILD_CPPFLAGS@
flmsg_CXXFLAGS = @FLMSG_BUILD_CXXFLAGS@
flmsg_CFLAGS = $(flmsg_CXXFLAGS)
flmsg_LDFLAGS = @FLMSG_BUILD_LDFLAGS@
flmsg_LDADD = @FLMSG_BUILD_LDADD@
else
flmsg_CPPFLAGS = @FLMSG_BUILD_CPPFLAGS@ @FLXMLRPC_CFLAGS@
flmsg_CXXFLAGS = @FLMSG_BUILD_CXXFLAGS@ @FLXMLRPC_CFLAGS@
flmsg_CFLAGS = $(flmsg_CXXFLAGS)
flmsg_LDFLAGS = @FLMSG_BUILD_LDFLAGS@ @FLXMLRPC_LIBS@
flmsg_LDADD = @FLMSG_BUILD_LDADD@
endif
if MINGW32
if HAVE_WINDRES
flmsg_SOURCES += $(MINGW32_SRC)
endif
endif
########################################################################
flmsg_VERSION_MAJOR = @FLMSG_VERSION_MAJOR@
flmsg_VERSION_MINOR = @FLMSG_VERSION_MINOR@
flmsg_VERSION_PATCH = @FLMSG_VERSION_PATCH@
flmsg_VERSION = @FLMSG_VERSION@
.EXPORT_ALL_VARIABLES: nsisinst appbundle
# Sources that are generated,
BUILT_SOURCES =
# not distributed,
nodist_flmsg_SOURCES = $(BUILT_SOURCES)
# and deleted by the clean targets
CLEANFILES = $(BUILT_SOURCES)
CLEAN_LOCAL =
if MINGW32
if HAVE_WINDRES
.rc.o:
$(WINDRES) -Iinclude -I../data/win32 $< -O coff $@
endif
endif
install-data-local:
if test -f ../data/flmsg.xpm; then \
$(mkinstalldirs) $(DESTDIR)/$(datadir)/pixmaps; \
$(INSTALL_DATA) ../data/flmsg.xpm $(DESTDIR)/$(datadir)/pixmaps; \
fi
if test -f ../data/flmsg.desktop; then \
$(mkinstalldirs) $(DESTDIR)/$(datadir)/applications; \
$(INSTALL_DATA) ../data/flmsg.desktop $(DESTDIR)/$(datadir)/applications; \
fi
uninstall-local:
rm -f $(DESTDIR)/$(datadir)/pixmaps/flmsg.xpm
rm -f $(DESTDIR)/$(datadir)/applications/flmsg.desktop
# FL_SRC = flmsg_dialog.fl
if HAVE_FLUID
flgen: $(FL_SRC)
(cd include; \
for f in $(FL_SRC); do \
c=$${f%.fl}.cxx; \
h=$${f%.fl}.h; \
h=$${h##*/}; \
$(FLUID) -c -o ../$$c -h $$h ../$$f; \
done)
endif
INSTALLER_FILE = flmsg-$(FLMSG_VERSION)_setup.exe
APPBUNDLE=flmsg-$(FLMSG_VERSION)
APPBUNDLE_NOLIBS=$(APPBUNDLE)-nolibs
if HAVE_NSIS
nsisinst: $(bin_PROGRAMS)
sh ../scripts/mknsisinst.sh "../data" .
CLEANFILES += $(INSTALLER_FILE)
endif
if DARWIN
appbundle: $(bin_PROGRAMS)
sh ../scripts/mkappbundle.sh "../data" .
CLEAN_LOCAL += $(APPBUNDLE_NOLIBS) $(APPBUNDLE) $(APPBUNDLE)*.dmg
endif
clean-local:
-rm -rf $(CLEAN_LOCAL)
# Sources that we build. It is OK to have headers here.
flmsg_SOURCES += \
arq/arq.cxx \
arq/flmsg-arq.cxx \
blank-dnd/baddata_templates.cxx \
blank-dnd/blank.cxx \
blank-dnd/blank_tab.cxx \
blank-dnd/blank_templates.cxx \
blank-dnd/dnd_tab.cxx \
cap/cap105.cxx \
cap/cap105_tab.cxx \
cap/cap110.cxx \
cap/cap110_tab.cxx \
cap/cap_templates.cxx \
cap/f126.cxx \
cap/f126_tab.cxx \
cap/rafac_templates.cxx \
csv/csv.cxx \
csv/csv_tab.cxx \
csv/csv_templates.cxx \
csv/csv_table.cxx \
custom/custom.cxx \
custom/custom_tab.cxx \
custom/custom_templates.cxx \
include/custom.h \
flmsg.cxx \
flmsg_dialog.cxx \
ham_forms/ham_forms_tab.cxx \
ham_forms/netlog.cxx \
ham_forms/netlog_templates.cxx \
ham_forms/netlog_tab.cxx \
iaru/iaru.cxx \
iaru/iaru_tab.cxx \
iaru/iaru_templates.cxx \
ics/ics203.cxx \
ics/ics205.cxx \
ics/ics205a.cxx \
ics/ics206.cxx \
ics/ics213.cxx \
ics/ics214.cxx \
ics/ics216.cxx \
ics/ics309.cxx \
ics/ics_tab.cxx \
ics/ics203_tab.cxx \
ics/ics205_tab.cxx \
ics/ics205a_tab.cxx \
ics/ics206_tab.cxx \
ics/ics213_tab.cxx \
ics/ics214_tab.cxx \
ics/ics216_tab.cxx \
ics/ics309_tab.cxx \
ics/ics203_templates.cxx \
ics/ics205_templates.cxx \
ics/ics205a_templates.cxx \
ics/ics206_templates.cxx \
ics/ics213_templates.cxx \
ics/ics214_templates.cxx \
ics/ics216_templates.cxx \
ics/ics309_templates.cxx \
hics/hics_tab.cxx \
hics/hics203.cxx \
hics/hics203_tab.cxx \
hics/hics203_templates.cxx\
hics/hics206.cxx \
hics/hics206_tab.cxx \
hics/hics206_templates.cxx\
hics/hics213.cxx \
hics/hics213_tab.cxx \
hics/hics213_templates.cxx\
hics/hics214.cxx \
hics/hics214_tab.cxx \
hics/hics214_templates.cxx\
lzma/Alloc.h \
lzma/Alloc.c \
lzma/LzFind.c \
lzma/LzFind.h \
lzma/LzHash.h \
lzma/LzmaDec.c \
lzma/LzmaDec.h \
lzma/LzmaEnc.c \
lzma/LzmaEnc.h \
lzma/LzmaLib.c \
lzma/LzmaLib.h \
lzma/Types.h \
mars/mars_tab.cxx \
mars/mars_daily.cxx \
mars/mars_ineei.cxx \
mars/mars_net.cxx \
mars/mars_daily_tab.cxx \
mars/mars_ineei_tab.cxx \
mars/mars_net_tab.cxx \
mars/mars_army.cxx \
mars/mars_army_tab.cxx \
mars/mars_msg.cxx \
mars/mars_msg_tab.cxx \
mars/mars_templates.cxx \
plaintext/plaintext.cxx \
plaintext/plaintext_tab.cxx \
plaintext/plaintext_templates.cxx \
radiogram/arl_msgs.cxx \
radiogram/hx_msgs.cxx \
radiogram/radiogram.cxx \
radiogram/radiogram_tab.cxx \
radiogram/radiogram_templates.cxx \
transfer/transfer.cxx \
transfer/transfer_tab.cxx \
custom/custom_transfer_tab.cxx \
utils/base64.cxx \
utils/base128.cxx \
utils/base256.cxx \
utils/debug.cxx \
utils/ext_string.cxx \
utils/mongoose.c \
utils/parse_xml.cxx \
utils/socket.cxx \
utils/status.cxx \
utils/timeops.cxx \
utils/time_table.cxx \
utils/threads.cxx \
utils/util.cxx \
utils/wrap.cxx \
utils/xml_io.cxx \
widgets/calendar.cxx \
widgets/combo.cxx \
widgets/date.cxx \
widgets/drop_button.cxx \
widgets/fileselect.cxx \
widgets/flinput2.cxx \
widgets/flmisc.cxx \
widgets/flslider2.cxx \
widgets/Fl_Text_Buffer_mod.cxx \
widgets/Fl_Text_Editor_mod.cxx \
widgets/Fl_Text_Display_mod.cxx \
widgets/FTextView.cxx \
widgets/icons.cxx \
widgets/pixmaps.cxx \
widgets/pixmaps_tango.cxx \
widgets/font_browser.cxx \
wx/hurricane.cxx \
wx/hurricane_tab.cxx \
wx/hurricane_template.cxx \
wx/severe_wx.cxx \
wx/severe_wx_tab.cxx \
wx/severe_wx_template.cxx \
wx/wx_strings.cxx \
wx/storm_report.cxx \
wx/storm_report_tab.cxx \
wx/storm_report_template.cxx
# wx/storm_report.cxx
# wx/storm_report_template.cxx
EXTRA_DIST =
# Additional source files that are distributed
EXTRA_DIST += \
config.h \
utils/mingw.c \
utils/time_table_dat.cxx \
widgets/flnfc_common.cxx \
include/arl_msgs.h \
include/arq.h \
include/flmsg_arq.h \
include/ascii.h \
include/base64.h \
include/base128.h \
include/base256.h \
include/calendar.h \
include/cap.h \
include/combo.h \
include/compat.h \
include/compat-mingw.h \
include/crc16.h \
include/date.h \
include/debug.h \
include/dirent-check.h \
include/drop_button.h \
include/ext_string.h \
include/fileselect.h \
include/fl_lock.h \
include/flmisc.h \
include/flmsg_config.h \
include/flmsgrc.h \
include/flinput2.h \
include/flslider2.h \
include/font_browser.h \
include/gettext.h \
include/hx_msgs.h \
include/iaru.h \
include/icons.h \
include/flmsg.h \
include/flmsg_dialog.h \
include/mongoose.h \
include/socket.h \
include/templates.h \
include/mingw.h \
include/parse_xml.h \
include/pixmaps.h \
include/stacktrace.h \
include/status.h \
include/flmsg_strings.h \
include/threads.h \
include/timeops.h \
include/time_table.h \
include/transfer.h \
include/util.h \
include/wrap.h \
include/wx_strings.h \
include/xml_io.h \
widgets/missing_strings.c \
include/FTextView.h \
include/Fl_Text_Buffer_mod.H \
include/Fl_Text_Display_mod.H \
include/Fl_Text_Editor_mod.H \
include/blank.h \
include/csv.h \
include/missing_strings.h \
include/plaintext.h \
include/radiogram.h \
flmsg_dialog.cxx
# Additional non-source files that are distributed
EXTRA_DIST += \
../data/template.rtf \
html_templates/blank_template.html \
html_templates/ics203_template.html \
html_templates/ics205_template.html \
html_templates/ics205a_template.html \
html_templates/ics206_template.html \
html_templates/ics213_templates.html \
html_templates/ics214_templates.html \
html_templates/ics216_templates.html \
html_templates/plaintext_template.html \
html_templates/radiogram_fc_template.html \
html_templates/radiogram_template.html \
html_templates/mars_daily.html \
html_templates/mars_ineei.html \
html_templates/mars_net.html
# Additional source files that support non-Linux cross compilation
EXTRA_DIST += \
../data/flmsg.desktop \
../data/flmsg.xpm \
../data/win32/fl_app.nsi \
../data/win32/flmsg.ico \
../scripts/buildmxe.sh \
../scripts/builddist.sh \
../scripts/mkappbundle.sh \
../scripts/mknsisinst.sh \
../data/mac/Info.plist.in \
../data/mac/flmsg.icns \
$(FLMSG_WIN32_SRC) \
$(FLMSG_FL_SRC)
flmsg-4.0.23/src/flmsg.cxx 0000664 0001750 0001750 00000243170 14465706466 012307 0000000 0000000 // ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "config.h"
#include "flmsg_config.h"
#include "flmsg.h"
#include "flmsg_arq.h"
#include "templates.h"
#include "debug.h"
#include "util.h"
#include "gettext.h"
#include "flmsg_dialog.h"
#include "flinput2.h"
#include "date.h"
#include "calendar.h"
#include "icons.h"
#include "fileselect.h"
#include "wrap.h"
#include "status.h"
#include "pixmaps.h"
#include "threads.h"
#include "xml_io.h"
#include "socket.h"
#include "mongoose.h"
#include "timeops.h"
#include "arq.h"
#ifdef WIN32
# include "flmsgrc.h"
# include "compat.h"
# define dirent fl_dirent_no_thanks
#endif
#include
#include "dirent-check.h"
#include
#include
#include
#include "XmlRpcClient.h"
using namespace std;
//----------------------------------------------------------------------
// Mongoose web server
struct mg_server *server = (mg_server *)NULL;
void *poll_server(void *);
int start_web_server();
void close_server();
char *mongoose_msg;
string mongoose_msgs;
int srvr_portnbr = 8080;
char sz_srvr_portnbr[6];
//----------------------------------------------------------------------
// log files
void rotate_log(std::string filename);
//----------------------------------------------------------------------
const char *options[] = {\
"flmsg unique options",
"--help",
"--version",
"--server-port\tstarting port number for forms web server [8080]",
"--flmsg-dir\tfull-path-name-of-folder for all FLMSG folders",
"--auto-dir\tfull-path-name-of-folder for autosend files",
"\tauto-dir, flmsg-dir can be separate and unique",
"--p FILENAME\tprint and exit",
"--b FILENAME\tprint and stay open",
"Fltk UI options",
"-bg\t-background [COLOR]",
"-bg2\t-background2 [COLOR]",
"-di\t-display [host:n.n]",
"-dn\t-dnd : enable drag and drop",
"-nodn\t-nodnd : disable drag and drop",
"-fg\t-foreground [COLOR]",
"-g\t-geometry [WxH+X+Y]",
"-i\t-iconic",
"-k\t-kbd : enable keyboard focus:",
"-nok\t-nokbd : en/disable keyboard focus",
"-na\t-name [CLASSNAME]",
"-s\t-scheme [none | base | gtk+ | plastic | gleam], default = gtk+",
"-ti\t[WINDOWTITLE]",
"-to\t-tooltips : enable tooltips",
"-not\t-notooltips : disable tooltips\n",
0
};
Fl_Double_Window *mainwindow = (Fl_Double_Window *)0;
Fl_Double_Window *expert_dialog = (Fl_Double_Window *)0;
Fl_Double_Window *tyro_dialog = (Fl_Double_Window *)0;
Fl_Double_Window *optionswindow = (Fl_Double_Window *)0;
Fl_Double_Window *arlwindow = (Fl_Double_Window *)0;
Fl_Double_Window *config_dialog = (Fl_Double_Window *)0;
Fl_Double_Window *hxwindow = (Fl_Double_Window *)0;
Fl_Double_Window *header_window = (Fl_Double_Window *)0;
pthread_t *xmlrpc_thread = 0;
pthread_mutex_t mutex_xmlrpc = PTHREAD_MUTEX_INITIALIZER;
bool printme = false;
bool exit_after_print = false;
int selected_form = NONE;
string title;
string errtext;
// fldigi, flmsg share a common files directory structure
#ifdef __WIN32__
string FLMSG_dir_default = "$USERPROFILE/NBEMS.files/";
#else
string FLMSG_dir_default = "$HOME/.nbems/";
#endif
string FLMSG_dir = "";
string ARQ_dir = "";
string ARQ_files_dir = "";
string ARQ_recv_dir = "";
string ARQ_send_dir = "";
string WRAP_dir = "";
string WRAP_recv_dir = "";
string WRAP_send_dir = "";
//string WRAP_auto_dir = "";
string ICS_dir = "";
string ICS_msg_dir = "";
string ICS_tmp_dir = "";
string CSV_dir = "";
string CUSTOM_dir = "";
string XFR_dir = "";
string FLMSG_temp_dir = "";
string FLMSG_log_dir = "";
string FLMSG_custom_dir = "";
string cmd_fname = "";
string TITLE = ":TITLE:";
string evalstr = "";
string parse_info = "";
//======================================================================
// custom edit/view only program use
bool update_custom = false;
//======================================================================
//string defRTFname = "";
// utility functions
//----------------------------------------------------------------------
// header fields
//----------------------------------------------------------------------
string hdr_from = "";
string hdr_edit = "";
static string szFrom = ":hdr_fm:";
static string szEdit = ":hdr_ed:";
bool check_mycall()
{
if (mainwindow == tyro_dialog)
return true;
if (!progStatus.my_call.empty())
return true;
if (!config_dialog->visible())
cb_config_personal();
return false;
}
// create flmsg line output for string data
string lineout(string &field, string &data)
{
static string sout;
static char sznum[80];
if (data.empty()) return "";
snprintf(sznum, sizeof(sznum), "%0d", (int)data.length());
sout.assign(field);
sout.append(sznum).append(" ").append(data).append("\n");
return sout;
}
// create flmsg line output for binary data
string binout( string &field, bool &data)
{
static string sout;
if (!data) return "";
sout = field;
sout.append(" ").append( data ? "T" : "F").append("\n");
return sout;
}
//----------------------------------------------------------------------
// header for flmsg output file
//----------------------------------------------------------------------
void clear_header()
{
hdr_from.clear();
hdr_edit.clear();
}
string header(const char *msgtype )
{
string hdr;
hdr.assign("").append (PACKAGE_VERSION).append("\n");
hdr.append(lineout(szFrom, hdr_from));
hdr.append(lineout(szEdit, hdr_edit));
hdr.append(msgtype).append("\n");
return hdr;
}
void read_header(string &str)
{
clear_header();
hdr_from = findstr(str, szFrom);
hdr_edit = findstr(str, szEdit);
}
void update_header(hdr_reason reason)
{
if (progStatus.my_call.empty()) return;
static string dt;
int utc = progStatus.UTC;
int dtf = progStatus.dtformat;
progStatus.UTC = 2;
progStatus.dtformat = 4;
dt.assign(szDate()).append(szTime(6));
progStatus.UTC = utc;
progStatus.dtformat = dtf;
switch (reason) {
case NEW :
clear_header();
hdr_edit.assign("\n").append(progStatus.my_call).append(" ").append(dt);
break;
case CHANGED:
if (!hdr_edit.empty()) {
size_t p1 = string::npos, p2 = string::npos;
while( (p1 = hdr_edit.find(progStatus.my_call)) != string::npos) {
p2 = hdr_edit.find("\n", p1);
if (p2 != string::npos)
hdr_edit.erase(p1, p2 - p1 + 1);
else
hdr_edit.erase(p1);
}
}
hdr_edit.append("\n").append(progStatus.my_call).append(" ").append(dt);
break;
case FROM:
if (!hdr_from.empty()) {
size_t p1 = string::npos, p2 = string::npos;
while( (p1 = hdr_from.find(progStatus.my_call)) != string::npos) {
p2 = hdr_from.find("\n", p1);
if (p2 != string::npos)
hdr_from.erase(p1, p2 - p1 + 1);
else
hdr_from.erase(p1);
}
}
hdr_from.append("\n").append(progStatus.my_call).append(" ").append(dt);
break;
default: ;
}
size_t p;
p = hdr_from.find("\n\n");
while(hdr_from.find("\n\n") != string::npos) {
hdr_from.replace(p, 2, "\n");
p = hdr_from.find("\n\n");
}
p = hdr_edit.find("\n\n");
while(hdr_edit.find("\n\n") != string::npos) {
hdr_edit.replace(p, 2, "\n");
p = hdr_edit.find("\n\n");
}
}
// find string data associated with a field specifier
string findstr(string &haystack, string &needle)
{
size_t p = haystack.find(needle, 0);
if (p == string::npos) return "";
p += needle.length();
int nchar;
sscanf(&haystack[p], "%d", &nchar);
if (nchar) {
p = haystack.find(' ', p);
p++;
return haystack.substr(p, nchar);
}
return "";
}
// find boolean data associated with a field specifier
bool findbin(string &haystack, string &needle)
{
size_t p = haystack.find(needle, 0);
if (p == string::npos) return false;
p += needle.length() + 1;
if (haystack.find("F", p) == p) return false;
if (haystack.find("T", p) == p) return true;
return false;
}
// replace string
void replacestr(string &form, string &where, string &what)
{
size_t p = form.find(where);
while (p != string::npos) {
form.replace(p, where.length(), what);
p = form.find(where);
}
}
void replacelf(string &form, int n)
{
size_t p = 0;
int i = 0;
while ( (p = form.find("\n", p)) != string::npos) {
form.insert(p, "
");
p += 5;
i++;
}
if (n)
for (int j = i; j < n; j++)
form.append("
\n");
}
void substitutestr(string &form, string &where, string &what)
{
size_t p = 0;
p = form.find(where, p);
while (p != string::npos) {
form.replace(p, where.length(), what);
p++;
p = form.find(where, p);
}
}
void striplf(string &what)
{
while (*what.rbegin() == '\n') what.erase(what.end()-1);
}
void strip_html(string &buffer)
{
string amp = "&"; string amprep = "&";
string quote = "\""; string quoterep = """;
string less = "<"; string lessrep = "<";
string more = ">"; string morerep = ">";
substitutestr(buffer, amp, amprep);
substitutestr(buffer, quote, quoterep);
substitutestr(buffer, less, lessrep);
substitutestr(buffer, more, morerep);
}
void remove_cr(string &buffer)
{
size_t p = string::npos;
while ((p = buffer.find('\r')) != string::npos) buffer.erase(p,1);
}
//----------------------------------------------------------------------
void remove_spaces_from_filename(string &fname)
{
size_t n = fname.length();
char szfname[n + 1];
char *p;
memset(szfname, 0, n + 1);
strcpy(szfname, fname.c_str());
p = (char *)fl_filename_name(szfname);
while (*p) {
if (*p == ' ') *p = '_';
p++;
}
fname = szfname;
}
char *szTime(int typ)
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
switch (typ) {
case 0:
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%H%ML", &sTime);
break;
case 1:
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%H:%ML", &sTime);
break;
case 2:
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%H%MZ", &sTime);
break;
case 3:
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%H:%MZ", &sTime);
break;
case 4:
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%H%M UTC", &sTime);
break;
case 5:
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%H:%M UTC", &sTime);
break;
case 6:
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%H%M%S", &sTime);
break;
case 7:
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%H%M", &sTime);
break;
default:
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%H%ML", &sTime);
}
return szDt;
}
char *szDate(int df)
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
if (progStatus.UTC > 1) {
gmtime_r (&tmptr, &sTime);
} else {
localtime_r(&tmptr, &sTime);
}
switch (df > -1 ? df: progStatus.dtformat) {
case 0: strftime(szDt, 79, "%Y-%m-%d", &sTime); break;
case 1: strftime(szDt, 79, "%m/%d/%y", &sTime); break;
case 2: strftime(szDt, 79, "%d/%m/%y", &sTime); break;
case 3: strftime(szDt, 79, "%Y-%d-%m", &sTime); break;
case 4: strftime(szDt, 79, "%Y%d%m", &sTime); break;
default: strftime(szDt, 79, "%Y-%m-%d", &sTime);
}
return szDt;
}
char *szAbbrevDate()
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
if (progStatus.UTC) {
gmtime_r (&tmptr, &sTime);
} else {
localtime_r(&tmptr, &sTime);
}
strftime(szDt, 79, "%b %d", &sTime);
for (int i = 0; i < 3; i++) szDt[i] = toupper(szDt[i]);
return szDt;
}
char *szDateTime()
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
if (progStatus.UTC) {
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%d%H%MZ %b %Y", &sTime);
} else {
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%d%H%ML %b %Y", &sTime);
}
for (size_t i = 0; i < strlen(szDt); i++) szDt[i] = toupper(szDt[i]);
return szDt;
}
char *szMarsDateTime()
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%d%H%MZ %b %Y", &sTime);
for (size_t i = 0; i < strlen(szDt); i++) szDt[i] = toupper(szDt[i]);
return szDt;
}
char *szCAPDateTime()
{
static char szDt[80];
time_t tmptr;
tm sTime;
time (&tmptr);
if (progStatus.caplocal) {
localtime_r(&tmptr, &sTime);
strftime(szDt, 79, "%d %H%ML %b %y", &sTime);
} else {
gmtime_r (&tmptr, &sTime);
strftime(szDt, 79, "%d %H%MZ %b %y", &sTime);
}
for (size_t i = 0; i < strlen(szDt); i++) szDt[i] = toupper(szDt[i]);
return szDt;
}
char *named_file()
{
static char szfname[400];
static char szDt[80];
szfname[0] = 0;
if (!progStatus.call_fname && !progStatus.dt_fname && !progStatus.sernbr_fname)
return szfname;
time_t tmptr;
tm sTime;
time (&tmptr);
switch (progStatus.dt_fname) {
case 1 :
localtime_r (&tmptr, &sTime);
strftime(szDt, sizeof(szDt), "%Y%m%d-%H%M%SL", &sTime);
break;
case 2 :
localtime_r (&tmptr, &sTime);
strftime(szDt, sizeof(szDt), "%Y%m%d-%H%M%S%Z", &sTime);
break;
case 3 :
localtime_r (&tmptr, &sTime);
strftime(szDt, sizeof(szDt), "%Y%m%d-%H%M%S%z", &sTime);
break;
case 4 :
gmtime_r (&tmptr, &sTime);
strftime(szDt, sizeof(szDt), "%Y%m%d-%H%M%SZ", &sTime);
break;
case 0 :
default :
szDt[0] = 0;
}
if (progStatus.call_fname) strcat(szfname, progStatus.my_call.c_str());
if (selected_form == RADIOGRAM && progStatus.rgnbr_fname) {
if (szfname[0]) strcat(szfname, "-");
strcat(szfname, progStatus.rgnbr.c_str());
} else {
if (szDt[0]) {
if (szfname[0]) strcat(szfname, "-");
strcat(szfname, szDt);
}
if (progStatus.sernbr_fname) {
if (szfname[0]) strcat(szfname, "-");
strcat(szfname, progStatus.sernbr.c_str());
}
}
return szfname;
}
void update_sernbr ()
{
string dfname = FLMSG_dir;
dfname.append("flmsg.sernbrs");
FILE *debug_file = fl_fopen(dfname.c_str(), "a");
int n = atoi(progStatus.sernbr.c_str());
n++;
char szn[12];
snprintf(szn, sizeof(szn), "%d", n);
progStatus.sernbr = szn;
txt_sernbr->value(szn);
txt_sernbr->redraw();
fprintf(debug_file, "New ser # %s\n" , szn);
fclose(debug_file);
}
void extract_text(string &buffer, const char *fname)
{
remove_cr(buffer);
if (buffer.find("") != string::npos) {
selected_form = RADIOGRAM;
read_rg_buffer(buffer);
if (fname) def_rg_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = IARU;
iaru_read_buffer(buffer);
if (fname) iaru_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = CAP105;
cap105_read_buffer(buffer);
if (fname) cap105_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = CAP110;
read_c110_buffer(buffer);
if (fname) cap110_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = F126;
f126_read_buffer(buffer);
if (fname) f126_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = MARSDAILY;
read_mars_daily_buffer(buffer);
if (fname) def_mars_daily_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = MARSINEEI;
read_mars_ineei_buffer(buffer);
if (fname) def_mars_ineei_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = MARSNET;
read_mars_net_buffer(buffer);
if (fname) def_mars_net_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = MARSARMY;
read_mars_army_buffer(buffer);
if (fname) def_mars_army_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = MARSMSG;
read_mars_msg_buffer(buffer);
if (fname) def_mars_msg_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = WXHC;
read_wxhc_buffer(buffer);
if (fname) def_wxhc_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = SEVEREWX;
read_severe_wx_buffer(buffer);
if (fname) def_severe_wx_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = STORMREP;
read_storm_buffer(buffer);
if (fname) def_storm_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = HICS203;
read_hics203_buffer(buffer);
if (fname) def_hics203_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = HICS206;
h206_read_buffer(buffer);
if (fname) h206_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = HICS213;
h213_read_buffer(buffer);
if (fname) h213_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = HICS214;
hics214_read_buffer(buffer);
if (fname) hics214_def_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS203;
read_203_buffer(buffer);
if (fname) def_203_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS205;
read_205_buffer(buffer);
if (fname) def_205_filename= fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS205A;
read_205a_buffer(buffer);
if (fname) def_205a_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS206;
read_206_buffer(buffer);
if (fname) def_206_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS213;
read_213_buffer(buffer);
if (fname) def_213_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS214;
read_214_buffer(buffer);
if (fname) def_214_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS216;
read_216_buffer(buffer);
if (fname) def_216_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = ICS309;
read_309_buffer(buffer);
if (fname) def_309_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = NETLOG;
read_netlog_buffer(buffer);
if (fname) def_netlog_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = PLAINTEXT;
read_ptbuffer(buffer);
if (fname) def_pt_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = BLANK;
read_blankbuffer(buffer);
if (fname) def_blank_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = CSV;
read_csvbuffer(buffer);
if (fname) def_csv_filename = fname;
select_form(selected_form);
} else if (buffer.find("") != string::npos) {
selected_form = CUSTOM;
read_custombuffer(buffer);
if (fname) def_custom_filename = fname;
select_form(selected_form);
} else if (!exit_after_print){
extern string blank_field;
extern void update_blankform();
selected_form = BLANK;
cb_blank_new();
if (fname) def_blank_filename = fname;
select_form(selected_form);
blank_field = buffer;
update_blankform();
}
}
//
void read_data_file(string s)
{
long filesize = 0;
// char *buff, *buffend;
int retval;
FILE *icsfile;
icsfile = fopen (s.c_str(), "rb");// "r");
if (!icsfile)
return;
// determine its size for buffer creation
fseek (icsfile, 0, SEEK_END);
filesize = ftell (icsfile);
// test file integrity
if (filesize == 0) {
fl_alert2(_("Empty file"));
fclose (icsfile);
return;
}
// read the entire file into the buffer
string buffer;
buffer.resize(filesize);
fseek(icsfile, 0, SEEK_SET);
retval = fread( (void*)buffer.c_str(), 1, filesize, icsfile);
fclose(icsfile);
if (retval != filesize) {
fl_alert2(_("Read error"));
return;
}
extract_text(buffer, s.c_str());
}
int eval_transfer_size()
{
switch (selected_form) {
case ICS203: return eval_203_fsize();
case ICS205: return eval_205_fsize();
case ICS205A: return eval_205a_fsize();
case ICS206: return eval_206_fsize();
case ICS213: return eval_213_fsize();
case ICS214: return eval_214_fsize();
case ICS216: return eval_216_fsize();
case ICS309: return eval_309_fsize();
case NETLOG: return eval_netlog_fsize();
case HICS203: return eval_hics203_fsize();
case HICS206: return eval_h206_fsize();
case HICS213: return eval_h213_fsize();
case HICS214: return eval_hics214_fsize();
case RADIOGRAM: return eval_rg_fsize();
case IARU: return eval_iaru_fsize();
case CAP105: return eval_cap105_fsize();
case CAP110: return eval_cap110_fsize();
case F126: return eval_f126_fsize();
case PLAINTEXT: return eval_pt_fsize();
case BLANK: return eval_blank_fsize();
case CSV: return eval_csv_fsize();
case CUSTOM: return eval_custom_fsize();
case TRANSFER: return eval_transfer_fsize();
case CUSTOM_TRANSFER: return eval_transfer_custom_form_fsize();
case MARSDAILY: return eval_mars_daily_fsize();
case MARSINEEI: return eval_mars_ineei_fsize();
case MARSNET: return eval_mars_net_fsize();
case MARSARMY: return eval_mars_army_fsize();
case MARSMSG: return eval_mars_msg_fsize();
case WXHC: return eval_wxhc_fsize();
case SEVEREWX: return eval_severe_wx_fsize();
case STORMREP: return eval_storm_fsize();
default : ;
}
return 0;
}
void cb_new()
{
switch (selected_form) {
case ICS203: cb_203_new(); break;
case ICS205: cb_205_new(); break;
case ICS205A: cb_205a_new(); break;
case ICS206: cb_206_new(); break;
case ICS213: cb_213_new(); break;
case ICS214: cb_214_new(); break;
case ICS216: cb_216_new(); break;
case ICS309: cb_309_new(); break;
case NETLOG: cb_netlog_new(); break;
case HICS203: cb_hics203_new(); break;
case HICS206: h206_cb_new(); break;
case HICS213: h213_cb_new(); break;
case HICS214: hics214_cb_new(); break;
case RADIOGRAM: cb_rg_new(); break;
case IARU: iaru_cb_new(); break;
case CAP105: cap105_cb_new(); break;
case CAP110: cap110_cb_new(); break;
case F126: f126_cb_new(); break;
case PLAINTEXT: cb_pt_new(); break;
case BLANK: cb_blank_new(); break;
case TRANSFER: cb_transfer_new(); break;
case CSV: cb_csv_new(); break;
case CUSTOM: cb_custom_new(); break;
case MARSDAILY: cb_mars_daily_new(); break;
case MARSINEEI: cb_mars_ineei_new(); break;
case MARSNET: cb_mars_net_new(); break;
case MARSARMY: cb_mars_army_new(); break;
case MARSMSG: cb_mars_msg_new(); break;
case WXHC: cb_wxhc_new(); break;
case SEVEREWX: cb_severe_wx_new(); break;
case STORMREP: cb_storm_new(); break;
default : return;
}
clear_estimate();
}
void cb_import()
{
switch (selected_form) {
case ICS203: cb_203_import(); break;
case ICS205: cb_205_import(); break;
case ICS205A: cb_205a_import(); break;
case ICS206: cb_206_import(); break;
case ICS213: cb_213_import(); break;
case ICS214: cb_214_import(); break;
case ICS216: cb_216_import(); break;
case ICS309: cb_309_import(); break;
case NETLOG: cb_netlog_import(); break;
case HICS203: cb_hics203_import(); break;
case HICS206: h206_cb_import(); break;
case HICS213: h213_cb_import(); break;
case HICS214: hics214_cb_import(); break;
case RADIOGRAM: cb_rg_import(); break;
case IARU: iaru_cb_import(); break;
case CAP105: cap105_cb_import(); break;
case CAP110: cap110_cb_import(); break;
case F126: f126_cb_import(); break;
case PLAINTEXT:
case BLANK:
case CSV:
case CUSTOM:
case MARSDAILY:
case MARSINEEI:
case MARSNET:
case MARSARMY:
case WXHC:
case SEVEREWX:
case STORMREP:
default:
fl_alert2("Not implemented");
}
estimate();
}
void cb_export()
{
switch (selected_form) {
case ICS203: cb_203_export(); break;
case ICS205: cb_205_export(); break;
case ICS205A: cb_205a_export(); break;
case ICS206: cb_206_export(); break;
case ICS213: cb_213_export(); break;
case ICS214: cb_214_export(); break;
case ICS216: cb_216_export(); break;
case ICS309: cb_309_export(); break;
case NETLOG: cb_netlog_export(); break;
case HICS203: cb_hics203_export(); break;
case HICS206: h206_cb_export(); break;
case HICS213: h213_cb_export(); break;
case HICS214: hics214_cb_export(); break;
case RADIOGRAM: cb_rg_export(); break;
case IARU: iaru_cb_export(); break;
case CAP105: cap105_cb_export(); break;
case CAP110: cap110_cb_export(); break;
case F126: f126_cb_export(); break;
case PLAINTEXT:
case BLANK:
case CSV:
case CUSTOM:
case MARSDAILY:
case MARSINEEI:
case MARSNET:
case MARSARMY:
case WXHC:
case SEVEREWX:
case STORMREP:
default:
fl_alert2("Not implemented");
}
}
void wrap_import(const char *fname)
{
string filename;
string inpbuffer;
bool isok = import_wrapfile(fname, filename, inpbuffer);
if (!isok && !exit_after_print) {
isok = !fl_choice2(_("Checksum failed\n\nIgnore errors?"), "yes", "no", NULL);
}
if (inpbuffer.find("") != string::npos &&
inpbuffer.find("") != string::npos) )
remove_cr( inpbuffer );
if (inpbuffer.find("") != string::npos) {
selected_form = ICS203;
cb_203_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = HICS203;
cb_hics203_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = HICS206;
h206_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = HICS213;
h213_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = HICS214;
hics214_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS205;
cb_205_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS205A;
cb_205a_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS206;
cb_206_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS213;
cb_213_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS214;
cb_214_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS216;
cb_216_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = ICS309;
cb_309_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = NETLOG;
cb_netlog_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = RADIOGRAM;
cb_rg_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = IARU;
iaru_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = CAP105;
cap105_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = CAP110;
cap110_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = F126;
f126_cb_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = PLAINTEXT;
cb_pt_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = BLANK;
cb_blank_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = CSV;
cb_csv_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = CUSTOM;
cb_custom_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = MARSDAILY;
cb_mars_daily_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = MARSINEEI;
cb_mars_ineei_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = MARSNET;
cb_mars_net_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = MARSARMY;
cb_mars_army_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = MARSMSG;
cb_mars_msg_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = WXHC;
cb_wxhc_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = SEVEREWX;
cb_severe_wx_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = STORMREP;
cb_storm_wrap_import(filename, inpbuffer);;
} else if (inpbuffer.find("") != string::npos) {
selected_form = TRANSFER;
cb_transfer_wrap_import(filename, inpbuffer);
} else if (inpbuffer.find("") != string::npos) {
selected_form = CUSTOM_TRANSFER;
cb_custom_form_wrap_import(filename, inpbuffer);
} else if (!exit_after_print) {
selected_form = NONE;
if (!fl_choice2(_("Cannot identify file type\n\nOpen as text file?"), "yes", "no", NULL)) {
filename = fname;
filename.append(".txt");
FILE *badfile = fopen(filename.c_str(), "w");
fwrite(inpbuffer.c_str(), inpbuffer.length(), 1, badfile);
fclose(badfile);
open_url(filename.c_str());
}
}
}
select_form(selected_form);
estimate();
return;
}
if (printme) {
string badform = baddata_html_template;
string mgstr = "value(fl_filename_name(p.c_str()));
txt_filename->redraw();
}
#define KNAME "flmsg"
#if !defined(__APPLE__) && !defined(__WOE32__) && USE_X
Pixmap flmsg_icon_pixmap;
void make_pixmap(Pixmap *xpm, const char **data)
{
Fl_Window w(0,0, KNAME);
w.xclass(KNAME);
w.show();
w.make_current();
Fl_Pixmap icon(data);
int maxd = (icon.w() > icon.h()) ? icon.w() : icon.h();
*xpm = fl_create_offscreen(maxd, maxd);
fl_begin_offscreen(*xpm);
fl_color(FL_BACKGROUND_COLOR);
fl_rectf(0, 0, maxd, maxd);
icon.draw(maxd - icon.w(), maxd - icon.h());
fl_end_offscreen();
}
#endif
void default_form()
{
selected_form = progStatus.tab;
select_form(selected_form);
cb_new();
}
#if FLMSG_FLTK_API_MAJOR == 1 && FLMSG_FLTK_API_MINOR == 3
int default_handler(int event)
{
if (event != FL_SHORTCUT)
return 0;
else if (Fl::event_ctrl()) {
Fl_Widget* w = Fl::focus();
return w->handle(FL_KEYBOARD);
}
return 0;
}
#endif
#ifdef __APPLE__
// registered file drop call back to operating system
void open_callback(const char *param)
{
string pathname = param;
if (pathname.find(WRAP_EXT) != string::npos)
wrap_import(pathname.c_str());
else {
read_data_file(pathname);
show_filename(pathname);
}
}
#endif
void after_start(void *)
{
check_mycall();
def_203_filename = ICS_msg_dir;
def_203_filename.append("default").append(F203_EXT);
def_203_TemplateName = ICS_tmp_dir;
def_203_TemplateName.append("default").append(T203_EXT);
def_205_filename = ICS_msg_dir;
def_205_filename.append("default").append(F205_EXT);
def_205_TemplateName = ICS_tmp_dir;
def_205_TemplateName.append("default").append(T205_EXT);
def_205a_filename = ICS_msg_dir;
def_205a_filename.append("default").append(F205A_EXT);
def_205a_TemplateName = ICS_tmp_dir;
def_205a_TemplateName.append("default").append(T205A_EXT);
def_206_filename = ICS_msg_dir;
def_206_filename.append("default").append(F206_EXT);
def_206_TemplateName = ICS_tmp_dir;
def_206_TemplateName.append("default").append(T206_EXT);
def_213_filename = ICS_msg_dir;
def_213_filename.append("default").append(F213_EXT);
def_213_TemplateName = ICS_tmp_dir;
def_213_TemplateName.append("default").append(T213_EXT);
def_214_filename = ICS_msg_dir;
def_214_filename.append("default").append(F214_EXT);
def_214_TemplateName = ICS_tmp_dir;
def_214_TemplateName.append("default").append(T214_EXT);
def_216_filename = ICS_msg_dir;
def_216_filename.append("default").append(F216_EXT);
def_216_TemplateName = ICS_tmp_dir;
def_216_TemplateName.append("default").append(T216_EXT);
def_309_filename = ICS_msg_dir;
def_309_filename.append("default").append(F309_EXT);
def_309_TemplateName = ICS_tmp_dir;
def_309_TemplateName.append("default").append(T309_EXT);
def_netlog_filename = ICS_msg_dir;
def_netlog_filename.append("default").append(FNET_EXT);
def_netlog_TemplateName = ICS_tmp_dir;
def_netlog_TemplateName.append("default").append(TNET_EXT);
def_hics203_filename = ICS_msg_dir;
def_hics203_filename.append("default").append(HF203_EXT);
def_hics203_TemplateName = ICS_tmp_dir;
def_hics203_TemplateName.append("default").append(HT203_EXT);
h206_def_filename = ICS_msg_dir;
h206_def_filename.append("default").append(HF206_EXT);
h206_def_template_name = ICS_tmp_dir;
h206_def_template_name.append("default").append(HT206_EXT);
h213_def_filename = ICS_msg_dir;
h213_def_filename.append("default").append(HF213_EXT);
h213_def_template_name = ICS_tmp_dir;
h213_def_template_name.append("default").append(HT213_EXT);
hics214_def_filename = ICS_msg_dir;
hics214_def_filename.append("default").append(HF214_EXT);
hics214_template_name = ICS_tmp_dir;
hics214_template_name.append("default").append(HT214_EXT);
def_rg_filename = ICS_msg_dir;
def_rg_filename.append("default").append(RGFILE_EXT);
def_rg_TemplateName = ICS_tmp_dir;
def_rg_TemplateName.append("default").append(RGTEMP_EXT);
iaru_def_filename = ICS_msg_dir;
iaru_def_filename.append("default").append(IARU_FILE_EXT);
iaru_def_template_name = ICS_tmp_dir;
iaru_def_template_name.append("default").append(IARU_TEMP_EXT);
cap105_def_filename = ICS_msg_dir;
cap105_def_filename.append("default").append(CAP105_FILE_EXT);
cap105_def_template_name = ICS_tmp_dir;
cap105_def_template_name.append("default").append(CAP105_TEMP_EXT);
cap105_set_choices();
cap110_def_filename = ICS_msg_dir;
cap110_def_filename.append("default").append(CAP105_FILE_EXT);
cap110_def_template_name = ICS_tmp_dir;
cap110_def_template_name.append("default").append(CAP105_TEMP_EXT);
f126_def_filename = ICS_msg_dir;
f126_def_filename.append("default").append(F126_FILE_EXT);
f126_def_template_name = ICS_tmp_dir;
f126_def_template_name.append("default").append(F126_TEMP_EXT);
f126_set_choices();
def_pt_filename = ICS_msg_dir;
def_pt_filename.append("default").append(PTFILE_EXT);
def_pt_TemplateName = ICS_tmp_dir;
def_pt_TemplateName.append("default").append(PTTEMP_EXT);
def_blank_filename = ICS_msg_dir;
def_blank_filename.append("default").append(BLANKFILE_EXT);
def_blank_TemplateName = ICS_tmp_dir;
def_blank_TemplateName.append("default").append(BLANKTEMP_EXT);
def_csv_filename = ICS_msg_dir;
def_csv_filename.append("default").append(CSVFILE_EXT);
def_csv_TemplateName = ICS_tmp_dir;
def_csv_TemplateName.append("default").append(CSVTEMP_EXT);
def_custom_filename = ICS_msg_dir;
def_custom_filename.append("default").append(CUSTOMFILE_EXT);
def_custom_TemplateName = ICS_tmp_dir;
def_custom_TemplateName.append("default").append(CUSTOMTEMP_EXT);
def_mars_daily_filename = ICS_msg_dir;
def_mars_daily_filename.append("default").append(FMARSDAILY_EXT);
def_mars_daily_TemplateName = ICS_tmp_dir;
def_mars_daily_TemplateName.append("default").append(TMARSDAILY_EXT);
def_mars_ineei_filename = ICS_msg_dir;
def_mars_ineei_filename.append("default").append(FMARSINEEI_EXT);
def_mars_ineei_TemplateName = ICS_tmp_dir;
def_mars_ineei_TemplateName.append("default").append(TMARSINEEI_EXT);
def_mars_net_filename = ICS_msg_dir;
def_mars_net_filename.append("default").append(FMARSNET_EXT);
def_mars_net_TemplateName = ICS_tmp_dir;
def_mars_net_TemplateName.append("default").append(TMARSNET_EXT);
def_mars_army_filename = ICS_msg_dir;
def_mars_army_filename.append("default").append(FMARSARMY_EXT);
def_mars_army_TemplateName = ICS_tmp_dir;
def_mars_army_TemplateName.append("default").append(TMARSARMY_EXT);
def_mars_msg_filename = ICS_msg_dir;
def_mars_msg_filename.append("default").append(FMARSMSG_EXT);
def_mars_msg_TemplateName = ICS_tmp_dir;
def_mars_msg_TemplateName.append("default").append(TMARSMSG_EXT);
def_wxhc_filename = ICS_msg_dir;
def_wxhc_filename.append("default").append(FWXHC_EXT);
def_wxhc_TemplateName = ICS_tmp_dir;
def_wxhc_TemplateName.append("default").append(TWXHC_EXT);
def_severe_wx_filename = ICS_msg_dir;
def_severe_wx_filename.append("default").append(FSWX_EXT);
def_severe_wx_TemplateName = ICS_tmp_dir;
def_severe_wx_TemplateName.append("default").append(TSWX_EXT);
def_storm_filename = ICS_msg_dir;
def_storm_filename.append("default").append(FSTRM_EXT);
def_storm_TemplateName = ICS_tmp_dir;
def_storm_TemplateName.append("default").append(TSTRM_EXT);
{
if (!cmd_fname.empty()) {
if (cmd_fname.find(WRAP_EXT) != string::npos)
wrap_import(cmd_fname.c_str());
else {
read_data_file(cmd_fname);
show_filename(cmd_fname);
}
estimate();
} else
default_form();
// Check to see what io mode FLDIGI is in.
std::string io_mode = get_io_mode();
int flag = 0;
if(!io_mode.empty()) {
flag = strncmp(io_mode.c_str(), "ARQ", 3);
if(flag != 0) {
flag = fl_choice2(_("KISS interface active! Switch FLDIGI to ARQ?"),
_("No"), _("Yes"), NULL);
if(flag == 1)
enable_arq();
}
}
}
#ifdef __APPLE__
fl_open_callback(open_callback);
#endif
init_flmsg_arq();
}
static std::string pname = "";
int main (int argc, char *argv[])
{
pname = argv[0];
size_t pn = pname.rfind("/");
if (pn != std::string::npos) pname.erase(0, pn + 1);
pn = pname.rfind("\\");
if (pn != std::string::npos) pname.erase(0, pn + 1);
XmlRpc::set_pname(pname);
bool have_title = false;
if (argc > 1) {
if (strcasecmp("--help", argv[1]) == 0) {
int i = 0;
while (options[i] != NULL) {
printf("%s\n", options[i]);
i++;
}
return 0;
}
if (strcasecmp("--version", argv[1]) == 0) {
printf("Version: %s\n", VERSION);
return 0;
}
for (int i = 0; i < argc; i++)
if (strcasecmp("-ti", argv[i]) == 0) have_title = true;
}
Fl::lock();
Fl::scheme("base");
int arg_idx;
FLMSG_dir.clear();
if (Fl::args(argc, argv, arg_idx, parse_args) != argc)
showoptions();
size_t p;
string appdir = argv[0];;
#ifdef __WOE32__
if (FLMSG_dir.empty()) {
p = appdir.find("FL_APPS\\");
if (p == string::npos)
p = appdir.find("FL_APPS/");
if (p != string::npos) {
FLMSG_dir.assign(appdir.substr(0, p + 8));
FLMSG_dir.append("NBEMS.files\\");
} else {
char dirbuf[FL_PATH_MAX + 1];
fl_filename_expand(dirbuf, sizeof(dirbuf) -1, "$USERPROFILE\\");
FLMSG_dir.assign(dirbuf);
FLMSG_dir.append("NBEMS.files/\\");
}
}
#else
char dirbuf[FL_PATH_MAX + 1];
fl_filename_absolute(dirbuf, FL_PATH_MAX, argv[0]);
appdir.assign(dirbuf);
p = appdir.rfind("flmsg");
if (p != string::npos)
appdir.erase(p);
p = appdir.find("FL_APPS/");
if (p == string::npos) p = appdir.find("ARC_MSG/");
if (p != string::npos) {
FLMSG_dir.assign(appdir.substr(0, p + 8));
FLMSG_dir.append("NBEMS.files/");
} else if (FLMSG_dir.empty()) {
fl_filename_expand(dirbuf, FL_PATH_MAX, "$HOME/");
FLMSG_dir = dirbuf;
FLMSG_dir.append(".nbems/");
}
#endif
progStatus.loadLastState();
expert_dialog = flmsg_dialog();
tyro_dialog = edit_view_dialog();
if (!progStatus.UI_default) {
int answer = fl_choice(
"FLMSG: Select Default User Interface\n\n\n",
"Communicator / Expert",
"Service Agency / Simple",
NULL );
progStatus.UI_default = 1;
progStatus.UI_expert = !answer;
}
if (progStatus.UI_expert)
mainwindow = expert_dialog;
else
mainwindow = tyro_dialog;
mainwindow->callback(exit_main);
set_rg_choices();
iaru_set_choices();
set_datetime_widgets();
#if FLMSG_FLTK_API_MAJOR == 1 && FLMSG_FLTK_API_MINOR == 3
Fl::add_handler(default_handler);
#endif
config_dialog = create_config_dialog();
header_window = headers_dialog();
btn_utc_format0->value(progStatus.UTC == 0);
btn_utc_format1->value(progStatus.UTC == 1);
btn_utc_format2->value(progStatus.UTC == 2);
btn_utc_format3->value(progStatus.UTC == 3);
btn_utc_format4->value(progStatus.UTC == 4);
btn_utc_format5->value(progStatus.UTC == 5);
btn_dtformat0->value(progStatus.dtformat == 0);
btn_dtformat1->value(progStatus.dtformat == 1);
btn_dtformat2->value(progStatus.dtformat == 2);
btn_dtformat3->value(progStatus.dtformat == 3);
cnt_wpl->value(progStatus.wpl);
Fl_File_Icon::load_system_icons();
FSEL::create();
checkdirectories();
string logname = FLMSG_log_dir;
logname.append("flmsg.log");
rotate_log(logname);
load_custom_menu();
string debug_file = FLMSG_dir;
debug_file.append("debug_log_").append(sz_srvr_portnbr).append(".txt");
debug::start(debug_file.c_str());
LOG_INFO("FLMSG_dir %s", FLMSG_dir.c_str());
LOG_INFO("ARQ_dir %s", ARQ_dir.c_str());
LOG_INFO("ARQ_files_dir %s", ARQ_files_dir.c_str());
LOG_INFO("ARQ_recv_dir %s", ARQ_recv_dir.c_str());
LOG_INFO("ARQ_send_dir %s", ARQ_send_dir.c_str());
LOG_INFO("WRAP_dir %s", WRAP_dir.c_str());
LOG_INFO("WRAP_recv_dir %s", WRAP_recv_dir.c_str());
LOG_INFO("WRAP_send_dir %s", WRAP_send_dir.c_str());
// LOG_INFO("WRAP_auto_dir %s", WRAP_auto_dir.c_str());
LOG_INFO("ICS_dir %s", ICS_dir.c_str());
LOG_INFO("ICS_msg_dir %s", ICS_msg_dir.c_str());
LOG_INFO("ICS_tmp_dir %s", ICS_tmp_dir.c_str());
LOG_INFO("CSV_dir %s", CSV_dir.c_str());
LOG_INFO("CUSTOM_dir %s", CUSTOM_dir.c_str());
LOG_INFO("Transfer dir %s", XFR_dir.c_str());
LOG_INFO("FLMSG_temp_dir %s", FLMSG_temp_dir.c_str());
LOG_INFO("FLMSG_log_dir %s", FLMSG_log_dir.c_str());
if (!parse_info.empty())
LOG_INFO("%s", parse_info.c_str());
start_web_server();
if (!mongoose_msgs.empty())
LOG_INFO("%s", mongoose_msgs.c_str());
if (printme) {
#ifdef __APPLE_
fl_open_display();
#endif
print_and_exit();
if (exit_after_print) {
if (server) mg_destroy_server(&server);
return 0;
}
}
open_xmlrpc();
xmlrpc_thread = new pthread_t;
if (pthread_create(xmlrpc_thread, NULL, xmlrpc_loop, NULL)) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
expert_dialog->size_range(570, 492);
expert_dialog->resize(
progStatus.mainX, progStatus.mainY,
progStatus.expertW, progStatus.expertH);
tyro_dialog->resize( progStatus.mainX, progStatus.mainY, tyro_dialog->w(), tyro_dialog->h());
#if defined(__WOE32__)
# ifndef IDI_ICON
# define IDI_ICON 101
# endif
mainwindow->icon((char*)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON)));
mainwindow->show (argc, argv);
#elif !defined(__APPLE__)
make_pixmap(&flmsg_icon_pixmap, flmsg_icon);
mainwindow->icon((char *)flmsg_icon_pixmap);
mainwindow->show(argc, argv);
// read in the current window hints, then modify them to allow icon transparency
Pixmap mask = -1; // create pixmaps to hold the icon image and its mask
XWMHints* hints = XGetWMHints(fl_display, fl_xid(mainwindow));
hints->flags |= IconMaskHint; // ensure transparency mask is enabled for the XPM icon
hints->icon_mask = mask; // set the transparency mask
XSetWMHints(fl_display, fl_xid(mainwindow), hints);
XFree(hints);
#else
mainwindow->show(argc, argv);
#endif
if (!have_title) {
static string main_label;
main_label = PACKAGE_NAME;
main_label.append(": ").append(PACKAGE_VERSION);
expert_dialog->label(main_label.c_str());
tyro_dialog->label(main_label.c_str());
}
Fl::add_timeout(0.10, after_start);
int result = Fl::run();
if (server) mg_destroy_server(&server);
return result;
}
void print_and_exit()
{
if (!cmd_fname.empty()) {
if (cmd_fname.find(WRAP_EXT) != string::npos) {
wrap_import(cmd_fname.c_str());
} else {
read_data_file(cmd_fname);
}
switch (selected_form) {
case ICS203 :
cb_203_save();
cb_203_html();
break;
case ICS205 :
cb_205_save();
cb_205_html();
break;
case ICS205A :
cb_205a_save();
cb_205a_html();
break;
case ICS206 :
cb_206_save();
cb_206_html();
break;
case ICS213 :
cb_213_save();
cb_213_html();
break;
case ICS214 :
cb_214_save();
cb_214_html();
break;
case ICS216 :
cb_216_save();
cb_216_html();
break;
case ICS309 :
cb_309_save();
cb_309_html();
break;
case NETLOG :
cb_netlog_save();
cb_netlog_html();
break;
case HICS203 :
cb_hics203_save();
cb_hics203_html();
break;
case HICS206 :
h206_cb_save();
h206_cb_html();
break;
case HICS213 :
h213_cb_save();
h213_cb_html();
break;
case HICS214 :
hics214_cb_save();
hics214_cb_html();
break;
case RADIOGRAM :
cb_rg_save();
cb_rg_html();
break;
case PLAINTEXT :
cb_pt_save();
cb_pt_html();
break;
case BLANK :
cb_blank_save();
cb_blank_html();
break;
case CSV :
cb_csv_save();
cb_csv_html();
break;
case CUSTOM :
cb_custom_save();
cb_custom_html(true);
break;
case MARSDAILY :
cb_mars_daily_save();
cb_mars_daily_html();
break;
case MARSINEEI :
cb_mars_ineei_save();
cb_mars_ineei_html();
break;
case MARSNET :
cb_mars_net_save();
cb_mars_net_html();
break;
case MARSARMY :
cb_mars_army_save();
cb_mars_army_html();
break;
case MARSMSG :
cb_mars_msg_save();
cb_mars_msg_html();
break;
case WXHC :
cb_wxhc_save();
cb_wxhc_html();
break;
case SEVEREWX :
cb_severe_wx_save();
cb_severe_wx_html();
break;
case STORMREP :
cb_storm_save();
cb_storm_html();
break;
}
}
}
void drop_box_changed()
{
string buffer = drop_box->value();
size_t n;
drop_box->value("");
drop_box->redraw();
if ((n = buffer.find("file:///")) != string::npos)
buffer.erase(0, n + 7);
if ((buffer.find(":\\")) != string::npos || (buffer.find("/") == 0)) {
while ((n = buffer.find('\n')) != string::npos)
buffer.erase(n, 1);
while ((n = buffer.find('\r')) != string::npos)
buffer.erase(n, 1);
if (buffer.find(WRAP_EXT) != string::npos)
wrap_import(buffer.c_str());
else
read_data_file(buffer.c_str());
} else // try to extract as a text buffer
extract_text(buffer, NULL);
estimate();
}
void drop_file_changed()
{
string buffer = drop_file->value();
size_t n;
drop_file->value("");
drop_file->redraw();
if ((n = buffer.find("file:///")) != string::npos)
buffer.erase(0, n + 7);
if ((buffer.find(":\\")) != string::npos || (buffer.find("/") == 0)) {
while ((n = buffer.find('\n')) != string::npos)
buffer.erase(n, 1);
while ((n = buffer.find('\r')) != string::npos)
buffer.erase(n, 1);
if (buffer.find(WRAP_EXT) != string::npos)
wrap_import(buffer.c_str());
else
read_data_file(buffer.c_str());
} else // try to extract as a text buffer
extract_text(buffer, NULL);
estimate();
}
void checkdirectories(void)
{
struct DIRS {
string& dir;
const char* suffix;
void (*new_dir_func)(void);
};
#ifdef __WIN32__
DIRS FLMSG_dirs[] = {
{ FLMSG_dir, 0, 0 },
{ ARQ_dir, "ARQ", 0 },
{ ARQ_files_dir, "ARQ\\files", 0 },
{ ARQ_recv_dir, "ARQ\\recv", 0 },
{ ARQ_send_dir, "ARQ\\send", 0 },
{ WRAP_dir, "WRAP", 0 },
{ WRAP_recv_dir, "WRAP\\recv", 0 },
{ WRAP_send_dir, "WRAP\\send", 0 },
{ ICS_dir, "ICS", 0 },
{ ICS_msg_dir, "ICS\\messages", 0 },
{ ICS_tmp_dir, "ICS\\templates", 0 },
{ CSV_dir, "CSV", 0},
{ CUSTOM_dir, "CUSTOM", 0},
{ XFR_dir, "TRANSFERS", 0},
{ FLMSG_temp_dir, "temp_files", 0 },
{ FLMSG_log_dir, "log_files", 0 }
};
#else
DIRS FLMSG_dirs[] = {
{ FLMSG_dir, 0, 0 },
{ ARQ_dir, "ARQ", 0 },
{ ARQ_files_dir, "ARQ/files", 0 },
{ ARQ_recv_dir, "ARQ/recv", 0 },
{ ARQ_send_dir, "ARQ/send", 0 },
{ WRAP_dir, "WRAP", 0 },
{ WRAP_recv_dir, "WRAP/recv", 0 },
{ WRAP_send_dir, "WRAP/send", 0 },
{ ICS_dir, "ICS", 0 },
{ ICS_msg_dir, "ICS/messages", 0 },
{ ICS_tmp_dir, "ICS/templates", 0 },
{ CSV_dir, "CSV", 0},
{ CUSTOM_dir, "CUSTOM", 0},
{ XFR_dir, "TRANSFERS", 0},
{ FLMSG_temp_dir, "temp_files", 0 },
{ FLMSG_log_dir, "log_files", 0 }
};
#endif
int r;
for (size_t i = 0; i < sizeof(FLMSG_dirs)/sizeof(*FLMSG_dirs); i++) {
if (FLMSG_dirs[i].dir.empty() && FLMSG_dirs[i].suffix)
FLMSG_dirs[i].dir.assign(FLMSG_dir).append(FLMSG_dirs[i].suffix).append(PATH_SEP);
if ((r = mkdir(FLMSG_dirs[i].dir.c_str(), 0777)) == -1 && errno != EEXIST) {
cerr << _("Could not make directory") << ' ' << FLMSG_dirs[i].dir
<< ": " << strerror(errno) << '\n';
exit(EXIT_FAILURE);
}
else if (r == 0 && FLMSG_dirs[i].new_dir_func)
FLMSG_dirs[i].new_dir_func();
}
if (FLMSG_dir.find("FL_APPS") != std::string::npos) {
ICS_dir = FLMSG_dir;
#if __WIN32__
ICS_dir.append("..\\..\\");
#else
ICS_dir.append("../../");
#endif
ICS_msg_dir.clear();
ICS_tmp_dir.clear();
CUSTOM_dir.clear();
DIRS MSG_dirs[] = {
{ ICS_msg_dir, "flmsg.messages", 0},
{ ICS_tmp_dir, "flmsg.templates", 0},
{ CUSTOM_dir, "flmsg.forms", 0},
};
for (size_t i = 0; i < sizeof(MSG_dirs) / sizeof(*MSG_dirs); i++) {
if (MSG_dirs[i].dir.empty() && MSG_dirs[i].suffix)
MSG_dirs[i].dir.assign(ICS_dir).append(MSG_dirs[i].suffix).append(PATH_SEP);
r = mkdir(MSG_dirs[i].dir.c_str(), 0777);
if (r == -1 && errno != EEXIST) {
cerr << _("Could not make directory") << ' ' << MSG_dirs[i].dir
<< ": " << strerror(errno) << '\n';
exit(EXIT_FAILURE);
}
else if (r == 0 && MSG_dirs[i].new_dir_func)
MSG_dirs[i].new_dir_func();
}
}
}
void showoptions()
{
if (!optionswindow) {
optionswindow = optionsdialog();
for (int i = 0; options[i] != 0; i++)
brwsOptions->add(options[i]);
}
optionswindow->show();
}
void closeoptions()
{
optionswindow->hide();
}
//extern Fl_Group *tab_headers;
void set_config_values()
{
btn_dtformat0->value(progStatus.dtformat == 0);
btn_dtformat1->value(progStatus.dtformat == 1);
btn_dtformat2->value(progStatus.dtformat == 2);
btn_utc_format0->value(progStatus.UTC == 0);
btn_utc_format1->value(progStatus.UTC == 1);
btn_utc_format2->value(progStatus.UTC == 2);
btn_utc_format3->value(progStatus.UTC == 3);
btn_utc_format4->value(progStatus.UTC == 4);
btn_utc_format5->value(progStatus.UTC == 5);
txt_my_call->value(progStatus.my_call.c_str());
txt_my_name->value(progStatus.my_name.c_str());
txt_my_addr->value(progStatus.my_addr.c_str());
txt_my_city->value(progStatus.my_city.c_str());
txt_my_tel->value(progStatus.my_tel.c_str());
cnt_wpl->value(progStatus.wpl);
txt_rgnbr->value(progStatus.rgnbr.c_str());
btn_rgnbr_fname->value(progStatus.rgnbr_fname);
btn_open_on_export->value(progStatus.open_on_export);
btn_use_compression->value(progStatus.use_compression);
txt_sernbr->value(progStatus.sernbr.c_str());
btn_sernbr_fname->value(progStatus.sernbr_fname);
btn_call_fname->value(progStatus.call_fname);
cbo_dt_fname->index(progStatus.dt_fname);
txt_mars_roster_file->value(progStatus.mars_roster_file.c_str());
txt_socket_addr->value(progStatus.xmlrpc_addr.c_str());
txt_socket_port->value(progStatus.xmlrpc_port.c_str());
}
void cb_config_date_time()
{
set_config_values();
tabs_config->value(tab_date_time);
config_dialog->show();
}
void cb_config_personal()
{
set_config_values();
tabs_config->value(tab_personal);
config_dialog->show();
}
void cb_config_radiogram()
{
set_config_values();
tabs_config->value(tab_config_radiogram);
config_dialog->show();
}
void cb_config_files()
{
set_config_values();
tabs_config->value(tab_files);
config_dialog->show();
}
//void cb_config_socket()
//{
// set_config_values();
// tabs_config->value(tab_socket);
// config_dialog->show();
//}
void cb_config_arq()
{
set_config_values();
tabs_config->value(tab_arq);
config_dialog->show();
}
void cb_config_UI()
{
set_config_values();
tabs_config->value(tab_UI);
config_dialog->show();
}
void show_help()
{
open_url("http://www.w1hkj.com/flmsg-help/index.html");
}
void custom_download()
{
open_url("https://sourceforge.net/projects/fldigi/files/flmsg/");
}
int parse_args(int argc, char **argv, int& idx)
{
if (strstr(argv[idx], "--p")) {
printme = true;
exit_after_print = true;
idx++;
parse_info.append("parsed --p\n");
return 1;
}
if (strstr(argv[idx], "--b")) {
printme = true;
idx++;
parse_info.append("parsed --b\n");
return 1;
}
if (strstr(argv[idx], "--flmsg-dir")) {
idx++;
string tmp = argv[idx];
if (!tmp.empty()) FLMSG_dir_default = tmp;
size_t p = string::npos;
while ( (p = FLMSG_dir_default.find("\\")) != string::npos)
FLMSG_dir_default[p] = '/';
if (FLMSG_dir_default[FLMSG_dir_default.length() - 1] != '/')
FLMSG_dir_default += '/';
FLMSG_dir = FLMSG_dir_default;
parse_info.append("parsed --flmsg-dir ");
parse_info.append(FLMSG_dir).append("\n");
idx++;
return 2;
}
if (strstr(argv[idx], "--server-port")) {
idx++;
int port = 0;
if (sscanf(argv[idx], "%d", &port) == 1)
srvr_portnbr = port;
idx++;
return 2;
}
/*
if (strstr(argv[idx], "--auto-dir")) {
idx++;
string tmp = argv[idx];
if (!tmp.empty()) WRAP_auto_dir = tmp;
size_t p = string::npos;
while ( (p = WRAP_auto_dir.find("\\")) != string::npos)
WRAP_auto_dir[p] = '/';
parse_info.append("parsed --autodir ");
parse_info.append(WRAP_auto_dir).append("\n");
idx++;
return 2;
}
*/
if ( argv[idx][0] == '-' ) {
return 0;
}
parse_info.append("parsed filename: ").append(argv[idx]).append("\n");
string fname = argv[idx];
if (fname.find(DATAFILE_EXT) != string::npos ||
fname.find(DATATEMP_EXT) != string::npos ||
fname.find(F203_EXT) != string::npos ||
fname.find(T203_EXT) != string::npos ||
fname.find(F205_EXT) != string::npos ||
fname.find(T205_EXT) != string::npos ||
fname.find(F205A_EXT) != string::npos ||
fname.find(T205A_EXT) != string::npos ||
fname.find(F206_EXT) != string::npos ||
fname.find(T206_EXT) != string::npos ||
fname.find(F213_EXT) != string::npos ||
fname.find(T213_EXT) != string::npos ||
fname.find(F214_EXT) != string::npos ||
fname.find(T214_EXT) != string::npos ||
fname.find(F216_EXT) != string::npos ||
fname.find(T216_EXT) != string::npos ||
fname.find(F309_EXT) != string::npos ||
fname.find(T309_EXT) != string::npos ||
fname.find(FNET_EXT) != string::npos ||
fname.find(TNET_EXT) != string::npos ||
fname.find(HF203_EXT) != string::npos ||
fname.find(HT203_EXT) != string::npos ||
fname.find(HF206_EXT) != string::npos ||
fname.find(HT206_EXT) != string::npos ||
fname.find(HF213_EXT) != string::npos ||
fname.find(HT213_EXT) != string::npos ||
fname.find(HF214_EXT) != string::npos ||
fname.find(HT214_EXT) != string::npos ||
fname.find(RGFILE_EXT) != string::npos ||
fname.find(RGTEMP_EXT) != string::npos ||
fname.find(PTFILE_EXT) != string::npos ||
fname.find(PTTEMP_EXT) != string::npos ||
fname.find(BLANKFILE_EXT) != string::npos ||
fname.find(BLANKTEMP_EXT) != string::npos ||
fname.find(CSVFILE_EXT) != string::npos ||
fname.find(CSVTEMP_EXT) != string::npos ||
fname.find(CUSTOMFILE_EXT) != string::npos ||
fname.find(CUSTOMTEMP_EXT) != string::npos ||
fname.find(FMARSDAILY_EXT) != string::npos ||
fname.find(TMARSDAILY_EXT) != string::npos ||
fname.find(FMARSINEEI_EXT) != string::npos ||
fname.find(TMARSINEEI_EXT) != string::npos ||
fname.find(FMARSNET_EXT) != string::npos ||
fname.find(TMARSNET_EXT) != string::npos ||
fname.find(FMARSARMY_EXT) != string::npos ||
fname.find(TMARSARMY_EXT) != string::npos ||
fname.find(FWXHC_EXT) != string::npos ||
fname.find(TWXHC_EXT) != string::npos ||
fname.find(FSWX_EXT) != string::npos ||
fname.find(TSWX_EXT) != string::npos ||
fname.find(IARU_FILE_EXT) != string::npos ||
fname.find(IARU_TEMP_EXT) != string::npos ||
fname.find(CAP105_FILE_EXT) != string::npos ||
fname.find(CAP105_TEMP_EXT) != string::npos ||
fname.find(CAP110_FILE_EXT) != string::npos ||
fname.find(CAP110_TEMP_EXT) != string::npos ||
fname.find(F126_FILE_EXT) != string::npos ||
fname.find(F126_TEMP_EXT) != string::npos ||
fname.find(TRANSFER_EXT) != string::npos ||
fname.find(WRAP_EXT) != string::npos ) {
cmd_fname = fname;
}
idx++;
return 1;
}
void open_url(const char* url, int folder)
{
//LOG_INFO("%s", url);
#ifndef __WOE32__
const char *folders[] = {
# ifdef __APPLE__
"open" // OS X
# else
"fl-xdg-open", // Puppy Linux
"xdg-open" // all other Linux/Unix
#endif
};
const char* browsers[] = {
# ifdef __APPLE__
getenv("FLMSG_BROWSER"), // valid for any OS - set by user
getenv("BROWSER"), // valid for any OS - set by user
"open" // OS X
# else
"fl-xdg-open", // Puppy Linux
getenv("FLMSG_BROWSER"), // force use of spec'd browser
getenv("BROWSER"), // most Linux distributions
"chromium-browser", // preferred browser for HTML-5
"firefox", // nice, but incomplete HTML-5
"mozilla", // nice, but incomplete HTML-5
"xdg-open", // let OS determine browser
"sensible-browser" // must be something out there!
# endif
};
switch (fork()) {
case 0:
# ifndef NDEBUG
unsetenv("MALLOC_CHECK_");
unsetenv("MALLOC_PERTURB_");
# endif
if (folder) {
for (size_t i = 0; i < sizeof(folders)/sizeof(folders[0]); i++) {
if (folders[i])
execlp(folders[i], folders[i], url, (char*)0);
}
} else {
for (size_t i = 0; i < sizeof(browsers)/sizeof(browsers[0]); i++) {
if (browsers[i])
execlp(browsers[i], browsers[i], url, (char*)0);
}
}
exit(EXIT_FAILURE);
case -1:
fl_alert2(_("Could not run a web browser:\n%s\n\n"
"Open this URL manually:\n%s"),
strerror(errno), url);
}
#else
if ((size_t)ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL) <= 32)
fl_alert2(_("Could not open url:\n%s\n"), url);
#endif
}
//------------------------------------------------------------------------------
// mongoose server support
//------------------------------------------------------------------------------
bool exit_server = false;
pthread_t *web_server_thread = 0;
pthread_mutex_t mutex_web_server = PTHREAD_MUTEX_INITIALIZER;
int handle_type = HANDLE_WAITING;
static const char *html_waiting =
"\n\
Custom form not posted
\n\
";
//void load_custom(void *)
//{
// load_custom_menu();
//}
void * poll_server(void *d)
{
// int n = 10;
exit_server = false;
while(!exit_server) {
pthread_mutex_lock(&mutex_web_server);
mg_poll_server(server, 200);
pthread_mutex_unlock(&mutex_web_server);
// n--;
// if (!n) {
// if (!progStatus.UI_expert) //flmsg_editor)
// Fl::awake(load_custom, 0);
// n = 30;
// }
MilliSleep(10);
}
return NULL;
}
void close_server()
{
pthread_mutex_lock(&mutex_web_server);
exit_server = true;
pthread_mutex_unlock(&mutex_web_server);
MilliSleep(200);
}
void update_form(void *)
{
cb_custom_save_as();
update_custom = false;
}
extern void get_html_vars(struct mg_connection *conn);
static int web_handler(struct mg_connection *conn)
{
if (strcmp(conn->uri, "/handle_post_request") == 0) {
get_html_vars(conn);
custom_viewer(conn);
if (update_custom) Fl::awake(update_form);
} else {
if (handle_type == HANDLE_EDIT) {
custom_editor(conn);
}
else if (handle_type == HANDLE_VIEW) {
custom_viewer(conn);
}
else if (handle_type == HANDLE_WAITING)
// Show HTML waiting
mg_send_data(conn, html_waiting, strlen(html_waiting));
}
handle_type = HANDLE_NONE;
return MG_REQUEST_PROCESSED;
}
extern char *mg_open_msg;
int start_web_server()
{
if ((server = mg_create_server(NULL)) == NULL) {
fl_alert2("%s", "Failed to start web server");
exit(EXIT_FAILURE);
return 0;
}
mongoose_msgs.clear();
char retmsg[500];
int ret = mg_set_option(server, "document_root", CUSTOM_dir.c_str(), retmsg);
if (ret) {
fl_alert2("%s", "Failed to set file server root directory");
exit(EXIT_FAILURE);
return 0;
}
int last_portnbr = srvr_portnbr + 100;
int test_portnbr = srvr_portnbr;
while (test_portnbr < last_portnbr) {
snprintf(sz_srvr_portnbr, sizeof(sz_srvr_portnbr),
"%d", test_portnbr);
ret = mg_set_option(server, "listening_port", sz_srvr_portnbr, retmsg);
if (ret == 0) break;
mongoose_msgs.append(retmsg).append(" ")
.append(sz_srvr_portnbr);
test_portnbr++;
Fl::awake();
}
if (test_portnbr == last_portnbr) {
LOG_ERROR("%s", mongoose_msgs.c_str());
fl_alert2(
"Web server port bind failed.\n\
Range %d - %d", srvr_portnbr, last_portnbr - 1);
exit(EXIT_FAILURE);
return 0;
}
else {
if (!mongoose_msgs.empty()) mongoose_msgs.append("\n");
mongoose_msgs.append("Listening on port ").
append(sz_srvr_portnbr);
}
mg_set_request_handler(server, web_handler);
web_server_thread = new pthread_t;
if (pthread_create(web_server_thread, NULL, poll_server, NULL)) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
return 1;
}
void rotate_log(std::string filename)
{
const int n = 5; // rename existing log files to keep up to 5 old versions
ostringstream oldfn, newfn;
size_t p;
oldfn << filename << '.';
newfn << filename << '.';
p = oldfn.tellp();
for (int i = n - 1; i > 0; i--) {
oldfn.seekp(p);
newfn.seekp(p);
oldfn << i;
newfn << i + 1;
rename(oldfn.str().c_str(), newfn.str().c_str());
}
rename(filename.c_str(), oldfn.str().c_str());
}
flmsg-4.0.23/src/arq/ 0000775 0001750 0001750 00000000000 14474644702 011301 5 0000000 0000000 flmsg-4.0.23/src/arq/arq.cxx 0000664 0001750 0001750 00000044030 14463050240 012513 0000000 0000000 // ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flmsg is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flmsg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include "arq.h"
#include "status.h"
#include "xml_io.h"
#include "flmsg_arq.h"
#include "gettext.h"
static pthread_t arq_thread;
static pthread_mutex_t arq_mutex = PTHREAD_MUTEX_INITIALIZER;
static arq *inst = NULL;
static bool first_rtry = true;
std::string arqstates[] = {
"ARQ_DOWN", "TIMEDOUT", "ABORT", "ARQ_CONNECTING", "ARQ_CONNECTED",
"WAITING", "WAITFORACK", "ARQ_DISCONNECT", "ARQ_DISCONNECTING",
"ABORTING", "STOPPED"};
std::string arq::upcase(std::string s)
{
for (size_t i = 0; i < s.length(); i++)
s[i] = toupper(s[i]);
return s;
}
arq::arq()
{
do_sendfnc = NULL;
do_getc1 = NULL;
do_rcvfnc = NULL;
do_printRX = NULL;
do_printTX = NULL;
do_printLOG = NULL;
do_printTALK = NULL;
do_abortfnc = NULL;
do_disconnectfnc = NULL;
do_rxUrCall = NULL;
do_qualityfnc = NULL;
do_printSTATUS = NULL;
UrCall.erase();
MyCall.erase();
// queues //
TxTextQueue.clear();
RxTextQueue.clear();
exponent = EXPONENT;
// static status
LinkState = ARQ_DOWN; // ARQ link is initially down
sender = false;
retries = getRetries();
loopcount = 0;
xfrsize = 0;
str_xfrsize = "";
lastblock = ' ';
timeout = -1;
retrytime = rtry();
arq_running = false;
arq_exit = false;
arqreset = false;
}
void arq::resetTx()
{
TxTextQueue.clear();
}
void arq::resetRx()
{
RxTextQueue.clear();
}
void arq::reset()
{
resetTx();
resetRx();
blknbr = 0;
timeout = -1;
LinkState = ARQ_DOWN;
sender = false;
disconnectfnc();
str_blknbr = "000";
retrytime = rtry();
}
// Checksum of std::string s
std::string arq::checksum(std::string &s)
{
framecrc.reset();
return framecrc.scrc16(s);
}
void arq::addToTxQue(std::string s)
{
if (s.empty()) return;
TxTextQueue.assign(s);
}
std::string arq::calls()
{
std::string s;
s.assign(MyCall);
s.append(ARQ_DLE);
s.append(UrCall);
s.append(ARQ_DLE);
return s;
}
// Connect
// e.g.: '~1cW1HKJ;KH6TY;12345;XXXX~4'
//
void arq::connectFrame()
{
reset();
std::string Frame;
Frame.append(ARQ_SOF);
Frame += CONREQ;
Frame.append(calls());
Frame.append(str_xfrsize);
Frame.append(ARQ_DLE);
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
LinkState = ARQ_CONNECTING;
sender = true;
printLOG("send CONREQ", "");
addToTxQue(Frame);
lastblock = CONREQ;
}
// Connect acknowledge
// e.g: '~1CKH6TY;W1HKJ;XXXX~4'
//
void arq::conackFrame ()
{
reset();
if (progStatus.ID_off) {
set_fldigi_rxid(0);
set_fldigi_txid(0);
}
std::string Frame;
Frame.append(ARQ_SOF);
Frame += CONACK;
Frame.append(calls());
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send CONACK", "");
addToTxQue(Frame);
lastblock = CONACK;
}
void arq::ackFrame()
{
std::string Frame;
Frame.append(ARQ_SOF);
Frame += ACK;
Frame.append(calls());
Frame.append(str_blknbr);
Frame.append(ARQ_DLE);
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send ACK", "");
addToTxQue(Frame);
lastblock = ACK;
}
void arq::nakFrame()
{
std::string Frame;
Frame.append(ARQ_SOF);
Frame += NAK;
Frame.append(calls());
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send NAK", "");
addToTxQue(Frame);
lastblock = NAK;
}
// Disconnect session
void arq::disconnectFrame()
{
std::string Frame;
Frame.append(ARQ_SOF);
Frame += DISREQ;
Frame.append(calls());
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send DISCON", "");
addToTxQue(Frame);
lastblock = DISREQ;
sender = true;
}
void sked_reset(void *)
{
inst->exec_arqreset();
}
void arq::disackFrame()
{
std::string Frame;
Frame.append(ARQ_SOF);
Frame += DISACK;
Frame.append(calls());
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send DISACK", "");
addToTxQue(Frame);
lastblock = DISACK;
}
// poll
void arq::pollFrame()
{
std::string Frame;
Frame.append(ARQ_SOF);
Frame += POLL;
Frame.append(calls());
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
printLOG("send POLL", "");
addToTxQue(Frame);
lastblock = POLL;
}
// Text frame
static std::string lastframe;
void arq::dataFrame()
{
char msg[200] = "send DATA";
std::string Frame;
static char szbknbr[12];
payload = xmttext.substr(0, buffer_length);
last_buffer_length = buffer_length;
Frame.append(ARQ_SOF);
Frame += DATA;
Frame.append(calls());
blknbr++;
snprintf(szbknbr, sizeof(szbknbr), "%03d", blknbr);
str_blknbr = szbknbr;
Frame.append(szbknbr);
Frame.append(ARQ_DLE);
Frame.append(payload);
Frame.append(checksum(Frame));
Frame.append(ARQ_EOF);
if (xfrsize) {
qualityfnc( 1.0 * (xfrsize - xmttext.length()) / xfrsize);
snprintf(msg, sizeof(msg),"send DATA %0.1f %%", 100.0 * (xfrsize - xmttext.length()) / xfrsize);
}
printLOG(msg, "");
lastframe = Frame;
lastblock = DATA;
addToTxQue(Frame);
}
//=====================================================================
bool arq::rightCALLS()
{
// test call signs
// requesting stations callsign
std::string testcall;
size_t p1 = 1, p2 = rcvPayLoad.find(ARQ_DLE, p1);
if (p2 != std::string::npos) {
testcall = upcase(rcvPayLoad.substr(p1, p2 - p1));
if (UrCall != testcall) {
printLOG("Wrong call", "");
return false;
}
p1 = p2+1;
p2 = rcvPayLoad.find(ARQ_DLE, p1);
if (p2 != std::string::npos) {
testcall = upcase(rcvPayLoad.substr(p1, p2 - p1));
if (testcall != MyCall) {
printLOG("Not my call", "");
return false;
}
} else
return false;
} else
return false;
rcvPayLoad.erase(0, p2+1);
return true;
}
void arq::parseCONREQ()
{
size_t p1 = 1, p2 = rcvPayLoad.find(ARQ_DLE);
if (p2 == std::string::npos) {
printLOG("CONREQ no calls", "");
return;
}
std::string testcall = upcase(rcvPayLoad.substr(p1, p2 - p1));
if ((LinkState == ARQ_CONNECTED) && (UrCall != testcall) )
return; // disallow multiple connects
// requesting stations callsign
UrCall = testcall;
p1 = p2 + 1;
p2 = rcvPayLoad.find(ARQ_DLE, p1);
testcall = upcase(rcvPayLoad.substr(p1, p2 - p1));
if (testcall != MyCall) {
printLOG("CONREQ not my call", "");
UrCall.clear();
rxUrCall(UrCall);
return;
}
rxUrCall(UrCall);
p2++;
int sz;
sscanf(rcvPayLoad.substr(p2).c_str(), "%d", &sz);
xfrsize = sz;
TxTextQueue.clear();
RxTextQueue.clear();
arqfname.clear();
printLOG("received CONREQ", "");
conackFrame();
LinkState = ARQ_CONNECTED;
}
void arq::parseCONACK()
{
if (!rightCALLS()) return;
if (progStatus.ID_off) {
set_fldigi_rxid(0);
set_fldigi_txid(0);
}
RxTextQueue.clear();
printLOG("received CONACK", "");
dataFrame();
LinkState = ARQ_CONNECTED;
}
void arq::parseDISREQ()
{
if (!rightCALLS() || (LinkState != ARQ_CONNECTED)) return;
TxTextQueue.clear();
printLOG("received DISREQ", "");
disackFrame();
}
void arq::parseDISACK()
{
if (!rightCALLS()) return;
printLOG("received DISACK", "");
exec_arqreset();
}
void arq::parsePOLL()
{
if (!rightCALLS() || (LinkState != ARQ_CONNECTED)) return;
printLOG("received POLL", "");
ackFrame();
}
void arq::parseDATA()
{
if (!rightCALLS() || (LinkState != ARQ_CONNECTED)) return;
char msg[200] = "received DATA";
size_t pos = rcvPayLoad.find(ARQ_DLE);
if (pos == std::string::npos) return;
std::string str_test = rcvPayLoad.substr(0, pos);
if (str_test != str_blknbr) {
str_blknbr = str_test;
rcvPayLoad.erase(0, pos + 1);
RxTextQueue.append(rcvPayLoad);
if (xfrsize) {
qualityfnc( 1.0 * RxTextQueue.length() / xfrsize);
snprintf(msg, sizeof(msg),"received DATA %0.1f %%", 100.0 * RxTextQueue.length() / xfrsize);
}
if (xfrsize == RxTextQueue.length()) {
qualityfnc(1.0);
std::string fname = "message";
size_t p = std::string::npos;
if ((p = RxTextQueue.find("[ARQ:fn ")) != std::string::npos) {
p += 8;
size_t p2 = RxTextQueue.find("]", p);
if (p2 != std::string::npos)
fname = RxTextQueue.substr(p, p2 - p);
}
snprintf(msg, sizeof(msg),
"%s\"%s\" from %s",
sRcvd.c_str(),
fname.c_str(),
UrCall.c_str());
escape(false, RxTextQueue);
printRX(RxTextQueue);
RxTextQueue.clear();
}
}
printLOG(msg, "");
ackFrame();
}
void arq::parseACK()
{
if (!rightCALLS() || (LinkState != ARQ_CONNECTED)) return;
printLOG("received ACK", "");
size_t pos = rcvPayLoad.find(ARQ_DLE);
if (pos == std::string::npos) return;
if (str_blknbr == rcvPayLoad.substr(0, pos)) {
xmttext.erase(0, last_buffer_length);
if (!xmttext.empty())
dataFrame();
else {
qualityfnc(1.0);
std::string msg = "Transferred \"";
msg.append(arqfname).append("\" to ").append(UrCall);
printLOG(msg, "");
disconnect();
}
} else {
addToTxQue(lastframe);
}
}
void arq::parseNAK()
{
if (!rightCALLS() || (LinkState != ARQ_CONNECTED)) return;
printLOG("received NAK", "");
printLOG("resend DATA FRAME", "");
addToTxQue(lastframe);
}
void arq::parseFrame(std::string txt)
{
txt = noCR(txt);
Ccrc16 testcrc;
size_t len = txt.length();
if (len < 15) return;
rcvPayLoad = txt.substr(0, len - strlen(ARQ_EOF) - 4);
std::string sRcvdCRC = testcrc.scrc16( rcvPayLoad );
std::string rxCRC = txt.substr(len - strlen(ARQ_EOF) - 4, 4);
if (sRcvdCRC != rxCRC ) { // failed CRC test
retrytime = rtry();
timeout = getRetries() * retrytime;
printLOG("failed CRC test", "");
if (!sender && (LinkState == ARQ_CONNECTED))
nakFrame();
return;
}
rcvPayLoad.erase(0, strlen(ARQ_SOF));
switch (rcvPayLoad[0]) {
case CONREQ :
printLOG("", txt);
parseCONREQ();
break;
case CONACK :
printLOG("", txt);
parseCONACK();
break;
case DISREQ :
if (LinkState >= ARQ_CONNECTED)
printLOG("", txt);
parseDISREQ();
break;
case DISACK :
if (LinkState >= ARQ_CONNECTED)
printLOG("", txt);
parseDISACK();
break;
case POLL :
if (LinkState == ARQ_CONNECTED)
printLOG("", txt);
parsePOLL();
break;
case ACK:
if (LinkState == ARQ_CONNECTED)
printLOG("", txt);
parseACK();
break;
case NAK:
if (LinkState == ARQ_CONNECTED)
printLOG("", txt);
parseNAK();
break;
case DATA :
if (LinkState == ARQ_CONNECTED)
printLOG("", txt);
parseDATA();
break;
default :
nakFrame();
}
retrytime = rtry();
timeout = getRetries() * retrytime;
}
//=====================================================================
void arq::setbuffer_length()
{
if (exponent == 4) buffer_length = 16;
else if (exponent == 5) buffer_length = 32;
else if (exponent == 6) buffer_length = 64;
else if (exponent == 7) buffer_length = 128;
else if (exponent == 8) buffer_length = 256;
else if (exponent == 9) buffer_length = 512;
else if (exponent == 10) buffer_length = 1024;
else buffer_length = 128;
}
void arq::connect()
{
for (size_t i = 0; i < UrCall.length(); i++)
UrCall[i] = toupper(UrCall[i]);
rxUrCall(UrCall);
first_rtry = true;
TxTextQueue.clear();
connectFrame();
retries = getRetries();
LinkState = ARQ_CONNECTING;
}
void arq::disconnect()
{
disconnectFrame();
retries = getRetries();
LinkState = ARQ_DISCONNECT;
}
void arq::escape(bool encode, std::string &s)
{
if (encode) {
size_t p = s.find(ESC_CHR);
while (p != std::string::npos) {
p++;
s.insert(p, 1, ESC_CHR);
p = s.find(ESC_CHR, p+1);
}
} else {
std::string dblesc;
dblesc += ESC_CHR; dblesc += ESC_CHR;
size_t p = s.find(dblesc);
while (p != std::string::npos) {
s.erase(p,1);
p = s.find(dblesc, p+1);
}
}
}
void arq::sendtext(std::string call, std::string s)
{
char s_xfrsize[20];
if (LinkState != ARQ_DOWN) return;
xmttext = s;
escape(true, xmttext);
xfrsize = xmttext.length();
snprintf(s_xfrsize, sizeof(s_xfrsize), "%d", (int)xfrsize);
str_xfrsize = s_xfrsize;
UrCall = call;
if (progStatus.ID_on) {
set_fldigi_rxid(1);
set_fldigi_txid(1);
}
arqfname.clear();
size_t p = std::string::npos;
if ((p = s.find("[ARQ:fn ")) != std::string::npos) {
p += 8;
size_t p2 = s.find("]", p);
if (p2 != std::string::npos)
arqfname = s.substr(p, p2 - p);
}
connect();
}
// received a NAK resend the last frame
// add retry countdown etc.
void arq::resendFrame()
{
addToTxQue(lastframe);
printLOG("received NAK", "");
}
extern void arqlog(std::string, std::string);
int arq::rtry()
{
nomFrame.clear();
nomFrame.append(ARQ_SOF);
nomFrame += 'A';
nomFrame.append (MyCall);
nomFrame.append(ARQ_DLE);
nomFrame.append("AA9AAA/8");
nomFrame.append(ARQ_DLE);
nomFrame.append(std::string(16,'B'));
nomFrame.append("1234");
nomFrame.append(ARQ_EOF);
float response_delay = transmit_time(nomFrame);
if (response_delay < 5.0) response_delay = 5.0;
response_delay *= 1000.0; // in milliseconds
response_delay *= (1.0 + (0.5 * rand() / RAND_MAX));
int idelay = floorf(response_delay/ ARQLOOPTIME);
if (first_rtry) {
std::stringstream str;
str << "Wait " << idelay * ARQLOOPTIME / 1000.0 << " sec's before retry";
printLOG(str.str(), "");
first_rtry = false;
}
return idelay;
}
void arq::exec_arqreset()
{
MilliSleep(1000);
LinkState = ARQ_DOWN;
retries = getRetries();
retrytime = rtry();
timeout = -1;
xfrsize = 0;
xfrsize = 0;
sender = false;
RxTextQueue.clear();
TxTextQueue.clear();
printLOG("DISCONNECTED","");
rxUrCall("");
qualityfnc(0);
if (progStatus.ID_on) {
set_fldigi_rxid(1);
set_fldigi_txid(1);
}
disconnectfnc();
}
static std::string rxbuf = " ";
static char chkchar = ' ';
void arq::rcv_chars()
{
char c;
while (getc1(c) == true) {
chkchar = rxbuf[0];
rxbuf[0] = rxbuf[1];
rxbuf[1] = c;
if ((rxbuf == ARQ_SOF) && (chkchar != ESC_CHR)) {
RxFrameQueue.clear();
RxFrameQueue.append(rxbuf);
} else if (RxFrameQueue.find(ARQ_SOF) == 0) {
retrytime = rtry();
timeout = getRetries() * retrytime;
if ((rxbuf == ARQ_EOF) && (chkchar != ESC_CHR)) {
RxFrameQueue += c;
parseFrame(RxFrameQueue);
RxFrameQueue.clear();
goto retfunc;
} else
RxFrameQueue += c;
} else if ((rxbuf == ARQ_EOF) && (chkchar != ESC_CHR)) {
RxFrameQueue.clear();
}
if (RxFrameQueue.length() > 1200)
exec_arqreset();
}
retfunc:
if (trx()) return;
//!OK_to_transmit()) return;
if (LinkState != ARQ_DOWN) {
--timeout;
if (timeout == 0) {
std::string fname = "";
std::string msg = sTout;
size_t p = std::string::npos;
fname = arqfname;
if (fname.empty()) {
if ((p = RxTextQueue.find("[ARQ:fn ")) != std::string::npos) {
p += 8;
size_t p2 = RxTextQueue.find("]", p);
if (p2 != std::string::npos)
fname = RxTextQueue.substr(p, p2 - p);
}
}
if (fname.empty()) fname.assign(_("Filename not known"));
msg.append(fname);
msg.append(sColon).append(UrCall);
printLOG(msg, "");
exec_arqreset();
}
}
}
void arq::sendchars()
{
if (!OK_to_transmit()) {
return;
}
if (RxFrameQueue.find(ARQ_SOF) == 0) {
return;
}
// test for non response if this is the sending station
if (LinkState != arq::ARQ_DOWN) {
if (sender) {
retrytime--;
if (retrytime == 0) {
retries--;
if (retries == 0) {
std::string failtext = sRtry;
failtext.append(UrCall);
failtext.append(sColon);
failtext.append(arqfname);
failtext.append(sColon);
switch (lastblock) {
case DATA: failtext.append("DATA block"); break;
case POLL: failtext.append("POLL block"); break;
case CONREQ: failtext.append("CONREQ block"); break;
case DISREQ: failtext.append("DISREQ block"); break;
}
printLOG("", failtext);
exec_arqreset();
return;
}
std::stringstream s;
s << "Resend " << retries;
printLOG("", s.str());
retrytime = rtry();
if (lastblock == DATA) pollFrame();
if (lastblock == POLL) pollFrame();
else if (lastblock == CONREQ) connectFrame();
else if (lastblock == DISREQ) disconnectFrame();
printLOG("", TxTextQueue);
sendfnc(TxTextQueue.insert(0," \n"));
TxTextQueue.clear();
return;
}
}
}
// transmit new data
if (TxTextQueue.empty() )
return;
printLOG("", TxTextQueue);
sendfnc(TxTextQueue.insert(0," \n"));
retrytime = rtry();
if (lastblock == DISACK) exec_arqreset();
TxTextQueue.clear();
return;
}
//----------------------------------------------------------------------
// friend process of arq class
// operates in a separate thread
// all called by reference functions must use Fl::wait(fn,...)
// to isolate the UI thread from the arq thread
//----------------------------------------------------------------------
void * arqloop(void *)
{
int looptime = ARQLOOPTIME;
while (1) {
MilliSleep(
inst->LinkState == arq::ARQ_DOWN ? looptime * 10 : looptime);
if (inst->arq_exit) break;
{
guard_lock arqlock( &arq_mutex );
if (inst->arqreset) {
inst->exec_arqreset();
inst->arqreset = false;
}
inst->rcv_chars();
inst->sendchars();
}
}
return NULL;
}
void arq::start_arq()
{
if (arq_running) return; // ONLY ONE instance allowed
inst = this;
if (pthread_create(&arq_thread, NULL, arqloop, NULL) < 0) {
LOG_ERROR("arq init: pthread_create failed");
arq_running = false;
inst = NULL;
return;
}
if (progStatus.ID_on) {
set_fldigi_rxid(1);
set_fldigi_txid(1);
}
arq_running = true;
}
void arq::reset_arq() {
arqreset = true;
}
void arq::exit_arq() {
if (arq_running == false) return;
{
guard_lock arqlock( &arq_mutex );
arq_exit = true;
}
pthread_join(arq_thread, NULL);
arq_running = false;
}
//---------------------------------------------------------------------
flmsg-4.0.23/src/arq/flmsg-arq.cxx 0000664 0001750 0001750 00000037173 14463050240 013633 0000000 0000000 // ----------------------------------------------------------------------------
//
// flmsg is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flmsg is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// this tests depends on a modified FL/filename.H in the Fltk-1.3.0
// change
//# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
// to
//# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__) && !defined(__WOE32__)
#include
#ifdef __MINGW32__
# include "compat.h"
#endif
#include
#include "fileselect.h"
#include "socket.h"
#include
#include "flmsg.h"
#include "flmsg_dialog.h"
#include "flmsg_arq.h"
#include "xml_io.h"
#include "threads.h"
#include "flmsg_arq.h"
#include "flmisc.h"
#include "stacktrace.h"
#include "icons.h"
#include "arq.h"
#include "base64.h"
#include "gettext.h"
#include "status.h"
#include "wrap.h"
#include "time_table.h"
bool SHOWDEBUG = true;
Fl_Double_Window *dlgconfig = (Fl_Double_Window *)0;
arq flmsg_arq;
bool traffic = false;
int arqstate = 0;
std::string RX;
std::string TX;
std::string MyCall;
std::string UrCall;
#if !defined(__APPLE__) && !defined(__WOE32__) && USE_X
Pixmap flarq_icon_pixmap;
#endif
std::string rxbuffer;
size_t bufsize = 0;
int blocksSent = 0;
float vers = 0;
float version;
extern std::string arqstates[];
const char *ASCII[32] = {
"", "", "", "", // 0x00 - 0x03
"", "", "", "", // 0x04 - 0x07
"", "", "", "", // 0x08 - 0x0B
"", "", "", "", // 0x0C - 0x0F
"", "", "", "", // 0x10 - 0x13
"", "", "", "", // 0x14 - 0x17
"", "", "", "", // 0x18 - 0x1B
"", "", "", "" // 0x1C - 0x1F
};
static pthread_mutex_t nocr_mutex = PTHREAD_MUTEX_INITIALIZER;
std::string noCR(std::string s)
{
guard_lock lock(&nocr_mutex);
std::string text = s;
size_t p;
while ((p = text.find('\r')) != std::string::npos)
text.erase(p,1);
return text;
}
static pthread_mutex_t noctl_mutex = PTHREAD_MUTEX_INITIALIZER;
std::string noCTL(std::string s)
{
guard_lock lock(&noctl_mutex);
std::string text;
int c;
for (size_t n = 0; n < s.length(); n++) {
c = s[n];
if ((c >= 0) && (c < 0x20))
text.append(ASCII[c]);
else
text += c;
}
return text;
}
std::string incomingText = "";
std::string txtarqload = "";
std::string rxfname = "";
std::string arqstart = "ARQ::STX\n";
std::string arqend = "ARQ::ETX\n";
std::string arqfile = "ARQ:FILE::";
std::string arqbase64 = "ARQ:ENCODING::BASE64\n";
std::string arqsizespec = "ARQ:SIZE::";
size_t startpos = std::string::npos;
size_t endpos = std::string::npos;
size_t fnamepos = std::string::npos;
size_t indx = std::string::npos;
size_t sizepos = std::string::npos;
size_t lfpos = std::string::npos;
size_t arqPayloadSize = 0;
bool rxARQfile = false;
bool rxARQhavesize = false;
bool rxTextReady = false;
time_t StartTime_t;
time_t EndTime_t;
time_t TransferTime_t;
double TransferTime;
char statemsg[80];
void dispState()
{
switch (flmsg_arq.state()) {
case arq::ARQ_CONNECTING :
txtSTATE->value("CONNECTING");
txtSTATE->redraw();
btnSEND->label("Wait");
btnSEND->redraw_label();
break;
case arq::ARQ_CONNECTED :
txtSTATE->value("CONNECTED");
txtSTATE->redraw();
txtSENDTO->value( flmsg_arq.urCall().c_str() );
btnSEND->label("End");
btnSEND->redraw_label();
break;
case arq::ARQ_DISCONNECT:
txtSTATE->value("ARQ_DISCONNECT");
txtSTATE->redraw();
btnSEND->label("Wait");
btnSEND->redraw_label();
break;
case arq::ARQ_DISCONNECTING:
txtSTATE->value("ARQ_DISCONNECTING");
txtSTATE->redraw();
btnSEND->label("Wait");
btnSEND->redraw_label();
break;
case arq::ARQ_DOWN :
default :
txtSTATE->value("NOT CONNECTED");
txtSTATE->redraw();
btnSEND->label("Send");
btnSEND->redraw_label();
}
}
void client_transmit(const std::string& s )
{
MilliSleep(50);
try {
if (!s.empty()) {
xml_send_tx_chars(s);
}
}
catch (const SocketException& e) {
std::cerr << e.what() << '\n';
}
}
size_t rxbuffer_len = 0;
size_t rxbuffer_ptr = 0;
bool client_receive(char &c)
{
if (rxbuffer_len && (rxbuffer_ptr < rxbuffer_len)) {
c = rxbuffer[rxbuffer_ptr];
rxbuffer_ptr++;
return true;
}
rxbuffer.clear();
rxbuffer_len = rxbuffer_ptr = 0;
std::string rxstr = xml_get_rx_chars();
if (!rxstr.empty()) {
rxbuffer = rxstr;
rxbuffer_len = rxbuffer.length();
}
return false;
}
void restrt(void *)
{
prgSTATE->value(0.0);
prgSTATE->label("");
prgSTATE->redraw_label();
prgSTATE->redraw();
rxARQfile = false;
incomingText.clear();
}
void restart()
{
Fl::awake(restrt);
}
void arqSEND()
{
int state = Fl::event_state();
if ((state & FL_CTRL) == FL_CTRL) {
flmsg_arq.reset_arq();
txtSENDTO->value("");
Fl::awake(restrt);
return;
}
if (progStatus.my_call.empty()) return;
if (strlen(txtSENDTO->value()) == 0) return;
int arqstate = flmsg_arq.state();
if (arqstate == arq::ARQ_DOWN) {
flmsg_arq.myCall(progStatus.my_call.c_str());
cb_wrap_autosend();
} else {
flmsg_arq.disconnect();
txtSENDTO->value("");
Fl::awake(restrt);
}
}
pthread_mutex_t payload_mutex = PTHREAD_MUTEX_INITIALIZER;
void save_this_file_as(std::string fname, std::string txt)
{
if (txt.find("") != std::string::npos) {
cb_transfer_wrap_import(fname, txt);
select_form(TRANSFER);
return;
}
std::string fnam = fname;
std::string outfname;
std::string tst_name;
std::string tst_ext = "";
// write to file with name(s) such as
// test.b2s, test-01.txt, test-02.txt etc. up to 999
size_t pos = fnam.find(".");
if (pos != std::string::npos) {
tst_name = fnam.substr(0, pos);
tst_ext = fnam.substr(pos);
} else
tst_name = fnam;
char fnum[8]="";
int num = 0;
outfname.assign(ICS_msg_dir).append(tst_name).append(tst_ext);
std::ifstream tstfile;
tstfile.open(outfname.c_str());
while (tstfile) {
tstfile.close();
snprintf(fnum, sizeof(fnum), "-%03d", (++num % 1000));
outfname.assign(ICS_msg_dir).append(tst_name).append(fnum).append(tst_ext);
tstfile.open(outfname.c_str());
}
// decompress_maybe returns 0 on failure
decompress_maybe(txt);
std::ofstream ofile(outfname.c_str(), std::ios::binary);
if (ofile) ofile << txt;
ofile.close();
add_rcvd_msg(tst_name.append(fnum).append(tst_ext));
return;
}
void display_payloadtext(std::string fname, std::string txt)
{
save_this_file_as(fname, txt);
}
// process an AutoSend data stream
void direct_payload(std::string txt)
{
LOG_INFO("%s", txt.substr(0, 50).c_str());
size_t pos = txt.find("WRAP:fn ");
if (pos == std::string::npos) return;
txt.erase(0, pos + 8);
pos = txt.find("]");
if (pos == std::string::npos) return;
std::string fname = txt.substr(0,pos);
txt.erase(0,pos + 1);
pos = txt.find("[WRAP:chk");
if (pos == std::string::npos) return;
txt.erase(pos);
save_this_file_as(fname, txt);
}
// process an ARQ data stream
void payloadtext(void *)
{
guard_lock payload(&payload_mutex);
if ((startpos = incomingText.find(arqstart)) != std::string::npos) {
startpos += arqstart.length();
time(&StartTime_t);
} else
return;
if ((endpos = incomingText.find(arqend)) != std::string::npos) {
fnamepos = incomingText.find(arqfile);
fnamepos += arqfile.length();
indx = incomingText.find('\n', fnamepos);
rxfname = incomingText.substr(fnamepos, indx - fnamepos);
txtarqload = incomingText.substr(startpos, endpos - startpos);
if (incomingText.find(arqbase64) != std::string::npos) {
base64 b64;
txtarqload = b64.decode(txtarqload);
}
startpos = std::string::npos;
endpos = std::string::npos;
fnamepos = std::string::npos;
indx = std::string::npos;
sizepos = std::string::npos;
lfpos = std::string::npos;
arqPayloadSize = 0;
rxARQfile = false;
rxARQhavesize = false;
rxTextReady = true;
if (incomingText.find("FLMSG_XFR") != std::string::npos) {
std::string outfname;
std::string arqstr = "[ARQ:fn ";
size_t p = txtarqload.find(arqstr);
if (p != std::string::npos) {
txtarqload.erase(0, p + arqstr.length());
p = txtarqload.find("]");
if (p != std::string::npos) {
outfname = txtarqload.substr(0, p);
txtarqload.erase(0, p + 1);
display_payloadtext(outfname, txtarqload);
}
}
}
incomingText = "";
}
}
void payloadText(std::string s)
{
guard_lock payload(&payload_mutex);
incomingText.assign (s);
Fl::awake(payloadtext);
}
void abted(void *)
{
notify_dialog* alert_window = new notify_dialog;
alert_window->set_non_modal();
alert_window->notify(_("Transfer aborted"), 0, true);
restart();
}
void abortedTransfer()
{
Fl::awake(abted);
}
static std::string arqascii = "ARQ:ENCODING::ASCII\n";
void send_xml_text(std::string txt)
{
size_t txtsize;
char sizemsg[40];
if (!txt.empty()) {
TX.erase();
TX.append(arqfile);
TX.append("FLMSG_XFR");
TX.append("\n");
TX.append(arqascii);
txtsize = txt.length();
arqPayloadSize = txtsize;
blocksSent = 0;
snprintf(sizemsg, sizeof(sizemsg), "ARQ:SIZE::%d\n",
static_cast(txtsize));
TX.append(sizemsg);
TX.append(arqstart);
TX.append(txt);
TX.append(arqend);
}
traffic = true;
}
static float update_val;
static char szPercent[8];
void updateQuality(void *)
{
prgSTATE->value( update_val );
snprintf(szPercent, sizeof(szPercent), "%0.f %%", update_val*100.0 + 0.5);
prgSTATE->label(szPercent);
}
void showQuality(float val)
{
update_val = val;
Fl::awake(updateQuality);
}
void mainloop(void *)
{
if (traffic) {
flmsg_arq.sendtext(txtSENDTO->value(), TX);
traffic = false;
time(&StartTime_t);
}
dispState();
Fl::repeat_timeout(0.1, mainloop);
}
static std::string str_status;
//static double dtime;
pthread_mutex_t protect_status = PTHREAD_MUTEX_INITIALIZER;
void print_status(void *data)
{
if (!btext) return;
guard_lock protect(&protect_status);
if (str_status.empty()) return;
size_t pos;
pos = str_status.find("\n");
while (pos != std::string::npos) {
btext->add(str_status.substr(0, pos).c_str());
str_status.erase(0, pos + 1);
pos = str_status.find("\n");
}
btext->redraw();
btext->bottomline(btext->size());
str_status.clear();
}
static std::string notify_string;
void notify_(void *)
{
notify_dialog* alert_window = new notify_dialog;
alert_window->notify(notify_string.c_str(), progStatus.arq_notify_timeout, true);
}
std::string sXfrd = _("Transferred ");
std::string sRcvd = _("Received ");
std::string sRtry = _("Retries failed: ");
std::string sTout = _("Timed out:");
std::string sTo = _(" to ");
std::string sFm = _(" from ");
std::string sColon = _(" : ");
void STATUSprint(std::string s)
{
size_t p = 0;
if ( s.find(sXfrd) != std::string::npos) { // transferred
notify_string = s;
p = notify_string.find(sXfrd);
if (p != std::string::npos) notify_string[p + sXfrd.length() - 1] = '\n';
p = notify_string.find(sTo);
if (p != std::string::npos) notify_string[p] = '\n';
Fl::awake(notify_);
}
else if (s.find(sRcvd) != std::string::npos && progStatus.notify_receipt) { // received
notify_string = s;
p = notify_string.find(sRcvd);
if (p != std::string::npos) notify_string[p + sRcvd.length() - 1] = '\n';
p = notify_string.find(sFm);
if (p != std::string::npos) notify_string[p] = '\n';
Fl::awake(notify_);
}
else if (s.find(sRtry) != std::string::npos) { // retries
notify_string = s;
p = notify_string.find(">");
if (p != std::string::npos)
notify_string.insert(p+1, "\n");
p = notify_string.find(sColon);
while (p != std::string::npos) {
notify_string.replace(p, sColon.length(), "\n");
p = notify_string.find(sColon);
}
Fl::awake(notify_);
}
else if (s.find(sTout) != std::string::npos) { // timed
notify_string = s;
p = notify_string.find(sTout);
notify_string[p + sTout.length() -1] = '\n';
p = notify_string.find(sColon);
while (p != std::string::npos) {
notify_string.replace(p, sColon.length(), "\n");
p = notify_string.find(sColon);
}
Fl::awake(notify_);
}
}
void arqlog(std::string nom, std::string s)
{
char szGMT[80];
tm *now;
time_t tm;
if (nom.empty() && s.empty()) return;
time(&tm);
now = localtime( &tm );
memset(szGMT, 0, 80);
strftime(szGMT, sizeof(szGMT), "[%X] ", now);
std::string txtout;
txtout.assign(szGMT).append(nom).append(" ").append(noCTL(s));
STATUSprint(txtout);
std::string logname = FLMSG_log_dir;
logname.append("flmsg.log");
std::ofstream logfile(logname.c_str(), std::ios::app);
if (logfile){
logfile << txtout;
if (s.length() == 0 || s[s.length()-1] != '\n') logfile << std::endl;
}
logfile.close();
if (txtout.length() > 60) txtout.erase(60);
if (txtout.length() == 0) return;
Fl_Color color = FL_BLACK;
if (s.find(sTout) != std::string::npos) // timed
color = FL_RED;
else if (s.find(sXfrd) != std::string::npos) // transferred
color = FL_BLUE;
else if (s.find(sRtry) != std::string::npos) // retries
color = FL_RED;
else if (nom == "")
color = FL_DARK_RED;
else if (nom == "")
color = FL_DARK_GREEN;
char clr[12];
snprintf( clr, sizeof(clr),"@C%d@.", color);
txtout.insert(0, clr);
txtout.append("\n");
guard_lock protect(&protect_status);
str_status.append(txtout);
Fl::awake(print_status);
}
static std::string txecho_s;
static void txecho(void *)
{
std::string style;
blocksSent += txecho_s.length();
std::string text = noCR(txecho_s);
txecho_s.clear();
}
void TXecho(std::string s)
{
txecho_s = s;
Fl::awake(txecho);
}
static std::string rxurcall_s;
static void rxurcall(void *)
{
txtSENDTO->value(rxurcall_s.c_str());
rxurcall_s.clear();
}
void rxUrCall(std::string s)
{
rxurcall_s = s;
Fl::awake(rxurcall);
}
std::string flmsg_trx()
{
return xml_fldigi_trx();
}
float flmsg_xmt_time(std::string s)
{
float xfr_time = 0, overhead;
float rsid_time = 3.0;
if (s.empty()) return rsid_time;
xfr_time = seconds_from_c_string(cbo_modes->value(), s.c_str(), s.size(), &overhead);
xfr_time += overhead;
xfr_time += rsid_time;
return xfr_time;
}
void init_flmsg_arq()
{
// the following sequence of assigning callback functions is mandatory
// for the arq class to function
flmsg_arq.setRetries(progStatus.retries);
flmsg_arq.setExponent(progStatus.exponent);
flmsg_arq.setSendFunc (client_transmit);
flmsg_arq.setGetCFunc (client_receive);
flmsg_arq.setDisconnected(restart);
flmsg_arq.setrxUrCall (rxUrCall);
flmsg_arq.setOK_to_transmit (fldigi_OK_to_transmit);
flmsg_arq.setPrintRX (payloadText);
flmsg_arq.setPrintSTATUS (STATUSprint);
flmsg_arq.setPrintLOG (arqlog);
flmsg_arq.setQualityValue(showQuality);
flmsg_arq.setTRX (flmsg_trx);
flmsg_arq.setTransmitTime (flmsg_xmt_time);
flmsg_arq.myCall(progStatus.my_call);
flmsg_arq.start_arq();
Fl::add_timeout(0.1, mainloop);
}
flmsg-4.0.23/src/custom/ 0000775 0001750 0001750 00000000000 14474644702 012030 5 0000000 0000000 flmsg-4.0.23/src/custom/custom_templates.cxx 0000644 0001750 0001750 00000002321 14463050237 016050 0000000 0000000 // ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include "templates.h"
const char custom_html_template[] =
"\
\
:TITLE:\
:mg:\
";
const char custom_txt_template[] =
":mg:";
flmsg-4.0.23/src/custom/custom_tab.cxx 0000664 0001750 0001750 00000005522 14463050237 014630 0000000 0000000 // ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include
#include "gettext.h"
#include "status.h"
#include "util.h"
#include "threads.h"
#include "flmsg_dialog.h"
#include "flmsg.h"
Fl_Group *tab_custom = (Fl_Group *)0;
FTextView *txt_custom_msg = (FTextView *)0;
Fl_Button *btn_custom_edit = (Fl_Button *)0;
Fl_Button *btn_custom_view = (Fl_Button *)0;
static void cb_btn_custom_edit(Fl_Button*, void*) {
if (custom_select < 0) return;
handle_type = HANDLE_EDIT;
std::string url = "http://127.0.0.1:";
url.append(sz_srvr_portnbr);
open_url(url.c_str());
}
static void cb_btn_custom_view(Fl_Button*, void*) {
if (custom_select < 0) return;
handle_type = HANDLE_VIEW;
std::string url = "http://127.0.0.1:";
url.append(sz_srvr_portnbr);
open_url(url.c_str());
}
static void custom_changed(FTextEdit *, void *)
{
estimate();
}
static void do_read_cb(const char *fn) {
custom_set_fname(fn);
}
void create_custom_tab()
{
int width = 570;
tab_custom = new Fl_Group(0, tab_top, 570, 380);
tab_custom->align(FL_ALIGN_TOP);
btn_custom_edit = new Fl_Button(width/2 - 120, tab_top + 5, 100, 24, _("Edit Form"));
btn_custom_edit->tooltip(_(""));
btn_custom_edit->callback((Fl_Callback*)cb_btn_custom_edit);
btn_custom_view = new Fl_Button(width/2 + 20, tab_top + 5, 100, 24, _("View Form"));
btn_custom_view->tooltip(_(""));
btn_custom_view->callback((Fl_Callback*)cb_btn_custom_view);
txt_custom_msg = new FTextView(2, tab_top + 24 + 10, 566, 430 - (tab_top + 24 + 10 + 2));
txt_custom_msg->box(FL_DOWN_FRAME);
txt_custom_msg->color((Fl_Color)FL_BACKGROUND2_COLOR);
txt_custom_msg->selection_color((Fl_Color)FL_SELECTION_COLOR);
txt_custom_msg->labeltype(FL_NORMAL_LABEL);
txt_custom_msg->labelfont(0);
txt_custom_msg->labelsize(14);
txt_custom_msg->labelcolor((Fl_Color)FL_FOREGROUND_COLOR);
txt_custom_msg->align(FL_ALIGN_TOP_LEFT);
txt_custom_msg->set_read_cb(do_read_cb);
txt_custom_msg->callback((Fl_Callback*)custom_changed);
txt_custom_msg->when(FL_WHEN_CHANGED);
tab_custom->end();
tab_custom->hide();
}
flmsg-4.0.23/src/custom/custom.cxx 0000664 0001750 0001750 00000110107 14463050237 013776 0000000 0000000 // ----------------------------------------------------------------------------
// Copyright (C) 2014
// David Freese, W1HKJ
//
// This file is part of flmsg
//
// flrig is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// flrig is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
// ----------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "mongoose.h"
#include "config.h"
#include "flmsg.h"
#include "templates.h"
#include "debug.h"
#include "util.h"
#include "gettext.h"
#include "flmsg_dialog.h"
#include "flmsg_config.h"
#include "flinput2.h"
#include "date.h"
#include "calendar.h"
#include "icons.h"
#include "fileselect.h"
#include "wrap.h"
#include "status.h"
#include "parse_xml.h"
#include "icons.h"
#include "threads.h"
#include "ext_string.h"
#ifdef WIN32
# include "flmsgrc.h"
# include "compat.h"
# define dirent fl_dirent_no_thanks
#endif
#include
#include "dirent-check.h"
#include
#include
#include
using namespace std;
extern int custom_select;
extern struct mg_server *server;
static string action_str = "\n name_values;
string html_form;
string edit_txt;
void escape(string &s)
{
size_t p;
p = 0;
while ((p = s.find("\r", p)) != string::npos)
s.erase(p,1);
p = 0;
while ((p = s.find("\n", p)) != string::npos) {
s.replace(p, 1, "\\n");
p += 2;
}
p = 0;
while ((p = s.find("\"", p)) != string::npos) {
if (p == 0 || s[p-1] != '\\') {
s.replace(p, 1, "\\\"");
p += 2;
} else p++;
}
}
void unescape(string &s)
{
size_t p;
p = 0;
while ((p = s.find("\\n", p)) != string::npos) {
s.replace(p,2,"\n");
p++;
}
p = 0;
while ((p = s.find("\\\"", p)) != string::npos) {
s.replace(p,2,"\"");
p++;
}
}
int convert_case(string &s)
{
std::string s1, s3;
extstring s2;//s1;
s2.assign(s);
size_t p1 = s2.ufind("", ptype);
pname = html_form.find(name_str, pstart);
if (pname == string::npos || pname > pend) {
ptype = html_form.find(input_types[i].txt, ptype + 1);
continue;
}
pname += name_str.length();
p1 = html_form.find("\"", pname);
field_name = html_form.substr(pname, p1 - pname);
switch (input_types[i].id) {
case T_TEXT: case T_PASSWORD: case T_NUMBER:
case T_DATE: case T_DTIME: case T_DTIME_LOCAL:
case T_TIME: case T_WEEK: case T_MONTH: case T_TEL: case T_EMAIL:
pvalue = html_form.find(value_str, pstart);
if (pvalue == string::npos || pvalue > pend) break;
pvalue += value_str.length();
p2 = html_form.find("\"", pvalue);
val = html_form.substr(pvalue, p2 - pvalue);
p3 = val.find(""");
while (p3 != string::npos)
val.replace(p3, 6, "\"");
escape(val);
field_value = val;
break;
case T_RADIO:
pvalue = html_form.find(value_str, pstart);
if (pvalue == string::npos || pvalue > pend) break;
pvalue += value_str.length();
p1 = html_form.find("\"", pvalue);
if (p1 < pend) {
field_name.append(".")
.append(html_form.substr(pvalue, p1 - pvalue));
field_value.clear();
p2 = html_form.find(checkedeq, pstart);
if (p2 < pend) {
field_value = "Y";//checked;
html_form.erase(p2 - 1, checkedeq.length() + 1);
pend = html_form.find(">", pstart);
} else {
p2 = html_form.find(checked, pstart);
if (p2 < pend) {
field_value = "Y";//checked;
html_form.erase(p2 - 1, checked.length() + 1);
pend = html_form.find(">", pstart);
}
}
}
break;
case T_CHECKBOX:
pvalue = html_form.find(value_str, pstart);
if (pvalue != string::npos && pvalue < pend) {
pvalue += value_str.length();
p1 = html_form.find("\"", pvalue);
if (p1 < pend) {
field_name.append(".")
.append(html_form.substr(pvalue, p1 - pvalue));
}
}
field_value.clear();
p2 = html_form.find(checkedeq, pstart);
if (p2 < pend) {
field_value = "Y";//"ON";
html_form.erase(p2 - 1, checkedeq.length() + 1);
pend = html_form.find(">", pstart);
} else {
p2 = html_form.find(checked, pstart);
if (p2 < pend) {
field_value = "Y";//"ON";
html_form.erase(p2 - 1, checked.length() + 1);
pend = html_form.find(">", pstart);
} else {
p2 = html_form.find(" ON", pstart);
if (p2 < pend) {
field_value = "Y";//"ON";
html_form.erase(p2, 3);
pend = html_form.find(">", pstart);
}
}
}
break;
case T_AREA: //extract
pvalue = pend + 1;
p1 = html_form.find(textend_str, pvalue);
if (p1 == string::npos) break;
if (p1 > pvalue)
val = html_form.substr(pvalue, p1 - pvalue);
else
val.clear();
html_form.erase(pvalue, val.length());
escape(val);
field_value.assign(val);
break;
case T_SELECT:
p3 = html_form.find(end_sel_str, pstart);
if (p3 == string::npos) break;
p2 = html_form.find(selected, pstart);
if (p2 != string::npos && p2 < p3) {
pvalue = html_form.rfind(value_str, p2);
if (pvalue != string::npos) {
pvalue += value_str.length();
p1 = html_form.find("\"", pvalue);
if (p1 < p2)
field_value = html_form.substr(pvalue, p1 - pvalue);
}
}
break;
default:
break;
}
edit_txt.append(field_name).append(",");
edit_txt.append(field_value).append("\n");
name_values.push_back(NAME_VALUE(input_types[i].id, field_name, field_value));
ptype = html_form.find(input_types[i].txt, ptype+1);
}
}
}
void refresh_txt_custom_msg(void *)
{
txt_custom_msg->clear();
txt_custom_msg->add(edit_txt.c_str());
}
// called by web server thread
void get_html_vars(struct mg_connection *conn)
{
size_t p;
if (custom_select < 0) return;
edit_txt.assign("CUSTOM_FORM,")
.append(custom_pairs[custom_select].file_name)
.append("\n");
string field, line, val;
for (size_t n = 0; n < name_values.size(); n++)
name_values[n].value.clear();
for (size_t n = 0; n < name_values.size(); n++) {
field = name_values[n].name;
if (name_values[n].id == T_CHECKBOX ||
name_values[n].id == T_RADIO) {
if ((p = field.find(".")) != string::npos)
field.erase(p);
}
int fld_len = mg_get_var_len(conn, field.c_str());
char buff[fld_len + 1];
memset(buff, 0, sizeof(buff));
mg_get_var(conn, field.c_str(), buff, sizeof(buff));
switch (name_values[n].id) {
case T_RADIO :
p = name_values[n].name.find(".");
if (name_values[n].name.substr(p+1) == buff)
name_values[n].value = "Y";//checked;
line.assign(name_values[n].name)
.append(",")
.append(name_values[n].value);
break;
case T_CHECKBOX :
if (strstr(buff, "on") == buff || strstr(buff, "ON") == buff)
name_values[n].value = "Y";//"ON";
line.assign(name_values[n].name)
.append(",")
.append(name_values[n].value);
break;
case T_AREA://get html vars
val = buff;
escape(val);
name_values[n].value = val;
line.assign(name_values[n].name).append(",").append(val);
break;
// T_TEXT, T_PASSWORD, T_SELECT, T_DATE, T_DATETIME ...
default :
name_values[n].value = buff;
line.assign(name_values[n].name)
.append(",")
.append(name_values[n].value);
}
edit_txt.append(line).append("\n");
}
Fl::awake(refresh_txt_custom_msg);
}
// modify the html form with the value strings
void assign_values(string &html)
{
string nm, val, s1, s2, temp;
size_t p, p0, p1, p2, p3, pbeg, pend, pval, pnm;
for (size_t n = 0; n < name_values.size(); n++) {
switch (name_values[n].id) {
case T_TEXT : case T_PASSWORD : case T_NUMBER :
case T_DATE : case T_DTIME : case T_DTIME_LOCAL :
case T_TIME : case T_WEEK : case T_MONTH : case T_TEL : case T_EMAIL:
nm.assign("NAME=\"").append(name_values[n].name).append("\"");
pnm = html.find(nm);
if (pnm != string::npos) {
pnm += nm.length();
p1 = html.find(value_str, pnm);
p2 = html.find(">", pnm);
val = name_values[n].value;
unescape(val);
p3 = val.find("\"");
while (p3 != string::npos) {
val.replace(p3,1, """);
p3 = val.find("\"");
}
if (p1 < p2) {
p1 += value_str.length();
p2 = html.find("\"", p1);
html.replace(p1, p2 - p1, val);
} else {
temp.assign(" VALUE=\"").append(val).append("\"");
html.insert(p2, temp);
}
}
break;
case T_RADIO :
temp = name_values[n].name;
p = temp.find(".");
s1.assign(temp.substr(0, p));
s2.assign(temp.substr(p+1));
nm.assign(name_str).append(s1).append("\"");
val.assign(value_str).append(s2).append("\"");
pnm = html.find(nm);
while (pnm != string::npos) {
pbeg = html.rfind("<", pnm); // beginning of tag specifier
pend = html.find(">", pbeg); // end of tag specifier
pval = html.find(val, pbeg);
if (pval == string::npos || pval > pend) {
pnm = html.find(nm, pend);
continue;
}
// found name and value pair
if (name_values[n].value == checked ||
name_values[n].value == "Y")
html.insert(pend, string(" ").append(checked));
pend = html.find(">", pbeg);
pnm = html.find(nm, pend);
}
break;
case T_CHECKBOX :
nm.assign("NAME=\"").append(name_values[n].name).append("\"");
pnm = html.find(nm);
if (pnm != string::npos) {
pbeg = html.rfind("<", pnm);
pend = html.find(">", pbeg);
if (name_values[n].value == "ON" ||
name_values[n].value == "Y") {
html.insert(pend, string(" ").append(checked));
pend = html.find(">", pbeg);
}
}
break;
case T_AREA : //assign values
nm.assign("NAME=\"").append(name_values[n].name).append("\"");
pnm = html.find(nm);
if (pnm != string::npos) {
p1 = html.find(textend_str, pnm);
if (p1 == string::npos)
break;
p0 = html.rfind(">", p1) + 1;
val = name_values[n].value;
unescape(val);
if (p0 < p1) {
html.replace(p0, p1 - p0, val);
} else {
html.insert(p1, val);
}
}
break;
case T_SELECT :
nm.assign("NAME=\"").append(name_values[n].name).append("\"");
pnm = html.find(nm);
if (pnm != string::npos) {
p2 = html.find("", p1);
if (html.substr(p0, p1 - p0) == name_values[n].value) {
html.replace(p1+1, p3 - p1 - 1, " SELECTED");
} else
html.replace(p1+1, p3 - p1 - 1, "");
}
p0 = html.find(value_str, p0);
}
}
break;
default :
break;
}
}
}
void custom_editor(struct mg_connection *conn)
{
string html_edit = html_form;
size_t p = html_edit.find("