]> git.street.me.uk Git - andy/viking.git/blobdiff - src/viktrwlayer.c
Add ability to geotag images interpolating times against tracks.
[andy/viking.git] / src / viktrwlayer.c
index 4c42fa9cb29ad58e88d42e3a2e32337b59a35c4b..2d04a94d3c37cb2bab551cb24228c64f88d90d86 100644 (file)
@@ -1,7 +1,11 @@
 /*
  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
  *
- * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ * Copyright (C) 2003-2007, Evan Battaglia <gtoevan@gmx.net>
+ * 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) 2011, 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
@@ -22,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"
@@ -44,6 +52,7 @@
 #include "osm-traces.h"
 #endif
 #include "acquire.h"
+#include "datasources.h"
 #include "util.h"
 
 #include "icons/icons.h"
@@ -158,13 +167,13 @@ struct _VikTrwLayer {
   /* 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;
+  gchar *route_finder_added_track_name;
+  VikTrack *route_finder_current_track;
+  gboolean route_finder_append;
 
   gboolean drawlabels;
   gboolean drawimages;
@@ -179,6 +188,7 @@ struct _VikTrwLayer {
   gboolean has_verified_thumbnails;
 
   GtkMenu *wp_right_click_menu;
+  GtkMenu *track_right_click_menu;
 
   /* menu */
   VikStdLayerMenuItem menu_selection;
@@ -203,12 +213,9 @@ 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 void trw_layer_delete_item ( gpointer *pass_along );
-static void trw_layer_copy_item_cb( gpointer *pass_along);
-static void trw_layer_cut_item_cb( gpointer *pass_along);
+static void trw_layer_delete_item ( gpointer pass_along[6] );
+static void trw_layer_copy_item_cb ( gpointer pass_along[6] );
+static void trw_layer_cut_item_cb ( gpointer pass_along[6] );
 
 static void trw_layer_find_maxmin_waypoints ( const gchar *name, const VikWaypoint *w, struct LatLon maxmin[2] );
 static void trw_layer_find_maxmin_tracks ( const gchar *name, GList **t, struct LatLon maxmin[2] );    
@@ -221,42 +228,63 @@ static gint calculate_velocity ( VikTrwLayer *vtl, VikTrackpoint *tp1, VikTrackp
 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 void goto_coord ( VikLayersPanel *vlp, const VikCoord *coord );
-static void trw_layer_goto_track_startpoint ( gpointer pass_along[5] );
+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] );
+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_timestamp ( gpointer pass_along[6] );
+static void trw_layer_merge_with_other ( gpointer pass_along[6] );
 static void trw_layer_split_by_timestamp ( gpointer pass_along[6] );
-static void trw_layer_download_map_along_track_cb(gpointer pass_along[6]);
+static void trw_layer_split_by_n_points ( 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_export ( gpointer layer_and_vlp[2], guint file_type );
+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_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] );
+static void trw_layer_auto_tracks_view ( gpointer lav[2] );
+static void trw_layer_delete_all_tracks ( gpointer lav[2] );
+static void trw_layer_delete_tracks_from_selection ( gpointer lav[2] );
+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] );
-static void trw_layer_merge_with_other ( gpointer pass_along[6] );
+#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[5] );
-static void trw_layer_goto_waypoint ( gpointer pass_along[5] );
-static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[5] );
+static void trw_layer_properties_item ( gpointer pass_along[6] );
+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[4] );
-static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pass_along[4] );
+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 init_drawing_params ( struct DrawingParams *dp, VikViewport *vp );
 
-
-static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len );
-static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport *vvp );
-
-static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp );
-static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id );
-
-static void trw_layer_del_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 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 );
@@ -280,19 +308,16 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo
 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 );
+static gpointer tool_route_finder_create ( VikWindow *vw, VikViewport *vvp);
+static gboolean tool_route_finder_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp );
 
 
 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 track_convert ( const gchar *name, VikTrack *tr, VikCoordMode *dest_mode );
@@ -327,8 +352,8 @@ static VikToolInterface trw_layer_tools[] = {
   { 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_("Magic Scissors"),  (VikToolConstructorFunc) tool_magic_scissors_create,  NULL, NULL, NULL,
-    (VikToolMouseFunc) tool_magic_scissors_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_iscissors_pixbuf },
+  { N_("Route Finder"),  (VikToolConstructorFunc) tool_route_finder_create,  NULL, NULL, NULL,
+    (VikToolMouseFunc) tool_route_finder_click, NULL, NULL, (VikToolKeyFunc) NULL, GDK_CURSOR_IS_PIXMAP, &cursor_route_finder_pixbuf },
 };
 enum { TOOL_CREATE_WAYPOINT=0, TOOL_CREATE_TRACK, TOOL_BEGIN_TRACK, TOOL_EDIT_WAYPOINT, TOOL_EDIT_TRACKPOINT, TOOL_SHOW_PICTURE, NUM_TOOLS };
 
@@ -399,6 +424,38 @@ 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",
   &viktrwlayer_pixbuf,
@@ -413,23 +470,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)           trw_layer_selected,
 
   (VikLayerFuncMarshall)                trw_layer_marshall,
   (VikLayerFuncUnmarshall)              trw_layer_unmarshall,
@@ -441,11 +501,17 @@ VikLayerInterface vik_trw_layer_interface = {
   (VikLayerFuncWriteFileData)           a_gpspoint_write_file,
 
   (VikLayerFuncDeleteItem)              trw_layer_del_item,
+  (VikLayerFuncCutItem)                 trw_layer_cut_item,
   (VikLayerFuncCopyItem)                trw_layer_copy_item,
   (VikLayerFuncPasteItem)               trw_layer_paste_item,
   (VikLayerFuncFreeCopiedItem)          trw_layer_free_copied_item,
   
   (VikLayerFuncDragDropRequest)         trw_layer_drag_drop_request,
+
+  (VikLayerFuncSelectClick)             trw_layer_select_click,
+  (VikLayerFuncSelectMove)              trw_layer_select_move,
+  (VikLayerFuncSelectRelease)           trw_layer_select_release,
+  (VikLayerFuncSelectedViewportMenu)    trw_layer_show_selected_viewport_menu,
 };
 
 /* for copy & paste (I think?) */
@@ -482,7 +548,7 @@ GType vik_trw_layer_get_type ()
 
 static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer )
 {
-  static gpointer pass_along[5];
+  static gpointer pass_along[6];
   if (!sublayer) {
     return;
   }
@@ -491,12 +557,31 @@ static void trw_layer_del_item ( VikTrwLayer *vtl, gint subtype, gpointer sublay
   pass_along[1] = NULL;
   pass_along[2] = GINT_TO_POINTER (subtype);
   pass_along[3] = sublayer;
-  pass_along[4] = NULL;
+  pass_along[4] = GINT_TO_POINTER (1); // Confirm delete request
+  pass_along[5] = NULL;
 
   trw_layer_delete_item ( pass_along );
 }
 
-static void trw_layer_copy_item_cb( gpointer pass_along[5])
+static void trw_layer_cut_item ( VikTrwLayer *vtl, gint subtype, gpointer sublayer )
+{
+  static gpointer pass_along[6];
+  if (!sublayer) {
+    return;
+  }
+
+  pass_along[0] = vtl;
+  pass_along[1] = NULL;
+  pass_along[2] = GINT_TO_POINTER (subtype);
+  pass_along[3] = sublayer;
+  pass_along[4] = GINT_TO_POINTER (0); // No delete confirmation needed for auto delete
+  pass_along[5] = NULL;
+
+  trw_layer_copy_item_cb(pass_along);
+  trw_layer_cut_item_cb(pass_along);
+}
+
+static void trw_layer_copy_item_cb ( gpointer pass_along[6])
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   gint subtype = GPOINTER_TO_INT (pass_along[2]);
@@ -508,13 +593,14 @@ static void trw_layer_copy_item_cb( gpointer pass_along[5])
 
   if (data) {
     a_clipboard_copy( VIK_CLIPBOARD_DATA_SUBLAYER, VIK_LAYER_TRW,
-       subtype, len, data);
+                     subtype, len, (const gchar*) sublayer, data);
   }
 }
 
-static void trw_layer_cut_item_cb( gpointer pass_along[5])
+static void trw_layer_cut_item_cb ( gpointer pass_along[6])
 {
   trw_layer_copy_item_cb(pass_along);
+  pass_along[4] = GINT_TO_POINTER (0); // Never need to confirm automatic delete
   trw_layer_delete_item(pass_along);
 }
 
@@ -558,6 +644,9 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i
     w = vik_waypoint_unmarshall(fi->data + fi->len, len - sizeof(*fi) - fi->len);
     vik_trw_layer_add_waypoint ( vtl, name, w );
     waypoint_convert(name, 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), FALSE );
     return TRUE;
   }
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACK && fi )
@@ -568,6 +657,9 @@ static gboolean trw_layer_paste_item ( VikTrwLayer *vtl, gint subtype, guint8 *i
     t = vik_track_unmarshall(fi->data + fi->len, len - sizeof(*fi) - fi->len);
     vik_trw_layer_add_track ( vtl, name, t );
     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), FALSE );
     return TRUE;
   }
   return FALSE;
@@ -580,7 +672,7 @@ static void trw_layer_free_copied_item ( gint subtype, gpointer item )
   }
 }
 
-static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp )
+static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
 {
   switch ( id )
   {
@@ -603,14 +695,44 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara
                      trw_layer_new_track_gcs ( vtl, vp );
                    }
                    break;
-    case PARAM_BLT: if ( data.u > 0 && data.u <= 8 && data.u != vtl->bg_line_thickness )
+    case PARAM_BLT: if ( data.u >= 0 && data.u <= 8 && data.u != vtl->bg_line_thickness )
                    {
                      vtl->bg_line_thickness = data.u;
                      trw_layer_new_track_gcs ( vtl, vp );
                    }
                    break;
-    case PARAM_VMIN: vtl->velocity_min = data.d; break;
-    case PARAM_VMAX: vtl->velocity_max = data.d; 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_DLA: vtl->drawlabels = data.b; break;
     case PARAM_DI: vtl->drawimages = data.b; break;
@@ -638,7 +760,7 @@ static gboolean trw_layer_set_param ( VikTrwLayer *vtl, guint16 id, VikLayerPara
   return TRUE;
 }
 
-static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id )
+static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id, gboolean is_file_operation )
 {
   VikLayerParamData rv;
   switch ( id )
@@ -654,8 +776,38 @@ static VikLayerParamData trw_layer_get_param ( VikTrwLayer *vtl, guint16 id )
     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: rv.d = vtl->velocity_min; break;
-    case PARAM_VMAX: rv.d = vtl->velocity_max; 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;
@@ -703,10 +855,10 @@ static void trw_layer_marshall( VikTrwLayer *vtl, guint8 **data, gint *len )
   }
 }
 
-static VikTrwLayer *trw_layer_unmarshall( gpointer data, gint len, VikViewport *vvp )
+static VikTrwLayer *trw_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
 {
   VikTrwLayer *rv = VIK_TRW_LAYER(vik_layer_create ( VIK_LAYER_TRW, vvp, NULL, FALSE ));
-  guint pl;
+  gint pl;
   gchar *tmpname;
   FILE *f;
 
@@ -766,7 +918,7 @@ 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);
@@ -792,6 +944,7 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
   rv->drawlines = TRUE;
   rv->wplabellayout = NULL;
   rv->wp_right_click_menu = NULL;
