]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Allow uploading a single track via the GPS layer interface.
[andy/viking.git] / src / viktrwlayer.c
index 202a8266d22f441c214cea43aac49b3ff1239464..60082ce5a07af410a56a01dab2374a4dfcfdc463 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2005-2008, Alex Foobarian <foobarian@gmail.com>
  * Copyright (C) 2007, Quy Tonthat <qtonthat@gmail.com>
  * Copyright (C) 2009, Hein Ragas <viking@ragas.nl>
+ * Copyright (c) 2012, 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
@@ -25,7 +26,7 @@
 #define WAYPOINT_FONT "Sans 8"
 
 /* WARNING: If you go beyond this point, we are NOT responsible for any ill effects on your sanity */
-/* viktrwlayer.c -- 2200 lines can make a difference in the state of things */
+/* viktrwlayer.c -- 5000+ lines can make a difference in the state of things */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #include "vikmapslayer.h"
 #include "viktrwlayer_tpwin.h"
 #include "viktrwlayer_propwin.h"
+#ifdef VIK_CONFIG_GEOTAG
+#include "viktrwlayer_geotag.h"
+#include "geotag_exif.h"
+#endif
 #include "garminsymbols.h"
 #include "thumbnails.h"
 #include "background.h"
@@ -47,6 +52,7 @@
 #include "osm-traces.h"
 #endif
 #include "acquire.h"
+#include "datasources.h"
 #include "util.h"
 
 #include "icons/icons.h"
@@ -74,16 +80,28 @@ static gboolean return_true (gpointer a, gpointer b, gpointer c) { return TRUE;
 static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove ( ght, (GHRFunc) return_true, FALSE ); }
 #endif
 
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+// This is currently broken as Google have disabled the KML output in Google Maps API v3
+// It has been ifdefed out in the hope that Route Finding functionality will be restored one day...
+// Only have 'JSON' and 'XML' see:
+// https://developers.google.com/maps/documentation/directions/#DirectionsResponses
 #define GOOGLE_DIRECTIONS_STRING "maps.google.com/maps?q=from:%s,%s+to:%s,%s&output=kml"
-#define VIK_TRW_LAYER_TRACK_GC 13
+#endif
+
+#define VIK_TRW_LAYER_TRACK_GC 16
 #define VIK_TRW_LAYER_TRACK_GC_RATES 10
 #define VIK_TRW_LAYER_TRACK_GC_MIN 0
 #define VIK_TRW_LAYER_TRACK_GC_MAX 11
 #define VIK_TRW_LAYER_TRACK_GC_BLACK 12
+#define VIK_TRW_LAYER_TRACK_GC_SLOW 13
+#define VIK_TRW_LAYER_TRACK_GC_AVER 14
+#define VIK_TRW_LAYER_TRACK_GC_FAST 15
 
 #define DRAWMODE_BY_TRACK 0
-#define DRAWMODE_BY_VELOCITY 1
+#define DRAWMODE_BY_SPEED 1
 #define DRAWMODE_ALL_BLACK 2
+// Note using DRAWMODE_BY_SPEED may be slow especially for vast numbers of trackpoints
+//  as we are (re)calculating the colour for every point
 
 #define POINTS 1
 #define LINES 2
@@ -96,12 +114,6 @@ static g_hash_table_remove_all (GHashTable *ght) { g_hash_table_foreach_remove (
 #define MAX_STOP_LENGTH 86400
 #define DRAW_ELEVATION_FACTOR 30 /* height of elevation plotting, sort of relative to zoom level ("mpp" that isn't mpp necessarily) */
                                  /* this is multiplied by user-inputted value from 1-100. */
-enum {
-VIK_TRW_LAYER_SUBLAYER_TRACKS,
-VIK_TRW_LAYER_SUBLAYER_WAYPOINTS,
-VIK_TRW_LAYER_SUBLAYER_TRACK,
-VIK_TRW_LAYER_SUBLAYER_WAYPOINT
-};
 
 enum { WP_SYMBOL_FILLED_SQUARE, WP_SYMBOL_SQUARE, WP_SYMBOL_CIRCLE, WP_SYMBOL_X, WP_NUM_SYMBOLS };
 
@@ -127,10 +139,12 @@ struct _VikTrwLayer {
   guint8 wp_size;
   gboolean wp_draw_symbols;
 
-  gdouble velocity_min, velocity_max;
+  gdouble track_draw_speed_factor;
   GArray *track_gc;
-  guint16 track_gc_iter;
   GdkGC *current_track_gc;
+  // Separate GC for a track's potential new point as drawn via separate method
+  //  (compared to the actual track points drawn in the main trw_layer_draw_track function)
+  GdkGC *current_track_newpoint_gc;
   GdkGC *track_bg_gc;
   GdkGC *waypoint_gc;
   GdkGC *waypoint_text_gc;
@@ -138,36 +152,33 @@ struct _VikTrwLayer {
   GdkFont *waypoint_font;
   VikTrack *current_track;
   guint16 ct_x1, ct_y1, ct_x2, ct_y2;
-  gboolean ct_sync_done;
-
+  gboolean draw_sync_done;
+  gboolean draw_sync_do;
 
   VikCoordMode coord_mode;
 
   /* wp editing tool */
   VikWaypoint *current_wp;
-  gchar *current_wp_name;
+  gpointer current_wp_id;
   gboolean moving_wp;
   gboolean waypoint_rightclick;
 
   /* track editing tool */
   GList *current_tpl;
-  gchar *current_tp_track_name;
+  VikTrack *current_tp_track;
+  gpointer current_tp_id;
   VikTrwLayerTpwin *tpwin;
 
-  /* weird hack for joining tracks */
-  GList *last_tpl;
-  gchar *last_tp_track_name;
-
   /* track editing tool -- more specifically, moving tps */
   gboolean moving_tp;
 
-  /* magic scissors tool */
-  gboolean magic_scissors_started;
-  VikCoord magic_scissors_coord;
-  gboolean magic_scissors_check_added_track;
-  gchar *magic_scissors_added_track_name;
-  VikTrack *magic_scissors_current_track;
-  gboolean magic_scissors_append;
+  /* route finder tool */
+  gboolean route_finder_started;
+  VikCoord route_finder_coord;
+  gboolean route_finder_check_added_track;
+  VikTrack *route_finder_added_track;
+  VikTrack *route_finder_current_track;
+  gboolean route_finder_append;
 
   gboolean drawlabels;
   gboolean drawimages;
@@ -207,8 +218,7 @@ struct DrawingParams {
   gdouble ce1, ce2, cn1, cn2;
 };
 
-static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16);
-static guint16 vik_trw_layer_get_menu_selection(VikTrwLayer *vtl);
+static gboolean trw_layer_delete_waypoint ( VikTrwLayer *vtl, VikWaypoint *wp );
 
 static void trw_layer_delete_item ( gpointer pass_along[6] );
 static void trw_layer_copy_item_cb ( gpointer pass_along[6] );
@@ -221,13 +231,9 @@ static void trw_layer_find_maxmin (VikTrwLayer *vtl, struct LatLon maxmin[2]);
 static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp );
 static void trw_layer_free_track_gcs ( VikTrwLayer *vtl );
 
-static gint calculate_velocity ( VikTrwLayer *vtl, VikTrackpoint *tp1, VikTrackpoint *tp2 );
 static void trw_layer_draw_track_cb ( const gchar *name, VikTrack *track, struct DrawingParams *dp );
 static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct DrawingParams *dp );
 
-static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl );
-static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, gpointer sublayer );
-
 static void goto_coord ( gpointer *vlp, gpointer vvp, gpointer vl, const VikCoord *coord );
 static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] );
 static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] );
@@ -235,17 +241,24 @@ static void trw_layer_goto_track_max_speed ( gpointer pass_along[6] );
 static void trw_layer_goto_track_max_alt ( gpointer pass_along[6] );
 static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] );
 static void trw_layer_goto_track_center ( gpointer pass_along[6] );
+static void trw_layer_merge_by_segment ( gpointer pass_along[6] );
 static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] );
 static void trw_layer_merge_with_other ( gpointer pass_along[6] );
+static void trw_layer_append_track ( gpointer pass_along[6] );
 static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
 static void trw_layer_split_by_n_points ( gpointer pass_along[6] );
+static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] );
+static void trw_layer_split_segments ( gpointer pass_along[6] );
+static void trw_layer_delete_points_same_position ( gpointer pass_along[6] );
+static void trw_layer_delete_points_same_time ( gpointer pass_along[6] );
+static void trw_layer_reverse ( gpointer pass_along[6] );
 static void trw_layer_download_map_along_track_cb ( gpointer pass_along[6] );
 static void trw_layer_edit_trackpoint ( gpointer pass_along[6] );
 static void trw_layer_show_picture ( gpointer pass_along[6] );
 
 static void trw_layer_centerize ( gpointer layer_and_vlp[2] );
 static void trw_layer_auto_view ( gpointer layer_and_vlp[2] );
-static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar* title, const gchar* default_name, const gchar* trackname, guint file_type );
+static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar* title, const gchar* default_name, VikTrack* trk, guint file_type );
 static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] );
 static void trw_layer_new_wp ( gpointer lav[2] );
 static void trw_layer_auto_waypoints_view ( gpointer lav[2] );
@@ -256,38 +269,34 @@ static void trw_layer_delete_all_waypoints ( gpointer lav[2] );
 static void trw_layer_delete_waypoints_from_selection ( gpointer lav[2] );
 static void trw_layer_new_wikipedia_wp_viewport ( gpointer lav[2] );
 static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] );
+#ifdef VIK_CONFIG_GEOTAG
+static void trw_layer_geotagging_waypoint_mtime_keep ( gpointer pass_along[6] );
+static void trw_layer_geotagging_waypoint_mtime_update ( gpointer pass_along[6] );
+static void trw_layer_geotagging_track ( gpointer pass_along[6] );
+static void trw_layer_geotagging ( gpointer lav[2] );
+#endif
+static void trw_layer_acquire_gps_cb ( gpointer lav[2] );
+static void trw_layer_acquire_google_cb ( gpointer lav[2] );
+#ifdef VIK_CONFIG_OPENSTREETMAP
+static void trw_layer_acquire_osm_cb ( gpointer lav[2] );
+#endif
+#ifdef VIK_CONFIG_GEOCACHES
+static void trw_layer_acquire_geocache_cb ( gpointer lav[2] );
+#endif
+#ifdef VIK_CONFIG_GEOTAG
+static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] );
+#endif
 
 /* pop-up items */
-static void trw_layer_properties_item ( gpointer pass_along[6] );
+static void trw_layer_properties_item ( gpointer pass_along[7] );
 static void trw_layer_goto_waypoint ( gpointer pass_along[6] );
 static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[6] );
 
-static void trw_layer_realize_waypoint ( gchar *name, VikWaypoint *wp, gpointer pass_along[5] );
-static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pass_along[5] );
+static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] );
+static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] );
 static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
 
-
-static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len );
-static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
-
-static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
-static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gboolean is_file_operation );
-
-static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
-static void trw_layer_cut_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
-
-static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len );
-static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *item, guint len );
-static void trw_layer_free_copied_item ( gint subtype, gpointer item );
-static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, GtkTreeIter *src_item_iter, GtkTreePath *dest_path );
-
-static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
-static gboolean trw_layer_select_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
-static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
-static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
-
 static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl );
-static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl );
 static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy );
 static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response );
 static void trw_layer_tpwin_init ( VikTrwLayer *vtl );
@@ -307,24 +316,22 @@ static gboolean tool_begin_track_click ( VikTrwLayer *vtl, GdkEventButton *event
 static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp ); 
 static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp ); 
+static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
 static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event, VikViewport *vvp ); 
 static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp);
 static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
-static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp);
-static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
-
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp);
+static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+#endif
 
 static void cached_pixbuf_free ( CachedPixbuf *cp );
 static gint cached_pixbuf_cmp ( CachedPixbuf *cp, const gchar *name );
-static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp );
 
 static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y );
 static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikViewport *vvp, gint x, gint y );
 
-static void trw_layer_change_coord_mode ( VikTrwLayer *vtl, VikCoordMode dest_mode );
-
-static gchar *get_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name);
-static void waypoint_convert ( const gchar *name, VikWaypoint *wp, VikCoordMode *dest_mode );
+static void waypoint_convert ( const gpointer id, VikWaypoint *wp, VikCoordMode *dest_mode );
 static void track_convert ( const gchar *name, VikTrack *tr, VikCoordMode *dest_mode );
 
 static gchar *highest_wp_number_get(VikTrwLayer *vtl);
@@ -332,33 +339,63 @@ static void highest_wp_number_reset(VikTrwLayer *vtl);
 static void highest_wp_number_add_wp(VikTrwLayer *vtl, const gchar *new_wp_name);
 static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_name);
 
-
+// Note for the following tool GtkRadioActionEntry texts:
+//  the very first text value is an internal name not displayed anywhere
+//  the first N_ text value is the name used for menu entries - hence has an underscore for the keyboard accelerator
+//    * remember not to clash with the values used for VikWindow level tools (Pan, Zoom, Ruler + Select)
+//  the second N_ text value is used for the button tooltip (i.e. generally don't want an underscore here)
+//  the value is always set to 0 and the tool loader in VikWindow will set the actual appropriate value used
 static VikToolInterface trw_layer_tools[] = {
-  { N_("Create Waypoint"), (VikToolConstructorFunc) tool_new_waypoint_create,    NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_new_waypoint_click,    NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf },
-
-  { N_("Create Track"),    (VikToolConstructorFunc) tool_new_track_create,       NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_new_track_click, (VikToolMouseMoveFunc) tool_new_track_move, NULL,
-    (VikToolKeyFunc) tool_new_track_key_press, GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
-
-  { N_("Begin Track"),    (VikToolConstructorFunc) tool_begin_track_create,       NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_begin_track_click,       NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
-
-  { N_("Edit Waypoint"),   (VikToolConstructorFunc) tool_edit_waypoint_create,   NULL, NULL, NULL, 
+  { { "CreateWaypoint", "vik-icon-Create Waypoint", N_("Create _Waypoint"), "<control><shift>W", N_("Create Waypoint"), 0 },
+    (VikToolConstructorFunc) tool_new_waypoint_create,    NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_new_waypoint_click,    NULL, NULL, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_addwp_pixbuf },
+
+  { { "CreateTrack", "vik-icon-Create Track", N_("Create _Track"), "<control><shift>T", N_("Create Track"), 0 },
+    (VikToolConstructorFunc) tool_new_track_create,       NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_new_track_click,
+    (VikToolMouseMoveFunc) tool_new_track_move,
+    (VikToolMouseFunc) tool_new_track_release,
+    (VikToolKeyFunc) tool_new_track_key_press,
+    TRUE, // Still need to handle clicks when in PAN mode to disable the potential trackpoint drawing
+    GDK_CURSOR_IS_PIXMAP, &cursor_addtr_pixbuf },
+
+  { { "BeginTrack", "vik-icon-Begin Track", N_("_Begin Track"), "<control><shift>B", N_("Begin Track"), 0 },
+    (VikToolConstructorFunc) tool_begin_track_create,       NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_begin_track_click,       NULL, NULL, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_begintr_pixbuf },
+
+  { { "EditWaypoint", "vik-icon-Edit Waypoint", N_("_Edit Waypoint"), "<control><shift>E", N_("Edit Waypoint"), 0 },
+    (VikToolConstructorFunc) tool_edit_waypoint_create,   NULL, NULL, NULL,
     (VikToolMouseFunc) tool_edit_waypoint_click,   
     (VikToolMouseMoveFunc) tool_edit_waypoint_move,
-    (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
+    (VikToolMouseFunc) tool_edit_waypoint_release, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_edwp_pixbuf },
 
-  { N_("Edit Trackpoint"), (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL, 
+  { { "EditTrackpoint", "vik-icon-Edit Trackpoint", N_("Edit Trac_kpoint"), "<control><shift>K", N_("Edit Trackpoint"), 0 },
+    (VikToolConstructorFunc) tool_edit_trackpoint_create, NULL, NULL, NULL,
     (VikToolMouseFunc) tool_edit_trackpoint_click,
     (VikToolMouseMoveFunc) tool_edit_trackpoint_move,
-    (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
-
-  { N_("Show Picture"),    (VikToolConstructorFunc) tool_show_picture_create,    NULL, NULL, NULL, 
-    (VikToolMouseFunc) tool_show_picture_click,    NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf },
-
-  { N_("Route Finder"),  (VikToolConstructorFunc) tool_magic_scissors_create,  NULL, NULL, NULL,
-    (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
+    (VikToolMouseFunc) tool_edit_trackpoint_release, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_edtr_pixbuf },
+
+  { { "ShowPicture", "vik-icon-Show Picture", N_("Show P_icture"), "<control><shift>I", N_("Show Picture"), 0 },
+    (VikToolConstructorFunc) tool_show_picture_create,    NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_show_picture_click,    NULL, NULL, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_showpic_pixbuf },
+
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+  { { "RouteFinder", "vik-icon-Route Finder", N_("Route _Finder"), "<control><shift>F", N_("Route Finder"), 0 },
+    (VikToolConstructorFunc) tool_route_finder_create,  NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL,
+    FALSE,
+    GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
+#endif
 };
 enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
 
@@ -367,15 +404,15 @@ enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WA
 static gchar *params_groups[] = { N_("Waypoints"), N_("Tracks"), N_("Waypoint Images") };
 enum { GROUP_WAYPOINTS, GROUP_TRACKS, GROUP_IMAGES };
 
-static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Velocity"), N_("All Tracks Black"), 0 };
+static gchar *params_drawmodes[] = { N_("Draw by Track"), N_("Draw by Speed"), N_("All Tracks Black"), 0 };
 static gchar *params_wpsymbols[] = { N_("Filled Square"), N_("Square"), N_("Circle"), N_("X"), 0 };
 
 
 static VikLayerParamScale params_scales[] = {
  /* min  max    step digits */
  {  1,   10,    1,   0 }, /* line_thickness */
- {  0.0, 99.0,  1,   2 }, /* velocity_min */
- {  1.0, 100.0, 1.0, 2 }, /* velocity_max */
+ {  0,   100,   1,   0 }, /* track draw speed factor */
+ {  1.0, 100.0, 1.0, 2 }, /* UNUSED */
                 /* 5 * step == how much to turn */
  {  16,   128,  3.2, 0 }, /* image_size */
  {   0,   255,  5,   0 }, /* image alpha */
@@ -402,8 +439,7 @@ VikLayerParam trw_layer_params[] = {
   { "line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 0 },
   { "bg_line_thickness", VIK_LAYER_PARAM_UINT, GROUP_TRACKS, N_("Track BG Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 6 },
   { "trackbgcolor", VIK_LAYER_PARAM_COLOR, GROUP_TRACKS, N_("Track Background Color"), VIK_LAYER_WIDGET_COLOR, 0 },
-  { "velocity_min", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Min Track Velocity:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
-  { "velocity_max", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Max Track Velocity:"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 2 },
+  { "speed_factor", VIK_LAYER_PARAM_DOUBLE, GROUP_TRACKS, N_("Draw by Speed Factor (%):"), VIK_LAYER_WIDGET_SPINBUTTON, params_scales + 1 },
 
   { "drawlabels", VIK_LAYER_PARAM_BOOLEAN, GROUP_WAYPOINTS, N_("Draw Labels"), VIK_LAYER_WIDGET_CHECKBUTTON },
   { "wpcolor", VIK_LAYER_PARAM_COLOR, GROUP_WAYPOINTS, N_("Waypoint Color:"), VIK_LAYER_WIDGET_COLOR, 0 },
@@ -420,7 +456,7 @@ VikLayerParam trw_layer_params[] = {
   { "image_cache_size", VIK_LAYER_PARAM_UINT, GROUP_IMAGES, N_("Image Memory Cache Size:"), VIK_LAYER_WIDGET_HSCALE, params_scales + 5 },
 };
 
-enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_VMIN, PARAM_VMAX, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, NUM_PARAMS };
+enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PARAM_DS, PARAM_SL, PARAM_LT, PARAM_BLT, PARAM_TBGC, PARAM_TDSF, PARAM_DLA, PARAM_WPC, PARAM_WPTC, PARAM_WPBC, PARAM_WPBA, PARAM_WPSYM, PARAM_WPSIZE, PARAM_WPSYMS, PARAM_DI, PARAM_IS, PARAM_IA, PARAM_ICS, NUM_PARAMS };
 
 /*** TO ADD A PARAM:
  *** 1) Add to trw_layer_params and enumeration
@@ -429,8 +465,41 @@ enum { PARAM_TV, PARAM_WV, PARAM_DM, PARAM_DL, PARAM_DP, PARAM_DE, PARAM_EF, PAR
 
 /****** END PARAMETERS ******/
 
+static VikTrwLayer* trw_layer_new ( gint drawmode );
+/* Layer Interface function definitions */
+static VikTrwLayer* trw_layer_create ( VikViewport *vp );
+static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter );
+static void trw_layer_free ( VikTrwLayer *trwlayer );
+static void trw_layer_draw ( VikTrwLayer *l, gpointer data );
+static void trw_layer_change_coord_mode ( VikTrwLayer *vtl, VikCoordMode dest_mode );
+static void trw_layer_set_menu_selection ( VikTrwLayer *vtl, guint16 );
+static guint16 trw_layer_get_menu_selection ( VikTrwLayer *vtl );
+static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vlp );
+static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter, VikViewport *vvp );
+static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter );
+static gboolean trw_layer_sublayer_toggle_visible ( VikTrwLayer *l, gint subtype, gpointer sublayer );
+static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl );
+static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, gpointer sublayer );
+static gboolean trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublayer, gint type, gpointer vlp );
+static void trw_layer_marshall ( VikTrwLayer *vtl, guint8 **data, gint *len );
+static VikTrwLayer *trw_layer_unmarshall ( guint8 *data, gint len, VikViewport *vvp );
+static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
+static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gboolean is_file_operation );
+static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
+static void trw_layer_cut_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer );
+static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer, guint8 **item, guint *len );
+static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *item, guint len );
+static void trw_layer_free_copied_item ( gint subtype, gpointer item );
+static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, GtkTreeIter *src_item_iter, GtkTreePath *dest_path );
+static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
+static gboolean trw_layer_select_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
+static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t *t );
+static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
+/* End Layer Interface function definitions */
+
 VikLayerInterface vik_trw_layer_interface = {
-  "TrackWaypoint",
+  N_("TrackWaypoint"),
+  "<control><shift>Y",
   &viktrwlayer_pixbuf,
 
   trw_layer_tools,
@@ -443,26 +512,26 @@ VikLayerInterface vik_trw_layer_interface = {
 
   VIK_MENU_ITEM_ALL,
 
-  (VikLayerFuncCreate)                  vik_trw_layer_create,
-  (VikLayerFuncRealize)                 vik_trw_layer_realize,
+  (VikLayerFuncCreate)                  trw_layer_create,
+  (VikLayerFuncRealize)                 trw_layer_realize,
   (VikLayerFuncPostRead)                trw_layer_verify_thumbnails,
-  (VikLayerFuncFree)                    vik_trw_layer_free,
+  (VikLayerFuncFree)                    trw_layer_free,
 
   (VikLayerFuncProperties)              NULL,
-  (VikLayerFuncDraw)                    vik_trw_layer_draw,
+  (VikLayerFuncDraw)                    trw_layer_draw,
   (VikLayerFuncChangeCoordMode)         trw_layer_change_coord_mode,
 
-  (VikLayerFuncSetMenuItemsSelection)   vik_trw_layer_set_menu_selection,
-  (VikLayerFuncGetMenuItemsSelection)   vik_trw_layer_get_menu_selection,
+  (VikLayerFuncSetMenuItemsSelection)   trw_layer_set_menu_selection,
+  (VikLayerFuncGetMenuItemsSelection)   trw_layer_get_menu_selection,
 
-  (VikLayerFuncAddMenuItems)            vik_trw_layer_add_menu_items,
-  (VikLayerFuncSublayerAddMenuItems)    vik_trw_layer_sublayer_add_menu_items,
+  (VikLayerFuncAddMenuItems)            trw_layer_add_menu_items,
+  (VikLayerFuncSublayerAddMenuItems)    trw_layer_sublayer_add_menu_items,
 
-  (VikLayerFuncSublayerRenameRequest)   vik_trw_layer_sublayer_rename_request,
-  (VikLayerFuncSublayerToggleVisible)   vik_trw_layer_sublayer_toggle_visible,
+  (VikLayerFuncSublayerRenameRequest)   trw_layer_sublayer_rename_request,
+  (VikLayerFuncSublayerToggleVisible)   trw_layer_sublayer_toggle_visible,
   (VikLayerFuncSublayerTooltip)         trw_layer_sublayer_tooltip,
   (VikLayerFuncLayerTooltip)            trw_layer_layer_tooltip,
-  (VikLayerFuncLayerSelected)           vik_trw_layer_selected,
+  (VikLayerFuncLayerSelected)           trw_layer_selected,
 
   (VikLayerFuncMarshall)                trw_layer_marshall,
   (VikLayerFuncUnmarshall)              trw_layer_unmarshall,
@@ -487,12 +556,10 @@ VikLayerInterface vik_trw_layer_interface = {
   (VikLayerFuncSelectedViewportMenu)    trw_layer_show_selected_viewport_menu,
 };
 
-/* for copy & paste (I think?) */
+// for copy & paste
 typedef struct {
   guint len;
   guint8 data[0];
-  //  gchar *name;
-  //  VikWaypoint *wp;
 } FlatItem;
 
 GType vik_trw_layer_get_type ()
@@ -565,8 +632,24 @@ static void trw_layer_copy_item_cb ( gpointer pass_along[6])
   trw_layer_copy_item( vtl, subtype, sublayer, &data, &len);
 
   if (data) {
+    const gchar* name;
+    if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT ) {
+      VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, sublayer);
+      if ( wp && wp->name )
+        name = wp->name;
+      else
+        name = NULL; // Broken :(
+    }
+    else {
+      VikTrack *trk = g_hash_table_lookup ( vtl->tracks, sublayer);
+      if ( trk && trk->name )
+        name = trk->name;
+      else
+        name = NULL; // Broken :(
+    }
+
     a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
-       subtype, len, data);
+                     subtype, len, name, data);
   }
 }
 
