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