+  rv->track_right_click_menu = NULL;
   rv->waypoint_gc = NULL;
   rv->waypoint_text_gc = NULL;
   rv->waypoint_bg_gc = NULL;
@@ -810,11 +963,11 @@ VikTrwLayer *vik_trw_layer_new ( gint drawmode )
 
   rv->ct_sync_done = 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_added_track_name = NULL;
+  rv->route_finder_current_track = NULL;
+  rv->route_finder_append = FALSE;
 
   rv->waypoint_rightclick = FALSE;
   rv->last_tpl = NULL;
@@ -830,7 +983,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);
@@ -839,7 +992,10 @@ void vik_trw_layer_free ( VikTrwLayer *trwlayer )
   trw_layer_free_track_gcs ( trwlayer );
 
   if ( trwlayer->wp_right_click_menu )
-    gtk_object_sink ( GTK_OBJECT(trwlayer->wp_right_click_menu) );
+    g_object_ref_sink ( G_OBJECT(trwlayer->wp_right_click_menu) );
+
+  if ( trwlayer->track_right_click_menu )
+    gtk_object_sink ( GTK_OBJECT(trwlayer->track_right_click_menu) );
 
   if ( trwlayer->wplabellayout != NULL)
     g_object_unref ( G_OBJECT ( trwlayer->wplabellayout ) );
@@ -968,13 +1124,34 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
     drawstops = dp->vtl->drawstops;
   }
 
-  if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
-    dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
-
+  /* Current track - used for creation */
   if ( track == dp->vtl->current_track )
     main_gc = dp->vtl->current_track_gc;
-  else
-    main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+  else {
+    if ( vik_viewport_get_draw_highlight ( dp->vp ) ) {
+      /* Draw all tracks of the layer in special colour */
+      /* if track is member of selected layer or is the current selected track
+        then draw in the highlight colour.
+        NB this supercedes the drawmode */
+      if ( dp->vtl && ( ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) ||
+                       ( 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);
+      }
+      else {
+       if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
+         dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
+
+       main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+      }
+    }
+    else {
+      if ( dp->vtl->drawmode == DRAWMODE_ALL_BLACK )
+       dp->track_gc_iter = VIK_TRW_LAYER_TRACK_GC_BLACK;
+         
+      main_gc = g_array_index(dp->vtl->track_gc, GdkGC *, dp->track_gc_iter);
+    }
+  }
 
   if (list) {
     int x, y, oldx, oldy;
@@ -1011,8 +1188,6 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
           if ( list->next ) {
             vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
 
-            vik_viewport_draw_rectangle ( dp->vp, main_gc, TRUE, x-tp_size, y-tp_size, 2*tp_size, 2*tp_size );
-
             /* stops */
             if ( drawstops && 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 );
@@ -1029,8 +1204,10 @@ static void trw_layer_draw_track ( const gchar *name, VikTrack *track, struct Dr
           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 )
+          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 );
@@ -1077,8 +1254,10 @@ 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 )
+            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 ( drawing_white_background )
               vik_viewport_draw_line ( dp->vp, dp->vtl->track_bg_gc, oldx, oldy, x, y);
@@ -1188,6 +1367,18 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
 
         if ( x+(w/2) > 0 && y+(h/2) > 0 && x-(w/2) < dp->width && y-(h/2) < dp->height ) /* always draw within boundaries */
         {
+         if ( vik_viewport_get_draw_highlight ( dp->vp ) ) {
+           if ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
+                dp->vtl->waypoints == vik_window_get_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
+                wp == vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ) {
+             // Highlighted - so draw a little border around the chosen one
+             // single line seems a little weak so draw 2 of them
+             vik_viewport_draw_rectangle (dp->vp, vik_viewport_get_gc_highlight (dp->vp), FALSE,
+                                          x - (w/2) - 1, y - (h/2) - 1, w + 2, h + 2 );
+             vik_viewport_draw_rectangle (dp->vp, vik_viewport_get_gc_highlight (dp->vp), FALSE,
+                                          x - (w/2) - 2, y - (h/2) - 2, w + 4, h + 4 );
+           }
+         }
           if ( dp->vtl->image_alpha == 255 )
             vik_viewport_draw_pixbuf ( dp->vp, pixbuf, 0, 0, x - (w/2), y - (h/2), w, h );
           else
@@ -1233,13 +1424,24 @@ static void trw_layer_draw_waypoint ( const gchar *name, VikWaypoint *wp, struct
       else
         label_y = y - dp->vtl->wp_size - height - 2;
 
-      vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, label_x - 1, label_y-1,width+2,height+2);
+      /* if highlight mode on, then draw background text in highlight colour */
+      if ( vik_viewport_get_draw_highlight ( dp->vp ) ) {
+       if ( dp->vtl == vik_window_get_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
+            dp->vtl->waypoints == vik_window_get_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) ||
+            wp == vik_window_get_selected_waypoint ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(dp->vtl) ) )
+         vik_viewport_draw_rectangle ( dp->vp, vik_viewport_get_gc_highlight (dp->vp), TRUE, label_x - 1, label_y-1,width+2,height+2);
+       else
+         vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, label_x - 1, label_y-1,width+2,height+2);
+      }
+      else {
+       vik_viewport_draw_rectangle ( dp->vp, dp->vtl->waypoint_bg_gc, TRUE, label_x - 1, label_y-1,width+2,height+2);
+      }
       vik_viewport_draw_layout ( dp->vp, dp->vtl->waypoint_text_gc, label_x, label_y, dp->vtl->wplabellayout );
     }
   }
 }
 
-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 );
@@ -1308,16 +1510,16 @@ static void trw_layer_new_track_gcs ( VikTrwLayer *vtl, VikViewport *vp )
   gc[9] = vik_viewport_new_gc ( vp, "#96059f", width );
   gc[10] = vik_viewport_new_gc ( vp, "#f22ef2", width );
 
-  gc[11] = vik_viewport_new_gc ( vp, "#ff0000", width ); /* above range */
+  gc[11] = vik_viewport_new_gc ( vp, "#874200", width ); /* above range */
 
   gc[12] = vik_viewport_new_gc ( vp, "#000000", width ); /* black / no speed data */
 
   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 );
   PangoFontDescription *pfd;
   rv->wplabellayout = gtk_widget_create_pango_layout (GTK_WIDGET(vp), NULL);
   pfd = pango_font_description_from_string (WAYPOINT_FONT);
@@ -1348,14 +1550,14 @@ VikTrwLayer *vik_trw_layer_create ( VikViewport *vp )
   return rv;
 }
 
-static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pass_along[4] )
+static void trw_layer_realize_track ( gchar *name, 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 );
 #else
-  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, (gint) pass_along[4], NULL, TRUE, TRUE );
+  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 );
 #endif
 
   *new_iter = *((GtkTreeIter *) pass_along[1]);
@@ -1365,13 +1567,13 @@ static void trw_layer_realize_track ( gchar *name, VikTrack *track, gpointer pas
     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[4] )
+static void trw_layer_realize_waypoint ( gchar *name, 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 );
 #else
-  vik_treeview_add_sublayer ( (VikTreeview *) pass_along[3], (GtkTreeIter *) pass_along[0], (GtkTreeIter *) pass_along[1], name, pass_along[2], name, (gint) pass_along[4], NULL, TRUE, TRUE );
+  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 );
 #endif
 
   *new_iter = *((GtkTreeIter *) pass_along[1]);
@@ -1382,7 +1584,7 @@ static void trw_layer_realize_waypoint ( gchar *name, VikWaypoint *wp, gpointer
 }
 
 
-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 };
@@ -1413,7 +1615,7 @@ void vik_trw_layer_realize ( VikTrwLayer *vtl, VikTreeview *vt, GtkTreeIter *lay
 
 }
 