@@ -591,15 +674,21 @@ static void trw_layer_copy_item ( VikTrwLayer *vtl, gint subtype, gpointer subla
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
     vik_waypoint_marshall ( g_hash_table_lookup ( vtl->waypoints, sublayer ), &id, &il );
+    // 'Simple' memory copy of byte array from the marshalling above
+    *len = sizeof(FlatItem) + 1 + il; // not sure what the 1 is for yet...
+    fi = g_malloc ( *len );
+    fi->len = *len;
+    memcpy(fi->data, id, il);
   } else {
+
     vik_track_marshall ( g_hash_table_lookup ( vtl->tracks, sublayer ), &id, &il );
+    // less magic than before...
+    *len = sizeof(FlatItem) + 1 + il;
+    fi = g_malloc ( *len );
+    fi->len = *len;
+    memcpy(fi->data, id, il);
   }
 
-  *len = sizeof(FlatItem) + strlen(sublayer) + 1 + il;
-  fi = g_malloc ( *len );
-  fi->len = strlen(sublayer) + 1;
-  memcpy(fi->data, sublayer, fi->len);
-  memcpy(fi->data + fi->len, id, il);
   g_free(id);
   *item = (guint8 *)fi;
 }
@@ -613,26 +702,31 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i
     VikWaypoint *w;
     gchar *name;
 
-    name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, (gchar *)fi->data);
-    w = vik_waypoint_unmarshall(fi->data + fi->len, len - sizeof(*fi) - fi->len);
+    w = vik_waypoint_unmarshall(fi->data, fi->len);
+    // When copying - we'll create a new name based on the original
+    name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, w->name);
     vik_trw_layer_add_waypoint ( vtl, name, w );
-    waypoint_convert(name, w, &vtl->coord_mode);
+    waypoint_convert (NULL, w, &vtl->coord_mode);
+
     // Consider if redraw necessary for the new item
     if ( vtl->vl.visible && vtl->waypoints_visible && w->visible )
-      vik_layer_emit_update ( VIK_LAYER(vtl) );
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK && fi )
   {
     VikTrack *t;
     gchar *name;
-    name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, (gchar *)fi->data);
-    t = vik_track_unmarshall(fi->data + fi->len, len - sizeof(*fi) - fi->len);
+
+    t = vik_track_unmarshall(fi->data, fi->len);
+    // When copying - we'll create a new name based on the original
+    name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, t->name);
     vik_trw_layer_add_track ( vtl, name, t );
-    track_convert(name, t, &vtl->coord_mode);
+    track_convert (name, t, &vtl->coord_mode);
+
     // Consider if redraw necessary for the new item
     if ( vtl->vl.visible && vtl->tracks_visible && t->visible )
-      vik_layer_emit_update ( VIK_LAYER(vtl) );
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   return FALSE;
@@ -674,39 +768,8 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara
                      trw_layer_new_track_gcs ( vtl, vp );
                    }
                    break;
-    case PARAM_VMIN:
-    {
-      /* Convert to store internally
-         NB file operation always in internal units (metres per second) */
-      vik_units_speed_t speed_units = a_vik_get_units_speed ();
-      if ( is_file_operation || speed_units == VIK_UNITS_SPEED_METRES_PER_SECOND )
-       vtl->velocity_min = data.d;
-      else if ( speed_units == VIK_UNITS_SPEED_KILOMETRES_PER_HOUR )
-       vtl->velocity_min = VIK_KPH_TO_MPS(data.d);
-      else if ( speed_units == VIK_UNITS_SPEED_MILES_PER_HOUR )
-       vtl->velocity_min = VIK_MPH_TO_MPS(data.d);
-      else
-       /* Knots */
-       vtl->velocity_min = VIK_KNOTS_TO_MPS(data.d);
-      break;
-    }
-    case PARAM_VMAX:
-    {
-      /* Convert to store internally
-         NB file operation always in internal units (metres per second) */
-      vik_units_speed_t speed_units = a_vik_get_units_speed ();
-      if ( is_file_operation || speed_units == VIK_UNITS_SPEED_METRES_PER_SECOND )
-       vtl->velocity_max = data.d;
-      else if ( speed_units == VIK_UNITS_SPEED_KILOMETRES_PER_HOUR )
-       vtl->velocity_max = VIK_KPH_TO_MPS(data.d);
-      else if ( speed_units == VIK_UNITS_SPEED_MILES_PER_HOUR )
-       vtl->velocity_max = VIK_MPH_TO_MPS(data.d);
-      else
-       /* Knots */
-       vtl->velocity_max = VIK_KNOTS_TO_MPS(data.d);
-      break;
-    }
     case PARAM_TBGC: gdk_gc_set_rgb_fg_color(vtl->track_bg_gc, &(data.c)); break;
+    case PARAM_TDSF: vtl->track_draw_speed_factor = data.d; break;
     case PARAM_DLA: vtl->drawlabels = data.b; break;
     case PARAM_DI: vtl->drawimages = data.b; break;
     case PARAM_IS: if ( data.u != vtl->image_size )
@@ -749,41 +812,10 @@ static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gbo
     case PARAM_DL: rv.b = vtl->drawlines; break;
     case PARAM_LT: rv.u = vtl->line_thickness; break;
     case PARAM_BLT: rv.u = vtl->bg_line_thickness; break;
-    case PARAM_VMIN:
-    {
-      /* Convert to store internally
-         NB file operation always in internal units (metres per second) */
-      vik_units_speed_t speed_units = a_vik_get_units_speed ();
-      if ( is_file_operation || speed_units == VIK_UNITS_SPEED_METRES_PER_SECOND )
-       rv.d = vtl->velocity_min;
-      else if ( speed_units == VIK_UNITS_SPEED_KILOMETRES_PER_HOUR )
-       rv.d = VIK_MPS_TO_KPH(vtl->velocity_min);
-      else if ( speed_units == VIK_UNITS_SPEED_MILES_PER_HOUR )
-       rv.d = VIK_MPS_TO_MPH(vtl->velocity_min);
-      else
-       /* Knots */
-       rv.d = VIK_MPS_TO_KNOTS(vtl->velocity_min);
-      break;
-    }
-    case PARAM_VMAX:
-    {
-      /* Convert to store internally
-         NB file operation always in internal units (metres per second) */
-      vik_units_speed_t speed_units = a_vik_get_units_speed ();
-      if ( is_file_operation || speed_units == VIK_UNITS_SPEED_METRES_PER_SECOND )
-       rv.d = vtl->velocity_max;
-      else if ( speed_units == VIK_UNITS_SPEED_KILOMETRES_PER_HOUR )
-       rv.d = VIK_MPS_TO_KPH(vtl->velocity_max);
-      else if ( speed_units == VIK_UNITS_SPEED_MILES_PER_HOUR )
-       rv.d = VIK_MPS_TO_MPH(vtl->velocity_max);
-      else
-       /* Knots */
-       rv.d = VIK_MPS_TO_KNOTS(vtl->velocity_max);
-      break;
-    }
     case PARAM_DLA: rv.b = vtl->drawlabels; break;
     case PARAM_DI: rv.b = vtl->drawimages; break;
     case PARAM_TBGC: vik_gc_get_fg_color(vtl->track_bg_gc, &(rv.c)); break;
+    case PARAM_TDSF: rv.d = vtl->track_draw_speed_factor; break;
     case PARAM_IS: rv.u = vtl->image_size; break;
     case PARAM_IA: rv.u = vtl->image_alpha; break;
     case PARAM_ICS: rv.u = vtl->image_cache_size; break;
@@ -864,17 +896,14 @@ static GList * str_array_to_glist(gchar* data[])
   return(g_list_reverse(gl));
 }
 
-static gboolean strcase_equal(gconstpointer s1, gconstpointer s2)
-{
-  return (strcasecmp(s1, s2) == 0);
-}
-
+// Keep interesting hash function at least visible
+/*
 static guint strcase_hash(gconstpointer v)
 {
-  /* 31 bit hash function */
+  // 31 bit hash function
   int i;
   const gchar *t = v;
-  gchar s[128];   /* malloc is too slow for reading big files */
+  gchar s[128];   // malloc is too slow for reading big files
   gchar *p = s;
 
   for (i = 0; (i < (sizeof(s)- 1)) && t[i]; i++)
@@ -890,8 +919,9 @@ static guint strcase_hash(gconstpointer v)
 
   return h;  
 }
+*/
 
-VikTrwLayer *vik_trw_layer_new ( gint drawmode )
+static VikTrwLayer* trw_layer_new ( gint drawmode )
 {
   if (trw_layer_params[PARAM_DM].widget_data == NULL)
     trw_layer_params[PARAM_DM].widget_data = str_array_to_glist(params_drawmodes);
@@ -901,10 +931,22 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
   VikTrwLayer *rv = VIK_TRW_LAYER ( g_object_new ( VIK_TRW_LAYER_TYPE, NULL ) );
   vik_layer_init ( VIK_LAYER(rv), VIK_LAYER_TRW );
 
-  rv->waypoints = g_hash_table_new_full ( strcase_hash, strcase_equal, g_free, (GDestroyNotify) vik_waypoint_free );
-  rv->tracks = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, (GDestroyNotify) vik_track_free );
-  rv->tracks_iters = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, g_free );
-  rv->waypoints_iters = g_hash_table_new_full ( strcase_hash, strcase_equal, NULL, g_free );
+  // It's not entirely clear the benefits of hash tables usage here - possibly the simplicity of first implementation for unique names
+  // Now with the name of the item stored as part of the item - these tables are effectively straightforward lists
+
+  // For this reworking I've choosen to keep the use of hash tables since for the expected data sizes
+  // - even many hundreds of waypoints and tracks is quite small in the grand scheme of things,
+  //  and with normal PC processing capabilities - it has negligibile performance impact
+  // This also minimized the amount of rework - as the management of the hash tables already exists.
+
+  // The hash tables are indexed by simple integers acting as a UUID hash, which again shouldn't affect performance much
+  //   we have to maintain a uniqueness (as before when multiple names where not allowed),
+  //   this is to ensure it refers to the same item in the data structures used on the viewport and on the layers panel
+
+  rv->waypoints = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_waypoint_free );
+  rv->waypoints_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
+  rv->tracks = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) vik_track_free );
+  rv->tracks_iters = g_hash_table_new_full ( g_direct_hash, g_direct_equal, NULL, g_free );
 
   /* TODO: constants at top */
   rv->waypoints_visible = rv->tracks_visible = TRUE;
@@ -922,29 +964,27 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
   rv->waypoint_text_gc = NULL;
   rv->waypoint_bg_gc = NULL;
   rv->track_gc = NULL;
-  rv->velocity_max = 5.0;
-  rv->velocity_min = 0.0;
+  rv->track_draw_speed_factor = 30.0;
   rv->line_thickness = 1;
   rv->bg_line_thickness = 0;
   rv->current_wp = NULL;
-  rv->current_wp_name = NULL;
+  rv->current_wp_id = NULL;
   rv->current_track = NULL;
   rv->current_tpl = NULL;
-  rv->current_tp_track_name = NULL;
+  rv->current_tp_track = NULL;
+  rv->current_tp_id = NULL;
   rv->moving_tp = FALSE;
   rv->moving_wp = FALSE;
 
-  rv->ct_sync_done = TRUE;
+  rv->draw_sync_done = TRUE;
+  rv->draw_sync_do = TRUE;
 
-  rv->magic_scissors_started = FALSE;
-  rv->magic_scissors_check_added_track = FALSE;
-  rv->magic_scissors_added_track_name = NULL;
-  rv->magic_scissors_current_track = NULL;
-  rv->magic_scissors_append = FALSE;
+  rv->route_finder_started = FALSE;
+  rv->route_finder_check_added_track = FALSE;
+  rv->route_finder_current_track = NULL;
+  rv->route_finder_append = FALSE;
 
   rv->waypoint_rightclick = FALSE;
-  rv->last_tpl = NULL;
-  rv->last_tp_track_name = NULL;
   rv->tpwin = NULL;
   rv->image_cache = g_queue_new();
   rv->image_size = 64;
@@ -956,7 +996,7 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
 }
 
 
-void vik_trw_layer_free ( VikTrwLayer *trwlayer )
+static void trw_layer_free ( VikTrwLayer *trwlayer )
 {
   g_hash_table_destroy(trwlayer->waypoints);
   g_hash_table_destroy(trwlayer->tracks);
@@ -1029,27 +1069,28 @@ static void init_drawing_params ( struct DrawingParams *dp, VikViewport *vp )
   dp->track_gc_iter = 0;
 }
 
-static gint calculate_velocity ( VikTrwLayer *vtl, VikTrackpoint *tp1, VikTrackpoint *tp2 )
-{
-  static gdouble rv = 0;
-  if ( tp1->has_timestamp && tp2->has_timestamp )
-  {
-    rv = ( vik_coord_diff ( &(tp1->coord), &(tp2->coord) )
-           / (tp1->timestamp - tp2->timestamp) ) - vtl->velocity_min;
-
-    if ( rv < 0 )
-      return VIK_TRW_LAYER_TRACK_GC_MIN;
-    else if ( vtl->velocity_min >= vtl->velocity_max )
-      return VIK_TRW_LAYER_TRACK_GC_MAX;
-
-    rv *= (VIK_TRW_LAYER_TRACK_GC_RATES / (vtl->velocity_max - vtl->velocity_min));
-
-    if ( rv >= VIK_TRW_LAYER_TRACK_GC_MAX )
-      return VIK_TRW_LAYER_TRACK_GC_MAX;
-    return (gint) rv;
- }
- else
-   return VIK_TRW_LAYER_TRACK_GC_BLACK;
+/*
+ * Determine the colour of the trackpoint (and/or trackline) relative to the average speed
+ * Here a simple traffic like light colour system is used:
+ *  . slow points are red
+ *  . average is yellow
+ *  . fast points are green
+ */
+static gint track_section_colour_by_speed ( VikTrwLayer *vtl, VikTrackpoint *tp1, VikTrackpoint *tp2, gdouble average_speed, gdouble low_speed, gdouble high_speed )
+{
+  gdouble rv = 0;
+  if ( tp1->has_timestamp && tp2->has_timestamp ) {
+    if ( average_speed > 0 ) {
+      rv = ( vik_coord_diff ( &(tp1->coord), &(tp2->coord) ) / (tp1->timestamp - tp2->timestamp) );
+      if ( rv < low_speed )
+        return VIK_TRW_LAYER_TRACK_GC_SLOW;
+      else if ( rv > high_speed )
+        return VIK_TRW_LAYER_TRACK_GC_FAST;
+      else
+        return VIK_TRW_LAYER_TRACK_GC_AVER;
+    }
+  }
+  return VIK_TRW_LAYER_TRACK_GC_BLACK;
 }
 
 void draw_utm_skip_insignia ( VikViewport *vvp, GdkGC *gc, gint x, gint y )
@@ -1097,6 +1138,7 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     drawstops = dp->vtl->drawstops;
   }
 
+  gboolean drawing_highlight = FALSE;
   /* Current track - used for creation */
   if ( track == dp->vtl->current_track )
     main_gc = dp->vtl->current_track_gc;
@@ -1110,6 +1152,7 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
                        ( dp->vtl->tracks == vik_window_get_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
                        track == vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ) {
        main_gc = vik_viewport_get_gc_highlight (dp->vp);
+       drawing_highlight = TRUE;
       }
       else {
        if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
@@ -1143,6 +1186,17 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     oldx = x;
     oldy = y;
 
+    gdouble average_speed = 0.0;
+    gdouble low_speed = 0.0;
+    gdouble high_speed = 0.0;
+    // If necessary calculate these values - which is done only once per track redraw
+    if ( dp->vtl->drawmode == DRAWMODE_BY_SPEED ) {
+      // the percentage factor away from the average speed determines transistions between the levels
+      average_speed = vik_track_get_average_speed_moving(track, dp->vtl->stop_length);
+      low_speed = average_speed - (average_speed*(dp->vtl->track_draw_speed_factor/100.0));
+      high_speed = average_speed + (average_speed*(dp->vtl->track_draw_speed_factor/100.0));
+    }
+
     while ((list = g_list_next(list)))
     {
       tp = VIK_TRACKPOINT(list->data);
@@ -1156,32 +1210,59 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
       {
         vik_viewport_coord_to_screen ( dp->vp, &(tp->coord), &x, &y );
 
+       /*
+        * If points are the same in display coordinates, don't draw.
+        */
+       if ( useoldvals && x == oldx && y == oldy )
+       {
+         // Still need to process points to ensure 'stops' are drawn if required
+         if ( drawstops && drawpoints && ! drawing_white_background && list->next &&
+              (VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length) )
+           vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
+
+         goto skip;
+       }
+
+        VikTrackpoint *tp2 = VIK_TRACKPOINT(list->prev->data);
+        if ( drawpoints || dp->vtl->drawlines ) {
+          // setup main_gc for both point and line drawing
+          if ( !drawing_highlight && (dp->vtl->drawmode == DRAWMODE_BY_SPEED) ) {
+            dp->track_gc_iter = track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed );
+            main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+          }
+        }
+
         if ( drawpoints && ! drawing_white_background )
         {
-          if ( list->next ) {
-            vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
 
+          if ( list->next ) {
+           /*
+            * The concept of drawing stops is that a trackpoint
+            * that is if the next trackpoint has a timestamp far into
+            * the future, we draw a circle of 6x trackpoint size,
+            * instead of a rectangle of 2x trackpoint size.
+            * This is drawn first so the trackpoint will be drawn on top
+            */
             /* stops */
             if ( drawstops && VIK_TRACKPOINT(list->next->data)->timestamp - VIK_TRACKPOINT(list->data)->timestamp > dp->vtl->stop_length )
+             /* Stop point.  Draw 6x circle. */
               vik_viewport_draw_arc ( dp->vp, g_array_index(dp->vtl->track_gc, GdkGC *, 11), TRUE, x-(3*tp_size), y-(3*tp_size), 6*tp_size, 6*tp_size, 0, 360*64 );
+
+           /* Regular point - draw 2x square. */
+           vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
           }
           else
+           /* Final point - draw 4x circle. */
             vik_viewport_draw_arc ( dp->vp, main_gc, TRUE, x-(2*tp_size), y-(2*tp_size), 4*tp_size, 4*tp_size, 0, 360*64 );
         }
 
         if ((!tp->newsegment) && (dp->vtl->drawlines))
         {
-          VikTrackpoint *tp2 = VIK_TRACKPOINT(list->prev->data);
 
           /* UTM only: zone check */
           if ( drawpoints && dp->vtl->coord_mode == VIK_COORD_UTM && tp->coord.utm_zone != dp->center->utm_zone )
             draw_utm_skip_insignia (  dp->vp, main_gc, x, y);
 
-          if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) {
-            dp->track_gc_iter = calculate_velocity ( dp->vtl, tp, tp2 );
-            main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
-          }
-
           if (!useoldvals)
             vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &oldx, &oldy );
 
@@ -1191,31 +1272,32 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
           else {
 
             vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
-            if ( dp->vtl->drawelevation && list && list->next && VIK_TRACKPOINT(list->next->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
+            if ( dp->vtl->drawelevation && list->next && VIK_TRACKPOINT(list->next->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
               GdkPoint tmp[4];
               #define FIXALTITUDE(what) ((VIK_TRACKPOINT((what))->altitude-min_alt)/alt_diff*DRAW_ELEVATION_FACTOR*dp->vtl->elevation_factor/dp->xmpp)
-              if ( list && list->next && VIK_TRACKPOINT(list->next->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
-                tmp[0].x = oldx;
-                tmp[0].y = oldy;
-                tmp[1].x = oldx;
-                tmp[1].y = oldy-FIXALTITUDE(list->data);
-                tmp[2].x = x;
-                tmp[2].y = y-FIXALTITUDE(list->next->data);
-                tmp[3].x = x;
-                tmp[3].y = y;
-
-                GdkGC *tmp_gc;
-                if ( ((oldx - x) > 0 && (oldy - y) > 0) || ((oldx - x) < 0 && (oldy - y) < 0))
-                  tmp_gc = GTK_WIDGET(dp->vp)->style->light_gc[3];
-                else
-                  tmp_gc = GTK_WIDGET(dp->vp)->style->dark_gc[0];
-                vik_viewport_draw_polygon ( dp->vp, tmp_gc, TRUE, tmp, 4);
-              }
+
+             tmp[0].x = oldx;
+             tmp[0].y = oldy;
+             tmp[1].x = oldx;
+             tmp[1].y = oldy-FIXALTITUDE(list->data);
+             tmp[2].x = x;
+             tmp[2].y = y-FIXALTITUDE(list->next->data);
+             tmp[3].x = x;
+             tmp[3].y = y;
+
+             GdkGC *tmp_gc;
+             if ( ((oldx - x) > 0 && (oldy - y) > 0) || ((oldx - x) < 0 && (oldy - y) < 0))
+               tmp_gc = GTK_WIDGET(dp->vp)->style->light_gc[3];
+             else
+               tmp_gc = GTK_WIDGET(dp->vp)->style->dark_gc[0];
+             vik_viewport_draw_polygon ( dp->vp, tmp_gc, TRUE, tmp, 4);
+
               vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy-FIXALTITUDE(list->data), x, y-FIXALTITUDE(list->next->data));
             }
           }
         }
 
+      skip:
         oldx = x;
         oldy = y;
         useoldvals = TRUE;
@@ -1227,20 +1309,33 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
           if ( dp->vtl->coord_mode != VIK_COORD_UTM || tp->coord.utm_zone == dp->center->utm_zone )
           {
             vik_viewport_coord_to_screen ( dp->vp, &(tp->coord), &x, &y );
-            if ( dp->vtl->drawmode == DRAWMODE_BY_VELOCITY ) {
-              dp->track_gc_iter = calculate_velocity ( dp->vtl, tp, tp2 );
+
+            if ( !drawing_highlight && (dp->vtl->drawmode == DRAWMODE_BY_SPEED) ) {
+              dp->track_gc_iter = track_section_colour_by_speed ( dp->vtl, tp, tp2, average_speed, low_speed, high_speed );
               main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
-            }
+           }
 
-            if ( drawing_white_background )
-              vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
-            else
-              vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
+           /*
+            * If points are the same in display coordinates, don't draw.
+            */
+           if ( x != oldx || y != oldy )
+             {
+               if ( drawing_white_background )
+                 vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
+               else
+                 vik_viewport_draw_line ( dp->vp, main_gc, oldx, oldy, x, y);
+             }
           }
           else 
           {
-            vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &x, &y );
-            draw_utm_skip_insignia ( dp->vp, main_gc, x, y );
+           /*
+            * If points are the same in display coordinates, don't draw.
+            */
+           if ( x != oldx && y != oldy )
+             {
+               vik_viewport_coord_to_screen ( dp->vp, &(tp2->coord), &x, &y );
+               draw_utm_skip_insignia ( dp->vp, main_gc, x, y );
+             }
           }
         }
         useoldvals = FALSE;
@@ -1248,7 +1343,7 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     }
   }
   if ( dp->vtl->drawmode == DRAWMODE_BY_TRACK )
-    if ( ++(dp->track_gc_iter) >= VIK_TRW_LAYER_TRACK_GC )
+    if ( ++(dp->track_gc_iter) >= VIK_TRW_LAYER_TRACK_GC_MAX )
       dp->track_gc_iter = 0;
 }
 
@@ -1389,7 +1484,7 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
       /* thanks to the GPSDrive people (Fritz Ganter et al.) for hints on this part ... yah, I'm too lazy to study documentation */
       gint label_x, label_y;
       gint width, height;
-      pango_layout_set_text ( dp->vtl->wplabellayout, name, -1 );
+      pango_layout_set_text ( dp->vtl->wplabellayout, wp->name, -1 );
       pango_layout_get_pixel_size ( dp->vtl->wplabellayout, &width, &height );
       label_x = x - width/2;
       if (sym)
@@ -1414,7 +1509,7 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
   }
 }
 
-void vik_trw_layer_draw ( VikTrwLayer *l, gpointer data )
+static void trw_layer_draw ( VikTrwLayer *l, gpointer data )
 {
   static struct DrawingParams dp;
   g_assert ( l != NULL );
@@ -1442,6 +1537,11 @@ static void trw_layer_free_track_gcs ( VikTrwLayer *vtl )
     g_object_unref ( vtl->current_track_gc );
     vtl->current_track_gc = NULL;
   }
+  if ( vtl->current_track_newpoint_gc )
+  {
+    g_object_unref ( vtl->current_track_newpoint_gc );
+    vtl->current_track_newpoint_gc = NULL;
+  }
 
   if ( ! vtl->track_gc )
     return;
@@ -1468,6 +1568,12 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp )
   vtl->current_track_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 );
   gdk_gc_set_line_attributes ( vtl->current_track_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
 
+  // 'newpoint' gc is exactly the same as the current track gc
+  if ( vtl->current_track_newpoint_gc )
+    g_object_unref ( vtl->current_track_newpoint_gc );
+  vtl->current_track_newpoint_gc = vik_viewport_new_gc ( vp, "#FF0000", 2 );
+  gdk_gc_set_line_attributes ( vtl->current_track_newpoint_gc, 2, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND );
+
   vtl->track_gc = g_array_sized_new ( FALSE, FALSE, sizeof ( GdkGC * ), VIK_TRW_LAYER_TRACK_GC );
 
   gc[0] = vik_viewport_new_gc ( vp, "#2d870a", width ); /* below range */
@@ -1487,12 +1593,23 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp )
 
   gc[12] = vik_viewport_new_gc ( vp, "#000000", width ); /* black / no speed data */
 
