1 // ---------------------------------------------------------------------------- 2 // macros.cxx 3 // 4 // Copyright (C) 2007-2010 5 // Dave Freese, W1HKJ 6 // Copyright (C) 2008-2010 7 // Stelios Bounanos, M0GLD 8 // Copyright (C) 2009 9 // Chris Sylvain, KB3CS 10 // 11 // This file is part of fldigi. 12 // 13 // Fldigi is free software: you can redistribute it and/or modify 14 // it under the terms of the GNU General Public License as published by 15 // the Free Software Foundation, either version 3 of the License, or 16 // (at your option) any later version. 17 // 18 // Fldigi is distributed in the hope that it will be useful, 19 // but WITHOUT ANY WARRANTY; without even the implied warranty of 20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 // GNU General Public License for more details. 22 // 23 // You should have received a copy of the GNU General Public License 24 // along with fldigi. If not, see <http://www.gnu.org/licenses/>. 25 // ---------------------------------------------------------------------------- 26 27 #include <config.h> 28 #include <sys/time.h> 29 #include <ctime> 30 31 #include "macros.h" 32 33 #include "gettext.h" 34 #include "main.h" 35 #include "misc.h" 36 37 #include "fl_digi.h" 38 #include "timeops.h" 39 #include "configuration.h" 40 #include "confdialog.h" 41 #include "logger.h" 42 #include "newinstall.h" 43 #include "globals.h" 44 #include "debug.h" 45 #include "status.h" 46 #include "trx.h" 47 #include "modem.h" 48 #include "qrunner.h" 49 #include "waterfall.h" 50 #include "rigsupport.h" 51 #include "network.h" 52 #include "logsupport.h" 53 #include "icons.h" 54 #include "weather.h" 55 #include "utf8file_io.h" 56 #include "xmlrpc.h" 57 #include "rigio.h" 58 #include "strutil.h" 59 #include "threads.h" 60 61 #include <FL/Fl.H> 62 #include <FL/filename.H> 63 #include "fileselect.h" 64 65 #include <ctime> 66 #include <cstdio> 67 #include <cstdlib> 68 #include <unistd.h> 69 #include <string> 70 #include <sstream> 71 #include <fstream> 72 #include <queue> 73 #include <stack> 74 75 #ifdef __WIN32__ 76 #include "speak.h" 77 #endif 78 79 #include "audio_alert.h" 80 81 #include <float.h> 82 #include "re.h" 83 84 //using namespace std; 85 86 static pthread_mutex_t exec_mutex = PTHREAD_MUTEX_INITIALIZER; 87 88 struct CMDS { std::string cmd; void (*fp)(std::string); }; 89 static queue<CMDS> Tx_cmds; 90 static queue<CMDS> Rx_cmds; 91 92 bool txque_wait = false; 93 94 static std::string buffered_macro; 95 static bool buffered = false; 96 static size_t buffered_pointer; 97 98 /* 99 static const char *ascii4[256] = { 100 "<NUL>", "<SOH>", "<STX>", "<ETX>", "<EOT>", "<ENQ>", "<ACK>", "<BEL>", 101 "<BS>", "<TAB>", "<LF>\n", "<VT>", "<FF>", "<CR>", "<SO>", "<SI>", 102 "<DLE>", "<DC1>", "<DC2>", "<DC3>", "<DC4>", "<NAK>", "<SYN>", "<ETB>", 103 "<CAN>", "<EM>", "<SUB>", "<ESC>", "<FS>", "<GS>", "<RS>", "<US>", 104 " ", "!", "\"", "#", "$", "%", "&", "\'", 105 "(", ")", "*", "+", ",", "-", ".", "/", 106 "0", "1", "2", "3", "4", "5", "6", "7", 107 "8", "9", ":", ";", "<", "=", ">", "?", 108 "@", "A", "B", "C", "D", "E", "F", "G", 109 "H", "I", "J", "K", "L", "M", "N", "O", 110 "P", "Q", "R", "S", "T", "U", "V", "W", 111 "X", "Y", "Z", "[", "\\", "]", "^", "_", 112 "`", "a", "b", "c", "d", "e", "f", "g", 113 "h", "i", "j", "k", "l", "m", "n", "o", 114 "p", "q", "r", "s", "t", "u", "v", "w", 115 "x", "y", "z", "{", "|", "}", "~", "<DEL>", 116 "<128>", "<129>", "<130>", "<131>", "<132>", "<133>", "<134>", "<135>", 117 "<136>", "<137>", "<138>", "<139>", "<140>", "<141>", "<142>", "<143>", 118 "<144>", "<145>", "<146>", "<147>", "<148>", "<149>", "<150>", "<151>", 119 "<152>", "<153>", "<154>", "<155>", "<156>", "<157>", "<158>", "<159>", 120 "<160>", "<161>", "<162>", "<163>", "<164>", "<165>", "<166>", "<167>", 121 "<168>", "<169>", "<170>", "<171>", "<172>", "<173>", "<174>", "<175>", 122 "<176>", "<177>", "<178>", "<179>", "<180>", "<181>", "<182>", "<183>", 123 "<184>", "<185>", "<186>", "<187>", "<188>", "<189>", "<190>", "<191>", 124 "<192>", "<193>", "<194>", "<195>", "<196>", "<197>", "<198>", "<199>", 125 "<200>", "<201>", "<202>", "<203>", "<204>", "<205>", "<206>", "<207>", 126 "<208>", "<209>", "<210>", "<211>", "<212>", "<213>", "<214>", "<215>", 127 "<216>", "<217>", "<218>", "<219>", "<220>", "<221>", "<222>", "<223>", 128 "<224>", "<225>", "<226>", "<227>", "<228>", "<229>", "<230>", "<231>", 129 "<232>", "<233>", "<234>", "<235>", "<236>", "<237>", "<238>", "<239>", 130 "<240>", "<241>", "<242>", "<243>", "<244>", "<245>", "<246>", "<247>", 131 "<248>", "<249>", "<250>", "<251>", "<252>", "<253>", "<254>", "<255>" 132 }; 133 134 static std::string hout(std::string s) 135 { 136 static std::string sout; 137 sout.clear(); 138 for (size_t n = 0; n < s.length(); n++) 139 sout.append(ascii4[int(s[n])]); 140 return sout; 141 } 142 */ 143 144 static void substitute (std::string &s, size_t &start, size_t end, std::string sub) 145 { 146 if (start && s[start - 1] == '\n') { 147 start--; 148 } 149 //std::cout << "--------------------------------------------------------" << std::endl; 150 if (sub.empty()) { 151 //std::cout << "ERASED:" << hout(s.substr(start, end - start + 1)) << std::endl; 152 s.erase(start, end - start + 1); 153 } else { 154 //std::cout << "REPLACED: '" << hout(s.substr(start, end - start + 1)) << 155 // "' WITH '" << hout(sub) << "'" << std::endl; 156 s.replace(start, end - start + 1, sub); 157 } 158 //std::cout << "--------------------------------------------------------" << std::endl; 159 //std::cout << hout(s) << std::endl; 160 //std::cout << "=========================================================" << std::endl; 161 } 162 163 static void add_text(std::string text) 164 { 165 if (buffered) { 166 buffered_macro.append(text); 167 buffered_pointer = 0; 168 } else { 169 TransmitText->add_text(text); 170 } 171 } 172 173 void clear_buffered_text() 174 { 175 buffered_macro.clear(); 176 } 177 178 char next_buffered_macro_char() 179 { 180 if (buffered_macro.empty()) 181 return 0; 182 char c = buffered_macro[buffered_pointer++]; 183 if (buffered_pointer >= buffered_macro.length()) { 184 buffered_macro.clear(); 185 buffered_pointer = 0; 186 } 187 return c; 188 } 189 190 static void pBUFFERED(std::string &s, size_t &i, size_t endbracket) 191 { 192 substitute(s, i, endbracket, ""); 193 buffered = true; 194 buffered_macro.clear(); 195 } 196 197 static void setwpm(double d) 198 { 199 sldrCWxmtWPM->value(d); 200 cntCW_WPM->value(d); 201 progdefaults.CWusefarnsworth = false; 202 btnCWusefarnsworth->value(0); 203 que_ok = true; 204 } 205 206 static void setfwpm(double d) 207 { 208 sldrCWfarnsworth->value(d); 209 progdefaults.CWusefarnsworth = true; 210 btnCWusefarnsworth->value(1); 211 que_ok = true; 212 } 213 214 // following used for debugging and development 215 void push_txcmd(CMDS cmd) 216 { 217 LOG_INFO("%s, # = %d", cmd.cmd.c_str(), (int)Tx_cmds.size()); 218 Tx_cmds.push(cmd); 219 } 220 221 void push_rxcmd(CMDS cmd) 222 { 223 LOG_INFO("%s, # = %d", cmd.cmd.c_str(), (int)Rx_cmds.size()); 224 Rx_cmds.push(cmd); 225 } 226 227 // these variables are referenced outside of this file 228 MACROTEXT macros; 229 CONTESTCNTR contest_count; 230 231 std::string qso_time = ""; 232 std::string qso_exchange = ""; 233 std::string exec_date = ""; 234 std::string exec_time = ""; 235 std::string exec_string = ""; 236 std::string until_date = ""; 237 std::string until_time = ""; 238 std::string info1msg = ""; 239 std::string info2msg = ""; 240 std::string text2repeat = ""; 241 242 size_t repeatchar = 0; 243 244 bool macro_idle_on = false; 245 bool macro_rx_wait = false; 246 247 static float idleTime = 0; 248 static bool TransmitON = false; 249 static bool ToggleTXRX = false; 250 static int mNbr; 251 252 static std::string text2send = ""; 253 254 static size_t xbeg = 0, xend = 0; 255 256 static bool save_xchg; 257 static bool expand; 258 static bool GET = false; 259 static bool timed_exec = false; 260 static bool run_until = false; 261 static bool within_exec = false; 262 263 bool local_timed_exec = false; 264 265 void rx_que_continue(void *); 266 267 static void postQueue(std::string s) 268 { 269 s.append("\n"); 270 if (!progdefaults.macro_post) return; 271 if (active_modem->get_mode() == MODE_IFKP) 272 ifkp_rx_text->addstr(s, FTextBase::CTRL); 273 else if (active_modem->get_mode() == MODE_FSQ) 274 fsq_rx_text->addstr(s, FTextBase::CTRL); 275 else 276 ReceiveText->addstr(s, FTextBase::CTRL); 277 } 278 279 static const char cutnumbers[] = "T12345678N"; 280 static std::string cutstr; 281 282 static std::string cut_string(const char *s) 283 { 284 cutstr = s; 285 if (!progdefaults.cutnbrs || active_modem != cw_modem) 286 return cutstr; 287 288 for (size_t i = 0; i < cutstr.length(); i++) 289 if (cutstr[i] >= '0' && cutstr[i] <= '9') 290 cutstr[i] = cutnumbers[cutstr[i] - '0']; 291 return cutstr; 292 293 } 294 295 static size_t mystrftime( char *s, size_t max, const char *fmt, const struct tm *tm) { 296 return strftime(s, max, fmt, tm); 297 } 298 299 static std::string CPSstring = "\ 300 =============================================\n\ 301 ABCDEFGHIJKLMN OPQRSTUVWXYZ\n\ 302 abcdefghijklmn opqrstuvwxyz\n\ 303 0123456789 9876543210\n\ 304 !@#$%&*()_+-=[]{}\\|;:'\",.<>/?\n\ 305 =============================================\n\ 306 \n\ 307 The Jaberwocky\n\ 308 \n\ 309 'Twas brillig, and the slithy toves\n\ 310 Did gyre and gimble in the wabe;\n\ 311 All mimsy were the borogoves,\n\ 312 And the mome raths outgrabe.\n\ 313 \n\ 314 \"Beware the Jabberwock, my son!\n\ 315 The jaws that bite, the claws that catch!\n\ 316 Beware the Jubjub bird, and shun\n\ 317 The frumious Bandersnatch!\"\n\ 318 \n\ 319 He took his vorpal sword in hand:\n\ 320 Long time the manxome foe he sought-\n\ 321 So rested he by the Tumtum tree,\n\ 322 And stood awhile in thought.\n\ 323 \n\ 324 And as in uffish thought he stood,\n\ 325 The Jabberwock, with eyes of flame,\n\ 326 Came whiffling through the tulgey wood,\n\ 327 And burbled as it came!\n\ 328 \n\ 329 One, two! One, two! and through and through\n\ 330 The vorpal blade went snicker-snack!\n\ 331 He left it dead, and with its head\n\ 332 He went galumphing back.\n\ 333 \n\ 334 \"And hast thou slain the Jabberwock?\n\ 335 Come to my arms, my beamish boy!\n\ 336 O frabjous day! Callooh! Callay!\"\n\ 337 He chortled in his joy.\n\ 338 \n\ 339 'Twas brillig, and the slithy toves\n\ 340 Did gyre and gimble in the wabe;\n\ 341 All mimsy were the borogoves,\n\ 342 And the mome raths outgrabe.\n"; 343 344 static std::string ccode = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 345 346 bool PERFORM_CPS_TEST = false; 347 int num_cps_chars = 0; 348 string testfilename; 349 350 void CPS_report(int samples, int prepost) 351 { 352 char specs[1000]; 353 memset(specs, 0, 1000); 354 std::string results = "\nCPS test\ntext: "; 355 if (testfilename[0] != '\n') 356 results.append("\n"); 357 results.append(testfilename).append("\n"); 358 string strout; 359 double xmttime = 1.0 * samples / active_modem->get_samplerate(); 360 double overhead = 1.0 * prepost / active_modem->get_samplerate(); 361 num_cps_chars--; 362 snprintf(specs, sizeof(specs), "\ 363 mode: %s\n\ 364 # chars: %d\n\ 365 overhead: %f sec\n\ 366 xmt time: %f sec\n\ 367 xmt samples: %d\n\ 368 sample rate: %d\n\ 369 chars/sec: %f", 370 mode_info[active_modem->get_mode()].name, 371 num_cps_chars, 372 overhead, 373 xmttime - overhead, 374 samples, 375 active_modem->get_samplerate(), 376 num_cps_chars / (xmttime - overhead)); 377 results.append(specs); 378 LOG_INFO("%s", results.c_str()); 379 results.append("\n"); 380 if (active_modem->get_mode() == MODE_IFKP) 381 ifkp_rx_text->add(results.c_str(), FTextBase::ALTR); 382 else if (active_modem->get_mode() == MODE_FSQ) 383 fsq_rx_text->addstr(results.c_str(), FTextBase::ALTR); 384 else 385 ReceiveText->add(results.c_str(), FTextBase::ALTR); 386 PERFORM_CPS_TEST = false; 387 } 388 389 static void pCPS_TEST(std::string &s, size_t &i, size_t endbracket) 390 { 391 trx_mode id = active_modem->get_mode(); 392 if ( id == MODE_SSB || id == MODE_WWV || 393 id == MODE_ANALYSIS || 394 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 395 id == MODE_SITORB || id == MODE_NAVTEX ) { 396 if (active_modem->get_mode() == MODE_IFKP) 397 ifkp_tx_text->add("Mode not supported\n", FTextBase::ALTR); 398 else if (active_modem->get_mode() == MODE_FSQ) 399 fsq_rx_text->addstr("Mode not supported", FTextBase::ALTR); 400 else 401 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 402 s.clear(); 403 return; 404 } 405 406 std::string buffer = s.substr(i+10, endbracket - i - 10); 407 s.clear(); 408 409 int n; 410 if (buffer.empty()) n = 10; 411 sscanf(buffer.c_str(), "%d", &n); 412 if (n <= 0) n = 10; 413 if (n > 100) n = 100; 414 415 // sample count with 'n' characters 416 int s1[256]; 417 for (int i = 0; i < 256; i++) s1[i] = 0; 418 // converstion from sample count to milliseconds 419 double k = 1000.0 / (active_modem->get_samplerate() * n); 420 421 stopMacroTimer(); 422 active_modem->set_stopflag(false); 423 424 PERFORM_CPS_TEST = true; 425 int s0 = number_of_samples(""); 426 // sample count for characters ' ' through '~' 427 for(int j = 0; j < 256; j++) { 428 s1[j] = number_of_samples(string(n, j)) - s0; 429 } 430 PERFORM_CPS_TEST = false; 431 432 // report generator 433 char results[200]; 434 string line_out; 435 snprintf(results, sizeof(results), "\nCPS test\nMode : %s\n", mode_info[active_modem->get_mode()].name); 436 line_out = results; 437 snprintf(results, sizeof(results), "Based on %d character string\n", n); 438 line_out.append(results); 439 snprintf(results, sizeof(results), "Overhead = %.3f msec\n", 1000.0 * s0 / active_modem->get_samplerate()); 440 line_out.append(results); 441 for (int j = 0, ln = 0; j < 256; j++ ) { 442 snprintf(results, sizeof(results), "%2x%8.2f", j, k * s1[j]); 443 line_out.append(results); 444 ln++; 445 if (ln && (ln % 4 == 0)) line_out.append("\n"); 446 else line_out.append(" | "); 447 } 448 if (!line_out.empty()) { 449 LOG_INFO("%s", line_out.c_str()); 450 if (active_modem->get_mode() == MODE_IFKP) 451 ifkp_rx_text->add(line_out.c_str(), FTextBase::ALTR); 452 if (active_modem->get_mode() == MODE_FSQ) 453 fsq_rx_text->add(line_out.c_str(), FTextBase::ALTR); 454 else 455 ReceiveText->add(line_out.c_str(), FTextBase::ALTR); 456 } 457 return; 458 } 459 460 static void pCPS_FILE(std::string &s, size_t &i, size_t endbracket) 461 { 462 trx_mode id = active_modem->get_mode(); 463 if ( id == MODE_SSB || id == MODE_WWV || 464 id == MODE_ANALYSIS || 465 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 466 id == MODE_SITORB || id == MODE_NAVTEX ) { 467 if (active_modem->get_mode() == MODE_IFKP) 468 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 469 else if (active_modem->get_mode() == MODE_FSQ) 470 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 471 else 472 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 473 s.clear(); 474 return; 475 } 476 477 std::string fname = s.substr(i+10, endbracket - i - 10); 478 if (fname.length() > 0 && !within_exec) { 479 FILE *toadd = fl_fopen(fname.c_str(), "r"); 480 if (toadd) { 481 std::string buffer; 482 char c = getc(toadd); 483 while (c && !feof(toadd)) { 484 if (c != '\r') buffer += c; // damn MSDOS txt files 485 c = getc(toadd); 486 } 487 s.clear(); 488 fclose(toadd); 489 if (active_modem->get_mode() == MODE_IFKP) 490 ifkp_tx_text->clear(); 491 else if (active_modem->get_mode() == MODE_FSQ) 492 fsq_tx_text->clear(); 493 else 494 TransmitText->clear(); 495 testfilename = fname; 496 497 stopMacroTimer(); 498 active_modem->set_stopflag(false); 499 500 PERFORM_CPS_TEST = true; 501 int s0 = number_of_samples(""); 502 num_cps_chars = 0; 503 CPS_report(number_of_samples(buffer), s0); 504 PERFORM_CPS_TEST = false; 505 506 } else { 507 string resp = "Could not locate "; 508 resp.append(fname).append("\n"); 509 if (active_modem->get_mode() == MODE_IFKP) 510 ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR); 511 else if (active_modem->get_mode() == MODE_FSQ) 512 fsq_rx_text->add(resp.c_str(), FTextBase::ALTR); 513 else 514 ReceiveText->add(resp.c_str(), FTextBase::ALTR); 515 LOG_WARN("%s not found", fname.c_str()); 516 substitute(s, i, endbracket, ""); 517 PERFORM_CPS_TEST = false; 518 } 519 } else { 520 PERFORM_CPS_TEST = false; 521 s.clear(); 522 } 523 } 524 525 static void pCPS_STRING(std::string &s, size_t &i, size_t endbracket) 526 { 527 trx_mode id = active_modem->get_mode(); 528 if ( id == MODE_SSB || id == MODE_WWV || 529 id == MODE_ANALYSIS || 530 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 531 id == MODE_SITORB || id == MODE_NAVTEX ) { 532 if (active_modem->get_mode() == MODE_IFKP) 533 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 534 else if (active_modem->get_mode() == MODE_FSQ) 535 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 536 else 537 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 538 s.clear(); 539 return; 540 } 541 542 std::string buffer = s.substr(i+12, endbracket - i - 12); 543 std::string txtbuf = buffer; 544 s.clear(); 545 size_t p = buffer.find("\\n"); 546 while (p != string::npos) { 547 buffer.replace(p,2,"\n"); 548 p = buffer.find("\\n"); 549 } 550 if (buffer.length()) { 551 if (active_modem->get_mode() == MODE_IFKP) 552 ifkp_tx_text->clear(); 553 else if (active_modem->get_mode() == MODE_FSQ) 554 fsq_tx_text->clear(); 555 else 556 TransmitText->clear(); 557 558 stopMacroTimer(); 559 active_modem->set_stopflag(false); 560 561 PERFORM_CPS_TEST = true; 562 int s0 = number_of_samples(""); 563 num_cps_chars = 0; 564 testfilename = txtbuf; 565 CPS_report(number_of_samples(buffer), s0); 566 PERFORM_CPS_TEST = false; 567 568 } else { 569 string resp = "Text not specified"; 570 LOG_WARN("%s", resp.c_str()); 571 resp.append("\n"); 572 if (active_modem->get_mode() == MODE_IFKP) 573 ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR); 574 else if (active_modem->get_mode() == MODE_FSQ) 575 fsq_rx_text->add(resp.c_str(), FTextBase::ALTR); 576 else 577 ReceiveText->add(resp.c_str(), FTextBase::ALTR); 578 PERFORM_CPS_TEST = false; 579 } 580 } 581 582 static void pCPS_N(std::string &s, size_t &i, size_t endbracket) 583 { 584 trx_mode id = active_modem->get_mode(); 585 if ( id == MODE_SSB || id == MODE_WWV || 586 id == MODE_ANALYSIS || 587 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 588 id == MODE_SITORB || id == MODE_NAVTEX ) { 589 if (active_modem->get_mode() == MODE_IFKP) 590 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 591 else if (active_modem->get_mode() == MODE_FSQ) 592 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 593 else 594 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 595 s.clear(); 596 return; 597 } 598 599 std::string buffer = s.substr(i+7, endbracket - i - 7); 600 s.clear(); 601 602 if (buffer.empty()) return; 603 604 int numgroups, wc, cc, cl; 605 cl = ccode.length(); 606 607 sscanf(buffer.c_str(), "%d", &numgroups); 608 if (numgroups <= 0 || numgroups > 100000) numgroups = 100; 609 610 srand(time(0)); 611 buffer.clear(); 612 for (wc = 1; wc <= numgroups; wc++) { 613 for (cc = 0; cc < 5; cc++) { 614 buffer += ccode[ rand() % cl ]; 615 } 616 if (wc % 10 == 0) buffer += '\n'; 617 else buffer += ' '; 618 } 619 620 if (active_modem->get_mode() == MODE_IFKP) 621 ifkp_tx_text->clear(); 622 else if (active_modem->get_mode() == MODE_FSQ) 623 fsq_tx_text->clear(); 624 else 625 TransmitText->clear(); 626 627 stopMacroTimer(); 628 active_modem->set_stopflag(false); 629 630 PERFORM_CPS_TEST = true; 631 int s0 = number_of_samples(""); 632 num_cps_chars = 0; 633 testfilename = "Random group test"; 634 CPS_report(number_of_samples(buffer), s0); 635 PERFORM_CPS_TEST = false; 636 637 return; 638 } 639 640 static void pWAV_TEST(std::string &s, size_t &i, size_t endbracket) 641 { 642 s.clear(); 643 trx_mode id = active_modem->get_mode(); 644 if ( id == MODE_SSB || id == MODE_WWV || 645 id == MODE_ANALYSIS || 646 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 647 id == MODE_SITORB || id == MODE_NAVTEX ) { 648 if (active_modem->get_mode() == MODE_IFKP) 649 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 650 else if (active_modem->get_mode() == MODE_FSQ) 651 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 652 else 653 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 654 return; 655 } 656 testfilename = "internal string"; 657 658 stopMacroTimer(); 659 active_modem->set_stopflag(false); 660 661 PERFORM_CPS_TEST = true; 662 trx_transmit(); 663 number_of_samples(CPSstring); 664 PERFORM_CPS_TEST = false; 665 } 666 667 static void pWAV_N(std::string &s, size_t &i, size_t endbracket) 668 { 669 trx_mode id = active_modem->get_mode(); 670 if ( id == MODE_SSB || id == MODE_WWV || 671 id == MODE_ANALYSIS || 672 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 673 id == MODE_SITORB || id == MODE_NAVTEX ) { 674 if (active_modem->get_mode() == MODE_IFKP) 675 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 676 else if (active_modem->get_mode() == MODE_FSQ) 677 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 678 else 679 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 680 s.clear(); 681 return; 682 } 683 684 std::string buffer = s.substr(i+7, endbracket - i - 7); 685 s.clear(); 686 687 if (buffer.empty()) return; 688 689 int numgroups, wc, cc, cl; 690 cl = ccode.length(); 691 692 sscanf(buffer.c_str(), "%d", &numgroups); 693 if (numgroups <= 0 || numgroups > 100000) numgroups = 100; 694 695 srand(time(0)); 696 buffer.clear(); 697 for (wc = 1; wc <= numgroups; wc++) { 698 for (cc = 0; cc < 5; cc++) { 699 buffer += ccode[ rand() % cl ]; 700 } 701 if (wc % 10 == 0) buffer += '\n'; 702 else buffer += ' '; 703 } 704 705 if (active_modem->get_mode() == MODE_IFKP) 706 ifkp_tx_text->clear(); 707 else if (active_modem->get_mode() == MODE_FSQ) 708 fsq_tx_text->clear(); 709 else 710 TransmitText->clear(); 711 712 stopMacroTimer(); 713 active_modem->set_stopflag(false); 714 PERFORM_CPS_TEST = true; 715 trx_transmit(); 716 number_of_samples(buffer); 717 PERFORM_CPS_TEST = false; 718 return; 719 720 } 721 722 static void pWAV_FILE(std::string &s, size_t &i, size_t endbracket) 723 { 724 trx_mode id = active_modem->get_mode(); 725 if ( id == MODE_SSB || id == MODE_WWV || 726 id == MODE_ANALYSIS || 727 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 728 id == MODE_SITORB || id == MODE_NAVTEX ) { 729 if (active_modem->get_mode() == MODE_IFKP) 730 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 731 else if (active_modem->get_mode() == MODE_FSQ) 732 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 733 else 734 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 735 s.clear(); 736 return; 737 } 738 739 std::string fname = s.substr(i+10, endbracket - i - 10); 740 if (fname.length() > 0 && !within_exec) { 741 FILE *toadd = fl_fopen(fname.c_str(), "r"); 742 if (toadd) { 743 std::string buffer; 744 char c = getc(toadd); 745 while (c && !feof(toadd)) { 746 if (c != '\r') buffer += c; // damn MSDOS txt files 747 c = getc(toadd); 748 } 749 s.clear(); 750 fclose(toadd); 751 if (active_modem->get_mode() == MODE_IFKP) 752 ifkp_tx_text->clear(); 753 else if (active_modem->get_mode() == MODE_FSQ) 754 fsq_tx_text->clear(); 755 else 756 TransmitText->clear(); 757 testfilename = fname; 758 759 stopMacroTimer(); 760 active_modem->set_stopflag(false); 761 PERFORM_CPS_TEST = true; 762 trx_transmit(); 763 764 number_of_samples(buffer); 765 PERFORM_CPS_TEST = false; 766 767 } else { 768 string resp = "Could not locate "; 769 resp.append(fname).append("\n"); 770 if (active_modem->get_mode() == MODE_IFKP) 771 ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR); 772 else if (active_modem->get_mode() == MODE_FSQ) 773 fsq_rx_text->add(resp.c_str(), FTextBase::ALTR); 774 else 775 ReceiveText->add(resp.c_str(), FTextBase::ALTR); 776 LOG_WARN("%s not found", fname.c_str()); 777 substitute(s, i, endbracket, ""); 778 PERFORM_CPS_TEST = false; 779 } 780 } else { 781 PERFORM_CPS_TEST = false; 782 s.clear(); 783 } 784 } 785 786 static void pWAV_STRING(std::string &s, size_t &i, size_t endbracket) 787 { 788 trx_mode id = active_modem->get_mode(); 789 if ( id == MODE_SSB || id == MODE_WWV || 790 id == MODE_ANALYSIS || 791 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 792 id == MODE_SITORB || id == MODE_NAVTEX ) { 793 if (active_modem->get_mode() == MODE_IFKP) 794 ifkp_rx_text->add("Mode not supported\n", FTextBase::ALTR); 795 else if (active_modem->get_mode() == MODE_FSQ) 796 fsq_rx_text->add("Mode not supported\n", FTextBase::ALTR); 797 else 798 ReceiveText->add("Mode not supported\n", FTextBase::ALTR); 799 s.clear(); 800 return; 801 } 802 803 std::string buffer = s.substr(i+12, endbracket - i - 12); 804 std::string txtbuf = buffer; 805 s.clear(); 806 size_t p = buffer.find("\\n"); 807 while (p != string::npos) { 808 buffer.replace(p,2,"\n"); 809 p = buffer.find("\\n"); 810 } 811 if (buffer.length()) { 812 if (active_modem->get_mode() == MODE_IFKP) 813 ifkp_tx_text->clear(); 814 else if (active_modem->get_mode() == MODE_FSQ) 815 fsq_tx_text->clear(); 816 else 817 TransmitText->clear(); 818 819 stopMacroTimer(); 820 active_modem->set_stopflag(false); 821 PERFORM_CPS_TEST = true; 822 trx_transmit(); 823 824 testfilename = txtbuf; 825 number_of_samples(buffer); 826 PERFORM_CPS_TEST = false; 827 } else { 828 string resp = "Text not specified"; 829 LOG_WARN("%s", resp.c_str()); 830 resp.append("\n"); 831 if (active_modem->get_mode() == MODE_IFKP) 832 ifkp_rx_text->add(resp.c_str(), FTextBase::ALTR); 833 else if (active_modem->get_mode() == MODE_FSQ) 834 fsq_rx_text->add(resp.c_str(), FTextBase::ALTR); 835 else 836 ReceiveText->add(resp.c_str(), FTextBase::ALTR); 837 PERFORM_CPS_TEST = false; 838 } 839 } 840 841 static void pCOMMENT(std::string &s, size_t &i, size_t endbracket) 842 { 843 substitute(s, i, endbracket, ""); 844 if (s[i] == '\n') i++; 845 } 846 847 static void pFILE(std::string &s, size_t &i, size_t endbracket) 848 { 849 std::string fname = s.substr(i+6, endbracket - i - 6); 850 if (fname.length() > 0 && !within_exec) { 851 FILE *toadd = fl_fopen(fname.c_str(), "r"); 852 if (toadd) { 853 std::string buffer; 854 char c = getc(toadd); 855 while (c && !feof(toadd)) { 856 if (c != '\r') buffer += c; // change CRLF to LF 857 c = getc(toadd); 858 } 859 size_t blen = buffer.length(); 860 if (blen > 0) { 861 if (!(buffer[blen -1] == ' ' || buffer[blen-1] == '\n')) 862 buffer += ' '; 863 } 864 substitute(s, i, endbracket, buffer); 865 fclose(toadd); 866 } else { 867 LOG_WARN("%s not found", fname.c_str()); 868 substitute(s, i, endbracket, "ERROR: CANNOT OPEN FILE"); 869 } 870 } else { 871 substitute(s, i, endbracket, "OH SHIT"); 872 } 873 } 874 875 static notify_dialog *macro_alert_dialog = 0; 876 877 static void doTIMER(std::string s) 878 { 879 int number; 880 std::string sTime = s.substr(7); 881 if (sTime.length() > 0) { 882 sscanf(sTime.c_str(), "%d", &number); 883 int mtime = stop_macro_time(); 884 if (mtime >= number) { 885 if (!macro_alert_dialog) macro_alert_dialog = new notify_dialog; 886 ostringstream comment; 887 comment << "Macro timer must be > macro duration of " << mtime << " secs"; 888 macro_alert_dialog->notify(comment.str().c_str(), 5.0); 889 REQ(show_notifier, macro_alert_dialog); 890 progStatus.skip_sked_macro = false; 891 } else { 892 progStatus.timer = number - mtime; 893 progStatus.timerMacro = mNbr; 894 progStatus.skip_sked_macro = true; 895 } 896 } 897 que_ok = true; 898 } 899 900 static void pTIMER(std::string &s, size_t &i, size_t endbracket) 901 { 902 if (within_exec) { 903 substitute(s, i, endbracket, ""); 904 return; 905 } 906 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTIMER }; 907 push_rxcmd(cmd); 908 substitute(s, i, endbracket, ""); 909 } 910 911 static void doAFTER(std::string s) 912 { 913 int number; 914 std::string sTime = s.substr(7); 915 if (sTime.length() > 0) { 916 sscanf(sTime.c_str(), "%d", &number); 917 progStatus.timer = number; 918 progStatus.timerMacro = mNbr; 919 progStatus.skip_sked_macro = true; 920 } 921 que_ok = true; 922 } 923 924 static void pAFTER(std::string &s, size_t &i, size_t endbracket) 925 { 926 if (within_exec) { 927 substitute(s, i, endbracket, ""); 928 return; 929 } 930 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doAFTER }; 931 push_rxcmd(cmd); 932 substitute(s, i, endbracket, ""); 933 } 934 935 static void pREPEAT(std::string &s, size_t &i, size_t endbracket) 936 { 937 if (within_exec) { 938 substitute(s, i, endbracket, ""); 939 return; 940 } 941 progStatus.repeatMacro = mNbr; 942 substitute(s, i, endbracket, ""); 943 text2repeat = s; 944 repeatchar = 0; 945 s.insert(i, "[REPEAT]"); 946 } 947 948 static void pWPM(std::string &s, size_t &i, size_t endbracket) 949 { 950 if (within_exec) { 951 substitute(s, i, endbracket, ""); 952 return; 953 } 954 float number; 955 std::string snumber = s.substr(i+5, endbracket - i - 5); 956 957 if (snumber.length() > 0) { 958 959 // first value = WPM 960 sscanf(snumber.c_str(), "%f", &number); 961 if (number < 5) number = 5; 962 if (number > 200) number = 200; 963 progdefaults.CWspeed = number; 964 setwpm(number); 965 966 // second value = Farnsworth WPM 967 size_t pos; 968 if ((pos = snumber.find(":")) != std::string::npos) { 969 snumber.erase(0, pos+1); 970 if (snumber.length()) 971 sscanf(snumber.c_str(), "%f", &number); 972 if (number < 5) number = 5; 973 if (number > progdefaults.CWspeed) number = progdefaults.CWspeed; 974 progdefaults.CWfarnsworth = number; 975 if (number == progdefaults.CWspeed) 976 setwpm(number); 977 else 978 setfwpm(number); 979 } 980 } 981 982 substitute(s, i, endbracket, ""); 983 } 984 985 static void pRISETIME(std::string &s, size_t &i, size_t endbracket) 986 { 987 if (within_exec) { 988 substitute(s, i, endbracket, ""); 989 return; 990 } 991 float number; 992 std::string sVal = s.substr(i+6, endbracket - i - 6); 993 if (sVal.length() > 0) { 994 sscanf(sVal.c_str(), "%f", &number); 995 if (number < 0) number = 0; 996 if (number > 20) number = 20; 997 progdefaults.CWrisetime = number; 998 cntCWrisetime->value(number); 999 } 1000 substitute(s, i, endbracket, ""); 1001 } 1002 1003 static void pPRE(std::string &s, size_t &i, size_t endbracket) 1004 { 1005 if (within_exec) { 1006 substitute(s, i, endbracket, ""); 1007 return; 1008 } 1009 float number; 1010 std::string sVal = s.substr(i+5, endbracket - i - 5); 1011 if (sVal.length() > 0) { 1012 sscanf(sVal.c_str(), "%f", &number); 1013 if (number < 0) number = 0; 1014 if (number > 20) number = 20; 1015 progdefaults.CWpre = number; 1016 cntPreTiming->value(number); 1017 } 1018 substitute(s, i, endbracket, ""); 1019 } 1020 1021 static void pPOST(std::string &s, size_t &i, size_t endbracket) 1022 { 1023 if (within_exec) { 1024 substitute(s, i, endbracket, ""); 1025 return; 1026 } 1027 float number; 1028 std::string sVal = s.substr(i+6, endbracket - i - 6); 1029 if (sVal.length() > 0) { 1030 sscanf(sVal.c_str(), "%f", &number); 1031 if (number < -20) number = -20; 1032 if (number > 20) number = 20; 1033 progdefaults.CWpost = number; 1034 cntPostTiming->value(number); 1035 } 1036 substitute(s, i, endbracket, ""); 1037 } 1038 1039 static void doWPM(std::string s) 1040 { 1041 float number; 1042 std::string snumber = s.substr(6); 1043 1044 if (snumber.length() > 0) { 1045 1046 // first value = WPM 1047 sscanf(snumber.c_str(), "%f", &number); 1048 if (number < 5) number = 5; 1049 if (number > 200) number = 200; 1050 progdefaults.CWspeed = number; 1051 REQ(setwpm, number); 1052 1053 // second value = Farnsworth WPM 1054 size_t pos; 1055 if ((pos = snumber.find(":")) != std::string::npos) { 1056 snumber.erase(0, pos+1); 1057 if (snumber.length()) 1058 sscanf(snumber.c_str(), "%f", &number); 1059 if (number < 5) number = 5; 1060 if (number > progdefaults.CWspeed) number = progdefaults.CWspeed; 1061 progdefaults.CWfarnsworth = number; 1062 if (number == progdefaults.CWspeed) 1063 REQ(setwpm, number); 1064 else 1065 REQ(setfwpm, number); 1066 } 1067 } 1068 1069 } 1070 1071 static void pTxQueWPM(std::string &s, size_t &i, size_t endbracket) 1072 { 1073 if (within_exec) { 1074 substitute(s, i, endbracket, ""); 1075 return; 1076 } 1077 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doWPM }; 1078 push_txcmd(cmd); 1079 substitute(s, i, endbracket, "^!"); 1080 } 1081 1082 struct STRpush { 1083 string smode; 1084 int freq; 1085 STRpush() { smode = ""; freq = -1; } 1086 }; 1087 1088 stack<STRpush> mf_stack; 1089 1090 //static string mf_stack = ""; 1091 1092 static void mMODEM(std::string s) 1093 { 1094 trx_mode m; 1095 s = ucasestr(s); 1096 for (m = 0; m < NUM_MODES; m++) 1097 if (s == ucasestr(mode_info[m].sname)) 1098 break; 1099 if (m == NUM_MODES) { 1100 return; 1101 } 1102 if (active_modem->get_mode() != mode_info[m].mode) 1103 init_modem_sync(mode_info[m].mode); 1104 } 1105 1106 static void mFREQ(int f) 1107 { 1108 active_modem->set_freq(f); 1109 } 1110 1111 static void doPOP(std::string s) 1112 { 1113 if (!mf_stack.empty()) { 1114 STRpush psh = mf_stack.top(); 1115 mf_stack.pop(); 1116 LOG_INFO("%s, %d", psh.smode.c_str(), psh.freq); 1117 if (psh.freq != -1) mFREQ(psh.freq); 1118 if (!psh.smode.empty()) mMODEM(psh.smode); 1119 } else 1120 LOG_INFO("%s", "stack empty"); 1121 que_ok = true; 1122 } 1123 1124 static void pPOP(std::string &s, size_t &i, size_t endbracket) 1125 { 1126 if (!mf_stack.empty()) { 1127 STRpush psh = mf_stack.top(); 1128 mf_stack.pop(); 1129 LOG_INFO("%s, %d", psh.smode.c_str(), psh.freq); 1130 if (psh.freq != -1) mFREQ(psh.freq); 1131 if (!psh.smode.empty()) mMODEM(psh.smode); 1132 } else 1133 LOG_INFO("%s", "stack empty"); 1134 substitute(s, i, endbracket, ""); 1135 } 1136 1137 static void pTxQuePOP(std::string &s, size_t &i, size_t endbracket) 1138 { 1139 if (within_exec) { 1140 substitute(s, i, endbracket, ""); 1141 return; 1142 } 1143 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPOP }; 1144 push_txcmd(cmd); 1145 substitute(s, i, endbracket, "^!"); 1146 } 1147 1148 static void pRxQuePOP(std::string &s, size_t &i, size_t endbracket) 1149 { 1150 if (within_exec) { 1151 substitute(s, i, endbracket, ""); 1152 return; 1153 } 1154 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPOP }; 1155 push_rxcmd(cmd); 1156 substitute(s, i, endbracket, ""); 1157 } 1158 1159 static void doPUSHmode(std::string s) 1160 { 1161 STRpush psh; 1162 if (s[5] == '>') { 1163 psh.smode = mode_info[active_modem->get_mode()].sname; 1164 psh.freq = active_modem->get_freq(); 1165 } else { 1166 if (s[5] == ':') { 1167 if (s[6] == 'm' || s[7] == 'm') 1168 psh.smode = mode_info[active_modem->get_mode()].sname; 1169 if (s[6] == 'f' || s[7] == 'f') 1170 psh.freq = active_modem->get_freq(); 1171 } 1172 } 1173 LOG_INFO("%s, %d", psh.smode.c_str(), psh.freq); 1174 mf_stack.push(psh); 1175 que_ok = true; 1176 } 1177 1178 static void pTxQuePUSH(std::string &s, size_t &i, size_t endbracket) 1179 { 1180 if (within_exec) { 1181 substitute(s, i, endbracket, ""); 1182 return; 1183 } 1184 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPUSHmode }; 1185 push_txcmd(cmd); 1186 substitute(s, i, endbracket, "^!"); 1187 } 1188 1189 static void pRxQuePUSH(std::string &s, size_t &i, size_t endbracket) 1190 { 1191 if (within_exec) { 1192 substitute(s, i, endbracket, ""); 1193 return; 1194 } 1195 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPUSHmode }; 1196 push_rxcmd(cmd); 1197 // substitute(s, i, endbracket, "^!"); 1198 substitute(s, i, endbracket, ""); 1199 } 1200 1201 static void pPUSH(std::string &s, size_t &i, size_t endbracket) 1202 { 1203 STRpush psh; 1204 if (s[i+5] == '>') { 1205 psh.smode = mode_info[active_modem->get_mode()].sname; 1206 psh.freq = active_modem->get_freq(); 1207 } else { 1208 if (s[i+5] == ':') { 1209 if (s[i+6] == 'm' || s[i+7] == 'm') 1210 psh.smode = mode_info[active_modem->get_mode()].sname; 1211 if (s[i+6] == 'f' || s[i+7] == 'f') 1212 psh.freq = active_modem->get_freq(); 1213 } 1214 } 1215 LOG_INFO("%s, %d", psh.smode.c_str(), psh.freq); 1216 mf_stack.push(psh); 1217 substitute(s, i, endbracket, ""); 1218 return; 1219 } 1220 1221 static void pDIGI(std::string &s, size_t &i, size_t endbracket) 1222 { 1223 s.replace(i, endbracket - i + 1, mode_info[active_modem->get_mode()].adif_name); 1224 } 1225 1226 string macrochar = ""; 1227 static void doTxDIGI(std::string s) 1228 { 1229 macrochar = mode_info[active_modem->get_mode()].adif_name; 1230 que_ok = true; 1231 } 1232 1233 static void pTxDIGI(std::string &s, size_t &i, size_t endbracket) 1234 { 1235 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTxDIGI }; 1236 push_txcmd(cmd); 1237 substitute(s, i, endbracket, "^!"); 1238 } 1239 1240 static void doTxFREQ(std::string s) 1241 { 1242 macrochar = inpFreq->value(); 1243 que_ok = true; 1244 } 1245 1246 static void pTxFREQ(std::string &s, size_t &i, size_t endbracket) 1247 { 1248 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTxFREQ }; 1249 push_txcmd(cmd); 1250 substitute(s, i, endbracket, "^!"); 1251 } 1252 1253 static void setRISETIME(int d) 1254 { 1255 cntCWrisetime->value(d); 1256 que_ok = true; 1257 } 1258 1259 static void doRISETIME(std::string s) 1260 { 1261 float number; 1262 std::string sVal = s.substr(7, s.length() - 8); 1263 if (sVal.length() > 0) { 1264 sscanf(sVal.c_str(), "%f", &number); 1265 if (number < 0) number = 0; 1266 if (number > 20) number = 20; 1267 progdefaults.CWrisetime = number; 1268 REQ(setRISETIME, number); 1269 } 1270 } 1271 1272 static void pTxQueRISETIME(std::string &s, size_t &i, size_t endbracket) 1273 { 1274 if (within_exec) { 1275 substitute(s, i, endbracket, ""); 1276 return; 1277 } 1278 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRISETIME }; 1279 push_txcmd(cmd); 1280 substitute(s, i, endbracket, "^!"); 1281 } 1282 1283 static void setPRE(int d) 1284 { 1285 cntPreTiming->value(d); 1286 que_ok = true; 1287 } 1288 1289 static void doPRE(std::string s) 1290 { 1291 float number; 1292 std::string sVal = s.substr(6, s.length() - 7); 1293 if (sVal.length() > 0) { 1294 sscanf(sVal.c_str(), "%f", &number); 1295 if (number < 0) number = 0; 1296 if (number > 20) number = 20; 1297 progdefaults.CWpre = number; 1298 REQ(setPRE, number); 1299 } 1300 } 1301 1302 static void pTxQuePRE(std::string &s, size_t &i, size_t endbracket) 1303 { 1304 if (within_exec) { 1305 substitute(s, i, endbracket, ""); 1306 return; 1307 } 1308 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPRE }; 1309 push_txcmd(cmd); 1310 substitute(s, i, endbracket, "^!"); 1311 } 1312 1313 static void setPOST(int d) 1314 { 1315 cntPostTiming->value(d); 1316 que_ok = true; 1317 } 1318 1319 static void doPOST(std::string s) 1320 { 1321 float number; 1322 std::string sVal = s.substr(7, s.length() - 8); 1323 if (sVal.length() > 0) { 1324 sscanf(sVal.c_str(), "%f", &number); 1325 if (number < -20) number = -20; 1326 if (number > 20) number = 20; 1327 progdefaults.CWpost = number; 1328 REQ(setPOST, number); 1329 } 1330 } 1331 1332 static void pTxQuePOST(std::string &s, size_t &i, size_t endbracket) 1333 { 1334 if (within_exec) { 1335 substitute(s, i, endbracket, ""); 1336 return; 1337 } 1338 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doPOST }; 1339 push_txcmd(cmd); 1340 substitute(s, i, endbracket, "^!"); 1341 } 1342 1343 static void setTXATTEN(float v) 1344 { 1345 int d = (int)(v * 10); 1346 v = d / 10.0; 1347 v = clamp(v, -30.0, 0.0); 1348 progdefaults.txlevel = v; 1349 cntTxLevel->value(progdefaults.txlevel);; 1350 que_ok = true; 1351 } 1352 1353 static void pTXATTEN(std::string &s, size_t &i, size_t endbracket) 1354 { 1355 if (within_exec) { 1356 substitute(s, i, endbracket, ""); 1357 return; 1358 } 1359 float number; 1360 std::string sVal = s.substr(i+9, endbracket - i - 9); 1361 if (sVal.length() > 0) { 1362 sscanf(sVal.c_str(), "%f", &number); 1363 setTXATTEN(number); 1364 } 1365 substitute(s, i, endbracket, ""); 1366 } 1367 1368 static void doTXATTEN(std::string s) 1369 { 1370 float number; 1371 std::string sVal = s.substr(10); 1372 if (sVal.length() > 0) { 1373 sscanf(sVal.c_str(), "%f", &number); 1374 REQ(setTXATTEN, number); 1375 } 1376 } 1377 1378 static void pTxQueTXATTEN(std::string &s, size_t &i, size_t endbracket) 1379 { 1380 if (within_exec) { 1381 substitute(s, i, endbracket, ""); 1382 return; 1383 } 1384 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTXATTEN }; 1385 push_txcmd(cmd); 1386 substitute(s, i, endbracket, ""); 1387 } 1388 1389 static void pIDLE(std::string &s, size_t &i, size_t endbracket) 1390 { 1391 if (within_exec) { 1392 substitute(s, i, endbracket, ""); 1393 return; 1394 } 1395 float number; 1396 std::string sTime = s.substr(i+6, endbracket - i - 6); 1397 if (sTime.length() > 0) { 1398 sscanf(sTime.c_str(), "%f", &number); 1399 macro_idle_on = true; 1400 idleTime = number; 1401 } 1402 substitute(s, i, endbracket, ""); 1403 } 1404 1405 static int idle_time = 0; // in 0.1 second increments 1406 static int idle_count = 0; 1407 static void doneIDLE(void *) 1408 { 1409 idle_count++; 1410 if (idle_count == idle_time) { 1411 Qidle_time = 0; 1412 que_ok = true; 1413 idle_time = idle_count = 0; 1414 return; 1415 } 1416 Fl::repeat_timeout(0.1, doneIDLE); 1417 } 1418 1419 static void doIDLE(std::string s) 1420 { 1421 std::string sTime = s.substr(7, s.length() - 8); 1422 if (sTime.length() > 0) { 1423 float ftime; 1424 if (sscanf(sTime.c_str(), "%f", &ftime) != 1) 1425 ftime = 1.0; 1426 idle_time = 10 * ftime; 1427 Qidle_time = 1; 1428 Fl::add_timeout(0.1, doneIDLE); 1429 } else { 1430 Qidle_time = 0; 1431 } 1432 } 1433 1434 static void pTxQueIDLE(std::string &s, size_t &i, size_t endbracket) 1435 { 1436 if (within_exec) { 1437 substitute(s, i, endbracket, ""); 1438 return; 1439 } 1440 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doIDLE }; 1441 push_txcmd(cmd); 1442 substitute(s, i, endbracket, "^!"); 1443 } 1444 1445 bool do_tune_on; 1446 static bool tune_on; 1447 static bool rx_tune_on; 1448 static float tune_timeout = 0; 1449 1450 static void start_tune(void *) 1451 { 1452 trx_tune(); 1453 } 1454 1455 static void end_tune(void *data = 0) 1456 { 1457 if (data == 0) 1458 trx_receive(); 1459 else 1460 trx_transmit(); 1461 tune_on = false; 1462 } 1463 1464 static void end_do_tune(void *) 1465 { 1466 trx_transmit(); 1467 do_tune_on = false; 1468 } 1469 1470 static void doTUNE(std::string s) 1471 { 1472 std::string sTime = s.substr(7, s.length() - 8); 1473 1474 if (sTime.length() > 0) { 1475 if (sscanf(sTime.c_str(), "%f", &tune_timeout) != 1) 1476 tune_timeout = 1.0; 1477 do_tune_on = true; 1478 Fl::add_timeout(0, start_tune); 1479 Fl::add_timeout(tune_timeout, end_do_tune); 1480 } 1481 que_ok = true; 1482 } 1483 1484 static void pTxQueTUNE(std::string &s, size_t &i, size_t endbracket) 1485 { 1486 if (within_exec) { 1487 substitute(s, i, endbracket, ""); 1488 return; 1489 } 1490 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTUNE }; 1491 push_txcmd(cmd); 1492 substitute(s, i, endbracket, "^!"); 1493 } 1494 1495 static void end_rxtune(void *) 1496 { 1497 trx_receive(); 1498 rx_tune_on = false; 1499 } 1500 1501 static void doRxTUNE(std::string s) 1502 { 1503 std::string sTime = s.substr(7, s.length() - 8); 1504 1505 if (sTime.length() > 0) { 1506 if (sscanf(sTime.c_str(), "%f", &tune_timeout) != 1) 1507 tune_timeout = 1.0; 1508 rx_tune_on = true; 1509 Fl::add_timeout(0, start_tune); 1510 Fl::add_timeout(tune_timeout, end_rxtune); 1511 } 1512 } 1513 1514 static void pRxQueTUNE(std::string &s, size_t &i, size_t endbracket) 1515 { 1516 if (within_exec) { 1517 substitute(s, i, endbracket, ""); 1518 return; 1519 } 1520 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRxTUNE }; 1521 push_rxcmd(cmd); 1522 substitute(s, i, endbracket, ""); 1523 } 1524 1525 static void pTUNE(std::string &s, size_t &i, size_t endbracket) 1526 { 1527 if (within_exec) { 1528 substitute(s, i, endbracket, ""); 1529 return; 1530 } 1531 std::string sTime = s.substr(i+6, endbracket - i - 6); 1532 if (sTime.length() > 0) { 1533 if (sscanf(sTime.c_str(), "%f", &tune_timeout) != 1) 1534 tune_timeout = 1.0; 1535 tune_on = true; 1536 Fl::add_timeout(0, start_tune); 1537 } 1538 1539 substitute(s, i, endbracket, ""); 1540 } 1541 1542 static void pQSONBR(std::string &s, size_t &i, size_t endbracket) 1543 { 1544 if (within_exec) { 1545 s.replace(i, endbracket - i + 1, ""); 1546 return; 1547 } 1548 char szqsonbr[10]; 1549 snprintf(szqsonbr, sizeof(szqsonbr), "%d", qsodb.nbrRecs()); 1550 s.replace(i, endbracket - i + 1, szqsonbr); 1551 } 1552 1553 static void pNXTNBR(std::string &s, size_t &i, size_t endbracket) 1554 { 1555 if (within_exec) { 1556 s.replace(i, endbracket - i + 1, ""); 1557 return; 1558 } 1559 char szqsonbr[20]; 1560 snprintf(szqsonbr, sizeof(szqsonbr), "%d", qsodb.nbrRecs() + 1); 1561 s.replace(i, endbracket - i + 1, szqsonbr); 1562 } 1563 1564 static void pNRSID(std::string &s, size_t &i, size_t endbracket) 1565 { 1566 if (within_exec) { 1567 substitute(s, i, endbracket, ""); 1568 return; 1569 } 1570 int number = 0; 1571 std::string sNumber = s.substr(i+7, endbracket - i - 7); 1572 if (sNumber.length() > 0) { 1573 sscanf(sNumber.c_str(), "%d", &number); 1574 progStatus.n_rsids = number; 1575 } 1576 substitute(s, i, endbracket, ""); 1577 } 1578 1579 static bool useWait = false; 1580 static float waitTime = 0; 1581 1582 static void pWAIT(std::string &s, size_t &i, size_t endbracket) 1583 { 1584 if (within_exec) { 1585 substitute(s, i, endbracket, ""); 1586 return; 1587 } 1588 float number; 1589 std::string sTime = s.substr(i+6, endbracket - i - 6); 1590 if (sTime.length() > 0) { 1591 sscanf(sTime.c_str(), "%f", &number); 1592 useWait = true; 1593 waitTime = number; 1594 } 1595 substitute(s, i, endbracket, ""); 1596 } 1597 1598 static void doneWAIT(void *) 1599 { 1600 Qwait_time = 0; 1601 start_tx(); 1602 que_ok = true; 1603 } 1604 1605 static void doWAIT(std::string s) 1606 { 1607 float number; 1608 std::string sTime = s.substr(7, s.length() - 8); 1609 if (sTime.length() > 0) { 1610 sscanf(sTime.c_str(), "%f", &number); 1611 Qwait_time = number; 1612 Fl::add_timeout (number, doneWAIT); 1613 } else 1614 Qwait_time = 0; 1615 } 1616 1617 static void pTxQueWAIT(std::string &s, size_t &i, size_t endbracket) 1618 { 1619 if (within_exec) { 1620 substitute(s, i, endbracket, ""); 1621 return; 1622 } 1623 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doWAIT }; 1624 push_txcmd(cmd); 1625 substitute(s, i, endbracket, "^!"); 1626 } 1627 1628 static void doRxWAIT(std::string s) 1629 { 1630 float number = 0; 1631 std::string sTime = s.substr(7, s.length() - 8); 1632 if (sTime.length() > 0) { 1633 sscanf(sTime.c_str(), "%f", &number); 1634 macro_rx_wait = true; 1635 Fl::add_timeout(number, rx_que_continue); 1636 } 1637 } 1638 1639 static void pRxQueWAIT(std::string &s, size_t &i, size_t endbracket) 1640 { 1641 if (within_exec) { 1642 substitute(s, i, endbracket, ""); 1643 return; 1644 } 1645 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRxWAIT }; 1646 push_rxcmd(cmd); 1647 substitute(s, i, endbracket, ""); 1648 } 1649 1650 static void pINFO1(std::string &s, size_t &i, size_t endbracket) 1651 { 1652 s.replace( i, 7, info1msg ); 1653 } 1654 1655 static void pINFO2(std::string &s, size_t &i, size_t endbracket) 1656 { 1657 s.replace( i, 7, info2msg ); 1658 } 1659 1660 static void pCLRRX(std::string &s, size_t &i, size_t endbracket) 1661 { 1662 if (within_exec) { 1663 substitute(s, i, endbracket, ""); 1664 return; 1665 } 1666 substitute(s, i, endbracket, ""); 1667 trx_mode md = active_modem->get_mode(); 1668 1669 if (md == MODE_IFKP) 1670 ifkp_rx_text->clear(); 1671 else if (md == MODE_FSQ) 1672 fsq_rx_text->clear(); 1673 else if ((md >= MODE_FELDHELL) && (md <= MODE_HELL80)) 1674 FHdisp->clear(); 1675 else 1676 ReceiveText->clear(); 1677 } 1678 1679 static void pCLRTX(std::string &s, size_t &i, size_t endbracket) 1680 { 1681 if (within_exec) { 1682 substitute(s, i, endbracket, ""); 1683 return; 1684 } 1685 substitute(s, i, endbracket, ""); 1686 queue_reset(); 1687 if (active_modem->get_mode() == MODE_IFKP) 1688 ifkp_tx_text->clear(); 1689 else if (active_modem->get_mode() == MODE_FSQ) 1690 fsq_tx_text->clear(); 1691 else 1692 TransmitText->clear(); 1693 } 1694 1695 static void pCLRQSO(std::string &s, size_t &i, size_t endbracket) 1696 { 1697 if (within_exec) { 1698 substitute(s, i, endbracket, ""); 1699 return; 1700 } 1701 substitute(s, i, endbracket, ""); 1702 clearQSO(); 1703 } 1704 1705 static void pFOCUS(std::string &s, size_t &i, size_t endbracket) 1706 { 1707 if (!within_exec) { 1708 if (qsoFreqDisp->is_reversed_colors()) { 1709 qsoFreqDisp->restore_colors(); 1710 if (active_modem->get_mode() == MODE_IFKP) 1711 ifkp_tx_text->take_focus(); 1712 else if (active_modem->get_mode() == MODE_FSQ) 1713 fsq_tx_text->take_focus (); 1714 else 1715 TransmitText->take_focus(); 1716 } else { 1717 qsoFreqDisp->take_focus(); 1718 qsoFreqDisp->reverse_colors(); 1719 } 1720 } 1721 substitute(s, i, endbracket, ""); 1722 } 1723 1724 static void pQSYPLUS(std::string &s, size_t &i, size_t endbracket) 1725 { 1726 if (within_exec) { 1727 substitute(s, i, endbracket, ""); 1728 return; 1729 } 1730 int rf = 0; 1731 float rfd = 0; 1732 std::string sIncrFreq = s.substr(i+6, endbracket - i - 6); 1733 // no frequency(s) specified 1734 if (sIncrFreq.length() == 0) { 1735 substitute(s, i, endbracket, ""); 1736 return; 1737 } 1738 // rf first value 1739 sscanf(sIncrFreq.c_str(), "%f", &rfd); 1740 if (rfd != 0) { 1741 rf = wf->rfcarrier() + (int)(1000*rfd); 1742 qsy(rf, active_modem ? active_modem->get_freq() : 1500); 1743 } 1744 substitute(s, i, endbracket, ""); 1745 } 1746 1747 static void pCALL(std::string &s, size_t &i, size_t endbracket) 1748 { 1749 string call = inpCall->value(); 1750 if (active_modem->get_mode() == MODE_IFKP && progdefaults.ifkp_lowercase_call) 1751 for (size_t n = 0; n < call.length(); n++) call[n] = tolower(call[n]); 1752 s.replace( i, 6, call ); 1753 } 1754 1755 static void pGET(std::string &s, size_t &i, size_t endbracket) 1756 { 1757 s.erase( i, 9 ); 1758 GET = true; 1759 } 1760 1761 static void pFREQ(std::string &s, size_t &i, size_t endbracket) 1762 { 1763 s.replace( i, 6, inpFreq->value() ); 1764 } 1765 1766 static void pBAND(std::string &s, size_t &i, size_t endbracket) 1767 { 1768 s.replace( i, 6, band_name( band( wf->rfcarrier() ) ) ); 1769 } 1770 1771 static void pLOC(std::string &s, size_t &i, size_t endbracket) 1772 { 1773 s.replace( i, 5, inpLoc->value() ); 1774 } 1775 1776 static void pMODE(std::string &s, size_t &i, size_t endbracket) 1777 { 1778 s.replace( i, 6, active_modem->get_mode_name()); 1779 } 1780 1781 static void pNAME(std::string &s, size_t &i, size_t endbracket) 1782 { 1783 s.replace( i, 6, inpName->value() ); 1784 } 1785 1786 static void pQTH(std::string &s, size_t &i, size_t endbracket) 1787 { 1788 s.replace( i,5, inpQth->value() ); 1789 } 1790 1791 static void pST(std::string &s, size_t &i, size_t endbracket) 1792 { 1793 s.replace( i, 4, inpState->value() ); 1794 } 1795 1796 static void pPR(std::string &s, size_t &i, size_t endbracket) 1797 { 1798 s.replace( i, 4, inpVEprov->value() ); 1799 } 1800 1801 static void pQSOTIME(std::string &s, size_t &i, size_t endbracket) 1802 { 1803 qso_time = inpTimeOff->value(); 1804 s.replace( i, 9, qso_time.c_str() ); 1805 } 1806 1807 static void pRST(std::string &s, size_t &i, size_t endbracket) 1808 { 1809 s.replace( i, 5, cut_string(inpRstOut->value())); 1810 } 1811 1812 static void pMYCALL(std::string &s, size_t &i, size_t endbracket) 1813 { 1814 string call = inpMyCallsign->value(); 1815 if (active_modem->get_mode() == MODE_IFKP && progdefaults.ifkp_lowercase) 1816 for (size_t n = 0; n < call.length(); n++) call[n] = tolower(call[n]); 1817 s.replace( i, 8, call ); 1818 } 1819 1820 static void pMYLOC(std::string &s, size_t &i, size_t endbracket) 1821 { 1822 s.replace( i, 7, inpMyLocator->value() ); 1823 } 1824 1825 static void pMYNAME(std::string &s, size_t &i, size_t endbracket) 1826 { 1827 s.replace( i, 8, inpMyName->value() ); 1828 } 1829 1830 static void pMYQTH(std::string &s, size_t &i, size_t endbracket) 1831 { 1832 s.replace( i, 7, inpMyQth->value() ); 1833 } 1834 1835 static void pMYRST(std::string &s, size_t &i, size_t endbracket) 1836 { 1837 s.replace( i, 7, inpRstIn->value() ); 1838 } 1839 1840 static void pANTENNA(std::string &s, size_t &i, size_t endbracket) 1841 { 1842 s.replace( i, 9, progdefaults.myAntenna.c_str() ); 1843 } 1844 1845 static void pMYCLASS(std::string &s, size_t &i, size_t endbracket) 1846 { 1847 s.replace( i, 9, progdefaults.my_FD_class.c_str() ); 1848 } 1849 1850 static void pMYSECTION(std::string &s, size_t &i, size_t endbracket) 1851 { 1852 s.replace( i, 11, progdefaults.my_FD_section.c_str() ); 1853 } 1854 1855 static void pMYSTATE(std::string &s, size_t &i, size_t endbracket) 1856 { 1857 s.replace( i, 9, listbox_states->value() ); 1858 } 1859 1860 static void pMYST(std::string &s, size_t &i, size_t endbracket) 1861 { 1862 s.replace( i, 6, inp_QP_state_short->value() ); 1863 } 1864 1865 static void pMYCOUNTY(std::string &s, size_t &i, size_t endbracket) 1866 { 1867 s.replace( i, 10, listbox_counties->value() ); 1868 } 1869 1870 static void pMYCNTY(std::string &s, size_t &i, size_t endbracket) 1871 { 1872 s.replace( i, 8, inp_QP_short_county->value() ); 1873 } 1874 1875 static void pLDT(std::string &s, size_t &i, size_t endbracket) 1876 { 1877 char szDt[80]; 1878 1879 std::string fmt = "%x %H:%M %Z"; 1880 std::string timefmt = s.substr(i, endbracket-i); 1881 1882 size_t p = timefmt.find(":"); 1883 if (p == 4) { 1884 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1885 if (fmt[0] == '"') fmt.erase(0,1); 1886 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1887 } 1888 1889 time_t tmptr; 1890 tm sTime; 1891 time (&tmptr); 1892 localtime_r(&tmptr, &sTime); 1893 mystrftime(szDt, 79, fmt.c_str(), &sTime); 1894 s.replace(i, endbracket - i + 1, szDt); 1895 } 1896 1897 static void pILDT(std::string &s, size_t &i, size_t endbracket) 1898 { 1899 char szDt[80]; 1900 1901 std::string fmt = "%Y-%m-%d %H:%M%z"; 1902 std::string timefmt = s.substr(i, endbracket-i); 1903 1904 size_t p = timefmt.find(":"); 1905 if (p == 5) { 1906 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1907 if (fmt[0] == '"') fmt.erase(0,1); 1908 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1909 } 1910 1911 time_t tmptr; 1912 tm sTime; 1913 time (&tmptr); 1914 localtime_r(&tmptr, &sTime); 1915 mystrftime(szDt, 79, fmt.c_str(), &sTime); 1916 s.replace(i, endbracket - i + 1, szDt); 1917 } 1918 1919 static void pZDT(std::string &s, size_t &i, size_t endbracket) 1920 { 1921 char szDt[80]; 1922 1923 std::string fmt = "%x %H:%MZ"; 1924 std::string timefmt = s.substr(i, endbracket - i); 1925 1926 size_t p = timefmt.find(":"); 1927 if (p == 4) { 1928 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1929 if (fmt[0] == '"') fmt.erase(0,1); 1930 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1931 } 1932 1933 time_t tmptr; 1934 tm sTime; 1935 time (&tmptr); 1936 gmtime_r(&tmptr, &sTime); 1937 mystrftime(szDt, 79, fmt.c_str(), &sTime); 1938 s.replace(i, endbracket - i + 1, szDt); 1939 } 1940 1941 static void pIZDT(std::string &s, size_t &i, size_t endbracket) 1942 { 1943 char szDt[80]; 1944 1945 std::string fmt = "%Y-%m-%d %H:%MZ"; 1946 std::string timefmt = s.substr(i, endbracket-i); 1947 1948 size_t p = timefmt.find(":"); 1949 if (p == 5) { 1950 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1951 if (fmt[0] == '"') fmt.erase(0,1); 1952 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1953 } 1954 1955 time_t tmptr; 1956 tm sTime; 1957 time (&tmptr); 1958 gmtime_r(&tmptr, &sTime); 1959 mystrftime(szDt, 79, fmt.c_str(), &sTime); 1960 s.replace(i, endbracket - i + 1, szDt); 1961 } 1962 1963 static void pLT(std::string &s, size_t &i, size_t endbracket) 1964 { 1965 char szDt[80]; 1966 1967 std::string fmt = "%H%ML"; 1968 std::string timefmt = s.substr(i, endbracket-i); 1969 1970 size_t p = timefmt.find(":"); 1971 if (p == 3) { 1972 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1973 if (fmt[0] == '"') fmt.erase(0,1); 1974 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1975 } 1976 1977 time_t tmptr; 1978 tm sTime; 1979 time (&tmptr); 1980 localtime_r(&tmptr, &sTime); 1981 mystrftime(szDt, 79, fmt.c_str(), &sTime); 1982 s.replace(i, endbracket - i + 1, szDt); 1983 } 1984 1985 static void pZT(std::string &s, size_t &i, size_t endbracket) 1986 { 1987 char szDt[80]; 1988 1989 std::string fmt = "%H%MZ"; 1990 std::string timefmt = s.substr(i, endbracket-i); 1991 1992 size_t p = timefmt.find(":"); 1993 if (p == 3) { 1994 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 1995 if (fmt[0] == '"') fmt.erase(0,1); 1996 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 1997 } 1998 1999 time_t tmptr; 2000 tm sTime; 2001 time (&tmptr); 2002 gmtime_r(&tmptr, &sTime); 2003 mystrftime(szDt, 79, fmt.c_str(), &sTime); 2004 s.replace(i, endbracket - i + 1, szDt); 2005 } 2006 2007 static void pLD(std::string &s, size_t &i, size_t endbracket) 2008 { 2009 char szDt[80]; 2010 2011 std::string fmt = "%Y-%m-%d"; 2012 std::string timefmt = s.substr(i, endbracket - i); 2013 2014 size_t p = timefmt.find(":"); 2015 if (p == 3) { 2016 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 2017 if (fmt[0] == '"') fmt.erase(0,1); 2018 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 2019 } 2020 2021 time_t tmptr; 2022 tm sTime; 2023 time (&tmptr); 2024 localtime_r(&tmptr, &sTime); 2025 mystrftime(szDt, 79, fmt.c_str(), &sTime); 2026 s.replace(i, endbracket - i + 1, szDt); 2027 } 2028 2029 static void pZD(std::string &s, size_t &i, size_t endbracket) 2030 { 2031 char szDt[80]; 2032 2033 std::string fmt = "%Y-%m-%d"; 2034 std::string timefmt = s.substr(i, endbracket - i); 2035 2036 size_t p = timefmt.find(":"); 2037 if (p == 3) { 2038 fmt = timefmt.substr(p + 1, timefmt.length() - p - 1); 2039 if (fmt[0] == '"') fmt.erase(0,1); 2040 if (fmt[fmt.length()-1] == '"') fmt.erase(fmt.length()-1); 2041 } 2042 2043 time_t tmptr; 2044 tm sTime; 2045 time (&tmptr); 2046 gmtime_r(&tmptr, &sTime); 2047 mystrftime(szDt, 79, fmt.c_str(), &sTime); 2048 s.replace(i, endbracket - i + 1, szDt); 2049 } 2050 2051 static void p_ID(std::string &s, size_t &i, size_t endbracket) 2052 { 2053 if (within_exec) { 2054 substitute(s, i, endbracket, ""); 2055 return; 2056 } 2057 progdefaults.macroid = true; 2058 substitute(s, i, endbracket, ""); 2059 } 2060 2061 static void pTEXT(std::string &s, size_t &i, size_t endbracket) 2062 { 2063 if (within_exec) { 2064 substitute(s, i, endbracket, ""); 2065 return; 2066 } 2067 progdefaults.macrotextid = true; 2068 substitute(s, i, endbracket, ""); 2069 } 2070 2071 static void doCWID(std::string s) 2072 { 2073 progdefaults.macroCWid = true; 2074 que_ok = true; 2075 } 2076 2077 static void pCWID(std::string &s, size_t &i, size_t endbracket) 2078 { 2079 if (within_exec) { 2080 substitute(s, i, endbracket, ""); 2081 return; 2082 } 2083 CMDS cmd = {s.substr(i, endbracket - i + 1), doCWID}; 2084 push_txcmd(cmd); 2085 substitute(s, i, endbracket, "^!"); 2086 } 2087 2088 static void doDTMF(std::string s) 2089 { 2090 progdefaults.DTMFstr = s.substr(6, s.length() - 8); 2091 que_ok = true; 2092 } 2093 2094 static void pDTMF(std::string &s, size_t &i, size_t endbracket) 2095 { 2096 if (within_exec) { 2097 substitute(s, i, endbracket, ""); 2098 return; 2099 } 2100 CMDS cmd = {s.substr(i, endbracket - i + 1), doDTMF}; 2101 push_txcmd(cmd); 2102 substitute(s, i, endbracket, "^!"); 2103 } 2104 2105 static void pALERT(std::string &s, size_t &i, size_t endbracket) 2106 { 2107 if (trx_state != STATE_RX) { 2108 substitute(s, i, endbracket, ""); 2109 return; 2110 } 2111 2112 if (within_exec) { 2113 substitute(s, i, endbracket, ""); 2114 return; 2115 } 2116 std::string cmd = s.substr(i+7, endbracket - i - 7); 2117 if (audio_alert) 2118 try { 2119 audio_alert->alert(cmd); 2120 } catch (...) { 2121 } 2122 substitute(s, i, endbracket, ""); 2123 } 2124 2125 static void doAUDIO(std::string s) 2126 { 2127 s.erase(0, 16); 2128 active_modem->Audio_filename(s); 2129 que_ok = true; 2130 } 2131 2132 static void pAUDIO(std::string &s, size_t &i, size_t endbracket) 2133 { 2134 if (within_exec) { 2135 substitute(s, i, endbracket, ""); 2136 return; 2137 } 2138 std::string acmd = "Xmt audio file: "; 2139 acmd.append(s.substr(i + 7, endbracket - (i + 7))); 2140 CMDS cmd = {acmd, doAUDIO}; 2141 push_txcmd(cmd); 2142 substitute(s, i, endbracket, "^!"); 2143 } 2144 2145 static void pPAUSE(std::string &s, size_t &i, size_t endbracket) 2146 { 2147 if (within_exec) { 2148 substitute(s, i, endbracket, ""); 2149 return; 2150 } 2151 substitute(s, i, endbracket, ""); 2152 } 2153 2154 static void pRX(std::string &s, size_t &i, size_t endbracket) 2155 { 2156 if (within_exec) { 2157 substitute(s, i, endbracket, ""); 2158 return; 2159 } 2160 substitute(s, i, endbracket, "^r"); 2161 } 2162 2163 static void pTX(std::string &s, size_t &i, size_t endbracket) 2164 { 2165 if (within_exec) { 2166 substitute(s, i, endbracket, ""); 2167 return; 2168 } 2169 substitute(s, i, endbracket, ""); 2170 if (rx_only) 2171 TransmitON = false; 2172 else { 2173 start_macro_time(); 2174 TransmitON = true; 2175 } 2176 } 2177 2178 static void pTXRX(std::string &s, size_t &i, size_t endbracket) 2179 { 2180 if (within_exec) { 2181 substitute(s, i, endbracket, ""); 2182 return; 2183 } 2184 substitute(s, i, endbracket, ""); 2185 if (rx_only) 2186 ToggleTXRX = false; 2187 else 2188 ToggleTXRX = true; 2189 } 2190 2191 /* 2192 static std::string hexstr(std::string &s) 2193 { 2194 static std::string hex; 2195 static char val[3]; 2196 hex.clear(); 2197 for (size_t i = 0; i < s.length(); i++) { 2198 snprintf(val, sizeof(val), "%02x", s[i] & 0xFF); 2199 hex.append("<").append(val).append(">"); 2200 } 2201 return hex; 2202 } 2203 */ 2204 2205 static void doRIGCAT(std::string s) 2206 { 2207 size_t start = s.find(':'); 2208 std::string buff; 2209 2210 LOG_INFO("!RIGCAT %s", s.substr(start + 1, s.length() - start + 1).c_str()); 2211 2212 size_t val = 0; 2213 int retnbr = 0; 2214 char c, ch; 2215 bool asciisw = false; 2216 bool valsw = false; 2217 2218 for (size_t j = start+1 ; j <= s.length() ; j++) { 2219 ch = s[j]; 2220 if (ch == '\"') { 2221 asciisw = !asciisw; 2222 continue; 2223 } 2224 // accumulate ascii string 2225 if (asciisw) { 2226 if (isprint(ch)) buff += ch; 2227 continue; 2228 } 2229 // following digits is expected size of CAT response from xcvr 2230 if (ch == ':' && s[j+1] != '>') { 2231 sscanf(&s[j+1], "%d", &retnbr); 2232 } 2233 // accumulate hex string values 2234 if ((ch == ' ' || ch == '>' || ch == ':') && valsw) { 2235 c = char(val); 2236 // LOG_INFO("c=%02x, val=%d", c, val); 2237 buff += c; 2238 val = 0; 2239 valsw = false; 2240 } else { 2241 val *= 16; 2242 ch = toupper(ch); 2243 if (isdigit(ch)) val += ch - '0'; 2244 else if (ch >= 'A' && ch <= 'F') val += ch - 'A' + 10; 2245 valsw = true; 2246 } 2247 if (ch == ':') break; 2248 } 2249 2250 add_to_cmdque("RIGCAT macro", buff, retnbr, progdefaults.RigCatWait); 2251 2252 que_ok = true; 2253 } 2254 2255 static void pTxQueRIGCAT(std::string &s, size_t &i, size_t endbracket) 2256 { 2257 if (within_exec) { 2258 substitute(s, i, endbracket, ""); 2259 return; 2260 } 2261 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGCAT }; 2262 push_txcmd(cmd); 2263 substitute(s, i, endbracket, "^!"); 2264 } 2265 2266 static void pRxQueRIGCAT(std::string &s, size_t &i, size_t endbracket) 2267 { 2268 if (within_exec) { 2269 substitute(s, i, endbracket, ""); 2270 return; 2271 } 2272 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGCAT }; 2273 push_rxcmd(cmd); 2274 substitute(s, i, endbracket, ""); 2275 } 2276 2277 static void pRIGCAT(std::string &s, size_t &i, size_t endbracket) 2278 { 2279 if (within_exec) { 2280 substitute(s, i, endbracket, ""); 2281 return; 2282 } 2283 2284 LOG_INFO("cat cmd:retnbr %s", s.substr(i, endbracket - i + 1).c_str()); 2285 2286 size_t start = s.find(':', i); 2287 std::basic_string<char> buff; 2288 2289 size_t val = 0; 2290 int retnbr = 0; 2291 char c, ch; 2292 bool asciisw = false; 2293 bool valsw = false; 2294 2295 for (size_t j = start+1 ; j <= endbracket ; j++) { 2296 ch = s[j]; 2297 if (ch == '\"') { 2298 asciisw = !asciisw; 2299 continue; 2300 } 2301 // accumulate ascii string 2302 if (asciisw) { 2303 if (isprint(ch)) buff += ch; 2304 continue; 2305 } 2306 // following digits is expected size of CAT response from xcvr 2307 if (ch == ':' && s[j+1] != '>') { 2308 sscanf(&s[j+1], "%d", &retnbr); 2309 } 2310 // accumulate hex string values 2311 if ((ch == ' ' || ch == '>' || ch == ':') && valsw) { 2312 c = char(val); 2313 // LOG_INFO("c=%02x, val=%d", c, val); 2314 buff += c; 2315 val = 0; 2316 valsw = false; 2317 } else { 2318 val *= 16; 2319 ch = toupper(ch); 2320 if (isdigit(ch)) val += ch - '0'; 2321 else if (ch >= 'A' && ch <= 'F') val += ch - 'A' + 10; 2322 valsw = true; 2323 } 2324 if (ch == ':') break; 2325 } 2326 2327 add_to_cmdque( "RIGCAT macro", buff, retnbr, progdefaults.RigCatWait); 2328 2329 substitute(s, i, endbracket, ""); 2330 } 2331 2332 static void doFLRIG(std::string s) 2333 { 2334 size_t start = s.find(':'); 2335 std::string cmd = s.substr(start + 1, s.length() - start + 1); 2336 2337 LOG_INFO("!FLRIG %s", cmd.c_str()); 2338 2339 xmlrpc_send_command(cmd); 2340 2341 que_ok = true; 2342 } 2343 2344 static void pTxQueFLRIG(std::string &s, size_t &i, size_t endbracket) 2345 { 2346 if (within_exec) { 2347 substitute(s, i, endbracket, ""); 2348 return; 2349 } 2350 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doFLRIG }; 2351 push_txcmd(cmd); 2352 substitute(s, i, endbracket, "^!"); 2353 } 2354 2355 static void pRxQueFLRIG(std::string &s, size_t &i, size_t endbracket) 2356 { 2357 if (within_exec) { 2358 substitute(s, i, endbracket, ""); 2359 return; 2360 } 2361 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doFLRIG }; 2362 push_rxcmd(cmd); 2363 substitute(s, i, endbracket, ""); 2364 } 2365 2366 static void pFLRIG(std::string &s, size_t &i, size_t endbracket) 2367 { 2368 if (within_exec) { 2369 substitute(s, i, endbracket, ""); 2370 return; 2371 } 2372 2373 LOG_INFO("flrig CAT cmd: %s", s.substr(i, endbracket - i + 1).c_str()); 2374 2375 size_t start = s.find(':'); 2376 std::string cmd = s.substr(start + 1, s.length() - start - 2); 2377 xmlrpc_send_command(cmd); 2378 2379 substitute(s, i, endbracket, ""); 2380 } 2381 2382 static void doVIDEO(string s) 2383 { 2384 trx_mode id = active_modem->get_mode(); 2385 if ( id == MODE_SSB || 2386 id == MODE_ANALYSIS || 2387 id == MODE_WEFAX_576 || id == MODE_WEFAX_288 || 2388 id == MODE_SITORB || id == MODE_NAVTEX ) { 2389 return; 2390 } 2391 size_t start = s.find(':') + 1; 2392 size_t end = s.find('>'); 2393 active_modem->macro_video_text = s.substr(start, end - start); 2394 que_ok = true; 2395 } 2396 2397 static void pVIDEO(std::string &s, size_t &i, size_t endbracket) 2398 { 2399 if (within_exec) { 2400 substitute(s, i, endbracket, ""); 2401 return; 2402 } 2403 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doVIDEO }; 2404 push_txcmd(cmd); 2405 substitute(s, i, endbracket, "^!"); 2406 } 2407 2408 2409 static void pVER(std::string &s, size_t &i, size_t endbracket) 2410 { 2411 std::string progname; 2412 progname = "Fldigi "; 2413 progname.append(PACKAGE_VERSION); 2414 s.replace( i, 5, progname ); 2415 } 2416 2417 static void pSERNO(std::string &s, size_t &i, size_t endbracket) 2418 { 2419 if (within_exec) { 2420 s.replace(i, endbracket - i + 1, ""); 2421 return; 2422 } 2423 int contestval; 2424 contestval = atoi(outSerNo->value()); 2425 if (contestval) { 2426 char serstr[10]; 2427 contest_count.Format(progdefaults.ContestDigits, progdefaults.UseLeadingZeros); 2428 snprintf(serstr, sizeof(serstr), contest_count.fmt.c_str(), contestval); 2429 s.replace (i, 7, cut_string(serstr)); 2430 } else 2431 s.replace (i, 7, ""); 2432 } 2433 2434 static void pLASTNO(std::string &s, size_t &i, size_t endbracket) 2435 { 2436 if (within_exec) { 2437 s.replace(i, endbracket - i + 1, ""); 2438 return; 2439 } 2440 int contestval; 2441 contestval = atoi(outSerNo->value()) - 1; 2442 if (contestval) { 2443 char serstr[10]; 2444 contest_count.Format(progdefaults.ContestDigits, progdefaults.UseLeadingZeros); 2445 snprintf(serstr, sizeof(serstr), contest_count.fmt.c_str(), contestval); 2446 s.replace (i, 8, cut_string(serstr)); 2447 } else 2448 s.replace (i, 8, ""); 2449 } 2450 2451 static void pCNTR(std::string &s, size_t &i, size_t endbracket) 2452 { 2453 if (within_exec) { 2454 s.replace(i, endbracket - i + 1, ""); 2455 return; 2456 } 2457 int contestval; 2458 contestval = contest_count.count; 2459 if (contestval) { 2460 contest_count.Format(progdefaults.ContestDigits, progdefaults.UseLeadingZeros); 2461 snprintf(contest_count.szCount, sizeof(contest_count.szCount), contest_count.fmt.c_str(), contestval); 2462 s.replace (i, 6, cut_string(contest_count.szCount)); 2463 } else 2464 s.replace (i, 6, ""); 2465 } 2466 2467 static void pDECR(std::string &s, size_t &i, size_t endbracket) 2468 { 2469 if (within_exec) { 2470 substitute(s, i, endbracket, ""); 2471 return; 2472 } 2473 contest_count.count--; 2474 if (contest_count.count < 0) contest_count.count = 0; 2475 substitute(s, i, endbracket, ""); 2476 updateOutSerNo(); 2477 } 2478 2479 static void pINCR(std::string &s, size_t &i, size_t endbracket) 2480 { 2481 if (within_exec) { 2482 substitute(s, i, endbracket, ""); 2483 return; 2484 } 2485 contest_count.count++; 2486 substitute(s, i, endbracket, ""); 2487 updateOutSerNo(); 2488 } 2489 2490 static void pXIN(std::string &s, size_t &i, size_t endbracket) 2491 { 2492 s.replace( i, 5, inpXchgIn->value() ); 2493 } 2494 2495 static void pXOUT(std::string &s, size_t &i, size_t endbracket) 2496 { 2497 s.replace( i, 6, cut_string(progdefaults.myXchg.c_str())); 2498 } 2499 2500 static void pXBEG(std::string &s, size_t &i, size_t endbracket) 2501 { 2502 if (within_exec) { 2503 substitute(s, i, endbracket, ""); 2504 return; 2505 } 2506 substitute(s, i, endbracket, ""); 2507 xbeg = i; 2508 } 2509 2510 static void pXEND(std::string &s, size_t &i, size_t endbracket) 2511 { 2512 if (within_exec) { 2513 substitute(s, i, endbracket, ""); 2514 return; 2515 } 2516 substitute(s, i, endbracket, ""); 2517 xend = i; 2518 } 2519 2520 static void pSAVEXCHG(std::string &s, size_t &i, size_t endbracket) 2521 { 2522 if (within_exec) { 2523 substitute(s, i, endbracket, ""); 2524 return; 2525 } 2526 save_xchg = true; 2527 substitute(s, i, endbracket, ""); 2528 } 2529 2530 static void pFD_CLASS(std::string &s, size_t &i, size_t endbracket) 2531 { 2532 s.replace( i, 9, inpClass->value() ); 2533 } 2534 2535 static void pFD_SECTION(std::string &s, size_t &i, size_t endbracket) 2536 { 2537 s.replace( i, 8, inpSection->value() ); 2538 } 2539 2540 static void pCLASS(std::string &s, size_t &i, size_t endbracket) 2541 { 2542 s.replace( i, 7, inpClass->value() ); 2543 } 2544 2545 static void pSECTION(std::string &s, size_t &i, size_t endbracket) 2546 { 2547 s.replace( i, 9, inpSection->value() ); 2548 } 2549 2550 static void pLOG(std::string &s, size_t &i, size_t endbracket) 2551 { 2552 if (within_exec) { 2553 substitute(s, i, endbracket, ""); 2554 return; 2555 } 2556 size_t start = s.find(':', i); 2557 if (start != std::string::npos) { 2558 string msg = inpNotes->value(); 2559 if (!msg.empty()) msg.append("\n"); 2560 msg.append(s.substr(start + 1, endbracket-start-1)); 2561 inpNotes->value(msg.c_str()); 2562 } 2563 substitute(s, i, endbracket, ""); 2564 qsoSave_cb(0, 0); 2565 } 2566 2567 static void pLNW(std::string &s, size_t &i, size_t endbracket) 2568 { 2569 if (within_exec) { 2570 substitute(s, i, endbracket, ""); 2571 return; 2572 } 2573 size_t start = s.find(':', i); 2574 if (start != std::string::npos) { 2575 string msg = inpNotes->value(); 2576 if (!msg.empty()) msg.append("\n"); 2577 msg.append(s.substr(start + 1, endbracket-start-1)); 2578 inpNotes->value(msg.c_str()); 2579 } 2580 substitute(s, i, endbracket, ""); 2581 qsoSave_cb(0, 0); 2582 } 2583 2584 static void pCLRLOG(std::string &s, size_t &i, size_t endbracket) 2585 { 2586 if (within_exec) { 2587 substitute(s, i, endbracket, ""); 2588 return; 2589 } 2590 substitute(s, i, endbracket, ""); 2591 } 2592 2593 static void pMODEM_COMPSKED(std::string &s, size_t &i, size_t endbracket) 2594 { 2595 if (within_exec) { 2596 substitute(s, i, endbracket, ""); 2597 return; 2598 } 2599 size_t j, k, 2600 len = s.length(); 2601 std::string name; 2602 2603 if ((j = s.find('>', i)) == std::string::npos) 2604 return; 2605 while (++j < len) 2606 if (!isspace(s[j])) break; 2607 k = j; 2608 while (++k < len) 2609 if (isspace(s[k]) || s[k] == '<') break; 2610 name = ucasestr(s.substr(j, k - j)); 2611 for (int m = 0; m < NUM_MODES; m++) { 2612 if (name == ucasestr(mode_info[m].sname)) { 2613 if (active_modem->get_mode() != mode_info[m].mode) 2614 init_modem(mode_info[m].mode); 2615 break; 2616 } 2617 } 2618 s.erase(i, k-i); 2619 } 2620 2621 static void doIMAGE(std::string s) 2622 { 2623 if (s.length() > 0) { 2624 2625 bool Greyscale = false; 2626 size_t p = string::npos; 2627 string fname = s.substr(7); 2628 p = fname.find(">"); 2629 fname.erase(p); 2630 p = fname.find("G,"); 2631 if (p == string::npos) p = fname.find("g,"); 2632 if (p != string::npos) { 2633 Greyscale = true; 2634 fname.erase(p,2); 2635 } 2636 while (fname[0] == ' ') fname.erase(0,1); 2637 2638 trx_mode active_mode = active_modem->get_mode(); 2639 if ((active_mode == MODE_MFSK16 || 2640 active_mode == MODE_MFSK32 || 2641 active_mode == MODE_MFSK64 || 2642 active_mode == MODE_MFSK128) && 2643 active_modem->get_cap() & modem::CAP_IMG) { 2644 Greyscale ? 2645 active_modem->send_Grey_image(fname) : 2646 active_modem->send_color_image(fname); 2647 } else if (active_mode >= MODE_THOR_FIRST && active_mode <= MODE_THOR_LAST) { 2648 thor_load_scaled_image(fname, Greyscale); 2649 } else if (active_mode == MODE_IFKP) { 2650 ifkp_load_scaled_image(fname, Greyscale); 2651 } 2652 } 2653 que_ok = true; 2654 } 2655 2656 static void pTxQueIMAGE(std::string &s, size_t &i, size_t endbracket) 2657 { 2658 if (within_exec) { 2659 substitute(s, i, endbracket, ""); 2660 return; 2661 } 2662 string Tx_cmdstr = s.substr(i, endbracket - i + 1); 2663 struct CMDS cmd = { Tx_cmdstr, doIMAGE }; 2664 push_txcmd(cmd); 2665 substitute(s, i, endbracket, "^!"); 2666 } 2667 2668 static void doINSERTIMAGE(std::string s) 2669 { 2670 if (s.length() > 0) { 2671 2672 bool Greyscale = false; 2673 size_t p = string::npos; 2674 string fname = s.substr(7); 2675 p = fname.find(">"); 2676 fname.erase(p); 2677 p = fname.find("G,"); 2678 if (p == string::npos) p = fname.find("g,"); 2679 if (p != string::npos) { 2680 Greyscale = true; 2681 fname.erase(p,2); 2682 } 2683 while (fname[0] == ' ') fname.erase(0,1); 2684 if (s.empty()) return; 2685 2686 trx_mode md = active_modem->get_mode(); 2687 if ((md == MODE_MFSK16 || md == MODE_MFSK32 || 2688 md == MODE_MFSK64 || md == MODE_MFSK128) && 2689 active_modem->get_cap() & modem::CAP_IMG) { 2690 Greyscale ? 2691 active_modem->send_Grey_image(fname) : 2692 active_modem->send_color_image(fname); 2693 } 2694 else if (md == MODE_IFKP) 2695 ifkp_load_scaled_image(fname, Greyscale); 2696 else if (md >= MODE_THOR_FIRST && md <= MODE_THOR_LAST) 2697 thor_load_scaled_image(fname, Greyscale); 2698 } 2699 que_ok = true; 2700 } 2701 2702 void TxQueINSERTIMAGE(std::string s) 2703 { 2704 trx_mode active_mode = active_modem->get_mode(); 2705 if (! (active_mode == MODE_MFSK16 || 2706 active_mode == MODE_MFSK32 || 2707 active_mode == MODE_MFSK64 || 2708 active_mode == MODE_MFSK128 || 2709 active_mode == MODE_IFKP || 2710 (active_mode >= MODE_THOR_FIRST && active_mode <= MODE_THOR_LAST) ) && 2711 active_modem->get_cap() & modem::CAP_IMG) 2712 return; 2713 2714 string scmd = "<IMAGE:>"; 2715 scmd.insert(7,s); 2716 2717 struct CMDS cmd = { scmd, doINSERTIMAGE }; 2718 push_txcmd(cmd); 2719 2720 string itext = s; 2721 size_t p = itext.rfind("\\"); 2722 if (p == string::npos) p = itext.rfind("/"); 2723 if (p != string::npos) itext.erase(0, p+1); 2724 p = itext.rfind("."); 2725 if (p != string::npos) itext.erase(p); 2726 itext.insert(0, "\nImage: "); 2727 itext.append(" ^!"); 2728 2729 if (active_mode == MODE_IFKP) 2730 ifkp_tx_text->add_text(itext); 2731 else if (active_mode == MODE_FSQ) 2732 fsq_tx_text->add_text(itext); 2733 else 2734 add_text(itext); 2735 } 2736 2737 static void doAVATAR(std::string s) 2738 { 2739 if (active_modem->get_mode() == MODE_IFKP) 2740 active_modem->m_ifkp_send_avatar(); 2741 2742 que_ok = true; 2743 } 2744 2745 static void pTxQueAVATAR(std::string &s, size_t &i, size_t endbracket) 2746 { 2747 if (within_exec) { 2748 s.replace(i, endbracket - i + 1, ""); 2749 return; 2750 } 2751 2752 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doAVATAR }; 2753 push_txcmd(cmd); 2754 substitute(s, i, endbracket, "^!"); 2755 } 2756 2757 static void doMODEM(std::string s) 2758 { 2759 static fre_t re("<!MODEM:([[:alnum:]-]+)((:[[:digit:].+-]*)*)>", REG_EXTENDED); 2760 std::string tomatch = s; 2761 for (int i = 2; i < 7; i++) s[i] = toupper(s[i]); 2762 2763 if (!re.match(tomatch.c_str())) { 2764 que_ok = true; 2765 return; 2766 } 2767 2768 const std::vector<regmatch_t>& o = re.suboff(); 2769 std::string name = ucasestr(tomatch.substr(o[1].rm_so, o[1].rm_eo - o[1].rm_so)); 2770 2771 trx_mode m; 2772 for (m = 0; m < NUM_MODES; m++) 2773 if (name == ucasestr(mode_info[m].sname)) 2774 break; 2775 // do we have arguments and a valid modem? 2776 if (o.size() == 2 || m == NUM_MODES) { 2777 que_ok = true; 2778 return; 2779 } 2780 2781 // parse arguments 2782 vector<double> args; 2783 args.reserve(8); 2784 char* end; 2785 double d; 2786 for (const char* p = s.c_str() + o[2].rm_so + 1; *p; p++) { 2787 errno = 0; 2788 d = strtod(p, &end); 2789 if (!errno && p != end) { 2790 args.push_back(d); 2791 p = end; 2792 } 2793 else // push an invalid value 2794 args.push_back(DBL_MIN); 2795 } 2796 2797 try { 2798 switch (m) { 2799 case MODE_RTTY: // carrier shift, baud rate, bits per char 2800 if (args.at(0) != DBL_MIN) 2801 set_rtty_shift((int)args[0]); 2802 if (args.at(1) != DBL_MIN) 2803 set_rtty_baud((float)args[1]); 2804 if (args.at(2) != DBL_MIN) 2805 set_rtty_bits((int)args[2]); 2806 break; 2807 case MODE_CONTESTIA: // bandwidth, tones 2808 if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { 2809 int bw = (int)args[0]; 2810 int tones = (int)args[1]; 2811 set_contestia_bw(bw); 2812 set_contestia_tones(tones); 2813 switch (tones) { 2814 case 4 : 2815 if (bw == 125) m = MODE_CONTESTIA_4_125; 2816 else if (bw == 250) m = MODE_CONTESTIA_4_250; 2817 else if (bw == 500) m = MODE_CONTESTIA_4_500; 2818 else if (bw == 1000) m = MODE_CONTESTIA_4_1000; 2819 else if (bw == 2000) m = MODE_CONTESTIA_4_2000; 2820 else { 2821 set_contestia_bw(bw); 2822 set_contestia_tones(tones); 2823 } 2824 break; 2825 case 8 : 2826 if (bw == 125) m = MODE_CONTESTIA_8_125; 2827 else if (bw == 250) m = MODE_CONTESTIA_8_250; 2828 else if (bw == 500) m = MODE_CONTESTIA_8_500; 2829 else if (bw == 1000) m = MODE_CONTESTIA_8_1000; 2830 else if (bw == 2000) m = MODE_CONTESTIA_8_2000; 2831 else { 2832 set_contestia_bw(bw); 2833 set_contestia_tones(tones); 2834 } 2835 break; 2836 case 16 : 2837 if (bw == 250) m = MODE_CONTESTIA_16_250; 2838 else if (bw == 500) m = MODE_CONTESTIA_16_500; 2839 else if (bw == 1000) m = MODE_CONTESTIA_16_1000; 2840 else if (bw == 2000) m = MODE_CONTESTIA_16_2000; 2841 else { 2842 set_contestia_bw(bw); 2843 set_contestia_tones(tones); 2844 } 2845 break; 2846 case 32 : 2847 if (bw == 1000) m = MODE_CONTESTIA_32_1000; 2848 else if (bw == 2000) m = MODE_CONTESTIA_32_2000; 2849 else { 2850 set_contestia_bw(bw); 2851 set_contestia_tones(tones); 2852 } 2853 break; 2854 case 64 : 2855 if (bw == 500) m = MODE_CONTESTIA_64_500; 2856 else if (bw == 1000) m = MODE_CONTESTIA_64_1000; 2857 else if (bw == 2000) m = MODE_CONTESTIA_64_2000; 2858 else { 2859 set_contestia_bw(bw); 2860 set_contestia_tones(tones); 2861 } 2862 break; 2863 default : 2864 set_contestia_bw(bw); 2865 set_contestia_tones(tones); 2866 } 2867 } 2868 break; 2869 case MODE_OLIVIA: // bandwidth, tones 2870 if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { 2871 int bw = (int)args[0]; 2872 int tones = (int)args[1]; 2873 set_olivia_bw(bw); 2874 set_olivia_tones(tones); 2875 switch (tones) { 2876 case 4 : 2877 if (bw == 125) m = MODE_OLIVIA_4_125; 2878 else if (bw == 250) m = MODE_OLIVIA_4_250; 2879 else if (bw == 500) m = MODE_OLIVIA_4_500; 2880 else if (bw == 1000) m = MODE_OLIVIA_4_1000; 2881 else if (bw == 2000) m = MODE_OLIVIA_4_2000; 2882 else { 2883 set_olivia_bw(bw); 2884 set_olivia_tones(tones); 2885 } 2886 break; 2887 case 8 : 2888 if (bw == 125) m = MODE_OLIVIA_8_125; 2889 else if (bw == 250) m = MODE_OLIVIA_8_250; 2890 else if (bw == 500) m = MODE_OLIVIA_8_500; 2891 else if (bw == 1000) m = MODE_OLIVIA_8_1000; 2892 else if (bw == 2000) m = MODE_OLIVIA_8_2000; 2893 else { 2894 set_olivia_bw(bw); 2895 set_olivia_tones(tones); 2896 } 2897 break; 2898 case 16 : 2899 if (bw == 500) m = MODE_OLIVIA_16_500; 2900 else if (bw == 1000) m = MODE_OLIVIA_16_1000; 2901 else if (bw == 2000) m = MODE_OLIVIA_16_2000; 2902 else { 2903 set_olivia_bw(bw); 2904 set_olivia_tones(tones); 2905 } 2906 break; 2907 case 32 : 2908 if (bw == 1000) m = MODE_OLIVIA_32_1000; 2909 else if (bw == 2000) m = MODE_OLIVIA_32_2000; 2910 else { 2911 set_olivia_bw(bw); 2912 set_olivia_tones(tones); 2913 } 2914 break; 2915 case 64 : 2916 if (bw == 500) m = MODE_OLIVIA_64_500; 2917 else if (bw == 1000) m = MODE_OLIVIA_64_1000; 2918 else if (bw == 2000) m = MODE_OLIVIA_64_2000; 2919 else { 2920 set_olivia_bw(bw); 2921 set_olivia_tones(tones); 2922 } 2923 break; 2924 default : 2925 set_olivia_bw(bw); 2926 set_olivia_tones(tones); 2927 } 2928 } 2929 break; 2930 default: 2931 break; 2932 } 2933 } 2934 catch (const exception& e) { } 2935 2936 if (active_modem->get_mode() != mode_info[m].mode) { 2937 init_modem_sync(mode_info[m].mode); 2938 } 2939 que_ok = true; 2940 } 2941 2942 static void pTxQueMODEM(std::string &s, size_t &i, size_t endbracket) 2943 { 2944 if (within_exec) { 2945 substitute(s, i, endbracket, ""); 2946 return; 2947 } 2948 string Tx_cmdstr = s.substr(i, endbracket - i + 1); 2949 struct CMDS cmd = { Tx_cmdstr, doMODEM }; 2950 if (Tx_cmdstr.find("SSB") != string::npos || Tx_cmdstr.find("ANALYSIS") != string::npos) { 2951 LOG_ERROR("Disallowed: %s", Tx_cmdstr.c_str()); 2952 size_t nowbracket = s.find('<', endbracket); 2953 if (nowbracket != string::npos) 2954 s.erase(i, nowbracket - i - 1); 2955 else 2956 s.clear(); 2957 } else { 2958 push_txcmd(cmd); 2959 if (i && s[i-1] == '\n') i--; 2960 substitute(s, i, endbracket, "^!"); 2961 } 2962 } 2963 2964 static void pRxQueMODEM(std::string &s, size_t &i, size_t endbracket) 2965 { 2966 if (within_exec) { 2967 substitute(s, i, endbracket, ""); 2968 return; 2969 } 2970 string rx_cmdstr = s.substr(i, endbracket - i + 1); 2971 struct CMDS cmd = { rx_cmdstr, doMODEM }; 2972 push_rxcmd(cmd); 2973 substitute(s, i, endbracket, ""); 2974 } 2975 2976 static void pMODEM(std::string &s, size_t &i, size_t endbracket) 2977 { 2978 if (within_exec) { 2979 substitute(s, i, endbracket, ""); 2980 return; 2981 } 2982 static fre_t re("<MODEM:([[:alnum:]-]+)((:[[:digit:].+-]*)*)>", REG_EXTENDED); 2983 2984 std::string testmode = s.substr(i, endbracket - i + 1); 2985 for (int i = 2; i < 7; i++) testmode[i] = toupper(testmode[i]); 2986 2987 std::string name = testmode; 2988 name.erase(0,7); 2989 name.erase(name.length() - 1); 2990 name = ucasestr(name); 2991 2992 // test for exact match on mode name (ignore case) 2993 2994 for (trx_mode m = 0; m < NUM_MODES; m++) { 2995 if (name == ucasestr(mode_info[m].sname)) { 2996 init_modem(mode_info[m].mode); 2997 s.erase(i, endbracket - i + 1); 2998 int count = 500; 2999 while ((active_modem->get_mode() != mode_info[m].mode) && --count) 3000 MilliSleep(10); 3001 return; 3002 } 3003 } 3004 3005 if (!re.match(testmode.c_str())) { 3006 s.erase(i, endbracket - i + 1); 3007 return; 3008 } 3009 3010 const std::vector<regmatch_t>& o = re.suboff(); 3011 name = ucasestr(testmode.substr(o[1].rm_so, o[1].rm_eo - o[1].rm_so)); 3012 trx_mode m; 3013 for (m = 0; m < NUM_MODES; m++) 3014 if (name == ucasestr(mode_info[m].sname)) 3015 break; 3016 // do we have arguments and a valid modem? 3017 if (o.size() == 2 || m == NUM_MODES) { 3018 if (m < NUM_MODES && active_modem->get_mode() != mode_info[m].mode) 3019 init_modem(mode_info[m].mode); 3020 s.erase(i, o[0].rm_eo - i); 3021 int count = 500; 3022 while ((active_modem->get_mode() != mode_info[m].mode) && --count) 3023 MilliSleep(10); 3024 return; 3025 } 3026 3027 // parse arguments 3028 vector<double> args; 3029 args.reserve(8); 3030 char* end; 3031 double d; 3032 for (const char* p = testmode.c_str() + o[2].rm_so + 1; *p; p++) { 3033 errno = 0; 3034 d = strtod(p, &end); 3035 if (!errno && p != end) { 3036 args.push_back(d); 3037 p = end; 3038 } 3039 else // push an invalid value 3040 args.push_back(DBL_MIN); 3041 } 3042 3043 try { 3044 switch (m) { 3045 case MODE_RTTY: // carrier shift, baud rate, bits per char 3046 if (args.at(0) != DBL_MIN) 3047 set_rtty_shift((int)args[0]); 3048 if (args.at(1) != DBL_MIN) 3049 set_rtty_baud((float)args[1]); 3050 if (args.at(2) != DBL_MIN) 3051 set_rtty_bits((int)args[2]); 3052 break; 3053 case MODE_CONTESTIA: // bandwidth, tones 3054 if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { 3055 int bw = (int)args[0]; 3056 int tones = (int)args[1]; 3057 set_contestia_bw(bw); 3058 set_contestia_tones(tones); 3059 switch (tones) { 3060 case 4 : 3061 if (bw == 125) m = MODE_CONTESTIA_4_125; 3062 else if (bw == 250) m = MODE_CONTESTIA_4_250; 3063 else if (bw == 500) m = MODE_CONTESTIA_4_500; 3064 else if (bw == 1000) m = MODE_CONTESTIA_4_1000; 3065 else if (bw == 2000) m = MODE_CONTESTIA_4_2000; 3066 else { 3067 set_contestia_bw(bw); 3068 set_contestia_tones(tones); 3069 } 3070 break; 3071 case 8 : 3072 if (bw == 125) m = MODE_CONTESTIA_8_125; 3073 else if (bw == 250) m = MODE_CONTESTIA_8_250; 3074 else if (bw == 500) m = MODE_CONTESTIA_8_500; 3075 else if (bw == 1000) m = MODE_CONTESTIA_8_1000; 3076 else if (bw == 2000) m = MODE_CONTESTIA_8_2000; 3077 else { 3078 set_contestia_bw(bw); 3079 set_contestia_tones(tones); 3080 } 3081 break; 3082 case 16 : 3083 if (bw == 250) m = MODE_CONTESTIA_16_250; 3084 else if (bw == 500) m = MODE_CONTESTIA_16_500; 3085 else if (bw == 1000) m = MODE_CONTESTIA_16_1000; 3086 else if (bw == 2000) m = MODE_CONTESTIA_16_2000; 3087 else { 3088 set_contestia_bw(bw); 3089 set_contestia_tones(tones); 3090 } 3091 break; 3092 case 32 : 3093 if (bw == 1000) m = MODE_CONTESTIA_32_1000; 3094 else if (bw == 2000) m = MODE_CONTESTIA_32_2000; 3095 else { 3096 set_contestia_bw(bw); 3097 set_contestia_tones(tones); 3098 } 3099 break; 3100 case 64 : 3101 if (bw == 500) m = MODE_CONTESTIA_64_500; 3102 else if (bw == 1000) m = MODE_CONTESTIA_64_1000; 3103 else if (bw == 2000) m = MODE_CONTESTIA_64_2000; 3104 else { 3105 set_contestia_bw(bw); 3106 set_contestia_tones(tones); 3107 } 3108 break; 3109 default : 3110 set_contestia_bw(bw); 3111 set_contestia_tones(tones); 3112 } 3113 } 3114 break; 3115 case MODE_OLIVIA: // bandwidth, tones 3116 if (args.at(0) != DBL_MIN && args.at(1) != DBL_MIN) { 3117 int bw = (int)args[0]; 3118 int tones = (int)args[1]; 3119 set_olivia_bw(bw); 3120 set_olivia_tones(tones); 3121 switch (tones) { 3122 case 4 : 3123 if (bw == 125) m = MODE_OLIVIA_4_125; 3124 else if (bw == 250) m = MODE_OLIVIA_4_250; 3125 else if (bw == 500) m = MODE_OLIVIA_4_500; 3126 else if (bw == 1000) m = MODE_OLIVIA_4_1000; 3127 else if (bw == 2000) m = MODE_OLIVIA_4_2000; 3128 else { 3129 set_olivia_bw(bw); 3130 set_olivia_tones(tones); 3131 } 3132 break; 3133 case 8 : 3134 if (bw == 125) m = MODE_OLIVIA_8_125; 3135 else if (bw == 250) m = MODE_OLIVIA_8_250; 3136 else if (bw == 500) m = MODE_OLIVIA_8_500; 3137 else if (bw == 1000) m = MODE_OLIVIA_8_1000; 3138 else if (bw == 2000) m = MODE_OLIVIA_8_2000; 3139 else { 3140 set_olivia_bw(bw); 3141 set_olivia_tones(tones); 3142 } 3143 break; 3144 case 16 : 3145 if (bw == 500) m = MODE_OLIVIA_16_500; 3146 else if (bw == 1000) m = MODE_OLIVIA_16_1000; 3147 else if (bw == 2000) m = MODE_OLIVIA_16_2000; 3148 else { 3149 set_olivia_bw(bw); 3150 set_olivia_tones(tones); 3151 } 3152 break; 3153 case 32 : 3154 if (bw == 1000) m = MODE_OLIVIA_32_1000; 3155 else if (bw == 2000) m = MODE_OLIVIA_32_2000; 3156 else { 3157 set_olivia_bw(bw); 3158 set_olivia_tones(tones); 3159 } 3160 break; 3161 case 64 : 3162 if (bw == 500) m = MODE_OLIVIA_64_500; 3163 else if (bw == 1000) m = MODE_OLIVIA_64_1000; 3164 else if (bw == 2000) m = MODE_OLIVIA_64_2000; 3165 else { 3166 set_olivia_bw(bw); 3167 set_olivia_tones(tones); 3168 } 3169 break; 3170 default : 3171 set_olivia_bw(bw); 3172 set_olivia_tones(tones); 3173 } 3174 } 3175 break; 3176 default: 3177 break; 3178 } 3179 } 3180 catch (const exception& e) { } 3181 3182 if (active_modem->get_mode() != mode_info[m].mode) { 3183 init_modem(mode_info[m].mode); 3184 int count = 500; 3185 while ((active_modem->get_mode() != mode_info[m].mode) && --count) 3186 MilliSleep(10); 3187 } 3188 3189 substitute(s, i, endbracket, ""); 3190 } 3191 3192 static void pAFC(std::string &s, size_t &i, size_t endbracket) 3193 { 3194 if (within_exec) { 3195 substitute(s, i, endbracket, ""); 3196 return; 3197 } 3198 std::string sVal = s.substr(i+5, endbracket - i - 5); 3199 if (sVal.length() > 0) { 3200 // sVal = on|off|t [ON, OFF or Toggle] 3201 if (sVal.compare(0,2,"on") == 0) 3202 btnAFC->value(1); 3203 else if (sVal.compare(0,3,"off") == 0) 3204 btnAFC->value(0); 3205 else if (sVal.compare(0,1,"t") == 0) 3206 btnAFC->value(!btnAFC->value()); 3207 3208 btnAFC->do_callback(); 3209 } 3210 substitute(s, i, endbracket, ""); 3211 } 3212 3213 static void pREV(std::string &s, size_t &i, size_t endbracket) 3214 { 3215 if (within_exec) { 3216 substitute(s, i, endbracket, ""); 3217 return; 3218 } 3219 std::string sVal = s.substr(i+5, endbracket - i - 5); 3220 if (sVal.length() > 0) { 3221 // sVal = on|off|t [ON, OFF or Toggle] 3222 if (sVal.compare(0,2,"on") == 0) 3223 wf->btnRev->value(1); 3224 else if (sVal.compare(0,3,"off") == 0) 3225 wf->btnRev->value(0); 3226 else if (sVal.compare(0,1,"t") == 0) 3227 wf->btnRev->value(!wf->btnRev->value()); 3228 3229 wf->btnRev->do_callback(); 3230 } 3231 substitute(s, i, endbracket, ""); 3232 } 3233 3234 // <HS:on|off|t> 3235 static void pHS(std::string &s, size_t &i, size_t endbracket) 3236 { 3237 if (within_exec) { 3238 substitute(s, i, endbracket, ""); 3239 return; 3240 } 3241 std::string sVal = s.substr(i+4, endbracket - i - 4); 3242 if (sVal.length() > 0) { 3243 // sVal = on|off|t [ON, OFF or Toggle] 3244 if (sVal.compare(0,2,"on") == 0) 3245 bHighSpeed = 1; 3246 else if (sVal.compare(0,3,"off") == 0) 3247 bHighSpeed = 0; 3248 else if (sVal.compare(0,1,"t") == 0) 3249 bHighSpeed = !bHighSpeed; 3250 } 3251 substitute(s, i, endbracket, ""); 3252 } 3253 3254 3255 static void pLOCK(std::string &s, size_t &i, size_t endbracket) 3256 { 3257 if (within_exec) { 3258 substitute(s, i, endbracket, ""); 3259 return; 3260 } 3261 std::string sVal = s.substr(i+6, endbracket - i - 6); 3262 if (sVal.length() > 0) { 3263 // sVal = on|off|t [ON, OFF or Toggle] 3264 if (sVal.compare(0,2,"on") == 0) 3265 wf->xmtlock->value(1); 3266 else if (sVal.compare(0,3,"off") == 0) 3267 wf->xmtlock->value(0); 3268 else if (sVal.compare(0,1,"t") == 0) 3269 wf->xmtlock->value(!wf->xmtlock->value()); 3270 3271 wf->xmtlock->damage(); 3272 wf->xmtlock->do_callback(); 3273 } 3274 substitute(s, i, endbracket, ""); 3275 } 3276 3277 static void doLOCK( std::string s){ 3278 std::string sVal = s.substr(7, s.length() - 8); 3279 if (sVal.length() > 0) { 3280 // sVal = on|off|t[oggle] [ON, OFF or Toggle] 3281 if (sVal.compare(0,2,"on") == 0) 3282 wf->xmtlock->value(1); 3283 else if (sVal.compare(0,3,"off") == 0) 3284 wf->xmtlock->value(0); 3285 else if (sVal.compare(0,1,"t") == 0) 3286 wf->xmtlock->value(!wf->xmtlock->value()); 3287 wf->xmtlock->damage(); 3288 wf->xmtlock->do_callback(); 3289 } 3290 } 3291 3292 static void pRxQueLOCK(std::string &s, size_t &i, size_t endbracket) 3293 { 3294 if (within_exec) { 3295 substitute(s, i, endbracket, ""); 3296 return; 3297 } 3298 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doLOCK }; 3299 push_rxcmd(cmd); 3300 substitute(s, i, endbracket, ""); 3301 } 3302 3303 3304 static void pTX_RSID(std::string &s, size_t &i, size_t endbracket) 3305 { 3306 if (within_exec) { 3307 substitute(s, i, endbracket, ""); 3308 return; 3309 } 3310 std::string sVal = s.substr(i+8, endbracket - i - 8); 3311 if (sVal.length() > 0) { 3312 // sVal = on|off|t [ON, OFF or Toggle] 3313 if (sVal.compare(0,2,"on") == 0) 3314 btnTxRSID->value(1); 3315 else if (sVal.compare(0,3,"off") == 0) 3316 btnTxRSID->value(0); 3317 else if (sVal.compare(0,1,"t") == 0) 3318 btnTxRSID->value(!btnTxRSID->value()); 3319 btnTxRSID->do_callback(); 3320 } 3321 substitute(s, i, endbracket, ""); 3322 } 3323 3324 static void doTXRSID(std::string s) 3325 { 3326 if (s.find("on") != std::string::npos) { 3327 btnTxRSID->value(1); 3328 btnTxRSID->do_callback(); 3329 } 3330 else if (s.find("off") != std::string::npos) { 3331 btnTxRSID->value(0); 3332 btnTxRSID->do_callback(); 3333 } 3334 else if (s.find("t") != std::string::npos) { 3335 btnTxRSID->value(!btnTxRSID->value()); 3336 btnTxRSID->do_callback(); 3337 } 3338 que_ok = true; 3339 } 3340 3341 static void pRxQueTXRSID(std::string &s, size_t &i, size_t endbracket) 3342 { 3343 if (within_exec) { 3344 substitute(s, i, endbracket, ""); 3345 return; 3346 } 3347 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doTXRSID }; 3348 push_rxcmd(cmd); 3349 substitute(s, i, endbracket, ""); 3350 } 3351 3352 static void pRX_RSID(std::string &s, size_t &i, size_t endbracket) 3353 { 3354 if (within_exec) { 3355 substitute(s, i, endbracket, ""); 3356 return; 3357 } 3358 std::string sVal = s.substr(i+8, endbracket - i - 8); 3359 if (sVal.length() > 0) { 3360 // sVal = on|off|t [ON, OFF or Toggle] 3361 if (sVal.compare(0,2,"on") == 0) 3362 btnRSID->value(1); 3363 else if (sVal.compare(0,3,"off") == 0) 3364 btnRSID->value(0); 3365 else if (sVal.compare(0,1,"t") == 0) 3366 btnRSID->value(!btnRSID->value()); 3367 3368 btnRSID->do_callback(); 3369 } 3370 substitute(s, i, endbracket, ""); 3371 } 3372 3373 static void pCSV(std::string &s, size_t &i, size_t endbracket) 3374 { 3375 if (within_exec) { 3376 substitute(s, i, endbracket, ""); 3377 return; 3378 } 3379 std::string sVal = s.substr(i+5, endbracket - i - 5); 3380 if (sVal.length() > 0) { 3381 // sVal = on|off [ON, OFF] 3382 if (sVal.compare(0,2,"on") == 0) 3383 set_CSV(1); 3384 else if (sVal.compare(0,3,"off") == 0) 3385 set_CSV(0); 3386 else if (sVal.compare(0,1,"t") == 0) 3387 set_CSV(2); 3388 } 3389 substitute(s, i, endbracket, ""); 3390 } 3391 3392 #ifdef __WIN32__ 3393 static void pTALK(std::string &s, size_t &i, size_t endbracket) 3394 { 3395 if (within_exec) { 3396 substitute(s, i, endbracket, ""); 3397 return; 3398 } 3399 std::string sVal = s.substr(i+6, endbracket - i - 6); 3400 if (sVal.length() > 0) { 3401 // sVal = on|off [ON, OFF] 3402 if (sVal.compare(0,2,"on") == 0) 3403 open_talker(); 3404 else if (sVal.compare(0,3,"off") == 0) 3405 close_talker(); 3406 else if (sVal.compare(0,1,"t") == 0) 3407 toggle_talker(); 3408 } 3409 substitute(s, i, endbracket, ""); 3410 } 3411 #endif 3412 3413 static void pSRCHUP(std::string &s, size_t &i, size_t endbracket) 3414 { 3415 if (within_exec) { 3416 substitute(s, i, endbracket, ""); 3417 return; 3418 } 3419 substitute(s, i, endbracket, ""); 3420 active_modem->searchUp(); 3421 if (progdefaults.WaterfallClickInsert) 3422 wf->insert_text(true); 3423 } 3424 3425 static void pSRCHDN(std::string &s, size_t &i, size_t endbracket) 3426 { 3427 if (within_exec) { 3428 substitute(s, i, endbracket, ""); 3429 return; 3430 } 3431 substitute(s, i, endbracket, ""); 3432 active_modem->searchDown(); 3433 if (progdefaults.WaterfallClickInsert) 3434 wf->insert_text(true); 3435 } 3436 3437 static void pGOHOME(std::string &s, size_t &i, size_t endbracket) 3438 { 3439 if (within_exec) { 3440 substitute(s, i, endbracket, ""); 3441 return; 3442 } 3443 substitute(s, i, endbracket, ""); 3444 if (active_modem == cw_modem) 3445 active_modem->set_freq(progdefaults.CWsweetspot); 3446 else if (active_modem == rtty_modem) 3447 active_modem->set_freq(progdefaults.RTTYsweetspot); 3448 else 3449 active_modem->set_freq(progdefaults.PSKsweetspot); 3450 } 3451 3452 static void doGOHOME(std::string s) 3453 { 3454 if (active_modem == cw_modem) 3455 active_modem->set_freq(progdefaults.CWsweetspot); 3456 else if (active_modem == rtty_modem) 3457 active_modem->set_freq(progdefaults.RTTYsweetspot); 3458 else 3459 active_modem->set_freq(progdefaults.PSKsweetspot); 3460 que_ok = true; 3461 } 3462 3463 static void pTxQueGOHOME(std::string &s, size_t &i, size_t endbracket) 3464 { 3465 if (within_exec) { 3466 substitute(s, i, endbracket, ""); 3467 return; 3468 } 3469 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOHOME }; 3470 push_txcmd(cmd); 3471 substitute(s, i, endbracket, "^!"); 3472 } 3473 3474 static void pRxQueGOHOME(std::string &s, size_t &i, size_t endbracket) 3475 { 3476 if (within_exec) { 3477 substitute(s, i, endbracket, ""); 3478 return; 3479 } 3480 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOHOME }; 3481 push_rxcmd(cmd); 3482 substitute(s, i, endbracket, ""); 3483 } 3484 3485 static void pGOFREQ(std::string &s, size_t &i, size_t endbracket) 3486 { 3487 if (within_exec) { 3488 substitute(s, i, endbracket, ""); 3489 return; 3490 } 3491 int number; 3492 std::string sGoFreq = s.substr(i+8, endbracket - i - 8); 3493 if (sGoFreq.length() > 0) { 3494 sscanf(sGoFreq.c_str(), "%d", &number); 3495 if (number < progdefaults.LowFreqCutoff) 3496 number = progdefaults.LowFreqCutoff; 3497 if (number > progdefaults.HighFreqCutoff) 3498 number = progdefaults.HighFreqCutoff; 3499 active_modem->set_freq(number); 3500 } 3501 substitute(s, i, endbracket, ""); 3502 } 3503 3504 static void doGOFREQ(std::string s) 3505 { 3506 int number; 3507 std::string sGoFreq = s.substr(9, s.length() - 10); 3508 if (sGoFreq.length() > 0) { 3509 sscanf(sGoFreq.c_str(), "%d", &number); 3510 if (number < progdefaults.LowFreqCutoff) 3511 number = progdefaults.LowFreqCutoff; 3512 if (number > progdefaults.HighFreqCutoff) 3513 number = progdefaults.HighFreqCutoff; 3514 active_modem->set_freq(number); 3515 } 3516 que_ok = true; 3517 } 3518 3519 static void pTxQueGOFREQ(std::string &s, size_t &i, size_t endbracket) 3520 { 3521 if (within_exec) { 3522 s.replace(i, endbracket - i + 1, ""); 3523 return; 3524 } 3525 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOFREQ }; 3526 push_txcmd(cmd); 3527 substitute(s, i, endbracket, "^!"); 3528 } 3529 3530 static void pRxQueGOFREQ(std::string &s, size_t &i, size_t endbracket) 3531 { 3532 if (within_exec) { 3533 substitute(s, i, endbracket, ""); 3534 return; 3535 } 3536 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doGOFREQ }; 3537 push_rxcmd(cmd); 3538 substitute(s, i, endbracket, ""); 3539 } 3540 3541 static void pQRG(std::string &s, size_t &i, size_t endbracket) 3542 { 3543 if (within_exec) { 3544 substitute(s, i, endbracket, ""); 3545 return; 3546 } 3547 std::string prefix = "\n"; 3548 prefix.append(s.substr(i+5, endbracket - i - 5)); 3549 if (prefix.length()) note_qrg ( false, prefix.c_str(), "\n" ); 3550 substitute(s, i, endbracket, ""); 3551 } 3552 3553 static void pQSYTO(std::string &s, size_t &i, size_t endbracket) 3554 { 3555 if (within_exec) { 3556 substitute(s, i, endbracket, ""); 3557 return; 3558 } 3559 substitute(s, i, endbracket, ""); 3560 do_qsy(true); 3561 } 3562 3563 static void pQSYFM(std::string &s, size_t &i, size_t endbracket) 3564 { 3565 if (within_exec) { 3566 substitute(s, i, endbracket, ""); 3567 return; 3568 } 3569 substitute(s, i, endbracket, ""); 3570 do_qsy(false); 3571 } 3572 3573 struct rfafmd { int rf; int af; std::string mdname; 3574 rfafmd(int a, int b, std::string nm) { rf = a; af = b; mdname = nm;} 3575 rfafmd(int a, int b) {rf = a; af = b; mdname = active_modem->get_mode_name();} 3576 rfafmd(){rf = af = 0; mdname = active_modem->get_mode_name();} 3577 }; 3578 static queue<rfafmd> fpairs; 3579 3580 static void pQSY(std::string &s, size_t &i, size_t endbracket) 3581 { 3582 if (within_exec) { 3583 substitute(s, i, endbracket, ""); 3584 return; 3585 } 3586 3587 std::string mdname = active_modem->get_mode_name(); 3588 int rf = 0; 3589 int af = 0; 3590 float rfd = 0; 3591 std::string sGoFreq = s.substr(i+5, endbracket - i - 5); 3592 // no frequency(s) specified 3593 if (sGoFreq.length() == 0) { 3594 substitute(s, i, endbracket, ""); 3595 return; 3596 } 3597 3598 if (fpairs.empty()) { 3599 std::string triad; 3600 size_t pos; 3601 while (!sGoFreq.empty()) { 3602 pos = sGoFreq.find(";"); 3603 if (pos == std::string::npos) triad = sGoFreq; 3604 else triad = sGoFreq.substr(0, pos); 3605 sGoFreq.erase(0, triad.length()+1); 3606 sscanf(triad.c_str(), "%f", &rfd); 3607 if (rfd > 0) rf = (int)(1000*rfd); 3608 if ((pos = triad.find(":")) != std::string::npos) { 3609 triad.erase(0,pos+1); 3610 if (triad.length()) 3611 sscanf(triad.c_str(), "%d", &af); 3612 if (af < 0) af = 0; 3613 if (af < progdefaults.LowFreqCutoff) af = progdefaults.LowFreqCutoff; 3614 if (af > progdefaults.HighFreqCutoff) af = progdefaults.HighFreqCutoff; 3615 } else af = active_modem->get_freq(); 3616 3617 if ((pos = triad.find(":")) != std::string::npos) { 3618 triad.erase(0, pos+1); 3619 strtrim(triad); 3620 fpairs.push(rfafmd(rf, af, triad)); 3621 } else 3622 fpairs.push(rfafmd(rf,af, mdname)); 3623 } 3624 } 3625 3626 struct rfafmd fpair; 3627 3628 fpair = fpairs.front(); 3629 rf = fpair.rf; 3630 af = fpair.af; 3631 if (fpair.mdname != mdname) { 3632 for (int m = 0; m < NUM_MODES; m++) { 3633 if (fpair.mdname == mode_info[m].sname) { 3634 init_modem_sync(mode_info[m].mode); 3635 break; 3636 } 3637 } 3638 } 3639 fpairs.pop(); 3640 3641 if (rf && rf != wf->rfcarrier()) 3642 qsy(rf, af); 3643 else 3644 active_modem->set_freq(af); 3645 3646 substitute(s, i, endbracket, ""); 3647 } 3648 3649 static void doQSY(std::string s) 3650 { 3651 int rf = 0; 3652 int audio = 0; 3653 float rfd = 0; 3654 std::string sGoFreq; 3655 sGoFreq = s.substr(6, s.length() - 7); 3656 // no frequency(s) specified 3657 if (sGoFreq.length() == 0) { 3658 que_ok = true; 3659 return; 3660 } 3661 // rf first value 3662 sscanf(sGoFreq.c_str(), "%f", &rfd); 3663 if (rfd > 0) 3664 rf = (int)(1000*rfd); 3665 size_t pos; 3666 if ((pos = sGoFreq.find(":")) != std::string::npos) { 3667 // af second value 3668 sGoFreq.erase(0, pos+1); 3669 if (sGoFreq.length()) 3670 sscanf(sGoFreq.c_str(), "%d", &audio); 3671 if (audio < 0) audio = 0; 3672 if (audio < progdefaults.LowFreqCutoff) 3673 audio = progdefaults.LowFreqCutoff; 3674 if (audio > progdefaults.HighFreqCutoff) 3675 audio = progdefaults.HighFreqCutoff; 3676 } 3677 if (rf && rf != wf->rfcarrier()) 3678 qsy(rf, audio); 3679 else 3680 active_modem->set_freq(audio); 3681 que_ok = true; 3682 } 3683 3684 static void pTxQueQSY(std::string &s, size_t &i, size_t endbracket) 3685 { 3686 if (within_exec) { 3687 substitute(s, i, endbracket, ""); 3688 return; 3689 } 3690 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doQSY }; 3691 push_txcmd(cmd); 3692 substitute(s, i, endbracket, "^!"); 3693 } 3694 3695 float wait_after_mode_change = 0.0; 3696 static string sFILWID; 3697 static void delayedFILWID(void *) 3698 { 3699 qso_opBW->value(sFILWID.c_str()); 3700 cb_qso_opBW(); 3701 wait_after_mode_change = 0.0; 3702 } 3703 3704 static void pFILWID(std::string& s, size_t& i, size_t endbracket) 3705 { 3706 if (within_exec) { 3707 substitute(s, i, endbracket, ""); 3708 return; 3709 } 3710 std::string sWidth = s.substr(i+8, endbracket - i - 8); 3711 sFILWID = sWidth; 3712 Fl::add_timeout(wait_after_mode_change, delayedFILWID); 3713 substitute(s, i, endbracket, ""); 3714 } 3715 3716 static void doFILWID(std::string s) 3717 { 3718 std::string sWID = s.substr(9, s.length() - 10); 3719 qso_opBW->value(sWID.c_str()); 3720 cb_qso_opBW(); 3721 que_ok = true; 3722 } 3723 3724 static void pTxQueFILWID(std::string &s, size_t &i, size_t endbracket) 3725 { 3726 if (within_exec) { 3727 substitute(s, i, endbracket, ""); 3728 return; 3729 } 3730 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doFILWID }; 3731 push_txcmd(cmd); 3732 substitute(s, i, endbracket, "^!"); 3733 } 3734 3735 static void pRxQueFILWID(std::string &s, size_t &i, size_t endbracket) 3736 { 3737 if (within_exec) { 3738 substitute(s, i, endbracket, ""); 3739 return; 3740 } 3741 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doFILWID }; 3742 push_rxcmd(cmd); 3743 substitute(s, i, endbracket, ""); 3744 } 3745 3746 static void pRIGMODE(std::string& s, size_t& i, size_t endbracket) 3747 { 3748 if (within_exec) { 3749 substitute(s, i, endbracket, ""); 3750 return; 3751 } 3752 std::string sMode = s.substr(i+9, endbracket - i - 9); 3753 qso_opMODE->value(sMode.c_str()); 3754 cb_qso_opMODE(); 3755 substitute(s, i, endbracket, ""); 3756 if ((s.find("FILWID") != string::npos) || 3757 (s.find("RIGLO") != string::npos) || 3758 (s.find("RIGHI") != string::npos) ) 3759 wait_after_mode_change = progdefaults.mbw; 3760 else 3761 wait_after_mode_change = 0; 3762 } 3763 3764 static void doRIGMODE(std::string s) 3765 { 3766 std::string sMode = s.substr(10, s.length() - 11); 3767 qso_opMODE->value(sMode.c_str()); 3768 cb_qso_opMODE(); 3769 que_ok = true; 3770 } 3771 3772 static void pTxQueRIGMODE(std::string &s, size_t &i, size_t endbracket) 3773 { 3774 if (within_exec) { 3775 substitute(s, i, endbracket, ""); 3776 return; 3777 } 3778 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE }; 3779 push_txcmd(cmd); 3780 substitute(s, i, endbracket, "^!"); 3781 } 3782 3783 static void pRxQueRIGMODE(std::string &s, size_t &i, size_t endbracket) 3784 { 3785 if (within_exec) { 3786 substitute(s, i, endbracket, ""); 3787 return; 3788 } 3789 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGMODE }; 3790 push_rxcmd(cmd); 3791 substitute(s, i, endbracket, ""); 3792 } 3793 3794 static string sRIGLO; 3795 3796 static void delayedRIGLO(void *) 3797 { 3798 qso_opBW2->value(sRIGLO.c_str()); 3799 cb_qso_opBW2(); 3800 wait_after_mode_change = 0.0; 3801 } 3802 3803 static void pRIGLO(std::string& s, size_t& i, size_t endbracket) 3804 { 3805 if (within_exec) { 3806 substitute(s, i, endbracket, ""); 3807 return; 3808 } 3809 std::string sLO = s.substr(i+7, endbracket - i - 7); 3810 sRIGLO = sLO; 3811 if (wait_after_mode_change) 3812 Fl::add_timeout(wait_after_mode_change, delayedRIGLO); 3813 else { 3814 qso_opBW2->value(sLO.c_str()); 3815 cb_qso_opBW2(); 3816 } 3817 substitute(s, i, endbracket, ""); 3818 } 3819 3820 static void doRIGLO(std::string s) 3821 { 3822 std::string sLO = s.substr(8, s.length() - 9); 3823 qso_opBW2->value(sLO.c_str()); 3824 cb_qso_opBW2(); 3825 que_ok = true; 3826 } 3827 3828 static void pTxQueRIGLO(std::string &s, size_t &i, size_t endbracket) 3829 { 3830 if (within_exec) { 3831 substitute(s, i, endbracket, ""); 3832 return; 3833 } 3834 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGLO }; 3835 push_txcmd(cmd); 3836 substitute(s, i, endbracket, "^!"); 3837 } 3838 3839 static void pRxQueRIGLO(std::string &s, size_t &i, size_t endbracket) 3840 { 3841 if (within_exec) { 3842 substitute(s, i, endbracket, ""); 3843 return; 3844 } 3845 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGLO }; 3846 push_rxcmd(cmd); 3847 substitute(s, i, endbracket, ""); 3848 } 3849 3850 static string sRIGHI; 3851 3852 static void delayedRIGHI(void *) 3853 { 3854 qso_opBW1->value(sRIGHI.c_str()); 3855 cb_qso_opBW1(); 3856 wait_after_mode_change = 0.0; 3857 } 3858 3859 static void pRIGHI(std::string& s, size_t& i, size_t endbracket) 3860 { 3861 if (within_exec) { 3862 substitute(s, i, endbracket, ""); 3863 return; 3864 } 3865 std::string sHI = s.substr(i+7, endbracket - i - 7); 3866 sRIGHI = sHI; 3867 if (wait_after_mode_change) 3868 Fl::add_timeout(wait_after_mode_change, delayedRIGHI); 3869 else { 3870 qso_opBW1->value(sHI.c_str()); 3871 cb_qso_opBW1(); 3872 } 3873 substitute(s, i, endbracket, ""); 3874 } 3875 3876 static void doRIGHI(std::string s) 3877 { 3878 std::string sHI = s.substr(8, s.length() - 9); 3879 qso_opBW1->value(sHI.c_str()); 3880 cb_qso_opBW1(); 3881 que_ok = true; 3882 } 3883 3884 static void pTxQueRIGHI(std::string &s, size_t &i, size_t endbracket) 3885 { 3886 if (within_exec) { 3887 substitute(s, i, endbracket, ""); 3888 return; 3889 } 3890 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGHI }; 3891 push_txcmd(cmd); 3892 substitute(s, i, endbracket, "^!"); 3893 } 3894 3895 static void pRxQueRIGHI(std::string &s, size_t &i, size_t endbracket) 3896 { 3897 if (within_exec) { 3898 substitute(s, i, endbracket, ""); 3899 return; 3900 } 3901 struct CMDS cmd = { s.substr(i, endbracket - i + 1), doRIGHI }; 3902 push_rxcmd(cmd); 3903 substitute(s, i, endbracket, ""); 3904 } 3905 3906 static void pWX(std::string &s, size_t &i, size_t endbracket) 3907 { 3908 string wx; 3909 getwx(wx); 3910 s.replace(i, 4, wx); 3911 } 3912 3913 // <WX:metar> 3914 static void pWX2(std::string &s, size_t &i, size_t endbracket) 3915 { 3916 string wx; 3917 getwx(wx, s.substr(i+4, endbracket - i - 4).c_str()); 3918 substitute(s, i, endbracket, wx); 3919 } 3920 3921 3922 void set_macro_env(void) 3923 { 3924 enum { 3925 #ifndef __WOE32__ 3926 pSKEDH, FLDIGI_RX_IPC_KEY, FLDIGI_TX_IPC_KEY, 3927 #endif 3928 FLDIGI_XMLRPC_ADDRESS, 3929 FLDIGI_XMLRPC_PORT, 3930 FLDIGI_ARQ_ADDRESS, 3931 FLDIGI_ARQ_PORT, 3932 3933 FLDIGI_VERSION_ENVVAR, 3934 FLDIGI_PID, 3935 FLDIGI_CONFIG_DIR, 3936 3937 FLDIGI_MY_CALL, 3938 FLDIGI_MY_NAME, 3939 FLDIGI_MY_LOCATOR, 3940 3941 FLDIGI_MODEM, 3942 FLDIGI_MODEM_LONG_NAME, 3943 FLDIGI_MODEM_ADIF_NAME, 3944 FLDIGI_DIAL_FREQUENCY, 3945 FLDIGI_AUDIO_FREQUENCY, 3946 FLDIGI_FREQUENCY, 3947 3948 FLDIGI_MACRO_FILE, 3949 3950 FLDIGI_LOG_FILE, 3951 FLDIGI_LOG_FREQUENCY, 3952 FLDIGI_LOG_DATE, 3953 FLDIGI_LOG_DATE_OFF, 3954 FLDIGI_LOG_TIME_ON, 3955 FLDIGI_LOG_TIME_OFF, 3956 FLDIGI_LOG_CALL, 3957 FLDIGI_LOG_NAME, 3958 FLDIGI_LOG_RST_IN, 3959 FLDIGI_LOG_RST_OUT, 3960 FLDIGI_LOG_QTH, 3961 FLDIGI_LOG_LOCATOR, 3962 FLDIGI_LOG_NOTES, 3963 FLDIGI_LOG_STATE, 3964 FLDIGI_LOG_COUNTRY, 3965 FLDIGI_LOG_COUNTY, 3966 FLDIGI_LOG_SERNO_IN, 3967 FLDIGI_LOG_SERNO_OUT, 3968 FLDIGI_XCHG_IN, 3969 FLDIGI_XCGH_OUT, 3970 FLDIGI_CLASS_IN, 3971 FLDIGI_ARRL_SECTION_IN, 3972 FLDIGI_VE_PROV, 3973 FLDIGI_AZ, 3974 3975 FLDIGI_LOGBOOK_CALL, 3976 FLDIGI_LOGBOOK_NAME, 3977 FLDIGI_LOGBOOK_DATE, 3978 FLDIGI_LOGBOOK_TIME_ON, 3979 FLDIGI_LOGBOOK_DATE_OFF, 3980 FLDIGI_LOGBOOK_TIME_OFF, 3981 FLDIGI_LOGBOOK_RST_IN, 3982 FLDIGI_LOGBOOK_RST_OUT, 3983 FLDIGI_LOGBOOK_FREQUENCY, 3984 FLDIGI_LOGBOOK_MODE, 3985 FLDIGI_LOGBOOK_STATE, 3986 FLDIGI_LOGBOOK_VE_PROV, 3987 FLDIGI_LOGBOOK_COUNTRY, 3988 FLDIGI_LOGBOOK_SERNO_IN, 3989 FLDIGI_LOGBOOK_SERNO_OUT, 3990 FLDIGI_LOGBOOK_XCHG_IN, 3991 FLDIGI_LOGBOOK_XCHG_OUT, 3992 FLDIGI_LOGBOOK_CLASS_IN, 3993 FLDIGI_LOGBOOK_SECTION_IN, 3994 FLDIGI_LOGBOOK_QTH, 3995 FLDIGI_LOGBOOK_LOCATOR, 3996 FLDIGI_LOGBOOK_QSL_R, 3997 FLDIGI_LOGBOOK_QSL_S, 3998 FLDIGI_LOGBOOK_NOTES, 3999 FLDIGI_LOGBOOK_TX_PWR, 4000 FLDIGI_LOGBOOK_COUNTY, 4001 FLDIGI_LOGBOOK_IOTA, 4002 FLDIGI_LOGBOOK_DXCC, 4003 FLDIGI_LOGBOOK_QSL_VIA, 4004 FLDIGI_LOGBOOK_CONTINENT, 4005 FLDIGI_LOGBOOK_CQZ, 4006 FLDIGI_LOGBOOK_ITUZ, 4007 FLDIGI_LOGBOOK_SS_SERNO, 4008 FLDIGI_LOGBOOK_SS_PREC, 4009 FLDIGI_LOGBOOK_SS_CHK, 4010 FLDIGI_LOGBOOK_SS_SEC, 4011 4012 ENV_SIZE 4013 }; 4014 4015 struct { 4016 const char* var; 4017 const char* val; 4018 } env[] = { 4019 #ifndef __WOE32__ 4020 { "pSKEDH", "" }, 4021 { "FLDIGI_RX_IPC_KEY", "" }, 4022 { "FLDIGI_TX_IPC_KEY", "" }, 4023 #endif 4024 { "FLDIGI_XMLRPC_ADDRESS", progdefaults.xmlrpc_address.c_str() }, 4025 { "FLDIGI_XMLRPC_PORT", progdefaults.xmlrpc_port.c_str() }, 4026 { "FLDIGI_ARQ_ADDRESS", progdefaults.arq_address.c_str() }, 4027 { "FLDIGI_ARQ_PORT", progdefaults.arq_port.c_str() }, 4028 4029 { "FLDIGI_VERSION", PACKAGE_VERSION }, 4030 { "FLDIGI_PID", "" }, 4031 { "FLDIGI_CONFIG_DIR", HomeDir.c_str() }, 4032 4033 { "FLDIGI_MY_CALL", progdefaults.myCall.c_str() }, 4034 { "FLDIGI_MY_NAME", progdefaults.myName.c_str() }, 4035 { "FLDIGI_MY_LOCATOR", progdefaults.myLocator.c_str() }, 4036 4037 { "FLDIGI_MODEM", mode_info[active_modem->get_mode()].sname }, 4038 { "FLDIGI_MODEM_LONG_NAME", mode_info[active_modem->get_mode()].name }, 4039 { "FLDIGI_MODEM_ADIF_NAME", mode_info[active_modem->get_mode()].adif_name }, 4040 4041 { "FLDIGI_DIAL_FREQUENCY", "" }, 4042 { "FLDIGI_AUDIO_FREQUENCY", "" }, 4043 { "FLDIGI_FREQUENCY", "" }, 4044 4045 // logging frame 4046 { "FLDIGI_MACRO_FILE", progStatus.LastMacroFile.c_str() }, 4047 4048 { "FLDIGI_LOG_FILE", progdefaults.logbookfilename.c_str() }, 4049 4050 { "FLDIGI_LOG_FREQUENCY", inpFreq->value() }, 4051 { "FLDIGI_LOG_DATE", inpDate_log->value() }, 4052 { "FLDIGI_LOG_DATE_OFF", inpDateOff_log->value() }, 4053 { "FLDIGI_LOG_TIME_ON", inpTimeOn->value() }, 4054 { "FLDIGI_LOG_TIME_OFF", inpTimeOff->value() }, 4055 { "FLDIGI_LOG_CALL", inpCall->value() }, 4056 { "FLDIGI_LOG_NAME", inpName->value() }, 4057 { "FLDIGI_LOG_RST_IN", inpRstIn->value() }, 4058 { "FLDIGI_LOG_RST_OUT", inpRstOut->value() }, 4059 { "FLDIGI_LOG_QTH", inpQth->value() }, 4060 { "FLDIGI_LOG_LOCATOR", inpLoc->value() }, 4061 { "FLDIGI_LOG_NOTES", inpNotes->value() }, 4062 { "FLDIGI_LOG_STATE", inpState->value() }, 4063 { "FLDIGI_LOG_COUNTRY", cboCountry->value() }, 4064 { "FLDIGI_LOG_COUNTY", inpCounty->value() }, 4065 { "FLDIGI_LOG_SERNO_IN", inpSerNo->value() }, 4066 { "FLDIGI_LOG_SERNO_OUT", outSerNo->value() }, 4067 { "FLDIGI_XCHG_IN", inpXchgIn->value() }, 4068 { "FLDIGI_XCHG_OUT", inpSend1->value() }, 4069 { "FLDIGI_CLASS_IN", inpClass->value() }, 4070 { "FLDIGI_ARRL_SECTION_IN", inpSection->value() }, 4071 { "FLDIGI_VE_PROV", inpVEprov->value() }, 4072 { "FLDIGI_AZ", inpAZ->value() }, 4073 4074 { "FLDIGI_LOGBOOK_CALL", inpCall_log->value() }, 4075 { "FLDIGI_LOGBOOK_NAME", inpName_log->value () }, 4076 { "FLDIGI_LOGBOOK_DATE", inpDate_log->value() }, 4077 { "FLDIGI_LOGBOOK_TIME_ON", inpTimeOn_log->value() }, 4078 { "FLDIGI_LOGBOOK_DATE_OFF", inpDateOff_log->value() }, 4079 { "FLDIGI_LOGBOOK_TIME_OFF", inpTimeOff_log->value() }, 4080 { "FLDIGI_LOGBOOK_RST_IN", inpRstR_log->value() }, 4081 { "FLDIGI_LOGBOOK_RST_OUT", inpRstS_log->value() }, 4082 { "FLDIGI_LOGBOOK_FREQUENCY", inpFreq_log->value() }, 4083 { "FLDIGI_LOGBOOK_BAND", inpBand_log->value() }, 4084 { "FLDIGI_LOGBOOK_MODE", inpMode_log->value() }, 4085 { "FLDIGI_LOGBOOK_STATE", inpState_log->value() }, 4086 { "FLDIGI_LOGBOOK_VE_PROV", inpVE_Prov_log->value() }, 4087 { "FLDIGI_LOGBOOK_COUNTRY", inpCountry_log->value() }, 4088 { "FLDIGI_LOGBOOK_SERNO_IN", inpSerNoIn_log->value() }, 4089 { "FLDIGI_LOGBOOK_SERNO_OUT", inpSerNoOut_log->value() }, 4090 { "FLDIGI_LOGBOOK_XCHG_IN", inpXchgIn_log->value() }, 4091 { "FLDIGI_LOGBOOK_XCHG_OUT", inpMyXchg_log->value() }, 4092 { "FLDIGI_LOGBOOK_CLASS_IN", inpClass_log->value() }, 4093 { "FLDIGI_LOGBOOK_ARRL_SECT_IN", inpSection_log->value() }, 4094 { "FLDIGI_LOGBOOK_QTH", inpQth_log->value() }, 4095 { "FLDIGI_LOGBOOK_LOCATOR", inpLoc_log->value() }, 4096 { "FLDIGI_LOGBOOK_QSL_R", inpQSLrcvddate_log->value() }, 4097 { "FLDIGI_LOGBOOK_QSL_S", inpQSLsentdate_log->value() }, 4098 { "FLDIGI_LOGBOOK_TX_PWR", inpTX_pwr_log->value() }, 4099 { "FLDIGI_LOGBOOK_COUNTY", inpCNTY_log->value() }, 4100 { "FLDIGI_LOGBOOK_IOTA", inpIOTA_log->value() }, 4101 { "FLDIGI_LOGBOOK_DXCC", inpDXCC_log->value() }, 4102 { "FLDIGI_LOGBOOK_QSL_VIA", inpQSL_VIA_log->value() }, 4103 { "FLDIGI_LOGBOOK_CONTINENT", inpCONT_log->value() }, 4104 { "FLDIGI_LOGBOOK_CQZ", inpCQZ_log->value() }, 4105 { "FLDIGI_LOGBOOK_ITUZ", inpITUZ_log->value() }, 4106 { "FLDIGI_LOGBOOK_SS_SERNO", inp_log_cwss_serno->value() }, 4107 { "FLDIGI_LOGBOOK_SS_PREC", inp_log_cwss_prec->value() }, 4108 { "FLDIGI_LOGBOOK_SS_CHK", inp_log_cwss_chk->value() }, 4109 { "FLDIGI_LOGBOOK_SS_SEC", inp_log_cwss_sec->value() }, 4110 { "FLDIGI_LOGBOOK_NOTES", inpNotes_log->value() } 4111 4112 }; 4113 4114 #ifndef __WOE32__ 4115 // pSKEDH 4116 static std::string pSKEDh = ScriptsDir; 4117 pSKEDh.erase(pSKEDh.length()-1,1); 4118 const char* p; 4119 if ((p = getenv("pSKEDH"))) 4120 pSKEDh.append(":").append(p); 4121 env[pSKEDH].val = pSKEDh.c_str(); 4122 4123 // IPC keys 4124 char key[2][8]; 4125 snprintf(key[0], sizeof(key[0]), "%d", progdefaults.rx_msgid); 4126 env[FLDIGI_RX_IPC_KEY].val = key[0]; 4127 snprintf(key[1], sizeof(key[1]), "%d", progdefaults.tx_msgid); 4128 env[FLDIGI_TX_IPC_KEY].val = key[1]; 4129 #endif 4130 4131 // pid 4132 char pid[6]; 4133 snprintf(pid, sizeof(pid), "%d", getpid()); 4134 env[FLDIGI_PID].val = pid; 4135 4136 // frequencies 4137 char dial_freq[20]; 4138 snprintf(dial_freq, sizeof(dial_freq), "%ld", (long)wf->rfcarrier()); 4139 env[FLDIGI_DIAL_FREQUENCY].val = dial_freq; 4140 char audio_freq[6]; 4141 snprintf(audio_freq, sizeof(audio_freq), "%d", active_modem->get_freq()); 4142 env[FLDIGI_AUDIO_FREQUENCY].val = audio_freq; 4143 char freq[20]; 4144 snprintf(freq, sizeof(freq), "%ld", (long)(wf->rfcarrier() + (wf->USB() 4145 ? active_modem->get_freq() 4146 : -active_modem->get_freq()))); 4147 env[FLDIGI_FREQUENCY].val = freq; 4148 4149 // debugging vars 4150 #if !defined(NDEBUG) && !defined(__WOE32__) 4151 unsetenv("FLDIGI_NO_EXEC"); 4152 unsetenv("MALLOC_CHECK_"); 4153 unsetenv("MALLOC_PERTURB_"); 4154 #endif 4155 4156 string temp; 4157 size_t pch; 4158 for (size_t j = 0; j < sizeof(env) / sizeof (*env); j++) { 4159 temp = env[j].val; 4160 while ((pch = temp.find("\n")) != string::npos) temp[pch] = ';'; 4161 setenv(env[j].var, temp.c_str(), 1); 4162 } 4163 4164 string path = getenv("PATH"); 4165 string mypath = ScriptsDir; 4166 if (mypath[mypath.length()-1] == '/') 4167 mypath.erase(mypath.length()-1, 1); 4168 mypath.append(":"); 4169 path.insert(0,mypath); 4170 setenv("PATH", path.c_str(), 1); 4171 4172 } 4173 4174 // this is only for the case where the user tries to nest <EXEC>... 4175 // as in 4176 // <EXEC> ... <EXEC> ... </EXEC></EXEC> 4177 // which is not permitted 4178 static void pEND_EXEC(std::string &s, size_t &i, size_t endbracket) 4179 { 4180 substitute(s, i, endbracket, ""); 4181 return; 4182 } 4183 4184 #ifndef __MINGW32__ 4185 static void pEXEC(std::string &s, size_t &i, size_t endbracket) 4186 { 4187 if (within_exec) { 4188 substitute(s, i, endbracket, ""); 4189 return; 4190 } 4191 4192 size_t start = s.find(">", i); 4193 size_t end = s.find("</EXEC>", start); 4194 4195 if (start == std::string::npos || 4196 end == std::string::npos) { 4197 i++; 4198 return; 4199 } 4200 4201 std::string execstr = s.substr(start+1, end-start-1); 4202 within_exec = true; 4203 MACROTEXT m; 4204 execstr = m.expandMacro(execstr, true); 4205 // execstr.insert(0,ScriptsDir); 4206 within_exec = false; 4207 4208 int pfd[2]; 4209 if (pipe(pfd) == -1) { 4210 LOG_PERROR("pipe"); 4211 return; 4212 } 4213 pid_t pid; 4214 switch (pid = fork()) { 4215 case -1: 4216 LOG_PERROR("fork"); 4217 return; 4218 case 0: // child 4219 close(pfd[0]); 4220 if (dup2(pfd[1], STDOUT_FILENO) != STDOUT_FILENO) { 4221 LOG_PERROR("dup2"); 4222 exit(EXIT_FAILURE); 4223 } 4224 close(pfd[1]); 4225 set_macro_env(); 4226 execl("/bin/sh", "sh", "-c", execstr.c_str(), (char *)NULL); 4227 perror("execl"); 4228 exit(EXIT_FAILURE); 4229 } 4230 4231 // parent 4232 close(pfd[1]); 4233 4234 // give child process time to complete 4235 MilliSleep(50); 4236 FILE* fp = fdopen(pfd[0], "r"); 4237 if (!fp) { 4238 LOG_PERROR("fdopen"); 4239 close(pfd[0]); 4240 return; 4241 } 4242 4243 s.erase(i, end - i + strlen("</EXEC>")); 4244 4245 char ln[BUFSIZ]; 4246 string lnbuff = ""; 4247 while (fgets(ln, sizeof(ln), fp)) { 4248 lnbuff.append(ln); 4249 } 4250 // remove all trailing end-of-lines 4251 while (lnbuff[lnbuff.length()-1] == '\n') 4252 lnbuff.erase(lnbuff.length()-1,1); 4253 4254 if (!lnbuff.empty()) { 4255 lnbuff = m.expandMacro(lnbuff, false); 4256 s.insert(i, lnbuff); 4257 i += lnbuff.length(); 4258 } else 4259 i++; 4260 4261 fclose(fp); 4262 close(pfd[0]); 4263 4264 } 4265 #else // !__MINGW32__ 4266 4267 static void pEXEC(std::string& s, size_t& i, size_t endbracket) 4268 { 4269 if (within_exec) { 4270 substitute(s, i, endbracket, ""); 4271 return; 4272 } 4273 size_t start, end; 4274 if ((start = s.find('>', i)) == std::string::npos || 4275 (end = s.rfind("</EXEC>")) == std::string::npos) { 4276 i++; 4277 return; 4278 } 4279 start++; 4280 4281 std::string execstr = s.substr(start, end-start); 4282 within_exec = true; 4283 MACROTEXT m; 4284 execstr = m.expandMacro(execstr, true); 4285 within_exec = false; 4286 4287 char* cmd = strdup(execstr.c_str()); 4288 4289 STARTUPINFO si; 4290 PROCESS_INFORMATION pi; 4291 memset(&si, 0, sizeof(si)); 4292 si.cb = sizeof(si); 4293 memset(&pi, 0, sizeof(pi)); 4294 if (!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 4295 LOG_ERROR("CreateProcess failed with error code %ld", GetLastError()); 4296 CloseHandle(pi.hProcess); 4297 CloseHandle(pi.hThread); 4298 free(cmd); 4299 4300 s.erase(i, end + strlen("</EXEC>") - i); 4301 } 4302 #endif // !__MINGW32__ 4303 4304 static void pEQSL(std::string& s, size_t& i, size_t endbracket) 4305 { 4306 if (within_exec || progdefaults.eqsl_when_logged) { 4307 substitute(s, i, endbracket, ""); 4308 return; 4309 } 4310 size_t start = s.find(':', i); 4311 4312 std::string msg = ""; 4313 if (start != std::string::npos) 4314 msg = s.substr(start + 1, endbracket-start-1); 4315 4316 makeEQSL(msg.c_str()); 4317 4318 substitute(s, i, endbracket, ""); 4319 return; 4320 } 4321 4322 static void MAPIT(int how) 4323 { 4324 float lat = 0, lon = 0; 4325 std::string sCALL = inpCall->value(); 4326 std::string sLOC = inpLoc->value(); 4327 4328 std::string url = "http://maps.google.com/maps?q="; 4329 4330 if (how > 1 && !lookup_country.empty()) { 4331 url.append(lookup_addr1).append(",").append(lookup_addr2).append(","); 4332 url.append(lookup_state).append(",").append(lookup_country); 4333 } else { 4334 if (how > 0 && (!lookup_latd.empty() && !lookup_lond.empty())) { 4335 url.append(lookup_latd).append(","); 4336 url.append(lookup_lond); 4337 } else { 4338 if (sLOC.empty()) return; 4339 if (sLOC.length() < 4) return; 4340 if (sLOC.length() < 6) sLOC.append("aa"); 4341 for (size_t i = 0; i < 6; i++) sLOC[i] = toupper(sLOC[i]); 4342 if (sLOC[0] -'A' > 17 || sLOC[4] - 'A' > 23 || 4343 sLOC[1] -'A' > 17 || sLOC[5] - 'A' > 23 || 4344 !isdigit(sLOC[2]) || !isdigit(sLOC[3])) return; 4345 lon = -180.0 + 4346 (sLOC[0] - 'A') * 20 + 4347 (sLOC[2] - '0') * 2 + 4348 (sLOC[4] - 'A' + 0.5) / 12; 4349 lat = -90.0 + 4350 (sLOC[1] - 'A') * 10 + 4351 (sLOC[3] - '0') + 4352 (sLOC[5] - 'A' + 0.5) / 24; 4353 char sdata[20]; 4354 snprintf(sdata, sizeof(sdata),"%10.6f", lat); 4355 url.append(sdata).append(","); 4356 snprintf(sdata, sizeof(sdata),"%10.6f", lon); 4357 url.append(sdata); 4358 } 4359 } 4360 if (!sCALL.empty()) url.append("(").append(sCALL).append(")"); 4361 else url.append("(nocall)"); 4362 url.append("&t=p&z=10"); 4363 cb_mnuVisitURL(NULL, (void*)url.c_str()); 4364 } 4365 4366 static void pMAPIT(std::string &s, size_t &i, size_t endbracket) 4367 { 4368 if (within_exec) { 4369 substitute(s, i, endbracket, ""); 4370 return; 4371 } 4372 std::string sVal = s.substr(i + 7, endbracket - i - 7); 4373 if (sVal.length() > 0) { 4374 if (sVal.compare(0,3,"adr") == 0) 4375 REQ(MAPIT,2); 4376 else if (sVal.compare(0,6,"latlon") == 0) 4377 REQ(MAPIT,1); 4378 else if (sVal.compare(0,3,"loc") == 0) 4379 REQ(MAPIT,0); 4380 else 4381 REQ(MAPIT,2); 4382 } else 4383 REQ(MAPIT,2); 4384 s.erase(i, s.find('>', i) + 1 - i); 4385 expand = false; 4386 } 4387 4388 static void pSTOP(std::string &s, size_t &i, size_t endbracket) 4389 { 4390 if (within_exec) { 4391 substitute(s, i, endbracket, ""); 4392 return; 4393 } 4394 s.erase(i, s.find('>', i) + 1 - i); 4395 expand = false; 4396 } 4397 4398 static void pCONT(std::string &s, size_t &i, size_t endbracket) 4399 { 4400 if (within_exec) { 4401 substitute(s, i, endbracket, ""); 4402 return; 4403 } 4404 s.erase(i, s.find('>', i) + 1 - i); 4405 expand = true; 4406 } 4407 4408 //---------------------------------------------------------------------- 4409 // macro scheduling 4410 //---------------------------------------------------------------------- 4411 4412 static long sk_xdt, sk_xtm; 4413 4414 static void pLOCAL(std::string &s, size_t &i, size_t endbracket) 4415 { 4416 local_timed_exec = true; 4417 substitute(s, i, endbracket, ""); 4418 } 4419 4420 static void pSKED(std::string &s, size_t &i, size_t endbracket) 4421 { 4422 if (within_exec || progStatus.skip_sked_macro) { 4423 substitute(s, i, endbracket, ""); 4424 return; 4425 } 4426 std::string data = s.substr(i+6, endbracket - i - 6); 4427 size_t p = data.find(":"); 4428 if (p == std::string::npos) { 4429 exec_date = (local_timed_exec ? ldate() : zdate()); 4430 exec_time = data; 4431 if (exec_time.empty()) exec_time = (local_timed_exec ? ltime() : ztime()); 4432 } else { 4433 exec_time = data.substr(0, p); 4434 exec_date = data.substr(p+1); 4435 } 4436 if (exec_time.length() == 4) 4437 exec_time.append("00"); 4438 4439 sk_xdt = atol(exec_date.c_str()); 4440 sk_xtm = atol(exec_time.c_str()); 4441 4442 timed_exec = true; 4443 substitute(s, i, endbracket, ""); 4444 } 4445 4446 int timed_ptt = -1; 4447 4448 void do_timed_execute(void *) 4449 { 4450 long dt, tm; 4451 dt = atol( local_timed_exec ? ldate() : zdate() ); 4452 tm = atol( local_timed_exec ? ltime() : ztime() ); 4453 4454 if (dt >= sk_xdt && tm >= sk_xtm) { 4455 show_clock(false); 4456 if (timed_ptt != 1) { 4457 push2talk->set(true); 4458 timed_ptt = 1; 4459 } 4460 Qwait_time = 0; 4461 start_tx(); 4462 que_ok = true; 4463 btnMacroTimer->label(0); 4464 btnMacroTimer->color(FL_BACKGROUND_COLOR); 4465 btnMacroTimer->set_output(); 4466 sk_xdt = sk_xtm = 0; 4467 } else { 4468 show_clock(true); 4469 if (timed_ptt != 0) { 4470 push2talk->set(false); 4471 timed_ptt = 0; 4472 } 4473 Fl::repeat_timeout(1.0, do_timed_execute); 4474 } 4475 } 4476 4477 static void doSKED(std::string s) 4478 { 4479 size_t p = s.find(":"); 4480 if (p == std::string::npos) { 4481 exec_date = (local_timed_exec ? ldate() : zdate()); 4482 exec_time = s; 4483 if (exec_time.empty()) 4484 exec_time = (local_timed_exec ? ltime() : ztime()); 4485 } else { 4486 exec_time = s.substr(0, p); 4487 exec_date = s.substr(p+1); 4488 } 4489 if (exec_time.length() == 4) 4490 exec_time.append("00"); 4491 4492 string txt; 4493 txt.assign("Next scheduled transmission at "). 4494 append(exec_time.substr(0,2)).append(":"). 4495 append(exec_time.substr(2,2)).append(":"). 4496 append(exec_time.substr(4,2)). 4497 append(", on "). 4498 append(exec_date.substr(0,4)).append("/"). 4499 append(exec_date.substr(4,2)).append("/"). 4500 append(exec_date.substr(6,2)).append("\n"); 4501 btnMacroTimer->label("SKED"); 4502 btnMacroTimer->color(fl_rgb_color(240, 240, 0)); 4503 btnMacroTimer->redraw_label(); 4504 ReceiveText->addstr(txt, FTextBase::CTRL); 4505 4506 Qwait_time = 9999; 4507 4508 sk_xdt = atol(exec_date.c_str()); 4509 sk_xtm = atol(exec_time.c_str()); 4510 4511 Fl::add_timeout(0.0, do_timed_execute); 4512 4513 } 4514 4515 static void pTxQueSKED(std::string &s, size_t &i, size_t endbracket) 4516 { 4517 if (within_exec) { 4518 substitute(s, i, endbracket, ""); 4519 return; 4520 } 4521 struct CMDS cmd = { s.substr(i + 7, endbracket - i - 7), doSKED }; 4522 push_txcmd(cmd); 4523 substitute(s, i, endbracket, "^!"); 4524 } 4525 4526 static void pUNTIL(std::string &s, size_t &i, size_t endbracket) 4527 { 4528 if (within_exec) { 4529 substitute(s, i, endbracket, ""); 4530 return; 4531 } 4532 std::string data = s.substr(i+7, endbracket - i - 7); 4533 size_t p = data.find(":"); 4534 if (p == std::string::npos) { 4535 until_date = (local_timed_exec ? ldate() : zdate()); 4536 until_time = data; 4537 } else { 4538 until_time = data.substr(0, p); 4539 until_date = data.substr(p+1); 4540 } 4541 if (until_time.empty()) { 4542 substitute(s, i, endbracket, ""); 4543 return; 4544 } 4545 if (until_time.length() == 4) until_time.append("00"); 4546 run_until = true; 4547 substitute(s, i, endbracket, ""); 4548 } 4549 4550 void queue_reset() 4551 { 4552 if (!Tx_cmds.empty()) { 4553 Fl::remove_timeout(post_queue_execute); 4554 Fl::remove_timeout(queue_execute_after_rx); 4555 Fl::remove_timeout(doneIDLE); 4556 Fl::remove_timeout(doneWAIT); 4557 while (!Tx_cmds.empty()) Tx_cmds.pop(); 4558 } 4559 while (!Rx_cmds.empty()) Rx_cmds.pop(); 4560 while (!mf_stack.empty()) mf_stack.pop(); 4561 Qwait_time = 0; 4562 Qidle_time = 0; 4563 que_ok = true; 4564 run_until = false; 4565 tx_queue_done = true; 4566 progStatus.skip_sked_macro = false; 4567 } 4568 4569 // execute an in-line macro tag 4570 // occurs during the Tx state 4571 void Tx_queue_execute() 4572 { 4573 if (Tx_cmds.empty()) { 4574 Qwait_time = 0; 4575 Qidle_time = 0; 4576 tx_queue_done = true; 4577 return; 4578 } 4579 CMDS cmd = Tx_cmds.front(); 4580 Tx_cmds.pop(); 4581 LOG_INFO("%s", cmd.cmd.c_str()); 4582 REQ(postQueue, cmd.cmd); 4583 cmd.fp(cmd.cmd); 4584 return; 4585 } 4586 4587 bool queue_must_rx() 4588 { 4589 // return true if current command is not a member 'must_rx' 4590 static std::string must_rx = "<!MOD<!WAI<!GOH<!QSY<!GOF<!RIG<!FIL<!PUS<!POP";//<!DIG<!FRE"; 4591 if (Tx_cmds.empty()) return false; 4592 CMDS cmd = Tx_cmds.front(); 4593 return (must_rx.find(cmd.cmd.substr(0,5)) != std::string::npos); 4594 } 4595 4596 // execute all post Tx macros in the Rx_cmds queu 4597 // occurs immediately after the ^r execution 4598 // AND after TX_STATE returns to Rx 4599 // ^r is the control string substitute for the <RX> macro tag 4600 int time_out = 400; 4601 void Rx_queue_execution(void *) 4602 { 4603 if (rx_tune_on) { 4604 Fl::repeat_timeout( .050, Rx_queue_execution ); 4605 return; 4606 } 4607 4608 if (!Tx_cmds.empty()) { 4609 Fl::remove_timeout(post_queue_execute); 4610 Fl::remove_timeout(queue_execute_after_rx); 4611 Fl::remove_timeout(doneIDLE); 4612 Fl::remove_timeout(doneWAIT); 4613 while (!Tx_cmds.empty()) Tx_cmds.pop(); 4614 } 4615 4616 if (trx_state != STATE_RX) { 4617 if (time_out-- == 0) { 4618 while (!Rx_cmds.empty()) Rx_cmds.pop(); 4619 LOG_ERROR("%s", "failed"); 4620 time_out = 200; 4621 return; 4622 } 4623 Fl::repeat_timeout( .050, Rx_queue_execution ); 4624 return; 4625 } 4626 LOG_INFO("action delayed by %4.2f seconds", (400 - time_out)*.050); 4627 4628 time_out = 400; 4629 CMDS cmd; 4630 while (!Rx_cmds.empty()) { 4631 cmd = Rx_cmds.front(); 4632 Rx_cmds.pop(); 4633 LOG_INFO("%s", cmd.cmd.c_str()); 4634 REQ(postQueue, cmd.cmd); 4635 cmd.cmd.erase(0,2); 4636 cmd.cmd.insert(0,"<!"); 4637 cmd.fp(cmd.cmd); 4638 Fl::awake(); 4639 if (rx_tune_on) { 4640 Fl::repeat_timeout( .050, Rx_queue_execution ); 4641 return; 4642 } 4643 if (macro_rx_wait) return; 4644 } 4645 return; 4646 } 4647 4648 void Rx_queue_execute() 4649 { 4650 if (Rx_cmds.empty()) return; 4651 Fl::add_timeout(0, Rx_queue_execution); 4652 } 4653 4654 void rx_que_continue(void *) 4655 { 4656 macro_rx_wait = false; 4657 Rx_queue_execute(); 4658 } 4659 4660 struct MTAGS { const char *mTAG; void (*fp)(std::string &, size_t&, size_t );}; 4661 4662 static const MTAGS mtags[] = { 4663 {"<CPS_FILE:", pCPS_FILE}, 4664 {"<CPS_N:", pCPS_N}, 4665 {"<CPS_STRING:",pCPS_STRING}, 4666 {"<CPS_TEST", pCPS_TEST}, 4667 4668 {"<WAV_FILE:", pWAV_FILE}, 4669 {"<WAV_N:", pWAV_N}, 4670 {"<WAV_STRING:",pWAV_STRING}, 4671 {"<WAV_TEST", pWAV_TEST}, 4672 4673 {"<COMMENT:", pCOMMENT}, 4674 {"<#", pCOMMENT}, 4675 {"<CALL>", pCALL}, 4676 {"<FREQ>", pFREQ}, 4677 {"<BAND>", pBAND}, 4678 {"<LOC>", pLOC}, 4679 {"<MODE>", pMODE}, 4680 {"<NAME>", pNAME}, 4681 {"<QTH>", pQTH}, 4682 {"<RST>", pRST}, 4683 {"<ST>", pST}, 4684 {"<PR>", pPR}, 4685 {"<MYCALL>", pMYCALL}, 4686 {"<MYLOC>", pMYLOC}, 4687 {"<MYNAME>", pMYNAME}, 4688 {"<MYQTH>", pMYQTH}, 4689 {"<MYRST>", pMYRST}, 4690 {"<MYCLASS>", pMYCLASS}, 4691 {"<MYSECTION>", pMYSECTION}, 4692 {"<MYSTATE>", pMYSTATE}, 4693 {"<MYST>", pMYST}, 4694 {"<MYCOUNTY>", pMYCOUNTY}, 4695 {"<MYCNTY>", pMYCNTY}, 4696 {"<ANTENNA>", pANTENNA}, 4697 {"<QSOTIME>", pQSOTIME}, 4698 {"<QSONBR>", pQSONBR}, 4699 {"<NXTNBR>", pNXTNBR}, 4700 {"<INFO1>", pINFO1}, 4701 {"<INFO2>", pINFO2}, 4702 {"<LDT>", pLDT}, 4703 {"<LDT:", pLDT}, 4704 {"<ILDT", pILDT}, 4705 {"<ZDT>", pZDT}, 4706 {"<ZDT:", pZDT}, 4707 {"<IZDT", pIZDT}, 4708 {"<LT", pLT}, 4709 {"<ZT", pZT}, 4710 {"<LD>", pLD}, 4711 {"<LD:", pLD}, 4712 {"<ZD>", pZD}, 4713 {"<ZD:", pZD}, 4714 {"<ID>", p_ID}, 4715 {"<TEXT>", pTEXT}, 4716 {"<VIDEO:", pVIDEO}, 4717 {"<CWID>", pCWID}, 4718 {"<VER>", pVER}, 4719 {"<RIGCAT:", pRIGCAT}, 4720 {"<FLRIG:", pFLRIG}, 4721 {"<CNTR>", pCNTR}, 4722 {"<DECR>", pDECR}, 4723 {"<INCR>", pINCR}, 4724 {"<X1>", pXOUT}, 4725 {"<XIN>", pXIN}, 4726 {"<XOUT>", pXOUT}, 4727 {"<FDCLASS>", pFD_CLASS}, 4728 {"<FDSECT>", pFD_SECTION}, 4729 {"<CLASS>", pCLASS}, 4730 {"<SECTION>", pSECTION}, 4731 {"<XBEG>", pXBEG}, 4732 {"<XEND>", pXEND}, 4733 {"<SAVEXCHG>", pSAVEXCHG}, 4734 {"<SERNO>", pSERNO}, 4735 {"<LASTNO>", pLASTNO}, 4736 {"<LOG", pLOG}, 4737 {"<LNW", pLNW}, 4738 {"<CLRLOG>", pCLRLOG}, 4739 {"<EQSL", pEQSL}, 4740 {"<TIMER:", pTIMER}, 4741 {"<AFTER:", pAFTER}, 4742 {"<IDLE:", pIDLE}, 4743 {"<TUNE:", pTUNE}, 4744 {"<WAIT:", pWAIT}, 4745 {"<NRSID:", pNRSID}, 4746 {"<MODEM>", pMODEM_COMPSKED}, 4747 {"<MODEM:", pMODEM}, 4748 {"<EXEC>", pEXEC}, 4749 {"</EXEC>", pEND_EXEC}, 4750 {"<STOP>", pSTOP}, 4751 {"<CONT>", pCONT}, 4752 {"<PAUSE>", pPAUSE}, 4753 {"<GET>", pGET}, 4754 {"<CLRRX>", pCLRRX}, 4755 {"<CLRTX>", pCLRTX}, 4756 {"<CLRQSO>", pCLRQSO}, 4757 {"<FOCUS>", pFOCUS}, 4758 {"<QSY+:", pQSYPLUS}, 4759 {"<FILE:", pFILE}, 4760 {"<WPM:", pWPM}, 4761 {"<RISE:", pRISETIME}, 4762 {"<PRE:", pPRE}, 4763 {"<POST:", pPOST}, 4764 {"<AFC:", pAFC}, 4765 {"<LOCK:", pLOCK}, 4766 {"<REV:", pREV}, 4767 {"<HS:", pHS}, 4768 {"<RXRSID:", pRX_RSID}, 4769 {"<TXRSID:", pTX_RSID}, 4770 {"<DTMF:", pDTMF}, 4771 {"<SRCHUP>", pSRCHUP}, 4772 {"<SRCHDN>", pSRCHDN}, 4773 {"<GOHOME>", pGOHOME}, 4774 {"<GOFREQ:", pGOFREQ}, 4775 {"<QRG:", pQRG}, 4776 {"<QSY:", pQSY}, 4777 {"<QSYTO>", pQSYTO}, 4778 {"<QSYFM>", pQSYFM}, 4779 {"<RIGMODE:", pRIGMODE}, 4780 {"<FILWID:", pFILWID}, 4781 {"<RIGHI:", pRIGHI}, 4782 {"<RIGLO:", pRIGLO}, 4783 {"<MAPIT:", pMAPIT}, 4784 {"<MAPIT>", pMAPIT}, 4785 {"<REPEAT>", pREPEAT}, 4786 {"<SKED:", pSKED}, 4787 {"<UNTIL:", pUNTIL}, 4788 {"<LOCAL>", pLOCAL}, 4789 {"<TXATTEN:", pTXATTEN}, 4790 {"<POP>", pPOP}, 4791 {"<PUSH", pPUSH}, 4792 {"<DIGI>", pDIGI}, 4793 {"<ALERT:", pALERT}, 4794 {"<AUDIO:", pAUDIO}, 4795 {"<BUFFERED>", pBUFFERED}, 4796 #ifdef __WIN32__ 4797 {"<TALK:", pTALK}, 4798 #endif 4799 {"<CSV:", pCSV}, 4800 {"<WX>", pWX}, 4801 {"<WX:", pWX2}, 4802 {"<IMAGE:", pTxQueIMAGE}, 4803 {"<AVATAR>", pTxQueAVATAR}, 4804 // Tx Delayed action 4805 {"<!WPM:", pTxQueWPM}, 4806 {"<!RISE:", pTxQueRISETIME}, 4807 {"<!PRE:", pTxQuePRE}, 4808 {"<!POST:", pTxQuePOST}, 4809 {"<!GOHOME>", pTxQueGOHOME}, 4810 {"<!GOFREQ:", pTxQueGOFREQ}, 4811 {"<!QSY:", pTxQueQSY}, 4812 {"<!IDLE:", pTxQueIDLE}, 4813 {"<!WAIT:", pTxQueWAIT}, 4814 {"<!SKED:", pTxQueSKED}, 4815 {"<!MODEM:", pTxQueMODEM}, 4816 {"<!RIGMODE:", pTxQueRIGMODE}, 4817 {"<!FILWID:", pTxQueFILWID}, 4818 {"<!RIGHI:", pTxQueRIGHI}, 4819 {"<!RIGLO:", pTxQueRIGLO}, 4820 {"<!TXATTEN:", pTxQueTXATTEN}, 4821 {"<!RIGCAT:", pTxQueRIGCAT}, 4822 {"<!FLRIG:", pTxQueFLRIG}, 4823 {"<!PUSH", pTxQuePUSH}, 4824 {"<!POP>", pTxQuePOP}, 4825 {"<!DIGI>", pTxDIGI}, 4826 {"<!FREQ>", pTxFREQ}, 4827 {"<!TUNE:", pTxQueTUNE}, 4828 4829 // Rx After action 4830 {"<@MODEM:", pRxQueMODEM}, 4831 {"<@RIGCAT:", pRxQueRIGCAT}, 4832 {"<@FLRIG:", pRxQueFLRIG}, 4833 {"<@GOFREQ:", pRxQueGOFREQ}, 4834 {"<@GOHOME>", pRxQueGOHOME}, 4835 {"<@RIGMODE:", pRxQueRIGMODE}, 4836 {"<@FILWID:", pRxQueFILWID}, 4837 {"<@RIGHI:", pRxQueRIGHI}, 4838 {"<@RIGLO:", pRxQueRIGLO}, 4839 {"<@TXRSID:", pRxQueTXRSID}, 4840 {"<@LOCK:", pRxQueLOCK}, 4841 {"<@WAIT:", pRxQueWAIT}, 4842 {"<@TUNE:", pRxQueTUNE}, 4843 {"<@PUSH", pRxQuePUSH}, 4844 {"<@POP>", pRxQuePOP}, 4845 4846 {"<RX>", pRX}, 4847 {"<TX>", pTX}, 4848 {"<TX/RX>", pTXRX}, 4849 4850 {0, 0} 4851 }; 4852 4853 int MACROTEXT::loadMacros(const std::string& filename) 4854 { 4855 std::string mLine; 4856 std::string mName; 4857 std::string mDef; 4858 int mNumber = 0; 4859 size_t crlf, idx; 4860 char szLine[4096]; 4861 bool convert = false; 4862 4863 ifstream mFile(filename.c_str()); 4864 4865 if (!mFile) { 4866 create_new_macros(); 4867 } else { 4868 4869 mFile.getline(szLine, 4095); 4870 mLine = szLine; 4871 if (mLine.find("//fldigi macro definition file") != 0) { 4872 mFile.close(); 4873 return -2; 4874 } 4875 if (mLine.find("extended") == std::string::npos) { 4876 convert = true; 4877 changed = true; 4878 } 4879 // clear all of the macros 4880 for (int i = 0; i < MAXMACROS; i++) { 4881 name[i] = ""; 4882 text[i] = ""; 4883 } 4884 while (!mFile.eof()) { 4885 mFile.getline(szLine,4095); 4886 mLine = szLine; 4887 if (!mLine.length()) 4888 continue; 4889 if (mLine.find("//") == 0) // skip over all comment lines 4890 continue; 4891 if (mLine.find("/$") == 0) { 4892 idx = mLine.find(" ", 3); 4893 if (idx != std::string::npos) { 4894 mNumber = atoi(&mLine[3]); 4895 if (mNumber < 0 || mNumber > (MAXMACROS - 1)) 4896 break; 4897 if (convert && mNumber > 9) mNumber += 2; 4898 name[mNumber] = mLine.substr(idx+1); 4899 } 4900 continue; 4901 } 4902 crlf = mLine.rfind("\\n"); 4903 if (crlf != std::string::npos) { 4904 mLine.erase(crlf); 4905 mLine.append("\n"); 4906 } 4907 text[mNumber] = text[mNumber] + mLine; 4908 } 4909 mFile.close(); 4910 } 4911 4912 return 0; 4913 } 4914 4915 void MACROTEXT::loadDefault() 4916 { 4917 int erc; 4918 std::string Filename = MacrosDir; 4919 Filename.append("macros.mdf"); 4920 LOG_INFO("macro file name: %s", progStatus.LastMacroFile.c_str()); 4921 if (progdefaults.UseLastMacro == true) { 4922 if (progStatus.LastMacroFile.find("/") != string::npos || 4923 progStatus.LastMacroFile.find("\\") != string::npos) 4924 Filename.assign(progStatus.LastMacroFile); 4925 else 4926 Filename.assign(MacrosDir).append(progStatus.LastMacroFile); 4927 } 4928 LOG_INFO("loading: %s", Filename.c_str()); 4929 progStatus.LastMacroFile = Filename; 4930 4931 if ((erc = loadMacros(Filename)) != 0) 4932 #ifndef __WOE32__ 4933 LOG_ERROR("Error #%d loading %s\n", erc, Filename.c_str()); 4934 #else 4935 ; 4936 #endif 4937 showMacroSet(); 4938 if (progdefaults.DisplayMacroFilename) { 4939 LOG_INFO("%s", progStatus.LastMacroFile.c_str()); 4940 string Macroset; 4941 Macroset.assign("\ 4942 \n================================================\n\ 4943 Read macros from: ").append(progStatus.LastMacroFile).append("\ 4944 \n================================================\n"); 4945 #ifdef __WOE32__ 4946 size_t p = string::npos; 4947 while ( (p = Macroset.find("/")) != string::npos) 4948 Macroset[p] = '\\'; 4949 #endif 4950 if (active_modem->get_mode() == MODE_IFKP) 4951 ifkp_rx_text->addstr(Macroset); 4952 else if (active_modem->get_mode() == MODE_FSQ) 4953 fsq_rx_text->addstr(Macroset); 4954 else 4955 ReceiveText->addstr(Macroset); 4956 } 4957 } 4958 4959 void MACROTEXT::openMacroFile() 4960 { 4961 std::string deffilename = MacrosDir; 4962 4963 if (progStatus.LastMacroFile.find("/") != string::npos || 4964 progStatus.LastMacroFile.find("\\") != string::npos) 4965 deffilename.assign(progStatus.LastMacroFile); 4966 else 4967 deffilename.append(progStatus.LastMacroFile); 4968 4969 const char *p = FSEL::select( 4970 _("Open macro file"), 4971 _("Fldigi macro definition file\t*.{mdf}"), 4972 deffilename.c_str()); 4973 if (p && *p) { 4974 loadMacros(p); 4975 progStatus.LastMacroFile = p; 4976 showMacroSet(); 4977 if (progdefaults.DisplayMacroFilename) { 4978 string Macroset; 4979 Macroset.assign("\nLoaded macros: ").append(progStatus.LastMacroFile).append("\n"); 4980 if (active_modem->get_mode() == MODE_IFKP) 4981 ifkp_rx_text->addstr(Macroset); 4982 if (active_modem->get_mode() == MODE_FSQ) 4983 fsq_rx_text->addstr(Macroset); 4984 else 4985 ReceiveText->addstr(Macroset); 4986 } 4987 } 4988 } 4989 4990 void MACROTEXT::writeMacroFile() 4991 { 4992 std::string deffilename = MacrosDir; 4993 if (progStatus.LastMacroFile.find("/") != string::npos || 4994 progStatus.LastMacroFile.find("\\") != string::npos) 4995 deffilename.assign(progStatus.LastMacroFile); 4996 else 4997 deffilename.append(progStatus.LastMacroFile); 4998 4999 saveMacros(deffilename.c_str()); 5000 } 5001 5002 void MACROTEXT::saveMacroFile() 5003 { 5004 std::string deffilename = MacrosDir; 5005 5006 if (progStatus.LastMacroFile.find("/") != string::npos || 5007 progStatus.LastMacroFile.find("\\") != string::npos) 5008 deffilename.assign(progStatus.LastMacroFile); 5009 else 5010 deffilename.append(progStatus.LastMacroFile); 5011 5012 const char *p = FSEL::saveas( 5013 _("Save macro file"), 5014 _("Fldigi macro definition file\t*.{mdf}"), 5015 deffilename.c_str()); 5016 if (!p) return; 5017 if (!*p) return; 5018 5019 string sp = p; 5020 if (sp.empty()) return; 5021 if (sp.rfind(".mdf") == string::npos) sp.append(".mdf"); 5022 saveMacros(sp.c_str()); 5023 progStatus.LastMacroFile = sp; 5024 5025 } 5026 5027 void MACROTEXT::savecurrentMACROS(std::string &s, size_t &i, size_t endbracket) 5028 { 5029 writeMacroFile(); 5030 substitute(s, i, endbracket, ""); 5031 } 5032 5033 void MACROTEXT::loadnewMACROS(std::string &s, size_t &i, size_t endbracket) 5034 { 5035 std::string fname = s.substr(i+8, endbracket - i - 8); 5036 if (fname.length() > 0) { 5037 loadMacros(fname); 5038 progStatus.LastMacroFile = fl_filename_name(fname.c_str()); 5039 } 5040 substitute(s, i, endbracket, ""); 5041 showMacroSet(); 5042 } 5043 5044 std::string MACROTEXT::expandMacro(std::string &s, bool recurse = false) 5045 { 5046 size_t idx = 0; 5047 expand = true; 5048 buffered = false; 5049 if (!recurse || rx_only) { 5050 TransmitON = false; 5051 ToggleTXRX = false; 5052 } 5053 expanded = s; 5054 const MTAGS *pMtags; 5055 5056 xbeg = xend = -1; 5057 save_xchg = false; 5058 progStatus.repeatMacro = -1; 5059 text2repeat.clear(); 5060 idleTime = 0; 5061 waitTime = 0; 5062 // tuneTime = 0; 5063 5064 while ((idx = expanded.find('<', idx)) != std::string::npos) { 5065 size_t endbracket = expanded.find('>',idx); 5066 if (ufind(expanded, "<SAVE", idx) == idx) { 5067 savecurrentMACROS(expanded, idx, endbracket); 5068 idx++; 5069 continue; 5070 } 5071 if (ufind(expanded, "<MACROS:",idx) == idx) { 5072 loadnewMACROS(expanded, idx, endbracket); 5073 idx++; 5074 continue; 5075 } 5076 // we must handle this specially 5077 if (ufind(expanded, "<CONT>", idx) == idx) 5078 pCONT(expanded, idx, endbracket); 5079 if (!expand) { 5080 idx++; 5081 continue; 5082 } 5083 5084 pMtags = mtags; 5085 while (pMtags->mTAG != 0) { 5086 if (ufind(expanded, pMtags->mTAG, idx) == idx) { 5087 pMtags->fp(expanded,idx, endbracket); 5088 break; 5089 } 5090 pMtags++; 5091 } 5092 if (pMtags->mTAG == 0) 5093 idx++; 5094 } 5095 if (GET) { 5096 size_t pos1 = ufind(expanded, "$NAME"); 5097 size_t pos2 = ufind(expanded, "$QTH"); 5098 size_t pos3 = ufind(expanded, "$LOC"); 5099 if (pos1 != std::string::npos && pos2 != std::string::npos) { 5100 pos1 += 5; 5101 inpName->value(expanded.substr(pos1, pos2 - pos1).c_str()); 5102 } 5103 if (pos2 != std::string::npos) { 5104 pos2 += 4; 5105 inpQth->value(expanded.substr(pos2, pos3 - pos2).c_str()); 5106 } 5107 if (pos3 != std::string::npos) { 5108 pos3 += 4; 5109 inpLoc->value(expanded.substr(pos3).c_str()); 5110 } 5111 GET = false; 5112 return ""; 5113 } 5114 5115 if (xbeg != std::string::npos && xend != std::string::npos && xend > xbeg) { 5116 qso_exchange = expanded.substr(xbeg, xend - xbeg); 5117 } else if (save_xchg) { 5118 qso_exchange = expanded; 5119 save_xchg = false; 5120 } 5121 5122 // force "^r" to be last tag in the expanded std::string 5123 if ((idx = expanded.find("^r")) != std::string::npos) { 5124 expanded.erase(idx, 2); 5125 expanded.append("^r"); 5126 } 5127 5128 if (!TransmitON && !Rx_cmds.empty()) 5129 Fl::add_timeout(0, rx_que_continue); 5130 5131 return expanded; 5132 } 5133 5134 void idleTimer(void *) 5135 { 5136 macro_idle_on = false; 5137 } 5138 5139 static void finishWait(void *) 5140 { 5141 if (rx_only) { 5142 TransmitON = false; 5143 return; 5144 } 5145 if ( TransmitON ) { 5146 active_modem->set_stopflag(false); 5147 if (macro_idle_on && idleTime > 0) 5148 Fl::add_timeout(idleTime, idleTimer); 5149 start_tx(); 5150 TransmitON = false; 5151 } 5152 } 5153 5154 static void set_button(Fl_Button* button, bool value) 5155 { 5156 button->value(value); 5157 button->do_callback(); 5158 } 5159 5160 void MACROTEXT::timed_execute() 5161 { 5162 queue_reset(); 5163 if (active_modem->get_mode() == MODE_IFKP) 5164 ifkp_tx_text->clear(); 5165 else if (active_modem->get_mode() == MODE_FSQ) 5166 fsq_tx_text->clear(); 5167 else 5168 TransmitText->clear(); 5169 if (!rx_only) { 5170 text2send = expandMacro(exec_string); 5171 progStatus.skip_sked_macro = true; 5172 if (active_modem->get_mode() == MODE_IFKP) 5173 ifkp_tx_text->add_text(text2send); 5174 else if (active_modem->get_mode() == MODE_FSQ) 5175 fsq_tx_text->add_text( text2send ); 5176 else 5177 add_text(text2send); 5178 exec_string.clear(); 5179 active_modem->set_stopflag(false); 5180 start_tx(); 5181 } 5182 } 5183 5184 void MACROTEXT::execute(int n) 5185 { 5186 guard_lock exec(&exec_mutex); 5187 5188 std::string dd, dt; 5189 dd = (local_timed_exec ? ldate() : zdate()); 5190 dt = (local_timed_exec ? ltime() : ldate()); 5191 5192 if (run_until && dd >= until_date && dt >= until_time) { 5193 stopMacroTimer(); 5194 queue_reset(); 5195 return; 5196 } 5197 5198 mNbr = n; 5199 text2send = expandMacro(text[n]); 5200 5201 if (timed_exec && !progStatus.skip_sked_macro) { 5202 progStatus.repeatMacro = -1; 5203 exec_string = text[n]; 5204 startTimedExecute(name[n]); 5205 timed_exec = false; 5206 return; 5207 } 5208 5209 trx_mode mode = active_modem->get_mode(); 5210 5211 if (!rx_only) { 5212 if (progStatus.repeatMacro == -1) { 5213 if (mode == MODE_IFKP) 5214 ifkp_tx_text->add_text( text2send ); 5215 else if (mode == MODE_FSQ) 5216 fsq_tx_text->add_text( text2send ); 5217 else 5218 add_text( text2send ); 5219 } else { 5220 size_t p = std::string::npos; 5221 text2send = text[n]; 5222 while ((p = text2send.find('<')) != std::string::npos) 5223 text2send[p] = '['; 5224 while ((p = text2send.find('>')) != std::string::npos) 5225 text2send[p] = ']'; 5226 if (mode == MODE_IFKP) 5227 ifkp_tx_text->add_text( text2send ); 5228 else if (mode == MODE_FSQ) 5229 fsq_tx_text->add_text( text2send ); 5230 else 5231 add_text( text2send ); 5232 } 5233 } 5234 bool keep_tx = !text2send.empty(); 5235 text2send.clear(); 5236 5237 if (tune_on) { 5238 if (tune_timeout > 0) { 5239 Fl::add_timeout(tune_timeout, end_tune, (void *)keep_tx); 5240 tune_timeout = 0; 5241 } 5242 return; 5243 } 5244 5245 if (ToggleTXRX) { 5246 text2send.clear(); 5247 if (!wf->xmtrcv->value()) { 5248 REQ(set_button, wf->xmtrcv, true); 5249 if (macro_idle_on && idleTime > 0) 5250 Fl::add_timeout(idleTime, idleTimer); 5251 } else 5252 REQ(set_button, wf->xmtrcv, false); 5253 return; 5254 } 5255 if (useWait && waitTime > 0) { 5256 Fl::add_timeout(waitTime, finishWait); 5257 useWait = false; 5258 return; 5259 } 5260 if ( TransmitON ) { 5261 if (macro_idle_on && idleTime > 0) 5262 Fl::add_timeout(idleTime, idleTimer); 5263 active_modem->set_stopflag(false); 5264 start_tx(); 5265 TransmitON = false; 5266 } 5267 } 5268 5269 void MACROTEXT::repeat(int n) 5270 { 5271 expandMacro(text[n]); 5272 progStatus.skip_sked_macro = true; 5273 LOG_WARN("%s",text2repeat.c_str()); 5274 macro_idle_on = false; 5275 if (idleTime) progStatus.repeatIdleTime = idleTime; 5276 } 5277 5278 MACROTEXT::MACROTEXT() 5279 { 5280 changed = false; 5281 char szname[5]; 5282 for (int i = 0; i < MAXMACROS; i++) { 5283 snprintf(szname, sizeof(szname), "F-%d", i+1); 5284 name[i] = szname;//""; 5285 text[i] = ""; 5286 } 5287 } 5288 5289 5290 static std::string mtext = 5291 "//fldigi macro definition file extended\n\ 5292 // This file defines the macro structure(s) for the digital modem program, fldigi\n\ 5293 // It also serves as a basis for any macros that are written by the user\n\ 5294 //\n\ 5295 // The top line of this file should always be the first line in every macro \n\ 5296 // definition file (.mdf) for the fldigi program to recognize it as such.\n\ 5297 //\n\ 5298 "; 5299 5300 void MACROTEXT::saveMacros(const std::string& fname) { 5301 5302 std::string work; 5303 std::string output; 5304 char temp[200]; 5305 output.assign(mtext); 5306 for (int i = 0; i < MAXMACROS; i++) { 5307 snprintf(temp, sizeof(temp), "\n//\n// Macro # %d\n/$ %d %s\n", 5308 i+1, i, macros.name[i].c_str()); 5309 output.append(temp); 5310 work = macros.text[i]; 5311 size_t pos; 5312 pos = work.find('\n'); 5313 while (pos != std::string::npos) { 5314 work.insert(pos, "\\n"); 5315 pos = work.find('\n', pos + 3); 5316 } 5317 output.append(work).append("\n"); 5318 } 5319 UTF8_writefile(fname.c_str(), output); 5320 5321 changed = false; 5322 } 5323 5324