1 /*
2  * Tlf - contest logging program for amateur radio operators
3  * Copyright (C) 2011, 2013 Thomas Beierlein <tb@forth-ev.de>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #include <glib.h>
26 #include <math.h>
27 
28 #include "dxcc.h"
29 
30 
31 GPtrArray *dxcc;
32 GPtrArray *prefix;
33 bool have_exact_matches;
34 
35 prefix_data dummy_pfx = {
36     "No Prefix",
37     0,
38     0,
39     0,
40     INFINITY,
41     INFINITY,
42     NULL,
43     INFINITY,
44     false
45 };
46 
47 
prefix_free(gpointer data)48 void prefix_free(gpointer data) {
49     prefix_data *pfx_data = data;
50 
51     g_free(pfx_data -> pfx);
52     g_free(pfx_data -> continent);
53     g_free(pfx_data);
54 }
55 
56 
prefix_init(void)57 void prefix_init(void) {
58     if (prefix) {
59 	g_ptr_array_free(prefix, TRUE);
60     }
61     prefix = g_ptr_array_new_with_free_func(prefix_free);
62 }
63 
64 /* return number of entries in prefix array */
prefix_count(void)65 unsigned int prefix_count(void) {
66     return prefix->len;
67 }
68 
69 /* give pointer to prefix struct at 'index' */
prefix_by_index(unsigned int index)70 prefix_data *prefix_by_index(unsigned int index) {
71     if (index >= prefix_count())
72 	return &dummy_pfx;
73 
74     return (prefix_data *)g_ptr_array_index(prefix, index);
75 }
76 
77 /* add a new prefix description */
prefix_add(char * pfxstr)78 void prefix_add(char *pfxstr) {
79     gchar *loc;
80     gint last_index = dxcc_count() - 1;
81     dxcc_data *last_dx = dxcc_by_index(last_index);
82     prefix_data *new_prefix = g_new(prefix_data, 1);
83 
84     if (*pfxstr == '=') {
85 	new_prefix -> exact = true;
86 	have_exact_matches = true;
87 	pfxstr++;
88     } else
89 	new_prefix -> exact = false;
90 
91     loc = strchr(pfxstr, '~');
92     if (loc != NULL) {
93 	new_prefix -> timezone = atof(loc + 1);
94 	*loc = '\0';
95     }
96     else
97 	new_prefix -> timezone = INFINITY;
98 
99     loc = strchr(pfxstr, '{');
100     if (loc != NULL) {
101 	new_prefix -> continent = g_strdup(loc + 1);
102 	*loc = '\0';
103 	loc = strchr(new_prefix -> continent, '}');
104 	if (loc != NULL)
105 	    *loc = '\0';
106     }
107     else
108 	new_prefix -> continent = NULL;
109 
110     loc = strchr(pfxstr, '<');
111     if (loc != NULL) {
112 	new_prefix -> lat = atof(loc + 1);
113 	*loc = '\0';
114 	if ((loc = strchr(loc, '/')) != NULL)
115 	    new_prefix -> lon = atof(loc + 1);
116 	else
117 	    new_prefix -> lon = INFINITY;
118     }
119     else
120 	new_prefix -> lat = new_prefix -> lon = INFINITY;
121 
122     loc = strchr(pfxstr, '[');
123     if (loc != NULL) {
124 	new_prefix -> itu = atoi(loc + 1);
125 	*loc = '\0';
126     } else
127 	new_prefix -> itu = last_dx -> itu;
128 
129     loc = strchr(pfxstr, '(');
130     if (loc != NULL) {
131 	new_prefix -> cq = atoi(loc + 1);
132 	*loc = '\0';
133     } else
134 	new_prefix -> cq = last_dx -> cq;
135 
136     new_prefix -> pfx = g_strdup(pfxstr);
137     new_prefix -> dxcc_index = last_index;
138 
139     g_ptr_array_add(prefix, new_prefix);
140 }
141 
142 
143 
dxcc_free(gpointer data)144 void dxcc_free(gpointer data) {
145     dxcc_data *dxcc = data;
146 
147     g_free(dxcc -> countryname);
148     g_free(dxcc -> continent);
149     g_free(dxcc -> pfx);
150     g_free(dxcc);
151 }
152 
dxcc_init(void)153 void dxcc_init(void) {
154     if (dxcc) {
155 	g_ptr_array_free(dxcc, TRUE);
156     }
157     dxcc = g_ptr_array_new_with_free_func(dxcc_free);
158 }
159 
160 /* return number of entries in dxcc array */
dxcc_count(void)161 unsigned int dxcc_count(void) {
162     return dxcc->len;
163 }
164 
165 /* give pointer to dxcc_data struct at 'index' */
dxcc_by_index(unsigned int index)166 dxcc_data *dxcc_by_index(unsigned int index) {
167     if (index >= dxcc_count())
168 	index = 0;
169 
170     return (dxcc_data *)g_ptr_array_index(dxcc, index);
171 }
172 
dxcc_add(char * dxcc_line)173 void dxcc_add(char *dxcc_line) {
174     gchar **split;
175     gint item;
176     dxcc_data *new_dxcc = g_new(dxcc_data, 1);
177 
178     /* split up the line */
179     split = g_strsplit(dxcc_line, ":", 9);
180 
181     if (g_strv_length(split) < 8) {	/* wrong syntax, ignore line */
182 	g_strfreev(split);
183 	g_free(new_dxcc);
184 	return;
185     }
186 
187     for (item = 0; item < 8; item++)
188 	g_strstrip(split[item]);
189 
190     new_dxcc -> countryname = g_strdup(split[0]);
191     new_dxcc -> cq = atoi(split[1]);
192     new_dxcc -> itu = atoi(split[2]);
193     new_dxcc -> continent = g_strdup(split[3]);
194     new_dxcc -> lat = atof(split[4]);
195     new_dxcc -> lon = atof(split[5]);
196     new_dxcc -> timezone = atof(split[6]);
197     if (*split[7] == '*') {
198 	new_dxcc -> pfx = g_strdup(split[7] + 1);
199 	new_dxcc -> starred = true;
200     } else {
201 	new_dxcc -> pfx = g_strdup(split[7]);
202 	new_dxcc -> starred = false;
203     }
204 
205     g_strfreev(split);
206 
207     g_ptr_array_add(dxcc, new_dxcc);
208 }
209 
210 /** load cty database from filename */
load_ctydata(char * filename)211 int load_ctydata(char *filename) {
212     FILE *fd;
213     char buf[181] = "";
214     char *loc;
215 
216     if ((fd = fopen(filename, "r")) == NULL)
217 	return -1;
218 
219     dxcc_init();
220     prefix_init();
221 
222     // set default for empty country
223     dxcc_add("Not Specified        :    --:  --:  --:  -00.00:    00.00:     0.0:     :");
224 
225     while (fgets(buf, sizeof(buf), fd) != NULL) {
226 
227 	g_strchomp(buf); 	/* drop CR and/or NL and */
228 	if (*buf == '\0')	/* ignore empty lines */
229 	    continue;
230 
231 	if (buf[0] != ' ') {	// data line
232 
233 	    dxcc_add(buf);
234 
235 	} else {		// prefix line
236 	    loc = strtok(buf, " ,;");
237 	    while (loc != NULL) {
238 
239 		prefix_add(loc);
240 
241 		loc = strtok(NULL, " ,;");
242 	    }
243 	}
244     }
245     fclose(fd);
246     return 0;
247 }
248 
249 
250