+  gc[VIK_TRW_LAYER_TRACK_GC_SLOW] = vik_viewport_new_gc ( vp, "#E6202E", width ); // red-ish
+  gc[VIK_TRW_LAYER_TRACK_GC_AVER] = vik_viewport_new_gc ( vp, "#D2CD26", width ); // yellow-ish
+  gc[VIK_TRW_LAYER_TRACK_GC_FAST] = vik_viewport_new_gc ( vp, "#2B8700", width ); // green-ish
+
   g_array_append_vals ( vtl->track_gc, gc, VIK_TRW_LAYER_TRACK_GC );
 }
 
-VikTrwLayer *vik_trw_layer_create ( VikViewport *vp )
+static VikTrwLayer* trw_layer_create ( VikViewport *vp )
 {
-  VikTrwLayer *rv = vik_trw_layer_new ( 0 );
+  VikTrwLayer *rv = trw_layer_new ( DRAWMODE_BY_TRACK );
+  vik_layer_rename ( VIK_LAYER(rv), vik_trw_layer_interface.name );
+
+  if ( vp == NULL || GTK_WIDGET(vp)->window == NULL ) {
+    /* early exit, as the rest is GUI related */
+    return rv;
+  }
+
   PangoFontDescription *pfd;
   rv->wplabellayout = gtk_widget_create_pango_layout (GTK_WIDGET(vp), NULL);
   pfd = pango_font_description_from_string (WAYPOINT_FONT);
@@ -1500,8 +1617,6 @@ VikTrwLayer *vik_trw_layer_create ( VikViewport *vp )
   /* freeing PangoFontDescription, cause it has been copied by prev. call */
   pango_font_description_free (pfd);
 
-  vik_layer_rename ( VIK_LAYER(rv), vik_trw_layer_interface.name );
-
   trw_layer_new_track_gcs ( rv, vp );
 
   rv->waypoint_gc = vik_viewport_new_gc ( vp, "#000000", 2 );
@@ -1523,44 +1638,44 @@ VikTrwLayer *vik_trw_layer_create ( VikViewport *vp )
   return rv;
 }
 
-static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pass_along[5] )
+static void trw_layer_realize_track ( gpointer id, VikTrack *track, gpointer pass_along[5] )
 {
   GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
 
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-  vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
+  vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], track->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
 #else
-  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
+  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], track->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
 #endif
 
   *new_iter = *((GtkTreeIter *) pass_along[1]);
-  g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, name, new_iter );
+  g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->tracks_iters, id, new_iter );
 
   if ( ! track->visible )
     vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
 }
 
-static void trw_layer_realize_waypoint ( gchar *name, VikWaypoint *wp, gpointer pass_along[5] )
+static void trw_layer_realize_waypoint ( gpointer id, VikWaypoint *wp, gpointer pass_along[5] )
 {
   GtkTreeIter *new_iter = g_malloc(sizeof(GtkTreeIter));
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-  vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
+  vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
 #else
-  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, GPOINTER_TO_INT (pass_along[4]), NULL, TRUE, TRUE );
+  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], wp->name, pass_along[2], id, GPOINTER_TO_UINT (pass_along[4]), NULL, TRUE, TRUE );
 #endif
 
   *new_iter = *((GtkTreeIter *) pass_along[1]);
-  g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->waypoints_iters, name, new_iter );
+  g_hash_table_insert ( VIK_TRW_LAYER(pass_along[2])->waypoints_iters, id, new_iter );
 
   if ( ! wp->visible )
     vik_treeview_item_set_visible ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[1], FALSE );
 }
 
 
-void vik_trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
+static void trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *layer_iter )
 {
   GtkTreeIter iter2;
-  gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, (gpointer) VIK_TRW_LAYER_SUBLAYER_TRACK };
+  gpointer pass_along[5] = { &(vtl->tracks_iter), &iter2, vtl, vt, GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_TRACK) };
 
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
   vik_treeview_add_sublayer_alphabetized ( (VikTreeview *) vt, layer_iter, &(vtl->tracks_iter), _("Tracks"), vtl, NULL, VIK_TRW_LAYER_SUBLAYER_TRACKS, NULL, TRUE, FALSE );
@@ -1582,13 +1697,13 @@ void vik_trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *lay
     vik_treeview_item_set_visible ( (VikTreeview *) vt, &(vtl->waypoints_iter), FALSE ); 
 
   pass_along[0] = &(vtl->waypoints_iter);
-  pass_along[4] = (gpointer) VIK_TRW_LAYER_SUBLAYER_WAYPOINT;
+  pass_along[4] = GINT_TO_POINTER(VIK_TRW_LAYER_SUBLAYER_WAYPOINT);
 
   g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_realize_waypoint, pass_along );
 
 }
 
-gboolean vik_trw_layer_sublayer_toggle_visible ( VikTrwLayer *l, gint subtype, gpointer sublayer )
+static gboolean trw_layer_sublayer_toggle_visible ( VikTrwLayer *l, gint subtype, gpointer sublayer )
 {
   switch ( subtype )
   {
@@ -1614,6 +1729,14 @@ gboolean vik_trw_layer_sublayer_toggle_visible ( VikTrwLayer *l, gint subtype, g
   return TRUE;
 }
 
+/*
+ * Return a property about tracks for this layer
+ */
+gint vik_trw_layer_get_property_tracks_line_thickness ( VikTrwLayer *vtl )
+{
+  return vtl->line_thickness;
+}
+
 // Structure to hold multiple track information for a layer
 typedef struct {
   gdouble length;
@@ -1790,7 +1913,8 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g
     {
       VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer );
       // NB It's OK to return NULL
-      return w->comment;
+      if ( w )
+        return w->comment;
     }
     break;
     default: break;
@@ -1798,16 +1922,103 @@ static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, g
   return NULL;
 }
 
+/*
+ * Function to show basic track point information on the statusbar
+ */
+static void set_statusbar_msg_info_trkpt ( VikTrwLayer *vtl, VikTrackpoint *trkpt )
+{
+  gchar tmp_buf1[64];
+  switch (a_vik_get_units_height ()) {
+  case VIK_UNITS_HEIGHT_FEET:
+    g_snprintf(tmp_buf1, sizeof(tmp_buf1), _("Trkpt: Alt %dft"), (int)round(VIK_METERS_TO_FEET(trkpt->altitude)));
+    break;
+  default:
+    //VIK_UNITS_HEIGHT_METRES:
+    g_snprintf(tmp_buf1, sizeof(tmp_buf1), _("Trkpt: Alt %dm"), (int)round(trkpt->altitude));
+  }
+  
+  gchar tmp_buf2[64];
+  tmp_buf2[0] = '\0';
+  if ( trkpt->has_timestamp ) {
+    // Compact date time format
+    strftime (tmp_buf2, sizeof(tmp_buf2), _(" | Time %x %X"), localtime(&(trkpt->timestamp)));
+  }
+
+  // Position part
+  // Position is put later on, as this bit may not be seen if the display is not big enough,
+  //   one can easily use the current pointer position to see this if needed
+  gchar *lat = NULL, *lon = NULL;
+  static struct LatLon ll;
+  vik_coord_to_latlon (&(trkpt->coord), &ll);
+  a_coords_latlon_to_string ( &ll, &lat, &lon );
+
+  // Track name
+  // Again is put later on, as this bit may not be seen if the display is not big enough
+  //  trackname can be seen from the treeview (when enabled)
+  // Also name could be very long to not leave room for anything else
+  gchar tmp_buf3[64];
+  tmp_buf3[0] = '\0';
+  if ( vtl->current_tp_track ) {
+    g_snprintf(tmp_buf3, sizeof(tmp_buf3),  _(" | Track: %s"), vtl->current_tp_track->name );
+  }
+
+  // Combine parts to make overall message
+  gchar *msg = g_strdup_printf (_("%s%s | %s %s %s"), tmp_buf1, tmp_buf2, lat, lon, tmp_buf3);
+  vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, msg );
+  g_free ( lat );
+  g_free ( lon );
+  g_free ( msg );
+}
+
+/*
+ * Function to show basic waypoint information on the statusbar
+ */
+static void set_statusbar_msg_info_wpt ( VikTrwLayer *vtl, VikWaypoint *wpt )
+{
+  gchar tmp_buf1[64];
+  switch (a_vik_get_units_height ()) {
+  case VIK_UNITS_HEIGHT_FEET:
+    g_snprintf(tmp_buf1, sizeof(tmp_buf1), _("Wpt: Alt %dft"), (int)round(VIK_METERS_TO_FEET(wpt->altitude)));
+    break;
+  default:
+    //VIK_UNITS_HEIGHT_METRES:
+    g_snprintf(tmp_buf1, sizeof(tmp_buf1), _("Wpt: Alt %dm"), (int)round(wpt->altitude));
+  }
+  
+  // Position part
+  // Position is put last, as this bit is most likely not to be seen if the display is not big enough,
+  //   one can easily use the current pointer position to see this if needed
+  gchar *lat = NULL, *lon = NULL;
+  static struct LatLon ll;
+  vik_coord_to_latlon (&(wpt->coord), &ll);
+  a_coords_latlon_to_string ( &ll, &lat, &lon );
+
+  // Combine parts to make overall message
+  gchar *msg;
+  if ( wpt->comment )
+    // Add comment if available
+    msg = g_strdup_printf ( _("%s | %s %s | Comment: %s"), tmp_buf1, lat, lon, wpt->comment );
+  else
+    msg = g_strdup_printf ( _("%s | %s %s"), tmp_buf1, lat, lon );
+  vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, msg );
+  g_free ( lat );
+  g_free ( lon );
+  g_free ( msg );
+}
+
 /**
  * General layer selection function, find out which bit is selected and take appropriate action
  */
-gboolean vik_trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublayer, gint type, gpointer vlp )
+static gboolean trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublayer, gint type, gpointer vlp )
 {
   // Reset
-  l->current_wp      = NULL;
-  l->current_wp_name = NULL;
+  l->current_wp    = NULL;
+  l->current_wp_id = NULL;
   trw_layer_cancel_current_tp ( l, FALSE );
 
+  // Clear statusbar
+  vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l))), VIK_STATUSBAR_INFO, "" );
+
   switch ( type )
     {
     case VIK_TREEVIEW_TYPE_LAYER:
@@ -1831,7 +2042,8 @@ gboolean vik_trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublaye
            break;
          case VIK_TRW_LAYER_SUBLAYER_TRACK:
            {
-             vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->tracks, sublayer ), l, sublayer );
+             VikTrack *track = g_hash_table_lookup ( l->tracks, sublayer );
+             vik_window_set_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)track, l, sublayer );
              /* Mark for redraw */
              return TRUE;
            }
@@ -1845,9 +2057,14 @@ gboolean vik_trw_layer_selected ( VikTrwLayer *l, gint subtype, gpointer sublaye
            break;
          case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
            {
-             vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), g_hash_table_lookup ( l->waypoints, sublayer ), l, sublayer );
-             /* Mark for redraw */
-             return TRUE;
+             VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
+             if ( wpt ) {
+            vik_window_set_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), (gpointer)wpt, l, sublayer );
+            // Show some waypoint info
+            set_statusbar_msg_info_wpt ( l, wpt );
+            /* Mark for redraw */
+            return TRUE;
+             }
            }
            break;
          default:
@@ -1876,6 +2093,48 @@ GHashTable *vik_trw_layer_get_waypoints ( VikTrwLayer *l )
   return l->waypoints;
 }
 
+/*
+ * ATM use a case sensitive find
+ * Finds the first one
+ */
+static gboolean trw_layer_waypoint_find ( const gpointer id, const VikWaypoint *wp, const gchar *name )
+{
+  if ( wp && wp->name )
+    if ( ! strcmp ( wp->name, name ) )
+      return TRUE;
+  return FALSE;
+}
+
+/*
+ * Get waypoint by name - not guaranteed to be unique
+ * Finds the first one
+ */
+VikWaypoint *vik_trw_layer_get_waypoint ( VikTrwLayer *vtl, const gchar *name )
+{
+  return g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find, (gpointer) name );
+}
+
+/*
+ * ATM use a case sensitive find
+ * Finds the first one
+ */
+static gboolean trw_layer_track_find ( const gpointer id, const VikTrack *trk, const gchar *name )
+{
+  if ( trk && trk->name )
+    if ( ! strcmp ( trk->name, name ) )
+      return TRUE;
+  return FALSE;
+}
+
+/*
+ * Get track by name - not guaranteed to be unique
+ * Finds the first one
+ */
+VikTrack *vik_trw_layer_get_track ( VikTrwLayer *vtl, const gchar *name )
+{
+  return g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find, (gpointer) name );
+}
+
 static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] )
 {
   static VikCoord fixme;
@@ -2038,7 +2297,7 @@ static void trw_layer_auto_view ( gpointer layer_and_vlp[2] )
     a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("This layer has no waypoints or trackpoints.") );
 }
 
-static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, const gchar* default_name, const gchar* trackname, guint file_type )
+static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, const gchar* default_name, VikTrack* trk, guint file_type )
 {
   GtkWidget *file_selector;
   const gchar *fn;
@@ -2057,7 +2316,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co
     if ( g_file_test ( fn, G_FILE_TEST_EXISTS ) == FALSE )
     {
       gtk_widget_hide ( file_selector );
-      failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trackname);
+      failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, tr);
       break;
     }
     else
@@ -2065,7 +2324,7 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, co
       if ( a_dialog_yes_or_no ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
       {
         gtk_widget_hide ( file_selector );
-       failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trackname);
+       failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, tr);
         break;
       }
     }
@@ -2087,7 +2346,14 @@ static void trw_layer_export_gpsmapper ( gpointer layer_and_vlp[2] )
 
 static void trw_layer_export_gpx ( gpointer layer_and_vlp[2] )
 {
-  trw_layer_export ( layer_and_vlp, _("Export Layer"), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])), NULL, FILE_TYPE_GPX );
+  /* Auto append '.gpx' to track name (providing it's not already there) for the default filename */
+  gchar *auto_save_name = g_strdup ( vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])) );
+  if ( ! check_file_ext ( auto_save_name, ".gpx" ) )
+    auto_save_name = g_strconcat ( auto_save_name, ".gpx", NULL );
+
+  trw_layer_export ( layer_and_vlp, _("Export Layer"), auto_save_name, NULL, FILE_TYPE_GPX );
+
+  g_free ( auto_save_name );
 }
 
 static void trw_layer_export_kml ( gpointer layer_and_vlp[2] )
@@ -2102,25 +2368,87 @@ static void trw_layer_export_kml ( gpointer layer_and_vlp[2] )
   g_free ( auto_save_name );
 }
 
+/**
+ * Convert the given TRW layer into a temporary GPX file and open it with the specified program
+ *
+ */
+static void trw_layer_export_external_gpx ( gpointer layer_and_vlp[2], const gchar* external_program )
+{
+  gchar *name_used = NULL;
+  int fd;
+
+  if ((fd = g_file_open_tmp("tmp-viking.XXXXXX.gpx", &name_used, NULL)) >= 0) {
+    gboolean failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), name_used, FILE_TYPE_GPX, NULL);
+    if (failed) {
+      a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Could not create temporary file for export.") );
+    }
+    else {
+      GError *err = NULL;
+      gchar *quoted_file = g_shell_quote ( name_used );
+      gchar *cmd = g_strdup_printf ( "%s %s", external_program, quoted_file );
+      g_free ( quoted_file );
+      if ( ! g_spawn_command_line_async ( cmd, &err ) )
+       {
+         a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_LAYER( layer_and_vlp[0]), _("Could not launch %s."), external_program );
+         g_error_free ( err );
+       }
+      g_free ( cmd );
+    }
+    // Note ATM the 'temporary' file is not deleted, as loading via another program is not instantaneous
+    //g_remove ( name_used );
+    // Perhaps should be deleted when the program ends?
+    // For now leave it to the user to delete it / use system temp cleanup methods.
+    g_free ( name_used );
+  }
+}
+
+static void trw_layer_export_external_gpx_1 ( gpointer layer_and_vlp[2] )
+{
+  trw_layer_export_external_gpx ( layer_and_vlp, a_vik_get_external_gpx_program_1() );
+}
+
+static void trw_layer_export_external_gpx_2 ( gpointer layer_and_vlp[2] )
+{
+  trw_layer_export_external_gpx ( layer_and_vlp, a_vik_get_external_gpx_program_2() );
+}
+
 static void trw_layer_export_gpx_track ( gpointer pass_along[6] )
 {
   gpointer layer_and_vlp[2];
   layer_and_vlp[0] = pass_along[0];
   layer_and_vlp[1] = pass_along[1];
+  VikTrack *trk = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+
+  if ( !trk || !trk->name )
+    return;
 
   /* Auto append '.gpx' to track name (providing it's not already there) for the default filename */
-  gchar *auto_save_name = g_strdup ( pass_along[3] );
+  gchar *auto_save_name = g_strdup ( trk->name );
   if ( ! check_file_ext ( auto_save_name, ".gpx" ) )
     auto_save_name = g_strconcat ( auto_save_name, ".gpx", NULL );
 
-  trw_layer_export ( layer_and_vlp, _("Export Track as GPX"), auto_save_name, pass_along[3], FILE_TYPE_GPX );
+  trw_layer_export ( layer_and_vlp, _("Export Track as GPX"), auto_save_name, trk, FILE_TYPE_GPX );
 
   g_free ( auto_save_name );
 }
 
+typedef struct {
+  VikWaypoint *wp; // input
+  gpointer uuid;   // output
+} wpu_udata;
+
+static gboolean trw_layer_waypoint_find_uuid ( const gpointer id, const VikWaypoint *wp, gpointer udata )
+{
+  wpu_udata *user_data = udata;
+  if ( wp == user_data->wp ) {
+    user_data->uuid = id;
+    return TRUE;
+  }
+  return FALSE;
+}
+
 static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
 {
-  GHashTable *wps = vik_trw_layer_get_waypoints ( VIK_TRW_LAYER(layer_and_vlp[0]) );
   GtkWidget *dia = gtk_dialog_new_with_buttons (_("Find"),
                                                  VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]),
                                                  GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -2143,26 +2471,34 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
 
   while ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_ACCEPT )
   {
-    VikWaypoint *wp;
-    gchar *upname = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
-    int i;
+    gchar *name = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+    // Find *first* wp with the given name
+    VikWaypoint *wp = vik_trw_layer_get_waypoint ( VIK_TRW_LAYER(layer_and_vlp[0]), name );
 
-    for ( i = strlen(upname)-1; i >= 0; i-- )
-      upname[i] = toupper(upname[i]);
-
-    wp = g_hash_table_lookup ( wps, upname );
-
-    if (!wp)
+    if ( !wp )
       a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("Waypoint not found in this layer.") );
     else
     {
       vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(layer_and_vlp[1])), &(wp->coord) );
       vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(layer_and_vlp[1]) );
-      vik_treeview_select_iter ( VIK_LAYER(layer_and_vlp[0])->vt, g_hash_table_lookup ( VIK_TRW_LAYER(layer_and_vlp[0])->waypoints_iters, upname ), TRUE );
+
+      // Find and select on the side panel
+      wpu_udata udata;
+      udata.wp   = wp;
+      udata.uuid = NULL;
+
+      // Hmmm, want key of it
+      gpointer *wpf = g_hash_table_find ( VIK_TRW_LAYER(layer_and_vlp[0])->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+
+      if ( wpf && udata.uuid ) {
+        GtkTreeIter *it = g_hash_table_lookup ( VIK_TRW_LAYER(layer_and_vlp[0])->waypoints_iters, udata.uuid );
+        vik_treeview_select_iter ( VIK_LAYER(layer_and_vlp[0])->vt, it, TRUE );
+      }
+
       break;
     }
 
-    g_free ( upname );
+    g_free ( name );
 
   }
   gtk_widget_destroy ( dia );
@@ -2175,12 +2511,20 @@ gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikC
   gchar *returned_name;
   gboolean updated;
   wp->coord = *def_coord;
+  
+  // Attempt to auto set height if DEM data is available
+  gint16 elev = a_dems_get_elev_by_coord ( &(wp->coord), VIK_DEM_INTERPOL_BEST );
+  if ( elev != VIK_DEM_INVALID_ELEVATION )
+    wp->altitude = (gdouble)elev;
 
-  if ( ( returned_name = a_dialog_waypoint ( w, default_name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode, TRUE, &updated ) ) )
+  returned_name = a_dialog_waypoint ( w, default_name, wp, vtl->coord_mode, TRUE, &updated );
+
+  if ( returned_name )
   {
     wp->visible = TRUE;
     vik_trw_layer_add_waypoint ( vtl, returned_name, wp );
     g_free (default_name);
+    g_free (returned_name);
     return TRUE;
   }
   g_free (default_name);
@@ -2231,34 +2575,159 @@ static void trw_layer_new_wikipedia_wp_layer ( gpointer lav[2] )
   a_geonames_wikipedia_box((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vtl, vlp, maxmin);
 }
 
-static void trw_layer_new_wp ( gpointer lav[2] )
+#ifdef VIK_CONFIG_GEOTAG
+static void trw_layer_geotagging_waypoint_mtime_keep ( gpointer pass_along[6] )
 {
-  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
-  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
-  /* TODO longone: okay, if layer above (aggregate) is invisible but vtl->visible is true, this redraws for no reason.
-     instead return true if you want to update. */
-  if ( vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), vik_viewport_get_center(vik_layers_panel_get_viewport(vlp))) && VIK_LAYER(vtl)->visible )
-    vik_layers_panel_emit_update ( vlp );
+  VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
+  if ( wp )
+    // Update directly - not changing the mtime
+    a_geotag_write_exif_gps ( wp->image, wp->coord, wp->altitude, TRUE );
 }
 
-static void trw_layer_auto_tracks_view ( gpointer lav[2] )
+static void trw_layer_geotagging_waypoint_mtime_update ( gpointer pass_along[6] )
 {
-  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
-  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
-
-  if ( g_hash_table_size (vtl->tracks) > 0 ) {
-    struct LatLon maxmin[2] = { {0,0}, {0,0} };
-    g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
-    trw_layer_zoom_to_show_latlons ( vtl, vik_layers_panel_get_viewport (vlp), maxmin );
-    vik_layers_panel_emit_update ( vlp );
-  }
+  VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
+  if ( wp )
+    // Update directly
+    a_geotag_write_exif_gps ( wp->image, wp->coord, wp->altitude, FALSE );
 }
 
-static void trw_layer_single_waypoint_jump ( const gchar *name, const VikWaypoint *wp, gpointer vvp )
+/*
+ * Use code in separate file for this feature as reasonably complex
+ */
+static void trw_layer_geotagging_track ( gpointer pass_along[6] )
 {
-  /* NB do not care if wp is visible or not */
-  vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), &(wp->coord) );
-}
+  VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+  VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+  // Unset so can be reverified later if necessary
+  vtl->has_verified_thumbnails = FALSE;
+
+  trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           vtl,
+                           track,
+                           track->name );
+}
+
+static void trw_layer_geotagging ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  // Unset so can be reverified later if necessary
+  vtl->has_verified_thumbnails = FALSE;
+
+  trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           vtl,
+                           NULL,
+                           NULL);
+}
+#endif
+
+// 'Acquires' - Same as in File Menu -> Acquire - applies into the selected TRW Layer //
+
+/*
+ * Acquire into this TRW Layer straight from GPS Device
+ */
+static void trw_layer_acquire_gps_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  vik_datasource_gps_interface.mode = VIK_DATASOURCE_ADDTOLAYER;
+  a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface );
+}
+
+/*
+ * Acquire into this TRW Layer from Google Directions
+ */
+static void trw_layer_acquire_google_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  a_acquire ( vw, vlp, vvp, &vik_datasource_google_interface );
+}
+
+#ifdef VIK_CONFIG_OPENSTREETMAP
+/*
+ * Acquire into this TRW Layer from OSM
+ */
+static void trw_layer_acquire_osm_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  a_acquire ( vw, vlp, vvp, &vik_datasource_osm_interface );
+}
+#endif
+
+#ifdef VIK_CONFIG_GEOCACHES
+/*
+ * Acquire into this TRW Layer from Geocaching.com
+ */
+static void trw_layer_acquire_geocache_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  a_acquire ( vw, vlp, vvp, &vik_datasource_gc_interface );
+}
+#endif
+
+#ifdef VIK_CONFIG_GEOTAG
+/*
+ * Acquire into this TRW Layer from images
+ */
+static void trw_layer_acquire_geotagged_cb ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
+  VikViewport *vvp =  vik_window_viewport(vw);
+
+  vik_datasource_geotag_interface.mode = VIK_DATASOURCE_ADDTOLAYER;
+  a_acquire ( vw, vlp, vvp, &vik_datasource_geotag_interface );
+
+  // Reverify thumbnails as they may have changed
+  vtl->has_verified_thumbnails = FALSE;
+  trw_layer_verify_thumbnails ( vtl, NULL );
+}
+#endif
+
+static void trw_layer_new_wp ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+  /* TODO longone: okay, if layer above (aggregate) is invisible but vtl->visible is true, this redraws for no reason.
+     instead return true if you want to update. */
+  if ( vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), vik_viewport_get_center(vik_layers_panel_get_viewport(vlp))) && VIK_LAYER(vtl)->visible )
+    vik_layers_panel_emit_update ( vlp );
+}
+
+static void trw_layer_auto_tracks_view ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+  if ( g_hash_table_size (vtl->tracks) > 0 ) {
+    struct LatLon maxmin[2] = { {0,0}, {0,0} };
+    g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_find_maxmin_tracks, maxmin );
+    trw_layer_zoom_to_show_latlons ( vtl, vik_layers_panel_get_viewport (vlp), maxmin );
+    vik_layers_panel_emit_update ( vlp );
+  }
+}
+
+static void trw_layer_single_waypoint_jump ( const gchar *name, const VikWaypoint *wp, gpointer vvp )
+{
+  /* NB do not care if wp is visible or not */
+  vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), &(wp->coord) );
+}
 
 static void trw_layer_auto_waypoints_view ( gpointer lav[2] )
 {
@@ -2281,12 +2750,11 @@ static void trw_layer_auto_waypoints_view ( gpointer lav[2] )
   vik_layers_panel_emit_update ( vlp );
 }
 
