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 GHashTable
*tracks
= vik_trw_layer_get_tracks ( trw
);
136 GHashTable
*waypoints
= vik_trw_layer_get_waypoints ( trw
);
137 g_assert ( f
!= NULL
&& trw
!= NULL
);
140 line_newsegment
= FALSE
;
144 current_track
= NULL
;
145 while (fgets(line_buffer
, 2048, f
))
147 gboolean inside_quote
= 0;
148 gboolean backslash
= 0;
150 line_buffer
[strlen(line_buffer
)-1] = '\0'; /* chop off newline */
152 /* for gpspoint files wrapped inside */
153 if ( strlen(line_buffer
) >= 13 && strncmp ( line_buffer
, "~EndLayerData", 13 ) == 0 )
156 /* each line: nullify stuff, make thing if nes, free name if ness */
157 tag_start
= line_buffer
;
160 /* my addition: find first non-whitespace character. if the null, skip line. */
161 while (*tag_start
!= '\0' && isspace(*tag_start
))
163 if (tag_start
== '\0')
166 if (*tag_start
== '#')
171 inside_quote
= !inside_quote
;
172 while (*tag_end
!= '\0' && (!isspace(*tag_end
) || inside_quote
)) {
174 if (*tag_end
== '\\' && !backslash
)
178 else if (*tag_end
== '"')
179 inside_quote
= !inside_quote
;
182 gpspoint_process_tag ( tag_start
, tag_end
- tag_start
);
184 if (*tag_end
== '\0' )
187 tag_start
= tag_end
+1;
189 if (line_type
== GPSPOINT_TYPE_WAYPOINT
&& line_name
)
191 VikWaypoint
*wp
= vik_waypoint_new();
192 gint i
= strlen(line_name
);
193 wp
->visible
= line_visible
;
194 wp
->altitude
= line_altitude
;
196 line_name
[i
] = toupper(line_name
[i
]); /* TODO: check for acceptable chars */
198 vik_coord_load_from_latlon ( &(wp
->coord
), coord_mode
, &line_latlon
);
200 g_hash_table_insert ( waypoints
, line_name
, wp
);
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 line_name
= NULL
; /* will be freed automatically */
222 else if (line_type
== GPSPOINT_TYPE_TRACK
&& line_name
)
224 VikTrack
*pl
= vik_track_new();
225 gint i
= strlen(line_name
);
227 /* Thanks to Peter Jones for this Fix */
228 if (!line_name
) line_name
= g_strdup("UNK");
230 pl
->visible
= line_visible
;
233 line_name
[i
] = toupper(line_name
[i
]);
237 vik_track_set_comment ( pl
, line_comment
);
241 pl
->trackpoints
= NULL
;
242 g_hash_table_insert ( tracks
, line_name
, pl
);
243 line_name
= NULL
; /* will be freed automatically */
247 else if (line_type
== GPSPOINT_TYPE_TRACKPOINT
&& current_track
)
249 VikTrackpoint
*tp
= g_malloc ( sizeof ( VikTrackpoint
) );
250 vik_coord_load_from_latlon ( &(tp
->coord
), coord_mode
, &line_latlon
);
251 tp
->newsegment
= line_newsegment
;
252 tp
->has_timestamp
= line_has_timestamp
;
253 tp
->timestamp
= line_timestamp
;
254 tp
->altitude
= line_altitude
;
255 current_track
->trackpoints
= g_list_append ( current_track
->trackpoints
, tp
);
259 g_free ( line_name
);
262 g_free ( line_comment
);
264 g_free ( line_image
);
266 g_free ( line_symbol
);
270 line_type
= GPSPOINT_TYPE_NONE
;
271 line_newsegment
= FALSE
;
272 line_has_timestamp
= FALSE
;
274 line_altitude
= VIK_DEFAULT_ALTITUDE
;
280 /* Tag will be of a few defined forms:
286 So we must determine end of tag name, start of value, end of value.
288 static void gpspoint_process_tag ( const gchar
*tag
, gint len
)
290 const gchar
*key_end
, *value_start
, *value_end
;
292 /* Searching for key end */
295 while (++key_end
- tag
< len
)
299 if (key_end
- tag
== len
)
300 return; /* no good */
302 if (key_end
- tag
== len
+ 1)
303 value_start
= value_end
= 0; /* size = 0 */
306 value_start
= key_end
+ 1; /* equal_sign plus one */
308 if (*value_start
== '"')
311 if (*value_start
== '"')
312 value_start
= value_end
= 0; /* size = 0 */
315 if (*(tag
+len
-1) == '"')
316 value_end
= tag
+ len
- 1;
322 value_end
= tag
+ len
; /* value start really IS value start. */
324 gpspoint_process_key_and_value(tag
, key_end
- tag
, value_start
, value_end
- value_start
);
329 value = NULL for none
331 static void gpspoint_process_key_and_value ( const gchar
*key
, gint key_len
, const gchar
*value
, gint value_len
)
333 if (key_len
== 4 && strncasecmp( key
, "type", key_len
) == 0 )
336 line_type
= GPSPOINT_TYPE_NONE
;
337 else if (value_len
== 5 && strncasecmp( value
, "track", value_len
) == 0 )
338 line_type
= GPSPOINT_TYPE_TRACK
;
339 else if (value_len
== 10 && strncasecmp( value
, "trackpoint", value_len
) == 0 )
340 line_type
= GPSPOINT_TYPE_TRACKPOINT
;
341 else if (value_len
== 8 && strncasecmp( value
, "waypoint", value_len
) == 0 )
342 line_type
= GPSPOINT_TYPE_WAYPOINT
;
344 /* all others are ignored */
345 line_type
= GPSPOINT_TYPE_NONE
;
347 else if (key_len
== 4 && strncasecmp( key
, "name", key_len
) == 0 && value
!= NULL
)
349 if (line_name
== NULL
)
351 line_name
= g_strndup ( value
, value_len
);
354 else if (key_len
== 7 && strncasecmp( key
, "comment", key_len
) == 0 && value
!= NULL
)
356 if (line_comment
== NULL
)
357 line_comment
= deslashndup ( value
, value_len
);
359 else if (key_len
== 5 && strncasecmp( key
, "image", key_len
) == 0 && value
!= NULL
)
361 if (line_image
== NULL
)
362 line_image
= deslashndup ( value
, value_len
);
364 else if (key_len
== 8 && strncasecmp( key
, "latitude", key_len
) == 0 && value
!= NULL
)
366 line_latlon
.lat
= g_strtod(value
, NULL
);
368 else if (key_len
== 9 && strncasecmp( key
, "longitude", key_len
) == 0 && value
!= NULL
)
370 line_latlon
.lon
= g_strtod(value
, NULL
);
372 else if (key_len
== 8 && strncasecmp( key
, "altitude", key_len
) == 0 && value
!= NULL
)
374 line_altitude
= g_strtod(value
, NULL
);
376 else if (key_len
== 7 && strncasecmp( key
, "visible", key_len
) == 0 && value
[0] != 'y' && value
[0] != 'Y' && value
[0] != 't' && value
[0] != 'T')
378 line_visible
= FALSE
;
380 else if (key_len
== 6 && strncasecmp( key
, "symbol", key_len
) == 0 && value
!= NULL
)
382 line_symbol
= g_strndup ( value
, value_len
);
384 else if (key_len
== 8 && strncasecmp( key
, "unixtime", key_len
) == 0 && value
!= NULL
)
386 line_timestamp
= g_strtod(value
, NULL
);
387 if ( line_timestamp
!= 0x80000000 )
388 line_has_timestamp
= TRUE
;
390 else if (key_len
== 10 && strncasecmp( key
, "newsegment", key_len
) == 0 && value
!= NULL
)
392 line_newsegment
= TRUE
;
396 static void a_gpspoint_write_waypoint ( const gchar
*name
, VikWaypoint
*wp
, FILE *f
)
398 static struct LatLon ll
;
399 vik_coord_to_latlon ( &(wp
->coord
), &ll
);
400 fprintf ( f
, "type=\"waypoint\" latitude=\"%f\" longitude=\"%f\" name=\"%s\"", ll
.lat
, ll
.lon
, name
);
401 if ( wp
->altitude
!= VIK_DEFAULT_ALTITUDE
)
402 fprintf ( f
, " altitude=\"%f\"", wp
->altitude
);
405 gchar
*tmp_comment
= slashdup(wp
->comment
);
406 fprintf ( f
, " comment=\"%s\"", tmp_comment
);
407 g_free ( tmp_comment
);
411 gchar
*tmp_image
= slashdup(wp
->image
);
412 fprintf ( f
, " image=\"%s\"", tmp_image
);
413 g_free ( tmp_image
);
417 fprintf ( f
, " symbol=\"%s\"", wp
->symbol
);
420 fprintf ( f
, " visible=\"n\"" );
424 static void a_gpspoint_write_trackpoint ( VikTrackpoint
*tp
, FILE *f
)
426 static struct LatLon ll
;
427 vik_coord_to_latlon ( &(tp
->coord
), &ll
);
429 fprintf ( f
, "type=\"trackpoint\" latitude=\"%f\" longitude=\"%f\"", ll
.lat
, ll
.lon
);
431 if ( tp
->altitude
!= VIK_DEFAULT_ALTITUDE
)
432 fprintf ( f
, " altitude=\"%f\"", tp
->altitude
);
433 if ( tp
->has_timestamp
)
434 fprintf ( f
, " unixtime=\"%ld\"", tp
->timestamp
);
435 if ( tp
->newsegment
)
436 fprintf ( f
, " newsegment=\"yes\"" );
441 static void a_gpspoint_write_track ( const gchar
*name
, VikTrack
*t
, FILE *f
)
445 gchar
*tmp_comment
= slashdup(t
->comment
);
446 fprintf ( f
, "type=\"track\" name=\"%s\" comment=\"%s\"%s\n", name
, tmp_comment
, t
->visible
? "" : " visible=\"n\"" );
447 g_free ( tmp_comment
);
450 fprintf ( f
, "type=\"track\" name=\"%s\"%s\n", name
, t
->visible
? "" : " visible=\"n\"" );
451 g_list_foreach ( t
->trackpoints
, (GFunc
) a_gpspoint_write_trackpoint
, f
);
452 fprintf ( f
, "type=\"trackend\"\n" );
455 void a_gpspoint_write_file ( VikTrwLayer
*trw
, FILE *f
)
457 GHashTable
*tracks
= vik_trw_layer_get_tracks ( trw
);
458 GHashTable
*waypoints
= vik_trw_layer_get_waypoints ( trw
);
460 fprintf ( f
, "type=\"waypointlist\"\n" );
461 g_hash_table_foreach ( waypoints
, (GHFunc
) a_gpspoint_write_waypoint
, f
);
462 fprintf ( f
, "type=\"waypointlistend\"\n" );
463 g_hash_table_foreach ( tracks
, (GHFunc
) a_gpspoint_write_track
, f
);