-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 )
   {
@@ -1439,6 +1641,357 @@ 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;
+  time_t  start_time;
+  time_t  end_time;
+  gint    duration;
+} tooltip_tracks;
+
+/*
+ * Build up layer multiple track information via updating the tooltip_tracks structure
+ */
+static void trw_layer_tracks_tooltip ( const gchar *name, VikTrack *tr, tooltip_tracks *tt )
+{
+  tt->length = tt->length + vik_track_get_length (tr);
+
+  // Ensure times are available
+  if ( tr->trackpoints &&
+       VIK_TRACKPOINT(tr->trackpoints->data)->has_timestamp &&
+       VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->has_timestamp ) {
+
+    time_t t1, t2;
+    t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
+    t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
+
+    // Assume never actually have a track with a time of 0 (1st Jan 1970)
+    // Hence initialize to the first 'proper' value
+    if ( tt->start_time == 0 )
+       tt->start_time = t1;
+    if ( tt->end_time == 0 )
+       tt->end_time = t2;
+
+    // Update find the earliest / last times
+    if ( t1 < tt->start_time )
+       tt->start_time = t1;
+    if ( t2 > tt->end_time )
+       tt->end_time = t2;
+
+    // Keep track of total time
+    //  there maybe gaps within a track (eg segments)
+    //  but this should be generally good enough for a simple indicator
+    tt->duration = tt->duration + (int)(t2-t1);
+  }
+}
+
+/*
+ * Generate tooltip text for the layer.
+ * This is relatively complicated as it considers information for
+ *   no tracks, a single track or multiple tracks
+ *     (which may or may not have timing information)
+ */
+static const gchar* trw_layer_layer_tooltip ( VikTrwLayer *vtl )
+{
+  gchar tbuf1[32];
+  gchar tbuf2[64];
+  gchar tbuf3[64];
+  gchar tbuf4[10];
+  tbuf1[0] = '\0';
+  tbuf2[0] = '\0';
+  tbuf3[0] = '\0';
+  tbuf4[0] = '\0';
+
+  static gchar tmp_buf[128];
+  tmp_buf[0] = '\0';
+
+  // For compact date format I'm using '%x'     [The preferred date representation for the current locale without the time.]
+
+  // Safety check - I think these should always be valid
+  if ( vtl->tracks && vtl->waypoints ) {
+    tooltip_tracks tt = { 0.0, 0, 0 };
+    g_hash_table_foreach ( vtl->tracks, (GHFunc) trw_layer_tracks_tooltip, &tt );
+
+    GDate* gdate_start = g_date_new ();
+    g_date_set_time_t (gdate_start, tt.start_time);
+
+    GDate* gdate_end = g_date_new ();
+    g_date_set_time_t (gdate_end, tt.end_time);
+
+    if ( g_date_compare (gdate_start, gdate_end) ) {
+      // Dates differ so print range on separate line
+      g_date_strftime (tbuf1, sizeof(tbuf1), "%x", gdate_start);
+      g_date_strftime (tbuf2, sizeof(tbuf2), "%x", gdate_end);
+      g_snprintf (tbuf3, sizeof(tbuf3), "%s to %s\n", tbuf1, tbuf2);
+    }
+    else {
+      // Same date so just show it and keep rest of text on the same line - provided it's a valid time!
+      if ( tt.start_time != 0 )
+       g_date_strftime (tbuf3, sizeof(tbuf3), "%x: ", gdate_start);
+    }
+
+    tbuf2[0] = '\0';
+    if ( tt.length > 0.0 ) {
+      gdouble len_in_units;
+
+      // Setup info dependent on distance units
+      if ( a_vik_get_units_distance() == VIK_UNITS_DISTANCE_MILES ) {
+       g_snprintf (tbuf4, sizeof(tbuf4), "miles");
+       len_in_units = VIK_METERS_TO_MILES(tt.length);
+      }
+      else {
+       g_snprintf (tbuf4, sizeof(tbuf4), "kms");
+       len_in_units = tt.length/1000.0;
+      }
+
+      // Timing information if available
+      tbuf1[0] = '\0';
+      if ( tt.duration > 0 ) {
+       g_snprintf (tbuf1, sizeof(tbuf1),
+                   _(" in %d:%02d hrs:mins"),
+                   (int)round(tt.duration/3600), (int)round((tt.duration/60)%60));
+      }
+      g_snprintf (tbuf2, sizeof(tbuf2),
+                 _("\n%sTotal Length %.1f %s%s"),
+                 tbuf3, len_in_units, tbuf4, tbuf1);
+    }
+
+    // Put together all the elements to form compact tooltip text
+    g_snprintf (tmp_buf, sizeof(tmp_buf),
+               _("Tracks: %d - Waypoints: %d%s"),
+               g_hash_table_size (vtl->tracks), g_hash_table_size (vtl->waypoints), tbuf2);
+
+    g_date_free (gdate_start);
+    g_date_free (gdate_end);
+
+  }
+
+  return tmp_buf;
+}
+
+static const gchar* trw_layer_sublayer_tooltip ( VikTrwLayer *l, gint subtype, gpointer sublayer )
+{
+  switch ( subtype )
+  {
+    case VIK_TRW_LAYER_SUBLAYER_TRACKS: return NULL;
+    case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS: return NULL;
+    case VIK_TRW_LAYER_SUBLAYER_TRACK:
+    {
+      VikTrack *tr = g_hash_table_lookup ( l->tracks, sublayer );
+      if ( tr ) {
+       // Could be a better way of handling strings - but this works...
+       gchar time_buf1[20];
+       gchar time_buf2[20];
+       time_buf1[0] = '\0';
+       time_buf2[0] = '\0';
+       static gchar tmp_buf[100];
+       // Compact info: Short date eg (11/20/99), duration and length
+       // Hopefully these are the things that are most useful and so promoted into the tooltip
+       if ( tr->trackpoints && VIK_TRACKPOINT(tr->trackpoints->data)->has_timestamp ) {
+         // %x     The preferred date representation for the current locale without the time.
+         strftime (time_buf1, sizeof(time_buf1), "%x: ", gmtime(&(VIK_TRACKPOINT(tr->trackpoints->data)->timestamp)));
+         if ( VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->has_timestamp ) {
+           gint dur = ( (VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp) - (VIK_TRACKPOINT(tr->trackpoints->data)->timestamp) );
+           if ( dur > 0 )
+             g_snprintf ( time_buf2, sizeof(time_buf2), _("- %d:%02d hrs:mins"), (int)round(dur/3600), (int)round((dur/60)%60) );
+         }
+       }
+       // Get length and consider the appropriate distance units
+       gdouble tr_len = vik_track_get_length(tr);
+       vik_units_distance_t dist_units = a_vik_get_units_distance ();
+       switch (dist_units) {
+       case VIK_UNITS_DISTANCE_KILOMETRES:
+         g_snprintf (tmp_buf, sizeof(tmp_buf), _("%s%.1f km %s"), time_buf1, tr_len/1000.0, time_buf2);
+         break;
+       case VIK_UNITS_DISTANCE_MILES:
+         g_snprintf (tmp_buf, sizeof(tmp_buf), _("%s%.1f miles %s"), time_buf1, VIK_METERS_TO_MILES(tr_len), time_buf2);
+         break;
+       default:
+         break;
+       }
+       return tmp_buf;
+      }
+    }
+    break;
+    case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
+    {
+      VikWaypoint *w = g_hash_table_lookup ( l->waypoints, sublayer );
+      // NB It's OK to return NULL
+      return w->comment;
+    }
+    break;
+    default: break;
+  }
+  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_name ) {
+    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
+ */
+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;
+  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:
+      {
+       vik_window_set_selected_trw_layer ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l );
+       /* Mark for redraw */
+       return TRUE;
+      }
+      break;
+
+    case VIK_TREEVIEW_TYPE_SUBLAYER:
+      {
+       switch ( subtype )
+         {
+         case VIK_TRW_LAYER_SUBLAYER_TRACKS:
+           {
+             vik_window_set_selected_tracks ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->tracks, l );
+             /* Mark for redraw */
+             return TRUE;
+           }
+           break;
+         case VIK_TRW_LAYER_SUBLAYER_TRACK:
+           {
+             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;
+           }
+           break;
+         case VIK_TRW_LAYER_SUBLAYER_WAYPOINTS:
+           {
+             vik_window_set_selected_waypoints ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l), l->waypoints, l );
+             /* Mark for redraw */
+             return TRUE;
+           }
+           break;
+         case VIK_TRW_LAYER_SUBLAYER_WAYPOINT:
+           {
+             VikWaypoint *wpt = g_hash_table_lookup ( l->waypoints, sublayer );
+             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:
+           {
+             return vik_window_clear_highlight ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l) );
+           }
+           break;
+         }
+       return FALSE;
+      }
+      break;
+
+    default:
+      return vik_window_clear_highlight ( (VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(l) );
+      break;
+    }
+}
+
 GHashTable *vik_trw_layer_get_tracks ( VikTrwLayer *l )
 {
   return l->tracks;
@@ -1535,23 +2088,94 @@ static void trw_layer_centerize ( gpointer layer_and_vlp[2] )
 {
   VikCoord coord;
   if ( vik_trw_layer_find_center ( VIK_TRW_LAYER(layer_and_vlp[0]), &coord ) )
-    goto_coord ( VIK_LAYERS_PANEL(layer_and_vlp[1]), &coord );
+    goto_coord ( layer_and_vlp[1], NULL, NULL, &coord );
+  else
+    a_dialog_info_msg ( VIK_GTK_WINDOW_FROM_LAYER(layer_and_vlp[0]), _("This layer has no waypoints or trackpoints.") );
+}
+
+static void trw_layer_zoom_to_show_latlons ( VikTrwLayer *vtl, VikViewport *vvp, struct LatLon maxmin[2] )
+{
+  /* First set the center [in case previously viewing from elsewhere] */
+  /* Then loop through zoom levels until provided positions are in view */
+  /* This method is not particularly fast - but should work well enough */
+  struct LatLon average = { (maxmin[0].lat+maxmin[1].lat)/2, (maxmin[0].lon+maxmin[1].lon)/2 };
+  VikCoord coord;
+  vik_coord_load_from_latlon ( &coord, vtl->coord_mode, &average );
+  vik_viewport_set_center_coord ( vvp, &coord );
+
+  /* Convert into definite 'smallest' and 'largest' positions */
+  struct LatLon minmin;
+  if ( maxmin[0].lat < maxmin[1].lat )
+    minmin.lat = maxmin[0].lat;
+  else
+    minmin.lat = maxmin[1].lat;
+
+  struct LatLon maxmax;
+  if ( maxmin[0].lon > maxmin[1].lon )
+    maxmax.lon = maxmin[0].lon;
+  else
+    maxmax.lon = maxmin[1].lon;
+
+  /* Never zoom in too far - generally not that useful, as too close ! */
+  /* Always recalculate the 'best' zoom level */
+  gdouble zoom = 1.0;
+  vik_viewport_set_zoom ( vvp, zoom );
+
+  gdouble min_lat, max_lat, min_lon, max_lon;
+  /* Should only be a maximum of about 18 iterations from min to max zoom levels */
+  while ( zoom <= VIK_VIEWPORT_MAX_ZOOM ) {
+    vik_viewport_get_min_max_lat_lon ( vvp, &min_lat, &max_lat, &min_lon, &max_lon );
+    /* NB I think the logic used in this test to determine if the bounds is within view
+       fails if track goes across 180 degrees longitude.
+       Hopefully that situation is not too common...
+       Mind you viking doesn't really do edge locations to well anyway */
+    if ( min_lat < minmin.lat &&
+        max_lat > minmin.lat &&
+        min_lon < maxmax.lon &&
+        max_lon > maxmax.lon )
+      /* Found within zoom level */
+      break;
+
+    /* Try next */
+    zoom = zoom * 2;
+    vik_viewport_set_zoom ( vvp, zoom );
+  }
+}
+
+gboolean vik_trw_layer_auto_set_view ( VikTrwLayer *vtl, VikViewport *vvp )
+{
+  /* TODO: what if there's only one waypoint @ 0,0, it will think nothing found. */
+  struct LatLon maxmin[2] = { {0.0,0.0}, {0.0,0.0} };
+  trw_layer_find_maxmin (vtl, maxmin);
+  if (maxmin[0].lat == 0.0 && maxmin[0].lon == 0.0 && maxmin[1].lat == 0.0 && maxmin[1].lon == 0.0)
+    return FALSE;
+  else {
+    trw_layer_zoom_to_show_latlons ( vtl, vvp, maxmin );
+    return TRUE;
+  }
+}
+
+static void trw_layer_auto_view ( gpointer layer_and_vlp[2] )
+{
+  if ( vik_trw_layer_auto_set_view ( VIK_TRW_LAYER(layer_and_vlp[0]), vik_layers_panel_get_viewport (VIK_LAYERS_PANEL(layer_and_vlp[1])) ) ) {
+    vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(layer_and_vlp[1]) );
+  }
   else
     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], guint file_type )
+static void trw_layer_export ( gpointer layer_and_vlp[2], const gchar *title, const gchar* default_name, const gchar* trackname, guint file_type )
 {
   GtkWidget *file_selector;
   const gchar *fn;
   gboolean failed = FALSE;
-  file_selector = gtk_file_chooser_dialog_new (_("Export Layer"),
-                                     NULL,
-                                     GTK_FILE_CHOOSER_ACTION_SAVE,
-                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
-                                     NULL);
-  gtk_file_chooser_set_filename (GTK_FILE_CHOOSER(file_selector), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])));
+  file_selector = gtk_file_chooser_dialog_new (title,
+                                              NULL,
+                                              GTK_FILE_CHOOSER_ACTION_SAVE,
+                                              GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                              GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                              NULL);
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER(file_selector), default_name);
 
   while ( gtk_dialog_run ( GTK_DIALOG(file_selector) ) == GTK_RESPONSE_ACCEPT )
   {
@@ -1559,15 +2183,15 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type )
     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 );
+      failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trackname);
       break;
     }
     else
     {
-      if ( a_dialog_overwrite ( GTK_WINDOW(file_selector), _("The file \"%s\" exists, do you wish to overwrite it?"), a_file_basename ( fn ) ) )
+      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 );
+       failed = ! a_file_export ( VIK_TRW_LAYER(layer_and_vlp[0]), fn, file_type, trackname);
         break;
       }
     }