-void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vlp )
+static void trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vlp )
 {
   static gpointer pass_along[2];
   GtkWidget *item;
   GtkWidget *export_submenu;
-  GtkWidget *wikipedia_submenu;
   pass_along[0] = vtl;
   pass_along[1] = vlp;
 
@@ -2294,7 +2762,9 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
   gtk_widget_show ( item );
 
-  item = gtk_menu_item_new_with_mnemonic ( _("_View Layer") );
+  /* Now with icons */
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_View Layer") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_view), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
@@ -2309,7 +2779,8 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
 
-  item = gtk_menu_item_new_with_mnemonic ( _("_Goto Center of Layer") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto Center of Layer") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_centerize), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
@@ -2320,7 +2791,8 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   gtk_widget_show ( item );
 
   export_submenu = gtk_menu_new ();
-  item = gtk_menu_item_new_with_mnemonic ( _("_Export Layer") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_Export Layer") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
   gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), export_submenu );
@@ -2345,58 +2817,127 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
   gtk_widget_show ( item );
 
-  item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+  gchar* external1 = g_strconcat ( _("Open with External Program_1: "), a_vik_get_external_gpx_program_1(), NULL );
+  item = gtk_menu_item_new_with_mnemonic ( external1 );
+  g_free ( external1 );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_external_gpx_1), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+  gtk_widget_show ( item );
+
+  gchar* external2 = g_strconcat ( _("Open with External Program_2: "), a_vik_get_external_gpx_program_2(), NULL );
+  item = gtk_menu_item_new_with_mnemonic ( external2 );
+  g_free ( external2 );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_external_gpx_2), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wp), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
 
 #ifdef VIK_CONFIG_GEONAMES
-  wikipedia_submenu = gtk_menu_new();
-  item = gtk_menu_item_new_with_mnemonic ( _("_Add Wikipedia Waypoints") );
+  GtkWidget *wikipedia_submenu = gtk_menu_new();
+  item = gtk_image_menu_item_new_with_mnemonic ( _("_Add Wikipedia Waypoints") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
   gtk_menu_shell_append(GTK_MENU_SHELL (menu), item);
   gtk_widget_show(item);
   gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), wikipedia_submenu);
 
-  item = gtk_menu_item_new_with_mnemonic ( _("Within _Layer Bounds") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Layer Bounds") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_layer), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
   gtk_widget_show ( item );
 
-  item = gtk_menu_item_new_with_mnemonic ( _("Within _Current View") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Within _Current View") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_100, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wikipedia_wp_viewport), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (wikipedia_submenu), item);
   gtk_widget_show ( item );
 #endif
 
+#ifdef VIK_CONFIG_GEOTAG
+  item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show ( item );
+#endif
+
+  GtkWidget *acquire_submenu = gtk_menu_new ();
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Ac_quire") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_DOWN, GTK_ICON_SIZE_MENU) );
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show ( item );
+  gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), acquire_submenu );
+  
+  item = gtk_menu_item_new_with_mnemonic ( _("From _GPS...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_gps_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("From G_oogle Directions...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_google_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
+
+#ifdef VIK_CONFIG_OPENSTREETMAP
+  item = gtk_menu_item_new_with_mnemonic ( _("From _OSM Traces...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_osm_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
+#endif
+
+#ifdef VIK_CONFIG_GEOCACHES
+  item = gtk_menu_item_new_with_mnemonic ( _("From Geo_caching...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_geocache_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
+#endif
+
+#ifdef VIK_CONFIG_GEOTAG
+  item = gtk_menu_item_new_with_mnemonic ( _("From Geotagged _Images...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_acquire_geotagged_cb), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
+  gtk_widget_show ( item );
+#endif
+
 #ifdef VIK_CONFIG_OPENSTREETMAP 
-  item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_cb), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
 #endif
 
   GtkWidget *delete_submenu = gtk_menu_new ();
-  item = gtk_menu_item_new_with_mnemonic ( _("De_lete") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("De_lete") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
   gtk_widget_show ( item );
   gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), delete_submenu );
   
-  item = gtk_menu_item_new_with_mnemonic ( _("Delete All _Tracks") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Delete All _Tracks") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_tracks), pass_along );
   gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
   gtk_widget_show ( item );
   
-  item = gtk_menu_item_new_with_mnemonic ( _("Delete Tracks _From Selection...") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Delete Tracks _From Selection...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_tracks_from_selection), pass_along );
   gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
   gtk_widget_show ( item );
   
-  item = gtk_menu_item_new_with_mnemonic ( _("Delete All _Waypoints") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Delete All _Waypoints") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_waypoints), pass_along );
   gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
   gtk_widget_show ( item );
   
-  item = gtk_menu_item_new_with_mnemonic ( _("Delete Waypoints From _Selection...") );
+  item = gtk_image_menu_item_new_with_mnemonic ( _("Delete Waypoints From _Selection...") );
+  gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
   g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_waypoints_from_selection), pass_along );
   gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
   gtk_widget_show ( item );
@@ -2416,69 +2957,72 @@ void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vl
   }  
 }
 
+// Fake Waypoint UUIDs vi simple increasing integer
+static guint wp_uuid = 0;
+
 void vik_trw_layer_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypoint *wp )
 {
+  wp_uuid++;
+
+  vik_waypoint_set_name (wp, name);
+
   if ( VIK_LAYER(vtl)->realized )
   {
-    VikWaypoint *oldwp = VIK_WAYPOINT ( g_hash_table_lookup ( vtl->waypoints, name ) );
-    if ( oldwp )
-      wp->visible = oldwp->visible; /* same visibility so we don't have to update viktreeview */
-    else
-    {
-      GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
-      // Visibility column always needed for waypoints
+    GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
+
+    // Visibility column always needed for waypoints
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-      vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
+    vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
 #else
-      vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
+    vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, GUINT_TO_POINTER(wp_uuid), VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
 #endif
-      // Actual setting of visibility dependent on the waypoint
-      vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, wp->visible );
-      g_hash_table_insert ( vtl->waypoints_iters, name, iter );
-    }
+    // Actual setting of visibility dependent on the waypoint
+    vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, wp->visible );
+
+    g_hash_table_insert ( vtl->waypoints_iters, GUINT_TO_POINTER(wp_uuid), iter );
   }
 
   highest_wp_number_add_wp(vtl, name);
-  g_hash_table_insert ( vtl->waypoints, name, wp );
+  g_hash_table_insert ( vtl->waypoints, GUINT_TO_POINTER(wp_uuid), wp );
  
 }
 
+// Fake Track UUIDs vi simple increasing integer
+static guint tr_uuid = 0;
+
 void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
 {
+  tr_uuid++;
+
+  vik_track_set_name (t, name);
+
   if ( VIK_LAYER(vtl)->realized )
   {
-    VikTrack *oldt = VIK_TRACK ( g_hash_table_lookup ( vtl->tracks, name ) );
-    if ( oldt )
-      t->visible = oldt->visible; /* same visibility so we don't have to update viktreeview */
-    else
-    {
-      GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
-      // Visibility column always needed for tracks
+    GtkTreeIter *iter = g_malloc(sizeof(GtkTreeIter));
+    // Visibility column always needed for tracks
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-      vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
+    vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, GUINT_TO_POINTER(tr_uuid), VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
 #else
-      vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
+    vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, GUINT_TO_POINTER(tr_uuid), VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
 #endif
-      // Actual setting of visibility dependent on the track
-      vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, t->visible );
-      g_hash_table_insert ( vtl->tracks_iters, name, iter );
-    }
+    // Actual setting of visibility dependent on the track
+    vik_treeview_item_set_visible ( VIK_LAYER(vtl)->vt, iter, t->visible );
+
+    g_hash_table_insert ( vtl->tracks_iters, GUINT_TO_POINTER(tr_uuid), iter );
   }
 
-  g_hash_table_insert ( vtl->tracks, name, t );
+  g_hash_table_insert ( vtl->tracks, GUINT_TO_POINTER(tr_uuid), t );
  
 }
 
 /* to be called whenever a track has been deleted or may have been changed. */
-void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, const gchar *trk_name )
+void trw_layer_cancel_tps_of_track ( VikTrwLayer *vtl, VikTrack *trk )
 {
-  if (vtl->current_tp_track_name && g_strcasecmp(trk_name, vtl->current_tp_track_name) == 0)
+  if (vtl->current_tp_track == trk )
     trw_layer_cancel_current_tp ( vtl, FALSE );
-  else if (vtl->last_tp_track_name && g_strcasecmp(trk_name, vtl->last_tp_track_name) == 0)
-    trw_layer_cancel_last_tp ( vtl );
 }
        
-static gchar *get_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name)
+gchar *trw_layer_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type, const gchar *name)
 {
  gint i = 2;
  gchar *newname = g_strdup(name);
@@ -2494,49 +3038,58 @@ static gchar *get_new_unique_sublayer_name (VikTrwLayer *vtl, gint sublayer_type
 
 void vik_trw_layer_filein_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypoint *wp )
 {
-  vik_trw_layer_add_waypoint ( vtl,
-                        get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, name),
-                        wp );
+  // No more uniqueness of name forced when loading from a file
+  // This now makes this function a little redunant as we just flow the parameters through
+  vik_trw_layer_add_waypoint ( vtl, name, wp );
 }
+
 void vik_trw_layer_filein_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *tr )
 {
-  if ( vtl->magic_scissors_append && vtl->magic_scissors_current_track ) {
+  if ( vtl->route_finder_append && vtl->route_finder_current_track ) {
     vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
-    vik_track_steal_and_append_trackpoints ( vtl->magic_scissors_current_track, tr );
+    vik_track_steal_and_append_trackpoints ( vtl->route_finder_current_track, tr );
     vik_track_free ( tr );
-    vtl->magic_scissors_append = FALSE; /* this means we have added it */
+    vtl->route_finder_append = FALSE; /* this means we have added it */
   } else {
-    gchar *new_name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, name);
-    vik_trw_layer_add_track ( vtl, new_name, tr );
 
-    if ( vtl->magic_scissors_check_added_track ) {
+    // No more uniqueness of name forced when loading from a file
+    vik_trw_layer_add_track ( vtl, name, tr );
+
+    if ( vtl->route_finder_check_added_track ) {
       vik_track_remove_dup_points ( tr ); /* make "double point" track work to undo */
-      if ( vtl->magic_scissors_added_track_name ) /* for google routes */
-        g_free ( vtl->magic_scissors_added_track_name );
-      vtl->magic_scissors_added_track_name = g_strdup(new_name);
+      vtl->route_finder_added_track = tr;
     }
   }
 }
 
-static void trw_layer_enum_item ( const gchar *name, GList **tr, GList **l )
+static void trw_layer_enum_item ( gpointer id, GList **tr, GList **l )
 {
-  *l = g_list_append(*l, (gpointer)name);
+  *l = g_list_append(*l, id);
 }
 
-static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, gchar *name, gint type )
+/*
+ * Move an item from one TRW layer to another TRW layer
+ */
+static void trw_layer_move_item ( VikTrwLayer *vtl_src, VikTrwLayer *vtl_dest, gpointer id, gint type )
 {
-  gchar *newname = get_new_unique_sublayer_name(vtl_dest, type, name);
   if (type == VIK_TRW_LAYER_SUBLAYER_TRACK) {
-    VikTrack *t;
-    t = vik_track_copy(vik_trw_layer_get_track(vtl_src, name));
-    vik_trw_layer_delete_track(vtl_src, name);
-    vik_trw_layer_add_track(vtl_dest, newname, t);
+    VikTrack *trk = g_hash_table_lookup ( vtl_src->tracks, id );
+
+    gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, trk->name);
+
+    VikTrack *trk2 = vik_track_copy ( trk );
+    vik_trw_layer_add_track ( vtl_dest, newname, trk2 );
+    vik_trw_layer_delete_track ( vtl_src, trk );
   }
-  if (type==VIK_TRW_LAYER_SUBLAYER_WAYPOINT) {
-    VikWaypoint *w;
-    w = vik_waypoint_copy(vik_trw_layer_get_waypoint(vtl_src, name));
-    vik_trw_layer_delete_waypoint(vtl_src, name);
-    vik_trw_layer_add_waypoint(vtl_dest, newname, w);
+
+  if (type == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) {
+    VikWaypoint *wp = g_hash_table_lookup ( vtl_src->waypoints, id );
+
+    gchar *newname = trw_layer_new_unique_sublayer_name(vtl_dest, type, wp->name);
+
+    VikWaypoint *wp2 = vik_waypoint_copy ( wp );
+    vik_trw_layer_add_waypoint ( vtl_dest, newname, wp2 );
+    trw_layer_delete_waypoint ( vtl_src, wp );
   }
 }
 
@@ -2573,59 +3126,180 @@ static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl
   }
 }
 
-gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, const gchar *trk_name )
+typedef struct {
+  VikTrack *trk; // input
+  gpointer uuid;   // output
+} trku_udata;
+
+static gboolean trw_layer_track_find_uuid ( const gpointer id, const VikTrack *trk, gpointer udata )
+{
+  trku_udata *user_data = udata;
+  if ( trk == user_data->trk ) {
+    user_data->uuid = id;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, VikTrack *trk )
 {
-  VikTrack *t = g_hash_table_lookup ( vtl->tracks, trk_name );
   gboolean was_visible = FALSE;
-  if ( t )
-  {
-    GtkTreeIter *it;
-    was_visible = t->visible;
-    if ( t == vtl->current_track ) {
+
+  if ( trk && trk->name ) {
+
+    if ( trk == vtl->current_track ) {
       vtl->current_track = NULL;
+      vtl->current_tp_track = NULL;
+      vtl->current_tp_id = NULL;
+      vtl->moving_tp = FALSE;
     }
-    if ( t == vtl->magic_scissors_current_track )
-      vtl->magic_scissors_current_track = NULL;
-    /* could be current_tp, so we have to check */
-    trw_layer_cancel_tps_of_track ( vtl, trk_name );
 
-    g_assert ( ( it = g_hash_table_lookup ( vtl->tracks_iters, trk_name ) ) );
-    vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
-    g_hash_table_remove ( vtl->tracks_iters, trk_name );
+    was_visible = trk->visible;
 
-    /* do this last because trk_name may be pointing to actual orig key */
-    g_hash_table_remove ( vtl->tracks, trk_name );
+    if ( trk == vtl->route_finder_current_track )
+      vtl->route_finder_current_track = NULL;
+
+    if ( trk == vtl->route_finder_added_track )
+      vtl->route_finder_added_track = NULL;
+
+    trku_udata udata;
+    udata.trk  = trk;
+    udata.uuid = NULL;
+
+    // Hmmm, want key of it
+    gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+
+    if ( trkf && udata.uuid ) {
+      /* could be current_tp, so we have to check */
+      trw_layer_cancel_tps_of_track ( vtl, trk );
+
+      GtkTreeIter *it = g_hash_table_lookup ( vtl->tracks_iters, udata.uuid );
+
+      if ( it ) {
+        vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
+        g_hash_table_remove ( vtl->tracks_iters, udata.uuid );
+        g_hash_table_remove ( vtl->tracks, udata.uuid );
+      }
+    }
   }
   return was_visible;
 }
 
-gboolean vik_trw_layer_delete_waypoint ( VikTrwLayer *vtl, const gchar *wp_name )
+static gboolean trw_layer_delete_waypoint ( VikTrwLayer *vtl, VikWaypoint *wp )
 {
   gboolean was_visible = FALSE;
-  VikWaypoint *wp;
 
-  wp = g_hash_table_lookup ( vtl->waypoints, wp_name );
-  if ( wp ) {
-    GtkTreeIter *it;
+  if ( wp && wp->name ) {
 
     if ( wp == vtl->current_wp ) {
       vtl->current_wp = NULL;
-      vtl->current_wp_name = NULL;
+      vtl->current_wp_id = NULL;
       vtl->moving_wp = FALSE;
     }
 
     was_visible = wp->visible;
-    g_assert ( ( it = g_hash_table_lookup ( vtl->waypoints_iters, (gchar *) wp_name ) ) );
-    vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
-    g_hash_table_remove ( vtl->waypoints_iters, (gchar *) wp_name );
+    
+    wpu_udata udata;
+    udata.wp   = wp;
+    udata.uuid = NULL;
+
+    // Hmmm, want key of it
+    gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+
+    if ( wpf && udata.uuid ) {
+      GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
+    
+      if ( it ) {
+        vik_treeview_item_delete ( VIK_LAYER(vtl)->vt, it );
+        g_hash_table_remove ( vtl->waypoints_iters, udata.uuid );
+
+        highest_wp_number_remove_wp(vtl, wp->name);
+        g_hash_table_remove ( vtl->waypoints, udata.uuid ); // last because this frees the name
+      }
+    }
 
-    highest_wp_number_remove_wp(vtl, wp_name);
-    g_hash_table_remove ( vtl->waypoints, wp_name ); /* last because this frees name */
   }
 
   return was_visible;
 }
 
+// Only for temporary use by trw_layer_delete_waypoint_by_name
+static gboolean trw_layer_waypoint_find_uuid_by_name ( const gpointer id, const VikWaypoint *wp, gpointer udata )
+{
+  wpu_udata *user_data = udata;
+  if ( ! strcmp ( wp->name, user_data->wp->name ) ) {
+    user_data->uuid = id;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/*
+ * Delete a waypoint by the given name
+ * NOTE: ATM this will delete the first encountered Waypoint with the specified name
+ *   as there be multiple waypoints with the same name
+ */
+static gboolean trw_layer_delete_waypoint_by_name ( VikTrwLayer *vtl, const gchar *name )
+{
+  wpu_udata udata;
+  // Fake a waypoint with the given name
+  udata.wp   = vik_waypoint_new ();
+  vik_waypoint_set_name (udata.wp, name);
+  // Currently only the name is used in this waypoint find function
+  udata.uuid = NULL;
+
+  // Hmmm, want key of it
+  gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid_by_name, (gpointer) &udata );
+
+  vik_waypoint_free (udata.wp);
+
+  if ( wpf && udata.uuid )
+    return trw_layer_delete_waypoint (vtl, g_hash_table_lookup ( vtl->waypoints, udata.uuid ));
+  else
+    return FALSE;
+}
+
+typedef struct {
+  VikTrack *trk; // input
+  gpointer uuid; // output
+} tpu_udata;
+
+// Only for temporary use by trw_layer_delete_track_by_name
+static gboolean trw_layer_track_find_uuid_by_name ( const gpointer id, const VikTrack *trk, gpointer udata )
+{
+  tpu_udata *user_data = udata;
+  if ( ! strcmp ( trk->name, user_data->trk->name ) ) {
+    user_data->uuid = id;
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/*
+ * Delete a track by the given name
+ * NOTE: ATM this will delete the first encountered Track with the specified name
+ *   as there be multiple track with the same name
+ */
+static gboolean trw_layer_delete_track_by_name ( VikTrwLayer *vtl, const gchar *name )
+{
+  tpu_udata udata;
+  // Fake a track with the given name
+  udata.trk   = vik_track_new ();
+  vik_track_set_name (udata.trk, name);
+  // Currently only the name is used in this waypoint find function
+  udata.uuid = NULL;
+
+  // Hmmm, want key of it
+  gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid_by_name, &udata );
+
+  vik_track_free (udata.trk);
+
+  if ( trkf && udata.uuid )
+    return vik_trw_layer_delete_track (vtl, g_hash_table_lookup ( vtl->tracks, udata.uuid ));
+  else
+    return FALSE;
+}
+
 static void remove_item_from_treeview(const gchar *name, GtkTreeIter *it, VikTreeview * vt)
 {
     vik_treeview_item_delete (vt, it );
@@ -2635,24 +3309,22 @@ void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
 {
 
   vtl->current_track = NULL;
-  vtl->magic_scissors_current_track = NULL;
-  if (vtl->current_tp_track_name)
+  vtl->route_finder_current_track = NULL;
+  vtl->route_finder_added_track = NULL;
+  if (vtl->current_tp_track)
     trw_layer_cancel_current_tp(vtl, FALSE);
-  if (vtl->last_tp_track_name)
-    trw_layer_cancel_last_tp ( vtl );
 
   g_hash_table_foreach(vtl->tracks_iters, (GHFunc) remove_item_from_treeview, VIK_LAYER(vtl)->vt);
   g_hash_table_remove_all(vtl->tracks_iters);
   g_hash_table_remove_all(vtl->tracks);
 
-  /* TODO: only update if the layer is visible (ticked) */
-  vik_layer_emit_update ( VIK_LAYER(vtl) );
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
 }
 
 void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
 {
   vtl->current_wp = NULL;
-  vtl->current_wp_name = NULL;
+  vtl->current_wp_id = NULL;
   vtl->moving_wp = FALSE;
 
   highest_wp_number_reset(vtl);
@@ -2661,8 +3333,7 @@ void vik_trw_layer_delete_all_waypoints ( VikTrwLayer *vtl )
   g_hash_table_remove_all(vtl->waypoints_iters);
   g_hash_table_remove_all(vtl->waypoints);
 
-  /* TODO: only update if the layer is visible (ticked) */
-  vik_layer_emit_update ( VIK_LAYER(vtl) );
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
 }
 
 static void trw_layer_delete_all_tracks ( gpointer lav[2] )
@@ -2691,54 +3362,60 @@ static void trw_layer_delete_item ( gpointer pass_along[6] )
   gboolean was_visible = FALSE;
   if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
-    if ( GPOINTER_TO_INT ( pass_along[4]) )
-      // Get confirmation from the user
-      // Maybe this Waypoint Delete should be optional as is it could get annoying...
-      if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
-                                 _("Are you sure you want to delete the waypoint \"%s\""),
-                                 pass_along[3] ) )
-       return;
-    was_visible = vik_trw_layer_delete_waypoint ( vtl, (gchar *) pass_along[3] );
+    VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
+    if ( wp && wp->name ) {
+      if ( GPOINTER_TO_INT ( pass_along[4]) )
+        // Get confirmation from the user
+        // Maybe this Waypoint Delete should be optional as is it could get annoying...
+        if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+            _("Are you sure you want to delete the waypoint \"%s\""),
+            wp->name ) )
+          return;
+      was_visible = trw_layer_delete_waypoint ( vtl, wp );
+    }
   }
   else
   {
-    if ( GPOINTER_TO_INT ( pass_along[4]) )
-      // Get confirmation from the user
-      if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+    VikTrack *trk = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+    if ( trk && trk->name ) {
+      if ( GPOINTER_TO_INT ( pass_along[4]) )
+        // Get confirmation from the user
+        if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
                                  _("Are you sure you want to delete the track \"%s\""),
-                                 pass_along[3] ) )
-       return;
-    was_visible = vik_trw_layer_delete_track ( vtl, (gchar *) pass_along[3] );
+                                 trk->name ) )
+          return;
+      was_visible = vik_trw_layer_delete_track ( vtl, trk );
+    }
   }
   if ( was_visible )
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
 }
 
 
-static void trw_layer_properties_item ( gpointer pass_along[6] )
+static void trw_layer_properties_item ( gpointer pass_along[7] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
-    VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
-    if ( wp )
+    VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] ); // sublayer
+
+    if ( wp && wp->name )
     {
       gboolean updated = FALSE;
-      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), pass_along[3], wp, NULL, vtl->coord_mode, FALSE, &updated );
+      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), wp->name, wp, vtl->coord_mode, FALSE, &updated );
 
       if ( updated && VIK_LAYER(vtl)->visible )
-       vik_layer_emit_update ( VIK_LAYER(vtl) );
+       vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     }
   }
   else
   {
     VikTrack *tr = g_hash_table_lookup ( vtl->tracks, pass_along[3] );
-    if ( tr )
+    if ( tr && tr->name )
     {
       vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
                                  vtl, tr,
                                  pass_along[1], /* vlp */
-                                 pass_along[3],  /* track name */
                                  pass_along[5] );  /* vvp */
     }
   }
@@ -2759,7 +3436,7 @@ static void goto_coord ( gpointer *vlp, gpointer vl, gpointer vvp, const VikCoor
     /* since vlp not set, vl & vvp should be valid instead! */
     if ( vl && vvp ) {
       vik_viewport_set_center_coord ( VIK_VIEWPORT(vvp), coord );
-      vik_layer_emit_update ( VIK_LAYER(vl) );
+      vik_layer_emit_update ( VIK_LAYER(vl), FALSE );
     }
   }
 }
@@ -2799,24 +3476,26 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] )
     goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) );
 }
 
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
 /**
- * extend a track using magic scissors
+ * extend a track using route finder
  */
-static void trw_layer_extend_track_end_ms ( gpointer pass_along[6] )
+static void trw_layer_extend_track_end_route_finder ( gpointer pass_along[6] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   VikTrack *track = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
   VikCoord last_coord = (((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord);
 
   vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, NUM_TOOLS );
-  vtl->magic_scissors_coord =  last_coord;
-  vtl->magic_scissors_current_track = track;
-  vtl->magic_scissors_started = TRUE;
+  vtl->route_finder_coord =  last_coord;
+  vtl->route_finder_current_track = track;
+  vtl->route_finder_started = TRUE;
 
   if ( track->trackpoints )
     goto_coord ( pass_along[1], pass_along[0], pass_along[5], &last_coord) ;
 
 }
+#endif
 
 static void trw_layer_apply_dem_data ( gpointer pass_along[6] )
 {
@@ -2860,10 +3539,10 @@ static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] )
   goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
 }
 
