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