@@ -1579,23 +2203,58 @@ static void trw_layer_export ( gpointer layer_and_vlp[2], guint file_type )
 
 static void trw_layer_export_gpspoint ( gpointer layer_and_vlp[2] )
 {
-  trw_layer_export ( layer_and_vlp, FILE_TYPE_GPSPOINT );
+  trw_layer_export ( layer_and_vlp, _("Export Layer"), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])), NULL, FILE_TYPE_GPSPOINT );
 }
 
 static void trw_layer_export_gpsmapper ( gpointer layer_and_vlp[2] )
 {
-  trw_layer_export ( layer_and_vlp, FILE_TYPE_GPSMAPPER );
+  trw_layer_export ( layer_and_vlp, _("Export Layer"), vik_layer_get_name(VIK_LAYER(layer_and_vlp[0])), NULL, FILE_TYPE_GPSMAPPER );
 }
 
 static void trw_layer_export_gpx ( gpointer layer_and_vlp[2] )
 {
-  trw_layer_export ( layer_and_vlp, 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] )
+{
+  /* Auto append '.kml' to the 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, ".kml" ) )
+    auto_save_name = g_strconcat ( auto_save_name, ".kml", NULL );
+
+  trw_layer_export ( layer_and_vlp, _("Export Layer"), auto_save_name, NULL, FILE_TYPE_KML );
+
+  g_free ( auto_save_name );
+}
+
+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];
+
+  /* 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] );
+  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 );
+
+  g_free ( auto_save_name );
 }
 
 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 (_("Create"),
+  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,
                                                  GTK_STOCK_CANCEL,
@@ -1613,6 +2272,8 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
   gtk_widget_show_all ( label );
   gtk_widget_show_all ( entry );
 
+  gtk_dialog_set_default_response ( GTK_DIALOG(dia), GTK_RESPONSE_ACCEPT );
+
   while ( gtk_dialog_run ( GTK_DIALOG(dia) ) == GTK_RESPONSE_ACCEPT )
   {
     VikWaypoint *wp;
@@ -1630,7 +2291,7 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
     {
       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 ) );
+      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 );
       break;
     }
 
@@ -1642,16 +2303,25 @@ static void trw_layer_goto_wp ( gpointer layer_and_vlp[2] )
 
 gboolean vik_trw_layer_new_waypoint ( VikTrwLayer *vtl, GtkWindow *w, const VikCoord *def_coord )
 {
-  gchar *name = highest_wp_number_get(vtl);
+  gchar *default_name = highest_wp_number_get(vtl);
   VikWaypoint *wp = vik_waypoint_new();
+  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 ( a_dialog_new_waypoint ( w, &name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode ) )
+  if ( ( returned_name = a_dialog_waypoint ( w, default_name, wp, vik_trw_layer_get_waypoints ( vtl ), vtl->coord_mode, TRUE, &updated ) ) )
   {
     wp->visible = TRUE;
-    vik_trw_layer_add_waypoint ( vtl, name, wp );
+    vik_trw_layer_add_waypoint ( vtl, returned_name, wp );
+    g_free (default_name);
     return TRUE;
   }
+  g_free (default_name);
   vik_waypoint_free(wp);
   return FALSE;
 }
@@ -1699,99 +2369,369 @@ 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 );
 }
 
-void vik_trw_layer_add_menu_items ( VikTrwLayer *vtl, GtkMenu *menu, gpointer vlp )
+static void trw_layer_geotagging_waypoint_mtime_update ( gpointer pass_along[6] )
 {
-  static gpointer pass_along[2];
-  GtkWidget *item;
-  GtkWidget *export_submenu;
-  GtkWidget *wikipedia_submenu;
-  pass_along[0] = vtl;
-  pass_along[1] = vlp;
-
-  item = gtk_menu_item_new();
-  gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-  gtk_widget_show ( item );
+  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 );
+}
 
-  item = gtk_menu_item_new_with_label ( _("Goto Center of Layer") );
-  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 );
+/*
+ * Use code in separate file for this feature as reasonably complex
+ */
+static void trw_layer_geotagging_track ( 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] );
+  // Unset so can be reverified later if necessary
+  vtl->has_verified_thumbnails = FALSE;
 
-  item = gtk_menu_item_new_with_label ( _("Goto Waypoint") );
-  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 );
+  trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           vtl,
+                           track,
+                           pass_along[3] );
+}
 
-  export_submenu = gtk_menu_new ();
-  item = gtk_menu_item_new_with_label ( _("Export layer") );
-  gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-  gtk_widget_show ( item );
-  gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), export_submenu );
-  
-  item = gtk_menu_item_new_with_label ( _("Export as GPSPoint") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpspoint), pass_along );
-  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
-  gtk_widget_show ( item );
+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;
 
-  item = gtk_menu_item_new_with_label ( _("Export as GPSMapper") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpsmapper), pass_along );
-  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
-  gtk_widget_show ( item );
+  trw_layer_geotag_dialog ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           vtl,
+                           NULL,
+                           NULL);
+}
+#endif
 
-  item = gtk_menu_item_new_with_label ( _("Export as GPX") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx), pass_along );
-  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
-  gtk_widget_show ( item );
+// 'Acquires' - Same as in File Menu -> Acquire - applies into the selected TRW Layer //
 
-  item = gtk_menu_item_new_with_label ( _("New Waypoint") );
-  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 );
+/*
+ * 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] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
+
+  /* Only 1 waypoint - jump straight to it */
+  if ( g_hash_table_size (vtl->waypoints) == 1 ) {
+    VikViewport *vvp = vik_layers_panel_get_viewport (vlp);
+    g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_single_waypoint_jump, (gpointer) vvp );
+  }
+  /* If at least 2 waypoints - find center and then zoom to fit */
+  else if ( g_hash_table_size (vtl->waypoints) > 1 )
+  {
+    struct LatLon maxmin[2] = { {0,0}, {0,0} };
+    g_hash_table_foreach ( vtl->waypoints, (GHFunc) trw_layer_find_maxmin_waypoints, 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_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;
+
+  item = gtk_menu_item_new();
+  gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+  gtk_widget_show ( item );
+
+  /* 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 );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("View All Trac_ks") );
+  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 ( _("V_iew All Waypoints") );
+  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_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 );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("Goto _Waypoint...") );
+  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 );
+
+  export_submenu = gtk_menu_new ();
+  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 );
+  
+  item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Point...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpspoint), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("Export as GPS_Mapper...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpsmapper), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("Export as _GPX...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_gpx), pass_along );
+  gtk_menu_shell_append (GTK_MENU_SHELL (export_submenu), item);
+  gtk_widget_show ( item );
+
+  item = gtk_menu_item_new_with_mnemonic ( _("Export as _KML...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_export_kml), 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_label ( _("Add Wikipedia Waypoints") );
+  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_label ( _("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_label ( _("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_label ( _("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_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_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_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_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_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 );
+  
   item = a_acquire_trwlayer_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vlp,
-       vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
+                                  vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
   if ( item ) {
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
   }  
 
   item = a_acquire_trwlayer_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), vlp,
-       vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
+                                        vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)), vtl );
   if ( item ) {
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
     gtk_widget_show ( item );
@@ -1808,18 +2748,17 @@ void vik_trw_layer_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypoint *wp
     else
     {
       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 );
 #else
       vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->waypoints_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_WAYPOINT, NULL, TRUE, TRUE );
 #endif
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, 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, name, iter );
-      wp->visible = TRUE;
     }
   }
-  else
-    wp->visible = TRUE;
 
   highest_wp_number_add_wp(vtl, name);
   g_hash_table_insert ( vtl->waypoints, name, wp );
@@ -1836,18 +2775,17 @@ void vik_trw_layer_add_track ( VikTrwLayer *vtl, gchar *name, VikTrack *t )
     else
     {
       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, t->visible, TRUE );
+      vik_treeview_add_sublayer_alphabetized ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, 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, t->visible, TRUE );
+      vik_treeview_add_sublayer ( VIK_LAYER(vtl)->vt, &(vtl->tracks_iter), iter, name, vtl, name, VIK_TRW_LAYER_SUBLAYER_TRACK, NULL, TRUE, TRUE );
 #endif
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, 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, name, iter );
-      /* t->visible = TRUE; */
     }
   }
-  else
-    ; /* t->visible = TRUE; // this is now used by file input functions */
 
   g_hash_table_insert ( vtl->tracks, name, t );
  
@@ -1884,20 +2822,20 @@ void vik_trw_layer_filein_add_waypoint ( VikTrwLayer *vtl, gchar *name, VikWaypo
 }
 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 ) {
+    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);
+      if ( vtl->route_finder_added_track_name ) /* for google routes */
+        g_free ( vtl->route_finder_added_track_name );
+      vtl->route_finder_added_track_name = g_strdup(new_name);
     }
   }
 }
@@ -1957,7 +2895,6 @@ static void trw_layer_drag_drop_request ( VikTrwLayer *vtl_src, VikTrwLayer *vtl
   }
 }
 
-
 gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, const gchar *trk_name )
 {
   VikTrack *t = g_hash_table_lookup ( vtl->tracks, trk_name );
@@ -1966,10 +2903,11 @@ gboolean vik_trw_layer_delete_track ( VikTrwLayer *vtl, const gchar *trk_name )
   {
     GtkTreeIter *it;
     was_visible = t->visible;
-    if ( t == vtl->current_track )
+    if ( t == vtl->current_track ) {
       vtl->current_track = NULL;
-    if ( t == vtl->magic_scissors_current_track )
-      vtl->magic_scissors_current_track = NULL;
+    }
+    if ( t == vtl->route_finder_current_track )
+      vtl->route_finder_current_track = NULL;
 
     /* could be current_tp, so we have to check */
     trw_layer_cancel_tps_of_track ( vtl, trk_name );
@@ -2020,7 +2958,7 @@ void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
 {
 
   vtl->current_track = NULL;
-  vtl->magic_scissors_current_track = NULL;
+  vtl->route_finder_current_track = NULL;
   if (vtl->current_tp_track_name)
     trw_layer_cancel_current_tp(vtl, FALSE);
   if (vtl->last_tp_track_name)
@@ -2030,8 +2968,7 @@ void vik_trw_layer_delete_all_tracks ( VikTrwLayer *vtl )
   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 )
@@ -2046,28 +2983,60 @@ 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] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  // Get confirmation from the user
+  if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           _("Are you sure you want to delete all tracks in %s?"),
+                           vik_layer_get_name ( VIK_LAYER(vtl) ) ) )
+    vik_trw_layer_delete_all_tracks (vtl);
 }
 
-static void trw_layer_delete_item ( gpointer pass_along[5] )
+static void trw_layer_delete_all_waypoints ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  // Get confirmation from the user
+  if ( a_dialog_yes_or_no ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           _("Are you sure you want to delete all waypoints in %s?"),
+                           vik_layer_get_name ( VIK_LAYER(vtl) ) ) )
+    vik_trw_layer_delete_all_waypoints (vtl);
+}
+
+static void trw_layer_delete_item ( gpointer pass_along[6] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   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] );
   }
   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),
+                                 _("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] );
   }
   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[5] )
+static void trw_layer_properties_item ( gpointer pass_along[6] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
   if ( GPOINTER_TO_INT (pass_along[2]) == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
@@ -2075,10 +3044,11 @@ static void trw_layer_properties_item ( gpointer pass_along[5] )
     VikWaypoint *wp = g_hash_table_lookup ( vtl->waypoints, pass_along[3] );
     if ( wp )
     {
-      if ( a_dialog_new_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), NULL, wp, NULL, vtl->coord_mode ) )
+      gboolean updated = FALSE;
+      a_dialog_waypoint ( VIK_GTK_WINDOW_FROM_LAYER(vtl), pass_along[3], wp, NULL, vtl->coord_mode, FALSE, &updated );
 
-      if ( VIK_LAYER(vtl)->visible )
-        vik_layer_emit_update ( VIK_LAYER(vtl) );
+      if ( updated && VIK_LAYER(vtl)->visible )
+       vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
     }
   }
   else