-/* 
+/*
  * Automatically change the viewport to center on the track and zoom to see the extent of the track
- */ 
-static void trw_layer_auto_track_view ( gpointer pass_along[5] )
+ */
+static void trw_layer_auto_track_view ( gpointer pass_along[6] )
 {
   GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
   if ( trps && *trps )
@@ -2874,7 +3553,7 @@ static void trw_layer_auto_track_view ( gpointer pass_along[5] )
     if ( pass_along[1] )
       vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(pass_along[1]) );
     else
-      vik_layer_emit_update ( VIK_LAYER(pass_along[0]) );
+      vik_layer_emit_update ( VIK_LAYER(pass_along[0]), FALSE );
   }
 }
 
@@ -2889,16 +3568,17 @@ static void trw_layer_edit_trackpoint ( gpointer pass_along[6] )
  *************************************/
 
 /* called for each key in track hash table.
- * If the current track has time stamp, add it to the result,
+ * If the current track has the same time stamp type, add it to the result,
  * except the one pointed by "exclude".
  * set exclude to NULL if there is no exclude to check.
- * Not that result is in reverse (for performance reason).
+ * Note that the result is in reverse (for performance reasons).
  */
 typedef struct {
   GList **result;
   GList  *exclude;
+  gboolean with_timestamps;
 } twt_udata;
-static void find_tracks_with_timestamp(gpointer key, gpointer value, gpointer udata)
+static void find_tracks_with_timestamp_type(gpointer key, gpointer value, gpointer udata)
 {
   twt_udata *user_data = udata;
   VikTrackpoint *p1, *p2;
@@ -2911,11 +3591,17 @@ static void find_tracks_with_timestamp(gpointer key, gpointer value, gpointer ud
     p1 = VIK_TRACKPOINT(VIK_TRACK(value)->trackpoints->data);
     p2 = VIK_TRACKPOINT(g_list_last(VIK_TRACK(value)->trackpoints)->data);
 
-    if (!p1->has_timestamp || !p2->has_timestamp) {
-      g_print("no timestamp\n");
-      return;
+    if ( user_data->with_timestamps ) {
+      if (!p1->has_timestamp || !p2->has_timestamp) {
+       return;
+      }
+    }
+    else {
+      // Don't add tracks with timestamps when getting non timestamp tracks
+      if (p1->has_timestamp || p2->has_timestamp) {
+       return;
+      }
     }
-
   }
 
   *(user_data->result) = g_list_prepend(*(user_data->result), key);
@@ -2924,47 +3610,49 @@ static void find_tracks_with_timestamp(gpointer key, gpointer value, gpointer ud
 /* called for each key in track hash table. if original track user_data[1] is close enough
  * to the passed one, add it to list in user_data[0] 
  */
-static void find_nearby_track(gpointer key, gpointer value, gpointer user_data)
+static void find_nearby_tracks_by_time (gpointer key, gpointer value, gpointer user_data)
 {
   time_t t1, t2;
   VikTrackpoint *p1, *p2;
+  VikTrack *trk = VIK_TRACK(value);
 
   GList **nearby_tracks = ((gpointer *)user_data)[0];
-  GList *orig_track = ((gpointer *)user_data)[1];
-  guint thr = GPOINTER_TO_UINT (((gpointer *)user_data)[2]);
+  GList *tpoints = ((gpointer *)user_data)[1];
 
   /* outline: 
    * detect reasons for not merging, and return
    * if no reason is found not to merge, then do it.
    */
 
-  if (VIK_TRACK(value)->trackpoints == orig_track) {
+  // Exclude the original track from the compiled list
+  if (trk->trackpoints == tpoints) {
     return;
   }
 
-  t1 = VIK_TRACKPOINT(orig_track->data)->timestamp;
-  t2 = VIK_TRACKPOINT(g_list_last(orig_track)->data)->timestamp;
+  t1 = VIK_TRACKPOINT(g_list_first(tpoints)->data)->timestamp;
+  t2 = VIK_TRACKPOINT(g_list_last(tpoints)->data)->timestamp;
 
-  if (VIK_TRACK(value)->trackpoints) {
-    p1 = VIK_TRACKPOINT(VIK_TRACK(value)->trackpoints->data);
-    p2 = VIK_TRACKPOINT(g_list_last(VIK_TRACK(value)->trackpoints)->data);
+  if (trk->trackpoints) {
+    p1 = VIK_TRACKPOINT(g_list_first(trk->trackpoints)->data);
+    p2 = VIK_TRACKPOINT(g_list_last(trk->trackpoints)->data);
 
     if (!p1->has_timestamp || !p2->has_timestamp) {
-      g_print("no timestamp\n");
+      //g_print("no timestamp\n");
       return;
     }
 
-    /*  g_print("Got track named %s, times %d, %d\n", (gchar *)key, p1->timestamp, p2->timestamp); */
-    if (! (abs(t1 - p2->timestamp) < thr*60 ||
+    guint threshold = GPOINTER_TO_UINT (((gpointer *)user_data)[2]);
+    //g_print("Got track named %s, times %d, %d\n", trk->name, p1->timestamp, p2->timestamp);
+    if (! (abs(t1 - p2->timestamp) < threshold ||
        /*  p1 p2      t1 t2 */
-          abs(p1->timestamp - t2) < thr*60)
+          abs(p1->timestamp - t2) < threshold)
        /*  t1 t2      p1 p2 */
        ) {
       return;
     }
   }
 
-  *nearby_tracks = g_list_prepend(*nearby_tracks, key);
+  *nearby_tracks = g_list_prepend(*nearby_tracks, value);
 }
 
 /* comparison function used to sort tracks; a and b are hash table keys */
@@ -2993,7 +3681,6 @@ static gint trackpoint_compare(gconstpointer a, gconstpointer b)
   return 0;
 }
 
-#ifdef VIK_CONFIG_ALPHABETIZED_TRW
 /**
  * comparison function which can be used to sort tracks or waypoints by name
  */
@@ -3007,54 +3694,66 @@ static gint sort_alphabetically (gconstpointer a, gconstpointer b, gpointer user
     // Same sort method as used in the vik_treeview_*_alphabetize functions
     return strcmp ( namea, nameb );
 }
-#endif
 
+/**
+ * Attempt to merge selected track with other tracks specified by the user
+ * Tracks to merge with must be of the same 'type' as the selected track -
+ *  either all with timestamps, or all without timestamps
+ */
 static void trw_layer_merge_with_other ( gpointer pass_along[6] )
 {
   VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
-  gchar *orig_track_name = pass_along[3];
-  GList *tracks_with_timestamp = NULL;
-  VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
+  GList *other_tracks = NULL;
+  VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
 
-  if (track->trackpoints &&
-      !VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp) {
-    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. This track does not have timestamp"));
+  if ( !track->trackpoints )
     return;
-  }
 
-  if (1) {
+  twt_udata udata;
+  udata.result = &other_tracks;
+  udata.exclude = track->trackpoints;
+  // Allow merging with 'similar' time type time tracks
+  // i.e. either those times, or those without
+  udata.with_timestamps = (VIK_TRACKPOINT(track->trackpoints->data)->has_timestamp);
 
-    twt_udata udata;
-    udata.result = &tracks_with_timestamp;
-    udata.exclude = track->trackpoints;
-    g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp, (gpointer)&udata);
-    tracks_with_timestamp = g_list_reverse(tracks_with_timestamp);
-  }
+  g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
+  other_tracks = g_list_reverse(other_tracks);
 
-  if (!tracks_with_timestamp) {
-    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other track in this layer has timestamp"));
+  if ( !other_tracks ) {
+    if ( udata.with_timestamps )
+      a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other tracks with timestamps in this layer found"));
+    else
+      a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other tracks without timestamps in this layer found"));
     return;
   }
 
-#ifdef VIK_CONFIG_ALPHABETIZED_TRW
   // Sort alphabetically for user presentation
-  tracks_with_timestamp = g_list_sort_with_data (tracks_with_timestamp, sort_alphabetically, NULL);
-#endif
+  // Convert into list of names for usage with dialog function
+  // TODO: Need to consider how to work best when we can have multiple tracks the same name...
+  GList *other_tracks_names = NULL;
+  GList *iter = g_list_first ( other_tracks );
+  while ( iter ) {
+    other_tracks_names = g_list_append ( other_tracks_names, VIK_TRACK(g_hash_table_lookup (vtl->tracks, iter->data))->name );
+    iter = g_list_next ( iter );
+  }
+
+  other_tracks_names = g_list_sort_with_data (other_tracks_names, sort_alphabetically, NULL);
 
   GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
-      tracks_with_timestamp, TRUE,
-      _("Merge with..."), _("Select track to merge with"));
-  g_list_free(tracks_with_timestamp);
+                                                other_tracks_names, TRUE,
+                                                _("Merge with..."), _("Select track to merge with"));
+  g_list_free(other_tracks);
+  g_list_free(other_tracks_names);
 
   if (merge_list)
   {
     GList *l;
     for (l = merge_list; l != NULL; l = g_list_next(l)) {
-      VikTrack *merge_track = (VikTrack *) g_hash_table_lookup (vtl->tracks, l->data );
+      VikTrack *merge_track = vik_trw_layer_get_track ( vtl, l->data );
       if (merge_track) {
         track->trackpoints = g_list_concat(track->trackpoints, merge_track->trackpoints);
         merge_track->trackpoints = NULL;
-        vik_trw_layer_delete_track(vtl, l->data);
+        vik_trw_layer_delete_track (vtl, merge_track);
         track->trackpoints = g_list_sort(track->trackpoints, trackpoint_compare);
       }
     }
@@ -3062,42 +3761,143 @@ static void trw_layer_merge_with_other ( gpointer pass_along[6] )
     for (l = merge_list; l != NULL; l = g_list_next(l))
       g_free(l->data);
     g_list_free(merge_list);
-    vik_layer_emit_update( VIK_LAYER(vtl) );
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
   }
 }
 
-/* merge by time routine */
-static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
+// c.f. trw_layer_sorted_track_id_by_name_list
+//  but don't add the specified track to the list (normally current track)
+static void trw_layer_sorted_track_id_by_name_list_exclude_self (const gpointer id, const VikTrack *trk, gpointer udata)
 {
-  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
-  gchar *orig_track_name = strdup(pass_along[3]);
-
-  //time_t t1, t2;
-  GList *nearby_tracks;
-  VikTrack *track;
-  GList *trps;
-  static  guint thr = 1;
-  guint track_count = 0;
+  twt_udata *user_data = udata;
 
-  if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(vtl), 
-                              _("Merge Threshold..."), 
-                              _("Merge when time between tracks less than:"), 
-                              &thr)) {
-    free(orig_track_name);
+  // Skip self
+  if (trk->trackpoints == user_data->exclude) {
     return;
   }
 
-  /* merge tracks until we can't */
-  nearby_tracks = NULL;
-  do {
-    gpointer params[3];
-
-    track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
-    trps = track->trackpoints;
+  // Sort named list alphabetically
+  *(user_data->result) = g_list_insert_sorted_with_data (*(user_data->result), trk->name, sort_alphabetically, NULL);
+}
+
+/**
+ * Join - this allows combining 'routes' and 'tracks'
+ *  i.e. doesn't care about whether tracks have consistent timestamps
+ * ATM can only append one track at a time to the currently selected track
+ */
+static void trw_layer_append_track ( gpointer pass_along[6] )
+{
+
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+  GList *other_tracks_names = NULL;
+
+  // Sort alphabetically for user presentation
+  // Convert into list of names for usage with dialog function
+  // TODO: Need to consider how to work best when we can have multiple tracks the same name...
+  twt_udata udata;
+  udata.result = &other_tracks_names;
+  udata.exclude = trk->trackpoints;
+
+  g_hash_table_foreach(vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list_exclude_self, (gpointer)&udata);
+
+  // Note the limit to selecting one track only
+  //  this is to control the ordering of appending tracks, i.e. the selected track always goes after the current track
+  //  (otherwise with multiple select the ordering would not be controllable by the user - automatically being alphabetically)
+  GList *append_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                                               other_tracks_names,
+                                               FALSE,
+                                               _("Append Track"),
+                                               _("Select the track to append after the current track"));
+
+  g_list_free(other_tracks_names);
+
+  // It's a list, but shouldn't contain more than one other track!
+  if ( append_list ) {
+    GList *l;
+    for (l = append_list; l != NULL; l = g_list_next(l)) {
+      // TODO: at present this uses the first track found by name,
+      //  which with potential multiple same named tracks may not be the one selected...
+      VikTrack *append_track = vik_trw_layer_get_track ( vtl, l->data );
+      if ( append_track ) {
+        trk->trackpoints = g_list_concat(trk->trackpoints, append_track->trackpoints);
+        append_track->trackpoints = NULL;
+        vik_trw_layer_delete_track (vtl, append_track);
+      }
+    }
+    for (l = append_list; l != NULL; l = g_list_next(l))
+      g_free(l->data);
+    g_list_free(append_list);
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+  }
+}
+
+/* merge by segments */
+static void trw_layer_merge_by_segment ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+  guint segments = vik_track_merge_segments ( trk );
+  // NB currently no need to redraw as segments not actually shown on the display
+  // However inform the user of what happened:
+  gchar str[64];
+  const gchar *tmp_str = ngettext("%d segment merged", "%d segments merged", segments);
+  g_snprintf(str, 64, tmp_str, segments);
+  a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str );
+}
+
+/* merge by time routine */
+static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+
+  //time_t t1, t2;
+
+  GList *tracks_with_timestamp = NULL;
+  VikTrack *orig_trk = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+  if (orig_trk->trackpoints &&
+      !VIK_TRACKPOINT(orig_trk->trackpoints->data)->has_timestamp) {
+    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. This track does not have timestamp"));
+    return;
+  }
+
+  twt_udata udata;
+  udata.result = &tracks_with_timestamp;
+  udata.exclude = orig_trk->trackpoints;
+  udata.with_timestamps = TRUE;
+  g_hash_table_foreach(vtl->tracks, find_tracks_with_timestamp_type, (gpointer)&udata);
+  tracks_with_timestamp = g_list_reverse(tracks_with_timestamp);
+
+  if (!tracks_with_timestamp) {
+    a_dialog_error_msg(VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Failed. No other track in this layer has timestamp"));
+    return;
+  }
+  g_list_free(tracks_with_timestamp);
+
+  static guint threshold_in_minutes = 1;
+  if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                               _("Merge Threshold..."),
+                               _("Merge when time between tracks less than:"),
+                               &threshold_in_minutes)) {
+    return;
+  }
+
+  // keep attempting to merge all tracks until no merges within the time specified is possible
+  gboolean attempt_merge = TRUE;
+  GList *nearby_tracks = NULL;
+  GList *trps;
+  static gpointer params[3];
+
+  while ( attempt_merge ) {
+
+    // Don't try again unless tracks have changed
+    attempt_merge = FALSE;
+
+    trps = orig_trk->trackpoints;
     if ( !trps )
       return;
 
-
     if (nearby_tracks) {
       g_list_free(nearby_tracks);
       nearby_tracks = NULL;
@@ -3108,63 +3908,97 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
     
     /*    g_print("Original track times: %d and %d\n", t1, t2);  */
     params[0] = &nearby_tracks;
-    params[1] = trps;
-    params[2] = GUINT_TO_POINTER (thr);
+    params[1] = (gpointer)trps;
+    params[2] = GUINT_TO_POINTER (threshold_in_minutes*60); // In seconds
 
     /* get a list of adjacent-in-time tracks */
-    g_hash_table_foreach(vtl->tracks, find_nearby_track, (gpointer)params);
-
-    /* add original track */
-    nearby_tracks = g_list_prepend(nearby_tracks, orig_track_name);
+    g_hash_table_foreach(vtl->tracks, find_nearby_tracks_by_time, params);
 
     /* merge them */
-    { 
-#define get_track(x) VIK_TRACK(g_hash_table_lookup(vtl->tracks, (gchar *)((x)->data)))
-#define get_first_trackpoint(x) VIK_TRACKPOINT(get_track(x)->trackpoints->data)
-#define get_last_trackpoint(x) VIK_TRACKPOINT(g_list_last(get_track(x)->trackpoints)->data)
-      GList *l = nearby_tracks;
-      VikTrack *tr = vik_track_new();
-      tr->visible = track->visible;
-      track_count = 0;
-      while (l) {
-       /*
-       time_t t1, t2;
-       t1 = get_first_trackpoint(l)->timestamp;
-       t2 = get_last_trackpoint(l)->timestamp;
-       g_print("     %20s: track %d - %d\n", (char *)l->data, (int)t1, (int)t2);
-       */
-
+    GList *l = nearby_tracks;
+    while ( l ) {
+       /*
+#define get_first_trackpoint(x) VIK_TRACKPOINT(VIK_TRACK(x)->trackpoints->data)
+#define get_last_trackpoint(x) VIK_TRACKPOINT(g_list_last(VIK_TRACK(x)->trackpoints)->data)
+        time_t t1, t2;
+        t1 = get_first_trackpoint(l)->timestamp;
+        t2 = get_last_trackpoint(l)->timestamp;
+#undef get_first_trackpoint
+#undef get_last_trackpoint
+        g_print("     %20s: track %d - %d\n", VIK_TRACK(l->data)->name, (int)t1, (int)t2);
+       */
 
-       /* remove trackpoints from merged track, delete track */
-       tr->trackpoints = g_list_concat(tr->trackpoints, get_track(l)->trackpoints);
-       get_track(l)->trackpoints = NULL;
-       vik_trw_layer_delete_track(vtl, l->data);
+      /* remove trackpoints from merged track, delete track */
+      orig_trk->trackpoints = g_list_concat(orig_trk->trackpoints, VIK_TRACK(l->data)->trackpoints);
+      VIK_TRACK(l->data)->trackpoints = NULL;
+      vik_trw_layer_delete_track (vtl, VIK_TRACK(l->data));
 
-       track_count ++;
-       l = g_list_next(l);
-      }
-      tr->trackpoints = g_list_sort(tr->trackpoints, trackpoint_compare);
-      vik_trw_layer_add_track(vtl, strdup(orig_track_name), tr);
+      // Tracks have changed, therefore retry again against all the remaining tracks
+      attempt_merge = TRUE;
 
-#undef get_first_trackpoint
-#undef get_last_trackpoint
-#undef get_track
+      l = g_list_next(l);
     }
-  } while (track_count > 1);
+
+    orig_trk->trackpoints = g_list_sort(orig_trk->trackpoints, trackpoint_compare);
+  }
+
   g_list_free(nearby_tracks);
-  free(orig_track_name);
-  vik_layer_emit_update( VIK_LAYER(vtl) );
+  vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+}
+
+/**
+ * Split a track at the currently selected trackpoint
+ */
+static void trw_layer_split_at_selected_trackpoint ( VikTrwLayer *vtl )
+{
+  if ( !vtl->current_tpl )
+    return;
+
+  if ( vtl->current_tpl->next && vtl->current_tpl->prev ) {
+    gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, vtl->current_tp_track->name);
+    if ( name ) {
+      VikTrack *tr = vik_track_new ();
+      GList *newglist = g_list_alloc ();
+      newglist->prev = NULL;
+      newglist->next = vtl->current_tpl->next;
+      newglist->data = vik_trackpoint_copy(VIK_TRACKPOINT(vtl->current_tpl->data));
+      tr->trackpoints = newglist;
+
+      vtl->current_tpl->next->prev = newglist; /* end old track here */
+      vtl->current_tpl->next = NULL;
+
+      vtl->current_tpl = newglist; /* change tp to first of new track. */
+      vtl->current_tp_track = tr;
+
+      tr->visible = TRUE;
+
+      vik_trw_layer_add_track ( vtl, name, tr );
+
+      trku_udata udata;
+      udata.trk  = tr;
+      udata.uuid = NULL;
+
+      // Also need id of newly created track
+      gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udata );
+      if ( trkf && udata.uuid )
+        vtl->current_tp_id = udata.uuid;
+      else
+        vtl->current_tp_id = NULL;
+
+      vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
+    }
+  }
 }
 
 /* split by time routine */
 static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
 {
-  VikTrack *track = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, pass_along[3] );
   GList *trps = track->trackpoints;
   GList *iter;
   GList *newlists = NULL;
   GList *newtps = NULL;
-  guint i;
   static guint thr = 1;
 
   time_t ts, prev_ts;
@@ -3206,7 +4040,6 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
 
   /* put lists of trackpoints into tracks */
   iter = newlists;
-  i = 1;
   // Only bother updating if the split results in new tracks
   if (g_list_length (newlists) > 1) {
     while (iter) {
@@ -3217,15 +4050,16 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
       tr->visible = track->visible;
       tr->trackpoints = (GList *)(iter->data);
 
-      new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i++);
-      vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr);
+      new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, track->name);
+      vik_trw_layer_add_track(vtl, new_tr_name, tr);
       /*    g_print("adding track %s, times %d - %d\n", new_tr_name, VIK_TRACKPOINT(tr->trackpoints->data)->timestamp,
          VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp);*/
 
       iter = g_list_next(iter);
     }
-    vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]);
-    vik_layer_emit_update(VIK_LAYER(pass_along[0]));
+    // Remove original track and then update the display
+    vik_trw_layer_delete_track (vtl, track);
+    vik_layer_emit_update(VIK_LAYER(pass_along[0]), FALSE);
   }
   g_list_free(newlists);
 }
@@ -3282,7 +4116,6 @@ static void trw_layer_split_by_n_points ( gpointer pass_along[6] )
 
   /* put lists of trackpoints into tracks */
   iter = newlists;
-  guint i = 1;
   // Only bother updating if the split results in new tracks
   if (g_list_length (newlists) > 1) {
     while (iter) {
@@ -3293,30 +4126,286 @@ static void trw_layer_split_by_n_points ( gpointer pass_along[6] )
       tr->visible = track->visible;
       tr->trackpoints = (GList *)(iter->data);
 
-      new_tr_name = g_strdup_printf("%s #%d", (gchar *) pass_along[3], i++);
-      vik_trw_layer_add_track(VIK_TRW_LAYER(pass_along[0]), new_tr_name, tr);
+      new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, track->name);
+      vik_trw_layer_add_track(vtl, new_tr_name, tr);
 
       iter = g_list_next(iter);
     }
     // Remove original track and then update the display
-    vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]);
-    vik_layer_emit_update(VIK_LAYER(pass_along[0]));
+    vik_trw_layer_delete_track (vtl, track);
+    vik_layer_emit_update(VIK_LAYER(pass_along[0]), FALSE);
   }
   g_list_free(newlists);
 }
 
+/**
+ * Split a track at the currently selected trackpoint
+ */
+static void trw_layer_split_at_trackpoint ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  trw_layer_split_at_selected_trackpoint ( vtl );
+}
+
+/**
+ * Split a track by its segments
+ */
+static void trw_layer_split_segments ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+  guint ntracks;
+
+  VikTrack **tracks = vik_track_split_into_segments (trk, &ntracks);
+  gchar *new_tr_name;
+  guint i;
+  for ( i = 0; i < ntracks; i++ ) {
+    if ( tracks[i] ) {
+      new_tr_name = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, trk->name);
+      vik_trw_layer_add_track ( vtl, new_tr_name, tracks[i] );
+    }
+  }
+  if ( tracks ) {
+    g_free ( tracks );
+    // Remove original track
+    vik_trw_layer_delete_track ( vtl, trk );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+  }
+  else {
+    a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Can not split track as it has no segments"));
+  }
+}
 /* end of split/merge routines */
 
+/**
+ * Delete adjacent track points at the same position
+ * AKA Delete Dulplicates on the Properties Window
+ */
+static void trw_layer_delete_points_same_position ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+  gulong removed = vik_track_remove_dup_points ( trk );
+
+  // Track has been updated so update tps:
+  trw_layer_cancel_tps_of_track ( vtl, trk );
+
+  // Inform user how much was deleted as it's not obvious from the normal view
+  gchar str[64];
+  const gchar *tmp_str = ngettext("Deleted %ld point", "Deleted %ld points", removed);
+  g_snprintf(str, 64, tmp_str, removed);
+  a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str);
+
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+}
+
+/**
+ * Delete adjacent track points with the same timestamp
+ * Normally new tracks that are 'routes' won't have any timestamps so should be OK to clean up the track
+ */
+static void trw_layer_delete_points_same_time ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *trk = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+  gulong removed = vik_track_remove_same_time_points ( trk );
+
+  // Track has been updated so update tps:
+  trw_layer_cancel_tps_of_track ( vtl, trk );
+
+  // Inform user how much was deleted as it's not obvious from the normal view
+  gchar str[64];
+  const gchar *tmp_str = ngettext("Deleted %ld point", "Deleted %ld points", removed);
+  g_snprintf(str, 64, tmp_str, removed);
+  a_dialog_info_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl), str);
+
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+}
+
+/**
+ * Reverse a track
+ */
+static void trw_layer_reverse ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
+  VikTrack *track = (VikTrack *)g_hash_table_lookup ( vtl->tracks, pass_along[3] );
+
+  // Check valid track
+  GList *trps = track->trackpoints;
+  if ( !trps )
+    return;
+
+  vik_track_reverse ( track );
+  vik_layer_emit_update ( VIK_LAYER(pass_along[0]), FALSE );
+}
+
 /**
  * Similar to trw_layer_enum_item, but this uses a sorted method
  */
