2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 static void a_gpspoint_write_track ( const gchar
*name
, VikTrack
*t
, FILE *f
);
32 static void a_gpspoint_write_trackpoint ( VikTrackpoint
*tp
, FILE *f
);
33 static void a_gpspoint_write_waypoint ( const gchar
*name
, VikWaypoint
*wp
, FILE *f
);
36 /* outline for file gpspoint.c
41 get first tag, if not type, skip it.
42 if type, record type. if waypoint list, etc move on. if track, make a new track, make it current track, add it, etc.
43 if waypoint, read on and store to the waypoint.
44 if trackpoint, make trackpoint, store to current track (error / skip if none)
48 /* Thanks to etrex-cache's gpsbabel's gpspoint.c for starting me off! */
50 static char line_buffer
[2048];
52 #define GPSPOINT_TYPE_NONE 0
53 #define GPSPOINT_TYPE_WAYPOINT 1
54 #define GPSPOINT_TYPE_TRACKPOINT 2
55 /* #define GPSPOINT_TYPE_ROUTEPOINT 3 */
56 #define GPSPOINT_TYPE_TRACK 4
58 /* #define GPSPOINT_TYPE_ROUTE 5 */
60 static VikTrack
*current_track
; /* pointer to pointer to first GList */
62 static gint line_type
= GPSPOINT_TYPE_NONE
;
63 static struct LatLon line_latlon
;
64 static gchar
*line_name
;
65 static gchar
*line_comment
;
66 static gchar
*line_image
;
67 static gchar
*line_symbol
;
68 static gboolean line_newsegment
= FALSE
;
69 static gboolean line_has_timestamp
= FALSE
;
70 static time_t line_timestamp
= 0;
71 static gdouble line_altitude
= VIK_DEFAULT_ALTITUDE
;
72 static gboolean line_visible
= TRUE
;
73 /* other possible properties go here */
76 static void gpspoint_process_tag ( const gchar
*tag
, gint len
);
77 static void gpspoint_process_key_and_value ( const gchar
*key
, gint key_len
, const gchar
*value
, gint value_len
);
79 static gchar
*slashdup(const gchar
*str
)
81 guint16 len
= strlen(str
);
82 guint16 need_bs_count
, i
, j
;
84 for ( i
= 0, need_bs_count
= 0; i
< len
; i
++ )
85 if ( str
[i
] == '\\' || str
[i
] == '"' )
87 rv
= g_malloc ( (len
+need_bs_count
+1) * sizeof(gchar
) );
88 for ( i
= 0, j
= 0; i
< len
; i
++, j
++ )
90 if ( str
[i
] == '\\' || str
[i
] == '"' )
98 static gchar
*deslashndup ( const gchar
*str
, guint16 len
)
100 guint16 i
,j
, bs_count
, new_len
;
101 gboolean backslash
= FALSE
;
107 for ( i
= 0, bs_count
= 0; i
< len
; i
++ )
108 if ( str
[i
] == '\\' )
114 if ( str
[i
-1] == '\\' && (len
== 1 || str
[i
-2] != '\\') )
117 new_len
= len
- bs_count
;
118 rv
= g_malloc ( (new_len
+1) * sizeof(gchar
) );
119 for ( i
= 0, j
= 0; i
< len
&& j
< new_len
; i
++ )
120 if ( str
[i
] == '\\' && !backslash
)
132 void a_gpspoint_read_file(VikTrwLayer
*trw
, FILE *f
) {
133 VikCoordMode coord_mode
= vik_trw_layer_get_coord_mode ( trw
);
134 gchar
*tag_start
, *tag_end
;
135 g_assert ( f
!= NULL
&& trw
!= NULL
);
138 line_newsegment
= FALSE
;
142 current_track
= NULL
;
143 while (fgets(line_buffer
, 2048, f
))
145 gboolean inside_quote
= 0;
146 gboolean backslash
= 0;
148 line_buffer
[strlen(line_buffer
)-1] = '\0'; /* chop off newline */
150 /* for gpspoint files wrapped inside */
151 if ( strlen(line_buffer
) >= 13 && strncmp ( line_buffer
, "~EndLayerData", 13 ) == 0 )
154 /* each line: nullify stuff, make thing if nes, free name if ness */
155 tag_start
= line_buffer
;
158 /* my addition: find first non-whitespace character. if the null, skip line. */
159 while (*tag_start
!= '\0' && isspace(*tag_start
))
161 if (tag_start
== '\0')
164 if (*tag_start
== '#')
169 inside_quote
= !inside_quote
;
170 while (*tag_end
!= '\0' && (!isspace(*tag_end
) || inside_quote
)) {
172 if (*tag_end
== '\\' && !backslash
)
176 else if (*tag_end
== '"')
177 inside_quote
= !inside_quote
;
180 gpspoint_process_tag ( tag_start
, tag_end
- tag_start
);
182 if (*tag_end
== '\0' )
185 tag_start
= tag_end
+1;
187 if (line_type
== GPSPOINT_TYPE_WAYPOINT
&& line_name
)
189 VikWaypoint
*wp
= vik_waypoint_new();
190 gint i
= strlen(line_name
);
191 wp
->visible
= line_visible
;
192 wp
->altitude
= line_altitude
;
194 line_name
[i
] = toupper(line_name
[i
]); /* TODO: check for acceptable chars */
196 vik_coord_load_from_latlon ( &(wp
->coord
), coord_mode
, &line_latlon
);
198 vik_trw_layer_filein_add_waypoint ( trw
, line_name
, wp
);
199 g_free ( line_name
);
204 vik_waypoint_set_comment ( wp
, line_comment
);
210 vik_waypoint_set_image ( wp
, line_image
);
216 vik_waypoint_set_symbol ( wp
, line_symbol
);
220 else if (line_type
== GPSPOINT_TYPE_TRACK
&& line_name
)
222 VikTrack
*pl
= vik_track_new();
223 gint i
= strlen(line_name
);
225 /* Thanks to Peter Jones for this Fix */
226 if (!line_name
) line_name
= g_strdup("UNK");
228 pl
->visible
= line_visible
;
231 line_name
[i
] = toupper(line_name
[i
]);
235 vik_track_set_comment ( pl
, line_comment
);
239 pl
->trackpoints
= NULL
;
240 vik_trw_layer_filein_add_track ( trw
, line_name
, pl
);
241 g_free ( line_name
);
246 else if (line_type
== GPSPOINT_TYPE_TRACKPOINT
&& current_track
)
248 VikTrackpoint
*tp
= g_malloc ( sizeof ( VikTrackpoint
) );
249 vik_coord_load_from_latlon ( &(tp
->coord
), coord_mode
, &line_latlon
);
250 tp
->newsegment
= line_newsegment
;
251 tp
->has_timestamp
= line_has_timestamp
;
252 tp
->timestamp
= line_timestamp
;
253 tp
->altitude
= line_altitude
;
254 current_track
->trackpoints
= g_list_append ( current_track
->trackpoints
, tp
);
258 g_free ( line_name
);
261 g_free ( line_comment
);
263 g_free ( line_image
);
265 g_free ( line_symbol
);
269 line_type
= GPSPOINT_TYPE_NONE
;
270 line_newsegment
= FALSE
;
271 line_has_timestamp
= FALSE
;
273 line_altitude
= VIK_DEFAULT_ALTITUDE
;
279 /* Tag will be of a few defined forms:
285 So we must determine end of tag name, start of value, end of value.
287 static void gpspoint_process_tag ( const gchar
*tag
, gint len
)
289 const gchar
*key_end
, *value_start
, *value_end
;
291 /* Searching for key end */
294 while (++key_end
- tag
< len
)
298 if (key_end
- tag
== len
)
299 return; /* no good */
301 if (key_end
- tag
== len
+ 1)
302 value_start
= value_end
= 0; /* size = 0 */
305 value_start
= key_end
+ 1; /* equal_sign plus one */
307 if (*value_start
== '"')
310 if (*value_start
== '"')
311 value_start
= value_end
= 0; /* size = 0 */
314 if (*(tag
+len
-1) == '"')
315 value_end
= tag
+ len
- 1;
321 value_end
= tag
+ len
; /* value start really IS value start. */
323 gpspoint_process_key_and_value(tag
, key_end
- tag
, value_start
, value_end
- value_start
);
328 value = NULL for none
330 static void gpspoint_process_key_and_value ( const gchar
*key
, gint key_len
, const gchar
*value
, gint value_len
)
332 if (key_len
== 4 && strncasecmp( key
, "type", key_len
) == 0 )
335 line_type
= GPSPOINT_TYPE_NONE
;
336 else if (value_len
== 5 && strncasecmp( value
, "track", value_len
) == 0 )
337 line_type
= GPSPOINT_TYPE_TRACK
;
338 else if (value_len
== 10 && strncasecmp( value
, "trackpoint", value_len
) == 0 )
339 line_type
= GPSPOINT_TYPE_TRACKPOINT
;
340 else if (value_len
== 8 && strncasecmp( value
, "waypoint", value_len
) == 0 )
341 line_type
= GPSPOINT_TYPE_WAYPOINT
;
343 /* all others are ignored */
344 line_type
= GPSPOINT_TYPE_NONE
;
346 else if (key_len
== 4 && strncasecmp( key
, "name", key_len
) == 0 && value
!= NULL
)
348 if (line_name
== NULL
)
350 line_name
= g_strndup ( value
, value_len
);
353 else if (key_len
== 7 && strncasecmp( key
, "comment", key_len
) == 0 && value
!= NULL
)
355 if (line_comment
== NULL
)
356 line_comment
= deslashndup ( value
, value_len
);
358 else if (key_len
== 5 && strncasecmp( key
, "image", key_len
) == 0 && value
!= NULL
)
360 if (line_image
== NULL
)
361 line_image
= deslashndup ( value
, value_len
);
363 else if (key_len
== 8 && strncasecmp( key
, "latitude", key_len
) == 0 && value
!= NULL
)
365 line_latlon
.lat
= g_strtod(value
, NULL
);
367 else if (key_len
== 9 && strncasecmp( key
, "longitude", key_len
) == 0 && value
!= NULL
)
369 line_latlon
.lon
= g_strtod(value
, NULL
);
371 else if (key_len
== 8 && strncasecmp( key
, "altitude", key_len
) == 0 && value
!= NULL
)
373 line_altitude
= g_strtod(value
, NULL
);
375 else if (key_len
== 7 && strncasecmp( key
, "visible", key_len
) == 0 && value
[0] != 'y' && value
[0] != 'Y' && value
[0] != 't' && value
[0] != 'T')
377 line_visible
= FALSE
;
379 else if (key_len
== 6 && strncasecmp( key
, "symbol", key_len
) == 0 && value
!= NULL
)
381 line_symbol
= g_strndup ( value
, value_len
);
383 else if (key_len
== 8 && strncasecmp( key
, "unixtime", key_len
) == 0 && value
!= NULL
)
385 line_timestamp
= g_strtod(value
, NULL
);
386 if ( line_timestamp
!= 0x80000000 )
387 line_has_timestamp
= TRUE
;
389 else if (key_len
== 10 && strncasecmp( key
, "newsegment", key_len
) == 0 && value
!= NULL
)
391 line_newsegment
= TRUE
;
395 static void a_gpspoint_write_waypoint ( const gchar
*name
, VikWaypoint
*wp
, FILE *f
)
397 static struct LatLon ll
;
398 gchar
*s_lat
, *s_lon
;
399 vik_coord_to_latlon ( &(wp
->coord
), &ll
);
400 s_lat
= a_coords_dtostr(ll
.lat
);
401 s_lon
= a_coords_dtostr(ll
.lon
);
402 fprintf ( f
, "type=\"waypoint\" latitude=\"%s\" longitude=\"%s\" name=\"%s\"", s_lat
, s_lon
, name
);
406 if ( wp
->altitude
!= VIK_DEFAULT_ALTITUDE
) {
407 gchar
*s_alt
= a_coords_dtostr(wp
->altitude
);
408 fprintf ( f
, " altitude=\"%s\"", s_alt
);
413 gchar
*tmp_comment
= slashdup(wp
->comment
);
414 fprintf ( f
, " comment=\"%s\"", tmp_comment
);
415 g_free ( tmp_comment
);
419 gchar
*tmp_image
= slashdup(wp
->image
);
420 fprintf ( f
, " image=\"%s\"", tmp_image
);
421 g_free ( tmp_image
);
425 fprintf ( f
, " symbol=\"%s\"", wp
->symbol
);
428 fprintf ( f
, " visible=\"n\"" );
432 static void a_gpspoint_write_trackpoint ( VikTrackpoint
*tp
, FILE *f
)
434 static struct LatLon ll
;
435 gchar
*s_lat
, *s_lon
;
436 vik_coord_to_latlon ( &(tp
->coord
), &ll
);
438 s_lat
= a_coords_dtostr(ll
.lat
);
439 s_lon
= a_coords_dtostr(ll
.lon
);
440 fprintf ( f
, "type=\"trackpoint\" latitude=\"%s\" longitude=\"%s\"", s_lat
, s_lon
);
444 if ( tp
->altitude
!= VIK_DEFAULT_ALTITUDE
) {
445 gchar
*s_alt
= a_coords_dtostr(tp
->altitude
);
446 fprintf ( f
, " altitude=\"%s\"", s_alt
);
449 if ( tp
->has_timestamp
)
450 fprintf ( f
, " unixtime=\"%ld\"", tp
->timestamp
);
451 if ( tp
->newsegment
)
452 fprintf ( f
, " newsegment=\"yes\"" );
457 static void a_gpspoint_write_track ( const gchar
*name
, VikTrack
*t
, FILE *f
)
461 gchar
*tmp_comment
= slashdup(t
->comment
);
462 fprintf ( f
, "type=\"track\" name=\"%s\" comment=\"%s\"%s\n", name
, tmp_comment
, t
->visible
? "" : " visible=\"n\"" );
463 g_free ( tmp_comment
);
466 fprintf ( f
, "type=\"track\" name=\"%s\"%s\n", name
, t
->visible
? "" : " visible=\"n\"" );
467 g_list_foreach ( t
->trackpoints
, (GFunc
) a_gpspoint_write_trackpoint
, f
);
468 fprintf ( f
, "type=\"trackend\"\n" );
471 void a_gpspoint_write_file ( VikTrwLayer
*trw
, FILE *f
)
473 GHashTable
*tracks
= vik_trw_layer_get_tracks ( trw
);
474 GHashTable
*waypoints
= vik_trw_layer_get_waypoints ( trw
);
476 fprintf ( f
, "type=\"waypointlist\"\n" );
477 g_hash_table_foreach ( waypoints
, (GHFunc
) a_gpspoint_write_waypoint
, f
);
478 fprintf ( f
, "type=\"waypointlistend\"\n" );
479 g_hash_table_foreach ( tracks
, (GHFunc
) a_gpspoint_write_track
, f
);