55 |
const gint editest_widths[] = { 9, 5, 14, 8, 8, 9, 9, 5 }; |
const gint editest_widths[] = { 9, 5, 14, 8, 8, 9, 9, 5 }; |
56 |
const gint editest_field_nr = 7; |
const gint editest_field_nr = 7; |
57 |
|
|
58 |
static gint editest_open(LOGDB*); |
static gint editest_open (LOGDB *); |
59 |
static void editest_close(LOGDB*); |
static void editest_close (LOGDB *); |
60 |
static gint editest_create(LOGDB*); |
static gint editest_create (LOGDB *); |
61 |
static gint editest_qso_append(LOGDB*, const qso_t*); |
static gint editest_qso_append (LOGDB *, const qso_t *); |
62 |
static gint editest_qso_foreach(LOGDB*, gint (*fn)(LOGDB*, qso_t*, gpointer arg), gpointer arg); |
static gint editest_qso_foreach (LOGDB *, |
63 |
|
gint (*fn) (LOGDB *, qso_t *, gpointer arg), |
64 |
|
gpointer arg); |
65 |
|
|
66 |
const struct log_ops editest_ops = { |
const struct log_ops editest_ops = { |
67 |
open: editest_open, |
open:editest_open, |
68 |
close: editest_close, |
close:editest_close, |
69 |
create: editest_create, |
create:editest_create, |
70 |
qso_append: editest_qso_append, |
qso_append:editest_qso_append, |
71 |
qso_foreach: editest_qso_foreach, |
qso_foreach:editest_qso_foreach, |
72 |
type: TYPE_EDITEST, |
type:TYPE_EDITEST, |
73 |
name: "Editest", |
name:"Editest", |
74 |
extension: ".exp", |
extension:".exp", |
75 |
}; |
}; |
76 |
|
|
77 |
/* |
/* |
78 |
* open for read |
* open for read |
79 |
*/ |
*/ |
80 |
gint editest_open(LOGDB *handle) |
gint |
81 |
|
editest_open (LOGDB * handle) |
82 |
{ |
{ |
83 |
FILE *fp; |
FILE *fp; |
84 |
|
|
85 |
fp = fopen(handle->path, "r"); |
fp = fopen (handle->path, "r"); |
86 |
if (!fp) return -1; |
if (!fp) |
87 |
handle->priv = (gpointer)fp; |
return -1; |
88 |
|
handle->priv = (gpointer) fp; |
89 |
|
|
90 |
|
handle->column_nr = editest_field_nr; |
91 |
|
memcpy (handle->column_fields, editest_fields, sizeof (editest_fields)); |
92 |
|
memcpy (handle->column_widths, editest_widths, sizeof (editest_widths)); |
93 |
|
|
94 |
handle->column_nr = editest_field_nr; |
return 0; |
|
memcpy(handle->column_fields, editest_fields, sizeof(editest_fields)); |
|
|
memcpy(handle->column_widths, editest_widths, sizeof(editest_widths)); |
|
|
|
|
|
return 0; |
|
95 |
} |
} |
96 |
|
|
97 |
/* |
/* |
98 |
* open for write |
* open for write |
99 |
*/ |
*/ |
100 |
gint editest_create(LOGDB *handle) |
gint |
101 |
|
editest_create (LOGDB * handle) |
102 |
{ |
{ |
103 |
FILE *fp; |
FILE *fp; |
104 |
|
|
105 |
fp = fopen(handle->path, "w"); |
fp = fopen (handle->path, "w"); |
106 |
if (!fp) return -1; |
if (!fp) |
107 |
handle->priv = (gpointer)fp; |
return -1; |
108 |
return 0; |
handle->priv = (gpointer) fp; |
109 |
|
return 0; |
110 |
} |
} |
111 |
|
|
112 |
void editest_close(LOGDB *handle) |
void |
113 |
|
editest_close (LOGDB * handle) |
114 |
{ |
{ |
115 |
FILE *fp = (FILE*)handle->priv; |
FILE *fp = (FILE *) handle->priv; |
116 |
fclose(fp); |
fclose (fp); |
117 |
} |
} |
118 |
|
|
119 |
/* |
/* |
120 |
*/ |
*/ |
121 |
gint editest_qso_append(LOGDB *handle, const qso_t *q) |
gint |
122 |
|
editest_qso_append (LOGDB * handle, const qso_t * q) |
123 |
{ |
{ |
124 |
FILE *fp = (FILE *)handle->priv; |
FILE *fp = (FILE *) handle->priv; |
125 |
gchar rst[16], exch[16] = "", my_rst[16], my_exch[16] = ""; |
gchar rst[16], exch[16] = "", my_rst[16], my_exch[16] = ""; |
126 |
gchar date[16], locator[16]; |
gchar date[16], locator[16]; |
127 |
gchar *p; |
gchar *p; |
128 |
gint rst_len; |
gint rst_len; |
129 |
|
|
130 |
/* |
/* |
131 |
* there's no exchange fields in xlog. However, the exchange information |
* there's no exchange fields in xlog. However, the exchange information |
132 |
* may be piggybacked by the rst field. eg. "599 35". |
* may be piggybacked by the rst field. eg. "599 35". |
133 |
*/ |
*/ |
134 |
p = strchr(q[RST], ' '); |
p = strchr (q[RST], ' '); |
135 |
rst_len = p ? p - q[RST] : strlen(q[RST]); |
rst_len = p ? p - q[RST] : strlen (q[RST]); |
136 |
|
|
137 |
strncpy(rst, q[RST], rst_len); |
strncpy (rst, q[RST], rst_len); |
138 |
rst[rst_len] = '\0'; |
rst[rst_len] = '\0'; |
139 |
strncpy(my_rst, q[MYRST], rst_len); |
strncpy (my_rst, q[MYRST], rst_len); |
140 |
my_rst[rst_len] = '\0'; |
my_rst[rst_len] = '\0'; |
141 |
if (strlen(q[RST]) > rst_len) |
if (strlen (q[RST]) > rst_len) |
142 |
strcpy(exch, q[RST]+rst_len); |
strcpy (exch, q[RST] + rst_len); |
143 |
if (strlen(q[MYRST]) > rst_len) |
if (strlen (q[MYRST]) > rst_len) |
144 |
strcpy(my_exch, q[MYRST]+rst_len); |
strcpy (my_exch, q[MYRST] + rst_len); |
145 |
|
|
146 |
//const gint editest_fields[] = { DATE, GMT, CALL, RST, MYRST, LOCATOR, BAND }; |
//const gint editest_fields[] = { DATE, GMT, CALL, RST, MYRST, LOCATOR, BAND }; |
147 |
|
|
148 |
if (strlen(q[DATE]) == 11 && q[DATE][2]==' ' && q[DATE][6]==' ') |
if (strlen (q[DATE]) == 11 && q[DATE][2] == ' ' && q[DATE][6] == ' ') |
149 |
sprintf(date, "%c%c-%02d-%s", q[DATE][0], q[DATE][1], |
sprintf (date, "%c%c-%02d-%s", q[DATE][0], q[DATE][1], |
150 |
scan_month(q[DATE]+3), q[DATE]+9); |
scan_month (q[DATE] + 3), q[DATE] + 9); |
151 |
|
|
152 |
if (q[NR] && (!q[LOCATOR] || strlen(q[LOCATOR]) == 0)) |
if (q[NR] && (!q[LOCATOR] || strlen (q[LOCATOR]) == 0)) |
153 |
sprintf(locator, "%s", q[NR]); |
sprintf (locator, "%s", q[NR]); |
154 |
else |
else |
155 |
strcpy(locator, q[LOCATOR] ? q[LOCATOR] : ""); |
strcpy (locator, q[LOCATOR] ? q[LOCATOR] : ""); |
156 |
|
|
157 |
/* |
/* |
158 |
* .exp CSV-like format |
* .exp CSV-like format |
159 |
* |
* |
160 |
* If there's no locator data, maybe it's a HF log |
* If there's no locator data, maybe it's a HF log |
161 |
* |
* |
162 |
* We're missing the points and zone/km column, |
* We're missing the points and zone/km column, |
163 |
* hence the empty semicolon |
* hence the empty semicolon |
164 |
* |
* |
165 |
* TODO: compute these from location set in the preferences |
* TODO: compute these from location set in the preferences |
166 |
*/ |
*/ |
167 |
|
|
168 |
fprintf(fp, "%s;%s;%s;%s;%s;%s;%s;%s;%s;;\n", |
fprintf (fp, "%s;%s;%s;%s;%s;%s;%s;%s;%s;;\n", |
169 |
date, q[GMT], q[CALL], rst, exch, my_rst, my_exch, |
date, q[GMT], q[CALL], rst, exch, my_rst, my_exch, |
170 |
locator, q[BAND]); |
locator, q[BAND]); |
171 |
|
|
172 |
return 0; |
return 0; |
173 |
} |
} |
174 |
|
|
175 |
#define MAXROWLEN 120 |
#define MAXROWLEN 120 |
176 |
|
|
177 |
gint editest_qso_foreach(LOGDB *handle, gint (*fn)(LOGDB*, qso_t*, gpointer arg), gpointer arg) |
gint |
178 |
|
editest_qso_foreach (LOGDB * handle, |
179 |
|
gint (*fn) (LOGDB *, qso_t *, gpointer arg), |
180 |
|
gpointer arg) |
181 |
{ |
{ |
182 |
FILE *fp = (FILE*)handle->priv; |
FILE *fp = (FILE *) handle->priv; |
183 |
gint ret, i; |
gint ret, i; |
184 |
qso_t q[QSO_FIELDS]; |
qso_t q[QSO_FIELDS]; |
185 |
gchar *field; |
gchar *field; |
186 |
gchar buffer[MAXROWLEN]; |
gchar buffer[MAXROWLEN]; |
187 |
gint field_cnt = 0; |
gint field_cnt = 0; |
188 |
gint concat; |
gint concat; |
189 |
gchar *p, *qfield; |
gchar *p, *qfield; |
190 |
|
|
191 |
while (!feof(fp)) { |
while (!feof (fp)) |
192 |
if (!fgets(buffer, MAXROWLEN-1, fp)) |
{ |
193 |
break; |
if (!fgets (buffer, MAXROWLEN - 1, fp)) |
194 |
|
break; |
195 |
memset(q, 0, sizeof(q)); |
|
196 |
|
memset (q, 0, sizeof (q)); |
197 |
field = buffer; |
|
198 |
concat = 0; |
field = buffer; |
199 |
field_cnt = 0; |
concat = 0; |
200 |
for (p = buffer; *p && field_cnt < editest_field_nr; p++) { |
field_cnt = 0; |
201 |
if (*p == ';') { |
for (p = buffer; *p && field_cnt < editest_field_nr; p++) |
202 |
/* concat rst with exchange number */ |
{ |
203 |
if (!concat && (field_cnt == 3 || field_cnt == 4)) { |
if (*p == ';') |
204 |
*p = ' '; |
{ |
205 |
concat = 1; |
/* concat rst with exchange number */ |
206 |
continue; |
if (!concat && (field_cnt == 3 || field_cnt == 4)) |
207 |
} |
{ |
208 |
concat = 0; |
*p = ' '; |
209 |
*p = '\0'; |
concat = 1; |
210 |
if (editest_fields[field_cnt] == DATE) { |
continue; |
|
struct tm timestruct; |
|
|
gchar sdate[16]; |
|
|
|
|
|
sscanf(field, "%2i-%2i-%2i", |
|
|
×truct.tm_mday, |
|
|
×truct.tm_mon, |
|
|
×truct.tm_year); |
|
|
if (timestruct.tm_year < 70) |
|
|
timestruct.tm_year += 100; |
|
|
timestruct.tm_mon--; |
|
|
strftime (sdate, 16, "%d %b %Y", ×truct); |
|
|
qfield = g_strdup(sdate); |
|
|
} else |
|
|
qfield = g_strdup(field); |
|
|
|
|
|
q[editest_fields[field_cnt]] = qfield; |
|
|
field = p+1; |
|
|
field_cnt++; |
|
|
} |
|
211 |
} |
} |
212 |
|
concat = 0; |
213 |
/* fill in empty fields */ |
*p = '\0'; |
214 |
for (i = 0; i<editest_field_nr; i++) { |
if (editest_fields[field_cnt] == DATE) |
215 |
if (!q[editest_fields[i]]) |
{ |
216 |
q[editest_fields[i]] = g_strdup(""); |
struct tm timestruct; |
217 |
|
gchar sdate[16]; |
218 |
|
|
219 |
|
sscanf (field, "%2i-%2i-%2i", |
220 |
|
×truct.tm_mday, |
221 |
|
×truct.tm_mon, ×truct.tm_year); |
222 |
|
if (timestruct.tm_year < 70) |
223 |
|
timestruct.tm_year += 100; |
224 |
|
timestruct.tm_mon--; |
225 |
|
strftime (sdate, 16, "%d %b %Y", ×truct); |
226 |
|
qfield = g_strdup (sdate); |
227 |
} |
} |
228 |
|
else |
229 |
|
qfield = g_strdup (field); |
230 |
|
|
231 |
ret = (*fn)(handle, q, arg); |
q[editest_fields[field_cnt]] = qfield; |
232 |
if (ret) return ret; |
field = p + 1; |
233 |
|
field_cnt++; |
234 |
|
} |
235 |
} |
} |
|
return 0; |
|
|
} |
|
236 |
|
|
237 |
|
/* fill in empty fields */ |
238 |
|
for (i = 0; i < editest_field_nr; i++) |
239 |
|
{ |
240 |
|
if (!q[editest_fields[i]]) |
241 |
|
q[editest_fields[i]] = g_strdup (""); |
242 |
|
} |
243 |
|
|
244 |
|
ret = (*fn) (handle, q, arg); |
245 |
|
if (ret) |
246 |
|
return ret; |
247 |
|
} |
248 |
|
return 0; |
249 |
|
} |