+/* Currently unused
 static void trw_layer_sorted_name_list(gpointer key, gpointer value, gpointer udata)
 {
   GList **list = (GList**)udata;
-  //*list = g_list_prepend(*all, key); //unsorted method
+  // *list = g_list_prepend(*all, key); //unsorted method
   // Sort named list alphabetically
   *list = g_list_insert_sorted_with_data (*list, key, sort_alphabetically, NULL);
 }
+*/
+
+/**
+ * Now Waypoint specific sort
+ */
+static void trw_layer_sorted_wp_id_by_name_list (const gpointer id, const VikWaypoint *wp, gpointer udata)
+{
+  GList **list = (GList**)udata;
+  // Sort named list alphabetically
+  *list = g_list_insert_sorted_with_data (*list, wp->name, sort_alphabetically, NULL);
+}
+
+/**
+ * Track specific sort
+ */
+static void trw_layer_sorted_track_id_by_name_list (const gpointer id, const VikTrack *trk, gpointer udata)
+{
+  GList **list = (GList**)udata;
+  // Sort named list alphabetically
+  *list = g_list_insert_sorted_with_data (*list, trk->name, sort_alphabetically, NULL);
+}
+
+
+typedef struct {
+  gboolean    has_same_track_name;
+  const gchar *same_track_name;
+} same_track_name_udata;
+
+static gint check_tracks_for_same_name ( gconstpointer aa, gconstpointer bb, gpointer udata )
+{
+  const gchar* namea = (const gchar*) aa;
+  const gchar* nameb = (const gchar*) bb;
+
+  // the test
+  gint result = strcmp ( namea, nameb );
+
+  if ( result == 0 ) {
+    // Found two names the same
+    same_track_name_udata *user_data = udata;
+    user_data->has_same_track_name = TRUE;
+    user_data->same_track_name = namea;
+  }
+
+  // Leave ordering the same
+  return 0;
+}
+
+/**
+ * Find out if any tracks have the same name in this layer
+ */
+static gboolean trw_layer_has_same_track_names ( VikTrwLayer *vtl )
+{
+  // Sort items by name, then compare if any next to each other are the same
+
+  GList *track_names = NULL;
+  g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+
+  // No tracks
+  if ( ! track_names )
+    return FALSE;
+
+  same_track_name_udata udata;
+  udata.has_same_track_name = FALSE;
+
+  // Use sort routine to traverse list comparing items
+  // Don't care how this list ends up ordered ( doesn't actually change ) - care about the returned status
+  GList *dummy_list = g_list_sort_with_data ( track_names, check_tracks_for_same_name, &udata );
+  // Still no tracks...
+  if ( ! dummy_list )
+    return FALSE;
+
+  return udata.has_same_track_name;
+}
+
+/**
+ * Force unqiue track names for this layer
+ * Note the panel is a required parameter to enable the update of the names displayed
+ */
+static void vik_trw_layer_uniquify_tracks ( VikTrwLayer *vtl, VikLayersPanel *vlp )
+{
+  // . Search list for an instance of repeated name
+  // . get track of this name
+  // . create new name
+  // . rename track & update equiv. treeview iter
+  // . repeat until all different
+
+  same_track_name_udata udata;
+
+  GList *track_names = NULL;
+  udata.has_same_track_name = FALSE;
+  udata.same_track_name = NULL;
+
+  g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+
+  // No tracks
+  if ( ! track_names )
+    return;
+
+  GList *dummy_list1 = g_list_sort_with_data ( track_names, check_tracks_for_same_name, &udata );
+
+  // Still no tracks...
+  if ( ! dummy_list1 )
+    return;
+
+  while ( udata.has_same_track_name ) {
+
+    // Find a track with the same name
+    VikTrack *trk = vik_trw_layer_get_track ( vtl, (gpointer) udata.same_track_name );
+
+    if ( ! trk ) {
+      // Broken :(
+      g_critical("Houston, we've had a problem.");
+      vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, 
+                                  _("Internal Error in vik_trw_layer_uniquify_tracks") );
+      return;
+    }
+
+    // Rename it
+    gchar *newname = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, udata.same_track_name );
+    vik_track_set_name ( trk, newname );
+
+    trku_udata udataU;
+    udataU.trk  = trk;
+    udataU.uuid = NULL;
+
+    // Need want key of it for treeview update
+    gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+
+    if ( trkf && udataU.uuid ) {
+
+      GtkTreeIter *it = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+
+      if ( it ) {
+        vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname );
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+        vik_treeview_sublayer_realphabetize ( VIK_LAYER(vtl)->vt, it, newname );
+#endif
+      }
+    }
+
+    // Start trying to find same names again...
+    track_names = NULL;
+    g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &track_names );
+    udata.has_same_track_name = FALSE;
+    GList *dummy_list2 = g_list_sort_with_data ( track_names, check_tracks_for_same_name, &udata );
+
+    // No tracks any more - give up searching
+    if ( ! dummy_list2 )
+      udata.has_same_track_name = FALSE;
+  }
+
+  // Update
+  vik_layers_panel_emit_update ( vlp );
+}
 
 /**
  *
@@ -3325,32 +4414,176 @@ static void trw_layer_delete_tracks_from_selection ( gpointer lav[2] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
   GList *all = NULL;
+
+  // Ensure list of track names offered is unique
+  if ( trw_layer_has_same_track_names ( vtl ) ) {
+    if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                             _("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
+      vik_trw_layer_uniquify_tracks ( vtl, VIK_LAYERS_PANEL(lav[1]) );
+    }
+    else
+      return;
+  }
+
   // Sort list alphabetically for better presentation
-  g_hash_table_foreach(vtl->tracks, trw_layer_sorted_name_list, &all);
+  g_hash_table_foreach(vtl->tracks, (GHFunc) trw_layer_sorted_track_id_by_name_list, &all);
+
+  if ( ! all ) {
+    a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl),        _("No tracks found"));
+    return;
+  }
+
+  // Get list of items to delete from the user
+  GList *delete_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                                                all,
+                                                TRUE,
+                                                _("Delete Selection"),
+                                                _("Select tracks to delete"));
+  g_list_free(all);
+
+  // Delete requested tracks
+  // since specificly requested, IMHO no need for extra confirmation
+  if ( delete_list ) {
+    GList *l;
+    for (l = delete_list; l != NULL; l = g_list_next(l)) {
+      // This deletes first trk it finds of that name (but uniqueness is enforced above)
+      trw_layer_delete_track_by_name (vtl, l->data);
+    }
+    g_list_free(delete_list);
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+  }
+}
+
+typedef struct {
+  gboolean    has_same_waypoint_name;
+  const gchar *same_waypoint_name;
+} same_waypoint_name_udata;
+
+static gint check_waypoints_for_same_name ( gconstpointer aa, gconstpointer bb, gpointer udata )
+{
+  const gchar* namea = (const gchar*) aa;
+  const gchar* nameb = (const gchar*) bb;
+
+  // the test
+  gint result = strcmp ( namea, nameb );
+
+  if ( result == 0 ) {
+    // Found two names the same
+    same_waypoint_name_udata *user_data = udata;
+    user_data->has_same_waypoint_name = TRUE;
+    user_data->same_waypoint_name = namea;
+  }
+
+  // Leave ordering the same
+  return 0;
+}
+
+/**
+ * Find out if any waypoints have the same name in this layer
+ */
+gboolean trw_layer_has_same_waypoint_names ( VikTrwLayer *vtl )
+{
+  // Sort items by name, then compare if any next to each other are the same
+
+  GList *waypoint_names = NULL;
+  g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_sorted_wp_id_by_name_list, &waypoint_names );
+
+  // No waypoints
+  if ( ! waypoint_names )
+    return FALSE;
+
+  same_waypoint_name_udata udata;
+  udata.has_same_waypoint_name = FALSE;
+
+  // Use sort routine to traverse list comparing items
+  // Don't care how this list ends up ordered ( doesn't actually change ) - care about the returned status
+  GList *dummy_list = g_list_sort_with_data ( waypoint_names, check_waypoints_for_same_name, &udata );
+  // Still no waypoints...
+  if ( ! dummy_list )
+    return FALSE;
+
+  return udata.has_same_waypoint_name;
+}
+
+/**
+ * Force unqiue waypoint names for this layer
+ * Note the panel is a required parameter to enable the update of the names displayed
+ */
+static void vik_trw_layer_uniquify_waypoints ( VikTrwLayer *vtl, VikLayersPanel *vlp )
+{
+  // . Search list for an instance of repeated name
+  // . get waypoint of this name
+  // . create new name
+  // . rename waypoint & update equiv. treeview iter
+  // . repeat until all different
+
+  same_waypoint_name_udata udata;
+
+  GList *waypoint_names = NULL;
+  udata.has_same_waypoint_name = FALSE;
+  udata.same_waypoint_name = NULL;
+
+  g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_sorted_wp_id_by_name_list, &waypoint_names );
+
+  // No waypoints
+  if ( ! waypoint_names )
+    return;
+
+  GList *dummy_list1 = g_list_sort_with_data ( waypoint_names, check_waypoints_for_same_name, &udata );
+
+  // Still no waypoints...
+  if ( ! dummy_list1 )
+    return;
+
+  while ( udata.has_same_waypoint_name ) {
+
+    // Find a waypoint with the same name
+    VikWaypoint *waypoint = vik_trw_layer_get_waypoint ( vtl, (gpointer) udata.same_waypoint_name );
+
+    if ( ! waypoint ) {
+      // Broken :(
+      g_critical("Houston, we've had a problem.");
+      vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, 
+                                  _("Internal Error in vik_trw_layer_uniquify_waypoints") );
+      return;
+    }
 
-  if ( ! all ) {
-    a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl),        _("No tracks found"));
-    return;
-  }
+    // Rename it
+    gchar *newname = trw_layer_new_unique_sublayer_name ( vtl, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, udata.same_waypoint_name );
+    vik_waypoint_set_name ( waypoint, newname );
 
-  // Get list of items to delete from the user
-  GList *delete_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
-                                                all,
-                                                TRUE,
-                                                _("Delete Selection"),
-                                                _("Select tracks to delete"));
-  g_list_free(all);
+    wpu_udata udataU;
+    udataU.wp   = waypoint;
+    udataU.uuid = NULL;
 
-  // Delete requested tracks
-  // since specificly requested, IMHO no need for extra confirmation
-  if ( delete_list ) {
-    GList *l;
-    for (l = delete_list; l != NULL; l = g_list_next(l)) {
-      vik_trw_layer_delete_track(vtl, l->data);
+    // Need want key of it for treeview update
+    gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, &udataU );
+
+    if ( wpf && udataU.uuid ) {
+
+      GtkTreeIter *it = g_hash_table_lookup ( vtl->waypoints_iters, udataU.uuid );
+
+      if ( it ) {
+        vik_treeview_item_set_name ( VIK_LAYER(vtl)->vt, it, newname );
+#ifdef VIK_CONFIG_ALPHABETIZED_TRW
+        vik_treeview_sublayer_realphabetize ( VIK_LAYER(vtl)->vt, it, newname );
+#endif
+      }
     }
-    g_list_free(delete_list);
-    vik_layer_emit_update( VIK_LAYER(vtl) );
+
+    // Start trying to find same names again...
+    waypoint_names = NULL;
+    g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_sorted_wp_id_by_name_list, &waypoint_names );
+    udata.has_same_waypoint_name = FALSE;
+    GList *dummy_list2 = g_list_sort_with_data ( waypoint_names, check_waypoints_for_same_name, &udata );
+
+    // No waypoints any more - give up searching
+    if ( ! dummy_list2 )
+      udata.has_same_waypoint_name = FALSE;
   }
+
+  // Update
+  vik_layers_panel_emit_update ( vlp );
 }
 
 /**
@@ -3361,8 +4594,18 @@ static void trw_layer_delete_waypoints_from_selection ( gpointer lav[2] )
   VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
   GList *all = NULL;
 
+  // Ensure list of waypoint names offered is unique
+  if ( trw_layer_has_same_waypoint_names ( vtl ) ) {
+    if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                             _("Multiple entries with the same name exist. This method only works with unique names. Force unique names now?"), NULL ) ) {
+      vik_trw_layer_uniquify_waypoints ( vtl, VIK_LAYERS_PANEL(lav[1]) );
+    }
+    else
+      return;
+  }
+
   // Sort list alphabetically for better presentation
-  g_hash_table_foreach ( vtl->waypoints, trw_layer_sorted_name_list, &all);
+  g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_sorted_wp_id_by_name_list, &all);
   if ( ! all ) {
     a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl),        _("No waypoints found"));
     return;
@@ -3383,10 +4626,11 @@ static void trw_layer_delete_waypoints_from_selection ( gpointer lav[2] )
   if ( delete_list ) {
     GList *l;
     for (l = delete_list; l != NULL; l = g_list_next(l)) {
-      vik_trw_layer_delete_waypoint(vtl, l->data);
+      // This deletes first waypoint it finds of that name (but uniqueness is enforced above)
+      trw_layer_delete_waypoint_by_name (vtl, l->data);
     }
     g_list_free(delete_list);
-    vik_layer_emit_update( VIK_LAYER(vtl) );
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
   }
 
 }
@@ -3405,96 +4649,73 @@ static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[6] )
   g_free ( webpage );
 }
 
-const gchar *vik_trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
+static const gchar* trw_layer_sublayer_rename_request ( VikTrwLayer *l, const gchar *newname, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
 {
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
   {
-    gchar *rv;
-    VikWaypoint *wp;
+    VikWaypoint *wp = g_hash_table_lookup ( l->waypoints, sublayer );
 
-    if (strcmp(newname, sublayer) == 0 )
+    // No actual change to the name supplied
+    if (strcmp(newname, wp->name) == 0 )
       return NULL;
 
-    if (strcasecmp(newname, sublayer)) { /* Not just changing case */
-      if (g_hash_table_lookup( l->waypoints, newname))
-      {
-        a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Waypoint Already Exists") );
+    VikWaypoint *wpf = vik_trw_layer_get_waypoint ( l, newname );
+
+    if ( wpf ) {
+      // An existing waypoint has been found with the requested name
+      if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
+           _("A waypoint with the name \"%s\" already exists. Really create one with the same name?"), 
+           newname ) )
         return NULL;
-      }
     }
 
-    iter = g_hash_table_lookup ( l->waypoints_iters, sublayer );
-    g_hash_table_steal ( l->waypoints_iters, sublayer );
-
-    wp = vik_waypoint_copy ( VIK_WAYPOINT(g_hash_table_lookup ( l->waypoints, sublayer )) );
-    highest_wp_number_remove_wp(l, sublayer);
-    g_hash_table_remove ( l->waypoints, sublayer );
+    // Update WP name and refresh the treeview
+    vik_waypoint_set_name (wp, newname);
 
-    rv = g_strdup(newname);
-
-    vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
-
-    highest_wp_number_add_wp(l, rv);
-    g_hash_table_insert ( l->waypoints, rv, wp );
-    g_hash_table_insert ( l->waypoints_iters, rv, iter );
-
-    /* it hasn't been updated yet so we pass new name */
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-    vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, rv );
+    vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname );
 #endif
 
     vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) );
-    return rv;
+
+    return newname;
   }
+
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
-    gchar *rv;
-    VikTrack *tr;
-    GtkTreeIter *iter;
-    gchar *orig_key;
+    VikTrack *trk = g_hash_table_lookup ( l->tracks, sublayer );
 
-    if (strcmp(newname, sublayer) == 0)
+    // No actual change to the name supplied
+    if (strcmp(newname, trk->name) == 0)
       return NULL;
 
-    if (strcasecmp(newname, sublayer)) { /* Not just changing case */
-      if (g_hash_table_lookup( l->tracks, newname))
-      {
-        a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(l), _("Track Already Exists") );
+    VikTrack *trkf = vik_trw_layer_get_track ( l, (gpointer) newname );
+
+    if ( trkf ) {
+      // An existing track has been found with the requested name
+      if ( ! a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(l),
+          _("A track with the name \"%s\" already exists. Really create one with the same name?"),
+          newname ) )
         return NULL;
-      }
     }
+    // Update track name and refresh GUI parts
+    vik_track_set_name (trk, newname);
 
-    g_hash_table_lookup_extended ( l->tracks, sublayer, (void *)&orig_key, (void *)&tr );
-    g_hash_table_steal ( l->tracks, sublayer );
-
-    iter = g_hash_table_lookup ( l->tracks_iters, sublayer );
-    g_hash_table_steal ( l->tracks_iters, sublayer );
-
-    rv = g_strdup(newname);
-
-    vik_treeview_item_set_pointer ( VIK_LAYER(l)->vt, iter, rv );
-
-    g_hash_table_insert ( l->tracks, rv, tr );
-    g_hash_table_insert ( l->tracks_iters, rv, iter );
-
-    /* don't forget about current_tp_track_name, update that too */
-    if ( l->current_tp_track_name && g_strcasecmp(orig_key,l->current_tp_track_name) == 0 )
-    {
-      l->current_tp_track_name = rv;
-      if ( l->tpwin )
-        vik_trw_layer_tpwin_set_track_name ( l->tpwin, rv );
+    // Update any subwindows that could be displaying this track which has changed name
+    // Only one Track Edit Window
+    if ( l->current_tp_track == trk && l->tpwin ) {
+      vik_trw_layer_tpwin_set_track_name ( l->tpwin, newname );
     }
-    else if ( l->last_tp_track_name && g_strcasecmp(orig_key,l->last_tp_track_name) == 0 )
-      l->last_tp_track_name = rv;
-
-    g_free ( orig_key );
+    // Property Dialog of the track
+    vik_trw_layer_propwin_update ( trk );
 
 #ifdef VIK_CONFIG_ALPHABETIZED_TRW
-    vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, rv );
+    vik_treeview_sublayer_realphabetize ( VIK_LAYER(l)->vt, iter, newname );
 #endif
 
     vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) );
-    return rv;
+
+    return newname;
   }
   return NULL;
 }
@@ -3507,21 +4728,19 @@ static gboolean is_valid_geocache_name ( gchar *str )
 
 static void trw_layer_track_use_with_filter ( gpointer pass_along[6] )
 {
-  gchar *track_name = (gchar *) pass_along[3];
-  VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, track_name );
-  a_acquire_set_filter_track ( tr, track_name );
+  VikTrack *trk = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+  a_acquire_set_filter_track ( trk );
 }
 
-static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gchar *track_name )
+static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gpointer track_id )
 {
-  VikTrack *tr = g_hash_table_lookup ( vtl->tracks, track_name );
+  VikTrack *tr = g_hash_table_lookup ( vtl->tracks, track_id );
   return ( tr && tr->comment && strlen(tr->comment) > 7 && !strncmp(tr->comment, "from:", 5) );
 }
 
 static void trw_layer_track_google_route_webpage ( gpointer pass_along[6] )
 {
-  gchar *track_name = (gchar *) pass_along[3];
-  VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, track_name );
+  VikTrack *tr = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
   if ( tr ) {
     gchar *escaped = uri_escape ( tr->comment );
     gchar *webpage = g_strdup_printf("http://maps.google.com/maps?f=q&hl=en&q=%s", escaped );
@@ -3533,9 +4752,9 @@ static void trw_layer_track_google_route_webpage ( gpointer pass_along[6] )
 
 /* vlp can be NULL if necessary - i.e. right-click from a tool */
 /* viewpoint is now available instead */
-gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter, VikViewport *vvp )
+static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter, VikViewport *vvp )
 {
-  static gpointer pass_along[6];
+  static gpointer pass_along[8];
   GtkWidget *item;
   gboolean rv = FALSE;
 
@@ -3545,6 +4764,8 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
   pass_along[3] = sublayer;
   pass_along[4] = GINT_TO_POINTER (1); // Confirm delete request
   pass_along[5] = vvp;
+  pass_along[6] = iter;
+  pass_along[7] = NULL; // For misc purposes - maybe track or waypoint
 
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
@@ -3589,28 +4810,31 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
        separator_created = TRUE;
 
-        item = gtk_menu_item_new_with_mnemonic ( _("_Goto") );
+        item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto") );
+       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
         g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_waypoint), pass_along );
         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
         gtk_widget_show ( item );
       }
 
-      if ( is_valid_geocache_name ( (gchar *) sublayer ) )
-      {
-       if ( !separator_created ) {
-         item = gtk_menu_item_new ();
-         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-         gtk_widget_show ( item );
-         separator_created = TRUE;
-       }
+      VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(l)->waypoints, sublayer );
 
-        item = gtk_menu_item_new_with_mnemonic ( _("_Visit Geocache Webpage") );
-        g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_gc_webpage), pass_along );
-        gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-        gtk_widget_show ( item );
-      }
+      if ( wp && wp->name ) {
+        if ( is_valid_geocache_name ( wp->name ) ) {
 
-      VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(l)->waypoints, sublayer );
+          if ( !separator_created ) {
+            item = gtk_menu_item_new ();
+            gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+            gtk_widget_show ( item );
+            separator_created = TRUE;
+          }
+
+          item = gtk_menu_item_new_with_mnemonic ( _("_Visit Geocache Webpage") );
+          g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_waypoint_gc_webpage), pass_along );
+          gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+          gtk_widget_show ( item );
+        }
+      }
 
       if ( wp && wp->image )
       {
@@ -3624,10 +4848,30 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
        // Set up image paramater
        pass_along[5] = wp->image;
 
-        item = gtk_menu_item_new_with_mnemonic ( _("_Show Picture...") );
+        item = gtk_image_menu_item_new_with_mnemonic ( _("_Show Picture...") );
+       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Show Picture", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
         g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_show_picture), pass_along );
         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
         gtk_widget_show ( item );
+
+#ifdef VIK_CONFIG_GEOTAG
+       GtkWidget *geotag_submenu = gtk_menu_new ();
+       item = gtk_image_menu_item_new_with_mnemonic ( _("Update Geotag on _Image") );
+       gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REFRESH, GTK_ICON_SIZE_MENU) );
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show ( item );
+       gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), geotag_submenu );
+  
+       item = gtk_menu_item_new_with_mnemonic ( _("_Update") );
+       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_waypoint_mtime_update), pass_along );
+       gtk_menu_shell_append (GTK_MENU_SHELL (geotag_submenu), item);
+       gtk_widget_show ( item );
+
+       item = gtk_menu_item_new_with_mnemonic ( _("Update and _Keep File Timestamp") );
+       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_waypoint_mtime_keep), pass_along );
+       gtk_menu_shell_append (GTK_MENU_SHELL (geotag_submenu), item);
+       gtk_widget_show ( item );
+#endif
       }
 
     }
@@ -3636,7 +4880,8 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
   if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
   {
     rv = TRUE;
-    item = gtk_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_New Waypoint...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NEW, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_new_wp), pass_along );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
@@ -3644,22 +4889,26 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS )
   {
-    item = gtk_menu_item_new_with_mnemonic ( _("_View All Waypoints") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Waypoints") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_waypoints_view), pass_along );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Goto _Waypoint...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Goto _Waypoint...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_wp), pass_along );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Delete _All Waypoints") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Waypoints") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_waypoints), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Delete Waypoints From Selection...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Delete Waypoints From Selection...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_waypoints_from_selection), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
@@ -3669,17 +4918,20 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
   {
     rv = TRUE;
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_View All Tracks") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_View All Tracks") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_tracks_view), pass_along );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Delete _All Tracks") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Delete _All Tracks") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_all_tracks), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Delete Tracks From Selection...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Delete Tracks From Selection...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_tracks_from_selection), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
@@ -3687,116 +4939,199 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
-    GtkWidget *goto_submenu;
     item = gtk_menu_item_new ();
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_View Track") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ZOOM_FIT, GTK_ICON_SIZE_MENU) );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_track_view), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_widget_show ( item );
+
+    GtkWidget *goto_submenu;
     goto_submenu = gtk_menu_new ();
-    item = gtk_menu_item_new_with_mnemonic ( _("_Goto") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Goto") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
     gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), goto_submenu );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Startpoint") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Startpoint") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GOTO_FIRST, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_startpoint), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("\"_Center\"") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("\"_Center\"") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_center), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Endpoint") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Endpoint") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GOTO_LAST, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_endpoint), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Highest Altitude") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Highest Altitude") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GOTO_TOP, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_alt), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Lowest Altitude") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Lowest Altitude") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GOTO_BOTTOM, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_min_alt), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Maximum Speed") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_MEDIA_FORWARD, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_goto_track_max_speed), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_View Track") );
-    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_auto_track_view), pass_along );
-    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    GtkWidget *combine_submenu;
+    combine_submenu = gtk_menu_new ();
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Co_mbine") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_CONNECT, GTK_ICON_SIZE_MENU) );
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
+    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), combine_submenu );
 
     item = gtk_menu_item_new_with_mnemonic ( _("_Merge By Time...") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_timestamp), pass_along );
-    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
     gtk_widget_show ( item );
 
     item = gtk_menu_item_new_with_mnemonic ( _("Merge _With Other Tracks...") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_with_other), pass_along );
-    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_menu_item_new_with_mnemonic ( _("Merge _Segments") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_merge_by_segment), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_menu_item_new_with_mnemonic ( _("_Append Track...") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_append_track), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(combine_submenu), item );
+    gtk_widget_show ( item );
+
+    GtkWidget *split_submenu;
+    split_submenu = gtk_menu_new ();
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Split") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DISCONNECT, GTK_ICON_SIZE_MENU) );
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
+    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), split_submenu );
 
     item = gtk_menu_item_new_with_mnemonic ( _("_Split By Time...") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_timestamp), pass_along );
-    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
     gtk_widget_show ( item );
 
     item = gtk_menu_item_new_with_mnemonic ( _("Split By _Number of Points...") );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_by_n_points), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+    gtk_widget_show ( item );