@@ -2087,27 +3057,42 @@ static void trw_layer_properties_item ( gpointer pass_along[5] )
     if ( tr )
     {
       vik_trw_layer_propwin_run ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
-                     vtl, tr,
-                     pass_along[1], /* vlp */ 
-                     pass_along[3]  /* track name */);
+                                 vtl, tr,
+                                 pass_along[1], /* vlp */
+                                 pass_along[3],  /* track name */
+                                 pass_along[5] );  /* vvp */
     }
   }
 }
 
-static void goto_coord ( VikLayersPanel *vlp, const VikCoord *coord )
-{
-  vik_viewport_set_center_coord ( vik_layers_panel_get_viewport(vlp), coord );
-  vik_layers_panel_emit_update ( vlp );
+/*
+   Parameter 1 -> VikLayersPanel
+   Parameter 2 -> VikLayer
+   Parameter 3 -> VikViewport
+*/
+static void goto_coord ( gpointer *vlp, gpointer vl, gpointer vvp, const VikCoord *coord )
+{
+  if ( vlp ) {
+    vik_viewport_set_center_coord ( vik_layers_panel_get_viewport (VIK_LAYERS_PANEL(vlp)), coord );
+    vik_layers_panel_emit_update ( VIK_LAYERS_PANEL(vlp) );
+  }
+  else {
+    /* 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), FALSE );
+    }
+  }
 }
 
-static void trw_layer_goto_track_startpoint ( gpointer pass_along[5] )
+static void trw_layer_goto_track_startpoint ( gpointer pass_along[6] )
 {
   GList *trps = ((VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ))->trackpoints;
   if ( trps && trps->data )
-    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *) trps->data)->coord));
+    goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) trps->data)->coord));
 }
 
-static void trw_layer_goto_track_center ( gpointer pass_along[5] )
+static void trw_layer_goto_track_center ( gpointer pass_along[6] )
 {
   /* FIXME: get this into viktrack.c, and should be ->trackpoints right? */
   GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
@@ -2119,7 +3104,7 @@ static void trw_layer_goto_track_center ( gpointer pass_along[5] )
     average.lat = (maxmin[0].lat+maxmin[1].lat)/2;
     average.lon = (maxmin[0].lon+maxmin[1].lon)/2;
     vik_coord_load_from_latlon ( &coord, VIK_TRW_LAYER(pass_along[0])->coord_mode, &average );
-    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &coord);
+    goto_coord ( pass_along[1], pass_along[0], pass_along[5], &coord);
   }
 }
 
@@ -2132,24 +3117,25 @@ static void trw_layer_extend_track_end ( gpointer pass_along[6] )
   vik_window_enable_layer_tool ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vtl)), VIK_LAYER_TRW, TOOL_CREATE_TRACK);
 
   if ( track->trackpoints )
-    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) );
+    goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *)g_list_last(track->trackpoints)->data)->coord) );
 }
 
 /**
- * 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->route_finder_coord =  last_coord;
+  vtl->route_finder_current_track = track;
+  vtl->route_finder_started = TRUE;
 
   if ( track->trackpoints )
-    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &last_coord) ;
+    goto_coord ( pass_along[1], pass_along[0], pass_along[5], &last_coord) ;
 
 }
 
@@ -2168,25 +3154,73 @@ static void trw_layer_goto_track_endpoint ( gpointer pass_along[6] )
   if ( !trps )
     return;
   trps = g_list_last(trps);
-  goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(((VikTrackpoint *) trps->data)->coord));
+  goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(((VikTrackpoint *) trps->data)->coord));
+}
+
+static void trw_layer_goto_track_max_speed ( gpointer pass_along[6] )
+{
+  VikTrackpoint* vtp = vik_track_get_tp_by_max_speed ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+  if ( !vtp )
+    return;
+  goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
 }
 
+static void trw_layer_goto_track_max_alt ( gpointer pass_along[6] )
+{
+  VikTrackpoint* vtp = vik_track_get_tp_by_max_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+  if ( !vtp )
+    return;
+  goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(vtp->coord));
+}
+
+static void trw_layer_goto_track_min_alt ( gpointer pass_along[6] )
+{
+  VikTrackpoint* vtp = vik_track_get_tp_by_min_alt ( g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] ) );
+  if ( !vtp )
+    return;
+  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] )
+{
+  GList **trps = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
+  if ( trps && *trps )
+  {
+    struct LatLon maxmin[2] = { {0,0}, {0,0} };
+    trw_layer_find_maxmin_tracks ( NULL, trps, maxmin );
+    trw_layer_zoom_to_show_latlons ( VIK_TRW_LAYER(pass_along[0]), pass_along[5], maxmin );
+    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]), FALSE );
+  }
+}
+
+static void trw_layer_edit_trackpoint ( gpointer pass_along[6] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(pass_along[0]);
+  trw_layer_tpwin_init ( vtl );
+}
 
 /*************************************
  * merge/split by time routines 
  *************************************/
 
 /* 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;
@@ -2199,11 +3233,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);
@@ -2256,6 +3296,7 @@ static void find_nearby_track(gpointer key, gpointer value, gpointer user_data)
 }
 
 /* comparison function used to sort tracks; a and b are hash table keys */
+/* Not actively used - can be restored if needed
 static gint track_compare(gconstpointer a, gconstpointer b, gpointer user_data)
 {
   GHashTable *tracks = user_data;
@@ -2268,6 +3309,7 @@ static gint track_compare(gconstpointer a, gconstpointer b, gpointer user_data)
   if (t1 > t2) return 1;
   return 0;
 }
+*/
 
 /* comparison function used to sort trackpoints */
 static gint trackpoint_compare(gconstpointer a, gconstpointer b)
@@ -2279,37 +3321,64 @@ 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
+ */
+static gint sort_alphabetically (gconstpointer a, gconstpointer b, gpointer user_data)
+{
+  const gchar* namea = (const gchar*) a;
+  const gchar* nameb = (const gchar*) b;
+  if ( namea == NULL || nameb == NULL)
+    return 0;
+  else
+    // 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;
+  GList *other_tracks = NULL;
   VikTrack *track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
 
-  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
+  other_tracks = g_list_sort_with_data (other_tracks, sort_alphabetically, NULL);
+#endif
+
   GList *merge_list = a_dialog_select_from_list(VIK_GTK_WINDOW_FROM_LAYER(vtl),
-      vtl->tracks, tracks_with_timestamp, TRUE,
+      other_tracks, TRUE,
       _("Merge with..."), _("Select track to merge with"));
-  g_list_free(tracks_with_timestamp);
+  g_list_free(other_tracks);
 
   if (merge_list)
   {
@@ -2327,7 +3396,7 @@ 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 );
   }
 }
 
@@ -2337,13 +3406,36 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
   VikTrwLayer *vtl = (VikTrwLayer *)pass_along[0];
   gchar *orig_track_name = strdup(pass_along[3]);
 
-  time_t t1, t2;
+  //time_t t1, t2;
   GList *nearby_tracks;
   VikTrack *track;
   GList *trps;
   static  guint thr = 1;
   guint track_count = 0;
 
+  GList *tracks_with_timestamp = NULL;
+  track = (VikTrack *) g_hash_table_lookup ( vtl->tracks, orig_track_name );
+  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"));
+    free(orig_track_name);
+    return;
+  }
+
+  twt_udata udata;
+  udata.result = &tracks_with_timestamp;
+  udata.exclude = track->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"));
+    free(orig_track_name);
+    return;
+  }
+  g_list_free(tracks_with_timestamp);
+
   if (!a_dialog_time_threshold(VIK_GTK_WINDOW_FROM_LAYER(vtl), 
                               _("Merge Threshold..."), 
                               _("Merge when time between tracks less than:"), 
@@ -2368,8 +3460,8 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
       nearby_tracks = NULL;
     }
 
-    t1 = ((VikTrackpoint *)trps->data)->timestamp;
-    t2 = ((VikTrackpoint *)g_list_last(trps)->data)->timestamp;
+    //t1 = ((VikTrackpoint *)trps->data)->timestamp;
+    //t2 = ((VikTrackpoint *)g_list_last(trps)->data)->timestamp;
     
     /*    g_print("Original track times: %d and %d\n", t1, t2);  */
     params[0] = &nearby_tracks;
@@ -2418,7 +3510,7 @@ static void trw_layer_merge_by_timestamp ( gpointer pass_along[6] )
   } while (track_count > 1);
   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 by time routine */
@@ -2456,7 +3548,7 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
     }
     if (ts - prev_ts > thr*60) {
       /* flush accumulated trackpoints into new list */
-      newlists = g_list_prepend(newlists, g_list_reverse(newtps));
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
       newtps = NULL;
     }
 
@@ -2466,50 +3558,229 @@ static void trw_layer_split_by_timestamp ( gpointer pass_along[6] )
     iter = g_list_next(iter);
   }
   if (newtps) {
-      newlists = g_list_prepend(newlists, g_list_reverse(newtps));
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
   }
 
   /* put lists of trackpoints into tracks */
   iter = newlists;
   i = 1;
-  while (iter) {
-    gchar *new_tr_name;
-    VikTrack *tr;
+  // Only bother updating if the split results in new tracks
+  if (g_list_length (newlists) > 1) {
+    while (iter) {
+      gchar *new_tr_name;
+      VikTrack *tr;
 
-    tr = vik_track_new();
-    tr->visible = track->visible;
-    tr->trackpoints = (GList *)(iter->data);
+      tr = vik_track_new();
+      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);
-    /*    g_print("adding track %s, times %d - %d\n", new_tr_name, VIK_TRACKPOINT(tr->trackpoints->data)->timestamp,
+      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);
+      /*    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]), FALSE);
+  }
+  g_list_free(newlists);
+}
+
+/**
+ * Split a track by the number of points as specified by the user
+ */
+static void trw_layer_split_by_n_points ( 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;
+
+  gint points = a_dialog_get_positive_number(VIK_GTK_WINDOW_FROM_LAYER(pass_along[0]),
+                                            _("Split Every Nth Point"),
+                                            _("Split on every Nth point:"),
+                                            250,   // Default value as per typical limited track capacity of various GPS devices
+                                            2,     // Min
+                                            65536, // Max
+                                            5);    // Step
+  // Was a valid number returned?
+  if (!points)
+    return;
+
+  // Now split...
+  GList *iter;
+  GList *newlists = NULL;
+  GList *newtps = NULL;
+  gint count = 0;
+  iter = trps;
+
+  while (iter) {
+    /* accumulate trackpoint copies in newtps, in reverse order */
+    newtps = g_list_prepend(newtps, vik_trackpoint_copy(VIK_TRACKPOINT(iter->data)));
+    count++;
+    if (count >= points) {
+      /* flush accumulated trackpoints into new list */
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
+      newtps = NULL;
+      count = 0;
+    }
     iter = g_list_next(iter);
   }
+
+  // If there is a remaining chunk put that into the new split list
+  // This may well be the whole track if no split points were encountered
+  if (newtps) {
+      newlists = g_list_append(newlists, g_list_reverse(newtps));
+  }
+
+  /* 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) {
+      gchar *new_tr_name;
+      VikTrack *tr;
+
+      tr = vik_track_new();
+      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);
+
+      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]), FALSE);
+  }
   g_list_free(newlists);
-  vik_trw_layer_delete_track(VIK_TRW_LAYER(pass_along[0]), (gchar *)pass_along[3]);
-  vik_layer_emit_update(VIK_LAYER(pass_along[0]));
 }
 
 /* end of split/merge routines */
 
+/**
+ * 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
+ */
+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
+  // Sort named list alphabetically
+  *list = g_list_insert_sorted_with_data (*list, key, sort_alphabetically, NULL);
+}
+
+/**
+ *
+ */
+static void trw_layer_delete_tracks_from_selection ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  GList *all = NULL;
+  // Sort list alphabetically for better presentation
+  g_hash_table_foreach(vtl->tracks, trw_layer_sorted_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)) {
+      vik_trw_layer_delete_track(vtl, l->data);
+    }
+    g_list_free(delete_list);
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+  }
+}
+
+/**
+ *
+ */
+static void trw_layer_delete_waypoints_from_selection ( gpointer lav[2] )
+{
+  VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
+  GList *all = NULL;
+
+  // Sort list alphabetically for better presentation
+  g_hash_table_foreach ( vtl->waypoints, trw_layer_sorted_name_list, &all);
+  if ( ! all ) {
+    a_dialog_error_msg (VIK_GTK_WINDOW_FROM_LAYER(vtl),        _("No waypoints found"));
+    return;
+  }
+
+  all = g_list_sort_with_data(all, sort_alphabetically, NULL);
+
+  // 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 waypoints to delete"));
+  g_list_free(all);
 
-static void trw_layer_goto_waypoint ( gpointer pass_along[5] )
+  // Delete requested waypoints
+  // 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_waypoint(vtl, l->data);
+    }
+    g_list_free(delete_list);
+    vik_layer_emit_update( VIK_LAYER(vtl), FALSE );
+  }
+
+}
+
+static void trw_layer_goto_waypoint ( gpointer pass_along[6] )
 {
   VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->waypoints, pass_along[3] );
   if ( wp )
