kopia lustrzana https://github.com/jamescoxon/dl-fldigi
2301 wiersze
52 KiB
C++
2301 wiersze
52 KiB
C++
// ----------------------------------------------------------------------------
|
|
// macros.cxx
|
|
//
|
|
// Copyright (C) 2007-2010
|
|
// Dave Freese, W1HKJ
|
|
// Copyright (C) 2008-2010
|
|
// Stelios Bounanos, M0GLD
|
|
// Copyright (C) 2009
|
|
// Chris Sylvain, KB3CS
|
|
//
|
|
// This file is part of fldigi.
|
|
//
|
|
// Fldigi 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.
|
|
//
|
|
// Fldigi 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 fldigi. If not, see <http://www.gnu.org/licenses/>.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include <config.h>
|
|
|
|
#include "macros.h"
|
|
|
|
#include "gettext.h"
|
|
#include "main.h"
|
|
|
|
#include "fl_digi.h"
|
|
#include "configuration.h"
|
|
#include "confdialog.h"
|
|
#include "logger.h"
|
|
#include "newinstall.h"
|
|
#include "globals.h"
|
|
#include "debug.h"
|
|
#include "status.h"
|
|
#include "trx.h"
|
|
#include "modem.h"
|
|
#include "qrunner.h"
|
|
#include "waterfall.h"
|
|
#include "rigsupport.h"
|
|
#include "network.h"
|
|
#include "logsupport.h"
|
|
#include "icons.h"
|
|
|
|
#include <FL/Fl.H>
|
|
#include <FL/filename.H>
|
|
#include "fileselect.h"
|
|
|
|
#include <ctime>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <unistd.h>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <queue>
|
|
|
|
#ifdef __WIN32__
|
|
#include "speak.h"
|
|
#endif
|
|
|
|
//using namespace std;
|
|
|
|
struct CMDS { std::string cmd; void (*fp)(std::string); };
|
|
static queue<CMDS> cmds;
|
|
|
|
// following used for debugging and development
|
|
void pushcmd(CMDS cmd)
|
|
{
|
|
LOG_INFO("%s, # = %d", cmd.cmd.c_str(), (int)cmds.size());
|
|
cmds.push(cmd);
|
|
}
|
|
//#define pushcmd(a) cmds.push((a))
|
|
|
|
// these variables are referenced outside of this file
|
|
MACROTEXT macros;
|
|
CONTESTCNTR contest_count;
|
|
|
|
std::string qso_time = "";
|
|
std::string qso_exchange = "";
|
|
std::string exec_date = "";
|
|
std::string exec_time = "";
|
|
std::string exec_string = "";
|
|
std::string info1msg = "";
|
|
std::string info2msg = "";
|
|
std::string text2repeat = "";
|
|
|
|
size_t repeatchar = 0;
|
|
|
|
bool macro_idle_on = false;
|
|
|
|
static float idleTime = 0;
|
|
static bool TransmitON = false;
|
|
static bool ToggleTXRX = false;
|
|
static int mNbr;
|
|
|
|
static std::string text2send = "";
|
|
|
|
static size_t xbeg = 0, xend = 0;
|
|
|
|
static bool save_xchg;
|
|
static bool expand;
|
|
static bool GET = false;
|
|
static bool timed_exec = false;
|
|
static bool within_exec = false;
|
|
|
|
static const char cutnumbers[] = "T12345678N";
|
|
static std::string cutstr;
|
|
|
|
static std::string cut_string(const char *s)
|
|
{
|
|
cutstr = s;
|
|
if (!progdefaults.cutnbrs || active_modem != cw_modem)
|
|
return cutstr;
|
|
|
|
for (size_t i = 0; i < cutstr.length(); i++)
|
|
if (cutstr[i] >= '0' && cutstr[i] <= '9')
|
|
cutstr[i] = cutnumbers[cutstr[i] - '0'];
|
|
return cutstr;
|
|
|
|
}
|
|
|
|
static size_t mystrftime( char *s, size_t max, const char *fmt, const struct tm *tm) {
|
|
return strftime(s, max, fmt, tm);
|
|
}
|
|
|
|
static void pFILE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
std::string fname = s.substr(i+6, endbracket - i - 6);
|
|
if (fname.length() > 0 && !within_exec) {
|
|
FILE *toadd = fopen(fname.c_str(), "r");
|
|
if (toadd) {
|
|
std::string buffer;
|
|
char c = getc(toadd);
|
|
while (c && !feof(toadd)) {
|
|
if (c != '\r') buffer += c; // damn MSDOS txt files
|
|
c = getc(toadd);
|
|
}
|
|
s.replace(i, endbracket - i + 1, buffer);
|
|
fclose(toadd);
|
|
} else {
|
|
LOG_WARN("%s not found", fname.c_str());
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
} else
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pTIMER(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
int number;
|
|
std::string sTime = s.substr(i+7, endbracket - i - 7);
|
|
if (sTime.length() > 0 && !within_exec) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
progStatus.timer = number;
|
|
progStatus.timerMacro = mNbr;
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pREPEAT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
progStatus.repeatMacro = mNbr;
|
|
s.replace(i, endbracket - i + 1, "");
|
|
text2repeat = s;
|
|
repeatchar = 0;
|
|
s.insert(i, "[REPEAT]");
|
|
}
|
|
|
|
static void pWPM(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int number;
|
|
std::string sTime = s.substr(i+5, endbracket - i - 5);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
if (number < 5) number = 5;
|
|
if (number > 200) number = 200;
|
|
progdefaults.CWspeed = number;
|
|
sldrCWxmtWPM->value(number);
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pRISETIME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
float number;
|
|
std::string sVal = s.substr(i+6, endbracket - i - 6);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < 0) number = 0;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWrisetime = number;
|
|
cntCWrisetime->value(number);
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pPRE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
float number;
|
|
std::string sVal = s.substr(i+5, endbracket - i - 5);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < 0) number = 0;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWpre = number;
|
|
cntPreTiming->value(number);
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pPOST(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
float number;
|
|
std::string sVal = s.substr(i+6, endbracket - i - 6);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < -20) number = -20;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWpost = number;
|
|
cntPostTiming->value(number);
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void setwpm(int d)
|
|
{
|
|
sldrCWxmtWPM->value(d);
|
|
cntCW_WPM->value(d);
|
|
}
|
|
|
|
static void doWPM(std::string s)
|
|
{
|
|
int number;
|
|
std::string sTime = s.substr(6);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
if (number < 5) number = 5;
|
|
if (number > 200) number = 200;
|
|
progdefaults.CWspeed = number;
|
|
REQ(setwpm, number);
|
|
}
|
|
}
|
|
|
|
static void pQueWPM(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doWPM };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void setRISETIME(int d)
|
|
{
|
|
cntCWrisetime->value(d);
|
|
}
|
|
|
|
static void doRISETIME(std::string s)
|
|
{
|
|
float number;
|
|
std::string sVal = s.substr(7, s.length() - 8);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < 0) number = 0;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWrisetime = number;
|
|
REQ(setRISETIME, number);
|
|
}
|
|
}
|
|
|
|
static void pQueRISETIME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRISETIME };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void setPRE(int d)
|
|
{
|
|
cntPreTiming->value(d);
|
|
}
|
|
|
|
static void doPRE(std::string s)
|
|
{
|
|
float number;
|
|
std::string sVal = s.substr(6, s.length() - 7);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < 0) number = 0;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWpre = number;
|
|
REQ(setPRE, number);
|
|
}
|
|
}
|
|
|
|
static void pQuePRE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPRE };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void setPOST(int d)
|
|
{
|
|
cntPostTiming->value(d);
|
|
}
|
|
|
|
static void doPOST(std::string s)
|
|
{
|
|
float number;
|
|
std::string sVal = s.substr(7, s.length() - 8);
|
|
if (sVal.length() > 0) {
|
|
sscanf(sVal.c_str(), "%f", &number);
|
|
if (number < -20) number = -20;
|
|
if (number > 20) number = 20;
|
|
progdefaults.CWpost = number;
|
|
REQ(setPOST, number);
|
|
}
|
|
}
|
|
|
|
static void pQuePOST(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPOST };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pIDLE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
float number;
|
|
std::string sTime = s.substr(i+6, endbracket - i - 6);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%f", &number);
|
|
macro_idle_on = true;
|
|
idleTime = number;
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void doneIDLE(void *)
|
|
{
|
|
Qidle_time = 0;
|
|
}
|
|
|
|
static void doIDLE(std::string s)
|
|
{
|
|
float number;
|
|
std::string sTime = s.substr(7, s.length() - 8);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%f", &number);
|
|
Qidle_time = 1;
|
|
Fl::add_timeout(number, doneIDLE);
|
|
} else {
|
|
Qidle_time = 0;
|
|
}
|
|
}
|
|
|
|
static void pQueIDLE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doIDLE };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static bool useTune = false;
|
|
static int tuneTime = 0;
|
|
|
|
static void pTUNE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int number;
|
|
std::string sTime = s.substr(i+6, endbracket - i - 6);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
useTune = true;
|
|
tuneTime = number;
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static bool useWait = false;
|
|
static int waitTime = 0;
|
|
|
|
static void pWAIT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int number;
|
|
std::string sTime = s.substr(i+6, endbracket - i - 6);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
useWait = true;
|
|
waitTime = number;
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void doneWAIT(void *)
|
|
{
|
|
Qwait_time = 0;
|
|
start_tx();
|
|
}
|
|
|
|
static void doWAIT(std::string s)
|
|
{
|
|
int number;
|
|
std::string sTime = s.substr(7, s.length() - 8);
|
|
if (sTime.length() > 0) {
|
|
sscanf(sTime.c_str(), "%d", &number);
|
|
Qwait_time = number;
|
|
Fl::add_timeout (number * 1.0, doneWAIT);
|
|
} else
|
|
Qwait_time = 0;
|
|
que_ok = true;
|
|
}
|
|
|
|
static void pQueWAIT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doWAIT };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
|
|
static void pINFO1(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 7, info1msg );
|
|
}
|
|
|
|
static void pINFO2(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 7, info2msg );
|
|
}
|
|
|
|
static void pCLRRX(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 7, "" );
|
|
ReceiveText->clear();
|
|
}
|
|
|
|
static void pCLRTX(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 7, "" );
|
|
queue_reset();
|
|
TransmitText->clear();
|
|
}
|
|
|
|
static void pCALL(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 6, inpCall->value() );
|
|
}
|
|
|
|
static void pGET(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.erase( i, 9 );
|
|
GET = true;
|
|
}
|
|
|
|
static void pFREQ(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 6, inpFreq->value() );
|
|
}
|
|
|
|
static void pLOC(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 5, inpLoc->value() );
|
|
}
|
|
|
|
static void pMODE(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 6, active_modem->get_mode_name());
|
|
}
|
|
|
|
static void pNAME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 6, inpName->value() );
|
|
}
|
|
|
|
static void pQTH(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i,5, inpQth->value() );
|
|
}
|
|
|
|
static void pQSOTIME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
qso_time = inpTimeOff->value();
|
|
s.replace( i, 9, qso_time.c_str() );
|
|
}
|
|
|
|
static void pRST(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 5, cut_string(inpRstOut->value()));
|
|
}
|
|
|
|
static void pMYCALL(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 8, inpMyCallsign->value() );
|
|
}
|
|
|
|
static void pMYLOC(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 7, inpMyLocator->value() );
|
|
}
|
|
|
|
static void pMYNAME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 8, inpMyName->value() );
|
|
}
|
|
|
|
static void pMYQTH(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 7, inpMyQth->value() );
|
|
}
|
|
|
|
static void pMYRST(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 7, inpRstIn->value() );
|
|
}
|
|
|
|
static void pLDT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
localtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%x %H:%M %Z", &sTime);
|
|
s.replace( i, 5, szDt);
|
|
}
|
|
|
|
static void pILDT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
localtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%Y-%m-%d %H:%M%z", &sTime);
|
|
s.replace( i, 6, szDt);
|
|
}
|
|
|
|
static void pZDT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
gmtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%x %H:%MZ", &sTime);
|
|
s.replace( i, 5, szDt);
|
|
}
|
|
|
|
static void pIZDT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
gmtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%Y-%m-%d %H:%MZ", &sTime);
|
|
s.replace( i, 6, szDt);
|
|
}
|
|
|
|
static void pLT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
localtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%H%M", &sTime);
|
|
s.replace( i, 4, szDt);
|
|
}
|
|
|
|
static void pZT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
gmtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%H%MZ", &sTime);
|
|
s.replace( i, 4, szDt);
|
|
}
|
|
|
|
static void pLD(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
localtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%Y-%m-%d", &sTime);
|
|
s.replace( i, 4, szDt);
|
|
}
|
|
|
|
static void pZD(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
char szDt[80];
|
|
time_t tmptr;
|
|
tm sTime;
|
|
time (&tmptr);
|
|
gmtime_r(&tmptr, &sTime);
|
|
mystrftime(szDt, 79, "%Y-%m-%d", &sTime);
|
|
s.replace( i, 4, szDt);
|
|
}
|
|
|
|
static void p_ID(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
progdefaults.macroid = true;
|
|
s.replace( i, 4, "");
|
|
}
|
|
|
|
static void pTEXT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
progdefaults.macrotextid = true;
|
|
s.replace( i, 6, "");
|
|
}
|
|
|
|
static void pCWID(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
progdefaults.macroCWid = true;
|
|
s.replace( i, 6, "");
|
|
}
|
|
|
|
static void doDTMF(std::string s)
|
|
{
|
|
progdefaults.DTMFstr = s.substr(6, s.length() - 7);
|
|
}
|
|
|
|
static void pDTMF(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
CMDS cmd = {s.substr(i, endbracket - i + 1), doDTMF};
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pRX(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace (i, 4, "^r");
|
|
}
|
|
|
|
static void pTX(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.erase(i, 4);
|
|
TransmitON = true;
|
|
}
|
|
|
|
static void pTXRX(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.erase(i, 7);
|
|
ToggleTXRX = true;
|
|
}
|
|
|
|
|
|
static void pVER(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
std::string progname;
|
|
progname = "Fldigi ";
|
|
progname.append(PACKAGE_VERSION);
|
|
s.replace( i, 5, progname );
|
|
}
|
|
|
|
static void pCNTR(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int contestval;
|
|
contestval = contest_count.count;
|
|
if (contestval) {
|
|
contest_count.Format(progdefaults.ContestDigits, progdefaults.UseLeadingZeros);
|
|
snprintf(contest_count.szCount, sizeof(contest_count.szCount), contest_count.fmt.c_str(), contestval);
|
|
s.replace (i, 6, cut_string(contest_count.szCount));
|
|
} else
|
|
s.replace (i, 6, "");
|
|
}
|
|
|
|
static void pDECR(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int contestval;
|
|
contest_count.count--;
|
|
if (contest_count.count < 0) contest_count.count = 0;
|
|
contestval = contest_count.count;
|
|
s.replace (i, 6, "");
|
|
updateOutSerNo();
|
|
}
|
|
|
|
static void pINCR(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int contestval;
|
|
contest_count.count++;
|
|
contestval = contest_count.count;
|
|
s.replace (i, 6, "");
|
|
updateOutSerNo();
|
|
}
|
|
|
|
static void pXIN(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 5, inpXchgIn->value() );
|
|
}
|
|
|
|
static void pXOUT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace( i, 6, cut_string(progdefaults.myXchg.c_str()));
|
|
}
|
|
|
|
static void pXBEG(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 6, "");
|
|
xbeg = i;
|
|
}
|
|
|
|
static void pXEND(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 6, "");
|
|
xend = i;
|
|
}
|
|
|
|
static void pSAVEXCHG(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
save_xchg = true;
|
|
s.replace( i, 10, "");
|
|
}
|
|
|
|
static void pLOG(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
qsoSave_cb(0, 0);
|
|
s.replace(i, 5, "");
|
|
}
|
|
|
|
static void pLNW(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace(i, 5, "^L");
|
|
}
|
|
|
|
static void pCLRLOG(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace(i, 10, "^C");
|
|
}
|
|
|
|
static void pMODEM_compSKED(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
size_t j, k,
|
|
len = s.length();
|
|
std::string name;
|
|
|
|
if ((j = s.find('>', i)) == std::string::npos)
|
|
return;
|
|
while (++j < len)
|
|
if (!isspace(s[j])) break;
|
|
k = j;
|
|
while (++k < len)
|
|
if (isspace(s[k]) || s[k] == '<') break;
|
|
name = s.substr(j, k - j);
|
|
for (int m = 0; m < NUM_MODES; m++) {
|
|
if (name == mode_info[m].sname) {
|
|
if (active_modem->get_mode() != mode_info[m].mode)
|
|
init_modem(mode_info[m].mode);
|
|
break;
|
|
}
|
|
}
|
|
s.erase(i, k-i);
|
|
}
|
|
|
|
#include <float.h>
|
|
#include "re.h"
|
|
|
|
static void doMODEM(std::string s)
|
|
{
|
|
static fre_t re("<!MODEM:([[:alnum:]-]+)((:[[:digit:].+-]*)*)>", REG_EXTENDED);
|
|
std::string tomatch = s;
|
|
|
|
if (!re.match(tomatch.c_str())) {
|
|
que_ok = true;
|
|
return;
|
|
}
|
|
|
|
const std::vector<regmatch_t>& o = re.suboff();
|
|
std::string name = tomatch.substr(o[1].rm_so, o[1].rm_eo - o[1].rm_so);
|
|
trx_mode m;
|
|
for (m = 0; m < NUM_MODES; m++)
|
|
if (name == mode_info[m].sname)
|
|
break;
|
|
// do we have arguments and a valid modem?
|
|
if (o.size() == 2 || m == NUM_MODES) {
|
|
que_ok = true;
|
|
return;
|
|
}
|
|
|
|
// parse arguments
|
|
vector<double> args;
|
|
args.reserve(8);
|
|
char* end;
|
|
double d;
|
|
for (const char* p = s.c_str() + o[2].rm_so + 1; *p; p++) {
|
|
errno = 0;
|
|
d = strtod(p, &end);
|
|
if (!errno && p != end) {
|
|
args.push_back(d);
|
|
p = end;
|
|
}
|
|
else // push an invalid value
|
|
args.push_back(DBL_MIN);
|
|
}
|
|
|
|
try {
|
|
switch (m) {
|
|
case MODE_RTTY: // carrier shift, baud rate, bits per char
|
|
if (args.at(0) != DBL_MIN)
|
|
set_rtty_shift((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_rtty_baud((float)args[1]);
|
|
if (args.at(2) != DBL_MIN)
|
|
set_rtty_bits((int)args[2]);
|
|
if (args.at(3) != DBL_MIN)
|
|
set_rtty_bw((float)args[3]);
|
|
break;
|
|
case MODE_CONTESTIA: // bandwidth, tones
|
|
if (args.at(0) != DBL_MIN)
|
|
set_contestia_bw((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_contestia_tones((int)args[1]);
|
|
break;
|
|
case MODE_OLIVIA: // bandwidth, tones
|
|
if (args.at(0) != DBL_MIN)
|
|
set_olivia_bw((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_olivia_tones((int)args[1]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
catch (const exception& e) { }
|
|
|
|
if (active_modem->get_mode() != mode_info[m].mode)
|
|
init_modem_sync(mode_info[m].mode);
|
|
que_ok = true;
|
|
}
|
|
|
|
static void pQueMODEM(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doMODEM };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pMODEM(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
static fre_t re("<MODEM:([[:alnum:]-]+)((:[[:digit:].+-]*)*)>", REG_EXTENDED);
|
|
|
|
if (!re.match(s.c_str() + i)) {
|
|
size_t end = s.find('>', i);
|
|
if (end != std::string::npos)
|
|
s.erase(i, end - i);
|
|
return;
|
|
}
|
|
|
|
const std::vector<regmatch_t>& o = re.suboff();
|
|
std::string name = s.substr(o[1].rm_so, o[1].rm_eo - o[1].rm_so);
|
|
trx_mode m;
|
|
for (m = 0; m < NUM_MODES; m++)
|
|
if (name == mode_info[m].sname)
|
|
break;
|
|
// do we have arguments and a valid modem?
|
|
if (o.size() == 2 || m == NUM_MODES) {
|
|
if (m < NUM_MODES && active_modem->get_mode() != mode_info[m].mode)
|
|
init_modem(mode_info[m].mode);
|
|
s.erase(i, o[0].rm_eo - i);
|
|
return;
|
|
}
|
|
|
|
// parse arguments
|
|
vector<double> args;
|
|
args.reserve(8);
|
|
char* end;
|
|
double d;
|
|
for (const char* p = s.c_str() + o[2].rm_so + 1; *p; p++) {
|
|
errno = 0;
|
|
d = strtod(p, &end);
|
|
if (!errno && p != end) {
|
|
args.push_back(d);
|
|
p = end;
|
|
}
|
|
else // push an invalid value
|
|
args.push_back(DBL_MIN);
|
|
}
|
|
|
|
try {
|
|
switch (m) {
|
|
case MODE_RTTY: // carrier shift, baud rate, bits per char
|
|
if (args.at(0) != DBL_MIN)
|
|
set_rtty_shift((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_rtty_baud((float)args[1]);
|
|
if (args.at(2) != DBL_MIN)
|
|
set_rtty_bits((int)args[2]);
|
|
if (args.at(3) != DBL_MIN)
|
|
set_rtty_bw((float)args[3]);
|
|
break;
|
|
case MODE_CONTESTIA: // bandwidth, tones
|
|
if (args.at(0) != DBL_MIN)
|
|
set_contestia_bw((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_contestia_tones((int)args[1]);
|
|
break;
|
|
case MODE_OLIVIA: // bandwidth, tones
|
|
if (args.at(0) != DBL_MIN)
|
|
set_olivia_bw((int)args[0]);
|
|
if (args.at(1) != DBL_MIN)
|
|
set_olivia_tones((int)args[1]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
catch (const exception& e) { }
|
|
|
|
if (active_modem->get_mode() != mode_info[m].mode) {
|
|
init_modem(mode_info[m].mode);
|
|
int count = 100;
|
|
while ((active_modem->get_mode() != mode_info[m].mode) && --count)
|
|
MilliSleep(10);
|
|
}
|
|
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pAFC(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+5, endbracket - i - 5);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off|t [ON, OFF or Toggle]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
btnAFC->value(1);
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
btnAFC->value(0);
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
btnAFC->value(!btnAFC->value());
|
|
|
|
btnAFC->do_callback();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pREV(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+5, endbracket - i - 5);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off|t [ON, OFF or Toggle]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
wf->btnRev->value(1);
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
wf->btnRev->value(0);
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
wf->btnRev->value(!wf->btnRev->value());
|
|
|
|
wf->btnRev->do_callback();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pLOCK(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+6, endbracket - i - 6);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off|t [ON, OFF or Toggle]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
wf->xmtlock->value(1);
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
wf->xmtlock->value(0);
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
wf->xmtlock->value(!wf->xmtlock->value());
|
|
|
|
wf->xmtlock->damage();
|
|
wf->xmtlock->do_callback();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pTX_RSID(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+8, endbracket - i - 8);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off|t [ON, OFF or Toggle]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
btnTxRSID->value(1);
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
btnTxRSID->value(0);
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
btnTxRSID->value(!btnTxRSID->value());
|
|
|
|
btnTxRSID->do_callback();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pRX_RSID(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+8, endbracket - i - 8);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off|t [ON, OFF or Toggle]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
btnRSID->value(1);
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
btnRSID->value(0);
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
btnRSID->value(!btnRSID->value());
|
|
|
|
btnRSID->do_callback();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
#ifdef __WIN32__
|
|
static void pTALK(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i+6, endbracket - i - 6);
|
|
if (sVal.length() > 0) {
|
|
// sVal = on|off [ON, OFF]
|
|
if (sVal.compare(0,2,"on") == 0)
|
|
open_talker();
|
|
else if (sVal.compare(0,3,"off") == 0)
|
|
close_talker();
|
|
else if (sVal.compare(0,1,"t") == 0)
|
|
toggle_talker();
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
#endif
|
|
|
|
static void pSRCHUP(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 8, "");
|
|
active_modem->searchUp();
|
|
if (progdefaults.WaterfallClickInsert)
|
|
wf->insert_text(true);
|
|
}
|
|
|
|
static void pSRCHDN(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 8, "");
|
|
active_modem->searchDown();
|
|
if (progdefaults.WaterfallClickInsert)
|
|
wf->insert_text(true);
|
|
}
|
|
|
|
static void pGOHOME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 8, "");
|
|
if (active_modem == cw_modem)
|
|
active_modem->set_freq(progdefaults.CWsweetspot);
|
|
else if (active_modem == rtty_modem)
|
|
active_modem->set_freq(progdefaults.RTTYsweetspot);
|
|
else
|
|
active_modem->set_freq(progdefaults.PSKsweetspot);
|
|
}
|
|
|
|
static void doGOHOME(std::string s)
|
|
{
|
|
if (active_modem == cw_modem)
|
|
active_modem->set_freq(progdefaults.CWsweetspot);
|
|
else if (active_modem == rtty_modem)
|
|
active_modem->set_freq(progdefaults.RTTYsweetspot);
|
|
else
|
|
active_modem->set_freq(progdefaults.PSKsweetspot);
|
|
que_ok = true;
|
|
}
|
|
|
|
static void pQueGOHOME(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOHOME };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pGOFREQ(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int number;
|
|
std::string sGoFreq = s.substr(i+8, endbracket - i - 8);
|
|
if (sGoFreq.length() > 0) {
|
|
sscanf(sGoFreq.c_str(), "%d", &number);
|
|
if (number < progdefaults.LowFreqCutoff)
|
|
number = progdefaults.LowFreqCutoff;
|
|
if (number > progdefaults.HighFreqCutoff)
|
|
number = progdefaults.HighFreqCutoff;
|
|
active_modem->set_freq(number);
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void doGOFREQ(std::string s)
|
|
{
|
|
int number;
|
|
std::string sGoFreq = s.substr(9, s.length() - 10);
|
|
if (sGoFreq.length() > 0) {
|
|
sscanf(sGoFreq.c_str(), "%d", &number);
|
|
if (number < progdefaults.LowFreqCutoff)
|
|
number = progdefaults.LowFreqCutoff;
|
|
if (number > progdefaults.HighFreqCutoff)
|
|
number = progdefaults.HighFreqCutoff;
|
|
active_modem->set_freq(number);
|
|
}
|
|
que_ok = true;
|
|
}
|
|
|
|
static void pQueGOFREQ(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOFREQ };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pQSYTO(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 7, "");
|
|
do_qsy(true);
|
|
}
|
|
|
|
static void pQSYFM(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.replace( i, 7, "");
|
|
do_qsy(false);
|
|
}
|
|
|
|
static void pQSY(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
int rf = 0;
|
|
int audio = 0;
|
|
float rfd = 0;
|
|
std::string sGoFreq = s.substr(i+5, endbracket - i - 5);
|
|
// no frequency(s) specified
|
|
if (sGoFreq.length() == 0) {
|
|
s.replace(i, endbracket-i+1, "");
|
|
return;
|
|
}
|
|
// rf first value
|
|
sscanf(sGoFreq.c_str(), "%f", &rfd);
|
|
if (rfd > 0)
|
|
rf = (int)(1000*rfd);
|
|
size_t pos;
|
|
if ((pos = sGoFreq.find(":")) != std::string::npos) {
|
|
// af second value
|
|
sGoFreq.erase(0, pos+1);
|
|
if (sGoFreq.length())
|
|
sscanf(sGoFreq.c_str(), "%d", &audio);
|
|
if (audio < 0) audio = 0;
|
|
if (audio < progdefaults.LowFreqCutoff)
|
|
audio = progdefaults.LowFreqCutoff;
|
|
if (audio > progdefaults.HighFreqCutoff)
|
|
audio = progdefaults.HighFreqCutoff;
|
|
}
|
|
if (rf && rf != wf->rfcarrier())
|
|
qsy(rf, audio);
|
|
else
|
|
active_modem->set_freq(audio);
|
|
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void doQSY(std::string s)
|
|
{
|
|
int rf = 0;
|
|
int audio = 0;
|
|
float rfd = 0;
|
|
std::string sGoFreq;
|
|
sGoFreq = s.substr(6, s.length() - 7);
|
|
// no frequency(s) specified
|
|
if (sGoFreq.length() == 0) {
|
|
que_ok = true;
|
|
return;
|
|
}
|
|
// rf first value
|
|
sscanf(sGoFreq.c_str(), "%f", &rfd);
|
|
if (rfd > 0)
|
|
rf = (int)(1000*rfd);
|
|
size_t pos;
|
|
if ((pos = sGoFreq.find(":")) != std::string::npos) {
|
|
// af second value
|
|
sGoFreq.erase(0, pos+1);
|
|
if (sGoFreq.length())
|
|
sscanf(sGoFreq.c_str(), "%d", &audio);
|
|
if (audio < 0) audio = 0;
|
|
if (audio < progdefaults.LowFreqCutoff)
|
|
audio = progdefaults.LowFreqCutoff;
|
|
if (audio > progdefaults.HighFreqCutoff)
|
|
audio = progdefaults.HighFreqCutoff;
|
|
}
|
|
if (rf && rf != wf->rfcarrier())
|
|
qsy(rf, audio);
|
|
else
|
|
active_modem->set_freq(audio);
|
|
que_ok = true;
|
|
}
|
|
|
|
static void pQueQSY(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
struct CMDS cmd = { s.substr(i, endbracket - i + 1), doQSY };
|
|
pushcmd(cmd);
|
|
s.replace(i, endbracket - i + 1, "^!");
|
|
}
|
|
|
|
static void pRIGMODE(std::string& s, size_t& i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sMode = s.substr(i+9, endbracket - i - 9);
|
|
qso_opMODE->value(sMode.c_str());
|
|
cb_qso_opMODE();
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
static void pFILWID(std::string& s, size_t& i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sWidth = s.substr(i+8, endbracket - i - 8);
|
|
qso_opBW->value(sWidth.c_str());
|
|
cb_qso_opBW();
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
void set_macro_env(void)
|
|
{
|
|
enum {
|
|
#ifndef __WOE32__
|
|
pSKEDH, FLDIGI_RX_IPC_KEY, FLDIGI_TX_IPC_KEY,
|
|
#endif
|
|
FLDIGI_XMLRPC_ADDRESS, FLDIGI_XMLRPC_PORT,
|
|
FLDIGI_ARQ_ADDRESS, FLDIGI_ARQ_PORT,
|
|
|
|
FLDIGI_VERSION_ENVVAR, FLDIGI_PID, FLDIGI_CONFIG_DIR,
|
|
|
|
FLDIGI_MY_CALL, FLDIGI_MY_NAME, FLDIGI_MY_LOCATOR,
|
|
|
|
FLDIGI_MODEM, FLDIGI_MODEM_LONG_NAME, FLDIGI_DIAL_FREQUENCY,
|
|
FLDIGI_AUDIO_FREQUENCY, FLDIGI_FREQUENCY,
|
|
|
|
FLDIGI_LOG_FREQUENCY, FLDIGI_LOG_TIME_ON, FLDIGI_LOG_TIME_OFF, FLDIGI_LOG_CALL, FLDIGI_LOG_NAME,
|
|
FLDIGI_LOG_RST_IN, FLDIGI_LOG_RST_OUT, FLDIGI_LOG_QTH, FLDIGI_LOG_LOCATOR,
|
|
FLDIGI_LOG_NOTES, FLDIGI_AZ, ENV_SIZE
|
|
};
|
|
|
|
struct {
|
|
const char* var;
|
|
const char* val;
|
|
} env[] = {
|
|
#ifndef __WOE32__
|
|
{ "pSKEDH", "" },
|
|
{ "FLDIGI_RX_IPC_KEY", "" },
|
|
{ "FLDIGI_TX_IPC_KEY", "" },
|
|
#endif
|
|
{ "FLDIGI_XMLRPC_ADDRESS", progdefaults.xmlrpc_address.c_str() },
|
|
{ "FLDIGI_XMLRPC_PORT", progdefaults.xmlrpc_port.c_str() },
|
|
{ "FLDIGI_ARQ_ADDRESS", progdefaults.arq_address.c_str() },
|
|
{ "FLDIGI_ARQ_PORT", progdefaults.arq_port.c_str() },
|
|
|
|
{ "FLDIGI_VERSION", PACKAGE_VERSION },
|
|
{ "FLDIGI_PID", "" },
|
|
{ "FLDIGI_CONFIG_DIR", HomeDir.c_str() },
|
|
|
|
{ "FLDIGI_MY_CALL", progdefaults.myCall.c_str() },
|
|
{ "FLDIGI_MY_NAME", progdefaults.myName.c_str() },
|
|
{ "FLDIGI_MY_LOCATOR", progdefaults.myLocator.c_str() },
|
|
|
|
{ "FLDIGI_MODEM", mode_info[active_modem->get_mode()].sname },
|
|
{ "FLDIGI_MODEM_LONG_NAME", mode_info[active_modem->get_mode()].name },
|
|
{ "FLDIGI_DIAL_FREQUENCY", "" },
|
|
{ "FLDIGI_AUDIO_FREQUENCY", "" },
|
|
{ "FLDIGI_FREQUENCY", "" },
|
|
|
|
// logging frame
|
|
{ "FLDIGI_LOG_FREQUENCY", inpFreq->value() },
|
|
{ "FLDIGI_LOG_TIME_ON", inpTimeOn->value() },
|
|
{ "FLDIGI_LOG_TIME_OFF", inpTimeOff->value() },
|
|
{ "FLDIGI_LOG_CALL", inpCall->value() },
|
|
{ "FLDIGI_LOG_NAME", inpName->value() },
|
|
{ "FLDIGI_LOG_RST_IN", inpRstIn->value() },
|
|
{ "FLDIGI_LOG_RST_OUT", inpRstOut->value() },
|
|
{ "FLDIGI_LOG_QTH", inpQth->value() },
|
|
{ "FLDIGI_LOG_LOCATOR", inpLoc->value() },
|
|
{ "FLDIGI_LOG_NOTES", inpNotes->value() },
|
|
{ "FLDIGI_AZ", inpAZ->value() }
|
|
};
|
|
|
|
#ifndef __WOE32__
|
|
// pSKEDH
|
|
static std::string pSKEDh = ScriptsDir;
|
|
pSKEDh.erase(pSKEDh.length()-1,1);
|
|
const char* p;
|
|
if ((p = getenv("pSKEDH")))
|
|
pSKEDh.append(":").append(p);
|
|
env[pSKEDH].val = pSKEDh.c_str();
|
|
|
|
// IPC keys
|
|
char key[2][8];
|
|
snprintf(key[0], sizeof(key[0]), "%d", progdefaults.rx_msgid);
|
|
env[FLDIGI_RX_IPC_KEY].val = key[0];
|
|
snprintf(key[1], sizeof(key[1]), "%d", progdefaults.tx_msgid);
|
|
env[FLDIGI_TX_IPC_KEY].val = key[1];
|
|
#endif
|
|
|
|
// pid
|
|
char pid[6];
|
|
snprintf(pid, sizeof(pid), "%d", getpid());
|
|
env[FLDIGI_PID].val = pid;
|
|
|
|
// frequencies
|
|
char dial_freq[20];
|
|
snprintf(dial_freq, sizeof(dial_freq), "%lld", wf->rfcarrier());
|
|
env[FLDIGI_DIAL_FREQUENCY].val = dial_freq;
|
|
char audio_freq[6];
|
|
snprintf(audio_freq, sizeof(audio_freq), "%d", active_modem->get_freq());
|
|
env[FLDIGI_AUDIO_FREQUENCY].val = audio_freq;
|
|
char freq[20];
|
|
snprintf(freq, sizeof(freq), "%lld", wf->rfcarrier() + (wf->USB()
|
|
? active_modem->get_freq()
|
|
: -active_modem->get_freq()));
|
|
env[FLDIGI_FREQUENCY].val = freq;
|
|
|
|
// debugging vars
|
|
#if !defined(NDEBUG) && !defined(__WOE32__)
|
|
unsetenv("FLDIGI_NO_EXEC");
|
|
unsetenv("MALLOC_CHECK_");
|
|
unsetenv("MALLOC_PERTURB_");
|
|
#endif
|
|
|
|
for (size_t j = 0; j < ENV_SIZE; j++)
|
|
setenv(env[j].var, env[j].val, 1);
|
|
|
|
string path = getenv("PATH");
|
|
string mypath = ScriptsDir;
|
|
if (mypath[mypath.length()-1] == '/')
|
|
mypath.erase(mypath.length()-1, 1);
|
|
mypath.append(":");
|
|
path.insert(0,mypath);
|
|
setenv("PATH", path.c_str(), 1);
|
|
}
|
|
|
|
// this is only for the case where the user tries to nest <EXEC>...
|
|
// as in
|
|
// <EXEC> ... <EXEC> ... </EXEC></EXEC>
|
|
// which is not permitted
|
|
static void pEND_EXEC(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
|
|
#ifndef __MINGW32__
|
|
static void pEXEC(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
|
|
size_t start, end;
|
|
if ((start = s.find('>', i)) == std::string::npos ||
|
|
(end = s.rfind("</EXEC>")) == std::string::npos) {
|
|
i++;
|
|
return;
|
|
}
|
|
start++;
|
|
i++;
|
|
|
|
std::string execstr = s.substr(start, end-start);
|
|
within_exec = true;
|
|
MACROTEXT m;
|
|
execstr = m.expandMacro(execstr);
|
|
// execstr.insert(0,ScriptsDir);
|
|
within_exec = false;
|
|
|
|
int pfd[2];
|
|
if (pipe(pfd) == -1) {
|
|
LOG_PERROR("pipe");
|
|
return;
|
|
}
|
|
pid_t pid;
|
|
switch (pid = fork()) {
|
|
case -1:
|
|
LOG_PERROR("fork");
|
|
return;
|
|
case 0: // child
|
|
close(pfd[0]);
|
|
if (dup2(pfd[1], STDOUT_FILENO) != STDOUT_FILENO) {
|
|
LOG_PERROR("dup2");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
close(pfd[1]);
|
|
set_macro_env();
|
|
execl("/bin/sh", "sh", "-c", execstr.c_str(), (char *)NULL);
|
|
perror("execl");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
// parent
|
|
close(pfd[1]);
|
|
FILE* fp = fdopen(pfd[0], "r");
|
|
if (!fp) {
|
|
LOG_PERROR("fdopen");
|
|
close(pfd[0]);
|
|
return;
|
|
}
|
|
|
|
start = --i;
|
|
end = s.find('>', end) + 1;
|
|
s.erase(start, end-start);
|
|
char ln[BUFSIZ];
|
|
while (fgets(ln, sizeof(ln), fp)) {
|
|
end = strlen(ln);
|
|
s.insert(start, ln, end);
|
|
start += end;
|
|
}
|
|
// delete the trailing newline of what we read
|
|
if (start > i && s[start - 1] == '\n')
|
|
s.erase(start - 1, 1);
|
|
|
|
fclose(fp);
|
|
close(pfd[0]);
|
|
|
|
// what should we do with the shell-generated text?
|
|
// option 1: uncomment this line to skip & ignore it
|
|
// i = start;
|
|
// option 2: do nothing and allow it to be parsed for more macros
|
|
}
|
|
#else // !__MINGW32__
|
|
|
|
static void pEXEC(std::string& s, size_t& i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
size_t start, end;
|
|
if ((start = s.find('>', i)) == std::string::npos ||
|
|
(end = s.rfind("</EXEC>")) == std::string::npos) {
|
|
i++;
|
|
return;
|
|
}
|
|
start++;
|
|
|
|
std::string execstr = s.substr(start, end-start);
|
|
within_exec = true;
|
|
MACROTEXT m;
|
|
execstr = m.expandMacro(execstr);
|
|
within_exec = false;
|
|
|
|
char* cmd = strdup(execstr.c_str());
|
|
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
memset(&si, 0, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
memset(&pi, 0, sizeof(pi));
|
|
if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
|
LOG_ERROR("CreateProcess failed with error code %ld", GetLastError());
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
free(cmd);
|
|
|
|
s.erase(i, end + strlen("</EXEC>") - i);
|
|
}
|
|
#endif // !__MINGW32__
|
|
|
|
static void pEQSL(std::string& s, size_t& i, size_t endbracket)
|
|
{
|
|
if (within_exec || progdefaults.eqsl_when_logged) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
size_t start = s.find(':', i);
|
|
|
|
std::string msg = "";
|
|
if (start != std::string::npos)
|
|
msg = s.substr(start + 1, endbracket-start-1);
|
|
|
|
makeEQSL(msg.c_str());
|
|
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
|
|
static void MAPIT(int how)
|
|
{
|
|
float lat = 0, lon = 0;
|
|
std::string sCALL = inpCall->value();
|
|
std::string sLOC = inpLoc->value();
|
|
|
|
std::string url = "http://maps.google.com/maps?q=";
|
|
|
|
if (how > 1 && !lookup_country.empty()) {
|
|
url.append(lookup_addr1).append(",").append(lookup_addr2).append(",");
|
|
url.append(lookup_state).append(",").append(lookup_country);
|
|
} else {
|
|
if (how > 0 && (!lookup_latd.empty() && !lookup_lond.empty())) {
|
|
url.append(lookup_latd).append(",");
|
|
url.append(lookup_lond);
|
|
} else {
|
|
if (sLOC.empty()) return;
|
|
if (sLOC.length() < 4) return;
|
|
if (sLOC.length() < 6) sLOC.append("aa");
|
|
for (size_t i = 0; i < 6; i++) sLOC[i] = toupper(sLOC[i]);
|
|
if (sLOC[0] -'A' > 17 || sLOC[4] - 'A' > 23 ||
|
|
sLOC[1] -'A' > 17 || sLOC[5] - 'A' > 23 ||
|
|
!isdigit(sLOC[2]) || !isdigit(sLOC[3])) return;
|
|
lon = -180.0 +
|
|
(sLOC[0] - 'A') * 20 +
|
|
(sLOC[2] - '0') * 2 +
|
|
(sLOC[4] - 'A' + 0.5) / 12;
|
|
lat = -90.0 +
|
|
(sLOC[1] - 'A') * 10 +
|
|
(sLOC[3] - '0') +
|
|
(sLOC[5] - 'A' + 0.5) / 24;
|
|
char sdata[20];
|
|
snprintf(sdata, sizeof(sdata),"%10.6f", lat);
|
|
url.append(sdata).append(",");
|
|
snprintf(sdata, sizeof(sdata),"%10.6f", lon);
|
|
url.append(sdata);
|
|
}
|
|
}
|
|
if (!sCALL.empty()) url.append("(").append(sCALL).append(")");
|
|
else url.append("(nocall)");
|
|
url.append("&t=p&z=10");
|
|
cb_mnuVisitURL(NULL, (void*)url.c_str());
|
|
}
|
|
|
|
static void pMAPIT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string sVal = s.substr(i + 7, endbracket - i - 7);
|
|
if (sVal.length() > 0) {
|
|
if (sVal.compare(0,3,"adr") == 0)
|
|
REQ(MAPIT,2);
|
|
else if (sVal.compare(0,6,"latlon") == 0)
|
|
REQ(MAPIT,1);
|
|
else if (sVal.compare(0,3,"loc") == 0)
|
|
REQ(MAPIT,0);
|
|
else
|
|
REQ(MAPIT,2);
|
|
} else
|
|
REQ(MAPIT,2);
|
|
s.erase(i, s.find('>', i) + 1 - i);
|
|
expand = false;
|
|
}
|
|
|
|
static void pSTOP(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.erase(i, s.find('>', i) + 1 - i);
|
|
expand = false;
|
|
}
|
|
|
|
static void pCONT(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
s.erase(i, s.find('>', i) + 1 - i);
|
|
expand = true;
|
|
}
|
|
|
|
static void pSKED(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
if (within_exec) {
|
|
s.replace(i, endbracket - i + 1, "");
|
|
return;
|
|
}
|
|
std::string data = s.substr(i+6, endbracket - i - 6);
|
|
size_t p = data.find(":");
|
|
if (p == std::string::npos) {
|
|
exec_date = zdate();
|
|
exec_time = data;
|
|
if (exec_time.empty()) exec_time = ztime();
|
|
} else {
|
|
exec_time = data.substr(0, p);
|
|
exec_date = data.substr(p+1);
|
|
}
|
|
timed_exec = true;
|
|
s.replace(i, endbracket - i + 1, "");
|
|
}
|
|
|
|
void queue_reset()
|
|
{
|
|
if (!cmds.empty()) {
|
|
Fl::remove_timeout(post_queue_execute);
|
|
Fl::remove_timeout(queue_execute_after_rx);
|
|
Fl::remove_timeout(doneIDLE);
|
|
Fl::remove_timeout(doneWAIT);
|
|
while (!cmds.empty()) cmds.pop();
|
|
}
|
|
Qwait_time = 0;
|
|
Qidle_time = 0;
|
|
que_ok = true;
|
|
}
|
|
|
|
static void postQueue(std::string s)
|
|
{
|
|
ReceiveText->add(s.c_str(), FTextBase::CTRL);
|
|
}
|
|
|
|
void queue_execute()
|
|
{
|
|
if (cmds.empty()) {
|
|
Qwait_time = 0;
|
|
Qidle_time = 0;
|
|
que_ok = true;
|
|
return;
|
|
}
|
|
CMDS cmd = cmds.front();
|
|
cmds.pop();
|
|
cmd.fp(cmd.cmd);
|
|
LOG_INFO("%s", cmd.cmd.c_str());
|
|
REQ(postQueue, cmd.cmd.append("\n"));
|
|
return;
|
|
}
|
|
|
|
bool queue_must_rx()
|
|
{
|
|
static std::string rxcmds = "<!MOD<!WAI<!GOH<!QSY<!GOF";
|
|
if (cmds.empty()) return false;
|
|
CMDS cmd = cmds.front();
|
|
bool ret = (rxcmds.find(cmd.cmd.substr(0,5)) != std::string::npos);
|
|
return ret;
|
|
}
|
|
|
|
struct MTAGS { const char *mTAG; void (*fp)(std::string &, size_t&, size_t );};
|
|
|
|
static const MTAGS mtags[] = {
|
|
{"<CALL>", pCALL},
|
|
{"<FREQ>", pFREQ},
|
|
{"<LOC>", pLOC},
|
|
{"<MODE>", pMODE},
|
|
{"<NAME>", pNAME},
|
|
{"<QTH>", pQTH},
|
|
{"<RST>", pRST},
|
|
{"<MYCALL>", pMYCALL},
|
|
{"<MYLOC>", pMYLOC},
|
|
{"<MYNAME>", pMYNAME},
|
|
{"<MYQTH>", pMYQTH},
|
|
{"<MYRST>", pMYRST},
|
|
{"<QSOTIME>", pQSOTIME},
|
|
{"<INFO1>", pINFO1},
|
|
{"<INFO2>", pINFO2},
|
|
{"<LDT>", pLDT},
|
|
{"<ILDT>", pILDT},
|
|
{"<ZDT>", pZDT},
|
|
{"<IZDT>", pIZDT},
|
|
{"<LT>", pLT},
|
|
{"<ZT>", pZT},
|
|
{"<LD>", pLD},
|
|
{"<ZD>", pZD},
|
|
{"<ID>", p_ID},
|
|
{"<TEXT>", pTEXT},
|
|
{"<CWID>", pCWID},
|
|
{"<RX>", pRX},
|
|
{"<TX>", pTX},
|
|
{"<TX/RX>", pTXRX},
|
|
{"<VER>", pVER},
|
|
{"<CNTR>", pCNTR},
|
|
{"<DECR>", pDECR},
|
|
{"<INCR>", pINCR},
|
|
{"<X1>", pXOUT},
|
|
{"<XIN>", pXIN},
|
|
{"<XOUT>", pXOUT},
|
|
{"<XBEG>", pXBEG},
|
|
{"<XEND>", pXEND},
|
|
{"<SAVEXCHG>", pSAVEXCHG},
|
|
{"<LOG>", pLOG},
|
|
{"<LNW>", pLNW},
|
|
{"<CLRLOG>", pCLRLOG},
|
|
{"<EQSL", pEQSL},
|
|
{"<TIMER:", pTIMER},
|
|
{"<IDLE:", pIDLE},
|
|
{"<TUNE:", pTUNE},
|
|
{"<WAIT:", pWAIT},
|
|
{"<MODEM>", pMODEM_compSKED},
|
|
{"<MODEM:", pMODEM},
|
|
{"<EXEC>", pEXEC},
|
|
{"</EXEC>", pEND_EXEC},
|
|
{"<STOP>", pSTOP},
|
|
{"<CONT>", pCONT},
|
|
{"<GET>", pGET},
|
|
{"<CLRRX>", pCLRRX},
|
|
{"<CLRTX>", pCLRTX},
|
|
{"<FILE:", pFILE},
|
|
{"<WPM:", pWPM},
|
|
{"<RISE:", pRISETIME},
|
|
{"<PRE:", pPRE},
|
|
{"<POST:", pPOST},
|
|
{"<AFC:", pAFC},
|
|
{"<LOCK:", pLOCK},
|
|
{"<REV:", pREV},
|
|
{"<RXRSID:", pRX_RSID},
|
|
{"<TXRSID:", pTX_RSID},
|
|
{"<DTMF:", pDTMF},
|
|
{"<SRCHUP>", pSRCHUP},
|
|
{"<SRCHDN>", pSRCHDN},
|
|
{"<GOHOME>", pGOHOME},
|
|
{"<GOFREQ:", pGOFREQ},
|
|
{"<QSY:", pQSY},
|
|
{"<QSYTO>", pQSYTO},
|
|
{"<QSYFM>", pQSYFM},
|
|
{"<RIGMODE:", pRIGMODE},
|
|
{"<FILWID:", pFILWID},
|
|
{"<MAPIT:", pMAPIT},
|
|
{"<MAPIT>", pMAPIT},
|
|
{"<REPEAT>", pREPEAT},
|
|
{"<SKED:", pSKED},
|
|
#ifdef __WIN32__
|
|
{"<TALK:", pTALK},
|
|
#endif
|
|
{"<!WPM:", pQueWPM},
|
|
{"<!RISE:", pQueRISETIME},
|
|
{"<!PRE:", pQuePRE},
|
|
{"<!POST:", pQuePOST},
|
|
{"<!GOHOME>", pQueGOHOME},
|
|
{"<!GOFREQ:", pQueGOFREQ},
|
|
{"<!QSY:", pQueQSY},
|
|
{"<!IDLE:", pQueIDLE},
|
|
{"<!WAIT:", pQueWAIT},
|
|
{"<!MODEM:", pQueMODEM},
|
|
{0, 0}
|
|
};
|
|
|
|
int MACROTEXT::loadMacros(const std::string& filename)
|
|
{
|
|
std::string mLine;
|
|
std::string mName;
|
|
std::string mDef;
|
|
bool inMacro = false;
|
|
int mNumber = 0;
|
|
unsigned long int crlf; // 64 bit cpu's
|
|
char szLine[4096];
|
|
bool convert = false;
|
|
|
|
ifstream mFile(filename.c_str());
|
|
|
|
if (!mFile) {
|
|
create_new_macros();
|
|
} else {
|
|
|
|
mFile.getline(szLine, 4095);
|
|
mLine = szLine;
|
|
if (mLine.find("//fldigi macro definition file") != 0) {
|
|
mFile.close();
|
|
return -2;
|
|
}
|
|
if (mLine.find("extended") == std::string::npos) {
|
|
convert = true;
|
|
changed = true;
|
|
}
|
|
// clear all of the macros
|
|
for (int i = 0; i < MAXMACROS; i++) {
|
|
name[i] = "";
|
|
text[i] = "";
|
|
}
|
|
inMacro = false;
|
|
while (!mFile.eof()) {
|
|
mFile.getline(szLine,4095);
|
|
mLine = szLine;
|
|
if (mLine.find("//") == 0) // skip over all comment lines
|
|
continue;
|
|
if (mLine.find("/$") == 0) {
|
|
int idx = mLine.find_first_not_of("0123456789", 3);
|
|
sscanf((mLine.substr(3, idx - 3)).c_str(), "%d", &mNumber);
|
|
if (mNumber < 0 || mNumber > (MAXMACROS - 1))
|
|
break;
|
|
if (convert && mNumber > 9) mNumber += 2;
|
|
name[mNumber] = mLine.substr(idx+1);
|
|
continue;
|
|
}
|
|
while ((crlf = mLine.find("\\n")) != std::string::npos) {
|
|
mLine.erase(crlf, 2);
|
|
mLine.append("\n");
|
|
}
|
|
text[mNumber] = text[mNumber] + mLine;
|
|
}
|
|
mFile.close();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void MACROTEXT::loadDefault()
|
|
{
|
|
int erc;
|
|
std::string Filename = MacrosDir;
|
|
if (progdefaults.UseLastMacro == true)
|
|
Filename.append(progStatus.LastMacroFile);
|
|
else {
|
|
Filename.append("macros.mdf");
|
|
progStatus.LastMacroFile = "macros.mdf";
|
|
}
|
|
if ((erc = loadMacros(Filename)) != 0)
|
|
#ifndef __WOE32__
|
|
LOG_ERROR("Error #%d loading %s\n", erc, Filename.c_str());
|
|
#else
|
|
;
|
|
#endif
|
|
}
|
|
|
|
void MACROTEXT::openMacroFile()
|
|
{
|
|
std::string deffilename = MacrosDir;
|
|
deffilename.append(progStatus.LastMacroFile);
|
|
const char *p = FSEL::select(_("Open macro file"), _("Fldigi macro definition file\t*.{mdf}"), deffilename.c_str());
|
|
if (p) {
|
|
loadMacros(p);
|
|
progStatus.LastMacroFile = fl_filename_name(p);
|
|
}
|
|
showMacroSet();
|
|
}
|
|
|
|
void MACROTEXT::saveMacroFile()
|
|
{
|
|
std::string deffilename = MacrosDir;
|
|
deffilename.append(progStatus.LastMacroFile);
|
|
const char *p = FSEL::saveas(
|
|
_("Save macro file"),
|
|
_("Fldigi macro definition file\t*.{mdf}"),
|
|
deffilename.c_str());
|
|
if (p) {
|
|
string sp = p;
|
|
if (sp.rfind(".mdf") == string::npos) sp.append(".mdf");
|
|
saveMacros(sp.c_str());
|
|
progStatus.LastMacroFile = fl_filename_name(sp.c_str());
|
|
}
|
|
}
|
|
|
|
void MACROTEXT::loadnewMACROS(std::string &s, size_t &i, size_t endbracket)
|
|
{
|
|
std::string fname = s.substr(i+8, endbracket - i - 8);
|
|
if (fname.length() > 0) {
|
|
loadMacros(fname);
|
|
progStatus.LastMacroFile = fl_filename_name(fname.c_str());
|
|
}
|
|
s.replace(i, endbracket - i + 1, "");
|
|
showMacroSet();
|
|
}
|
|
|
|
std::string MACROTEXT::expandMacro(std::string &s)
|
|
{
|
|
size_t idx = 0;
|
|
expand = true;
|
|
TransmitON = false;
|
|
ToggleTXRX = false;
|
|
// mNbr = n;
|
|
expanded = s;//text[n];
|
|
const MTAGS *pMtags;
|
|
|
|
xbeg = xend = -1;
|
|
save_xchg = false;
|
|
progStatus.repeatMacro = -1;
|
|
text2repeat.clear();
|
|
idleTime = 0;
|
|
waitTime = 0;
|
|
tuneTime = 0;
|
|
|
|
while ((idx = expanded.find('<', idx)) != std::string::npos) {
|
|
size_t endbracket = expanded.find('>',idx);
|
|
if (expanded.find("<MACROS:",idx) == idx) {
|
|
loadnewMACROS(expanded, idx, endbracket);
|
|
idx++;
|
|
continue;
|
|
}
|
|
// we must handle this specially
|
|
if (expanded.find("<CONT>", idx) == idx)
|
|
pCONT(expanded, idx, endbracket);
|
|
if (!expand) {
|
|
idx++;
|
|
continue;
|
|
}
|
|
|
|
pMtags = mtags;
|
|
while (pMtags->mTAG != 0) {
|
|
if (expanded.find(pMtags->mTAG,idx) == idx) {
|
|
pMtags->fp(expanded,idx, endbracket);
|
|
break;
|
|
}
|
|
pMtags++;
|
|
}
|
|
if (pMtags->mTAG == 0)
|
|
idx++;
|
|
}
|
|
if (GET) {
|
|
size_t pos1 = expanded.find("$NAME");
|
|
size_t pos2 = expanded.find("$QTH");
|
|
size_t pos3 = expanded.find("$LOC");
|
|
if (pos1 != std::string::npos && pos2 != std::string::npos) {
|
|
pos1 += 5;
|
|
inpName->value(expanded.substr(pos1, pos2 - pos1).c_str());
|
|
}
|
|
if (pos2 != std::string::npos) {
|
|
pos2 += 4;
|
|
inpQth->value(expanded.substr(pos2, pos3 - pos2).c_str());
|
|
}
|
|
if (pos3 != std::string::npos) {
|
|
pos3 += 4;
|
|
inpLoc->value(expanded.substr(pos3).c_str());
|
|
}
|
|
GET = false;
|
|
return "";
|
|
}
|
|
|
|
if (xbeg != std::string::npos && xend != std::string::npos && xend > xbeg) {
|
|
qso_exchange = expanded.substr(xbeg, xend - xbeg);
|
|
} else if (save_xchg) {
|
|
qso_exchange = expanded;
|
|
save_xchg = false;
|
|
}
|
|
|
|
// force "^r" to be last tag in the expanded std::string
|
|
if ((idx = expanded.find("^r")) != std::string::npos) {
|
|
expanded.erase(idx, 2);
|
|
expanded.append("^r");
|
|
}
|
|
|
|
return expanded;
|
|
}
|
|
|
|
void idleTimer(void *)
|
|
{
|
|
macro_idle_on = false;
|
|
}
|
|
|
|
static void continueMacro(void *)
|
|
{
|
|
if ( TransmitON ) {
|
|
active_modem->set_stopflag(false);
|
|
if (macro_idle_on && idleTime > 0)
|
|
Fl::add_timeout(idleTime, idleTimer);
|
|
start_tx();
|
|
TransmitON = false;
|
|
}
|
|
text2send.clear();
|
|
}
|
|
|
|
static void finishTune(void *)
|
|
{
|
|
trx_receive();
|
|
// delay to allow tx/rx loop to change state
|
|
Fl::add_timeout(0.5, continueMacro);
|
|
}
|
|
|
|
static void finishWait(void *)
|
|
{
|
|
if (useTune && tuneTime > 0) {
|
|
trx_tune();
|
|
Fl::add_timeout(tuneTime, finishTune);
|
|
useTune = false;
|
|
return;
|
|
}
|
|
if ( TransmitON ) {
|
|
active_modem->set_stopflag(false);
|
|
if (macro_idle_on && idleTime > 0)
|
|
Fl::add_timeout(idleTime, idleTimer);
|
|
start_tx();
|
|
TransmitON = false;
|
|
}
|
|
}
|
|
|
|
static void set_button(Fl_Button* button, bool value)
|
|
{
|
|
button->value(value);
|
|
button->do_callback();
|
|
}
|
|
|
|
void MACROTEXT::timed_execute()
|
|
{
|
|
queue_reset();
|
|
TransmitText->clear();
|
|
text2send = expandMacro(exec_string);
|
|
TransmitText->add(text2send.c_str());
|
|
exec_string.clear();
|
|
active_modem->set_stopflag(false);
|
|
start_tx();
|
|
}
|
|
|
|
void MACROTEXT::execute(int n)
|
|
{
|
|
mNbr = n;
|
|
text2send = expandMacro(text[n]);
|
|
|
|
if (timed_exec) {
|
|
progStatus.repeatMacro = -1;
|
|
exec_string = text[n];
|
|
timed_exec = false;
|
|
startTimedExecute(name[n]);
|
|
return;
|
|
}
|
|
|
|
if (progStatus.repeatMacro == -1)
|
|
TransmitText->add( text2send.c_str() );
|
|
else {
|
|
size_t p = std::string::npos;
|
|
text2send = text[n];
|
|
while ((p = text2send.find('<')) != std::string::npos)
|
|
text2send[p] = '[';
|
|
while ((p = text2send.find('>')) != std::string::npos)
|
|
text2send[p] = ']';
|
|
TransmitText->add( text2send.c_str() );
|
|
}
|
|
text2send.clear();
|
|
|
|
if (ToggleTXRX) {
|
|
text2send.clear();
|
|
if (!wf->xmtrcv->value()) {
|
|
REQ(set_button, wf->xmtrcv, true);
|
|
if (macro_idle_on && idleTime > 0)
|
|
Fl::add_timeout(idleTime, idleTimer);
|
|
} else
|
|
REQ(set_button, wf->xmtrcv, false);
|
|
return;
|
|
}
|
|
if (useWait && waitTime > 0) {
|
|
Fl::add_timeout(waitTime, finishWait);
|
|
useWait = false;
|
|
return;
|
|
}
|
|
if (useTune && tuneTime > 0) {
|
|
trx_tune();
|
|
Fl::add_timeout(tuneTime, finishTune);
|
|
useTune = false;
|
|
return;
|
|
}
|
|
if ( TransmitON ) {
|
|
if (macro_idle_on && idleTime > 0)
|
|
Fl::add_timeout(idleTime, idleTimer);
|
|
|
|
active_modem->set_stopflag(false);
|
|
start_tx();
|
|
TransmitON = false;
|
|
}
|
|
}
|
|
|
|
void MACROTEXT::repeat(int n)
|
|
{
|
|
expandMacro(text[n]);
|
|
LOG_WARN("%s",text2repeat.c_str());
|
|
macro_idle_on = false;
|
|
if (idleTime) progStatus.repeatIdleTime = idleTime;
|
|
}
|
|
|
|
MACROTEXT::MACROTEXT()
|
|
{
|
|
changed = false;
|
|
char szname[5];
|
|
for (int i = 0; i < MAXMACROS; i++) {
|
|
snprintf(szname, sizeof(szname), "F-%d", i+1);
|
|
name[i] = szname;//"";
|
|
text[i] = "";
|
|
}
|
|
}
|
|
|
|
|
|
static std::string mtext =
|
|
"//fldigi macro definition file extended\n\
|
|
// This file defines the macro structure(s) for the digital modem program, fldigi\n\
|
|
// It also serves as a basis for any macros that are written by the user\n\
|
|
//\n\
|
|
// The top line of this file should always be the first line in every macro \n\
|
|
// definition file (.mdf) for the fldigi program to recognize it as such.\n\
|
|
//\n\
|
|
";
|
|
|
|
void MACROTEXT::saveMacros(const std::string& fname) {
|
|
std::string work;
|
|
ofstream mfile(fname.c_str());
|
|
mfile << mtext;
|
|
for (int i = 0; i < MAXMACROS; i++) {
|
|
mfile << "\n//\n// Macro # " << i+1 << "\n";
|
|
mfile << "/$ " << i << " " << macros.name[i].c_str() << "\n";
|
|
work = macros.text[i];
|
|
size_t pos;
|
|
pos = work.find('\n');
|
|
while (pos != std::string::npos) {
|
|
work.insert(pos, "\\n");
|
|
pos = work.find('\n', pos + 3);
|
|
}
|
|
mfile << work.c_str();
|
|
}
|
|
mfile << "\n";
|
|
mfile.close();
|
|
changed = false;
|
|
}
|
|
|