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