-    goto_coord ( VIK_LAYERS_PANEL(pass_along[1]), &(wp->coord) );
+    goto_coord ( pass_along[1], pass_along[0], pass_along[5], &(wp->coord) );
 }
 
-static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[5] )
+static void trw_layer_waypoint_gc_webpage ( gpointer pass_along[6] )
 {
   gchar *webpage = g_strdup_printf("http://www.geocaching.com/seek/cache_details.aspx?wp=%s", (gchar *) pass_along[3] );
   open_url(VIK_GTK_WINDOW_FROM_LAYER(VIK_LAYER(pass_along[0])), webpage);
   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 )
   {
@@ -2609,7 +3880,7 @@ static gboolean is_valid_geocache_name ( gchar *str )
   return len >= 3 && len <= 7 && str[0] == 'G' && str[1] == 'C' && isalnum(str[2]) && (len < 4 || isalnum(str[3])) && (len < 5 || isalnum(str[4])) && (len < 6 || isalnum(str[5])) && (len < 7 || isalnum(str[6]));
 }
 
-static void trw_layer_track_use_with_filter ( gpointer *pass_along )
+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 );
@@ -2622,7 +3893,7 @@ static gboolean is_valid_google_route ( VikTrwLayer *vtl, const gchar *track_nam
   return ( tr && tr->comment && strlen(tr->comment) > 7 && !strncmp(tr->comment, "from:", 5) );
 }
 
-static void trw_layer_track_google_route_webpage( gpointer *pass_along )
+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 );
@@ -2635,11 +3906,11 @@ static void trw_layer_track_google_route_webpage( gpointer *pass_along )
   }
 }
 
-/* vlp can be NULL if necessary - i.e. right-click from a tool -- but be careful, some functions may try to use it */
-gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter )
+/* vlp can be NULL if necessary - i.e. right-click from a tool */
+/* viewpoint is now available instead */
+static gboolean trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu, gpointer vlp, gint subtype, gpointer sublayer, GtkTreeIter *iter, VikViewport *vvp )
 {
-  static GtkTreeIter staticiter;
-  static gpointer pass_along[5];
+  static gpointer pass_along[6];
   GtkWidget *item;
   gboolean rv = FALSE;
 
@@ -2647,8 +3918,8 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
   pass_along[1] = vlp;
   pass_along[2] = GINT_TO_POINTER (subtype);
   pass_along[3] = sublayer;
-  staticiter = *iter; /* will exist after function has ended */
-  pass_along[4] = &staticiter;
+  pass_along[4] = GINT_TO_POINTER (1); // Confirm delete request
+  pass_along[5] = vvp;
 
   if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT || subtype == VIK_TRW_LAYER_SUBLAYER_TRACK )
   {
@@ -2683,9 +3954,18 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
     if ( subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT )
     {
+      gboolean separator_created = FALSE;
+
       /* could be a right-click using the tool */
       if ( vlp != NULL ) {
-        item = gtk_menu_item_new_with_label ( _("Goto") );
+       item = gtk_menu_item_new ();
+       gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+       gtk_widget_show ( item );
+
+       separator_created = TRUE;
+
+        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 );
@@ -2693,116 +3973,350 @@ gboolean vik_trw_layer_sublayer_add_menu_items ( VikTrwLayer *l, GtkMenu *menu,
 
       if ( is_valid_geocache_name ( (gchar *) sublayer ) )
       {
-        item = gtk_menu_item_new_with_label ( _("Visit Geocache Webpage") );
+       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 );
       }
 
+      VikWaypoint *wp = g_hash_table_lookup ( VIK_TRW_LAYER(l)->waypoints, sublayer );
+
+      if ( wp && wp->image )
+      {
+       if ( !separator_created ) {
+         item = gtk_menu_item_new ();
+         gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+         gtk_widget_show ( item );
+         separator_created = TRUE;
+       }
+
+       // Set up image paramater
+       pass_along[5] = wp->image;
+
+        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
+      }
+
     }
   }
 
+  if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
+  {
+    rv = TRUE;
+    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 );
+  }
+
+  if ( subtype == VIK_TRW_LAYER_SUBLAYER_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_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_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_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 );
+  }
+
+  if ( subtype == VIK_TRW_LAYER_SUBLAYER_TRACKS )
+  {
+    rv = TRUE;
+
+    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_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_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 );
+  }
+
   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_menu_item_new_with_label ( _("Goto Startpoint") );
+    goto_submenu = gtk_menu_new ();
+    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_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(menu), item );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Goto \"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(menu), item );
+    gtk_menu_shell_append ( GTK_MENU_SHELL(goto_submenu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Goto 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_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_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_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_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 );
 
-    item = gtk_menu_item_new_with_label ( _("Merge By Time") );
+    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_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Merge With Other Tracks...") );
+    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_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Split By Time") );
+    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_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Download maps along track...") );
-    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_download_map_along_track_cb), pass_along );
+    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(menu), item );
     gtk_widget_show ( item );
 
-    item = gtk_menu_item_new_with_label ( _("Apply DEM Data") );
+    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_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_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_label ( _("Extend track end") );
+    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_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_label ( _("Extend using magic scissors") );
-    g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_extend_track_end_ms), pass_along );
+    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 );
 
 #ifdef VIK_CONFIG_OPENSTREETMAP
-    item = gtk_menu_item_new_with_label ( _("Upload to OSM") );
+    item = gtk_image_menu_item_new_with_mnemonic ( _("Upload to _OSM...") );
     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 ) )
     {
-      item = gtk_menu_item_new_with_label ( _("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_label ( _("Use with filter") );
-    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 );
+    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 );
+
+    /* ATM This function is only available via the layers panel, due to needing a vlp */
+    if ( vlp ) {
+      item = a_acquire_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), vlp,
+                                   vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)),
+                                   g_hash_table_lookup ( l->tracks, (gchar *) sublayer ) );
+      if ( item ) {
+       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+       gtk_widget_show ( item );
+      }
+    }
+
+#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
+      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 ( _("_Edit Trackpoint") );
+      gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU) );
+      g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(trw_layer_edit_trackpoint), pass_along );
+      gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
+      gtk_widget_show ( item );
+    }
+
+  }
+
+  return rv;
+}
+
+static void trw_layer_insert_tp_after_current_tp ( VikTrwLayer *vtl )
+{
+  /* sanity checks */
+  if (!vtl->current_tpl)
+    return;
+  if (!vtl->current_tpl->next)
+    return;
+
+  VikTrackpoint *tp_current = VIK_TRACKPOINT(vtl->current_tpl->data);
+  VikTrackpoint *tp_next = VIK_TRACKPOINT(vtl->current_tpl->next->data);
+
+  /* Use current and next trackpoints to form a new track point which is inserted into the tracklist */
+  if ( tp_next ) {
+
+    VikTrackpoint *tp_new = vik_trackpoint_new();
+    struct LatLon ll_current, ll_next;
+    vik_coord_to_latlon ( &tp_current->coord, &ll_current );
+    vik_coord_to_latlon ( &tp_next->coord, &ll_next );
+
+    /* main positional interpolation */
+    struct LatLon ll_new = { (ll_current.lat+ll_next.lat)/2, (ll_current.lon+ll_next.lon)/2 };
+    vik_coord_load_from_latlon ( &(tp_new->coord), vtl->coord_mode, &ll_new );
+
+    /* Now other properties that can be interpolated */
+    tp_new->altitude = (tp_current->altitude + tp_next->altitude) / 2;
+
+    if (tp_current->has_timestamp && tp_next->has_timestamp) {
+      /* Note here the division is applied to each part, then added
+        This is to avoid potential overflow issues with a 32 time_t for dates after midpoint of this Unix time on 2004/01/04 */
+      tp_new->timestamp = (tp_current->timestamp/2) + (tp_next->timestamp/2);
+      tp_new->has_timestamp = TRUE;
+    }
+
+    if (tp_current->speed != NAN && tp_next->speed != NAN)
+      tp_new->speed = (tp_current->speed + tp_next->speed)/2;
 
-    item = a_acquire_track_menu ( VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(l)), vlp,
-       vik_layers_panel_get_viewport(VIK_LAYERS_PANEL(vlp)),
-       g_hash_table_lookup ( l->tracks, (gchar *) sublayer ) );
-    if ( item ) {
-      gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
-      gtk_widget_show ( item );
-    }  
-  }
+    /* TODO - improve interpolation of course, as it may not be correct.
+       if courses in degrees are 350 + 020, the mid course more likely to be 005 (not 185)
+       [similar applies if value is in radians] */
+    if (tp_current->course != NAN && tp_next->course != NAN)
+      tp_new->speed = (tp_current->course + tp_next->course)/2;
 
-  if ( vlp && (subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINTS || subtype == VIK_TRW_LAYER_SUBLAYER_WAYPOINT) )
-  {
-    item = gtk_menu_item_new ();
-    gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
-    gtk_widget_show ( item );
+    /* DOP / sat values remain at defaults as not they do not seem applicable to a dreamt up point */
 
-    item = gtk_menu_item_new_with_label ( _("New Waypoint") );
-    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 );
+    /* Insert new point into the trackpoints list after the current TP */
+    VikTrack *tr = g_hash_table_lookup ( vtl->tracks, vtl->current_tp_track_name );
+    gint index =  g_list_index ( tr->trackpoints, tp_current );
+    if ( index > -1 ) {
+      tr->trackpoints = g_list_insert (tr->trackpoints, tp_new, index+1 );
+    }
   }