+
+    // ATM always enable this entry - don't want to have to analyse the track before displaying the menu - to keep the menu speedy
+    item = gtk_menu_item_new_with_mnemonic ( _("Split Se_gments") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_segments), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_menu_item_new_with_mnemonic ( _("Split at _Trackpoint") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_split_at_trackpoint), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(split_submenu), item );
+    gtk_widget_show ( item );
+    // Make it available only when a trackpoint is selected.
+    gtk_widget_set_sensitive ( item, (gboolean)GPOINTER_TO_INT(l->current_tpl) );
+
+    GtkWidget *delete_submenu;
+    delete_submenu = gtk_menu_new ();
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Delete Poi_nts") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_DELETE, GTK_ICON_SIZE_MENU) );
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+    gtk_widget_show ( item );
+    gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), delete_submenu );
+
+    item = gtk_menu_item_new_with_mnemonic ( _("Delete Points With The Same _Position") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_points_same_position), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_menu_item_new_with_mnemonic ( _("Delete Points With The Same _Time") );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_delete_points_same_time), pass_along );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(delete_submenu), item );
+    gtk_widget_show ( item );
+
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Reverse Track") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_MENU) );
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_reverse), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
     /* ATM This function is only available via the layers panel, due to the method in finding out the maps in use */
     if ( vlp ) {
-      item = gtk_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
+      item = gtk_image_menu_item_new_with_mnemonic ( _("Down_load Maps Along Track...") );
+      gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Maps Download", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along );
       gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
       gtk_widget_show ( item );
     }
 
-    item = gtk_menu_item_new_with_mnemonic ( _("_Apply DEM Data") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("_Apply DEM Data") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("DEM Download/Import", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_apply_dem_data), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Export Trac_k as GPX...") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_HARDDISK, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx_track), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("E_xtend Track End") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") );
-    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_ms), pass_along );
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Extend _Using Route Finder") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock ("Route Finder", GTK_ICON_SIZE_MENU) ); // Own icon - see stock_icons in vikwindow.c
+    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_route_finder), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
+#endif
 
 #ifdef VIK_CONFIG_OPENSTREETMAP
-    item = gtk_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
+    // Convert internal pointer into actual track for usage outside this file
+    pass_along[7] = g_hash_table_lookup ( l->tracks, sublayer);
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(osm_traces_upload_track_cb), pass_along );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_GO_UP, GTK_ICON_SIZE_MENU) );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
 #endif
 
-    if ( is_valid_google_route ( l, (gchar *) sublayer ) )
+    if ( is_valid_google_route ( l, sublayer ) )
     {
-      item = gtk_menu_item_new_with_mnemonic ( _("_View Google Directions") );
+      item = gtk_image_menu_item_new_with_mnemonic ( _("_View Google Directions") );
+      gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_NETWORK, GTK_ICON_SIZE_MENU) );
       g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_google_route_webpage), pass_along );
       gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
       gtk_widget_show ( item );
     }
 
-    item = gtk_menu_item_new_with_mnemonic ( _("Use with _Filter") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Use with _Filter") );
+    gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INDEX, GTK_ICON_SIZE_MENU) );
     g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_track_use_with_filter), pass_along );
     gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
     gtk_widget_show ( item );
@@ -3812,6 +5147,13 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
       }
     }
 
+#ifdef VIK_CONFIG_GEOTAG
+  item = gtk_menu_item_new_with_mnemonic ( _("Geotag _Images...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_geotagging_track), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+  gtk_widget_show ( item );
+#endif
+
     // Only show on viewport popmenu when a trackpoint is selected
     if ( ! vlp && l->current_tpl ) {
       // Add separator
@@ -3876,7 +5218,7 @@ static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl )
     /* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */
 
     /* Insert new point into the trackpoints list after the current TP */
-    VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_track_name );
+    VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
     gint index =  g_list_index ( tr->trackpoints, tp_current );
     if ( index > -1 ) {
       tr->trackpoints = g_list_insert (tr->trackpoints, tp_new, index+1 );
@@ -3884,15 +5226,6 @@ static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl )
   }
 }
 
-/* to be called when last_tpl no long exists. */
-static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl )
-{
-  if ( vtl->tpwin ) /* can't join with a non-existant TP. */
-    vik_trw_layer_tpwin_disable_join ( vtl->tpwin );
-  vtl->last_tpl = NULL;
-  vtl->last_tp_track_name = NULL;
-}
-
 static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy )
 {
   if ( vtl->tpwin )
@@ -3908,8 +5241,9 @@ static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy )
   if ( vtl->current_tpl )
   {
     vtl->current_tpl = NULL;
-    vtl->current_tp_track_name = NULL;
-    vik_layer_emit_update(VIK_LAYER(vtl));
+    vtl->current_tp_track = NULL;
+    vtl->current_tp_id = NULL;
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
   }
 }
 
@@ -3924,121 +5258,63 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
 
   if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
   {
-    gchar *name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, vtl->current_tp_track_name);
-    if ( ( name = a_dialog_new_track ( GTK_WINDOW(vtl->tpwin), vtl->tracks, name ) ) )
-    {
-      VikTrack *tr = vik_track_new ();
-      GList *newglist = g_list_alloc ();
-      newglist->prev = NULL;
-      newglist->next = vtl->current_tpl->next;
-      newglist->data = vik_trackpoint_copy(VIK_TRACKPOINT(vtl->current_tpl->data));
-      tr->trackpoints = newglist;
-
-      vtl->current_tpl->next->prev = newglist; /* end old track here */
-      vtl->current_tpl->next = NULL;
-
-      vtl->current_tpl = newglist; /* change tp to first of new track. */
-      vtl->current_tp_track_name = name;
-
-      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
-
-      tr->visible = TRUE;
-
-      vik_trw_layer_add_track ( vtl, name, tr );
-      vik_layer_emit_update(VIK_LAYER(vtl));
-    }
+    trw_layer_split_at_selected_trackpoint ( vtl );
+    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_DELETE )
   {
-    VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_track_name );
-    GList *new_tpl;
-    g_assert(tr != NULL);
+    VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_id );
+    if ( tr == NULL )
+      return;
 
-    /* can't join with a non-existent trackpoint */
-    vtl->last_tpl = NULL;
-    vtl->last_tp_track_name = NULL;
+    GList *new_tpl;
 
+    // Find available adjacent trackpoint
     if ( (new_tpl = vtl->current_tpl->next) || (new_tpl = vtl->current_tpl->prev) )
     {
       if ( VIK_TRACKPOINT(vtl->current_tpl->data)->newsegment && vtl->current_tpl->next )
         VIK_TRACKPOINT(vtl->current_tpl->next->data)->newsegment = TRUE; /* don't concat segments on del */
 
-      tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl ); /* this nulls current_tpl->prev and next */
+      // Delete current trackpoint
+      vik_trackpoint_free ( vtl->current_tpl->data );
+      tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
 
-      /* at this point the old trackpoint exists, but the list links are correct (new), so it is safe to do this. */
-      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track_name );
+      // Set to current to the available adjacent trackpoint
+      vtl->current_tpl = new_tpl;
 
-      trw_layer_cancel_last_tp ( vtl );
+      // Reset dialog with the available adjacent trackpoint
+      if ( vtl->current_tp_track )
+        vik_trw_layer_tpwin_set_tp ( vtl->tpwin, new_tpl, vtl->current_tp_track->name );
 
-      g_free ( vtl->current_tpl->data ); /* TODO: vik_trackpoint_free() */
-      g_list_free_1 ( vtl->current_tpl );
-      vtl->current_tpl = new_tpl;
-      vik_layer_emit_update(VIK_LAYER(vtl));
+      vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
     }
     else
     {
-      tr->trackpoints = g_list_remove_link ( tr->trackpoints, vtl->current_tpl );
-      g_free ( vtl->current_tpl->data ); /* TODO longone: vik_trackpoint_new() and vik_trackpoint_free() */
-      g_list_free_1 ( vtl->current_tpl );
+      // Delete current trackpoint
+      vik_trackpoint_free ( vtl->current_tpl->data );
+      tr->trackpoints = g_list_delete_link ( tr->trackpoints, vtl->current_tpl );
       trw_layer_cancel_current_tp ( vtl, FALSE );
     }
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_FORWARD && vtl->current_tpl->next )
   {
-    vtl->last_tpl = vtl->current_tpl;
-    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->next, vtl->current_tp_track_name );
-    vik_layer_emit_update(VIK_LAYER(vtl)); /* TODO longone: either move or only update if tp is inside drawing window */
+    if ( vtl->current_tp_track )
+      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->next, vtl->current_tp_track->name );
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE); /* TODO longone: either move or only update if tp is inside drawing window */
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_BACK && vtl->current_tpl->prev )
   {
-    vtl->last_tpl = vtl->current_tpl;
-    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->prev, vtl->current_tp_track_name );
-    vik_layer_emit_update(VIK_LAYER(vtl));
-  }
-  else if ( response == VIK_TRW_LAYER_TPWIN_JOIN )
-  {
-    VikTrack *tr1 = g_hash_table_lookup ( vtl->tracks, vtl->last_tp_track_name );
-    VikTrack *tr2 = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_track_name );
-
-    VikTrack *tr_first = tr1, *tr_last = tr2;
-
-    gchar *tmp;
-
-    if ( (!vtl->last_tpl->next) && (!vtl->current_tpl->next) ) /* both endpoints */
-      vik_track_reverse ( tr2 ); /* reverse the second, that way second track clicked will be later. */
-    else if ( (!vtl->last_tpl->prev) && (!vtl->current_tpl->prev) )
-      vik_track_reverse ( tr1 );
-    else if ( (!vtl->last_tpl->prev) && (!vtl->current_tpl->next) ) /* clicked startpoint, then endpoint -- concat end to start */
-    {
-      tr_first = tr2;
-      tr_last = tr1;
-    }
-    /* default -- clicked endpoint then startpoint -- connect endpoint to startpoint */
-
-    if ( tr_last->trackpoints ) /* deleting this part here joins them into 1 segmented track. useful but there's no place in the UI for this feature. segments should be deprecated anyway. */
-      VIK_TRACKPOINT(tr_last->trackpoints->data)->newsegment = FALSE;
-    tr1->trackpoints = g_list_concat ( tr_first->trackpoints, tr_last->trackpoints );
-    tr2->trackpoints = NULL;
-
-    tmp = vtl->current_tp_track_name;
-
-    vtl->current_tp_track_name = vtl->last_tp_track_name; /* current_tp stays the same (believe it or not!) */
-    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
-
-    /* if we did this before, trw_layer_delete_track would have canceled the current tp because
-     * it was the current track. canceling the current tp would have set vtl->current_tpl to NULL */
-    vik_trw_layer_delete_track ( vtl, tmp );
-
-    trw_layer_cancel_last_tp ( vtl ); /* same TP, can't join. */
-    vik_layer_emit_update(VIK_LAYER(vtl));
+    if ( vtl->current_tp_track )
+      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl = vtl->current_tpl->prev, vtl->current_tp_track->name );
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_INSERT && vtl->current_tpl->next )
   {
     trw_layer_insert_tp_after_current_tp ( vtl );
-    vik_layer_emit_update(VIK_LAYER(vtl));
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_DATA_CHANGED )
-    vik_layer_emit_update (VIK_LAYER(vtl));
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
 }
 
 static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
@@ -4052,7 +5328,8 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
     gtk_widget_show_all ( GTK_WIDGET(vtl->tpwin) );
   }
   if ( vtl->current_tpl )
-    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
+    if ( vtl->current_tp_track )
+      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
   /* set layer name and TP data */
 }
 
@@ -4065,7 +5342,7 @@ static void trw_layer_tpwin_init ( VikTrwLayer *vtl )
 typedef struct {
   gint x, y;
   gint closest_x, closest_y;
-  gchar *closest_wp_name;
+  gpointer *closest_wp_id;
   VikWaypoint *closest_wp;
   VikViewport *vvp;
 } WPSearchParams;
@@ -4073,13 +5350,13 @@ typedef struct {
 typedef struct {
   gint x, y;
   gint closest_x, closest_y;
-  gchar *closest_track_name;
+  gpointer closest_track_id;
   VikTrackpoint *closest_tp;
   VikViewport *vvp;
   GList *closest_tpl;
 } TPSearchParams;
 
-static void waypoint_search_closest_tp ( gchar *name, VikWaypoint *wp, WPSearchParams *params )
+static void waypoint_search_closest_tp ( gpointer id, VikWaypoint *wp, WPSearchParams *params )
 {
   gint x, y;
   if ( !wp->visible )
@@ -4095,7 +5372,7 @@ static void waypoint_search_closest_tp ( gchar *name, VikWaypoint *wp, WPSearchP
 
     if (    x <= params->x + slackx && x >= params->x - slackx
          && y <= params->y + slacky && y >= params->y - slacky ) {
-      params->closest_wp_name = name;
+      params->closest_wp_id = id;
       params->closest_wp = wp;
       params->closest_x = x;
       params->closest_y = y;
@@ -4105,14 +5382,14 @@ static void waypoint_search_closest_tp ( gchar *name, VikWaypoint *wp, WPSearchP
            ((!params->closest_wp) ||        /* was the old waypoint we already found closer than this one? */
             abs(x - params->x)+abs(y - params->y) < abs(x - params->closest_x)+abs(y - params->closest_y)))
     {
-      params->closest_wp_name = name;
+      params->closest_wp_id = id;
       params->closest_wp = wp;
       params->closest_x = x;
       params->closest_y = y;
     }
 }
 
-static void track_search_closest_tp ( gchar *name, VikTrack *t, TPSearchParams *params )
+static void track_search_closest_tp ( gpointer id, VikTrack *t, TPSearchParams *params )
 {
   GList *tpl = t->trackpoints;
   VikTrackpoint *tp;
@@ -4131,7 +5408,7 @@ static void track_search_closest_tp ( gchar *name, VikTrack *t, TPSearchParams *
         ((!params->closest_tp) ||        /* was the old trackpoint we already found closer than this one? */
           abs(x - params->x)+abs(y - params->y) < abs(x - params->closest_x)+abs(y - params->closest_y)))
     {
-      params->closest_track_name = name;
+      params->closest_track_id = id;
       params->closest_tp = tp;
       params->closest_tpl = tpl;
       params->closest_x = x;
@@ -4147,7 +5424,7 @@ static VikTrackpoint *closest_tp_in_five_pixel_interval ( VikTrwLayer *vtl, VikV
   params.x = x;
   params.y = y;
   params.vvp = vvp;
-  params.closest_track_name = NULL;
+  params.closest_track_id = NULL;
   params.closest_tp = NULL;
   g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &params);
   return params.closest_tp;
@@ -4160,11 +5437,12 @@ static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikVie
   params.y = y;
   params.vvp = vvp;
   params.closest_wp = NULL;
-  params.closest_wp_name = NULL;
+  params.closest_wp_id = NULL;
   g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &params);
   return params.closest_wp;
 }
 
+
 // Some forward declarations
 static void marker_begin_move ( tool_ed_t *t, gint x, gint y );
 static void marker_moveto ( tool_ed_t *t, gint x, gint y );
@@ -4237,23 +5515,20 @@ static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *eve
       vtl->current_wp->coord = new_coord;
     else {
       if ( vtl->current_tpl ) {
-       VIK_TRACKPOINT(vtl->current_tpl->data)->coord = new_coord;
+        VIK_TRACKPOINT(vtl->current_tpl->data)->coord = new_coord;
       
        if ( vtl->tpwin )
-         vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
-
-       // Don't really know what this is for but seems like it might be handy...
-       /* can't join with itself! */
-       trw_layer_cancel_last_tp ( vtl );
+          if ( vtl->current_tp_track )
+            vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
       }
     }
 
     // Reset
-    vtl->current_wp      = NULL;
-    vtl->current_wp_name = NULL;
+    vtl->current_wp    = NULL;
+    vtl->current_wp_id = NULL;
     trw_layer_cancel_current_tp ( vtl, FALSE );
 
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   return FALSE;
@@ -4282,7 +5557,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
     wp_params.vvp = vvp;
     wp_params.x = event->x;
     wp_params.y = event->y;
-    wp_params.closest_wp_name = NULL;
+    wp_params.closest_wp_id = NULL;
     wp_params.closest_wp = NULL;
 
     g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &wp_params);
@@ -4290,12 +5565,12 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
     if ( wp_params.closest_wp )  {
 
       // Select
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, wp_params.closest_wp_name ), TRUE );
+      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, wp_params.closest_wp_id ), TRUE );
 
       // Too easy to move it so must be holding shift to start immediately moving it
-      //   or otherwise be previously selected
+      //   or otherwise be previously selected but not have an image (otherwise clicking within image bounds (again) moves it)
       if ( event->state & GDK_SHIFT_MASK ||
-          vtl->current_wp == wp_params.closest_wp ) {
+          ( vtl->current_wp == wp_params.closest_wp && !vtl->current_wp->image ) ) {
        // Put into 'move buffer'
        // NB vvp & vw already set in tet
        tet->vtl = (gpointer)vtl;
@@ -4304,10 +5579,10 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
        marker_begin_move (tet, event->x, event->y);
       }
 
-      vtl->current_wp =      wp_params.closest_wp;
-      vtl->current_wp_name = wp_params.closest_wp_name;
+      vtl->current_wp =    wp_params.closest_wp;
+      vtl->current_wp_id = wp_params.closest_wp_id;
 
-      vik_layer_emit_update ( VIK_LAYER(vtl) );
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
 
       return TRUE;
     }
@@ -4318,7 +5593,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
     tp_params.vvp = vvp;
     tp_params.x = event->x;
     tp_params.y = event->y;
-    tp_params.closest_track_name = NULL;
+    tp_params.closest_track_id = NULL;
     tp_params.closest_tp = NULL;
 
     g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params);
@@ -4326,7 +5601,7 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
     if ( tp_params.closest_tp )  {
 
       // Always select + highlight the track
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->tracks_iters, tp_params.closest_track_name ), TRUE );
+      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->tracks_iters, tp_params.closest_track_id ), TRUE );
 
       tet->is_waypoint = FALSE;
 
@@ -4341,21 +5616,27 @@ static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event
       }
 
       vtl->current_tpl = tp_params.closest_tpl;
-      vtl->current_tp_track_name = tp_params.closest_track_name;
+      vtl->current_tp_id = tp_params.closest_track_id;
+      vtl->current_tp_track = g_hash_table_lookup ( vtl->tracks, tp_params.closest_track_id );
+
+      set_statusbar_msg_info_trkpt ( vtl, tp_params.closest_tp );
 
       if ( vtl->tpwin )
-       vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
+       vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
 
-      vik_layer_emit_update ( VIK_LAYER(vtl) );
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
       return TRUE;
     }
   }
 
   /* these aren't the droids you're looking for */
-  vtl->current_wp      = NULL;
-  vtl->current_wp_name = NULL;
+  vtl->current_wp    = NULL;
+  vtl->current_wp_id = NULL;
   trw_layer_cancel_current_tp ( vtl, FALSE );
 
+  // Blank info
+  vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, "" );
+
   return FALSE;
 }
 
@@ -4376,20 +5657,31 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve
   VikTrack *track = (VikTrack*)vik_window_get_selected_track ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) );
   if ( track && track->visible ) {
 
-    if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) {
+    if ( track->name ) {
 
       if ( vtl->track_right_click_menu )
-       gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) );
+        gtk_object_sink ( GTK_OBJECT(vtl->track_right_click_menu) );
 
       vtl->track_right_click_menu = GTK_MENU ( gtk_menu_new () );
       
-      vik_trw_layer_sublayer_add_menu_items ( vtl,
-                                             vtl->track_right_click_menu,
-                                             NULL,
-                                             VIK_TRW_LAYER_SUBLAYER_TRACK,
-                                             vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ),
-                                             g_hash_table_lookup ( vtl->tracks_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ),
-                                             vvp);
+      trku_udata udataU;
+      udataU.trk  = track;
+      udataU.uuid = NULL;
+
+      gpointer *trkf = g_hash_table_find ( vtl->tracks, (GHRFunc) trw_layer_track_find_uuid, &udataU );
+
+      if ( trkf && udataU.uuid ) {
+
+        GtkTreeIter *iter = g_hash_table_lookup ( vtl->tracks_iters, udataU.uuid );
+
+        trw_layer_sublayer_add_menu_items ( vtl,
+                                            vtl->track_right_click_menu,
+                                            NULL,
+                                            VIK_TRW_LAYER_SUBLAYER_TRACK,
+                                            udataU.uuid,
+                                            iter,
+                                            vvp );
+      }
 
       gtk_menu_popup ( vtl->track_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
        
@@ -4400,19 +5692,30 @@ static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEve
   /* See if a waypoint is selected */
   VikWaypoint *waypoint = (VikWaypoint*)vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) );
   if ( waypoint && waypoint->visible ) {
-    if ( vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ) {
+    if ( waypoint->name ) {
 
       if ( vtl->wp_right_click_menu )
-       gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) );
+        gtk_object_sink ( GTK_OBJECT(vtl->wp_right_click_menu) );
 
       vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () );
-      vik_trw_layer_sublayer_add_menu_items ( vtl,
-                                             vtl->wp_right_click_menu,
-                                             NULL,
-                                             VIK_TRW_LAYER_SUBLAYER_WAYPOINT,
-                                             vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ),
-                                             g_hash_table_lookup ( vtl->waypoints_iters, vik_window_get_selected_name ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl) ) ),
-                                             vvp);
+
+      wpu_udata udata;
+      udata.wp   = waypoint;
+      udata.uuid = NULL;
+
+      gpointer *wpf = g_hash_table_find ( vtl->waypoints, (GHRFunc) trw_layer_waypoint_find_uuid, (gpointer) &udata );
+
+      if ( wpf && udata.uuid ) {
+        GtkTreeIter *iter = g_hash_table_lookup ( vtl->waypoints_iters, udata.uuid );
+
+        trw_layer_sublayer_add_menu_items ( vtl,
+                                            vtl->wp_right_click_menu,
+                                            NULL,
+                                            VIK_TRW_LAYER_SUBLAYER_WAYPOINT,
+                                            udata.uuid,
+                                            iter,
+                                            vvp );
+      }
       gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
 
       return TRUE;
@@ -4514,7 +5817,7 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
   params.vvp = vvp;
   params.x = event->x;
   params.y = event->y;
-  params.closest_wp_name = NULL;
+  params.closest_wp_id = NULL;
   /* TODO: should get track listitem so we can break it up, make a new track, mess it up, all that. */
   params.closest_wp = NULL;
   g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &params);
@@ -4532,21 +5835,20 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
     else
       vtl->waypoint_rightclick = FALSE;
 
-    vtl->current_wp = params.closest_wp;
-    vtl->current_wp_name = params.closest_wp_name;
+    vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, params.closest_wp_id ), TRUE );
 
-    if ( params.closest_wp )
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_name ), TRUE );
+    vtl->current_wp = params.closest_wp;
+    vtl->current_wp_id = params.closest_wp_id;
 
     /* could make it so don't update if old WP is off screen and new is null but oh well */
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
 
   vtl->current_wp = NULL;
-  vtl->current_wp_name = NULL;
+  vtl->current_wp_id = NULL;
   vtl->waypoint_rightclick = FALSE;
-  vik_layer_emit_update ( VIK_LAYER(vtl) );
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
   return FALSE;
 }
 
@@ -4621,7 +5923,7 @@ static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *e
     marker_end_move ( t );
 
     vtl->current_wp->coord = new_coord;
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   /* PUT IN RIGHT PLACE!!! */
@@ -4629,9 +5931,11 @@ static gboolean tool_edit_waypoint_release ( VikTrwLayer *vtl, GdkEventButton *e
   {
     if ( vtl->wp_right_click_menu )
       g_object_ref_sink ( G_OBJECT(vtl->wp_right_click_menu) );
-    vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () );
-    vik_trw_layer_sublayer_add_menu_items ( vtl, vtl->wp_right_click_menu, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, vtl->current_wp_name, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_name ), vvp );
-    gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+    if ( vtl->current_wp ) {
+      vtl->wp_right_click_menu = GTK_MENU ( gtk_menu_new () );
+      trw_layer_sublayer_add_menu_items ( vtl, vtl->wp_right_click_menu, NULL, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, vtl->current_wp_id, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_id ), vvp );
+      gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+    }
     vtl->waypoint_rightclick = FALSE;
   }
   return FALSE;
@@ -4658,49 +5962,208 @@ static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp)
 
 typedef struct {
   VikTrwLayer *vtl;
-  VikViewport *vvp;
-  gint x1,y1,x2,y2;
-} new_track_move_passalong_t;
-
-/* sync and undraw, but only when we have time */
-static gboolean ct_sync ( gpointer passalong )
-{
-  new_track_move_passalong_t *p = (new_track_move_passalong_t *) passalong;
-  vik_viewport_sync ( p->vvp );
-  gdk_gc_set_function ( p->vtl->current_track_gc, GDK_INVERT );
-  vik_viewport_draw_line ( p->vvp, p->vtl->current_track_gc, p->x1, p->y1, p->x2, p->y2 );
-  gdk_gc_set_function ( p->vtl->current_track_gc, GDK_COPY );
-  p->vtl->ct_sync_done = TRUE;
-  g_free ( p );
+  GdkDrawable *drawable;
+  GdkGC *gc;
+  GdkPixmap *pixmap;
+} draw_sync_t;
+
+/*
+ * Draw specified pixmap
+ */
+static gboolean draw_sync ( gpointer data )
+{
+  draw_sync_t *ds = (draw_sync_t*) data;
+  // Sometimes don't want to draw
+  //  normally because another update has taken precedent such as panning the display
+  //   which means this pixmap is no longer valid
+  if ( ds->vtl->draw_sync_do ) {
+    gdk_threads_enter();
+    gdk_draw_drawable (ds->drawable,
+                       ds->gc,
+                       ds->pixmap,
+                       0, 0, 0, 0, -1, -1);
+    ds->vtl->draw_sync_done = TRUE;
+    gdk_threads_leave();
+  }
   return FALSE;
 }
 
