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\"", °rees, &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