-
-  return rv;
 }
 
-
 /* to be called when last_tpl no long exists. */
 static void trw_layer_cancel_last_tp ( VikTrwLayer *vtl )
 {
@@ -2828,7 +4342,7 @@ static void trw_layer_cancel_current_tp ( VikTrwLayer *vtl, gboolean destroy )
   {
     vtl->current_tpl = NULL;
     vtl->current_tp_track_name = NULL;
-    vik_layer_emit_update(VIK_LAYER(vtl));
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
   }
 }
 
@@ -2837,10 +4351,14 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
   g_assert ( vtl->tpwin != NULL );
   if ( response == VIK_TRW_LAYER_TPWIN_CLOSE )
     trw_layer_cancel_current_tp ( vtl, TRUE );
-  else if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
+
+  if ( vtl->current_tpl == NULL )
+    return;
+
+  if ( response == VIK_TRW_LAYER_TPWIN_SPLIT && vtl->current_tpl->next && vtl->current_tpl->prev )
   {
-    gchar *name;
-    if ( ( name = a_dialog_new_track ( GTK_WINDOW(vtl->tpwin), vtl->tracks ) ) )
+    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 ();
@@ -2860,7 +4378,7 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
       tr->visible = TRUE;
 
       vik_trw_layer_add_track ( vtl, name, tr );
-      vik_layer_emit_update(VIK_LAYER(vtl));
+      vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
     }
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_DELETE )
@@ -2888,7 +4406,7 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
       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
     {
@@ -2902,16 +4420,20 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
   {
     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 */
+    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));
+    vik_layer_emit_update(VIK_LAYER(vtl), FALSE);
   }
   else if ( response == VIK_TRW_LAYER_TPWIN_JOIN )
   {
+    // Check tracks exist and are different before joining
+    if ( ! vtl->last_tp_track_name || ! vtl->current_tp_track_name || vtl->last_tp_track_name == vtl->current_tp_track_name )
+      return;
+
     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 );
 
@@ -2945,10 +4467,15 @@ static void trw_layer_tpwin_response ( VikTrwLayer *vtl, gint response )
     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));
+    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), 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 )
@@ -2996,16 +4523,30 @@ static void waypoint_search_closest_tp ( gchar *name, VikWaypoint *wp, WPSearchP
     return;
 
   vik_viewport_coord_to_screen ( params->vvp, &(wp->coord), &x, &y );
-  if ( abs (x - params->x) <= WAYPOINT_SIZE_APPROX && abs (y - params->y) <= WAYPOINT_SIZE_APPROX &&
-      ((!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 = wp;
-    params->closest_x = x;
-    params->closest_y = y;
+
+  // If waypoint has an image then use the image size to select
+  if ( wp->image ) {
+    gint slackx, slacky;
+    slackx = wp->image_width / 2;
+    slacky = wp->image_height / 2;
+
+    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 = wp;
+      params->closest_x = x;
+      params->closest_y = y;
+    }
   }
+  else if ( abs (x - params->x) <= WAYPOINT_SIZE_APPROX && abs (y - params->y) <= WAYPOINT_SIZE_APPROX &&
+           ((!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 = wp;
+      params->closest_x = x;
+      params->closest_y = y;
+    }
 }
 
 static void track_search_closest_tp ( gchar *name, VikTrack *t, TPSearchParams *params )
@@ -3061,6 +4602,269 @@ static VikWaypoint *closest_wp_in_five_pixel_interval ( VikTrwLayer *vtl, VikVie
   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 );
+static void marker_end_move ( tool_ed_t *t );
+//
+
+static gboolean trw_layer_select_move ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* t )
+{
+  if ( t->holding ) {
+    VikCoord new_coord;
+    vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord );
+
+    // Here always allow snapping back to the original location
+    //  this is useful when one decides not to move the thing afterall
+    // If one wants to move the item only a little bit then don't hold down the 'snap' key!
+    // snap to TP
+    if ( event->state & GDK_CONTROL_MASK )
+    {
+      VikTrackpoint *tp = closest_tp_in_five_pixel_interval ( vtl, vvp, event->x, event->y );
+      if ( tp )
+        new_coord = tp->coord;
+    }
+
+    // snap to WP
+    if ( event->state & GDK_SHIFT_MASK )
+    {
+      VikWaypoint *wp = closest_wp_in_five_pixel_interval ( vtl, vvp, event->x, event->y );
+      if ( wp )
+        new_coord = wp->coord;
+    }
+    
+    gint x, y;
+    vik_viewport_coord_to_screen ( vvp, &new_coord, &x, &y );
+
+    marker_moveto ( t, x, y );
+
+    return TRUE;
+  }
+  return FALSE;
+}
+
+static gboolean trw_layer_select_release ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* t )
+{
+  if ( t->holding && event->button == 1 )
+  {
+    VikCoord new_coord;
+    vik_viewport_screen_to_coord ( vvp, event->x, event->y, &new_coord );
+
+    // snap to TP
+    if ( event->state & GDK_CONTROL_MASK )
+    {
+      VikTrackpoint *tp = closest_tp_in_five_pixel_interval ( vtl, vvp, event->x, event->y );
+      if ( tp )
+        new_coord = tp->coord;
+    }
+
+    // snap to WP
+    if ( event->state & GDK_SHIFT_MASK )
+    {
+      VikWaypoint *wp = closest_wp_in_five_pixel_interval ( vtl, vvp, event->x, event->y );
+      if ( wp )
+        new_coord = wp->coord;
+    }
+
+    marker_end_move ( t );
+
+    // Determine if working on a waypoint or a trackpoint
+    if ( t->is_waypoint )
+      vtl->current_wp->coord = new_coord;
+    else {
+      if ( vtl->current_tpl ) {
+       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 );
+      }
+    }
+
+    // Reset
+    vtl->current_wp      = NULL;
+    vtl->current_wp_name = NULL;
+    trw_layer_cancel_current_tp ( vtl, FALSE );
+
+    vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/*
+  Returns true if a waypoint or track is found near the requested event position for this particular layer
+  The item found is automatically selected
+  This is a tool like feature but routed via the layer interface, since it's instigated by a 'global' layer tool in vikwindow.c
+ */
+static gboolean trw_layer_select_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp, tool_ed_t* tet )
+{
+  if ( event->button != 1 )
+    return FALSE;
+
+  if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
+    return FALSE;
+
+  if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+    return FALSE;
+
+  // Go for waypoints first as these often will be near a track, but it's likely the wp is wanted rather then the track
+
+  if (vtl->waypoints_visible) {
+    WPSearchParams wp_params;
+    wp_params.vvp = vvp;
+    wp_params.x = event->x;
+    wp_params.y = event->y;
+    wp_params.closest_wp_name = NULL;
+    wp_params.closest_wp = NULL;
+
+    g_hash_table_foreach ( vtl->waypoints, (GHFunc) waypoint_search_closest_tp, &wp_params);
+
+    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 );
+
+      // Too easy to move it so must be holding shift to start immediately moving it
+      //   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->image ) ) {
+       // Put into 'move buffer'
+       // NB vvp & vw already set in tet
+       tet->vtl = (gpointer)vtl;
+       tet->is_waypoint = TRUE;
+      
+       marker_begin_move (tet, event->x, event->y);
+      }
+
+      vtl->current_wp =      wp_params.closest_wp;
+      vtl->current_wp_name = wp_params.closest_wp_name;
+
+      vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
+
+      return TRUE;
+    }
+  }
+
+  if (vtl->tracks_visible) {
+    TPSearchParams tp_params;
+    tp_params.vvp = vvp;
+    tp_params.x = event->x;
+    tp_params.y = event->y;
+    tp_params.closest_track_name = NULL;
+    tp_params.closest_tp = NULL;
+
+    g_hash_table_foreach ( vtl->tracks, (GHFunc) track_search_closest_tp, &tp_params);
+
+    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 );
+
+      tet->is_waypoint = FALSE;
+
+      // Select the Trackpoint
+      // Can move it immediately when control held or it's the previously selected tp
+      if ( event->state & GDK_CONTROL_MASK ||
+          vtl->current_tpl == tp_params.closest_tpl ) {
+       // Put into 'move buffer'
+       // NB vvp & vw already set in tet
+       tet->vtl = (gpointer)vtl;
+       marker_begin_move (tet, event->x, event->y);
+      }
+
+      vtl->current_tpl = tp_params.closest_tpl;
+      vtl->current_tp_track_name = tp_params.closest_track_name;
+
+      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_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;
+  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;
+}
+
+static gboolean trw_layer_show_selected_viewport_menu ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
+{
+  if ( event->button != 3 )
+    return FALSE;
+
+  if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
+    return FALSE;
+
+  if ( !vtl->tracks_visible && !vtl->waypoints_visible )
+    return FALSE;
+
+  /* Post menu for the currently selected item */
+
+  /* See if a track is selected */
+  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 ( 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 () );
+      
+      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);
+
+      gtk_menu_popup ( vtl->track_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+       
+      return TRUE;
+    }
+  }
+
+  /* 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 ( 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 () );
+      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);
+      gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 /* background drawing hook, to be passed the viewport */
 static gboolean tool_sync_done = TRUE;
 
@@ -3074,13 +4878,6 @@ static gboolean tool_sync(gpointer data)
   return FALSE;
 }
 
-typedef struct {
-  VikViewport *vvp;
-  gboolean holding;
-  GdkGC *gc;
-  int oldx, oldy;
-} tool_ed_t;
-
 static void marker_begin_move ( tool_ed_t *t, gint x, gint y )
 {
   t->holding = TRUE;
@@ -3136,6 +4933,9 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
     return TRUE;
   }
 
+  if ( !vtl->vl.visible || !vtl->waypoints_visible )
+    return FALSE;
+
   if ( vtl->current_wp && vtl->current_wp->visible )
   {
     /* first check if current WP is within area (other may be 'closer', but we want to move the current) */
@@ -3175,21 +4975,20 @@ static gboolean tool_edit_waypoint_click ( VikTrwLayer *vtl, GdkEventButton *eve
     else
       vtl->waypoint_rightclick = FALSE;
 
+    vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, params.closest_wp_name ), TRUE );
+
     vtl->current_wp = params.closest_wp;
     vtl->current_wp_name = params.closest_wp_name;
 
-    if ( params.closest_wp )
-      vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_name ) );
-
     /* 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->waypoint_rightclick = FALSE;
-  vik_layer_emit_update ( VIK_LAYER(vtl) );
+  vik_layer_emit_update ( VIK_LAYER(vtl), FALSE );
   return FALSE;
 }
 
@@ -3264,17 +5063,19 @@ 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!!! */
   if ( event->button == 3 && vtl->waypoint_rightclick )
   {
     if ( 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, vtl->current_wp_name, g_hash_table_lookup ( vtl->waypoints_iters, vtl->current_wp_name  ) );
-    gtk_menu_popup ( vtl->wp_right_click_menu, NULL, NULL, NULL, NULL, event->button, gtk_get_current_event_time() );
+      g_object_ref_sink ( G_OBJECT(vtl->wp_right_click_menu) );
+    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_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() );
+    }
     vtl->waypoint_rightclick = FALSE;
   }
   return FALSE;
@@ -3302,22 +5103,98 @@ static gpointer tool_new_track_create ( VikWindow *vw, VikViewport *vvp)
 typedef struct {
   VikTrwLayer *vtl;
   VikViewport *vvp;
-  gint x1,y1,x2,y2;
+  gint x1,y1,x2,y2,x3,y3;
+  const gchar* str;
 } 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 );
