1 /*
2 
3     Implementation of special data used by Garmin products.
4 
5     Copyright (C) 2006 Olaf Klein, o.b.klein@gpsbabel.org
6     Copyright (C) 2006-2014 Robert Lipe, robertlipe@gpsbabel.org
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 
22  */
23 
24 #ifndef GARMIN_FS_H
25 #define GARMIN_FS_H
26 
27 #include <cstddef>                  // for size_t
28 #include <cstdint>                  // for int32_t, int16_t, uint16_t
29 
30 #include <QtCore/QString>           // for QString
31 #include <QtCore/QXmlStreamWriter>  // for QXmlStreamWriter
32 
33 #include "defs.h"
34 #include "formspec.h"               // for FsChainFind, kFsGmsd, FormatSpecificData
35 #include "jeeps/gps.h"
36 
37 
38 /* this order is used by most devices */
39 /* enum garmin_display_t {
40 	garmin_display_symbol_and_name = 0,
41 	garmin_display_symbol_only = 1,
42 	garmin_display_symbol_and_description = 2
43 };
44 */
45 
46 struct garmin_ilink_t {
47   int ref_count;
48   double lat, lon, alt;
49   garmin_ilink_t* next;
50 };
51 
52 struct garmin_fs_flags_t {
53 public:
garmin_fs_flags_tgarmin_fs_flags_t54   garmin_fs_flags_t() :
55   icon(0),
56   wpt_class(0),
57   display(0),
58   category(0),
59   city(0),
60   state(0),
61   facility(0),
62   cc(0),
63   cross_road(0),
64   addr(0),
65   country(0),
66   phone_nr(0),
67   phone_nr2(0),
68   fax_nr(0),
69   postal_code(0),
70   email(0),
71   duration(0)
72 #ifdef GMSD_EXPERIMENTAL
73   , subclass(0)
74 #endif
75   {}
76 
77   unsigned int icon:1;
78   unsigned int wpt_class:1;
79   unsigned int display:1;
80   unsigned int category:1;
81   unsigned int city:1;
82   unsigned int state:1;
83   unsigned int facility:1;
84   unsigned int cc:1;
85   unsigned int cross_road:1;
86   unsigned int addr:1;
87   unsigned int country:1;
88   unsigned int phone_nr:1;
89   unsigned int phone_nr2:1;
90   unsigned int fax_nr:1;
91   unsigned int postal_code:1;
92   unsigned int email:1;
93   unsigned int duration:1;
94 #ifdef GMSD_EXPERIMENTAL
95   unsigned int subclass:1;
96 #endif
97 };
98 
99 class garmin_fs_t : public FormatSpecificData {
100 public:
101   garmin_fs_flags_t flags;
102 
103   int protocol{0};		/* ... used by device (-1 is MapSource) */
104 
105   int32_t icon{0};
106   int wpt_class{0};
107   int32_t display{0};
108   int16_t category{0};
109   QString city;					/* city name */
110   QString facility;			/* facility name */
111   QString state;				/* state */
112   QString cc;						/* country code */
113   QString cross_road;		/* Intersection road label */
114   QString addr;					/* address + number */
115   QString country;			/* country */
116   QString phone_nr;			/* phone number */
117   QString phone_nr2;		/* phone number (2) */
118   QString fax_nr;				/* fax number */
119   QString postal_code;	/* postal code */
120   QString email;				/* email address */
121   unsigned int duration; /* expected travel time to next route point, in seconds, only when auto-routed */
122 
123   garmin_ilink_t* ilinks{nullptr};
124 #ifdef GMSD_EXPERIMENTAL
125   char subclass[22]{};
126 #endif
127 
128 public:
garmin_fs_t()129   garmin_fs_t() : FormatSpecificData(kFsGmsd) {}
130 private:
131   garmin_fs_t(const garmin_fs_t& other) = default;
132 public:
133   garmin_fs_t& operator=(const garmin_fs_t& rhs) = delete; /* not implemented */
134   garmin_fs_t(garmin_fs_t&&) = delete; /* not implemented */
135   garmin_fs_t& operator=(garmin_fs_t&&) = delete; /* not implemented */
136   ~garmin_fs_t() override;
137 
138   garmin_fs_t* clone() const override;
find(const Waypoint * wpt)139   static garmin_fs_t* find(const Waypoint* wpt) {
140     return reinterpret_cast<garmin_fs_t*>(wpt->fs.FsChainFind(kFsGmsd));
141   }
142 
143 #define GEN_GMSD_METHODS(field) \
144   static bool has_##field(const garmin_fs_t* gmsd) \
145   { \
146     return gmsd && gmsd->flags.field; \
147   } \
148   static decltype(field) get_##field(const garmin_fs_t* gmsd, decltype(field) p) \
149   { \
150     return (gmsd && gmsd->flags.field)? gmsd->field : p; \
151   } \
152   static void set_##field(garmin_fs_t* gmsd, decltype(field) p) \
153   { \
154     if (gmsd) { \
155       gmsd->field = p; \
156       gmsd->flags.field = 1; \
157     } \
158   } \
159   static void unset_##field(garmin_fs_t* gmsd) \
160   { \
161     if (gmsd) { \
162       gmsd->flags.field = 0; \
163     } \
164   }
165 
166   GEN_GMSD_METHODS(icon)
167   GEN_GMSD_METHODS(wpt_class)
168   GEN_GMSD_METHODS(display)
169   GEN_GMSD_METHODS(category)
170   GEN_GMSD_METHODS(duration)
171 
172 #undef GEN_GMSD_METHODS
173 
174 #define GEN_GMSD_STR_METHODS(field) \
175   static bool has_##field(const garmin_fs_t* gmsd) \
176   { \
177     return gmsd && gmsd->flags.field; \
178   } \
179   static QString get_##field(const garmin_fs_t* gmsd, const QString& p) \
180   { \
181     return (gmsd && gmsd->flags.field)? gmsd->field : p; \
182   } \
183   static void set_##field(garmin_fs_t* gmsd, const char* p) \
184   { \
185     if (gmsd && p && *p) { \
186       gmsd->field = p; \
187       gmsd->flags.field = 1; \
188     } \
189   } \
190   static void set_##field(garmin_fs_t* gmsd, const QString& p) \
191   { \
192     if (gmsd && !p.isEmpty()) { \
193       gmsd->field = p; \
194       gmsd->flags.field = 1; \
195     } \
196   } \
197   static void unset_##field(garmin_fs_t* gmsd) \
198   { \
199     if (gmsd) { \
200       gmsd->flags.field = 0; \
201     } \
202   }
203 
204   GEN_GMSD_STR_METHODS(city)
205   GEN_GMSD_STR_METHODS(facility)
206   GEN_GMSD_STR_METHODS(state)
207   GEN_GMSD_STR_METHODS(cc)
208   GEN_GMSD_STR_METHODS(cross_road)
209   GEN_GMSD_STR_METHODS(addr)
210   GEN_GMSD_STR_METHODS(country)
211   GEN_GMSD_STR_METHODS(phone_nr)
212   GEN_GMSD_STR_METHODS(phone_nr2)
213   GEN_GMSD_STR_METHODS(fax_nr)
214   GEN_GMSD_STR_METHODS(postal_code)
215   GEN_GMSD_STR_METHODS(email)
216 
217 #undef GEN_GMSD_STR_METHODS
218 };
219 
220 garmin_fs_t* garmin_fs_alloc(int protocol);
221 void garmin_fs_destroy(void* fs);
222 void garmin_fs_copy(void** dest, const void* src);
223 char* garmin_fs_xstrdup(const char* src, size_t size);
224 
225 /* for GPX */
226 void garmin_fs_xml_convert(int base_tag, int tag, const QString& qstr, Waypoint* waypt);
227 void garmin_fs_xml_fprint(const Waypoint* waypt, QXmlStreamWriter*);
228 
229 /* common garmin_fs utilities */
230 
231 /* ..convert_category: returns 1=OK; 0=Unable to convert category */
232 unsigned char garmin_fs_convert_category(const char* category_name, uint16_t* category);
233 
234 /* ..merge_category: returns 1=OK; 0=Unable to convert category */
235 unsigned char garmin_fs_merge_category(const char* category_name, Waypoint* waypt);
236 
237 #define GMSD_SECTION_CATEGORIES "Garmin Categories"
238 
239 void garmin_fs_garmin_after_read(GPS_PWay way, Waypoint* wpt, int protoid);
240 void garmin_fs_garmin_before_write(const Waypoint* wpt, GPS_PWay way, int protoid);
241 
242 #endif
243