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.

cst.cc 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. Support for CarteSurTable data file,
  3. Copyright (C) 2005 Olaf Klein, o.b.klein@gpsbabel.org
  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. #include "defs.h"
  17. #include "cet_util.h"
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #define MYNAME "cst"
  21. #undef CST_DEBUG
  22. #define CST_UNKNOWN 0
  23. #define CST_HEADER 1
  24. #define CST_ROUTE 2
  25. #define CST_NOTES 3
  26. #define CST_REFERENCE 4
  27. #define CST_VERSION 5
  28. static gbfile* fin;
  29. static route_head* temp_route;
  30. /* placeholders for options */
  31. static
  32. arglist_t cst_args[] = {
  33. ARG_TERMINATOR
  34. };
  35. /* helpers */
  36. static void
  37. cst_add_wpt(const route_head* track, Waypoint* wpt)
  38. {
  39. if ((wpt == NULL) || (track == NULL)) {
  40. return;
  41. }
  42. if (wpt->shortname != NULL) {
  43. waypt_add(new Waypoint(*wpt));
  44. // Rather than creating a new waypt on each read, tis format bizarrely
  45. // recycles the same one, relying on new waypoint(*) above and then manually
  46. // resetting fields. Weird.
  47. wpt->url_link_list_.clear();
  48. if (temp_route == NULL) {
  49. temp_route = route_head_alloc();
  50. route_add_head(temp_route);
  51. }
  52. route_add_wpt(temp_route, new Waypoint(*wpt));
  53. }
  54. track_add_wpt((route_head*)track, (Waypoint*)wpt);
  55. }
  56. static char*
  57. cst_make_url(char* str)
  58. {
  59. int len = strlen(str);
  60. char* res;
  61. if (len < 3) {
  62. return NULL;
  63. }
  64. if (strstr(str, "://") > str) {
  65. return xstrdup(str);
  66. } else if (strstr(str, ":\\") == str+1) { /* DOS 0.01++ file format */
  67. res = xstrdup("file://*:");
  68. res[7] = *str++;
  69. res[8] = *str++;
  70. res = xstrappend(res, str);
  71. {
  72. char* c;
  73. int i;
  74. c = res; /* replace all backslashes with a slash */
  75. while ((c = strchr(c, '\\'))) {
  76. *c++ = '/';
  77. }
  78. c = res; /* enumerate number of spaces within filename */
  79. i = 0;
  80. while ((c = strchr(c, ' '))) {
  81. c++;
  82. i++;
  83. }
  84. if (i > 0) { /* .. and replace them with "%20" */
  85. char* src, *dest, *last;
  86. last = src = res;
  87. res = dest = (char*) xcalloc(strlen(src) + (2*i) + 1, 1);
  88. while ((c = strchr(src, ' '))) {
  89. if (c != src) {
  90. strncpy(dest, src, c - src);
  91. }
  92. strcat(dest, "%20");
  93. c++;
  94. src = c;
  95. dest = res + strlen(res);
  96. }
  97. while (*src != '\0') {
  98. *dest++ = *src++;
  99. }
  100. xfree(last);
  101. }
  102. }
  103. return res;
  104. } else {
  105. return NULL;
  106. }
  107. }
  108. /* --------------------------------------------------------------------------- */
  109. static void
  110. cst_rd_init(const QString& fname)
  111. {
  112. fin = gbfopen(fname, "rb", MYNAME);
  113. temp_route = NULL;
  114. }
  115. static void
  116. cst_rd_deinit(void)
  117. {
  118. gbfclose(fin);
  119. }
  120. /* --------------------------------------------------------------------------- */
  121. static void
  122. cst_data_read(void)
  123. {
  124. char* buff;
  125. int line = 0;
  126. int data_lines = -1;
  127. int line_of_count = -1;
  128. int valid = 0;
  129. int section = CST_UNKNOWN;
  130. int cst_version;
  131. int cst_points = -1;
  132. route_head* track = NULL;
  133. Waypoint* wpt = NULL;
  134. while ((buff = gbfgetstr(fin))) {
  135. char* cin = buff;
  136. if ((line++ == 0) && fin->unicode) {
  137. cet_convert_init(CET_CHARSET_UTF8, 1);
  138. }
  139. cin = lrtrim(buff);
  140. if (strlen(cin) == 0) {
  141. continue;
  142. }
  143. if (strncmp(cin, "; ", 2) == 0) {
  144. continue;
  145. }
  146. if (*cin == '#') {
  147. section = CST_UNKNOWN;
  148. if (strcmp(cin+1, "ROUTE") == 0) {
  149. section = CST_ROUTE;
  150. } else if (strcmp(cin+1, "VERSION") == 0) {
  151. section = CST_VERSION;
  152. } else if (strcmp(cin+1, "NOTES") == 0) {
  153. section = CST_NOTES;
  154. } else if (strcmp(cin+1, "REFERENCE") == 0) {
  155. section = CST_REFERENCE;
  156. } else if (strcmp(cin+1, "CARTE SUR TABLE DATA FILE") == 0) {
  157. section = CST_HEADER;
  158. valid = 1;
  159. } else {
  160. warning(MYNAME ": Unknown section \"%s\".\n", cin+1);
  161. }
  162. continue;
  163. }
  164. if (valid == 0) {
  165. continue;
  166. }
  167. switch (section) {
  168. case CST_ROUTE:
  169. if (*cin == ';') {
  170. int data = 0;
  171. if (*(cin+1) != '\xA4') {
  172. continue;
  173. }
  174. if (strncmp(cin + 2, "bitmap", 6) == 0) {
  175. cin = lrtrim(cin + 8);
  176. if (*cin != '\0') {
  177. char* url = cst_make_url(cin);
  178. wpt->AddUrlLink(url);
  179. if (url) {
  180. xfree(url);
  181. }
  182. }
  183. }
  184. while ((buff = gbfgetstr(fin))) {
  185. line++;
  186. cin = lrtrim(buff);
  187. if (strcmp(cin + 2, "note") == 0) {
  188. buff = gbfgetstr(fin);
  189. if (buff == NULL) {
  190. buff = (char*) "";
  191. }
  192. line++;
  193. cin = lrtrim(buff);
  194. if (*cin != '\0') {
  195. wpt->notes = QString::fromLatin1(cin);
  196. }
  197. } else if (strcmp(cin + 2, "end") == 0) {
  198. data = 1;
  199. break;
  200. }
  201. }
  202. if (data == 0) {
  203. fatal(MYNAME ": Unexpected end of file!\n");
  204. }
  205. } else {
  206. int interp, i;
  207. char name[256];
  208. if (data_lines < 0) {
  209. if ((2 != sscanf(cin, "%d %128s", &i, name)) ||
  210. (case_ignore_strcmp(name, "Points") != 0)) {
  211. fatal(MYNAME "-line %d: Number of points expected!\n", line);
  212. }
  213. line_of_count = line;
  214. data_lines = 0;
  215. cst_points = i;
  216. continue;
  217. }
  218. cst_add_wpt(track, wpt);
  219. wpt = NULL;
  220. wpt = new Waypoint;
  221. if (5 != sscanf(cin, "%lf %lf %lf %d %s",
  222. &wpt->longitude,
  223. &wpt->latitude,
  224. &wpt->altitude,
  225. &interp, name)) {
  226. fatal(MYNAME ": Could not interprete line %d!\n", line);
  227. }
  228. data_lines++;
  229. if (strcmp(name, "1") == 0) {
  230. track = route_head_alloc();
  231. track_add_head(track);
  232. } else if (strncmp(name, "NAME:", 5) == 0) {
  233. wpt->shortname = QString::fromLatin1(((char*)&name) + 5);
  234. }
  235. QString time_string(cin);
  236. int caret = time_string.indexOf('^');
  237. if (caret > -1) {
  238. QString dts = time_string.mid(caret + 1).trimmed();
  239. QDateTime dt = QDateTime::fromString(dts, "yyyy MM dd hh:mm:ss");
  240. dt.setTimeSpec(Qt::UTC);
  241. wpt->SetCreationTime(dt);
  242. }
  243. wpt->latitude /= 100000.0;
  244. wpt->longitude /= 100000.0;
  245. }
  246. break;
  247. case CST_VERSION:
  248. cst_version = atoi(cin);
  249. if (cst_version != 40) {
  250. warning(MYNAME ": Not tested with file version %d.\n", cst_version);
  251. }
  252. break;
  253. case CST_REFERENCE:
  254. if ((strncmp(cin, "DATUM ", 6) == 0) && (strstr(cin, "WGS 84") == NULL)) {
  255. fatal(MYNAME ": Unsupported datum (%s)!\n", cin);
  256. }
  257. break;
  258. case CST_HEADER:
  259. case CST_NOTES:
  260. break;
  261. }
  262. }
  263. cst_add_wpt(track, wpt);
  264. wpt = NULL;
  265. if ((cst_points >= 0) && (data_lines != cst_points)) {
  266. warning(MYNAME ": Loaded %d point(s), but line %d says %d!\n", data_lines, line_of_count, cst_points);
  267. }
  268. }
  269. ff_vecs_t cst_vecs = {
  270. ff_type_file,
  271. { ff_cap_read, ff_cap_read, ff_cap_read },
  272. cst_rd_init,
  273. NULL, /* cst_wr_init, */
  274. cst_rd_deinit,
  275. NULL, /* cst_wr_deinit, */
  276. cst_data_read,
  277. NULL, /* cst_data_write, */
  278. NULL,
  279. cst_args,
  280. CET_CHARSET_MS_ANSI, 0 /* CET-REVIEW */
  281. };