+  vik_viewport_draw_string (p->vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), p->vtl->current_track_gc, p->x3, p->y3, p->str);
   gdk_gc_set_function ( p->vtl->current_track_gc, GDK_COPY );
+
+  g_free ( (gpointer) p->str ) ;
   p->vtl->ct_sync_done = TRUE;
   g_free ( p );
   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. */
@@ -3331,6 +5208,44 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo
     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 );
+
+    /* 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;
+    /* note attempted setting text using pango layouts - but the 'undraw' technique didn't work */
+    vik_viewport_draw_string (vvp, gdk_font_from_description (pango_font_description_from_string ("Sans 8")), vtl->current_track_gc, xd, yd, str);
+
     gdk_gc_set_function ( vtl->current_track_gc, GDK_COPY );
 
     passalong = g_new(new_track_move_passalong_t,1); /* freed by sync */
@@ -3340,6 +5255,12 @@ static VikLayerToolFuncStatus tool_new_track_move ( VikTrwLayer *vtl, GdkEventMo
     passalong->y1 = y1;
     passalong->x2 = event->x;
     passalong->y2 = event->y;
+    passalong->x3 = xd;
+    passalong->y3 = yd;
+    passalong->str = str;
+
+    // Update statusbar with full gain/loss information
+    statusbar_write (str, elev_gain, elev_loss, vtl);
 
     /* this will sync and undraw when we have time to */
     g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, ct_sync, passalong, NULL);
@@ -3353,7 +5274,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 */
@@ -3363,7 +5284,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;
@@ -3385,7 +5309,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;
   }
 
@@ -3400,14 +5326,14 @@ 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;
-    if ( ( name = a_dialog_new_track ( VIK_GTK_WINDOW_FROM_LAYER(vtl), vtl->tracks ) ) )
+    gchar *name = get_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();
       vtl->current_track->visible = TRUE;
@@ -3434,17 +5360,18 @@ 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;
 }
 
-
 /*** New waypoint ****/
 
 static gpointer tool_new_waypoint_create ( VikWindow *vw, VikViewport *vvp)
@@ -3459,7 +5386,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;
 }
 
@@ -3498,6 +5425,9 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
   if (!vtl || vtl->vl.type != VIK_LAYER_TRW)
     return FALSE;
 
+  if ( !vtl->vl.visible || !vtl->tracks_visible )
+    return FALSE;
+
   if ( vtl->current_tpl )
   {
     /* 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.) */
@@ -3523,11 +5453,12 @@ static gboolean tool_edit_trackpoint_click ( VikTrwLayer *vtl, GdkEventButton *e
 
   if ( params.closest_tp )
   {
+    vik_treeview_select_iter ( VIK_LAYER(vtl)->vt, g_hash_table_lookup ( vtl->tracks_iters, params.closest_track_name ), 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 ) );
     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;
   }
 
@@ -3594,62 +5525,63 @@ 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 );
+    if ( vtl->tpwin )
+      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 );
 
-    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)
+/*** 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,
@@ -3661,31 +5593,31 @@ 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 ) {
+    if ( vtl->route_finder_check_added_track && vtl->route_finder_added_track_name ) {
       VikTrack *tr;
 
-      tr = g_hash_table_lookup ( vtl->tracks, vtl->magic_scissors_added_track_name );
+      tr = g_hash_table_lookup ( vtl->tracks, vtl->route_finder_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 ) ); 
+        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 );
+      vtl->route_finder_current_track = tr;
+
+      g_free ( vtl->route_finder_added_track_name );
+      vtl->route_finder_added_track_name = NULL;
+    } 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_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;
 }
@@ -3718,6 +5650,25 @@ static void tool_show_picture_wp ( char *name, VikWaypoint *wp, gpointer params[
   }
 }
 
+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);
+#else /* WINDOWS */
+  GError *err = NULL;
+  gchar *quoted_file = g_shell_quote ( (gchar *) pass_along[5] );
+  gchar *cmd = g_strdup_printf ( "eog %s", 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.") );
+      g_error_free ( err );
+    }
+  g_free ( cmd );
+#endif /* WINDOWS */
+}
+
 static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *event, VikViewport *vvp )
 {
   gpointer params[3] = { vvp, event, NULL };
@@ -3726,21 +5677,10 @@ static gboolean tool_show_picture_click ( VikTrwLayer *vtl, GdkEventButton *even
   g_hash_table_foreach ( vtl->waypoints, (GHFunc) tool_show_picture_wp, params );
   if ( params[2] )
   {
-    /* thanks to the Gaim people for showing me ShellExecute and g_spawn_command_line_async */
-#ifdef WINDOWS
-    ShellExecute(NULL, NULL, (char *) params[2], NULL, ".\\", 0);
-#else /* WINDOWS */
-    GError *err = NULL;
-    gchar *quoted_file = g_shell_quote ( (gchar *) params[2] );
-    gchar *cmd = g_strdup_printf ( "eog %s", quoted_file );
-    g_free ( quoted_file );
-    if ( ! g_spawn_command_line_async ( cmd, &err ) )
-    {
-      a_dialog_error_msg ( VIK_GTK_WINDOW_FROM_LAYER(vtl), _("Could not launch eog to open file.") );
-      g_error_free ( err );
-    }
-    g_free ( cmd );
-#endif /* WINDOWS */
+    static gpointer pass_along[6];
+    pass_along[0] = vtl;
+    pass_along[5] = params[2];
+    trw_layer_show_picture ( pass_along );
     return TRUE; /* found a match */
   }
   else
@@ -3761,27 +5701,43 @@ static void image_wp_make_list ( char *name, VikWaypoint *wp, GSList **pics )
     *pics = g_slist_append ( *pics, (gpointer) g_strdup ( wp->image ) );
 }
 
-static void create_thumbnails_thread ( GSList *pics, gpointer threaddata )
+/* Structure for thumbnail creating data used in the background thread */
+typedef struct {
+  VikTrwLayer *vtl; // Layer needed for redrawing
+  GSList *pics;     // Image list
+} thumbnail_create_thread_data;
+
+static int create_thumbnails_thread ( thumbnail_create_thread_data *tctd, gpointer threaddata )
 {
-  guint total = g_slist_length(pics), done = 0;
-  while ( pics )
+  guint total = g_slist_length(tctd->pics), done = 0;
+  while ( tctd->pics )
   {
-    a_thumbnails_create ( (gchar *) pics->data );
-    a_background_thread_progress ( threaddata, ((gdouble) ++done) / total );
-    pics = pics->next;
+    a_thumbnails_create ( (gchar *) tctd->pics->data );
+    int result = a_background_thread_progress ( threaddata, ((gdouble) ++done) / total );
+    if ( result != 0 )
+      return -1; /* Abort thread */
+
+    tctd->pics = tctd->pics->next;
   }
+
+  // Redraw to show the thumbnails as they are now created
+  if ( IS_VIK_LAYER(tctd->vtl) )
+    vik_layer_emit_update ( VIK_LAYER(tctd->vtl), TRUE ); // Yes update from background thread
+
+  return 0;
 }
 
-static void free_pics_slist ( GSList *pics )
+static void thumbnail_create_thread_free ( thumbnail_create_thread_data *tctd )
 {
-  while ( pics )
+  while ( tctd->pics )
   {
-    g_free ( pics->data );
-    pics = g_slist_delete_link ( pics, pics );
+    g_free ( tctd->pics->data );
+    tctd->pics = g_slist_delete_link ( tctd->pics, tctd->pics );
   }
+  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 )
   {
@@ -3791,7 +5747,16 @@ static void trw_layer_verify_thumbnails ( VikTrwLayer *vtl, GtkWidget *vp )
     {
       gint len = g_slist_length ( pics );
       gchar *tmp = g_strdup_printf ( _("Creating %d Image Thumbnails..."), len );
-      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vtl), tmp, (vik_thr_func) create_thumbnails_thread, pics, (vik_thr_free_func) free_pics_slist, NULL, len );
+      thumbnail_create_thread_data *tctd = g_malloc ( sizeof(thumbnail_create_thread_data) );
+      tctd->vtl = vtl;
+      tctd->pics = pics;
+      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vtl),
+                           tmp,
+                           (vik_thr_func) create_thumbnails_thread,
+                           tctd,
+                           (vik_thr_free_func) thumbnail_create_thread_free,
+                           NULL,
+                           len );
       g_free ( tmp );
     }
   }
@@ -3829,19 +5794,19 @@ 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, gchar *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 --------------- */
@@ -3949,17 +5914,22 @@ void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, g
       new_map = TRUE;
   }
 
-  /* fill-ins for far apart points */
-  GList *cur_rect, *next_rect;
   GList *fillins = NULL;
-  for (cur_rect = rects_to_download;
-      (next_rect = cur_rect->next) != NULL;
-      cur_rect = cur_rect->next) {
-    if ((wh.lon < ABS(GLRECT(cur_rect)->center.east_west - GLRECT(next_rect)->center.east_west)) ||
-        (wh.lat < ABS(GLRECT(cur_rect)->center.north_south - GLRECT(next_rect)->center.north_south))) {
-      fillins = add_fillins(fillins, &GLRECT(cur_rect)->center, &GLRECT(next_rect)->center, &wh);
+  /* 'fillin' doesn't work in UTM mode - potentially ending up in massive loop continually allocating memory - hence don't do it */
+  /* seems that ATM the function get_next_coord works only for LATLON */
+  if ( cur_coord->mode == VIK_COORD_LATLON ) {
+    /* fill-ins for far apart points */
+    GList *cur_rect, *next_rect;
+    for (cur_rect = rects_to_download;
+        (next_rect = cur_rect->next) != NULL;
+        cur_rect = cur_rect->next) {
+      if ((wh.lon < ABS(GLRECT(cur_rect)->center.east_west - GLRECT(next_rect)->center.east_west)) ||
+         (wh.lat < ABS(GLRECT(cur_rect)->center.north_south - GLRECT(next_rect)->center.north_south))) {
+       fillins = add_fillins(fillins, &GLRECT(cur_rect)->center, &GLRECT(next_rect)->center, &wh);
+      }
     }
-  }
+  } else
+    g_message("%s: this feature works only in Mercator mode", __FUNCTION__);
 
   if (fillins) {
     GList *iter = fillins;
@@ -3991,7 +5961,7 @@ void vik_track_download_map(VikTrack *tr, VikMapsLayer *vml, VikViewport *vvp, g
   }
 }
 
-static void trw_layer_download_map_along_track_cb(gpointer pass_along[6])
+static void trw_layer_download_map_along_track_cb ( gpointer pass_along[6] )
 {
   VikMapsLayer *vml;
   gint selected_map, default_map;
@@ -4006,7 +5976,7 @@ static void trw_layer_download_map_along_track_cb(gpointer pass_along[6])
   VikTrack *tr = (VikTrack *) g_hash_table_lookup ( VIK_TRW_LAYER(pass_along[0])->tracks, pass_along[3] );
   VikViewport *vvp = vik_window_viewport((VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl)));
 
-  GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS);
+  GList *vmls = vik_layers_panel_get_all_layers_of_type(vlp, VIK_LAYER_MAPS, TRUE); // Includes hidden map layer types
   int num_maps = g_list_length(vmls);
 
   if (!num_maps) {