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.

802 lines
20KB

  1. /*
  2. Access to PsiTrex text files.
  3. Based on information provided by Ian Cowley.
  4. Copyright (C) 2003 Mark Bradley, mrcb.gpsb@osps.net
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  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. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  16. */
  17. #include "defs.h"
  18. #include "garmin_tables.h"
  19. #include <ctype.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #define MYNAME "PSITREX"
  23. typedef enum {
  24. ltrimEOL = 1 , /* skip spaces & tabs to start; ends on EOL */
  25. EOL, /* don't skip spaces and tabs to start; end on EOL */
  26. comma, /* skip spaces & tabs to start; ends on comma or EOL */
  27. whitespace, /* skip spaces & tabs to start; ends on white space or EOL */
  28. wscomma /* skip spaces & tabs to start; ends on white space, comma or EOL */
  29. } psit_tokenSep_type;
  30. typedef struct psit_icon_mapping {
  31. const int value;
  32. const char* icon;
  33. } psit_icon_mapping_t;
  34. static gbfile* psit_file_in;
  35. static gbfile* psit_file_out;
  36. static short_handle mkshort_handle;
  37. /* 2 = not written any tracks out
  38. 1 = change of track to write out track header
  39. 0 = in the middle of writing out track datapoints, so don't write a header */
  40. static int psit_track_state = 2;
  41. static char psit_current_token[256];
  42. char* snlen;
  43. static
  44. arglist_t psit_args[] = {
  45. /* {"snlen", &snlen, "Length of generated shortnames",
  46. NULL, ARGTYPE_INT, "1", NULL }, */
  47. ARG_TERMINATOR
  48. };
  49. /* Taken from PsiTrex 1.13 */
  50. static
  51. const psit_icon_mapping_t psit_icon_value_table[] = {
  52. { 0x00, "anchor" },
  53. { 0x06, "dollar" },
  54. { 0x07, "fish" },
  55. { 0x08, "fuel" },
  56. { 0x0a, "house" },
  57. { 0x0b, "knife" },
  58. { 0x0d, "mug" },
  59. { 0x0e, "skull" },
  60. { 0x12, "wpt_dot" },
  61. { 0x13, "wreck" },
  62. { 0x15, "mob" },
  63. { 0x0096, "boat_ramp" },
  64. { 0x0097, "camp" },
  65. { 0x0098, "restrooms" },
  66. { 0x0099, "showers" },
  67. { 0x009a, "drinking_wtr" },
  68. { 0x009b, "phone" },
  69. { 0x009c, "1st_aid" },
  70. { 0x009d, "info" },
  71. { 0x009e, "parking" },
  72. { 0x009f, "park" },
  73. { 0x00a0, "picnic" },
  74. { 0x00a1, "scenic" },
  75. { 0x00a2, "skiing" },
  76. { 0x00a3, "swimming" },
  77. { 0x00a4, "dam" },
  78. { 0x00a6, "danger" },
  79. { 0x00a9, "ball" },
  80. { 0x00aa, "car" },
  81. { 0x00ab, "deer" },
  82. { 0x00ac, "shpng_cart" },
  83. { 0x00ad, "lodging" },
  84. { 0x00ae, "mine" },
  85. { 0x00af, "trail_head" },
  86. { 0x00b0, "truck_stop" },
  87. { 0x00b2, "flag" },
  88. { 0x2005, "golf" },
  89. { 0x2006, "sml_cty" },
  90. { 0x2007, "med_cty" },
  91. { 0x2008, "lrg_cty" },
  92. { 0x200c, "amuse_pk" },
  93. { 0x200d, "bowling" },
  94. { 0x200e, "car_rental" },
  95. { 0x200f, "car_repair" },
  96. { 0x2010, "fastfood" },
  97. { 0x2011, "fitness" },
  98. { 0x2012, "movie" },
  99. { 0x2013, "museum" },
  100. { 0x2014, "pharmacy" },
  101. { 0x2015, "pizza" }, /* how specific does this really need to be? C'mon! */
  102. { 0x2016, "post_ofc" },
  103. { 0x2017, "rv_park" },
  104. { 0x2018, "school" },
  105. { 0x2019, "stadium" },
  106. { 0x201a, "store" },
  107. { 0x201b, "zoo" },
  108. { 0x201c, "gas_plus" },
  109. { 0x201d, "faces" },
  110. { 0x2022, "weigh_sttn" },
  111. { 0x2023, "toll_booth" },
  112. { 0x2029, "bridge" },
  113. { 0x202a, "building" },
  114. { 0x202b, "cemetery" },
  115. { 0x202c, "church" },
  116. { 0x202e, "crossing" },
  117. { 0x2032, "oil_field" },
  118. { 0x2033, "tunnel" },
  119. { 0x2035, "forest" },
  120. { 0x2036, "summit" },
  121. { 0x203f, "geocache" },
  122. { 0x2040, "geocache_fnd" },
  123. { 0x4000, "airport" },
  124. { 0x4007, "tall_tower" },
  125. { 0x4008, "short_tower" },
  126. { 0x4009, "glider" },
  127. { 0x400a, "ultralight" },
  128. { 0x400b, "parachute" },
  129. { 0x4012, "seaplane" },
  130. { -1, NULL }
  131. };
  132. static const char*
  133. psit_find_desc_from_icon_number(const int icon)
  134. {
  135. const psit_icon_mapping_t* i;
  136. for (i = psit_icon_value_table; i->icon; i++) {
  137. if (icon == i->value) {
  138. return i->icon;
  139. }
  140. }
  141. return "";
  142. }
  143. static int
  144. psit_find_icon_number_from_desc(const char* desc)
  145. {
  146. const psit_icon_mapping_t* i;
  147. int def_icon = 18;
  148. if (!desc) {
  149. return def_icon;
  150. }
  151. for (i = psit_icon_value_table; i->icon; i++) {
  152. if (case_ignore_strcmp(desc,i->icon) == 0) {
  153. return i->value;
  154. }
  155. }
  156. if (atoi(desc) > 0) {
  157. return atoi(desc);
  158. }
  159. return def_icon;
  160. }
  161. static void
  162. psit_rd_init(const QString& fname)
  163. {
  164. psit_file_in = gbfopen(fname, "r", MYNAME);
  165. }
  166. static void
  167. psit_rd_deinit(void)
  168. {
  169. gbfclose(psit_file_in);
  170. }
  171. static void
  172. psit_wr_init(const QString& fname)
  173. {
  174. psit_file_out = gbfopen(fname, "w", MYNAME);
  175. }
  176. static void
  177. psit_wr_deinit(void)
  178. {
  179. gbfclose(psit_file_out);
  180. }
  181. /*
  182. * get characters until and including terminating NULL from psit_file_in
  183. * and write into buf.
  184. */
  185. static void
  186. psit_getToken(gbfile* psit_file, char* buf, size_t sz, psit_tokenSep_type delimType)
  187. {
  188. int c = -1;
  189. *buf = 0;
  190. if (delimType != EOL) {
  191. while ((c = gbfgetc(psit_file)) != EOF) {
  192. if (!isspace(c)) {
  193. break;
  194. }
  195. }
  196. }
  197. if (gbfeof(psit_file)) {
  198. return;
  199. }
  200. if (delimType == EOL) {
  201. c = gbfgetc(psit_file);
  202. }
  203. if (c == '#') {
  204. if (gbfgets(buf, sz, psit_file) == NULL) {
  205. *buf = 0;
  206. return;
  207. }
  208. /* use recursion to skip multiple comment lines or just to return the next token */
  209. psit_getToken(psit_file, buf, sz, delimType);
  210. return;
  211. }
  212. if ((delimType == EOL) || (delimType == ltrimEOL)) {
  213. *buf = c;
  214. buf++;
  215. gbfgets(buf, sz-1, psit_file);
  216. return;
  217. }
  218. while (sz--) {
  219. *buf++ = c;
  220. if ((c = gbfgetc(psit_file)) == EOF) {
  221. *buf = 0;
  222. return;
  223. }
  224. if (((c == 0) || isspace(c)) &&
  225. ((delimType == whitespace) || (delimType == wscomma))) {
  226. *buf = 0;
  227. return;
  228. }
  229. if (((delimType == comma) || (delimType == wscomma)) &&
  230. (c == ',')) {
  231. *buf = 0;
  232. return;
  233. }
  234. }
  235. }
  236. /*
  237. * test if a token is known
  238. *
  239. */
  240. static int
  241. psit_isKnownToken(char* buf)
  242. {
  243. if (strcmp(buf, "Track:") == 0) {
  244. return 0;
  245. }
  246. if (strcmp(buf, "Route:") == 0) {
  247. return 0;
  248. }
  249. if (strcmp(buf, "Waypoint:") == 0) {
  250. return 0;
  251. }
  252. if (strcmp(buf, "Map:") == 0) {
  253. return 0;
  254. }
  255. return 1;
  256. }
  257. /*
  258. * read in from file a waypoint record
  259. * MRCB
  260. */
  261. static void
  262. psit_waypoint_r(gbfile* psit_file, Waypoint** wpt)
  263. {
  264. int garmin_icon_num;
  265. Waypoint* thisWaypoint;
  266. if (strlen(psit_current_token) > 0) {
  267. thisWaypoint = new Waypoint;
  268. thisWaypoint->latitude = atof(psit_current_token);
  269. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  270. thisWaypoint->longitude = atof(psit_current_token);
  271. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  272. if (psit_current_token[0] == '*') {
  273. thisWaypoint->altitude = unknown_alt;
  274. } else {
  275. thisWaypoint->altitude = atof(psit_current_token);
  276. }
  277. /* the name */
  278. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  279. rtrim(psit_current_token);
  280. thisWaypoint->shortname = psit_current_token;
  281. thisWaypoint->description = "";
  282. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL);
  283. rtrim(psit_current_token);
  284. /* since PsiTrex only deals with Garmins, let's use the "proper" Garmin icon name */
  285. /* convert the PsiTrex name to the number, which is the PCX one; from there to Garmin desc */
  286. garmin_icon_num = psit_find_icon_number_from_desc(psit_current_token);
  287. thisWaypoint->icon_descr = gt_find_desc_from_icon_number(garmin_icon_num, PCX);
  288. waypt_add(thisWaypoint);
  289. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), wscomma);
  290. }
  291. }
  292. /*
  293. * write out to file a waypoint record
  294. * MRCB
  295. */
  296. static void
  297. psit_waypoint_w(gbfile* psit_file, const Waypoint* wpt)
  298. {
  299. int icon;
  300. const char* ident;
  301. char* src = 0; /* BUGBUG Passed to mkshort */
  302. gbfprintf(psit_file, "%11.6f,%11.6f,",
  303. wpt->latitude,
  304. wpt->longitude);
  305. if (wpt->altitude == unknown_alt) {
  306. gbfprintf(psit_file, "********,");
  307. } else
  308. gbfprintf(psit_file, "%8.2f,",
  309. wpt->altitude);
  310. ident = global_opts.synthesize_shortnames ?
  311. mkshort(mkshort_handle, src) :
  312. xstrdup(wpt->shortname);
  313. gbfprintf(psit_file, " %-6s, ", ident);
  314. xfree(ident);
  315. icon = gt_find_icon_number_from_desc(wpt->icon_descr, PCX);
  316. if (get_cache_icon(wpt) && wpt->icon_descr.compare("Geocache Found") != 0) {
  317. icon = gt_find_icon_number_from_desc(get_cache_icon(wpt), PCX);
  318. }
  319. ident = psit_find_desc_from_icon_number(icon);
  320. if (strlen(ident) == 0) {
  321. gbfprintf(psit_file, "%1d\n", icon);
  322. } else {
  323. gbfprintf(psit_file, "%s\n", ident);
  324. }
  325. }
  326. static void
  327. psit_waypoint_w_wrapper(const Waypoint* wpt)
  328. {
  329. psit_waypoint_w(psit_file_out, wpt);
  330. }
  331. /*
  332. * read in from file a route record
  333. * MRCB
  334. */
  335. static void
  336. psit_route_r(gbfile* psit_file, route_head** rte)
  337. {
  338. char rtename[256];
  339. int garmin_icon_num;
  340. route_head* rte_head;
  341. Waypoint* thisWaypoint;
  342. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL);
  343. if (strlen(psit_current_token) == 0) {
  344. strcpy(rtename, "ROUTE");
  345. } else {
  346. strcpy(rtename, psit_current_token);
  347. }
  348. rtrim(rtename);
  349. rte_head = route_head_alloc();
  350. rte_head->rte_name = rtename;
  351. route_add_head(rte_head);
  352. *rte = rte_head;
  353. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), wscomma);
  354. while (psit_isKnownToken(psit_current_token) != 0) {
  355. if (strlen(psit_current_token) > 0) {
  356. thisWaypoint = new Waypoint;
  357. thisWaypoint->latitude = atof(psit_current_token);
  358. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  359. thisWaypoint->longitude = atof(psit_current_token);
  360. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  361. if (psit_current_token[0] == '*') {
  362. thisWaypoint->altitude = unknown_alt;
  363. } else {
  364. thisWaypoint->altitude = atof(psit_current_token);
  365. }
  366. /* the name */
  367. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  368. rtrim(psit_current_token);
  369. thisWaypoint->shortname = psit_current_token;
  370. thisWaypoint->description = "";
  371. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL);
  372. rtrim(psit_current_token);
  373. /* since PsiTrex only deals with Garmins, let's use the "proper" Garmin icon name */
  374. /* convert the PsiTrex name to the number, which is the PCX one; from there to Garmin desc */
  375. garmin_icon_num = psit_find_icon_number_from_desc(psit_current_token);
  376. thisWaypoint->icon_descr = gt_find_desc_from_icon_number(garmin_icon_num, PCX);
  377. route_add_wpt(rte_head, thisWaypoint);
  378. if (gbfeof(psit_file)) {
  379. break;
  380. }
  381. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), wscomma);
  382. } else {
  383. break;
  384. }
  385. }
  386. }
  387. /*
  388. * write out to file a route header
  389. * MRCB
  390. */
  391. static void
  392. psit_routehdr_w(gbfile* psit_file, const route_head* rte)
  393. {
  394. unsigned int rte_datapoints;
  395. QString rname;
  396. Waypoint* testwpt;
  397. time_t uniqueValue = 0;
  398. queue* elem, *tmp;
  399. /* total nodes (waypoints) this route */
  400. rte_datapoints = 0;
  401. if (rte->waypoint_list.next) { /* this test doesn't do what I want i.e test if this is a valid route - treat as a placeholder for now */
  402. QUEUE_FOR_EACH(&rte->waypoint_list, elem, tmp) {
  403. testwpt = (Waypoint*)elem;
  404. if (rte_datapoints == 0) {
  405. uniqueValue = testwpt->GetCreationTime().toTime_t();
  406. }
  407. rte_datapoints++;
  408. }
  409. if (uniqueValue == 0) {
  410. uniqueValue = current_time().toTime_t();
  411. }
  412. /* route name */
  413. if (rte->rte_name.isEmpty()) {
  414. rname = QString("Route%1").arg((uint) uniqueValue, 4, 16, QChar('0'));
  415. } else {
  416. rname = rte->rte_name;
  417. }
  418. /* check for psitrex comment sign; replace with '$' */
  419. rname = rname.replace(QChar('#'), QChar('$'));
  420. gbfputs(QString("Route: %1\n").arg(rname), psit_file);
  421. }
  422. }
  423. static void
  424. psit_routehdr_w_wrapper(const route_head* rte)
  425. {
  426. psit_routehdr_w(psit_file_out, rte);
  427. }
  428. /*
  429. * read in from file a track record
  430. * MRCB
  431. */
  432. static void
  433. psit_track_r(gbfile* psit_file, route_head** trk)
  434. {
  435. char trkname[256];
  436. unsigned int trk_num;
  437. struct tm tmTime;
  438. time_t dateTime = 0;
  439. route_head* track_head = NULL;
  440. Waypoint* thisWaypoint;
  441. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), ltrimEOL);
  442. if (strlen(psit_current_token) == 0) {
  443. strcpy(trkname, "TRACK");
  444. } else {
  445. strcpy(trkname, psit_current_token);
  446. }
  447. rtrim(trkname);
  448. trk_num = 0;
  449. track_head = NULL;
  450. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), wscomma);
  451. while (psit_isKnownToken(psit_current_token) != 0) {
  452. if (strlen(psit_current_token) > 0) {
  453. thisWaypoint = new Waypoint;
  454. thisWaypoint->latitude = atof(psit_current_token);
  455. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  456. thisWaypoint->longitude = atof(psit_current_token);
  457. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), comma);
  458. if (psit_current_token[0] == '*') {
  459. thisWaypoint->altitude = unknown_alt;
  460. } else {
  461. thisWaypoint->altitude = atof(psit_current_token);
  462. }
  463. /* date portion of the date time DD/MM/YY */
  464. psit_getToken(psit_file, psit_current_token,
  465. sizeof(psit_current_token), whitespace);
  466. sscanf(psit_current_token, "%02d/%02d/%02d",
  467. &(tmTime.tm_mday) , &(tmTime.tm_mon),
  468. &(tmTime.tm_year));
  469. /* years are less 1900 in the tm struct */
  470. tmTime.tm_year += (tmTime.tm_year > 50 ? 0 : 100);
  471. /* months are 0 to 11 in the tm struct */
  472. tmTime.tm_mon--;
  473. /* time portion of the date time hh:mm:ss */
  474. psit_getToken(psit_file,psit_current_token,
  475. sizeof(psit_current_token), wscomma);
  476. sscanf(psit_current_token, "%02d:%02d:%02d",
  477. &(tmTime.tm_hour) , &(tmTime.tm_min),
  478. &(tmTime.tm_sec));
  479. tmTime.tm_isdst = 0;
  480. dateTime = mkgmtime(&tmTime);
  481. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), whitespace);
  482. if ((strcmp(psit_current_token, "1") == 0) || (track_head == NULL)) {
  483. track_head = route_head_alloc();
  484. /* Add a number to the track name. With Garmins, the "first"
  485. tracklog is usually ACTIVE LOG
  486. the second is ACTIVE LOG001 and so on */
  487. if (trk_num > 0) {
  488. track_head->rte_name = QString().sprintf("%s%03d", trkname, trk_num);
  489. } else {
  490. track_head->rte_name = trkname;
  491. }
  492. trk_num++;
  493. track_add_head(track_head);
  494. }
  495. thisWaypoint->SetCreationTime(dateTime);
  496. track_add_wpt(track_head, thisWaypoint);
  497. if (gbfeof(psit_file)) {
  498. break;
  499. }
  500. psit_getToken(psit_file,psit_current_token,sizeof(psit_current_token), wscomma);
  501. } else {
  502. break;
  503. }
  504. }
  505. }
  506. /*
  507. * write out to file a tracklog header
  508. * MRCB
  509. */
  510. static void
  511. psit_trackhdr_w(gbfile* psit_file, const route_head* trk)
  512. {
  513. unsigned int trk_datapoints;
  514. QString tname;
  515. Waypoint* testwpt;
  516. time_t uniqueValue = 0;
  517. queue* elem, *tmp;
  518. if (psit_track_state == 2) {
  519. /* total nodes (waypoints) this track */
  520. trk_datapoints = 0;
  521. if (trk->waypoint_list.next) { /* this test doesn't do what I want i.e test if this is a valid track - treat as a placeholder for now */
  522. QUEUE_FOR_EACH(&trk->waypoint_list, elem, tmp) {
  523. if (trk_datapoints == 0) {
  524. testwpt = (Waypoint*)elem;
  525. uniqueValue = testwpt->GetCreationTime().toTime_t();
  526. }
  527. trk_datapoints++;
  528. }
  529. if (uniqueValue == 0) {
  530. uniqueValue = current_time().toTime_t();
  531. }
  532. /* track name */
  533. if (trk->rte_name.isEmpty()) {
  534. tname = QString("Track%1").arg((uint) uniqueValue, 4, 16, QChar('0'));
  535. } else {
  536. tname = trk->rte_name;
  537. }
  538. /* check for psitrex comment sign; replace with '$' */
  539. tname = tname.replace(QChar('#'), QChar('$'));
  540. gbfputs(QString("Track: %1\n").arg(tname), psit_file);
  541. }
  542. }
  543. psit_track_state = 1;
  544. }
  545. static void
  546. psit_trackhdr_w_wrapper(const route_head* trk)
  547. {
  548. psit_trackhdr_w(psit_file_out, trk);
  549. }
  550. /*
  551. * write out to file a tracklog datapoint
  552. * MRCB
  553. */
  554. static void
  555. psit_trackdatapoint_w(gbfile* psit_file, const Waypoint* wpt)
  556. {
  557. time_t t = wpt->GetCreationTime().toTime_t();
  558. struct tm* tmTime = gmtime(&t);
  559. gbfprintf(psit_file, "%11.6f,%11.6f,",
  560. wpt->latitude,
  561. wpt->longitude);
  562. if (wpt->altitude == unknown_alt) {
  563. gbfprintf(psit_file, "********, ");
  564. } else
  565. gbfprintf(psit_file, "%8.2f, ",
  566. wpt->altitude);
  567. /* Following date time format is fixed and reveals the origin of PsiTrex (i.e. the UK) */
  568. gbfprintf(psit_file, "%02d/%02d/%02d %02d:%02d:%02d,",
  569. tmTime->tm_mday,
  570. tmTime->tm_mon+1,
  571. tmTime->tm_year % 100,
  572. tmTime->tm_hour,
  573. tmTime->tm_min,
  574. tmTime->tm_sec);
  575. gbfprintf(psit_file," %d\n", psit_track_state);
  576. psit_track_state = 0;
  577. }
  578. static void
  579. psit_trackdatapoint_w_wrapper(const Waypoint* wpt)
  580. {
  581. psit_trackdatapoint_w(psit_file_out, wpt);
  582. }
  583. static void
  584. psit_read(void)
  585. {
  586. Waypoint* wpt;
  587. route_head* rte;
  588. route_head* trk;
  589. #ifdef DUMP_ICON_TABLE
  590. printf("static icon_mapping_t icon_table[] = {\n");
  591. #endif
  592. psit_getToken(psit_file_in, psit_current_token, sizeof(psit_current_token), whitespace);
  593. do {
  594. if (strlen(psit_current_token) == 0) {
  595. break;
  596. }
  597. if (strcmp(psit_current_token, "Track:") == 0) {
  598. if (global_opts.objective == trkdata) {
  599. psit_track_r(psit_file_in, &trk);
  600. } else {
  601. break; /* psitrex files only have one format in; */
  602. }
  603. /* if this is a track file and we don't want them, them bail out */
  604. } else if (strcmp(psit_current_token, "Route:") == 0) {
  605. if (global_opts.objective == rtedata) {
  606. psit_route_r(psit_file_in, &rte);
  607. } else {
  608. break; /* ditto, but for routes */
  609. }
  610. } else {
  611. /* Must be waypoints in this file */
  612. if (global_opts.objective == wptdata) {
  613. psit_waypoint_r(psit_file_in, &wpt);
  614. #ifdef DUMP_ICON_TABLE
  615. printf("\t{ %4u, \"%s\" },\n", icon, wpt->shortname);
  616. #endif
  617. } else {
  618. break;
  619. }
  620. }
  621. } while (!gbfeof(psit_file_in));
  622. return;
  623. #ifdef DUMP_ICON_TABLE
  624. printf("\t{ -1, NULL },\n");
  625. printf("};\n");
  626. #endif
  627. }
  628. static void
  629. psit_noop(const route_head* wp)
  630. {
  631. /* no-op */
  632. }
  633. void
  634. psit_write(void)
  635. {
  636. int short_length;
  637. if (snlen) {
  638. short_length = atoi(snlen);
  639. } else {
  640. short_length = 10;
  641. }
  642. mkshort_handle = mkshort_new_handle();
  643. setshort_length(mkshort_handle, short_length);
  644. setshort_whitespace_ok(mkshort_handle, 0);
  645. psit_track_state = 2;
  646. if (global_opts.objective == wptdata) {
  647. waypt_disp_all(psit_waypoint_w_wrapper);
  648. }
  649. if (global_opts.objective == rtedata) {
  650. route_disp_all(psit_routehdr_w_wrapper, psit_noop, psit_waypoint_w_wrapper);
  651. }
  652. if (global_opts.objective == trkdata) {
  653. track_disp_all(psit_trackhdr_w_wrapper,
  654. psit_noop, psit_trackdatapoint_w_wrapper);
  655. }
  656. mkshort_del_handle(&mkshort_handle);
  657. }
  658. ff_vecs_t psit_vecs = {
  659. ff_type_file,
  660. FF_CAP_RW_ALL,
  661. psit_rd_init,
  662. psit_wr_init,
  663. psit_rd_deinit,
  664. psit_wr_deinit,
  665. psit_read,
  666. psit_write,
  667. NULL,
  668. psit_args,
  669. CET_CHARSET_ASCII, 0 /* CET-REVIEW */
  670. };