1 /*
2 	PocketFMS waypoint text files (wpt).
3 
4 	Copyright (C) 2009 Tobias Kretschmar, tobias.kretschmar@gmx.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 
21 #include "defs.h"
22 #include "csv_util.h"
23 #include <cstdio>
24 #include <cstdlib>
25 
26 #define MYNAME "PocketFMS waypoint text file format"
27 
28 static gbfile* file_in, *file_out;
29 
30 static void
rd_init(const QString & fname)31 rd_init(const QString& fname)
32 {
33   file_in = gbfopen_le(fname, "r", MYNAME);
34 }
35 
wppos_to_dec(char * value)36 static double wppos_to_dec(char* value)
37 {
38   if (strstr(value, "\xB0") == nullptr) {
39     return atof(value);
40   } else {
41     int degrees, minutes;
42     float seconds;
43     int sign = 1;
44 
45     if (toupper(value[0]) == 'N' || toupper(value[0]) == 'E' || value[0] == '+') {
46       value = &value[1];
47     } else if (toupper(value[0]) == 'S' || toupper(value[0]) == 'W' || value[0] == '-') {
48       value = &value[1];
49       sign = -1;
50     }
51 
52     sscanf(value, "%d\xB0%d'%f\"", &degrees, &minutes, &seconds);
53     return sign * (degrees + ((float)minutes / 60) + (seconds / 3600));
54   }
55 }
56 
57 static void
data_read()58 data_read()
59 {
60   char* buff;
61   int linecount = 0;
62   while ((buff = gbfgetstr(file_in))) {
63     rtrim(buff);
64     if (strlen(buff) == 0) {
65       break;
66     }
67     linecount++;
68     auto* wpt = new Waypoint;
69     char* s = buff;
70     s = csv_lineparse(s, "\\w", "", linecount);
71     if (!s) {
72       fatal(MYNAME "Invalid name");
73     }
74     wpt->shortname = s;
75     s = csv_lineparse(nullptr, "\\w", "", linecount);
76     if (!s) {
77       fatal(MYNAME "Invalid latitude %s", qPrintable(wpt->shortname));
78     }
79     wpt->latitude = wppos_to_dec(s);
80 
81     s = csv_lineparse(nullptr, "\\w", "", linecount);
82     if (!s) {
83       fatal(MYNAME "Invalid longitude %s", qPrintable(wpt->shortname));
84     }
85     wpt->longitude = wppos_to_dec(s);
86     waypt_add(wpt);
87 
88     // continue reading until csv_lineparse returns null indicating all dynamic memory has been deallocated.
89     while (csv_lineparse(nullptr, "\\w", "", linecount));
90   }
91 }
92 
93 static void
rd_deinit()94 rd_deinit()
95 {
96   gbfclose(file_in);
97 }
98 
99 static void
wr_init(const QString & fname)100 wr_init(const QString& fname)
101 {
102   file_out = gbfopen_le(fname, "w", MYNAME);
103 }
104 
105 static void
enigma_waypt_disp(const Waypoint * wpt)106 enigma_waypt_disp(const Waypoint* wpt)
107 {
108   if (!wpt->shortname.isEmpty()) {
109     // The output might have a space or control character.
110     int l = wpt->shortname.length();
111     char *t = (char*) xmalloc(l + 1);
112     char* d = t;
113     for (int i = 0; i < l; i++) {
114       char s = wpt->shortname[i].cell();
115       if (isgraph(s)) {
116         *d++ = s;
117       }
118     }
119     *d = 0;
120     gbfprintf(file_out, "%s %f %f\n", t, wpt->latitude, wpt->longitude);
121     xfree(t);
122   } else {
123     gbfprintf(file_out, "%s %f %f\n", "NONAME", wpt->latitude, wpt->longitude);
124   }
125 }
126 
127 static void
data_write()128 data_write()
129 {
130   waypt_disp_all(enigma_waypt_disp);
131 }
132 
133 static void
wr_deinit()134 wr_deinit()
135 {
136   gbfclose(file_out);
137 }
138 
139 ff_vecs_t pocketfms_wp_vecs = {
140   ff_type_file,
141   {
142     (ff_cap)(ff_cap_read | ff_cap_write),  	/* waypoints */
143     ff_cap_none,                    /* tracks */
144     ff_cap_none,			/* routes */
145   },
146   rd_init,
147   wr_init,
148   rd_deinit,
149   wr_deinit,
150   data_read,
151   data_write,
152   nullptr,
153   nullptr,
154   CET_CHARSET_ASCII, 0	/* CET-REVIEW */
155   , NULL_POS_OPS,
156   nullptr
157 };
158