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.

main.cc 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  1. /*
  2. Copyright (C) 2002-2005 Robert Lipe, robertlipe+source@gpsbabel.org
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  14. */
  15. #include <QtCore/QTextCodec>
  16. #include <QtCore/QCoreApplication>
  17. #include "defs.h"
  18. #include "filterdefs.h"
  19. #include "cet.h"
  20. #include "cet_util.h"
  21. #include "csv_util.h"
  22. #include "inifile.h"
  23. #include "session.h"
  24. #include "src/core/usasciicodec.h"
  25. #include <ctype.h>
  26. #include <locale.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <signal.h>
  30. #define MYNAME "main"
  31. void signal_handler(int sig);
  32. typedef struct arg_stack_s {
  33. int argn;
  34. int argc;
  35. char** argv;
  36. struct arg_stack_s* prev;
  37. } arg_stack_t;
  38. static arg_stack_t
  39. * push_args(arg_stack_t* stack, const int argn, const int argc, char* argv[])
  40. {
  41. arg_stack_t* res = (arg_stack_t*) xmalloc(sizeof(*res));
  42. res->prev = stack;
  43. res->argn = argn;
  44. res->argc = argc;
  45. res->argv = (char**)argv;
  46. return res;
  47. }
  48. static arg_stack_t
  49. * pop_args(arg_stack_t* stack, int* argn, int* argc, char** argv[])
  50. {
  51. arg_stack_t* res;
  52. char** argv2 = *argv;
  53. int i;
  54. if (stack == NULL) {
  55. fatal("main: Invalid point in time to call 'pop_args'\n");
  56. }
  57. for (i = 0; i < *argc; i++) {
  58. xfree(argv2[i]);
  59. }
  60. xfree(*argv);
  61. *argn = stack->argn;
  62. *argc = stack->argc;
  63. *argv = stack->argv;
  64. res = stack->prev;
  65. xfree(stack);
  66. return res;
  67. }
  68. static void
  69. load_args(const char* filename, int* argc, char** argv[])
  70. {
  71. gbfile* fin;
  72. char* str, *line = NULL;
  73. int argc2;
  74. char** argv2;
  75. fin = gbfopen(filename, "r", "main");
  76. while ((str = gbfgetstr(fin))) {
  77. str = lrtrim(str);
  78. if ((*str == '\0') || (*str == '#')) {
  79. continue;
  80. }
  81. if (line == NULL) {
  82. line = xstrdup(str);
  83. } else {
  84. char* tmp;
  85. xasprintf(&tmp, "%s %s", line, str);
  86. xfree(line);
  87. line = tmp;
  88. }
  89. }
  90. gbfclose(fin);
  91. argv2 = (char**) xmalloc(2 * sizeof(*argv2));
  92. argv2[0] = xstrdup(*argv[0]);
  93. argc2 = 1;
  94. str = csv_lineparse(line, " ", "\"", 0);
  95. while (str != NULL) {
  96. argv2 = (char**) xrealloc(argv2, (argc2 + 2) * sizeof(*argv2));
  97. argv2[argc2] = xstrdup(str);
  98. argc2++;
  99. str = csv_lineparse(NULL, " ", "\"", 0);
  100. }
  101. xfree(line);
  102. argv2[argc2] = NULL;
  103. *argc = argc2;
  104. *argv = argv2;
  105. }
  106. static void
  107. usage(const char* pname, int shorter)
  108. {
  109. printf("GPSBabel Version %s. http://www.gpsbabel.org\n\n",
  110. gpsbabel_version);
  111. printf(
  112. "Usage:\n"
  113. " %s [options] -i INTYPE -f INFILE [filter] -o OUTTYPE -F OUTFILE\n"
  114. " %s [options] -i INTYPE -o OUTTYPE INFILE [filter] OUTFILE\n"
  115. "\n"
  116. " Converts GPS route and waypoint data from one format type to another.\n"
  117. " The input type and filename are specified with the -i INTYPE\n"
  118. " and -f INFILE options. The output type and filename are specified\n"
  119. " with the -o OUTTYPE and -F OUTFILE options.\n"
  120. " If '-' is used for INFILE or OUTFILE, stdin or stdout will be used.\n"
  121. "\n"
  122. " In the second form of the command, INFILE and OUTFILE are the\n"
  123. " first and second positional (non-option) arguments.\n"
  124. "\n"
  125. " INTYPE and OUTTYPE must be one of the supported file types and\n"
  126. " may include options valid for that file type. For example:\n"
  127. " 'gpx', 'gpx,snlen=10' and 'ozi,snlen=10,snwhite=1'\n"
  128. " (without the quotes) are all valid file type specifications.\n"
  129. "\n"
  130. "Options:\n"
  131. " -p Preferences file (gpsbabel.ini)\n"
  132. " -s Synthesize shortnames\n"
  133. " -r Process route information\n"
  134. " -t Process track information\n"
  135. " -T Process realtime tracking information\n"
  136. " -w Process waypoint information [default]\n"
  137. " -b Process command file (batch mode)\n"
  138. " -N No smart icons on output\n"
  139. " -x filtername Invoke filter (placed between inputs and output) \n"
  140. " -D level Set debug level [%d]\n"
  141. " -h, -? Print detailed help and exit\n"
  142. " -V Print GPSBabel version and exit\n"
  143. "\n"
  144. , pname
  145. , pname
  146. , global_opts.debug_level
  147. );
  148. if (shorter) {
  149. printf("\n\n[Press enter]");
  150. fgetc(stdin);
  151. } else {
  152. printf("File Types (-i and -o options):\n");
  153. disp_vecs();
  154. printf("\nSupported data filters:\n");
  155. disp_filter_vecs();
  156. }
  157. }
  158. static void
  159. spec_usage(const char* vec)
  160. {
  161. printf("\n");
  162. disp_vec(vec);
  163. disp_filter_vec(vec);
  164. printf("\n");
  165. }
  166. static void
  167. print_extended_info(void)
  168. {
  169. printf(
  170. #if !ZLIB_INHIBITED /* Note polarity inverted here */
  171. "ZLIB_ENABLED "
  172. #endif
  173. #if FILTERS_ENABLED
  174. "FILTERS_ENABLED "
  175. #endif
  176. #if CSVFMTS_ENABLED
  177. "CSVFMTS_ENABLED "
  178. #endif
  179. #if PDBFMTS_ENABLED
  180. "PDBFMTS_ENABLED "
  181. #endif
  182. #if SHAPELIB_ENABLED
  183. "SHAPELIB_ENABLED "
  184. #endif
  185. #if defined CET_WANTED
  186. "CET_ENABLED "
  187. #endif
  188. "\n");
  189. }
  190. int
  191. main(int argc, char* argv[])
  192. {
  193. int c;
  194. int argn;
  195. ff_vecs_t* ivecs = NULL;
  196. ff_vecs_t* ovecs = NULL;
  197. filter_vecs_t* fvecs = NULL;
  198. char* fname = NULL;
  199. char* ofname = NULL;
  200. const char* ivec_opts = NULL;
  201. const char* ovec_opts = NULL;
  202. char* fvec_opts = NULL;
  203. int opt_version = 0;
  204. int did_something = 0;
  205. const char* prog_name = argv[0]; /* argv is modified during processing */
  206. queue* wpt_head_bak, *rte_head_bak, *trk_head_bak; /* #ifdef UTF8_SUPPORT */
  207. signed int wpt_ct_bak, rte_ct_bak, trk_ct_bak; /* #ifdef UTF8_SUPPORT */
  208. arg_stack_t* arg_stack = NULL;
  209. // Create a QCoreApplication object to handle application initialization.
  210. // TODO: Someday we may actually use this, but for now we are just trying
  211. // to get Qt initialized, especially locale related QTextCodec stuff.
  212. // For example, this will get the QTextCodec::codecForLocale set
  213. // correctly.
  214. QCoreApplication app(argc, argv);
  215. // TODO: use QCoreApplication::arguments() to process command line.
  216. (void) new gpsbabel::UsAsciiCodec(); /* make sure a US-ASCII codec is available */
  217. #if (QT_VERSION < QT_VERSION_CHECK(5, 2, 0))
  218. #error This version of Qt is not supported.
  219. #endif
  220. // The first invocation of QTextCodec::codecForLocale() may result in LC_ALL being set to the native environment
  221. // as opposed to the initial default "C" locale.
  222. // This was demonstrated with Qt5 on Mac OS X.
  223. // TODO: This need to invoke QTextCodec::codecForLocale() may be taken care of
  224. // by creating a QCoreApplication.
  225. #ifdef DEBUG_LOCALE
  226. printf("Initial locale: %s\n",setlocale(LC_ALL, NULL));
  227. #endif
  228. (void) QTextCodec::codecForLocale();
  229. #ifdef DEBUG_LOCALE
  230. printf("Locale after codedForLocale: %s\n",setlocale(LC_ALL, NULL));
  231. #endif
  232. // As recommended in QCoreApplication reset the locale to the default.
  233. // Note the documentation says to set LC_NUMERIC, but QCoreApplicationPrivate::initLocale()
  234. // actually sets LC_ALL.
  235. // Perhaps we should restore LC_ALL instead of only LC_NUMERIC.
  236. if (strcmp(setlocale(LC_NUMERIC,0), "C") != 0) {
  237. #ifdef DEBUG_LOCALE
  238. printf("Resetting LC_NUMERIC\n");
  239. #endif
  240. setlocale(LC_NUMERIC,"C");
  241. #ifdef DEBUG_LOCALE
  242. printf("LC_ALL: %s\n",setlocale(LC_ALL, NULL));
  243. #endif
  244. }
  245. /* reset LC_TIME for strftime */
  246. if (strcmp(setlocale(LC_TIME,0), "C") != 0) {
  247. #ifdef DEBUG_LOCALE
  248. printf("Resetting LC_TIME\n");
  249. #endif
  250. setlocale(LC_TIME,"C");
  251. #ifdef DEBUG_LOCALE
  252. printf("LC_ALL: %s\n",setlocale(LC_ALL, NULL));
  253. #endif
  254. }
  255. global_opts.objective = wptdata;
  256. global_opts.masked_objective = NOTHINGMASK; /* this makes the default mask behaviour slightly different */
  257. global_opts.charset_name.clear();
  258. global_opts.inifile = NULL;
  259. gpsbabel_now = time(NULL); /* gpsbabel startup-time */
  260. gpsbabel_time = current_time().toTime_t(); /* same like gpsbabel_now, but freezed to zero during testo */
  261. #ifdef DEBUG_MEM
  262. debug_mem_open();
  263. debug_mem_output("command line: ");
  264. for (argn = 1; argn < argc; argn++) {
  265. debug_mem_output("%s ", argv[argn]);
  266. }
  267. debug_mem_output("\n");
  268. #endif
  269. if (gpsbabel_time != 0) { /* within testo ? */
  270. global_opts.inifile = inifile_init(NULL, MYNAME);
  271. }
  272. init_vecs();
  273. init_filter_vecs();
  274. cet_register();
  275. session_init();
  276. waypt_init();
  277. route_init();
  278. if (argc < 2) {
  279. usage(argv[0],1);
  280. exit(0);
  281. }
  282. /*
  283. * Open-code getopts since POSIX-impaired OSes don't have one.
  284. */
  285. argn = 1;
  286. while (argn < argc) {
  287. char* optarg;
  288. if (argv[argn][0] != '-') {
  289. break;
  290. }
  291. if (argv[argn][1] == '-') {
  292. break;
  293. }
  294. if (argv[argn][1] == 'V') {
  295. printf("\nGPSBabel Version %s\n\n", gpsbabel_version);
  296. if (argv[argn][2] == 'V') {
  297. print_extended_info();
  298. }
  299. exit(0);
  300. }
  301. if (argv[argn][1] == '?' || argv[argn][1] == 'h') {
  302. if (argn < argc-1) {
  303. spec_usage(argv[argn+1]);
  304. } else {
  305. usage(argv[0],0);
  306. }
  307. exit(0);
  308. }
  309. c = argv[argn][1];
  310. if (argv[argn][2]) {
  311. opt_version = atoi(&argv[argn][2]);
  312. }
  313. switch (c) {
  314. //case 'c':
  315. // optarg = argv[argn][2] ? argv[argn]+2 : argv[++argn];
  316. // cet_convert_init(optarg, 1);
  317. // break;
  318. case 'i':
  319. optarg = argv[argn][2]
  320. ? argv[argn]+2 : argv[++argn];
  321. ivecs = find_vec(optarg, &ivec_opts);
  322. if (ivecs == NULL) {
  323. fatal("Input type '%s' not recognized\n", optarg);
  324. }
  325. break;
  326. case 'o':
  327. if (ivecs == NULL) {
  328. warning("-o appeared before -i. This is probably not what you want to do.\n");
  329. }
  330. optarg = argv[argn][2]
  331. ? argv[argn]+2 : argv[++argn];
  332. ovecs = find_vec(optarg, &ovec_opts);
  333. if (ovecs == NULL) {
  334. fatal("Output type '%s' not recognized\n", optarg);
  335. }
  336. break;
  337. case 'f':
  338. optarg = argv[argn][2]
  339. ? argv[argn]+2 : argv[++argn];
  340. fname = optarg;
  341. if (fname == NULL) {
  342. fatal("No file or device name specified.\n");
  343. }
  344. if (ivecs == NULL) {
  345. fatal("No valid input type specified\n");
  346. }
  347. if (ivecs->rd_init == NULL) {
  348. fatal("Format does not support reading.\n");
  349. }
  350. if (global_opts.masked_objective & POSNDATAMASK) {
  351. did_something = 1;
  352. break;
  353. }
  354. /* simulates the default behaviour of waypoints */
  355. if (doing_nothing) {
  356. global_opts.masked_objective |= WPTDATAMASK;
  357. }
  358. cet_convert_init(ivecs->encode, ivecs->fixed_encode); /* init by module vec */
  359. start_session(ivecs->name, fname);
  360. ivecs->rd_init(QString::fromLocal8Bit(fname));
  361. ivecs->read();
  362. ivecs->rd_deinit();
  363. cet_convert_strings(global_opts.charset, NULL, NULL);
  364. cet_convert_deinit();
  365. did_something = 1;
  366. break;
  367. case 'F':
  368. optarg = argv[argn][2]
  369. ? argv[argn]+2 : argv[++argn];
  370. ofname = optarg;
  371. if (ofname == NULL) {
  372. fatal("No output file or device name specified.\n");
  373. }
  374. if (ovecs && (!(global_opts.masked_objective & POSNDATAMASK))) {
  375. /* simulates the default behaviour of waypoints */
  376. if (doing_nothing) {
  377. global_opts.masked_objective |= WPTDATAMASK;
  378. }
  379. if (ovecs->wr_init == NULL) {
  380. fatal("Format does not support writing.\n");
  381. }
  382. cet_convert_init(ovecs->encode, ovecs->fixed_encode);
  383. wpt_ct_bak = -1;
  384. rte_ct_bak = -1;
  385. trk_ct_bak = -1;
  386. rte_head_bak = trk_head_bak = NULL;
  387. ovecs->wr_init(QString::fromLocal8Bit(ofname));
  388. if (global_opts.charset != &cet_cs_vec_utf8) {
  389. /*
  390. * Push and pop verbose_status so
  391. * we don't get dual progress bars
  392. * when doing characterset
  393. * transformation.
  394. */
  395. int saved_status = global_opts.verbose_status;
  396. global_opts.verbose_status = 0;
  397. waypt_backup(&wpt_ct_bak, &wpt_head_bak);
  398. route_backup(&rte_ct_bak, &rte_head_bak);
  399. track_backup(&trk_ct_bak, &trk_head_bak);
  400. cet_convert_strings(NULL, global_opts.charset, NULL);
  401. global_opts.verbose_status = saved_status;
  402. }
  403. ovecs->write();
  404. ovecs->wr_deinit();
  405. cet_convert_deinit();
  406. if (wpt_ct_bak != -1) {
  407. waypt_restore(wpt_ct_bak, wpt_head_bak);
  408. }
  409. if (rte_ct_bak != -1) {
  410. route_restore(rte_head_bak);
  411. xfree(rte_head_bak);
  412. }
  413. if (trk_ct_bak != -1) {
  414. track_restore(trk_head_bak);
  415. xfree(trk_head_bak);
  416. }
  417. }
  418. break;
  419. case 's':
  420. global_opts.synthesize_shortnames = 1;
  421. break;
  422. case 't':
  423. global_opts.objective = trkdata;
  424. global_opts.masked_objective |= TRKDATAMASK;
  425. break;
  426. case 'w':
  427. global_opts.objective = wptdata;
  428. global_opts.masked_objective |= WPTDATAMASK;
  429. break;
  430. case 'r':
  431. global_opts.objective = rtedata;
  432. global_opts.masked_objective |= RTEDATAMASK;
  433. break;
  434. case 'T':
  435. global_opts.objective = posndata;
  436. global_opts.masked_objective |= POSNDATAMASK;
  437. break;
  438. case 'N':
  439. #if 0
  440. /* This option is silently eaten for compatibilty. -N is now the
  441. * default. If you want the old behaviour, -S allows you to individually
  442. * turn them on. The -N option will be removed in 2008.
  443. */
  444. switch (argv[argn][2]) {
  445. case 'i':
  446. global_opts.no_smart_icons = 1;
  447. break;
  448. case 'n':
  449. global_opts.no_smart_names = 1;
  450. break;
  451. default:
  452. global_opts.no_smart_names = 1;
  453. global_opts.no_smart_icons = 1;
  454. break;
  455. }
  456. #endif
  457. break;
  458. case 'S':
  459. switch (argv[argn][2]) {
  460. case 'i':
  461. global_opts.smart_icons = 1;
  462. break;
  463. case 'n':
  464. global_opts.smart_names = 1;
  465. break;
  466. default:
  467. global_opts.smart_icons = 1;
  468. global_opts.smart_names = 1;
  469. break;
  470. }
  471. break;
  472. case 'x':
  473. optarg = argv[argn][2]
  474. ? argv[argn]+2 : argv[++argn];
  475. fvecs = find_filter_vec(optarg, &fvec_opts);
  476. if (fvecs) {
  477. if (fvecs->f_init) {
  478. fvecs->f_init(fvec_opts);
  479. }
  480. fvecs->f_process();
  481. if (fvecs->f_deinit) {
  482. fvecs->f_deinit();
  483. }
  484. free_filter_vec(fvecs);
  485. } else {
  486. fatal("Unknown filter '%s'\n",optarg);
  487. }
  488. break;
  489. case 'D':
  490. optarg = argv[argn][2]
  491. ? argv[argn]+2 : argv[++argn];
  492. global_opts.debug_level = atoi(optarg);
  493. /*
  494. * When debugging, announce version.
  495. */
  496. if (global_opts.debug_level > 0) {
  497. warning("GPSBabel Version: %s \n", gpsbabel_version);
  498. }
  499. break;
  500. /*
  501. * Undocumented '-vs' option for GUI wrappers.
  502. */
  503. case 'v':
  504. switch (argv[argn][2]) {
  505. case 's':
  506. global_opts.verbose_status = 1;
  507. break;
  508. case 'S':
  509. global_opts.verbose_status = 2;
  510. break;
  511. }
  512. break;
  513. /*
  514. * DOS-derived systems will need to escape
  515. * this as -^^.
  516. */
  517. case '^':
  518. disp_formats(opt_version);
  519. exit(0);
  520. case '%':
  521. disp_filters(opt_version);
  522. exit(0);
  523. case 'h':
  524. case '?':
  525. usage(argv[0],0);
  526. exit(0);
  527. case 'p':
  528. optarg = argv[argn][2] ? argv[argn]+2 : argv[++argn];
  529. inifile_done(global_opts.inifile);
  530. if (!optarg || strcmp(optarg, "") == 0) { /* from GUI to preserve inconsistent options */
  531. global_opts.inifile = NULL;
  532. } else {
  533. global_opts.inifile = inifile_init(optarg, MYNAME);
  534. }
  535. break;
  536. case 'b':
  537. optarg = argv[argn][2] ? argv[argn]+2 : argv[++argn];
  538. arg_stack = push_args(arg_stack, argn, argc, argv);
  539. load_args(optarg, &argc, &argv);
  540. if (argc == 0) {
  541. arg_stack = pop_args(arg_stack, &argn, &argc, &argv);
  542. } else {
  543. argn = 0;
  544. }
  545. break;
  546. default:
  547. fatal("Unknown option '%s'.\n", argv[argn]);
  548. break;
  549. }
  550. if ((argn+1 >= argc) && (arg_stack != NULL)) {
  551. arg_stack = pop_args(arg_stack, &argn, &argc, &argv);
  552. }
  553. argn++;
  554. }
  555. /*
  556. * Allow input and output files to be specified positionally
  557. * as well. This is the typical command line format.
  558. */
  559. argc -= argn;
  560. argv += argn;
  561. if (argc > 2) {
  562. fatal("Extra arguments on command line\n");
  563. } else if (argc && ivecs) {
  564. did_something = 1;
  565. /* simulates the default behaviour of waypoints */
  566. if (doing_nothing) {
  567. global_opts.masked_objective |= WPTDATAMASK;
  568. }
  569. cet_convert_init(ivecs->encode, 1);
  570. start_session(ivecs->name, argv[0]);
  571. if (ivecs->rd_init == NULL) {
  572. fatal("Format does not support reading.\n");
  573. }
  574. ivecs->rd_init(QString::fromLocal8Bit(argv[0]));
  575. ivecs->read();
  576. ivecs->rd_deinit();
  577. cet_convert_strings(global_opts.charset, NULL, NULL);
  578. cet_convert_deinit();
  579. if (argc == 2 && ovecs) {
  580. cet_convert_init(ovecs->encode, 1);
  581. cet_convert_strings(NULL, global_opts.charset, NULL);
  582. if (ovecs->wr_init == NULL) {
  583. fatal("Format does not support writing.\n");
  584. }
  585. ovecs->wr_init(QString::fromLocal8Bit(argv[1]));
  586. ovecs->write();
  587. ovecs->wr_deinit();
  588. cet_convert_deinit();
  589. }
  590. } else if (argc) {
  591. usage(prog_name,0);
  592. exit(0);
  593. }
  594. if (ovecs == NULL) {
  595. /*
  596. * Push and pop verbose_status so we don't get dual
  597. * progress bars when doing characterset transformation.
  598. */
  599. int saved_status = global_opts.verbose_status;
  600. global_opts.verbose_status = 0;
  601. cet_convert_init(CET_CHARSET_ASCII, 1);
  602. cet_convert_strings(NULL, global_opts.charset, NULL);
  603. waypt_disp_all(waypt_disp);
  604. global_opts.verbose_status = saved_status;
  605. }
  606. /*
  607. * This is very unlike the rest of our command sequence.
  608. * If we're doing realtime position tracking, we enforce that
  609. * we're not doing anything else and we just bounce between
  610. * the special "read position" and "write position" vectors
  611. * in our most recent vecs.
  612. */
  613. if (global_opts.masked_objective & POSNDATAMASK) {
  614. if (!ivecs) {
  615. fatal("Realtime tracking (-T) requires an input type (-t)i such as Garmin or NMEA.\n");
  616. }
  617. if (!ivecs->position_ops.rd_position) {
  618. fatal("Realtime tracking (-T) is not suppored by this input type.\n");
  619. }
  620. if (ivecs->position_ops.rd_init) {
  621. if (!fname) {
  622. fatal("An input file (-f) must be specified.\n");
  623. }
  624. start_session(ivecs->name, fname);
  625. ivecs->position_ops.rd_init(QString::fromLocal8Bit(fname));
  626. }
  627. if (global_opts.masked_objective & ~POSNDATAMASK) {
  628. fatal("Realtime tracking (-T) is exclusive of other modes.\n");
  629. }
  630. if (ovecs) {
  631. if (!ovecs->position_ops.wr_position) {
  632. fatal("This output format does not support output of realtime positioning.\n");
  633. }
  634. }
  635. if (signal(SIGINT, signal_handler) == SIG_ERR) {
  636. fatal("Couldn't install the exit signal handler.\n");
  637. }
  638. if (ovecs && ovecs->position_ops.wr_init) {
  639. ovecs->position_ops.wr_init(QString::fromLocal8Bit(ofname));
  640. }
  641. tracking_status.request_terminate = 0;
  642. while (!tracking_status.request_terminate) {
  643. Waypoint* wpt;
  644. wpt = ivecs->position_ops.rd_position(&tracking_status);
  645. if (tracking_status.request_terminate) {
  646. if (wpt) {
  647. delete wpt;
  648. }
  649. break;
  650. }
  651. if (wpt) {
  652. if (ovecs) {
  653. // ovecs->position_ops.wr_init(QString::fromLocal8Bit(ofname));
  654. ovecs->position_ops.wr_position(wpt);
  655. // ovecs->position_ops.wr_deinit();
  656. } else {
  657. /* Just print to screen */
  658. waypt_disp(wpt);
  659. }
  660. delete wpt;
  661. }
  662. }
  663. if (ivecs->position_ops.rd_deinit) {
  664. ivecs->position_ops.rd_deinit();
  665. }
  666. if (ovecs && ovecs->position_ops.wr_deinit) {
  667. ovecs->position_ops.wr_deinit();
  668. }
  669. exit(0);
  670. }
  671. if (!did_something) {
  672. fatal("Nothing to do! Use '%s -h' for command-line options.\n", prog_name);
  673. }
  674. cet_deregister();
  675. waypt_flush_all();
  676. route_flush_all();
  677. session_exit();
  678. exit_vecs();
  679. exit_filter_vecs();
  680. inifile_done(global_opts.inifile);
  681. #ifdef DEBUG_MEM
  682. debug_mem_close();
  683. #endif
  684. exit(0);
  685. }
  686. void signal_handler(int sig)
  687. {
  688. (void)sig;
  689. tracking_status.request_terminate = 1;
  690. }