/* * xlog - GTK+ logging program for amateur radio operators * Copyright (C) 2001-2003 Joop Stakenborg * * This program is free oftware; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* * edi.c - scanner for EDI (Electronic Data Interchange) IARU Region 1 * from version 1.1 of 06-21-1995 * * Reports to Stephane Fillod F8CFE * Specifications (in French) from http://www.ref-union.org * */ #include #include #include #include #include #include #include "logfile.h" #include "types.h" extern preferencestype preferences; /* * fields to be stored in the edi file */ static const gint edi_fields[] = { DATE, GMT, CALL, MODE, RST, MYRST, LOCATOR }; static const gint edi_widths[] = { 6, 4, 14, 1, 3, 3, 6 }; static const gint edi_field_nr = 7; static gint edi_open (LOGDB *); static void edi_close (LOGDB *); static gint edi_create (LOGDB *); static gint edi_qso_append (LOGDB *, const qso_t *); static gint edi_qso_foreach (LOGDB *, gint (*fn) (LOGDB *, qso_t *, gpointer arg), gpointer arg); const struct log_ops edi_ops = { .open = edi_open, .close = edi_close, .create = edi_create, .qso_append = edi_qso_append, .qso_foreach = edi_qso_foreach, .type = TYPE_EDI, .name = "EDI", .extension = ".edi", }; /* * open for read */ gint edi_open (LOGDB * handle) { FILE *fp; fp = fopen (handle->path, "r"); if (!fp) return -1; handle->priv = (gpointer) fp; handle->column_nr = edi_field_nr; memcpy (handle->column_fields, edi_fields, sizeof (edi_fields)); memcpy (handle->column_widths, edi_widths, sizeof (edi_widths)); return 0; } /* * open for write */ gint edi_create (LOGDB * handle) { FILE *fp; fp = fopen (handle->path, "w"); if (!fp) return -1; handle->priv = (gpointer) fp; /* write header */ fprintf (fp, "[REG1TEST;1]\n" "TName=\n" "TDate=\n" "PCall=%s\n" "PWWLo=%s\n" "PExch=\n" "RName=\n" "RAdr1=\n" "RAdr2=\n" "RPoCo=\n" "RCity=\n" "RHBBS=\n" "PBand=\n" "PSect=\n" "MOpe1=\n" "STXEq=\n" "SRXEq=\n" "SPowe=\n" "SAnte=\n" "CQSOs=\n" "CQSOP=\n" "CWWLs=\n" "CODXC=\n" "LSoft=" PACKAGE " Version " VERSION "\n" "[Remarks]\n" "[QSORecords;]\n", preferences.callsign, preferences.locator); return 0; } void edi_close (LOGDB * handle) { FILE *fp = (FILE *) handle->priv; fclose (fp); } extern gdouble wwl_dist(gchar *my, gchar *dx); /* */ gint edi_qso_append (LOGDB * handle, const qso_t * q) { FILE *fp = (FILE *) handle->priv; gchar rst[16], exch[16] = "", my_rst[16], my_exch[16] = ""; gchar date[16]; gchar *p; gint rst_len; gint mode, kms; /* * there's no exchange fields in xlog. However, the exchange information * may be piggybacked by the rst field. eg. "599 35". */ p = strchr (q[RST], ' '); rst_len = p ? p - q[RST] : strlen (q[RST]); strncpy (rst, q[RST], rst_len); rst[rst_len] = '\0'; strncpy (my_rst, q[MYRST], rst_len); my_rst[rst_len] = '\0'; if (strlen (q[RST]) > rst_len) strcpy (exch, q[RST] + rst_len + 1); if (strlen (q[MYRST]) > rst_len) strcpy (my_exch, q[MYRST] + rst_len + 1); /* AAMMDD */ if (strlen (q[DATE]) == 11 && q[DATE][2] == ' ' && q[DATE][6] == ' ') sprintf (date, "%s%02d%c%c", q[DATE] + 9, scan_month (q[DATE] + 3), q[DATE][0], q[DATE][1]); if (!strcmp(q[MODE], "SSB")) { mode = 1; } else if (!strcmp(q[MODE], "CW")) { mode = 2; } else if (!strcmp(q[MODE], "AM")) { mode = 5; } else if (!strcmp(q[MODE], "FM")) { mode = 6; } else if (!strcmp(q[MODE], "RTTY")) { mode = 7; } else if (!strcmp(q[MODE], "SSTV")) { mode = 8; } else if (!strcmp(q[MODE], "ATV")) { mode = 9; } else { mode = 0; } kms = wwl_dist (preferences.locator, q[LOCATOR]); /* * CSV-alike format * * We're missing the points and zone/km column, * hence the empty semicolon */ //020907;1404;PI4GN;1;59;001;59;005;;JO33II;515;;;; fprintf (fp, "%s;%s;%s;%d;%s;%s;%s;%s;;%s;%d;;;;\n", date, q[GMT], q[CALL], mode, rst, exch, my_rst, my_exch, q[LOCATOR],kms); return 0; } #define MAXROWLEN 120 gint edi_qso_foreach (LOGDB * handle, gint (*fn) (LOGDB *, qso_t *, gpointer arg), gpointer arg) { FILE *fp = (FILE *) handle->priv; gint ret, i; qso_t q[QSO_FIELDS]; gchar *field; gchar buffer[MAXROWLEN]; gchar band[MAXROWLEN]; gint field_cnt = 0; gint concat; gchar *p, *qfield; gint header = 1; while (!feof (fp)) { if (!fgets (buffer, MAXROWLEN - 1, fp)) break; /* skip header */ if (header) { if (!memcmp(buffer, "PBand=", 6)) { /* strcpy and strip CR LF */ for (p = buffer+6, i=0; p[i] != '\0' && p[i] != 10 && p[i] != 13; i++) band[i] = p[i]; band[i] = '\0'; } if (!memcmp(buffer, "[QSORecords;", 12)) header = 0; continue; } memset (q, 0, sizeof (q)); field = buffer; concat = 0; field_cnt = 0; for (p = buffer; *p && field_cnt < edi_field_nr; p++) { if (*p == ';') { /* concat rst with exchange number */ if (!concat && (edi_fields[field_cnt] == RST || edi_fields[field_cnt] == MYRST)) { *p = ' '; concat = 1; continue; } concat = 0; *p = '\0'; if (edi_fields[field_cnt] == DATE) { struct tm timestruct; gchar sdate[16]; timestruct.tm_year = (field[0]-'0')*10 + (field[1]-'0'); timestruct.tm_mon = (field[2]-'0')*10 + (field[3]-'0'); timestruct.tm_mday = (field[4]-'0')*10 + (field[5]-'0'); if (timestruct.tm_year < 70) timestruct.tm_year += 100; timestruct.tm_mon--; strftime (sdate, 16, "%d %b %Y", ×truct); qfield = g_strdup (sdate); } else if (edi_fields[field_cnt] == MODE) { gchar *mode; gint mode_id; sscanf (field, "%i", &mode_id); switch(mode_id) { case 1: mode = "SSB"; break; case 2: mode = "CW"; break; case 5: mode = "AM"; break; case 6: mode = "FM"; break; case 7: mode = "RTTY"; break; case 8: mode = "SSTV"; break; case 9: mode = "ATV"; break; default: mode = "other"; } qfield = g_strdup (mode); } else if (edi_fields[field_cnt] == MYRST) { qfield = g_strdup (field); /* eat up the next field */ while (*++p != ';') if (!*p) break; } else qfield = g_strdup (field); q[edi_fields[field_cnt]] = qfield; field = p + 1; field_cnt++; } } q[BAND] = g_strdup (band); /* fill in empty fields */ for (i = 0; i < edi_field_nr; i++) { if (!q[edi_fields[i]]) q[edi_fields[i]] = g_strdup (""); } ret = (*fn) (handle, q, arg); if (ret) return ret; } return 0; }