f = g_fopen(name_dst, "r");
if (f) {
- ret = a_gpx_read_file ( vt, f );
+ gchar *dirpath = g_path_get_dirname ( name_dst );
+ ret = a_gpx_read_file ( vt, f, dirpath );
+ g_free ( dirpath );
fclose(f);
- f = NULL;
}
}
g_debug("%s: directly read GPX file %s", __FUNCTION__, name_src);
FILE *f = g_fopen(name_src, "r");
if (f) {
- ret = a_gpx_read_file ( vt, f );
+ gchar *dirpath = g_path_get_dirname ( name_src );
+ ret = a_gpx_read_file ( vt, f, dirpath );
+ g_free ( dirpath );
fclose(f);
- f = NULL;
}
}
}
}
}
-static void write_layer_params_and_data ( VikLayer *l, FILE *f )
+static void write_layer_params_and_data ( VikLayer *l, FILE *f, const gchar *dirpath )
{
VikLayerParam *params = vik_layer_get_interface(l->type)->params;
VikLayerFuncGetParam get_param = vik_layer_get_interface(l->type)->get_param;
if ( vik_layer_get_interface(l->type)->write_file_data )
{
fprintf ( f, "\n\n~LayerData\n" );
- vik_layer_get_interface(l->type)->write_file_data ( l, f );
+ vik_layer_get_interface(l->type)->write_file_data ( l, f, dirpath );
fprintf ( f, "~EndLayerData\n" );
}
/* foreach param:
*/
}
-static void file_write ( VikAggregateLayer *top, FILE *f, gpointer vp )
+static void file_write ( VikAggregateLayer *top, FILE *f, gpointer vp, const gchar *dirpath )
{
Stack *stack = NULL;
VikLayer *current_layer;
{
current_layer = VIK_LAYER(((GList *)stack->data)->data);
fprintf ( f, "\n~Layer %s\n", vik_layer_get_interface(current_layer->type)->fixed_layer_name );
- write_layer_params_and_data ( current_layer, f );
+ write_layer_params_and_data ( current_layer, f, dirpath );
if ( current_layer->type == VIK_LAYER_AGGREGATE && !vik_aggregate_layer_is_empty(VIK_AGGREGATE_LAYER(current_layer)) )
{
push(&stack);
VikLoadType_t load_answer = LOAD_TYPE_OTHER_SUCCESS;
- gchar *dirpath = g_path_get_dirname ( filename );
+ gchar *absolute = file_realpath_dup ( filename );
+ gchar *dirpath = NULL;
+ if ( absolute )
+ dirpath = g_path_get_dirname ( absolute );
+ g_free ( absolute );
+
// Attempt loading the primary file type first - our internal .vik file:
if ( check_magic ( f, VIK_MAGIC, VIK_MAGIC_LEN ) )
{
// NB use a extension check first, as a GPX file header may have a Byte Order Mark (BOM) in it
// - which currently confuses our check_magic function
else if ( a_file_check_ext ( filename, ".gpx" ) || check_magic ( f, GPX_MAGIC, GPX_MAGIC_LEN ) ) {
- if ( ! ( success = a_gpx_read_file ( vtl, f ) ) ) {
+ if ( ! ( success = a_gpx_read_file ( vtl, f, dirpath ) ) ) {
load_answer = LOAD_TYPE_GPX_FAILURE;
}
}
if ( g_chdir ( dir ) ) {
g_warning ( "Could not change directory to %s", dir );
}
- g_free (dir);
}
- file_write ( top, f, vp );
+ file_write ( top, f, vp, dir );
+ g_free (dir);
// Restore previous working directory
if ( cwd ) {
if ( f )
{
gboolean result = TRUE;
+ gchar *dirpath = g_path_get_dirname ( filename );
if ( trk ) {
switch ( file_type ) {
a_gpsmapper_write_file ( vtl, f );
break;
case FILE_TYPE_GPX:
- a_gpx_write_file ( vtl, f, &options );
+ a_gpx_write_file ( vtl, f, &options, dirpath );
break;
case FILE_TYPE_GPSPOINT:
- a_gpspoint_write_file ( vtl, f );
+ a_gpspoint_write_file ( vtl, f, dirpath );
break;
case FILE_TYPE_GEOJSON:
result = a_geojson_write_file ( vtl, f );
g_critical("Houston, we've had a problem. file_type=%d", file_type);
}
}
+ g_free ( dirpath );
fclose ( f );
return result;
}
#endif
#include "viking.h"
+#include "vikutils.h"
#include <ctype.h>
#ifdef HAVE_STRING_H
static void a_gpspoint_write_track ( const gpointer id, const VikTrack *t, FILE *f );
static void a_gpspoint_write_trackpoint ( VikTrackpoint *tp, TP_write_info_type *write_info );
-static void a_gpspoint_write_waypoint ( const gpointer id, const VikWaypoint *wp, FILE *f );
/* outline for file gpspoint.c
vik_waypoint_set_type ( wp, line_xtype );
if ( line_image ) {
- // Ensure the filename is absolute
- if ( g_path_is_absolute ( line_image ) )
- vik_waypoint_set_image ( wp, line_image );
- else {
- // Otherwise create the absolute filename from the directory of the .vik file & and the relative filename
- gchar *full = g_strconcat(dirpath, G_DIR_SEPARATOR_S, line_image, NULL);
- gchar *absolute = file_realpath_dup ( full ); // resolved into the canonical name
- vik_waypoint_set_image ( wp, absolute );
- g_free ( absolute );
- g_free ( full );
- }
+ gchar *fn = util_make_absolute_filename ( line_image, dirpath );
+ vik_waypoint_set_image ( wp, fn ? fn : line_image );
+ g_free ( fn );
}
if ( line_symbol )
}
}
-static void a_gpspoint_write_waypoint ( const gpointer id, const VikWaypoint *wp, FILE *f )
+typedef struct {
+ FILE *file;
+ const gchar *dirpath;
+} WritingContext;
+
+static void a_gpspoint_write_waypoint ( const gpointer id, const VikWaypoint *wp, WritingContext *wc )
{
struct LatLon ll;
gchar s_lat[COORDS_STR_BUFFER_SIZE];
return;
if ( !(wp->name) )
return;
+ if ( !wc )
+ return;
+
+ FILE *f = wc->file;
vik_coord_to_latlon ( &(wp->coord), &ll );
a_coords_dtostr_buffer ( ll.lat, s_lat );
if ( wp->image )
{
gchar *tmp_image = NULL;
- gchar *cwd = NULL;
if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
- cwd = g_get_current_dir();
- if ( cwd )
- tmp_image = g_strdup ( file_GetRelativeFilename ( cwd, wp->image ) );
+ if ( wc->dirpath )
+ tmp_image = g_strdup ( file_GetRelativeFilename ( (gchar*)wc->dirpath, wp->image ) );
}
- // if cwd not available - use image filename as is
+ // if tmp_image not available - use image filename as is
// this should be an absolute path as set in thumbnails
- if ( !cwd )
+ if ( !tmp_image )
tmp_image = slashdup(wp->image);
if ( tmp_image )
fprintf ( f, " image=\"%s\"", tmp_image );
- g_free ( cwd );
g_free ( tmp_image );
}
if ( wp->symbol )
fprintf ( f, "type=\"%send\"\n", trk->is_route ? "route" : "track" );
}
-void a_gpspoint_write_file ( VikTrwLayer *trw, FILE *f )
+void a_gpspoint_write_file ( VikTrwLayer *trw, FILE *f, const gchar *dirpath )
{
GHashTable *tracks = vik_trw_layer_get_tracks ( trw );
GHashTable *routes = vik_trw_layer_get_routes ( trw );
GHashTable *waypoints = vik_trw_layer_get_waypoints ( trw );
+ WritingContext wc = { f, dirpath };
fprintf ( f, "type=\"waypointlist\"\n" );
- g_hash_table_foreach ( waypoints, (GHFunc) a_gpspoint_write_waypoint, f );
+ g_hash_table_foreach ( waypoints, (GHFunc) a_gpspoint_write_waypoint, &wc );
fprintf ( f, "type=\"waypointlistend\"\n" );
g_hash_table_foreach ( tracks, (GHFunc) a_gpspoint_write_track, f );
g_hash_table_foreach ( routes, (GHFunc) a_gpspoint_write_track, f );
G_BEGIN_DECLS
gboolean a_gpspoint_read_file ( VikTrwLayer *trw, FILE *f, const gchar *dirpath );
-void a_gpspoint_write_file ( VikTrwLayer *trw, FILE *f );
+void a_gpspoint_write_file ( VikTrwLayer *trw, FILE *f, const gchar *dirpath );
G_END_DECLS
#include "gpx.h"
#include "viking.h"
+#include "vikutils.h"
#include <expat.h>
+#include "misc/gtkhtml-private.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
typedef struct {
GpxWritingOptions *options;
FILE *file;
+ const gchar *dirpath;
} GpxWritingContext;
/*
/* specialty flags / etc */
gboolean f_tr_newseg;
+const gchar *c_link = NULL;
guint unnamed_waypoints = 0;
guint unnamed_tracks = 0;
guint unnamed_routes = 0;
+typedef struct {
+ VikTrwLayer *vtl;
+ const gchar *dirpath;
+} UserDataT;
+
static const char *get_attr ( const char **attr, const char *key )
{
while ( *attr ) {
return FALSE;
}
-static void gpx_start(VikTrwLayer *vtl, const char *el, const char **attr)
+static void gpx_start(UserDataT *ud, const char *el, const char **attr)
{
static const gchar *tmp;
+ VikTrwLayer *vtl = ud->vtl;
g_string_append_c ( xpath, '/' );
g_string_append ( xpath, el );
}
break;
+ case tt_wpt_link:
+ c_link = get_attr ( attr, "href" );
+ break;
case tt_gpx_name:
case tt_gpx_author:
case tt_gpx_desc:
case tt_wpt_ele:
case tt_wpt_time:
case tt_wpt_url:
- case tt_wpt_link:
case tt_trk_cmt:
case tt_trk_desc:
case tt_trk_src:
}
}
-static void gpx_end(VikTrwLayer *vtl, const char *el)
+static void gpx_end(UserDataT *ud, const char *el)
{
static GTimeVal tp_time;
static GTimeVal wp_time;
+ VikTrwLayer *vtl = ud->vtl;
g_string_truncate ( xpath, xpath->len - strlen(el) - 1 );
break;
case tt_wpt_link:
- vik_waypoint_set_image ( c_wp, c_cdata->str );
+ if ( c_link ) {
+ // Correct <link href="uri"></link> format
+ vu_waypoint_set_image_uri ( c_wp, c_link, ud->dirpath );
+ }
+ else {
+ // Fallback for incorrect GPX <link> format (probably from previous versions of Viking!)
+ // of the form <link>file</link>
+ gchar *fn = util_make_absolute_filename ( c_cdata->str, ud->dirpath );
+ vik_waypoint_set_image ( c_wp, fn ? fn : c_cdata->str );
+ g_free ( fn );
+ }
+ c_link = NULL;
g_string_erase ( c_cdata, 0, -1 );
break;
// make like a "stack" of tag names
// like gpspoint's separated like /gpx/wpt/whatever
-gboolean a_gpx_read_file( VikTrwLayer *vtl, FILE *f ) {
+gboolean a_gpx_read_file( VikTrwLayer *vtl, FILE *f, const gchar* dirpath ) {
XML_Parser parser = XML_ParserCreate(NULL);
int done=0, len;
enum XML_Status status = XML_STATUS_ERROR;
+ UserDataT *ud = g_malloc (sizeof(UserDataT));
+ ud->vtl = vtl;
+ ud->dirpath = dirpath;
+
XML_SetElementHandler(parser, (XML_StartElementHandler) gpx_start, (XML_EndElementHandler) gpx_end);
- XML_SetUserData(parser, vtl); /* in the future we could remove all global variables */
+ XML_SetUserData(parser, ud);
XML_SetCharacterDataHandler(parser, (XML_CharacterDataHandler) gpx_cdata);
gchar buf[4096];
done = feof(f) || !len;
status = XML_Parse(parser, buf, len, done);
}
-
+
XML_ParserFree (parser);
+ g_free ( ud );
g_string_free ( xpath, TRUE );
g_string_free ( c_cdata, TRUE );
}
if ( wp->image )
{
- tmp = entitize(wp->image);
- fprintf ( f, " <link>%s</link>\n", tmp );
+ gchar *tmp = NULL;
+ if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
+ if ( context->dirpath ) {
+ gchar *rtmp = g_strdup ( file_GetRelativeFilename ( (gchar*)context->dirpath, wp->image ) );
+ if ( rtmp ) {
+ tmp = gtk_html_filename_to_uri ( rtmp );
+ }
+ }
+ }
+ if ( !tmp )
+ tmp = gtk_html_filename_to_uri ( wp->image );
+ fprintf ( f, " <link href=\"%s\"></link>\n", tmp );
g_free ( tmp );
}
if ( wp->symbol )
return strcmp(a->name,b->name);
}
-void a_gpx_write_file ( VikTrwLayer *vtl, FILE *f, GpxWritingOptions *options )
+void a_gpx_write_file ( VikTrwLayer *vtl, FILE *f, GpxWritingOptions *options, const gchar* dirpath )
{
- GpxWritingContext context = { options, f };
+ GpxWritingContext context = { options, f, dirpath };
gpx_write_header ( f );
if ( trk )
a_gpx_write_track_file ( trk, ff, options );
else
- a_gpx_write_file ( vtl, ff, options );
+ a_gpx_write_file ( vtl, ff, options, NULL );
fclose (ff);
gboolean is_route; /// For internal convenience
} GpxWritingOptions;
-gboolean a_gpx_read_file ( VikTrwLayer *trw, FILE *f );
-void a_gpx_write_file ( VikTrwLayer *trw, FILE *f, GpxWritingOptions *options );
+gboolean a_gpx_read_file ( VikTrwLayer *trw, FILE *f, const gchar* dirpath );
+void a_gpx_write_file ( VikTrwLayer *trw, FILE *f, GpxWritingOptions *options, const gchar *dirpath );
void a_gpx_write_track_file ( VikTrack *trk, FILE *f, GpxWritingOptions *options );
gchar* a_gpx_write_tmp_file ( VikTrwLayer *vtl, GpxWritingOptions *options );
/* Parameters (for I/O and Properties) */
/* --> moved to uibuilder.h */
-
/* layer interface functions */
/* Create a new layer of a certain type. Should be filled with defaults */
typedef void (*VikLayerFuncChangeParam) (GtkWidget *, ui_change_values );
typedef gboolean (*VikLayerFuncReadFileData) (VikLayer *, FILE *, const gchar *); // gchar* is the directory path. Function should report success or failure
-typedef void (*VikLayerFuncWriteFileData) (VikLayer *, FILE *);
+typedef void (*VikLayerFuncWriteFileData) (VikLayer *, FILE *, const gchar *); // gchar* is the directory path.
/* item manipulation */
typedef void (*VikLayerFuncDeleteItem) (VikLayer *, gint, gpointer);
/*
* viking -- GPS Data and Topo Analyzer, Explorer, and Manager
*
- * Copyright (C) 2013, Rob Norris <rw_norris@hotmail.com>
+ * Copyright (C) 2013-2017, Rob Norris <rw_norris@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "ui_util.h"
#include "dir.h"
#include "misc/kdtree.h"
+#include "misc/gtkhtml-private.h"
#define FMT_MAX_NUMBER_CODES 9
vik_viewport_set_zoom ( vvp, zoom );
}
}
+
+/**
+ * Set the waypoint image given a URI
+ */
+void vu_waypoint_set_image_uri ( VikWaypoint *wp, const gchar *uri, const gchar *dirpath )
+{
+ gchar *filename = gtk_html_filename_from_uri ( uri );
+ if ( g_path_is_absolute ( filename ) ) {
+ vik_waypoint_set_image ( wp, filename );
+ }
+ else {
+ // Try to form full path
+ gchar *full = g_strconcat ( dirpath, G_DIR_SEPARATOR_S, filename, NULL );
+ vik_waypoint_set_image ( wp, full );
+ g_free ( full );
+ }
+}
void vu_zoom_to_show_latlons ( VikCoordMode mode, VikViewport *vvp, struct LatLon maxmin[2] );
+void vu_waypoint_set_image_uri ( VikWaypoint *wp, const gchar *uri, const gchar *dirpath );
+
G_END_DECLS
#endif