1 /*
2 * Tlf - contest logging program for amateur radio operators
3 * Copyright (C) 2001-2002-2003 Rein Couperus <pa0rct@amsat.org>
4 * 2012-2013 Thomas Beierlein <tb@forth-ev.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 /* ------------------------------------------------------------
21 * write cabrillo file
22 *
23 *--------------------------------------------------------------*/
24
25
26 #ifndef _GNU_SOURCE
27 #define _GNU_SOURCE
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <unistd.h>
35
36 #include "getsummary.h"
37 #include "log_utils.h"
38 #include "tlf_curses.h"
39 #include "ui_utils.h"
40 #include "cabrillo_utils.h"
41
42 extern char call[];
43
44 /* conversion table between tag name in format file and internal tag */
45 extern struct tag_conv tag_tbl[];
46
47 struct qso_t *get_next_record(FILE *fp);
48 struct qso_t *get_next_qtc_record(FILE *fp, int qtcdirection);
49 void free_qso(struct qso_t *ptr);
50
51 /** get next qso record from log
52 *
53 * Read next line from logfile until it is no comment.
54 * Then parse the logline into a new allocated QSO data structure
55 * and return that structure.
56 *
57 * \return ptr to new qso record (or NULL if eof)
58 */
get_next_record(FILE * fp)59 struct qso_t *get_next_record(FILE *fp) {
60
61 char buffer[160];
62 char *tmp;
63 char *sp;
64 struct qso_t *ptr;
65 struct tm date_n_time;
66
67 while ((fgets(buffer, sizeof(buffer), fp)) != NULL) {
68
69 if (!log_is_comment(buffer)) {
70
71 ptr = g_malloc0(sizeof(struct qso_t));
72
73 /* remember whole line */
74 ptr->logline = g_strdup(buffer);
75 ptr->qtcdirection = 0;
76 ptr->qsots = 0;
77
78 /* split buffer into parts for qso_t record and parse
79 * them accordingly */
80 tmp = strtok_r(buffer, " \t", &sp);
81
82 /* band */
83 ptr->band = atoi(tmp);
84
85
86 /* mode */
87 if (strcasestr(tmp, "CW"))
88 ptr->mode = CWMODE;
89 else if (strcasestr(tmp, "SSB"))
90 ptr->mode = SSBMODE;
91 else
92 ptr->mode = DIGIMODE;
93
94 /* date & time */
95 memset(&date_n_time, 0, sizeof(struct tm));
96
97 strptime(strtok_r(NULL, " \t", &sp), "%d-%b-%y", &date_n_time);
98 strptime(strtok_r(NULL, " \t", &sp), "%H:%M", &date_n_time);
99
100 ptr->year = date_n_time.tm_year + 1900; /* convert to
101 1968..2067 */
102 ptr->month = date_n_time.tm_mon + 1; /* tm_mon = 0..11 */
103 ptr->day = date_n_time.tm_mday;
104
105 ptr->hour = date_n_time.tm_hour;
106 ptr->min = date_n_time.tm_min;
107
108 /* qso number */
109 ptr->qso_nr = atoi(strtok_r(NULL, " \t", &sp));
110
111 /* his call */
112 ptr->call = g_strdup(strtok_r(NULL, " \t", &sp));
113
114 /* RST send and received */
115 ptr->rst_s = atoi(strtok_r(NULL, " \t", &sp));
116 ptr->rst_r = atoi(strtok_r(NULL, " \t", &sp));
117
118 /* comment (exchange) */
119 ptr->comment = g_strndup(buffer + 54, 13);
120
121 /* tx */
122 ptr->tx = (buffer[79] == '*') ? 1 : 0;
123
124 /* frequency (kHz) */
125 ptr->freq = atof(buffer + 80) * 1000.0;
126 if ((ptr->freq < 1800000.) || (ptr->freq >= 30000000.)) {
127 ptr->freq = 0.;
128 }
129
130 return ptr;
131 }
132 }
133
134 return NULL;
135 }
136
137 /** get next qtc record from log
138 *
139 * Read next line from logfile.
140 * Then parse the received or sent qtc logline into a new allocated received QTC data structure
141 * and return that structure.
142 *
143 * \return ptr to new qtc record (or NULL if eof)
144 */
get_next_qtc_record(FILE * fp,int qtcdirection)145 struct qso_t *get_next_qtc_record(FILE *fp, int qtcdirection) {
146
147 char buffer[100];
148 char *tmp;
149 char *sp;
150 struct qso_t *ptr;
151 int pos, shift;
152 struct tm date_n_time;
153
154 if (fp == NULL) {
155 return NULL;
156 }
157
158 while ((fgets(buffer, sizeof(buffer), fp)) != NULL) {
159
160
161 ptr = g_malloc0(sizeof(struct qso_t));
162
163 /* remember whole line */
164 ptr->logline = g_strdup(buffer);
165 ptr->qtcdirection = qtcdirection;
166
167 /* tx */
168 if (qtcdirection == RECV) {
169 pos = 28;
170 shift = 0;
171 } else {
172 pos = 33;
173 shift = 5;
174 }
175 ptr->tx = (buffer[pos] == ' ') ? 0 : 1;
176
177 /* split buffer into parts for qso_t record and parse
178 * them accordingly */
179 tmp = strtok_r(buffer, " \t", &sp);
180
181 /* band */
182 ptr->band = atoi(tmp);
183
184 /* mode */
185 if (strcasestr(tmp, "CW"))
186 ptr->mode = CWMODE;
187 else if (strcasestr(tmp, "SSB"))
188 ptr->mode = SSBMODE;
189 else
190 ptr->mode = DIGIMODE;
191
192 /* qso number */
193 ptr->qso_nr = atoi(strtok_r(NULL, " \t", &sp));
194
195 /* in case of SEND direction, the 3rd field is the original number of sent QSO,
196 but it doesn't need for QTC line */
197 if (qtcdirection & SEND) {
198 tmp = strtok_r(NULL, " \t", &sp);
199 }
200 /* date & time */
201 memset(&date_n_time, 0, sizeof(struct tm));
202
203 strptime(strtok_r(NULL, " \t", &sp), "%d-%b-%y", &date_n_time);
204 strptime(strtok_r(NULL, " \t", &sp), "%H:%M", &date_n_time);
205
206 ptr->qsots = timegm(&date_n_time);
207
208 ptr->year = date_n_time.tm_year + 1900; /* convert to
209 1968..2067 */
210 ptr->month = date_n_time.tm_mon + 1; /* tm_mon = 0..11 */
211 ptr->day = date_n_time.tm_mday;
212
213 ptr->hour = date_n_time.tm_hour;
214 ptr->min = date_n_time.tm_min;
215
216 if (ptr->tx == 1) {
217 /* ignore TX if set */
218 strtok_r(NULL, " \t", &sp);
219 }
220 /* his call */
221 ptr->call = g_strdup(strtok_r(NULL, " \t", &sp));
222
223 /* QTC serial and number */
224 ptr->qtc_serial = atoi(strtok_r(NULL, " \t", &sp));
225 ptr->qtc_number = atoi(strtok_r(NULL, " \t", &sp));
226
227 ptr->qtc_qtime = g_strdup(strtok_r(NULL, " \t", &sp));
228 ptr->qtc_qcall = g_strdup(strtok_r(NULL, " \t", &sp));
229 ptr->qtc_qserial = g_strdup(strtok_r(NULL, " \t", &sp));
230
231 /* frequency */
232 ptr->freq = atof(buffer + 80 + shift) * 1000.0;
233 if ((ptr->freq < 1800000.) || (ptr->freq >= 30000000.)) {
234 ptr->freq = 0.;
235 }
236
237 return ptr;
238 }
239
240 return NULL;
241 }
242
243 /** free qso record pointed to by ptr */
free_qso(struct qso_t * ptr)244 void free_qso(struct qso_t *ptr) {
245
246 if (ptr != NULL) {
247 g_free(ptr->comment);
248 g_free(ptr->logline);
249 g_free(ptr->call);
250 if (ptr->qtc_qtime != NULL) {
251 g_free(ptr->qtc_qtime);
252 g_free(ptr->qtc_qcall);
253 g_free(ptr->qtc_qserial);
254 }
255 g_free(ptr);
256 }
257 }
258
259 /** write out information */
info(char * s)260 void info(char *s) {
261 attron(modify_attr(COLOR_PAIR(C_INPUT) | A_STANDOUT));
262 mvprintw(13, 29, "%s", s);
263 refreshp();
264 }
265
266
267 const char *to_mode[] = {
268 "CW",
269 "PH",
270 "RY"
271 };
272
273 /* converts band to frequency of start of band */
band2freq(int band)274 static freq_t band2freq(int band) {
275 freq_t freq;
276
277 switch (band) {
278 case 160:
279 freq = 1800000.;
280 break;
281 case 80:
282 freq = 3500000.;
283 break;
284 case 40:
285 freq = 7000000.;
286 break;
287 case 30:
288 freq = 10100000.;
289 break;
290 case 20:
291 freq = 14000000.;
292 break;
293 case 17:
294 freq = 18068000.;
295 break;
296 case 15:
297 freq = 21000000.;
298 break;
299 case 12:
300 freq = 24890000.;
301 break;
302 case 10:
303 freq = 28000000.;
304 break;
305 default:
306 freq = 0.;
307 break;
308 }
309
310 return freq;
311 }
312
313 /* add 'src' to 'dst' with max. 'len' chars left padded */
add_lpadded(char * dst,char * src,int len)314 void add_lpadded(char *dst, char *src, int len) {
315 char *field;
316 int l;
317
318 field = g_malloc(len + 1);
319 strcat(dst, " ");
320 memset(field, ' ', len);
321 l = strlen(src);
322 if (l > len) l = len;
323 memcpy(field + len - l, src, l);
324 field[len] = '\0';
325 strcat(dst, field);
326 g_free(field);
327 }
328
329 /* add 'src' to 'dst' with max. 'len' char right padded */
add_rpadded(char * dst,char * src,int len)330 void add_rpadded(char *dst, char *src, int len) {
331 char *field;
332 int l;
333
334 field = g_malloc(len + 1);
335 strcat(dst, " ");
336 memset(field, ' ', len);
337 l = strlen(src);
338 if (l > len) l = len;
339 memcpy(field, src, l);
340 field[len] = '\0';
341 strcat(dst, field);
342 g_free(field);
343 }
344
345 /* get the n-th token of a string, return empty string if no n-th token */
get_nth_token(gchar * str,int n)346 gchar *get_nth_token(gchar *str, int n) {
347 gchar *string = g_strdup(str);
348 gchar *ptr;
349 char *sp;
350
351 ptr = strtok_r(string, " \t", &sp);
352
353 while (n > 0 && ptr != NULL) {
354 ptr = strtok_r(NULL, " \t", &sp);
355 n--;
356 }
357
358 /* if no n-th element in string, return empty string */
359 if (ptr == NULL)
360 ptr = strdup("");
361 else
362 ptr = strdup(ptr);
363
364 g_free(string);
365 return ptr;
366 }
367
368
369 /* format QSO: line for actual qso according to cabrillo format description
370 * and put it into buffer */
prepare_line(struct qso_t * qso,struct cabrillo_desc * desc,char * buf)371 void prepare_line(struct qso_t *qso, struct cabrillo_desc *desc, char *buf) {
372
373 extern char exchange[];
374
375 freq_t freq;
376 int i;
377 char tmp[80];
378 struct line_item *item;
379 gchar *token;
380 int item_count;
381 GPtrArray *item_array;
382
383 if (qso == NULL) {
384 strcpy(buf, "");
385 return;
386 }
387
388 freq = qso->freq;
389 if (freq < 1800000.)
390 freq = band2freq(qso->band);
391
392 if (qso->qtcdirection == 0) {
393 strcpy(buf, "QSO:"); /* start the line */
394 item_count = desc->item_count;
395 item_array = desc->item_array;
396 } else {
397 if (desc->qtc_item_array == NULL) {
398 strcpy(buf, ""); /* no QTC format description */
399 return;
400 }
401 strcpy(buf, "QTC:"); /* start the line */
402 item_count = desc->qtc_item_count;
403 item_array = desc->qtc_item_array;
404 }
405 for (i = 0; i < item_count; i++) {
406 item = g_ptr_array_index(item_array, i);
407 switch (item->tag) {
408 case FREQ:
409 sprintf(tmp, "%d", (int)(freq / 1000.0));
410 add_lpadded(buf, tmp, item->len);
411 break;
412 case MODE:
413 sprintf(tmp, "%s", to_mode[qso->mode]);
414 add_lpadded(buf, tmp, item->len);
415 break;
416 case DATE:
417 sprintf(tmp, "%4d-%02d-%02d",
418 qso->year, qso->month, qso->day);
419 add_lpadded(buf, tmp, item->len);
420 break;
421 case TIME:
422 sprintf(tmp, "%02d%02d", qso->hour, qso->min);
423 add_lpadded(buf, tmp, item->len);
424 break;
425 case MYCALL:
426 strcpy(tmp, call);
427 add_rpadded(buf, g_strchomp(tmp), item->len);
428 break;
429 case HISCALL:
430 add_rpadded(buf, qso->call, item->len);
431 break;
432 case RST_S:
433 sprintf(tmp, "%d", qso->rst_s);
434 add_rpadded(buf, tmp, item->len);
435 break;
436 case RST_R:
437 sprintf(tmp, "%d", qso->rst_r);
438 add_rpadded(buf, tmp, item->len);
439 break;
440 case EXCH:
441 add_rpadded(buf, qso->comment, item->len);
442 break;
443 case EXC1:
444 token = get_nth_token(qso->comment, 0);
445 add_rpadded(buf, token, item->len);
446 g_free(token);
447 break;
448 case EXC2:
449 token = get_nth_token(qso->comment, 1);
450 add_rpadded(buf, token, item->len);
451 g_free(token);
452 break;
453 case EXC3:
454 token = get_nth_token(qso->comment, 2);
455 add_rpadded(buf, token, item->len);
456 g_free(token);
457 break;
458 case EXC4:
459 token = get_nth_token(qso->comment, 3);
460 add_rpadded(buf, token, item->len);
461 g_free(token);
462 break;
463 case EXC_S: {
464 int pos;
465 char *start = exchange;
466 tmp[0] = '\0';
467 pos = strcspn(start, "#");
468 strncat(tmp, start, pos); /** \todo avoid buffer overflow */
469 while (pos < strlen(start)) {
470 if (start[pos] == '#') {
471 /* format and add serial number */
472 char number[6];
473 sprintf(number, "%04d", qso->qso_nr);
474 strcat(tmp, number);
475 }
476
477 start = start + pos + 1; /* skip special character */
478 pos = strcspn(start, "#");
479 strncat(tmp, start, pos);
480 }
481 add_rpadded(buf, tmp, item->len);
482 }
483 break;
484 case TX:
485 sprintf(tmp, "%1d", qso->tx);
486 add_rpadded(buf, tmp, item->len);
487 break;
488 case QTCRCALL:
489 if (qso->qtcdirection == 1) { // RECV
490 strcpy(tmp, call);
491 }
492 if (qso->qtcdirection == 2) { // SEND
493 strcpy(tmp, qso->call);
494 }
495 add_rpadded(buf, g_strchomp(tmp), item->len);
496 break;
497 case QTCHEAD:
498 tmp[0] = '\0';
499 sprintf(tmp, "%*d/%d", 3, qso->qtc_serial, qso->qtc_number);
500 add_rpadded(buf, g_strchomp(tmp), item->len);
501 break;
502 case QTCSCALL:
503 if (qso->qtcdirection == 1) { // RECV
504 strcpy(tmp, qso->call);
505 }
506 if (qso->qtcdirection == 2) { // SEND
507 strcpy(tmp, call);
508 }
509 add_rpadded(buf, g_strchomp(tmp), item->len);
510 break;
511 case QTC:
512 sprintf(tmp, "%s %-13s %4s", qso->qtc_qtime, qso->qtc_qcall, qso->qtc_qserial);
513 add_rpadded(buf, g_strchomp(tmp), item->len);
514 case NO_ITEM:
515 default:
516 tmp[0] = '\0';
517 }
518
519 }
520 strcat(buf, "\n"); /* closing nl */
521 }
522
write_cabrillo(void)523 int write_cabrillo(void) {
524
525 extern char *cabrillo;
526 extern char logfile[];
527 extern char exchange[];
528 extern char call[];
529
530 char *cab_dfltfile;
531 struct cabrillo_desc *cabdesc;
532 char cabrillo_tmp_name[80];
533 char buffer[4000] = "";
534
535 FILE *fp1, *fp2, *fpqtcrec = NULL, *fpqtcsent = NULL;
536 struct qso_t *qso, *qtcrec = NULL, *qtcsent = NULL;
537 int qsonr, qtcrecnr, qtcsentnr;
538
539 if (cabrillo == NULL) {
540 info("Missing CABRILLO= keyword (see man page)");
541 sleep(2);
542 return (1);
543 }
544
545 /* Try to read cabrillo format first from local directory.
546 * Try also in default data dir if not found.
547 */
548 cabdesc = read_cabrillo_format("cabrillo.fmt", cabrillo);
549 if (!cabdesc) {
550 cab_dfltfile = g_strconcat(PACKAGE_DATA_DIR, G_DIR_SEPARATOR_S,
551 "cabrillo.fmt", NULL);
552 cabdesc = read_cabrillo_format(cab_dfltfile, cabrillo);
553 g_free(cab_dfltfile);
554 }
555
556 if (!cabdesc) {
557 info("Cabrillo format specification not found!");
558 sleep(2);
559 return (2);
560 }
561
562 /* open logfile and create a cabrillo file */
563 strcpy(cabrillo_tmp_name, call);
564 g_strstrip(cabrillo_tmp_name); /* drop \n */
565 strcat(cabrillo_tmp_name, ".cbr");
566
567 if ((fp1 = fopen(logfile, "r")) == NULL) {
568 info("Can't open logfile.");
569 sleep(2);
570 free_cabfmt(cabdesc);
571 return (1);
572 }
573 if (cabdesc->qtc_item_array != NULL) {
574 if (qtcdirection & 1) {
575 fpqtcrec = fopen(QTC_RECV_LOG, "r");
576 if (fpqtcrec == NULL) {
577 info("Can't open received QTC logfile.");
578 sleep(2);
579 free_cabfmt(cabdesc);
580 fclose(fp1);
581 return (1);
582 }
583 }
584 if (qtcdirection & 2) {
585 fpqtcsent = fopen(QTC_SENT_LOG, "r");
586 if (fpqtcsent == NULL) {
587 info("Can't open sent QTC logfile.");
588 sleep(2);
589 free_cabfmt(cabdesc);
590 fclose(fp1);
591 if (fpqtcrec != NULL) fclose(fpqtcrec);
592 return (1);
593 }
594 }
595 }
596 if ((fp2 = fopen(cabrillo_tmp_name, "w")) == NULL) {
597 info("Can't create cabrillo file.");
598 sleep(2);
599 free_cabfmt(cabdesc);
600 fclose(fp1);
601 if (fpqtcsent != NULL) fclose(fpqtcsent);
602 if (fpqtcrec != NULL) fclose(fpqtcrec);
603 return (2);
604 }
605
606
607 /* ask for exchange and header information */
608 ask(buffer,
609 "Your exchange (e.g. State, province, age etc... (# if serial number)): ");
610 g_strlcpy(exchange, buffer, 11);
611 getsummary(fp2);
612
613 info("Writing cabrillo file");
614
615 qsonr = 0;
616 qtcrecnr = 0;
617 qtcsentnr = 0;
618 while ((qso = get_next_record(fp1))) {
619
620 qsonr++;
621 prepare_line(qso, cabdesc, buffer);
622
623 if (strlen(buffer) > 5) {
624 fputs(buffer, fp2);
625 }
626 if (fpqtcrec != NULL && qtcrec == NULL) {
627 qtcrec = get_next_qtc_record(fpqtcrec, RECV);
628 if (qtcrec != NULL) {
629 qtcrecnr = qtcrec->qso_nr;
630 }
631 }
632 if (fpqtcsent != NULL && qtcsent == NULL) {
633 qtcsent = get_next_qtc_record(fpqtcsent, SEND);
634 if (qtcsent != NULL) {
635 qtcsentnr = qtcsent->qso_nr;
636 }
637 }
638 while (qtcrecnr == qsonr || qtcsentnr == qsonr) {
639 if (qtcsent == NULL || (qtcrec != NULL && qtcrec->qsots < qtcsent->qsots)) {
640 prepare_line(qtcrec, cabdesc, buffer);
641 if (strlen(buffer) > 5) {
642 fputs(buffer, fp2);
643 free_qso(qtcrec);
644 }
645 qtcrec = get_next_qtc_record(fpqtcrec, RECV);
646 if (qtcrec != NULL) {
647 qtcrecnr = qtcrec->qso_nr;
648 } else {
649 qtcrecnr = 0;
650 }
651 } else {
652 prepare_line(qtcsent, cabdesc, buffer);
653 if (strlen(buffer) > 5) {
654 fputs(buffer, fp2);
655 free_qso(qtcsent);
656 }
657 qtcsent = get_next_qtc_record(fpqtcsent, SEND);
658 if (qtcsent != NULL) {
659 qtcsentnr = qtcsent->qso_nr;
660 } else {
661 qtcsentnr = 0;
662 }
663 }
664 }
665
666 free_qso(qso);
667 }
668
669 fclose(fp1);
670
671 fputs("END-OF-LOG:\n", fp2);
672 fclose(fp2);
673 if (fpqtcrec != NULL) {
674 fclose(fpqtcrec);
675 }
676
677 free_cabfmt(cabdesc);
678
679 return 0;
680 }
681
682
683 /* write ADIF header to open file */
write_adif_header(FILE * fp)684 void write_adif_header(FILE* fp) {
685 extern char whichcontest[];
686
687 time_t now = time(0);
688 struct tm *time_ptr = gmtime(&now);
689 char timebuf[100];
690
691 fputs
692 ("################################################################################\n",
693 fp);
694 fputs ("# ADIF v3.10 data file exported by TLF\n", fp);
695 fputs ("# according to specifications on http://www.adif.org\n", fp);
696 fputs
697 ("################################################################################\n",
698 fp);
699
700 strftime(timebuf, sizeof(timebuf), "%d-%b-%y at %H:%Mz", time_ptr);
701 fprintf(fp, "Created %s for %s\n", timebuf, call);
702
703 /* Write contest name */
704 fprintf(fp, "Contest Name: %s\n", whichcontest);
705 fputs("<adif_ver:4>3.10\n", fp);
706 fputs("<programid:3>TLF\n", fp);
707 fprintf(fp, "<programversion:%ld>%s\n", strlen(VERSION), VERSION);
708 fputs("<eoh>\n", fp);
709 }
710
711
712 /*
713 The ADIF function has been written according ADIF v1.00 specifications
714 as shown on http://www.adif.org
715 LZ3NY
716 */
write_adif(void)717 int write_adif(void) {
718
719 extern char logfile[];
720 extern char exchange[];
721 extern char whichcontest[];
722 extern int exchange_serial;
723 extern char modem_mode[];
724
725 char buf[181] = "";
726 char buffer[181] = "";
727 char standardexchange[70] = "";
728 char adif_tmp_name[40] = "";
729 char adif_tmp_call[13] = "";
730 char adif_tmp_str[2] = "";
731 char adif_year_check[3] = "";
732 char adif_rcvd_num[16] = "";
733 char resultat[16];
734 char adif_tmp_rr[5] = "";
735 char freq_buf[16];
736
737 int adif_mode_dep = 0;
738
739 FILE *fp1, *fp2;
740
741 if ((fp1 = fopen(logfile, "r")) == NULL) {
742 info("Opening logfile not possible.");
743 sleep(2);
744 return (1);
745 }
746 strcpy(adif_tmp_name, whichcontest);
747 strcat(adif_tmp_name, ".adi");
748
749 if ((fp2 = fopen(adif_tmp_name, "w")) == NULL) {
750 info("Opening ADIF file not possible.");
751 sleep(2);
752 fclose(fp1); //added by F8CFE
753 return (2);
754 }
755
756 if (strlen(exchange) > 0)
757 strcpy(standardexchange, exchange);
758
759 /* in case using write_adif() without write_cabrillo() before
760 * just ask for the needed information */
761 if ((strlen(standardexchange) == 0) && (exchange_serial != 1)) {
762 ask(buffer,
763 "Your exchange (e.g. State, province, age etc... (# if serial number)): ");
764 g_strlcpy(standardexchange, buffer, 11);
765 }
766
767 info("Writing ADIF file");
768
769 write_adif_header(fp2);
770
771 while (fgets(buf, sizeof(buf), fp1)) {
772
773 buffer[0] = '\0';
774
775 if ((buf[0] != ';') && ((buf[0] != ' ') || (buf[1] != ' '))
776 && (buf[0] != '#') && (buf[0] != '\n') && (buf[0] != '\r')) {
777
778 /* CALLSIGN */
779 strcat(buffer, "<CALL:");
780 strncpy(adif_tmp_call, buf + 29, 12);
781 strcpy(adif_tmp_call, g_strstrip(adif_tmp_call));
782 snprintf(resultat, sizeof(resultat), "%zd",
783 strlen(adif_tmp_call));
784 strcat(buffer, resultat);
785 strcat(buffer, ">");
786 strcat(buffer, adif_tmp_call);
787
788 /* BAND */
789 if (buf[1] == '6')
790 strcat(buffer, "<BAND:4>160M");
791 else if (buf[1] == '8')
792 strcat(buffer, "<BAND:3>80M");
793 else if (buf[1] == '4')
794 strcat(buffer, "<BAND:3>40M");
795 else if (buf[1] == '3')
796 strcat(buffer, "<BAND:3>30M");
797 else if (buf[1] == '2')
798 strcat(buffer, "<BAND:3>20M");
799 else if (buf[1] == '1' && buf[2] == '5')
800 strcat(buffer, "<BAND:3>15M");
801 else if (buf[1] == '1' && buf[2] == '7')
802 strcat(buffer, "<BAND:3>17M");
803 else if (buf[1] == '1' && buf[2] == '2')
804 strcat(buffer, "<BAND:3>12M");
805 else if (buf[1] == '1' && buf[2] == '0')
806 strcat(buffer, "<BAND:3>10M");
807
808 /* FREQ if available */
809 if (strlen(buf) > 81) {
810 // read kHz and write MHz
811 const double mhz = atof(buf + 80) / 1000.0;
812 freq_buf[0] = '\0';
813 if (mhz > 1.799) {
814 sprintf(freq_buf, "<FREQ:%d>%.4f",
815 mhz < 10 ? 6 : 7, mhz);
816 }
817 strcat(buffer, freq_buf);
818 }
819
820 /* QSO MODE */
821 if (buf[3] == 'C')
822 strcat(buffer, "<MODE:2>CW");
823 else if (buf[3] == 'S')
824 strcat(buffer, "<MODE:3>SSB");
825 else if (strcmp(modem_mode, "RTTY") == 0)
826 strcat(buffer, "<MODE:4>RTTY");
827 else
828 /* \todo DIGI is no allowed mode */
829 strcat(buffer, "<MODE:4>DIGI");
830
831 /* QSO_DATE */
832 /* Y2K :) */
833 adif_year_check[0] = '\0';
834 strncpy(adif_year_check, buf + 14, 2);
835 if (atoi(adif_year_check) <= 70)
836 strcat(buffer, "<QSO_DATE:8>20");
837 else
838 strcat(buffer, "<QSO_DATE:8>19");
839
840 /* year */
841 strncat(buffer, buf + 14, 2);
842
843 /*month */
844 if (buf[10] == 'J' && buf[11] == 'a')
845 strcat(buffer, "01");
846 if (buf[10] == 'F')
847 strcat(buffer, "02");
848 if (buf[10] == 'M' && buf[12] == 'r')
849 strcat(buffer, "03");
850 if (buf[10] == 'A' && buf[12] == 'r')
851 strcat(buffer, "04");
852 if (buf[10] == 'M' && buf[12] == 'y')
853 strcat(buffer, "05");
854 if (buf[10] == 'J' && buf[11] == 'u' && buf[12] == 'n')
855 strcat(buffer, "06");
856 if (buf[10] == 'J' && buf[12] == 'l')
857 strcat(buffer, "07");
858 if (buf[10] == 'A' && buf[12] == 'g')
859 strcat(buffer, "08");
860 if (buf[10] == 'S')
861 strcat(buffer, "09");
862 if (buf[10] == 'O')
863 strcat(buffer, "10");
864 if (buf[10] == 'N')
865 strcat(buffer, "11");
866 if (buf[10] == 'D')
867 strcat(buffer, "12");
868
869 /*date */
870 strncat(buffer, buf + 7, 2);
871
872 /* TIME_ON */
873 strcat(buffer, "<TIME_ON:4>");
874 strncat(buffer, buf + 17, 2);
875 strncat(buffer, buf + 20, 2);
876
877 /* RS(T) flag */
878 if (buf[3] == 'S') /* check for SSB */
879 adif_mode_dep = 2;
880 else
881 adif_mode_dep = 3;
882
883 /* RST_SENT */
884 strcat(buffer, "<RST_SENT:");
885 adif_tmp_str[1] = '\0'; /* PA0R 02/10/2003 */
886 adif_tmp_str[0] = adif_mode_dep + 48;
887 strcat(buffer, adif_tmp_str);
888 strcat(buffer, ">");
889 strncat(buffer, buf + 44, adif_mode_dep);
890
891 /* STX - sent contest number */
892 strcat(buffer, "<STX:");
893
894 if ((exchange_serial == 1) || (standardexchange[0] == '#')) {
895 strcat(buffer, "4>");
896 strncat(buffer, buf + 23, 4);
897 } else {
898 snprintf(resultat, sizeof(resultat), "%zd",
899 strlen(standardexchange));
900 strcat(buffer, resultat);
901 strcat(buffer, ">");
902 strcat(buffer, g_strstrip(standardexchange));
903 }
904
905 /* RST_RCVD */
906 strncpy(adif_tmp_rr, buf + 49, 4);
907 strcpy(adif_tmp_rr, g_strstrip(adif_tmp_rr));
908 strcat(buffer, "<RST_RCVD:");
909 snprintf(resultat, sizeof(resultat), "%zd",
910 strlen(adif_tmp_rr));
911 strcat(buffer, resultat);
912 strcat(buffer, ">");
913 strncat(buffer, buf + 49, adif_mode_dep);
914
915 /* SRX - received contest number */
916 strncpy(adif_rcvd_num, buf + 54, 14);
917 strcpy(adif_rcvd_num, g_strstrip(adif_rcvd_num));
918 snprintf(resultat, sizeof(resultat), "%zd",
919 strlen(adif_rcvd_num));
920 strcat(buffer, "<SRX:");
921 strcat(buffer, resultat);
922 strcat(buffer, ">");
923 if (strcmp(buf + 54, " ") != 0)
924 strcat(buffer, adif_rcvd_num);
925
926 /* <EOR> */
927 strcat(buffer, "<eor>\n"); //end of ADIF row
928
929 fputs(buffer, fp2);
930 }
931 } // end fgets() loop
932
933 fclose(fp1);
934 fclose(fp2);
935
936 return (0);
937 } // end write_adif
938