1 // ----------------------------------------------------------------------------
2 // rigxml.cxx - parse a rig control xml file
3 //
4 // Copyright (C) 2007-2009
5 // Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22
23 #include <config.h>
24
25 #include <fstream>
26 #include <string>
27 #include <list>
28
29 #include <FL/filename.H>
30
31 #include "gettext.h"
32 #include "rigio.h"
33 #include "rigxml.h"
34 #include "rigsupport.h"
35 #ifdef RIGCATTEST
36 #include "rigCAT.h"
37 #else
38 #include "main.h"
39 #endif
40 #include "debug.h"
41
42 #include "configuration.h"
43 #include "fileselect.h"
44 #include "confdialog.h"
45
46 #include "icons.h"
47 #include "fl_digi.h"
48
49 using namespace std;
50
51 //#define DEBUGXML 1
52
53 void parseRIGDEF(size_t &);
54 void parseRIG(size_t &);
55 void parseCOMMAND(size_t &);
56 void parseREPLY(size_t &);
57 void parseMODES(size_t &);
58 void parseBANDWIDTHS(size_t &);
59 void parseBWCMD(size_t &);
60 void parseBWREPLY(size_t &);
61 void parseMODECMD(size_t &);
62 void parseMODEREPLY(size_t &);
63 void parseTITLE(size_t &);
64 void parseLSBMODES(size_t &);
65 void parseDISCARD(size_t &);
66 void parseDEBUG(size_t &);
67 void parseNOSERIAL(size_t &);
68 void parseASCII(size_t &);
69
70 void parseWRITE_DELAY(size_t &);
71 void parseINIT_DELAY(size_t &);
72 void parseWAIT_FOR_DEVICE(size_t &);
73 void parsePOST_WRITE_DELAY(size_t &);
74 void parseRETRIES(size_t &);
75 void parseTIMEOUT(size_t &);
76 void parseBAUDRATE(size_t &);
77 void parseSTOPBITS(size_t &);
78 void parseRTSCTS(size_t &);
79 void parseCMDPTT(size_t &);
80 void parseRTSPLUS(size_t &);
81 void parseDTRPLUS(size_t &);
82 void parseRTSPTT(size_t &);
83 void parseDTRPTT(size_t &);
84 void parseRESTORE_TIO(size_t &);
85 void parseECHO(size_t &);
86 void parseVSP(size_t &);
87 void parseLOGSTR(size_t &);
88 void parsePOLLINT(size_t &);
89 void parseSMETER(size_t &);
90 void parsePMETER(size_t &);
91 void parseNOTCH(size_t &);
92 void parsePWRLEVEL(size_t &);
93
94 void parseIOSsymbol(size_t &);
95 void parseIOSsize(size_t &);
96 void parseIOSbytes(size_t &);
97 void parseIOSbyte(size_t &);
98 void parseIOSdata(size_t &);
99 void parseIOSinfo(size_t &);
100 void parseIOSok(size_t &);
101 void parseIOSbad(size_t &);
102 void parseIOSstring(size_t &);
103 void parseIOSint(size_t &);
104 void parseIOSfill(size_t &);
105
106 void parseDTYPE(size_t &);
107 void parseDSIZE(size_t &);
108 void parseDMAX(size_t &);
109 void parseDMIN(size_t &);
110 void parseDRESOL(size_t &);
111 void parseDREV(size_t &);
112 void parseDMAKS(size_t &);
113 void parseDSHIFT(size_t &);
114
115 void print(size_t &);
116
117 list<XMLIOS> commands;
118 list<XMLIOS> reply;
119 list<MODE> lmodes;
120 list<BW> lbws;
121 list<BW> lbwCMD;
122 list<BW> lbwREPLY;
123 list<MODE> lmodeCMD;
124 list<MODE> lmodeREPLY;
125 list<string> LSBmodes;
126
127 XMLRIG xmlrig;
128
129 XMLIOS iosTemp;
130
131 string strXML;
132
133 TAGS rigdeftags[] = {
134 {"<RIGDEF", parseRIGDEF},
135 {"<RIG", parseRIG},
136 {"<COMMAND", parseCOMMAND},
137 {"<REPLY", parseREPLY},
138 {"<BANDWIDTHS", parseBANDWIDTHS},
139 {"<BW-CMD", parseBWCMD},
140 {"<BW-REPLY", parseBWREPLY},
141 {"<MODES", parseMODES},
142 {"<MODE-CMD", parseMODECMD},
143 {"<MODE-REPLY", parseMODEREPLY},
144 {"<TITLE", parseTITLE},
145 {"<LSBMODES", parseLSBMODES},
146 {"<PROGRAMMER", parseDISCARD},
147 {"<STATUS", parseDISCARD},
148 {"<WRITE_DELAY", parseWRITE_DELAY},
149 {"<INIT_DELAY", parseINIT_DELAY},
150 {"<POST_WRITE_DELAY", parsePOST_WRITE_DELAY},
151 {"<RETRIES", parseRETRIES},
152 {"<TIMEOUT", parseTIMEOUT},
153 {"<BAUDRATE", parseBAUDRATE},
154 {"<RTSCTS", parseRTSCTS},
155 {"<RTSPLUS", parseRTSPLUS},
156 {"<DTRPLUS", parseDTRPLUS},
157 {"<RTSPTT", parseRTSPTT},
158 {"<DTRPTT", parseDTRPTT},
159 {"<WAIT_FOR_DEVICE", parseWAIT_FOR_DEVICE},
160 {"<RESTORE_TIO", parseRESTORE_TIO},
161 {"<ECHO", parseECHO},
162 {"<CMDPTT", parseCMDPTT},
163 {"<STOPBITS", parseSTOPBITS},
164 {"<VSP", parseVSP},
165 {"<LOGSTR", parseLOGSTR},
166 {"<POLLINT", parsePOLLINT},
167 {"<SMETER", parseSMETER},
168 {"<PMETER", parsePMETER},
169 {"<NOTCH", parseNOTCH},
170 {"<PWRLEVEL", parsePWRLEVEL},
171 {"<DEBUG", parseDEBUG},
172 {"<NOSERIAL", parseNOSERIAL},
173 {"<ASCII", parseASCII},
174 {0, 0}
175 };
176
177 TAGS commandtags[] = {
178 {"<SIZE", parseIOSsize},
179 {"<SYMBOL", parseIOSsymbol},
180 {"<BYTES", parseIOSbytes},
181 {"<BYTE", parseIOSbyte},
182 {"<DATA", parseIOSdata},
183 {"<STRING", parseIOSstring},
184 {"<INT", parseIOSint},
185 {"<INFO", parseIOSinfo},
186 {"<OK", parseIOSok},
187 {"<BAD", parseIOSbad},
188 {0,0}
189 };
190
191 TAGS replytags[] = {
192 {"<SIZE", parseIOSsize},
193 {"<SYMBOL", parseIOSsymbol},
194 {"<BYTES", parseIOSbytes},
195 {"<BYTE", parseIOSbyte},
196 {"<DATA", parseIOSdata},
197 {"<STRING", parseIOSstring},
198 {"<INT", parseIOSint},
199 {"<FILL", parseIOSfill},
200 {0,0}
201 };
202
203 TAGS datatags[] = {
204 {"<DTYPE", parseDTYPE},
205 {"<SIZE", parseDSIZE},
206 {"<MAX", parseDMAX},
207 {"<MIN", parseDMIN},
208 {"<RESOL", parseDRESOL},
209 {"<REV", parseDREV},
210 {"<MASK", parseDMAKS},
211 {"<SHIFT", parseDSHIFT},
212 {0,0}
213 }
214 ;
215
216 //=====================================================================
217
print(size_t & p0,int indent)218 void print(size_t &p0, int indent)
219 {
220 #ifdef DEBUGXML
221 std::string istr(indent, '\t');
222 size_t tend = strXML.find(">", p0);
223 LOG_INFO("%s%s", istr.c_str(), strXML.substr(p0, tend - p0 + 1).c_str());
224 #endif
225 }
226
tagEnd(size_t p0)227 size_t tagEnd(size_t p0)
228 {
229 size_t p1, p2, p3;
230 p1 = p0;
231 string strtag = "</";
232 p2 = strXML.find(">", p0);
233 p3 = strXML.find(" ", p0);
234 if (p2 == string::npos) {
235 return p2;
236 }
237 if (p3 < p2)
238 p2 = p3;
239 strtag.append(strXML.substr(p1 + 1, p2 - p1 - 1));
240 strtag.append(">");
241 p3 = strXML.find(strtag, p1);
242 return p3;
243 }
244
nextTag(size_t p0)245 size_t nextTag(size_t p0)
246 {
247 p0 = strXML.find("<", p0+1);
248 return p0;
249 }
250
getElement(size_t p0)251 string getElement(size_t p0)
252 {
253 size_t p1 = strXML.find(">",p0),
254 p2 = nextTag(p1+1);
255 if (p1 == string::npos || p2 == string::npos)
256 return "";
257 p1++; p2--;
258 while (p1 < p2 && strXML[p1] == ' ') p1++; // skip leading spaces
259 while (p1 < p2 && strXML[p2] == ' ') p2--; // skip trailing spaces
260 return strXML.substr(p1, p2 - p1 + 1);
261 }
262
getInt(size_t p0)263 int getInt(size_t p0)
264 {
265 string stemp = getElement(p0);
266 if (stemp.length() == 0)
267 return 0;
268 return atoi(stemp.c_str());
269 }
270
getFloat(size_t p0)271 float getFloat(size_t p0)
272 {
273 string stemp = getElement(p0);
274 if (stemp.length() == 0)
275 return 0;
276 return atof(stemp.c_str());
277 }
278
getBool(size_t p0)279 bool getBool( size_t p0)
280 {
281 string stemp = getElement(p0);
282 if (stemp.length() == 0)
283 return false;
284 if (strcasecmp(stemp.c_str(), "true") == 0)
285 return true;
286 if (stemp == "1") return true;
287 return false;
288 }
289
getByte(size_t p0)290 char getByte(size_t p0)
291 {
292 unsigned int val;
293 if (sscanf( getElement(p0).c_str(), "%x", &val ) != 1)
294 return 0;
295 return (val & 0xFF);
296 }
297
getBytes(size_t p0)298 string getBytes(size_t p0)
299 {
300 unsigned int val;
301 size_t space;
302 string stemp = getElement(p0);
303 string s;
304 while ( stemp.length() ) {
305 if (sscanf( stemp.c_str(), "%x", &val) != 1) {
306 s = "";
307 return s;
308 }
309 s += (char)(val & 0xFF);
310 space = stemp.find(" ");
311 if (space == string::npos) break;
312 stemp.erase(0, space + 1);
313 }
314 return s;
315 }
316
isInt(size_t p0,int & i)317 bool isInt(size_t p0, int &i)
318 {
319 // p0 = nextTag(p0);
320 if (strXML.find("<INT", p0) != p0)
321 return false;
322 i = getInt(p0);
323 return true;
324 }
325
isByte(size_t p0,char & ch)326 bool isByte(size_t p0, char &ch)
327 {
328 // p0 = nextTag(p0);
329 if (strXML.find("<BYTE", p0) != p0)
330 return false;
331 ch = getByte(p0);
332 return true;
333 }
334
isBytes(size_t p0,string & s)335 bool isBytes( size_t p0, string &s )
336 {
337 // p0 = nextTag(p0);
338 if (strXML.find ("<BYTES", p0) != p0)
339 return false;
340 s = getBytes(p0);
341 return true;
342 }
343
isString(size_t p0,string & s)344 bool isString( size_t p0, string &s )
345 {
346 // p0 = nextTag(p0);
347 if (strXML.find("<STRING", p0) != p0)
348 return false;
349 s = getElement(p0);
350 return true;
351 }
352
isSymbol(size_t p0,string & s)353 bool isSymbol( size_t p0, string &s)
354 {
355 if (strXML.find("<SYMBOL", p0) != p0)
356 return false;
357 s = getElement(p0);
358 return true;
359 }
360
tagIs(size_t & p0,string tag)361 bool tagIs(size_t &p0, string tag)
362 {
363 return (strXML.find(tag,p0) == p0);
364 }
365
366 //---------------------------------------------------------------------
367 // Parse modesTO definitions
368 //---------------------------------------------------------------------
369
parseMODEdefs(size_t & p0,list<MODE> & lmd)370 void parseMODEdefs(size_t &p0, list<MODE> &lmd)
371 {
372 size_t pend = tagEnd(p0);
373 size_t elend;
374 char ch;
375 int n;
376 string stemp;
377 string strELEMENT;
378 if (pend == string::npos) {
379 p0++;
380 return;
381 }
382 print(p0,0);
383 p0 = nextTag(p0);
384 while (p0 != string::npos && p0 < pend && tagIs(p0, "<ELEMENT")) {
385 elend = tagEnd(p0);
386 p0 = nextTag(p0);
387 if (isSymbol(p0, strELEMENT)) {
388 p0 = tagEnd(p0);
389 p0 = nextTag(p0);
390 while (p0 != string::npos && p0 < elend) {
391 print(p0,1);
392 if ( isBytes(p0, stemp) ) {
393 lmd.push_back(MODE(strELEMENT,stemp));
394 }
395 else if ( isByte(p0, ch) ) {
396 stemp = ch;
397 lmd.push_back(MODE(strELEMENT,stemp));
398 }
399 else if ( isInt(p0, n) ) {
400 stemp = (char)(n & 0xFF);
401 lmd.push_back(MODE(strELEMENT, stemp));
402 }
403 else if ( isString(p0, stemp) ) {
404 lmd.push_back(MODE(strELEMENT,stemp));
405 }
406 p0 = tagEnd(p0);
407 p0 = nextTag(p0);
408 }
409 }
410 p0 = nextTag(p0);
411 }
412 p0 = pend;
413 }
414
parseMODES(size_t & p0)415 void parseMODES(size_t &p0)
416 {
417 parseMODEdefs(p0, lmodes);
418 }
419
420
parseMODECMD(size_t & p0)421 void parseMODECMD(size_t &p0)
422 {
423 parseMODEdefs(p0, lmodeCMD);
424 }
425
parseMODEREPLY(size_t & p0)426 void parseMODEREPLY(size_t &p0)
427 {
428 parseMODEdefs(p0, lmodeREPLY);
429 }
430
parseLSBMODES(size_t & p0)431 void parseLSBMODES(size_t &p0)
432 {
433 size_t pend = tagEnd(p0);
434 string sMode;
435 print(p0,0);
436 p0 = nextTag(p0);
437 while (p0 < pend && isString(p0, sMode)) {
438 LSBmodes.push_back(sMode);
439 print (p0,1);
440 p0 = tagEnd(p0);
441 p0 = nextTag(p0);
442 }
443 p0 = pend;
444 }
445
446 //---------------------------------------------------------------------
447 // Parse Bandwidth definitions
448 //---------------------------------------------------------------------
449
parseBWdefs(size_t & p0,list<BW> & lbw)450 void parseBWdefs(size_t &p0, list<BW> &lbw)
451 {
452 size_t pend = tagEnd(p0);
453 size_t elend;
454 char ch;
455 int n;
456 string strELEMENT;
457 string stemp;
458 if (pend == string::npos) {
459 LOG_ERROR("Unmatched tag %s", strXML.substr(p0, 10).c_str());
460 p0++;
461 return;
462 }
463 print(p0,0);
464 size_t p1 = nextTag(p0);
465 while (p1 != string::npos && p1 < pend && tagIs(p1, "<ELEMENT")) {
466 elend = tagEnd(p1);
467 if (elend == string::npos || elend > pend) {
468 LOG_ERROR("Unmatched tag %s", "<ELEMENT");
469 p0 = pend;
470 return;
471 }
472 p1 = nextTag(p1);
473 if (isSymbol(p1, strELEMENT)) {
474 p1 = tagEnd(p1);
475 p1 = nextTag(p1);
476 while (p1 != string::npos && p1 < elend) {
477 print(p1,1);
478 if ( isBytes(p1, stemp) ) {
479 lbw.push_back(BW(strELEMENT,stemp));
480 p1 = tagEnd(p1);
481 }
482 else if ( isByte(p1, ch) ) {
483 stemp = ch;
484 lbw.push_back(BW(strELEMENT,stemp));
485 p1 = tagEnd(p1);
486 }
487 else if ( isInt(p1, n) ) {
488 stemp = (char)(n & 0xFF);
489 lbw.push_back(BW(strELEMENT, stemp));
490 p1 = tagEnd(p1);
491 }
492 else if ( isString(p1, stemp) ) {
493 lbw.push_back(BW(strELEMENT,stemp));
494 p1 = tagEnd(p1);
495 } else {
496 LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
497 parseDISCARD(p1);
498 }
499 p1 = nextTag(p1);
500 }
501 }
502 p1 = nextTag(p1);
503 }
504 p0 = pend;
505 }
506
parseBANDWIDTHS(size_t & p0)507 void parseBANDWIDTHS(size_t &p0)
508 {
509 parseBWdefs(p0, lbws);
510 }
511
parseBWCMD(size_t & p0)512 void parseBWCMD(size_t &p0)
513 {
514 parseBWdefs(p0, lbwCMD);
515 }
516
parseBWREPLY(size_t & p0)517 void parseBWREPLY(size_t &p0)
518 {
519 parseBWdefs(p0, lbwREPLY);
520 }
521
522 //---------------------------------------------------------------------
523 // Parse Title definition
524 //---------------------------------------------------------------------
525
parseTITLE(size_t & p0)526 void parseTITLE(size_t &p0)
527 {
528 size_t pend = tagEnd(p0);
529 xmlrig.rigTitle = getElement(p0);
530 p0 = pend;
531 }
532
533 //---------------------------------------------------------------------
534 // Parse Rig definition
535 //---------------------------------------------------------------------
536
parseRIG(size_t & p0)537 void parseRIG(size_t &p0)
538 {
539 size_t pend = tagEnd(p0);
540 p0 = pend;
541 }
542
543 //---------------------------------------------------------------------
544 // Parse DEBUG, use during xml file creation/testing
545 //---------------------------------------------------------------------
546
parseDEBUG(size_t & p0)547 void parseDEBUG(size_t &p0){
548 bool val = getBool(p0);
549 xmlrig.debug = val;
550 size_t pend = tagEnd(p0);
551 p0 = pend;
552 }
553
554 //---------------------------------------------------------------------
555 // Parse NOSERIAL, use during xml file creation/testing
556 // suppresses serial port i/o
557 //---------------------------------------------------------------------
558
parseNOSERIAL(size_t & p0)559 void parseNOSERIAL(size_t &p0){
560 bool val = getBool(p0);
561 xmlrig.noserial = val;
562 size_t pend = tagEnd(p0);
563 p0 = pend;
564 }
565
566 //---------------------------------------------------------------------
567 // Parse ASCII, use during xml file creation/testing
568 // prints events as ASCII string vice HEX sequence
569 //---------------------------------------------------------------------
570
parseASCII(size_t & p0)571 void parseASCII(size_t &p0){
572 bool val = getBool(p0);
573 xmlrig.ascii = val;
574 size_t pend = tagEnd(p0);
575 p0 = pend;
576 }
577
578
579 //---------------------------------------------------------------------
580 // Parse Baudrate, write_delay, post_write_delay, timeout, retries
581 // RTSCTS handshake
582 //---------------------------------------------------------------------
583
parseBAUDRATE(size_t & p0)584 void parseBAUDRATE(size_t &p0)
585 {
586 string sVal = getElement(p0);
587 xmlrig.baud = progdefaults.nBaudRate(sVal.c_str());
588 size_t pend = tagEnd(p0);
589 p0 = pend;
590 }
591
parseSTOPBITS(size_t & p0)592 void parseSTOPBITS(size_t &p0){
593 int val = getInt(p0);
594 if (val < 0 || val > 2) val = 2;
595 xmlrig.stopbits = val;
596 size_t pend = tagEnd(p0);
597 p0 = pend;
598 }
599
parseWRITE_DELAY(size_t & p0)600 void parseWRITE_DELAY(size_t &p0){
601 int val = getInt(p0);
602 xmlrig.write_delay = val;
603 size_t pend = tagEnd(p0);
604 p0 = pend;
605 }
606
parseINIT_DELAY(size_t & p0)607 void parseINIT_DELAY(size_t &p0){
608 int val = getInt(p0);
609 xmlrig.init_delay = val;
610 size_t pend = tagEnd(p0);
611 p0 = pend;
612 }
613
parseWAIT_FOR_DEVICE(size_t & p0)614 void parseWAIT_FOR_DEVICE(size_t &p0){
615 int val = getInt(p0);
616 xmlrig.wait_for_device = val;
617 size_t pend = tagEnd(p0);
618 p0 = pend;
619 }
620
parsePOST_WRITE_DELAY(size_t & p0)621 void parsePOST_WRITE_DELAY(size_t &p0){
622 int val = getInt(p0);
623 xmlrig.post_write_delay = val;
624 size_t pend = tagEnd(p0);
625 p0 = pend;
626 }
627
parseRETRIES(size_t & p0)628 void parseRETRIES(size_t &p0){
629 int val = getInt(p0);
630 xmlrig.retries = val;
631 size_t pend = tagEnd(p0);
632 p0 = pend;
633 }
634
parseTIMEOUT(size_t & p0)635 void parseTIMEOUT(size_t &p0){
636 int val = getInt(p0);
637 xmlrig.timeout = val;
638 size_t pend = tagEnd(p0);
639 p0 = pend;
640 }
641
parseRTSCTS(size_t & p0)642 void parseRTSCTS(size_t &p0){
643 bool val = getBool(p0);
644 xmlrig.rtscts = val;
645 size_t pend = tagEnd(p0);
646 p0 = pend;
647 }
648
parseRTSPLUS(size_t & p0)649 void parseRTSPLUS(size_t &p0)
650 {
651 bool val = getBool(p0);
652 xmlrig.rts = val;
653 size_t pend = tagEnd(p0);
654 p0 = pend;
655 }
656
parseDTRPLUS(size_t & p0)657 void parseDTRPLUS(size_t &p0)
658 {
659 bool val = getBool(p0);
660 xmlrig.dtr = val;
661 size_t pend = tagEnd(p0);
662 p0 = pend;
663 }
664
parseRTSPTT(size_t & p0)665 void parseRTSPTT(size_t &p0)
666 {
667 bool val = getBool(p0);
668 xmlrig.rtsptt = val;
669 size_t pend = tagEnd(p0);
670 p0 = pend;
671 }
672
parseDTRPTT(size_t & p0)673 void parseDTRPTT(size_t &p0)
674 {
675 bool val = getBool(p0);
676 xmlrig.dtrptt = val;
677 size_t pend = tagEnd(p0);
678 p0 = pend;
679 }
680
parseRESTORE_TIO(size_t & p0)681 void parseRESTORE_TIO(size_t &p0)
682 {
683 bool val = getBool(p0);
684 xmlrig.restore_tio = val;
685 size_t pend = tagEnd(p0);
686 p0 = pend;
687 }
688
parseCMDPTT(size_t & p0)689 void parseCMDPTT(size_t &p0) {
690 bool val = getBool(p0);
691 xmlrig.cmdptt = val;
692 size_t pend = tagEnd(p0);
693 p0 = pend;
694 }
695
parseECHO(size_t & p0)696 void parseECHO(size_t &p0) {
697 bool val = getBool(p0);
698 xmlrig.echo = val;
699 size_t pend = tagEnd(p0);
700 p0 = pend;
701 }
702
parseVSP(size_t & p0)703 void parseVSP(size_t &p0)
704 {
705 bool val = getBool(p0);
706 xmlrig.vsp = val;
707 size_t pend = tagEnd(p0);
708 p0 = pend;
709 }
710
parseLOGSTR(size_t & p0)711 void parseLOGSTR(size_t &p0) {
712 bool val = getBool(p0);
713 xmlrig.logstr = val;
714 size_t pend = tagEnd(p0);
715 p0 = pend;
716 }
717
parsePOLLINT(size_t & p0)718 void parsePOLLINT(size_t &p0) {
719 int val = getInt(p0);
720 if (val < 100) val = 1000;
721 if (val > 20000) val = 20000;
722 xmlrig.pollinterval = val;
723 size_t pend = tagEnd(p0);
724 p0 = pend;
725 }
726
parseSMETER(size_t & p0)727 void parseSMETER(size_t &p0) {
728 string strmeter = getElement(p0);
729 size_t pend = tagEnd(p0);
730 p0 = pend;
731 xmlrig.smeter.clear();
732 int val, sm;
733 size_t p = strmeter.find(",");
734 while ( !strmeter.empty() && (p != string::npos) ) {
735 val = atoi(&strmeter[0]);
736 sm = atoi(&strmeter[p+1]);
737 xmlrig.smeter.push_back(PAIR(val,sm));
738 p = strmeter.find(";");
739 if (p == string::npos) strmeter.clear();
740 else {
741 strmeter.erase(0, p+1);
742 p = strmeter.find(",");
743 }
744 }
745 xmlrig.use_smeter = true;
746 }
747
parsePMETER(size_t & p0)748 void parsePMETER(size_t &p0) {
749 string strmeter = getElement(p0);
750 size_t pend = tagEnd(p0);
751 p0 = pend;
752 xmlrig.pmeter.clear();
753 int val, sm;
754 size_t p = strmeter.find(",");
755 while ( !strmeter.empty() && (p != string::npos) ) {
756 val = atoi(&strmeter[0]);
757 sm = atoi(&strmeter[p+1]);
758 xmlrig.pmeter.push_back(PAIR(val,sm));
759 p = strmeter.find(";");
760 if (p == string::npos) strmeter.clear();
761 else {
762 strmeter.erase(0, p+1);
763 p = strmeter.find(",");
764 }
765 }
766 xmlrig.use_pwrmeter = true;
767 }
768
parseNOTCH(size_t & p0)769 void parseNOTCH(size_t &p0) {
770 string strnotch = getElement(p0);
771 size_t pend = tagEnd(p0);
772 p0 = pend;
773 xmlrig.notch.clear();
774 int val, ntch;
775 size_t p = strnotch.find(",");
776 while ( !strnotch.empty() && (p != string::npos) ) {
777 val = atoi(&strnotch[0]);
778 ntch = atoi(&strnotch[p+1]);
779 xmlrig.notch.push_back(PAIR(val,ntch));
780 p = strnotch.find(";");
781 if (p == string::npos) strnotch.clear();
782 else {
783 strnotch.erase(0, p+1);
784 p = strnotch.find(",");
785 }
786 }
787 xmlrig.use_notch = true;
788 }
789
parsePWRLEVEL(size_t & p0)790 void parsePWRLEVEL(size_t &p0) {
791 string strpwrlevel = getElement(p0);
792 size_t pend = tagEnd(p0);
793 p0 = pend;
794 xmlrig.pwrlevel.clear();
795 int val, pwr;
796 float min = 500, max = 0;
797 size_t p = strpwrlevel.find(",");
798 while ( !strpwrlevel.empty() && (p != string::npos) ) {
799 val = atoi(&strpwrlevel[0]);
800 pwr = atoi(&strpwrlevel[p+1]);
801 if (pwr < min) min = pwr;
802 if (pwr > max) max = pwr;
803 xmlrig.pwrlevel.push_back(PAIR(val,pwr));
804 p = strpwrlevel.find(";");
805 if (p == string::npos) strpwrlevel.clear();
806 else {
807 strpwrlevel.erase(0, p+1);
808 p = strpwrlevel.find(",");
809 }
810 }
811 pwr_level->range(min, max);
812 xmlrig.use_pwrlevel = true;
813 }
814
815 //---------------------------------------------------------------------
816 // Parse IOS (serial stream format) definitions
817 //---------------------------------------------------------------------
818
parseIOSsize(size_t & p0)819 void parseIOSsize(size_t &p0)
820 {
821 iosTemp.size = getInt(p0);
822 }
823
parseIOSbytes(size_t & p0)824 void parseIOSbytes(size_t &p0)
825 {
826 if (iosTemp.data.size == 0)
827 iosTemp.str1.append(getBytes(p0));
828 else
829 iosTemp.str2.append(getBytes(p0));
830 }
831
parseIOSbyte(size_t & p0)832 void parseIOSbyte(size_t &p0)
833 {
834 if (iosTemp.data.size == 0)
835 iosTemp.str1 += getByte(p0);
836 else
837 iosTemp.str2 += getByte(p0);
838 }
839
parseIOSstring(size_t & p0)840 void parseIOSstring(size_t &p0)
841 {
842 if (iosTemp.data.size == 0)
843 iosTemp.str1 += getElement(p0);
844 else
845 iosTemp.str2 += getElement(p0);
846 }
847
parseIOSint(size_t & p0)848 void parseIOSint(size_t &p0)
849 {
850 if (iosTemp.data.size == 0)
851 iosTemp.str1 += (char)(getInt(p0) & 0xFF);
852 else
853 iosTemp.str2 += (char)(getInt(p0) & 0xFF);
854 }
855
parseDTYPE(size_t & p1)856 void parseDTYPE(size_t &p1)
857 {
858 print(p1,2);
859 iosTemp.data.dtype = getElement(p1);
860 }
861
parseDSIZE(size_t & p1)862 void parseDSIZE(size_t &p1)
863 {
864 print(p1,2);
865 iosTemp.data.size = getInt(p1);
866 }
867
parseDMAX(size_t & p1)868 void parseDMAX(size_t &p1)
869 {
870 print(p1,2);
871 iosTemp.data.max = getInt(p1);
872 }
873
parseDMIN(size_t & p1)874 void parseDMIN(size_t &p1)
875 {
876 print(p1,2);
877 iosTemp.data.min = getInt(p1);
878 }
879
parseDRESOL(size_t & p1)880 void parseDRESOL(size_t &p1)
881 {
882 print(p1,2);
883 iosTemp.data.resolution = getFloat(p1);
884 }
885
parseDREV(size_t & p1)886 void parseDREV(size_t &p1)
887 {
888 print(p1,2);
889 iosTemp.data.reverse = getBool(p1);
890 }
891
parseDMAKS(size_t & p1)892 void parseDMAKS(size_t &p1)
893 {
894 print(p1,2);
895 iosTemp.data.andmask = getInt(p1);
896 }
897
parseDSHIFT(size_t & p1)898 void parseDSHIFT(size_t &p1)
899 {
900 print(p1,2);
901 iosTemp.data.shiftbits = getInt(p1);
902 }
903
parseIOSdata(size_t & p0)904 void parseIOSdata(size_t &p0)
905 {
906 size_t pend = tagEnd(p0);
907 size_t p1;
908 TAGS *pv;
909
910 p1 = nextTag(p0);
911 while (p1 < pend) {
912 pv = datatags;
913 while (pv->tag) {
914 if (strXML.find(pv->tag, p1) == p1)
915 break;
916 pv++;
917 }
918 if (pv->fp) {
919 print(p1, 1);
920 (pv->fp)(p1);
921 p1 = tagEnd(p1);
922 } else {
923 LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
924 parseDISCARD(p1);
925 }
926 p1 = nextTag(p1);
927 }
928 }
929
parseIOSinfo(size_t & p0)930 void parseIOSinfo(size_t &p0)
931 {
932 string strR = getElement(p0);
933 if (strR.empty()) return;
934 iosTemp.info = strR;
935 }
936
parseIOSok(size_t & p0)937 void parseIOSok(size_t &p0)
938 {
939 string strR = getElement(p0);
940 if (strR.empty()) return;
941 iosTemp.ok = strR;
942 }
943
parseIOSbad(size_t & p0)944 void parseIOSbad(size_t &p0)
945 {
946 string strR = getElement(p0);
947 if (strR.empty()) return;
948 iosTemp.bad = strR;
949 }
950
parseIOSsymbol(size_t & p0)951 void parseIOSsymbol(size_t &p0)
952 {
953 string strR = getElement(p0);
954 if (strR.empty()) return;
955 iosTemp.SYMBOL = strR;
956 }
957
parseIOSfill(size_t & p0)958 void parseIOSfill(size_t &p0)
959 {
960 if (iosTemp.data.size == 0)
961 iosTemp.fill1 = getInt(p0);
962 else
963 iosTemp.fill2 = getInt(p0);
964 }
965
966 //=======================================================================
967
parseIOS(size_t & p0,TAGS * valid)968 bool parseIOS(size_t &p0, TAGS *valid)
969 {
970 size_t pend = tagEnd(p0);
971 size_t p1;
972 TAGS *pv;
973
974 print(p0,0);
975
976 iosTemp.clear();
977 p1 = nextTag(p0);
978 while (p1 < pend) {
979 pv = valid;
980 while (pv->tag) {
981 if (strXML.find(pv->tag, p1) == p1)
982 break;
983 pv++;
984 }
985 if (pv->fp) {
986 print(p1, 1);
987 (pv->fp)(p1);
988 p1 = tagEnd(p1);
989 } else {
990 LOG_ERROR("Invalid tag: %s", strXML.substr(p1, 10).c_str());
991 parseDISCARD(p1);
992 }
993 p1 = nextTag(p1);
994 }
995 p0 = pend;
996 return (!iosTemp.SYMBOL.empty());
997 }
998
parseCOMMAND(size_t & p0)999 void parseCOMMAND(size_t &p0)
1000 {
1001 if (parseIOS(p0, commandtags))
1002 commands.push_back(iosTemp);
1003 }
1004
parseREPLY(size_t & p0)1005 void parseREPLY(size_t &p0)
1006 {
1007 if (parseIOS(p0, replytags))
1008 reply.push_back(iosTemp);
1009 }
1010
parseRIGDEF(size_t & p0)1011 void parseRIGDEF(size_t &p0)
1012 {
1013 print(p0,0);
1014 size_t p1 = tagEnd(p0);
1015 if (p1 != string::npos)
1016 strXML.erase(p1);
1017 }
1018
parseDISCARD(size_t & p0)1019 void parseDISCARD(size_t &p0)
1020 {
1021 size_t pend = tagEnd(p0);
1022 if (pend == string::npos) p0++;
1023 else p0 = pend;
1024 }
1025
parseXML()1026 void parseXML()
1027 {
1028 size_t p0 = 0;
1029 TAGS *pValid = rigdeftags;
1030
1031 p0 = strXML.find("<");
1032 while (p0 != string::npos) {
1033 pValid = rigdeftags;
1034 while (pValid->tag) {
1035 if (strXML.find(pValid->tag, p0) == p0)
1036 break;
1037 pValid++;
1038 }
1039 if (pValid->tag) {
1040 (pValid->fp)(p0);
1041 } else {
1042 LOG_ERROR("Invalid tag: %s", strXML.substr(p0, 10).c_str());
1043 parseDISCARD(p0);
1044 }
1045 p0 = nextTag(p0);
1046 }
1047 }
1048
remove_comments()1049 bool remove_comments()
1050 {
1051 size_t p0 = 0;
1052 size_t p1 = 0;
1053
1054 // remove comments from xml text
1055 while ((p0 = strXML.find("<!--")) != string::npos) {
1056 p1 = strXML.find("-->", p0);
1057 if (p1 == string::npos) {
1058 fl_alert2("Corrupt rig XML definition file\nMismatched comment tags!");
1059 return false;
1060 }
1061 strXML.erase(p0, p1 - p0 + 3);
1062 }
1063 if (strXML.find("-->") != string::npos) {
1064 fl_alert2("Corrupt rig XML definition file\nMismatched comment tags!");
1065 return false;
1066 }
1067 return true;
1068 }
1069
testXML()1070 bool testXML()
1071 {
1072 if (!remove_comments()) return false;
1073
1074 return true;
1075 }
1076
readRigXML()1077 bool readRigXML()
1078 {
1079 char szLine[256];
1080 int lines = 0;
1081
1082 commands.clear();
1083 reply.clear();
1084 lmodes.clear();
1085 lmodeCMD.clear();
1086 lmodeREPLY.clear();
1087 lbws.clear();
1088 lbwCMD.clear();
1089 lbwREPLY.clear();
1090 LSBmodes.clear();
1091 strXML = "";
1092
1093 ifstream xmlfile(progdefaults.XmlRigFilename.c_str(), ios::in);
1094 if (xmlfile) {
1095 while (!xmlfile.eof()) {
1096 lines++;
1097 memset(szLine, 0, sizeof(szLine));
1098 xmlfile.getline(szLine,255);
1099 strXML.append(szLine);
1100 }
1101 xmlfile.close();
1102 if (testXML()) {
1103 parseXML();
1104 xmlrig.xmlok = true;
1105 return true;
1106 }
1107 }
1108 return false;
1109 }
1110
selectRigXmlFilename()1111 void selectRigXmlFilename()
1112 {
1113 string deffilename;
1114 deffilename = progdefaults.XmlRigFilename;
1115 const char *p = FSEL::select(_("Open rig xml file"), _("Fldigi rig xml definition file\t*.xml"), deffilename.c_str());
1116 if (!p) return;
1117 if (!*p) return;
1118
1119 progdefaults.XmlRigFilename = p;
1120 txtXmlRigFilename->value(fl_filename_name(p));
1121 loadRigXmlFile();
1122 }
1123
loadRigXmlFile(void)1124 void loadRigXmlFile(void)
1125 {
1126 rigCAT_close();
1127 readRigXML();
1128 rigCAT_defaults();
1129 }
1130