1 /*
2 Copyright (C) 2002-2014 Robert Lipe, robertlipe+source@gpsbabel.org
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 */
19 #ifndef DEFS_H_INCLUDED_
20 #define DEFS_H_INCLUDED_
21
22 #include <algorithm> // for sort, stable_sort
23 #include <cmath> // for M_PI
24 #include <cstdarg> // for va_list
25 #include <cstddef> // for NULL, nullptr_t, size_t
26 #include <cstdint> // for int32_t, uint32_t
27 #include <cstdio> // for NULL, fprintf, FILE, stdout
28 #include <ctime> // for time_t
29 #include <utility> // for move
30
31 #if HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #if HAVE_LIBZ
35 #include <zlib.h> // doesn't really belong here, but is missing elsewhere.
36 #elif !ZLIB_INHIBITED
37 #include "zlib.h" // doesn't really belong here, but is missing elsewhere.
38 #endif
39
40 #include <QtCore/QDebug> // for QDebug
41 #include <QtCore/QList> // for QList, QList<>::const_reverse_iterator, QList<>::reverse_iterator
42 #include <QtCore/QScopedPointer> // for QScopedPointer
43 #include <QtCore/QString> // for QString
44 #include <QtCore/QStringRef> // for QStringRef
45 #include <QtCore/QTextCodec> // for QTextCodec
46 #include <QtCore/QVector> // for QVector
47 #include <QtCore/Qt> // for CaseInsensitive
48 #include <QtCore/QtGlobal> // for foreach
49
50 #include "formspec.h" // for FormatSpecificData
51 #include "inifile.h" // for inifile_t
52 #include "gbfile.h" // doesn't really belong here, but is missing elsewhere.
53 #include "session.h" // for session_t
54 #include "src/core/datetime.h" // for DateTime
55 #include "src/core/optional.h" // for optional
56
57
58 #define CSTR(qstr) ((qstr).toUtf8().constData())
59 #define CSTRc(qstr) ((qstr).toLatin1().constData())
60 #define STRFROMUNICODE(qstr) (global_opts.codec->fromUnicode(qstr).constData())
61 #define STRTOUNICODE(cstr) (global_opts.codec->toUnicode(cstr))
62
63 /*
64 * Amazingly, this constant is not specified in the standard...
65 */
66 #ifndef M_PI
67 # define M_PI 3.14159265358979323846
68 #endif
69
70 /*
71 * The constants marked "exact in decimal notation" may be more accurately
72 * converted to doubles when we don't ask the compiler to do any multiplication.
73 * e.g. kMetersPerMile = 0.0254 * 12.0 * 5280.0; might have a larger error than
74 * kMetersPerMile = 1609.344;
75 * Historically we have had some problematic test cases where this mattered.
76 * It is a better idea to use test cases that aren't so demanding.
77 */
78 constexpr double kMetersPerFoot = 0.3048; /* exact in decimal notation */
79 constexpr double kFeetPerMeter = 1.0 / kMetersPerFoot;
80 constexpr double kMetersPerMile = 1609.344; /* exact in decimal notation */
81 constexpr double kMilesPerMeter = 1.0 / kMetersPerMile;
82 constexpr double kKilometersPerMile = 1.609344; /* exact in decimal notation */
83 constexpr double kMilesPerKilometer = 1.0 / kKilometersPerMile;
84
FEET_TO_METERS(double feetsies)85 constexpr double FEET_TO_METERS(double feetsies) { return (feetsies) * kMetersPerFoot; }
METERS_TO_FEET(double meetsies)86 constexpr double METERS_TO_FEET(double meetsies) { return (meetsies) * kFeetPerMeter; }
87
NMILES_TO_METERS(double a)88 constexpr double NMILES_TO_METERS(double a) { return a * 1852.0;} /* nautical miles */
METERS_TO_NMILES(double a)89 constexpr double METERS_TO_NMILES(double a) { return a / 1852.0;}
90
MILES_TO_METERS(double a)91 constexpr double MILES_TO_METERS(double a) { return (a) * kMetersPerMile;}
METERS_TO_MILES(double a)92 constexpr double METERS_TO_MILES(double a) { return (a) * kMilesPerMeter;}
FATHOMS_TO_METERS(double a)93 constexpr double FATHOMS_TO_METERS(double a) { return (a) * 1.8288;}
94
CELSIUS_TO_FAHRENHEIT(double a)95 constexpr double CELSIUS_TO_FAHRENHEIT(double a) { return (((a) * 1.8) + 32.0);}
FAHRENHEIT_TO_CELSIUS(double a)96 constexpr double FAHRENHEIT_TO_CELSIUS(double a) { return (((a) - 32.0) / 1.8);}
97
98 constexpr long SECONDS_PER_HOUR = 60L * 60;
99 constexpr long SECONDS_PER_DAY = 24L * 60 * 60;
100
101 /* meters/second to kilometers/hour */
MPS_TO_KPH(double a)102 constexpr double MPS_TO_KPH(double a) { return (a)*SECONDS_PER_HOUR/1000.0;}
103
104 /* meters/second to miles/hour */
MPS_TO_MPH(double a)105 constexpr double MPS_TO_MPH(double a) { return METERS_TO_MILES(a) * SECONDS_PER_HOUR;}
106
107 /* meters/second to knots */
MPS_TO_KNOTS(double a)108 constexpr double MPS_TO_KNOTS(double a) { return MPS_TO_KPH((a)/1.852);}
109
110 /* kilometers/hour to meters/second */
KPH_TO_MPS(double a)111 constexpr double KPH_TO_MPS(double a) { return a * 1000.0/SECONDS_PER_HOUR;}
112
113 /* miles/hour to meters/second */
114 #define MPH_TO_MPS(a) (MILES_TO_METERS(a) / SECONDS_PER_HOUR)
115
116 /* knots to meters/second */
KNOTS_TO_MPS(double a)117 constexpr double KNOTS_TO_MPS(double a) {return KPH_TO_MPS(a) * 1.852; }
118
119 #define MILLI_TO_MICRO(t) ((t) * 1000) /* Milliseconds to Microseconds */
120 #define MICRO_TO_MILLI(t) ((t) / 1000) /* Microseconds to Milliseconds*/
121 #define CENTI_TO_MICRO(t) ((t) * 10000) /* Centiseconds to Microseconds */
122 #define MICRO_TO_CENTI(t) ((t) / 10000) /* Centiseconds to Microseconds */
123
124 /*
125 * Snprintf is in SUS (so it's in most UNIX-like substance) and it's in
126 * C99 (albeit with slightly different semantics) but it isn't in C89.
127 * This tweaks allows us to use snprintf on the holdout.
128 */
129 #if __WIN32__
130 # define snprintf _snprintf
131 # define vsnprintf _vsnprintf
132 # ifndef fileno
133 # define fileno _fileno
134 # endif
135 # define strdup _strdup
136 #endif
137
138 /* Turn off numeric conversion warning */
139 #if __WIN32__
140 # if _MSC_VER
141 # pragma warning(disable:4244)
142 # endif
143 #if !defined _CRT_SECURE_NO_DEPRECATE
144 # define _CRT_SECURE_NO_DEPRECATE 1
145 #endif
146 #endif
147
148 /* Pathname separator character */
149 #if __WIN32__
150 # define GB_PATHSEP '\\'
151 #else
152 # define GB_PATHSEP '/'
153 #endif
154
155 /*
156 * Toss in some GNU C-specific voodoo for checking.
157 */
158 #if __GNUC__
159 # define PRINTFLIKE(x,y) __attribute__ ((__format__ (__printf__, (x), (y))))
160 #else
161 # define PRINTFLIKE(x,y)
162 #endif
163
164
165 /*
166 * Common definitions. There should be no protocol or file-specific
167 * data in this file.
168 */
169
170
171 /*
172 * Define globally on which kind of data gpsbabel is working.
173 * Important for "file types" that are essentially a communication
174 * protocol for a receiver, like the Magellan serial data.
175 */
176 enum gpsdata_type {
177 unknown_gpsdata = 0,
178 trkdata = 1,
179 wptdata,
180 rtedata,
181 posndata
182 };
183
184 #define NOTHINGMASK 0U
185 #define WPTDATAMASK 1U
186 #define TRKDATAMASK 2U
187 #define RTEDATAMASK 4U
188 #define POSNDATAMASK 8U
189
190 /* mask objective testing */
191 #define doing_nothing (global_opts.masked_objective == NOTHINGMASK)
192 #define doing_wpts ((global_opts.masked_objective & WPTDATAMASK) == WPTDATAMASK)
193 #define doing_trks ((global_opts.masked_objective & TRKDATAMASK) == TRKDATAMASK)
194 #define doing_rtes ((global_opts.masked_objective & RTEDATAMASK) == RTEDATAMASK)
195 #define doing_posn ((global_opts.masked_objective & POSNDATAMASK) == POSNDATAMASK)
196
197 struct global_options {
198 int synthesize_shortnames;
199 int debug_level;
200 gpsdata_type objective;
201 unsigned int masked_objective;
202 int verbose_status; /* set by GUI wrappers for status */
203 int smart_icons;
204 int smart_names;
205 inifile_t* inifile;
206 QTextCodec* codec;
207 };
208
209 extern global_options global_opts;
210 extern const char gpsbabel_version[];
211 extern time_t gpsbabel_now; /* gpsbabel startup-time; initialized in main.c with time() */
212 extern time_t gpsbabel_time; /* gpsbabel startup-time; initialized in main.c with current_time(), ! ZERO within testo ! */
213
214 enum fix_type {
215 fix_unknown=-1,
216 fix_none=0,
217 fix_2d=1,
218 fix_3d,
219 fix_dgps,
220 fix_pps
221 };
222
223 enum status_type {
224 status_unknown=0,
225 status_true,
226 status_false
227 };
228
229 /*
230 * Extended data if waypoint happens to represent a geocache. This is
231 * totally voluntary data...
232 */
233
234 enum geocache_type {
235 gt_unknown = 0,
236 gt_traditional,
237 gt_multi,
238 gt_virtual,
239 gt_letterbox,
240 gt_event,
241 gt_surprise,
242 gt_webcam,
243 gt_earth,
244 gt_locationless,
245 gt_benchmark, /* Extension to Groundspeak for GSAK */
246 gt_cito,
247 gt_ape,
248 gt_mega,
249 gt_wherigo
250 };
251
252 enum geocache_container {
253 gc_unknown = 0,
254 gc_micro,
255 gc_other,
256 gc_regular,
257 gc_large,
258 gc_virtual,
259 gc_small
260 };
261
262 class utf_string
263 {
264 public:
265 utf_string() = default;
utf_string(bool html,QString str)266 utf_string(bool html, QString str) :
267 is_html{html},
268 utfstring{std::move(str)}
269 {}
270 bool is_html{false};
271 QString utfstring;
272 };
273
274 class geocache_data
275 {
276 public:
geocache_data()277 geocache_data() :
278 id(0),
279 type(gt_unknown),
280 container(gc_unknown),
281 diff(0),
282 terr(0),
283 is_archived(status_unknown),
284 is_available(status_unknown),
285 is_memberonly(status_unknown),
286 has_customcoords(status_unknown),
287 placer_id(0),
288 favorite_points(0)
289 {}
290 long long id; /* The decimal cache number */
291 geocache_type type:5;
292 geocache_container container:4;
293 unsigned int diff:6; /* (multiplied by ten internally) */
294 unsigned int terr:6; /* (likewise) */
295 status_type is_archived:2;
296 status_type is_available:2;
297 status_type is_memberonly:2;
298 status_type has_customcoords:2;
299 gpsbabel::DateTime exported;
300 gpsbabel::DateTime last_found;
301 QString placer; /* Placer name */
302 int placer_id; /* Placer id */
303 QString hint; /* all these UTF8, XML entities removed, May be not HTML. */
304 utf_string desc_short;
305 utf_string desc_long;
306 int favorite_points;
307 QString personal_note;
308 };
309
310 class gb_color
311 {
312 public:
313 int bbggrr{-1}; // 32 bit color: Blue/Green/Red. < 0 == unknown.
314 unsigned char opacity{255}; // 0 == transparent. 255 == opaque.
315 };
316
317 /*
318 * Structures and functions for multiple URLs per waypoint.
319 */
320
321 class UrlLink
322 {
323 public:
324 UrlLink() = default;
UrlLink(QString url)325 UrlLink(QString url) :
326 url_(std::move(url))
327 { }
UrlLink(const char * url)328 UrlLink(const char* url) :
329 url_(url)
330 { }
UrlLink(QString url,QString url_link_text)331 UrlLink(QString url, QString url_link_text) :
332 url_(std::move(url)),
333 url_link_text_(std::move(url_link_text))
334 { }
UrlLink(QString url,QString url_link_text,QString url_link_type)335 UrlLink(QString url, QString url_link_text, QString url_link_type) :
336 url_(std::move(url)),
337 url_link_text_(std::move(url_link_text)),
338 url_link_type_(std::move(url_link_type))
339 { }
340 QString url_;
341 QString url_link_text_;
342 QString url_link_type_;
343 };
344
345 class UrlList : public QList<UrlLink>
346 {
347 public:
AddUrlLink(const UrlLink & l)348 void AddUrlLink(const UrlLink& l)
349 {
350 push_back(l);
351 }
352
HasUrlLink()353 bool HasUrlLink() const
354 {
355 return !isEmpty();
356 }
357
GetUrlLink()358 const UrlLink& GetUrlLink() const
359 {
360 return first();
361 }
362 };
363
364 /*
365 * Misc bitfields inside struct waypoint;
366 */
367 class wp_flags
368 {
369 public:
wp_flags()370 wp_flags() :
371 shortname_is_synthetic(0),
372 fmt_use(0),
373 temperature(0),
374 proximity(0),
375 course(0),
376 speed(0),
377 geoidheight(0),
378 depth(0),
379 is_split(0),
380 new_trkseg(0) {}
381 unsigned int shortname_is_synthetic:1;
382 unsigned int fmt_use:2; /* lightweight "extra data" */
383 /* "flagged fields" */
384 unsigned int temperature:1; /* temperature field is set */
385 unsigned int proximity:1; /* proximity field is set */
386 unsigned int course:1; /* course field is set */
387 unsigned int speed:1; /* speed field is set */
388 unsigned int geoidheight:1; /* geoidheight field is set */
389 unsigned int depth:1; /* depth field is set */
390 /* !ToDo!
391 unsigned int altitude:1; /+ altitude field is set +/
392 ... and others
393 */
394 unsigned int is_split:1; /* the waypoint represents a split */
395 unsigned int new_trkseg:1; /* True if first in new trkseg. */
396
397 };
398
399 // These are dicey as they're collected on read. Subsequent filters may change
400 // things, though it's unlikely to matter in practical terms. Don't use these
401 // if a false positive would be deleterious.
402 #
403 class global_trait
404 {
405 public:
global_trait()406 global_trait() :
407 trait_geocaches(0),
408 trait_heartrate(0),
409 trait_cadence(0),
410 trait_power(0),
411 trait_depth(0),
412 trait_temperature(0) {}
413 unsigned int trait_geocaches:1;
414 unsigned int trait_heartrate:1;
415 unsigned int trait_cadence:1;
416 unsigned int trait_power:1;
417 unsigned int trait_depth:1;
418 unsigned int trait_temperature:1;
419 };
420
421 /*
422 * Bounding box information.
423 */
424 struct bounds {
425 double max_lat;
426 double max_lon;
427 double max_alt; /* unknown_alt => invalid */
428 double min_lat;
429 double min_lon;
430 double min_alt; /* -unknown_alt => invalid */
431 };
432
433 #define WAYPT_SET(wpt,member,val) do { (wpt)->member = (val); wpt->wpt_flags.member = 1; } while (0)
434 #define WAYPT_GET(wpt,member,def) ((wpt->wpt_flags.member) ? (wpt->member) : (def))
435 #define WAYPT_UNSET(wpt,member) wpt->wpt_flags.member = 0
436 #define WAYPT_HAS(wpt,member) (wpt->wpt_flags.member)
437
438 /*
439 * This is a waypoint, as stored in the GPSR. It tries to not
440 * cater to any specific model or protocol. Anything that needs to
441 * be truncated, edited, or otherwise trimmed should be done on the
442 * way to the target.
443 */
444 class Waypoint
445 {
446 private:
447 static geocache_data empty_gc_data;
448
449 public:
450
451 double latitude; /* Degrees */
452 double longitude; /* Degrees */
453 double altitude; /* Meters. */
454 double geoidheight; /* Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. */
455
456 /*
457 * The "thickness" of a waypoint; adds an element of 3D. Can be
458 * used to construct rudimentary polygons for, say, airspace
459 * definitions. The units are meters.
460 */
461 double depth;
462
463 /*
464 * An alarm trigger value that can be considered to be a circle
465 * surrounding a waypoint (or cylinder if depth is also defined).
466 * The units are meters.
467 */
468 double proximity;
469
470 /* shortname is a waypoint name as stored in receiver. It should
471 * strive to be, well, short, and unique. Enforcing length and
472 * character restrictions is the job of the output. A typical
473 * minimum length for shortname is 6 characters for NMEA units,
474 * 8 for Magellan and 10 for Vista. These are only guidelines.
475 */
476 QString shortname;
477 /*
478 * description is typically a human readable description of the
479 * waypoint. It may be used as a comment field in some receivers.
480 * These are probably under 40 bytes, but that's only a guideline.
481 */
482 QString description;
483 /*
484 * notes are relatively long - over 100 characters - prose associated
485 * with the above. Unlike shortname and description, these are never
486 * used to compute anything else and are strictly "passed through".
487 * Few formats support this.
488 */
489 QString notes;
490
491 UrlList urls;
492
493 wp_flags wpt_flags;
494 QString icon_descr;
495
496 gpsbabel::DateTime creation_time;
497
498 /*
499 * route priority is for use by the simplify filter. If we have
500 * some reason to believe that the route point is more important,
501 * we can give it a higher (numerically; 0 is the lowest) priority.
502 * This causes it to be removed last.
503 * This is currently used by the saroute input filter to give named
504 * waypoints (representing turns) a higher priority.
505 * This is also used by the google input filter because they were
506 * nice enough to use exactly the same priority scheme.
507 */
508 int route_priority;
509
510 /* Optional dilution of precision: positional, horizontal, vertical.
511 * 1 <= dop <= 50
512 */
513 float hdop;
514 float vdop;
515 float pdop;
516 float course; /* Optional: degrees true */
517 float speed; /* Optional: meters per second. */
518 fix_type fix; /* Optional: 3d, 2d, etc. */
519 int sat; /* Optional: number of sats used for fix */
520
521 unsigned char heartrate; /* Beats/min. likely to get moved to fs. */
522 unsigned char cadence; /* revolutions per minute */
523 float power; /* watts, as measured by cyclists */
524 float temperature; /* Degrees celsius */
525 float odometer_distance; /* Meters? */
526 geocache_data* gc_data;
527 FormatSpecificDataList fs;
528 const session_t* session; /* pointer to a session struct */
529 void* extra_data; /* Extra data added by, say, a filter. */
530
531 public:
532 Waypoint();
533 ~Waypoint();
534 Waypoint(const Waypoint& other);
535 Waypoint& operator=(const Waypoint& other);
536
537 bool HasUrlLink() const;
538 const UrlLink& GetUrlLink() const;
539 [[deprecated]] const QList<UrlLink> GetUrlLinks() const;
540 void AddUrlLink(const UrlLink& l);
541 QString CreationTimeXML() const;
542 gpsbabel::DateTime GetCreationTime() const;
543 void SetCreationTime(const gpsbabel::DateTime& t);
544 void SetCreationTime(qint64 t, qint64 ms = 0);
545 geocache_data* AllocGCData();
546 int EmptyGCData() const;
547 };
548
549 using waypt_cb = void (*)(const Waypoint*);
550
551 // TODO: Consider using composition instead of private inheritance.
552 class WaypointList : private QList<Waypoint*>
553 {
554 public:
555 void waypt_add(Waypoint* wpt); // a.k.a. append(), push_back()
556 void add_rte_waypt(int waypt_ct, Waypoint* wpt, bool synth, const QString& namepart, int number_digits);
557 // FIXME: Generally it is inefficient to use an element pointer or reference to define the element to be deleted, use iterator instead,
558 // and/or implement pop_back() a.k.a. removeLast(), and/or pop_front() a.k.a. removeFirst().
559 void waypt_del(Waypoint* wpt); // a.k.a. erase()
560 // FIXME: Generally it is inefficient to use an element pointer or reference to define the element to be deleted, use iterator instead,
561 // and/or implement pop_back() a.k.a. removeLast(), and/or pop_front() a.k.a. removeFirst().
562 void del_rte_waypt(Waypoint* wpt);
563 void waypt_compute_bounds(bounds* bounds) const;
564 Waypoint* find_waypt_by_name(const QString& name) const;
565 void flush(); // a.k.a. clear()
566 void copy(WaypointList** dst) const;
567 void restore(WaypointList* src);
568 void swap(WaypointList& other);
569 template <typename Compare>
sort(Compare cmp)570 void sort(Compare cmp) {std::stable_sort(begin(), end(), cmp);}
571 template <typename T>
572 void waypt_disp_session(const session_t* se, T cb);
573
574 // Expose limited methods for portability.
575 // public types
576 using QList<Waypoint*>::const_iterator;
577 using QList<Waypoint*>::const_reverse_iterator;
578 using QList<Waypoint*>::iterator;
579 using QList<Waypoint*>::reverse_iterator;
580 // public functions
581 using QList<Waypoint*>::back; // a.k.a. last()
582 using QList<Waypoint*>::begin;
583 using QList<Waypoint*>::cbegin;
584 using QList<Waypoint*>::cend;
585 using QList<Waypoint*>::count; // a.k.a. size()
586 using QList<Waypoint*>::crbegin;
587 using QList<Waypoint*>::crend;
588 using QList<Waypoint*>::empty; // a.k.a. isEmpty()
589 using QList<Waypoint*>::end;
590 using QList<Waypoint*>::front; // a.k.a. first()
591 using QList<Waypoint*>::rbegin;
592 using QList<Waypoint*>::rend;
593 };
594
595 const global_trait* get_traits();
596 void waypt_init();
597 //void update_common_traits(const Waypoint* wpt);
598 void waypt_add(Waypoint* wpt);
599 void waypt_del(Waypoint* wpt);
600 unsigned int waypt_count();
601 void waypt_status_disp(int total_ct, int myct);
602 //void waypt_disp_all(waypt_cb); /* template */
603 //void waypt_disp_session(const session_t* se, waypt_cb cb); /* template */
604 void waypt_init_bounds(bounds* bounds);
605 int waypt_bounds_valid(bounds* bounds);
606 void waypt_add_to_bounds(bounds* bounds, const Waypoint* waypointp);
607 void waypt_compute_bounds(bounds* bounds);
608 Waypoint* find_waypt_by_name(const QString& name);
609 void waypt_flush_all();
610 void waypt_deinit();
611 void waypt_append(WaypointList* src);
612 void waypt_backup(WaypointList** head_bak);
613 void waypt_restore(WaypointList* head_bak);
614 void waypt_swap(WaypointList& other);
615 template <typename Compare>
waypt_sort(Compare cmp)616 void waypt_sort(Compare cmp)
617 {
618 extern WaypointList* global_waypoint_list;
619
620 global_waypoint_list->sort(cmp);
621 }
622 void waypt_add_url(Waypoint* wpt, const QString& link,
623 const QString& url_link_text);
624 void waypt_add_url(Waypoint* wpt, const QString& link,
625 const QString& url_link_text,
626 const QString& url_link_type);
627 double gcgeodist(double lat1, double lon1, double lat2, double lon2);
628 double waypt_time(const Waypoint* wpt);
629 double waypt_distance_ex(const Waypoint* A, const Waypoint* B);
630 double waypt_distance(const Waypoint* A, const Waypoint* B);
631 double waypt_speed_ex(const Waypoint* A, const Waypoint* B);
632 double waypt_speed(const Waypoint* A, const Waypoint* B);
633 double waypt_vertical_speed(const Waypoint* A, const Waypoint* B);
634 double waypt_gradient(const Waypoint* A, const Waypoint* B);
635 double waypt_course(const Waypoint* A, const Waypoint* B);
636
637 template <typename T>
638 void
waypt_disp_session(const session_t * se,T cb)639 WaypointList::waypt_disp_session(const session_t* se, T cb)
640 {
641 int i = 0;
642 foreach (Waypoint* waypointp, *this) {
643 if ((se == nullptr) || (waypointp->session == se)) {
644 if (global_opts.verbose_status) {
645 i++;
646 waypt_status_disp(waypt_count(), i);
647 }
648 cb(waypointp);
649 }
650 }
651 if (global_opts.verbose_status) {
652 fprintf(stdout, "\r\n");
653 }
654 }
655
656 template <typename T>
657 void
waypt_disp_session(const session_t * se,T cb)658 waypt_disp_session(const session_t* se, T cb)
659 {
660 extern WaypointList* global_waypoint_list;
661
662 global_waypoint_list->waypt_disp_session(se, cb);
663 }
664
665 template <typename T>
666 void
waypt_disp_all(T cb)667 waypt_disp_all(T cb)
668 {
669 extern WaypointList* global_waypoint_list;
670
671 global_waypoint_list->waypt_disp_session(nullptr, cb);
672 }
673
674 /*
675 * Structure of recomputed track/route data.
676 */
677 struct computed_trkdata {
678 double distance_meters{0.0};
679 gpsbabel_optional::optional<double> max_alt; /* Meters */
680 gpsbabel_optional::optional<double> min_alt; /* Meters */
681 gpsbabel_optional::optional<double> max_spd; /* Meters/sec */
682 gpsbabel_optional::optional<double> min_spd; /* Meters/sec */
683 gpsbabel_optional::optional<double> avg_hrt; /* Avg Heartrate */
684 gpsbabel_optional::optional<double> avg_cad; /* Avg Cadence */
685 gpsbabel::DateTime start; /* Min time */
686 gpsbabel::DateTime end; /* Max time */
687 gpsbabel_optional::optional<int> min_hrt; /* Min Heartrate */
688 gpsbabel_optional::optional<int> max_hrt; /* Max Heartrate */
689 gpsbabel_optional::optional<int> max_cad; /* Max Cadence */
690 };
691
692 class route_head
693 {
694 public:
695 WaypointList waypoint_list; /* List of child waypoints */
696 QString rte_name;
697 QString rte_desc;
698 UrlList rte_urls;
699 int rte_num;
700 int rte_waypt_ct; /* # waypoints in waypoint list */
701 FormatSpecificDataList fs;
702 gb_color line_color; /* Optional line color for rendering */
703 int line_width; /* in pixels (sigh). < 0 is unknown. */
704 const session_t* session; /* pointer to a session struct */
705
706 public:
707 route_head();
708 // the default copy constructor and assignment operator are not appropriate as we do deep copy of some members,
709 // and we haven't bothered to write an appropriate one.
710 // Catch attempts to use the default copy constructor and assignment operator.
711 route_head(const route_head& other) = delete;
712 route_head& operator=(const route_head& rhs) = delete;
713 ~route_head();
714 };
715
716 using route_hdr = void (*)(const route_head*);
717 using route_trl = void (*)(const route_head*);
718
719 // TODO: Consider using composition instead of private inheritance.
720 class RouteList : private QList<route_head*>
721 {
722 public:
723 int waypt_count() const;
724 void add_head(route_head* rte); // a.k.a. append(), push_back()
725 // FIXME: Generally it is inefficient to use an element pointer or reference to define the element to be deleted, use iterator instead,
726 // and/or implement pop_back() a.k.a. removeLast(), and/or pop_front() a.k.a. removeFirst().
727 void del_head(route_head* rte); // a.k.a. erase()
728 // FIXME: Generally it is inefficient to use an element pointer or reference to define the insertion point, use iterator instead.
729 void insert_head(route_head* rte, route_head* predecessor); // a.k.a. insert
730 void add_wpt(route_head* rte, Waypoint* wpt, bool synth, const QString& namepart, int number_digits);
731 // FIXME: Generally it is inefficient to use an element pointer or reference to define the insertion point, use iterator instead.
732 void del_wpt(route_head* rte, Waypoint* wpt);
733 void common_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc);
734 void flush(); // a.k.a. clear()
735 void copy(RouteList** dst) const;
736 void restore(RouteList* src);
737 void swap(RouteList& other);
738 template <typename Compare>
sort(Compare cmp)739 void sort(Compare cmp) {std::sort(begin(), end(), cmp);}
740 template <typename T1, typename T2, typename T3>
741 void disp_all(T1 rh, T2 rt, T3 wc);
742 template <typename T2, typename T3>
743 void disp_all(std::nullptr_t /* rh */, T2 rt, T3 wc);
744 template <typename T1, typename T3>
745 void disp_all(T1 rh, std::nullptr_t /* rt */, T3 wc);
746 template <typename T3>
747 void disp_all(std::nullptr_t /* rh */, std::nullptr_t /* rt */, T3 wc);
748
749 // Only expose methods from our underlying container that won't corrupt our private data.
750 // Our contained element (route_head) also contains a container (waypoint_list),
751 // and we maintain a total count the elements in these contained containers, i.e.
752 // the total number of waypoints in all the routes in the RouteList.
753 // public types
754 using QList<route_head*>::const_iterator;
755 using QList<route_head*>::const_reverse_iterator;
756 using QList<route_head*>::iterator;
757 using QList<route_head*>::reverse_iterator;
758 // public functions
759 using QList<route_head*>::back; // a.k.a. last()
760 using QList<route_head*>::begin;
761 using QList<route_head*>::cbegin;
762 using QList<route_head*>::cend;
763 using QList<route_head*>::count; // a.k.a. size()
764 using QList<route_head*>::crbegin;
765 using QList<route_head*>::crend;
766 using QList<route_head*>::empty; // a.k.a. isEmpty()
767 using QList<route_head*>::end;
768 using QList<route_head*>::front; // a.k.a. first()
769 using QList<route_head*>::rbegin;
770 using QList<route_head*>::rend;
771
772 private:
773 int waypt_ct{0};
774 };
775
776 void route_init();
777 unsigned int route_waypt_count();
778 unsigned int route_count();
779 unsigned int track_waypt_count();
780 unsigned int track_count();
781 route_head* route_head_alloc();
782 void route_add_head(route_head* rte);
783 void route_del_head(route_head* rte);
784 void track_add_head(route_head* rte);
785 void track_del_head(route_head* rte);
786 void track_insert_head(route_head* rte, route_head* predecessor);
787 void route_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart = "RPT", int number_digits = 3);
788 void track_add_wpt(route_head* rte, Waypoint* wpt, const QString& namepart = "RPT", int number_digits = 3);
789 void route_del_wpt(route_head* rte, Waypoint* wpt);
790 void track_del_wpt(route_head* rte, Waypoint* wpt);
791 //void route_disp(const route_head* rte, waypt_cb); /* template */
792 void route_disp(const route_head* rte, std::nullptr_t /* waypt_cb */); /* override to catch nullptr */
793 //void route_disp_all(route_hdr, route_trl, waypt_cb); /* template */
794 //void track_disp_all(route_hdr, route_trl, waypt_cb); /* template */
795 void route_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc);
796 void track_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc);
797 void route_flush_all_routes();
798 void route_flush_all_tracks();
799 void route_deinit();
800 void route_append(RouteList* src);
801 void track_append(RouteList* src);
802 void route_backup(RouteList** head_bak);
803 void route_restore(RouteList* head_bak);
804 void route_swap(RouteList& other);
805 template <typename Compare>
route_sort(Compare cmp)806 void route_sort(Compare cmp)
807 {
808 extern RouteList* global_route_list;
809
810 global_route_list->sort(cmp);
811 }
812 void track_backup(RouteList** head_bak);
813 void track_restore(RouteList* head_bak);
814 void track_swap(RouteList& other);
815 template <typename Compare>
track_sort(Compare cmp)816 void track_sort(Compare cmp)
817 {
818 extern RouteList* global_track_list;
819
820 global_track_list->sort(cmp);
821 }
822 computed_trkdata track_recompute(const route_head* trk);
823
824 template <typename T>
825 void
route_disp(const route_head * rh,T cb)826 route_disp(const route_head* rh, T cb)
827 {
828 // cb != nullptr, caught with an overload of route_disp
829 foreach (const Waypoint* waypointp, rh->waypoint_list) {
830 cb(waypointp);
831 }
832 }
833
834 template <typename T1, typename T2, typename T3>
835 void
disp_all(T1 rh,T2 rt,T3 wc)836 RouteList::disp_all(T1 rh, T2 rt, T3 wc)
837 {
838 foreach (const route_head* rhp, *this) {
839 // rh != nullptr, caught with an overload of common_disp_all
840 rh(rhp);
841 route_disp(rhp, wc);
842 // rt != nullptr, caught with an overload of common_disp_all
843 rt(rhp);
844 }
845 }
846
847 template <typename T2, typename T3>
848 void
disp_all(std::nullptr_t,T2 rt,T3 wc)849 RouteList::disp_all(std::nullptr_t /* rh */, T2 rt, T3 wc)
850 {
851 foreach (const route_head* rhp, *this) {
852 // rh == nullptr
853 route_disp(rhp, wc);
854 // rt != nullptr, caught with an overload of common_disp_all
855 rt(rhp);
856 }
857 }
858
859 template <typename T1, typename T3>
860 void
disp_all(T1 rh,std::nullptr_t,T3 wc)861 RouteList::disp_all(T1 rh, std::nullptr_t /* rt */, T3 wc)
862 {
863 foreach (const route_head* rhp, *this) {
864 // rh != nullptr, caught with an overload of common_disp_all
865 rh(rhp);
866 route_disp(rhp, wc);
867 // rt == nullptr
868 }
869 }
870
871 template <typename T3>
872 void
disp_all(std::nullptr_t,std::nullptr_t,T3 wc)873 RouteList::disp_all(std::nullptr_t /* rh */, std::nullptr_t /* rt */, T3 wc)
874 {
875 foreach (const route_head* rhp, *this) {
876 // rh == nullptr
877 route_disp(rhp, wc);
878 // rt == nullptr
879 }
880 }
881
882 template <typename T1, typename T2, typename T3>
883 void
route_disp_all(T1 rh,T2 rt,T3 wc)884 route_disp_all(T1 rh, T2 rt, T3 wc)
885 {
886 extern RouteList* global_route_list;
887
888 global_route_list->disp_all(rh, rt, wc);
889 }
890
891 template <typename T1, typename T2, typename T3>
892 void
track_disp_all(T1 rh,T2 rt,T3 wc)893 track_disp_all(T1 rh, T2 rt, T3 wc)
894 {
895 extern RouteList* global_track_list;
896
897 global_track_list->disp_all(rh, rt, wc);
898 }
899
900 struct posn_status {
901 volatile int request_terminate;
902 };
903
904 extern posn_status tracking_status;
905
906 using ff_init = void (*)(const QString&);
907 using ff_deinit = void (*)();
908 using ff_read = void (*)();
909 using ff_write = void (*)();
910 using ff_exit = void (*)();
911 using ff_writeposn = void (*)(Waypoint*);
912 using ff_readposn = Waypoint* (*)(posn_status*);
913
914 geocache_type gs_mktype(const QString& t);
915 geocache_container gs_mkcont(const QString& t);
916
917 /*
918 * All shortname functions take a shortname handle as the first arg.
919 * This is an opaque pointer. Callers must not fondle the contents of it.
920 */
921 // This is a crutch until the new C++ shorthandle goes in.
922
923 struct mkshort_handle_imp; // forward declare, definition in mkshort.cc
924 using short_handle = mkshort_handle_imp*;
925
926 char* mkshort(short_handle, const char*, bool);
927 QString mkshort(short_handle, const QString&);
928 short_handle mkshort_new_handle();
929 QString mkshort_from_wpt(short_handle h, const Waypoint* wpt);
930 void mkshort_del_handle(short_handle* h);
931 void setshort_length(short_handle, int n);
932 void setshort_badchars(short_handle, const char*);
933 void setshort_goodchars(short_handle, const char*);
934 void setshort_mustupper(short_handle, int n);
935 void setshort_mustuniq(short_handle, int n);
936 void setshort_whitespace_ok(short_handle, int n);
937 void setshort_repeating_whitespace_ok(short_handle, int n);
938 void setshort_defname(short_handle, const char* s);
939
940 #define ARGTYPE_UNKNOWN 0x00000000U
941 #define ARGTYPE_INT 0x00000001U
942 #define ARGTYPE_FLOAT 0x00000002U
943 #define ARGTYPE_STRING 0x00000003U
944 #define ARGTYPE_BOOL 0x00000004U
945 #define ARGTYPE_FILE 0x00000005U
946 #define ARGTYPE_OUTFILE 0x00000006U
947
948 /* REQUIRED means that the option is required to be set.
949 * See also BEGIN/END_REQ */
950 #define ARGTYPE_REQUIRED 0x40000000U
951
952 /* HIDDEN means that the option does not appear in help texts. Useful
953 * for debugging or testing options */
954 #define ARGTYPE_HIDDEN 0x20000000U
955
956 /* BEGIN/END_EXCL mark the beginning and end of an exclusive range of
957 * options. No more than one of the options in the range may be selected
958 * or set. If exactly one must be set, use with BEGIN/END_REQ
959 * Both of these flags set is just like neither set, so avoid doing that. */
960 #define ARGTYPE_BEGIN_EXCL 0x10000000U
961 #define ARGTYPE_END_EXCL 0x08000000U
962
963 /* BEGIN/END_REQ mark the beginning and end of a required range of
964 * options. One or more of the options in the range MUST be selected or set.
965 * If exactly one must be set, use with BEGIN/END_EXCL
966 * Both of these flags set is synonymous with REQUIRED, so use that instead
967 * for "groups" of exactly one option. */
968 #define ARGTYPE_BEGIN_REQ 0x04000000U
969 #define ARGTYPE_END_REQ 0x02000000U
970
971 #define ARGTYPE_TYPEMASK 0x00000fffU
972 #define ARGTYPE_FLAGMASK 0xfffff000U
973
974 #define ARG_NOMINMAX nullptr, nullptr
975
976 struct arglist_t {
977 /* MSVC 2015 generates C2440, C2664 errors without some help. */
978 #if defined(_MSC_VER) && (_MSC_VER < 1910) /* MSVC 2015 or earlier */
979 arglist_t() = default;
arglist_targlist_t980 arglist_t(const char* astr, char** aval, const char* hstr, const char* dval,
981 const uint32_t atyp, const char* minv, const char* maxv, char* avp) :
982 argstring(astr),
983 argval(aval),
984 helpstring(hstr),
985 defaultvalue(dval),
986 argtype(atyp),
987 minvalue(minv),
988 maxvalue(maxv),
989 argvalptr(avp) {}
990 #endif
991 const char* argstring{nullptr};
992 char** argval{nullptr};
993 const char* helpstring{nullptr};
994 const char* defaultvalue{nullptr};
995 const uint32_t argtype{ARGTYPE_UNKNOWN};
996 const char* minvalue{nullptr}; /* minimum value for numeric options */
997 const char* maxvalue{nullptr}; /* maximum value for numeric options */
998 char* argvalptr{nullptr}; /* !!! internal helper. Not used in definitions !!! */
999 };
1000
1001 enum ff_type {
1002 ff_type_file = 1, /* normal format: useful to a GUI. */
1003 ff_type_internal, /* fmt not useful with default options */
1004 ff_type_serial /* format describes a serial protocol (GUI can display port names) */
1005 };
1006
1007 enum ff_cap_array {
1008 ff_cap_rw_wpt,
1009 ff_cap_rw_trk,
1010 ff_cap_rw_rte
1011 };
1012
1013 enum ff_cap {
1014 ff_cap_none,
1015 ff_cap_read = 1,
1016 ff_cap_write = 2
1017 };
1018
1019 #define FF_CAP_RW_ALL \
1020 { (ff_cap) (ff_cap_read | ff_cap_write), (ff_cap) (ff_cap_read | ff_cap_write), (ff_cap) (ff_cap_read | ff_cap_write) }
1021
1022 #define FF_CAP_RW_WPT \
1023 { (ff_cap) (ff_cap_read | ff_cap_write), ff_cap_none, ff_cap_none}
1024
1025 /*
1026 * Format capabilities for realtime positioning.
1027 */
1028 struct position_ops_t {
1029 ff_init rd_init;
1030 ff_readposn rd_position;
1031 ff_deinit rd_deinit;
1032
1033 ff_init wr_init;
1034 ff_writeposn wr_position;
1035 ff_deinit wr_deinit;
1036 };
1037
1038 #define NULL_POS_OPS { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, }
1039
1040 /*
1041 * Describe the file format to the caller.
1042 */
1043 struct ff_vecs_t {
1044 ff_type type;
1045 QVector<ff_cap> cap;
1046 ff_init rd_init;
1047 ff_init wr_init;
1048 ff_deinit rd_deinit;
1049 ff_deinit wr_deinit;
1050 ff_read read;
1051 ff_write write;
1052 ff_exit exit;
1053 QVector<arglist_t>* args;
1054 QString encode;
1055 int fixed_encode;
1056 position_ops_t position_ops;
1057 void* unused; /* TODO: delete this field */
1058 };
1059
1060 struct style_vecs_t {
1061 const char* name;
1062 const char* style_buf;
1063 };
1064 extern const QVector<style_vecs_t> style_list;
1065
1066 [[noreturn]] void fatal(QDebug& msginstance);
1067 [[noreturn]] void fatal(const char*, ...) PRINTFLIKE(1, 2);
1068 void is_fatal(int condition, const char*, ...) PRINTFLIKE(2, 3);
1069 void warning(const char*, ...) PRINTFLIKE(1, 2);
1070 void debug_print(int level, const char* fmt, ...) PRINTFLIKE(2,3);
1071
1072 void printposn(double c, int is_lat);
1073
1074 void* xcalloc(size_t nmemb, size_t size);
1075 void* xmalloc(size_t size);
1076 void* xrealloc(void* p, size_t s);
1077 void xfree(const void* mem);
1078 char* xstrdup(const QString& s);
1079 char* xstrndup(const char* str, size_t sz);
1080 char* xstrappend(char* src, const char* newd);
1081 char* xstrdup(const char* s);
1082
1083 FILE* xfopen(const char* fname, const char* type, const char* errtxt);
1084
1085 // Thin wrapper around fopen() that supports Unicode fname on all platforms.
1086 FILE* ufopen(const QString& fname, const char* mode);
1087
1088 // OS-abstracting wrapper for getting Unicode environment variables.
1089 QString ugetenv(const char* env_var);
1090
1091 // FIXME: case_ignore_strcmp() and case_ignore_strncmp() should probably
1092 // just be replaced at the call sites. These shims are just here to make
1093 // them more accommodating of QString input.
1094 inline int
case_ignore_strcmp(const QString & s1,const QString & s2)1095 case_ignore_strcmp(const QString& s1, const QString& s2)
1096 {
1097 return QString::compare(s1, s2, Qt::CaseInsensitive);
1098 }
1099 // In 95% of the callers, this could be s1.startsWith(s2)...
case_ignore_strncmp(const QString & s1,const QString & s2,int n)1100 inline int case_ignore_strncmp(const QString& s1, const QString& s2, int n)
1101 {
1102 return s1.leftRef(n).compare(s2.left(n), Qt::CaseInsensitive);
1103 }
1104
1105 int str_match(const char* str, const char* match);
1106
1107 char* strsub(const char* s, const char* search, const char* replace);
1108 char* gstrsub(const char* s, const char* search, const char* replace);
1109
1110 void rtrim(char* s);
1111 char* lrtrim(char* buff);
1112 int xasprintf(char** strp, const char* fmt, ...) PRINTFLIKE(2, 3);
1113 int xasprintf(QString* strp, const char* fmt, ...) PRINTFLIKE(2, 3);
1114 int xasprintf(QScopedPointer<char, QScopedPointerPodDeleter>& strp, const char* fmt, ...) PRINTFLIKE(2, 3);
1115 int xvasprintf(char** strp, const char* fmt, va_list ap);
1116 char* strupper(char* src);
1117 char* strlower(char* src);
1118 signed int get_tz_offset();
1119 time_t mklocaltime(struct tm* t);
1120 time_t mkgmtime(struct tm* t);
1121 bool gpsbabel_testmode();
1122 gpsbabel::DateTime current_time();
1123 void dotnet_time_to_time_t(double dotnet, time_t* t, int* millisecs);
1124 signed int month_lookup(const char* m);
1125 const char* get_cache_icon(const Waypoint* waypointp);
1126 const char* gs_get_cachetype(geocache_type t);
1127 const char* gs_get_container(geocache_container t);
1128 char* xml_entitize(const char* str);
1129 char* html_entitize(const QString& str);
1130 char* strip_html(const utf_string*);
1131 char* strip_nastyhtml(const QString& in);
1132 char* convert_human_date_format(const char* human_datef); /* "MM,YYYY,DD" -> "%m,%Y,%d" */
1133 char* convert_human_time_format(const char* human_timef); /* "HH+mm+ss" -> "%H+%M+%S" */
1134 char* pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html); /* decimal -> dd.dddd or dd mm.mmm or dd mm ss */
1135
1136 const QString get_filename(const QString& fname); /* extract the filename portion */
1137
1138 /*
1139 * Character encoding transformations.
1140 */
1141
1142 #define CET_NOT_CONVERTABLE_DEFAULT '$'
1143 #define CET_CHARSET_ASCII "US-ASCII"
1144 #define CET_CHARSET_UTF8 "UTF-8"
1145 #define CET_CHARSET_HEBREW "ISO-8859-8"
1146 #define CET_CHARSET_MS_ANSI "windows-1252"
1147 #define CET_CHARSET_LATIN1 "ISO-8859-1"
1148
1149 /* this lives in gpx.c */
1150 gpsbabel::DateTime xml_parse_time(const QString& dateTimeString);
1151
1152 QString rot13(const QString& s);
1153
1154 /*
1155 * PalmOS records like fixed-point numbers, which should be rounded
1156 * to deal with possible floating-point representation errors.
1157 */
1158
1159 signed int si_round(double d);
1160
1161 /*
1162 * Prototypes for Endianness helpers.
1163 */
1164
1165 signed int be_read16(const void* ptr);
1166 unsigned int be_readu16(const void* ptr);
1167 signed int be_read32(const void* ptr);
1168 signed int le_read16(const void* ptr);
1169 unsigned int le_readu16(const void* ptr);
1170 signed int le_read32(const void* ptr);
1171 unsigned int le_readu32(const void* ptr);
1172 void le_read64(void* dest, const void* src);
1173 void be_write16(void* ptr, unsigned value);
1174 void be_write32(void* ptr, unsigned value);
1175 void le_write16(void* ptr, unsigned value);
1176 void le_write32(void* ptr, unsigned value);
1177
1178 double endian_read_double(const void* ptr, int read_le);
1179 float endian_read_float(const void* ptr, int read_le);
1180 void endian_write_double(void* ptr, double value, int write_le);
1181 void endian_write_float(void* ptr, float value, int write_le);
1182
1183 float be_read_float(void* ptr);
1184 double be_read_double(void* ptr);
1185 void be_write_float(void* ptr, float value);
1186 void be_write_double(void* ptr, double value);
1187
1188 float le_read_float(const void* ptr);
1189 double le_read_double(const void* ptr);
1190 void le_write_float(void* ptr, float value);
1191 void le_write_double(void* ptr, double value);
1192
1193 /*
1194 * Prototypes for generic conversion routines (util.c).
1195 */
1196
1197 double ddmm2degrees(double pcx_val);
1198 double degrees2ddmm(double deg_val);
1199
1200 enum grid_type {
1201 grid_unknown = -1,
1202 grid_lat_lon_ddd = 0,
1203 grid_lat_lon_dmm = 1,
1204 grid_lat_lon_dms = 2,
1205 grid_bng = 3,
1206 grid_utm = 4,
1207 grid_swiss = 5
1208 };
1209
1210 #define GRID_INDEX_MIN grid_lat_lon_ddd
1211 #define GRID_INDEX_MAX grid_swiss
1212
1213 #define DATUM_OSGB36 86
1214 #define DATUM_WGS84 118
1215
1216 /* bit manipulation functions (util.c) */
1217
1218 char gb_getbit(const void* buf, uint32_t nr);
1219 void gb_setbit(void* buf, uint32_t nr);
1220
1221 void* gb_int2ptr(int i);
1222 int gb_ptr2int(const void* p);
1223
1224 void list_codecs();
1225 void list_timezones();
1226
1227 /*
1228 * From parse.c
1229 */
1230 int parse_coordinates(const char* str, int datum, grid_type grid,
1231 double* latitude, double* longitude, const char* module);
1232 int parse_coordinates(const QString& str, int datum, grid_type grid,
1233 double* latitude, double* longitude, const char* module);
1234 int parse_distance(const char* str, double* val, double scale, const char* module);
1235 int parse_distance(const QString& str, double* val, double scale, const char* module);
1236 int parse_speed(const char* str, double* val, double scale, const char* module);
1237 int parse_speed(const QString& str, double* val, double scale, const char* module);
1238
1239 /*
1240 * From util_crc.c
1241 */
1242 unsigned long get_crc32(const void* data, int datalen);
1243
1244 /*
1245 * From nmea.c
1246 */
1247 int nmea_cksum(const char* buf);
1248
1249 /*
1250 * Color helpers.
1251 */
1252 int color_to_bbggrr(const char* cname);
1253
1254 /*
1255 * A constant for unknown altitude. It's tempting to just use zero
1256 * but that's not very nice for the folks near sea level.
1257 */
1258 #define unknown_alt -99999999.0
1259 #define unknown_color -1
1260
1261 // TODO: this is a (probably temporary) shim for the C->QString conversion.
1262 // It's here instead of gps to avoid C/C++ linkage issues.
1263 int32_t GPS_Lookup_Datum_Index(const QString& n);
1264
1265 #endif // DEFS_H_INCLUDED_
1266