You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gtm.cc 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /*
  2. Support for GPS TrackMaker data file.
  3. Copyright (C) 2005 Gustavo Niemeyer <gustavo@niemeyer.net>.
  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. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. /*
  17. * Documentation can be found at http://www.trackmaker.com/download/ref_guide_eng.pdf
  18. */
  19. #include "defs.h"
  20. #include "jeeps/gpsmath.h"
  21. static gbfile* file_in, *file_out;
  22. static int indatum;
  23. static int wp_count;
  24. static int ws_count;
  25. static int tr_count;
  26. static int ts_count;
  27. static int rt_count;
  28. static int im_count;
  29. static const route_head* rte_active;
  30. static int start_new;
  31. #define MYNAME "GTM"
  32. #define EPOCH89DIFF 631065600
  33. /* was 631076400 but that seems to include a three-hour bias */
  34. #define WAYPOINTSTYLES \
  35. "\xf5\xff\xff\xff\x0f\x00Times New Roman\x00\x00\x00\x00\x00\x90\x01"\
  36. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\
  37. "\xf5\xff\xff\xff\x0f\x00Times New Roman\x01\x00\x00\x00\x00\x90\x01"\
  38. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\
  39. "\xf5\xff\xff\xff\x0f\x00Times New Roman\x02\x00\x00\x00\x00\x90\x01"\
  40. "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"\
  41. "\xf5\xff\xff\xff\x0f\x00Times New Roman\x03\x00\x00\x00\x00\x90\x01"\
  42. "\x00\x00\x00\x00\x00\x00\x8b\xff\xff\xff\xff\x00\x00\x00\x00\x00\x01"
  43. #define unknown_alt_gtm -10000000
  44. /* Read functions, according to specification. */
  45. #define fread_discard(a,b) gbfseek(a, (b), SEEK_CUR)
  46. #define fread_byte(a) (unsigned char) gbfgetc(a)
  47. #if 0
  48. /* not used */
  49. static short int
  50. fread_bool(gbfile* fd)
  51. {
  52. char buf[2];
  53. gbfread(buf, 2, 1, fd);
  54. return le_read16(buf) ? 1 : 0;
  55. }
  56. #endif
  57. #define fread_integer(a) gbfgetint16(a)
  58. #define fread_long(a) gbfgetint32(a)
  59. #define fread_single(a) gbfgetflt(a)
  60. #define fread_double(a) gbfgetdbl(a)
  61. QString
  62. fread_string(gbfile* fd)
  63. {
  64. char* val;
  65. int len = fread_integer(fd);
  66. if (len == 0) {
  67. return NULL;
  68. }
  69. val = (char*) xmalloc(len+1);
  70. gbfread(val, 1, len, fd);
  71. while (len != 0 && val[len-1] == ' ') {
  72. len--;
  73. }
  74. val[len] = 0;
  75. QString v(val);
  76. xfree(val);
  77. return v;
  78. }
  79. static void
  80. fread_string_discard(gbfile* fd)
  81. {
  82. fread_string(fd);
  83. }
  84. QString
  85. fread_fixedstring(gbfile* fd, int len)
  86. {
  87. char* val = (char*) xmalloc(len+1);
  88. gbfread(val, 1, len, fd);
  89. while (len != 0 && val[len-1] == ' ') {
  90. len--;
  91. }
  92. val[len] = 0;
  93. QString v(val);
  94. xfree(val);
  95. return v;
  96. }
  97. /* Write functions, according to specification. */
  98. static void
  99. fwrite_null(gbfile* fd, int len)
  100. {
  101. char buf[1024];
  102. memset(buf, 0, len);
  103. gbfwrite(buf, 1, len, fd);
  104. }
  105. #define fwrite_byte(a,b) gbfputc((signed char)(b), a)
  106. #define fwrite_bool(a,b) gbfputuint16((b) ? 0xffff : 0, a)
  107. #define fwrite_integer(a,b) gbfputint16((b), a)
  108. #define fwrite_long(a,b) gbfputint32((b), a)
  109. #define fwrite_single(a,b) gbfputflt((b), a)
  110. #define fwrite_double(a,b) gbfputdbl((b), a)
  111. static void
  112. fwrite_string(gbfile* fd, const char* str)
  113. {
  114. if (str && str[0]) {
  115. int len = strlen(str);
  116. fwrite_integer(fd, len);
  117. gbfwrite(str, 1, len, fd);
  118. } else {
  119. fwrite_integer(fd, 0);
  120. }
  121. }
  122. static void
  123. fwrite_string(gbfile* fd, const QString& str)
  124. {
  125. if (str.isEmpty()) {
  126. fwrite_integer(fd, 0);
  127. } else {
  128. fwrite_integer(fd, str.length());
  129. gbfwrite(CSTRc(str), 1, str.length(), fd);
  130. }
  131. }
  132. void
  133. fwrite_fixedstring(gbfile* fd, const char* str, int fieldlen)
  134. {
  135. int len = str ? strlen(str) : 0;
  136. if (len > fieldlen) {
  137. len = fieldlen;
  138. }
  139. if (str) {
  140. gbfwrite(str, 1, len, fd);
  141. }
  142. for (; len != fieldlen; len++) {
  143. gbfputc(' ', fd);
  144. }
  145. }
  146. void
  147. fwrite_fixedstring(gbfile* fd, const QString& str, int fieldlen)
  148. {
  149. fwrite_fixedstring(fd, CSTR(str), fieldlen);
  150. }
  151. /* Auxiliar functions */
  152. #define MAX_INDATUM_INDEX 263
  153. static const int indatum_array[MAX_INDATUM_INDEX] = {
  154. -1, // < 1
  155. 0, 0, 0, 0, 0, 0, 0, // < 8 : Adindan
  156. 1, // < 9 : Afgooye
  157. 2, // < 10 : Ain el Abd
  158. -1, -1, -1, -1, // < 14
  159. 6, 6, 6, 6, 6, 6, 6, 6, 6, // < 23 : ARC 1950
  160. 7, 7, 7, // < 26 : ARC 1960
  161. 8, // < 27 : Ascension Island 58
  162. -1, -1, -1, -1, -1, // < 32
  163. 13, // < 33 : Australian Geo 84
  164. -1, // < 34
  165. 15, // < 35 : Bellevue IGN
  166. 16, // < 36 : Bermuda 1957
  167. -1, -1, // < 38
  168. 17, // < 39 : Bukit Rimpah
  169. 18, // < 40 : Camp Area Astro
  170. 19, // < 41 : Campo Inchauspe
  171. 22, // < 42 : Canton Islan 1966
  172. 23, // < 43 : Cape
  173. 24, // < 44 : Cape Canaveral
  174. 26, // < 45 : Carthe
  175. 28, // < 46 : Chatham
  176. 29, // < 47 : Chua Astro
  177. 30, // < 48 : Corrego Alegre
  178. -1, -1, // < 50
  179. 33, // < 51 : Djakarta (Batavia)
  180. 34, // < 52 : DOS 1968
  181. 35, // < 53 : Easter Island 1967
  182. -1, // < 54
  183. 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, // < 69 : European 1950 Mean
  184. 39, // < 70 : European 1979 Mean
  185. -1, // < 71
  186. 41, // < 72 : Gandajika
  187. 42, // < 73 : Geodetic Datum 49
  188. -1, // < 74
  189. 45, // < 75 : Guam 1963
  190. 46, // < 76 : Gunung Segara
  191. -1, // < 77
  192. 49, // < 78 : Hearth North
  193. -1, // < 79
  194. 50, // < 80 : Hjorsey 1955
  195. 51, // < 81 : Hong Kong 1963
  196. 52, // < 82 : Hu-Tzu-Shan
  197. 53, 53, 53, 53, 53, 53, 53, // < 89 : Indian
  198. -1, // < 90
  199. 55, // < 91 : Ireland 1965
  200. -1, // < 92
  201. 56, // < 93 : ISTS 073 69
  202. 57, // < 94 : Johnston Island 61
  203. 58, // < 95 : Kandawala
  204. 59, // < 96 : Kerguelen Island
  205. 60, // < 97 : Kertau 48
  206. -1, -1, // < 99
  207. 61, // < 100 : L.C. 5 Astro
  208. -1, // < 101
  209. 63, // < 102 : Liberia 1964
  210. 64, 64, // < 104 : Luzon
  211. -1, // < 105
  212. 65, // < 106 : Mahe 1971
  213. -1, // < 107
  214. 69, // < 108 : Merchich
  215. 71, // < 109 : Midway Astro 61
  216. 73, 73, // < 111 : Minna
  217. -1, // < 112
  218. 75, 75, 75, // < 115 : Nahrwan
  219. 76, // < 116 : Naparima BWI
  220. 3, 3, 3, // < 119 : Alaska NAD27
  221. 14, 14, // < 121 : Bahamas NAD27
  222. 20, 20, 20, 20, 20, // < 126 : Canada Mean NAD27
  223. 21, // < 127 : Canal Zone NAD27
  224. 31, // < 128 : Cuba NAD27
  225. 44, // < 129 : Greenland NAD27
  226. -1, -1, // < 131
  227. 20, // < 132 : Canada Mean NAD27
  228. -1, -1, -1, // < 135
  229. 70, // < 136 : Mexico NAD27
  230. -1, -1, -1, -1, -1, -1, -1, -1, // < 144
  231. 80, // < 145 : Old Egyptian
  232. 81, // < 146 : Old Hawaiian
  233. 82, // < 147 : Old Hawaiian Kauai
  234. 83, // < 148 : Old Hawaiian Maui
  235. 81, // < 149 : Old Hawaiian Mean
  236. 84, // < 150 : Old Hawaiian Oahu
  237. 85, // < 151 : Oman
  238. 86, 86, 86, 86, 86, // < 156 : OSG Britain
  239. 87, // < 157 : Pico de Las Nieves
  240. 88, // < 158 : Pitcairn Astro 67
  241. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // < 171
  242. 91, // < 172 : Puerto Rico
  243. 92, // < 173 : Pulkovo 1942
  244. 94, // < 174 : Quatar National
  245. -1, -1, // < 176
  246. 95, // < 177 : Rome 1940
  247. 96, 96, 96, 96, 96, 96, 96, // < 184 : S-42 (Pulkovo 1942)
  248. -1, // < 185
  249. 100, // < 186 : Santo DOS
  250. 99, // < 187 : Sao Braz
  251. -1, -1, -1, -1, // < 191
  252. 105, 105, // < 193 : SAD-69/Mean
  253. 98, // < 194 : SAD-69/Brazil
  254. 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, // < 204 : SAD-69/Mean
  255. 106, // < 205 : South Asia
  256. 109, // < 206 : Tananarive 1926
  257. 111, // < 207 : Timbalai 1948
  258. 112, 112, 112, 112, // < 211 : Tokyo mean
  259. 113, // < 212 : Tristan Astro 1968
  260. 115, // < 213 : Viti Levu 1916
  261. -1, -1, // < 215
  262. 116, // < 216 : Wake Eniwetok 1960
  263. 117, // < 217 : WGS 72
  264. 118, // < 218 : WGS 84
  265. 119, // < 219 : Yacare
  266. 120, // < 220 : Zanderij
  267. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // < 231
  268. 98, // < 232 : SAD-69/Brazil
  269. -1, -1, // < 234
  270. 117, // < 235 : WGS 72
  271. 0, // < 236 : Adindan
  272. 2, // < 237 : Ain el Abd
  273. 7, // < 238 : ARC 1960
  274. 8, // < 239 : Ascension Island 58
  275. -1, -1, // < 241
  276. 52, // < 242 : Hu-Tzu-Shan
  277. 53, 53, 53, // < 245 : Indian
  278. -1, // < 246
  279. 57, // < 247 : Johnston Island 61
  280. 64, // < 248 : Luzon
  281. -1, // < 249
  282. 75, // < 250 : Nahrwan
  283. 76, // < 251 : Naparima BWI
  284. -1, -1, -1, // < 254
  285. 82, // < 255 : Old Hawaiian Kauai
  286. 83, // < 256 : Old Hawaiian Maui
  287. 84, // < 257 : Old Hawaiian Oahu
  288. -1, -1, // < 259
  289. 101, // < 260 : Sapper Hill 43
  290. 111, // < 261 : Timbalai 1948
  291. 112, // < 262 : Tokyo mean
  292. 116 // < 263 : Wake Eniwetok 1960
  293. };
  294. void set_datum(int n)
  295. {
  296. indatum = -1;
  297. if (n > 0 && n < MAX_INDATUM_INDEX) {
  298. indatum = indatum_array[n];
  299. }
  300. if (indatum == -1) {
  301. warning(MYNAME ": Unsupported datum (%d), won't convert to WGS84\n", n);
  302. }
  303. }
  304. static const char* icon_descr[] = {
  305. "", "Airport", "Ball Park", "Bank", "Bar", "Boat Ramp", "Campground", "Car",
  306. "City (Large)", "City (Medium)", "City (Small)", "Dam", "Danger Area",
  307. "Drinking Water", "Fishing Area", "Gas Station", "Glider Area", "Golf Course",
  308. "Heliport", "Hotel", "Animals", "Information", "Man Overboard", "Marina",
  309. "Mine", "Medical Facility", "Parachute Area", "Park", "Parking Area",
  310. "Picnic Area", "Private Field", "Residence", "Restaurant", "Restroom",
  311. "Scenic Area", "School", "Seaplane Base", "Shipwreck", "Shopping Center",
  312. "Short Tower", "Policy Station", "Ski Resort", "Soft Field", "Swimming Area",
  313. "Tall Tower", "Telephone", "Tracback Point", "Ultralight Area", "Waypoint",
  314. "Boat", "Exit", "Flag", "Duck", "Buoy", "Back Track", "Beach", "Bridge",
  315. "Building", "Car Repair", "Cemetery", "Church", "Civil", "Convenience Store",
  316. "Crossing", "Fast Food", "Forest", "Ghost Town", "Levee", "Military",
  317. "Oil Field", "Post Office", "Rv Park", "Scales", "Summit", "Toll Booth",
  318. "Trail Head", "Truck Stop", "Tunnel", "Highway", "Gate", "Fall", "Fence",
  319. "Mata-Burro", "Fitness Center", "Movie Theater", "Live Theater", "Zoo", "Horn",
  320. "Bowling", "Car Rental", "City (Capitol)", "Controlled Area", "Stadium",
  321. "Museum", "Amusement Park", "Skull", "Department Store", "Pharmacy", "Pizza",
  322. "Diver Down Flag 1", "Light", "Pin", "", "Pigsty", "Tree", "Bamboo",
  323. "Banana Plant", "Arrow-Down", "Bifurcation", "Cavern", "River", "Rock",
  324. "Arrow-Up", "Trunk", "Soccer Field", "Sporting Court", "Flag, Green", "Trench",
  325. "Ship-Yellow", "Green Sign", "Swamp", "Lake", "Stop!",
  326. "Fishing Hot Spot Facility", "Speed Reducer", "Stairway", "Cactus", "Ship-Red",
  327. "Letter - S", "Letter - D", "Letter - N",
  328. "Crossing", "Cross", "Flag, Red", "Curve1", "Curve2", "Curve3", "Curve4",
  329. "Letter - W", "Letter - L", "Letter - R", "Radio Beacon", "Road Sign",
  330. "Geocache", "Geocache Found", "Traffic Light", "Bus Station", "Train Station",
  331. "School", "Mile Marker", "Conservation Area", "Waypoint", "Box", "Aerial",
  332. "Auto Repair", "Boat", "Exit Ramp", "Fixed Nav Aid", "Floating Buoy", "Garden",
  333. "Fish Farm", "Lighthouse", "Truck Service", "Resort", "Scuba", "Shooting",
  334. "Sight Seeing", "Sounding", "Winery", "Navaid, Amber", "Navaid, Black",
  335. "Navaid, Blue", "Navaid, Green", "Navaid, Green/Red", "Navaid, Green/White",
  336. "Navaid, Orange", "Navaid, Red", "Navaid, Red/Green", "Navaid, Red/White",
  337. "Navaid, Violet", "Navaid, White", "Navaid, White/Green", "Navaid, White/Red",
  338. "Buoy, White", "Dot, White", "Red Square", "Red Diamond", "Green Square",
  339. "Green Diamond", "Restricted Area", "Navaid (unlit)", "Dot (Small)", "Libraries", "Waypoint", "Waypoint1",
  340. "Waypoint2", "Mark (1)", "Mark (2)", "Mark (3)", "Cross (Red)", "Store",
  341. "Exclamation", "Flag (EUA)", "Flag (CAN)", "Flag (BRA)", "Man", "Animals",
  342. "Deer Tracks", "Tree Stand", "Bridge", "Fence", "Intersection",
  343. "Non Direct Beacon", "VHF Omni Range", "Vor/Tacan", "Vor-Dme",
  344. "1st Approach Fix", "Localizer Outer", "Missed Appr. Pt", "Tacan",
  345. "CheckPoint", NULL
  346. };
  347. void convert_datum(double* lat, double* lon)
  348. {
  349. double amt;
  350. if (indatum != -1 && indatum != 118) {
  351. GPS_Math_Known_Datum_To_WGS84_M(*lat, *lon, 0.0,
  352. lat, lon, &amt, indatum);
  353. }
  354. }
  355. /* Callbacks */
  356. static void
  357. gtm_rd_init(const QString& fname)
  358. {
  359. int version;
  360. file_in = gbfopen_le(fname, "rb", MYNAME);
  361. version = fread_integer(file_in);
  362. QString name = fread_fixedstring(file_in, 10);
  363. if (version == -29921) {
  364. fatal(MYNAME ": Uncompress the file first\n");
  365. }
  366. if (name != "TrackMaker") {
  367. fatal(MYNAME ": Invalid file format\n");
  368. }
  369. if (version != 211) {
  370. fatal(MYNAME ": Invalid format version\n");
  371. }
  372. /* Header */
  373. fread_discard(file_in, 15);
  374. ws_count = fread_long(file_in);
  375. fread_discard(file_in, 4);
  376. wp_count = fread_long(file_in);
  377. tr_count = fread_long(file_in);
  378. rt_count = fread_long(file_in);
  379. fread_discard(file_in, 16);
  380. im_count = fread_long(file_in);
  381. ts_count = fread_long(file_in);
  382. fread_discard(file_in, 28);
  383. fread_string_discard(file_in);
  384. fread_string_discard(file_in);
  385. fread_string_discard(file_in);
  386. fread_string_discard(file_in);
  387. /* User Grid and Datum */
  388. fread_discard(file_in, 34);
  389. set_datum(fread_integer(file_in));
  390. fread_discard(file_in, 22);
  391. }
  392. static void
  393. gtm_rd_deinit(void)
  394. {
  395. gbfclose(file_in);
  396. }
  397. static void count_route_waypts(const Waypoint* wpt)
  398. {
  399. rt_count++;
  400. }
  401. static void count_track_waypts(const Waypoint* wpt)
  402. {
  403. tr_count++;
  404. }
  405. static void
  406. gtm_wr_init(const QString& fname)
  407. {
  408. rt_count = tr_count = 0;
  409. track_disp_all(NULL, NULL, count_track_waypts);
  410. route_disp_all(NULL, NULL, count_route_waypts);
  411. file_out = gbfopen_le(fname, "wb", MYNAME); /* little endian */
  412. /* Header */
  413. fwrite_integer(file_out, 211);
  414. fwrite_fixedstring(file_out, "TrackMaker", 10);
  415. fwrite_byte(file_out, 0);
  416. fwrite_byte(file_out, 0);
  417. fwrite_byte(file_out, 8);
  418. fwrite_byte(file_out, 0);
  419. fwrite_byte(file_out, 0);
  420. fwrite_byte(file_out, 0);
  421. fwrite_byte(file_out, 0);
  422. fwrite_long(file_out, 0);
  423. fwrite_long(file_out, 16777215);
  424. fwrite_long(file_out, waypt_count() ? 4 : 0); /* num waypoint styles */
  425. fwrite_long(file_out, 0);
  426. fwrite_long(file_out, waypt_count()); /* num waypoints */
  427. fwrite_long(file_out, tr_count);
  428. fwrite_long(file_out, rt_count);
  429. fwrite_single(file_out, 0); /* maxlon */
  430. fwrite_single(file_out, 0); /* minlon */
  431. fwrite_single(file_out, 0); /* maxlat */
  432. fwrite_single(file_out, 0); /* minlat */
  433. fwrite_long(file_out, 0);
  434. fwrite_long(file_out, track_count()); /* num tracklog styles */
  435. fwrite_single(file_out, 0);
  436. fwrite_single(file_out, 0);
  437. fwrite_bool(file_out, 0);
  438. fwrite_bool(file_out, 0);
  439. fwrite_bool(file_out, 0);
  440. fwrite_bool(file_out, 0);
  441. fwrite_bool(file_out, 0);
  442. fwrite_bool(file_out, 0);
  443. fwrite_bool(file_out, 0);
  444. fwrite_bool(file_out, 0);
  445. fwrite_bool(file_out, 0);
  446. fwrite_bool(file_out, 0);
  447. fwrite_string(file_out, "Times New Roman");
  448. fwrite_string(file_out, "");
  449. fwrite_string(file_out, "");
  450. fwrite_string(file_out, "");
  451. /* User Grid and Datum */
  452. fwrite_null(file_out, 34);
  453. fwrite_integer(file_out, 217); /* WGS84 */
  454. fwrite_null(file_out, 22);
  455. }
  456. static void
  457. gtm_wr_deinit(void)
  458. {
  459. gbfclose(file_out);
  460. }
  461. static void
  462. gtm_read(void)
  463. {
  464. route_head* first_trk_head = NULL;
  465. route_head* trk_head = NULL;
  466. route_head* rte_head = NULL;
  467. Waypoint* wpt;
  468. int real_tr_count = 0;
  469. unsigned int icon;
  470. int i;
  471. /* Image information */
  472. for (i = 0; i != im_count; i++) {
  473. fread_string_discard(file_in);
  474. fread_string_discard(file_in);
  475. fread_discard(file_in, 30);
  476. }
  477. /* Waypoints */
  478. for (i = 0; i != wp_count; i++) {
  479. wpt = new Waypoint;
  480. wpt->latitude = fread_double(file_in);
  481. wpt->longitude = fread_double(file_in);
  482. convert_datum(&wpt->latitude, &wpt->longitude);
  483. wpt->shortname = fread_fixedstring(file_in, 10);
  484. wpt->description = fread_string(file_in);
  485. icon = fread_integer(file_in);
  486. if (icon < sizeof(icon_descr)/sizeof(char*)) {
  487. wpt->icon_descr = icon_descr[icon];
  488. }
  489. fread_discard(file_in, 1);
  490. wpt->SetCreationTime(fread_long(file_in));
  491. if (wpt->creation_time.isValid()) {
  492. wpt->creation_time += EPOCH89DIFF;
  493. }
  494. fread_discard(file_in, 2);
  495. wpt->altitude = fread_single(file_in);
  496. if (wpt->altitude == unknown_alt_gtm) {
  497. wpt->altitude = unknown_alt;
  498. }
  499. fread_discard(file_in, 2);
  500. waypt_add(wpt);
  501. }
  502. /* Waypoint Styles */
  503. if (wp_count) {
  504. for (i = 0; i != ws_count; i++) {
  505. fread_discard(file_in, 4);
  506. fread_string_discard(file_in);
  507. fread_discard(file_in, 24);
  508. }
  509. }
  510. /* Tracklogs */
  511. for (i = 0; i != tr_count; i++) {
  512. wpt = new Waypoint;
  513. wpt->latitude = fread_double(file_in);
  514. wpt->longitude = fread_double(file_in);
  515. convert_datum(&wpt->latitude, &wpt->longitude);
  516. wpt->SetCreationTime(fread_long(file_in));
  517. if (wpt->creation_time.isValid()) {
  518. wpt->creation_time += EPOCH89DIFF;
  519. }
  520. start_new = fread_byte(file_in);
  521. wpt->altitude = fread_single(file_in);
  522. if (wpt->altitude == unknown_alt_gtm) {
  523. wpt->altitude = unknown_alt;
  524. }
  525. if (start_new || !trk_head) {
  526. trk_head = route_head_alloc();
  527. track_add_head(trk_head);
  528. real_tr_count++;
  529. if (!first_trk_head) {
  530. first_trk_head = trk_head;
  531. }
  532. }
  533. track_add_wpt(trk_head, wpt);
  534. }
  535. /* Tracklog styles */
  536. trk_head = first_trk_head;
  537. for (i = 0; i != ts_count && i != real_tr_count; i++) {
  538. trk_head->rte_name = fread_string(file_in);
  539. fread_discard(file_in, 12);
  540. trk_head = (route_head*)QUEUE_NEXT(&trk_head->Q);
  541. }
  542. /* Routes */
  543. for (i = 0; i != rt_count; i++) {
  544. wpt = new Waypoint;
  545. wpt->latitude = fread_double(file_in);
  546. wpt->longitude = fread_double(file_in);
  547. convert_datum(&wpt->latitude, &wpt->longitude);
  548. wpt->shortname = fread_fixedstring(file_in, 10);
  549. wpt->description = fread_string(file_in);
  550. QString route_name = fread_string(file_in);
  551. icon = fread_integer(file_in);
  552. if (icon < sizeof(icon_descr)/sizeof(char*)) {
  553. wpt->icon_descr = icon_descr[icon];
  554. }
  555. fread_discard(file_in, 1);
  556. start_new = fread_byte(file_in);
  557. fread_discard(file_in, 6);
  558. wpt->altitude = fread_single(file_in);
  559. if (wpt->altitude == unknown_alt_gtm) {
  560. wpt->altitude = unknown_alt;
  561. }
  562. fread_discard(file_in, 2);
  563. if (start_new || !rte_head) {
  564. rte_head = route_head_alloc();
  565. rte_head->rte_name = route_name;
  566. route_add_head(rte_head);
  567. }
  568. route_add_wpt(rte_head, wpt);
  569. }
  570. }
  571. static int icon_from_descr(const QString& descr)
  572. {
  573. for (int i = 0; icon_descr[i]; i++) {
  574. if (descr.compare(icon_descr[i]) == 0) {
  575. return i;
  576. }
  577. }
  578. return 48;
  579. }
  580. static void write_waypt(const Waypoint* wpt)
  581. {
  582. fwrite_double(file_out, wpt->latitude);
  583. fwrite_double(file_out, wpt->longitude);
  584. fwrite_fixedstring(file_out, wpt->shortname, 10);
  585. fwrite_string(file_out, wpt->description);
  586. fwrite_integer(file_out, icon_from_descr(wpt->icon_descr));
  587. fwrite_byte(file_out, 3);
  588. if (wpt->creation_time.isValid()) {
  589. fwrite_long(file_out, wpt->GetCreationTime().toTime_t()-EPOCH89DIFF);
  590. } else {
  591. fwrite_long(file_out, 0);
  592. }
  593. fwrite_integer(file_out, 0);
  594. if (wpt->altitude == unknown_alt) {
  595. fwrite_single(file_out, unknown_alt_gtm);
  596. } else {
  597. fwrite_single(file_out, wpt->altitude);
  598. }
  599. fwrite_integer(file_out, 0);
  600. }
  601. static void start_rte(const route_head* rte)
  602. {
  603. rte_active = rte;
  604. start_new = 1;
  605. }
  606. static void write_trk_waypt(const Waypoint* wpt)
  607. {
  608. fwrite_double(file_out, wpt->latitude);
  609. fwrite_double(file_out, wpt->longitude);
  610. fwrite_long(file_out, wpt->GetCreationTime().toTime_t()-EPOCH89DIFF);
  611. fwrite_byte(file_out, start_new);
  612. if (wpt->altitude == unknown_alt) {
  613. fwrite_single(file_out, unknown_alt_gtm);
  614. } else {
  615. fwrite_single(file_out, wpt->altitude);
  616. }
  617. start_new = 0;
  618. }
  619. static void write_trk_style(const route_head* trk)
  620. {
  621. fwrite_string(file_out, trk->rte_name);
  622. fwrite_byte(file_out, 1);
  623. fwrite_long(file_out, 0);
  624. fwrite_single(file_out, 0);
  625. fwrite_byte(file_out, 0);
  626. fwrite_integer(file_out, 0);
  627. }
  628. static void write_rte_waypt(const Waypoint* wpt)
  629. {
  630. fwrite_double(file_out, wpt->latitude);
  631. fwrite_double(file_out, wpt->longitude);
  632. fwrite_fixedstring(file_out, wpt->shortname, 10);
  633. fwrite_string(file_out, wpt->description);
  634. fwrite_string(file_out, rte_active->rte_name);
  635. fwrite_integer(file_out, icon_from_descr(wpt->icon_descr));
  636. fwrite_byte(file_out, 3);
  637. fwrite_byte(file_out, start_new);
  638. fwrite_long(file_out, 0);
  639. fwrite_integer(file_out, 0);
  640. if (wpt->altitude == unknown_alt) {
  641. fwrite_single(file_out, unknown_alt_gtm);
  642. } else {
  643. fwrite_single(file_out, wpt->altitude);
  644. }
  645. fwrite_integer(file_out, 0);
  646. start_new = 0;
  647. }
  648. static void
  649. gtm_write(void)
  650. {
  651. waypt_disp_all(write_waypt);
  652. if (waypt_count()) {
  653. gbfwrite(WAYPOINTSTYLES, 1, sizeof(WAYPOINTSTYLES)-1, file_out);
  654. }
  655. track_disp_all(start_rte, NULL, write_trk_waypt);
  656. track_disp_all(write_trk_style, NULL, NULL);
  657. route_disp_all(start_rte, NULL, write_rte_waypt);
  658. }
  659. static
  660. arglist_t gtm_args[] = {
  661. ARG_TERMINATOR
  662. };
  663. ff_vecs_t gtm_vecs = {
  664. ff_type_file,
  665. FF_CAP_RW_ALL,
  666. gtm_rd_init,
  667. gtm_wr_init,
  668. gtm_rd_deinit,
  669. gtm_wr_deinit,
  670. gtm_read,
  671. gtm_write,
  672. NULL,
  673. gtm_args,
  674. };