+}
+
+static int gpx_waypoint_compare(const void *x, const void *y)
+{
+ VikWaypoint *a = (VikWaypoint *)x;
+ VikWaypoint *b = (VikWaypoint *)y;
+ return strcmp(a->name,b->name);
+}
+
+static int gpx_track_compare_name(const void *x, const void *y)
+{
+ VikTrack *a = (VikTrack *)x;
+ VikTrack *b = (VikTrack *)y;
+ return strcmp(a->name,b->name);
+}
+
+void a_gpx_write_file ( VikTrwLayer *vtl, FILE *f, GpxWritingOptions *options )
+{
+ GpxWritingContext context = { options, f };
+
+ gpx_write_header ( f );
+
+ gchar *tmp;
+ const gchar *name = vik_layer_get_name(VIK_LAYER(vtl));
+ if ( name ) {
+ tmp = entitize ( name );
+ fprintf ( f, " <name>%s</name>\n", tmp );
+ g_free ( tmp );
+ }
+
+ VikTRWMetadata *md = vik_trw_layer_get_metadata (vtl);
+ if ( md ) {
+ if ( md->author ) {
+ tmp = entitize ( md->author );
+ fprintf ( f, " <author>%s</author>\n", tmp );
+ g_free ( tmp );
+ }
+ if ( md->description ) {
+ tmp = entitize ( md->description );
+ fprintf ( f, " <desc>%s</desc>\n", tmp );
+ g_free ( tmp );
+ }
+ if ( md->timestamp ) {
+ tmp = entitize ( md->timestamp );
+ fprintf ( f, " <time>%s</time>\n", tmp );
+ g_free ( tmp );
+ }
+ if ( md->keywords ) {
+ tmp = entitize ( md->keywords );
+ fprintf ( f, " <keywords>%s</keywords>\n", tmp );
+ g_free ( tmp );
+ }
+ }
+
+ if ( vik_trw_layer_get_waypoints_visibility(vtl) || (options && options->hidden) ) {
+ // gather waypoints in a list, then sort
+ GList *gl = g_hash_table_get_values ( vik_trw_layer_get_waypoints ( vtl ) );
+ gl = g_list_sort ( gl, gpx_waypoint_compare );
+
+ for (GList *iter = g_list_first (gl); iter != NULL; iter = g_list_next (iter)) {
+ gpx_write_waypoint ( (VikWaypoint*)iter->data, &context );
+ }
+ g_list_free ( gl );
+ }
+
+ GList *gl = NULL;
+ if ( vik_trw_layer_get_tracks_visibility(vtl) || (options && options->hidden) ) {
+ //gl = g_hash_table_get_values ( vik_trw_layer_get_tracks ( vtl ) );
+ // Forming the list manually seems to produce one that is more likely to be nearer to the creation order
+ gpointer key, value;
+ GHashTableIter ght_iter;
+ g_hash_table_iter_init ( &ght_iter, vik_trw_layer_get_tracks ( vtl ) );
+ while ( g_hash_table_iter_next (&ght_iter, &key, &value) ) {
+ gl = g_list_prepend ( gl ,value );
+ }
+ gl = g_list_reverse ( gl );
+
+ // Sort method determined by preference
+ if ( a_vik_get_gpx_export_trk_sort() == VIK_GPX_EXPORT_TRK_SORT_TIME )
+ gl = g_list_sort ( gl, vik_track_compare_timestamp );
+ else if ( a_vik_get_gpx_export_trk_sort() == VIK_GPX_EXPORT_TRK_SORT_ALPHA )
+ gl = g_list_sort ( gl, gpx_track_compare_name );
+ }
+
+ GList *glrte = NULL;
+ // Routes sorted by name
+ if ( vik_trw_layer_get_tracks_visibility(vtl) || (options && options->hidden) ) {
+ glrte = g_hash_table_get_values ( vik_trw_layer_get_routes ( vtl ) );
+ glrte = g_list_sort ( glrte, gpx_track_compare_name );
+ }
+
+ // g_list_concat doesn't copy memory properly
+ // so process each list separately
+
+ GpxWritingContext context_tmp = context;
+ GpxWritingOptions opt_tmp = { FALSE, FALSE, FALSE, FALSE };
+ // Force trackpoints on tracks
+ if ( !context.options )
+ context_tmp.options = &opt_tmp;
+ context_tmp.options->is_route = FALSE;
+
+ // Loop around each list and write each one
+ for (GList *iter = g_list_first (gl); iter != NULL; iter = g_list_next (iter)) {
+ gpx_write_track ( (VikTrack*)iter->data, &context_tmp );
+ }
+
+ // Routes (to get routepoints)
+ context_tmp.options->is_route = TRUE;
+ for (GList *iter = g_list_first (glrte); iter != NULL; iter = g_list_next (iter)) {
+ gpx_write_track ( (VikTrack*)iter->data, &context_tmp );
+ }
+
+ g_list_free ( gl );
+ g_list_free ( glrte );
+
+ gpx_write_footer ( f );
+}
+
+void a_gpx_write_track_file ( VikTrack *trk, FILE *f, GpxWritingOptions *options )
+{
+ GpxWritingContext context = {options, f};
+ gpx_write_header ( f );
+ gpx_write_track ( trk, &context );
+ gpx_write_footer ( f );
+}
+
+/**
+ * Common write of a temporary GPX file
+ */
+static gchar* write_tmp_file ( VikTrwLayer *vtl, VikTrack *trk, GpxWritingOptions *options )
+{
+ gchar *tmp_filename = NULL;
+ GError *error = NULL;
+ // Opening temporary file
+ int fd = g_file_open_tmp("viking_XXXXXX.gpx", &tmp_filename, &error);
+ if (fd < 0) {
+ g_warning ( _("failed to open temporary file: %s"), error->message );
+ g_clear_error ( &error );
+ return NULL;
+ }
+ g_debug ("%s: temporary file = %s", __FUNCTION__, tmp_filename);
+
+ FILE *ff = fdopen (fd, "w");
+
+ if ( trk )
+ a_gpx_write_track_file ( trk, ff, options );
+ else
+ a_gpx_write_file ( vtl, ff, options );
+
+ fclose (ff);
+
+ return tmp_filename;
+}