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.

296 lines
6.3KB

  1. /*
  2. Support for Navigon Mobile Navigator .rte files.
  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. /*
  17. line structure, items delimited by '|'
  18. -|-|17|-|ZIP-Code|City|ZIP-Code2|Street|No.|-|-|longitude|latitude|-|-| + 0D0A
  19. */
  20. #include "defs.h"
  21. #include "cet_util.h"
  22. #include "csv_util.h"
  23. #include <ctype.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdarg.h>
  27. static gbfile* fin, *fout;
  28. static int curr_rte_num, target_rte_num;
  29. #define MYNAME "navigon"
  30. static char* index_opt;
  31. static
  32. arglist_t nmn4_args[] = {
  33. {"index", &index_opt, "Index of route to write (if more than one in source)", NULL, ARGTYPE_INT, "1", NULL },
  34. ARG_TERMINATOR
  35. };
  36. static void
  37. nmn4_check_line(char* line)
  38. {
  39. char* c = line;
  40. int i = 0;
  41. while ((c = strchr(c, '|'))) {
  42. c++;
  43. i++;
  44. }
  45. is_fatal((i != 15),
  46. MYNAME ": Invalid or unknown structure!");
  47. }
  48. static void
  49. nmn4_read_data(void)
  50. {
  51. char* buff;
  52. char* str;
  53. QString c;
  54. int column;
  55. int line = 0;
  56. QString zip1, zip2, city, street, number;
  57. route_head* route;
  58. Waypoint* wpt;
  59. route = route_head_alloc();
  60. route_add_head(route);
  61. while ((buff = gbfgetstr(fin))) {
  62. if ((line++ == 0) && fin->unicode) {
  63. cet_convert_init(CET_CHARSET_UTF8, 1);
  64. }
  65. str = buff = lrtrim(buff);
  66. if (*buff == '\0') {
  67. continue;
  68. }
  69. nmn4_check_line(buff);
  70. /* for a quiet compiler */
  71. zip1 = zip2 = city = street = number = QString();
  72. wpt = new Waypoint;
  73. column = -1;
  74. c = csv_lineparse(str, "|", "", column++);
  75. while (c != NULL) {
  76. switch (column) {
  77. case 0: /* "-" */ /* unknown fields for the moment */
  78. case 1: /* "-" */
  79. case 2: /* "-" */
  80. case 3: /* "-" */
  81. case 9: /* "-" */
  82. case 10: /* "-" */
  83. case 13: /* "-" */
  84. case 14: /* "-" */
  85. case 15: /* "" */
  86. break;
  87. case 4: /* ZIP Code */
  88. if (c[0] != '-') {
  89. zip1 = c;
  90. }
  91. break;
  92. case 5: /* City */
  93. if (c[0] != '-') {
  94. city = c;
  95. }
  96. break;
  97. case 6: /* ZIP Code -2- */
  98. if (c[0] != '-') {
  99. zip2 = c;
  100. }
  101. break;
  102. case 7: /* Street */
  103. if (c[0] != '-') {
  104. street = c;
  105. }
  106. break;
  107. case 8: /* Number */
  108. if (c[0] != '-') {
  109. number = c;
  110. }
  111. /*
  112. This is our final index
  113. All stuff for generating names or comments
  114. is hold locally.
  115. We don't have fields for street, city or zip-code.
  116. Instead we construct a description from that.
  117. */
  118. if (zip1 == zip2) {
  119. zip2 = QString();
  120. }
  121. if (!city.isEmpty()) {
  122. /*
  123. if any field following city has a value, add a comma to city
  124. */
  125. if (!street.isEmpty() || !number.isEmpty() || !zip2.isEmpty()) {
  126. city += ",";
  127. }
  128. }
  129. /* concats all fields to one string and release */
  130. wpt->description = zip1.trimmed() + " " +
  131. city.trimmed() + " " +
  132. street.trimmed() + " " +
  133. number.trimmed() + " " +
  134. zip2.trimmed();
  135. break;
  136. case 11: /* longitude */
  137. wpt->longitude = c.toDouble();
  138. break;
  139. case 12: /* latitude */
  140. wpt->latitude = c.toDouble();
  141. break;
  142. }
  143. c = QString::fromLatin1(csv_lineparse(NULL, "|", "", column++));
  144. }
  145. route_add_wpt(route, wpt);
  146. }
  147. }
  148. static void
  149. nmn4_route_hdr(const route_head* route)
  150. {
  151. curr_rte_num++;
  152. }
  153. static void
  154. nmn4_route_tlr(const route_head* rte)
  155. {
  156. }
  157. static void
  158. nmn4_write_waypt(const Waypoint* wpt)
  159. {
  160. char city[128], street[128], zipc[32], number[32];
  161. if (curr_rte_num != target_rte_num) {
  162. return;
  163. }
  164. strncpy(city, "-", sizeof(city));
  165. strncpy(street, "-", sizeof(street));
  166. strncpy(zipc, "-", sizeof(zipc));
  167. strncpy(number, "-", sizeof(number));
  168. /*
  169. Population of specific data used by Navigon may come in the
  170. future or it may be impossible. We currently output only the
  171. coordinates in the output, but this is sufficient for Navigon.
  172. The coordinates are the only item we are about guaranteed to have
  173. when converting to any from any format, so we leave the other
  174. fields unpopulated. So i have to pay Navigon a compliment for
  175. implementing a simple data exchange.
  176. */
  177. gbfprintf(fout, "-|-|-|-|%s|%s|%s|%s|%s|-|-|%.5f|%.5f|-|-|\r\n",
  178. zipc, city, zipc, street, number,
  179. wpt->longitude, wpt->latitude);
  180. }
  181. static void
  182. nmn4_write_data(void)
  183. {
  184. target_rte_num = 1;
  185. if (index_opt != NULL) {
  186. target_rte_num = atoi(index_opt);
  187. is_fatal(((target_rte_num > (int) route_count()) || (target_rte_num < 1)),
  188. MYNAME ": invalid route number %d (1..%d))!\n", target_rte_num, route_count());
  189. }
  190. curr_rte_num = 0;
  191. route_disp_all(nmn4_route_hdr, nmn4_route_tlr, nmn4_write_waypt);
  192. }
  193. /* %%% global callbacks %%% */
  194. static void
  195. nmn4_rd_init(const QString& fname)
  196. {
  197. fin = gbfopen(fname, "rb", MYNAME);
  198. }
  199. static void
  200. nmn4_rd_deinit(void)
  201. {
  202. gbfclose(fin);
  203. }
  204. static void
  205. nmn4_read(void)
  206. {
  207. nmn4_read_data();
  208. }
  209. static void
  210. nmn4_wr_init(const QString& fname)
  211. {
  212. fout = gbfopen(fname, "wb", MYNAME);
  213. }
  214. static void
  215. nmn4_wr_deinit(void)
  216. {
  217. gbfclose(fout);
  218. }
  219. static void
  220. nmn4_write(void)
  221. {
  222. nmn4_write_data();
  223. }
  224. /* --------------------------------------------------------------------------- */
  225. ff_vecs_t nmn4_vecs = {
  226. ff_type_file,
  227. { ff_cap_none, ff_cap_none, (ff_cap)(ff_cap_read | ff_cap_write)},
  228. nmn4_rd_init,
  229. nmn4_wr_init,
  230. nmn4_rd_deinit,
  231. nmn4_wr_deinit,
  232. nmn4_read,
  233. nmn4_write,
  234. NULL,
  235. nmn4_args,
  236. CET_CHARSET_MS_ANSI, 1 /* CET-REVIEW */
  237. };