+static const gchar* distance_string (gdouble distance)
+{
+  gchar str[128];
+
+  /* draw label with distance */
+  vik_units_distance_t dist_units = a_vik_get_units_distance ();
+  switch (dist_units) {
+  case VIK_UNITS_DISTANCE_MILES:
+    if (distance >= VIK_MILES_TO_METERS(1) && distance < VIK_MILES_TO_METERS(100)) {
+      g_sprintf(str, "%3.2f miles", VIK_METERS_TO_MILES(distance));
+    } else if (distance < 1609.4) {
+      g_sprintf(str, "%d yards", (int)(distance*1.0936133));
+    } else {
+      g_sprintf(str, "%d miles", (int)VIK_METERS_TO_MILES(distance));
+    }
+    break;
+  default:
+    // VIK_UNITS_DISTANCE_KILOMETRES
+    if (distance >= 1000 && distance < 100000) {
+      g_sprintf(str, "%3.2f km", distance/1000.0);
+    } else if (distance < 1000) {
+      g_sprintf(str, "%d m", (int)distance);
+    } else {
+      g_sprintf(str, "%d km", (int)distance/1000);
+    }
+    break;
+  }
+  return g_strdup (str);
+}
+
+/*
+ * Actually set the message in statusbar
+ */
+static void statusbar_write (const gchar *distance_string, gdouble elev_gain, gdouble elev_loss, VikTrwLayer *vtl )
+{
+  // Only show elevation data when track has some elevation properties
+  gchar str_gain_loss[64];
+  str_gain_loss[0] = '\0';
+  
+  if ( (elev_gain > 0.1) || (elev_loss > 0.1) ) {
+    if ( a_vik_get_units_height () == VIK_UNITS_HEIGHT_METRES )
+      g_sprintf(str_gain_loss, _(" - Gain %dm:Loss %dm"), (int)elev_gain, (int)elev_loss);
+    else
+      g_sprintf(str_gain_loss, _(" - Gain %dft:Loss %dft"), (int)VIK_METERS_TO_FEET(elev_gain), (int)VIK_METERS_TO_FEET(elev_loss));
+  }
+
+  // Write with full gain/loss information
+  gchar *msg = g_strdup_printf ( "%s%s", distance_string, str_gain_loss);
+  vik_statusbar_set_message ( vik_window_get_statusbar (VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl))), VIK_STATUSBAR_INFO, msg );
+  g_free ( msg );
+}
+
+/*
+ * Figure out what information should be set in the statusbar and then write it
+ */
+static void update_statusbar ( VikTrwLayer *vtl )
+{
+  // Get elevation data
+  gdouble elev_gain, elev_loss;
+  vik_track_get_total_elevation_gain ( vtl->current_track, &elev_gain, &elev_loss);
+
+  /* Find out actual distance of current track */
+  gdouble distance = vik_track_get_length (vtl->current_track);
+  const gchar *str = distance_string (distance);
+
+  statusbar_write (str, elev_gain, elev_loss, vtl);
+
+  g_free ((gpointer)str);
+}
+
+
 static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMotion *event, VikViewport *vvp )
 {
   /* if we haven't sync'ed yet, we don't have time to do more. */
-  if ( vtl->ct_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
-    GList *iter = vtl->current_track->trackpoints;
-    new_track_move_passalong_t *passalong;
+  if ( vtl->draw_sync_done && vtl->current_track && vtl->current_track->trackpoints ) {
+    GList *iter = g_list_last ( vtl->current_track->trackpoints );
+
+    static GdkPixmap *pixmap = NULL;
+    int w1, h1, w2, h2;
+    // Need to check in case window has been resized
+    w1 = vik_viewport_get_width(vvp);
+    h1 = vik_viewport_get_height(vvp);
+    if (!pixmap) {
+      pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+    }
+    gdk_drawable_get_size (pixmap, &w2, &h2);
+    if (w1 != w2 || h1 != h2) {
+      g_object_unref ( G_OBJECT ( pixmap ) );
+      pixmap = gdk_pixmap_new ( GTK_WIDGET(vvp)->window, w1, h1, -1 );
+    }
+
+    // Reset to background
+    gdk_draw_drawable (pixmap,
+                       vtl->current_track_newpoint_gc,
+                       vik_viewport_get_pixmap(vvp),
+                       0, 0, 0, 0, -1, -1);
+
+    draw_sync_t *passalong;
     gint x1, y1;
 
-    while ( iter->next )
-      iter = iter->next;
-    gdk_gc_set_function ( vtl->current_track_gc, GDK_INVERT );
     vik_viewport_coord_to_screen ( vvp, &(VIK_TRACKPOINT(iter->data)->coord), &x1, &y1 );
-    vik_viewport_draw_line ( vvp, vtl->current_track_gc, x1, y1, event->x, event->y );
-    gdk_gc_set_function ( vtl->current_track_gc, GDK_COPY );
 
-    passalong = g_new(new_track_move_passalong_t,1); /* freed by sync */
+    // FOR SCREEN OVERLAYS WE MUST DRAW INTO THIS PIXMAP (when using the reset method)
+    //  otherwise using vik_viewport_draw_* functions puts the data into the base pixmap,
+    //  thus when we come to reset to the background it would include what we have already drawn!!
+    gdk_draw_line ( pixmap,
+                    vtl->current_track_newpoint_gc,
+                    x1, y1, event->x, event->y );
+    // Using this reset method is more reliable than trying to undraw previous efforts via the GDK_INVERT method
+
+    /* Find out actual distance of current track */
+    gdouble distance = vik_track_get_length (vtl->current_track);
+
+    // Now add distance to where the pointer is //
+    VikCoord coord;
+    struct LatLon ll;
+    vik_viewport_screen_to_coord ( vvp, (gint) event->x, (gint) event->y, &coord );
+    vik_coord_to_latlon ( &coord, &ll );
+    distance = distance + vik_coord_diff( &coord, &(VIK_TRACKPOINT(iter->data)->coord));
+
+    // Get elevation data
+    gdouble elev_gain, elev_loss;
+    vik_track_get_total_elevation_gain ( vtl->current_track, &elev_gain, &elev_loss);
+
+    // Adjust elevation data (if available) for the current pointer position
+    gdouble elev_new;
+    elev_new = (gdouble) a_dems_get_elev_by_coord ( &coord, VIK_DEM_INTERPOL_BEST );
+    if ( elev_new != VIK_DEM_INVALID_ELEVATION ) {
+      if ( VIK_TRACKPOINT(iter->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
+       // Adjust elevation of last track point
+       if ( elev_new > VIK_TRACKPOINT(iter->data)->altitude )
+         // Going up
+         elev_gain += elev_new - VIK_TRACKPOINT(iter->data)->altitude;
+       else
+         // Going down
+         elev_loss += VIK_TRACKPOINT(iter->data)->altitude - elev_new;
+      }
+    }
+      
+    const gchar *str = distance_string (distance);
+    gint xd,yd;
+    /* offset from cursor a bit */
+    xd = event->x + 10;
+    yd = event->y - 10;
+
+    PangoLayout *pl = gtk_widget_create_pango_layout (GTK_WIDGET(vvp), NULL);
+    PangoFontDescription *pfd = pango_font_description_from_string ("Sans 8"); // FIXME: settable option? global variable?
+    pango_layout_set_font_description (pl, pfd);
+    pango_font_description_free (pfd);
+
+    pango_layout_set_text (pl, str, -1);
+    gint wd, hd;
+    pango_layout_get_pixel_size ( pl, &wd, &hd );
+
+    // Create a background block to make the text easier to read over the background map
+    GdkGC *background_block_gc = vik_viewport_new_gc ( vvp, "#cccccc", 1);
+    gdk_draw_rectangle (pixmap, background_block_gc, TRUE, xd-2, yd-2, wd+4, hd+2);
+    gdk_draw_layout (pixmap, vtl->current_track_newpoint_gc, xd, yd, pl);
+
+    g_object_unref ( G_OBJECT ( pl ) );
+    g_object_unref ( G_OBJECT ( background_block_gc ) );
+
+    passalong = g_new(draw_sync_t,1); // freed by draw_sync()
     passalong->vtl = vtl;
-    passalong->vvp = vvp;
-    passalong->x1 = x1;
-    passalong->y1 = y1;
-    passalong->x2 = event->x;
-    passalong->y2 = event->y;
-
-    /* this will sync and undraw when we have time to */
-    g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, ct_sync, passalong, NULL);
-    vtl->ct_sync_done = FALSE;
+    passalong->pixmap = pixmap;
+    passalong->drawable = GTK_WIDGET(vvp)->window;
+    passalong->gc = vtl->current_track_newpoint_gc;
+
+    // Update statusbar with full gain/loss information
+    statusbar_write (str, elev_gain, elev_loss, vtl);
+
+    g_free ((gpointer)str);
+
+    // draw pixmap when we have time to
+    g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, draw_sync, passalong, NULL);
+    vtl->draw_sync_done = FALSE;
     return VIK_LAYER_TOOL_ACK_GRAB_FOCUS;
   }
   return VIK_LAYER_TOOL_ACK;
@@ -4710,7 +6173,7 @@ static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event,
 {
   if ( vtl->current_track && event->keyval == GDK_Escape ) {
     vtl->current_track = NULL;
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   } else if ( vtl->current_track && event->keyval == GDK_BackSpace ) {
     /* undo */
@@ -4720,7 +6183,10 @@ static gboolean tool_new_track_key_press ( VikTrwLayer *vtl, GdkEventKey *event,
       g_free ( last->data );
       vtl->current_track->trackpoints = g_list_remove_link ( vtl->current_track->trackpoints, last );
     }
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    
+    update_statusbar ( vtl );
+
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   return FALSE;
@@ -4733,6 +6199,13 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
   if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
     return FALSE;
 
+  if ( event->button == 2 ) {
+    // As the display is panning, the new track pixmap is now invalid so don't draw it
+    //  otherwise this drawing done results in flickering back to an old image
+    vtl->draw_sync_do = FALSE;
+    return FALSE;
+  }
+
   if ( event->button == 3 && vtl->current_track )
   {
     /* undo */
@@ -4742,7 +6215,9 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
       g_free ( last->data );
       vtl->current_track->trackpoints = g_list_remove_link ( vtl->current_track->trackpoints, last );
     }
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    update_statusbar ( vtl );
+
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
 
@@ -4757,13 +6232,13 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
       /* undo last, then end */
       vtl->current_track = NULL;
     }
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
 
   if ( ! vtl->current_track )
   {
-    gchar *name = get_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track"));
+    gchar *name = trw_layer_new_unique_sublayer_name(vtl, VIK_TRW_LAYER_SUBLAYER_TRACK, _("Track"));
     if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks, name ) ) )
     {
       vtl->current_track = vik_track_new();
@@ -4791,16 +6266,27 @@ static gboolean tool_new_track_click ( VikTrwLayer *vtl, GdkEventButton *event,
   tp->has_timestamp = FALSE;
   tp->timestamp = 0;
   vtl->current_track->trackpoints = g_list_append ( vtl->current_track->trackpoints, tp );
+  /* Auto attempt to get elevation from DEM data (if it's available) */
+  vik_track_apply_dem_data_last_trackpoint ( vtl->current_track );
 
   vtl->ct_x1 = vtl->ct_x2;
   vtl->ct_y1 = vtl->ct_y2;
   vtl->ct_x2 = event->x;
   vtl->ct_y2 = event->y;
 
-  vik_layer_emit_update ( VIK_LAYER(vtl) );
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
   return TRUE;
 }
 
+static void tool_new_track_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+  if ( event->button == 2 ) {
+    // Pan moving ended - enable potential point drawing again
+    vtl->draw_sync_do = TRUE;
+    vtl->draw_sync_done = TRUE;
+  }
+}
+
 /*** New waypoint ****/
 
 static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp)
@@ -4815,7 +6301,7 @@ static gboolean tool_new_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *even
     return FALSE;
   vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
   if (vik_trw_layer_new_waypoint ( vtl, VIK_GTK_WINDOW_FROM_LAYER(vtl), &coord ) && VIK_LAYER(vtl)->visible)
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
   return TRUE;
 }
 
@@ -4844,7 +6330,7 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
   params.vvp = vvp;
   params.x = event->x;
   params.y = event->y;
-  params.closest_track_name = NULL;
+  params.closest_track_id = NULL;
   /* TODO: should get track listitem so we can break it up, make a new track, mess it up, all that. */
   params.closest_tp = NULL;
 
@@ -4861,10 +6347,11 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
   {
     /* first check if it is within range of prev. tp. and if current_tp track is shown. (if it is, we are moving that trackpoint.) */
     VikTrackpoint *tp = VIK_TRACKPOINT(vtl->current_tpl->data);
-    VikTrack *current_tr = VIK_TRACK(g_hash_table_lookup(vtl->tracks, vtl->current_tp_track_name));
-    gint x, y;
-    g_assert ( current_tr );
+    VikTrack *current_tr = VIK_TRACK(g_hash_table_lookup(vtl->tracks, vtl->current_tp_id));
+    if ( !current_tr )
+      return FALSE;
 
+    gint x, y;
     vik_viewport_coord_to_screen ( vvp, &(tp->coord), &x, &y );
 
     if ( current_tr->visible && 
@@ -4874,19 +6361,19 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
       return TRUE;
     }
 
-    vtl->last_tpl = vtl->current_tpl;
-    vtl->last_tp_track_name = vtl->current_tp_track_name;
   }
 
   g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &params);
 
   if ( params.closest_tp )
   {
+    vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->tracks_iters, params.closest_track_id ), TRUE );
     vtl->current_tpl = params.closest_tpl;
-    vtl->current_tp_track_name = params.closest_track_name;
-    vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->tracks_iters, vtl->current_tp_track_name ), TRUE );
+    vtl->current_tp_id = params.closest_track_id;
+    vtl->current_tp_track = g_hash_table_lookup ( vtl->tracks, params.closest_track_id );
     trw_layer_tpwin_init ( vtl );
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    set_statusbar_msg_info_trkpt ( vtl, params.closest_tp );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
 
@@ -4953,62 +6440,62 @@ static gboolean tool_edit_trackpoint_release ( VikTrwLayer *vtl, GdkEventButton
     marker_end_move ( t );
 
     /* diff dist is diff from orig */
-    vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track_name );
-    /* can't join with itself! */
-    trw_layer_cancel_last_tp ( vtl );
+    if ( vtl->tpwin )
+      vik_trw_layer_tpwin_set_tp ( vtl->tpwin, vtl->current_tpl, vtl->current_tp_track->name );
 
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     return TRUE;
   }
   return FALSE;
 }
 
 
-/*** Magic Scissors ***/
-static gpointer tool_magic_scissors_create ( VikWindow *vw, VikViewport *vvp)
+#ifdef VIK_CONFIG_GOOGLE_DIRECTIONS
+/*** Route Finder ***/
+static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp)
 {
   return vvp;
 }
 
-static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
 {
   VikCoord tmp;
   if ( !vtl ) return FALSE;
   vik_viewport_screen_to_coord ( vvp, event->x, event->y, &tmp );
-  if ( event->button == 3 && vtl->magic_scissors_current_track ) {
+  if ( event->button == 3 && vtl->route_finder_current_track ) {
     VikCoord *new_end;
-    new_end = vik_track_cut_back_to_double_point ( vtl->magic_scissors_current_track );
+    new_end = vik_track_cut_back_to_double_point ( vtl->route_finder_current_track );
     if ( new_end ) {
-      vtl->magic_scissors_coord = *new_end;
+      vtl->route_finder_coord = *new_end;
       g_free ( new_end );
-      vik_layer_emit_update ( VIK_LAYER(vtl) );
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
       /* remove last ' to:...' */
-      if ( vtl->magic_scissors_current_track->comment ) {
-        gchar *last_to = strrchr ( vtl->magic_scissors_current_track->comment, 't' );
-        if ( last_to && (last_to - vtl->magic_scissors_current_track->comment > 1) ) {
-          gchar *new_comment = g_strndup ( vtl->magic_scissors_current_track->comment,
-                                           last_to - vtl->magic_scissors_current_track->comment - 1);
-          vik_track_set_comment_no_copy ( vtl->magic_scissors_current_track, new_comment );
+      if ( vtl->route_finder_current_track->comment ) {
+        gchar *last_to = strrchr ( vtl->route_finder_current_track->comment, 't' );
+        if ( last_to && (last_to - vtl->route_finder_current_track->comment > 1) ) {
+          gchar *new_comment = g_strndup ( vtl->route_finder_current_track->comment,
+                                           last_to - vtl->route_finder_current_track->comment - 1);
+          vik_track_set_comment_no_copy ( vtl->route_finder_current_track, new_comment );
         }
       }
     }
   }
-  else if ( vtl->magic_scissors_started || (event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track) ) {
+  else if ( vtl->route_finder_started || (event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track) ) {
     struct LatLon start, end;
     gchar startlat[G_ASCII_DTOSTR_BUF_SIZE], startlon[G_ASCII_DTOSTR_BUF_SIZE];
     gchar endlat[G_ASCII_DTOSTR_BUF_SIZE], endlon[G_ASCII_DTOSTR_BUF_SIZE];
     gchar *url;
 
-    vik_coord_to_latlon ( &(vtl->magic_scissors_coord), &start );
+    vik_coord_to_latlon ( &(vtl->route_finder_coord), &start );
     vik_coord_to_latlon ( &(tmp), &end );
-    vtl->magic_scissors_coord = tmp; /* for continuations */
+    vtl->route_finder_coord = tmp; /* for continuations */
 
     /* these are checked when adding a track from a file (vik_trw_layer_filein_add_track) */
-    if ( event->state & GDK_CONTROL_MASK && vtl->magic_scissors_current_track ) {
-      vtl->magic_scissors_append = TRUE;  // merge tracks. keep started true.
+    if ( event->state & GDK_CONTROL_MASK && vtl->route_finder_current_track ) {
+      vtl->route_finder_append = TRUE;  // merge tracks. keep started true.
     } else {
-      vtl->magic_scissors_check_added_track = TRUE;
-      vtl->magic_scissors_started = FALSE;
+      vtl->route_finder_check_added_track = TRUE;
+      vtl->route_finder_started = FALSE;
     }
 
     url = g_strdup_printf(GOOGLE_DIRECTIONS_STRING,
@@ -5020,34 +6507,26 @@ static gboolean tool_magic_scissors_click ( VikTrwLayer *vtl, GdkEventButton *ev
     g_free ( url );
 
     /* see if anything was done -- a track was added or appended to */
-    if ( vtl->magic_scissors_check_added_track && vtl->magic_scissors_added_track_name ) {
-      VikTrack *tr;
-
-      tr = g_hash_table_lookup ( vtl->tracks, vtl->magic_scissors_added_track_name );
-
-      if ( tr )
-        vik_track_set_comment_no_copy ( tr, g_strdup_printf("from: %f,%f to: %f,%f", start.lat, start.lon, end.lat, end.lon ) );
-      vtl->magic_scissors_current_track = tr;
-
-      g_free ( vtl->magic_scissors_added_track_name );
-      vtl->magic_scissors_added_track_name = NULL;
-    } else if ( vtl->magic_scissors_append == FALSE && vtl->magic_scissors_current_track ) {
-      /* magic_scissors_append was originally TRUE but set to FALSE by filein_add_track */
-      gchar *new_comment = g_strdup_printf("%s to: %f,%f", vtl->magic_scissors_current_track->comment, end.lat, end.lon );
-      vik_track_set_comment_no_copy ( vtl->magic_scissors_current_track, new_comment );
+    if ( vtl->route_finder_check_added_track && vtl->route_finder_added_track ) {
+      vik_track_set_comment_no_copy ( vtl->route_finder_added_track, g_strdup_printf("from: %f,%f to: %f,%f", start.lat, start.lon, end.lat, end.lon ) );
+    } else if ( vtl->route_finder_append == FALSE && vtl->route_finder_current_track ) {
+      /* route_finder_append was originally TRUE but set to FALSE by filein_add_track */
+      gchar *new_comment = g_strdup_printf("%s to: %f,%f", vtl->route_finder_current_track->comment, end.lat, end.lon );
+      vik_track_set_comment_no_copy ( vtl->route_finder_current_track, new_comment );
     }
-    vtl->magic_scissors_check_added_track = FALSE;
-    vtl->magic_scissors_append = FALSE;
+    vtl->route_finder_added_track = NULL;
+    vtl->route_finder_check_added_track = FALSE;
+    vtl->route_finder_append = FALSE;
 
-    vik_layer_emit_update ( VIK_LAYER(vtl) );
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
   } else {
-    vtl->magic_scissors_started = TRUE;
-    vtl->magic_scissors_coord = tmp;
-    vtl->magic_scissors_current_track = NULL;
+    vtl->route_finder_started = TRUE;
+    vtl->route_finder_coord = tmp;
+    vtl->route_finder_current_track = NULL;
   }
   return TRUE;
 }
+#endif
 
 /*** Show picture ****/
 
@@ -5057,7 +6536,7 @@ static gpointer tool_show_picture_create ( VikWindow *vw, VikViewport *vvp)
 }
 
 /* Params are: vvp, event, last match found or NULL */
-static void tool_show_picture_wp ( char *name, VikWaypoint *wp, gpointer params[2] )
+static void tool_show_picture_wp ( char *name, VikWaypoint *wp, gpointer params[3] )
 {
   if ( wp->image && wp->visible )
   {
@@ -5081,15 +6560,15 @@ static void trw_layer_show_picture ( gpointer pass_along[6] )
 {
   /* thanks to the Gaim people for showing me ShellExecute and g_spawn_command_line_async */
 #ifdef WINDOWS
-  ShellExecute(NULL, NULL, (char *) pass_along[2], NULL, ".\\", 0);
+  ShellExecute(NULL, "open", (char *) pass_along[5], NULL, NULL, SW_SHOWNORMAL);
 #else /* WINDOWS */
   GError *err = NULL;
   gchar *quoted_file = g_shell_quote ( (gchar *) pass_along[5] );
-  gchar *cmd = g_strdup_printf ( "eog %s", quoted_file );
+  gchar *cmd = g_strdup_printf ( "%s %s", a_vik_get_image_viewer(), quoted_file );
   g_free ( quoted_file );
   if ( ! g_spawn_command_line_async ( cmd, &err ) )
     {
-      a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER( pass_along[0]), _("Could not launch eog to open file.") );
+      a_dialog_error_msg_extra ( VIK_GTK_WINDOW_FROM_LAYER( pass_along[0]), _("Could not launch %s to open file."), a_vik_get_image_viewer() );
       g_error_free ( err );
     }
   g_free ( cmd );
@@ -5148,10 +6627,8 @@ static int create_thumbnails_thread ( thumbnail_create_thread_data *tctd, gpoint
   }
 
   // Redraw to show the thumbnails as they are now created
-  gdk_threads_enter();
   if ( IS_VIK_LAYER(tctd->vtl) )
-    vik_layer_emit_update ( VIK_LAYER(tctd->vtl) );
-  gdk_threads_leave();
+    vik_layer_emit_update ( VIK_LAYER(tctd->vtl), TRUE ); // Yes update from background thread
 
   return 0;
 }
@@ -5166,7 +6643,7 @@ static void thumbnail_create_thread_free ( thumbnail_create_thread_data *tctd )
   g_free ( tctd );
 }
 
-static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
+void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
 {
   if ( ! vtl->has_verified_thumbnails )
   {
@@ -5196,9 +6673,22 @@ VikCoordMode vik_trw_layer_get_coord_mode ( VikTrwLayer *vtl )
   return vtl->coord_mode;
 }
 
+/**
+ * Uniquify the whole layer
+ * Also requires the layers panel as the names shown there need updating too
+ * Returns whether the operation was successful or not
+ */
+gboolean vik_trw_layer_uniquify ( VikTrwLayer *vtl, VikLayersPanel *vlp )
+{
+  if ( vtl && vlp ) {
+    vik_trw_layer_uniquify_tracks ( vtl, vlp );
+    vik_trw_layer_uniquify_waypoints ( vtl, vlp );
+    return TRUE;
+  }
+  return FALSE;
+}
 
-
-static void waypoint_convert ( const gchar *name, VikWaypoint *wp, VikCoordMode *dest_mode )
+static void waypoint_convert ( const gpointer id, VikWaypoint *wp, VikCoordMode *dest_mode )
 {
   vik_coord_convert ( &(wp->coord), *dest_mode );
 }
@@ -5218,24 +6708,14 @@ static void trw_layer_change_coord_mode ( VikTrwLayer *vtl, VikCoordMode dest_mo
   }
 }
 
-VikWaypoint *vik_trw_layer_get_waypoint ( VikTrwLayer *vtl, gchar *name )
-{
-  return g_hash_table_lookup ( vtl->waypoints, name );
-}
-
-VikTrack *vik_trw_layer_get_track ( VikTrwLayer *vtl, const gchar *name )
-{
-  return g_hash_table_lookup ( vtl->tracks, name );
-}
-
-static void vik_trw_layer_set_menu_selection(VikTrwLayer *vtl, guint16 selection)
+static void trw_layer_set_menu_selection ( VikTrwLayer *vtl, guint16 selection )
 {
   vtl->menu_selection = selection;
 }
 
-static guint16 vik_trw_layer_get_menu_selection(VikTrwLayer *vtl)
+static guint16 trw_layer_get_menu_selection ( VikTrwLayer *vtl )
 {
-  return(vtl->menu_selection);
+  return (vtl->menu_selection);
 }
 
 /* ----------- Downloading maps along tracks --------------- */
@@ -5499,13 +6979,13 @@ static void highest_wp_number_remove_wp(VikTrwLayer *vtl, const gchar *old_wp_na
   gint old_wp_num = highest_wp_number_name_to_number(old_wp_name);
   if ( vtl->highest_wp_number == old_wp_num ) {
     gchar buf[4];
-    vtl->highest_wp_number --;
+    vtl->highest_wp_number--;
 
     g_snprintf(buf,4,"%03d", vtl->highest_wp_number );
     /* search down until we find something that *does* exist */
 
-    while ( vtl->highest_wp_number > 0 && ! g_hash_table_lookup ( vtl->waypoints, buf ) ) {
-      vtl->highest_wp_number --;
+    while ( vtl->highest_wp_number > 0 && ! vik_trw_layer_get_waypoint ( vtl, buf )) {
+      vtl->highest_wp_number--;
       g_snprintf(buf,4,"%03d", vtl->highest_wp_number );
     }
   }