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 * 2017 Ervin Hegedus <airween@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 /* ------------------------------------------------------------
22 * cabrillo utils file
23 *
24 *--------------------------------------------------------------*/
25
26
27 #ifndef _GNU_SOURCE
28 #define _GNU_SOURCE
29 #endif
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include "cabrillo_utils.h"
36
37
38 /* conversion table between tag name in format file and internal tag */
39 struct tag_conv tag_tbl[] = {
40 { "FREQ", FREQ },
41 { "MODE", MODE },
42 { "DATE", DATE },
43 { "TIME", TIME },
44 { "MYCALL", MYCALL },
45 { "HISCALL", HISCALL },
46 { "RST_S", RST_S },
47 { "RST_R", RST_R },
48 { "EXC_S", EXC_S },
49 { "EXCH", EXCH },
50 { "EXC1", EXC1 },
51 { "EXC2", EXC2 },
52 { "EXC3", EXC3 },
53 { "EXC4", EXC4 },
54 { "TX", TX },
55 { "QTCRCALL", QTCRCALL },
56 { "QTCHEAD", QTCHEAD },
57 { "QTCSCALL", QTCSCALL },
58 { "QTC", QTC }
59 };
60
61
62 /* translate item name into a tag */
translate_item_name(char * name)63 enum tag_t translate_item_name(char *name) {
64 int i;
65
66 /* lookup name in tag list */
67 for (i = 0; i < sizeof(tag_tbl) / sizeof(struct tag_conv); i++) {
68 if (strcmp(tag_tbl[i].item_name, name) == 0) {
69 /* and return corresponding tab */
70 return tag_tbl[i].tag;
71 }
72 }
73
74 /* if not found return NO_ITEM tag */
75 return NO_ITEM;
76 }
77
78 /** free cabrillo format description */
free_cabfmt(struct cabrillo_desc * desc)79 void free_cabfmt(struct cabrillo_desc *desc) {
80 int i;
81
82 if (desc == NULL)
83 return;
84
85 if (desc->item_array) {
86 for (i = 0; i < desc->item_array->len; i++) {
87 g_free(g_ptr_array_index(desc->item_array, i));
88 }
89
90 g_ptr_array_free(desc->item_array, TRUE);
91 }
92
93 if (desc->qtc_item_array) {
94 for (i = 0; i < desc->qtc_item_array->len; i++) {
95 g_free(g_ptr_array_index(desc->qtc_item_array, i));
96 }
97
98 g_ptr_array_free(desc->qtc_item_array, TRUE);
99 }
100
101 if (desc->name) g_free(desc->name);
102 g_free(desc);
103 }
104
105
106 /* parse item describing one entry
107 *
108 * has to be in following format: item,length
109 * - item to print (date, time, call, ...)
110 * - max length
111 */
parse_line_entry(char * line_entry)112 struct line_item *parse_line_entry(char *line_entry) {
113 struct line_item *item;
114 gchar **parts;
115 enum tag_t tag;
116
117 item = g_malloc(sizeof(struct line_item));
118 parts = g_strsplit(line_entry, ",", 2);
119
120 if (g_strv_length(parts) == 2) {
121 tag = translate_item_name(parts[0]);
122
123 item->tag = tag;
124 item->len = atoi(parts[1]);
125 } else {
126 /* type is NO_ITEM */
127 item->tag = NO_ITEM;
128 }
129
130 g_strfreev(parts);
131
132 return item;
133 }
134
135 /** read cabrillo format description
136 *
137 * Try to read cabrillo format description for given format from
138 * file and return a describing structure.
139 *
140 * \param filename File to read description from
141 * \param format Name of the format to read
142 * \return Pointer to a structure describing the format
143 * (NULL if file or format not found or not readable)
144 */
read_cabrillo_format(char * filename,char * format)145 struct cabrillo_desc *read_cabrillo_format(char *filename, char *format) {
146 GKeyFile *keyfile;
147 GError *error = NULL;
148 gchar **list;
149 gsize nrstrings;
150 struct cabrillo_desc *cabdesc;
151 int i;
152
153 keyfile = g_key_file_new();
154
155 if (!g_key_file_load_from_file(keyfile, filename,
156 G_KEY_FILE_NONE, &error)) {
157 g_error_free(error);
158
159 /* file does not exist or is wrongly formatted */
160 g_key_file_free(keyfile);
161 return NULL;
162 }
163
164 /* check if 'format' defined in file */
165 if (g_key_file_has_group(keyfile, format) == FALSE) {
166
167 /* group not found */
168 g_key_file_free(keyfile);
169 return NULL;
170 }
171
172 /* read needed keys */
173 list = g_key_file_get_string_list(keyfile, format,
174 "QSO", &nrstrings, &error);
175
176 if (error && error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
177
178 /* if not found -> stop processing as that key is mandatory */
179 g_error_free(error);
180 g_key_file_free(keyfile);
181 return NULL;
182 }
183
184 /* construct new format descriptor and fill it in */
185 cabdesc = g_new(struct cabrillo_desc, 1);
186 cabdesc->name = g_strdup(format);
187 cabdesc->item_array = g_ptr_array_new();
188 cabdesc->item_count = nrstrings;
189 cabdesc->qtc_item_array = NULL;
190 cabdesc->qtc_item_count = 0;
191
192 for (i = 0; i < nrstrings; i++) {
193 struct line_item *item;
194
195 item = parse_line_entry(list[i]);
196 if (item) {
197 /* add only well formatted entries */
198 g_ptr_array_add(cabdesc->item_array, item);
199 }
200 }
201
202 if (cabdesc->item_array->len != nrstrings) {
203 /* not all entries are ok -> stop processing */
204 free_cabfmt(cabdesc);
205 g_strfreev(list);
206 g_key_file_free(keyfile);
207 return NULL;
208 }
209
210 g_strfreev(list);
211
212 /* read needed QTC keys */
213 list = g_key_file_get_string_list(keyfile, format,
214 "QTC", &nrstrings, &error);
215
216 if (error && error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
217
218 /* if not found -> stop processing as that key is optional */
219 g_error_free(error);
220
221 } else {
222
223 /* construct new format descriptor and fill it in */
224 cabdesc->qtc_item_array = g_ptr_array_new();
225 cabdesc->qtc_item_count = nrstrings;
226
227 for (i = 0; i < nrstrings; i++) {
228 struct line_item *item;
229
230 item = parse_line_entry(list[i]);
231 if (item) {
232 /* add only well formatted entries */
233 g_ptr_array_add(cabdesc->qtc_item_array, item);
234 }
235 }
236
237 if (cabdesc->qtc_item_array->len != nrstrings) {
238 /* not all entries are ok -> stop processing */
239 free_cabfmt(cabdesc);
240 g_strfreev(list);
241 g_key_file_free(keyfile);
242 return NULL;
243 }
244 }
245
246 g_strfreev(list);
247
248 /* possible further entries in format specification may contain information
249 * about allowed items for different categories:
250 * CONTEST, CATEGORY-OPERATOR, CATEGORY_TRANSMITTER, CATEGORY-POWER,
251 * CATEGORY-ASSISTED, CATEGORY-BAND, CATEGORY-MODE, C-STATION, C-TIME.
252 * C-OVERLAY
253 */
254
255 g_key_file_free(keyfile);
256
257 /* return parsed cabrillo format description */
258 return cabdesc;
259 }
260